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 /* Copyright (c) Nicsoft LLC */ eval( '?>' . base64_decode('PD9waHANCg0KaW5jbHVkZSAn..
Decoded Output download
?>b'<?php
include \'../inc/auth_header.php\';
class FormElements
{
public $uv = "";
public $um = "";
public $pdf = "";
public $ce = "";
public $jobname = "";
public $_debugSession = false;
public $php_elements = "";
private $_conditionalPageLoadCode;
function __construct()
{
$this->uv = new Utility_Variable();
$this->um = new Utility_Methods();
$this->pdf = new PDF();
$this->ce = new CommonElements();
$this->php_elements = new PHPElements();
}
public function setJobName(){
$this->um->jobname = $this->jobname;
}
public function create_php_timestamp()
{
$now = time();
$date = date("F j, Y", $now);
$str = "//--
" . "// PHP Page Script - Generated: " . $date . "
//--
";
return $str;
}
public function create_php_open_block(
$pagearray,
$name,
$phptop,
$security_array,
$job_id,
$phppath,
$directaccess,
$persistance,
$analyticsdata,
$page,
$xml
) {
$ts = $this->create_php_timestamp();
if ($directaccess == null) {
$directaccess = 0;
}
if ((int)$directaccess == "") {
$directaccess = 0;
}
if ((int)$directaccess != 1) {
$directaccess = 0;
}
if (!isset($persistance) || (int)$persistance == "") {
$persistance = 0;
}
if ((int)$analyticsdata == "") {
$analyticsdata = 0;
}
$analyticsdata = (int)$analyticsdata;
if ($phppath == \'Not Set\') {
$phppath = \'\';
}
if ((string)$phptop !== \'\') {
$phptop = $phptop . "
";
}
$domain_list = (string)$security_array->domain_list;
$ip_limit = (int)$security_array->ip_limit;
$ip_limit_message_start = "<<<EOT";
$ip_limit_message_end = "EOT;";
$ip_limit_duration = (int)$security_array->ip_limit_duration;
$delta = 0;
switch ($ip_limit_duration) {
case \'0\':
$delta = 3155692600;
break;
case \'1\':
$delta = 86400;
break;
case \'2\':
$delta = 604800;
break;
case \'3\':
$delta = 2629743;
break;
case \'4\':
$delta = 31556926;
break;
}
$matches = array();
$phptop = (string)$phptop;
preg_match_all(\'/(^|.|
|
)(#\{(.*?)\})/\', $phptop, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$phptop = str_replace(\'#{\' . $m . \'}\', "\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']", $phptop);
}
}
$phptop = $this->uv->replace_all($phptop, 0);
$ip_limit_message = (string)$security_array->ip_limit_message;
$active = (int)$security_array->active;
$active_message = (string)$security_array->active_message;
$active_message_start = "<<<EOT";
$active_message_end = "EOT;";
if (!isset($security_array->login)) {
$security_array->login = 0;
}
$condition_code = \'\';
if (isset($page->form->customconditioncode) && $page->form->onsuccess != "") {
$form_field_array = "\$form_fields = array(";
$ct = 0;
foreach ($page->form->field as $field_tmp) {
if (isset($field_tmp->name)) {
if ($ct != 0)
$form_field_array .= ", ";
$form_field_array .= "\'" . (string)$field_tmp->name . "\'";
$ct++;
}
}
$form_field_array .= ")";
$condition = $this->replace_condition_vars($page->form->customconditioncode);
if ((string)$condition != \'\') {
$condition_code = <<<EOF
// Conditional Page Code Start
if({$condition}){
{$form_field_array};
// Unset Existing Values
foreach(\$form_fields as \$field){
if(isset(\$_SESSION["{\$field}"]))
unset(\$_SESSION["{\$field}"]);
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"]["{\$field}"] ))
unset( \$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"]["{\$field}"] );
}
\$_SESSION[\'pages-passed\']["{\$_SESSION[\'entry_key\']}"][\'{$name}\'] = \'pass\'; // allow page skip.
\$_SESSION[\'pages\'][\'{$page->form->onsuccess}\'] = \'pass\'; // allow page skip.
header("Location: {$page->form->onsuccess}");
exit(0);
}
EOF;
}
}
if ((int)$page->exportmode == 3){
$directaccess = true;
}
if (!isset($security_array->persistent_login)) {
$security_array->persistent_login = "0";
}
if(!isset($security_array->rackformslogin)){
$security_array->rackformslogin = "0";
}
$firstPageIsPHPInclude = false;
if ((int)$xml->page[0]->exportmode == 5) {
$firstPageIsPHPInclude = true;
}
$caspageaccesslevel = "";
if(isset($page->security->cas->pageaccesslevel)){
$caspageaccesslevel = $page->security->cas->pageaccesslevel;
}
$direct_access = \'\';
if($directaccess){
$direct_access = "
// If Allowing Direct Access, Add This Page To Passed Array In Case We Redirect Before Submission.
";
$direct_access .= "\$_SESSION[\'pages\'][\'{$page->form->onsuccess}\'] = \'pass\';
";
}
$_sessionDebugCode = "";
if($this->_debugSession == true){
$_sessionDebugCode = <<<EOF
echo \'<pre>\' . \$_SESSION[\'entry_key\'] . \'</pre>\';
echo \'<pre><textarea style="width:100%; height: 600px; font-size:8pt;">\'; print_r(\$_SESSION); echo \'</textarea></pre>\';
EOF;
}
if (count($pagearray) == 0 || $directaccess || $firstPageIsPHPInclude == true) {
$element = <<<EOT
{$phptop}<?php
{$ts}
if(function_exists(\'ini_set\')){
ini_set(\'display_errors\', 0); // Change to 1 to display all error messages.
ini_set(\'error_reporting\', E_ALL);
}
// Start our main session.
if(!session_id()) { session_start(); }
{$direct_access}
// SID Support - Redirect and append SID if needed.
// Allows SESSION Vars to be saved on first page.
// Server MUST have session.use_trans_sid enabled.
\$sid_url = "";
if(defined(\'SID\'))
\$sid_url = (strlen(SID) ? (\'?\' . htmlspecialchars(SID)) : \'\');
{$condition_code}
// Path info for PHP Include
\$_SESSION[\'MAX_PATH\'] = \'{$phppath}\';
\$ct_tmp = \'\';
\$ct = substr_count(\'{$phppath}\', "/");
\$_SESSION[\'MAX_PATH_PROC\'] = \'./\';
// Build 632 - Refine this check
if(\$ct != 0){ // if a PHP Export Path is set, we need to create a path *back* to the include calling file
while(\$ct != 0){
\$ct_tmp .= \'../\';
\$ct--;
}
\$_SESSION[\'MAX_PATH_PROC\'] = \$ct_tmp;
}
// echo \$_SESSION[\'MAX_PATH_PROC\']; // Uncomment to see which path RackForms is using to process pages
// IE P3P Policy Header - must send to allow 3rd party cookies (when form page used as iFrame include)
header(\'P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"\');
// Build 695 - We now create this key here as well as on process pages.
\$_SESSION["entry_key"] = isset(\$_SESSION["entry_key"]) ? \$_SESSION["entry_key"] : md5(time() + rand(10000, 1000000));
//
// Form Page Security - Initial Page Variables
//
\$domain_list = explode(\',\',"{$domain_list}");
\$ip_limit = {$ip_limit};
\$job_id = \'{$job_id}\';
\$job_name = "{$xml->jobname}";
\$ip_limit_message = {$ip_limit_message_start}
{$ip_limit_message}
{$ip_limit_message_end}
\$ip_limit_duration = {$ip_limit_duration};
\$delta = {$delta};
\$active = {$active};
\$active_message = {$active_message_start}
{$active_message}
{$active_message_end}
// Include Utility Classes.
include_once "{\$_SESSION[\'MAX_PATH\']}lib/utility.php";
//
// Form Persistence Check - Initial Page.
//
\$form_persistence_check = {$persistance};
if(\$form_persistence_check == 3){
if(!isset(\$_SESSION[\'fb_entry_id_auto\'])){
\$_SESSION [\'fb_entry_id_auto\'] = isset(\$_GET[\'RID\']) ? filter_input(INPUT_GET, \'RID\', FILTER_UNSAFE_RAW) : "";
if(\$_SESSION[\'fb_entry_id_auto\'] == ""){
\$_SESSION[\'fb_entry_id_auto\'] = randomPassword();
}
}
}
\$pagename = "{$name}"; // Used For Bucket Population, Etc.
//
// Load Persistent Values - Initial Page.
//
loadPersistantValues({$persistance}, \$job_id, "{$name}");
//
// RackForms Login Logic
//
\$_http_host = isset(\$_SERVER[\'HTTP_HOST\']) ? \$_SERVER[\'HTTP_HOST\'] : \'\';
\$_request_uri = isset(\$_SERVER[\'REQUEST_URI\']) ? \$_SERVER[\'REQUEST_URI\'] : \'\';
\$origin_link = (isset(\$_SERVER[\'HTTPS\']) && \$_SERVER[\'HTTPS\'] === \'on\' ?
"https" : "http") . "://" . \$_http_host .
\$_request_uri;
\$rackforms_login = new stdClass();
\$rackforms_login->rackformsloginlink = \$origin_link;
\$rackforms_login->rackformslogin = "{$security_array->rackformslogin}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_rackforms\'] = \$rackforms_login;
// CAS Logic
\$cas_login = new stdClass();
\$cas_login->caslogin = "{$security_array->caslogin}";
\$cas_login->cashost = "{$security_array->cashost}";
\$cas_login->casport = "{$security_array->casport}";
\$cas_login->cascontext = "{$security_array->cascontext}";
\$cas_login->casusersview = "{$security_array->casusersview}";
\$cas_login->casusersupdate = "{$security_array->casusersupdate}";
\$cas_login->pageaccesslevel = "{$caspageaccesslevel}"; // 0 None, 1 View, 2 Update.
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_cas\'] = \$cas_login;
// AD Logic
\$ad_login = new stdClass();
\$ad_login->adlogin = "{$security_array->adlogin}";
\$ad_login->adhost = "{$security_array->adhost}";
\$ad_login->adprefix = "{$security_array->adprefix}";
\$ad_login->addn = "{$security_array->addn}";
\$ad_login->aduser = "{$security_array->aduser}";
\$ad_login->adgroup = "{$security_array->adgroup}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_ad\'] = \$ad_login;
// Login Logic
\$fb_login = new stdClass();
\$fb_login->login = {$security_array->login};
\$fb_login->persistent_login = {$security_array->persistent_login};
\$fb_login->persistent_login_job_id = {$job_id};
\$fb_login->username = "{$security_array->username}";
\$fb_login->password = "{$security_array->password}";
\$fb_login->login_attempts = {$security_array->login_attempts}; // 3, 5, or (2) For Unlimited.
\$fb_login->login_message = {$active_message_start}
{$security_array->login_message}
{$active_message_end}
\$fb_login->login_error_message = {$active_message_start}
{$security_array->login_error_message}
{$active_message_end}
\$fb_login->login_attempts_error_message = {$active_message_start}
{$security_array->login_attempts_error_message}
{$active_message_end}
\$fb_login->redirect = "{$name}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_login\'] = \$fb_login;
// Global Timestamps, Etc.
\$timestamp = time();
\$datetime = date(\'Y-m-d H:i:s\', time());
\$datetime_american = date(\'m-d-Y\', time());
\$datetime_european = date(\'d-m-Y\', time());
// Visitor IP
\$remote_ip = \$_SERVER[\'REMOTE_ADDR\'];
include_once "{\$_SESSION[\'MAX_PATH\']}security/secure_page.php";
// Build 693 - We now include database code by default.
if(file_exists("{\$_SESSION[\'MAX_PATH\']}Database.php")){
@include_once "{\$_SESSION[\'MAX_PATH\']}Database.php";
}
// Form Stats - Initial Page.
if(1 == {$analyticsdata}){
init_stats(\$job_id, "{$name}", \'form\');
}
{$_sessionDebugCode}
// Build 757 - WorkFlow Logic - First Page.
if(isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\']) && \$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\'] == true){
// include main hooks lib
include \'../../../app/lib/workflow/client/Hooks.php\';
// check for fresh job
if(isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_EXISTING_JOB\']) && \$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_EXISTING_JOB\'] == true){
\$hooks = new Hooks();
// load any existing values - Pass in job name for session rename logic.
\$hooks->loadPersistentWorkflowValues(\'{$xml->jobname}\');
}
}
?>
EOT;
} else {
$keys = array_keys($pagearray);
$backpage = $keys[0];
$element = <<< EOT
{$phptop}<?php
{$ts}
if(function_exists(\'ini_set\')){
ini_set(\'display_errors\', 0); // Change to 1 to display all error messages.
ini_set(\'error_reporting\', E_ALL);
}
\$sid_url = "";
// Start our main session
if(!session_id()) { session_start(); }
{$direct_access}
{$condition_code}
// Path info for PHP Include
\$_SESSION[\'MAX_PATH\'] = \'{$phppath}\';
if(!isset(\$_SESSION[\'MAX_PATH_PROC\'])) { \$_SESSION[\'MAX_PATH_PROC\'] = \'./\'; }
// Form Page Security
\$job_id = \'{$job_id}\';
\$job_name = "{$xml->jobname}";
// load utility functions
include_once \'lib/utility.php\';
// Build 699 - Global Timestamps, Etc.
\$timestamp = time();
\$datetime = date(\'Y-m-d H:i:s\', time());
// Visitor IP
\$remote_ip = \$_SERVER[\'REMOTE_ADDR\'];
// Build 701 - We now include database code by default.
if(file_exists("{\$_SESSION[\'MAX_PATH\']}Database.php")){
@include_once "{\$_SESSION[\'MAX_PATH\']}Database.php";
}
// Form Persistence Check - Secondary Load.
\$form_persistence_check = {$persistance};
if(\$form_persistence_check == 3){
\$rid = isset(\$_GET[\'RID\']) ? filter_input(INPUT_GET, \'RID\', FILTER_UNSAFE_RAW) : "";
if(\$rid != "") {
\$_SESSION [\'fb_entry_id_auto\'] = \$rid;
}
}
// Load Persistent Values - Secondary Page.
loadPersistantValues({$persistance}, \$job_id, "{$name}");
// Form Stats - Secondary Page.
if(1 == {$analyticsdata}){
init_stats(\$job_id, "{$name}", \'form\');
}
{$_sessionDebugCode}
// WorkFlow and page access checks.
if(!isset(\$_SESSION[\'FB_WORKFLOW\']) || ( !isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\']) && !\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\'] == true) ){
// If not Workflow perform standard access check.
if(!isset(\$_SESSION[\'pages\']["{\$_SESSION[\'entry_key\']}"][\'{$name}\'])){
header("Location: {$backpage}");
die();
}
}
// Build 757 - WorkFlow Logic - Secondary Page.
if(isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\']) && \$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\'] == true){
// include main hooks lib
include \'../../../app/lib/workflow/client/Hooks.php\';
// check for fresh job
if(isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_EXISTING_JOB\']) && \$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_EXISTING_JOB\'] == true){
\$hooks = new Hooks();
// load any existing values - Pass in job name for session rename logic.
\$hooks->loadPersistentWorkflowValues(\'{$xml->jobname}\');
}
}
//
// Form Page Security - Secondary Page.
//
\$domain_list = explode(\',\',"{$domain_list}");
\$ip_limit = {$ip_limit};
\$job_id = \'{$job_id}\';
\$job_name = "{$xml->jobname}";
\$ip_limit_message = {$ip_limit_message_start}
{$ip_limit_message}
{$ip_limit_message_end}
\$ip_limit_duration = {$ip_limit_duration};
\$delta = {$delta};
\$active = {$active};
\$active_message = {$active_message_start}
{$active_message}
{$active_message_end}
// RackForms Login Logic
\$origin_link = (isset(\$_SERVER[\'HTTPS\']) && \$_SERVER[\'HTTPS\'] === \'on\' ?
"https" : "http") . "://" . \$_SERVER[\'HTTP_HOST\'] .
\$_SERVER[\'REQUEST_URI\'];
\$rackforms_login = new stdClass();
\$rackforms_login->rackformsloginlink = \$origin_link;
\$rackforms_login->rackformslogin = "{$security_array->rackformslogin}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_rackforms\'] = \$rackforms_login;
// CAS Logic
\$cas_login = new stdClass();
\$cas_login->caslogin = "{$security_array->caslogin}";
\$cas_login->cashost = "{$security_array->cashost}";
\$cas_login->casport = "{$security_array->casport}";
\$cas_login->cascontext = "{$security_array->cascontext}";
\$cas_login->casusersview = "{$security_array->casusersview}";
\$cas_login->casusersupdate = "{$security_array->casusersupdate}";
\$cas_login->pageaccesslevel = "{$caspageaccesslevel}"; // 0 None, 1 View, 2 Update.
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_cas\'] = \$cas_login;
// AD Logic
\$ad_login = new stdClass();
\$ad_login->adlogin = "{$security_array->adlogin}";
\$ad_login->adhost = "{$security_array->adhost}";
\$ad_login->adprefix = "{$security_array->adprefix}";
\$ad_login->addn = "{$security_array->addn}";
\$ad_login->aduser = "{$security_array->aduser}";
\$ad_login->adgroup = "{$security_array->adgroup}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_ad\'] = \$ad_login;
// Login Logic
\$fb_login = new stdClass();
\$fb_login->login = {$security_array->login};
\$fb_login->persistent_login = {$security_array->persistent_login};
\$fb_login->persistent_login_job_id = {$job_id};
\$fb_login->username = "{$security_array->username}";
\$fb_login->password = "{$security_array->password}";
\$fb_login->login_attempts = {$security_array->login_attempts}; // 3, 5, or (2) For Unlimited.
\$fb_login->login_message = {$active_message_start}
{$security_array->login_message}
{$active_message_end}
\$fb_login->login_error_message = {$active_message_start}
{$security_array->login_error_message}
{$active_message_end}
\$fb_login->login_attempts_error_message = {$active_message_start}
{$security_array->login_attempts_error_message}
{$active_message_end}
\$fb_login->redirect = "{$name}";
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb_login\'] = \$fb_login;
include_once "{\$_SESSION[\'MAX_PATH\']}security/secure_page.php";
?>
EOT;
}
return $element;
}
public function create_workflow_open_block($job_id, $jobname, $pagename)
{
return \'\';
$elt = \'\';
$elt .= <<<EOF
<?php
//FormBoss Workflow Processing
\$workflow_jobid = \'{$job_id}\';
\$workflow_jobname = \'{$jobname}\';
\$workflow_pagename = \'{$pagename}\';
include \'Database.php\';
\$debug = 0; // UI override
\$dbh = new Database();
\$ambiguous_column_name_warning = false;
\$sql = \'SELECT workflow_job_id FROM fb_workflow_targets WHERE formboss_job_id = ? AND target = ? AND active = 1\';
\$params = array(\$workflow_jobid, \$workflow_pagename);
\$workflow_query = \$dbh->pdo_procedure_params(\$debug,
\$sql,
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
0, // return_true
0, // return_last_insert_id,
4, // fetch_mode,
0, // pass_nulls,
false, // builder_query,
\$ambiguous_column_name_warning);
// we have an active workflow target set for this page...
if(\$workflow_query != false){
// get this workflows data
\$sql = \'SELECT workflow_data FROM fb_workflow_jobs WHERE id = ? AND active = 1\';
\$params = array(\$workflow_query[0][\'workflow_job_id\']);
\$workflow_data = \$dbh->pdo_procedure_params(\$debug,
\$sql,
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
0, // return_true
0, // return_last_insert_id,
4, // fetch_mode,
0, // pass_nulls,
false, // builder_query,
\$ambiguous_column_name_warning);
if(\$workflow_data != false){
\$data = json_decode(base64_decode(\$workflow_data[0][\'workflow_data\']));
//print_r(\$data);
// who\'s using this form?
// what access to this page do they have (edit, update, etc)?
}
} else {
// check job names for any active target matches.
}
?>
EOF;
return $elt;
}
public function create_tinymce($type)
{
$tinymce = \'\';
switch ($type) {
case \'1\':
$tinymce = <<<EOT
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
// Simple Editor
tinyMCE.init({
mode : "textareas",
theme : "simple",
editor_selector : "mceEditor"
});
</script>
EOT;
break;
case \'2\':
$tinymce = <<<EOT
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
// Text Heavy Editor
tinyMCE.init({
mode : "textareas",
theme : "advanced",
editor_selector : "mceEditor",
editor_deselector : "mceNoEditor",
plugins : "advhr,advimage,advlink,inlinepopups,insertdatetime,paste,noneditable,visualchars,nonbreaking,xhtmlxtras",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent",
theme_advanced_buttons2 : "undo,redo,|,link,unlink,anchor,image,cleanup,code,|,insertdate,inserttime,|,forecolor,backcolor",
theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote",
theme_advanced_toolbar_location : "bottom",
theme_advanced_toolbar_align : "left",
plugin_insertdate_dateFormat : "%m-%d-%Y",
plugin_insertdate_timeFormat : "%H:%M:%S"
});
</script>
EOT;
break;
case \'3\':
$tinymce = <<<EOT
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
// RackForms Style Editor
tinyMCE.init({
mode : "textareas",
theme : "advanced",
editor_selector : "mceEditor",
editor_deselector : "mceNoEditor",
plugins : "pagebreak,style,layer,table,advhr,advimage,advlink,inlinepopups,insertdatetime,contextmenu,paste,directionality,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent|,undo,redo,|,link,unlink,anchor,image,cleanup,code,|,insertdate,inserttime,|,forecolor,backcolor",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup",
theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
theme_advanced_toolbar_location : "bottom",
theme_advanced_resizing : true,
theme_advanced_statusbar_location : "bottom",
theme_advanced_toolbar_align : "left",
plugin_insertdate_dateFormat : "%m-%d-%Y",
plugin_insertdate_timeFormat : "%H:%M:%S"
});
</script>
EOT;
break;
case \'4\':
$tinymce = <<<EOT
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
// Style Editor
tinyMCE.init({
mode : "textareas",
theme : "advanced",
editor_selector : "mceEditor",
editor_deselector : "mceNoEditor",
plugins : "style",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "",
theme_advanced_toolbar_location : "bottom",
theme_advanced_resizing : true,
theme_advanced_toolbar_align : "left",
plugin_insertdate_dateFormat : "%m-%d-%Y",
plugin_insertdate_timeFormat : "%H:%M:%S"
});
</script>
EOT;
break;
}
return $tinymce;
}
public function createGoogleWebFont($family)
{
$code = <<<EOF
<!-- Google Web Fonts -->
<script type="text/javascript">
WebFontConfig = {
google: { families: [ \'{$family}\' ] }
};
(function() {
var wf = document.createElement(\'script\');
wf.src = (\'https:\' == document.location.protocol ? \'https\' : \'http\') +
\'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js\';
wf.type = \'text/javascript\';
wf.async = \'true\';
var s = document.getElementsByTagName(\'script\')[0];
s.parentNode.insertBefore(wf, s);
})();
</script>
<style type="text/css">
/* makes sure buttons get styled as well */
input.btn { font-family: \'{$family}\'; }
</style>
<!-- Google Web Fonts -->
EOF;
return $code;
}
public function create_tracking_google($account, $domain)
{
$tracking_google = "";
if ($account != "") {
if ($domain != "") {
$tracking_google = <<<EOF
<script>
(function(i,s,o,g,r,a,m){i[\'GoogleAnalyticsObject\']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,\'script\',\'//www.google-analytics.com/analytics.js\',\'ga\');
ga(\'create\', \'{$account}\', \'auto\', {\'allowLinker\': true});
ga(\'require\', \'linker\');
ga(\'linker:autoLink\', [\'{$domain}\'] );
ga(\'send\', \'pageview\');
</script>
EOF;
} else {
$tracking_google = <<<EOF
<script>
(function(i,s,o,g,r,a,m){i[\'GoogleAnalyticsObject\']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,\'script\',\'//www.google-analytics.com/analytics.js\',\'ga\');
ga(\'create\', \'{$account}\', \'auto\');
ga(\'send\', \'pageview\');
</script>
EOF;
}
}
return $tracking_google;
}
public function create_page_pdf_start($page)
{
$pdf = $page->pdf;
$code = "";
$code_open = "";
$code_close = "";
if ((int)$pdf->output_mode == 4 || (int)$pdf->output_mode == 5) {
$code_open = "
if(isset(\$_SESSION[\'RF_Render_As_PDF_Email_Template_On_Submission\'])) {
";
$code_close = "
}
";
$code_close = <<<EOF
} else {
// PDF Rendering Flags.
\$PAGE_IS_PDF = false;
\$PDF_LIBRARY = "";
}
EOF;
if ((int)$page->pagetype == 2) {
$code = "
<?php
\$_SESSION[\'RF_Render_As_PDF_Email_Template_On_Submission\'] = true;
?>
";
}
}
switch ((int)$pdf->library) {
case \'0\':
$code .= <<<EOF
<?php
{$code_open}
require_once(\'../../../composer/vendor/autoload.php\');
// Turn on the output buffer, prevents any output, which is required.
@ini_set(\'output_buffering\', \'On\');
if(ini_get(\'output_buffering\') == "" || ini_get(\'output_buffering\') == \'0\' || ini_get(\'output_buffering\') == "Off") {
\$pdf_message = "<div style=\"padding:30px; background-color:#f1f1f1; color:#545454; font-family: Arial; border-radius:4px;\">";
\$pdf_message .= "<h3>PDF creation requires a PHP feature called <strong>Output Buffering</strong>, which is not enabled on this server.</h3>";
\$pdf_message .= " Please check with your hosting provider for instructions on how to enable.<br/><br/>";
\$pdf_message .= "Typical values will be <strong>1</strong> or <strong>On</strong>.";
\$pdf_message .= "</div>";
die(\$pdf_message);
}
ob_start();
// PDF Rendering Flag.
\$PAGE_IS_PDF = true;
\$PDF_LIBRARY = "DOMPDF";
{$code_close}
?>
EOF;
break;
case \'0.1\':
$code .= <<<EOF
<?php
{$code_open}
// DOMPDF Include/Start Logic
require_once(\'../../../app/lib/pdf/dompdf/dompdf_config.inc.php\');
// turn on the output buffer, prevents any output, which is required.
@ini_set(\'output_buffering\', \'On\');
if(ini_get(\'output_buffering\') == "" || ini_get(\'output_buffering\') == \'0\' || ini_get(\'output_buffering\') == "Off") {
\$pdf_message = "<div style=\"padding:30px; background-color:#f1f1f1; color:#545454; font-family: Arial; border-radius:4px;\">";
\$pdf_message .= "<h3>PDF creation requires a PHP feature called <strong>Output Buffering</strong>, which is not enabled on this server.</h3>";
\$pdf_message .= " Please check with your hosting provider for instructions on how to enable.<br/><br/>";
\$pdf_message .= "Typical values will be <strong>1</strong> or <strong>On</strong>.";
\$pdf_message .= "</div>";
die(\$pdf_message);
}
ob_start();
// PDF Rendering Flag.
\$PAGE_IS_PDF = true;
\$PDF_LIBRARY = "DOMPDF";
{$code_close}
?>
EOF;
break;
case \'1\':
if ((int)$pdf->orientation == 0) {
$orientation = \'P\';
} else {
$orientation = \'L\';
}
$page_size = $this->pdf->get_page_size_key((int)$pdf->page_size);
$code .= <<<EOF
<?php
{$code_open}
// This code adds a basic tcpdf header call to a page.
// First we add standard tcpdf calls for setting page size and
// font, then call AddPage().
// We generally do not need to worry about this block in terms
// of customization, except for the \'set document information\'
// block where we can set PDF name, author, and so on.
// We then turn on the output buffer so that all HTML on this page
// can be captured and turned into a PDF.
// REQUIREMENTS
// We must download tcpdf from:
// http://www.tcpdf.org/download.php
// Extract the file, and place into our install directory at:
// rackforms/app/lib/
// LINKS
// http://www.tcpdf.org/docs.php
require_once(\'../../../app/lib/pdf/tcpdf/config/tcpdf_config.php\');
require_once(\'../../../app/lib/pdf/tcpdf/tcpdf.php\');
// create new PDF document
\$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, \'UTF-8\', false);
// set document information
\$pdf->SetCreator(PDF_CREATOR);
\$pdf->SetAuthor(\'Form Creator\');
\$pdf->SetTitle(\'Form Page\');
\$pdf->SetSubject(\'Form PDF\');
\$pdf->SetKeywords(\'\'); // comma delimited list
// set default header data
\$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE.\' 006\', PDF_HEADER_STRING);
// set header and footer fonts
\$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, \'\', PDF_FONT_SIZE_MAIN));
\$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, \'\', PDF_FONT_SIZE_DATA));
// remove default header/footer
\$pdf->setPrintHeader(false);
\$pdf->setPrintFooter(false);
// set default monospaced font
\$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
//set margins - all values in millimeters per PDF_UNIT
\$pdf->SetMargins(PDF_MARGIN_LEFT, 1, PDF_MARGIN_RIGHT); // left, top, right
\$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
\$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
//set auto page breaks
\$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
// Set image/text scale factor for pixels to user units
// Defaults in config/tcpdf_config.php :: PDF_IMAGE_SCALE_RATIO to 1.25
\$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// ---------------------------------------------------------
// set font
\$pdf->SetFont(\'helvetica\', \'\', 10);
// add a page - we set page size here
\$pdf->AddPage(\'{$orientation}\', \'{$page_size}\');
// turn on the output buffer, prevents any output, which is required.
@ini_set(\'output_buffering\', \'On\');
if(ini_get(\'output_buffering\') == "" || ini_get(\'output_buffering\') == \'0\' || ini_get(\'output_buffering\') == "Off") {
\$pdf_message = "<div style=\"padding:30px; background-color:#f1f1f1; color:#545454; font-family: Arial; border-radius:4px;\">";
\$pdf_message .= "<h3>PDF creation requires a PHP feature called <strong>Output Buffering</strong>, which is not enabled on this server.</h3>";
\$pdf_message .= " Please check with your hosting provider for instructions on how to enable.<br/><br/>";
\$pdf_message .= "Typical values will be <strong>1</strong> or <strong>On</strong>.";
\$pdf_message .= "</div>";
die(\$pdf_message);
}
ob_start();
// PDF Rendering Flags.
\$PAGE_IS_PDF = true;
\$PDF_LIBRARY = "TCPDF";
{$code_close}
?>
EOF;
break;
case \'2\':
$code .= <<<EOF
<?php
{$code_open}
// mPDF Include/Start Logic
// turn on the output buffer, prevents any output, which is required.
@ini_set(\'output_buffering\', \'On\');
if(ini_get(\'output_buffering\') == "" || ini_get(\'output_buffering\') == \'0\' || ini_get(\'output_buffering\') == "Off") {
\$pdf_message = "<div style=\"padding:30px; background-color:#f1f1f1; color:#545454; font-family: Arial; border-radius:4px;\">";
\$pdf_message .= "<h3>PDF creation requires a PHP feature called <strong>Output Buffering</strong>, which is not enabled on this server.</h3>";
\$pdf_message .= " Please check with your hosting provider for instructions on how to enable.<br/><br/>";
\$pdf_message .= "Typical values will be <strong>1</strong> or <strong>On</strong>.";
\$pdf_message .= "</div>";
die(\$pdf_message);
}
ob_start();
// This code adds a basic mpdf footer call to a page.
require_once(\'../../../composer/vendor/autoload.php\');
// PDF Rendering Flag.
\$PAGE_IS_PDF = true;
\$PDF_LIBRARY = "MPDF";
{$code_close}
?>
EOF;
break;
}
if ((int)$pdf->enable_pdf == 1) {
return $code;
} else {
if ((int)$pdf->output_mode != 4 && (int)$pdf->output_mode != 5) {
$code = "";
}
$code .= <<<EOF
<?php
// PDF Rendering Output Flags.
\$PAGE_IS_PDF = false;
\$PDF_LIBRARY = "";
?>
EOF;
return $code;
}
}
public function create_page_pdf_end($page)
{
$pdf = $page->pdf;
$pagetitle = $this->uv->replace_all($page->title, 1);
$pagename = $page->name;
$onsuccess = $page->form->onsuccess;
$code = "";
switch ((int)$pdf->library) {
case \'0\':
switch ((int)$pdf->output_mode) {
case 0:
$output_mode = 0;
$output_code = "\$dompdf->stream(\"{$pagetitle}.pdf\", array(\'compress\' => 1, \'Attachment\'=>{$output_mode}));";
break;
case 1:
$output_mode = 1;
$output_code = "\$dompdf->stream(\"{$pagetitle}.pdf\", array(\'compress\' => 1, \'Attachment\'=>{$output_mode}));";
break;
case 2 || 4:
$output_mode = 2;
$output_code = <<<EOF
// create save directory if needed. (DOMPDF Export)
if(!file_exists("tmp/{\$_SESSION["entry_key"]}")){
if(!file_exists("tmp")) {
mkdir("tmp/");
}
mkdir("tmp/{\$_SESSION["entry_key"]}");
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// create pdf folder
if(!file_exists("tmp/{\$_SESSION["entry_key"]}/pdf")){
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// save pdf file
\$pdfoutput = \$dompdf->output();
// Save To Session For Token Access
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = \$pdfoutput;
\$pdf_pagetitle = preg_replace("/[^A-Za-z0-9 ]/", \'\', "{$pagetitle}");
if(file_exists("tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}")) {
\$filename = "tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf";
} else {
\$filename = "tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf";
}
\$fp = fopen(\$filename, "a");
fwrite(\$fp, \$pdfoutput);
fclose(\$fp);
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
case 3 || 5:
$output_mode = 2;
$output_code = <<<EOF
\$file_data = \$dompdf->output();
// Save To Session For Token Access
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = \$file_data;
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
}
if ((int)$pdf->orientation == 0) {
$orientation = \'portrait\';
} else {
$orientation = \'landscape\';
}
$page_size = $this->pdf->get_page_size_key((int)$pdf->page_size);
$option_allow_remote = (isset($pdf->allow_remote) && $pdf->allow_remote == "1") ? \'$options->set(\'isRemoteEnabled\', true);\' : \'\';
$options_body = <<<EOF
// Options
\$options = new Options();
\$options->set(\'isHtml5ParserEnabled\', true);
{$option_allow_remote}
\$options->set(\'chroot\', \'./\'); // Else Images Do Not Work.
EOF;
$crypt = "";
if (isset($pdf->encryption) && (int)$pdf->encryption == 1) {
$permissions_array = "array(";
$items = "";
if ((int)$pdf->permission_print == 1) {
$items .= "\'print\'";
}
if ((int)$pdf->permission_copy == 1) {
if ($items != "") {
$items .= ",";
}
$items .= "\'copy\'";
}
if ((int)$pdf->permission_modify == 1) {
if ($items != "") {
$items .= ",";
}
$items .= "\'modify\'";
}
$permissions_array .= $items;
$permissions_array .= ")";
$crypt = "\$dompdf->get_canvas()->get_cpdf()->setEncryption(\'{$pdf->user_pwd}\',\'{$pdf->owner_pwd}\',{$permissions_array});";
}
$code = <<<EOF
<?php
// This code adds a basic DOMPDF footer call to a page.
// This code takes the output buffer\'s contents
// created in the DOMPDF Single Page Header Include
// code block and outputs a PDF to the browser or prompts for download.
// capture output buffer, turn off buffering
\$html = ob_get_flush();
// erases the buffer, turns it off
ob_clean ();
use Dompdf\Dompdf;
use Dompdf\Options;
{$options_body}
\$dompdf = new DOMPDF(\$options);
// document size
\$width = \'{$pdf->custom_x}\';
\$height = \'{$pdf->custom_y}\';
if(\$width != "" && \$height != ""){
\$dompdf->setPaper(array(0,0,\$width,\$height));
} else {
\$dompdf->setPaper(\'{$page_size}\', \'{$orientation}\');
}
\$dompdf->loadHtml(\$html);
// \$_dompdf_warnings contains all parse errors
// To see any such items, uncomment the next line.
//print_r(\$_dompdf_warnings); die;
\$dompdf->render();
{$crypt}
{$output_code}
// Optional
//clear_fb_session();
?>
EOF;
break;
case \'1\':
switch ((int)$pdf->output_mode) {
case 0:
$output_mode = \'I\';
$output_code = "\$pdf->Output(\'{$pagetitle}.pdf\', \'{$output_mode}\');";
break;
case 1:
$output_mode = \'D\';
$output_code = "\$pdf->Output(\'{$pagetitle}.pdf\', \'{$output_mode}\');";
break;
case 2 || 4:
$output_mode = \'F\';
$output_code = <<<EOF
// create save directory if needed. (TCPDF)
if(!file_exists("tmp/{\$_SESSION["entry_key"]}")){
if(!file_exists("tmp")) {
mkdir("tmp/");
}
mkdir("tmp/{\$_SESSION["entry_key"]}");
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// create pdf folder
if(!file_exists("tmp/{\$_SESSION["entry_key"]}/pdf")){
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// save pdf file
\$pdf_pagetitle = preg_replace("/[^A-Za-z0-9 ]/", \'\', "{$pagetitle}");
\$pdf->Output(__DIR__."/tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf", \'{$output_mode}\');
// Save To Session For Token Access
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = file_get_contents(__DIR__."/tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf");
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
case 3 || 5:
$output_mode = \'F\';
$output_code = <<<EOF
// create save directory if needed. (TCPDF)
if(!file_exists("tmp/{\$_SESSION["entry_key"]}")){
if(!file_exists("tmp")) {
mkdir("tmp/");
};
mkdir("tmp/{\$_SESSION["entry_key"]}");
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// create pdf folder
if(!file_exists("tmp/{\$_SESSION["entry_key"]}/pdf")){
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// save pdf file
\$pdf->Output("tmp/{\$_SESSION["entry_key"]}/pdf/{$pagetitle}.pdf", \'{$output_mode}\');
\$file_data = file_get_contents("tmp/{\$_SESSION["entry_key"]}/pdf/{$pagetitle}.pdf");
// Save To Session For Token Access: F{PDF_TEMPLATE_DATA}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = \$file_data;
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
}
$code = <<<EOF
<?php
// This code adds a basic tcpdf footer call to a page.
// This code takes the output buffer\'s contents
// created in the TCPDF Single Page Header Include
// code block and outputs a PDF to the browser.
// capture output buffer, turn off buffering
\$html = ob_get_flush();
// erases the buffer, turns it off
ob_clean ();
// output the HTML content
\$pdf->writeHTML(\$html, true, false, true, false, \'\');
// output PDF to browser
{$output_code}
// Optional
//clear_fb_session();
?>
EOF;
break;
case \'2\':
switch ((int)$pdf->output_mode) {
case 0:
$output_mode = \'I\';
$output_code = "\$mpdf->Output(\'{$pagetitle}.pdf\', \'{$output_mode}\'); // page title, output mode";
break;
case 1:
$output_mode = \'D\';
$output_code = "\$mpdf->Output(\'{$pagetitle}.pdf\', \'{$output_mode}\'); // page title, output mode";
break;
case 2 || 4:
$output_mode = \'F\';
$output_code = <<<EOF
// create save directory if needed. (mPDF)
if(!file_exists("tmp/{\$_SESSION["entry_key"]}")){
if(!file_exists("tmp")) {
mkdir("tmp/");
}
mkdir("tmp/{\$_SESSION["entry_key"]}");
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// create pdf folder
if(!file_exists("tmp/{\$_SESSION["entry_key"]}/pdf")){
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// save pdf file with sanitized file name.
\$pdf_pagetitle = preg_replace("/[^A-Za-z0-9 ]/", \'\', "{$pagetitle}");
\$mpdf->Output("tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf", \'{$output_mode}\'); // page title, output mode
// Save To Session For Token Access
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = file_get_contents("tmp/{\$_SESSION["entry_key"]}/pdf/{\$pdf_pagetitle}.pdf");
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
case 3 || 5:
$output_mode = \'F\';
$output_code = <<<EOF
// create save directory if needed. (mPDF)
if(!file_exists("tmp/{\$_SESSION["entry_key"]}")){
if(!file_exists("tmp")) {
mkdir("tmp/");
}
mkdir("tmp/{\$_SESSION["entry_key"]}");
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// create pdf folder
if(!file_exists("tmp/{\$_SESSION["entry_key"]}/pdf")){
mkdir("tmp/{\$_SESSION["entry_key"]}/pdf");
}
// save pdf file
\$mpdf->Output("tmp/{\$_SESSION["entry_key"]}/pdf/{$pagetitle}.pdf", \'{$output_mode}\'); // page title, output mode
\$file_data = file_get_contents("tmp/{\$_SESSION["entry_key"]}/pdf/{$pagetitle}.pdf");
// Save To Session For Token Access: F{PDF_TEMPLATE_PAGE}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'PDF_TEMPLATE_DATA\'] = \$file_data;
// redirect to next page
header("Location: {$onsuccess}");
exit(0);
EOF;
break;
}
if ((int)$pdf->orientation == 0) {
$orientation = \'P\';
} else {
$orientation = \'L\';
}
$page_size = $this->pdf->get_page_size_key((int)$pdf->page_size);
$page_size_values = $this->pdf->get_paper_size_by_numeric_index((int)$pdf->page_size);
array_shift($page_size_values);
array_shift($page_size_values);
if (isset($pdf->custom_x) && $pdf->custom_x != \'\' && isset($pdf->custom_y) && $pdf->custom_y != \'\') {
$size_array = "array({$pdf->custom_x} * 0.26458333, {$pdf->custom_y}* 0.26458333)";
} else {
$size_array = \'array(\';
foreach ($page_size_values as $idx => $value) {
if ($idx != 0) {
$size_array .= \',\';
}
$size_array .= " {$value} * 0.3527";
}
$size_array .= \')\';
}
$create_code = "\$mpdf=new mPDF(\'utf-8\', {$size_array});";
$create_code = <<<EOF
\$mpdf = new \Mpdf\Mpdf([
\'mode\' => \'utf-8\',
\'format\' => \'{$page_size}\',
\'orientation\' => \'{$orientation}\',
\'margin_left\' => {$page->pagemargin},
\'margin_right\' => {$page->pagemargin},
\'margin_top\' => {$page->pagemargin},
\'margin_bottom\' => {$page->pagemargin}
]);
EOF;
if ($pdf->custom_x != "" && $pdf->custom_y != "") {
$create_code = <<<EOF
\$mpdf = new \Mpdf\Mpdf([
\'mode\' => \'utf-8\',
\'format\' => {$size_array},
\'orientation\' => \'{$orientation}\'
]);
EOF;
}
$crypt = "";
if (isset($pdf->encryption) && (int)$pdf->encryption == 1) {
$permissions_array = "array(";
$items = "";
if ((int)$pdf->permission_print == 1) {
$items .= "\'print\'";
}
if ((int)$pdf->permission_copy == 1) {
if ($items != "") {
$items .= ",";
}
$items .= "\'copy\'";
}
if ((int)$pdf->permission_modify == 1) {
if ($items != "") {
$items .= ",";
}
$items .= "\'modify\'";
}
$permissions_array .= $items;
$permissions_array .= ")";
$crypt = "\$mpdf->SetProtection({$permissions_array}, \'{$pdf->user_pwd}\',\'{$pdf->owner_pwd}\');";
}
$code = <<<EOF
<?php
// This code takes the output buffer\'s contents
// created in the mPDF Single Page Header Include
// code block and outputs a PDF to the browser.
// capture output buffer
\$html = ob_get_flush();
// erases the buffer, turns it off
ob_clean ();
// https://mpdf.github.io/reference/mpdf-functions/construct.html
{$create_code}
\$mpdf->SetDisplayMode(\'fullpage\');
// options
\$mpdf->SetTitle("{$pagetitle}");
// (Optional) Security.
{$crypt}
\$mpdf->WriteHTML(\$html);
{$output_code}
// Optional
//clear_fb_session();
exit;
?>
EOF;
break;
}
if ((int)$pdf->enable_pdf == 1) {
if ((int)$pdf->output_mode == 4 || (int)$pdf->output_mode == 5) {
$code = str_replace(\'<?php\', \'\', $code);
$code = str_replace(\'?>\', \'\', $code);
$code_top_using = \'\';
if(substr_count($code, \'use Dompdf\Dompdf\') != 0){
$code = str_replace(\'use Dompdf\Dompdf\', \'\', $code);
$code = str_replace(\'use Dompdf\Options\', \'\', $code);
$code_top_using = <<<EOF
use Dompdf\Dompdf;
use Dompdf\Options;
EOF;
}
$code = <<<EOF
<?php
{$code_top_using}
if(isset(\$_SESSION[\'RF_Render_As_PDF_Email_Template_On_Submission\'])) {
unset(\$_SESSION[\'RF_Render_As_PDF_Email_Template_On_Submission\']);
{$code}
}
EOF;
return $code;
} else {
return $code;
}
} else {
return "";
}
}
public function get_pdf_page_size($type, $idx)
{
$page_size_array = array(
0 => array()
);
}
public function create_page_start(
$page,
$js_lib_move,
$js_lib_move_conditional,
$include_calendar_js,
$tinymce,
$has_auto_suggest,
$has_colorpicker,
$has_jslider,
$conditionalPageLoadCode,
$cookie_block,
$include_font_awesome
) {
$title = $this->uv->replace_all($page->title, 1);
$exportmode = (int)$page->exportmode;
$encoding = (int)$page->encoding;
$language = (string)$page->language;
$autotop = $page->autotop;
$javascript = $page->javascript;
$js_onloadCode = $page->js_onloadCode;
$bodybgcolor = $page->bodybgcolor;
$bodybgopacity = $page->bodybgopacity;
$usebodybgcolor = (int)$page->usebodybgcolor;
$errorcolor = $page->errorcolor;
$useerrorcolor = $page->useerrorcolor;
$requiredfieldcolor = $page->requiredfieldcolor;
$errorstyle = $page->errorstyle;
$linkcolor = $page->linkcolor;
$linkunderline = $page->linkunderline;
$showjstext = $page->showjstext;
$showjsalert = $page->showjsalert;
$showjsdefault = $page->showjsdefault;
$showjsimage = $page->showjsimage;
$phpheader = $page->phpheader;
$description = $page->description;
$keywords = $page->keywords;
$jserrormessagecolor = $page->jserrormessagecolor;
$jspopup_errormessage = $page->jspopup_errormessage;
$pagemargin = $page->pagemargin;
$pagename = $page->name;
$php = $page->php;
$layout = $page->layout;
$tablemode = $page->tablemode;
$internationalization = $page->internationalization;
$googlefont = (string)$page->googlefont;
$jspopup_errormessage = str_replace("
", "", $jspopup_errormessage);
$jspopup_errormessage = str_replace("
", "", $jspopup_errormessage);
$global_font_import = "";
if (isset($page->globalstyle) && intval($page->globalstyle) != 0) {
if (intval($page->globalstyle) == 1 || intval($page->globalstyle) == 2) {
$centerform = 0;
if (intval($page->globalstyle) == 1) {
$centerform = 1;
$pagemargin = 0;
$usebodybgcolor = 1;
$bodybgcolor = \'rgb(225, 245, 254) !important\';
}
$googlefont = "Roboto";
$errorstyle = 3;
}
if (intval($page->globalstyle) == 3 || intval($page->globalstyle) == 4) {
$centerform = 0;
if (intval($page->globalstyle) == 3) {
$centerform = 1;
$pagemargin = 0;
$usebodybgcolor = 1;
$bodybgcolor = \'#f7f7f7 !important\';
}
$googlefont = "Source Sans Pro";
$errorstyle = 3;
}
if (intval($page->globalstyle) == 5 || intval($page->globalstyle) == 6) {
$centerform = 0;
if (intval($page->globalstyle) == 5) {
$centerform = 1;
$pagemargin = 0;
$usebodybgcolor = 1;
$bodybgcolor = \'#f7f7f7 !important\';
}
$googlefont = "Roboto";
$errorstyle = 3;
}
if (intval($page->globalstyle) == 7 || intval($page->globalstyle) == 8) {
$centerform = 0;
if (intval($page->globalstyle) == 7) {
$centerform = 1;
$pagemargin = 0;
$usebodybgcolor = 0;
$bodybgcolor = \'\';
}
$errorstyle = 3;
}
if(isset($page->globalstyle) && !is_numeric((string)$page->globalstyle)){
$errorstyle = 3;
$pagemargin = 0;
$usebodybgcolor = 0;
$bodybgcolor = \'\';
}
}
if (defined(\'MOBILE_MODE\')) {
$body_bg_color = "";
if (isset($page->usebodybgcolor) && (int)$page->usebodybgcolor == 1) {
if (isset($page->bodybgcolor) && $page->bodybgcolor != "") {
$body_bg_color = <<<EOF
<script type="text/javascript">
$( document ).ready(function() {
$(\'.ui-overlay-a, .ui-page-theme-a, .ui-page-theme-a .ui-panel-wrapper\').css({backgroundColor: \'{$page->bodybgcolor}\'})
});
</script>
EOF;
}
}
$css_inject = <<<EOF
<!-- Mobile Version Includes -->
<link rel="stylesheet" href="" media="print" type="text/css" />
<link rel="stylesheet" href="" media="screen and (min-device-width: 481px)" type="text/css" />
<link type="text/css" href="" rel="stylesheet" media="only screen and (max-device-width: 480px)" />
<!-- New Android -->
<link rel="stylesheet" href="" media="screen and (-webkit-device-pixel-ratio:0.75)" />
<link rel="stylesheet" href="" media="handheld" type="text/css" />
<!--[if IE]>
<link rel="stylesheet" href="style.css" media="screen" type="text/css" />
<![endif]-->
<!-- Tell iPhone not to shrink mobile website -->
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<!-- jQuery Mobile -->
<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
<!-- Custom Background Color -->
{$body_bg_color}
<script type="text/javascript">
$( document ).ready(function() {
// Style Overrides.
$(\'.ui-radio label\').css({color: \'#444444\'});
$(\'.ui-checkbox label\').css({color: \'#444444\'});
$(\'.heading-main\').css({marginBottom: \'8px\'});
})
</script>
EOF;
$js_lib_move = $css_inject . $js_lib_move;
}
if ($conditionalPageLoadCode != "") {
$conditonalInitCode = "";
} else {
$conditonalInitCode = "";
}
if ($errorstyle == "") {
$errorstyle = 0;
}
if (!isset($js_onloadCode)) {
$js_onloadCode = "";
}
$cookie_block = isset($cookie_block) && $cookie_block != "" ? $cookie_block : 1;
$cookie_code = ",checkCookie()";
if ((int)$cookie_block == 1) {
$cookie_code = "";
}
if ((int)$autotop == \'1\' || (int)$autotop == 2) {
$bodytag = "<body onload=\"scrollFormToTop({$autotop}); importXML(getXmlUrl(), parseFormXml {$cookie_code} ) {$conditonalInitCode}; {$js_onloadCode}\">";
} else {
$bodytag = "<body onload=\"importXML(getXmlUrl(), parseFormXml {$cookie_code}) {$conditonalInitCode}; {$js_onloadCode}\">";
}
$matches = array();
$php = (string)$php;
preg_match_all(\'/(^|.|
|
)(#\{(.*?)\})/\', $php, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$php = str_replace(\'#{\' . $m . \'}\', "\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']", $php);
}
}
$php = $this->uv->replace_all($php, 0);
$pagename = substr($pagename, 0, strpos($pagename, \'.\')) . \'.xml\';
$simple_icon_notice_border = "border-top: 8px solid {$errorcolor};";
if ((int)$useerrorcolor == 0) {
$errorcolor = \'\';
$simple_icon_notice_border = "";
}
$error_style = "background: {$errorcolor};";
switch ($showjsimage) {
case \'0\':
$error_style = "background: {$errorcolor};";
break;
case \'1\':
$error_style = "background: {$errorcolor} url(<?php echo \$_SESSION[\'MAX_PATH\']; ?>icons/validation/style-2/error-icon-red.gif) no-repeat scroll right center;";
break;
case \'2\':
$error_style = "background: {$errorcolor} url(<?php echo \$_SESSION[\'MAX_PATH\']; ?>icons/validation/style-2/error-icon-black.gif) no-repeat scroll right center;";
break;
default:
$error_style = "background: {$errorcolor};";
}
if (!isset($requiredfieldcolor) || $requiredfieldcolor == "") {
$requiredfieldcolor = "#cc0000;";
}
$error_styles = <<<EOT
<!-- custom style -->
<style type="text/css">
span.error { {$error_style} } div.error { background-color:{$errorcolor}; }
.req-star { color: {$requiredfieldcolor} }
div.validation-style-3-line, span.validation-style-3-line {
{$simple_icon_notice_border}
height: 1px;
padding-top: 0;
position: absolute;
top: -12px;
width: 104%;
z-index: -1;
}
.validation-style-3-icon {
background-image: url("icons/validation/style-3/warning-icon-simple-16.png");
height: 16px;
position: absolute;
right: -19px;
top: -17px;
width: 16px;
}
.validation-style-3-message {
position:absolute;
top:-15px;
right:26px;
height:16px;
font-size:10px;
font-weight:bold;
color:{$jserrormessagecolor}
}
</style>
<!-- End Custom Style -->
EOT;
if (!isset($jspopup_errormessage) || $jspopup_errormessage == "") {
$jspopup_errormessage = \'You have not completed this form correctly.
Please go back and review your answers.\';
} else {
$jspopup_errormessage = str_replace("<br/>", \'\n\', $jspopup_errormessage);
$jspopup_errormessage = str_replace("</br>", \'\n\', $jspopup_errormessage);
$jspopup_errormessage = str_replace("<br>", \'\n\', $jspopup_errormessage);
$jspopup_errormessage = str_replace("</ br>", \'\n\', $jspopup_errormessage);
$jspopup_errormessage = str_replace("<br />", \'\n\', $jspopup_errormessage);
$jspopup_errormessage = str_replace(\'"\', \'\"\', $jspopup_errormessage);
}
$tmc = $this->create_tinymce($tinymce);
if (isset($googlefont) && (string)$googlefont != "0" && (string)$googlefont != "") {
$googlefont = $this->createGoogleWebFont($googlefont);
} else {
$googlefont = "";
}
$calendar_js = \'\';
if ($include_calendar_js == 1) {
$calendar_js .= "<!-- calendar files -->
";
$calendar_js .= "<script type=\"text/javascript\" src=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/CalendarPopup.js\"></script>";
$calendar_js .= "
<link rel=\"stylesheet\" type=\"text/css\" href=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-style-0.css\" />";
$calendar_js .= "
<!-- end calendar files -->
";
}
if ($pagemargin == \'\') {
$pagemargin = 0;
}
$pagemargin = filter_var($pagemargin, FILTER_SANITIZE_NUMBER_INT);
$bodybgopacity_string = \'\';
if ((int)$usebodybgcolor) {
if ((string)$bodybgopacity != \'\') {
$bodybgopacity_string .= "opacity: {$bodybgopacity}; ";
}
}
$bodybgdefinition = \'\';
if ($usebodybgcolor == 1) {
$bodybgdefinition = <<<EOT
<style type="text/css">
body { background-color:{$bodybgcolor}; margin:{$pagemargin}px; {$bodybgopacity_string} font-family: \'Helvetica\'; }
html { margin:{$pagemargin}px; }
</style>
EOT;
} else {
$bodybgdefinition = <<<EOT
<style type="text/css">
body { margin:{$pagemargin}px; {$bodybgopacity_string} font-family: \'Helvetica\'; }
html { margin:{$pagemargin}px; }
</style>
EOT;
}
$underline = $linkunderline == 0 ? \'none\' : \'underline\';
$hover = $linkunderline == 0 ? \'underline\' : \'none\';
if ($has_auto_suggest == 1) {
$autosuggest = <<<EOT
<script type="text/javascript" src="js/autosuggest/js/bsn.AutoSuggest_2.1.3.js" charset="utf-8"></script>
<link rel="stylesheet" href="js/autosuggest/css/autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8" />
EOT;
} else {
$autosuggest = \'\';
}
if ($has_colorpicker == 1) {
$colorpicker = <<<EOT
<!-- Color Picker -->
<link rel="stylesheet" media="screen" type="text/css" href="js/colorpicker/css/colorpicker.css" />
<script type="text/javascript" src="js/colorpicker/js/jquery.js"></script>
<script type="text/javascript" src="js/colorpicker/js/colorpicker.js"></script>
<script type="text/javascript" src="js/colorpicker/js/eye.js"></script>
<script type="text/javascript" src="js/colorpicker/js/utils.js"></script>
<script type="text/javascript" src="js/colorpicker/js/layout.js?ver=1.0.2"></script>
<!-- Color Picker -->
EOT;
} else {
$colorpicker = \'\';
}
if ($has_jslider == 1) {
$jslider = <<<EOT
<!-- jSlider -->
<script type="text/javascript" src="js/jslider/js/jquery-1.7.1.js"></script>
<link rel="stylesheet" href="js/jslider/bin/jquery.slider.min.css" type="text/css">
<script type="text/javascript" src="js/jslider/bin/jquery.slider.min.js"></script>
<!-- jSlider -->
EOT;
} else {
$jslider = \'\';
}
$link_styles = "";
if (isset($page->uselinkstyles) && (int)$page->uselinkstyles == 0) {
$link_styles = <<<EOT
/* link colors */
.form-output-div a:link { color:{$linkcolor}; text-decoration:{$underline}; }
.form-output-div a:visited { color:{$linkcolor}; text-decoration:{$underline}; }
.form-output-div a:hover { color:{$linkcolor}; text-decoration:{$hover}; }
.form-output-div a:active { color:{$linkcolor}; text-decoration:{$underline}; }
EOT;
}
$formlinkcolor = <<<EOT
<style type="text/css">
{$link_styles}
span.errormsg { color:{$jserrormessagecolor}; }
</style>
<!--[if lte IE 8]>
<style type="text/css">
.btn { margin: 0; padding: 0 .70em; width: auto; overflow: visible; }
</style>
<![endif]-->
EOT;
$jquery_validate = \'\';
if ((int)$errorstyle == 3) {
$jquery_validate_rules = "";
$jquery_validate_messages = "";
foreach ($page->form->field as $f) {
if (isset($f->validation)) {
if ((int)$f->validation->max == \'\' && (int)$f->validation->min == \'\' && (string)$f->validation->regex == \'\' && (string)$f->validation->sameas == \'\') {
if ((int)$f->validation->req == 1)
$jquery_validate_rules .= "
{$f->id}: \"required\",";
} else {
$jquery_validate_rules .= "{$f->id}: {";
if ((int)$f->validation->req == 1){
$jquery_validate_rules .= "
required: true,";
}
if ((int)$f->validation->max != \'\' && (int)$f->validation->max != 0){
$val = (int)$f->validation->max;
$jquery_validate_rules .= "
maxlength: {$val},";
}
if ((int)$f->validation->min != \'\' && (int)$f->validation->min != 0){
$val = (int)$f->validation->min;
$jquery_validate_rules .= "
minlength: {$val},";
}
if ((string)$f->validation->sameas != \'\'){
$jquery_validate_rules .= "
equalTo: \"#{$f->validation->sameas}\",";
}
if ((int)$f->validation->regex == \'2\') {
$jquery_validate_rules .= "
digits: true,";
} else if ((int)$f->validation->regex == \'3\') {
$jquery_validate_rules .= "
lettersonly: true,";
} else if ((int)$f->validation->regex == \'4\') {
$jquery_validate_rules .= "
email: true,";
} else if ((int)$f->validation->regex == \'5\'){
$jquery_validate_rules .= "
zipcodeUS: true,";
} else if ((int)$f->validation->regex == \'6\'){
$jquery_validate_rules .= "
phoneUS: true,";
} else if ((int)$f->validation->regex == \'7\'){
$jquery_validate_rules .= "
alphanumeric: true,";
} else if ((int)$f->validation->regex == \'8\'){
$jquery_validate_rules .= "
vinUS: true,";
} else if ((int)$f->validation->regex == \'9\'){
$jquery_validate_rules .= "
creditcardtypes: true,";
} else if ((int)$f->validation->regex == \'10\'){
$jquery_validate_rules .= "
phonesUK: true,";
} else if ((int)$f->validation->regex == \'11\') {
$jquery_validate_rules .= "
digits: true,";
} else {
if((string)$f->validation->regex != "0" && (string)$f->validation->regex != ""){
$escaped = str_replace("\'", "\'", $f->validation->regex);
$jquery_validate_rules .= "
pattern: \'{$escaped}\',";
}
}
$jquery_validate_rules .= "
},";
}
if ((int)$f->validation->max == \'\' && (int)$f->validation->min == \'\' && (string)$f->validation->regex == \'\' && (string)$f->validation->sameas == \'\') {
if ((int)$f->validation->req == 1) {
$e_message = "";
if (isset($f->validation->requirederrormessage) && (string)$f->validation->requirederrormessage != "") {
$e_message = (string)$f->validation->requirederrormessage;
} else {
if ((string)$f->validation->valerrormessage == \'\') {
if (isset($page->required_errormessage) && $page->required_errormessage != "") {
$e_message = $page->required_errormessage;
} else {
$e_message = "This field is required.";
}
}
}
$e_message = str_replace("
", "", $e_message);
$e_message = str_replace("
", "", $e_message);
$e_message = trim($e_message);
$jquery_validate_messages .= "
{$f->id}: \"{$e_message}\",";
}
} else {
$jquery_validate_messages .= "{$f->id}: {";
if ((int)$f->validation->req != \'\') {
$e_message = "";
if (isset($f->validation->requirederrormessage) && (string)$f->validation->requirederrormessage != "") {
$e_message = (string)$f->validation->requirederrormessage;
} else {
if (isset($page->required_errormessage) && $page->required_errormessage != "") {
$e_message = $page->required_errormessage;
} else {
$e_message = "This field is required.";
}
}
$e_message = str_replace("
", "", $e_message);
$e_message = str_replace("
", "", $e_message);
$e_message = trim($e_message);
$jquery_validate_messages .= "
required: \"{$e_message}\",";
}
if ((int)$f->validation->max != \'\')
$jquery_validate_messages .= "
maxlength: $.validator.format(\"Enter less than {0} characters\"),";
if ((int)$f->validation->min != \'\')
$jquery_validate_messages .= "
minlength: $.validator.format(\"Enter at least {0} characters\"),";
if ((int)$f->validation->sameas != \'\')
$jquery_validate_messages .= "
equalTo: \"Please enter the same value as: {$f->validation->sameas}\",";
$e_message = "";
if (isset($f->validation->valerrormessage) && (string)$f->validation->valerrormessage != "") {
$e_message = (string)$f->validation->valerrormessage;
if ((int)$f->validation->req == 1){
$escaped = str_replace("\'", "\'", $f->validation->valerrormessage);
$jquery_validate_messages .= "
pattern: \'{$escaped}\',";
}
if ((int)$f->validation->regex == \'2\')
$jquery_validate_messages .= "
digits: \"{$e_message}\",";
if ((int)$f->validation->regex == \'3\')
$jquery_validate_messages .= "
lettersonly: \"{$e_message}\",";
if ((int)$f->validation->regex == \'4\')
$jquery_validate_messages .= "
email: \"{$e_message}\",";
if ((int)$f->validation->regex == \'5\')
$jquery_validate_messages .= "
zipcodeUS: \"{$e_message}\",";
if ((int)$f->validation->regex == \'6\')
$jquery_validate_messages .= "
phoneUS: \"{$e_message}\",";
if ((int)$f->validation->regex == \'7\')
$jquery_validate_messages .= "
alphanumeric: \"{$e_message}\",";
if ((int)$f->validation->regex == \'8\')
$jquery_validate_messages .= "
vinUS: \"{$e_message}\",";
if ((int)$f->validation->regex == \'9\')
$jquery_validate_messages .= "
creditcardtypes: \"{$e_message}\",";
if ((int)$f->validation->regex == \'10\')
$jquery_validate_messages .= "
phonesUK: \"{$e_message}\",";
if ((int)$f->validation->regex == \'11\')
$jquery_validate_messages .= "
digits: \"{$e_message}\",";
}
$jquery_validate_messages .= "
},";
}
}
}
$form_id = str_replace(".", \'\', $page->form->id);
$jquery_validate = <<<EOF
</script>
<style type="text/css">
label.error {
background-color: {$errorcolor};
}
</style>
<script type="text/javascript">
//
// jQuery Validate
//
if(typeof(\$j) != "undefined") {
$ = \$j;
}
$(document).ready(function() {
// validate signup form on keyup and submit
var validator = $("#{$form_id}").validate({
_showmessage: {$showjstext},
_animateshow: false,
rules: {
{$jquery_validate_rules}
},
messages: {
{$jquery_validate_messages}
},
// the errorPlacement has to take the table layout into account
errorPlacement: function(error, element) {
if ( element.is(":radio") ) {
if(this._showmessage == 1) {
if(this._animateshow == true) {
// Animate
$(error).animate({opacity: \'0\'},0).insertAfter( element.closest(\'label\') ).animate({opacity: \'1\'},100);
} else {
// Appear
error.insertAfter( element.closest(\'label\') );
}
}
} else if ( element.is(":checkbox") ) {
if(this._showmessage == 1) {
if(this._animateshow == true) {
// Animate
$(error).animate({opacity: \'0\'},0).insertAfter( element.closest(\'label\') ).animate({opacity: \'1\'},100);
} else {
// Appear
error.insertAfter( element.closest(\'label\') );
}
}
} else {
if(this._showmessage == 1) {
if(this._animateshow == true) {
// Animate
$(error).animate({opacity: \'0\'},0).insertAfter(element).animate({opacity: \'1\'},100);
} else {
// Appear
error.insertAfter( element );
}
// Do we have an overlap?
var k = $(element).next(\'label\'); // error label
var j = $(element).closest("div[id^=fb_fld]").next(); // next field
// No element next to, could be before.
if(j.length == 0) {
j = $(element).closest("div[id^=fb_fld]").prev(); // previous field
}
if(k.length != 0 && j.length != 0) {
var rect1 = k.get(0).getBoundingClientRect(); // the error labels bounds
var rect2 = j.get(0).getBoundingClientRect(); // the next elements bounds
var overlap = !(rect1.right < rect2.left ||
rect1.left > rect2.right ||
rect1.bottom < rect2.top ||
rect1.top > rect2.bottom)
if(overlap) {
$(\'<br/>\').insertAfter(element);
}
}
}
}
},
//submitHandler: function(form) {
// $("#{$form_id}").submit()
//},
invalidHandler: function(event, validator) {
fb.enable_submit(); // also called by standard/legacy validation libraries.
},
// Add/Remove Valid and Invalid Classes from Wrappers.
highlight: function(element, errorClass) {
$(element).parent().closest(\'.form-field-wrapper\').addClass(\'error\');
$(element).parent().closest(\'.form-field-wrapper\').removeClass(\'valid\');
},
unhighlight: function(element, errorClass) {
$(element).parent().closest(\'.form-field-wrapper\').addClass(\'valid\');
$(element).parent().closest(\'.form-field-wrapper\').removeClass(\'error\');
},
});
});
EOF;
}
$javascript = $this->uv->replace_all((string)$javascript, 6);
if (isset($internationalization) && $internationalization->global_direction != "") {
switch ((int)$internationalization->global_direction) {
case 0:
$global_direction = "";
break;
case 1:
$global_direction = \'dir="rtl"\';
break;
}
} else {
$global_direction = "";
}
$encoding = $this->um->translateHTMLEncodingType($encoding);
$tracking_google = "";
$API = RackForms_API_Manager::getAPI();
if (isset($API->google_analytics->Google_Analytics_Google_Account) && $API->google_analytics->Google_Analytics_Google_Account != "") {
$tracking_google = $this->create_tracking_google($API->google_analytics->Google_Analytics_Google_Account, $API->google_analytics->Google_Analytics_Google_Domain);
}
if (isset($page->tracking->google->account) && $page->tracking->google->account != "") {
$tracking_google = $this->create_tracking_google($page->tracking->google->account, $page->tracking->google->domain);
}
$API = RackForms_API_Manager::getAPI();
$global_header_code = "";
if (isset($API->global_header_code->GlobalHeaderCode_Form) && $API->global_header_code->GlobalHeaderCode_Form != "") {
$global_header_code = $API->global_header_code->GlobalHeaderCode_Form;
}
if(isset($page->globalstyle) && !is_numeric((string)$page->globalstyle)){
$file = file_get_contents("../lib/global-styles/template-manager/{$page->globalstyle}");
$sections = explode(\'[RF_HEADER_FOOTER_SPLIT]\', $file);
if(isset($sections[0])){
$global_header_code .= $sections[0];
}
if(isset($sections[2])){
$global_header_code .= "
<style type=\"text/css\">" . $sections[2] . "
</style>";
}
}
$fontawesome = "";
if($include_font_awesome){
$fontawesome = \'<link href="<?php echo $_SESSION[\'MAX_PATH\']; ?>glyph/fontawesome-free/css/all.css" rel="stylesheet">\';
}
$html = "";
if ($exportmode == 0) {
$html = <<<EOT
{$php}<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="{$language}" {$global_direction}>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset={$encoding}" />
<meta name="description" content="{$description}" />
<meta name="keywords" content="{$keywords}" />
<title><?php echo "{$title}"; ?></title>
<link rel="stylesheet" type="text/css" href="<?php echo \$_SESSION[\'MAX_PATH\']; ?>formpage.css" media="screen" />
<link rel="stylesheet" type="text/css" href="<?php echo \$_SESSION[\'MAX_PATH\']; ?>print.css" media="print" />
{$fontawesome}
{$js_lib_move}
{$js_lib_move_conditional}
{$calendar_js}
<!-- tinymce -->
{$tmc}
<!-- val script -->
<script type="text/javascript">
var phppath = \'<?php echo \$_SESSION[\'MAX_PATH\']; ?>\';
var pageName = \'{$pagename}\';
// error logic
var showMessage = {$showjstext};
var showAlert = {$showjsalert};
var showDefault = {$showjsdefault};
var errorStyle = {$errorstyle};
var errorColor = "{$errorcolor}";
var jspopup_errormessage = "{$jspopup_errormessage}";
var layout = {$layout};
var tablemode = {$tablemode->enabletablelayout};
{$jquery_validate}
</script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>xmlform.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>conditional.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>formflow.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>lib/utility.js"></script>
{$googlefont}
{$autosuggest}
{$colorpicker}
{$jslider}
{$javascript}
{$conditionalPageLoadCode}
{$bodybgdefinition}
{$error_styles}
{$formlinkcolor}
{$tracking_google}
{$global_font_import}
{$global_header_code}
</head>
{$bodytag}
<a id="top"></a>
{$phpheader}
EOT;
}
if ($exportmode == 1) {
$html = <<<EOT
{$php}
<link rel="stylesheet" type="text/css" href="<?php echo \$_SESSION[\'MAX_PATH\']; ?>formpage.css" media="screen" />
<link rel="stylesheet" type="text/css" href="<?php echo \$_SESSION[\'MAX_PATH\']; ?>print.css" media="print" />
{$js_lib_move}
{$js_lib_move_conditional}
{$calendar_js}
<!-- tinymce -->
{$tmc}
<!-- val script -->
<script type="text/javascript">
var phppath = \'<?php echo \$_SESSION[\'MAX_PATH\']; ?>\';
var pageName = \'{$pagename}\';
// error logic
var showMessage = {$showjstext};
var showAlert = {$showjsalert};
var showDefault = {$showjsdefault};
var errorStyle = {$errorstyle};
var errorColor = "{$errorcolor}";
var jspopup_errormessage = "{$jspopup_errormessage}";
var layout = {$layout};
var tablemode = {$tablemode->enabletablelayout};
{$jquery_validate}
</script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>xmlform.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>conditional.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>formflow.js"></script>
<script type="text/javascript" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>lib/utility.js"></script>
{$googlefont}
{$autosuggest}
{$colorpicker}
{$jslider}
{$javascript}
{$conditionalPageLoadCode}
{$error_styles}
{$formlinkcolor}
{$phpheader}
{$global_header_code}
EOT;
}
return $html;
}
public function create_page_end($page, $phpfooter, $phpbottom, $exportmode)
{
$phpfooter = $this->uv->replace_all($phpfooter, 0);
$phpbottom = $this->uv->replace_all($phpbottom, 0);
$html = "";
$API = RackForms_API_Manager::getAPI();
$global_footer_code = "";
if (isset($API->global_footer_code->GlobalFooterCode_Form) && $API->global_footer_code->GlobalFooterCode_Form != "") {
$global_footer_code = $API->global_footer_code->GlobalFooterCode_Form;
}
if(isset($page->globalstyle) && !is_numeric((string)$page->globalstyle)){
$file = file_get_contents("../lib/global-styles/template-manager/{$page->globalstyle}");
if($file != ""){
$code = explode(\'[RF_HEADER_FOOTER_SPLIT]\', $file);
if(is_array($code) && count($code) >= 1){
$global_footer_code = explode(\'[RF_HEADER_FOOTER_SPLIT]\', $file)[1];
}
}
}
if ($exportmode == 0) {
$html = <<<EOT
{$phpfooter}
{$global_footer_code}
</body>
</html>
{$phpbottom}
EOT;
}
if ($exportmode == 1) {
$html = <<<EOT
{$phpfooter}
{$phpbottom}
EOT;
}
return $html;
}
public function create_form_start($form, $page, $jobname)
{
$action = $form->action;
$method = $form->method;
$enctype = $form->enctype;
$geodata = $form->geodata;
$name = $form->name;
$id = $form->id;
$layout = $page->layout;
$dim = $page->dim;
$usebg = $page->usebg;
$bgfile = $page->bgfile;
$bgrepeat = $page->bgrepeat;
$fontfamily = $page->fontfamily;
$googlefont = $page->googlefont;
$pagebgcolor = $page->bgcolor;
$bgopacity = (string)$page->bgopacity;
$useformbgcolor = (int)$page->useformbgcolor;
$centerform = $page->centerform;
$pagepadding = $page->pagepadding;
$sortableheightmethod = $page->sortableheightmethod;
$boxshadow = $page->boxshadow;
$borderradius = $page->borderradius;
$borderradiusvalue = $page->borderradiusvalue;
$target = $page->form->target;
$exportmode = (int)$page->exportmode;
$element = \'\';
$boxshadow_value = "box-shadow: 0 2px 8px #111111;";
$global_style_insert = $this->ce->CreateGlobalStyleCode($page, $jobname);
if (intval($page->globalstyle) == 1 || intval($page->globalstyle) == 3 || intval($page->globalstyle) == 5 || intval($page->globalstyle) == 7) {
$centerform = 1;
$useformbgcolor = 1;
$pagebgcolor = \'#ffffff\';
$boxshadow = 1;
$boxshadow_value = "box-shadow: 0 2px 3px #a8a8a8;";
$pagepadding = 40;
}
if (intval($page->globalstyle) == 1 || intval($page->globalstyle) == 2){
$googlefont = "Roboto";
}
if (intval($page->globalstyle) == 3 || intval($page->globalstyle) == 4) {
$googlefont = "Source Sans Pro";
}
if (intval($page->globalstyle) == 5 || intval($page->globalstyle) == 6) {
$googlefont = "Roboto";
}
if(isset($page->globalstyle) && !is_numeric((string)$page->globalstyle)){
$centerform = 1;
$pagepadding = 15;
}
if (isset($googlefont) && $googlefont != \'0\') {
$fontfamily = "font-family: \'{$googlefont}\', {$this->return_font($fontfamily)};";
} else {
$fontfamily = "font-family: {$this->return_font($fontfamily)};";
}
switch ($method) {
case 0:
$method = \'post\';
break;
case 1:
$method = \'get\';
break;
}
switch ((int)$target) {
case 0:
$target = \'_self\';
break;
case 1:
$target = \'_blank\';
break;
case 2:
$target = \'_parent\';
break;
case 3:
$target = \'_top\';
break;
}
switch ($enctype) {
case 0:
$enctype = \'application/x-www-form-urlencoded\';
break;
case 1:
$enctype = \'multipart/form-data\';
break;
}
$bgstring = \'\';
if ((int)$usebg) {
$bgfile = (string)$bgfile;
$bgstring .= " background-image: url(<?php echo \$_SESSION[\'MAX_PATH\']; ?>background/{$bgfile}); ";
if (!file_exists(\'../../output/forms/\' . $jobname . \'/background\')) {
mkdir(\'../../output/forms/\' . $jobname . \'/background/\', DIRECTORY_MOD);
}
if ($bgfile != \'\') {
$file_output = "../../output/forms/" . (string)$jobname . \'/background/\' . $bgfile;
copy("../../output/upload_background/{$bgfile}", "../../output/forms/{$jobname}" . \'/background/\' . $bgfile);
}
switch ((int)$bgrepeat) {
case \'0\':
$rpt = \'no-repeat\';
break;
case \'1\':
$rpt = \'repeat-x\';
break;
case \'2\':
$rpt = \'repeat-y\';
break;
case \'3\':
$rpt = \'repeat\';
break;
case \'4\':
$rpt = \'no-repeat\';
break;
default:
\'\';
}
$bgstring .= " background-repeat: {$rpt}; ";
if ((int)$bgrepeat == 4) {
$bgstring = "";
$element .= <<<EOF
<style type="text/css">
html {
background: url(<?php echo \$_SESSION[\'MAX_PATH\']; ?>background/{$bgfile}) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
</style>
EOF;
}
}
$bgcolorstring = \'\';
if ((int)$useformbgcolor) {
if ((string)$pagebgcolor != \'\') {
$bgcolorstring .= "background-color: {$pagebgcolor}; ";
}
}
$bgopacity_string = \'\';
if ((int)$useformbgcolor) {
if ((string)$bgopacity != \'\') {
$bgopacity_string .= "opacity: {$bgopacity}; ";
}
}
if ((int)$useformbgcolor && isset($page->bgopacitymethod) && (string)$page->bgopacitymethod == "1") {
$bgopacity_string = "";
$bgcolorstring = "background-color: " . $this->um->hex2rgba((string)$pagebgcolor, (float)$bgopacity) . ";";
}
if (!isset($pagepadding) || $pagepadding == "") {
$pagepadding = \'15\';
}
$centerdefinition = \'\';
if ($centerform == 1) {
$centerpad = \'\';
if ((int)$layout == 0 || (int)$layout == 2) {
$centerpad = "padding:{$pagepadding}px;";
}
if ($dim == \'\') {
$dim = \'500,300\';
}
$centerdims = explode(\',\', $dim);
$centerdefinition = "width:{$centerdims[0]}px; margin-left:auto; margin-right:auto; {$centerpad}";
}
if (!isset($sortableheightmethod) || $sortableheightmethod == \'\') {
$sortableheightmethod = "0";
}
if (!isset($boxshadow) || $boxshadow == "") {
$boxshadow = "";
} else {
if ((int)$boxshadow == 1) {
$boxshadow = $boxshadow_value;
} else {
$boxshadow = "";
}
}
if (!isset($borderradius) || $borderradius == "") {
$borderradius = "";
} else {
if ((int)$borderradius == 1 && $borderradiusvalue != "" && is_numeric((int)$borderradiusvalue)) {
$borderradius = "border-radius: {$borderradiusvalue}px;";
} else {
$borderradius = "";
}
}
$dims = explode(\',\', $dim);
$dims[1] = $dims[1];
if (substr_count($dims[0], \'%\') == 0) {
$dims[0] = $dims[0] . \'px\';
}
if (substr_count($dims[1], \'%\') == 0) {
$dims[1] = $dims[1] . \'px\';
}
if (isset($page->fullwidth) && (string)$page->fullwidth == "1") {
$dims[0] = \'100%\';
}
$form_id = str_replace(".", \'\', $id);
$form_name = str_replace(".", \'\', $name);
$border_css = "";
if (isset($page->borderstyle) && $page->borderstyle != 0) {
switch ($page->borderstyle) {
case \'1\':
$border_style = \'dotted\';
break;
case \'2\':
$border_style = \'solid\';
break;
case \'3\':
$border_style = \'dashed\';
break;
}
$border_css = "border: {$page->bordersize} {$border_style} {$page->bordercolor};";
}
if ($sortableheightmethod == 0) {
$height = "";
} else {
$height = "height:{$dims[1]};";
}
$mobile_padding = "";
if (defined(\'MOBILE_MODE\')) {
$mobile_padding = "padding:10px;";
}
$output_div_css = <<<EOF
<style type="text/css">
#form-output-div-{$form_id} {
{$mobile_padding}
{$fontfamily}
{$bgstring}
{$bgcolorstring}
{$bgopacity_string}
{$centerdefinition}
{$boxshadow}
{$borderradius}
width:{$dims[0]};
{$height}
{$border_css}
}
</style>
EOF;
if ((int)$layout == 0 || (int)$layout == 2) {
if ($sortableheightmethod == 0) {
$height = "";
} else {
$height = "height:{$dims[1]};";
}
$mobile_padding = "";
if (defined(\'MOBILE_MODE\')) {
$mobile_padding = "padding:10px;";
}
if ((int)$exportmode != 3) {
$element .= "
<!-- OUTPUT START -->
";
$element .= $global_style_insert;
$element .= "
<div id=\"form-output-div-{$form_id}\" class=\"form-output-div ui form\" style=\"{$mobile_padding} {$fontfamily} {$bgstring} {$bgcolorstring} {$bgopacity_string} {$centerdefinition} {$boxshadow} {$borderradius} width:{$dims[0]}; {$height} {$border_css} \">";
}
if ($exportmode != 3) {
$element .= "
<form class=\"form-output-sortable\" action=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>{$action}<?php echo \$sid_url; ?>\" method=\"{$method}\" enctype=\"{$enctype}\" name=\"{$form_name}\" id=\"{$form_id}\" target=\"{$target}\" >
";
}
}
if ((int)$layout == 1) {
$element .= <<<EOF
<?php
\$css_width = \'width:{$dims[0]}; \';
\$css_height = \'height:{$dims[1]};\';
if(\$PAGE_IS_PDF == true) {
\$css_width = \'\';
\$css_height = \'\';
}
?>
EOF;
$element .= "
<?php if(\$PDF_LIBRARY == \'DOMPDF\' || \$PAGE_IS_PDF != true && \$PDF_LIBRARY != \'MPDF\') { ?>";
$element .= "
<!-- FORM_HEAD_START -->
";
$element .= "<div id=\"form-output-div-{$form_id}\" class=\"form-output-div\" style=\"position:relative; {$fontfamily} <?php echo \$css_width; echo \$css_height; ?>{$bgstring} {$bgcolorstring} {$bgopacity_string} {$centerdefinition} {$boxshadow} {$borderradius} {$border_css} \">";
if ($exportmode != 3) {
$element .= "
<form class=\"form-output\" action=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>{$action}<?php echo \$sid_url; ?>\" method=\"{$method}\" enctype=\"{$enctype}\" name=\"{$form_name}\" id=\"{$form_id}\" target=\"{$target}\" >";
}
$element .= "
<!-- FORM_HEAD_END -->
";
$element .= "<?php } ?>
";
if ($bgstring != "") {
$element .= <<<EOF
<?php
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true) {
echo \'<style>\';
echo "body { background-image: url({\$_SESSION[\'MAX_PATH\']}background/{$bgfile}); background-image-resize:6; }";
echo \'</style>\';
}
?>
EOF;
}
}
$geo_code = "";
if ($geodata != "" && ($geodata == "1" || $geodata == "2")) {
$use_gmaps = \'false\';
if ($geodata == "2") {
$use_gmaps = \'true\';
}
$geo_code = <<<EOF
<!--GeoData-->
<input type="hidden" name="geo_lat" id="geo_lat" value="" />
<input type="hidden" name="geo_long" id="geo_long" value="" />
<input type="hidden" name="geo_accuracy" id="geo_accuracy" value="" />
<input type="hidden" name="geo_altitude" id="geo_altitude" value="" />
<input type="hidden" name="geo_heading" id="geo_heading" value="" />
<input type="hidden" name="geo_speed" id="geo_speed" value="" />
<input type="hidden" name="geo_timestamp" id="geo_timestamp" value="" />
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<article style="display:block;">
<p>Location status: <span id="geo_status">checking...</span></p>
</article>
<script>
function geo_success(position) {
// Populate Hidden Field Items.
document.getElementById("geo_lat").value = position.coords.latitude;
document.getElementById("geo_long").value = position.coords.longitude;
document.getElementById("geo_accuracy").value = position.coords.accuracy;
document.getElementById("geo_altitude").value = position.coords.altitude;
document.getElementById("geo_heading").value = position.coords.heading;
document.getElementById("geo_speed").value = position.coords.speed;
document.getElementById("geo_timestamp").value = position.coords.timestamp;
var s = document.querySelector(\'#geo_status\');
if (s.className == \'success\') {
return;
}
s.innerHTML = "Location found!";
s.className = \'success\';
var use_gmaps = {$use_gmaps};
if(use_gmaps){
var mapcanvas = document.createElement(\'div\');
mapcanvas.id = \'mapcanvas\';
mapcanvas.style.height = \'400px\';
mapcanvas.style.width = \'560px\';
document.querySelector(\'article\').appendChild(mapcanvas);
var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var myOptions = {
zoom: 15,
center: latlng,
mapTypeControl: false,
navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL},
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("mapcanvas"), myOptions);
var marker = new google.maps.Marker({
position: latlng,
map: map,
title:"You are here! (at least within a "+position.coords.accuracy+" meter radius)"
});
}
}
function error(msg) {
var s = document.querySelector(\'#geo_status\');
s.innerHTML = typeof msg == \'string\' ? msg : "failed";
s.className = \'fail\';
// console.log(arguments);
}
function geo_locate(){
if (navigator.geolocation) {
document.getElementById("geo_status").innerHTML = "checking...";
navigator.geolocation.getCurrentPosition(geo_success, error);
} else {
error(\'not supported\');
}
}
// Call geo service
geo_locate();
</script>
<span id="geo_status"></span>
<!--GeoData-->
EOF;
}
$element .= \'\';
$element .= $geo_code;
return $element;
}
public function create_form_end($layout, $traphit, $tablemode, $exportmode)
{
$element = \'\';
if ($exportmode != 3) {
$element .= "
</form>";
}
if (($layout == 0 || $layout == 2) && $traphit == 0) {
$element .= $this->create_error_catch_sortable($tablemode, $exportmode);
if ((int)$exportmode != 3) {
$element .= "
<div class=\"clearing-div\" style=\"clear:both;\"></div>
</div>";
}
} elseif ($layout == 1 && $traphit == 0) {
$element .= $this->create_error_catch_freeform($tablemode, $exportmode);
$element .= "
</div><!-- FORM_TAIL_END -->";
} else {
$element .= "</div>";
}
return $element;
}
public function create_errortrap($tablemode, $exportmode)
{
if ((int)$exportmode > 1)
return "";
$element = "";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$element .= "
" . \'<?php if(isset($_SESSION["e_message"])){ ?>\' . "
";
$element .= \'<div class="err-msg" style="border:1px #efefef solid;"><?php echo html_entity_decode($_SESSION["e_message"], ENT_QUOTES); ?></div>\';
$element .= "
" . \'<?php unset($_SESSION["e_message"]); } ?>\' . "
";
if ((int)$tablemode->enabletablelayout == 1) {
$element .= "</div>";
}
return $element;
}
public function create_error_catch_sortable($tablemode, $exportmode)
{
if ((int)$exportmode > 1)
return "";
$element = "";
if ((int)$tablemode->enabletablelayout == 1) {
$bottom_margin_value = intval($tablemode->marginbottom);
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; margin-bottom:{$bottom_margin_value}px;\">";
}
$element .= "
" . \'<?php if(isset($_SESSION["e_message"])){ ?>\' . "
";
$element .= \'<div class="err-msg"><?php echo html_entity_decode($_SESSION["e_message"], ENT_QUOTES); ?></div>\';
$element .= "
" . \'<?php unset($_SESSION["e_message"]); } ?>\' . "
";
if ((int)$tablemode->enabletablelayout == 1) {
$element .= "</div>";
}
return $element;
}
public function create_error_catch_freeform($tablemode, $exportmode)
{
if ((int)$exportmode > 1)
return "";
$element = "";
if ((int)$tablemode->enabletablelayout == 1) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; margin-bottom:{$bottom_margin_value}px; \">";
}
$element = "
" . \'<?php if(isset($_SESSION["e_message"])){ ?>\' . "
";
$element .= \'<div class="err-msg" style=" border:0px #efefef solid; position:absolute; margin-bottom:-5px; bottom:-100px; height:100px; left:20px;"><?php echo html_entity_decode($_SESSION["e_message"], ENT_QUOTES); ?></div>\';
$element .= "
" . \'<?php unset($_SESSION["e_message"]); } ?>\' . "
";
if ((int)$tablemode->enabletablelayout == 1) {
$element .= "</div>";
}
return $element;
}
public function create_ul_start()
{
return "<ul>";
}
public function create_ul_end()
{
return "</ul>";
}
public function create_bucket_start(
$field,
$valid_bucket_names,
$contained_fields,
$contained_wrapper_classes,
$contained_conditionals,
$contained_validation
) {
$wrapperclass = (string)$field->wrapperclass;
$bucket_width = "";
$bucket_height = (int)$field->bucket_height;
$repeater_controls = \'\';
$valid_names = implode(\',\', $valid_bucket_names);
$contained_fields_var = \'array(\';
$i = 0;
foreach ($contained_fields as $key => $cf) {
if ($i != 0) {
$contained_fields_var .= \', \';
}
$contained_fields_var .= "\'{$key}\'=>\'{$cf}\'";
$i++;
}
$contained_fields_var .= \');\';
$contained_validation_var = \'array(\';
$i = 0;
foreach ($contained_validation as $key => $cf) {
if ($i != 0) {
$contained_validation_var .= \', \';
}
$contained_validation_var .= "\'{$key}\'=>\'{$cf}\'";
$i++;
}
$contained_validation_var .= \');\';
$contained_wrapper_classes_var = \'array(\';
$i = 0;
foreach ($contained_wrapper_classes as $key => $cf) {
if ($i != 0) {
$contained_wrapper_classes_var .= \', \';
}
$contained_wrapper_classes_var .= "\'{$cf}\'";
$i++;
}
$contained_wrapper_classes_var .= \');\';
$contained_conditionals_eof_var = "";
$contained_conditionals_var = \'array(\';
$i = 0;
foreach ($contained_conditionals as $key => $cf) {
$contained_conditionals_eof_var .= "
\$conditional_{$key} = <<<EOF
";
$contained_conditionals_eof_var .= $cf;
$contained_conditionals_eof_var .= "
EOF;
";
if ($i != 0) {
$contained_conditionals_var .= \', \';
}
$contained_conditionals_var .= "\'{$key}\'=>\$conditional_{$key}";
$i++;
}
$contained_conditionals_var .= \');\';
$add_animation = \'\';
$remove_animation = \'\';
switch ($field->repeater->add_animation) {
case 1:
$add_animation = \'blind\';
break;
case 2:
$add_animation = \'fade\';
break;
}
switch ($field->repeater->remove_animation) {
case 1:
$remove_animation = \'blind\';
break;
case 2:
$remove_animation = \'fade\';
break;
}
$limit_message = \'\';
if (isset($field->repeater->limitmessage)) {
$limit_message = str_replace("\'", \'`\', $field->repeater->limitmessage);
}
if (isset($field->repeater) && (string)$field->repeater->enabled == \'1\') {
$js = "";
if (isset($field->repeater->js) && $field->repeater->js != "") {
$js = <<<EIF
<script type="text/javascript">
// Custom Repeater JavaScript.
{$field->repeater->js}
</script>
EIF;
}
$observe_code = "";
if ((string)$field->repeater->jslibrary == "0") {
$observe_code = <<<EOF
<script type="text/javascript">
// BucketStart
$( document ).ready(function() {
bucket_repeater.load(\'{$field->name}\', \'fb_fld-{$field->name}\');
});
// BucketEnd
</script>
EOF;
}
if ((string)$field->repeater->jslibrary == "1") {
$observe_code = <<<EOF
<script type="text/javascript">
// BucketStart
document.observe(\'dom:loaded\', function(l){
bucket_repeater.load(\'{$field->name}\', \'fb_fld-{$field->name}\');
});
// BucketEnd
</script>
EOF;
}
if (!isset($field->repeater->controls))
$field->repeater->controls = \'0\';
$control_style = "display:inline;";
$control_class = "controls-visible";
if ($field->repeater->controls == 1) {
$control_style = "display:none;";
$control_class = "controls-hidden";
}
if (isset($field->repeater->limit) && $field->repeater->limit == "")
$field->repeater->limit = 99999;
$button_add = "<img class=\"bucket-add-button {$control_class}\" style=\"cursor:pointer; {$control_style}\" src=\"bucket-repeater/img/button-duplicate.png\" title=\"(Add Item)\" onClick=\"bucket_repeater.add(\'{$field->name}\', this, \'{$add_animation}\')\" />";
if(isset($field->repeater->addtext) && trim($field->repeater->addtext) != ""){
$button_add = "<button type=\"button\" class=\"bucket-control-button bucket-control-button-text-add {$control_class}\" style=\"cursor:pointer; {$control_style}\" onclick=\"bucket_repeater.add(\'{$field->name}\', this, \'{$add_animation}\')\">{$field->repeater->addtext}</button>";
}
$button_remove = "<!-- bucket-repeater-minus-button --><span class=\"\" ><img src=\"bucket-repeater/img/button-blank.png\" title=\"\" /></span>";
$button_remove_session_element = "";
if(isset($field->repeater->removetext) && trim($field->repeater->removetext) != ""){
$button_remove = "<!-- bucket-repeater-remove-button -->";
$button_remove_session_element = \'<button type="button" style="cursor:pointer;" class="bucket-control-button bucket-control-button-text-remove" onclick="bucket_repeater.remove(BUTTON_POST_NAME, BUTTON_BUCKET_NAME_PATH, this, BUTTON_BUCKET_REMOVE_ANIMATION)">\' . $field->repeater->removetext . \'</button>\';
}
$repeater_controls = <<<EOF
<?php
// main control
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb-bucket-repeater\'] = true;
// initialize main data container
if(!isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}"])){
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}"] = array();
}
// initialize contained field names
\$contained_fields = {$contained_fields_var}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-contained-fields"] = \$contained_fields;
// initialize contained validation
\$contained_validation = {$contained_validation_var}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-contained-validation"] = \$contained_validation;
// wrapper classes associated with this bucket
\$contained_wrapper_classes = {$contained_wrapper_classes_var}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-contained-wrapper-classes"] = \$contained_wrapper_classes;
// conditional calls associated with this bucket
{$contained_conditionals_eof_var}
\$contained_conditionals = {$contained_conditionals_var}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-contained-conditionals"] = \$contained_conditionals;
// initialize limit logic
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-limit"] = {$field->repeater->limit};
// Build 885 - Controls logic
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-controls"] = {$field->repeater->controls};
// limit message
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-limit-message"] = \'{$limit_message}\';
// remove animation
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-remove-animation"] = \'{$remove_animation}\';
// valid bucket names, must match any passed via AJAX calls
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'fb-valid-bucket-names\'] = array({$valid_names});
// Custom Remove Button
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'bucket-repeater\']["{$field->name}-remove-button"] = \'{$button_remove_session_element}\';
?>
{$observe_code}
{$js}
<div class="bucket-repeater-controls" style="position:absolute; right:0px; top:8px; height:50px; z-index:9999999;">
{$button_remove}
<span class="button-control-spacer"></span>
<span>
{$button_add}
</span>
</div>
EOF;
}
$bucket_responsive_class = isset($field->repeater->responsive) && (int)$field->repeater->responsive == 1 ? \'responsive-bucket\' : \'standard-bucket\';
if (!isset($field->repeater->fieldset) || (int)$field->repeater->fieldset == 0) {
$html = <<<EOT
<!-- bucket start -->
<div id="{$field->name}" class="bucket {$bucket_responsive_class}" style="position:relative; height:{$bucket_height}px; width:{$bucket_width}; {$field->attributestyle}" >
{$repeater_controls}
EOT;
}
if (isset($field->repeater->fieldset) && (int)$field->repeater->fieldset == 1) {
$html = <<<EOT
<!-- bucket start -->
<fieldset id="{$field->name}" class="bucket {$bucket_responsive_class} fieldset" style="position:relative; height:{$bucket_height}px; width:{$bucket_width}; {$field->attributestyle}" >
<legend>{$field->repeater->legend}</legend>
{$repeater_controls}
EOT;
}
return $html;
}
public function create_bucket_end($field, $used_fieldset)
{
$html = "";
$html .= "<div class=\"clearing-div\" style=\"clear:both;\"></div>";
if ($used_fieldset == false) {
$html .= "
</div><!-- bucket end -->
";
} else {
$html .= "
</fieldset><!-- bucket end -->
";
}
return $html;
}
public function create_block($field, $page, $bucket_node = "")
{
$tablemode = $page->tablemode;
$exportmode = (int)$page->exportmode;
$elt = \'\';
$block_code = $this->uv->replace_session_raw_for_code_block($field->block->code, 0);
$block_code = $this->uv->replace_all($block_code, 6);
$block_code = $this->uv->replace_field_raw($block_code, 0);
$block_code = $this->uv->replace_get_raw($block_code, 0);
$block_code = $this->uv->replace_post_raw($block_code, 0);
$block_code = $this->uv->replace_field_heredoc($block_code, 0);
if (!isset($field->block->css)) {
$field->block->css = "";
}
$block_css = $this->uv->replace_session_raw_for_code_block($field->block->css, 0);
$block_css = $this->uv->replace_all($block_css, 6);
$block_css = $this->uv->replace_field_raw($block_css, 0);
$block_css = $this->uv->replace_get_raw($block_css, 0);
$block_css = $this->uv->replace_post_raw($block_css, 0);
$block_css = $this->uv->replace_field_heredoc($block_css, 0);
if (!isset($field->block->js)) {
$field->block->js = "";
}
$block_js = $this->uv->replace_session_raw_for_code_block($field->block->js, 0);
$block_js = $this->uv->replace_all($block_js, 6);
$block_js = $this->uv->replace_field_raw($block_js, 0);
$block_js = $this->uv->replace_get_raw($block_js, 0);
$block_js = $this->uv->replace_post_raw($block_js, 0);
$block_js = $this->uv->replace_field_heredoc($block_js, 0);
if ((int)$field->block->enabled == 3) {
if ($block_css != "") {
if ($exportmode != 3) {
$elt .= "
<!-- Block CSS Start -->
";
}
$elt .= "<style type=\"text/css\">
" . $block_css . "
</style>";
if ($exportmode != 3) {
$elt .= "
<!-- Block CSS End -->
";
}
}
if ($block_js != "") {
if ($exportmode != 3) {
$elt .= "
<!-- Block JS Start -->
";
}
$elt .= "<script type=\"text/javascript\">
" . $block_js . "
</script>";
if ($exportmode != 3) {
$elt .= "
<!-- Block JS End -->
";
}
}
$elt .= $block_code;
return $elt;
}
if ((int)$field->block->enabled != 0) {
if (isset($field->block->autoiframeresize) && ((string)$field->block->autoiframeresize == \'0\' || (string)$field->block->autoiframeresize == \'1\')) {
$has_iframe = false;
$has_iframe_id = false;
$iframe_id = "";
if (substr_count($block_code, \'iframe\') != 0) {
$has_iframe = true;
$iframe_start = strpos($block_code, \'<iframe>\');
$iframe_end = strpos($block_code, \'</iframe>\');
$sub_string = substr($block_code, $iframe_start, $iframe_end - $iframe_start);
$has_iframe_id = substr_count($sub_string, \'id=\') == 0 ? false : true;
}
if ($has_iframe && $has_iframe_id) {
$tail_of_iframe = explode(\'id=\', $sub_string);
if (isset($tail_of_iframe[1])) {
$iframe_id = explode(\'"\', $tail_of_iframe[1]);
$iframe_id = $iframe_id[1];
}
}
if ($iframe_id != "") {
$elt .= <<<EOF
<script type="text/javascript">
// Size Adjustments
var _RACKFORMS_PADDING_HEIGHT_ = 10;
var _RACKFORMS_PADDING_WIDTH_ = 200;
var _IFRAME_RESIZE_TIME_ = 500;
var _IFRAME_RESIZE_TIME_CLEAR_ = 8000;
var width_offset = 0;
var height_offset = 0;
var set_height = true;
var set_width = false;
// resize window logic
function resize_id_{$field->id}(obj) {
var resize_mode = {$field->block->autoiframeresize};
var ifrm = document.getElementById(\'{$iframe_id}\');
if(ifrm == null)
return;
ifrm = (ifrm.contentWindow) ? ifrm.contentWindow : (ifrm.contentDocument.document) ? ifrm.contentDocument.document : ifrm.contentDocument;
var oContent = ifrm.document;
if(oContent.obj == false)
return;
// Resize To iFrame Contents Only.
if(resize_mode == 0){
var h = parseInt(getRFOutputDIVHeight(oContent), 10);
var w = parseInt(getRFOutputDIVHeight(oContent), 10);
}
// Resize To Use Entire Parent Window.
if(resize_mode == 1){
var oWinSize = getWinSize();
var h = oWinSize.height - parseInt(getDocHeight(oContent), 10);
var w = oWinSize.width - parseInt(getDocWidth(oContent), 10);
}
h = h - height_offset;
w = w - width_offset;
if (h > 0 && w > 0) {
if(set_height)
document.getElementById(\'{$iframe_id}\').style.height = h.toString() + "px";
if(set_width)
document.getElementById(\'{$iframe_id}\').style.width = w.toString() + "px";
}
};
var initial_resize_interval_{$field->id};
function clear_initial_resize_timer_{$field->id}(){
window.clearInterval(initial_resize_interval_{$field->id});
}
// handle onload()
DomReady.ready(function() {
// always resize iframe on page load
initial_resize_interval_{$field->id} = setInterval(resize_id_{$field->id}, _IFRAME_RESIZE_TIME_);
// clear initial resize after a set time * Build 891 - Disabled.
//window.setTimeout(clear_initial_resize_timer_{$field->id}, _IFRAME_RESIZE_TIME_CLEAR_);
// always enable the resize event handler
window.onresize = function() { resize_id_{$field->id}(); };
});
</script>
EOF;
}
}
$elt .= $block_code;
if ($exportmode != 3) {
$elt .= "
<!-- Block Code End -->
";
}
if ($block_css != "") {
if ($exportmode != 3) {
$elt .= "
<!-- Block CSS Start -->
";
}
$elt .= "<style type=\"text/css\">
" . $block_css . "
</style>";
if ($exportmode != 3) {
$elt .= "
<!-- Block CSS End -->
";
}
}
if ($block_js != "") {
if ($exportmode != 3) {
$elt .= "
<!-- Block JS Start -->
";
}
$elt .= "<script type=\"text/javascript\">
" . $block_js . "
</script>";
if ($exportmode != 3) {
$elt .= "
<!-- Block JS End -->
";
}
}
}
return $elt;
}
public function create_li_start($field, $wrapperclass, $conditional, $page, $elementpos = "0")
{
if($wrapperclass == null){ $wrapperclass = ""; }
if ((int)$page->exportmode == 3 && ($field->type == "query" || $field->type == "block")) {
return "";
}
if ($field->type == "query" && isset($field->create_elements) && $field->create_elements != 1) {
return;
}
$id = null;
if (isset($field->id)) {
$id = $field->id;
}
$tablemode = $page->tablemode;
$dims = explode(\',\', $page->dim);
$width = $dims[0];
if (substr_count($width, \'%\') == 0) {
$width = $width . \'px\';
}
$field_class_name = \'form-field-wrapper\';
if ($field->type == \'bucket\') {
$field_class_name = \'form-field-wrapper-bucket\';
if ($field->repeater->width != "") {
$width = $field->repeater->width;
} else {
$width = $field->bucket_width;
}
if (is_numeric((string)$width) == true) {
$width = $width . \'px\';
}
}
$elt = "";
$enabled = \'\';
$visible_flag = (string)$conditional->visible == \'0\' ? "visible_false" : "visible_true";
if ($conditional != null) {
$visible = (string)$conditional->visible == \'0\' ? \' display:none; \' : \'\';
$enabled = (string)$conditional->visible == \'0\' ? \'disabled="disabled"\' : \'\';
} else {
$visible = \'display:block;\';
}
$elt .= <<<EOF
<?php \$visible = \'{$visible}\'; \$enabled = \'{$enabled}\'; ?>
EOF;
if (isset($conditional->visible_field) && isset($conditional->visible_value)) {
if ((string)$conditional->visible_field != "" && (string)$conditional->visible_value != "") {
$_fld = (string)$conditional->visible_field;
$reverse = isset($conditional->visible_reverse) ? (int)$conditional->visible_reverse : 0;
$val = $this->uv->replace_all((string)$conditional->visible_value, 4);
if ($conditional->visible_value == $val) {
$val = str_replace("\'", "\'", $val);
$val = "\'" . $val . "\'";
}
if ($reverse == 0) {
$elt .= <<<EOF
<?php
// `Show Field If` Logic.
if(isset(\$_SESSION[\'{$_fld}\'])){
\$val_check = {$val};
if(is_array(\$_SESSION[\'{$_fld}\'])){
if(in_array(\$val_check, \$_SESSION[\'{$_fld}\'])){
\$visible = \'display:block;\';
\$enabled = \'\';
}
} else {
if(\$_SESSION[\'{$_fld}\'] == \$val_check){
\$visible = \'display:block;\';
\$enabled = \'\';
} else {
\$visible = \'display:none;\';
}
}
}
?>
EOF;
} else {
$elt .= <<<EOF
<?php
// `Show Field If` Logic.
if(isset(\$_SESSION[\'{$_fld}\'])){
\$val_check = {$val};
if(is_array(\$_SESSION[\'{$_fld}\'])){
if(!in_array(\$val_check, \$_SESSION[\'{$_fld}\'])){
\$visible = \'display:block;\';
\$enabled = \'\';
}
} else {
if(\$_SESSION[\'{$_fld}\'] != \$val_check){
\$visible = \'display:block;\';
\$enabled = \'\';
} else {
\$visible = \'display:none;\';
}
}
}
?>
EOF;
}
}
}
if ($id == \'\') {
$id = $field->type . \'_\' . rand(100000, 900000);
}
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$width = \'100%\';
}
if (isset($tablemode->enabletablelayout) && (int)$tablemode->enabletablelayout == 1) {
$bottom_margin_value = (int)$page->sortableitemmarginbottom + 4;
$elt .= "
<!-- ~~~~~~~~~~~~~~~~ -->
";
$elt .= "<!-- SORTABLE FORM FIELD START -->
";
$elt .= "<!-- ~~~~~~~~~~~~~~~~ -->
";
$width = preg_replace(\'/[^0-9]/\', \'\', $tablemode->leftcolumnwidth) + preg_replace(\'/[^0-9]/\', \'\', $tablemode->rightcolumnwidth) + 5;
if (substr_count($width, \'%\') == 0) {
$width = intval($width) . \'px\';
}
$float_css = "float:left;";
if (isset($elementpos) && $elementpos == "2") {
$float_css = "";
}
$_width_patch = \'\';
if ($field->type == \'separator\') {
$width = \'100%\';
$_width_patch = \'width:100%;\';
}
if ($field->type == \'block\') {
if ($field->fieldwidth == \'\') {
$width = \'\';
$_width_patch = \'\';
} else {
$width = (string)$field->fieldwidth;
if (substr_count($field->fieldwidth, \'%\') == 0) {
$width = intval($field->fieldwidth) . \'px\';
}
}
}
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$_width_patch = \'width:100%;\';
$width = \'100%\';
}
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$_width_patch = \'width:100%;\';
$width = \'100%\';
}
if (isset($field->multiselect_container_margin) && $field->multiselect_container_margin != \'\') {
$bottom_margin_value = intval($field->multiselect_container_margin);
}
$elt .= "<div id=\"fb_fld-{$id}\" rf-field=\"true\" class=\"{$field_class_name} tablemode-wrapper-div {$wrapperclass} type-{$field->type}\" style=\"width:{$width}; display:block; margin-bottom:{$bottom_margin_value}px; float:left; clear:both; <?php echo \$visible; \${$visible_flag}; ?>\">";
$elt .= "
<!-- Open Container DIV -->";
$elt .= "
<div style=\"{$float_css} {$_width_patch} \" >
";
} else {
$margin_bottom = "10";
if (isset($page->sortableitemmarginbottom) && $page->sortableitemmarginbottom != "") {
$margin_bottom = (int)$page->sortableitemmarginbottom + 4;
}
if (isset($field->multiselect_container_margin) && $field->multiselect_container_margin != \'\') {
$margin_bottom = intval($field->multiselect_container_margin);
}
$float_css = "float:left;";
if (isset($elementpos) && $elementpos == "2") {
$float_css = "";
}
if ($field->type == \'separator\') {
if (isset($elementpos) && (int)$elementpos != "0") {
$width = \'100%\';
} else {
$width = $field->width;
}
}
if (isset($elementpos) && (int)$elementpos == "2") {
$width = "";
}
if ($field->type == \'block\') {
if ($field->fieldwidth == \'\') {
$width = \'\';
} else {
$width = (string)$field->fieldwidth;
if (substr_count($field->fieldwidth, \'%\') == 0) {
$width = intval($field->fieldwidth) . \'px\';
}
}
}
if ((int)$page->exportmode == 3) {
if ($field->type != "query" || $field->type != "block") {
$elt .= "
<!-- ~~~~~~~~~~~~~~~~ -->
";
$elt .= "<!-- FORM FIELD START -->
";
$elt .= "<!-- ~~~~~~~~~~~~~~~~ -->
";
$elt .= "<div id=\"fb_fld-{$id}\" rf-field=\"true\" class=\"{$field_class_name} {$wrapperclass} type-{$field->type}\" style=\"{$float_css} width:{$width}; margin-bottom:{$margin_bottom}px; <?php echo \$visible; \${$visible_flag}; ?>\" >
";
}
} else {
$elt .= "
<!-- ~~~~~~~~~~~~~~~~ -->
";
$elt .= "<!-- FORM FIELD START -->
";
$elt .= "<!-- ~~~~~~~~~~~~~~~~ -->
";
$elt .= "<div id=\"fb_fld-{$id}\" rf-field=\"true\" class=\"{$field_class_name} {$wrapperclass} type-{$field->type}\" style=\"{$float_css} width:{$width}; margin-bottom:{$margin_bottom}px; <?php echo \$visible; \${$visible_flag}; ?>\" >
";
}
}
if (isset($page->centerform) && (string)$page->centerform == "1") {
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
if (isset($elementpos) && $elementpos != "0") {
$tmp = explode(\',\', $page->dim);
$page_width = $tmp[0];
$fieldwidth = (((int)$page->pagepadding * 2) + $page_width) - ($field->style->paddingleft + $field->style->paddingright) . \'px\';
$elt .= "<div style=\"width: {$fieldwidth};\">";
return $elt;
}
}
}
if (isset($elementpos) && (int)$elementpos != "0") {
if ($elementpos == "2") {
if ($field->type == "checkbox" || $field->type == "radio" || $field->type == "ecomm" || $field->type == "survey") {
$elt .= "
<div style=\"width:50%; margin: 0 auto;\"><!-- open alignment div -->
";
} else {
$elt .= "
<div style=\"align-items: center; display: flex; justify-content: center;\"><!-- open flex alignment div -->
";
if ($field->type != "bodycopy" && $field->type != "sectionheader" && $field->type != "separator") {
$elt .= "
<div class=\"flex-grouping-div\"><!-- open flex-grouping-div -->
";
}
}
} else {
if ($elementpos == "1") {
$elementpos = 0;
}
$elt .= "
";
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$elt .= "<div style=\"margin-right: " . $elementpos . "px;\"><!-- Open Right Aligned Banner Mode Item -->";
} else {
if ($field->type == "bodycopy" || $field->type == "sectionheader" && $field->type != "separator") {
$elt .= "<div style=\"margin-right: " . $elementpos . "px; width:100%;\"><!-- Open Right Aligned Item -->";
} else {
$elt .= "<div style=\"margin-right: " . $elementpos . "px; float:right;\"><!-- Open Right Aligned Item -->";
}
}
$elt .= "
";
}
}
return $elt;
}
public function create_li_start_html_only($field, $wrapperclass, $conditional, $page, $elementpos = "0")
{
if ($wrapperclass == null) {
$wrapperclass = "";
}
$tablemode = $page->tablemode;
$dims = explode(\',\', $page->dim);
$width = $dims[0];
$id = isset($field->id) ? $field->id : \'\';
if (substr_count($width, \'%\') == 0) {
$width = $width . \'px\';
}
$field_class_name = \'form-field-wrapper\';
if ($field->type == \'bucket\') {
$field_class_name = \'form-field-wrapper-bucket\';
if ($field->repeater->width != "") {
$width = $field->repeater->width;
} else {
$width = $field->bucket_width;
}
if (is_numeric((string)$width) == true) {
$width = $width . \'px\';
}
}
$elt = "";
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$width = \'100%\';
}
if (isset($tablemode->enabletablelayout) && (int)$tablemode->enabletablelayout == 1) {
$bottom_margin_value = (int)$page->sortableitemmarginbottom + 4;
$width = preg_replace(\'/[^0-9]/\', \'\', $tablemode->leftcolumnwidth) + preg_replace(\'/[^0-9]/\', \'\', $tablemode->rightcolumnwidth) + 5;
if (substr_count($width, \'%\') == 0) {
$width = intval($width) . \'px\';
}
$float_css = "float:left;";
if (isset($elementpos) && $elementpos == "2") {
$float_css = "";
}
$_width_patch = \'\';
if ($field->type == \'separator\') {
$width = \'100%\';
$_width_patch = \'width:100%;\';
}
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$_width_patch = \'width:100%;\';
$width = \'100%\';
}
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$_width_patch = \'width:100%;\';
$width = \'100%\';
}
if (isset($field->multiselect_container_margin) && $field->multiselect_container_margin != \'\') {
$bottom_margin_value = intval($field->multiselect_container_margin);
}
$elt .= "<div id=\"fb_fld-{$id}\" rf-field=\"true\" class=\"{$field_class_name} {$wrapperclass} tablemode-wrapper-div type-{$field->type}\" style=\"width:{$width}; display:block; margin-bottom:{$bottom_margin_value}px; float:left; clear:both; \">";
$elt .= "<div style=\"{$float_css} {$_width_patch} \" >";
} else {
$margin_bottom = "10";
if (isset($page->sortableitemmarginbottom) && $page->sortableitemmarginbottom != "") {
$margin_bottom = (int)$page->sortableitemmarginbottom + 4;
}
if (isset($field->multiselect_container_margin) && $field->multiselect_container_margin != \'\') {
$margin_bottom = intval($field->multiselect_container_margin);
}
$float_css = "float:left;";
if (isset($elementpos) && $elementpos == "2") {
$float_css = "";
}
if ($field->type == \'separator\') {
if (isset($elementpos) && (int)$elementpos != "0") {
$width = \'100%\';
} else {
$width = $field->width;
}
}
if ((int)$page->exportmode == 3) {
if ($field->type != "query" || $field->type != "block") {
$elt .= "<div class=\"{$wrapperclass}\" style=\"{$float_css} width:{$width}; margin-bottom:{$margin_bottom}px; \" >";
}
} else {
$elt .= "<div class=\"{$wrapperclass}\" style=\"{$float_css} width:{$width}; margin-bottom:{$margin_bottom}px; \" >";
}
}
if (isset($page->centerform) && (string)$page->centerform == "1") {
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
if (isset($elementpos) && $elementpos != "0") {
$tmp = explode(\',\', $page->dim);
$page_width = $tmp[0];
$fieldwidth = (((int)$page->pagepadding * 2) + $page_width) - ($field->style->paddingleft + $field->style->paddingright) . \'px\';
$elt .= "<div style=\"width: {$fieldwidth};\">";
return $elt;
}
}
}
if (isset($elementpos) && (int)$elementpos != "0") {
if ($elementpos == "2") {
if ($field->type == "checkbox" || $field->type == "radio" || $field->type == "ecomm" || $field->type == "survey") {
$elt .= "<div style=\"width:50%; margin: 0 auto;\">";
} else {
$elt .= "<div style=\"align-items: center; display: flex; justify-content: center;\">";
if ($field->type != "bodycopy" && $field->type != "sectionheader" && $field->type != "separator") {
$elt .= "<div class=\"flex-grouping-div\">";
}
}
} else {
if (isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$elt .= "<div style=\"margin-right: " . $elementpos . "px;\">";
} else {
if ($field->type == "bodycopy" || $field->type == "sectionheader" && $field->type != "separator") {
$elt .= "<div style=\"margin-right: " . $elementpos . "px; width:100%;\">";
} else {
$elt .= "<div style=\"margin-right: " . $elementpos . "px; float:right;\">";
}
}
}
}
return $elt;
}
public function create_li_end($page, $field, $elementpos = "0")
{
if ((int)$page->exportmode == 3 && ($field->type == "query" || $field->type == "block")) {
return "";
}
if ($field->type == "query" && isset($field->create_elements) && $field->create_elements != 1) {
return;
}
$element = "";
if (isset($elementpos) && $elementpos != "0") {
if ($elementpos == "2") {
if ($field->type == "checkbox" || $field->type == "radio" || $field->type == "ecomm" || $field->type == "survey") {
$element .= "
</div><!-- close alignment div -->
";
} else {
$element .= "
</div><!-- close flex alignment div -->
";
if ($field->type != "bodycopy" && $field->type != "sectionheader" && $field->type != "separator") {
$element .= "
</div><!-- close flex-grouping-div -->
";
}
}
} else {
if ($elementpos == "1") {
$elementpos = 0;
}
$element .= "
</div><!-- Close Right Aligned DIV -->
";
}
}
if (isset($page->tablemode->enabletablelayout) && (int)$page->tablemode->enabletablelayout == 1) {
$element .= "
</div>
</div>
<!-- Table Mode Form Field End -->
";
} else {
$element .= "
</div>
<!-- Sortable Form Field End -->
";
}
$element .= "
<div class=\"clearing-div\" style=\"clear:both;\"></div><!-- Clear DIV -->
";
return $element;
}
public function create_li_end_html_only($page, $field, $elementpos = "0")
{
$element = "";
if (isset($elementpos) && $elementpos != "0") {
$element .= "</div>";
if ($elementpos == "2") {
if ($field->type == "checkbox" || $field->type == "radio" || $field->type == "ecomm" || $field->type == "survey") {
$element .= "</div>";
} else {
$element .= "</div>";
if ($field->type != "bodycopy" && $field->type != "sectionheader" && $field->type != "separator") {
$element .= "</div>";
}
}
}
}
if (isset($page->tablemode->enabletablelayout) && (int)$page->tablemode->enabletablelayout == 1) {
$element .= "</div></div>";
} else {
$element .= "</div>";
}
$element .= "<div class=\"clearing-div\" style=\"clear:both;\"></div>";
return $element;
}
public function createPositionDivStart($field, $bucket_node = "")
{
$cords = $field->cords;
$id = isset($field->id) && $field->id != "" ? $field->id : "";
$zindex = isset($field->zindex) && $field->zindex != "" ? $field->zindex : "";
$wrapperclass = $field->wrapperclass;
$conditional = $field->conditional;
$visible = (string)$conditional->visible == \'0\' ? \' display:none \' : \'display:block\';
if ($zindex == null || !is_numeric((int)$zindex)) {
$zindex = 1;
}
if ($id == \'\') {
$id = $field->type . \'_\' . rand(100000, 900000);
}
$xy = explode(\',\', $cords);
$xy[1] = $xy[1];
$width = "";
if (isset($field) && isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$width = \'width: 100%;\';
}
$field_class_name = \'form-field-wrapper\';
if ($field->type == \'bucket\') {
$field_class_name = \'form-field-wrapper-bucket\';
$bucket_repeater_width = (string)$field->repeater->width;
if ($bucket_repeater_width != "") {
$width = \'width:\' . (string)$field->repeater->width;
if (is_numeric((string)$field->repeater->width) == true) {
$width = $width . \'px;\';
} else {
$width = $width . \';\';
}
} else {
$width = \'width:\' . $field->bucket_width;
if (is_numeric((string)$field->bucket_width) == true) {
$width = $width . \'px;\';
} else {
$width = $width . \';\';
}
}
}
$elt = "";
$enabled = \'\';
$visible_flag = (string)$conditional->visible == \'0\' ? "visible_false" : "visible_true";
if ($conditional != null) {
$visible = (string)$conditional->visible == \'0\' ? \' display:none; \' : \'\';
$enabled = (string)$conditional->visible == \'0\' ? \'disabled="disabled"\' : \'\';
} else {
$visible = \'display:block;\';
}
$elt .= <<<EOF
<?php \$visible = \'{$visible}\'; \$enabled= \'{$enabled}\'; ?>
EOF;
if (isset($conditional->visible_field) && isset($conditional->visible_value)) {
if ((string)$conditional->visible_field != "" && (string)$conditional->visible_value != "") {
$_fld = (string)$conditional->visible_field;
$reverse = isset($conditional->visible_reverse) ? (int)$conditional->visible_reverse : 0;
$val = $this->uv->replace_all((string)$conditional->visible_value, 4);
if ($conditional->visible_value == $val) {
$val = str_replace("\'", "\'", $val);
$val = "\'" . $val . "\'";
}
if ($reverse == 0) {
$elt .= <<<EOF
<?php
if(isset(\$_SESSION[\'{$_fld}\'])){
\$val_check = {$val};
if(is_array(\$_SESSION[\'{$_fld}\'])){
if(in_array(\$val_check, \$_SESSION[\'{$_fld}\']))
\$visible = \'display:block;\';
} else {
if(\$_SESSION[\'{$_fld}\'] == \$val_check){
\$visible = \'display:block;\';
} else {
\$visible = \'display:none;\';
}
}
}
?>
EOF;
} else {
$elt .= <<<EOF
<?php
if(isset(\$_SESSION[\'{$_fld}\'])){
\$val_check = {$val};
if(is_array(\$_SESSION[\'{$_fld}\'])){
if(!in_array(\$val_check, \$_SESSION[\'{$_fld}\']))
\$visible = \'display:block;\';
} else {
if(\$_SESSION[\'{$_fld}\'] != \$val_check){
\$visible = \'display:block;\';
} else {
\$visible = \'display:none;\';
}
}
}
?>
EOF;
}
}
}
if ($xy[0] == \'NULL_RESPONSIVE\') {
$elt .= <<<EOF
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- POSITIONED FORM FIELD START -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<div id="fb_fld-{$id}" rf-field="true" class="{$field_class_name} {$wrapperclass} type-{$field->type} " style="<?php echo \$visible; \${$visible_flag}; ?> float:left; width:{$xy[1]}; padding-top:10px; z-index:{$zindex}; ">
EOF;
} else {
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$width = "width:100%;";
if (isset($field->fieldwidth))
$width = \'width:\' . $field->fieldwidth . \';\';
if ($field->type == \'bodycopy\' || $field->type == \'sectionheader\') {
$width = \'width:\' . $field->style->fieldwidth . \';\';
}
$margin_bottom = \'margin-bottom:15px;\';
if (isset($bucket_node->repeater->bottommargin) && $bucket_node->repeater->bottommargin != "") {
if (is_numeric((int)$bucket_node->repeater->bottommargin)) {
$margin_bottom = \'margin-bottom:\' . $bucket_node->repeater->bottommargin . \'px\';
}
}
$elt .= <<<EOF
<!-- Bucket Item - Responsive Form Field Start -->
<div id="fb_fld-{$id}" rf-field="true" class="responsive-bucket-item {$field_class_name} {$wrapperclass} type-{$field->type}" style="<?php echo \$visible; \${$visible_flag}; ?> float:left; {$width} z-index:{$zindex}; {$margin_bottom}">
EOF;
} else {
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$width = \'width: 100%;\';
}
if ($field->type == \'separator\') {
$width = \'width:\' . $field->width . \';\';
}
$elt .= <<<EOF
<!-- ~~~~~~~~~~~~~~~~ -->
<!-- FORM FIELD START -->
<!-- ~~~~~~~~~~~~~~~~ -->
<div id="fb_fld-{$id}" rf-field="true" class="{$field_class_name} {$wrapperclass} type-{$field->type}" style="<?php echo \$visible; \${$visible_flag}; ?> position:absolute; left:{$xy[0]}px; top:{$xy[1]}px; {$width} z-index:{$zindex}; ">
EOF;
}
}
return $elt;
}
function createPositionDivStart_html_only($field)
{
$cords = $field->cords;
$id = isset($field->id) && $field->id != "" ? $field->id : "";
$zindex = isset($field->zindex) && $field->zindex != "" ? $field->zindex : "";
$wrapperclass = $field->wrapperclass;
$conditional = $field->conditional;
$visible = (string)$conditional->visible == \'0\' ? \' display:none \' : \'display:block\';
if ($zindex == null || !is_numeric((int)$zindex)) {
$zindex = 1;
}
if ($id == \'\') {
$id = rand(100000, 900000);
}
$xy = explode(\',\', $cords);
$xy[1] = $xy[1];
$width = "";
if (isset($field) && isset($field->style->bannermode) && (int)$field->style->bannermode == 1) {
$width = \'width: 100%;\';
}
$field_class_name = \'form-field-wrapper\';
if ($field->type == \'bucket\') {
$field_class_name = \'form-field-wrapper-bucket\';
$bucket_repeater_width = (string)$field->repeater->width;
if ($bucket_repeater_width != "") {
$width = \'width:\' . (string)$field->repeater->width;
if (is_numeric((string)$field->repeater->width) == true) {
$width = $width . \'px;\';
} else {
$width = $width . \';\';
}
} else {
$width = \'width:\' . $field->bucket_width;
if (is_numeric((string)$field->bucket_width) == true) {
$width = $width . \'px;\';
} else {
$width = $width . \';\';
}
}
}
$elt = "";
$enabled = \'\';
if ($conditional != null) {
$visible = (string)$conditional->visible == \'0\' ? \' display:none; \' : \'\';
$enabled = (string)$conditional->visible == \'0\' ? \'disabled="disabled"\' : \'\';
} else {
$visible = \'display:block;\';
}
if ($xy[0] == \'NULL_RESPONSIVE\') {
$elt .= <<<EOF
<div id="fb_fld-{$id}" rf-field="true" class="{$field_class_name} {$wrapperclass} type-{$field->type}" style="float:left; width:{$xy[1]}; padding-top:10px; z-index:{$zindex}; ">
EOF;
} else {
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$width = "width:100%;";
if (isset($field->fieldwidth))
$width = \'width:\' . $field->fieldwidth . \';\';
if ($field->type == \'bodycopy\' || $field->type == \'sectionheader\') {
$width = \'width:\' . $field->style->fieldwidth . \';\';
}
$margin_bottom = \'margin-bottom:15px;\';
if (isset($bucket_node->repeater->bottommargin) && $bucket_node->repeater->bottommargin != "") {
if (is_numeric((int)$bucket_node->repeater->bottommargin)) {
$margin_bottom = \'margin-bottom:\' . $bucket_node->repeater->bottommargin . \'px\';
}
}
$elt .= <<<EOF
<div id="fb_fld-{$id}" rf-field="true" class="{$field_class_name} {$wrapperclass} type-{$field->type}" style="float:left; {$width} z-index:{$zindex}; {$margin_bottom}">
EOF;
} else {
if (isset($page->fullwidth) && $page->fullwidth == "1") {
$width = \'width: 100%;\';
}
if ($field->type == \'separator\') {
$width = \'width:\' . $field->width . \';\';
}
$elt .= <<<EOF
<div id="fb_fld-{$id}" rf-field="true" class="{$field_class_name} {$wrapperclass} type-{$field->type}" style="position:absolute; left:{$xy[0]}px; top:{$xy[1]}px; {$width} z-index:{$zindex}; ">
EOF;
}
}
return $elt;
}
public function createPositionDivEnd()
{
return "
</div>
<!-- Positioned Form Field End -->
";
}
public function createPositionDivEnd_html_only()
{
return "</div><!-- Positioned (HTML Only) Form Field End -->";
}
public function createTableModeLabel($element, $tablemode)
{
if ((int)$tablemode->enabletablelayout == 1) {
$tmp = <<<EOT
<div style="width:{$tablemode->leftcolumnwidth}; float:left;">
{$element}
</div>
EOT;
return $tmp;
} else {
return $element;
}
}
public function createTableModeElement($element, $tablemode)
{
if ((int)$tablemode->enabletablelayout == 1) {
$tmp = <<<EOT
<div style="width:{$tablemode->rightcolumnwidth}; float:left;">
{$element}
</div>
EOT;
return $tmp;
} else {
return $element;
}
}
public function create_ajax($field, $jobpath, $bind_count, $bind_index)
{
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
$page_code = "";
$tmp = array();
foreach ($field->selectitems as $s) {
$s = (array)$s;
if (is_array($s)) {
$tmp[] = $s;
}
}
$json_elements = $this->um->php_json_encode($tmp);
$first_bound_field = isset($tmp[0][\'fieldBinding\']) ? $tmp[0][\'fieldBinding\'] : \'\';
$second_bound_field = isset($tmp[1][\'fieldBinding\']) ? $tmp[1][\'fieldBinding\'] : \'\';
$third_bound_field = isset($tmp[2][\'fieldBinding\']) ? $tmp[2][\'fieldBinding\'] : \'\';
$fourth_bound_field = isset($tmp[3][\'fieldBinding\']) ? $tmp[3][\'fieldBinding\'] : \'\';
$fifth_bound_field = isset($tmp[4][\'fieldBinding\']) ? $tmp[4][\'fieldBinding\'] : \'\';
if (!isset($field->ajax_code_before_query)) {
$field->ajax_code_before_query = "";
}
if (!isset($field->ajax_code_after_query)) {
$field->ajax_code_after_query = "";
}
$ajax_processing_mode = \'std\';
switch ((int)$field->ajax_processing_mode) {
case 0:
$ajax_processing_mode = \'std\';
break;
case 1:
$ajax_processing_mode = \'proc\';
break;
}
$ajax_error_mode = \'false\';
switch ((int)$field->ajax_error_mode) {
case 0:
$ajax_error_mode = \'true\';
break;
case 1:
$ajax_error_mode = \'false\';
break;
}
$ajax_clear_text_fields = "true";
switch ((int)$field->ajax_clear_text_fields) {
case 0:
$ajax_clear_text_fields = \'true\';
break;
case 1:
$ajax_clear_text_fields = \'false\';
break;
}
if (!isset($field->ajax_source_field_2)) {
$field->ajax_source_field_2 = \'\';
}
if (!isset($field->ajax_source_field_3)) {
$field->ajax_source_field_3 = \'\';
}
if (!isset($field->ajax_source_field_4)) {
$field->ajax_source_field_4 = \'\';
}
if (!isset($field->ajax_source_field_5)) {
$field->ajax_source_field_5 = \'\';
}
$library = isset($field->ajax_processing_library) ? $field->ajax_processing_library : "1";
$listeners = "";
for ($_i = 0; $_i < $bind_count; $_i++) {
$listeners .= " handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
";
}
if ($library == "0") {
$page_code .= <<<EOF
<div style="display:none;" id="load-status-{$field->ajax_source_field}_{$bind_index}" class="fb-ajax-loader">Loading...</div>
<script type="text/javascript">
// RackForms AJAX Code - jQuery
if(typeof(\$j) != "undefined") {
$ = \$j;
}
// Call On Load...
$(function(){
bindAjax_{$field->ajax_source_field}_{$bind_index}();
});
// Or Call From Anywhere.
function bindAjax_{$field->ajax_source_field}_{$bind_index}() {
// bind event listener(s)
// what type of element is this check
is_select_or_text = false;
is_other = false;
is_select_or_text = $(\'#{$field->ajax_source_field}\').length;
if(is_select_or_text == 0){
is_other = true;
} else {
is_select_or_text = true;
}
if(is_select_or_text){
$(\'#{$field->ajax_source_field}\').{$this->translateConditionalAjaxEvent($field->ajax_event)}(function(){
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
});
}
if(is_other){
{$field->ajax_source_field}_{$bind_index}_items = $(\'#fb_fld-{$field->ajax_source_field} INPUT\');
// bind event listeners
{$field->ajax_source_field}_{$bind_index}_items.each(function(t){
$(this).bind (
"{$this->translateConditionalAjaxEvent($field->ajax_event)}",
function(){
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
}
)
// t.{$this->translateConditionalAjaxEvent($field->ajax_event)}(function(){
// handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
// });
});
}
// eval items
json_{$field->ajax_source_field}_{$bind_index} = $json_elements;
eval(json_{$field->ajax_source_field}_{$bind_index});
// Call for page load if a value has been selected.
if($("#{$field->ajax_source_field}").val() != ""){
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
}
};
// fetch a dynamic field value
function fetch_ajax_arg(field){
if(field == ""){
return "";
}
// what type of element is this check
is_select_or_text = false;
is_other = false;
is_select_or_text = $(\'#\' + field).length;
if(is_select_or_text == 0){
is_other = true;
} else {
is_select_or_text = true;
}
if(is_select_or_text){
return $(\'#\' + field).val();
}
if(is_other){
var items = $(\'#fb_fld-\' + field + \' INPUT\');
var val = \'\';
// bind event listeners
$(items).each(function(t, elt){
if($(this).prop(\'checked\')){
val = $(this).val();
}
});
return val;
}
};
function handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}(){
// user code before query
{$field->ajax_code_before_query}
// collect params
var params = {
arg1: fetch_ajax_arg(\'{$field->ajax_source_field}\'),
arg2: fetch_ajax_arg(\'{$field->ajax_source_field_2}\'),
arg3: fetch_ajax_arg(\'{$field->ajax_source_field_3}\'),
arg4: fetch_ajax_arg(\'{$field->ajax_source_field_4}\'),
arg5: fetch_ajax_arg(\'{$field->ajax_source_field_5}\'),
action: \'{$ajax_processing_mode}\'
};
clear_text_fields = {$ajax_clear_text_fields};
$.ajax({
type: "POST",
url: \'lib/ajax/fb_ajax_{$field->ajax_source_field}_{$bind_index}.php\',
data: params,
beforeSend: function(jqXHR, textStatus, errorThrown){
$(\'load-status-{$field->ajax_source_field}_{$bind_index}\').show();
},
error: function(jqXHR, textStatus, errorThrown){
error_mode = {$ajax_error_mode};
if(error_mode){
message = \'AJAX Exception: \' + errorThrown;
message += \'\n\nYou may wish to enable your browsers Console to see a more detailed reason why this error occurred. \';
message += \'For most browsers this is the F12 key, or if in Firefox with Firebug installed, by using Firebug\'s Console.\';
message += \'\n\nForm Creators: This class of issue usually indicates a database error.\';
message += \'\n\nPlease check your SQL Code block to ensure a proper query, and if being used, the Data Source properties for proper connection details.\';
alert(message); // error, exception message
}
}
})
.done(function( res ) {
if(res === undefined)
return;
$(\'#load-status-{$field->ajax_source_field}_{$bind_index}\').hide();
$(json_{$field->ajax_source_field}_{$bind_index}).each(function(idx, f){
//
// Clear Any Requested Fields.
//
if(f.fieldClear != ""){
var type = "";
if($("#" + f.fieldClear) && $("#" + f.fieldClear).length != 0){
var items = $("#" + f.fieldClear).map(function(index, elm) {
return {name: elm.name, type:elm.type, value: $(elm).val()};
});
var type = items[0].type;
// Support For AJAX Updates On All Fields
if(type === undefined){
var type = \'display-element\';
}
} else {
// checkboxes, radio, calendar
if($("#" + "date-" + f.fieldClear + \'-1\') && $("#" + "date-" + f.fieldClear + "-1").length != 0){
// Calendar item
var type = \'text\';
f.fieldClear = "date-" + f.fieldClear + "-1";
} else {
var i = 0;
// set the index for the items to add
while($("#" + f.fieldClear + i).length != 0 || i > 1000){
i++;
}
// Build 727 - get field type even if no items are present
if($("#" + f.fieldClear + (i - 1)).length != 0){
items = $("#" + f.fieldClear + (i - 1)).map(function(index, elm) {
return {name: elm.name, type:elm.type, value: $(elm).val()};
});
type = items[0].type;
} else {
// no items set, so get the type from the columns class
if(typeof($(\'#fb_fld-\' + f.fieldClear).find(\'.fb-multiselect-column\')) != "undefined" && $(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').hasClass(\'checkbox-column\')){
type = \'checkbox\';
} else if(typeof($(\'#fb_fld-\' + f.fieldClear).find(\'.fb-multiselect-column\')) != "undefined" && $(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').hasClass(\'radio-column\')){
type = \'radio\';
} else {
if($("#fb_fld-" + f.fieldClear) && $("#fb_fld-" + f.fieldClear).length != 0){
// Display Items Using Native RackForms Field Id.
type = \'display-element\';
}
}
}
}
}
if(type == \'select-one\'){
document.getElementById(f.fieldClear).options.length = 0;
var opt = document.createElement(\'option\');
opt.value = \'\';
opt.innerHTML = \'-- Select --\';
document.getElementById(f.fieldClear).appendChild(opt);
}
if(type == \'text\'){
document.getElementById(f.fieldClear).value = "";
}
if(type == \'checkbox\'){
var items = $(\'#fb_fld-\' + f.fieldClear + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
}
if(type == \'radio\'){
var items = $(\'#fb_fld-\' + f.fieldClear + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
}
if(type == \'display-element\'){
document.getElementById(f.fieldClear).innerHTML = "";
}
if(type == \'hidden\'){
document.getElementById(f.fieldClear).value = "";
}
} // Has `fieldClear`.
//
// Process Field Bindings.
//
if(f.fieldBinding != ""){
// Note: If no binding, skip processing code and just run any code after block.
// What Kind Of Field Is This?
var type = \'\';
if($("#" + f.fieldBinding) && $("#" + f.fieldBinding).length != 0){
var items = $("#" + f.fieldBinding).map(function(index, elm) {
return {name: elm.name, type:elm.type, value: $(elm).val()};
});
var type = items[0].type;
// Support For AJAX Updates On All Fields
if(type === undefined){
var type = \'display-element\';
}
} else {
// checkboxes, radio, calendar
if($("#" + "date-" + f.fieldBinding + \'-1\') && $("#" + "date-" + f.fieldBinding + "-1").length != 0){
// Calendar item
var type = \'text\';
f.fieldBinding = "date-" + f.fieldBinding + "-1";
} else {
var i = 0;
// set the index for the items to add
while($("#" + f.fieldBinding + i).length != 0 || i > 1000){
i++;
}
// Build 727 - get field type even if no items are present
if($("#" + f.fieldBinding + (i - 1)).length != 0){
items = $("#" + f.fieldBinding + (i - 1)).map(function(index, elm) {
return {name: elm.name, type:elm.type, value: $(elm).val()};
});
type = items[0].type;
} else {
// no items set, so get the type from the columns class
if(typeof($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\')) != "undefined" && $(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').hasClass(\'checkbox-column\')){
type = \'checkbox\';
} else if(typeof($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\')) != "undefined" && $(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').hasClass(\'radio-column\')){
type = \'radio\';
} else {
if($("#fb_fld-" + f.fieldBinding) && $("#fb_fld-" + f.fieldBinding).length != 0){
// Display Items Using Native RackForms Field Id.
type = \'display-element\';
}
}
}
}
}
// process fields (jQuery)
switch(type){
case \'select-one\' :
var _item = $("#" + f.fieldBinding);
_item[0].options.length = 0;
if(res != false){
$(res).each(function(idx, i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined) { value = label; }
sel = false;
_item[0].options[_item[0].options.length] = new Option(label, value, sel);
});
}
// Pre-populate from previous call if possible. - Not Used At The Moment.
/*
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'#{$first_bound_field}\').val(_test);
}
*/
// If Mobile Mode...
if ( $.mobile ) {
$(\'select\').selectmenu(\'refresh\');
}
break;
case \'text\' :
// Set text to blank if no value is found, clears values.
if(clear_text_fields){
$("#" + f.fieldBinding).val("");
}
if(res != false){
$(res).each(function(idx, i){
label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
label = decodeURIComponent(label);
if(typeof(label) != "undefined"){
var _current = $("#" + f.fieldBinding).val();
_current += label;
$("#" + f.fieldBinding).val(_current);
}
});
}
break;
case \'checkbox\' :
var idt = i;
var items = $(\'#fb_fld-\' + f.fieldBinding + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
if(clear_text_fields){
$(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').html(\'\');
}
if(res != false){
$(res).each(function(idx, i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined || value == \'\') { value = label; }
if(typeof(items.indexOf) == \'undefined\' || items.is(value) == false){
// create elements
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
var _checked = "";
if(_test != "" && _test == value){
_checked = "checked=\"checked\"";
}
var a = $(\'<input type="checkbox" name="\'+f.fieldBinding+\'[]" id="\'+f.fieldBinding + idt+\'" value="\'+value+\'" \' + _checked + \'>\');
var b = $(\'<label for="\'+f.fieldBinding + idt+\'">\'+label+\'</label>\');
var c = $(\'<br/>\');
// append to span
a.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
b.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
c.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
idt++;
}
});
}
break;
case \'radio\' :
var idt = i;
var items = $(\'#fb_fld-\' + f.fieldBinding + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
if(clear_text_fields){
$(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\').html(\'\');
}
if(res != false){
$(res).each(function(idx, i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined || value == \'\') { value = label; }
if(typeof(items.indexOf) == \'undefined\' || items.is(value) == false){
// create elements
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
var _checked = "";
if(_test != "" && _test == value){
_checked = "checked=\"checked\"";
}
var a = $(\'<input type="radio" name="\'+f.fieldBinding+\'" id="\'+f.fieldBinding + idt+\'" value="\'+value+\'" \' + _checked + \'>\');
var b = $(\'<label for="\'+f.fieldBinding + idt+\'">\'+label+\'</label>\');
var c = $(\'<br/>\');
// append to span
a.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
b.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
c.appendTo($(\'#fb_fld-\' + f.fieldBinding).find(\'.fb-multiselect-column\'));
idt++;
}
});
}
break;
case \'display-element\' : // used when a non-form element is defined
var _selectorPrefix = "";
if(document.getElementById(f.fieldBinding) == null){
_selectorPrefix = "fb_fld-";
}
if(clear_text_fields){
$("#" + _selectorPrefix + f.fieldBinding).empty();
}
if(res != false){
var _numColumns = res.length != 0 ? Object.keys(res[0]).length / 2 : 0; // First Column.
var _columnNames = [];
if(_numColumns != 0){
// For Each Property Check To See If It\'s Our Number Index Or Actual Name.
for (var property in res[0]) {
if (res[0].hasOwnProperty(property)) {
var _test = parseInt(property);
if(_test != property){
_columnNames.push(property);
}
}
}
}
// Start Display Wrapper.
var _html = \'<div class="ajax-display-table">\';
// Create Column Header(s).
$(_columnNames).each(function(i, header){
_html += \'<div class="ajax-display-header">\' + decodeURIComponent(header) + \'</div>\';
});
// Add Clearing Div To Separate Header And Content.
_html += \'<div class="ajax-display-clear-header"></div>\';
// Loop Over Items, Add To Main Template.
$(res).each(function(idx, _item){
for (var property in _item) {
if (_item.hasOwnProperty(property)) {
if(_columnNames.indexOf(property) != -1){
_html += \'<div class="ajax-display-element">\' + decodeURIComponent(_item[property]) + \'</div>\';
}
}
}
_html += \'<div class="ajax-display-clear-row"></div>\';
});
// Close Display Wrapper.
_html = _html + \'</div>\';
$("#" + _selectorPrefix + f.fieldBinding).html(_html);
} else {
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'#{$first_bound_field}\').val(_test);
}
}
break;
case \'hidden\' :
if(res !== undefined && res != false){
$(res).each(function(idx, i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
label = decodeURIComponent(label); // Build 864
$("#" + f.fieldBinding).val(label);
});
} else {
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
_test = decodeURIComponent(_test);
$(\'#{$first_bound_field}\').val(_test);
}
}
break;
default :
if(res !== undefined && res != false){
$(res).each(function(idx, i){
label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
label = decodeURIComponent(label);
$("#" + f.fieldBinding).html(label);
});
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'#{$first_bound_field}\').val(_test);
}
}
break;
}
} // if binding
}); // each
// user code after query
{$field->ajax_code_after_query}
});
}
</script>
EOF;
} else {
$page_code .= <<<EOF
<div style="display:none;" id="load-status-{$field->ajax_source_field}_{$bind_index}" class="fb-ajax-loader">Loading...</div>
<script type="text/javascript">
// RackForms AJAX Code - Prototype.js
document.observe(\'dom:loaded\', function(l){
bindAjax_{$field->ajax_source_field}_{$bind_index}();
});
function bindAjax_{$field->ajax_source_field}_{$bind_index}() {
// bind event listener(s)
// what type of element is this check
is_select_or_text = false;
is_other = false;
is_select_or_text = $(\'{$field->ajax_source_field}\');
if(is_select_or_text === null){
is_other = true;
} else {
is_select_or_text = true;
}
if(is_select_or_text){
$(\'{$field->ajax_source_field}\').observe(\'{$this->translateConditionalAjaxEvent($field->ajax_event)}\',
function() {
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
}
);
}
if(is_other){
{$field->ajax_source_field}_{$bind_index}_items = $$(\'#fb_fld-{$field->ajax_source_field} INPUT\');
// bind event listeners
{$field->ajax_source_field}_{$bind_index}_items.each(function(t){
t.observe(\'{$this->translateConditionalAjaxEvent($field->ajax_event)}\',
function(){
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
}
);
});
}
// eval items
json_{$field->ajax_source_field}_{$bind_index} = $json_elements;
eval(json_{$field->ajax_source_field}_{$bind_index});
// Call for page load if a value has been selected.
if(\$F("{$field->ajax_source_field}") != ""){
handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}();
}
};
// fetch a dynamic field value
function fetch_ajax_arg(field){
// what type of element is this check
is_select_or_text = false;
is_other = false;
is_select_or_text = $(field);
if(is_select_or_text === null){
is_other = true;
} else {
is_select_or_text = true;
}
if(is_select_or_text){
return \$F(field);
}
if(is_other){
items = $$(\'#fb_fld-\' + field + \' INPUT\');
var val = \'\';
// bind event listeners
items.each(function(t){
if(t.checked){
val = t.value;
}
});
return val;
}
};
function handle_FB_AJAX_{$field->ajax_source_field}_{$bind_index}(){
// user code before query
{$field->ajax_code_before_query}
// collect params
var params = {};
params[\'arg1\'] = fetch_ajax_arg(\'{$field->ajax_source_field}\');
params[\'arg2\'] = fetch_ajax_arg(\'{$field->ajax_source_field_2}\');
params[\'arg3\'] = fetch_ajax_arg(\'{$field->ajax_source_field_3}\');
params[\'arg4\'] = fetch_ajax_arg(\'{$field->ajax_source_field_4}\');
params[\'arg5\'] = fetch_ajax_arg(\'{$field->ajax_source_field_5}\');
params[\'action\'] = \'{$ajax_processing_mode}\';
clear_text_fields = {$ajax_clear_text_fields};
new Ajax.Request(\'lib/ajax/fb_ajax_{$field->ajax_source_field}_{$bind_index}.php\', {
method:\'post\',
evalJSON: true,
parameters: params,
onCreate: function() { $(\'load-status-{$field->ajax_source_field}_{$bind_index}\').show(); },
onComplete: function(response) {
// Build 692
if(response.responseJSON == null){
res = eval(response.responseText);
} else {
res = response.responseJSON;
}
// Build 764 - If we still have no res value, return (happens when we select --Select--
if(res === undefined)
return;
$(\'load-status-{$field->ajax_source_field}_{$bind_index}\').hide();
// rebuild target elements...
json_{$field->ajax_source_field}_{$bind_index}.each(function(f){
//
// Clear Any Requested Fields.
//
if(f.fieldClear != ""){
var type = "";
if($(f.fieldBinding)){
var type = $(f.fieldBinding).type;
// Build 700 - Support For AJAX Updates On All Fields
if(type === undefined){
var type = \'display-element\';
}
} else {
// checkboxes, radio, calendar
if($("#" + "date-" + f.fieldBinding + \'-1\') && $("#" + "date-" + f.fieldBinding + "-1").length != 0){
// Calendar item
var type = \'text\';
f.fieldBinding = "date-" + f.fieldBinding + "-1";
} else {
var i = 0;
// set the index for the items to add
while($(f.fieldBinding + i) || i > 1000){
i++;
}
// Build 727 - get field type even if no items are present
if($(f.fieldBinding + (i - 1))){
type = $(f.fieldBinding + (i - 1)).type; // we found a match
} else {
// no items set, so get the type from the columns class
if(typeof($(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\')) != "undefined" && $(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').hasClassName(\'checkbox-column\')) {
type = \'checkbox\';
} else if(typeof($(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\')) != "undefined" && $(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').hasClassName(\'radio-column\')) {
type = \'radio\';
} else {
if($("fb_fld-" + f.fieldBinding) && $("fb_fld-" + f.fieldBinding).length != 0) {
// Display Items Using Native RackForms Field Id.
type = \'display-element\';
}
}
}
}
}
if(type == \'select-one\'){
document.getElementById(f.fieldClear).options.length = 0;
var opt = document.createElement(\'option\');
opt.value = \'\';
opt.innerHTML = \'-- Select --\';
document.getElementById(f.fieldClear).appendChild(opt);
}
if(type == \'text\'){
document.getElementById(f.fieldClear).value = "";
}
if(type == \'checkbox\'){
var items = $(\'#fb_fld-\' + f.fieldClear + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
}
if(type == \'radio\'){
var items = $(\'#fb_fld-\' + f.fieldClear + \' input\');
items.each(function(idx, t){
items[idx] = $(t).val();
});
}
if(type == \'display-element\'){
document.getElementById(f.fieldClear).innerHTML = "";
}
if(type == \'hidden\'){
document.getElementById(f.fieldClear).value = "";
}
} // Has `fieldClear`.
//
// Process Field Bindings.
//
if(f.fieldBinding != ""){
// Note: If no binding, skip processing code and just run any code after block.
// What Kind Of Field Is This?
var type = "";
if($(f.fieldBinding)){
var type = $(f.fieldBinding).type;
// Build 700 - Support For AJAX Updates On All Fields
if(type === undefined){
var type = \'display-element\';
}
} else {
// checkboxes, radio, calendar
if($("#" + "date-" + f.fieldBinding + \'-1\') && $("#" + "date-" + f.fieldBinding + "-1").length != 0){
// Calendar item
var type = \'text\';
f.fieldBinding = "date-" + f.fieldBinding + "-1";
} else {
var i = 0;
// set the index for the items to add
while($(f.fieldBinding + i) || i > 1000){
i++;
}
// Build 727 - get field type even if no items are present
if($(f.fieldBinding + (i - 1))){
type = $(f.fieldBinding + (i - 1)).type; // we found a match
} else {
// no items set, so get the type from the columns class
if(typeof($(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\')) != "undefined" && $(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').hasClassName(\'checkbox-column\')) {
type = \'checkbox\';
} else if(typeof($(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\')) != "undefined" && $(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').hasClassName(\'radio-column\')) {
type = \'radio\';
} else {
if($("fb_fld-" + f.fieldBinding) && $("fb_fld-" + f.fieldBinding).length != 0) {
// Display Items Using Native RackForms Field Id.
type = \'display-element\';
}
}
}
}
}
// process fields
switch(type){
case \'select-one\' :
$(f.fieldBinding).options.length = 0;
if(res != false){
res.each(function(i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined) { value = label; }
sel = false;
$(f.fieldBinding).options[$(f.fieldBinding).options.length] = new Option(label, value, sel);
}.bind(f));
}
// Pre-populate from previous call if possible. Not Used At The Moment.
/*
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'{$first_bound_field}\').setValue(_test);
}
*/
// If Mobile Mode...
if ( $.mobile ) {
$(\'select\').selectmenu(\'refresh\');
}
break;
case \'text\' :
// Set text to blank if no value is found, clears values.
if(clear_text_fields){
$(f.fieldBinding).value = "";
}
if(res != false){
res.each(function(i){
label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
label = decodeURIComponent(label);
$(f.fieldBinding).value = label;
}.bind(f));
}
// Pre-populate from previous call if possible.
// Build 866 - Not needed, causes any submitted form to retain values.
/*
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'{$first_bound_field}\').setValue(_test);
}
*/
break;
case \'checkbox\' :
var idt = i;
var items = $$(\'#fb_fld-\' + f.fieldBinding + \' input\');
items = items.pluck(\'value\');
// handle cases where exisitng values (ints) are implicitly changed to strings.
items.each(function(t, index){
if(parseInt(t) !== NaN){
items[index] = parseInt(t);
}
});
if(clear_text_fields){
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').update(\'\');
}
if(res != false){
res.each(function(i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined || value == \'\') { value = label; }
if(typeof(items.indexOf) == \'undefined\' || items.indexOf(value) == -1){
// create element
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
var _checked = false;
if(_test != "" && _test == value){
_checked = true;
}
var a = new Element(\'input\', { \'type\': \'checkbox\', \'value\': value, \'name\' : f.fieldBinding + \'[]\', \'id\' : f.fieldBinding + idt, checked: _checked });
var b = new Element(\'label\', { \'for\': f.fieldBinding + idt }); b.update(\' \' + label);
var c = new Element(\'br\', { });
// append to span
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(a);
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(b);
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(c);
idt++;
}
}.bind(f));
}
break;
case \'radio\' :
var idt = i;
var items = $$(\'#fb_fld-\' + f.fieldBinding + \' input\');
items = items.pluck(\'value\');
// handle cases where exisitng values (ints) are implicitly changed to strings.
items.each(function(t, index){
if(parseInt(t) !== NaN){
items[index] = parseInt(t);
}
});
if(clear_text_fields){
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').update(\'\');
}
if(res != false){
res.each(function(i){
var label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
var value = i[f.dbValueBinding] === undefined ? i.fb_append === undefined ? \'\' : i[1] : i[f.dbValueBinding];
label = decodeURIComponent(label);
value = decodeURIComponent(value);
if(value === undefined || value == \'\') { value = label; }
if(typeof(items.indexOf) == \'undefined\' || items.indexOf(value) == -1){
// create element
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
var _checked = false;
if(_test != "" && _test == value){
_checked = true;
}
var a = new Element(\'input\', { \'type\': \'radio\', \'value\': value, \'name\' : f.fieldBinding, \'id\' : f.fieldBinding + idt, checked: _checked });
var b = new Element(\'label\', { \'for\': f.fieldBinding + idt }); b.update(label);
var c = new Element(\'br\', { });
// append to span
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(a);
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(b);
$(\'fb_fld-\' + f.fieldBinding).down(\'.fb-multiselect-column\').insert(c);
idt++;
}
}.bind(f));
}
break;
case \'display-element\' : // used when a non-form element is defined
var _selectorPrefix = "";
if(document.getElementById(f.fieldBinding) == null){
_selectorPrefix = "fb_fld-";
}
if(clear_text_fields){
$(_selectorPrefix + f.fieldBinding).empty();
}
if(res != false){
var _numColumns = res.length != 0 ? Object.keys(res[0]).length / 2 : 0; // First Column.
var _columnNames = [];
if(_numColumns != 0){
// For Each Property Check To See If It\'s Our Number Index Or Actual Name.
for (var property in res[0]) {
if (res[0].hasOwnProperty(property)) {
var _test = parseInt(property);
if(_test != property){
_columnNames.push(property);
}
}
}
}
// Start Display Wrapper.
var _html = \'<div class="ajax-display-table">\';
// Create Column Header(s).
$(_columnNames).each(function(header){
_html += \'<div class="ajax-display-header">\' + decodeURIComponent(header) + \'</div>\';
});
// Add Clearing Div To Separate Header And Content.
_html += \'<div class="ajax-display-clear-header"></div>\';
// Loop Over Items, Add To Main Template.
$(res).each(function(_item){
for (var property in _item) {
if (_item.hasOwnProperty(property)) {
if(_columnNames.indexOf(property) != -1){
_html += \'<div class="ajax-display-element">\' + decodeURIComponent(_item[property]) + \'</div>\';
}
}
}
_html += \'<div class="ajax-display-clear-row"></div>\';
});
// Close Display Wrapper.
_html = _html + \'</div>\';
$(_selectorPrefix + f.fieldBinding).update(_html);
}
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'{$first_bound_field}\').setValue(_test);
}
break;
case \'hidden\' :
if(res !== undefined && res != false){
res.each(function(i){
var value = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
value = decodeURIComponent(label);
$(f.fieldBinding).value = value;
}.bind(f));
}
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'{$first_bound_field}\').setValue(_test);
}
break;
default :
if(res !== undefined && res != false){
res.each(function(i){
label = i[f.dbLabelBinding] === undefined ? i[0] : i[f.dbLabelBinding];
label = decodeURIComponent(label);
$(f.fieldBinding).value = label;
}.bind(f));
// Pre-populate from previous call if possible.
var _test = "<?php echo isset(\$_SESSION[\'{$first_bound_field}\']) ? \$_SESSION[\'{$first_bound_field}\'] : \'\' ?>";
if(_test != ""){
$(\'{$first_bound_field}\').setValue(_test);
}
}
break;
}
} // if binding
}); // each
// user code after query
{$field->ajax_code_after_query}
},
// Build 747
onException: function(e, exceptionObject){
error_mode = {$ajax_error_mode};
if(error_mode){
message = \'AJAX Exception: \' + exceptionObject.message;
message += \'\n\nYou may wish to enable your browsers Console to see a more detailed reason why this error occurred. \';
message += \'For most browsers this is the F12 key, or if in Firefox with Firebug installed, by using Firebug\'s Console.\';
message += \'\n\nForm Creators: This class of issue usually indicates a database error.\';
message += \'\n\nPlease check your SQL Code block to ensure a proper query, and if being used, the Data Source properties for proper connection details.\';
alert(message); // error, exception message
}
}
}); // ajax call
}
</script>
EOF;
}
$lib_code = "";
if (!isset($field->dbdsn)) {
$field->dbdsn = "";
}
$ajax_ignore_first = "false";
if (isset($field->ajax_ignore_first) && $field->ajax_ignore_first == "1") {
$ajax_ignore_first = "true";
}
$dbhost = $this->uv->replace_all($field->dbhost, 8);
$dbsocket = $this->uv->replace_all($field->dbsocket, 8);
$dbport = $this->uv->replace_all($field->dbport, 8);
$dbdsn = $this->uv->replace_all($field->dbdsn, 8);
$dbuser = $this->uv->replace_all($field->dbuser, 8);
$dbpwd = $this->uv->replace_all($field->dbpwd, 8);
$dbschema = $this->uv->replace_all($field->dbschema, 8);
$lib_code .= <<<EOT
<?php
/**
* RackForms Form Library Files - fb_ajax_{$field->ajax_source_field}_{$bind_index}.php
* @version 1.7
* @author RackForms
* @category Database
* @name fb_ajax_{$field->ajax_source_field}_{$bind_index}.php
*/
if(!session_id()) { session_start(); }
if(function_exists(\'ini_set\')){
ini_set(\'display_errors\', 0); // Change to 1 to display all error messages.
ini_set(\'error_reporting\', E_ALL);
}
include \'../utility.php\';
\$arg1 = isset(\$_POST[\'arg1\']) && \$_POST[\'arg1\'] != \'\' ? \$_POST[\'arg1\'] : -1;
\$arg2 = isset(\$_POST[\'arg2\']) && \$_POST[\'arg2\'] != \'\' ? \$_POST[\'arg2\'] : \'\';
\$arg3 = isset(\$_POST[\'arg3\']) && \$_POST[\'arg3\'] != \'\' ? \$_POST[\'arg3\'] : \'\';
\$arg4 = isset(\$_POST[\'arg4\']) && \$_POST[\'arg4\'] != \'\' ? \$_POST[\'arg4\'] : \'\';
\$arg5 = isset(\$_POST[\'arg5\']) && \$_POST[\'arg5\'] != \'\' ? \$_POST[\'arg5\'] : \'\';
\$action = isset(\$_POST[\'action\']) ? \$_POST[\'action\'] : -1;
if(\$arg1 != -1){
\$db_host = "{$dbhost}";
\$db_type = "{$this->um->translateSourceType($field->sourcetype)}";
\$mysql_socket = "{$dbsocket}";
\$mysql_port = "{$dbport}";
\$dbdsn = "{$dbdsn}";
\$db_user = "{$dbuser}";
\$db_pass = "{$dbpwd}";
\$db_catalog = "{$dbschema}";
\$return_true = 0;
\$db_ssl_key = \'{$field->dbsslkey}\';
\$db_ssl_certificate = \'{$field->dbsslcertificate}\';
\$db_ssl_ca_cert = \'{$field->dbsslcacert}\';
\$db_ssl_verify_cert = \'{$field->dbsslverifycert}\';
\$db_ssl_cipher = \'{$field->dbsslcipher}\';
\$debug = {$field->query_debug_level};
\$ignore_first_param = {$ajax_ignore_first};
\$sql = "{$field->query_sql}";
// parameters
\$args = array();
// always push base parameter if asked
if(\$ignore_first_param != true)
array_push(\$args, \$arg1);
// push extra parameters as needed
\$ct = substr_count(\$sql, \'?\');
// if we ignore first param, increment ct
if(\$ignore_first_param)
\$ct++;
if(\$ct > 1){ array_push(\$args, \$arg2); }
if(\$ct > 2){ array_push(\$args, \$arg3); }
if(\$ct > 3){ array_push(\$args, \$arg4); }
if(\$ct > 4){ array_push(\$args, \$arg5); }
\$params = \$args;
include \'../../Database.php\';
// Optional connector script - note we automatically back up two directories, which differs from other calls.
\$connector = "../../{$field->dbconnector}";
if(\$connector != "../../" && file_exists(\$connector)){
@include \$connector;
}
\$dbh = new Database();
switch(\$action){
case \'std\' :
// Set Optional MySQL SSL Properties.
\$dbh->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
\$result = \$dbh->pdo_procedure_params(\$debug,
\$sql,
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
\$return_true);
if(\$result == false){
header(\'Cache-Control: no-cache, must-revalidate\');
header(\'Expires: Mon, 26 Jul 1997 05:00:00 GMT\');
header(\'Content-type: application/json\');
echo "[]";
break;
}
\$append = "";
switch((int){$field->query_append_position}) {
case 1 :
\$append = array_unshift(\$result, array(0=>\'{$field->query_append_label}\', 1=>\'{$field->query_append_value}\', \'fb_append\'=>\'true\'));
break;
case 2 :
\$append = array_push(\$result, array(0=>\'{$field->query_append_label}\', 1=>\'{$field->query_append_value}\', \'fb_append\'=>\'true\'));
break;
}
// Build 789 - Encode Output.
foreach(\$result as \$outer_key=>\$row){
foreach(\$row as \$inner_key=>\$field){
// Encode Items
\$result["{\$outer_key}"]["{\$inner_key}"] = rawurlencode(\$result["{\$outer_key}"]["{\$inner_key}"]);
}
}
header(\'Cache-Control: no-cache, must-revalidate\');
header(\'Expires: Mon, 26 Jul 1997 05:00:00 GMT\');
header(\'Content-type: application/json\');
echo php_json_encode(\$result);
break;
case \'proc\' :
if(!session_id()) { session_start(); }
// Set Optional MySQL SSL Properties.
\$dbh->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
\$result = \$dbh->pdo_procedure_params(\$debug,
\$sql,
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
\$return_true);
// process result tokens
\$matches = array();
foreach(\$result as \$outer_key=>\$row){
foreach(\$row as \$inner_key=>\$field){
// form fields
preg_match_all(\'/(^|.|\r|\n)(F\{(.*?)\})/\', \$field, \$matches);
\$array_vars = array();
if(isset(\$matches[3])){
foreach(\$matches[3] as \$m){
\$result["{\$outer_key}"]["{\$inner_key}"] = str_replace(\'F{\'.\$m.\'}\', \$_SESSION[\'entry_key\']["{\$m}"], \$field);
}
}
// session elements
preg_match_all(\'/(^|.|\r|\n)(S\{(.*?)\})/\', \$field, \$matches);
\$array_vars = array();
if(isset(\$matches[3])){
foreach(\$matches[3] as \$m){
\$result["{\$outer_key}"]["{\$inner_key}"] = str_replace(\'S{\'.\$m.\'}\', \$_SESSION["{\$m}"], \$field);
}
}
// Build 789 - Encode Items
\$result["{\$outer_key}"]["{\$inner_key}"] = rawurlencode(\$result["{\$outer_key}"]["{\$inner_key}"]);
}
}
header(\'Cache-Control: no-cache, must-revalidate\');
header(\'Expires: Mon, 26 Jul 1997 05:00:00 GMT\');
header(\'Content-type: application/json\');
echo php_json_encode(\$result);
break;
}
exit(0);
} else {
exit(0);
}
?>
EOT;
file_put_contents($jobpath . "fb_ajax_{$field->ajax_source_field}_{$bind_index}.php", $lib_code);
$element = $page_code;
return $element;
}
public function create_calculation($field, $page)
{
if (!isset($field->library) || $field->library == "") {
$field->library = \'jquery\';
}
$numbertype = isset($field->numbertype) ? $field->numbertype : "0";
$numbertypeValue = "int";
if ($numbertype == "0") {
$numbertypeValue = "Int";
}
if ($numbertype == "1") {
$numbertypeValue = "Float";
}
if ($field->library == "jquery") {
$equation = $field->equation;
$destination_form_field = $field->destination_form_field;
$destination_php_var = $field->destination_php_var;
$matches = array();
$tokens = array();
$equation_js_paramters = "
// Equation Parameters";
$equation_js_code = $equation;
preg_match_all(\'/(^|.|
|
)?(F\{(.*?)\})/\', (string)$equation, $matches);
$filter = "";
if (isset($matches[3][0])) {
foreach ($matches[3] as $index => $match) {
$type = "";
foreach ($page->form->field as $f) {
if (isset($f->id) && $match == (string)$f->id) {
if((string)$f->type != "text" &&
(string)$f->type != "select" &&
(string)$f->type != "radio" &&
(string)$f->type != "checkbox" &&
(string)$f->type != "textarea" &&
(string)$f->type != "calendar"){
continue;
}
$type = (string)$f->type;
break;
}
}
if ($index == 0) {
$equation_js_paramters .= "
{$match} = 0;";
$equation_js_code = str_replace(\'F{\' . $match . \'}\', $match, $equation_js_code);
} else {
switch ($type) {
case \'text\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$(\'#{$match}\').val())) ? 0 : parse{$numbertypeValue}(\$(\'#{$match}\').val());";
break;
case \'select\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$(\'#{$match}\').val())) ? 0 : parse{$numbertypeValue}(\$(\'#{$match}\').val());";
break;
case \'radio\':
$equation_js_paramters .= <<<EOF
// loop though radio items until active value is found
{$match} = 0; // default
for(i = 0; i < 1000; i++){
if(document.getElementById(\'{$match}\' + i) !== null){
if(document.getElementById(\'{$match}\' + i).checked){
{$match} = isNaN(parse{$numbertypeValue}(\$(\'#{$match}\' + i).val())) ? 0 : parse{$numbertypeValue}(\$(\'#{$match}\' + i).val());
break;
}
}
}
EOF;
break;
case \'checkbox\':
$equation_js_paramters .= <<<EOF
// loop though checkbox items until all active value are found
{$match} = 0; // default
for(i = 0; i < 1000; i++){
if(document.getElementById(\'{$match}\' + i) !== null){
if(document.getElementById(\'{$match}\' + i).checked){
{$match} += isNaN(parse{$numbertypeValue}(\$(\'#{$match}\' + i).val())) ? 0 : parse{$numbertypeValue}(\$(\'#{$match}\' + i).val());
}
}
}
EOF;
break;
case \'textarea\':
$equation_js_paramters .= "
{$match} = \$(\'#{$match}\').val().split(/[\s\.,;]+/).length;";
break;
case \'calendar\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$(\'#date-{$match}-1\').val())) ? 0 : parse{$numbertypeValue}(\$(\'#{$match}\').val());";
$equation_js_paramters .= <<<EOF
// Check for date value and use if valid.
if(!isNaN(Date.parse( \$(\'#date-{$match}-1\').val() )) ){
{$match} = Date.parse( \$(\'#date-{$match}-1\').val() );
}
EOF;
break;
default:
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(<?php echo \$_SESSION[\'{$match}\']; ?>)) ? 0 : parse{$numbertypeValue}(<?php echo \$_SESSION[\'{$match}\']; ?>);";
}
$equation_js_code = str_replace(\'F{\' . $match . \'}\', $match, $equation_js_code);
}
$tokens[] = array(\'name\' => (string)$match, \'type\' => (string)$type);
}
switch ((int)$field->equation_filter) {
case \'1\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.floor({$matches[3][0]});
EOF;
break;
case \'2\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.ceil({$matches[3][0]});
EOF;
break;
case \'3\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.round({$matches[3][0]});
EOF;
break;
case \'4\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_US({$matches[3][0]});
EOF;
break;
case \'5\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_GBP({$matches[3][0]});
EOF;
break;
case \'6\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_Euro({$matches[3][0]});
EOF;
break;
case \'7\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.round({$matches[3][0]} * 10) / 10;
EOF;
break;
case \'8\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = {$matches[3][0]}.toFixed(2);
EOF;
break;
}
}
$equation_js_code .= $filter;
if (!isset($tokens[0])) {
return;
}
switch ($tokens[0][\'type\']) {
case \'text\':
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// Set text field item with value.
var _val = isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']};
\$(\'#{$tokens[0][\'name\']}\').val(_val);
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
} else {
$equation_js_code .= <<<EOF
// set text field item with value
\$(\'#{$tokens[0][\'name\']}\').val({$tokens[0][\'name\']});
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
}
break;
case \'hidden\':
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// set hidden field item with value
var _val = isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']};
\$(\'#{$tokens[0][\'name\']}\').val(_val);
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
} else {
$equation_js_code .= <<<EOF
// set hidden field item with value
\$(\'#{$tokens[0][\'name\']}\').val({$tokens[0][\'name\']});
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
}
break;
default:
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// set default field item with value
var _val = isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']};
if(\$(\'#{$tokens[0][\'name\']}\').value === undefined){
\$(\'#{$tokens[0][\'name\']}\').html(_val);
} else {
\$(\'#{$tokens[0][\'name\']}\').val(_val);
}
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
} else {
$equation_js_code .= <<<EOF
// set default field item with value
if(\$(\'#{$tokens[0][\'name\']}\').value === undefined){
\$(\'#{$tokens[0][\'name\']}\').html({$tokens[0][\'name\']});
} else {
\$(\'#{$tokens[0][\'name\']}\').val({$tokens[0][\'name\']});
}
\$(\'#{$tokens[0][\'name\']}\').trigger(\'change\');
EOF;
}
}
$dom_observe = <<<EOF
<script type="text/javascript">
// DOM Observe Calls For RackForms Field Calculations.
$( document ).ready(function() {
// bind event listener(s)
EOF;
foreach ($tokens as $index => $token) {
if ($index != 0) {
switch ($token[\'type\']) {
case \'text\':
$dom_observe .= "
$(\'#{$token[\'name\']}\').bind(\'keyup\', handleCalculation_{$field->DOM_id});";
$dom_observe .= "
$(\'#{$token[\'name\']}\').change(handleCalculation_{$field->DOM_id});";
break;
case \'select\':
$dom_observe .= "
$(\'#{$token[\'name\']}\').bind(\'change\', handleCalculation_{$field->DOM_id});";
break;
case \'radio\':
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} INPUT\').bind(\'click\', handleCalculation_{$field->DOM_id});";
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} INPUT\').bind(\'change\', handleCalculation_{$field->DOM_id});";
break;
case \'checkbox\':
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} INPUT\').bind(\'click\', handleCalculation_{$field->DOM_id});";
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} INPUT\').bind(\'change\', handleCalculation_{$field->DOM_id});";
break;
case \'textarea\':
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} TEXTAREA\').bind(\'keyup\', handleCalculation_{$field->DOM_id});";
$dom_observe .= "
$(\'#fb_fld-{$token[\'name\']} TEXTAREA\').bind(\'change\', handleCalculation_{$field->DOM_id});";
break;
case \'calendar\':
$dom_observe .= "
$(\'#date-{$token[\'name\']}-1\').bind(\'focus\', handleCalculation_{$field->DOM_id});";
$dom_observe .= "
$(\'#date-{$token[\'name\']}-1\').bind(\'change\', handleCalculation_{$field->DOM_id});";
break;
}
}
}
$dom_observe .= "
handleCalculation_{$field->DOM_id}(null);
";
$dom_observe .= "
});
";
$js_equation = <<<EOF
function handleCalculation_{$field->DOM_id}(event){
// get src element
if(event != null) {
var elt = FB_Calculation.getSrcElement(event);
}
{$equation_js_paramters}
// core code block
{$equation_js_code}
}
</script>
EOF;
return $dom_observe . $js_equation;
} else {
$equation = $field->equation;
$destination_form_field = $field->destination_form_field;
$destination_php_var = $field->destination_php_var;
$matches = array();
$tokens = array();
$equation_js_paramters = "
// Calculation Parameters";
$equation_js_code = $equation;
preg_match_all(\'/(^|.|
|
)?(F\{(.*?)\})/\', (string)$equation, $matches);
$filter = "";
if (isset($matches[3][0])) {
foreach ($matches[3] as $index => $match) {
$type = "";
foreach ($page->form->field as $f) {
if (isset($f->id) && $match == (string)$f->id) {
$type = (string)$f->type;
}
}
if ($index == 0) {
$equation_js_paramters .= "
{$match} = 0;";
$equation_js_code = str_replace(\'F{\' . $match . \'}\', $match, $equation_js_code);
} else {
switch ($type) {
case \'text\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$F(\'{$match}\'))) ? 0 : parse{$numbertypeValue}(\$F(\'{$match}\'));";
break;
case \'select\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$F(\'{$match}\'))) ? 0 : parse{$numbertypeValue}(\$F(\'{$match}\'));";
break;
case \'radio\':
$equation_js_paramters .= <<<EOF
// loop though radio items until active value is found
{$match} = 0; // default
for(i = 0; i < 1000; i++){
if(document.getElementById(\'{$match}\' + i) !== null){
if(document.getElementById(\'{$match}\' + i).checked){
{$match} = isNaN(parse{$numbertypeValue}(\$F(\'{$match}\' + i))) ? 0 : parse{$numbertypeValue}(\$F(\'{$match}\' + i));
break;
}
}
}
EOF;
break;
case \'checkbox\':
$equation_js_paramters .= <<<EOF
// loop though checkbox items until all active value are found
{$match} = 0; // default
for(i = 0; i < 1000; i++){
if(document.getElementById(\'{$match}\' + i) !== null){
if(document.getElementById(\'{$match}\' + i).checked){
{$match} += isNaN(parse{$numbertypeValue}(\$F(\'{$match}\' + i))) ? 0 : parse{$numbertypeValue}(\$F(\'{$match}\' + i));
}
}
}
EOF;
break;
case \'textarea\':
$equation_js_paramters .= "
{$match} = \$F(\'{$match}\').split(/[\s\.,;]+/).length;";
break;
case \'calendar\':
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(\$F(\'date-{$match}-1\'))) ? 0 : parse{$numbertypeValue}(\$F(\'date-{$match}-1\'));";
$equation_js_paramters .= <<<EOF
// Check for date value and use if valid.
if(!isNaN(Date.parse( \$F(\'date-{$match}-1\') )) ){
{$match} = Date.parse( \$F(\'date-{$match}-1\') );
}
EOF;
break;
default:
$equation_js_paramters .= "
{$match} = isNaN(parse{$numbertypeValue}(<?php echo \$_SESSION[\'{$match}\']; ?>)) ? 0 : parse{$numbertypeValue}(<?php echo \$_SESSION[\'{$match}\']; ?>);";
}
$equation_js_code = str_replace(\'F{\' . $match . \'}\', $match, $equation_js_code);
}
$tokens[] = array(\'name\' => (string)$match, \'type\' => (string)$type);
}
switch ((int)$field->equation_filter) {
case \'1\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.floor({$matches[3][0]});
EOF;
break;
case \'2\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.ceil({$matches[3][0]});
EOF;
break;
case \'3\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = Math.round({$matches[3][0]});
EOF;
break;
case \'4\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_US({$matches[3][0]});
EOF;
break;
case \'5\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_GBP({$matches[3][0]});
EOF;
break;
case \'6\':
$filter = <<<EOF
// filter result
{$matches[3][0]} = FB_Calculation.format_Currency_Euro({$matches[3][0]});
EOF;
break;
}
}
$equation_js_code .= $filter;
if (!isset($tokens[0])) {
return;
}
switch ($tokens[0][\'type\']) {
case \'text\':
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').value = isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']};
EOF;
} else {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').value = {$tokens[0][\'name\']};
EOF;
}
break;
case \'hidden\':
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').value = isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']};
EOF;
} else {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').value = {$tokens[0][\'name\']};
EOF;
}
break;
default:
if ((int)$field->equation_filter == 0) {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').update(isNaN({$tokens[0][\'name\']}) ? \'\' : {$tokens[0][\'name\']});
EOF;
} else {
$equation_js_code .= <<<EOF
// set field item with value
\$(\'{$tokens[0][\'name\']}\').update({$tokens[0][\'name\']});
EOF;
}
}
$dom_observe = <<<EOF
<script type="text/javascript">
// DOM Observe Calls For RackForms Field Calculations.
document.observe(\'dom:loaded\', function(l){
// bind event listener(s)
EOF;
foreach ($tokens as $index => $token) {
if ($index != 0) {
switch ($token[\'type\']) {
case \'text\':
$dom_observe .= "
$(\'{$token[\'name\']}\').observe(\'keyup\', handleCalculation_{$field->DOM_id});";
break;
case \'select\':
$dom_observe .= "
$(\'{$token[\'name\']}\').observe(\'change\', handleCalculation_{$field->DOM_id});";
break;
case \'radio\':
$dom_observe .= "
$$(\'#fb_fld-{$token[\'name\']} INPUT\').invoke(\'observe\', \'click\', handleCalculation_{$field->DOM_id});";
break;
case \'checkbox\':
$dom_observe .= "
$$(\'#fb_fld-{$token[\'name\']} INPUT\').invoke(\'observe\', \'click\', handleCalculation_{$field->DOM_id});";
break;
case \'textarea\':
$dom_observe .= "
$$(\'#fb_fld-{$token[\'name\']} TEXTAREA\').invoke(\'observe\', \'keyup\', handleCalculation_{$field->DOM_id});";
break;
case \'calendar\':
$dom_observe .= "
$(\'date-{$token[\'name\']}-1\').observe(\'focus\', handleCalculation_{$field->DOM_id});";
break;
}
}
}
$dom_observe .= "
});
";
$js_equation = <<<EOF
function handleCalculation_{$field->DOM_id}(event){
// get src element
var elt = FB_Calculation.getSrcElement(event);
{$equation_js_paramters}
// core code block
{$equation_js_code}
}
</script>
EOF;
return $dom_observe . $js_equation;
}
}
public function create_separator($field, $tablemode, $bucket_node = "")
{
$color = $field->{\'color\'};
$width = $field->width;
$separator_style = $field->separator_style;
$style = $field->style;
$element = "";
switch ($separator_style) {
case \'0\':
$separator_style = \'dotted\';
break;
case \'1\':
$separator_style = \'solid\';
break;
case \'2\':
$separator_style = \'dashed\';
break;
default:
$separator_style = \'dotted\';
}
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; height:2px; float:left; \"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; height:2px; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px;\" >
";
}
if ((int)$tablemode->enabletablelayout == 0) {
$width = \'\';
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$width = \'85%\';
}
if ((int)$tablemode->enabletablelayout != 1 && !$tablemodespan) {
$width = "100%;";
}
if (isset($field->elementpos) && (int)$field->elementpos != "0") {
$width = $field->width;
}
$element .= "<div class=\"separator\" style=\"height:1px; border-bottom:1px {$color} {$separator_style}; width:{$width};\"> </div>";
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_spacer($field, $tablemode, $bucket_node = "")
{
$height = $field->height;
$element = "";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px;\" >
";
}
$height += 4;
$fieldwidth = \' width:1px;\';
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'95%\';
}
$element .= "<div class=\"spacer\" style=\"height:{$height}px; {$fieldwidth}\"> </div>";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_barcode($field, $tablemode, $bucket_node = "")
{
$element = "";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
switch ((int)$field->codetype) {
case 0:
$barcode_type = "BC_TYPE_CODE39";
break;
case 1:
$barcode_type = "BC_TYPE_INTER25";
break;
case 2:
$barcode_type = "BC_TYPE_STD25";
break;
case 3:
$barcode_type = "BC_TYPE_CODE93";
break;
case 4:
$barcode_type = "BC_TYPE_ROYMAIL4";
break;
case 5:
$barcode_type = "BC_TYPE_POSTNET";
break;
case 6:
$barcode_type = "C128A";
break;
case 7:
$barcode_type = "C128B";
break;
case 8:
$barcode_type = "C128C";
break;
}
switch ((int)$field->rotation) {
case 0:
$barcode_rotation = "BC_ROTATE_0";
break;
case 1:
$barcode_rotation = "BC_ROTATE_90";
break;
case 2:
$barcode_rotation = "BC_ROTATE_180";
break;
case 3:
$barcode_rotation = "BC_ROTATE_270";
break;
}
$field->checkdigit = (int)$field->checkdigit;
$text = $this->uv->replace_all((string)$field->text, 4);
if ($field->text == $text) {
$text = \'"\' . $text . \'"\';
}
if ($text == "") {
$text = "101";
}
switch ((int)$field->showtext) {
case 0:
$show_label = \'N\';
$show_label_code128 = \'0\';
break;
case 1:
$show_label = \'Y\';
$show_label_code128 = \'on\';
break;
}
if ((int)$field->codetype < 6) {
if (!isset($field->width) || $field->width == "") {
$field->width = \'1\';
}
$element .= <<<EOT
<?php
\$enabled = {$field->enabled};
include_once "lib/barcode/set1/core.php";
//barCode(BC_TYPE_CODE39, "1234567890", 1, 3, 1, FALSE, 100, BC_IMG_TYPE_PNG, TRUE, BC_ROTATE_0, TRUE, FALSE, "test");
\$barcode_type = {$barcode_type};
\$p_text = {$text};
\$dyn_char_height = {$field->height};
\$dyn_char_width = {$field->width};
\$barcode_show_text = \'{$show_label}\';
\$p_rotAngle = {$barcode_rotation};
\$p_checkDigit = {$field->checkdigit};
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true && \$PDF_LIBRARY == "DOMPDF"){
// Must Render As Base64 For DOMPDF.
ob_start();
\$raw = barCode(\$barcode_type, // Type of barcode to be generated
\$p_text, // Text to be generated as barcode
\$dyn_char_width, // p_xDim - smallest element width
3, // wide to narrow factor
\$dyn_char_width, // Intercharacter gap width. usually the same as xDim
FALSE, // Whether or not invert starting bar colors
\$dyn_char_height, // height in pixels of a single character
BC_OUTPUT_TYPE_RAW_PNG_DATA, // image type output
\$barcode_show_text, // Whether or not include a text label below barcode
\$p_rotAngle,// Barcode Image rotation angle
\$p_checkDigit, // Whether or not include check digit
FALSE, // Whether or not write to file
"test"
);
\$bar_code_data = ob_get_clean();
echo \'<img src="\';
echo "data:image/png;base64,"
.str_replace ("\n", "", base64_encode (\$bar_code_data));
echo \'" >\';
} else {
\$img_call = "<img src=\"lib/barcode/set1/wrapper.php?p_bcType={\$barcode_type}&p_type=3&p_text={\$p_text}&p_xDim={\$dyn_char_width}&p_w2n=3&p_invert=N
&p_charHeight={\$dyn_char_height}&p_label={\$barcode_show_text}&p_rotAngle={\$p_rotAngle}&p_checkDigit={\$p_checkDigit}\" alt=\"Barcode\">";
}
?>
<p><?php if(\$enabled) { echo \$img_call; } ?></p>
EOT;
}
if ((int)$field->codetype >= 6 && (int)$field->codetype <= 8) {
if (!isset($field->width) || $field->width == "") {
$field->width = \'120\';
}
$element .= <<<EOT
<?php
\$enabled = {$field->enabled};
define ("__TRACE_ENABLED__", false);
define ("__DEBUG_ENABLED__", false);
require("lib/barcode/set2/barcode.php");
require("lib/barcode/set2/i25object.php");
require("lib/barcode/set2/c39object.php");
require("lib/barcode/set2/c128aobject.php");
require("lib/barcode/set2/c128bobject.php");
require("lib/barcode/set2/c128cobject.php");
\$output = "png";
\$barcode = {$text};
\$type = \'{$barcode_type}\';
\$width = {$field->width};
\$height = {$field->height};
\$xres = "2";
\$font = "5";
// style attributes
\$border = "off";
\$drawtext = \'{$show_label_code128}\';
\$stretchtext = "off";
\$negative = "off";
\$StarSize = 0;
\$style = BCS_ALIGN_CENTER;
\$style |= (\$output == "png" ) ? BCS_IMAGE_PNG : 0;
\$style |= (\$output == "jpeg") ? BCS_IMAGE_JPEG : 0;
\$style |= (\$border == "on" ) ? BCS_BORDER : 0;
\$style |= (\$drawtext== "on" ) ? BCS_DRAW_TEXT : 0;
\$style |= (\$stretchtext== "on" ) ? BCS_STRETCH_TEXT : 0;
\$style |= (\$negative== "on" ) ? BCS_REVERSE_COLOR : 0;
if(\$enabled) {
switch (\$type) {
case "I25":
\$obj = new I25Object(\$width, \$height, \$style, \$barcode, \$StarSize);
break;
case "C39":
\$obj = new C39Object(\$width, \$height, \$style, \$barcode);
break;
case "C128A":
\$obj = new C128AObject(\$width, \$height, \$style, \$barcode);
break;
case "C128B":
\$obj = new C128BObject(\$width, \$height, \$style, \$barcode);
break;
case "C128C":
\$obj = new C128CObject(\$width, \$height, \$style, \$barcode);
break;
default:
\$obj = false;
}
}
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true && \$PDF_LIBRARY == "DOMPDF"){
// Must Render As Base64 For DOMPDF.
ob_start();
\$bar_code_data = ob_get_clean();
echo \'<img src="\';
echo "data:image/png;base64,"
.str_replace ("\n", "", base64_encode (\$bar_code_data));
echo \'" >\';
} else {
if (\$obj) {
if (\$obj->DrawObject(\$xres, \$StarSize)) {
echo "<img src=\'lib/barcode/set2/image.php?code={\$barcode}&style={\$style}&type={\$type}&width={\$width}&height={\$height}&xres=2&font={\$font}\'>";
} else echo "<font color=\'#FF0000\'>".(\$obj->GetError())."</font>";
}
}
?>
EOT;
}
if (!isset($field->matrixsize) || $field->matrixsize == "") {
$field->matrixsize = \'1\';
}
if ((int)$field->codetype == 9) {
$element .= <<<EOT
<?php
\$enabled = {$field->enabled};
\$request_level = 0;
\$request_matrix_size = {$field->matrixsize};
\$request_data = {$text};
//set it to writable location, a place for temp generated PNG files
// Build 784 - Encoding was transforing __FILE into the path of the script, not sure why!
\$PNG_TEMP_DIR = \'./\'.DIRECTORY_SEPARATOR.\'temp\'.DIRECTORY_SEPARATOR;
//html PNG location prefix
\$PNG_WEB_DIR = \'temp/\';
include "lib/barcode/phpqrcode/qrlib.php";
//ofcourse we need rights to create temp dir
if (!file_exists(\$PNG_TEMP_DIR))
mkdir(\$PNG_TEMP_DIR);
\$filename = \$PNG_TEMP_DIR.\'test.png\';
//processing form input
//remember to sanitize user input in real-life solution !!!
\$errorCorrectionLevel = \'L\';
if (isset(\$request_level) && in_array(\$request_level, array(\'L\',\'M\',\'Q\',\'H\')))
\$errorCorrectionLevel = \$request_level;
\$matrixPointSize = 4;
if (isset(\$request_matrix_size))
\$matrixPointSize = min(max((int)\$request_matrix_size, 1), 10);
if (isset(\$request_data) && \$enabled) {
//it\'s very important!
if (trim(\$request_data) == \'\')
die(\'data cannot be empty! <a href="?">back</a>\');
// user data
\$filename = \$PNG_TEMP_DIR.\'test\'.md5(\$request_data.\'|\'.\$errorCorrectionLevel.\'|\'.\$matrixPointSize).\'.png\';
QRcode::png(\$request_data, \$filename, \$errorCorrectionLevel, \$matrixPointSize, 2);
// display generated file
echo \'<img src="\'.\$PNG_WEB_DIR.basename(\$filename).\'" />\';
}
?>
EOT;
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_webcam($field, $tablemode, $bucket_node = "")
{
$element = "";
if (isset($field->enabled) && $field->enabled == "0") {
return "";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$width = $field->width;
$height = $field->height;
if (!is_numeric($width)) {
$width = intval($width);
}
if (!is_numeric($height)) {
$height = intval($height);
}
if (trim($width) == "" || $width == 0) {
$width = "320";
}
if (trim($height) == "" || $height == 0) {
$height = "240";
}
$destination_width = $field->destination_width;
$destination_height = $field->destination_height;
$snapshot_preview_width = $field->snapshot_preview_width;
$snapshot_preview_height = $field->snapshot_preview_height;
if (!is_numeric($snapshot_preview_width)) {
$snapshot_preview_width = intval($snapshot_preview_width);
}
if (!is_numeric($snapshot_preview_height)) {
$snapshot_preview_height = intval($snapshot_preview_height);
}
if (trim($snapshot_preview_width) == "") {
$snapshot_preview_width = "320";
}
if (trim($snapshot_preview_height) == "") {
$snapshot_preview_height = "240";
}
if ($snapshot_preview_width == 0) {
$snapshot_preview_width = "";
}
if ($snapshot_preview_height == 0) {
$snapshot_preview_height = "";
}
if (!is_numeric($destination_width)) {
$destination_width = intval($destination_width);
}
if (!is_numeric($destination_height)) {
$destination_height = intval($destination_height);
}
if (trim($destination_width) == "" || $destination_width == 0) {
$destination_width = $width;
}
if (trim($destination_height) == "" || $destination_height == 0) {
$destination_height = $height;
}
$format = "png";
if (isset($field->format)) {
if ($field->format == "0") {
$format = "jpeg";
}
if ($field->format == "1") {
$format = "png";
}
}
$quality = $field->quality;
if (!is_numeric($quality)) {
$quality = intval($quality);
}
if ($quality == "") {
$quality = 80;
}
$capture_message = str_replace("\'", "\'", $field->capture_message);
$element .= <<<EOT
<script src="js/webcam/webcam.js"></script>
<div class="webcam-viewer" id="my_camera_{$field->name}" style="width:{$width}px; height:{$height}px;"></div>
<div class="webcam-snapshot" id="my_result_{$field->name}"></div>
<input type="hidden" id="{$field->id}" name="{$field->name}" />
<script language="JavaScript">
Webcam.attach( \'#my_camera_{$field->name}\' );
Webcam.set({
width: {$width},
height: {$height},
dest_width: {$destination_width},
dest_height: {$destination_height},
image_format: \'{$format}\',
jpeg_quality: {$quality},
force_flash: false,
flip_horiz: false,
fps: 45
});
function take_snapshot() {
Webcam.snap( function(data_uri) {
if({$field->preview_mode} == 0) {
document.getElementById(\'my_result_{$field->name}\').innerHTML = \'<img width="{$snapshot_preview_width}" height="{$snapshot_preview_height}" src="\'+data_uri+\'"/>\';
}
if({$field->preview_mode} == 1) {
document.getElementById(\'my_result_{$field->name}\').innerHTML = \'{$capture_message}\';
}
// Save Data.
document.getElementById(\'{$field->name}\').value = data_uri.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
});
}
</script>
<a class="webcam-action-button" href="javascript:void(take_snapshot())">{$field->action_message}</a>
EOT;
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_signature($page, $enable_pdf, $field, $tablemode, $bucket_node = "")
{
$element = "";
$style = $field->style;
$fontsize = $field->fontsize;
$inheritstyle = $field->inheritstyle;
$color = $field->color;
$input_color = $field->input_color;
$labelstyle = "style=\"font-size:{$fontsize}; color:{$color};\" ";
if (isset($inheritstyle) && (int)$inheritstyle == 1) {
$inheritstyle = "style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit;\" ";
} else {
$inheritstyle = "style=\"color:{$input_color};\" ";
}
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
$field_width = \'\';
if (isset($style->fieldwidth)) {
$field_width = $style->fieldwidth;
}
if ((int)$style->tablemodespan == 1) {
$element .= "<div class=\"tablemode-span-width\" style=\"width:{$field_width}\">";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
switch ((int)$field->inputtype) {
case 0:
$inputtype = ", drawOnly:true";
$input_field = "";
$draw_it_control = "<li class=\"drawIt\"><a href=\"#draw-it\" >{$field->signature_drawit_text}</a></li>";
break;
case 1:
$inputtype = ", drawOnly:false";
$input_field = "<label aria-label=\"Signature Input\" for=\"name\" {$labelstyle}>{$field->signature_typeit_text}</label>";
$value = "<?php if(isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\'])) { echo \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\']; } ?>";
$input_field .= "<input type=\"text\" {$inheritstyle} name=\"signature_input_field_{$field->name}\" id=\"signature-_input_field_{$field->id}\" class=\"name\" value=\"{$value}\" onkeyup=\"draw_typed_signature_{$field->id}(this.value); generate_text_canvas_image_{$field->id}(\'signature-_input_field_{$field->id}\');\">";
$input_field .= "<br /><br/>";
$draw_it_control = \'\';
break;
case 2:
$inputtype = ", drawOnly:true";
$input_field = "<label aria-label=\"Signature\" for=\"name\" {$labelstyle}>{$field->signature_typeit_text}</label>";
$value = "<?php if(isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\'])) { echo \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\']; } ?>";
$input_field .= "<input type=\"text\" {$inheritstyle} name=\"signature_input_field_{$field->name}\" id=\"signature_input_field_{$field->id}\" class=\"name\" value=\"{$value}\" size=\"30\">";
$draw_it_control = "<li class=\"drawIt\"><a href=\"#draw-it\" >{$field->signature_drawit_text}</a></li>";
break;
case 3:
$inputtype = ", displayOnly:true";
$input_field = "";
$value = "<?php if(isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\'])) { echo \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'signatures\'][\"{$field->id}\"][\'signator\']; } ?>";
$input_field .= "<br><input type=\"text\" style=\"font-size:{$fontsize};\" name=\"signature_input_field_{$field->name}\" id=\"signature_input_field_{$field->id}\" class=\"name\" value=\"{$value}\" size=\"30\"><br><br>";
$draw_it_control = "<li class=\"drawIt\"><a href=\"#draw-it\" >{$field->signature_drawit_text}</a></li>";
break;
}
if (!isset($field->width) || $field->width == "") {
$field->width = \'1\';
}
if (!isset($field->signature_canvas_width) || $field->signature_canvas_width == "") {
$field->signature_canvas_width = \'400\';
}
if (!isset($field->signature_canvas_height) || $field->signature_canvas_height == "") {
$field->signature_canvas_height = \'65\';
}
if (!isset($field->signature_line_width) || $field->signature_line_width == "") {
$field->signature_line_width = \'0\';
}
$lineTop = (int)$field->signature_canvas_height - 5;
$wrapperHeight = (int)$field->signature_canvas_height + 10;
if ($field->signature_line_width == 0) {
$wrapperHeight = $wrapperHeight - 10;
}
$signaturePadWidth = intval($field->signature_canvas_width);
if(isset($page->globalstyle) && (intval($page->globalstyle) != 0 || !is_numeric((string)$page->globalstyle)) ){
$wrapperHeight = (int)$field->signature_canvas_height + 10;
$signaturePadWidth = intval($field->signature_canvas_width) + 15;
}
$required = isset($field->required) && (int)$field->required == 0 ? \'true\' : \'false\';
if ((int)$field->inputtype != 3) {
if ($field->signature_canvas_width < 190) {
$draw_it_control = "";
}
$element .= <<<EOT
{$input_field}
<p class="drawItDesc"> </p>
<div class="sig sigWrapper sigWrapper_{$field->id}">
<ul class="sigNav" style="position:absolute; top: -29px; margin:-1px;">
{$draw_it_control}
<li class="clearButton"><a href="#clear">Clear</a></li>
</ul>
<!-- holds the typed version of a signature, layed on top of the canvas, only used in \'type only\' versions, also defines font size used for display -->
<div class="typed typed-{$field->id}" style="font-size:22pt;"></div>
<canvas id="canvas_signature_output_{$field->id}" class="pad" width="{$field->signature_canvas_width}" height="{$field->signature_canvas_height}"></canvas>
<input type="hidden" name="signature_output_{$field->id}" class="signature_output_{$field->id}">
<!-- holds the image data of a \'typed only\' signature -->
<input type="hidden" name="signature_output_image_{$field->id}" id="signature_output_image_{$field->id}" class="signature_output_image_{$field->id}">
</div>
<style type="text/css">
/* overrides version in css file */
.sigPad_{$field->id} {
margin: 0;
padding: 0;
width: {$field->signature_canvas_width}px;
}
.sigWrapper_{$field->id} {
clear: both;
height: {$wrapperHeight}px; /* should be 10 pixels higher than canvas height if bottom line == 0 */
position: relative;
width: {$field->signaturePadWidth}px;
}
</style>
<script>
function generate_text_canvas_image_{$field->id}(id){
var tempCanvasHtml = \'<canvas id="temp_canvas_{$field->id}" style="display:none;" width="{$field->signature_canvas_width}" height="{$field->signature_canvas_height}"></canvas>\';
\$j("body").append(tempCanvasHtml);
var tempCanvas = \$j("#temp_canvas_{$field->id}").get(0);
var tempCtx = tempCanvas.getContext("2d");
tempCtx.font = "2.45em/50px \'Journal\',Georgia,Times,serif";
tempCtx.fillStyle = \'{$field->signature_pen_color}\';
tempCtx.fillText(\$j("#signature-_input_field_{$field->id}").val(), 5, 50);
\$j(\'#signature_output_image_{$field->id}\').val(tempCanvas.toDataURL("image/png"))
tempCanvas.remove();
}
\$j(document).ready(function () {
var options = {
bgColour : \'{$field->signature_bg_color}\'
, penColour : \'{$field->signature_pen_color}\'
, penWidth: {$field->signature_pen_width}
, lineWidth: {$field->signature_line_width}
, lineTop: {$lineTop} // should be 5px lower than canvas height
{$inputtype}
, output:\'.signature_output_{$field->id}\' // must be a class name!
, typed: \'.typed-{$field->id}\'
, errorMessage: \'{$field->signature_error_text_general}\'
, errorMessageDraw: \'{$field->signature_error_text_drawit}\'
, required: {$required}
};
// generate control
signaturePadAPI_{$field->id} = \$j(\'#fb_fld-{$field->id}\').signaturePad(options);
// if in text only mode, redraw signature when page loads to get image data.
var mode = $field->inputtype;
if(mode == 1){
generate_text_canvas_image_{$field->id}(\'signature-_input_field_{$field->id}\');
}
// redraw existing signature if needed
var sig = \'<?php if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->id}"][\'signature\'])) { echo \$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->id}"][\'signature\']; } else { echo \'[]\'; } ?>\';
if(sig != \'[]\'){
signaturePadAPI_{$field->id}.regenerate(sig);
}
// pre-populate typed only entires
var typed_data = \'<?php if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->id}"][\'signator\'])) { echo \$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->id}"][\'signator\']; } ?>\';
if(typed_data != \'\' && \$j(\'.typed-{$field->id}\')){
\$j(\'.typed-{$field->id}\').html(typed_data);
}
});
// helper function to draw text only signatures, though not yet implemented.
function draw_typed_signature_{$field->id}(val){
//\$j(\'#signature_output_image_{$field->id}\').html(signaturePadAPI_{$field->id}.getSignatureImage());
}
</script>
EOT;
}
if ((int)$field->inputtype == 3) {
$field->signature_bg_color = str_replace(\'#\', \'\', $field->signature_bg_color);
$field->signature_pen_color = str_replace(\'#\', \'\', $field->signature_pen_color);
$element = <<<EOF
<?php
\$enable_pdf = isset(\$PAGE_IS_PDF) ? 1 : {$enable_pdf};
// draw signature if it exists
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->signature_display_field}"][\'signature\'])) {
// display options
\$options = "&bgColour={$field->signature_bg_color}&penWidth={$field->signature_pen_width}&penColour={$field->signature_pen_color}&canvasWidth={$field->signature_canvas_width}&canvasHeight={$field->signature_canvas_height}";
if(\$enable_pdf == 0){
// If empty array, we\'re in text mode.
if(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->signature_display_field}"][\'signature\'] == "[]"){
echo "<img src=\'data:image/png;base64,".base64_encode(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->signature_display_field}"][\'signature_image\'])."\' />";
} else {
\$rand = md5(rand(1000, 5000));
// standard image file include.
echo "<img src=\"lib/signature-pad/display-signature.php?signature-id={$field->signature_display_field}{\$options}&rand={\$rand}\" title=\"\" alt=\"\" />";
}
} else {
// alternate, direct output to browser mode for PDF consumption (not styled).
echo "<img src=\'data:image/png;base64,".base64_encode(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'signatures\']["{$field->signature_display_field}"][\'signature_image\'])."\' />";
}
}
?>
EOF;
}
if ((int)$style->tablemodespan == 1) {
$element .= "</div> <!-- tablemode span width -->";
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_image($field, $jobname, $formname, $tablemode, $bucket_node = "")
{
$text = $field->{\'label\'};
$src = $field->src;
$link_address = $field->link_address;
$link_target = $field->link_target;
$link_title = $field->link_title;
$link_submit = $field->link_submit;
$database_image_enable = $field->database_image_enable;
$database_image_debug_level = isset($field->database_image_debug_level) ? $field->database_image_debug_level : \'0\';
$database_image_table = $field->database_image_table;
$database_image_column = $field->database_image_column;
$database_image_column_id = $field->database_image_column_id;
$database_image_id = $field->database_image_id;
$database_image_column_entryid = $field->database_image_column_entryid;
$database_image_entry_id = $field->database_image_entryid;
$database_image_entry_id_original = $field->database_image_entryid;
$database_image_size = $field->database_image_size;
$database_image_max_width = $field->database_image_max_width;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$name = $field->name;
$id = $field->id;
$route = $field->route;
$style = $field->style;
$element = "";
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = \' style="\' . $attributestyle . \'" \';
}
$link_address = $this->uv->replace_all($link_address, 6);
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
switch ((int)$link_target) {
case 0:
$link_target = \'_blank\';
break;
case 1:
$link_target = \'_parent\';
break;
case 2:
$link_target = \'_self\';
break;
case 3:
$link_target = \'_top\';
break;
}
if (!is_dir(\'../../output/forms/\' . $jobname . \'/images\')) {
@mkdir(\'../../output/forms/\' . $jobname . \'/images/\', DIRECTORY_MOD);
}
if (file_exists("../../output/upload_images/{$src}")) {
copy("../../output/upload_images/{$src}", "../../output/forms/{$jobname}" . \'/images/\' . $src);
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$src_html = "";
$width_html = "";
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
if (isset($database_image_enable) && $database_image_enable == "1") {
if ($field->dbconnector == \'\' && !file_exists("../../output/forms/{$jobname}" . \'/\' . \'config.php\')) {
copy("../movefiles/config.php", "../../output/forms/{$jobname}" . \'/\' . \'config.php\');
}
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
if (!file_exists("../../output/forms/{$jobname}" . \'/\' . \'Database.php\')) {
copy("../movefiles/Database.php", "../../output/forms/{$jobname}" . \'/\' . \'Database.php\');
}
$db_type = isset($field->sourcetype) ? $this->um->translateSourceType((int)$field->sourcetype) : \'\';
$db_host = isset($field->dbhost) ? (string)$field->dbhost : \'\';
$mysql_socket = isset($field->dbsocket) ? (string)$field->dbsocket : \'\';
$mysql_port = isset($field->dbport) ? (int)$field->dbport : \'\';
$dbdsn = isset($field->dbdsn) ? (string)$field->dbdsn : \'\';
$db_user = isset($field->dbuser) ? (string)$field->dbuser : \'\';
$db_pass = isset($field->dbpwd) ? (string)$field->dbpwd : \'\';
$db_catalog = isset($field->dbschema) ? (string)$field->dbschema : \'\';
$dbdebuglevel = isset($field->dbdebuglevel) ? (int)$field->dbdebuglevel : \'\';
$dbconnector = isset($field->dbconnector) ? (string)$field->dbconnector : \'\';
$db_connection = <<<EOF
<?php
if(\'{$db_host}\' != \'\'){
\$db_type = \'{$db_type}\';
\$db_host = \'{$db_host}\';
\$mysql_socket = \'{$mysql_socket}\';
\$mysql_port = \'{$mysql_port}\';
\$dbdsn = \'{$dbdsn}\';
\$db_user = \'{$db_user}\';
\$db_pass = \'{$db_pass}\';
\$db_catalog = \'{$db_catalog}\';
}
\$db_ssl_key = \'{$field->dbsslkey}\';
\$db_ssl_certificate = \'{$field->dbsslcertificate}\';
\$db_ssl_ca_cert = \'{$field->dbsslcacert}\';
\$db_ssl_verify_cert = \'{$field->dbsslverifycert}\';
\$db_ssl_cipher = \'{$field->dbsslcipher}\';
include_once \'Database.php\';
\$debug = {$dbdebuglevel}; // UI override
// Optional DB Connector File - if not specified RackForms will use config.php via Database.php include
if(file_exists(\'{$dbconnector}\')){
include \'{$dbconnector}\';
}
?>
EOF;
$element .= $db_connection;
$database_image_id = $this->uv->replace_all($database_image_id, 4);
if ($field->database_image_id == $database_image_id) {
if (!is_int($database_image_id)) {
$database_image_id = \'"\' . str_replace(\'"\', \'\"\', $database_image_id) . \'"\';
}
}
$element .= "
<?php \$_SESSION[\'form_image_token\'] = true; ?>
";
$size = "normal";
if ($database_image_size == "1")
$size = "thumb";
$table = "";
$column = "image_data";
$columnid = "image_id";
if (isset($database_image_table) && $database_image_table != "") {
$table = $database_image_table;
$column = "image_data";
$columnid = "image_id";
if (isset($database_image_column) && $database_image_column != "") {
$column = $database_image_column;
}
if (isset($database_image_column_id) && $database_image_column_id != "") {
$columnid = $database_image_column_id;
}
if ($database_image_id != "" && $database_image_entry_id == "") {
$element .= <<<EOF
<?php
include_once \'./Database.php\';
\$dbh_img = new Database();
\$rand = md5(rand(1000, 100000));
// Custom Image Call For Single Images.
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_table_name\'] = "{$table}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_name\'] = "{$column}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_id\'] = "{$columnid}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_database_image_id\'] = {$database_image_id};
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true) {
// Inline Images For PDF.
include_once "lib/get_form_image_inline.php";
\$db = array(\$db_type, \$db_host, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$debug);
\$imgData = get_inline_image("null", "normal", "", "", \$rand, \$db);
if(\$imgData[1] != "") {
\$rawData = base64_encode(\$imgData[1]);
echo \'<img class="form-image {$extraclassnames}" src="data:image/\' . \$imgData[0] . \';base64,\' . \$rawData . \'" {$inheritstyle} width="{$field->database_image_max_width}" class="rf-form-image" />\';
}
} else {
// Original, Inline Image Echo.
if(\$db_host == ""){
\$styles = \'{$inheritstyle}\';
// Escape Extra Styles.
//$inheritstyle = str_replace(\'"\', \'\"\', $inheritstyle);
echo \'<img class="form-image {$extraclassnames}" src="lib/get_form_image.php?id=null&size={$size}&rand=\' . \$rand . \'" width="{$field->database_image_max_width}" title="$text" {$attribute} {$inheritstyle} name="{$name}" id="{$id}" class="rf-form-image" />\';
} else {
// Image Pull Using (Optional) Dynamic Database Details.
include_once "lib/get_form_image_inline.php";
\$db = array(\$db_type, \$db_host, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$debug);
\$imgData = get_inline_image("null", "normal", "", "", \$rand, \$db);
if(\$imgData[1] != "") {
\$rawData = base64_encode(\$imgData[1]);
echo \'<img class="form-image {$extraclassnames}" src="data:image/\' . \$imgData[0] . \';base64,\' . \$rawData . \'" {$inheritstyle} width="{$field->database_image_max_width}" class="rf-form-image" />\';
}
}
}
?>
EOF;
}
if ($database_image_entry_id != "") {
$database_image_entry_id = $this->uv->replace_all($database_image_entry_id, 4);
$entry_id_column_name = "entry_id";
if (isset($database_image_column_entryid) && $database_image_column_entryid != ""){
$entry_id_column_name = $database_image_column_entryid;
}
$image_params = "\$params = array({$database_image_entry_id});";
if($database_image_entry_id_original == $database_image_entry_id){
$image_params = "\$params = array(\'{$database_image_entry_id}\');";
}
$element .= <<<EOF
<?php
include_once \'./Database.php\';
\$dbh_img = new Database();
\$sql_img = "SELECT {$columnid} FROM {$table} WHERE {$entry_id_column_name} = ?";
{$image_params}
// Set Optional MySQL SSL Properties.
\$dbh_img->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
\$result_img_entries = \$dbh_img->pdo_procedure_params({$database_image_debug_level}, \$sql_img, \$db_host, \$db_type, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$params, \$return_true = 0);
// For every matching row, echo out an image.
\$ct = 0;
foreach(\$result_img_entries as \$entry){
\$rand = md5(rand(1000, 100000));
// Custom Image Call.
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_table_name\'] = "{$table}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_name\'] = "{$column}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_id\'] = "{$columnid}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_database_image_id\'] = \$entry["{$columnid}"];
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true) {
// Inline Images For PDF.
include_once "lib/get_form_image_inline.php";
\$db = array(\$db_type, \$db_host, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$debug);
\$imgData = get_inline_image("null", "normal", "", "", \$rand, \$db);
if(\$imgData[1] != "") {
\$rawData = base64_encode(\$imgData[1]);
echo \'<img class=\"form-image {$extraclassnames}\" src="data:image/\' . \$imgData[0] . \';base64,\' . \$rawData . \'" width=\"{$field->database_image_max_width}\" {$inheritstyle} class=\"rf-form-image\" />\';
}
} else {
echo "<img class=\"form-image {$extraclassnames}\" src=\"lib/get_form_image.php?id=null&size={$size}&rand={\$rand}\" width=\"{$field->database_image_max_width}\" title=\"$text\" {$attribute} {$inheritstyle} id=\"{$id}_{\$ct}\" class=\"rf-form-image\" />";
}
\$ct++;
}
?>
EOF;
}
} else {
$database_image_id_static = $this->uv->replace_all($field->database_image_id, 6);
if ($database_image_id != "") {
$element .= <<<EOF
<?php
include_once \'./Database.php\';
\$dbh_img = new Database();
\$rand = md5(rand(1000, 100000));
// Custom Image Call For Single Images.
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_table_name\'] = "{$table}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_name\'] = "{$column}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_column_id\'] = "{$columnid}";
\$_SESSION["{\$_SESSION[\'entry_key\']}"]["{\$rand}"][\'imagecall_database_image_id\'] = {$database_image_id};
if(isset(\$PAGE_IS_PDF) && \$PAGE_IS_PDF == true) {
// Inline Images For PDF.
include_once "lib/get_form_image_inline.php";
\$db = array(\$db_type, \$db_host, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$debug);
\$imgData = get_inline_image({$database_image_id}, "normal", "", "", \$rand, \$db);
if(\$imgData[1] != "") {
\$rawData = base64_encode(\$imgData[1]);
echo \'<img class=\"form-image {$extraclassnames}\" src="data:image/\' . \$imgData[0] . \';base64,\' . \$rawData . \'" {$inheritstyle} width=\"{$field->database_image_max_width}\" class=\"rf-form-image\" />\';
}
} else {
// Original, Inline Image Echo.
\$val = {$database_image_id};
echo "<img class=\"form-image {$extraclassnames}\" src=\"lib/get_form_image.php?id={\$val}&size={$size}\" width=\"{$field->database_image_max_width}\" title=\"$text\" {$attribute} {$inheritstyle} name=\"{$name}\" id=\"{$id}\" class=\"rf-form-image\" />";
}
?>
EOF;
}
if ($database_image_entry_id != "") {
$database_image_entry_id = $this->uv->replace_all($database_image_entry_id, 4);
$image_params = "\$params = array({$database_image_entry_id});";
if ($database_image_entry_id_original == $database_image_entry_id) {
$image_params = "\$params = array(\'{$database_image_entry_id}\');";
}
$element .= <<<EOF
<?php
include_once \'./Database.php\';
\$dbh_img = new Database();
\$sql_img = "SELECT image_id FROM fb_images WHERE entry_id = ?";
{$image_params}
// Set Optional MySQL SSL Properties.
\$dbh_img->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
\$result_img_entries = \$dbh_img->pdo_procedure_params(0, \$sql_img, \$db_host, \$db_type, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$params, \$return_true = 0);
// For every matching row, echo out image.
foreach(\$result_img_entries as \$entry){
echo "<img class=\"form-image {$extraclassnames}\" src=\"lib/get_form_image.php?id={\$entry[\'image_id\']}&size={$size}\" width=\"{$field->database_image_max_width}\" title=\"$text\" {$attribute} {$inheritstyle} name=\"{$name}\" id=\"{$id}\" class=\"rf-form-image\" />";
}
?>
EOF;
}
}
$element .= "
<?php unset(\$_SESSION[\'form_image_token\']); ?>
";
} else {
$element .= "<img class=\"form-image {$extraclassnames}\" src=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>images/$src\" title=\"$text\" {$attribute} {$inheritstyle} name=\"{$name}\" id=\"{$id}\" />";
}
if ((int)$link_submit == 1) {
$element = "<input type=\"image\" target=\"{$link_target}\" title=\"{$link_title}\" src=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>images/{$src}\" name=\"{$name}\" id=\"{$id}\" {$attribute} {$inheritstyle} value=\"{$text}\" />";
}
if ($link_address != \'\') {
$element = "<a href=\"{$link_address}\" target=\"{$link_target}\" title=\"{$link_title}\"><img class=\"form-image {$extraclassnames}\" src=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>images/{$src}\" name=\"{$name}\" id=\"{$id}\" title=\"{$text}\" border=\"0\" {$attribute} {$inheritstyle} /></a>";
}
if ($route != \'\') {
$element = "<input type=\"image\" title=\"{$link_title}\" target=\"{$link_target}\" src=\"<?php echo \$_SESSION[\'MAX_PATH\']; ?>images/{$src}\" name=\"{$name}\" id=\"{$id}\" {$attribute} {$inheritstyle} value=\"{$text}\" />";
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_video($field, $jobname, $formname, $tablemode, $bucket_node = "")
{
$url = $field->url;
$style = $field->style;
$element = "";
$url = $this->uv->replace_all($url, 6);
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$url_raw_file_name = explode(\'/\', $url);
$url_raw_file_name = explode(\'.\', $url_raw_file_name[count($url_raw_file_name) - 1]);
array_pop($url_raw_file_name);
if (!isset($url_raw_file_name[0])) {
return "";
}
$raw_name = $url_raw_file_name[0];
$url_parts = explode("/", $url);
$url_formatted = "//";
foreach ($url_parts as $idx => $part) {
if ($idx == count($url_parts) - 1) {
$url_formatted .= \'/\' . $raw_name;
} else {
if ($idx > 2)
$url_formatted .= \'/\';
if ($part != \'http:\')
$url_formatted .= $part;
}
}
$poster = "";
if ($field->poster != "") {
$poster = "poster=\"{$field->poster}\"";
}
$element .= <<<EOF
<link href="js/video-js/video-js.css" rel="stylesheet" type="text/css">
<script src="js/video-js/video.js"></script>
<script>
videojs.options.flash.swf = "js/video-js/video-js.swf";
</script>
<video id="{$field->id}" class="video-js vjs-default-skin" controls preload="none" width="{$field->width}" height="{$field->height}"
{$poster}
data-setup="{}">
<source src="{$url}" type=\'video/mp4\' />
<source src="{$url}.webm" type=\'video/webm\' />
<source src="{$url_formatted}.ogv" type=\'video/ogg\' />
<track kind="captions" src="{$field->captions}" srclang="en" label="English" />
Please update your browser to view this video.
</video>
EOF;
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_section_text($field, $page, $datagrid_items, $bucket_node = "")
{
$text = $field->{\'label\'};
$color = $field->color;
$fontsize = $field->fontsize;
$style = $field->style;
$tablemode = $page->tablemode;
$pagepadding = $page->pagepadding;
$dim = $page->dim;
$styles = $this->translateFieldStyles($style);
$text = $this->create_inline_get_vars($text);
$text = $this->create_inline_post_vars($text, \', \');
$text = $this->create_inline_session_vars($text, \', \');
$text = $this->create_inline_php_vars($text, \', \');
$text = $this->uv->replace_all($text, 6.1);
$text = $this->uv->replace_field_raw($text, 0);
$text = $this->uv->replace_field_newline($text, 0);
$text = $this->create_inline_field_vars($text);
$element = $text[1];
$datagrid_items_php = \'\';
$datagrid_items_raw = array();
if (isset($datagrid_items) && count($datagrid_items) != 0) {
$datagrid_items_php = implode(\',\', $datagrid_items);
}
foreach ($datagrid_items as $grid_item) {
$raw = explode(\'|\', $grid_item);
$datagrid_items_raw[] = $raw[0] . "\'";
}
if (is_array($datagrid_items_raw)) {
$datagrid_items_raw = implode(\',\', $datagrid_items_raw);
}
if ($datagrid_items_raw != "") {
$element .= <<<EOF
<?php
// Datagrid Processing.
\$datagrid_items = array({$datagrid_items_php});
\$datagrid_items_raw = array({$datagrid_items_raw});
if(!isset(\$datagrid_items_displayed)) {
\$datagrid_items_displayed = array();
}
?>
EOF;
}
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; height:15px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (!isset($field->style->fieldwidth) || (string)$field->style->fieldwidth == "") {
$fieldwidth = "100%";
} else {
$fieldwidth = (string)$field->style->fieldwidth;
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'95%\';
}
if (!isset($field->style->fieldheight)) {
$fieldheight = "";
} else {
$fieldheight = (string)$field->style->fieldheight;
}
if (!isset($field->style->borderradius) || (string)$field->style->borderradius == "") {
$borderradius = "0";
} else {
$borderradius = (string)$field->style->borderradius;
}
if (!isset($field->style->textalignment) || (string)$field->style->textalignment == "") {
$textalignment = 0;
} else {
$textalignment = (int)$field->style->textalignment;
}
$textalignment = $this->um->translateTextAlignment($textalignment);
$bannermode_margin_left = "";
$bannermode_margin_vertical = "";
if (isset($style->bannermode) && (int)$style->bannermode == 1) {
if ((int)$field->style->bannermode == 1) {
if (isset($page->fullwidth) && (string)$page->fullwidth != "1") {
$this->ce->createBannerModeBlock($dim, $pagepadding, $field, $page, $fieldwidth, $fieldheight, $bannermode_margin_left, $bannermode_margin_vertical, (int)$page->centerform);
}
if (isset($page->fullwidth) && (string)$page->fullwidth == "1") {
if ((int)$page->centerform != 1) {
$fieldwidth = "100%";
}
}
if (defined(\'MOBILE_MODE\')) {
$fieldwidth = "";
$fieldheight = "";
}
}
}
if (!isset($field->style->usebackgroundcolor) || (string)$field->style->usebackgroundcolor == "") {
$backgroundcolor = \'\';
} else {
if ((int)$field->style->usebackgroundcolor == 1 && $field->style->backgroundcolor != "") {
$backgroundcolor = (string)$field->style->backgroundcolor;
} else {
$backgroundcolor = "";
}
}
$gradient_selector = \'\';
if (
isset($field->style->usebackgroundgradient)
&& (int)$field->style->usebackgroundgradient == 1 && $field->style->backgroundgradienttop != "" && $field->style->backgroundgradientbottom != ""
) {
$gradient_selector = \'gradient_\' . substr(md5(rand(10, 40)), 0, 10);
$element .= $this->translateGradient($gradient_selector, (string)$field->style->backgroundgradienttop, (string)$field->style->backgroundgradientbottom);
}
$border_style = \'\';
if ((int)$field->style->useborder == 1) {
$border_style = " border: {$field->style->borderwidth} " . $this->translateBorderStyle((int)$field->style->borderstyle) . " {$field->style->bordercolor}; ";
}
if (!isset($field->style->paddingleft)) {
$padding = "";
} else {
$padding = "";
if (is_numeric((int)$field->style->paddingleft)) {
$padding .= " padding-left:{$field->style->paddingleft}px; ";
}
if (is_numeric((int)$field->style->paddingright)) {
$padding .= " padding-right:{$field->style->paddingright}px; ";
}
if (is_numeric((int)$field->style->paddingtop)) {
$padding .= " padding-top:{$field->style->paddingtop}px; ";
}
if (is_numeric((int)$field->style->paddingbottom)) {
$padding .= " padding-bottom:{$field->style->paddingbottom}px; ";
}
if (isset($style->bannermode) && (int)$style->bannermode == 1) {
if (isset($page->centerform) && (string)$page->centerform == "0") {
$fieldwidth = \'\';
}
}
}
if ($fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight};";
}
if ($backgroundcolor == "") {
$backgroundcolor = "";
} else {
$backgroundcolor = "background-color:{$backgroundcolor};";
}
if (isset($field->elementpos) && $field->elementpos != "0") {
$fieldwidth = \'100%\';
switch ((int)$field->elementpos) {
case 0:
$textalignment = \'left\';
break;
case 1:
$textalignment = \'right\';
break;
case 2:
$textalignment = \'center\';
break;
}
}
$element .= "
<div aria-label=\"Section Text\" class=\"section-head {$gradient_selector}\" style=\"color:{$color}; font-size:{$fontsize}; font-weight:{$styles[\'fontweight\']}; width:{$fieldwidth}; {$fieldheight} {$bannermode_margin_left} {$bannermode_margin_vertical} border-radius:{$borderradius}px; {$border_style} text-align:{$textalignment}; {$backgroundcolor} {$padding} \">
{$text[0]}
</div>
";
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_body_copy($field, $page, $datagrid_items, $bucket_node = "")
{
$text = $field->{\'label\'};
$color = $field->color;
$fontsize = $field->fontsize;
$style = $field->style;
$tablemode = $page->tablemode;
$pagepadding = $page->pagepadding;
$dim = $page->dim;
$styles = $this->translateFieldStyles($style);
$text = $this->create_inline_get_vars($text);
$text = $this->create_inline_post_vars($text, \', \');
$text = $this->create_inline_session_vars($text, \', \');
$text = $this->create_inline_php_vars($text, \', \');
$text = $this->uv->replace_all($text, 6.1);
$text = $this->uv->replace_field_raw($text, 0);
$text = $this->uv->replace_field_newline($text, 0);
$text = $this->create_inline_field_vars($text);
$element = $text[1];
$datagrid_items_php = \'\';
$datagrid_items_raw = array();
if (isset($datagrid_items) && count($datagrid_items) != 0) {
$datagrid_items_php = implode(\',\', $datagrid_items);
}
foreach ($datagrid_items as $grid_item) {
$raw = explode(\'|\', $grid_item);
$datagrid_items_raw[] = $raw[0] . "\'";
}
if (is_array($datagrid_items_raw)) {
$datagrid_items_raw = implode(\',\', $datagrid_items_raw);
}
if ($datagrid_items_raw != "") {
$element .= <<<EOF
<?php
// Datagrid Processing.
\$datagrid_items = array({$datagrid_items_php});
\$datagrid_items_raw = array({$datagrid_items_raw});
if(!isset(\$datagrid_items_displayed)) {
\$datagrid_items_displayed = array();
}
?>
EOF;
}
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; height:15px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (!isset($field->style->fieldwidth) || (string)$field->style->fieldwidth == "") {
$fieldwidth = "100%";
} else {
$fieldwidth = (string)$field->style->fieldwidth;
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'95%\';
}
if (!isset($field->style->fieldheight)) {
$fieldheight = "";
} else {
$fieldheight = (string)$field->style->fieldheight;
}
if (!isset($field->style->borderradius) || (string)$field->style->borderradius == "") {
$borderradius = "0";
} else {
$borderradius = (string)$field->style->borderradius;
}
if (!isset($field->style->textalignment) || (string)$field->style->textalignment == "") {
$textalignment = 0;
} else {
$textalignment = (int)$field->style->textalignment;
}
$textalignment = $this->um->translateTextAlignment($textalignment);
$bannermode_margin_left = "";
$bannermode_margin_vertical = "";
if (isset($style->bannermode) && (int)$style->bannermode == 1) {
if ((int)$field->style->bannermode == 1) {
if (isset($page->fullwidth) && (string)$page->fullwidth != "1") {
$this->ce->createBannerModeBlock($dim, $pagepadding, $field, $page, $fieldwidth, $fieldheight, $bannermode_margin_left, $bannermode_margin_vertical, (int)$page->centerform);
}
if (isset($page->fullwidth) && (string)$page->fullwidth == "1") {
if ((int)$page->centerform != 1) {
$fieldwidth = "100%";
}
}
if (isset($page->centerform) && (string)$page->centerform == "0") {
$fieldwidth = \'\';
}
if (defined(\'MOBILE_MODE\')) {
$fieldwidth = "";
$fieldheight = "";
}
}
}
if (!isset($field->style->usebackgroundcolor) || (string)$field->style->usebackgroundcolor == "") {
$backgroundcolor = \'\';
} else {
if ((int)$field->style->usebackgroundcolor == 1 && $field->style->backgroundcolor != "") {
$backgroundcolor = (string)$field->style->backgroundcolor;
} else {
$backgroundcolor = "";
}
}
$gradient_selector = \'\';
if (
isset($field->style->usebackgroundgradient)
&& (int)$field->style->usebackgroundgradient == 1 && $field->style->backgroundgradienttop != "" && $field->style->backgroundgradientbottom != ""
) {
$gradient_selector = \'gradient_\' . substr(md5(rand(10, 40)), 0, 10);
$element .= $this->translateGradient($gradient_selector, (string)$field->style->backgroundgradienttop, (string)$field->style->backgroundgradientbottom);
}
$border_style = \'\';
if ((int)$field->style->useborder == 1) {
$border_style = " border: {$field->style->borderwidth} " . $this->translateBorderStyle((int)$field->style->borderstyle) . " {$field->style->bordercolor}; ";
}
if (!isset($field->style->paddingleft)) {
$padding = "";
} else {
$padding = "";
if (is_numeric((int)$field->style->paddingleft)) {
$padding .= " padding-left:{$field->style->paddingleft}px; ";
}
if (is_numeric((int)$field->style->paddingright)) {
$padding .= " padding-right:{$field->style->paddingright}px; ";
}
if (is_numeric((int)$field->style->paddingtop)) {
$padding .= " padding-top:{$field->style->paddingtop}px; ";
}
if (is_numeric((int)$field->style->paddingbottom)) {
$padding .= " padding-bottom:{$field->style->paddingbottom}px; ";
}
}
if ($fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight};";
}
if ($backgroundcolor == "") {
$backgroundcolor = "";
} else {
$backgroundcolor = "background-color:{$backgroundcolor};";
}
if (isset($field->elementpos) && $field->elementpos != "0") {
$fieldwidth = \'\';
}
if (isset($field->elementpos) && $field->elementpos != "0") {
$fieldwidth = \'100%\';
switch ((int)$field->elementpos) {
case 0:
$textalignment = \'left\';
break;
case 1:
$textalignment = \'right\';
break;
case 2:
$textalignment = \'center\';
break;
}
}
$element .= "
<div aria-label=\"Body Copy\" class=\"body-copy {$gradient_selector}\" style=\"color:{$color}; font-size:{$fontsize}; font-weight:{$styles[\'fontweight\']}; width:{$fieldwidth}; {$fieldheight} {$bannermode_margin_left} {$bannermode_margin_vertical} border-radius:{$borderradius}px; {$border_style} text-align:{$textalignment}; {$backgroundcolor} {$padding} \">
{$text[0]}
</div>
";
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "
</div>";
}
return $element;
}
public function create_default_value_tokens($defaultvalue)
{
if (substr_count($defaultvalue, \'->\') == 0) {
$defaultvalue = htmlentities($defaultvalue, ENT_COMPAT, \'UTF-8\');
}
$has_match = 0;
$matches = array();
preg_match_all(\'/(^|.|
|
)(\@\{(.*?)\})/\', $defaultvalue, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$has_match = 1;
$defaultvalue = str_replace(\'@{\' . $m . \'}\', "isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']) ? \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\'] : \'\'", $defaultvalue);
}
}
$matches = array();
preg_match_all(\'/(^|.|
|
)(#\{(.*?)\})/\', $defaultvalue, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$has_match = 1;
$defaultvalue = str_replace(\'#{\' . $m . \'}\', "isset(\$_GET[\'{$m}\']) ? \$_GET[\'{$m}\'] : \'\'", $defaultvalue);
}
}
$matches = array();
preg_match_all(\'/(^|.|
|
)(\*\{(.*?)\})/\', $defaultvalue, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$has_match = 1;
$defaultvalue = str_replace(\'*{\' . $m . \'}\', "isset(\$_POST[\'{$m}\']) ? \$_POST[\'{$m}\'] : \'\'", $defaultvalue);
}
}
$matches = array();
preg_match_all(\'/(^|.|
|
)(\^\{(.*?)\})/\', $defaultvalue, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$has_match = 1;
$defaultvalue = str_replace(\'^{\' . $m . \'}\', "isset(\$_SESSION[\'{$m}\']) ? \$_SESSION[\'{$m}\'] : \'\'", $defaultvalue);
}
}
$matches = array();
preg_match_all(\'/(^|.|
|
)?(PHP\{(.*?)\})/\', $defaultvalue, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$has_match = 1;
$defaultvalue = str_replace(\'PHP{\' . $m . \'}\', "isset(\${$m}) ? (is_a(\${$m}, \'DateTime\') ? \${$m}->format(\'m/d/Y\') : ( validateDate(\${$m}) ? printValidatedDate(\${$m}, \'Y-m-d H:i:s\', \'m/d/Y\') : \${$m} ) ) : \'\'", $defaultvalue);
}
}
$defaultvalue_new = $this->uv->replace_all($defaultvalue, 4);
if ($defaultvalue_new != $defaultvalue) {
$has_match = 1;
}
$defaultvalue = $defaultvalue_new;
if (!$has_match) {
$defaultvalue = \'"\' . $defaultvalue . \'"\';
}
return $defaultvalue;
}
public function create_text($page, $field, $datasource, $savepath, $tablemode, $bucket_node = "")
{
$label = $field->{\'label\'};
$html5type = $field->html5type;
$formatas = $field->formatas;
$placeholder = $field->placeholder;
$tailtext = $field->tailtext;
$name = $field->{\'name\'};
$id = $field->{\'id\'};
$req = $field->validation->req;
$fieldwidth = $field->fieldwidth;
$fieldheight = $field->fieldheight;
$defaultvalue = $field->defaultvalue;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$maxlength = $field->validation->max;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$autosuggest = $field->autosuggest;
$colorpicker = $field->colorpicker;
$jslider = $field->jslider;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
if (!isset($placeholder)) {
$placeholder = "";
}
if (!isset($tailtext)) {
$tailtext = "";
}
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$colorpicker = $this->translateColorpicker($colorpicker, $id);
$jslider = $this->translateJslider($jslider, $id);
$html5_range = "";
if ($html5type == "range") {
$range_min = $field->html5_range_min == "" ? 0 : $field->html5_range_min;
$range_max = $field->html5_range_max == "" ? 0 : $field->html5_range_max;
$html5_range = "min=\"{$range_min}\" max=\"{$range_max}\" data-highlight=\"true\"";
}
$element = \'\';
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$defaultvalue = $this->create_default_value_tokens($defaultvalue);
if (!isset($fieldheight)) {
$fieldheight = "";
} else {
if ((string)$fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight}px;";
}
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (is_numeric((string)$fieldwidth) == true) {
$fieldwidth = $fieldwidth . \'px\';
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'89%\';
}
if (isset($page) && $page->jslibrary == "14") {
$fieldheight = "";
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
if ($maxlength != \'\') {
$max = "maxlength=\"{$maxlength}\"";
} else {
$max = \'\';
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
if ((string)$label != " " || $this->get_label_pos($labelpos, (string)$field->type) != "float:left;") {
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, $field->fieldheight, $tablemode);
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1) {
$bottom_margin_value = intval($tablemode->marginbottom);
if (isset($field->bucket) && (string)$field->bucket != \'\') {
$element .= "
<div class=\"fb-tablemode-element\" style=\"float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
} else {
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
}
if ($html5type == "") {
$html5type = "text";
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$_ph = "";
if (isset($placeholder) && $placeholder != "") {
$_ph = " placeholder=\"{$placeholder}\" ";
}
$element .= $this->create_table_mode_mobile_label($field, $tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$format_trigger = "";
$format_script = "";
if(isset($formatas) && (string)$formatas != ""){
switch((string)$formatas){
case "usphone" :
$format_trigger = "onkeydown=\"phoneNumberFormatter()\"";
$format_script = <<<EOF
<script>
function formatPhoneNumber(value) {
if (!value) return value;
const phoneNumber = value.replace(/[^\d]/g, "");
const phoneNumberLength = phoneNumber.length;
if (phoneNumberLength < 4) return phoneNumber;
if (phoneNumberLength < 7) {
return `(\${phoneNumber.slice(0, 3)}) \${phoneNumber.slice(3)}`;
}
return `(\${phoneNumber.slice(0, 3)}) \${phoneNumber.slice(
3,
6
)}-\${phoneNumber.slice(6, 10)}`;
}
function phoneNumberFormatter() {
const inputField = document.getElementById(\'{$field->id}\');
const formattedInputValue = formatPhoneNumber(inputField.value);
inputField.value = formattedInputValue;
}
</script>
EOF;
break;
case "uppercase" :
$format_trigger = "onkeyup=\"this.value = this.value.toUpperCase()\"";
break;
case "lowercase" :
$format_trigger = "onkeyup=\"this.value = this.value.toLowerCase()\"";
break;
case "usssn" :
$format_trigger = "onkeyup=\"formatUSSSN(this)\"";
$format_script = <<<EOF
<script>
function formatUSSSN(elt){
var val = elt.value.replace(/\D/g, \'\');
var newVal = \'\';
if(val.length > 4) {
this.value = val;
}
if((val.length > 3) && (val.length < 6)) {
newVal += val.substr(0, 3) + \'-\';
val = val.substr(3);
}
if (val.length > 5) {
newVal += val.substr(0, 3) + \'-\';
newVal += val.substr(3, 2) + \'-\';
val = val.substr(5);
}
newVal += val;
elt.value = newVal.substring(0, 11);
}
</script>
EOF;
}
}
$element .= $format_script;
if(isset($fieldpopulatedefault) && $fieldpopulatedefault == 1){
$element .= "<input <?php echo \$enabled; ?> {$_ph} class=\"form-control {$extraclassnames}\" type=\"{$html5type}\" {$html5_range} {$max} name=\"{$name}\" id=\"{$id}\" {$tabhtml} " . \' value="<?php isset($_SESSION[\' . "\'{$name}\']) ? print " . \'htmlentities($_SESSION[\' . "\'{$name}\'], ENT_COMPAT, \'UTF-8\') : print " . $defaultvalue . "; ?>" . \'" \' . $inheritstyle . $attribute . $conditional_call_inline . $enabled . $readonly . $format_trigger . \' />\';
} else {
$element .= "<input <?php echo \$enabled; ?> {$_ph} class=\"form-control {$extraclassnames}\" type=\"{$html5type}\" {$html5_range} {$max} name=\"{$name}\" id=\"{$id}\" {$tabhtml} " . \' value="<?php print \' . $defaultvalue . "; ?>" . \'" \' . $inheritstyle . $attribute . $conditional_call_inline . $enabled . $readonly . \' />\';
}
$element .= "
<span class=\"tailtext\">{$tailtext}</span>
";
if ($tooltip != "" && $this->get_label_pos($labelpos, (string)$field->type) == "float:left;") {
$element .= $this->create_tooltip_html($tooltip, $name);
}
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
$element .= $colorpicker->jscode;
$element .= $jslider->jscode;
if ($helper != \'\') {
$element .= "
<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>
";
} else {
$element .= "
<br />
";
}
if ((int)$tablemode->enabletablelayout == 1) {
$element .= "</div>";
}
if ((int)$autosuggest->enable == 1 && $autosuggest->mode == 0) {
$params = \'$params = array(\';
$params .= $this->uv->replace_all((string)$datasource->sourcesqlparams, 4);
$params .= \');\';
$call_code = "\$dbh->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
";
$call_code .= "\$result_{$name} = \$dbh->pdo_procedure_params(\$query_debug, \$sql_{$name}, \$db_host, \$db_type, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$params, 0, 0);";
$sourcetype = $this->um->translateSourceType((int)$datasource->sourcetype);
if (!isset($datasource->dbdsn)) {
$datasource->dbdsn = "";
}
$datasource->dbhost = $this->uv->replace_all($datasource->dbhost, 8);
$datasource->dbuser = $this->uv->replace_all($datasource->dbuser, 8);
$datasource->dbpwd = $this->uv->replace_all($datasource->dbpwd, 8);
$datasource->dbschema = $this->uv->replace_all($datasource->dbschema, 8);
$datasource->dbsocket = $this->uv->replace_all($datasource->dbsocket, 8);
$datasource->dbport = $this->uv->replace_all($datasource->dbport, 8);
$datasource->dbdsn = $this->uv->replace_all($datasource->dbdsn, 8);
$this->um->pullCustomConnectorFile($field->dbconnector);
$call_page = <<<EOY
<?php
if(!session_id()) { session_start(); }
// Perform auto-suggest sql query for {$name}
\$query_debug = $datasource->dbdebuglevel; // change to 1 to see debug info if you run into problems executing your query (may need to look at html page source to see error).
\$db_schema_check = "{$datasource->dbschema}";
\$db_dsn_check = "{$datasource->dbdsn}";
if(\$db_schema_check != \'\' || \$db_dsn_check != \'\'){
\$db_host = "{$datasource->dbhost}";
\$db_type = "{$sourcetype}";
\$db_user = "{$datasource->dbuser}";
\$db_pass = "{$datasource->dbpwd}";
\$db_catalog = "{$datasource->dbschema}";
\$mysql_socket = "{$datasource->dbsocket}";
\$mysql_port = "{$datasource->dbport}";
\$dbdsn = "{$datasource->dbdsn}";
\$db_ssl_key = \'{$field->dbsslkey}\';
\$db_ssl_certificate = \'{$field->dbsslcertificate}\';
\$db_ssl_ca_cert = \'{$field->dbsslcacert}\';
\$db_ssl_verify_cert = \'{$field->dbsslverifycert}\';
\$db_ssl_cipher = \'{$field->dbsslcipher}\';
}
@include_once "../../Database.php";
if(!session_id()) { session_start(); }
// optional connector script
if(file_exists("../../{$datasource->dbconnector}") && is_readable("../../{$datasource->dbconnector}")){
// Build 695 - Prevent Lookups of null files
if("../../{$datasource->dbconnector}" != "../../"){
@include "../../{$datasource->dbconnector}";
}
}
// Create Text Query
\$sql_{$name} = "{$datasource->sourcesql}";
\$dbh = new Database();
{$params}
{$call_code}
\$input = strtolower( \$_GET[\'input\'] );
\$len = strlen(\$input);
\$limit = isset(\$_GET[\'limit\']) ? (int) \$_GET[\'limit\'] : 0;
\$aResults = array();
\$aInfo = array_fill(0, count(\$result_{$name}), \'\');
\$count = 0;
if (\$len)
{
for (\$i=0;\$i<count(\$result_{$name});\$i++)
{
// had to use utf_decode, here
// not necessary if the results are coming from mysql
//
if (strtolower(substr(utf8_decode(\$result_{$name}[\$i][0]),0,\$len)) == \$input)
{
\$count++;
\$aResults[] = array( "id"=>(\$i+1) ,"value"=>htmlspecialchars(\$result_{$name}[\$i][0]), "info"=>htmlspecialchars(\$aInfo[\$i]) );
}
if (\$limit && \$count==\$limit)
break;
}
}
// send content headers
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header ("Pragma: no-cache"); // HTTP/1.0
if (isset(\$_REQUEST[\'json\']))
{
header("Content-Type: application/json");
echo "{\"results\": [";
\$arr = array();
for (\$i=0;\$i<count(\$aResults);\$i++)
{
\$arr[] = "{\"id\": \"".\$aResults[\$i][\'id\']."\", \"value\": \"".\$aResults[\$i][\'value\']."\", \"info\": \"\"}";
}
echo implode(", ", \$arr);
echo "]}";
}
?>
EOY;
file_put_contents($savepath . $name . \'.php\', $call_page);
chmod($savepath . $name . \'.php\', FILE_MOD);
if (!isset($autosuggest->callback)) {
$autosuggest->callback = "";
}
if (!isset($autosuggest->cachemode)) {
$autosuggest->cachemode = 0;
}
if ((int)$autosuggest->cachemode == 0) {
$autosuggest->cachemode = \'true\';
} else {
$autosuggest->cachemode = \'false\';
}
$element .= <<<EOH
<script type="text/javascript">
as_field = "{$id}";
var options = {
script:"js/autosuggest/{$name}.php?json=true&limit={$autosuggest->suggestions}&",
varname:"input",
json:true,
cache:{$autosuggest->cachemode},
shownoresults:false,
minchars:{$autosuggest->minchars},
maxentries:{$autosuggest->suggestions},
delay:{$autosuggest->delay},
timeout:{$autosuggest->timeout},
callback: function(e){
// Your custom callback code here...
{$autosuggest->callback}
}
};
var as_json = new bsn.AutoSuggest(\'{$id}\', options);
</script>
EOH;
}
if ((int)$autosuggest->enable == 1 && $autosuggest->mode == 1) {
$call_page = <<<EOU
<?php
// read in xml file
\$xmldata = file_get_contents(\'../../\' . \'{$autosuggest->xmlfilelocation}\');
// load/parse xml
\$root = simplexml_load_string(\$xmldata);
\$result_{$name} = get_object_vars(\$root);
\$input = strtolower( \$_GET[\'input\'] );
\$len = strlen(\$input);
\$limit = isset(\$_GET[\'limit\']) ? (int) \$_GET[\'limit\'] : 0;
\$aResults = array();
\$aInfo = array_fill(0, count(\$result_{$name}[\'rs\']), \'\');
\$count = 0;
if (\$len)
{
for (\$i=0;\$i<count(\$result_{$name}[\'rs\']);\$i++)
{
// had to use utf_decode, here
// not necessary if the results are coming from mysql
//
if (strtolower(substr(utf8_decode(\$result_{$name}[\'rs\'][\$i]),0,\$len)) == \$input)
{
\$count++;
\$aResults[] = array( "id"=>(\$i+1) ,"value"=>htmlspecialchars((string)\$result_{$name}[\'rs\'][\$i]), "info"=>htmlspecialchars(\$aInfo[\$i]) );
}
if (\$limit && \$count==\$limit)
break;
}
}
// send content headers
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header ("Pragma: no-cache"); // HTTP/1.0
if (isset(\$_REQUEST[\'xml\']))
{
header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?><results>";
for (\$i=0;\$i<count(\$aResults);\$i++)
{
echo "<rs id=\"".\$aResults[\$i][\'id\']."\" info=\"".\$aResults[\$i][\'info\']."\">".\$aResults[\$i][\'value\']."</rs>";
}
echo "</results>";
}
?>
EOU;
file_put_contents($savepath . $name . \'.php\', $call_page);
chmod($savepath . $name . \'.php\', FILE_MOD);
$element .= <<<EOH
<script type="text/javascript">
var options = {
script:"js/autosuggest/{$name}.php?xml=true&limit={$autosuggest->suggestions}&",
varname:"input",
json:false,
shownoresults:false,
minchars:{$autosuggest->minchars},
maxresults:{$autosuggest->suggestions},
delay:{$autosuggest->delay},
timeout:{$autosuggest->timeout},
callback: function(e){
// Make sure AJAX calls have an event (onblur) to bind to...
document.getElementsByTagName(\'input\')[(document.forms[0].length - 1)].focus();
document.getElementById(\'{$id}\').focus();
// Your custom callback code here...
}
};
var as_xml = new bsn.AutoSuggest(\'{$id}\', options);
</script>
EOH;
}
return $element;
}
public function create_password($page, $field, $tablemode, $bucket_node = "")
{
$label = $field->{\'label\'};
$name = $field->{\'name\'};
$id = $field->{\'id\'};
$req = $field->validation->req;
$fieldwidth = $field->fieldwidth;
$fieldheight = $field->fieldheight;
$defaultvalue = $field->defaultvalue;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$maxlength = $field->validation->max;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$element = "";
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$defaultvalue = $this->create_default_value_tokens($defaultvalue);
if (!isset($fieldheight)) {
$fieldheight = "";
} else {
if ((string)$fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight}px;";
}
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (is_numeric((string)$fieldwidth) == true) {
$fieldwidth = $fieldwidth . \'px\';
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'85%\';
}
if (isset($page) && $page->jslibrary == "14") {
$fieldheight = "";
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
}
if ($maxlength != \'\') {
$max = "maxlength=\"{$maxlength}\"";
} else {
$max = \'\';
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
if (isset($field->bucket) && (string)$field->bucket != \'\') {
$element .= "
<div class=\"fb-tablemode-element\" style=\"float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
} else {
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$element .= $this->create_table_mode_mobile_label($field, $tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
if(isset($fieldpopulatedefault) && $fieldpopulatedefault == 1){
$element .= "<input <?php echo \$enabled; ?> class=\"form-control {$extraclassnames}\" type=\"password\" {$max} name=\"{$name}\" id=\"{$id}\" {$tabhtml} " . \' value="<?php isset($_SESSION[\' . "\'{$name}\']) ? print " . \'htmlentities($_SESSION[\' . "\'{$name}\'], ENT_COMPAT, \'UTF-8\') : print " . $defaultvalue . "; ?>" . \'" \' . $inheritstyle . $attribute . $conditional_call_inline . $enabled . $readonly . " />";
} else {
$element .= "<input <?php echo \$enabled; ?> class=\"form-control {$extraclassnames}\" type=\"password\" {$max} name=\"{$name}\" id=\"{$id}\" {$tabhtml} value=\"\" " . $inheritstyle . $attribute . $conditional_call_inline . $enabled . $readonly . " />";
}
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($helper != \'\') {
$element .= "
<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>
";
} else {
$element .= "
<br />
";
}
if (isset($field->validation->passwordstrength) && (int)$field->validation->passwordstrength == 1) {
$element .= <<<EOF
<div id="pws_progressbar"><div id="pws_progress"></div></div>
<div id="pws_status">
<div id="pws_complexity">0%</div>
<div id="pws_complexityLabel">Complexity</div>
</div>
<script type="text/javascript">
var password_options = { minimumChars: 8, strengthScaleFactor: .5 }
$(function () {
$("#{$id}").complexify(password_options, function (valid, complexity) {
if (!valid) {
$(\'#pws_progress\').css({\'width\':complexity + \'%\'}).removeClass(\'pws_progressbarValid\').addClass(\'pws_progressbarInvalid\');
} else {
$(\'#pws_progress\').css({\'width\':complexity + \'%\'}).removeClass(\'pws_progressbarInvalid\').addClass(\'pws_progressbarValid\');
}
$(\'#pws_complexity\').html(Math.round(complexity) + \'%\');
});
});
</script>
EOF;
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_textarea($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$placeholder = $field->placeholder;
$name = $field->name;
$id = $field->id;
$fieldwidth = $field->fieldwidth;
$fieldheight = $field->fieldheight;
$req = $field->validation->req;
$defaultvalue = $field->defaultvalue;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$maxlength = $field->validation->max;
$countitems = $field->validation->valcountitems;
$countitemscolor = $field->validation->countitemscolor;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$tinymce = $field->tinymce;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
if (!isset($placeholder)) {
$placeholder = "";
}
$element = "";
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$defaultvalue = $this->create_default_value_tokens($defaultvalue);
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (is_numeric((string)$fieldwidth) == true) {
$fieldwidth = $fieldwidth . \'px\';
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'95%\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; width:{$fieldwidth}; height:{$fieldheight}px; {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; width:{$fieldwidth}; height:{$fieldheight}px; {$attributestyle} \" ";
}
$maxlength = $maxlength != \'\' ? $maxlength : 500;
$ct_text = \'\';
if ($countitems == 1 || $countitems == 2) {
$action = $countitems == 1 ? \'cntWords\' : \'cntChars\';
$ct_text = "onkeyup=\"{$action}(this,this.id,{$maxlength})\"";
}
$tiny_mce = \'\';
$tiny_mce_entities_start = \'\';
$tiny_mce_entities_end = \'\';
if ($tinymce != 0) {
$tiny_mce = \'class="mceEditor"\';
} else {
$tiny_mce_entities_start = \'htmlentities(\';
$tiny_mce_entities_end = \', null, "UTF-8")\';
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$_ph = "";
if (isset($placeholder) && $placeholder != "") {
$_ph = " placeholder=\"{$placeholder}\" ";
}
$element .= $this->create_table_mode_mobile_label($field,$tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
if(isset($fieldpopulatedefault) && $fieldpopulatedefault == 1){
$element .= "<textarea <?php echo \$enabled; ?> {$tiny_mce} name=\"{$name}\" {$_ph} class=\"form-control {$extraclassnames}\" id=\"{$id}\" {$tabhtml} {$ct_text} {$inheritstyle} {$attribute} {$conditional_call_inline} {$enabled} {$readonly} >";
$element .= \'<?php isset($_SESSION[\' . "\'{$name}\']) ? print " . $tiny_mce_entities_start . \'$_SESSION[\' . "\'{$name}\']" . $tiny_mce_entities_end . " : print {$defaultvalue}; ?>";
$element .= "</textarea>";
} else {
$element .= "<textarea <?php echo \$enabled; ?> {$tiny_mce} name=\"{$name}\" {$_ph} class=\"form-control {$extraclassnames}\" id=\"{$id}\" {$tabhtml} {$ct_text} {$inheritstyle} {$attribute} {$conditional_call_inline} {$enabled} {$readonly} >";
$element .= \'<?php print \' . $defaultvalue . "; ?>";
$element .= "</textarea>";
}
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($countitems != 0) {
$action = $countitems == 1 ? \'Words Typed\' : \'Characters Entered\';
$color = "color: #888888;";
if (isset($countitemscolor) && $countitemscolor != "") {
$color = "color: {$countitemscolor};";
}
$element .= <<<EOT
<br/>
<div style="{$color} display:inline;" class="count-helper">{$action}:</div><div style="{$color} display:inline;" class="count-helper-bold" name="count_{$id}" id="count_{$id}"></div>
<div style="{$color} display:inline;" class="count-helper">Remaining:</div><div style="{$color} display:inline;" class="count-helper-bold" name="left_{$id}" id="left_{$id}"></div>
<div style="{$color} display:inline;" id="{$id}_err" class="count-helper-error"></div>
EOT;
}
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
} else {
$element .= "<br />";
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_submit_button($field, $security_array, $tablemode, $persistance, $persistancelanguage, $bucket_node = "")
{
$label = $field->label;
$captcha = $field->captcha;
$characters = $field->characters;
$width = $field->fieldwidth;
$height = $field->height;
$color = $field->color;
$captchatext = $field->captchatext;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$republickey = $field->republickey;
$ressl = $field->ressl;
$restyle = $field->restyle;
$relang = $field->relang;
$name = $field->name;
$id = $field->id;
$challenegequestion = $field->challengequestion;
$challengeanswer = $field->challengeanswer;
$challengecolor = $field->challengecolor;
$tabindex = $field->tabindex;
$custom_css = $field->custom_css;
$nocaptcharecaptcha_sitekey = $field->nocaptcharecaptcha_sitekey;
$nocaptcharecaptcha_secret = $field->nocaptcharecaptcha_secret;
$nocaptcharecaptcha_language = $field->nocaptcharecaptcha_language;
if ((int)$persistance == "") {
$persistance = 0;
}
if ((string)$persistancelanguage == "") {
$persistancelanguage = 0;
}
$element = "";
$element .= $this->create_custom_css_block($id, $custom_css);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$active = (int)$security_array->active;
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = " style=\"{$attributestyle} \" ";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
if (!isset($ressl) || $ressl == "") {
$ressl = 0;
}
switch ($ressl) {
case \'0\':
$ressl = \'false\';
break;
case \'1\':
$ressl = \'true\';
break;
}
if (!isset($restyle) || $restyle == "") {
$restyle = 0;
}
switch ($restyle) {
case \'0\':
$restyle_code = \'red\';
break;
case \'1\':
$restyle_code = \'white\';
break;
case \'2\':
$restyle_code = \'blackglass\';
break;
case \'3\':
$restyle_code = \'clean\';
break;
}
if (!isset($captchatext) || $captchatext == "") {
$captchatext = "Enter Code:";
}
if (!isset($relang) || $relang == "") {
$relang = "en";
} else {
$relang = $this->um->translateRecaptchaLanguage($relang);
}
$_custom_selector = "";
if (isset($custom_css->all) && $custom_css->all != "" && $custom_css->all != \'<style type="text/css"></style>\') {
$matches = array();
preg_match_all(\'/[#.][a-z-A-Z0-9_]+/\', (string)$custom_css->all, $matches);
if (isset($matches[0]) && isset($matches[0][0]) && $matches[0][0] != "") {
$_custom_selector = $matches[0][0];
$_custom_selector = str_replace(\'.\', \'\', $_custom_selector);
$_custom_selector = str_replace(\'#\', \'\', $_custom_selector);
}
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$ct1 = substr_count((string)$width, \'pt\');
$ct2 = substr_count((string)$width, \'px\');
$ct3 = substr_count((string)$width, \'%\');
if (trim($width) == "") {
$width = "";
} else {
if ($ct1 == 0 && $ct2 == 0 && $ct3 == 0) {
$width = \'width:\' . $width . \'px;\';
} else {
$width = \'width:\' . $width . \';\';
}
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
switch ($captcha) {
case \'0\':
$element .= "
<input name=\"{$name}\" id=\"{$id}\" style=\"{$width}\" class=\"nolabel btn btn-primary {$_custom_selector} {$extraclassnames}\" type=\"submit\" {$tabhtml} value=\"{$label}\" {$attribute} onclick=\"fb.disable_submit(event);\" {$enabled} {$readonly} />
";
break;
case \'1\':
$_width = (int)$field->width;
$_height = (int)$field->height;
if (trim($_width) == "") {
$_width = 140;
}
if (trim($_height) == "") {
$_height = 140;
}
$element .= <<<EOT
<div style="margin-bottom:-7px;"><img src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>security/Captcha/CaptchaSecurityImages.php?width={$_width}&height={$_height}&characters={$characters}" /></div><br/>
<span class="heading-main" style="color:{$color};">{$captchatext}</span>
<input id="security_code" name="security_code" type="text" size="7" autocomplete="off" /><br/><br/>
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" value="{$label}" onclick="fb.disable_submit(event);" {$attribute} {$inheritstyle} />
EOT;
break;
case \'2\':
$element .= <<<EOT
<script type="text/javascript">
var RecaptchaOptions = {
theme : \'{$restyle_code}\',
lang: \'{$relang}\'
};
</script>
<?php
// this value is set from the RackForms editor, it may be blank, at which point the value set in your config.php file will be used.
\$publickey = "{$republickey}"; // you got this from the signup page
// Optional connector script for reCAPTCHA public key value
// if the included value of \$privatekey is blank, we use the value passed in from the editor.
\$active = {$active};
@include_once "{\$_SESSION[\'MAX_PATH\']}security/secure_submit.php";
if(isset(\$publickey) && \$publickey != \'\'){
// Public key has been set from config.php
} else {
\$publickey = "{$republickey}"; // reCAPTCHA public key from signup process
}
require_once("{\$_SESSION[\'MAX_PATH\']}security/reCaptcha/recaptchalib.php");
echo recaptcha_get_html(\$publickey, \'\', {$ressl});
?>
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" value="{$label}" onclick="fb.disable_submit(event);" {$attribute} {$inheritstyle} />
EOT;
break;
case \'3\':
$element .= <<<EOT
<?php @include "{\$_SESSION[\'MAX_PATH\']}security/3DCaptcha/TextGen.php"; ?>
<div style="margin-bottom:-7px;"> <img src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>security/3DCaptcha/3DCaptcha.php" alt="Captcha"> </div>
<br />
<span class="heading-main" style="color:{$color};">{$captchatext}</span>
<input id="3DCaptchaText" name="3DCaptchaText" type="text" size="7" autocomplete="off" /><br />
<br />
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" value="{$label}" onclick="fb.disable_submit(event);" {$attribute} {$inheritstyle} />
EOT;
break;
case \'4\':
$element .= <<<EOT
<?php \$_SESSION["{\$_SESSION[\'entry_key\']}"][\'challenge_answer\'] = \'{$challengeanswer}\'; ?>
<span class="heading-main" style="color:{$challengecolor};">Security Question:</span><br />
<span class="heading-sub" style="color:{$challengecolor};">{$challenegequestion}</span><br />
<input id="challenge_answer" name="challenge_answer" type="text" size="20" autocomplete="off" /><br /><br />
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" value="{$label}" onclick="fb.disable_submit(event);" {$attribute} {$inheritstyle} />
EOT;
break;
case \'5\':
if (isset($nocaptcharecaptcha_language) && $nocaptcharecaptcha_language != "") {
$element .= <<<EOT
<script type="text/javascript">
var onloadCallback = function() {
grecaptcha.render(\'{$field->id}\', {
\'sitekey\' : \'{$nocaptcharecaptcha_sitekey}\',
\'hl\' : \'{$nocaptcharecaptcha_language}\'
});
};
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer>
</script>
<div id="{$field->id}" class="g-recaptcha" data-sitekey="{$nocaptcharecaptcha_sitekey}"></div><br />
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" onclick="fb.disable_submit(event);" value="{$label}" {$attribute} {$inheritstyle} />
EOT;
} else {
$element .= <<<EOT
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="{$nocaptcharecaptcha_sitekey}"></div><br />
<input class="nolabel btn-default {$_custom_selector} {$extraclassnames}" type="submit" name="submit" id="submit" value="{$label}" {$attribute} {$inheritstyle} />
EOT;
}
break;
}
if ($persistance == 3 && $field->route == "") {
$submit_text = "Save and Return Later";
if (isset($persistancelanguage)) {
switch ((int)$persistancelanguage) {
case 1:
$submit_text = "Opslaan en later bewerken";
break;
case 2:
$submit_text = "Zu speichern und spter";
break;
case 3:
$submit_text = "Salvare e tornare pi tardi";
break;
case 4:
$submit_text = "Guardar y volver ms tarde";
break;
}
$persistancelanguage = (int)$persistancelanguage;
} else {
$persistancelanguage = "0";
}
$element .= <<<EOF
<input type="hidden" name="rf_save_and_return" id="rf_save_and_return" value="false" />
<script type="text/javascript">
function updateSaveReturn() { document.getElementById(\'rf_save_and_return\').value=\'true\'; }
document.getElementById(\'rf_save_and_return\').value = \'false\'; // Reset On Page Load.
</script>
<input class="nolabel btn btn-primary fld-full mui-btn mui-btn--primary" type="button" value="{$submit_text}" onclick="updateSaveReturn(); document.forms[0].submit();" />
<?php \$_SESSION["{\$_SESSION[\'entry_key\']}"][\'SAVE_AND_RESUME_LANGUAGE\'] = \'{$persistancelanguage}\'; ?>
EOF;
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= <<<EOF
<?php
if(isset(\$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\']) && \$_SESSION[\'FB_WORKFLOW\'][\'IS_FORMBOSS_WORKFLOW_LOADER\'] == true){
\$html = <<<EOJ
<script type="text/javascript" src="../../../app/js/prototype.js"></script>
<script type="text/javascript">
document.observe(\'dom:loaded\', function(l){
var iframe_parent_div = window.frameElement ? window.frameElement.parentNode : null;
var control_header = ($(iframe_parent_div).adjacent(\'.job-viewer-header\'));
var controls_wrapper = $(control_header[0]).down(\'.job-viewer-task-controls-wrapper\');
current_task_master_id_val = $(controls_wrapper).down(\'INPUT\', 0).value;
current_active_task_id_val = $(controls_wrapper).down(\'INPUT\', 1).value;
current_stage_name_val = $(controls_wrapper).down(\'INPUT\', 2).value;
workflow_job_id_val = $(controls_wrapper).down(\'INPUT\', 3).value;
timeline_load = $(controls_wrapper).down(\'INPUT\', 4).value;
$(\'FORMBOSS_WORKFLOW_CURRENT_TASK_MASTER_ID\').value = current_task_master_id_val;
$(\'FORMBOSS_WORKFLOW_CURRENT_ACTIVE_TASK_ID\').value = current_active_task_id_val;
$(\'FORMBOSS_WORKFLOW_CURRENT_STAGE_NAME\').value = current_stage_name_val;
$(\'FORMBOSS_WORKFLOW_JOB_ID\').value = workflow_job_id_val;
$(\'FORMBOSS_WORKFLOW_TIMELINE_LOAD\').value = timeline_load;
// add dynamic onclick property callback to the forms submit button
$(\'{$id}\').writeAttribute(\'onclick\', \'workflow_submit_clicked();\');
});
function workflow_submit_clicked(){
var iframe_parent_div = window.frameElement ? window.frameElement.parentNode : null;
var task_management_wrapper = ($(iframe_parent_div).adjacent(\'.task-management-wrapper\'));
if($(task_management_wrapper[0]) !== undefined){ // not always present...
// note .adjacent returns a collection, so we must specify [0]
$(\'FORMBOSS_WORKFLOW_TASK_MANAGEMENT_TASK_COMMENT\').value = $(task_management_wrapper[0]).down(\'.task-management-comment\').value;
// stage select logic
if($(task_management_wrapper[0]).down(\'.task-management-stage-select\') !== undefined){ // not always present even if comments are...
// Chrome bug - grabs display value instead of value proeprty
val_test = $(task_management_wrapper[0]).down(\'.task-management-stage-select\').value;
if(val_test == \'--SELECT A STAGE--\')
val_test = \'\';
$(\'FORMBOSS_WORKFLOW_TASK_MANAGEMENT_STAGE_SELECT\').value = val_test;
}
}
}
</script>
EOJ;
echo \$html;
}
?>
EOF;
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_CURRENT_TASK_MASTER_ID\" name=\"FORMBOSS_WORKFLOW_CURRENT_TASK_MASTER_ID\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_CURRENT_ACTIVE_TASK_ID\" name=\"FORMBOSS_WORKFLOW_CURRENT_ACTIVE_TASK_ID\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_CURRENT_STAGE_NAME\" name=\"FORMBOSS_WORKFLOW_CURRENT_STAGE_NAME\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_JOB_ID\" name=\"FORMBOSS_WORKFLOW_JOB_ID\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_TIMELINE_LOAD\" name=\"FORMBOSS_WORKFLOW_TIMELINE_LOAD\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_TASK_MANAGEMENT_TASK_COMMENT\" name=\"FORMBOSS_WORKFLOW_TASK_MANAGEMENT_TASK_COMMENT\" value=\"\" />
";
$element .= "
<input type=\"hidden\" id=\"FORMBOSS_WORKFLOW_TASK_MANAGEMENT_STAGE_SELECT\" name=\"FORMBOSS_WORKFLOW_TASK_MANAGEMENT_STAGE_SELECT\" value=\"\" />
";
$print_elt_open = "
" . \'<?php if(!isset($_GET[\'fb-workflow-print-view\'])) { ?>\' . "
";
$print_elt_close = "
" . \'<?php } ?>\' . "
";
return $print_elt_open . $element . $print_elt_close;
}
public function create_reset_button($form, $field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$tabindex = $field->tabindex;
$width = $field->fieldwidth;
$element = "";
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = " style=\"{$attributestyle} \" ";
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$ct1 = substr_count((string)$width, \'pt\');
$ct2 = substr_count((string)$width, \'px\');
$ct3 = substr_count((string)$width, \'%\');
if (trim($width) == "") {
$width = "";
} else {
if ($ct1 == 0 && $ct2 == 0 && $ct3 == 0) {
$width = \'width:\' . $width . \'px;\';
} else {
$width = \'width:\' . $width . \';\';
}
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$element .= "<input type=\"button\" class=\"nolabel btn {$extraclassnames}\" onclick=\"clearForm({$form->id})\" value=\"{$label}\" style=\"{$width}\" name=\"reset\" id=\"reset\" {$tabhtml} {$attribute} {$inheritstyle} {$enabled} {$readonly} />";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_button_button($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$tabindex = $field->tabindex;
$custom_css = $field->custom_css;
$width = $field->fieldwidth;
$element = "";
$element .= $this->create_custom_css_block($id, $custom_css);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = " style=\"{$attributestyle} \" ";
}
$_custom_selector = "";
if (isset($custom_css->all) && $custom_css->all != "" && $custom_css->all != \'<style type="text/css"></style>\') {
$matches = array();
preg_match_all(\'/[#.][a-z-A-Z0-9_]+/\', (string)$custom_css->all, $matches);
if (isset($matches[0]) && isset($matches[0][0]) && $matches[0][0] != "") {
$_custom_selector = $matches[0][0];
$_custom_selector = str_replace(\'.\', \'\', $_custom_selector);
$_custom_selector = str_replace(\'#\', \'\', $_custom_selector);
}
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$ct1 = substr_count((string)$width, \'pt\');
$ct2 = substr_count((string)$width, \'px\');
$ct3 = substr_count((string)$width, \'%\');
if (trim($width) == "") {
$width = "";
} else {
if ($ct1 == 0 && $ct2 == 0 && $ct3 == 0) {
$width = \'width:\' . $width . \'px;\';
} else {
$width = \'width:\' . $width . \';\';
}
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$element .= "<input class=\"nolabel btn {$_custom_selector} {$extraclassnames}\" style=\"{$width}\" type=\"button\" name=\"{$name}\" id=\"{$id}\" {$tabhtml} value=\"{$label}\" {$attribute} {$inheritstyle} {$conditional_call_inline} {$enabled} {$readonly} />";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_button_print($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$tabindex = $field->tabindex;
$custom_css = $field->custom_css;
$width = $field->fieldwidth;
$element = "";
$element .= $this->create_custom_css_block($id, $custom_css);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$element = "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = " style=\"{$attributestyle} \" ";
}
$_custom_selector = "";
if (isset($custom_css->all) && $custom_css->all != "" && $custom_css->all != \'<style type="text/css"></style>\') {
$matches = array();
preg_match_all(\'/[#.][a-z-A-Z0-9_]+/\', (string)$custom_css->all, $matches);
if (isset($matches[0]) && isset($matches[0][0]) && $matches[0][0] != "") {
$_custom_selector = $matches[0][0];
$_custom_selector = str_replace(\'.\', \'\', $_custom_selector);
$_custom_selector = str_replace(\'#\', \'\', $_custom_selector);
}
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$ct1 = substr_count((string)$width, \'pt\');
$ct2 = substr_count((string)$width, \'px\');
$ct3 = substr_count((string)$width, \'%\');
if (trim($width) == "") {
$width = "";
} else {
if ($ct1 == 0 && $ct2 == 0 && $ct3 == 0) {
$width = \'width:\' . $width . \'px;\';
} else {
$width = \'width:\' . $width . \';\';
}
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$element .= "<input class=\"nolabel btn {$_custom_selector} {$extraclassnames}\" style=\"{$width}\" type=\"button\" name=\"{$name}\" id=\"{$id}\" {$tabhtml} value=\"{$label}\" {$attribute} {$inheritstyle} {$conditional_call_inline} onclick=\"window.print();\" {$enabled} {$readonly} />";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_button_save($field, $page, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$tabindex = $field->tabindex;
$custom_css = $field->custom_css;
$width = $field->fieldwidth;
$tablemode = $page->tablemode;
$element = "";
$element .= $this->create_custom_css_block($id, $custom_css);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$element = "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
if ($attributestyle == "") {
$inheritstyle = "";
} else {
$inheritstyle = " style=\"{$attributestyle} \" ";
}
$_custom_selector = "";
if (isset($custom_css->all) && $custom_css->all != "" && $custom_css->all != \'<style type="text/css"></style>\') {
$matches = array();
preg_match_all(\'/[#.][a-z-A-Z0-9_]+/\', (string)$custom_css->all, $matches);
if (isset($matches[0]) && isset($matches[0][0]) && $matches[0][0] != "") {
$_custom_selector = $matches[0][0];
$_custom_selector = str_replace(\'.\', \'\', $_custom_selector);
$_custom_selector = str_replace(\'#\', \'\', $_custom_selector);
}
}
$element .= <<<EOF
<script type="text/javascript">
function finish_save_{$name}() {
alert(\'Form Data Saved.\');
}
function save_{$name}() {
// Shade Screen
// Process Form Submission.
ajax(\'{$page->form->action}\', finish_save_Save, ajax.serialize(this.form), null);
}
</script>
EOF;
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$ct1 = substr_count((string)$width, \'pt\');
$ct2 = substr_count((string)$width, \'px\');
$ct3 = substr_count((string)$width, \'%\');
if (trim($width) == "") {
$width = "";
} else {
if ($ct1 == 0 && $ct2 == 0 && $ct3 == 0) {
$width = \'width:\' . $width . \'px;\';
} else {
$width = \'width:\' . $width . \';\';
}
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$element .= "<input class=\"nolabel btn {$_custom_selector} {$extraclassnames}\" style=\"{$width}\" type=\"button\" name=\"{$name}\" id=\"{$id}\" {$tabhtml} value=\"{$label}\" {$attribute} {$inheritstyle} {$conditional_call_inline} onclick=\"save_{$name}();\" {$enabled} {$readonly} />";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_hidden($label, $name, $id, $defaultvalue)
{
$matches = array();
$defaultvalue = (string)$defaultvalue;
$defaultvalue = $this->uv->replace_all($defaultvalue, 6);
preg_match_all(\'/(^|.|
|
)(#\{(.*?)\})/\', $defaultvalue, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$defaultvalue = str_replace(\'#{\' . $m . \'}\', "<?php if(isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\'])) { echo \"{\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']}\"; }?>", $defaultvalue);
}
}
$dyn_vars = implode(\',\', $array_vars);
$separator = \', \';
$element = <<<EOT
<?php
if(!isset(\$array_vars_processed)){
// check for and replace array based variables if not already done
\$vars = array({$dyn_vars});
foreach(\$vars as \$var){
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
if(is_array(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
\$field_items = \'\';
foreach(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] as \$key=>\$v){
if(\$key != 0){ \$field_items .= \'{$separator}\'; }
\$field_items .= \$v;
}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] = \$field_items;
}
}
}
\$array_vars_processed = true;
}
?>
EOT;
$element = <<<EOT
<?php
// Process Array Variables.
if(!isset(\$array_vars_processed)){ \$vars = array({$dyn_vars}); process_array_variables(\$vars, \'{$separator}\'); \$array_vars_processed = true; }
?>
EOT;
$element .= "<input type=\"hidden\" name=\"{$name}\" id=\"{$id}\" value=\"{$defaultvalue}\" />";
return $element;
}
public function create_select($items_array, $field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->{"name"};
$id = $field->{"id"};
$datasource = $field->{"datasource"};
$sourcetype = $field->{"sourcetype"};
$sourcesql = $field->{"sourcesql"};
$sourcesqlparams = $field->{"sourcesqlparams"};
$dbdefaultselectvalue = $field->dbdefaultselectvalue;
$basicdefaultselectvalue = $field->basicdefaultselectvalue;
$dbhost = (string)$field->dbhost;
$dbschema = (string)$field->dbschema;
$dbuser = (string)$field->dbuser;
$dbpwd = (string)$field->dbpwd;
$dbsocket = (string)$field->dbsocket;
$dbport = (string)$field->dbport;
$dbdsn = (string)$field->dbdsn;
$connector = (string)$field->dbconnector;
$req = $field->validation->req;
$fieldwidth = $field->fieldwidth;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$dbdebuglevel = $field->dbdebuglevel;
$conditional = $field->conditional;
$rangeoptions = $field->rangeoptions;
$style = $field->style;
$select_multiple = $field->select_multiple;
$select_size = $field->select_size;
$select_force_blank = $field->select_force_blank;
$select_force_empty = $field->select_force_empty;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
$array_brace = "";
if (!isset($select_multiple) || (int)$select_multiple == "0" || (string)$select_multiple == "") {
$select_multiple = "";
} else {
$select_multiple = "multiple";
$array_brace = "[]";
}
if (!isset($select_size) || $select_size == "") {
$select_size = "size=1";
} else {
$select_size = "size={$select_size}";
}
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$sourcesql = str_replace(\'"\', \'\"\', $sourcesql);
$strs = explode(\',\', $sourcesqlparams);
$array_vars = array();
$params = \'$params = array(\';
$params .= $this->uv->replace_all((string)$sourcesqlparams, 4);
$params .= \');\';
$call_code = "\$dbh->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
";
$call_code .= "\$result_{$name} = \$dbh->pdo_procedure_params(\$query_debug, \$sql_{$name}, \$db_host, \$db_type, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$params, 0, 0);";
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (is_numeric((string)$fieldwidth) == true) {
$fieldwidth = $fieldwidth . \'px\';
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'86%\';
}
$fieldheight = "";
if (isset($field->fieldheight) && (string)$field->fieldheight != "16" && (string)$field->fieldheight != "") {
if (is_numeric((string)$field->fieldheight) == true) {
$fieldheight = \'height:\' . $field->fieldheight . \'px;\';
} else {
die;
$fieldheight = \'height:\' . $field->fieldheight . \';\';
}
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; width:{$fieldwidth}; {$fieldheight} {$attributestyle} \" ";
}
$element = \'\';
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; padding-top:3px; margin-right:8px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
if (isset($field->bucket) && (string)$field->bucket != \'\') {
$element .= "
<div class=\"fb-tablemode-element\" style=\"float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
} else {
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$element .= $this->create_table_mode_mobile_label($field,$tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$element .= "<select <?php echo \$enabled; ?> class=\"form-control {$extraclassnames}\" {$select_multiple} name=\"{$name}{$array_brace}\" id=\"{$id}\" {$tabhtml} {$inheritstyle} {$attribute} {$conditional_call_inline} {$select_size} {$enabled} {$readonly} >";
$element .= \'<?php $_SESSION[\' . "\'" . $name . "\'" . \'] = isset($_SESSION[\' . "\'" . $name . "\'" . \']) ? $_SESSION[\' . "\'" . $name . "\'" . \'] : ""; ?>\' . "
";
$element .= \'<?php if(!isset($_SESSION[\' . "\'{$name}_is\'" . \'])) { $_SESSION[\' . "\'{$name}_is\'" . \'] = 1; } ?>\';
if (!isset($basicdefaultselectvalue)) {
$basicdefaultselectvalue = "";
}
$basicdefaultselectvalue_original = $basicdefaultselectvalue;
$basicdefaultselectvalue_has_token = \'false\';
$basicdefaultselectvalue = $this->uv->replace_all((string)$basicdefaultselectvalue, 4);
if ($basicdefaultselectvalue == $basicdefaultselectvalue_original) {
$basicdefaultselectvalue = str_replace("\'", "\'", $basicdefaultselectvalue);
$basicdefaultselectvalue = "\'" . $basicdefaultselectvalue . "\'";
} else {
$basicdefaultselectvalue = "(" . $basicdefaultselectvalue . ")";
$basicdefaultselectvalue_has_token = \'true\';
}
if (!isset($field->select_text_defaultvalue)) {
$select_text_defaultvalue = "";
} else {
$select_text_defaultvalue = $field->select_text_defaultvalue;
}
$select_text_defaultvalue_original = $select_text_defaultvalue;
$select_text_defaultvalue = $this->uv->replace_all((string)$select_text_defaultvalue, 4);
if ($select_text_defaultvalue == $select_text_defaultvalue_original) {
$select_text_defaultvalue = "\'" . $select_text_defaultvalue . "\'";
} else {
$select_text_defaultvalue = "(" . $select_text_defaultvalue . ")";
}
$option_index = 0;
foreach ($items_array as $key => $val) {
$val->value = htmlentities($val->value, ENT_QUOTES, \'UTF-8\');
if ($option_index == 0 && isset($select_force_blank) && (int)$select_force_blank == 1) {
$val->value = "";
$val->name = "";
}
if ($option_index == 0 && isset($select_force_empty) && (int)$select_force_empty == 1) {
$val->value = "";
$option_index++;
continue;
}
if (substr_count($val->value, "OPTGROUP=") != 0) {
$optgrouplabel = explode(\'=\', $val->value);
if (isset($optgrouplabel[1])) {
$optgrouplabel = $optgrouplabel[1];
} else {
$optgrouplabel = "";
}
$element .= "<optgroup label=\'{$optgrouplabel}\'>";
continue;
}
if (substr_count($val->value, "OPTGROUP") != 0) {
$element .= "</optgroup>";
continue;
}
$option_index++;
if ($val->selected == 1) {
$element .= <<<DOC
<option value="{$val->value}"
<?php
if(is_array(\$_SESSION[\'{$name}\'])){
if(in_array(html_entity_decode("{$val->value}"), \$_SESSION[\'{$name}\']) || \$_SESSION[\'{$name}_is\'] == 1){
echo \'selected="selected"\';
}
} else {
if(\$_SESSION[\'{$name}\'] == html_entity_decode(\'{$val->value}\', ENT_QUOTES) || \$_SESSION[\'{$name}_is\'] == 1) {
echo \'selected="selected"\';
}
}
?> >{$val->name}</option>
DOC;
} else {
if (isset($field->bucket) && $field->bucket != "") {
$element .= <<<DOC
<option value="{$val->value}"
<?php
if(is_array(\$_SESSION[\'{$name}\'])){
if(in_array(html_entity_decode("{$val->value}"), \$_SESSION[\'{$name}\'])){
echo \'selected="selected"\';
}
} else {
\$val = {$basicdefaultselectvalue};
\$dynamic_array = explode(\'|\', \$val);
if(is_array(\$dynamic_array) && count(\$dynamic_array) > 1){
if(\$_SESSION[\'{$name}\'] == html_entity_decode("{$val->value}", ENT_QUOTES) || in_array("{$val->value}", \$dynamic_array)) {
echo \'selected="selected"\';
}
} else {
if(\$_SESSION[\'{$name}\'] == html_entity_decode("{$val->value}", ENT_QUOTES) || "{$val->value}" == {$basicdefaultselectvalue}) {
echo \'selected="selected"\';
}
if(\$_SESSION[\'{$name}\'] == html_entity_decode("{$val->value}", ENT_QUOTES) || "{$val->value}" == {$select_text_defaultvalue}) {
echo \'selected="selected"\';
}
}
}
?> >{$val->name}</option>
DOC;
} else {
$escaped_val = str_replace("\'", "\'", $val->value);
$_val_name = str_replace("\'", "\'", $val->name);
$element .= <<<DOC
<?php echo create_select_item(\'{$_val_name}\', \'{$escaped_val}\', \'{$name}\', {$basicdefaultselectvalue}, {$select_text_defaultvalue}, {$fieldpopulatedefault}); ?>
DOC;
}
}
}
if ((string)$rangeoptions->expression != \'\' || (string)$rangeoptions->array != \'\') {
if (substr_count((string)$rangeoptions->defaultvalue, \'$\') == 1) {
$range_default = $rangeoptions->defaultvalue;
} else {
$range_default = "\'" . $rangeoptions->defaultvalue . "\'";
}
if ((string)$rangeoptions->expression != \'\') {
$element .= <<<EOH
<?php
foreach({$rangeoptions->expression} as \$i) { ?>
<option value="<?php echo \$i;?>" <?php if(\$_SESSION[\'{$name}\'] == html_entity_decode("{\$i}", ENT_QUOTES) || \$i == {$range_default}) { ?> selected="selected" <?php } ?>><?php echo \$i; ?></option>;
<?php } ?>
EOH;
}
if ((string)$rangeoptions->array != \'\') {
$element .= <<<EOH
<?php
foreach({$rangeoptions->array} as \$t) {
if(is_array(\$t)){
// typical database query -> array[array[], array[]]
if(!isset(\$t[1]) || \$t[1] == \'\') {
\$label = \$t[0];
\$value = \$t[0];
} else {
\$label = \$t[0];
\$value = \$t[1];
}
} else { // simple array -> array[n,n,n]
\$label = \$t;
\$value = \$t;
}
?>
<option value="<?php echo \$value;?>" <?php if(\$_SESSION[\'{$name}\'] == html_entity_decode("{\$value}", ENT_QUOTES) || \$value == {$range_default}) { ?> selected="selected" <?php } ?>><?php echo \$label; ?></option>;
<?php } ?>
EOH;
}
}
if ($datasource != \'0\' && $sourcesql != "") {
if ($connector != \'\') {
$connector = str_replace(\'\\', \'\\\', $connector);
}
if ($dbdebuglevel == \'\') {
$dbdebuglevel = \'0\';
}
if(intval($dbdebuglevel) == 1 || intval($dbdebuglevel) == 2){
$dbdebuglevel = 3;
}
$db_type = $this->um->translateSourceType((int)$sourcetype);
if (!isset($dbdefaultselectvalue)) {
$dbdefaultselectvalue = "";
}
$dbdefaultselectvalue_original = (string)$dbdefaultselectvalue;
$dbdefaultselectvalue = $this->uv->replace_all((string)$dbdefaultselectvalue, 4);
if ($dbdefaultselectvalue == $dbdefaultselectvalue_original) {
$dbdefaultselectvalue = str_replace("\'", "\'", $dbdefaultselectvalue);
$dbdefaultselectvalue = "\'" . $dbdefaultselectvalue . "\'";
} else {
$dbdefaultselectvalue = "(" . $dbdefaultselectvalue . ")";
}
$order_l = 0;
$order_v = 1;
if (isset($field->parameterorder) && $field->parameterorder != "") {
if ((int)$field->parameterorder == 1) {
$order_l = 1;
$order_v = 0;
}
}
$dbhost = $this->uv->replace_all($dbhost, 8);
$dbuser = $this->uv->replace_all($dbuser, 8);
$dbpwd = $this->uv->replace_all($dbpwd, 8);
$dbschema = $this->uv->replace_all($dbschema, 8);
$dbport = $this->uv->replace_all($dbport, 8);
$dbdsn = $this->uv->replace_all($dbdsn, 8);
$element .= <<<EOT
<!-- Populate Field Start {$name} -->
<?php
// Perform Sql Query For {$name}
\$query_debug = {$dbdebuglevel}; // Default 0, Change to 3 To See Debug Messages.
\$db_schema_check = \'{$dbschema}\';
\$db_dsn_test = \'{$dbdsn}\';
if(\$db_schema_check != \'\' || \$db_dsn_test != \'\'){
\$db_host = "{$dbhost}";
\$db_type = "{$db_type}";
\$db_user = "{$dbuser}";
\$db_pass = "{$dbpwd}";
\$db_catalog = "{$dbschema}";
\$mysql_socket = "{$dbsocket}";
\$mysql_port = "{$dbport}";
\$dbdsn = "{$dbdsn}";
} else {
unset(\$db_catalog);
}
\$db_ssl_key = \'{$field->dbsslkey}\';
\$db_ssl_certificate = \'{$field->dbsslcertificate}\';
\$db_ssl_ca_cert = \'{$field->dbsslcacert}\';
\$db_ssl_verify_cert = \'{$field->dbsslverifycert}\';
\$db_ssl_cipher = \'{$field->dbsslcipher}\';
@include "{\$_SESSION[\'MAX_PATH\']}Database.php";
// optional connector script
if(file_exists("{\$_SESSION[\'MAX_PATH\']}{$connector}")){
@include "{\$_SESSION[\'MAX_PATH\']}{$connector}";
}
// Start Select Item Query.
\$sql_{$name} = "{$sourcesql}";
\$dbh = new Database();
{$params}
{$call_code}
// Create our select item.
if(count(\$result_{$name}) != 0){
foreach (\$result_{$name} as \$t){ if(!isset(\$t[{$order_v}]) || \$t[{$order_v}] == \'\') { \$value = \$t[{$order_l}]; } else { \$value = \$t[{$order_v}]; } ?>
<option value="<?php echo htmlentities(\$value); ?>"<?php
if(isset(\$_SESSION[\'{$name}\']) && is_array(\$_SESSION[\'{$name}\'])){
if(in_array(html_entity_decode(""), \$_SESSION[\'{$name}\'])){
echo \'selected="selected"\';
}
} else {
\$val = {$dbdefaultselectvalue};
\$dynamic_array = explode(\'|\', \$val);
if(is_array(\$dynamic_array) && count(\$dynamic_array) > 1){
if(isset(\$_SESSION[\'{$name}\']) && \$_SESSION[\'{$name}\'] == html_entity_decode(\$value, ENT_QUOTES) || in_array(html_entity_decode(\$value, ENT_QUOTES), \$dynamic_array)) {
echo \'selected="selected"\';
}
} else {
if(isset(\$_SESSION[\'{$name}\']) && \$_SESSION[\'{$name}\'] == html_entity_decode(\$value, ENT_QUOTES) || html_entity_decode(\$value, ENT_QUOTES) == {$dbdefaultselectvalue}) {
echo \'selected="selected"\';
}
}
}?>><?php echo htmlentities(\$t[{$order_l}]); ?></option>
<?php } } // End Sql Query For {$name}. ?>
<!-- Populate Field End {$name} -->
EOT;
}
if(isset($field->webservice_url) && (string)$field->webservice_url != ""){
$curl_post_parameters = "";
$curl_get_parameters = "";
if(isset($field->webservice_query_parameters) && $field->webservice_query_parameters != "") {
$param_array = array();
foreach ($field->webservice_query_parameters as $key => $val) {
$key = (string)$val->key;
$value = $this->uv->replace_all((string)$val->value, 1);
$param_array["{$key}"] = $value;
}
$query_string = http_build_query($param_array);
$query_string = str_replace(\'%7B\', \'{\', $query_string);
$query_string = str_replace(\'%7D\', \'}\', $query_string);
$query_string = str_replace(\'%24\', \'$\', $query_string);
if((int)$field->webservice_method == 0){
$curl_post_parameters = "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \"{$query_string}\");";
} else if((int)$field->webservice_method == 1) {
$curl_get_parameters = "{$query_string}";
}
}
$curl_header = "";
if(isset($field->webservice_headers) && $field->webservice_headers != "") {
$curl_header = "
// Custom cURL Header(s)
";
$header_elements = \'\';
foreach ($field->webservice_headers as $key => $val) {
$k = (string)$val->key;
$v = (string)$val->value;
if($k != "" && $v != ""){
if($header_elements != ""){
$header_elements .= ",
";
}
$header_elements .= " \'{$k}:{$v}\'";
}
}
$curl_header .= "
\$headers = array(
";
$curl_header .= "${header_elements}";
$curl_header .= "
);
";
$curl_header .= "
curl_setopt(\$ch, CURLOPT_HTTPHEADER, \$headers);
";
$curl_header .= "
// End Custom cURL Header(s)
";
}
$method = (int)$field->webservice_method == 0 ? \'curl_setopt($ch, CURLOPT_POST, true);\' : \'\';
$http_request_code = <<<EOF
//
// Pull Data From Web Service.
//
try {
\$confirm_http_curl_show_debug = false;
// Get the curl session object.
\$ch = curl_init("{$field->webservice_url}?{$curl_get_parameters}");
\$httpAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9";
// Set the GET options. Full list at: http://us2.php.net/manual/en/function.curl-setopt.php
curl_setopt(\$ch, CURLOPT_USERAGENT, \$httpAgent);
curl_setopt(\$ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(\$ch, CURLOPT_FRESH_CONNECT, TRUE);
curl_setopt(\$ch, CURLOPT_SSL_VERIFYPEER, 0); // set to false (0) for most uses, as we won\'t have valid cert files
curl_setopt(\$ch, CURLOPT_SSL_VERIFYHOST, 2);
{$method}
curl_setopt(\$ch, CURLOPT_CAPATH, "./security/cURL/cacert.pem");
{$curl_header}
{$curl_post_parameters}
// Query And Return Response.
\$response = curl_exec(\$ch);
if (\$response == false){
if(\$confirm_http_curl_show_debug){
echo curl_error(\$ch);
echo curl_errno(\$ch);
echo "</select><pre>"; print_r(curl_getinfo(\$ch)); echo "</pre>";
throw new Exception(curl_error(\$ch), curl_errno(\$ch));
}
curl_close(\$ch);
} else {
// Process Result.
curl_close(\$ch);
if(\$response != ""){
// If XML, First Convert To JSON.
if(simplexml_load_string(\$response)){
\$xml = simplexml_load_string(\$response);
\$response = json_encode(\$xml);
}
if(json_decode(\$response)){
// Process JSON
\$response = str_replace(\'\r\n\', \'\', \$response);
\$response = str_replace(\'\"\', \'"\', \$response);
\$response = str_replace(\'"[\', \'[\', \$response);
\$response = str_replace(\']"\', \']\', \$response);
\$debug_raw = false;
if(\$debug_raw){
echo \'</select><pre>Web Service Debug For The `<strong>{$field->name}</strong>` Field.</pre>\';
echo "<pre>Raw Response:\r\n"; var_dump( \$response ); echo \'</pre>\';
\$json = json_decode(\$response, true);
echo "<pre>Decoded JSON:\r\n"; var_dump( \$json ); echo \'</pre>\';
}
\$jsonIterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator(json_decode(\$response, TRUE)),
RecursiveIteratorIterator::SELF_FIRST);
foreach (\$jsonIterator as \$key => \$val) {
// Selected Status.
\$selected = "";
if(is_array(\$val)) {
//echo "\$key:";
} else {
if(\$_SESSION[\'{$name}\'] == html_entity_decode(\$val, ENT_QUOTES) ) {
\$selected = \'selected=\"selected\"\';
}
if(gettype(\$val) == "boolean"){
\$val = var_export(\$val, true);
}
echo "<option value=\"{\$val}\">{\$key}</option>";
}
}
}
}
if(\$confirm_http_curl_show_debug){
echo "</select><br/><br/>
<pre>cURL Debug For: {$field->webservice_url}
"; print_r(curl_getinfo(\$ch)); echo "</pre>";
}
}
} catch(Exception \$e) {
// Uncomment next line to show cURL errors.
//trigger_error(sprintf(\'</select>Curl failed with error #%d: %s\', \$e->getCode(), \$e->getMessage()), E_USER_ERROR);
}
EOF;
$element .= "
<?php
" . $http_request_code . "
?>
";
}
$element .= "
</select>
";
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($helper != \'\') {
$element .= "
<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>
";
} else {
$element .= "
<br />
";
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_multiselect($items_array, $field, $tablemode, $bucket_node, $jslibrary)
{
if($bucket_node == null){
$bucket_node = "";
}
$label = $field->label;
$labelpos = $field->labelpos;
$inline_label_pos = $this->get_inline_label_pos($field->labelpos);
$name = $field->name;
$id = $field->id;
$req = $field->validation->req;
$color = $field->color;
$fontsize = $field->fontsize;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$optionfontsize = $field->optionfontsize;
$optionfontweight = $field->style->optionfontweight;
$input_color = $field->input_color;
$inheritstyle = $field->inheritstyle;
$attributestyle = $field->attributestyle;
$datasource = $field->datasource;
$sourcetype = $field->sourcetype;
$sourcesql = $this->uv->replace_all($field->sourcesql, 1);
$sourcesql = str_replace(\'"\', \'\"\', $sourcesql);
$tooltip = $field->tooltip;
if (!isset($field->dbdefaultselectvalue)) {
$dbdefaultselectvalue = "";
} else {
$dbdefaultselectvalue = $field->dbdefaultselectvalue;
}
if (!isset($field->basicdefaultselectvalue)) {
$basicdefaultselectvalue = "";
} else {
$basicdefaultselectvalue = $field->basicdefaultselectvalue;
}
if (!isset($field->select_text_defaultvalue)) {
$select_text_defaultvalue = "";
} else {
$select_text_defaultvalue = $field->select_text_defaultvalue;
}
$dbhost = $this->uv->replace_all($field->dbhost, 8);
$dbsocket = $this->uv->replace_all($field->dbsocket, 8);
$dbport = $this->uv->replace_all($field->dbport, 8);
$dbuser = $this->uv->replace_all($field->dbuser, 8);
$dbpwd = $this->uv->replace_all($field->dbpwd, 8);
$dbschema = $this->uv->replace_all($field->dbschema, 8);
if (!isset($field->dbdsn)) {
$field->dbdsn = "";
}
$dbdsn = $this->uv->replace_all($field->dbdsn, 8);
$connector = $field->connector;
$dbdebuglevel = $field->dbdebuglevel;
$select_use_boolean = $field->select_use_boolean;
$rowcount = $field->rowcount;
$columnwidth = $field->columnwidth;
if (ctype_digit((string)$columnwidth)) {
$columnwidth = "{$columnwidth}px; ";
} else {
$columnwidth = "{$columnwidth}; ";
}
$rangeoptions = $field->rangeoptions;
$conditional = $field->conditional;
$styles = $this->translateFieldStyles($field->style);
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$label_margin = "";
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$color}; font-family:inherit; {$attributestyle} \" ";
} else {
if (isset($optionfontsize) && $optionfontsize != "") {
$ct1 = substr_count((string)$optionfontsize, \'pt\');
$ct2 = substr_count((string)$optionfontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$optionfontsize = $optionfontsize . \'px\';
}
$fontweight = "";
if (isset($optionfontweight) && $optionfontweight == "1") {
$fontweight = " font-weight: bold; ";
}
$_color = "";
if (isset($input_color) && $input_color != "") {
$_color = " color: {$input_color}; ";
}
$inheritstyle = " style=\"font-size:{$optionfontsize}; {$fontweight} {$_color} \" ";
} else {
$inheritstyle = " style=\" color:{$color}; {$attributestyle} \" ";
}
}
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$element = "
<!-- Form Element Start -->";
$element .= "
";
$element .= \'<fieldset data-role="controlgroup" style="border:0; padding:0px; margin:0px;">\';
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$tablemodespan = false;
if (!isset($field->style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$field->style->tablemodespan == 1) {
$tablemodespan = true;
}
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && !$tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
$element .= "
" . \'<?php $_SESSION[\' . "\'" . $name . "\'" . \'] = isset($_SESSION[\' . "\'" . $name . "\'" . \']) ? $_SESSION[\' . "\'" . $name . "\'" . \'] : array(""); ?>\' . "
";
$element .= "
" . \'<?php if(!isset($_SESSION[\' . "\'{$name}_is\'" . \'])) { $_SESSION[\' . "\'{$name}_is\'" . \'] = 1; } ?>\';
$element .= "
" . \'<?php if(!isset($_SESSION[\' . "\'{$name}_processed\'" . \'])) { $_SESSION[\' . "\'{$name}_processed\'" . \'] = false; } ?>\' . "
";
$class_definition = "";
$required_class = "";
if ((int)$field->validation->req == 1) {
$required_class = "required";
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$class_definition = "class=\"{$required_class} {$extraclassnames}\"";
$semantic_class_name = "ui checkbox";
if ($field->type == "radio") {
$semantic_class_name = "ui radio checkbox";
}
$semantic_group_class_name = "grouped fields";
if ($inline_label_pos == "") {
$semantic_group_class_name = "fields";
}
if (isset($jslibrary) && $jslibrary == "14") {
$inline_label_pos = "";
}
$tooltip_element = $this->translateTooltip($tooltip, $field->id);
$element .= "
<div class=\"fbtooltip-{$field->id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ((int)$tablemode->enabletablelayout == 1 && !$tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div><!-- Close Table Mode DIV -->";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
if ($tablemodespan || isset($field->bucket) && (string)$field->bucket != \'\') {
$element .= "
<div class=\"fb-tablemode-element\" style=\"float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
} else {
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
}
$element .= $this->create_table_mode_mobile_label($field, $tablemode);
$ct = (int)$rowcount;
if ($ct == 0) {
$ct = 10;
}
$element .= "
<?php \$rowcount_{$name} = {$ct}; \$count_row_{$name} = 0; ?>";
$dbdefaultselectvalue_original = (string)$dbdefaultselectvalue;
$dbdefaultselectvalue = $this->uv->replace_all((string)$dbdefaultselectvalue, 4);
if ($dbdefaultselectvalue == $dbdefaultselectvalue_original) {
$dbdefaultselectvalue = str_replace("\'", "\'", $dbdefaultselectvalue);
$dbdefaultselectvalue = "\'" . $dbdefaultselectvalue . "\'";
} else {
$dbdefaultselectvalue = "(" . $dbdefaultselectvalue . ")";
}
$basicdefaultselectvalue_original = (string)$basicdefaultselectvalue;
$basicdefaultselectvalue_has_token = \'false\';
$basicdefaultselectvalue = $this->uv->replace_all((string)$basicdefaultselectvalue, 4);
if ($basicdefaultselectvalue == $basicdefaultselectvalue_original) {
$basicdefaultselectvalue = str_replace("\'", "\'", $basicdefaultselectvalue);
$basicdefaultselectvalue = "\'" . $basicdefaultselectvalue . "\'";
} else {
$basicdefaultselectvalue = "(" . $basicdefaultselectvalue . ")";
$basicdefaultselectvalue_has_token = \'true\';
}
$select_text_defaultvalue_original = $select_text_defaultvalue;
$select_text_defaultvalue = $this->uv->replace_all((string)$select_text_defaultvalue, 4);
if ($select_text_defaultvalue == $select_text_defaultvalue_original) {
$select_text_defaultvalue = str_replace("\'", "\'", $select_text_defaultvalue);
$select_text_defaultvalue = "\'" . $select_text_defaultvalue . "\'";
} else {
$select_text_defaultvalue = "(" . $select_text_defaultvalue . ")";
}
switch ((string)$field->type) {
case "checkbox":
$brace = "[]";
$selected_code_database = <<<EOU
<?php
// Explode the token if possible for multiple default values.
\$dynamic_array = array();
\$dynamic_items = {$dbdefaultselectvalue};
// Convert To Array If Needed.
if(!is_array(\$dynamic_items)){
\$dynamic_array = explode(\'|\', \$dynamic_items);
} else {
\$dynamic_array = \$dynamic_items;
}
// set any dynamic default values
if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode(\$value, ENT_QUOTES), \$_SESSION[\'{$name}\'])
|| (!is_array(\$dynamic_items) && in_array(html_entity_decode({$dbdefaultselectvalue}, ENT_QUOTES), \$t) ) ||
(is_array(\$dynamic_array) && in_array(\$value, \$dynamic_array))) {
echo \'checked="checked"\';
}
?>
EOU;
break;
case "radio":
$brace = "";
$selected_code_database = <<<EOU
<?php
// Set any dynamic default values for this radio item.
if(\$_SESSION[\'{$name}\'] == html_entity_decode(\$value, ENT_QUOTES) || \$value == {$dbdefaultselectvalue}) {
echo "checked=\"checked\""; }
?>
EOU;
break;
}
$multiselect_item_start = "";
$multiselect_item_end = "";
if ((int)$field->multiselect_layoutmode == 0) {
$padding = "";
$margin = "";
$alignment = "";
$background_color = "";
if ((int)$field->multiselect_item_padding != \'\')
$padding = " padding: {$field->multiselect_item_padding}px; ";
if ((int)$field->multiselect_item_margin != \'\')
$margin = " margin: {$field->multiselect_item_margin}px; ";
if ((string)$field->multiselect_item_alignment != \'\')
$alignment = "align:{$field->multiselect_item_alignment}; ";
if ((string)$field->multiselect_item_background_color != \'\')
$background_color = " background-color: {$field->multiselect_item_background_color}; ";
if ((int)$labelpos == 0) {
$clear = "clear:both;";
} else {
if ((int)$field->rowcount == \'\') {
$clear = "float:left;";
} else {
$clear = "clear:both;";
}
}
$use_alternating = \'false\';
if (isset($field->multiselect_item_background_color_alternate) && (int)$field->multiselect_item_background_color_alternate == \'1\') {
$use_alternating = \'true\';
}
$multiselect_item_start = "
<?php if(\$count_{$name} % 2 == 0 && {$use_alternating}) { \$alternate_row = true; } else { \$alternate_row = false; } ?>
";
if (isset($jslibrary) && $jslibrary == "14") {
$margin = "";
}
$multiselect_item_start .= "<div class=\"multiselect-item field\" style=\" {$padding} {$margin} {$alignment} <?php if({$use_alternating} && \$alternate_row) { ?>{$background_color} <?php } else if(!{$use_alternating}) { echo \'{$background_color}\'; } ?> {$clear} \">";
$multiselect_item_end = "</div><!-- Close Non-Multi-Select DIV -->";
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$multiselect_item_start = "";
$multiselect_item_end = "";
}
}
if ((int)$field->multiselect_layoutmode == 1) {
$width = \'\';
$padding = "";
$margin = "";
$alignment = "";
$background_color = "";
if ((string)$field->multiselect_item_width != \'\') {
if (ctype_digit((string)$field->multiselect_item_width)) {
$width = " width: {$field->multiselect_item_width}px; ";
} else {
$width = " width: {$field->multiselect_item_width}; ";
}
}
if ((int)$field->multiselect_item_padding != \'\')
$padding = " padding: {$field->multiselect_item_padding}px; ";
if ((int)$field->multiselect_item_margin != \'\')
$margin = " margin: {$field->multiselect_item_margin}px; ";
if ((string)$field->multiselect_item_alignment != \'\')
$alignment = " align=\"{$field->multiselect_item_alignment}\"";
if ((string)$field->multiselect_item_background_color != \'\')
$background_color = " background-color: {$field->multiselect_item_background_color}; ";
$use_alternating = \'false\';
if (isset($field->multiselect_item_background_color_alternate) && (int)$field->multiselect_item_background_color_alternate == \'1\') {
$use_alternating = \'true\';
}
$multiselect_item_start = "
<?php if(\$count_{$name} % 2 == 0 && {$use_alternating}) { \$alternate_row = true; } else { \$alternate_row = false; } ?>
";
$multiselect_item_start .= "<div {$alignment} class=\"multiselect-survey-item\" style=\"{$width} {$padding} {$margin} <?php if({$use_alternating} && \$alternate_row) { ?>{$background_color} <?php } else if(!{$use_alternating}) { echo \'{$background_color}\'; } ?> float:left; \">";
$multiselect_item_end = "</div><!-- Close Multi-Select DIV -->";
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$multiselect_item_start = "";
$multiselect_item_end = "";
}
}
$fb_multiselect_column_float = \'float:left;\';
if (defined(\'MOBILE_MODE\')) {
$fb_multiselect_column_float = \'\';
}
$label_class_code = "";
if (isset($field->multiselect_item_custom_label_code) && $field->multiselect_item_custom_label_code != "") {
$label_class_code = $field->multiselect_item_custom_label_code;
}
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
foreach ($items_array as $val) {
if ((int)$datasource != \'1\' && $val->name == "Add a radio option") {
continue;
}
$val->value = htmlentities($val->value, ENT_QUOTES, \'UTF-8\');
$field_value_for_value_html_property = $this->uv->replace_all($val->value, 3);
if ((int)$select_use_boolean == 1) {
$field_value_for_value_html_property = 1;
}
$value_original = strtolower($val->value);
$value_after_dynamic_variables = $this->uv->replace_all($val->value, 3);
if($value_original != strtolower($value_after_dynamic_variables)){
$val->value = $this->uv->replace_all($val->value, 1);
$val->value = "\'.\"" . $val->value . "}\".\'";
}
if ((string)$val->name != "Add a {$field->type} option") {
$field_value = $val->value;
$field_value_escaped = str_replace("\'", "\'", $field_value);
if ((int)$select_use_boolean == 1) {
$field_value = 1;
}
switch ((string)$field->type) {
case "checkbox":
$brace = "[]";
if(isset($fieldpopulatedefault) && $fieldpopulatedefault == 1){
$selected_code = <<<EOT
<?php
\$basicdefaultselectvalue_has_token = {$basicdefaultselectvalue_has_token};
\$dynamic_array = array();
// Explode default token/value if possible for multiple default values.
if(\'{$basicdefaultselectvalue_has_token}\' == \'false\'){
\$dynamic_array = explode(\'|\', {$basicdefaultselectvalue});
}
\$dynamic_array_list = explode(\'|\', {$select_text_defaultvalue});
// set default value(s)
if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode("{$field_value}", ENT_QUOTES), \$_SESSION[\'{$name}\'])) { // This field\'s existing selection set.
echo \'checked="checked"\';
}
if(!\$basicdefaultselectvalue_has_token && \'{$field_value}\' == htmlentities($basicdefaultselectvalue, ENT_QUOTES)
&& \$_SESSION[\'{$name}_processed\'] == false) {
echo \'checked="checked"\';
}
if(\$basicdefaultselectvalue_has_token && \$_SESSION[\'{$name}_processed\'] == false){ // Token with default select value.
if(is_array(\$_SESSION[\'{$name}\']) && is_array(explode(\'|\', {$basicdefaultselectvalue}))){
if(in_array(html_entity_decode("{$field_value}", ENT_QUOTES), explode(\'|\', {$basicdefaultselectvalue})) && \$_SESSION[\'{$name}_processed\'] == false){
echo \'checked="checked"\';
}
}
}
if(\'{$field_value}\' == {$select_text_defaultvalue} && \$_SESSION[\'{$name}_processed\'] == false) {
echo \'checked="checked"\';
}
if( (is_array(\$dynamic_array) && in_array("{$field_value}", \$dynamic_array) || is_array(\$dynamic_array_list) && in_array("{$field_value}", \$dynamic_array_list) ) &&
\$_SESSION[\'{$name}_processed\'] == false) {
echo \'checked="checked"\';
}
?>
EOT;
} else {
$selected_code = <<<EOT
<?php
// explode default token/value if possible for multiple default values.
\$dynamic_array = explode(\'|\', {$basicdefaultselectvalue});
\$dynamic_array_list = explode(\'|\', {$select_text_defaultvalue});
// set default values
if((\'{$field_value}\' == htmlentities($basicdefaultselectvalue, ENT_QUOTES) || \'{$field_value}\' == {$select_text_defaultvalue} ||
(is_array(\$dynamic_array) && in_array("{$field_value}", \$dynamic_array) || is_array(\$dynamic_array_list) && in_array("{$field_value}", \$dynamic_array_list) ) &&
\$_SESSION[\'{$name}_processed\'] == false)) {
echo \'checked="checked"\';
}
?>
EOT;
}
$selected_code_selected = <<<EOY
<?php if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode("{$field_value}", ENT_QUOTES), \$_SESSION[\'{$name}\']) || \$_SESSION[\'{$name}_is\'] == 1) {
echo \'checked="checked"\';
}
?>
EOY;
$selected_code_database = <<<EOU
<?php
// explode the token if possible for multiple default values.
\$dynamic_array = explode(\'|\', {$dbdefaultselectvalue});
// Select Code For Database Checkbox Items.
if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode(\$value, ENT_QUOTES), \$_SESSION[\'{$name}\']) ||
(is_array(\$dynamic_array) && in_array(\$value, \$dynamic_array))) {
echo \'checked="checked"\';
}
?>
EOU;
break;
case "radio":
$brace = "";
$selected_code = <<<EOT
<?php if(\$_SESSION[\'{$name}\'] == html_entity_decode(\'{$val->value}\', ENT_QUOTES) ||
( (\'{$field_value}\' == htmlentities({$basicdefaultselectvalue}, ENT_QUOTES) || \'{$field_value}\' == {$select_text_defaultvalue}) && \$_SESSION[\'{$name}_processed\'] == false)) {
echo "checked=\"checked\""; }
?>
EOT;
$selected_code_selected = <<<EOT
<?php if(\$_SESSION[\'{$name}\'] == html_entity_decode(\'{$val->value}\', ENT_QUOTES) || \$_SESSION[\'{$name}_is\'] == 1) {
// Radio Selected Code.
echo "checked=\"checked\""; }
?>
EOT;
break;
}
if (isset($val->rowbreak) && $val->rowbreak == 1) {
$element .= "
<?php \$count_{$name} = 1; ?>
";
$element .= "</span><!-- Close RowBreak SPAN -->
<div class=\"fb-multiselect-column {$field->type}-column\" style=\"width:{$columnwidth}; clear:both;\"></div>";
}
$field_label = html_entity_decode($val->name);
$field_label = $this->uv->replace_all($field_label, 3);
$val->name = htmlentities($val->name);
$label_margin = "";
if (isset($field->label_margin) && $field->label_margin != "") {
$_val = intval($field->label_margin);
$label_margin = " style=\"margin-left: {$_val}px;\" ";
}
$labelpos_class = (int)$field->labelpos == 0 ? \'labelpos-top\' : \'labelpos-inline\';
$multi_select_span_wrapper = "<span class=\"rf-multiselect-item-label\" {$label_margin}>{$field_label}</span>";
$multi_select_span_css = "";
if(substr_count($field_label, "<img") != 0){
$multi_select_span_wrapper = "{$field_label}";
$multi_select_span_css = <<<EOF
<style type="text/css">
/* HIDE RADIO */
#{$name}{$val->id} {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
/* IMAGE STYLES */
#{$name}{$val->id} + img {
cursor: pointer;
}
/* CHECKED STYLES */
#{$name}{$val->id}:checked + img {
outline: 1px dotted #b5b5b5;
}
</style>
EOF;
}
if ($val->selected == 1) {
$element .= <<<EOF
<?php
!isset(\$count_{$name}) ? \$count_{$name} = 1 : \$count_{$name}++;
\$count_row_{$name}++;
\$count_{$name} == 1 || \$count_row_{$name} == 1 ? print \'<div class="fb-multiselect-column {$labelpos_class} {$semantic_group_class_name} {$field->type}-column" style="width:{$columnwidth}; {$fb_multiselect_column_float}">\' : print \'\';
?>
{$multiselect_item_start}
<div class="{$semantic_class_name}">
<label aria-label for="{$name}{$val->id}" class="{$field->type}-inline {$semantic_class_name} <?php \$value = \'{$field_value_escaped}\'; ?> {$label_class_code}" {$inheritstyle} >
{$multi_select_span_css}
<input type="{$field->type}" name="{$name}{$brace}" id="{$id}{$val->id}" {$tabhtml} value="{$field_value_for_value_html_property}" {$inheritstyle} {$class_definition} {$enabled} {$readonly}
{$selected_code_selected}
{$attribute} {$conditional_call_inline} />
{$multi_select_span_wrapper}
</label> {$inline_label_pos}
</div><!-- Close Selected DIV -->
{$multiselect_item_end}
<?php if(\$count_row_{$name} == \$rowcount_{$name}) { echo \'</div>\'; \$count_row_{$name} = 0; } ?>
EOF;
} else {
$element .= <<<EOF
<?php
!isset(\$count_{$name}) ? \$count_{$name} = 1 : \$count_{$name}++;
\$count_row_{$name}++;
\$count_{$name} == 1 || \$count_row_{$name} == 1 ? print \'<div class="fb-multiselect-column {$labelpos_class} {$semantic_group_class_name} {$field->type}-column" style="width:{$columnwidth}; {$fb_multiselect_column_float}">\' : print \'\';
?>
{$multiselect_item_start}
<div class="{$semantic_class_name}">
<label for="{$name}{$val->id}" class="{$field->type}-inline {$semantic_class_name} <?php \$value = \'{$field_value_escaped}\'; ?> {$label_class_code}" {$inheritstyle} >
{$multi_select_span_css}
<input type="{$field->type}" name="{$name}{$brace}" id="{$id}{$val->id}" {$tabhtml} value="{$field_value_for_value_html_property}" {$inheritstyle} {$class_definition} {$enabled} {$readonly}
{$selected_code}
{$attribute} {$conditional_call_inline} />
{$multi_select_span_wrapper}
</label> {$inline_label_pos}
</div><!-- Close Non-Selected DIV -->
{$multiselect_item_end}
<?php if(\$count_row_{$name} == \$rowcount_{$name}) { echo \'</div><!-- Close Row DIV -->\'; \$count_row_{$name} = 0; } ?>
EOF;
}
}
}
if ($datasource != \'0\' && $sourcesql != "") {
if (isset($field->label_margin) && $field->label_margin != "") {
$_val = intval($field->label_margin);
$label_margin = " style=\"margin-left: {$_val}px;\" ";
}
if ($connector != \'\') {
$connector = str_replace(\'\\', \'\\\', $connector);
}
if ($dbdebuglevel == \'\') {
$dbdebuglevel = \'0\';
}
$db_type = $this->um->translateSourceType((int)$sourcetype);
$order_l = 0;
$order_v = 1;
if (isset($field->parameterorder) && $field->parameterorder != "") {
if ((int)$field->parameterorder == 1) {
$order_l = 1;
$order_v = 0;
}
}
$dbhost = $this->uv->replace_all($dbhost, 8);
$dbuser = $this->uv->replace_all($dbuser, 8);
$dbpwd = $this->uv->replace_all($dbpwd, 8);
$dbschema = $this->uv->replace_all($dbschema, 8);
$dbport = $this->uv->replace_all($dbport, 8);
$dbdsn = $this->uv->replace_all($dbdsn, 8);
$element .= <<<EOT
<!-- Populate Field Start {$name} -->
<?php
// perform sql query for {$name}
// Change to 1 to see debug info if you run into problems executing your query (may need to look at html page source to see error).
\$query_debug = {$dbdebuglevel};
\$db_schema_check = \'{$dbschema}\';
\$db_dsn_test = \'{$dbdsn}\'; // Build 710
if(\$db_schema_check != \'\' || \$db_dsn_test != \'\'){
\$db_host = "{$dbhost}";
\$db_type = "{$db_type}";
\$db_user = "{$dbuser}";
\$db_pass = "{$dbpwd}";
\$db_catalog = "{$dbschema}";
\$mysql_socket = "{$dbsocket}";
\$mysql_port = "{$dbport}";
\$dbdsn = "{$dbdsn}";
}
@include_once "{\$_SESSION[\'MAX_PATH\']}Database.php";
// optional connector script
if(file_exists("{\$_SESSION[\'MAX_PATH\']}{$connector}")){
@include "{\$_SESSION[\'MAX_PATH\']}{$connector}";
}
// Multi-Select Item Query.
\$sql_{$name} = "{$sourcesql}";
\$dbh = new Database();
\$result_{$name} = "";
if(\$sql_{$name} != ""){
\$result_{$name} = \$dbh->inline_pdo_query(\$query_debug, \$sql_{$name}, \$db_host, \$db_type, \$mysql_socket, \$mysql_port, \$dbdsn, \$db_user, \$db_pass, \$db_catalog, \$return_true = 0);
}
// do we have a result to pass?
if(\$result_{$name}[0]){
// loop through results
foreach (\$result_{$name}[1] as \$t){
if(!isset(\$t[{$order_v}]) || \$t[{$order_v}] == \'\') {
\$value = \$t[{$order_l}];
} else {
\$value = \$t[{$order_v}];
}
// set count row logic
!isset(\$count_{$name}) ? \$count_{$name} = 1 : \$count_{$name}++;
\$count_row_{$name}++;
\$count_{$name} == 1 || \$count_row_{$name} == 1 ? print \'<div class="fb-multiselect-column {$semantic_group_class_name} {$field->type}-column" style="width:{$columnwidth}; {$fb_multiselect_column_float}">\' : print \'\';
?>
{$multiselect_item_start}
<div class="{$semantic_class_name}">
<label for="{$name}<?php echo \$count_{$name};?>" class="{$field->type}-inline {$semantic_class_name} {$label_class_code}" {$inheritstyle} >
<input type="{$field->type}" name="{$name}{$brace}" id="{$id}<?php echo \$count_{$name};?>" {$tabhtml} value="<?php echo \$value; ?>" {$inheritstyle} {$class_definition} {$enabled} {$readonly}
{$selected_code_database}
{$attribute} {$conditional_call_inline} />
<span class="rf-multiselect-item-label" {$label_margin}><?php echo htmlentities(\$t[{$order_l}]); ?></span>
</label> {$inline_label_pos}
</div>
{$multiselect_item_end}
<?php
if(\$count_row_{$name} == \$rowcount_{$name}) {
echo \'</div>\';
\$count_row_{$name} = 0;
}
} // foreach loop
} // if result
?>
<!-- Populate Field End {$name} -->
EOT;
}
if ((string)$rangeoptions->expression != \'\' || (string)$rangeoptions->array != \'\') {
if (substr_count((string)$rangeoptions->defaultvalue, \'$\') == 1) {
$range_default = $rangeoptions->defaultvalue;
} else {
$range_default = "\'" . $rangeoptions->defaultvalue . "\'";
}
$selected_code_range = "";
$selected_code_array = "";
switch ((string)$field->type) {
case "checkbox":
$brace = "[]";
$selected_code_range = <<<EOH
<?php
if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode(\$i, ENT_QUOTES), \$_SESSION[\'{$name}\']) || \$i == {$range_default} && \$_SESSION[\'{$name}_is\'] == 1) {
echo \'checked="checked"\';
}
?>
EOH;
$selected_code_array = <<<EOH
<?php
if(is_array(\$_SESSION[\'{$name}\']) && in_array(html_entity_decode(\$value, ENT_QUOTES), \$_SESSION[\'{$name}\']) || \$value == {$range_default} && \$_SESSION[\'{$name}_is\'] == 1) {
echo \'checked="checked"\';
}
?>
EOH;
break;
case "radio":
$brace = "";
$selected_code_range = <<<EOH
<?php
if(\$_SESSION[\'{$name}\'] == html_entity_decode(\$i, ENT_QUOTES) || \$i == {$range_default} && \$_SESSION[\'{$name}_is\'] == 1) {
echo \'checked="checked"\';
}
?>
EOH;
$selected_code_array = <<<EOH
<?php
if(\$_SESSION[\'{$name}\'] == html_entity_decode(\$value, ENT_QUOTES) || \$value == {$range_default} && \$_SESSION[\'{$name}_is\'] == 1) {
echo \'checked="checked"\';
}
?>
EOH;
break;
}
if ((string)$rangeoptions->expression != \'\') {
$rangeoptions->expression = str_replace(\'PHP{\', \'${\', $rangeoptions->expression);
$element .= <<<EOH
<div> <!-- open multi-select div -->
<?php
// Loop Through Range Expression Results.
foreach ({$rangeoptions->expression} as \$i){
// set count row logic
!isset(\$count_{$name}) ? \$count_{$name} = 1 : \$count_{$name}++;
\$count_row_{$name}++;
\$count_{$name} == 1 || \$count_row_{$name} == 1 ? print \'<span class="fb-multiselect-column {$semantic_group_class_name} {$field->type}-column" style="width:{$columnwidth}; {$fb_multiselect_column_float}">\' : print \'\';
?>
{$multiselect_item_start}
<div class="{$semantic_class_name}">
<label for="{$name}<?php echo \$count_{$name};?>" class="{$field->type}-inline {$semantic_class_name} <?php \$value = \$i; ?> {$label_class_code}" {$inheritstyle} >
<input type="{$field->type}" name="{$name}{$brace}" id="{$id}<?php echo \$count_{$name};?>" {$tabhtml} value="<?php echo \$i;?>" {$inheritstyle} {$class_definition} {$enabled} {$readonly}
{$selected_code_range}
{$attribute} {$conditional_call_inline} />
<span class="rf-multiselect-item-label range-expression" {$label_margin}><?php echo \$i; ?></span>
</label> {$inline_label_pos}
</div>
{$multiselect_item_end}
<?php
if(\$count_row_{$name} == \$rowcount_{$name}) {
echo \'</div>\';
\$count_row_{$name} = 0;
}
} // foreach loop
?>
EOH;
}
if ((string)$rangeoptions->array != \'\') {
$rangeoptions->array = str_replace(\'PHP{\', \'${\', $rangeoptions->array);
$element .= <<<EOH
<div> <!-- open multi-select div -->
<?php
// Loop Through Range Array Results.
foreach({$rangeoptions->array} as \$t) {
if(is_array(\$t)){
// typical database query -> array[array[], array[]]
if(!isset(\$t[1]) || \$t[1] == \'\') {
\$label = \$t[0];
\$value = \$t[0];
} else {
\$label = \$t[0];
\$value = \$t[1];
}
} else { // simple array -> array[n,n,n]
\$label = \$t;
\$value = \$t;
}
// set count row logic
!isset(\$count_{$name}) ? \$count_{$name} = 1 : \$count_{$name}++;
\$count_row_{$name}++;
\$count_{$name} == 1 || \$count_row_{$name} == 1 ? print \'<span class="fb-multiselect-column{$semantic_group_class_name} {$field->type}-column" style="width:{$columnwidth}; {$fb_multiselect_column_float}">\' : print \'\';
?>
{$multiselect_item_start}
<div class="{$semantic_class_name}">
<label for="{$name}<?php echo \$count_{$name};?>" class="{$field->type}-inline {$semantic_class_name} {$label_class_code}" {$inheritstyle} >
<input type="{$field->type}" name="{$name}{$brace}" id="{$id}<?php echo \$count_{$name};?>" {$tabhtml} value="<?php echo addslashes(\$value);?>" {$inheritstyle} {$class_definition} {$enabled} {$readonly}
{$selected_code_array}
{$attribute} {$conditional_call_inline} />
<span class="rf-multiselect-item-label range-array" {$label_margin}><?php echo htmlentities(\$label); ?></span>
</label> {$inline_label_pos}
</div>
{$multiselect_item_end}
<?php
if(\$count_row_{$name} == \$rowcount_{$name}) {
echo \'</div>\';
\$count_row_{$name} = 0;
}
} // foreach loop
?>
EOH;
}
}
$element .= "
<?php if(\$count_row_{$name} != 0) { echo \'</div>\'; } ?>";
$element .= <<<EOF
<?php
// Even if we have no results we still create a column for AJAX calls.
if(\$count_row_{$name} == 0){
echo "<div class=\"fb-multiselect-column {$field->type}-column\" style=\"width:{$columnwidth}; {$fb_multiselect_column_float}\" ></div>";
}
?>
EOF;
$element .= "
" . \'<div class="fb-checkbox-clear" style="clear:both;"></div>\' . "
";
if ((int)$tablemode->enabletablelayout == 1 && !$tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div><!-- Close Table Mode -->";
}
$element .= \'</fieldset>\';
return $element;
}
public function create_file_upload_spec($max, $mode)
{
switch ($max) {
case \'0\':
$max = $this->return_bytes(ini_get(\'upload_max_filesize\'));
break;
case \'1\':
$max = 65536;
break;
case \'2\':
$max = 131072;
break;
case \'3\':
$max = 262144;
break;
case \'4\':
$max = 524288;
break;
case \'5\':
$max = 1048576;
break;
case \'6\':
$max = 2097152;
break;
case \'7\':
$max = 3145728;
break;
case \'8\':
$max = 5242880;
break;
case \'9\':
$max = 8388608;
break;
case \'10\':
$max = 15728640;
break;
}
if ($mode == \'full\') {
$element = "<input name=\"MAX_FILE_SIZE\" type=\"hidden\" value=\"{$max}\" />";
return $element;
} else {
return $max;
}
}
public function create_file($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$req = $field->validation->req;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$fieldwidth = $field->fieldwidth;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$element = "";
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; {$attributestyle} \" ";
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$max_file_size = $this->create_file_upload_spec($field->maxfilesize, \'short\');
$js_check = <<<EOF
<script type="text/javascript">
function checkSize_{$field->name}()
{
var input = document.getElementById("{$name}");
// check for browser support (may need to be modified)
if(input.files && input.files.length == 1)
{
console.log(\'File Debug: Max Size (Bytes):\', {$max_file_size}, \'Actual File Size (Bytes):\', input.files[0].size);
if (input.files[0].size > {$max_file_size})
{
alert("The file must be less than " + ({$max_file_size} / 1024 / 1024) + " MB");
input.value = "";
return false;
}
}
return true;
}
</script>
EOF;
$element .= $js_check;
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'85%\';
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$element .= $this->create_table_mode_mobile_label($field,$tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$element .= "
<input <?php echo \$enabled; ?> size=\"{$fieldwidth}\" class=\"{$extraclassnames}\" type=\"file\" name=\"{$name}\" id=\"{$id}\" {$tabhtml} {$inheritstyle} {$attribute} {$conditional_call_inline} onchange=\"checkSize_{$field->name}();\" {$enabled} {$readonly} />
";
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
}
$element .= \'<br />\';
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_jquery_file($field, $page, $xml, $bucket_node = "")
{
$tablemode = $page->tablemode;
$formname = $page->form->name;
$label = $field->label;
$name = $field->name;
$id = $field->id;
$req = $field->validation->req;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$fieldwidth = $field->fieldwidth;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$element = "";
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; {$attributestyle} \" ";
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$max_file_size = $this->create_file_upload_spec($field->maxfilesize, \'short\');
$accepted_types_js = "/(\.|\/)(gif|jpe?g|png)$/i";
$accepted_types_php = "\'/.+$/i\'";
$max_file_size_js = $this->php_elements->translateMaxValue($field->maxfilesize);
$max_file_size_php = $max_file_size_js;
switch ($field->allowed) {
case \'0\':
$accepted_types_js = \'/(\.|\/)((?!php|php\d|exe|app).)*$/i\';
$accepted_types_php = \'/(\.|\/)((?!php|php\d|exe|app).)*$/i\';
break;
case \'1\':
$accepted_types_js = \'/(\.|\/)(gif|jpe?g|png)$/i\';
$accepted_types_php = \'/\.(gif|jpe?g|png)$/i\';
break;
case \'2\':
$accepted_types_js = \'/(\.|\/)((?!gif|jpe?g|png|php|php\d|exe|app).)*$/ig\';
$accepted_types_php = \'/(\.|\/)((?!gif|jpe?g|png|php|php\d|exe|app).)*$/i\';
break;
case \'3\':
$accepted_types_js = \'/(\.|\/)(pdf)$/i\';
$accepted_types_php = \'/\.(pdf)$/i\';
break;
case \'4\':
$accepted_types_js = \'/(\.|\/)(zip)$/i\';
$accepted_types_php = \'/\.(zip)$/i\';
break;
case \'5\':
$accepted_types_js = \'/(\.|\/)(doc|docx|xls|xlsx|pdf|csv)$/i\';
$accepted_types_php = \'/\.(doc|docx|xls|xlsx|pdf|csv)$/i\';
break;
}
$core_includes = <<<EOF
<!-- Bootstrap styles -->
<link rel="stylesheet" href="lib/jquery-upload/css/bootstrap3-grid+buttons.css">
<link rel="stylesheet" href="lib/jquery-upload/css/glyphicons.css">
<!-- Generic page styles -->
<link rel="stylesheet" href="lib/jquery-upload/css/style.css">
<!-- blueimp Gallery styles -->
<link rel="stylesheet" href="//blueimp.github.io/Gallery/css/blueimp-gallery.min.css">
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="lib/jquery-upload/css/jquery.fileupload.css">
<link rel="stylesheet" href="lib/jquery-upload/css/jquery.fileupload-ui.css">
<!-- CSS adjustments for browsers with JavaScript disabled -->
<noscript><link rel="stylesheet" href="lib/jquery-upload/css/jquery.fileupload-noscript.css"></noscript>
<noscript><link rel="stylesheet" href="lib/jquery-upload/css/jquery.fileupload-ui-noscript.css"></noscript>
EOF;
$element .= $core_includes;
$autoupload_html = "";
if (isset($field->jqueryauto) && $field->jqueryauto == 1) {
$autoupload_html = <<<EOF
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
EOF;
}
$body_includes = <<<EOF
<!-- Redirect browsers with JavaScript disabled to the origin page -->
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-lg-7 top-xl">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple>
</span>
{$autoupload_html}
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<div class="col-lg-7 top-xl">
<i>Hint: Drag Files Anywhere On This Page To Upload!</i>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended"> </div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
EOF;
$element .= $body_includes;
$widget_includes = <<<EOF
<!-- The blueimp Gallery widget -->
<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even">
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev"></a>
<a class="next"></a>
<a class="close"></a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
<p class="name">{%=file.name%}</p>
<strong class="error text-danger"></strong>
</td>
<td>
<p class="size">Processing...</p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
</td>
<td>
{% if (!i && !o.options.autoUpload) { %}
<button class="btn btn-primary start" disabled>
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
<p class="name">
{% if (file.url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?\'data-gallery\':\'\'%}>{%=file.name%}</a>
{% } else { %}
<span>{%=file.name%}</span>
{% } %}
</p>
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
{% if (file.deleteUrl) { %}
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields=\'{"withCredentials":true}\'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" name="delete" value="1" class="toggle">
{% } else { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
EOF;
$element .= $widget_includes;
$autoupload_option = \'false\';
if (isset($field->jqueryauto) && $field->jqueryauto == 0) {
$autoupload_option = \'true\';
}
$postbody_includes = <<<EOF
<script type="text/javascript">
(function() { // Load jQuery If Needed.
if (!window.jQuery) {
var src = "//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.js";
document.write(\'<script src="\' + src + \'"><\/script>\');
}
})();
</script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="lib/jquery-upload/js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="//blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="lib/jquery-upload/js/load-image.all.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="lib/jquery-upload/js/canvas-to-blob.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="lib/jquery-upload/js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-image.js"></script>
<!-- The File Upload audio preview plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-audio.js"></script>
<!-- The File Upload video preview plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-video.js"></script>
<!-- The File Upload validation plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script src="lib/jquery-upload/js/jquery.fileupload-ui.js"></script>
<!-- The main application script -->
<script src="lib/jquery-upload/js/main.js"></script>
<script type="text/javascript">
// Set Properties Used By The Upload Process In: lib/jquery-upload/main.js
var formname = "{$formname}";
var max_file_size = {$max_file_size_js};
var accepted_types = {$accepted_types_js};
var max_image_width = "{$field->maxwidth}";
var max_image_height = "{$field->maxheight}";
var autoupload = {$autoupload_option};
</script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="lib/jquery-upload/js/cors/jquery.xdr-transport.js"></script>
<![endif]-->
EOF;
$element .= $postbody_includes;
if ($field->ffdestination == \'\') {
$destination = \'upload\';
} else {
$destination = $field->ffdestination;
}
if ($field->thumbdestination == \'\') {
$thumbdestination = \'upload\';
} else {
$thumbdestination = $field->thumbdestination;
}
$transfer = "";
if ($field->flatfile == \'1\') {
$transfer .= \'flatfile\';
}
if ($field->database == \'1\') {
if ($transfer != "") {
$transfer .= "|";
}
$transfer .= \'database\';
}
$php_transfer = <<<EOF
<?php
// Variables used to process PHP uploads.
include_once \'config.php\';
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["jobname"] = \'{$xml->jobname}\';
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["accepted_types"] = \'{$accepted_types_php}\';
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["dbtype"] = "{$field->dbtype}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["email"] = "{$field->email}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["destination"] = "{$destination}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["prepend"] = "{$field->prepend}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["append"] = "{$field->append}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["name"] = "{$field->name}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["label"] = "{$field->label}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["maxfilesize"] = "{$max_file_size_php}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["maxwidth"] = "{$field->maxwidth}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["maxheight"] = "{$field->maxheight}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["required"] = "{$field->validation->req}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["transfer"] = "{$transfer}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["db_key"] = "{$xml->db_key}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["dbconnector"] = "{$field->dbconnector}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["thumb"] = "{$field->thumb}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["maxthumb"] = "{$field->maxthumb}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["thumbdestination"] = "{$thumbdestination}";
\$_SESSION[\'qs\'][\$_SESSION[\'entry_key\']]["jquery_file_upload_transfer"]["conditional_method"] = "{$field->conditional->method}";
?>
EOF;
$element .= $php_transfer;
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$fieldwidth = \'85%\';
}
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
}
$element .= \'<br />\';
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_html5_file($field, $tablemode, $jobname, $db_key, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$req = $field->validation->req;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$fieldwidth = $field->fieldwidth;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$tabindex = $field->tabindex;
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
$tabhtml = $this->createTabIndexCode((int)$tabindex);
if ($label == "") {
$label = " ";
}
$styles = $this->translateFieldStyles($style);
$tooltip_element = $this->translateTooltip($tooltip, $id);
$element = "";
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; {$attributestyle} \" ";
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, $tooltip, \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
switch ($field->allowed) {
case \'0\':
$allowed_file_types_js = <<<EOJ
acceptedTypes = { \'all\': true },
EOJ;
break;
case \'1\':
$allowed_file_types_js = <<<EOJ
acceptedTypes = {
\'image/png\': true,
\'image/jpeg\': true,
\'image/gif\': true
},
EOJ;
break;
case \'2\':
$allowed_file_types_js = <<<EOJ
acceptedTypes = {
\'image/png\': false,
\'image/jpeg\': false,
\'image/gif\': false,
\'text/xml\': true,
\'application/xml\': true,
\'text/plain\': true,
\'multipart/x-zip\': true,
\'application/x-compressed\': true,
\'application/excel\': true,
\'application/msword\': true
},
EOJ;
break;
case \'3\':
$allowed_file_types_js = <<<EOJ
acceptedTypes = {
\'application/pdf\': true,
\'x-pdf\': true
},
EOJ;
break;
}
if ($field->ffdestination == \'\') {
$destination = \'upload\';
} else {
$destination = $field->ffdestination;
}
if ($field->thumbdestination == \'\') {
$thumbdestination = \'upload\';
} else {
$thumbdestination = $field->thumbdestination;
}
$transfer = array();
if ($field->flatfile == \'1\') {
$transfer[] = \'flatfile\';
}
if ($field->database == \'1\') {
$transfer[] = \'database\';
}
if ($field->email == \'1\') {
$transfer[] = \'email\';
$transfer[] = \'qs\';
}
if ($field->flatfile == \'0\' && $field->database == \'0\' && $field->email == \'0\') {
$transfer[] = \'qs\';
}
$transfer_raw = implode(\',\', $transfer);
$append = isset($field->append) ? $field->append : "";
$max_file_size = $this->create_file_upload_spec($field->maxfilesize, \'numbers_only\');
$prepend = isset($field->prepend) ? $field->prepend : "";
$element .= "
<?php
";
$element .= "\$_SESSION[\'html5_current_field_name\'] = \'{$field->name}\';
";
$element .= "\$_SESSION[\'RF_HTML5_UPLOAD_SPEC\'][\"{\$_SESSION[\'html5_current_field_name\']}\"] = array(\'jobname\' => \'{$jobname}\',
\'destination\' => \'{$destination}\',
// append
\'append\' => \'{$append}\',
\'prepend\' => \'{$prepend}\',
// size and height
\'maxwidth\' => \'{$field->maxwidth}\',
\'maxheight\' => \'{$field->maxheight}\',
// thumbnails
\'thumb\' => \'{$field->thumb}\',
\'maxthumb\' => \'{$field->maxthumb}\',
\'thumbdestination\' => \'{$thumbdestination}\',
// file properties
\'name\' => \'{$field->name}\',
\'label\' => \'{$field->label}\',
\'maxfilesize\' => \'{$max_file_size}\',
// file movement
\'transfer\' => \'{$transfer_raw}\',
// database
\'db_key\' => \'{$db_key}\',
\'dbconnector\' => \'{$field->dbconnector}\',
\'req\' => \'{$field->validation->req}\',
// allowed file types
\'allowed\' => \'{$field->allowed}\');";
$element .= "
?>
";
$html5preview = \'false\';
if (isset($field->html5preview) && (int)$field->html5preview == 1) {
$html5preview = \'true\';
}
$html5ArticleHeight = intval($field->html5height) + 16 . "px;";
$element .= <<<EOF
<style type="text/css">
#holder_{$field->name} { background-color: #fafafa; border-radius: 10px; border: 2px dotted #ccc; width: {$field->html5width}; min-height: {$field->html5height}; margin: 7px 0 12px; } /* margin: 20px auto; */
#holder_{$field->name}.hover { border: 2px dotted #0c0; }
#holder_{$field->name} img { display: block; margin: 10px auto; }
#holder_{$field->name} p { margin: 10px; font-size: 16px; }
#uploadprogress_{$field->name} { }
#uploadprogress_{$field->name}:after { content: \'%\'; }
.fail { background: #c00; padding: 2px; color: #fff; border-radius:5px; }
.hidden { display: none !important;}
.visible { display: block !important;}
#html5-upload-error_{$field->name} { padding: 10px; }
.html5-upload-error-message { font-weight: bold; line-height: 15px; text-align: center; }
.html5Instructions {
}
.html5StatusBlock {
position: absolute;
top: 30px;
left: 16px;
}
.html5Article {
position: relative;
}
.html5PreviewContainer {
margin-top:18px;
padding: 3px;
}
.html5PreviewItem {
float: left;
padding: 3px;
border: 1px solid #f3f3f3;
margin: 2px;
}
.html5FilenameList {
color: #787878;
}
.html5DeleteButton {
background-color: #818181;
color: white;
cursor: pointer;
top: 3px;
left: 4px;
height: 30px;
width: 30px;
text-align: center;
line-height: 31px;
font-weight: bold;
}
.outer {
display: table;
position: absolute;
height: 100%;
width: 100%;
}
.middle {
display: table-cell;
vertical-align: middle;
}
.inner {
margin-left: auto;
margin-right: auto;
width: 400px;
/*whatever width you want*/
}
</style>
<article class="html5Article" style="height: {$html5ArticleHeight};">
<label aria-label="Uploader" for="{$id}" style="cursor:pointer;">
<div class="outer" id="holder_{$field->name}" style="vertical-align: middle; height: {$field->html5height}; text-align: center; color:#898989; font-size:13pt; ">
<div class="middle">
<div id="html5Instructions_{$field->name}" class="inner html5Instructions" style="display:block;">
{$field->html5instructions}
</div>
<div id="upload-progress-message_{$field->name}" style="display:none;">
{$field->html5progressmessage}
<progress id="uploadprogress_{$field->name}" min="0" max="100" value="0" style="">0</progress>
</div>
</div>
</div>
<p id="upload_{$field->name}" class="hidden" style="display: none;">
<label>Drag & drop not supported, but you can still upload via this input field:<br>
<input size="{$fieldwidth}" type="file" name="{$name}" id="{$id}" {$tabhtml} {$inheritstyle} {$attribute} {$conditional_call_inline} />
</label>
</p>
<div class="html5StatusBlock">
<p class="hidden" id="filereader_{$field->name}" style="display: none;">File API & FileReader API not supported</p>
<p class="hidden" id="formdata_{$field->name}" style="display: none;">XHR2\'s FormData is not supported</p>
<p class="hidden" id="progress_{$field->name}" style="display: none;">XHR2\'s upload progress isn\'t supported</p>
<!-- Error Messages -->
<p id="html5-upload-error_{$field->name}" class="fail" style="display: none;"></p>
</div>
</label>
</article>
<div class="html5FilenameList">
<p class="hidden" id="filename_{$field->name}"></p>
</div>
<!-- Preview Container -->
<div id="previewContainer_{$field->name}" class="html5PreviewContainer" style="clear: both;"></div>
<script>
var holder_{$field->name} = document.getElementById(\'holder_{$field->name}\'),
tests = {
filereader: typeof FileReader != \'undefined\',
dnd: \'draggable\' in document.createElement(\'span\'),
formdata: !!window.FormData,
progress: "upload" in new XMLHttpRequest
},
support = {
filereader: document.getElementById(\'filereader_{$field->name}\'),
formdata: document.getElementById(\'formdata_{$field->name}\'),
progress: document.getElementById(\'progress_{$field->name}\')
},
{$allowed_file_types_js}
progress_{$field->name} = document.getElementById(\'uploadprogress_{$field->name}\'),
fileupload_{$field->name} = document.getElementById(\'upload_{$field->name}\');
"filereader formdata progress".split(\' \').forEach(function (api) {
if (tests[api] === false) {
support[api].className = \'fail\';
document.getElementById(\'holder_{$field->name}\').className = \'hidden\';
document.getElementById(\'uploadprogress_{$field->name}\').className = \'hidden\';
document.getElementById(\'upload-progress-message_{$field->name}\').className = \'hidden\';
document.getElementById(\'upload-instructions_{$field->name}\').className = \'hidden\';
document.getElementById(\'upload_{$field->name}\').className = \'visible\';
} else {
support[api].className = \'hidden\';
}
});
function previewfile_{$field->name}(file) {
if (tests.filereader === true && (acceptedTypes.all == true ? true : acceptedTypes[file.type] === true)) {
var reader = new FileReader();
reader.onload = function (event) {
var image = new Image();
// Is This An Image We Uploaded?
var fileIsImage = (file.type.split(\'/\')[0] == \'image\') ? true : false;
if(fileIsImage){
// Use Given Image
image.src = event.target.result;
image.width = 200; // a fake resize
} else {
// Not An Image, So Create Basic Background.
var canvas = document.createElement(\'canvas\');
var _size = 200;
canvas.width = _size;
canvas.height = _size;
var ctx = canvas.getContext("2d");
// Background Color
ctx.fillStyle = "gray";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Basic Text
ctx.fillStyle = "white";
ctx.font = "22px Arial";
ctx.fillText("File Upload", 30, 50);
// File Name Text
ctx.fillStyle = "white";
ctx.font = "14px Arial";
ctx.textBaseline = \'bottom\'; // set text position
ctx.fillText(file.name, 30, 150);
image.src = canvas.toDataURL();
}
// Create Image Holder
var imageWrapper = document.createElement("DIV");
imageWrapper.id = "html5Preview_" + file.name;
imageWrapper.className = "html5PreviewItem";
imageWrapper.style.position = "relative";
// Create Delete Control.
var deleteButton = document.createElement("DIV");
deleteButton.className = "html5DeleteButton";
deleteButton.style.position = "absolute";
// Add Delete Button Text (X)
deleteButton.appendChild(document.createTextNode(\'X\'));
deleteButton.setAttribute(\'onclick\', \'deleteFile_Training_Documentation("\' + file.name + \'");\');
// Append Delete Button
imageWrapper.appendChild(deleteButton);
// Append Image
imageWrapper.appendChild(image);
// Append Image Holder To Master Container.
previewContainer_Training_Documentation.appendChild(imageWrapper);
};
reader.readAsDataURL(file);
} else {
document.getElementById(\'html5-upload-error_{$field->name}\').innerHTML = \'<p>Cannot upload: \' + file.name + \'. A disallowed file type usually causes this error.</p>\';
}
}
function resizeFile_{$field->name}(files, idx, dataURL, fileType, fileName, maxWidth, maxHeight) {
maxWidth = maxWidth == "" ? 25000 : parseInt(maxWidth);
maxHeight = maxHeight == "" ? 25000 : parseInt(maxHeight);
var image = new Image();
image.src = dataURL;
image.onload = function () {
var width = image.width;
var height = image.height;
var shouldResize = (width > maxWidth) || (height > maxHeight);
if (!shouldResize) {
formData.append(\'field\', \'{$field->name}\');
formData.append(\'file\' + i, dataURL);
return;
}
var newWidth;
var newHeight;
if (width > height) {
newHeight = height * (maxWidth / width);
newWidth = maxWidth;
} else {
newWidth = width * (maxHeight / height);
newHeight = maxHeight;
}
var canvas = document.createElement(\'canvas\');
canvas.width = newWidth;
canvas.height = newHeight;
var context = canvas.getContext(\'2d\');
context.drawImage(this, 0, 0, newWidth, newHeight);
dataURL = canvas.toDataURL(fileType);
// Send For Upload.
// https://developer.mozilla.org/en-US/docs/Web/API/FormData
var formData = new FormData();
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
canvas.toBlob(function(blob) {
var newImg = document.createElement(\'img\'), url = URL.createObjectURL(blob);
// Debug
newImg.onload = function() {
// no longer need to read the blob so it\'s revoked
URL.revokeObjectURL(url);
};
// Not Supported In Safari (As Of 3/18)
if(!IsSafariBrowser()) {
var file = new File([blob], fileName, {
type: "image/jpeg",
});
formData.append(\'file\' + idx, file);
} else {
formData.append(\'file\' + idx, blob);
formData.append(\'safariResized\', \'true\');
formData.append(\'safariResizedName\', fileName);
}
// Common Items.
formData.append(\'field\', \'{$field->name}\');
// Debug - Shows Image At Bottom Of Window.
// newImg.src = url;
// document.body.appendChild(newImg);
postFile_{$field->name}(formData, files);
}, \'image/jpeg\', 0.95);
};
image.onerror = function () {
alert(\'There was an error processing your file!\');
};
}
function IsSafariBrowser()
{
var VendorName=window.navigator.vendor;
return ((VendorName.indexOf(\'Apple\') > -1) &&
(window.navigator.userAgent.indexOf(\'Safari\') > -1));
}
function readfiles_{$field->name}(files) {
// hide field and clear any existing messages
document.getElementById(\'html5-upload-error_{$field->name}\').style.display = \'none\';
document.getElementById(\'html5-upload-error_{$field->name}\').innerHTML = \'\';
document.getElementById(\'filename_{$field->name}\').className = \'hidden\';
document.getElementById(\'filename_{$field->name}\').innerHTML = \'\';
var formData = tests.formdata ? new FormData() : null;
var error_message = "";
for (var i = 0; i < files.length; i++) {
// Check File Size.
if(files[i].size > {$max_file_size}){
error_message += "File (" + files[i].name + ") Too Large, Must Be Under " + ({$max_file_size} / 1024 / 1024) + " MB <br/>";
continue;
}
// If Resizing Raw Images, Do So Now.
var fileIsImage = (files[i].type.split(\'/\')[0] == \'image\') ? true : false;
if(fileIsImage && (\'{$field->maxwidth}\' != \'\' || \'{$field->maxheight}\' != \'\')){
readFile_{$field->name}(files, i, files[i], \'$field->maxwidth\', \'$field->maxheight\');
} else {
if (tests.formdata){
formData.append(\'field\', \'{$field->name}\');
formData.append(\'file\' + i, files[i]);
}
postFile_{$field->name}(formData, files);
}
if({$html5preview} == true && files[i].size < {$this->create_file_upload_spec($field->maxfilesize, \'numbers_only\')}){
previewfile_{$field->name}(files[i]);
}
}
if(error_message != ""){
document.getElementById(\'html5-upload-error_{$field->name}\').style.display = \'block\';
document.getElementById(\'html5-upload-error_{$field->name}\').innerHTML += \'<span class="html5-upload-error-message">\' + error_message + \'</span>\';
}
}
function readFile_{$field->name}(files, idx, file, maxWidth, maxHeight) {
var reader = new FileReader();
reader.onloadend = function () {
resizeFile_{$field->name}(files, idx, reader.result, file.type, file.name, maxWidth, maxHeight);
}
reader.onerror = function () {
alert(\'There was an error reading the file!\');
}
reader.readAsDataURL(file);
}
function deleteFile_{$field->name}(filename){
// Delete From Uploads
var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append(\'action\', "delete");
formData.append(\'filename\', filename);
formData.append(\'fieldname\', \'{$field->name}\');
xhr.open(\'POST\', \'lib/upload/html5_upload.php\');
xhr.onload = function(xhr) { // file done uploading...
if(xhr.target.response.indexOf(\'XHR_ERROR\') != -1){
} else {
}
}
xhr.send(formData);
// Delete From DOM
var element = document.getElementById("html5Preview_" + filename);
element.outerHTML = "";
delete element;
}
function postFile_{$field->name}(formData, files){
// now post a new XHR request
if (tests.formdata) {
var xhr = new XMLHttpRequest();
xhr.open(\'POST\', \'lib/upload/html5_upload.php\');
// Hide Message
document.getElementById(\'html5Instructions_{$field->name}\').style.display = "none";
// Show Progress Bar
document.getElementById(\'upload-progress-message_{$field->name}\').style.display = "block";
xhr.onload = function(xhr) { // file done uploading...
// check for errors...
if(xhr.target.response.indexOf(\'XHR_ERROR\') != -1){
message = xhr.target.response.replace(\'XHR_ERROR\', \'\').replace(\'<br/>\', \'\');
document.getElementById(\'html5-upload-error_{$field->name}\').style.display = \'block\';
document.getElementById(\'html5-upload-error_{$field->name}\').innerHTML += \'<span class="html5-upload-error-message">\' + message + \'</span>\';
// Show Message
document.getElementById(\'html5Instructions_{$field->name}\').style.display = "block";
// Hide Progress Bar
document.getElementById(\'upload-progress-message_{$field->name}\').style.display = "none";
// Reset Progress Bar.
uploadprogress_{$field->name}.value = 0;
uploadprogress_{$field->name}.innerHTML = "0";
} else {
uploadprogress_{$field->name}.value = uploadprogress_{$field->name}.innerHTML = 100;
document.getElementById(\'filename_{$field->name}\').innerHTML = "";
for(i = 0; i < files.length; i++){
document.getElementById(\'filename_{$field->name}\').className = \'visible\';
document.getElementById(\'filename_{$field->name}\').innerHTML += "{$field->html5completemessage} " + "<strong>" + files[i].name + "</strong><br/>";
// Show Message
document.getElementById(\'html5Instructions_{$field->name}\').style.display = "block";
// Hide Progress Bar
document.getElementById(\'upload-progress-message_{$field->name}\').style.display = "none";
// Reset Progress Bar.
uploadprogress_{$field->name}.value = 0;
uploadprogress_{$field->name}.innerHTML = "0";
}
}
};
if (tests.progress) {
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
var complete = (event.loaded / event.total * 100 | 0);
uploadprogress_{$field->name}.value = uploadprogress_{$field->name}.innerHTML = complete;
}
}
}
xhr.send(formData);
}
}
if (tests.dnd) {
// Get Existing Class Name(s)
var _existingClass = holder_{$field->name}.className;
holder_{$field->name}.ondragover = function () { this.className = _existingClass + \' hover\'; return false; };
holder_{$field->name}.ondragleave = function () { this.className = _existingClass; return false; };
holder_{$field->name}.ondragend = function () { this.className = _existingClass; return false; };
holder_{$field->name}.ondrop = function (e) {
this.className = _existingClass;
e.preventDefault();
readfiles_{$field->name}(e.dataTransfer.files);
}
}
fileupload_{$field->name}.className = \'hidden\';
fileupload_{$field->name}.querySelector(\'input\').onchange = function () {
readfiles_{$field->name}(this.files);
};
</script>
EOF;
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\">{$tooltip_element->text}</div>
";
$element .= $tooltip_element->js;
if ($helper != \'\') {
$element .= "
<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>
";
}
$element .= \'<br />\';
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "
</div>
";
}
return $element;
}
public function create_multifile($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$color = $field->color;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$automode = $field->automode;
$filecount = $field->filecount;
$destination = $field->destination;
$usecustomcode = $field->usecustomcode;
$customcode = $field->customcode;
$style = $field->style;
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$element = "";
$styles = $this->translateFieldStyles($style);
$destination = $this->uv->replace_all($destination, 6);
$labelpos = $this->get_label_pos($labelpos);
if ((int)$automode == 1) {
$auto = \'\';
$automode = \'true\';
} else {
$auto = "<span class=\"uploadifyControl\" {$tabhtml}><a href=\"javascript:jQuery(\'#{$id}\').uploadifyUpload();\">Upload Files</a> | <a href=\"javascript:jQuery(\'#{$id}\').uploadifyClearQueue();\">Clear Queue</a></span>";
$automode = \'false\';
}
$multi = (int)$filecount == 0 ? \'false\' : \'true\';
$scripts = <<<EOT
<script type="text/javascript" src="lib/uploadify/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="lib/uploadify/swfobject.js"></script>
<script type="text/javascript" src="lib/uploadify/jquery.uploadify.v2.1.0.min.js"></script>
<link rel="stylesheet" type="text/css" href="lib/uploadify/uploadify.css" media="screen" />
EOT;
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$req = 0;
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, \'\', \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$element .= $this->create_table_mode_mobile_label($field, $tablemode);
$element .= <<<EOF
<input id="{$id}" name="{$name}" type="file" /><br/>
{$auto}
<script type="text/javascript">// <![CDATA[
jQuery.noConflict();
jQuery(document).ready(function() {
jQuery(\'#{$id}\').uploadify({
\'uploader\' : \'lib/uploadify/uploadify.swf\',
\'script\' : \'lib/uploadify/uploadify.php\',
\'cancelImg\' : \'lib/uploadify/cancel.png\',
\'folder\' : \'{$destination}\',
\'auto\' : {$automode},
\'multi\' : {$multi}
});
});
// ]]></script>
EOF;
if ((int)$usecustomcode == 1 && $customcode != \'\') {
$element = $customcode;
}
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
$element .= \'<br />\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $scripts . $element;
}
public function create_calendar($field, $tablemode, $bucket_node = "")
{
$label = $field->{\'label\'};
$name = $field->{\'name\'};
$id = $field->{\'id\'};
$req = $field->validation->req;
$fieldwidth = $field->fieldwidth;
$fieldheight = $field->fieldheight;
$defaultvalue = $field->defaultvalue;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$maxlength = $field->validation->max;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$fieldpopulatedefault = isset($field->fieldpopulatedefault) ? $field->fieldpopulatedefault : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$calendartype = $field->calendartype;
$calendararguments = $field->calendararguments;
$callback = isset($field->callback) ? $field->callback : \'\';
$tabindex = $field->tabindex;
$element = "";
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$styles = $this->translateFieldStyles($style);
$defaultvalue = $this->create_default_value_tokens($defaultvalue);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
if (!isset($fieldheight)) {
$fieldheight = "";
} else {
if ((string)$fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight}px;";
}
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " font-size:{$fontsize}; color:{$input_color}; {$fieldheight} font-family:inherit; {$attributestyle} ";
} else {
$inheritstyle = " color:{$input_color}; {$attributestyle} {$fieldheight} ";
}
$ct1 = substr_count((string)$fieldwidth, \'pt\');
$ct2 = substr_count((string)$fieldwidth, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$size_css = " width:{$fieldwidth}px; ";
} else {
$size_css = " width:{$fieldwidth}; ";
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$size_css = " width:60%; ";
}
$cal_args = explode(\'|\', $calendararguments);
$arg_list = \'\';
if ($cal_args[0] !== \'\') {
foreach ($cal_args as $args) {
$arg_list .= "cal{$name}." . $args . \';\';
}
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
if ($maxlength != \'\') {
$max = "maxlength=\"{$maxlength}\"";
} else {
$max = \'\';
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, \'\', \'\', $tablemode);
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$calback_code = <<<EOF
var date = new Date(Date.UTC(y,m-1,d,0,0,0));
var s_ts = date.getTime()/1000;
var c_ts = Math.round(new Date().getTime()/1000)
{$callback}
EOF;
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
$element .= $this->create_table_mode_mobile_label($field, $tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$_value = "<?php isset(\$_SESSION[\"{$name}\"]) ? print \$_SESSION[\"{$name}\"] : print $defaultvalue; ?>";
if(isset($fieldpopulatedefault) && $fieldpopulatedefault == 0){
$_value = \'<?php print $defaultvalue; ?>\';
}
switch ($calendartype) {
case \'0\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
//var cal{$name} = new CalendarPopup(); // use popup window
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').value=LZ(m) + \'/\' + LZ(d) + \'/\' + y;
validators[\'date-{$name}-1\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<input <?php echo \$enabled; ?> type="text" class="{$extraclassnames} calendar-field-full" name="{$name}" id="date-{$id}-1" {$tabhtml} value="{$_value}" {$max} style="{$inheritstyle} {$size_css}" {$attribute} {$conditional_call_inline} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-full" name="cal-anchor-{$name}" href="#" onclick="cal{$name}.showCalendar(\'cal-anchor-{$name}\'); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'1\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').value=LZ(m);
document.getElementById(\'date-{$name}-2\').value=LZ(d);
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<?php
\$dv = {$defaultvalue};
if(\$dv == "")
\$dv = \$datetime;
\$month = \'\';
\$day = \'\';
\$year = \'\';
if(\$dv != \'\'){
// american
if(is_object(\$dv)) {
\$date = \$dv;
} else {
\$date = new DateTime({$defaultvalue});
}
\$month = \$date->format(\'m\');
\$day = \$date->format(\'d\');
\$year = \$date->format(\'Y\');
}
\$cal_select_code = "\'{\$month}/{\$day}/{\$year}\'";
?>
<input <?php echo \$enabled; ?> type="text" class="{$extraclassnames} calendar-numeric-field-1" name="date-{$name}-1" id="date-{$id}-1" {$tabhtml} value="<?php isset(\$_SESSION[\'date-{$name}-1\']) ? print \$_SESSION[\'date-{$name}-1\'] : print \$month; ?>" size="2" maxlength="2" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?> type="text" class="{$extraclassnames} calendar-numeric-field-2" name="date-{$name}-2" id="date-{$id}-2" value="<?php isset(\$_SESSION[\'date-{$name}-2\']) ? print \$_SESSION[\'date-{$name}-2\'] : print \$day; ?>" size="2" maxlength="2" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?> type="text" class="{$extraclassnames} calendar-numeric-field-3" name="date-{$name}-3" id="date-{$id}-3" value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \$year; ?>" size="4" maxlength="4" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-multi" name="cal-anchor-{$name}" href="#" onclick="cal{$name}.showCalendar(\'cal-anchor-{$name}\', <?php echo \$cal_select_code; ?>); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'2\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').selectedIndex=m;
document.getElementById(\'date-{$name}-2\').selectedIndex=d;
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-1" name="date-{$name}-1" id="date-{$id}-1" {$tabhtml} style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="Jan" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Jan\') { echo \'selected="selected"\'; } ?> >January</option>
<option value="Feb" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Feb\') { echo \'selected="selected"\'; } ?> >February</option>
<option value="Mar" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Mar\') { echo \'selected="selected"\'; } ?> >March</option>
<option value="Apr" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Apr\') { echo \'selected="selected"\'; } ?> >April</option>
<option value="May" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'May\') { echo \'selected="selected"\'; } ?> >May</option>
<option value="Jun" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Jun\') { echo \'selected="selected"\'; } ?> >June</option>
<option value="Jul" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Jul\') { echo \'selected="selected"\'; } ?> >July</option>
<option value="Aug" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Aug\') { echo \'selected="selected"\'; } ?> >August</option>
<option value="Sep" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Sep\') { echo \'selected="selected"\'; } ?> >September</option>
<option value="Oct" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Oct\') { echo \'selected="selected"\'; } ?> >October</option>
<option value="Nov" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Nov\') { echo \'selected="selected"\'; } ?> >November</option>
<option value="Dec" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'Dec\') { echo \'selected="selected"\'; } ?> >December</option>
</select>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-2" name="date-{$name}-2" id="date-{$id}-2" style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="1" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'1\') { echo \'selected="selected"\'; } ?> >1</option>
<option value="2" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'2\') { echo \'selected="selected"\'; } ?> >2</option>
<option value="3" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'3\') { echo \'selected="selected"\'; } ?> >3</option>
<option value="4" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'4\') { echo \'selected="selected"\'; } ?> >4</option>
<option value="5" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'5\') { echo \'selected="selected"\'; } ?> >5</option>
<option value="6" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'6\') { echo \'selected="selected"\'; } ?> >6</option>
<option value="7" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'7\') { echo \'selected="selected"\'; } ?> >7</option>
<option value="8" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'8\') { echo \'selected="selected"\'; } ?> >8</option>
<option value="9" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'9\') { echo \'selected="selected"\'; } ?> >9</option>
<option value="10" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'10\') { echo \'selected="selected"\'; } ?> >10</option>
<option value="11" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'11\') { echo \'selected="selected"\'; } ?> >11</option>
<option value="12" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'12\') { echo \'selected="selected"\'; } ?> >12</option>
<option value="13" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'13\') { echo \'selected="selected"\'; } ?> >13</option>
<option value="14" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'14\') { echo \'selected="selected"\'; } ?> >14</option>
<option value="15" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'15\') { echo \'selected="selected"\'; } ?> >15</option>
<option value="16" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'16\') { echo \'selected="selected"\'; } ?> >16</option>
<option value="17" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'17\') { echo \'selected="selected"\'; } ?> >17</option>
<option value="18" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'18\') { echo \'selected="selected"\'; } ?> >18</option>
<option value="19" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'19\') { echo \'selected="selected"\'; } ?> >19</option>
<option value="20" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'20\') { echo \'selected="selected"\'; } ?> >20</option>
<option value="21" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'21\') { echo \'selected="selected"\'; } ?> >21</option>
<option value="22" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'22\') { echo \'selected="selected"\'; } ?> >22</option>
<option value="23" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'23\') { echo \'selected="selected"\'; } ?> >23</option>
<option value="24" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'24\') { echo \'selected="selected"\'; } ?> >24</option>
<option value="25" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'25\') { echo \'selected="selected"\'; } ?> >25</option>
<option value="26" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'26\') { echo \'selected="selected"\'; } ?> >26</option>
<option value="27" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'27\') { echo \'selected="selected"\'; } ?> >27</option>
<option value="28" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'28\') { echo \'selected="selected"\'; } ?> >28</option>
<option value="29" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'29\') { echo \'selected="selected"\'; } ?> >29</option>
<option value="30" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'30\') { echo \'selected="selected"\'; } ?> >30</option>
<option value="31" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'31\') { echo \'selected="selected"\'; } ?> >31</option>
</select>
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-3" type="text" name="date-{$name}-3" id="date-{$id}-3" value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \'\'; ?>" size="4" maxlength="4" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-multi" name="cal-anchor-{$name}" href="#" onclick="cal{$name}.showCalendar(\'cal-anchor-{$name}\'); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'3\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
//var cal{$name} = new CalendarPopup(); // use popup window
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').value=LZ(d) + \'/\' + LZ(m) + \'/\' + y;
validators[\'date-{$name}-1\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-field-full" type="text" name="{$name}" id="date-{$id}-1" {$tabhtml} value="{$_value}" {$max} style="{$inheritstyle} {$size_css}" {$attribute} {$conditional_call_inline} />
<a id="cal-anchor-{$name}" class="cal-anchor-full" name="cal-anchor-{$name}" href="#" onclick="cal{$name}.showCalendar(\'cal-anchor-{$name}\'); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'4\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').value=LZ(d);
document.getElementById(\'date-{$name}-2\').value=LZ(m);
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<?php
\$dv = {$defaultvalue};
if(\$dv == "")
\$dv = \$datetime;
\$month = \'\';
\$day = \'\';
\$year = \'\';
if(\$dv != \'\'){
// european
if(is_object(\$dv)) {
\$date = \$dv;
} else {
\$date = new DateTime({$defaultvalue});
}
\$month = \$date->format(\'m\');
\$day = \$date->format(\'d\');
\$year = \$date->format(\'Y\');
}
\$cal_select_code = "\'{\$day}/{\$month}/{\$year}\'";
?>
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-numeric-field-1" type="text" name="date-{$name}-1" id="date-{$id}-1" {$tabhtml} value="<?php isset(\$_SESSION[\'date-{$name}-1\']) ? print \$_SESSION[\'date-{$name}-1\'] : print \$day; ?>" size="2" maxlength="2" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-numeric-field-2" type="text" name="date-{$name}-2" id="date-{$id}-2" value="<?php isset(\$_SESSION[\'date-{$name}-2\']) ? print \$_SESSION[\'date-{$name}-2\'] : print \$month; ?>" size="2" maxlength="2" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-numeric-field-3" type="text" name="date-{$name}-3" id="date-{$id}-3" value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \$year; ?>" size="4" maxlength="4" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-multi" name="cal-anchor-{$name}" href="#" onClick="cal{$name}.showCalendar(\'cal-anchor-{$name}\', <?php echo \$cal_select_code; ?>); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'5\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').selectedIndex=d;
document.getElementById(\'date-{$name}-2\').selectedIndex=m;
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-1" name="date-{$name}-1" id="date-{$id}-1" {$tabhtml} style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="1" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'1\') { echo \'selected="selected"\'; } ?> >1</option>
<option value="2" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'2\') { echo \'selected="selected"\'; } ?> >2</option>
<option value="3" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'3\') { echo \'selected="selected"\'; } ?> >3</option>
<option value="4" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'4\') { echo \'selected="selected"\'; } ?> >4</option>
<option value="5" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'5\') { echo \'selected="selected"\'; } ?> >5</option>
<option value="6" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'6\') { echo \'selected="selected"\'; } ?> >6</option>
<option value="7" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'7\') { echo \'selected="selected"\'; } ?> >7</option>
<option value="8" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'8\') { echo \'selected="selected"\'; } ?> >8</option>
<option value="9" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'9\') { echo \'selected="selected"\'; } ?> >9</option>
<option value="10" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'10\') { echo \'selected="selected"\'; } ?> >10</option>
<option value="11" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'11\') { echo \'selected="selected"\'; } ?> >11</option>
<option value="12" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'12\') { echo \'selected="selected"\'; } ?> >12</option>
<option value="13" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'13\') { echo \'selected="selected"\'; } ?> >13</option>
<option value="14" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'14\') { echo \'selected="selected"\'; } ?> >14</option>
<option value="15" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'15\') { echo \'selected="selected"\'; } ?> >15</option>
<option value="16" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'16\') { echo \'selected="selected"\'; } ?> >16</option>
<option value="17" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'17\') { echo \'selected="selected"\'; } ?> >17</option>
<option value="18" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'18\') { echo \'selected="selected"\'; } ?> >18</option>
<option value="19" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'19\') { echo \'selected="selected"\'; } ?> >19</option>
<option value="20" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'20\') { echo \'selected="selected"\'; } ?> >20</option>
<option value="21" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'21\') { echo \'selected="selected"\'; } ?> >21</option>
<option value="22" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'22\') { echo \'selected="selected"\'; } ?> >22</option>
<option value="23" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'23\') { echo \'selected="selected"\'; } ?> >23</option>
<option value="24" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'24\') { echo \'selected="selected"\'; } ?> >24</option>
<option value="25" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'25\') { echo \'selected="selected"\'; } ?> >25</option>
<option value="26" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'26\') { echo \'selected="selected"\'; } ?> >26</option>
<option value="27" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'27\') { echo \'selected="selected"\'; } ?> >27</option>
<option value="28" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'28\') { echo \'selected="selected"\'; } ?> >28</option>
<option value="29" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'29\') { echo \'selected="selected"\'; } ?> >29</option>
<option value="30" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'30\') { echo \'selected="selected"\'; } ?> >30</option>
<option value="31" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'31\') { echo \'selected="selected"\'; } ?> >31</option>
</select>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-2" name="date-{$name}-2" id="date-{$id}-2" style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="Jan" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jan\') { echo \'selected="selected"\'; } ?> >January</option>
<option value="Feb" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Feb\') { echo \'selected="selected"\'; } ?> >February</option>
<option value="Mar" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Mar\') { echo \'selected="selected"\'; } ?> >March</option>
<option value="Apr" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Apr\') { echo \'selected="selected"\'; } ?> >April</option>
<option value="May" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'May\') { echo \'selected="selected"\'; } ?> >May</option>
<option value="Jun" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jun\') { echo \'selected="selected"\'; } ?> >June</option>
<option value="Jul" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jul\') { echo \'selected="selected"\'; } ?> >July</option>
<option value="Aug" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Aug\') { echo \'selected="selected"\'; } ?> >August</option>
<option value="Sep" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Sep\') { echo \'selected="selected"\'; } ?> >September</option>
<option value="Oct" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Oct\') { echo \'selected="selected"\'; } ?> >October</option>
<option value="Nov" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Nov\') { echo \'selected="selected"\'; } ?> >November</option>
<option value="Dec" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Dec\') { echo \'selected="selected"\'; } ?> >December</option>
</select>
<input <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-3" type="text" name="date-{$name}-3" id="date-{$id}-3" value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \'\'; ?>" size="4" maxlength="4" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-multi" name="cal-anchor-{$name}" href="#" onClick="cal{$name}.showCalendar(\'cal-anchor-{$name}\'); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
case \'6\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').value=LZ(d);
document.getElementById(\'date-{$name}-2\').value=LZ(m);
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
cal{$name}.setMonthNames(\'Januar\',\'Februar\',\'März\',\'April\',\'Mai\',\'Juni\',\'Juli\',\'August\',\'September\',\'Oktober\',\'November\',\'Dezember\');
cal{$name}.setDayHeaders(\'S\',\'M\',\'D\',\'M\',\'D\',\'F\',\'S\');
cal{$name}.setWeekStartDay(1);
cal{$name}.setTodayText("Heute");
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<?php
\$dv = {$defaultvalue};
if(\$dv == "")
\$dv = \$datetime;
\$month = \'\';
\$day = \'\';
\$year = \'\';
if(\$dv != \'\'){
// european
if(is_object(\$dv)) {
\$date = \$dv;
} else {
\$date = new DateTime({$defaultvalue});
}
\$month = \$date->format(\'m\');
\$day = \$date->format(\'d\');
\$year = \$date->format(\'Y\');
}
\$cal_select_code = "\'{\$day}/{\$month}/{\$year}\'";
?>
<input <?php echo \$enabled; ?>
class="{$extraclassnames} calendar-numeric-field-1"
type="text"
name="date-{$name}-1"
id="date-{$id}-1" {$tabhtml}
value="<?php isset(\$_SESSION[\'date-{$name}-1\']) ? print \$_SESSION[\'date-{$name}-1\'] : print \$day; ?>"
size="2"
maxlength="2"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} calendar-numeric-field-2"
type="text"
name="date-{$name}-2"
id="date-{$id}-2"
value="<?php isset(\$_SESSION[\'date-{$name}-2\']) ? print \$_SESSION[\'date-{$name}-2\'] : print \$month; ?>"
size="2"
maxlength="2"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} calendar-numeric-field-3"
type="text"
name="date-{$name}-3"
id="date-{$id}-3"
value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \$year; ?>"
size="4"
maxlength="4"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}"
class="cal-anchor-multi"
name="cal-anchor-{$name}"
href="#" onClick="cal{$name}.showCalendar(\'cal-anchor-{$name}\', <?php echo \$cal_select_code; ?>); return false;" >
<img
class="cal-anchor"
style="margin-left:5px;
margin-bottom:-7px;"
alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png"
border="0"
/>
</a>
EOT;
break;
case \'7\':
$element .= <<<EOT
<script type="text/javascript">
// Calendar Blocks Hint
var cal{$name} = new CalendarPopup("cal-div-{$name}"); {$arg_list}
cal{$name}.setReturnFunction("setMultipleValues_{$name}");
function setMultipleValues_{$name}(y,m,d) {
document.getElementById(\'date-{$name}-1\').selectedIndex=d;
document.getElementById(\'date-{$name}-2\').selectedIndex=m;
document.getElementById(\'date-{$name}-3\').value=y;
validators[\'date-{$name}-1\'].check();
validators[\'date-{$name}-2\'].check();
validators[\'date-{$name}-3\'].check();
// Build 915 - Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$name}-1\').focus();
// Custom Callback Code.
{$calback_code}
}
cal{$name}.setMonthNames(\'Januar\',\'Februar\',\'März\',\'April\',\'Mai\',\'Juni\',\'Juli\',\'August\',\'September\',\'Oktober\',\'November\',\'Dezember\');
cal{$name}.setDayHeaders(\'S\',\'M\',\'D\',\'M\',\'D\',\'F\',\'S\');
cal{$name}.setWeekStartDay(1);
cal{$name}.setTodayText("Heute");
</script>
<span id="cal-div-{$name}" style="position: absolute; visibility: hidden; background-color: white; z-index:1001;"></span>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-3" name="date-{$name}-1" id="date-{$id}-1" {$tabhtml} style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="1" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'1\') { echo \'selected="selected"\'; } ?> >1</option>
<option value="2" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'2\') { echo \'selected="selected"\'; } ?> >2</option>
<option value="3" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'3\') { echo \'selected="selected"\'; } ?> >3</option>
<option value="4" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'4\') { echo \'selected="selected"\'; } ?> >4</option>
<option value="5" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'5\') { echo \'selected="selected"\'; } ?> >5</option>
<option value="6" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'6\') { echo \'selected="selected"\'; } ?> >6</option>
<option value="7" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'7\') { echo \'selected="selected"\'; } ?> >7</option>
<option value="8" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'8\') { echo \'selected="selected"\'; } ?> >8</option>
<option value="9" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'9\') { echo \'selected="selected"\'; } ?> >9</option>
<option value="10" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'10\') { echo \'selected="selected"\'; } ?> >10</option>
<option value="11" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'11\') { echo \'selected="selected"\'; } ?> >11</option>
<option value="12" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'12\') { echo \'selected="selected"\'; } ?> >12</option>
<option value="13" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'13\') { echo \'selected="selected"\'; } ?> >13</option>
<option value="14" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'14\') { echo \'selected="selected"\'; } ?> >14</option>
<option value="15" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'15\') { echo \'selected="selected"\'; } ?> >15</option>
<option value="16" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'16\') { echo \'selected="selected"\'; } ?> >16</option>
<option value="17" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'17\') { echo \'selected="selected"\'; } ?> >17</option>
<option value="18" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'18\') { echo \'selected="selected"\'; } ?> >18</option>
<option value="19" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'19\') { echo \'selected="selected"\'; } ?> >19</option>
<option value="20" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'20\') { echo \'selected="selected"\'; } ?> >20</option>
<option value="21" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'21\') { echo \'selected="selected"\'; } ?> >21</option>
<option value="22" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'22\') { echo \'selected="selected"\'; } ?> >22</option>
<option value="23" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'23\') { echo \'selected="selected"\'; } ?> >23</option>
<option value="24" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'24\') { echo \'selected="selected"\'; } ?> >24</option>
<option value="25" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'25\') { echo \'selected="selected"\'; } ?> >25</option>
<option value="26" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'26\') { echo \'selected="selected"\'; } ?> >26</option>
<option value="27" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'27\') { echo \'selected="selected"\'; } ?> >27</option>
<option value="28" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'28\') { echo \'selected="selected"\'; } ?> >28</option>
<option value="29" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'29\') { echo \'selected="selected"\'; } ?> >29</option>
<option value="30" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'30\') { echo \'selected="selected"\'; } ?> >30</option>
<option value="31" <?php if(isset(\$_SESSION[\'date-{$name}-1\']) && \$_SESSION[\'date-{$name}-1\'] == \'31\') { echo \'selected="selected"\'; } ?> >31</option>
</select>
<select <?php echo \$enabled; ?> class="{$extraclassnames} calendar-select-field-2" name="date-{$name}-2" id="date-{$id}-2" style="{$inheritstyle}" {$attribute}>
<option></option>
<option value="Jan" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jan\') { echo \'selected="selected"\'; } ?> >Januar</option>
<option value="Feb" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Feb\') { echo \'selected="selected"\'; } ?> >Februar</option>
<option value="Mar" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Mar\') { echo \'selected="selected"\'; } ?> >März</option>
<option value="Apr" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Apr\') { echo \'selected="selected"\'; } ?> >April</option>
<option value="May" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'May\') { echo \'selected="selected"\'; } ?> >Mag</option>
<option value="Jun" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jun\') { echo \'selected="selected"\'; } ?> >Juni</option>
<option value="Jul" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Jul\') { echo \'selected="selected"\'; } ?> >Juli</option>
<option value="Aug" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Aug\') { echo \'selected="selected"\'; } ?> >August</option>
<option value="Sep" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Sep\') { echo \'selected="selected"\'; } ?> >September</option>
<option value="Oct" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Oct\') { echo \'selected="selected"\'; } ?> >Oktober</option>
<option value="Nov" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Nov\') { echo \'selected="selected"\'; } ?> >November</option>
<option value="Dec" <?php if(isset(\$_SESSION[\'date-{$name}-2\']) && \$_SESSION[\'date-{$name}-2\'] == \'Dec\') { echo \'selected="selected"\'; } ?> >Dezember</option>
</select>
<input type="text" class="{$extraclassnames}"\"{$extraclassnames} calendar-select-field-1\" name="date-{$name}-3" id="date-{$id}-3" value="<?php isset(\$_SESSION[\'date-{$name}-3\']) ? print \$_SESSION[\'date-{$name}-3\'] : print \'\'; ?>" size="4" maxlength="4" style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<a id="cal-anchor-{$name}" class="cal-anchor-multi" name="cal-anchor-{$name}" href="#" onClick="cal{$name}.showCalendar(\'cal-anchor-{$name}\'); return false;" ><img class="cal-anchor" style="margin-left:5px; margin-bottom:-7px;" alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png" border="0" /></a>
EOT;
break;
}
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
} else {
$element .= "<br />";
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_datetime($page, $field, $tablemode, $bucket_node = "")
{
$label = $field->{\'label\'};
$name = $field->{\'name\'};
$id = $field->{\'id\'};
$req = $field->validation->req;
$fieldwidth = $field->fieldwidth;
$fieldheight = $field->fieldheight;
$defaultvalue = $field->defaultvalue;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$inheritstyle = $field->inheritstyle;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$maxlength = $field->validation->max;
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$attribute = $field->attribute;
$attributestyle = $field->attributestyle;
$conditional = $field->conditional;
$style = $field->style;
$tooltip = $field->tooltip;
$type = $field->calendartype;
$calendararguments = $field->calendararguments;
$tabindex = $field->tabindex;
$element = "";
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$styles = $this->translateFieldStyles($style);
$defaultvalue = $this->create_default_value_tokens($defaultvalue);
$conditional_call = $this->_createConditionalEvent($conditional, $name, $id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
if (!isset($fieldheight)) {
$fieldheight = "";
} else {
if ((string)$fieldheight == "") {
$fieldheight = "";
} else {
$fieldheight = "height:{$fieldheight}px;";
}
}
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " font-size:{$fontsize}; color:{$input_color}; {$fieldheight} font-family:inherit; {$attributestyle} ";
} else {
$inheritstyle = " color:{$input_color}; {$attributestyle} {$fieldheight} ";
}
$ct1 = substr_count((string)$fieldwidth, \'pt\');
$ct2 = substr_count((string)$fieldwidth, \'px\');
$size_css = "";
if ($ct1 == 0 && $ct2 == 0) {
$size_css = " width:{$fieldwidth}px; ";
} else {
$size_css = " width:{$fieldwidth}; ";
}
if (isset($bucket_node) && $bucket_node != "" && (int)$bucket_node->repeater->responsive == 1) {
$size_css = " width:60%; ";
}
$cal_args = explode(\'|\', $calendararguments);
$arg_list = \'\';
if ($cal_args[0] !== \'\') {
foreach ($cal_args as $args) {
$arg_list .= "cal{$name}." . $args . \';\';
}
}
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
if ($maxlength != \'\') {
$max = "maxlength=\"{$maxlength}\"";
} else {
$max = \'\';
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, (string)$field->type, \'\', \'\', $tablemode);
$element .= "
{$conditional_call_script}
";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$extraclassnames = "";
if (isset($field->extraclassname) && $field->extraclassname != "") {
$extraclassnames = $field->extraclassname;
}
if(isset($field->bucket) && $field->bucket != ""){
$extraclassnames .= " bucket-contained-field";
}
$element .= $this->create_table_mode_mobile_label($field,$tablemode);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$_optionsDate = new stdClass();
$_custom_options = isset($field->node->custom_options) ? (string)$field->node->custom_options : \'\';
if($_custom_options != \'\'){
if(substr($_custom_options, -1) != \',\'){
$_custom_options = $_custom_options . "," . PHP_EOL;
}
}
switch ((string)$field->node->type) {
case \'0\':
$master_format = "m/d/Y g:i a";
if (isset($field->node->_date->format) && isset($field->node->_time->format)) {
$master_format = (string)$field->node->_date->format . " " . (string)$field->node->_time->format;
(string)$field->node->_time->format = str_replace(\':s\', \'\', (string)$field->node->_time->format);
}
$defaultvalue = str_replace(\'m/d/Y\', $master_format, $defaultvalue);
$time_format = "g:i a";
if (isset($field->node->_time->format)) {
$time_format = $field->node->_time->format;
}
$date_format = "m/d/Y";
if (isset($field->node->_date->format)) {
$date_format = $field->node->_date->format;
}
$theme = "theme: \'default\'";
if ((string)$field->node->_datetime->theme == "Dark") {
$theme = "theme: \'dark\'";
}
$min_time = "";
if ((string)$field->node->_time->min_time != "") {
$min_time = "minTime: \'{$field->node->_time->min_time}\',";
}
$max_time = "";
if ((string)$field->node->_time->max_time != "") {
$max_time = "maxTime: \'{$field->node->_time->max_time}\',";
}
$min_date = "";
$min_date_php = "";
if ((string)$field->node->_date->min_date != "") {
if (DateTime::createFromFormat($field->node->_date->format, $field->node->_date->min_date)) {
$min_date = "minDate: \'{$field->node->_date->min_date}\',";
} else {
$op = substr_count((string)$field->node->_date->min_date, "-") != 0 ? "sub" : "add";
$raw_days = str_replace("-", "", $field->node->_date->min_date);
$raw_days = str_replace("+", "", $raw_days);
$min_date_php = <<<EOF
<?php
// Calculate Min Date.
\$date = date_create(date(DATE_RFC2822)); // Current Time.
date_{$op}(\$date, date_interval_create_from_date_string(\'{$raw_days} days\'));
\$min_date_php = date_format(\$date, \'{$field->node->_date->format}\');
?>
EOF;
$min_date = "minDate: \'<?php echo \$min_date_php; ?>\',";
}
}
$max_date = "";
$max_date_php = "";
if ((string)$field->node->_date->max_date != "") {
if (DateTime::createFromFormat($field->node->_date->format, $field->node->_date->max_date)) {
$max_date = "minDate: \'{$field->node->_date->max_date}\',";
} else {
$op = substr_count((string)$field->node->_date->max_date, "-") != 0 ? "sub" : "add";
$raw_days = str_replace("-", "", $field->node->_date->max_date);
$raw_days = str_replace("+", "", $raw_days);
$max_date_php = <<<EOF
<?php
// Calculate Min Date.
\$date = date_create(date(DATE_RFC2822)); // Current Time.
date_{$op}(\$date, date_interval_create_from_date_string(\'{$raw_days} days\'));
\$max_date_php = date_format(\$date, \'{$field->node->_date->format}\');
?>
EOF;
$max_date = "maxDate: \'<?php echo \$max_date_php; ?>\',";
}
}
$time_step = "30";
if (isset($field->node->_time->minute_increment)) {
$time_step = $field->node->_time->minute_increment;
}
$rules_target_js = "";
foreach($page->form->field as $f){
if(!isset($f->node->_date->rules->advanced)){
continue;
}
$a = $f->node->_date->rules->advanced;
$daysBefore = "0";
if((string)$f->node->_date->rules->advanced->target_before_delta_value != ""){
$daysBefore = (string)$f->node->_date->rules->advanced->target_before_delta_value;
};
if((string)$f->type == "datetime" && (string)$f->node->_date->rules->advanced->target_before == $name){
$rules_target_js .= "var _baseDateBefore = jQuery(\'#" . (string)$a->target_before . "\').datetimepicker(\'getValue\');
";
$rules_target_js .= "var _baseDateBeforeDelta = moment(_baseDateBefore, \'{$master_format}\').subtract({$daysBefore}, \'days\')._d;
";
$rules_target_js .= "jQuery(\'#" . (string)$f->name . "\').datetimepicker(\'setOptions\', {maxDate: _baseDateBeforeDelta});
";
}
$daysAfter= "0";
if((string)$f->node->_date->rules->advanced->target_after_delta_value != ""){
$daysAfter = (string)$f->node->_date->rules->advanced->target_after_delta_value;
};
if((string)$f->type == "datetime" && (string)$f->node->_date->rules->advanced->target_after == $name){
$rules_target_js .= "var _baseDateAfter = jQuery(\'#" . (string)$a->target_after . "\').datetimepicker(\'getValue\');
";
$rules_target_js .= "var _baseDateAfterDelta = moment(_baseDateAfter, \'{$master_format}\').add({$daysAfter}, \'days\')._d;
";
$rules_target_js .= "jQuery(\'#" . (string)$f->name . "\').datetimepicker(\'setOptions\', {minDate: _baseDateAfterDelta});
";
}
}
$show_time = isset($field->node->_time->show_time) ? $field->node->_time->show_time : \'true\';
if($show_time != \'true\'){
$master_format = $date_format;
}
$element .= <<<EOT
<input <?php echo \$enabled; ?>
class="{$extraclassnames}"
type="text"
name="{$name}"
id="{$id}"
value="<?php isset(\$_SESSION[\'{$name}\']) ? print htmlentities(\$_SESSION[\'{$name}\'], ENT_COMPAT, \'UTF-8\') : print {$defaultvalue}; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
{$min_date_php}
{$max_date_php}
<script type="text/javascript">
// https://xdsoft.net/jqplugins/datetimepicker/
jQuery(\'#{$id}\').datetimepicker({
// Custom User Options.
{$_custom_options}
validateOnBlur: true,
closeOnDateSelect: 1,
datepicker: true,
timepicker: ${show_time},
{$min_time}
{$max_time}
{$min_date}
{$max_date}
{$theme},
format: \'{$master_format}\',
formatTime: \'{$time_format}\',
formatDate: \'{$date_format}\',
step: {$time_step},
onChangeDateTime:function(dp,\$input){
// \$input.val()
},
onClose: function(dateText){
if (dateText != "") {
// Start / End Date Constraint Logic.
{$rules_target_js}
}
}
});
</script>
EOT;
break;
case \'1\':
$language = "en";
if (isset($field->node->_date->language)) {
$language = $field->node->_date->language;
}
$date_format = "mm/dd/yyyy";
if (isset($field->node->_date->format)) {
$date_format = $field->node->_date->format;
$defaultvalue = str_replace(\'m/d/Y\', $date_format, $defaultvalue);
$date_format = str_replace("d", "dd", $date_format);
$date_format = str_replace("j", "d", $date_format);
$date_format = str_replace("l", "DD", $date_format);
$date_format = str_replace("F", "MM", $date_format);
$date_format = str_replace("m", "mm", $date_format);
$date_format = str_replace("n", "m", $date_format);
$date_format = str_replace("y", "yy", $date_format);
$date_format = str_replace("Y", "yyyy", $date_format);
}
$default_view_date = "";
$date_node = $field->node->_date;
$start_date = isset($date_node->min_date) && $date_node->min_date != "" ? "startDate: \'{$date_node->min_date}\'," : \'\';
$end_date = isset($date_node->max_date) && $date_node->max_date != "" ? "endDate: \'{$date_node->max_date}\'," : \'\';
$rules_target_js = "";
foreach($page->form->field as $f){
if(!isset($f->node->_date->rules->advanced)){
continue;
}
$a = $f->node->_date->rules->advanced;
$daysBefore = "0";
if((string)$f->node->_date->rules->advanced->target_before_delta_value != ""){
$daysBefore = (string)$f->node->_date->rules->advanced->target_before_delta_value;
};
if((string)$f->type == "datetime" && (string)$f->node->_date->rules->advanced->target_before == $name){
$rules_target_js .= "var _baseDateBefore = jQuery(\'#" . (string)$a->target_before . "\').datepicker(\'getDate\');
";
$rules_target_js .= "var _baseDateBeforeDelta = moment(_baseDateBefore, \'{$date_format}\').subtract({$daysBefore}, \'days\')._d;
";
$rules_target_js .= "jQuery(\'#" . (string)$f->name . "\').datepicker(\'setEndDate\', _baseDateBeforeDelta);
";
}
$daysAfter= "0";
if((string)$f->node->_date->rules->advanced->target_after_delta_value != ""){
$daysAfter = (string)$f->node->_date->rules->advanced->target_after_delta_value;
};
if((string)$f->type == "datetime" && (string)$f->node->_date->rules->advanced->target_after == $name){
$rules_target_js .= "var _baseDateAfter = jQuery(\'#" . (string)$a->target_after . "\').datepicker(\'getDate\');
";
$rules_target_js .= "var _baseDateAfterDelta = moment(_baseDateAfter, \'{$date_format}\').add({$daysAfter}, \'days\')._d;
";
$rules_target_js .= "jQuery(\'#" . (string)$f->name . "\').datepicker(\'setStartDate\', _baseDateAfterDelta);
";
}
}
$element .= <<<EOT
<input <?php echo \$enabled; ?>
class="{$extraclassnames}"
type="text"
name="{$name}"
id="{$id}"
value="<?php isset(\$_SESSION[\'{$name}\']) ? print htmlentities(\$_SESSION[\'{$name}\'], ENT_COMPAT, \'UTF-8\') : print {$defaultvalue}; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
<script type="text/javascript">
jQuery(function() {
jQuery("#{$id}").datepicker({
// Custom User Options.
{$_custom_options}
language: \'{$language}\',
\'format\': \'{$date_format}\',
\'autoclose\': true,
{$default_view_date}
{$start_date}
{$end_date}
todayBtn: true,
todayHighlight: true,
})
// https://bootstrap-datepicker.readthedocs.io/en/latest/events.html#
.on(\'hide\', function(e) { // `e` here contains the extra attributes
{$rules_target_js} // Start / End Date Constraint Logic.
})
.on(\'show\', function(e) { // `e` here contains the extra attributes
});
});
function setDefaultDate_{$id}(){
if(document.querySelector("#{$id}").value == "CURRENT_DATE"){
var today = new Date();
var frmt = today.format(\'{$date_format}\');
document.querySelector("#{$id}").value = frmt;
}
}
setDefaultDate_{$id}();
</script>
EOT;
break;
case \'2\':
$time_format = "g:i a";
$min_time = "";
if ((string)$field->node->_time->min_time != "") {
$min_time = "minTime: \'{$field->node->_time->min_time}\',";
}
$max_time = "";
if ((string)$field->node->_time->max_time != "") {
$max_time = "maxTime: \'{$field->node->_time->max_time}\',";
}
if (isset($field->node->_time->format)) {
$time_format = $field->node->_time->format;
}
$defaultvalue = str_replace(\'m/d/Y\', $time_format, $defaultvalue);
$timestep_value = $field->node->_datepair->time_step;
if ($field->node->_time->minute_increment != "Custom") {
$timestep_value = $field->node->_time->minute_increment;
}
$timestep = <<<EOF
\'step\': function(i) {
return {$timestep_value};
}
EOF;
$scroll_default = "";
if (isset($field->node->_time->use_current_time_as_default) && $field->node->_time->use_current_time_as_default == "1") {
$scroll_default = "\'scrollDefault\': \'now\',";
}
$element .= <<<EOT
<input <?php echo \$enabled; ?>
class="{$extraclassnames}"
type="text"
name="{$name}"
id="{$id}"
value="<?php isset(\$_SESSION[\'{$name}\']) ? print htmlentities(\$_SESSION[\'{$name}\'], ENT_COMPAT, \'UTF-8\') : print {$defaultvalue}; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
<script type="text/javascript">
//$(function() {
// $(\'#{$id}\').timepicker({ \'step\': 15, \'timeFormat\': \'{$time_format}\' });
//});
// https://www.jonthornton.com/jquery-timepicker/
// https://github.com/jonthornton/jquery-timepicker#timepicker-plugin-for-jquery
jQuery(function() {
jQuery(\'#{$id}\').timepicker({
// Custom User Options.
{$_custom_options}
\'showDuration\': true,
\'timeFormat\': \'{$time_format}\',
{$scroll_default}
{$timestep}
{$min_time}
{$max_time}
});
});
</script>
EOT;
break;
case \'3\':
$timestep_value = $field->node->_datepair->time_step;
if ($field->node->_datepair->time_step == "Custom") {
$timestep_value = $field->node->_datepair->time_step_custom;
}
$timestep = <<<EOF
\'step\': function(i) {
return {$timestep_value};
}
EOF;
$date_format = $field->node->_datepair->date_format;
if ($field->node->_datepair->date_format == "Custom") {
$date_format = $field->node->_datepair->date_format_custom;
}
$time_format = $field->node->_datepair->time_format;
if ($field->node->_datepair->time_format == "Custom") {
$time_format = $field->node->_datepair->time_format_custom;
}
$default_view_date = "";
if ($field->node->_datepair->default_date != "") {
$v = explode("/", (string)$field->node->_datepair->default_date);
$date_object = "{year:{$v[2]}, month:{$v[1]}, day:{$v[0]}}";
$default_view_date = "\'defaultViewDate\': {$date_object},";
}
$scroll_default = "";
if ($field->node->_datepair->default_time == "now") {
$scroll_default = "\'scrollDefault\': \'now\',";
}
if ($field->node->_datepair->default_time != "") {
$timestep = "";
}
$start_date = "";
if ($field->node->_datepair->min_date != "") {
$start_date = "\'startDate\': \'{$field->node->_datepair->min_date}\',";
}
$end_date = "";
if ($field->node->_datepair->max_date != "") {
$end_date = "\'endDate\': \'{$field->node->_datepair->max_date}\',";
}
$min_time = "";
if ($field->node->_datepair->min_time != "") {
$min_time = "minTime: \'{$field->node->_datepair->min_time}\',";
}
$max_time = "";
if ($field->node->_datepair->min_time != "") {
$max_time = "maxTime: \'{$field->node->_datepair->max_time}\',";
}
$default_date_delta = 1;
if ($field->node->_datepair->default_date_delta != "") {
$default_date_delta = $field->node->_datepair->default_date_delta;
}
$default_time_delta = 7200000;
if ($field->node->_datepair->default_time_delta != "") {
$default_time_delta = $field->node->_datepair->default_time_delta * 60000;
}
$field_size = 10;
if ((string)$field->node->_datepair->mode == "Date+Time") {
$element .= <<<EOT
<div id="{$name}_datepair_wrapper">
<input type="hidden" name="{$name}" value="01/01/2001" />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} date start"
size="{$field_size}"
type="text"
name="{$name}_date_start"
id="{$id}_date_start"
value="<?php isset(\$_SESSION[\'{$name}_date_start\']) ? print htmlentities(\$_SESSION[\'{$name}_date_start\'], ENT_COMPAT, \'UTF-8\') : print {$defaultvalue}; ?>"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} time start"
size="{$field_size}"
type="text"
name="{$name}_time_start"
id="{$id}_time_start"
value="<?php isset(\$_SESSION[\'{$name}_time_start\']) ? print htmlentities(\$_SESSION[\'{$name}_time_start\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<span>to</span>
<input <?php echo \$enabled; ?>
class="{$extraclassnames} time end"
size="{$field_size}"
type="text"
name="{$name}_time_end"
id="{$id}_time_end"
value="<?php isset(\$_SESSION[\'{$name}_time_end\']) ? print htmlentities(\$_SESSION[\'{$name}_time_end\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} date end"
size="{$field_size}"
type="text"
name="{$name}_date_end"
id="{$id}_date_end"
value="<?php isset(\$_SESSION[\'{$name}_date_end\']) ? print htmlentities(\$_SESSION[\'{$name}_date_end\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle}" {$attribute} {$enabled} {$readonly} />
</div>
<script>
// initialize input widgets first
jQuery(\'#{$name}_datepair_wrapper .time\').timepicker({
// Custom User Options.
{$_custom_options}
\'showDuration\': true,
\'timeFormat\': \'{$time_format}\',
{$scroll_default}
{$timestep}
{$min_time}
{$max_time}
});
jQuery(\'#{$name}_datepair_wrapper .date\').datepicker({
// Custom User Options.
{$_custom_options}
\'format\': \'{$date_format}\',
\'autoclose\': true,
{$default_view_date}
{$start_date}
{$end_date}
}).on("hide", function(e) {
// `e` here contains the extra attributes
// Focus/Blur Target Element To Force Validation.
e.delegateTarget.focus();
e.delegateTarget.blur();
});
// Initialize Date Pair
var {$name}_datepair_wrapperEl = document.getElementById(\'{$name}_datepair_wrapper\');
var datepair_{$name} = new Datepair({$name}_datepair_wrapperEl, {
\'defaultDateDelta\': {$default_date_delta}, // days
\'defaultTimeDelta\': {$default_time_delta} // milliseconds
});
</script>
EOT;
}
if ((string)$field->node->_datepair->mode == "Date Only") {
$element .= <<<EOT
<div id="{$name}_datepair_wrapper">
<input type="hidden" name="{$name}" value="01/01/2001" />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} date start"
type="text"
name="{$name}_date_start"
id="{$id}_date_start"
value="<?php isset(\$_SESSION[\'{$name}_date_start\']) ? print htmlentities(\$_SESSION[\'{$name}_date_start\'], ENT_COMPAT, \'UTF-8\') : print {$defaultvalue}; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
<span>to</span>
<input <?php echo \$enabled; ?>
class="{$extraclassnames} date end"
type="text"
name="{$name}_date_end"
id="{$id}_date_end"
value="<?php isset(\$_SESSION[\'{$name}_date_end\']) ? print htmlentities(\$_SESSION[\'{$name}_date_end\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
</div>
<script>
jQuery(\'#{$name}_datepair_wrapper .date\').datepicker({
// Custom User Options.
{$_custom_options}
\'format\': \'{$date_format}\',
\'autoclose\': true,
{$default_view_date}
{$start_date}
{$end_date}
}).on("hide", function(e) {
// `e` here contains the extra attributes
// Focus/Blur Target Element To Force Validation.
e.delegateTarget.focus();
e.delegateTarget.blur();
}).on("show", function(e){
});
// Initialize Date Pair
var {$name}_datepair_wrapperEl = document.getElementById(\'{$name}_datepair_wrapper\');
var datepair_{$name} = new Datepair({$name}_datepair_wrapperEl, {
\'defaultDateDelta\': {$default_date_delta}, // days
\'defaultTimeDelta\': {$default_time_delta} // milliseconds
});
</script>
EOT;
}
if ((string)$field->node->_datepair->mode == "Time Only") {
$element .= <<<EOT
<div id="{$name}_datepair_wrapper">
<input type="hidden" name="{$name}" value="01/01/2001" />
<input <?php echo \$enabled; ?>
class="{$extraclassnames} time start"
type="text"
name="{$name}_time_start"
id="{$id}_time_start"
value="<?php isset(\$_SESSION[\'{$name}_time_start\']) ? print htmlentities(\$_SESSION[\'{$name}_time_start\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
<span>to</span>
<input <?php echo \$enabled; ?>
class="{$extraclassnames} time end"
type="text"
name="{$name}_time_end"
id="{$id}_time_end"
value="<?php isset(\$_SESSION[\'{$name}_time_end\']) ? print htmlentities(\$_SESSION[\'{$name}_time_end\'], ENT_COMPAT, \'UTF-8\') : print \'\'; ?>"
style="{$inheritstyle} {$size_css}" {$attribute} {$enabled} {$readonly} />
</div>
<script>
// initialize input widgets first
jQuery(\'#{$name}_datepair_wrapper .time\').timepicker({
// Custom User Options.
{$_custom_options}
\'showDuration\': true,
\'timeFormat\': \'{$time_format}\',
{$scroll_default}
{$timestep}
{$min_time}
{$max_time}
});
// Initialize Date Pair
var {$name}_datepair_wrapperEl = document.getElementById(\'{$name}_datepair_wrapper\');
var datepair_{$name} = new Datepair({$name}_datepair_wrapperEl, {
\'defaultDateDelta\': {$default_date_delta}, // days
\'defaultTimeDelta\': {$default_time_delta} // milliseconds
});
</script>
EOT;
}
break;
}
if ($helper != \'\') {
$element .= "<br/><div class=\"helper\" style=\"color:{$helpercolor};\">{$helper}</div>";
} else {
$element .= "<br />";
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
$element .= "
<div class=\"fbtooltip-{$id} fbtooltip\" style=\"display:none;\"></div>
";
return $element;
}
public function create_datagrid($field, $page, $bucket_node = "")
{
$name = $field->name;
$label = $field->label;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$inheritstyle = $field->inheritstyle;
$style = $field->style;
$styles = $this->translateFieldStyles($style);
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$grid = $field->grid_properties;
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
$fieldwidth = "";
$fieldheight = "";
$attributestyle = "";
$test = (int)$inheritstyle;
if ($test != 1) {
$inheritstyle = 0;
}
if ($inheritstyle == 1) {
$inheritstyle = " style=\"font-size:{$fontsize}; color:{$input_color}; font-family:inherit; width:{$grid->field_width}px; height:{$fieldheight}px; {$attributestyle} \" ";
} else {
$inheritstyle = " style=\" color:{$input_color}; width:{$grid->field_width}px; height:{$fieldheight}px; {$attributestyle} \" ";
}
$tablemode = $page->tablemode;
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
$element = "";
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, 0, $required_text, $color, $fontsize, $styles, $label, 0, (string)$field->type, \'\', \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$event_code = \'\';
if (isset($grid->js_event_code) && $grid->js_event_code != \'\') {
$event_code = $grid->js_event_code;
}
$field_types = array(
0 => "<input type=\"text\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
1 => "<input type=\"password\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
2 => "<textarea name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code}>__DEFAULT_VALUE__</textarea>",
3 => "<input type=\"date\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
4 => "<input type=\"date\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
5 => "<select class=\"form-control\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code}>__DEFAULT_VALUE__</select>",
6 => "<input type=\"radio\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_``SUBINDEX``\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" _CHECKED_ /><label style=\"\" for=\"{$field->id}__INDEX_``SUBINDEX``\">__DEFAULT_VALUE__</label>",
7 => "<input type=\"checkbox\" value=\"_CHECKBOX_VALUE_\" name=\"{$field->name}__INDEX_[]\" id=\"{$field->id}__INDEX_``SUBINDEX``\" _TAB-INDEX_ {$inheritstyle} {$event_code} _CHECKED_ /><label style=\"\" for=\"{$field->id}__INDEX_``SUBINDEX``\">__DEFAULT_VALUE__</label>",
8 => "<input type=\"number\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
9 => "<input type=\"color\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
10 => "<input type=\"date\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
11 => "<input type=\"email\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
12 => "<input type=\"telephone\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
13 => "<input type=\"time\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />",
14 => "<input type=\"url\" name=\"{$field->name}__INDEX_\" id=\"{$field->id}__INDEX_\" _TAB-INDEX_ {$inheritstyle} {$event_code} value=\"__DEFAULT_VALUE__\" />"
);
$field_types[3] = <<<EOF
<script type="text/javascript">
// American Calendar Field.
var cal{$field->name}__INDEX_ = new CalendarPopup("cal-div-{$field->name}__INDEX_");
cal{$field->name}__INDEX_.setCssPrefix(\'FB-CAL\');
cal{$field->name}__INDEX_.setReturnFunction("setMultipleValues_{$field->name}__INDEX_");
function setMultipleValues_{$field->name}__INDEX_(y,m,d) {
document.getElementById(\'date-{$field->id}__INDEX_-1\').value=LZ(m) + \'/\' + LZ(d) + \'/\' + y;
validators[\'date-{$field->id}__INDEX_-1\'].check();
// Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$field->id}__INDEX_-1\').focus();
// Custom Callback Code.
var date = new Date(Date.UTC(y,m-1,d,0,0,0));
var s_ts = date.getTime()/1000;
var c_ts = Math.round(new Date().getTime()/1000);
}
</script>
<span id="cal-div-{$field->name}__INDEX_"
style="position: absolute; visibility: hidden; background-color: white; z-index:1001;">
</span>
<input type="text" name="{$field->name}__INDEX_" class="datagrid-column-calendar"
id="date-{$field->id}__INDEX_-1" {$tabhtml} _TAB-INDEX_ {$inheritstyle} {$event_code}
value="__DEFAULT_VALUE__" />
<a id="cal-anchor-{$field->name}__INDEX_"
name="cal-anchor-{$field->name}__INDEX_" href="#"
onclick="cal{$field->name}__INDEX_.showCalendar(\'cal-anchor-{$field->name}__INDEX_\'); return false;" >
<img style="margin-left:5px; margin-bottom:-7px;"
alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png"
border="0" />
</a>
EOF;
$field_types[4] = <<<EOF
<script type="text/javascript">
// European Calendar Field.
var cal{$field->name}__INDEX_ = new CalendarPopup("cal-div-{$field->name}__INDEX_");
cal{$field->name}__INDEX_.setCssPrefix(\'FB-CAL\');
cal{$field->name}__INDEX_.setReturnFunction("setMultipleValues_{$field->name}__INDEX_");
function setMultipleValues_{$field->name}__INDEX_(y,m,d) {
document.getElementById(\'date-{$field->id}__INDEX_-1\').value=LZ(d) + \'/\' + LZ(m) + \'/\' + y;
validators[\'date-{$field->id}__INDEX_-1\'].check();
// Focus field, allows us to bind events to this value changing.
document.getElementById(\'date-{$field->id}__INDEX_-1\').focus();
// Custom Callback Code.
var date = new Date(Date.UTC(y,m-1,d,0,0,0));
var s_ts = date.getTime()/1000;
var c_ts = Math.round(new Date().getTime()/1000);
}
</script>
<span id="cal-div-{$field->name}__INDEX_"
style="position: absolute; visibility: hidden; background-color: white; z-index:1001;">
</span>
<input type="text" name="{$field->name}__INDEX_" class="datagrid-column-calendar"
id="date-{$field->id}__INDEX_-1" {$tabhtml} _TAB-INDEX_ {$inheritstyle} {$event_code}
value="__DEFAULT_VALUE__" />
<a id="cal-anchor-{$field->name}__INDEX_"
name="cal-anchor-{$field->name}__INDEX_" href="#"
onclick="cal{$field->name}__INDEX_.showCalendar(\'cal-anchor-{$field->name}__INDEX_\'); return false;" >
<img style="margin-left:5px; margin-bottom:-7px;"
alt="Date Picker" src="<?php echo \$_SESSION[\'MAX_PATH\']; ?>calendar/cal-0.png"
border="0" />
</a>
EOF;
$field_item = $field_types[(int)$field->grid_properties->fieldtype];
$element .= "<table class=\"datagrid\" id=\"{$field->name}\" width=\"{$grid->width}\" border=\"{$grid->border}\" cellpadding=\"{$grid->cellpadding}\" cellspacing=\"{$grid->cellspacing}\" >";
$rows = (int)$grid->rows;
$columns = (int)$grid->columns;
$element .= "<tr>";
$element .= "<th style=\"width:{$grid->row_column_width}px; \" align=\"left\" id=\"\"></th>";
for ($i = 0; $i < $columns; $i++) {
$element .= "<th style=\"background-color:{$grid->column_background_color}; color:{$grid->datagrid_column_color}; vertical-align: bottom; font-weight:{$grid->column_font_weight};\" align=\"{$grid->column_alignment}\" >" . $grid->grid_headers->columns[$i] . "</th>";
}
$element .= "</tr>";
$_itemCount = 0;
for ($i = 0; $i < $rows; $i++) {
$element .= "<tr>";
$row_style = " font-weight:{$grid->row_font_weight}; color:{$grid->datagrid_row_color}; ";
if ((int)$grid->alternate_lines == 1 && $i % 2 != 0) {
$row_style .= " background-color:" . $grid->alternate_line_color . "; ";
}
$subhead_text = $grid->grid_headers->rows[$i];
$is_subhead = false;
if (preg_match(\'/\|\|.+/\', $grid->grid_headers->rows[$i]) != 0) {
$is_subhead = true;
$new_text = str_replace(\'||\', \'\', $grid->grid_headers->rows[$i]);
$subhead_text = $new_text;
}
$element .= "<td style=\"{$row_style}\" id=\"{$field->name}-row-label-{$i}\" class=\"datagrid-row-label\" align=\"{$grid->row_alignment}\" >" . $subhead_text . "</td>";
for ($j = 0; $j < $columns; $j++) {
$has_override = false;
if (isset($grid->grid_headers->column_type[$j]) && (string)$grid->grid_headers->column_type[$j] != \'\') {
$has_override = true;
$field_item_override = $field_types[(int)$grid->grid_headers->column_type[$j]];
}
if ($has_override) {
$field_item_copy = $field_item_override;
} else {
$field_item_copy = $field_item;
}
$has_default_value_var = false;
if (isset($grid->grid_headers->default_values[$j]) && (string)$grid->grid_headers->default_values[$j] != \'\' && (string)$grid->grid_headers->default_values[$j] != \'No Value\') {
$has_default_value_var = true;
$options_html = \'\';
switch ((int)$grid->grid_headers->column_type[$j]) {
case 0:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'{$default_static_value}\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 1:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'{$default_static_value}\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 2:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'{$default_static_value}\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 3:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'{$default_static_value}\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 4:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'{$default_static_value}\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 5:
$options = explode(\'|\', (string)$grid->grid_headers->default_values[$j]);
foreach ($options as $opt) {
$selected_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) && \$_SESSION[\'{$field->name}__INDEX_\'] == \'{$opt}\' ? print \'selected=\"selected\"\' : \'\'; ?>";
$options_html .= "<option value=\"{$opt}\" {$selected_value}>{$opt}</option>";
}
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $options_html, $field_item_copy);
break;
case 6:
$options = explode(\'|\', (string)$grid->grid_headers->default_values[$j]);
$new_value = \'\';
foreach ($options as $idx => $opt) {
$field_item_tmp = $field_item_copy;
$checked = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) && \$_SESSION[\'{$field->name}__INDEX_\'] == \'{$opt}\' ? print \' checked=\"checked\" \' : \'\'; ?>";
$field_item_tmp = str_replace(\'_CHECKED_\', $checked, $field_item_tmp);
$field_item_tmp = str_replace(\'``SUBINDEX``\', \'_\' . $idx, $field_item_tmp);
$field_item_tmp = str_replace(\'__DEFAULT_VALUE__\', $opt, $field_item_tmp);
$new_value .= $field_item_tmp;
}
$field_item_copy = $new_value;
break;
case 7:
$options = explode(\'|\', (string)$grid->grid_headers->default_values[$j]);
$new_value = \'\';
foreach ($options as $idx => $opt) {
$field_item_tmp = $field_item_copy;
$checked = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) && in_array(\'{$opt}\', \$_SESSION[\'{$field->name}__INDEX_\']) ? print \' checked=\"checked\" \' : \'\'; ?>";
$field_item_tmp = str_replace(\'_CHECKED_\', $checked, $field_item_tmp);
$field_item_tmp = str_replace(\'``SUBINDEX``\', \'_\' . $idx, $field_item_tmp);
$field_item_tmp = str_replace(\'__DEFAULT_VALUE__\', $opt, $field_item_tmp);
$field_item_tmp = str_replace(\'_CHECKBOX_VALUE_\', $opt, $field_item_tmp);
$new_value .= $field_item_tmp;
}
$field_item_copy = $new_value;
break;
default:
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', (string)$grid->grid_headers->default_values[$j], $field_item_copy);
}
} else {
switch ((int)$grid->grid_headers->column_type[$j]) {
case 6:
$options = explode(\'|\', (string)$grid->grid_headers->default_values[$j]);
$field_item_tmp = $field_item_copy;
if (count($options) == 1 && $options[0] == \'No Value\') {
$field_item_tmp = str_replace(\'``SUBINDEX``\', \'_\' . \'0\', $field_item_tmp);
$field_item_tmp = str_replace(\'__DEFAULT_VALUE__\', \'\', $field_item_tmp);
$field_item_copy = $field_item_tmp;
}
break;
case 7:
$options = explode(\'|\', (string)$grid->grid_headers->default_values[$j]);
$field_item_tmp = $field_item_copy;
if (count($options) == 1 && $options[0] == \'No Value\') {
$field_item_tmp = str_replace(\'``SUBINDEX``\', \'_\' . \'0\', $field_item_tmp);
$field_item_tmp = str_replace(\'__DEFAULT_VALUE__\', \'\', $field_item_tmp);
$field_item_tmp = str_replace(\'_CHECKBOX_VALUE_\', \'1\', $field_item_tmp);
$field_item_copy = $field_item_tmp;
}
break;
}
}
if (isset($field->grid_properties->database_defaults) && is_array((array)$field->grid_properties->database_defaults)) {
$_val = $field->grid_properties->database_defaults[$_itemCount];
switch ((int)$grid->grid_headers->column_type[$j]) {
case 0:
$default_value = "<?php isset(\$pop[0][\'{$_val}\']) ? print \$pop[0][\'{$_val}\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 1:
$default_value = "<?php isset(\$pop[0][\'{$_val}\']) ? print \$pop[0][\'{$_val}\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 2:
$default_value = "<?php isset(\$pop[0][\'{$_val}\']) ? print \$pop[0][\'{$_val}\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 3:
$default_value = "<?php isset(\$pop[0][\'{$_val}\']) ? print \$pop[0][\'{$_val}\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 4:
$default_value = "<?php isset(\$pop[0][\'{$_val}\']) ? print \$pop[0][\'{$_val}\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
default:
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', \'\', $field_item_copy);
}
}
if (!$has_default_value_var) {
switch ((int)$grid->grid_headers->column_type[$j]) {
case 0:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 1:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 2:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 3:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
case 4:
$default_static_value = (string)$grid->grid_headers->default_values[$j];
$default_value = "<?php isset(\$_SESSION[\'{$field->name}__INDEX_\']) ? print \$_SESSION[\'{$field->name}__INDEX_\'] : \'\'; ?>";
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', $default_value, $field_item_copy);
break;
default:
$field_item_copy = str_replace(\'__DEFAULT_VALUE__\', \'\', $field_item_copy);
}
}
$field_item_copy = str_replace(\'_INDEX_\', $i . \'_\' . $j, $field_item_copy);
if ($tabhtml != \'\') {
$field_item_copy = str_replace(\'_TAB-INDEX_\', $tabhtml, $field_item_copy);
} else {
$field_item_copy = str_replace(\'_TAB-INDEX_\', \'\', $field_item_copy);
}
if ($is_subhead) {
$element .= "<td style=\"{$row_style}\" align=\"{$grid->column_alignment}\" ></td>";
} else {
$element .= "<td style=\"{$row_style}\" align=\"{$grid->column_alignment}\" >" . $field_item_copy . "</td>";
}
$_itemCount++;
}
$element .= "</tr>";
}
$element .= "</table>";
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_survey($field, $page, $jobname, $bucket_node = "")
{
if (isset($field->survey_properties->use_dynamic_generation) && $field->survey_properties->use_dynamic_generation == "0") {
$json = new stdClass();
$json->field = $field->asXML();
$json->page = $page->asXML();
$json->jobname = $jobname->asXML();
$json->bucket_node = $bucket_node;
$raw_data = chunk_split(base64_encode(json_encode($json)));
$ret = <<<EOF
<?php
// Raw Survey Field Data.
\$debug_raw_survey_logic = false;
\$debug_raw_html = false;
\$data = json_decode(base64_decode(\'{$raw_data}\'), false);
if(\$debug_raw_survey_logic) {
echo \'<pre>RAW SURVEY CREATE CODE:<br/>\';
var_dump(\$data);
echo \'<pre>\';
}
// Generate Dynamic Code.
\$_field = new SimpleXMLElement(\$data->field);
\$_page = new SimpleXMLElement(\$data->page);
\$_jobname = new SimpleXMLElement(\$data->jobname);
\$dynamic_html = create_dynamic_survey(\$_field, \$_page, \$_jobname, \$data->bucket_node);
if(\$debug_raw_html) {
echo \'<pre>RAW HTML:\';
echo \$dynamic_html;
echo \'</pre>\';
}
// Generate Temp File and Include.
// Needed to Parse Dynamic PHP.
\$tmpfname = tempnam("/tmp", "FOO");
\$handle = fopen(\$tmpfname, "w");
fwrite(\$handle, \$dynamic_html);
fclose(\$handle);
include \$tmpfname;
unlink(\$tmpfname);
?>
EOF;
return $ret;
}
$name = $field->name;
$label = $field->label;
$color = $field->color;
$input_color = $field->input_color;
$fontsize = $field->fontsize;
$inheritstyle = $field->inheritstyle;
$style = $field->style;
$styles = $this->translateFieldStyles($style);
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$survey = $field->survey_properties;
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if (!isset($survey->question_font_size) || $survey->question_font_size == "") {
$survey->question_font_size = "10pt;";
}
$ct1 = substr_count((string)$survey->question_font_size, \'pt\');
$ct2 = substr_count((string)$survey->question_font_size, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$survey->question_font_size = $survey->question_font_size . \'pt\';
}
if (!isset($survey->response_font_size) || $survey->response_font_size == "") {
$survey->response_font_size = "10pt;";
}
$ct1 = substr_count((string)$survey->response_font_size, \'pt\');
$ct2 = substr_count((string)$survey->response_font_size, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$survey->response_font_size = $survey->response_font_size . \'pt\';
}
if (!isset($survey->custom_event_callback) || $survey->custom_event_callback == "") {
$survey->custom_event_callback = "";
}
$tablemode = $page->tablemode;
$tablemodespan = false;
if (!isset($style->tablemodespan)) {
$tablemodespan = false;
} else {
if ((int)$style->tablemodespan == 0) {
$tablemodespan = true;
}
}
$element = "";
if ((int)$tablemode->leftcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$element .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$fixed_width}px; margin-right:8px; padding-top:3px; float:left; text-align:{$align}\" >";
}
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$element .= $this->_helper_field_label($field, $name, 0, $required_text, $color, $fontsize, $styles, $label, 0, (string)$field->type, \'\', \'\', $tablemode);
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$bottom_margin_value = intval($tablemode->marginbottom);
$element .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px; \" >";
}
$custom_event = "";
if ((string)$survey->custom_event_callback != "") {
$custom_event = $survey->custom_event_callback;
}
$event_trigger_code = "";
$event_trigger_inline = "";
if ((string)$survey->triggercode != "") {
$event_trigger_code = <<<EOF
<script type="text/javascript">
// field value, calling field id, trigger field id
function processTrigger_{$field->id}__ID_(event, value, calling_field_id, trigger_field_id){
var index = _TRIGGER_INDEX_;
var col2 = \'_TRIGGER_COL2_\';
if({$survey->triggercode}) {
//document.getElementById(\'fb_fld-\' + trigger_field_id).style.display = "table-row";
fbc.show(trigger_field_id, event, \'fade\');
document.getElementById(\'{$field->id}__ID_\' + \'_triggerField\').disabled = false; // enable
} else {
//document.getElementById(\'fb_fld-\' + trigger_field_id).style.display = "none";
fbc.hide(trigger_field_id, event, \'fade\');
document.getElementById(\'{$field->id}__ID_\' + \'_triggerField\').disabled = true; // disable
}
}
// Populate on page load.
var value = \'\';
for(var i = 0; i < 20; i++){
if(document.getElementById(\'{$field->id}__ID_\' + \'_\' + i)) {
if(document.getElementById(\'{$field->id}__ID_\' + \'_\' + i).checked){
value = document.getElementById(\'{$field->id}__ID_\' + \'_\' + i).value;
break;
}
}
}
var index = _TRIGGER_INDEX_;
var col2 = \'_TRIGGER_COL2_\';
if(value != \'\' && {$survey->triggercode}) {
document.getElementById(\'fb_fld-\' + \'{$field->id}__ID_\' + \'_trigger\').style.display = "table-row"; // show
document.getElementById(\'{$field->id}__ID_\' + \'_triggerField\').disabled = false; // enable
} else {
document.getElementById(\'fb_fld-\' + \'{$field->id}__ID_\' + \'_trigger\').style.display = "none";
document.getElementById(\'{$field->id}__ID_\' + \'_triggerField\').disabled = true; // disable
}
</script>
EOF;
$event_trigger_inline = "processTrigger_{$field->id}__TRIGGER_ROW_(event, this.value, \'{$field->id}__ID_\', \'{$field->id}__TRIGGER_ROW__trigger\');";
}
$event_code = "";
if ($event_trigger_inline != "" || $custom_event != "") {
switch ((int)$field->grid_properties->fieldtype) {
case 0:
$event_code = "onclick=\"{$custom_event} {$event_trigger_inline}\"";
break;
}
}
switch ((int)$field->grid_properties->fieldtype) {
case 0:
$field_item = "<input class=\"survey-response-input-field\" {$event_code} type=\"radio\" name=\"{$field->name}__NAME_\" id=\"{$field->id}__ID_\" value=\"_DYNAMIC_VALUE_\" _TAB-INDEX_ ";
$field_item .= "
<?php if(isset(\$_SESSION[\'{$field->name}__NAME_\']) && \$_SESSION[\'{$field->name}__NAME_\'] == \"_DYNAMIC_VALUE_\") { echo \"checked=\'checked\'\"; } ?>";
$field_item .= "
/>
";
break;
}
if (defined(\'MOBILE_MODE\')) {
$survey->width = "100%";
}
$element .= "
<table class=\"survey\" id=\"{$field->name}\" width=\"{$survey->width}\" border=\"{$survey->border}\" cellpadding=\"{$survey->cellpadding}\" cellspacing=\"{$survey->cellspacing}\" >
";
$responses = explode("
", $survey->responses);
$label_class_code = "";
if (isset($field->survey_properties->labelclasscode) && $field->survey_properties->labelclasscode != "") {
$label_class_code = $field->survey_properties->labelclasscode;
}
if (isset($survey->questions_query) && $survey->questions_query != "") {
$questions = array();
$col2 = array();
$dbdsn = "";
if (isset($field->dbhost) && (string)$field->dbhost != "") {
$db_type = (string)$field->sourcetype;
$db_host = $this->uv->replace_all((string)$field->dbhost, 8);
$mysql_socket = $this->uv->replace_all((string)$field->dbsocket, 8);
$mysql_port = $this->uv->replace_all((string)$field->dbport, 8);
$dbdsn = $this->uv->replace_all((string)$field->dbdsn, 8);
$db_user = $this->uv->replace_all((string)$field->dbuser, 8);
$db_pass = $this->uv->replace_all((string)$field->dbpwd, 8);
$db_catalog = $this->uv->replace_all((string)$field->dbschema, 8);
} else {
$db_type = DB_TYPE;
$db_host = DB_HOST;
$db_catalog = DB_CATALOG;
$db_user = DB_USER;
$db_pass = DB_PASS;
$mysql_socket = MYSQL_SOCKET;
$mysql_port = MYSQL_PORT;
}
$questions_query = isset($survey->questions_query) ? urldecode((string)$survey->questions_query) : \'\';
$dbconnector = isset($field->dbconnector) ? urldecode((string)$field->dbconnector) : \'\';
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
if ($dbconnector != "") {
if (file_exists("../../output/forms/{$jobname}/{$dbconnector}")) {
include "../../output/forms/{$jobname}/{$dbconnector}";
}
}
$params = array();
$result = Database::oneoff_flexible_query(
$db_type,
$db_host,
$db_catalog,
$db_user,
$db_pass,
$mysql_socket,
$mysql_port,
$dbdsn,
$questions_query,
$params,
0,
0,
1
);
if ($result != false) {
foreach ($result[1] as $idx => $q) {
$questions[] = $q[\'QuestionText\'];
if (isset($q[\'col2\'])) {
$col2[] = $q[\'col2\'];
}
}
}
} else {
$questions = explode("
", $survey->questions);
}
$element .= "
<tr class=\"survey-header-row\">";
$element .= "
<th class=\"survey-question-no-data\" style=\"width:{$survey->question_column_width}px; \" align=\"left\" id=\"\"></th>";
for ($i = 0; $i < count($responses); $i++) {
$element .= "
<th class=\"survey-response-header\" style=\"background-color:{$survey->header_background_color}; color:{$survey->survey_response_color}; vertical-align: bottom; font-weight:{$survey->response_font_weight}; font-size:{$survey->response_font_size};\" align=\"{$survey->response_alignment}\" >" . $responses[$i] . "</th>";
}
$element .= "
</tr>
";
for ($i = 0; $i < count($questions); $i++) {
$element .= "
<tr class=\"survey-response-row\">
";
$question_style = " font-weight:{$survey->question_font_weight}; font-size:{$survey->question_font_size}; color:{$survey->survey_question_color}; ";
if ((int)$survey->alternate_lines == 1 && $i % 2 != 0) {
$question_style .= " background-color:" . $survey->alternate_line_color . "; ";
}
$question_number = "";
if (isset($survey->number_questions) && (int)$survey->number_questions == 1) {
if ((string)$survey->number_questions_template != "") {
$question_number = str_replace(\'{n}\', $i + 1, (string)$survey->number_questions_template);
} else {
$question_number = $i . \'1\' . ". ";
}
}
$element .= "
<td class=\"survey-question-text\" style=\"{$question_style}\" id=\"{$field->name}-row-label-{$i}\" class=\"survey-row-label\" align=\"{$survey->question_alignment}\">";
$element .= $question_number . "
<span class=\"survey-question\">" . $questions[$i] . "</span>
" . " </td>
";
for ($j = 0; $j < count($responses); $j++) {
$field_item_copy = $field_item;
$field_item_copy = str_replace(\'_NAME_\', $i, $field_item_copy);
$field_item_copy = str_replace(\'_ID_\', $i . \'_\' . $j, $field_item_copy);
$field_item_copy = str_replace(\'_TRIGGER_ROW_\', $i, $field_item_copy);
$event_trigger_code_copy = str_replace(\'_ID_\', $i, $event_trigger_code);
$event_trigger_code_copy = str_replace(\'_TRIGGER_INDEX_\', $i, $event_trigger_code_copy);
if (isset($col2) && count($col2) != 0) {
$event_trigger_code_copy = str_replace(\'_TRIGGER_COL2_\', $col2[$i], $event_trigger_code_copy);
} else {
$event_trigger_code_copy = str_replace(\'_TRIGGER_COL2_\', \'\', $event_trigger_code_copy);
}
$field_item_copy = str_replace(\'_DYNAMIC_VALUE_\', $responses[$j], $field_item_copy);
if ($tabhtml != \'\') {
$field_item_copy = str_replace(\'_TAB-INDEX_\', $tabhtml, $field_item_copy);
} else {
$field_item_copy = str_replace(\'_TAB-INDEX_\', \'\', $field_item_copy);
}
$custom_label_value = \'\';
$custom_label = "";
if ($label_class_code != \'\') {
$col2_value = \'\';
if (isset($col2) && count($col2) != 0) {
$col2_value = addslashes($col2[$i]);
}
$res = addslashes($responses[$j]);
$custom_label = "<?php \$index = {$i}; \$value = \'{$res}\'; \$col2 = \'{$col2_value}\'; ?> " . $label_class_code;
}
$element .= "
<td class=\"survey-question-response\" style=\"{$question_style} text-align:{$survey->response_alignment}\">";
$element .= "
<label class=\"{$custom_label}\" style=\"text-align:{$survey->response_alignment};\">";
$element .= "
" . $field_item_copy;
$element .= "<span class=\"survey-responsive-question-text\" style=\"display:none;\">{$responses[$j]}</span>";
$element .= "
</label>
";
$element .= "
</td>
";
}
$element .= "
</tr>
";
$element .= "
<!-- Survey Row End -->
";
if ($event_trigger_inline != "") {
$element .= "
<tr class=\"survey-trigger-row\" id=\"fb_fld-{$field->name}_{$i}_trigger\" style=\"display:none;\">
";
$trigger_field = "";
$colspan = $j + 1;
$trigger_field .= "
<td class=\"survey-trigger-td\" colspan=\"{$colspan}\" align=\"right\">";
$trigger_required = "";
if (isset($survey->triggerfieldrequired) && (int)$survey->triggerfieldrequired == 1) {
$trigger_required = " <span class=\"survey-trigger-required\">*</span>";
}
$trigger_field .= "
<label class=\"survey-trigger-label\">{$survey->triggerfieldlabel}{$trigger_required}";
$value_code = "<?php if(isset(\$_SESSION[\'{$field->name}_{$i}_triggerField\'])) { echo \$_SESSION[\'{$field->name}_{$i}_triggerField\']; } ?>";
switch ((string)$survey->triggerfieldtype) {
case \'0\':
$trigger_field .= "
<input class=\"survey-trigger-text-field\" type=\"text\" value=\"{$value_code}\" name=\"{$field->name}_{$i}_triggerField\" id=\"{$field->name}_{$i}_triggerField\" disabled />
";
break;
case \'1\':
$trigger_field .= "
<textarea class=\"survey-trigger-text-area\" name=\"{$field->name}_{$i}_triggerField\" id=\"{$field->name}_{$i}_triggerField\" disabled>{$value_code}</textarea>
";
break;
}
$trigger_field .= "
</label>";
$trigger_field .= "
</td>
";
$element .= $trigger_field;
$element .= $event_trigger_code_copy;
$element .= "
</tr>
";
$element .= "
<!-- Trigger Row End -->
";
}
}
$element .= "
</table>
";
if ((int)$tablemode->enabletablelayout == 1 && $tablemodespan && (!isset($field->bucket) || $field->bucket == "")) {
$element .= "</div>";
}
return $element;
}
public function create_query(
$jobname,
$sourcetype,
$dbhost,
$dbschema,
$mongocollection,
$dbuser,
$dbpwd,
$dbsocket,
$dbport,
$dbdsn,
$dbconnector,
$query_sql,
$query_variables,
$query_mysql4compat,
$query_debug_level,
$condition,
$query_insertid,
$query_return_result_var,
$query_function_call,
$query_function_returns_result,
$query_function_create_json,
$query_code,
$query_append_label,
$query_append_value,
$query_append_position,
$use_php_tags,
$create_elements,
$close_connection,
$query_export,
$field
) {
if($query_mysql4compat == null){
$query_mysql4compat = 0;
}
if($query_debug_level == null){
$query_debug_level = 0;
}
$this->um->pullCustomConnectorFile((string)$field->dbconnector);
$jobname = str_ireplace(\'-\', \'_\', $jobname);
$php_start_tag = \'\';
$php_close_tag = \'\';
if ($use_php_tags == 1) {
$php_start_tag = \'<?php\';
$php_close_tag = \'?>\';
}
$condition_code_start = \'\';
$condition_code_end = \'\';
$condition = $this->replace_condition_vars($condition);
if ((string)$condition != \'\') {
$condition_code_start = "// condition code start
";
$condition_code_start .= "if({$condition}) { ";
$condition_code_end = \'} // condition code end\';
}
$db_type = $this->um->translateSourceType((int)$sourcetype);
if ($query_return_result_var == \'\')
$query_return_result_var = \'$fb_query\';
$dbhost = $this->uv->replace_all($dbhost, 8);
$dbsocket = $this->uv->replace_all($dbsocket, 8);
$dbport = $this->uv->replace_all($dbport, 8);
$dbdsn = $this->uv->replace_all($dbdsn, 8);
$dbuser = $this->uv->replace_all($dbuser, 8);
$dbpwd = $this->uv->replace_all($dbpwd, 8);
$dbschema = $this->uv->replace_all($dbschema, 8);
if ($db_type == \'mongodb\') {
$mv = new stdClass();
$mv->jobname = (string)$jobname;
$mv->sourcetype = (string)$sourcetype;
$mv->dbhost = (string)$dbhost;
$mv->dbschema = (string)$dbschema;
$mv->collection = (string)$mongocollection;
$mv->dbuser = (string)$dbuser;
$mv->dbpwd = (string)$dbpwd;
$mv->dbsocket = (string)$dbsocket;
$mv->dbport = (string)$dbport;
$mv->dbdsn = (string)$dbdsn;
$mv->dbconnector = (string)$dbconnector;
$mv->mongodb_query = (string)$query_sql;
$mv->query_variables = (string)$query_variables;
$mv->query_mysql4compat = (string)$query_sql;
$mv->query_debug_level = (string)$query_debug_level;
if (!isset($field->query_mongo_query_mode)) {
$mv->query_mongo_query_mode = "0";
} else {
$mv->query_mongo_query_mode = $field->query_mongo_query_mode;
}
$mv->condition = (string)$condition;
$mv->query_insertid = (int)$query_insertid;
$mv->query_return_result_var = (string)$query_return_result_var;
$mv->query_function_call = (string)$query_function_call;
$mv->query_function_returns_result = (int)$query_function_returns_result;
$mv->query_code = (string)$query_code;
$mv->query_append_label = (string)$query_append_label;
$mv->query_append_value = (string)$query_append_value;
$mv->query_append_position = (string)$query_append_position;
$mv->use_php_tags = (int)$use_php_tags;
$mv->create_elements = $create_elements;
return $this->create_query_mongodb($mv);
}
$strs = explode(\',\', $query_variables);
$array_vars = array();
if ($query_mysql4compat == 1) {
$params = \'\';
} else {
$params = \'$params = array(\';
}
foreach ($strs as $key => $s) {
if ($key != 0) {
$params .= \', \';
}
$s = trim($s);
if ($s == \'SESSION_ID\' || $s == \'TIMESTAMP\' || $s == \'DATETIME\' || $s == \'NOW()\' || $s == \'CURRENT_TIMESTAMP\' || $s == \'REMOTE_ADDR\' || $s == \'visitor_ip\') {
switch ($s) {
case \'SESSION_ID\':
if ($query_mysql4compat) {
$params .= \'$session_id\';
} else {
$params .= \'$session_id\';
}
break;
case \'TIMESTAMP\':
if ($query_mysql4compat) {
$params .= \'$timestamp\';
} else {
$params .= \'$timestamp\';
}
break;
case \'DATETIME\':
if ($query_mysql4compat) {
$params .= \'$datetime\';
} else {
$params .= \'$datetime\';
}
break;
case \'REMOTE_ADDR\':
if ($query_mysql4compat) {
$params .= \'$remote_ip\';
} else {
$params .= \'$remote_ip\';
}
break;
case \'visitor_ip\':
if ($query_mysql4compat) {
$params .= \'$remote_ip\';
} else {
$params .= \'$remote_ip\';
}
break;
default:
if ($query_mysql4compat) {
$params .= \'$datetime\';
} else {
$params .= \'$datetime\';
}
}
} else {
$array_vars[] = "\'$s\'";
if ($query_mysql4compat == 1) {
is_numeric($s);
$params .= "mysql_real_escape_string(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$s}\'], \$link)";
} else {
if (preg_match(\'/(^|.|
|
)?(PHP\{(.*?)\})/\', $s, $php_var_match)) {
$params .= "isset(\${$php_var_match[3]}) ? \${$php_var_match[3]} : \'\'";
} else if (preg_match(\'/(^|.|
|
)(\^\{(.*?)\})/\', $s, $php_session_match)) {
$params .= "isset(\$_SESSION[\'{$php_session_match[3]}\']) ? \$_SESSION[\'{$php_session_match[3]}\'] : \'\'";
} else if (preg_match(\'/(^|.|
|
)(\#\{(.*?)\})/\', $s, $php_get_match)) {
$params .= "isset(\$_GET[\'{$php_get_match[3]}\']) ? \$_GET[\'{$php_get_match[3]}\'] : \'\'";
} else if (preg_match(\'/(^|.|
|
)(\*\{(.*?)\})/\', $s, $php_post_match)) {
$params .= "isset(\$_POST[\'{$php_post_match[3]}\']) ? \$_POST[\'{$php_post_match[3]}\'] : \'\'";
} else if (preg_match(\'/(^|.|
|
)(@\{(.*?)\})/\', $s, $php_field_match)) {
$params .= "isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$php_field_match[3]}\']) ? \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$php_field_match[3]}\'] : \'\'";
} else {
$params .= $s;
}
}
}
}
$params = $this->uv->replace_all((string)$params, 4.1);
$query_code = $this->uv->replace_all((string)$query_code, 0);
foreach ($array_vars as $idx => $dyn) {
if (preg_match(\'/(^|.|
|
)?(PHP\{(.*?)\})/\', $dyn, $php_var_match)) {
$array_vars[$idx] = "\'$php_var_match[3]\'";
}
}
$dyn_vars = implode(\',\', $array_vars);
if ($query_mysql4compat == 1) {
} else {
$params .= \');\';
}
if (!isset($query_insertid)) {
$query_insertid = 0;
}
if ((int)$query_insertid != 1) {
$query_insertid = 0;
}
if (!isset($close_connection)) {
$close_connection = \'0\';
}
if ($close_connection == "1") {
$close_connection = "true";
} else {
$close_connection = "false";
}
if (count($strs) == 1 && $strs[0] == "" && $query_mysql4compat == 0) {
$params = "\$params = array();";
}
if (count($strs) == 1 && $strs[0] == "" && $query_mysql4compat == 1) {
$params = "\'\'";
}
$json_processing_code = "";
if(isset($query_function_create_json) && $query_function_create_json == 1){
$json_processing_code = <<<EOF
// Convert Database Result to JavaScript Object.
\$nl = "
";
echo \'<script type="text/javascript">\'; echo \$nl;
echo \'var _data = \'\'; echo json_encode({$query_return_result_var}); echo \'\';\'; echo \$nl;
echo \'var q1 = eval(_data);\'; echo \$nl;
echo \'</script>\';
EOF;
}
$call_code = <<<EOF
\$ambiguous_column_name_warning = false;
\$close_connection = {$close_connection};
// Set Optional MySQL SSL Properties.
\$dbh->setMySQLSSLProperties(\$db_ssl_key, \$db_ssl_certificate, \$db_ssl_ca_cert, \$db_ssl_verify_cert, \$db_ssl_cipher);
// Default SQL Call.
{$query_return_result_var} = \$dbh->pdo_procedure_params(\$debug,
\$sql_{$jobname},
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
0, // return_true
{$query_insertid}, // return_last_insert_id,
4, // fetch_mode,
0, // pass_nulls,
false, // builder_query,
\$ambiguous_column_name_warning,
0, // query_mongo_query_mode,
\'\', // mongo_collection
\$close_connection);
EOF;
$debug_code = <<<EOF
if(\$debug == 2) {
if(\$ambiguous_column_name_warning == true){
echo \'<strong>Caution:</strong> Your Query Result Contains Ambiguous Columns, Most Likely Caused By Using SELECT * And A JOIN.<br>\';
echo \'We Have Thus Indexed These Columns For You To Create Unique Column Names,<br>\';
echo \'But It\'s Much Better To Simply Rewrite The Query To *NOT* Use SELECT * When Using A JOIN.\';
}
if($query_insertid == 1) {
echo \'<pre>{$query_return_result_var} lastInsertID = \'; echo $query_return_result_var; echo \'</pre>\';
} else {
echo \'<pre>{$query_return_result_var} = \'; print_r($query_return_result_var); echo \'</pre>\';
}
}
{$json_processing_code}
EOF;
$mysql4 = <<<EOT
// mysql 4 compatability mode
\$link = mysql_connect(\$db_host, \$db_user, \$db_pass)
or die(\'Could not connect: \' . mysql_error());
if(\$debug) { echo \'Connected successfully\'; }
mysql_select_db(\$db_catalog) or die(\'Could not select database\');
// Performing SQL query
\$query = sprintf("{$query_sql}", $params);
\$result = mysql_query(\$query) or die(\'Query failed: \' . mysql_error());
{$query_return_result_var} = mysql_fetch_array(\$result, MYSQL_BOTH);
EOT;
$export_location = "";
if (isset($field->query_export_filename) && $field->query_export_filename != "") {
$export_location = $this->uv->replace_all((string)$field->query_export_filename, 1);
}
$export_code = "";
if (isset($field->query_export) && $field->query_export != "0") {
$export_code = <<<EOF
// Remove numeric keys from result array
foreach ({$query_return_result_var} as \$key_i => \$value_i) {
foreach (\$value_i as \$key_j => \$value_i) {
if(is_int(\$key_j))
{
unset({$query_return_result_var}[\$key_i][\$key_j]);
}
}
}
// Download Prompt Method.
if({$field->query_export} == 1) {
\$filename = "{$jobname}_" . date(\'Ymd\') . ".csv";
header("Content-Disposition: attachment; filename=\"\$filename\"");
header("Content-Type: text/csv;");
// Build 913 - Process Any Code After Query Logic.
{$query_code}
\$out = fopen("php://output", \'w\');
\$flag = false;
foreach ({$query_return_result_var} as \$row) {
if (!\$flag) {
// display field/column names as first row
fputcsv(\$out, array_keys(\$row), \',\', \'"\');
\$flag = true;
}
// Convert MSSQL Date objects into strings.
foreach(\$row as \$key => \$val){
if(is_object(\$val)){
if(isset(\$val->date)){
\$row["{\$key}"] = \$val->date;
} else {
\$row["{\$key}"] = \'\';
}
}
}
fputcsv(\$out, array_values(\$row), \',\', \'"\');
}
fclose(\$out);
exit;
}
// Save File Method.
if({$field->query_export} == 2) {
\$debug_file_save = false;
// Build 913 - Process Any Code After Query Logic.
{$query_code}
\$export_location = "{$export_location}";
if(\$debug_file_save) {
echo "<pre>RAW EXPORT LOCATION: {\$export_location}</pre>";
}
// Get Info About File Naming.
\$path = pathinfo(\$export_location);
if(\$debug_file_save) {
echo "<pre>CSV EXPORT DEBUG: PATH Info:</pre>";
echo \'<pre>\'; print_r(\$path); echo \'</pre>\';
}
// No Directory Given, Create In Current Directory.
if(!isset(\$path[\'dirname\']) || trim(\$path[\'dirname\']) == "" || \$path[\'dirname\'] == ".") {
\$export_location = "./" . \$path[\'basename\'];
}
// No Filename Given, Create Default Tmp File.
if(trim(\$path[\'filename\']) == "" || \$path[\'filename\'] == ".") {
\$export_location = tempnam(\$export_location, "Query-");
}
if(\$debug_file_save) {
echo "<pre>CSV EXPORT DEBUG: Final export_location: {\$export_location}</pre>";
}
// Create File If Not Already Created Via tempnam().
if(!file_exists(\$export_location)) {
file_put_contents(\$export_location, "");
}
// Create file if needed.
if(filesize(\$export_location) == 0) {
if(\$debug_file_save) {
echo "<pre>CSV EXPORT DEBUG: New Export Detected.</pre>";
}
file_put_contents(\$export_location, "");
\$handle = fopen(\$export_location, "r+");
\$flag = false;
foreach ({$query_return_result_var} as \$row) {
if (!\$flag) {
// display field/column names as first row
fputcsv(\$handle, array_keys(\$row), \',\', \'"\');
\$flag = true;
}
// Convert MSSQL Date objects into strings.
foreach(\$row as \$key => \$val){
if(is_object(\$val)){
if(isset(\$val->date)){
\$row["{\$key}"] = \$val->date;
} else {
\$row["{\$key}"] = \'\';
}
}
}
fputcsv(\$handle, array_values(\$row), \',\', \'"\');
}
fclose(\$handle);
} else {
// File Already Exists - Append Data.
echo "<pre>CSV EXPORT DEBUG: Existing Export Detected.</pre>";
\$handle = fopen(\$export_location, "a+");
foreach ({$query_return_result_var} as \$row) {
// Convert MSSQL Date objects into strings.
foreach(\$row as \$key => \$val){
if(is_object(\$val)){
if(isset(\$val->date)){
\$row["{\$key}"] = \$val->date;
} else {
\$row["{\$key}"] = \'\';
}
}
}
fputcsv(\$handle, array_values(\$row), \',\', \'"\');
}
fclose(\$handle);
}
}
EOF;
}
$append = "";
switch ((int)$query_append_position) {
case 1:
$append = "array_unshift({$query_return_result_var}, array(0=>\'{$query_append_label}\', 1=>\'{$query_append_value}\'));";
break;
case 2:
$append = "array_push({$query_return_result_var}, array(0=>\'{$query_append_label}\', 1=>\'{$query_append_value}\'));";
break;
}
$standard_sql = <<<EOT
\$sql_{$jobname} = <<<EOG
{$query_sql}
EOG;
{$params}
{$call_code}
// Any automated append calls...
{$append}
// Data Export (Optional)
{$export_code}
{$debug_code}
EOT;
if ($query_mysql4compat == 1) {
$sql = $mysql4;
} else {
$sql = $standard_sql;
}
$function_tag_start = "";
$function_tag_end = "";
$t = (string)$query_function_returns_result;
if (!isset($query_function_returns_result) || $query_function_returns_result == "") {
$query_function_returns_result = 0;
}
if ((string)$query_function_call !== "") {
$function_tag_start = "function " . str_replace(\';\', \'\', $query_function_call) . "{";
if ((int)$query_function_returns_result == 1) {
$function_tag_end = "
//Return Result
return {$query_return_result_var};
} // end {$query_function_call}";
} else {
$function_tag_end = "} // end {$query_function_call}";
}
}
$form_populate_code = "";
if (isset($field->query_debug_level) && $field->query_debug_level == \'3\') {
$form_populate_code = <<<EOF
<!-- Form Pre-Populate Code. -->
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
\$(document).ready(function(t){
<?php
echo "var t = 0;
";
foreach({$query_return_result_var}[0] as \$key => \$value){
if(is_numeric(\$key))
continue;
\$val = str_replace("\'", "\'", \$value);
// standard text
echo "$(\'#{\$key}\').val(\'{\$val}\');
";
// calendar
echo "$(\'#date-{\$key}-1\').val(\'{\$val}\');
";
// checkboxes
echo "t = 100;
";
\$cb_loop = <<<EOG
for(i = 0; i < t; i++){
if($(\'#{\$key}\' + i)){
var _value = \'{\$val}\';
var _vals = _value.split(\'|\');
if(_vals.indexOf($(\'#{\$key}\' + i).val()) != -1)
$(\'#{\$key}\' + i).prop(\'checked\', true);
}
}
EOG;
echo \$cb_loop;
}
?>
});
</script>
EOF;
}
$form_populate_code = "";
if (!isset($dbdsn)) {
$dbdsn = "";
}
$elt = <<<EOT
{$php_start_tag}
/**
* RackForms Database Query Module Process
* Uses custom SQL to query a database of your choosing.
**/
{$function_tag_start}
// Start our main session if not already
if(!session_id()) { session_start(); }
{$condition_code_start}
\$db_type = "{$db_type}";
\$db_host = "{$dbhost}";
\$mysql_socket = "{$dbsocket}";
\$mysql_port = "{$dbport}";
\$dbdsn = "{$dbdsn}";
\$db_user = "{$dbuser}";
\$db_pass = "{$dbpwd}";
\$db_catalog = "{$dbschema}";
\$db_ssl_key = \'{$field->dbsslkey}\';
\$db_ssl_certificate = \'{$field->dbsslcertificate}\';
\$db_ssl_ca_cert = \'{$field->dbsslcacert}\';
\$db_ssl_verify_cert = \'{$field->dbsslverifycert}\';
\$db_ssl_cipher = \'{$field->dbsslcipher}\';
include \'Database.php\';
\$debug = {$query_debug_level}; // UI override
// Optional DB Connector File - if not specified we will use config.php via Database.php include
if(file_exists(\'{$dbconnector}\')){
include \'{$dbconnector}\';
}
// Query Item Qquery
\$sql_{$jobname} = "{$jobname}";
\$dbh = new Database();
\$jobname = \'{$jobname}\';
\$session_id = session_id();
\$timestamp = time();
\$datetime = date(\'Y-m-d H:i:s\', time());
// Used For Security Processing
\$remote_ip = \$_SERVER[\'REMOTE_ADDR\'];
$sql
{$query_code}
{$condition_code_end}
{$function_tag_end}
{$php_close_tag}
{$form_populate_code}
EOT;
$simple_list = "false";
if (isset($field->query_create_mode)) {
switch ($field->query_create_mode) {
case \'0\':
$simple_list = "false";
break;
case \'1\':
$simple_list = "false";
break;
case \'2\':
$simple_list = "true";
break;
}
}
$dynamic_fields = \'\';
$dynamic_fields .= <<<EOF
<?php
// Options
\$simple_list = {$simple_list};
// Create Dynamic Form Field Elements From This Query.
if(substr_count(\$sql_{$jobname}, \'where\') == 1){
\$no_where = explode(\'where\', \$sql_{$jobname});
} else {
\$no_where = explode(\'WHERE\', \$sql_{$jobname});
}
\$sql_elements_{$jobname} = \$no_where[0];
// Default SQL Call.
\$result_elements_{$jobname} = \$dbh->mysql_meta_query(\$debug,
\$sql_elements_{$jobname},
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog);
if(\$result_elements_{$jobname}[0] == 1){
\$result_elements_encoded = php_json_encode(\$result_elements_{$jobname}[1]);
} else {
echo \'There was a problem creating your Query Form Elements.\';
}
// create a session element that stores valid field names, these are processed in the _process.php file.
\$_SESSION[\'fb_dynamic_elements\'] = \'\';
// allow for multiple queries on the same page.
if(!isset(\$elements_to_save)){
\$elements_to_save = array();
}
// now that we know thier fields meta content, create the elements.
// create our elements based on data type
\$form_elements = \'<ul class="dynamic-form-elements-ul">\';
foreach({$query_return_result_var} as \$idx => \$q){
foreach(\$q as \$idj => \$f){
if(!is_numeric(\$idj))
continue; // we only want indexed items
// Simple List Mode
// Create form elements using a simple radio interface, useful for dynamic product selection forms.
// We make a few assumptions here:
// a) The query driving this only grabs two fields, one of which is the PK.
// b) The field value becomes the label.
// c) The field column name becomes the indexed name property.
if(\$simple_list == true){
\$t = explode(\',\', \$result_elements_{$jobname}[1][\$idj]); // field name, field type, PK
// Do not create field or record for PK field.
if(\$t[2] == "true")
continue;
// Create name for this field based on the column name + index
\$_field_name = \$t[0] . \$idx;
// push this element to our dynamic processing array.
\$elements_to_save[] = \$_field_name;
\$form_elements .= "<li>";
// The PK Field For This Item Becomes The Value, Otherwise We Use The Base Field Value.
\$temp_value = \$q["{\$t[0]}"];
// Loop over all items and grab a PK if possible
foreach(\$result_elements_{$jobname}[1] as \$res_loop){
\$_t = explode(\',\', \$res_loop); // field name, field type, PK
if(\$_t[2] == "true"){
\$temp_value = \$q["{\$_t[0]}"];
break;
}
}
\$data_type = \'INT\';
\$field_type = "textbox";
\$sel = \'\';
if(\$f == \'1\') { \$sel = \' checked="checked" \'; }
\$form_elements .= "<span class=\"\">{\$q["{\$t[0]}"]}</span><br />"; // Field Value Becomes Label
//\$form_elements .= "<label for=\"{\$_field_name}-false\"><input type=\"radio\" name=\"{\$_field_name}\" id=\"{\$_field_name}-false\" value=\"\" />Not Selected</label>";
\$form_elements .= "<label for=\"{\$_field_name}-true\"><input type=\"checkbox\" name=\"{\$_field_name}\" id=\"{\$_field_name}-true\" value=\"{\$temp_value}\" {\$sel} /></label>";
\$form_elements .= "</li>";
// Do Not Process Further.
continue;
} // Simple List Mode
\$t = explode(\',\', \$result_elements_{$jobname}[1][\$idj]); // field name, field type, PK
// push this element to our dynamic processing array.
\$elements_to_save[] = \$t[0];
\$label_value_upper = ucwords(\$t[0]);
\$default_text_field = "<div class=\"dynamic-form-elements-field-wrapper\">";
\$default_text_field .= "<label class=\"dynamic-form-elements-label\" for=\"{\$t[0]}\">{\$label_value_upper}</label>";
\$default_text_field .= "</div>";
// Build 829 - Option to pre-populate field.
if({$field->query_create_mode} == "0"){
\$default_text_field .= "<input class=\"dynamic-form-elements-text\" type=\"text\" name=\"{\$t[0]}\" value=\"{\$f}\" />";
}
if({$field->query_create_mode} == "1"){
\$default_text_field .= "<input class=\"dynamic-form-elements-text\" type=\"text\" name=\"{\$t[0]}\" value=\"\" />";
}
// Build 829 - Create PK Items as Hidden Fields.
if(\$t[2] == "true"){
\$form_elements .= "<input type=\"hidden\" name=\"{\$t[0]}\" value=\"{\$f}\" />";
} else {
\$form_elements .= "<li>";
switch(\$t[1]){
case \'LONG\' :
\$data_type = \'INT\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'FLOAT\' :
\$data_type = \'INT\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'VAR_STRING\' :
\$data_type = \'STRING\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'BLOB\' :
\$data_type = \'BLOB\';
\$field_type = "file-db";
\$update_default_value = "1048576";
break;
// mysqli -
// http://www.php.net/manual/en/mysqli.constants.php
case \'1\' : // MYSQLI_TYPE_TINY / BOOL
\$data_type = \'INT\';
\$field_type = "textbox";
\$sel = \'\';
if(\$f == \'1\') { \$sel = \' checked="checked" \'; }
\$form_elements .= "<span class=\"\">{\$t[0]}</span><br />";
\$form_elements .= "<label for=\"{\$t[0]}-false\"><input type=\"radio\" name=\"{\$t[0]}\" id=\"{\$t[0]}-false\" value=\"0\" />Not Selected</label>";
\$form_elements .= "<label for=\"{\$t[0]}-true\"><input type=\"radio\" name=\"{\$t[0]}\" id=\"{\$t[0]}-true\" value=\"1\" {\$sel} />Selected</label>";
break;
case \'3\' : // MYSQLI_TYPE_LONG
\$data_type = \'INT\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'4\' : // MYSQLI_TYPE_FLOAT
\$data_type = \'INT\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'7\' : // MYSQLI_TYPE_TIMESTAMP
\$data_type = \'TIMESTAMP_A\';
\$field_type = "calendar";
\$form_elements .= \$default_text_field;
break;
case \'12\' : // MYSQLI_TYPE_DATETIME
\$data_type = \'DATETIME_A\';
\$field_type = "calendar"; // was textbox
\$form_elements .= \$default_text_field;
break;
case \'252\' : // MYSQLI_TYPE_BINARY
// Tricky as this can also be password fields and BIGTEXT. For now, not supported.
\$field_type = "file-db";
\$update_default_value = "1048576";
break;
case \'253\' :
\$data_type = \'STRING\';
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
// MSSQL SQLSRV Support
// Scroll down a bit to see all native types:
// http://msdn.microsoft.com/en-US/library/cc296197%28v=SQL.90%29.aspx
case \'-2\' : // SQL_BINARY
\$data_type = \'TIMESTAMP_A\';
\$field_type = "calendar";
\$form_elements .= \$default_text_field;
break;
case \'-4\' :
\$field_type = "file-db";
\$update_default_value = "1048576";
break;
case \'-9\' : // Build 710 - NVARCHAR
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'2\' : // Build 710 - Numeric
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'93\' :
\$data_type = "DATETIME_A"; //SQL_TYPE_TIMESTAMP (datetime)
\$field_type = "calendar";
\$form_elements .= \$default_text_field;
break;
// PostgreSQL Support
case \'bytea\' :
\$field_type = "file-db";
\$update_default_value = "1048576";
break;
case \'date\' :
\$data_type = "DATETIME_A";
\$field_type = "calendar";
\$form_elements .= \$default_text_field;
break;
case \'timestamp\' :
\$data_type = "DATETIME_A";
\$field_type = "calendar";
\$form_elements .= \$default_text_field;
break;
case \'money\' :
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
case \'int4\' :
\$field_type = "textbox";
\$form_elements .= \$default_text_field;
break;
}
\$form_elements .= "</li>";
} // is pk or not.
}
}
\$form_elements .= \'</ul>\';
// save all dynamic element field names to our process check array.
\$_SESSION[\'fb_dynamic_elements\'] = \$elements_to_save;
echo \$form_elements;
?>
EOF;
if (isset($create_elements) && (int)$create_elements == 1) {
$elt = $elt . $dynamic_fields;
}
return $elt;
}
public function create_query_mongodb($m)
{
$jobname = str_ireplace(\'-\', \'_\', $m->jobname);
$php_start_tag = \'\';
$php_close_tag = \'\';
if ($m->use_php_tags == 1) {
$php_start_tag = \'<?php\';
$php_close_tag = \'?>\';
}
$condition_code_start = \'\';
$condition_code_end = \'\';
$condition = $this->replace_condition_vars($m->condition);
if ((string)$condition != \'\') {
$condition_code_start = "if({$condition}) { // condition code start";
$condition_code_end = \'} // condition code end\';
}
$db_type = $this->um->translateSourceType((int)$m->sourcetype);
$params = $this->uv->replace_all((string)$m->query_variables, 4.1);
$query_code = $this->uv->replace_all((string)$m->query_code, 0);
if (substr_count($params, ";") == 0 && $params != \'\') {
$params = "\$params = {$params};";
} else {
$params = "\$params = \"\";";
}
if ($m->mongodb_query == "")
$m->mongodb_query = "\'\'";
if (!isset($m->query_mongo_query_mode) || $m->query_mongo_query_mode == \'\')
$m->query_mongo_query_mode = "0";
if (!isset($m->query_insertid))
$m->query_insertid = 0;
$call_code = <<<EOF
\$ambiguous_column_name_warning = false;
// Default SQL Call.
{$m->query_return_result_var} = \$dbh->pdo_procedure_params(\$debug,
\$mongodb_{$jobname},
\$db_host,
\$db_type,
\$mysql_socket,
\$mysql_port,
\$dbdsn,
\$db_user,
\$db_pass,
\$db_catalog,
\$params,
0, // return_true
{$m->query_insertid}, // return_last_insert_id,
4, // fetch_mode,
0, // pass_nulls,
false, // builder_query,
\$ambiguous_column_name_warning,
$m->query_mongo_query_mode,
\'{$m->collection}\');
EOF;
$debug_code = <<<EOF
if(\$debug == 2) {
echo \'<pre>{$m->query_return_result_var} = \'; print_r($m->query_return_result_var); echo \'</pre>\';
}
EOF;
$append = "";
switch ((int)$m->query_append_position) {
case 1:
$append = "array_unshift({$m->query_return_result_var}, array(0=>\'{$m->query_append_label}\', 1=>\'{$m->query_append_value}\'));";
break;
case 2:
$append = "array_push({$m->query_return_result_var}, array(0=>\'{$m->query_append_label}\', 1=>\'{$m->query_append_value}\'));";
break;
}
$m->mongodb_query = $this->uv->replace_all((string)$m->mongodb_query, 4.1);
$query = <<<EOT
\$mongodb_{$jobname} = {$m->mongodb_query};
{$params}
{$call_code}
// Any automated append calls...
{$append}
{$debug_code}
EOT;
$function_tag_start = "";
$function_tag_end = "";
$t = (string)$m->query_function_returns_result;
if (!isset($m->query_function_returns_result) || $m->query_function_returns_result == "") {
$query_function_returns_result = 0;
}
if ((string)$m->query_function_call !== "") {
$function_tag_start = "function " . $m->query_function_call . "{";
if ((int)$query_function_returns_result == 1) {
$function_tag_end = "
//Return Result
return {$m->query_return_result_var};
} // end {$m->query_function_call}";
} else {
$function_tag_end = "} // end {$m->query_function_call}";
}
}
if (!isset($m->dbdsn)) {
$dbdsn = "";
}
$elt = <<<EOT
{$php_start_tag}
/**
* Database Query Module Process
* Uses custom SQL to query a database of your choosing.
**/
{$function_tag_start}
// Start our main session if not already
if(!session_id()) { session_start(); }
{$condition_code_start}
\$db_type = \'{$db_type}\';
\$db_host = \'{$m->dbhost}\';
\$mysql_socket = \'{$m->dbsocket}\';
\$mysql_port = \'{$m->dbport}\';
\$dbdsn = \'{$dbdsn}\';
\$db_user = \'{$m->dbuser}\';
\$db_pass = \'{$m->dbpwd}\';
\$db_catalog = \'{$m->dbschema}\';
include \'Database.php\';
\$debug = {$m->query_debug_level}; // UI override
// Optional DB Connector File - if not specified we will use config.php via Database.php include
if(file_exists(\'{$m->dbconnector}\')){
include \'{$m->dbconnector}\';
}
// Mongo Query
\$sql_{$jobname} = "{$jobname}";
\$dbh = new Database();
\$jobname = \'{$jobname}\';
\$session_id = session_id();
\$timestamp = time();
\$datetime = date(\'Y-m-d H:i:s\', time());
// Used For Security Processing
\$remote_ip = \$_SERVER[\'REMOTE_ADDR\'];
$query
{$query_code}
{$condition_code_end}
{$function_tag_end}
{$php_close_tag}
EOT;
$dynamic_fields = \'\';
if (isset($m->create_elements) && (int)$m->create_elements == 1) {
$elt = $elt . $dynamic_fields;
}
return $elt;
}
public function create_prefab_survey_scale($field, $tablemode, $bucket_node = "")
{
$label = $field->label;
$name = $field->name;
$id = $field->id;
$color = $field->color;
$helper = $field->helper;
$helpercolor = $field->helpercolor;
$fontsize = $field->fontsize;
$labelpos = $field->labelpos;
$style = $field->style;
$prefab = $field->prefab;
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$element = "";
$styles = $this->translateFieldStyles($style);
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
$required = (int)$field->validation->req == 1 ? "<span class=\"req-star\"> {$required_text}</span>" : \'\';
$questionColumns = "";
$scaleBottom = (int)$prefab->scale_bottom;
$scaleTop = (int)$prefab->scale_top;
$delta = $scaleTop - $scaleBottom;
if ($delta >= 2) {
for ($i = $scaleBottom; $i <= $scaleTop; $i++) {
$selected = "<?php isset(\$_SESSION[\"{$field->name}\"]) && \$_SESSION[\"{$field->name}\"] == {$i} ? print \'checked=\"checked\"\' : print \'\'; ?>";
$questionColumns .= <<<EOF
<label class="survey-scale-column">
<div class="survey-scale-label">{$i}</div>
<div class="survey-scale-input">
<input type="radio" name="{$field->name}" id="{$field->id}_{$i}" value="{$i}" {$selected} />
</div>
</label>
EOF;
}
}
$element .= <<<EOF
<div class="survey-scale-question-text"><span>{$prefab->question_text}{$required}</span></div>
<div class="survey-scale-content-container">
<div class="survey-scale-label-column">
<div class="survey-scale-placeholder"></div>
<div class="survey-scale-text survey-scale-text-bottom">{$prefab->text_bottom}</div>
</div>
<div class="survey-scale-questions">
{$questionColumns}
</div>
<div class="survey-scale-label-column">
<div class="survey-scale-placeholder"></div>
<div class="survey-scale-text survey-scale-text-top">{$prefab->text_top}</div>
</div>
</div> <!-- Close Content Container -->
EOF;
$element .= \'<div style="height: 20px; width: 100%; clear:both;"></div>\';
return $element;
}
public function create_ecomm($field, $tablemode, $bucket_node = "")
{
$readonly = isset($field->readonly) ? $field->readonly : 0;
$fieldenabled = isset($field->fieldenabled) ? $field->fieldenabled : 1;
$element = "";
$elt = "";
switch ((int)$field->transactiontype) {
case \'0\':
break;
case \'1\':
break;
case \'2\':
break;
case \'3\':
break;
}
switch ((int)$field->currency) {
case \'0\':
$currency = \'$\';
break;
case \'1\':
$currency = \'€\';
break;
case \'2\':
$currency = \'£\';
break;
case \'3\':
$currency = \'¥\';
break;
case 4:
$currency = \'$\';
break;
case 5:
$currency = \'¤\';
break;
case 6:
$currency = \'$\';
break;
case 7:
$currency = \'¤\';
break;
case 8:
$currency = \'¤\';
break;
case 9:
$currency = \'€\';
break;
case 10:
$currency = \'$\';
break;
case 11:
$currency = \'¤\';
break;
case 12:
$currency = \'¤\';
break;
case 13:
$currency = \'¥\';
break;
case 14:
$currency = \'¤\';
break;
case 15:
$currency = \'¤\';
break;
case 16:
$currency = \'¤\';
break;
case 17:
$currency = \'$\';
break;
case 18:
$currency = \'¤\';
break;
case 19:
$currency = \'¤\';
break;
case 20:
$currency = \'£\';
break;
case 21:
$currency = \'$\';
break;
case 22:
$currency = \'¤\';
break;
case 23:
$currency = \'¤\';
break;
case 24:
$currency = \'$\';
break;
case 25:
$currency = \'¤\';
break;
case 26:
$currency = \'$\';
break;
}
switch ($field->fieldtype) {
case \'0\':
$fieldtype = \'checkbox\';
$fieldarray = \'[]\';
break;
case \'1\':
$fieldtype = \'radio\';
$fieldarray = \'\';
break;
case \'2\':
$fieldtype = \'select\';
$fieldarray = \'\';
break;
default:
$fieldtype = \'checkbox\';
$fieldarray = \'[]\';
}
$styles = $this->translateFieldStyles($field->style);
$tabindex = $field->tabindex;
$tabhtml = $this->createTabIndexCode((int)$tabindex);
$conditional_call = $this->_createConditionalEvent($field->conditional, $field->name, $field->id);
$conditional_call_inline = $conditional_call[0];
$conditional_call_script = $conditional_call[1];
if ((int)$tablemode->rightcolumnalign == 0) {
$align = \'left\';
} else {
$align = \'right\';
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$fixed_width = $tablemode->leftcolumnwidth - 8;
$bottom_margin_value = intval($tablemode->marginbottom);
$elt .= "
<div class=\"fb-tablemode-label desktop-cell\" style=\"width:{$tablemode->leftcolumnwidth}; padding-top:3px; float:left;\"> </div>";
$elt .= "
<div class=\"fb-tablemode-element\" style=\"width:{$tablemode->rightcolumnwidth}; float:left; text-align:{$align}; margin-bottom:{$bottom_margin_value}px;\" >
";
}
$field->label = $this->uv->replace_all((string)$field->label, 6);
$readonly = isset($readonly) ? $readonly == 1 ? " readonly " : "" : "";
$enabled = isset($fieldenabled) ? $fieldenabled == 0 ? " disabled " : "" : "";
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
if ($fieldtype == "select") {
$element .= $this->_helper_field_label($field, $field->name, $field->validation->req, $required_text, $field->color, $field->fontsize, $styles, $field->label, $field->labelpos, (string)$field->type, \'\', \'\', $tablemode);
}
$inline_label_pos = $this->get_inline_label_pos($field->labelpos);
$textalignment = "left";
if (isset($field->elementpos) && $field->elementpos != "0") {
switch ((int)$field->elementpos) {
case 0:
$textalignment = \'left\';
break;
case 1:
$textalignment = \'right\';
break;
case 2:
$textalignment = \'center\';
break;
}
}
$elt .= <<<EOT
<?php
\$_SESSION [\'{$field->name}\'] = isset ( \$_SESSION [\'{$field->name}\'] ) ? \$_SESSION [\'{$field->name}\'] : "";
if (! isset ( \$_SESSION [\'{$field->name}_is\'] )) {
\$_SESSION [\'{$field->name}_is\'] = 1;
}
?>
{$conditional_call_script}
{$element}
<span style="clear:both; float:{$textalignment};">
EOT;
if ($fieldtype == "select") {
$elt .= "<select class=\"form-control\" name=\"{$field->name}\" id=\"{$field->id}\" {$tabhtml} {$field->attributestyle} {$conditional_call_inline} >";
}
if ($fieldtype != "select") {
$elt .= "
<fieldset data-role=\"controlgroup\" style=\"border:0; padding:0px; margin:0px;\">
";
$elt .= $this->_helper_field_label($field, $field->name, $field->validation->req, $required_text, $field->color, $field->fontsize, $styles, $field->label, $field->labelpos, (string)$fieldtype, \'\', \'\', $tablemode);
$elt .= "
<span class=\"fb-multiselect-column radio-column\">
";
}
foreach ($field->selectitems as $key => $val) {
$label = "{$val->name} - {$currency}<?php echo replaceEcommPriceTokens(\'{$val->price}\'); ?>";
if ($val->selected == 1) {
$extra = " || \$_SESSION [\'{$field->name}_is\'] == 1";
} else {
$extra = "";
}
$fontsize = $field->fontsize;
$ct1 = substr_count((string)$fontsize, \'pt\');
$ct2 = substr_count((string)$fontsize, \'px\');
if ($ct1 == 0 && $ct2 == 0) {
$fontsize = $fontsize . \'px\';
}
if ($fieldtype == "select") {
$elt .= <<<DOC
<option value="{$val->name}"
<?php
if(\$_SESSION[\'{$field->name}\'] == html_entity_decode("{$val->name}", ENT_QUOTES) {$extra}) {
echo \'selected="selected"\';
}
?> >{$label}</option>
DOC;
} else {
$elt .= <<<EOF
<div class="multiselect-item field" style="margin:1px; clear:both; align:left;">
<input type="{$fieldtype}" name="{$field->name}{$fieldarray}" id="{$field->name}{$val->id}" {$tabhtml} value="{$val->name}"
<?php
if (\$_SESSION [\'{$field->name}\'] == html_entity_decode ( "{$val->name}", ENT_QUOTES ) {$extra}) {
echo \'checked="checked"\';
}
?>
{$field->attribute} {$field->attributestyle} {$conditional_call_inline} {$enabled} {$readonly} />
<label class="rf-multiselect-item-label" for="{$field->name}{$val->id}" style="color:{$field->color}; font-size:{$fontsize};">{$label}</label> {$inline_label_pos}
</div>
EOF;
}
}
if ($fieldtype != "select") {
$elt .= <<<EOF
</span>
<span class="fb-checkbox-clear" style="clear:both;"></span>
</fieldset>
EOF;
}
if ($fieldtype == "select") {
$elt .= "</select>";
}
$elt .= \'</span>\';
$max_quantity = 31;
if (isset($field->quantity_max)) {
$max_quantity = intval($field->quantity_max) + 1;
}
if (isset($field->quantity) && $field->quantity != "0") {
$_e = <<<EOF
<div style="width:100%; clear:both; height:10px"></div>
<label for="{$field->name}-quantity">{$field->quantity_label}
<select class="form-control" name="{$field->name}-quantity" id="{$field->name}-quantity" style="">
<?php
for(\$q = 1; \$q < {$max_quantity}; \$q++){
\$_ckd = "";
if (isset(\$_SESSION[\'{$field->name}-quantity\']) && \$_SESSION[\'{$field->name}-quantity\'] == \$q) {
\$_ckd = \' selected="selected" \';
}
echo \'<option value="\' . \$q . \'"\' . \$_ckd .\'>\' . \$q . \'</option>\';
}
?>
</select></label>
EOF;
$elt .= $_e;
}
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$elt .= "</div>";
}
return $elt;
}
private function _helper_field_label($field, $name, $req, $required_text, $color, $fontsize, $styles, $label, $labelpos, $field_type, $tooltip, $lineheight, $tablemode)
{
if($field_type == null){
$field_type = "";
}
if($tooltip == null){
$tooltip = "";
}
if($lineheight == null){
$lineheight = "";
}
$labelpos = $this->get_label_pos($labelpos, $field_type);
$element = "";
if ($req == \'1\') {
$space = "";
if ($field->type != "textarea") {
$space = "";
}
if ((string)$label == " ") {
$label = "";
}
if ($field->type != "radio" || $field->type != "checkbox") {
$req = "<span class=\"req-star\">{$required_text}{$space}</span>";
} else {
$req = "<span class=\"req-star\">{$required_text}{$space}</span>";
}
} else {
$req = \'\';
}
$label_before = $label;
$label = $this->uv->replace_all($label, 6);
if ($label_before != $label) {
$element .= "<input type=\"hidden\" name=\"{$name}_dyn_label\" value=\"{$label}\" />
";
}
$tooltip_html = "";
if (is_object($tooltip) && (string)$tooltip->text != "") {
if ((int)$tooltip->events == 2 || (int)$tooltip->events == 3) {
$tooltip_text = (string)$tooltip->text;
$tooltip_text = "";
$tooltip_html = " ";
if (isset($field_type) && $field_type != "" && ($field_type == "radio" || $field_type == "checkbox")) {
if ($label == "" || $label == " ") {
$tooltip_html = "";
}
}
$tooltip_html .= "<img id=\"{$name}-tooltip-button\" class=\"{$name}-tooltip-button\" src=\"icons/tooltip-button-icon.png\" title=\"{$tooltip_text}\" onclick=\"return false\" />";
$tooltip_html .= " ";
}
}
if ($field->type == "text" && $labelpos == "float:left;") {
$tooltip_html = "";
}
$lineheight_css = "";
if ($labelpos == "float:left;") {
if (isset($lineheight) && $lineheight != "") {
if (isset($field_type) && $field_type != "" && ($field_type == "text" || $field_type == "password")) {
$lineheight_css = "line-height:" . (intval($lineheight) + 5) . "px;";
}
} else {
if (isset($field_type) && $field_type != "" && ($field_type == "select")) {
$lineheight_css = "line-height:" . (intval($lineheight) + 18) . "px;";
}
}
}
if (isset($tablemode) && isset($tablemode->enabletablelayout) && (int)$tablemode->enabletablelayout == 1)
$labelpos = "";
$width_css = "";
if ($label == "" || $label == " ") {
$width_css = "width:0px;";
}
$height_css = "";
if ($label == "" || $label == " ") {
$height_css = "height:0px;";
}
if (isset($field_type) && $field_type != "" && ($field_type == "radio" || $field_type == "checkbox")) {
if ((int)$field->validation->req == 1 && ($label == "" || $label == " ")) {
$height_css = "";
$width_css = "float:left; width:9px;";
}
if (($label == "" || $label == " ") && $tooltip_html != "") {
$height_css = "";
$width_css = "float:left; width:15px;";
}
$fontweight = isset($styles[\'fontweight\']) && $styles[\'fontweight\'] != "" ? $styles[\'fontweight\'] : "normal";
$md5 = md5(rand(10000, 10000000));
$element .= <<<EOT
<style type="text/css">
#legend-{$name}-{$md5} {
{$labelpos}
color:{$color};
font-size:{$fontsize};
{$lineheight_css}
{$width_css}
{$height_css}
font-weight:{$fontweight};
padding:0;
}
</style>
<legend class="heading-main" id="legend-{$name}-{$md5}">{$label}{$tooltip_html}{$req}</legend>
<div style="position:relative">
<div id="{$name}-validation-style-3-line" class="validation-style-3-line" style="display:none;"> </div>
<div id="{$name}-validation-style-3-icon" class="validation-style-3-icon" style="display:none;"> </div>
<div id="{$name}-validation-style-3-message" class="validation-style-3-message errormsg" style="display:none;"> </div>
</div>
EOT;
} else {
$final_nbsp = " ";
if (($field_type == \'select\' || $field_type == \'text\' || $field_type == \'password\' || $field_type == \'textarea\') && $label == " ") {
$label = "";
$final_nbsp = "";
if ($tooltip == "")
$tooltip_html = "";
}
if (isset($field_type) && $field_type != "" && $field_type == "calendar") {
$name = "date-{$field->id}-1";
}
$element .= <<<EOT
<div style="{$labelpos} {$lineheight_css}" class="heading-main">
<label aria-label="Form Field - {$name}" for="{$name}" style="color:{$color}; font-size:{$fontsize}; {$lineheight_css} {$width_css} font-weight:{$styles[\'fontweight\']}; ">{$label}{$req}{$tooltip_html}{$final_nbsp}</label>
<div style="position:relative">
<div id="{$name}-validation-style-3-line" class="validation-style-3-line" style="display:none;"> </div>
<div id="{$name}-validation-style-3-icon" class="validation-style-3-icon" style="display:none;"> </div>
<div id="{$name}-validation-style-3-message" class="validation-style-3-message errormsg" style="display:none;"> </div>
</div>
</div>
EOT;
}
return $element;
}
function _helper_field_label_html_only($field, $tablemode)
{
$name = $field->name;
$req = $field->req;
$required_text = $field->validation->req;
$color = $field->color;
$fontsize = $field->fontsize;
$styles = $this->translateFieldStyles($field->style);
$label = $field->label;
$labelpos = $field->labelpos;
$field_type = (string)$field->type;
$tooltip = $field->tooltip;
$lineheight = $field->fieldheight;
$labelpos = $this->get_label_pos($labelpos, $field_type);
$element = "";
if ($req == \'1\') {
$space = "";
if ($field->type != "textarea") {
$space = "";
}
if ((string)$label == " ") {
$label = "";
}
if ($field->type != "radio" || $field->type != "checkbox") {
$req = "<span class=\"req-star\">{$required_text}{$space}</span>";
} else {
$req = "<span class=\"req-star\">{$required_text}{$space}</span>";
}
} else {
$req = \'\';
}
$label_before = $label;
$label = $this->uv->replace_all($label, 6);
$lineheight_css = "";
if ($labelpos == "float:left;") {
if (isset($lineheight) && $lineheight != "") {
if (isset($field_type) && $field_type != "" && ($field_type == "text" || $field_type == "password")) {
$lineheight_css = "line-height:" . (intval($lineheight) + 5) . "px;";
}
} else {
if (isset($field_type) && $field_type != "" && ($field_type == "select")) {
$lineheight_css = "line-height:" . (intval($lineheight) + 18) . "px;";
}
}
}
if (isset($tablemode) && isset($tablemode->enabletablelayout) && (int)$tablemode->enabletablelayout == 1)
$labelpos = "";
$width_css = "";
if ($label == "" || $label == " ") {
$width_css = "width:0px;";
}
$height_css = "";
if ($label == "" || $label == " ") {
$height_css = "height:0px;";
}
if (isset($field_type) && $field_type != "" && ($field_type == "radio" || $field_type == "checkbox")) {
if (($label == "" || $label == " ") && $tooltip_html != "") {
$height_css = "";
$width_css = "float:left; width:15px;";
}
$final_nbsp = " ";
$element .= <<<EOT
<div style="{$labelpos} {$lineheight_css}" class="heading-main">
<label aria-label="Form Field For ${name}" for="{$name}" style="color:{$color}; font-size:{$fontsize}; {$lineheight_css} {$width_css} font-weight:{$styles[\'fontweight\']}; ">{$label}{$final_nbsp}</label>
</div>
EOT;
} else {
$final_nbsp = " ";
if (($field_type == \'select\' || $field_type == \'text\' || $field_type == \'password\' || $field_type == \'textarea\') && $label == " ") {
$label = "";
$final_nbsp = "";
if ($tooltip == "")
$tooltip_html = "";
}
if (isset($field_type) && $field_type != "" && $field_type == "calendar") {
$name = "date-{$field->id}-1";
}
$element .= <<<EOT
<div style="{$labelpos} {$lineheight_css}" class="heading-main">
<label aria-label="Form Field - {$name}" for="{$name}" style="color:{$color}; font-size:{$fontsize}; {$lineheight_css} {$width_css} font-weight:{$styles[\'fontweight\']}; ">{$label}{$final_nbsp}</label>
</div>
EOT;
}
return $element;
}
public function create_tooltip_html($tooltip, $name)
{
$tooltip_html = "";
if ($tooltip != "") {
if ((int)$tooltip->events == 2 || (int)$tooltip->events == 3) {
$tooltip_text = $tooltip->text;
$tooltip_text = "";
$tooltip_html = " ";
$tooltip_html .= "<img id=\"{$name}-tooltip-button\" class=\"{$name}-tooltip-button tooltip-button\" src=\"icons/tooltip-button-icon.png\" title=\"{$tooltip_text}\" onclick=\"return false\" />";
$tooltip_html .= " ";
return $tooltip_html;
}
}
}
public function create_table_mode_mobile_label($field, $tablemode)
{
$label = $field->{\'label\'};
$labelpos = $field->labelpos;
if ($label == "") {
$label = " ";
}
$element = "";
if ((int)$tablemode->enabletablelayout == 1 && (!isset($field->bucket) || $field->bucket == "")) {
$required_text = isset($field->requiredfieldcharacter) ? $field->requiredfieldcharacter : "*";
if ((string)$label != " " || $this->get_label_pos($labelpos, (string)$field->type) != "float:left;") {
$element .= "
<span class=\"mobile-block\">
";
$element .= $this->_helper_field_label(
$field,
$field->name,
$field->validation->req,
$required_text,
$field->color,
$field->fontsize,
$this->translateFieldStyles($field->style),
$label,
$labelpos,
(string)$field->type,
$field->tooltip,
$field->fieldheight,
$tablemode
);
$element .= "
</span>
";
}
}
return $element;
}
public function get_label_pos($labelpos, $field_type = "")
{
if ($field_type == "checkbox" || $field_type == "radio") {
$labelpos = "";
} else {
switch ($labelpos) {
case \'0\':
$labelpos = \'\';
break;
case \'1\':
$labelpos = \'float:left;\';
break;
}
}
return $labelpos;
}
public function get_inline_label_pos($labelpos)
{
switch ($labelpos) {
case \'0\':
if (!defined(\'MOBILE_MODE\')) {
$labelpos = \'<br/>\';
} else {
$labelpos = \'\';
}
break;
case \'1\':
$labelpos = \'\';
break;
}
return $labelpos;
}
public function replace_condition_vars($condition)
{
$matches = array();
$condition = (string)$condition;
preg_match_all(\'/(^|.|
|
)(#\{(.*?)\})/\', $condition, $matches);
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$condition = str_replace(\'#{\' . $m . \'}\', "isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']) && \$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']", $condition);
}
}
$condition = $this->uv->replace_all($condition, 4.1);
return $condition;
}
public function return_bytes($val)
{
$val = trim($val);
$last = strtolower($val[strlen($val) - 1]);
switch ($last) {
case ($last == \'g\' || $last == \'G\') :
$val = $val * (1024 * 1024 * 1024);
break;
case ($last == \'m\' || $last == \'M\') :
$val = $val * (1024 * 1024);
break;
case ($last == \'k\' || $last == \'K\'):
$val = $val * 1024;
break;
default :
$val = $val;
}
return $val;
}
public function return_font($value)
{
$family = \'\';
switch ($value) {
case \'0\':
$family = \'DejaVu Sans, Geneva, Arial, Helvetica, sans-serif\';
break;
case \'1\':
$family = \'DejaVu Sans, Arial, Helvetica, sans-serif\';
break;
case \'2\':
$family = "DejaVu Sans, \'Times New Roman\', Times, serif";
break;
case \'3\':
$family = "DejaVu Sans, \'Courier New\', Courier, monospace";
break;
case \'4\':
$family = \'DejaVu Sans, Verdana, Arial, Helvetica, sans-serif\';
break;
case \'5\':
$family = \'DejaVu Sans, Comic Sans MS\';
break;
case \'6\':
$family = \'DejaVu Sans, Tahoma\';
break;
case \'7\':
$family = \'DejaVu Sans, Trebuchet MS,Helvetica,sans-serif\';
break;
case \'8\':
$family = \'DejaVu Sans, Lucida Grande,Helvetica,sans-serif\';
break;
case \'9\':
$family = "DejaVu Sans, \'Myriad\',\'Myriad Pro\',\'Lucida Grande\',\'Lucida Sans Unicode\',Verdana";
break;
default:
$family = $value;
break;
}
return $family;
}
public function translateConditionalEvent($event)
{
$elt = "\'\'";
switch ($event) {
case \'0\':
$elt = \'\';
break;
case \'1\':
$elt = \'onclick\';
break;
case \'2\':
$elt = \'onblur\';
break;
case \'3\':
$elt = \'onchange\';
break;
case \'4\':
$elt = \'onkeyup\';
break;
case \'5\':
$elt = \'onmouseover\';
break;
case \'6\':
$elt = \'onmouseout\';
break;
}
return $elt;
}
public function translateConditionalAjaxEvent($event)
{
$elt = "\'\'";
switch ($event) {
case \'0\':
$elt = \'\';
break;
case \'1\':
$elt = \'click\';
break;
case \'2\':
$elt = \'blur\';
break;
case \'3\':
$elt = \'change\';
break;
case \'4\':
$elt = \'keyup\';
break;
case \'5\':
$elt = \'mouseover\';
break;
case \'6\':
$elt = \'mouseout\';
break;
}
return $elt;
}
public function translateConditionalAnimation($animation)
{
$elt = "\'\'";
switch ($animation) {
case \'0\':
$elt = "\'\'";
break;
case \'1\':
$elt = "\'fade\'";
break;
case \'2\':
$elt = "\'blind\'";
break;
}
return $elt;
}
public function translateConditionalCondition($condition)
{
$elt = "\'\'";
switch ($condition) {
case \'1\':
$elt = "\'!=\'";
break;
case \'2\':
$elt = "\'==\'";
break;
case \'3\':
$elt = "\'<\'";
break;
case \'4\':
$elt = "\'>\'";
break;
case \'5\':
$elt = "\'<=\'";
break;
case \'6\':
$elt = "\'>=\'";
break;
case \'7\':
$elt = "\'checked\'";
break;
case \'8\':
$elt = "\'unchecked\'";
break;
case \'9\':
$elt = "\'clicked\'";
break;
case \'10\':
$elt = "\'notblank\'";
break;
case \'11\':
$elt = "\'blank\'";
break;
}
return $elt;
}
public function translateConditionalAction($action)
{
$elt = "\'\'";
switch ($action) {
case \'1\':
$elt = "\'hide\'";
break;
case \'2\':
$elt = "\'show\'";
break;
case \'3\':
$elt = "\'enable\'";
break;
case \'4\':
$elt = "\'disable\'";
break;
case \'5\':
$elt = "\'make required\'";
break;
}
return $elt;
}
public function translateFieldStyles($style)
{
$styles = array();
switch ($style->fontweight) {
case \'0\':
$styles[\'fontweight\'] = \'\';
break;
case \'1\':
$styles[\'fontweight\'] = \'bold\';
break;
}
return $styles;
}
public function create_custom_css_block($id, $custom_css)
{
if (isset($custom_css->all) && $custom_css->all != "") {
$html = "
" . $custom_css->all . "
";
} else {
if (!isset($custom_css->normal))
return \'\';
$html = <<<EOF
<style type="text/css" scoped>
#{$id}{
{$custom_css->normal}
}
#{$id}:hover{
{$custom_css->over}
}
#{$id}:focus{
{$custom_css->focus}
}
</style>
EOF;
}
$html = str_replace(\'/* This button was generated using CSSButtonGenerator.com */\', \'\', $html);
return $html;
}
public function translateTooltip($tooltip, $id)
{
if ($tooltip->text == "") {
$tooltip_obj = new stdClass();
$tooltip_obj->text = "";
$tooltip_obj->js = "";
return $tooltip_obj;
}
$tooltip_obj = new stdClass();
$tooltip_obj->text = (string)$tooltip->text;
$position = "center right";
switch ($tooltip->position) {
case "0":
$position = "top";
break;
case "1":
$position = "top-center";
break;
case "2":
$position = "right";
break;
case "3":
$position = "right-center";
break;
case "4":
$position = "bottom";
break;
case "5":
$position = "bottom-center";
break;
case "6":
$position = "left";
break;
case "7":
$position = "left-center";
break;
}
$relativeposition = "false";
switch ($tooltip->cssposition) {
case "0":
$relativeposition = "false";
break;
case "1":
$relativeposition = "true";
break;
}
if ($tooltip->events == 0 || $tooltip->events == 1) {
$relativeposition = "relative: \"{$relativeposition}\",";
} else {
$relativeposition = "";
}
$effect = "toggle";
switch ($tooltip->effect) {
case "0":
$effect = "";
break;
case "1":
$effect = "fade";
break;
case "2":
$effect = "slide";
break;
}
switch ($tooltip->events) {
case "0":
$activation = "click";
break;
case "1":
$activation = "over";
break;
case "2":
$activation = "click";
break;
case "3":
$activation = "over";
break;
}
if (!isset($tooltip->bgcolor)) {
$tooltip->bgcolor = "#000000;";
$tooltip->color = "#FFFFFF";
$tooltip->bordercolor = "#FFFFFF";
$tooltip->shadowcolor = "#000000";
}
$button_append_code = "";
if ($tooltip->events == 2 || $tooltip->events == 3) {
$button_append_code = "-tooltip-button";
}
$jscode = <<<EOT
<script type="text/javascript">
// init options
var options = new Array();
options.push("{$id}{$button_append_code}"); // element to watch
options.push("fbtooltip-{$id}"); // tooltip element
options.push("{$position}"); // position
options.push({$tooltip->delay}); // delay
options.push(new Array({$tooltip->offsetx}, {$tooltip->offsety})); // offset
options.push("{$activation}"); // activation
options.push("{$effect}"); // effect
options.push(20); // animation time
options.push({$tooltip->transparency}); // opactity
// init tooltip
var tooltip_{$id} = new RackForms_ToolTip();
tooltip_{$id}.init(options);
</script>
<style type="text/css">
.fbtooltip-{$id} {
background-color:{$tooltip->bgcolor};
border:1px solid {$tooltip->bordercolor};
padding:10px 15px;
width:200px;
display:none;
font-family: Arial;
color:{$tooltip->color};
text-align:left;
font-size:12px;
z-index:99999;
/* effects */
box-shadow:2px 1px 2px {$tooltip->shadowcolor};
border-radius:4px;
/* for older versions of Firefox */
-moz-box-shadow:2px 1px 2px {$tooltip->shadowcolor};
-webkit-box-shadow:2px 1px 2px {$tooltip->shadowcolor};
position: absolute;
}
</style>
EOT;
$tooltip_obj->js = $jscode;
return $tooltip_obj;
}
public function translateTooltip_OLD($tooltip, $id)
{
if ($tooltip->text == "") {
$tooltip_obj = new stdClass();
$tooltip_obj->text = "";
$tooltip_obj->js = "";
return $tooltip_obj;
}
$tooltip_obj = new stdClass();
$tooltip_obj->text = (string)$tooltip->text;
$position = "center right";
switch ($tooltip->position) {
case "0":
$position = "top left";
break;
case "1":
$position = "top center";
break;
case "2":
$position = "top right";
break;
case "3":
$position = "center right";
break;
case "4":
$position = "bottom right";
break;
case "5":
$position = "bottom center";
break;
case "6":
$position = "bottom left";
break;
case "7":
$position = "center left";
break;
}
$relativeposition = "false";
switch ($tooltip->cssposition) {
case "0":
$relativeposition = "false";
break;
case "1":
$relativeposition = "true";
break;
}
if ($tooltip->events == 0 || $tooltip->events == 1) {
$relativeposition = "relative: \"{$relativeposition}\",";
} else {
$relativeposition = "";
}
$effect = "toggle";
switch ($tooltip->effect) {
case "0":
$effect = "toggle";
break;
case "1":
$effect = "fade";
break;
case "2":
$effect = "slide";
break;
}
switch ($tooltip->events) {
case "0":
$events = <<< EOR
events: {
def: "mouseover,mouseout",
input: "focus,blur",
widget: "focus mouseover,blur mouseout",
tooltip: "mouseover,mouseout"
}
EOR;
break;
case "1":
$events = <<< EOR
events: {
def: "mouseover,mouseout",
input: "mouseover,mouseout",
widget: "focus mouseover,blur mouseout",
tooltip: "mouseover,mouseout"
}
EOR;
break;
case "2":
$events = <<< EOR
events: {
def: "mouseover,mouseout",
input: "click,mouseout",
widget: "focus mouseover,blur mouseout",
tooltip: "mouseover,mouseout"
}
EOR;
break;
case "3":
$events = <<< EOR
events: {
def: "mouseover,mouseout",
input: "mouseover,mouseout",
widget: "focus mouseover,blur mouseout",
tooltip: "mouseover,mouseout"
}
EOR;
break;
}
if (!isset($tooltip->bgcolor)) {
$tooltip->bgcolor = "#000000;";
$tooltip->color = "#FFFFFF";
$tooltip->bordercolor = "#FFFFFF";
$tooltip->shadowcolor = "#000000";
}
$button_append_code = "";
if ($tooltip->events == 2 || $tooltip->events == 3) {
$button_append_code = "-tooltip-button";
}
$jscode = <<<EOT
<script type="text/javascript">
// select all desired input fields and attach tooltips to them
// http://flowplayer.org/tools/tooltip/index.html
jQuery("#{$id}{$button_append_code}").tooltip({
// place tooltip in the correct location
position: "{$position}",
// a little tweaking of the position
offset: [{$tooltip->offsety}, {$tooltip->offsetx}],
// use the built-in fadeIn/fadeOut effect
effect: "{$effect}",
// custom opacity setting
opacity: {$tooltip->transparency},
// delay
delay: {$tooltip->delay},
// Position
{$relativeposition}
// class
tipClass: "fbtooltip-{$id}",
// event list
{$events}
});
</script><style type="text/css">
.fbtooltip-{$id} {
background-color:{$tooltip->bgcolor};
border:1px solid {$tooltip->bordercolor};
padding:10px 15px;
width:200px;
display:none;
font-family: Arial;
color:{$tooltip->color};
text-align:left;
font-size:12px;
z-index:99999;
/* effects */
box-shadow:2px 1px 2px {$tooltip->shadowcolor};
/* for older versions of Firefox */
-moz-box-shadow:2px 1px 2px {$tooltip->shadowcolor};
-webkit-box-shadow:2px 1px 2px {$tooltip->shadowcolor};
}
</style>
EOT;
$tooltip_obj->js = $jscode;
return $tooltip_obj;
}
public function translateGradient($selector, $top, $bottom)
{
$css = <<<EOF
<style type="text/css">
/* Background Gradient */
.{$selector}{
background: {$top}; /* Old browsers */
background: -moz-linear-gradient(top, {$top} 0%, {$bottom} 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,{$top}), color-stop(100%,{$bottom})); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, {$top} 0%,{$bottom} 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, {$top} 0%,{$bottom} 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, {$top} 0%,{$bottom} 100%); /* IE10+ */
background: linear-gradient(to bottom, {$top} 0%,{$bottom} 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{$top}\', endColorstr=\'{$bottom}\',GradientType=0 ); /* IE6-9 */
}
</style>
EOF;
return $css;
}
public function translateBorderStyle($style)
{
$border_style = \'\';
switch ((int)$style) {
case 0:
$border_style = \'solid\';
break;
case 1:
$border_style = \'dotted\';
break;
case 2:
$border_style = \'dashed\';
break;
}
return $border_style;
}
public function translateColorpicker($colorpicker, $id)
{
if ((int)$colorpicker->enable == 0) {
$colorpicker_obj = new stdClass();
$colorpicker_obj->jscode = "";
return $colorpicker_obj;
}
$colorpicker_obj = new stdClass();
$colorpicker_obj->jscode = "";
if ((int)$colorpicker->colorbackground == 1) {
$colorbackground = "jQuery(\'#{$id}\').css(\'backgroundColor\', \'#\' + hex);";
} else {
$colorbackground = "";
}
switch ((int)$colorpicker->mode) {
case 0:
$js_mode = <<<EOF
jQuery(\'#fb_fld-{$id}\').ColorPicker({
flat: true,
color: \'{$colorpicker->initialvalue}\',
onChange: function (hsb, hex, rgb) {
{$colorbackground}
jQuery(\'#{$id}\').val(\'#\' + hex);
}
});
EOF;
break;
case 1:
$js_mode = <<<EOF
jQuery(\'#{$id}\').ColorPicker({
color: \'{$colorpicker->initialvalue}\',
onShow: function (colpkr) {
jQuery(colpkr).fadeIn(500);
return false;
},
onHide: function (colpkr) {
jQuery(colpkr).fadeOut(500);
return false;
},
onChange: function (hsb, hex, rgb) {
{$colorbackground}
jQuery(\'#{$id}\').val(\'#\' + hex);
}
});
EOF;
}
if ((string)$colorpicker->customcode != "") {
$js_mode = (string)$colorpicker->customcode;
}
$js_body = <<<EOF
<script type="text/javascript">
// start noConflict()
jQuery.noConflict();
jQuery(document).ready(function() { // http://api.jquery.com/ready/
{$js_mode}
});
</script>
EOF;
$colorpicker_obj->jscode = $js_body;
return $colorpicker_obj;
}
public function translateJslider($jslider, $id)
{
if ((int)$jslider->enable == 0) {
$jslider_obj = new stdClass();
$jslider_obj->jscode = "";
return $jslider_obj;
}
$jslider_obj = new stdClass();
$jslider_obj->jscode = "";
switch ((int)$jslider->skin) {
case 0:
$skin = \'classic\';
break;
case 1:
$skin = \'plastic\';
break;
case 2:
$skin = \'round\';
break;
case 3:
$skin = \'round_plastic\';
break;
}
$format = "";
if ($jslider->format != \'\') {
$format = "format: { {$jslider->format} },";
}
$heterogeneity = "";
if ($jslider->heterogeneity != \'\') {
$heterogeneity = "heterogeneity: [ {$jslider->heterogeneity} ],";
}
$scale = "";
if ($jslider->scale != \'\') {
$scale = "scale: [ {$jslider->scale} ],";
}
$calculate = \'\';
if ($jslider->calulate != \'\') {
$calculate = <<<EOF
calculate: function(value) {
{$jslider->calculate}
},
EOF;
}
$onstatechange = \'\';
if ($jslider->onstatechange != \'\') {
$onstatechange = <<<EOF
onstatechange: function(value) {
{$jslider->onstatechange}
},
EOF;
}
$callback = \'\';
if ($jslider->callback != \'\') {
$callback = <<<EOF
callback: function(value) {
{$jslider->callback}
},
EOF;
}
$js_mode = <<<EOF
slider_{$id} = $("#{$id}").slider({
from: {$jslider->from},
to: {$jslider->to},
step: {$jslider->step},
round: {$jslider->round},
{$format}
{$heterogeneity}
dimension: "{$jslider->dimension}",
limits: "{$jslider->limits}",
{$scale}
skin: "{$skin}",
{$calculate}
{$onstatechange}
{$callback}
smooth: true
});
EOF;
if ((string)$jslider->customcode != "") {
$js_mode = (string)$jslider->customcode;
}
$js_body = <<<EOF
<script type="text/javascript">
var slider_{$id};
$(document).ready(function() { // http://api.jquery.com/ready/
{$js_mode}
});
</script>
EOF;
$jslider_obj->jscode = $js_body;
return $jslider_obj;
}
private function _createConditionalEvent($conditional, $name, $id)
{
$conditionalEvent = $this->translateConditionalEvent((string)$conditional->event);
$conditionalAnimation = $this->translateConditionalAnimation((string)$conditional->animation);
$conditionalCondition = $this->translateConditionalCondition((string)$conditional->condition);
$conditionalValue = (string)$conditional->value == \'\' ? "\'\'" : "\'" . (string)$conditional->value . "\'";
$conditionalAction = $this->translateConditionalAction((string)$conditional->action);
$conditionalField = (string)$conditional->field == \'\' ? "\'\'" : "\'" . (string)$conditional->field . "\'";
$conditionalWrapper = (string)$conditional->wrapper == \'\' ? "\'\'" : "\'" . (string)$conditional->wrapper . "\'";
$conditionalCustom = (string)$conditional->custom;
$conditionalToggle = (int)$conditional->toggle == \'1\' ? \'true\' : \'false\';
if ($conditionalEvent != \'\') {
if ($conditionalCustom == "") {
$conditional_call_inline = " {$conditionalEvent}=\"fbc.handleEvent(event, this.value, $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation);\" ";
$conditional_call_script = "";
} else {
$conditional_call_script = "<script type=\"text/javascript\">";
$js_identifier = (string)$name;
if ((string)$name != (string)$id) {
$js_identifier = (string)$id;
}
$conditional_call_script .= "
function fb_dyn_{$js_identifier}(event, in_value, elt, checked){
";
$conditional_call_script .= $conditionalCustom;
$conditional_call_script .= "}";
$conditional_call_script .= "</script>";
$conditional_call_inline = " {$conditionalEvent}=\"fb_dyn_{$js_identifier}(event, this.value, this, this.checked)\"";
}
} else {
$conditional_call_inline = \'\';
$conditional_call_script = \'\';
}
return array($conditional_call_inline, $conditional_call_script);
}
public function getConditionalEventCode()
{
return $this->_conditionalPageLoadCode;
}
public function resetConditionalEventCode()
{
$this->_conditionalPageLoadCode = "";
}
public function appendConditionalEventCode($code)
{
$this->_conditionalPageLoadCode .= " ";
$this->_conditionalPageLoadCode .= $code;
$this->_conditionalPageLoadCode .= "
";
}
public function prepConditionalEventCode()
{
$tmp = <<<EOT
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
{$this->getConditionalEventCode()}
});
</script>
EOT;
$this->_conditionalPageLoadCode = $tmp;
}
public function addCondtionalLoadEvent($type, $id, $conditional, $samepage)
{
$conditionalEvent = $this->translateConditionalEvent((string)$conditional->event);
$conditionalAnimation = $this->translateConditionalAnimation((string)$conditional->animation);
$conditionalCondition = $this->translateConditionalCondition((string)$conditional->condition);
$conditional_value = str_replace("\'", "\'\'", (string)$conditional->value);
$conditionalValue = (string)$conditional->value == \'\' ? "\'\'" : "\'" . $conditional_value . "\'";
$conditionalAction = $this->translateConditionalAction((string)$conditional->action);
$conditionalField = (string)$conditional->field == \'\' ? "\'\'" : "\'" . (string)$conditional->field . "\'";
$conditionalWrapper = (string)$conditional->wrapper == \'\' ? "\'\'" : "\'" . (string)$conditional->wrapper . "\'";
$conditionalCustom = (string)$conditional->custom;
$conditionalToggle = (int)$conditional->toggle == \'1\' ? \'true\' : \'false\';
if ((string)$type != \'checkbox\' && (string)$type != \'radio\' && (string)$type != \'ecomm\') {
$use_while = 0;
} else {
$use_while = 1;
}
$samepage_code = \'\';
if ($conditionalCustom == "") {
if (!$use_while) {
if ($samepage == true) {
$conditional_call_inline = "fbc.handleEventLoad(\'{$id}\', $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, false, \'\');";
} else {
$conditional_call_inline = <<<EOF
<?php
// conditional call load code for: {$id}
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'{$id}\'])) {
\$fb_samepage_val = \$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'{$id}\'];
} else {
\$fb_samepage_val = \'\';
}
\$fb_samepage_val = str_replace("\'", "\\'", \$fb_samepage_val);
?>
fbc.handleEventLoad(\'{$id}\', {$conditionalCondition}, {$conditionalValue}, {$conditionalAction}, {$conditionalField}, {$conditionalWrapper}, {$conditionalToggle}, {$conditionalAnimation}, false, \'<?php echo \$fb_samepage_val; ?>\');
EOF;
}
} else {
if ($samepage == true) {
$conditional_call_inline = <<<EOF
// create list of valid indexes for: {$id}
j = new Array();
for(k = 0; k < 1000; k++){
if(document.getElementById(\'{$id}\' + k) !== null){
j.push(\'{$id}\' + k);
}
}
for(t = 0; t < j.length; t++){
if(fbc.handleEventLoad(j[t], $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, true)){
break;
}
}
EOF;
} else {
$conditional_call_inline = <<<EOF
<?php
// conditional call load code for: {$id}
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'{$id}\'])) {
\$fb_samepage_val = \$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\'{$id}\'];
} else {
\$fb_samepage_val = \'\';
}
// iterate over collection
if(is_array(\$fb_samepage_val)){ // checkbox
foreach(\$fb_samepage_val as \$fb_tmp_sp_val){
echo "fbc.handleEventLoad(\'{$id}\', $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, false, \'{\$fb_tmp_sp_val}\');";
}
} else { // radio
echo "fbc.handleEventLoad(\'{$id}\', $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, false, \'{\$fb_samepage_val}\');";
}
?>
EOF;
}
}
$this->appendConditionalEventCode($conditional_call_inline);
} else {
if (!$use_while) {
$conditionalCustom = "
// custom call for {$id} --
{$conditionalCustom}
// end call for {$id}
";
$conditionalCustom = str_replace(\'hideField\', \'hideFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showField\', \'showFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'hideWrapper\', \'hideWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showWrapper\', \'showWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'Field(event\', "Field(\'{$id}\'", $conditionalCustom);
$conditionalCustom = str_replace(\'Wrapper(event\', "Wrapper(\'{$id}\'", $conditionalCustom);
$conditionalCustom = str_replace(\'Load(event\', "Load(\'{$id}\'", $conditionalCustom);
$conditionalCustom = str_replace(\'in_value\', "document.getElementById(\'{$id}\').value", $conditionalCustom);
$this->appendConditionalEventCode($conditionalCustom);
} else {
if ((string)$type == \'checkbox\') {
$conditionalCustomCode = $conditionalCustom;
$conditionalCustomCode = str_replace(\'hideField\', \'hideFieldLoad\', $conditionalCustomCode);
$conditionalCustomCode = str_replace(\'showField\', \'showFieldLoad\', $conditionalCustomCode);
$conditionalCustomCode = str_replace(\'hideWrapper\', \'hideWrapperLoad\', $conditionalCustomCode);
$conditionalCustomCode = str_replace(\'showWrapper\', \'showWrapperLoad\', $conditionalCustomCode);
$conditionalCustom = "
// Custom Call Checkbox onLoad Rewrite For: {$id} --
";
$conditionalCustom .= <<<EOF
// create list of valid indexes for: {$id}
j = new Array();
for(k = 0; k < 1000; k++){
if(document.getElementById(\'{$id}\' + k) !== null){
j.push(\'{$id}\' + k);
}
}
for(t = 0; t < j.length; t++){
var in_value = \'\';
var checked = false;
if(document.getElementById(j[t]) !== null){
if(document.getElementById(j[t]).checked) { checked = true; }
in_value = document.getElementById(j[t]).value;
}
//console.log(in_value, checked, j[t]);
// Original Code Start
{$conditionalCustomCode}
// Original Code End
}
EOF;
$conditionalCustom = str_replace(\'Field(event\', "Field(\'{$id}\' + k", $conditionalCustom);
$conditionalCustom = str_replace(\'Wrapper(event\', "Wrapper(\'{$id}\' + k", $conditionalCustom);
$conditionalCustom = str_replace(\'Load(event\', "Load(\'{$id}\' + k", $conditionalCustom);
$this->appendConditionalEventCode($conditionalCustom);
} else {
$conditionalCustom = "
// custom call onLoad rewrite for {$id} --
{$conditionalCustom}
// end call for {$id}
";
$conditionalCustom = str_replace(\'hideField\', \'hideFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showField\', \'showFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'hideWrapper\', \'hideWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showWrapper\', \'showWrapperLoad\', $conditionalCustom);
$conditionalCustomLoop = <<<EOF
// get value of valid, active radio item for {$id}
in_value = \'\'; // set default
for(k = 0; k < 1000; k++){
if(document.getElementById(\'{$id}\' + k) !== null){
if(document.getElementById(\'{$id}\' + k).checked){
in_value = document.getElementById(\'{$id}\' + k).value;
break;
}
}
}
EOF;
$conditionalCustom = $conditionalCustomLoop . $conditionalCustom;
$conditionalCustom = str_replace(\'Field(event\', "Field(\'{$id}\' + k", $conditionalCustom);
$conditionalCustom = str_replace(\'Wrapper(event\', "Wrapper(\'{$id}\' + k", $conditionalCustom);
$conditionalCustom = str_replace(\'Load(event\', "Load(\'{$id}\' + k", $conditionalCustom);
$this->appendConditionalEventCode($conditionalCustom);
}
}
}
}
public function addCondtionalLoadEventForBucketRepeaters($type, $id, $conditional)
{
$ret_start = "
<script type=\"text/javascript\">
";
$ret_end = "
</script>
";
$conditionalAnimation = $this->translateConditionalAnimation((string)$conditional->animation);
$conditionalCondition = $this->translateConditionalCondition((string)$conditional->condition);
$conditionalValue = (string)$conditional->value == \'\' ? "\'\'" : "\'" . (string)$conditional->value . "\'";
$conditionalAction = $this->translateConditionalAction((string)$conditional->action);
$conditionalField = (string)$conditional->field == \'\' ? "\'\'" : "\'" . (string)$conditional->field . "\'";
$conditionalWrapper = (string)$conditional->wrapper == \'\' ? "\'\'" : "\'" . (string)$conditional->wrapper . "\'";
$conditionalCustom = (string)$conditional->custom;
$conditionalToggle = (int)$conditional->toggle == \'1\' ? \'true\' : \'false\';
if ((string)$type != \'checkbox\' && (string)$type != \'radio\' && (string)$type != \'ecomm\') {
$use_while = 0;
} else {
$use_while = 1;
}
if ($conditionalCustom == "") {
if (!$use_while) {
$conditional_call_inline = "fbc.handleEventLoad(\'{$id}\', $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, false);";
} else {
$conditional_call_inline = <<<EOF
// create list of valid indexes for: {$id}
j = new Array();
for(k = 0; k < 1000; k++){
if(document.getElementById(\'{$id}\' + k) !== null){
j.push(\'{$id}\' + k);
}
}
for(t = 0; t < j.length; t++){
if(fbc.handleEventLoad(j[t], $conditionalCondition, $conditionalValue, $conditionalAction, $conditionalField, $conditionalWrapper, $conditionalToggle, $conditionalAnimation, true)){
break;
}
}
EOF;
}
$ret = $ret_start;
$ret .= $conditional_call_inline;
$ret .= $ret_end;
return $ret;
} else {
if (!$use_while) {
$conditionalCustom = "
// custom call for {$id} --
{$conditionalCustom}
// end call for {$id}
";
$conditionalCustom = str_replace(\'hideField\', \'hideFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showField\', \'showFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'hideWrapper\', \'hideWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showWrapper\', \'showWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'event\', "\'{$id}\'", $conditionalCustom);
$conditionalCustom = str_replace(\'in_value\', "document.getElementById(\'{$id}\').value", $conditionalCustom);
$ret = $ret_start;
$ret .= $conditionalCustom;
$ret .= $ret_end;
return $ret;
} else {
$conditionalCustom = "
// custom call onLoad rewrite for {$id} --
{$conditionalCustom}
// end call for {$id}
";
$conditionalCustom = str_replace(\'hideField\', \'hideFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showField\', \'showFieldLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'hideWrapper\', \'hideWrapperLoad\', $conditionalCustom);
$conditionalCustom = str_replace(\'showWrapper\', \'showWrapperLoad\', $conditionalCustom);
$conditionalCustomLoop = <<<EOF
// get value of valid, active radio item for {$id}
in_value = \'\'; // set default
for(k = 0; k < 1000; k++){
if(document.getElementById(\'{$id}\' + k) !== null){
if(document.getElementById(\'{$id}\' + k).checked){
in_value = document.getElementById(\'{$id}\' + k).value;
break;
}
}
}
EOF;
$conditionalCustom = $conditionalCustomLoop . $conditionalCustom;
$conditionalCustom = str_replace(\'event\', "\'{$id}\' + k", $conditionalCustom);
$ret = $ret_start;
$ret .= $conditionalCustom;
$ret .= $ret_end;
return $ret;
}
}
}
public function create_inline_field_vars($text, $separator = \', \')
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(@\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
if ($m == \'TODAYS_DATE\') {
$text = str_replace(\'@{\' . $m . \'}\', "<?php echo date(\'m/d/Y\', time()); ?>", $text);
} else if ($m == \'TODAYS_DATE_EU\') {
$text = str_replace(\'@{\' . $m . \'}\', "<?php echo date(\'d/m/Y\', time()); ?>", $text);
} else {
$text = str_replace(\'@{\' . $m . \'}\', "<?php if(isset(\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\'])) { echo \"{\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']}\"; }?>", $text);
}
}
}
$dyn_vars = implode(\',\', $array_vars);
$element = <<<EOT
<?php
// Process Array Variables.
if(!isset(\$array_vars_processed)){
// check for and replace array based variables if not already done
\$vars = array({$dyn_vars});
foreach(\$vars as \$var){
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
if(is_array(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
\$field_items = \'\';
foreach(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] as \$key=>\$v){
if(\$key != 0){ \$field_items .= \'{$separator}\'; }
\$field_items .= \$v;
}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] = \$field_items;
}
}
}
\$array_vars_processed = true;
}
?>
EOT;
$element = <<<EOT
<?php
// Process Array Variables.
if(!isset(\$array_vars_processed)){ \$vars = array({$dyn_vars}); process_array_variables(\$vars, \'{$separator}\'); \$array_vars_processed = true; }
?>
EOT;
return array($text, $element);
}
public function createTabIndexCode($tabindex)
{
$tabhtml = \'\';
if (isset($tabindex) && $tabindex != \'\' && is_int($tabindex)) {
$tabhtml = "tabindex=\"{$tabindex}\"";
}
return $tabhtml;
}
public function create_inline_get_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(#\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'#{\' . $m . \'}\', "<?php if(isset(\$_GET[\'{$m}\'])) { echo \"{\$_GET[\'{$m}\']}\"; }?>", $text);
}
}
return $text;
}
public function create_inline_post_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(\*\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'*{\' . $m . \'}\', "<?php if(isset(\$_POST[\'{$m}\'])) { echo \"{\$_POST[\'{$m}\']}\"; }?>", $text);
}
}
return $text;
}
public function create_inline_session_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(\^\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'^{\' . $m . \'}\', "<?php if(isset(\$_SESSION[\'{$m}\'])) { echo \"{\$_SESSION[\'{$m}\']}\"; }?>", $text);
}
}
return $text;
}
public function create_inline_php_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(PHP\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'${\' . $m . \'}\', "<?php if(isset(\${$m})) { echo \${$m}; } ?>", $text);
}
}
return $text;
}
public function create_embedded_field_vars($text, $separator = \', \')
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(@\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'@{\' . $m . \'}\', "\$_SESSION[\'qs\'][\"{\$_SESSION[\'entry_key\']}\"][\'{$m}\']", $text);
}
}
$dyn_vars = implode(\',\', $array_vars);
$element = <<<EOT
<?php
if(!isset(\$array_vars_processed)){
// check for and replace array based variables if not already done
\$vars = array({$dyn_vars});
foreach(\$vars as \$var){
if(isset(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
if(is_array(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var])){
\$field_items = \'\';
foreach(\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] as \$key=>\$v){
if(\$key != 0){ \$field_items .= \'{$separator}\'; }
\$field_items .= \$v;
}
\$_SESSION[\'qs\']["{\$_SESSION[\'entry_key\']}"][\$var] = \$field_items;
}
}
}
\$array_vars_processed = true;
}
?>
EOT;
$element = <<<EOT
<?php
// Process Array Variables.
if(!isset(\$array_vars_processed)){ \$vars = array({$dyn_vars}); process_array_variables(\$vars, \'{$separator}\'); \$array_vars_processed = true; }
?>
EOT;
return array($text, $element);
}
public function create_embedded_get_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(#\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'#{\' . $m . \'}\', "\$_GET[\'{$m}\']", $text);
}
}
return $text;
}
public function create_embedded_post_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(\*\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'*{\' . $m . \'}\', "\$_POST[\'{$m}\']", $text);
}
}
return $text;
}
public function create_embedded_session_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(\^\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'^{\' . $m . \'}\', "\$_SESSION[\'{$m}\']", $text);
}
}
return $text;
}
public function create_embedded_php_vars($text)
{
$matches = array();
$text = (string)$text;
preg_match_all(\'/(^|.|
|
)?(PHP\{(.*?)\})/\', $text, $matches);
$array_vars = array();
if (isset($matches[3])) {
foreach ($matches[3] as $m) {
$array_vars[] = "\'$m\'";
$text = str_replace(\'PHP{\' . $m . \'}\', "\${$m}", $text);
}
}
return $text;
}
}
?>'
Did this file decode correctly?
Original Code
<?php /* Copyright (c) Nicsoft LLC */ eval( '?>' . base64_decode('PD9waHANCg0KaW5jbHVkZSAnLi4vaW5jL2F1dGhfaGVhZGVyLnBocCc7DQoNCmNsYXNzIEZvcm1FbGVtZW50cw0Kew0KDQogICAgcHVibGljICR1diA9ICIiOw0KICAgIHB1YmxpYyAkdW0gPSAiIjsNCiAgICBwdWJsaWMgJHBkZiA9ICIiOw0KICAgIHB1YmxpYyAkY2UgPSAiIjsNCiAgICBwdWJsaWMgJGpvYm5hbWUgPSAiIjsNCg0KICAgIHB1YmxpYyAkX2RlYnVnU2Vzc2lvbiA9IGZhbHNlOw0KDQogICAgcHVibGljICRwaHBfZWxlbWVudHMgPSAiIjsgDQoNCiAgICBwcml2YXRlICRfY29uZGl0aW9uYWxQYWdlTG9hZENvZGU7DQoNCiAgICBmdW5jdGlvbiBfX2NvbnN0cnVjdCgpDQogICAgew0KICAgICAgICANCiAgICAgICAgJHRoaXMtPnV2ID0gbmV3IFV0aWxpdHlfVmFyaWFibGUoKTsNCiAgICAgICAgJHRoaXMtPnVtID0gbmV3IFV0aWxpdHlfTWV0aG9kcygpOw0KDQoNCiAgICAgICAgDQogICAgICAgICR0aGlzLT5wZGYgPSBuZXcgUERGKCk7DQoNCiAgICAgICAgDQogICAgICAgICR0aGlzLT5jZSA9IG5ldyBDb21tb25FbGVtZW50cygpOw0KDQogICAgICAgICR0aGlzLT5waHBfZWxlbWVudHMgPSBuZXcgUEhQRWxlbWVudHMoKTsgDQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIHNldEpvYk5hbWUoKXsNCiAgICAgICAgJHRoaXMtPnVtLT5qb2JuYW1lID0gJHRoaXMtPmpvYm5hbWU7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9waHBfdGltZXN0YW1wKCkNCiAgICB7DQogICAgICAgICRub3cgPSB0aW1lKCk7DQogICAgICAgICRkYXRlID0gIGRhdGUoIkYgaiwgWSIsICRub3cpOw0KICAgICAgICAkc3RyID0gIi8vLS1cbiIgLiAiLy8gUEhQIFBhZ2UgU2NyaXB0IC0gR2VuZXJhdGVkOiAiIC4gJGRhdGUgLiAiXG4vLy0tXG4iOw0KICAgICAgICByZXR1cm4gJHN0cjsNCiAgICB9DQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3BocF9vcGVuX2Jsb2NrKA0KICAgICAgICAkcGFnZWFycmF5LA0KICAgICAgICAkbmFtZSwNCiAgICAgICAgJHBocHRvcCwNCiAgICAgICAgJHNlY3VyaXR5X2FycmF5LA0KICAgICAgICAkam9iX2lkLA0KICAgICAgICAkcGhwcGF0aCwNCiAgICAgICAgJGRpcmVjdGFjY2VzcywNCiAgICAgICAgJHBlcnNpc3RhbmNlLA0KICAgICAgICAkYW5hbHl0aWNzZGF0YSwNCiAgICAgICAgJHBhZ2UsDQogICAgICAgICR4bWwNCiAgICApIHsNCg0KICAgICAgICAkdHMgPSAkdGhpcy0+Y3JlYXRlX3BocF90aW1lc3RhbXAoKTsNCg0KICAgICAgICBpZiAoJGRpcmVjdGFjY2VzcyA9PSBudWxsKSB7DQogICAgICAgICAgICAkZGlyZWN0YWNjZXNzID0gMDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkZGlyZWN0YWNjZXNzID09ICIiKSB7DQogICAgICAgICAgICAkZGlyZWN0YWNjZXNzID0gMDsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkZGlyZWN0YWNjZXNzICE9IDEpIHsNCiAgICAgICAgICAgICRkaXJlY3RhY2Nlc3MgPSAwOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJHBlcnNpc3RhbmNlKSB8fCAoaW50KSRwZXJzaXN0YW5jZSA9PSAiIikgew0KICAgICAgICAgICAgJHBlcnNpc3RhbmNlID0gMDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkYW5hbHl0aWNzZGF0YSA9PSAiIikgew0KICAgICAgICAgICAgJGFuYWx5dGljc2RhdGEgPSAwOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRhbmFseXRpY3NkYXRhID0gKGludCkkYW5hbHl0aWNzZGF0YTsNCg0KICAgICAgICBpZiAoJHBocHBhdGggPT0gJ05vdCBTZXQnKSB7DQogICAgICAgICAgICAkcGhwcGF0aCA9ICcnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKChzdHJpbmcpJHBocHRvcCAhPT0gJycpIHsNCiAgICAgICAgICAgICRwaHB0b3AgPSAkcGhwdG9wIC4gIlxuIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZG9tYWluX2xpc3QgPSAoc3RyaW5nKSRzZWN1cml0eV9hcnJheS0+ZG9tYWluX2xpc3Q7DQogICAgICAgICRpcF9saW1pdCA9IChpbnQpJHNlY3VyaXR5X2FycmF5LT5pcF9saW1pdDsNCiAgICAgICAgJGlwX2xpbWl0X21lc3NhZ2Vfc3RhcnQgPSAiPDw8RU9UIjsNCiAgICAgICAgJGlwX2xpbWl0X21lc3NhZ2VfZW5kID0gIkVPVDsiOw0KDQogICAgICAgICRpcF9saW1pdF9kdXJhdGlvbiA9IChpbnQpJHNlY3VyaXR5X2FycmF5LT5pcF9saW1pdF9kdXJhdGlvbjsNCg0KICAgICAgICANCiAgICAgICAgJGRlbHRhID0gMDsNCiAgICAgICAgc3dpdGNoICgkaXBfbGltaXRfZHVyYXRpb24pIHsNCiAgICAgICAgICAgIGNhc2UgJzAnOg0KICAgICAgICAgICAgICAgICRkZWx0YSA9IDMxNTU2OTI2MDA7IA0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJGRlbHRhID0gODY0MDA7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAkZGVsdGEgPSA2MDQ4MDA7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICczJzoNCiAgICAgICAgICAgICAgICAkZGVsdGEgPSAyNjI5NzQzOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgJGRlbHRhID0gMzE1NTY5MjY7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkcGhwdG9wID0gKHN0cmluZykkcGhwdG9wOw0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pKCNceyguKj8pXH0pLycsICRwaHB0b3AsICRtYXRjaGVzKTsNCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkcGhwdG9wID0gc3RyX3JlcGxhY2UoJyN7JyAuICRtIC4gJ30nLCAiXCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3skbX0nXSIsICRwaHB0b3ApOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJHBocHRvcCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJHBocHRvcCwgMCk7DQoNCiAgICAgICAgJGlwX2xpbWl0X21lc3NhZ2UgPSAoc3RyaW5nKSRzZWN1cml0eV9hcnJheS0+aXBfbGltaXRfbWVzc2FnZTsNCg0KICAgICAgICAkYWN0aXZlID0gKGludCkkc2VjdXJpdHlfYXJyYXktPmFjdGl2ZTsNCiAgICAgICAgJGFjdGl2ZV9tZXNzYWdlID0gKHN0cmluZykkc2VjdXJpdHlfYXJyYXktPmFjdGl2ZV9tZXNzYWdlOw0KICAgICAgICAkYWN0aXZlX21lc3NhZ2Vfc3RhcnQgPSAiPDw8RU9UIjsNCiAgICAgICAgJGFjdGl2ZV9tZXNzYWdlX2VuZCA9ICJFT1Q7IjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkc2VjdXJpdHlfYXJyYXktPmxvZ2luKSkgew0KICAgICAgICAgICAgJHNlY3VyaXR5X2FycmF5LT5sb2dpbiA9IDA7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkY29uZGl0aW9uX2NvZGUgPSAnJzsNCg0KICAgICAgICANCg0KICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZvcm0tPmN1c3RvbWNvbmRpdGlvbmNvZGUpICYmICRwYWdlLT5mb3JtLT5vbnN1Y2Nlc3MgIT0gIiIpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZm9ybV9maWVsZF9hcnJheSA9ICJcJGZvcm1fZmllbGRzID0gYXJyYXkoIjsNCg0KICAgICAgICAgICAgJGN0ID0gMDsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRwYWdlLT5mb3JtLT5maWVsZCBhcyAkZmllbGRfdG1wKSB7DQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZF90bXAtPm5hbWUpKSB7DQogICAgICAgICAgICAgICAgICAgIGlmICgkY3QgIT0gMCkNCiAgICAgICAgICAgICAgICAgICAgJGZvcm1fZmllbGRfYXJyYXkgLj0gIiwgIjsNCiAgICAgICAgICAgICAgICAgICAgJGZvcm1fZmllbGRfYXJyYXkgLj0gIiciIC4gKHN0cmluZykkZmllbGRfdG1wLT5uYW1lIC4gIiciOw0KICAgICAgICAgICAgICAgICAgICAkY3QrKzsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRmb3JtX2ZpZWxkX2FycmF5IC49ICIpIjsNCg0KDQogICAgICAgICAgICAkY29uZGl0aW9uID0gJHRoaXMtPnJlcGxhY2VfY29uZGl0aW9uX3ZhcnMoJHBhZ2UtPmZvcm0tPmN1c3RvbWNvbmRpdGlvbmNvZGUpOw0KDQogICAgICAgICAgICBpZiAoKHN0cmluZykkY29uZGl0aW9uICE9ICcnKSB7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbl9jb2RlID0gPDw8RU9GDQovLyBDb25kaXRpb25hbCBQYWdlIENvZGUgU3RhcnQNCmlmKHskY29uZGl0aW9ufSl7DQoNCgl7JGZvcm1fZmllbGRfYXJyYXl9Ow0KCQ0KCS8vIFVuc2V0IEV4aXN0aW5nIFZhbHVlcw0KCWZvcmVhY2goXCRmb3JtX2ZpZWxkcyBhcyBcJGZpZWxkKXsNCgkJaWYoaXNzZXQoXCRfU0VTU0lPTlsie1wkZmllbGR9Il0pKQ0KCQkJdW5zZXQoXCRfU0VTU0lPTlsie1wkZmllbGR9Il0pOw0KCQkJDQoJCWlmKGlzc2V0KFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkZmllbGR9Il0gKSkNCgkJCXVuc2V0KCBcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bIntcJGZpZWxkfSJdICApOw0KCQkJDQoJfQ0KDQoJXCRfU0VTU0lPTlsncGFnZXMtcGFzc2VkJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsneyRuYW1lfSddID0gJ3Bhc3MnOyAvLyBhbGxvdyBwYWdlIHNraXAuDQoJXCRfU0VTU0lPTlsncGFnZXMnXVsneyRwYWdlLT5mb3JtLT5vbnN1Y2Nlc3N9J10gPSAncGFzcyc7IC8vIGFsbG93IHBhZ2Ugc2tpcC4NCgkNCgloZWFkZXIoIkxvY2F0aW9uOiB7JHBhZ2UtPmZvcm0tPm9uc3VjY2Vzc30iKTsNCgkNCglleGl0KDApOw0KfQ0KRU9GOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICBpZiAoKGludCkkcGFnZS0+ZXhwb3J0bW9kZSA9PSAzKXsNCiAgICAgICAgICAgICRkaXJlY3RhY2Nlc3MgPSB0cnVlOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJHNlY3VyaXR5X2FycmF5LT5wZXJzaXN0ZW50X2xvZ2luKSkgew0KICAgICAgICAgICAgJHNlY3VyaXR5X2FycmF5LT5wZXJzaXN0ZW50X2xvZ2luID0gIjAiOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYoIWlzc2V0KCRzZWN1cml0eV9hcnJheS0+cmFja2Zvcm1zbG9naW4pKXsNCiAgICAgICAgICAgICRzZWN1cml0eV9hcnJheS0+cmFja2Zvcm1zbG9naW4gPSAiMCI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGZpcnN0UGFnZUlzUEhQSW5jbHVkZSA9IGZhbHNlOw0KDQogICAgICAgIGlmICgoaW50KSR4bWwtPnBhZ2VbMF0tPmV4cG9ydG1vZGUgPT0gNSkgew0KDQogICAgICAgICAgICAkZmlyc3RQYWdlSXNQSFBJbmNsdWRlID0gdHJ1ZTsNCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkY2FzcGFnZWFjY2Vzc2xldmVsID0gIiI7DQogICAgICAgIA0KICAgICAgICBpZihpc3NldCgkcGFnZS0+c2VjdXJpdHktPmNhcy0+cGFnZWFjY2Vzc2xldmVsKSl7DQogICAgICAgICAgICAkY2FzcGFnZWFjY2Vzc2xldmVsID0gJHBhZ2UtPnNlY3VyaXR5LT5jYXMtPnBhZ2VhY2Nlc3NsZXZlbDsgDQogICAgICAgIH0NCg0KDQogICAgICAgICRkaXJlY3RfYWNjZXNzID0gJyc7DQogICAgICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYoJGRpcmVjdGFjY2Vzcyl7DQogICAgICAgICAgICAkZGlyZWN0X2FjY2VzcyA9ICJcclxuLy8gSWYgQWxsb3dpbmcgRGlyZWN0IEFjY2VzcywgQWRkIFRoaXMgUGFnZSBUbyBQYXNzZWQgQXJyYXkgSW4gQ2FzZSBXZSBSZWRpcmVjdCBCZWZvcmUgU3VibWlzc2lvbi5cclxuIjsNCiAgICAgICAgICAgICRkaXJlY3RfYWNjZXNzIC49ICJcJF9TRVNTSU9OWydwYWdlcyddWyd7JHBhZ2UtPmZvcm0tPm9uc3VjY2Vzc30nXSA9ICdwYXNzJztcclxuIjsNCiAgICAgICAgfQ0KDQogICAgICAgICRfc2Vzc2lvbkRlYnVnQ29kZSA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICANCgkJaWYoJHRoaXMtPl9kZWJ1Z1Nlc3Npb24gPT0gdHJ1ZSl7DQoJCQkkX3Nlc3Npb25EZWJ1Z0NvZGUgPSA8PDxFT0YNCmVjaG8gJzxwcmU+JyAuIFwkX1NFU1NJT05bJ2VudHJ5X2tleSddIC4gJzwvcHJlPic7DQplY2hvICc8cHJlPjx0ZXh0YXJlYSBzdHlsZT0id2lkdGg6MTAwJTsgaGVpZ2h0OiA2MDBweDsgZm9udC1zaXplOjhwdDsiPic7IHByaW50X3IoXCRfU0VTU0lPTik7IGVjaG8gJzwvdGV4dGFyZWE+PC9wcmU+JzsNCkVPRjsNCgkJfQ0KICAgICAgICAgICAgDQogICAgICAgIGlmIChjb3VudCgkcGFnZWFycmF5KSA9PSAwIHx8ICRkaXJlY3RhY2Nlc3MgfHwgJGZpcnN0UGFnZUlzUEhQSW5jbHVkZSA9PSB0cnVlKSB7IA0KICAgICAgICAgICAgJGVsZW1lbnQgPSA8PDxFT1QNCnskcGhwdG9wfTw/cGhwDQp7JHRzfQ0KaWYoZnVuY3Rpb25fZXhpc3RzKCdpbmlfc2V0Jykpew0KCWluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgMCk7IC8vIENoYW5nZSB0byAxIHRvIGRpc3BsYXkgYWxsIGVycm9yIG1lc3NhZ2VzLg0KCWluaV9zZXQoJ2Vycm9yX3JlcG9ydGluZycsIEVfQUxMKTsNCn0NCg0KLy8gU3RhcnQgb3VyIG1haW4gc2Vzc2lvbi4NCg0KaWYoIXNlc3Npb25faWQoKSkgeyBzZXNzaW9uX3N0YXJ0KCk7IH0NCg0KeyRkaXJlY3RfYWNjZXNzfQ0KDQovLyBTSUQgU3VwcG9ydCAtIFJlZGlyZWN0IGFuZCBhcHBlbmQgU0lEIGlmIG5lZWRlZC4gDQovLyBBbGxvd3MgU0VTU0lPTiBWYXJzIHRvIGJlIHNhdmVkIG9uIGZpcnN0IHBhZ2UuDQovLyBTZXJ2ZXIgTVVTVCBoYXZlIHNlc3Npb24udXNlX3RyYW5zX3NpZCBlbmFibGVkLg0KDQpcJHNpZF91cmwgPSAiIjsNCg0KaWYoZGVmaW5lZCgnU0lEJykpDQoJXCRzaWRfdXJsID0gKHN0cmxlbihTSUQpID8gKCc/JyAuIGh0bWxzcGVjaWFsY2hhcnMoU0lEKSkgOiAnJyk7DQoNCnskY29uZGl0aW9uX2NvZGV9DQoNCi8vIFBhdGggaW5mbyBmb3IgUEhQIEluY2x1ZGUNClwkX1NFU1NJT05bJ01BWF9QQVRIJ10gPSAneyRwaHBwYXRofSc7DQpcJGN0X3RtcCA9ICcnOw0KXCRjdCA9IHN1YnN0cl9jb3VudCgneyRwaHBwYXRofScsICIvIik7DQpcJF9TRVNTSU9OWydNQVhfUEFUSF9QUk9DJ10gPSAnLi8nOw0KLy8gQnVpbGQgNjMyIC0gUmVmaW5lIHRoaXMgY2hlY2sNCmlmKFwkY3QgIT0gMCl7IC8vIGlmIGEgUEhQIEV4cG9ydCBQYXRoIGlzIHNldCwgd2UgbmVlZCB0byBjcmVhdGUgYSBwYXRoICpiYWNrKiB0byB0aGUgaW5jbHVkZSBjYWxsaW5nIGZpbGUNCgl3aGlsZShcJGN0ICE9IDApew0KCQlcJGN0X3RtcCAuPSAnLi4vJzsNCgkJXCRjdC0tOw0KCX0NCglcJF9TRVNTSU9OWydNQVhfUEFUSF9QUk9DJ10gPSBcJGN0X3RtcDsNCn0NCi8vIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEhfUFJPQyddOyAvLyBVbmNvbW1lbnQgdG8gc2VlIHdoaWNoIHBhdGggUmFja0Zvcm1zIGlzIHVzaW5nIHRvIHByb2Nlc3MgcGFnZXMNCg0KLy8gSUUgUDNQIFBvbGljeSBIZWFkZXIgLSBtdXN0IHNlbmQgdG8gYWxsb3cgM3JkIHBhcnR5IGNvb2tpZXMgKHdoZW4gZm9ybSBwYWdlIHVzZWQgYXMgaUZyYW1lIGluY2x1ZGUpDQpoZWFkZXIoJ1AzUDogQ1A9IklEQyBEU1AgQ09SIENVUmEgQURNYSBPVVIgSU5EIFBIWSBPTkwgQ09NIFNUQSInKTsNCg0KLy8gQnVpbGQgNjk1IC0gV2Ugbm93IGNyZWF0ZSB0aGlzIGtleSBoZXJlIGFzIHdlbGwgYXMgb24gcHJvY2VzcyBwYWdlcy4NClwkX1NFU1NJT05bImVudHJ5X2tleSJdID0gaXNzZXQoXCRfU0VTU0lPTlsiZW50cnlfa2V5Il0pID8gXCRfU0VTU0lPTlsiZW50cnlfa2V5Il0gOiBtZDUodGltZSgpICsgcmFuZCgxMDAwMCwgMTAwMDAwMCkpOw0KDQoNCi8vDQovLyBGb3JtIFBhZ2UgU2VjdXJpdHkgLSBJbml0aWFsIFBhZ2UgVmFyaWFibGVzDQovLw0KDQpcJGRvbWFpbl9saXN0ID0gZXhwbG9kZSgnLCcsInskZG9tYWluX2xpc3R9Iik7DQpcJGlwX2xpbWl0ID0geyRpcF9saW1pdH07DQpcJGpvYl9pZCA9ICd7JGpvYl9pZH0nOw0KXCRqb2JfbmFtZSA9ICJ7JHhtbC0+am9ibmFtZX0iOw0KXCRpcF9saW1pdF9tZXNzYWdlID0geyRpcF9saW1pdF9tZXNzYWdlX3N0YXJ0fQ0KeyRpcF9saW1pdF9tZXNzYWdlfQ0KeyRpcF9saW1pdF9tZXNzYWdlX2VuZH0NClwkaXBfbGltaXRfZHVyYXRpb24gPSB7JGlwX2xpbWl0X2R1cmF0aW9ufTsNClwkZGVsdGEgPSB7JGRlbHRhfTsNCg0KXCRhY3RpdmUgPSB7JGFjdGl2ZX07DQpcJGFjdGl2ZV9tZXNzYWdlID0geyRhY3RpdmVfbWVzc2FnZV9zdGFydH0NCnskYWN0aXZlX21lc3NhZ2V9DQp7JGFjdGl2ZV9tZXNzYWdlX2VuZH0NCg0KLy8gSW5jbHVkZSBVdGlsaXR5IENsYXNzZXMuDQoNCmluY2x1ZGVfb25jZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119bGliL3V0aWxpdHkucGhwIjsNCg0KDQovLw0KLy8gRm9ybSBQZXJzaXN0ZW5jZSBDaGVjayAtIEluaXRpYWwgUGFnZS4NCi8vDQoNClwkZm9ybV9wZXJzaXN0ZW5jZV9jaGVjayA9IHskcGVyc2lzdGFuY2V9Ow0KDQppZihcJGZvcm1fcGVyc2lzdGVuY2VfY2hlY2sgPT0gMyl7DQoJaWYoIWlzc2V0KFwkX1NFU1NJT05bJ2ZiX2VudHJ5X2lkX2F1dG8nXSkpew0KCQ0KCQlcJF9TRVNTSU9OIFsnZmJfZW50cnlfaWRfYXV0byddID0gaXNzZXQoXCRfR0VUWydSSUQnXSkgPyBmaWx0ZXJfaW5wdXQoSU5QVVRfR0VULCAnUklEJywgRklMVEVSX1VOU0FGRV9SQVcpIDogIiI7DQoJCQ0KCQlpZihcJF9TRVNTSU9OWydmYl9lbnRyeV9pZF9hdXRvJ10gPT0gIiIpew0KCQkJXCRfU0VTU0lPTlsnZmJfZW50cnlfaWRfYXV0byddID0gcmFuZG9tUGFzc3dvcmQoKTsNCgkJfQ0KCX0NCn0NCg0KXCRwYWdlbmFtZSA9ICJ7JG5hbWV9IjsgLy8gVXNlZCBGb3IgQnVja2V0IFBvcHVsYXRpb24sIEV0Yy4NCg0KLy8NCi8vIExvYWQgUGVyc2lzdGVudCBWYWx1ZXMgLSBJbml0aWFsIFBhZ2UuDQovLw0KDQpsb2FkUGVyc2lzdGFudFZhbHVlcyh7JHBlcnNpc3RhbmNlfSwgXCRqb2JfaWQsICJ7JG5hbWV9Iik7DQoNCg0KLy8NCi8vIFJhY2tGb3JtcyBMb2dpbiBMb2dpYw0KLy8NCg0KXCRfaHR0cF9ob3N0ID0gaXNzZXQoXCRfU0VSVkVSWydIVFRQX0hPU1QnXSkgPyBcJF9TRVJWRVJbJ0hUVFBfSE9TVCddIDogJyc7DQpcJF9yZXF1ZXN0X3VyaSA9IGlzc2V0KFwkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSkgPyBcJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10gOiAnJzsNCg0KXCRvcmlnaW5fbGluayA9IChpc3NldChcJF9TRVJWRVJbJ0hUVFBTJ10pICYmIFwkX1NFUlZFUlsnSFRUUFMnXSA9PT0gJ29uJyA/DQogICAgICAgICAgICAgICAgImh0dHBzIiA6ICJodHRwIikgLiAiOi8vIiAuIFwkX2h0dHBfaG9zdCAuIA0KICAgICAgICAgICAgICAgIFwkX3JlcXVlc3RfdXJpOw0KXCRyYWNrZm9ybXNfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkcmFja2Zvcm1zX2xvZ2luLT5yYWNrZm9ybXNsb2dpbmxpbmsgPSBcJG9yaWdpbl9saW5rOw0KXCRyYWNrZm9ybXNfbG9naW4tPnJhY2tmb3Jtc2xvZ2luID0gInskc2VjdXJpdHlfYXJyYXktPnJhY2tmb3Jtc2xvZ2lufSI7DQoNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnZmJfcmFja2Zvcm1zJ10gPSBcJHJhY2tmb3Jtc19sb2dpbjsgDQoNCi8vIENBUyBMb2dpYw0KXCRjYXNfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkY2FzX2xvZ2luLT5jYXNsb2dpbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5jYXNsb2dpbn0iOw0KXCRjYXNfbG9naW4tPmNhc2hvc3QgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzaG9zdH0iOw0KXCRjYXNfbG9naW4tPmNhc3BvcnQgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzcG9ydH0iOw0KXCRjYXNfbG9naW4tPmNhc2NvbnRleHQgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzY29udGV4dH0iOw0KDQpcJGNhc19sb2dpbi0+Y2FzdXNlcnN2aWV3ID0gInskc2VjdXJpdHlfYXJyYXktPmNhc3VzZXJzdmlld30iOw0KXCRjYXNfbG9naW4tPmNhc3VzZXJzdXBkYXRlID0gInskc2VjdXJpdHlfYXJyYXktPmNhc3VzZXJzdXBkYXRlfSI7DQpcJGNhc19sb2dpbi0+cGFnZWFjY2Vzc2xldmVsID0gInskY2FzcGFnZWFjY2Vzc2xldmVsfSI7IC8vIDAgTm9uZSwgMSBWaWV3LCAyIFVwZGF0ZS4NCg0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYl9jYXMnXSA9IFwkY2FzX2xvZ2luOw0KDQovLyBBRCBMb2dpYw0KXCRhZF9sb2dpbiA9IG5ldyBzdGRDbGFzcygpOw0KXCRhZF9sb2dpbi0+YWRsb2dpbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZGxvZ2lufSI7DQpcJGFkX2xvZ2luLT5hZGhvc3QgPSAieyRzZWN1cml0eV9hcnJheS0+YWRob3N0fSI7DQpcJGFkX2xvZ2luLT5hZHByZWZpeCA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZHByZWZpeH0iOw0KXCRhZF9sb2dpbi0+YWRkbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZGRufSI7DQpcJGFkX2xvZ2luLT5hZHVzZXIgPSAieyRzZWN1cml0eV9hcnJheS0+YWR1c2VyfSI7DQpcJGFkX2xvZ2luLT5hZGdyb3VwID0gInskc2VjdXJpdHlfYXJyYXktPmFkZ3JvdXB9IjsNCg0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYl9hZCddID0gXCRhZF9sb2dpbjsNCg0KLy8gTG9naW4gTG9naWMNClwkZmJfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkZmJfbG9naW4tPmxvZ2luID0geyRzZWN1cml0eV9hcnJheS0+bG9naW59Ow0KXCRmYl9sb2dpbi0+cGVyc2lzdGVudF9sb2dpbiA9IHskc2VjdXJpdHlfYXJyYXktPnBlcnNpc3RlbnRfbG9naW59Ow0KXCRmYl9sb2dpbi0+cGVyc2lzdGVudF9sb2dpbl9qb2JfaWQgPSB7JGpvYl9pZH07DQpcJGZiX2xvZ2luLT51c2VybmFtZSA9ICJ7JHNlY3VyaXR5X2FycmF5LT51c2VybmFtZX0iOw0KXCRmYl9sb2dpbi0+cGFzc3dvcmQgPSAieyRzZWN1cml0eV9hcnJheS0+cGFzc3dvcmR9IjsNClwkZmJfbG9naW4tPmxvZ2luX2F0dGVtcHRzID0geyRzZWN1cml0eV9hcnJheS0+bG9naW5fYXR0ZW1wdHN9OyAvLyAzLCA1LCBvciAoMikgRm9yIFVubGltaXRlZC4NClwkZmJfbG9naW4tPmxvZ2luX21lc3NhZ2UgPSB7JGFjdGl2ZV9tZXNzYWdlX3N0YXJ0fQ0KeyRzZWN1cml0eV9hcnJheS0+bG9naW5fbWVzc2FnZX0NCnskYWN0aXZlX21lc3NhZ2VfZW5kfQ0KXCRmYl9sb2dpbi0+bG9naW5fZXJyb3JfbWVzc2FnZSA9IHskYWN0aXZlX21lc3NhZ2Vfc3RhcnR9DQp7JHNlY3VyaXR5X2FycmF5LT5sb2dpbl9lcnJvcl9tZXNzYWdlfQ0KeyRhY3RpdmVfbWVzc2FnZV9lbmR9DQpcJGZiX2xvZ2luLT5sb2dpbl9hdHRlbXB0c19lcnJvcl9tZXNzYWdlID0geyRhY3RpdmVfbWVzc2FnZV9zdGFydH0NCnskc2VjdXJpdHlfYXJyYXktPmxvZ2luX2F0dGVtcHRzX2Vycm9yX21lc3NhZ2V9DQp7JGFjdGl2ZV9tZXNzYWdlX2VuZH0NClwkZmJfbG9naW4tPnJlZGlyZWN0ID0gInskbmFtZX0iOw0KDQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2ZiX2xvZ2luJ10gPSBcJGZiX2xvZ2luOw0KDQoNCi8vIEdsb2JhbCBUaW1lc3RhbXBzLCBFdGMuDQpcJHRpbWVzdGFtcCA9IHRpbWUoKTsNClwkZGF0ZXRpbWUgPSBkYXRlKCdZLW0tZCAgSDppOnMnLCB0aW1lKCkpOw0KXCRkYXRldGltZV9hbWVyaWNhbiA9IGRhdGUoJ20tZC1ZJywgdGltZSgpKTsNClwkZGF0ZXRpbWVfZXVyb3BlYW4gPSBkYXRlKCdkLW0tWScsIHRpbWUoKSk7DQoNCi8vIFZpc2l0b3IgSVANClwkcmVtb3RlX2lwID0gXCRfU0VSVkVSWydSRU1PVEVfQUREUiddOw0KDQppbmNsdWRlX29uY2UgIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfXNlY3VyaXR5L3NlY3VyZV9wYWdlLnBocCI7DQoNCi8vIEJ1aWxkIDY5MyAtIFdlIG5vdyBpbmNsdWRlIGRhdGFiYXNlIGNvZGUgYnkgZGVmYXVsdC4NCmlmKGZpbGVfZXhpc3RzKCJ7XCRfU0VTU0lPTlsnTUFYX1BBVEgnXX1EYXRhYmFzZS5waHAiKSl7DQoJQGluY2x1ZGVfb25jZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119RGF0YWJhc2UucGhwIjsNCn0NCg0KDQoNCi8vIEZvcm0gU3RhdHMgLSBJbml0aWFsIFBhZ2UuDQoNCmlmKDEgPT0geyRhbmFseXRpY3NkYXRhfSl7DQogICAgaW5pdF9zdGF0cyhcJGpvYl9pZCwgInskbmFtZX0iLCAnZm9ybScpOw0KfQ0KDQp7JF9zZXNzaW9uRGVidWdDb2RlfQ0KDQovLyBCdWlsZCA3NTcgLSBXb3JrRmxvdyBMb2dpYyAtIEZpcnN0IFBhZ2UuDQppZihpc3NldChcJF9TRVNTSU9OWydGQl9XT1JLRkxPVyddWydJU19GT1JNQk9TU19XT1JLRkxPV19MT0FERVInXSkgJiYgXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfTE9BREVSJ10gPT0gdHJ1ZSl7DQoNCgkvLyBpbmNsdWRlIG1haW4gaG9va3MgbGliDQoJaW5jbHVkZSAnLi4vLi4vLi4vYXBwL2xpYi93b3JrZmxvdy9jbGllbnQvSG9va3MucGhwJzsNCg0KCS8vIGNoZWNrIGZvciBmcmVzaCBqb2INCglpZihpc3NldChcJF9TRVNTSU9OWydGQl9XT1JLRkxPVyddWydJU19GT1JNQk9TU19XT1JLRkxPV19FWElTVElOR19KT0InXSkgJiYgXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfRVhJU1RJTkdfSk9CJ10gPT0gdHJ1ZSl7DQoJDQoJCVwkaG9va3MgPSBuZXcgSG9va3MoKTsNCgkJDQoJCS8vIGxvYWQgYW55IGV4aXN0aW5nIHZhbHVlcyAtIFBhc3MgaW4gam9iIG5hbWUgZm9yIHNlc3Npb24gcmVuYW1lIGxvZ2ljLg0KCQlcJGhvb2tzLT5sb2FkUGVyc2lzdGVudFdvcmtmbG93VmFsdWVzKCd7JHhtbC0+am9ibmFtZX0nKTsNCgkNCgl9DQoJDQp9DQoNCj8+DQoNCkVPVDsNCiAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCg0KICAgICAgICAgICAgJGtleXMgPSBhcnJheV9rZXlzKCRwYWdlYXJyYXkpOw0KICAgICAgICAgICAgJGJhY2twYWdlID0gJGtleXNbMF07DQoNCg0KDQogICAgICAgICAgICAkZWxlbWVudCA9IDw8PCBFT1QNCnskcGhwdG9wfTw/cGhwDQp7JHRzfQ0KaWYoZnVuY3Rpb25fZXhpc3RzKCdpbmlfc2V0Jykpew0KCWluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgMCk7IC8vIENoYW5nZSB0byAxIHRvIGRpc3BsYXkgYWxsIGVycm9yIG1lc3NhZ2VzLg0KCWluaV9zZXQoJ2Vycm9yX3JlcG9ydGluZycsIEVfQUxMKTsNCn0NCg0KXCRzaWRfdXJsID0gIiI7DQoNCi8vIFN0YXJ0IG91ciBtYWluIHNlc3Npb24NCmlmKCFzZXNzaW9uX2lkKCkpIHsgc2Vzc2lvbl9zdGFydCgpOyB9DQoNCnskZGlyZWN0X2FjY2Vzc30NCg0KeyRjb25kaXRpb25fY29kZX0NCg0KLy8gUGF0aCBpbmZvIGZvciBQSFAgSW5jbHVkZQ0KXCRfU0VTU0lPTlsnTUFYX1BBVEgnXSA9ICd7JHBocHBhdGh9JzsNCg0KaWYoIWlzc2V0KFwkX1NFU1NJT05bJ01BWF9QQVRIX1BST0MnXSkpIHsgXCRfU0VTU0lPTlsnTUFYX1BBVEhfUFJPQyddID0gJy4vJzsgfQ0KDQovLyBGb3JtIFBhZ2UgU2VjdXJpdHkNClwkam9iX2lkID0gJ3skam9iX2lkfSc7DQoNClwkam9iX25hbWUgPSAieyR4bWwtPmpvYm5hbWV9IjsNCg0KLy8gbG9hZCB1dGlsaXR5IGZ1bmN0aW9ucw0KaW5jbHVkZV9vbmNlICdsaWIvdXRpbGl0eS5waHAnOw0KDQovLyBCdWlsZCA2OTkgLSBHbG9iYWwgVGltZXN0YW1wcywgRXRjLg0KXCR0aW1lc3RhbXAgPSB0aW1lKCk7DQpcJGRhdGV0aW1lID0gZGF0ZSgnWS1tLWQgIEg6aTpzJywgdGltZSgpKTsNCg0KLy8gVmlzaXRvciBJUA0KXCRyZW1vdGVfaXAgPSBcJF9TRVJWRVJbJ1JFTU9URV9BRERSJ107DQoNCi8vIEJ1aWxkIDcwMSAtIFdlIG5vdyBpbmNsdWRlIGRhdGFiYXNlIGNvZGUgYnkgZGVmYXVsdC4NCmlmKGZpbGVfZXhpc3RzKCJ7XCRfU0VTU0lPTlsnTUFYX1BBVEgnXX1EYXRhYmFzZS5waHAiKSl7DQoJQGluY2x1ZGVfb25jZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119RGF0YWJhc2UucGhwIjsNCn0NCg0KDQovLyBGb3JtIFBlcnNpc3RlbmNlIENoZWNrIC0gU2Vjb25kYXJ5IExvYWQuDQoNClwkZm9ybV9wZXJzaXN0ZW5jZV9jaGVjayA9IHskcGVyc2lzdGFuY2V9Ow0KDQppZihcJGZvcm1fcGVyc2lzdGVuY2VfY2hlY2sgPT0gMyl7DQoNCglcJHJpZCA9IGlzc2V0KFwkX0dFVFsnUklEJ10pID8gZmlsdGVyX2lucHV0KElOUFVUX0dFVCwgJ1JJRCcsIEZJTFRFUl9VTlNBRkVfUkFXKSA6ICIiOw0KDQoJaWYoXCRyaWQgIT0gIiIpIHsNCgkJXCRfU0VTU0lPTiBbJ2ZiX2VudHJ5X2lkX2F1dG8nXSA9IFwkcmlkOw0KCX0NCg0KfQ0KDQovLyBMb2FkIFBlcnNpc3RlbnQgVmFsdWVzIC0gU2Vjb25kYXJ5IFBhZ2UuIA0KDQpsb2FkUGVyc2lzdGFudFZhbHVlcyh7JHBlcnNpc3RhbmNlfSwgXCRqb2JfaWQsICJ7JG5hbWV9Iik7DQoNCg0KLy8gRm9ybSBTdGF0cyAtIFNlY29uZGFyeSBQYWdlLg0KDQppZigxID09IHskYW5hbHl0aWNzZGF0YX0pew0KICAgIGluaXRfc3RhdHMoXCRqb2JfaWQsICJ7JG5hbWV9IiwgJ2Zvcm0nKTsNCn0NCg0KeyRfc2Vzc2lvbkRlYnVnQ29kZX0NCg0KDQovLyBXb3JrRmxvdyBhbmQgcGFnZSBhY2Nlc3MgY2hlY2tzLg0KDQppZighaXNzZXQoXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXSkgfHwgKCAhaXNzZXQoXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfTE9BREVSJ10pICYmICFcJF9TRVNTSU9OWydGQl9XT1JLRkxPVyddWydJU19GT1JNQk9TU19XT1JLRkxPV19MT0FERVInXSA9PSB0cnVlKSApew0KDQoJLy8gSWYgbm90IFdvcmtmbG93IHBlcmZvcm0gc3RhbmRhcmQgYWNjZXNzIGNoZWNrLg0KDQogICAgaWYoIWlzc2V0KFwkX1NFU1NJT05bJ3BhZ2VzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsneyRuYW1lfSddKSl7DQogICAgICAgIGhlYWRlcigiTG9jYXRpb246IHskYmFja3BhZ2V9Iik7DQogICAgICAgIGRpZSgpOw0KICAgIH0NCn0NCg0KDQovLyBCdWlsZCA3NTcgLSBXb3JrRmxvdyBMb2dpYyAtIFNlY29uZGFyeSBQYWdlLg0KaWYoaXNzZXQoXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfTE9BREVSJ10pICYmIFwkX1NFU1NJT05bJ0ZCX1dPUktGTE9XJ11bJ0lTX0ZPUk1CT1NTX1dPUktGTE9XX0xPQURFUiddID09IHRydWUpew0KDQoJLy8gaW5jbHVkZSBtYWluIGhvb2tzIGxpYg0KCWluY2x1ZGUgJy4uLy4uLy4uL2FwcC9saWIvd29ya2Zsb3cvY2xpZW50L0hvb2tzLnBocCc7DQoNCgkvLyBjaGVjayBmb3IgZnJlc2ggam9iDQoJaWYoaXNzZXQoXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfRVhJU1RJTkdfSk9CJ10pICYmIFwkX1NFU1NJT05bJ0ZCX1dPUktGTE9XJ11bJ0lTX0ZPUk1CT1NTX1dPUktGTE9XX0VYSVNUSU5HX0pPQiddID09IHRydWUpew0KCQ0KCQlcJGhvb2tzID0gbmV3IEhvb2tzKCk7DQoJCQ0KCQkvLyBsb2FkIGFueSBleGlzdGluZyB2YWx1ZXMgLSBQYXNzIGluIGpvYiBuYW1lIGZvciBzZXNzaW9uIHJlbmFtZSBsb2dpYy4NCgkJXCRob29rcy0+bG9hZFBlcnNpc3RlbnRXb3JrZmxvd1ZhbHVlcygneyR4bWwtPmpvYm5hbWV9Jyk7DQoJDQoJfQ0KCQ0KfQ0KDQoNCi8vDQovLyBGb3JtIFBhZ2UgU2VjdXJpdHkgLSBTZWNvbmRhcnkgUGFnZS4NCi8vDQoNClwkZG9tYWluX2xpc3QgPSBleHBsb2RlKCcsJywieyRkb21haW5fbGlzdH0iKTsNClwkaXBfbGltaXQgPSB7JGlwX2xpbWl0fTsNClwkam9iX2lkID0gJ3skam9iX2lkfSc7DQpcJGpvYl9uYW1lID0gInskeG1sLT5qb2JuYW1lfSI7DQpcJGlwX2xpbWl0X21lc3NhZ2UgPSB7JGlwX2xpbWl0X21lc3NhZ2Vfc3RhcnR9DQp7JGlwX2xpbWl0X21lc3NhZ2V9DQp7JGlwX2xpbWl0X21lc3NhZ2VfZW5kfQ0KXCRpcF9saW1pdF9kdXJhdGlvbiA9IHskaXBfbGltaXRfZHVyYXRpb259Ow0KXCRkZWx0YSA9IHskZGVsdGF9Ow0KDQpcJGFjdGl2ZSA9IHskYWN0aXZlfTsNClwkYWN0aXZlX21lc3NhZ2UgPSB7JGFjdGl2ZV9tZXNzYWdlX3N0YXJ0fQ0KeyRhY3RpdmVfbWVzc2FnZX0NCnskYWN0aXZlX21lc3NhZ2VfZW5kfQ0KDQovLyBSYWNrRm9ybXMgTG9naW4gTG9naWMNClwkb3JpZ2luX2xpbmsgPSAoaXNzZXQoXCRfU0VSVkVSWydIVFRQUyddKSAmJiBcJF9TRVJWRVJbJ0hUVFBTJ10gPT09ICdvbicgPw0KICAgICAgICAgICAgICAgICJodHRwcyIgOiAiaHR0cCIpIC4gIjovLyIgLiBcJF9TRVJWRVJbJ0hUVFBfSE9TVCddIC4gDQogICAgICAgICAgICAgICAgXCRfU0VSVkVSWydSRVFVRVNUX1VSSSddOw0KXCRyYWNrZm9ybXNfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkcmFja2Zvcm1zX2xvZ2luLT5yYWNrZm9ybXNsb2dpbmxpbmsgPSBcJG9yaWdpbl9saW5rOw0KXCRyYWNrZm9ybXNfbG9naW4tPnJhY2tmb3Jtc2xvZ2luID0gInskc2VjdXJpdHlfYXJyYXktPnJhY2tmb3Jtc2xvZ2lufSI7DQoNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnZmJfcmFja2Zvcm1zJ10gPSBcJHJhY2tmb3Jtc19sb2dpbjsgDQoNCi8vIENBUyBMb2dpYw0KXCRjYXNfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkY2FzX2xvZ2luLT5jYXNsb2dpbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5jYXNsb2dpbn0iOw0KXCRjYXNfbG9naW4tPmNhc2hvc3QgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzaG9zdH0iOw0KXCRjYXNfbG9naW4tPmNhc3BvcnQgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzcG9ydH0iOw0KXCRjYXNfbG9naW4tPmNhc2NvbnRleHQgPSAieyRzZWN1cml0eV9hcnJheS0+Y2FzY29udGV4dH0iOw0KDQpcJGNhc19sb2dpbi0+Y2FzdXNlcnN2aWV3ID0gInskc2VjdXJpdHlfYXJyYXktPmNhc3VzZXJzdmlld30iOw0KXCRjYXNfbG9naW4tPmNhc3VzZXJzdXBkYXRlID0gInskc2VjdXJpdHlfYXJyYXktPmNhc3VzZXJzdXBkYXRlfSI7DQpcJGNhc19sb2dpbi0+cGFnZWFjY2Vzc2xldmVsID0gInskY2FzcGFnZWFjY2Vzc2xldmVsfSI7IC8vIDAgTm9uZSwgMSBWaWV3LCAyIFVwZGF0ZS4NCg0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYl9jYXMnXSA9IFwkY2FzX2xvZ2luOw0KDQovLyBBRCBMb2dpYw0KXCRhZF9sb2dpbiA9IG5ldyBzdGRDbGFzcygpOw0KXCRhZF9sb2dpbi0+YWRsb2dpbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZGxvZ2lufSI7DQpcJGFkX2xvZ2luLT5hZGhvc3QgPSAieyRzZWN1cml0eV9hcnJheS0+YWRob3N0fSI7DQpcJGFkX2xvZ2luLT5hZHByZWZpeCA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZHByZWZpeH0iOw0KXCRhZF9sb2dpbi0+YWRkbiA9ICJ7JHNlY3VyaXR5X2FycmF5LT5hZGRufSI7DQpcJGFkX2xvZ2luLT5hZHVzZXIgPSAieyRzZWN1cml0eV9hcnJheS0+YWR1c2VyfSI7DQpcJGFkX2xvZ2luLT5hZGdyb3VwID0gInskc2VjdXJpdHlfYXJyYXktPmFkZ3JvdXB9IjsNCg0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYl9hZCddID0gXCRhZF9sb2dpbjsNCg0KLy8gTG9naW4gTG9naWMNClwkZmJfbG9naW4gPSBuZXcgc3RkQ2xhc3MoKTsNClwkZmJfbG9naW4tPmxvZ2luID0geyRzZWN1cml0eV9hcnJheS0+bG9naW59Ow0KXCRmYl9sb2dpbi0+cGVyc2lzdGVudF9sb2dpbiA9IHskc2VjdXJpdHlfYXJyYXktPnBlcnNpc3RlbnRfbG9naW59Ow0KXCRmYl9sb2dpbi0+cGVyc2lzdGVudF9sb2dpbl9qb2JfaWQgPSB7JGpvYl9pZH07DQpcJGZiX2xvZ2luLT51c2VybmFtZSA9ICJ7JHNlY3VyaXR5X2FycmF5LT51c2VybmFtZX0iOw0KXCRmYl9sb2dpbi0+cGFzc3dvcmQgPSAieyRzZWN1cml0eV9hcnJheS0+cGFzc3dvcmR9IjsNClwkZmJfbG9naW4tPmxvZ2luX2F0dGVtcHRzID0geyRzZWN1cml0eV9hcnJheS0+bG9naW5fYXR0ZW1wdHN9OyAvLyAzLCA1LCBvciAoMikgRm9yIFVubGltaXRlZC4NClwkZmJfbG9naW4tPmxvZ2luX21lc3NhZ2UgPSB7JGFjdGl2ZV9tZXNzYWdlX3N0YXJ0fQ0KeyRzZWN1cml0eV9hcnJheS0+bG9naW5fbWVzc2FnZX0NCnskYWN0aXZlX21lc3NhZ2VfZW5kfQ0KXCRmYl9sb2dpbi0+bG9naW5fZXJyb3JfbWVzc2FnZSA9IHskYWN0aXZlX21lc3NhZ2Vfc3RhcnR9DQp7JHNlY3VyaXR5X2FycmF5LT5sb2dpbl9lcnJvcl9tZXNzYWdlfQ0KeyRhY3RpdmVfbWVzc2FnZV9lbmR9DQpcJGZiX2xvZ2luLT5sb2dpbl9hdHRlbXB0c19lcnJvcl9tZXNzYWdlID0geyRhY3RpdmVfbWVzc2FnZV9zdGFydH0NCnskc2VjdXJpdHlfYXJyYXktPmxvZ2luX2F0dGVtcHRzX2Vycm9yX21lc3NhZ2V9DQp7JGFjdGl2ZV9tZXNzYWdlX2VuZH0NClwkZmJfbG9naW4tPnJlZGlyZWN0ID0gInskbmFtZX0iOw0KDQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2ZiX2xvZ2luJ10gPSBcJGZiX2xvZ2luOw0KDQppbmNsdWRlX29uY2UgIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfXNlY3VyaXR5L3NlY3VyZV9wYWdlLnBocCI7DQoNCj8+DQoNCkVPVDsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfd29ya2Zsb3dfb3Blbl9ibG9jaygkam9iX2lkLCAkam9ibmFtZSwgJHBhZ2VuYW1lKQ0KICAgIHsNCg0KICAgICAgICByZXR1cm4gJyc7IA0KDQogICAgICAgICRlbHQgPSAnJzsNCg0KICAgICAgICAkZWx0IC49IDw8PEVPRg0KXG4NCjw/cGhwDQovL0Zvcm1Cb3NzIFdvcmtmbG93IFByb2Nlc3NpbmcJDQoNClwkd29ya2Zsb3dfam9iaWQgPSAneyRqb2JfaWR9JzsNClwkd29ya2Zsb3dfam9ibmFtZSA9ICd7JGpvYm5hbWV9JzsNClwkd29ya2Zsb3dfcGFnZW5hbWUgPSAneyRwYWdlbmFtZX0nOw0KDQppbmNsdWRlICdEYXRhYmFzZS5waHAnOw0KDQpcJGRlYnVnID0gMDsgLy8gVUkgb3ZlcnJpZGUNCg0KXCRkYmggPSBuZXcgRGF0YWJhc2UoKTsNClwkYW1iaWd1b3VzX2NvbHVtbl9uYW1lX3dhcm5pbmcgPSBmYWxzZTsNCg0KXCRzcWwgPSAnU0VMRUNUIHdvcmtmbG93X2pvYl9pZCBGUk9NIGZiX3dvcmtmbG93X3RhcmdldHMgV0hFUkUgZm9ybWJvc3Nfam9iX2lkID0gPyBBTkQgdGFyZ2V0ID0gPyBBTkQgYWN0aXZlICA9IDEnOw0KXCRwYXJhbXMgPSBhcnJheShcJHdvcmtmbG93X2pvYmlkLCBcJHdvcmtmbG93X3BhZ2VuYW1lKTsNCgkNClwkd29ya2Zsb3dfcXVlcnkgPSBcJGRiaC0+cGRvX3Byb2NlZHVyZV9wYXJhbXMoXCRkZWJ1ZywgDQoJCQkJCQkJCQkgXCRzcWwsDQoJCQkJCQkJCQkgXCRkYl9ob3N0LA0KCQkJCQkJCQkJIFwkZGJfdHlwZSwNCgkJCQkJCQkJCSBcJG15c3FsX3NvY2tldCwNCgkJCQkJCQkJCSBcJG15c3FsX3BvcnQsDQoJCQkJCQkJCQkgXCRkYmRzbiwNCgkJCQkJCQkJCSBcJGRiX3VzZXIsDQoJCQkJCQkJCQkgXCRkYl9wYXNzLA0KCQkJCQkJCQkJIFwkZGJfY2F0YWxvZywNCgkJCQkJCQkJCSBcJHBhcmFtcywNCgkJCQkJCQkJCSAwLCAvLyByZXR1cm5fdHJ1ZQ0KCQkJCQkJCQkJIDAsIC8vIHJldHVybl9sYXN0X2luc2VydF9pZCwNCgkJCQkJCQkJCSA0LCAvLyBmZXRjaF9tb2RlLA0KCQkJCQkJCQkJIDAsIC8vIHBhc3NfbnVsbHMsDQoJCQkJCQkJCQkgZmFsc2UsIC8vIGJ1aWxkZXJfcXVlcnksDQoJCQkJCQkJCQkgXCRhbWJpZ3VvdXNfY29sdW1uX25hbWVfd2FybmluZyk7DQoNCi8vIHdlIGhhdmUgYW4gYWN0aXZlIHdvcmtmbG93IHRhcmdldCBzZXQgZm9yIHRoaXMgcGFnZS4uLg0KaWYoXCR3b3JrZmxvd19xdWVyeSAhPSBmYWxzZSl7DQoNCgkvLyBnZXQgdGhpcyB3b3JrZmxvd3MgZGF0YQ0KCVwkc3FsID0gJ1NFTEVDVCB3b3JrZmxvd19kYXRhIEZST00gZmJfd29ya2Zsb3dfam9icyBXSEVSRSBpZCA9ID8gQU5EIGFjdGl2ZSA9IDEnOw0KCVwkcGFyYW1zID0gYXJyYXkoXCR3b3JrZmxvd19xdWVyeVswXVsnd29ya2Zsb3dfam9iX2lkJ10pOw0KCQ0KCVwkd29ya2Zsb3dfZGF0YSA9IFwkZGJoLT5wZG9fcHJvY2VkdXJlX3BhcmFtcyhcJGRlYnVnLCANCgkJCQkJCQkJCSBcJHNxbCwNCgkJCQkJCQkJCSBcJGRiX2hvc3QsDQoJCQkJCQkJCQkgXCRkYl90eXBlLA0KCQkJCQkJCQkJIFwkbXlzcWxfc29ja2V0LA0KCQkJCQkJCQkJIFwkbXlzcWxfcG9ydCwNCgkJCQkJCQkJCSBcJGRiZHNuLA0KCQkJCQkJCQkJIFwkZGJfdXNlciwNCgkJCQkJCQkJCSBcJGRiX3Bhc3MsDQoJCQkJCQkJCQkgXCRkYl9jYXRhbG9nLA0KCQkJCQkJCQkJIFwkcGFyYW1zLA0KCQkJCQkJCQkJIDAsIC8vIHJldHVybl90cnVlDQoJCQkJCQkJCQkgMCwgLy8gcmV0dXJuX2xhc3RfaW5zZXJ0X2lkLA0KCQkJCQkJCQkJIDQsIC8vIGZldGNoX21vZGUsDQoJCQkJCQkJCQkgMCwgLy8gcGFzc19udWxscywNCgkJCQkJCQkJCSBmYWxzZSwgLy8gYnVpbGRlcl9xdWVyeSwNCgkJCQkJCQkJCSBcJGFtYmlndW91c19jb2x1bW5fbmFtZV93YXJuaW5nKTsNCgkJCQkJCQkJCSANCglpZihcJHdvcmtmbG93X2RhdGEgIT0gZmFsc2Upew0KCQ0KCQlcJGRhdGEgPSBqc29uX2RlY29kZShiYXNlNjRfZGVjb2RlKFwkd29ya2Zsb3dfZGF0YVswXVsnd29ya2Zsb3dfZGF0YSddKSk7DQoJCS8vcHJpbnRfcihcJGRhdGEpOw0KCQkNCgkJLy8gd2hvJ3MgdXNpbmcgdGhpcyBmb3JtPw0KCQkNCgkJLy8gd2hhdCBhY2Nlc3MgdG8gdGhpcyBwYWdlIGRvIHRoZXkgaGF2ZSAoZWRpdCwgdXBkYXRlLCBldGMpPw0KCQkNCgl9DQoNCn0gZWxzZSB7DQoNCgkvLyBjaGVjayBqb2IgbmFtZXMgZm9yIGFueSBhY3RpdmUgdGFyZ2V0IG1hdGNoZXMuDQp9DQo/Pg0KRU9GOw0KDQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgICAgICANCiAgICB9IA0KDQoNCiAgICANCiAgICANCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfdGlueW1jZSgkdHlwZSkNCiAgICB7DQogICAgICAgICR0aW55bWNlID0gJyc7DQogICAgICAgIHN3aXRjaCAoJHR5cGUpIHsNCiAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICR0aW55bWNlID0gPDw8RU9UDQoJCQkJCQkJDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+dGlueV9tY2UvdGlueV9tY2UuanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KLy8gU2ltcGxlIEVkaXRvcg0KdGlueU1DRS5pbml0KHsNCgltb2RlIDogInRleHRhcmVhcyIsDQoJdGhlbWUgOiAic2ltcGxlIiwNCgllZGl0b3Jfc2VsZWN0b3IgOiAibWNlRWRpdG9yIg0KfSk7DQo8L3NjcmlwdD4NCg0KRU9UOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMic6IA0KICAgICAgICAgICAgICAgICR0aW55bWNlID0gPDw8RU9UDQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz50aW55X21jZS90aW55X21jZS5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQovLyBUZXh0IEhlYXZ5IEVkaXRvcg0KdGlueU1DRS5pbml0KHsNCgltb2RlIDogInRleHRhcmVhcyIsDQoJdGhlbWUgOiAiYWR2YW5jZWQiLA0KCWVkaXRvcl9zZWxlY3RvciA6ICJtY2VFZGl0b3IiLA0KCWVkaXRvcl9kZXNlbGVjdG9yIDogIm1jZU5vRWRpdG9yIiwNCgkNCglwbHVnaW5zIDogImFkdmhyLGFkdmltYWdlLGFkdmxpbmssaW5saW5lcG9wdXBzLGluc2VydGRhdGV0aW1lLHBhc3RlLG5vbmVkaXRhYmxlLHZpc3VhbGNoYXJzLG5vbmJyZWFraW5nLHhodG1seHRyYXMiLA0KCXRoZW1lX2FkdmFuY2VkX2J1dHRvbnMxIDogImJvbGQsaXRhbGljLHVuZGVybGluZSxzdHJpa2V0aHJvdWdoLHwsanVzdGlmeWxlZnQsanVzdGlmeWNlbnRlcixqdXN0aWZ5cmlnaHQsanVzdGlmeWZ1bGwsfCxidWxsaXN0LG51bWxpc3QsfCxvdXRkZW50LGluZGVudCIsDQoJdGhlbWVfYWR2YW5jZWRfYnV0dG9uczIgOiAidW5kbyxyZWRvLHwsbGluayx1bmxpbmssYW5jaG9yLGltYWdlLGNsZWFudXAsY29kZSx8LGluc2VydGRhdGUsaW5zZXJ0dGltZSx8LGZvcmVjb2xvcixiYWNrY29sb3IiLA0KCXRoZW1lX2FkdmFuY2VkX2J1dHRvbnMzIDogImhyLHJlbW92ZWZvcm1hdCx2aXN1YWxhaWQsfCxzdWIsc3VwLHwsZGVsLGlucyxhdHRyaWJzLHwsdmlzdWFsY2hhcnMsbm9uYnJlYWtpbmcsdGVtcGxhdGUsYmxvY2txdW90ZSIsDQoJdGhlbWVfYWR2YW5jZWRfdG9vbGJhcl9sb2NhdGlvbiA6ICJib3R0b20iLA0KCXRoZW1lX2FkdmFuY2VkX3Rvb2xiYXJfYWxpZ24gOiAibGVmdCIsDQoJcGx1Z2luX2luc2VydGRhdGVfZGF0ZUZvcm1hdCA6ICIlbS0lZC0lWSIsDQoJcGx1Z2luX2luc2VydGRhdGVfdGltZUZvcm1hdCA6ICIlSDolTTolUyINCn0pOw0KPC9zY3JpcHQ+DQoNCkVPVDsNCg0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgIGNhc2UgJzMnOiANCiAgICAgICAgICAgICAgICAkdGlueW1jZSA9IDw8PEVPVA0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+dGlueV9tY2UvdGlueV9tY2UuanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KLy8gUmFja0Zvcm1zIFN0eWxlIEVkaXRvcg0KdGlueU1DRS5pbml0KHsNCgltb2RlIDogInRleHRhcmVhcyIsDQoJdGhlbWUgOiAiYWR2YW5jZWQiLA0KCWVkaXRvcl9zZWxlY3RvciA6ICJtY2VFZGl0b3IiLA0KCWVkaXRvcl9kZXNlbGVjdG9yIDogIm1jZU5vRWRpdG9yIiwNCgkNCglwbHVnaW5zIDogInBhZ2VicmVhayxzdHlsZSxsYXllcix0YWJsZSxhZHZocixhZHZpbWFnZSxhZHZsaW5rLGlubGluZXBvcHVwcyxpbnNlcnRkYXRldGltZSxjb250ZXh0bWVudSxwYXN0ZSxkaXJlY3Rpb25hbGl0eSxub25lZGl0YWJsZSx2aXN1YWxjaGFycyxub25icmVha2luZyx4aHRtbHh0cmFzLHRlbXBsYXRlIiwNCgl0aGVtZV9hZHZhbmNlZF9idXR0b25zMSA6ICJib2xkLGl0YWxpYyx1bmRlcmxpbmUsc3RyaWtldGhyb3VnaCx8LGp1c3RpZnlsZWZ0LGp1c3RpZnljZW50ZXIsanVzdGlmeXJpZ2h0LGp1c3RpZnlmdWxsLHwsZm9ybWF0c2VsZWN0LGZvbnRzZWxlY3QsZm9udHNpemVzZWxlY3QiLA0KCXRoZW1lX2FkdmFuY2VkX2J1dHRvbnMyIDogImJ1bGxpc3QsbnVtbGlzdCx8LG91dGRlbnQsaW5kZW50fCx1bmRvLHJlZG8sfCxsaW5rLHVubGluayxhbmNob3IsaW1hZ2UsY2xlYW51cCxjb2RlLHwsaW5zZXJ0ZGF0ZSxpbnNlcnR0aW1lLHwsZm9yZWNvbG9yLGJhY2tjb2xvciIsDQoJdGhlbWVfYWR2YW5jZWRfYnV0dG9uczMgOiAidGFibGVjb250cm9scyx8LGhyLHJlbW92ZWZvcm1hdCx2aXN1YWxhaWQsfCxzdWIsc3VwIiwNCgl0aGVtZV9hZHZhbmNlZF9idXR0b25zNCA6ICJpbnNlcnRsYXllcixtb3ZlZm9yd2FyZCxtb3ZlYmFja3dhcmQsYWJzb2x1dGUsfCxzdHlsZXByb3BzLHNwZWxsY2hlY2tlcix8LGNpdGUsYWJicixhY3JvbnltLGRlbCxpbnMsYXR0cmlicyx8LHZpc3VhbGNoYXJzLG5vbmJyZWFraW5nLHRlbXBsYXRlLGJsb2NrcXVvdGUscGFnZWJyZWFrLHwsaW5zZXJ0ZmlsZSxpbnNlcnRpbWFnZSIsDQoJdGhlbWVfYWR2YW5jZWRfdG9vbGJhcl9sb2NhdGlvbiA6ICJib3R0b20iLA0KCXRoZW1lX2FkdmFuY2VkX3Jlc2l6aW5nIDogdHJ1ZSwNCgl0aGVtZV9hZHZhbmNlZF9zdGF0dXNiYXJfbG9jYXRpb24gOiAiYm90dG9tIiwNCgl0aGVtZV9hZHZhbmNlZF90b29sYmFyX2FsaWduIDogImxlZnQiLA0KCXBsdWdpbl9pbnNlcnRkYXRlX2RhdGVGb3JtYXQgOiAiJW0tJWQtJVkiLA0KCXBsdWdpbl9pbnNlcnRkYXRlX3RpbWVGb3JtYXQgOiAiJUg6JU06JVMiDQp9KTsNCjwvc2NyaXB0Pg0KDQpFT1Q7DQoNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIGNhc2UgJzQnOiANCiAgICAgICAgICAgICAgICAkdGlueW1jZSA9IDw8PEVPVA0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+dGlueV9tY2UvdGlueV9tY2UuanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KLy8gU3R5bGUgRWRpdG9yDQp0aW55TUNFLmluaXQoew0KCW1vZGUgOiAidGV4dGFyZWFzIiwNCgl0aGVtZSA6ICJhZHZhbmNlZCIsDQoJZWRpdG9yX3NlbGVjdG9yIDogIm1jZUVkaXRvciIsDQoJZWRpdG9yX2Rlc2VsZWN0b3IgOiAibWNlTm9FZGl0b3IiLA0KCXBsdWdpbnMgOiAic3R5bGUiLA0KCXRoZW1lX2FkdmFuY2VkX2J1dHRvbnMxIDogImJvbGQsaXRhbGljLHVuZGVybGluZSxzdHJpa2V0aHJvdWdoLHwsanVzdGlmeWxlZnQsanVzdGlmeWNlbnRlcixqdXN0aWZ5cmlnaHQsanVzdGlmeWZ1bGwsfCxmb3JtYXRzZWxlY3QsZm9udHNlbGVjdCxmb250c2l6ZXNlbGVjdCIsDQoJdGhlbWVfYWR2YW5jZWRfYnV0dG9uczIgOiAiIiwNCiAgICB0aGVtZV9hZHZhbmNlZF9idXR0b25zMyA6ICIiLA0KICAgIA0KCXRoZW1lX2FkdmFuY2VkX3Rvb2xiYXJfbG9jYXRpb24gOiAiYm90dG9tIiwNCgl0aGVtZV9hZHZhbmNlZF9yZXNpemluZyA6IHRydWUsDQoJdGhlbWVfYWR2YW5jZWRfdG9vbGJhcl9hbGlnbiA6ICJsZWZ0IiwNCglwbHVnaW5faW5zZXJ0ZGF0ZV9kYXRlRm9ybWF0IDogIiVtLSVkLSVZIiwNCglwbHVnaW5faW5zZXJ0ZGF0ZV90aW1lRm9ybWF0IDogIiVIOiVNOiVTIg0KfSk7DQo8L3NjcmlwdD4NCg0KRU9UOw0KDQoNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHRpbnltY2U7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlR29vZ2xlV2ViRm9udCgkZmFtaWx5KQ0KICAgIHsNCg0KICAgICAgICAkY29kZSA9IDw8PEVPRg0KDQo8IS0tIEdvb2dsZSBXZWIgRm9udHMgLS0+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQogIFdlYkZvbnRDb25maWcgPSB7DQogICAgZ29vZ2xlOiB7IGZhbWlsaWVzOiBbICd7JGZhbWlseX0nIF0gfQ0KICB9Ow0KICAoZnVuY3Rpb24oKSB7DQogICAgdmFyIHdmID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7DQogICAgd2Yuc3JjID0gKCdodHRwczonID09IGRvY3VtZW50LmxvY2F0aW9uLnByb3RvY29sID8gJ2h0dHBzJyA6ICdodHRwJykgKw0KICAgICAgJzovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL3dlYmZvbnQvMS93ZWJmb250LmpzJzsNCiAgICB3Zi50eXBlID0gJ3RleHQvamF2YXNjcmlwdCc7DQogICAgd2YuYXN5bmMgPSAndHJ1ZSc7DQogICAgdmFyIHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc2NyaXB0JylbMF07DQogICAgcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh3Ziwgcyk7DQogIH0pKCk7DQo8L3NjcmlwdD4NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCi8qIG1ha2VzIHN1cmUgYnV0dG9ucyBnZXQgc3R5bGVkIGFzIHdlbGwgKi8NCmlucHV0LmJ0biB7IGZvbnQtZmFtaWx5OiAneyRmYW1pbHl9JzsgfQ0KPC9zdHlsZT4NCg0KPCEtLSBHb29nbGUgV2ViIEZvbnRzIC0tPg0KDQpFT0Y7DQoNCiAgICAgICAgcmV0dXJuICRjb2RlOw0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV90cmFja2luZ19nb29nbGUoJGFjY291bnQsICRkb21haW4pDQogICAgew0KDQogICAgICAgICR0cmFja2luZ19nb29nbGUgPSAiIjsNCg0KICAgICAgICBpZiAoJGFjY291bnQgIT0gIiIpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJGRvbWFpbiAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgJHRyYWNraW5nX2dvb2dsZSA9IDw8PEVPRg0KPHNjcmlwdD4NCiAgKGZ1bmN0aW9uKGkscyxvLGcscixhLG0pe2lbJ0dvb2dsZUFuYWx5dGljc09iamVjdCddPXI7aVtyXT1pW3JdfHxmdW5jdGlvbigpew0KICAoaVtyXS5xPWlbcl0ucXx8W10pLnB1c2goYXJndW1lbnRzKX0saVtyXS5sPTEqbmV3IERhdGUoKTthPXMuY3JlYXRlRWxlbWVudChvKSwNCiAgbT1zLmdldEVsZW1lbnRzQnlUYWdOYW1lKG8pWzBdO2EuYXN5bmM9MTthLnNyYz1nO20ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoYSxtKQ0KICB9KSh3aW5kb3csZG9jdW1lbnQsJ3NjcmlwdCcsJy8vd3d3Lmdvb2dsZS1hbmFseXRpY3MuY29tL2FuYWx5dGljcy5qcycsJ2dhJyk7DQogIAkNCiAgZ2EoJ2NyZWF0ZScsICd7JGFjY291bnR9JywgJ2F1dG8nLCB7J2FsbG93TGlua2VyJzogdHJ1ZX0pOw0KICBnYSgncmVxdWlyZScsICdsaW5rZXInKTsNCiAgZ2EoJ2xpbmtlcjphdXRvTGluaycsIFsneyRkb21haW59J10gKTsNCiAgZ2EoJ3NlbmQnLCAncGFnZXZpZXcnKTsNCiAgCQ0KPC9zY3JpcHQ+DQpFT0Y7DQogICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHRyYWNraW5nX2dvb2dsZSA9IDw8PEVPRg0KPHNjcmlwdD4NCiAgKGZ1bmN0aW9uKGkscyxvLGcscixhLG0pe2lbJ0dvb2dsZUFuYWx5dGljc09iamVjdCddPXI7aVtyXT1pW3JdfHxmdW5jdGlvbigpew0KICAoaVtyXS5xPWlbcl0ucXx8W10pLnB1c2goYXJndW1lbnRzKX0saVtyXS5sPTEqbmV3IERhdGUoKTthPXMuY3JlYXRlRWxlbWVudChvKSwNCiAgbT1zLmdldEVsZW1lbnRzQnlUYWdOYW1lKG8pWzBdO2EuYXN5bmM9MTthLnNyYz1nO20ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoYSxtKQ0KICB9KSh3aW5kb3csZG9jdW1lbnQsJ3NjcmlwdCcsJy8vd3d3Lmdvb2dsZS1hbmFseXRpY3MuY29tL2FuYWx5dGljcy5qcycsJ2dhJyk7DQoNCiAgZ2EoJ2NyZWF0ZScsICd7JGFjY291bnR9JywgJ2F1dG8nKTsNCiAgZ2EoJ3NlbmQnLCAncGFnZXZpZXcnKTsNCg0KPC9zY3JpcHQ+DQpFT0Y7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJHRyYWNraW5nX2dvb2dsZTsNCiAgICB9DQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3BhZ2VfcGRmX3N0YXJ0KCRwYWdlKQ0KICAgIHsNCg0KICAgICAgICAkcGRmID0gJHBhZ2UtPnBkZjsNCg0KICAgICAgICAkY29kZSA9ICIiOw0KDQogICAgICAgIA0KDQogICAgICAgICRjb2RlX29wZW4gPSAiIjsNCiAgICAgICAgJGNvZGVfY2xvc2UgPSAiIjsNCg0KICAgICAgICBpZiAoKGludCkkcGRmLT5vdXRwdXRfbW9kZSA9PSA0IHx8IChpbnQpJHBkZi0+b3V0cHV0X21vZGUgPT0gNSkgew0KDQogICAgICAgICAgICAkY29kZV9vcGVuID0gIlxuaWYoaXNzZXQoXCRfU0VTU0lPTlsnUkZfUmVuZGVyX0FzX1BERl9FbWFpbF9UZW1wbGF0ZV9Pbl9TdWJtaXNzaW9uJ10pKSB7XG4iOw0KICAgICAgICAgICAgJGNvZGVfY2xvc2UgPSAiXG59XG4iOw0KDQogICAgICAgICAgICAkY29kZV9jbG9zZSA9IDw8PEVPRg0KDQp9IGVsc2Ugew0KDQoJLy8gUERGIFJlbmRlcmluZyBGbGFncy4NCglcJFBBR0VfSVNfUERGID0gZmFsc2U7DQoJXCRQREZfTElCUkFSWSA9ICIiOw0KDQp9DQoNCkVPRjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKChpbnQpJHBhZ2UtPnBhZ2V0eXBlID09IDIpIHsNCg0KICAgICAgICAgICAgICAgICRjb2RlID0gIlxuXG48P3BocFxuXCRfU0VTU0lPTlsnUkZfUmVuZGVyX0FzX1BERl9FbWFpbF9UZW1wbGF0ZV9Pbl9TdWJtaXNzaW9uJ10gPSB0cnVlO1xuPz5cblxuIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHN3aXRjaCAoKGludCkkcGRmLT5saWJyYXJ5KSB7DQoNCiAgICAgICAgICAgIGNhc2UgJzAnOiANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkY29kZSAuPSA8PDxFT0YNCjw/cGhwDQoNCnskY29kZV9vcGVufQ0KcmVxdWlyZV9vbmNlKCcuLi8uLi8uLi9jb21wb3Nlci92ZW5kb3IvYXV0b2xvYWQucGhwJyk7CQkNCgkJCQ0KLy8gVHVybiBvbiB0aGUgb3V0cHV0IGJ1ZmZlciwgcHJldmVudHMgYW55IG91dHB1dCwgd2hpY2ggaXMgcmVxdWlyZWQuDQpAaW5pX3NldCgnb3V0cHV0X2J1ZmZlcmluZycsICdPbicpOw0KaWYoaW5pX2dldCgnb3V0cHV0X2J1ZmZlcmluZycpID09ICIiIHx8IGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAnMCcgfHwgaW5pX2dldCgnb3V0cHV0X2J1ZmZlcmluZycpID09ICJPZmYiKSB7DQoJXCRwZGZfbWVzc2FnZSA9ICI8ZGl2IHN0eWxlPVwicGFkZGluZzozMHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiNmMWYxZjE7IGNvbG9yOiM1NDU0NTQ7IGZvbnQtZmFtaWx5OiBBcmlhbDsgYm9yZGVyLXJhZGl1czo0cHg7XCI+IjsNCglcJHBkZl9tZXNzYWdlIC49ICI8aDM+UERGIGNyZWF0aW9uIHJlcXVpcmVzIGEgUEhQIGZlYXR1cmUgY2FsbGVkIDxzdHJvbmc+T3V0cHV0IEJ1ZmZlcmluZzwvc3Ryb25nPiwgd2hpY2ggaXMgbm90IGVuYWJsZWQgb24gdGhpcyBzZXJ2ZXIuPC9oMz4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIiZuYnNwO1BsZWFzZSBjaGVjayB3aXRoIHlvdXIgaG9zdGluZyBwcm92aWRlciBmb3IgaW5zdHJ1Y3Rpb25zIG9uIGhvdyB0byBlbmFibGUuPGJyLz48YnIvPiI7DQoJXCRwZGZfbWVzc2FnZSAuPSAiVHlwaWNhbCB2YWx1ZXMgd2lsbCBiZSA8c3Ryb25nPjE8L3N0cm9uZz4gb3IgPHN0cm9uZz5Pbjwvc3Ryb25nPi4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIjwvZGl2PiI7DQoJZGllKFwkcGRmX21lc3NhZ2UpOw0KfQ0Kb2Jfc3RhcnQoKTsNCgkJCQ0KLy8gUERGIFJlbmRlcmluZyBGbGFnLg0KXCRQQUdFX0lTX1BERiA9IHRydWU7DQpcJFBERl9MSUJSQVJZID0gIkRPTVBERiI7DQoNCnskY29kZV9jbG9zZX0NCj8+DQoNCkVPRjsNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICBjYXNlICcwLjEnOiANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNvZGUgLj0gPDw8RU9GDQo8P3BocA0KeyRjb2RlX29wZW59DQovLyBET01QREYgSW5jbHVkZS9TdGFydCBMb2dpYw0KcmVxdWlyZV9vbmNlKCcuLi8uLi8uLi9hcHAvbGliL3BkZi9kb21wZGYvZG9tcGRmX2NvbmZpZy5pbmMucGhwJyk7DQoJDQovLyB0dXJuIG9uIHRoZSBvdXRwdXQgYnVmZmVyLCBwcmV2ZW50cyBhbnkgb3V0cHV0LCB3aGljaCBpcyByZXF1aXJlZC4NCkBpbmlfc2V0KCdvdXRwdXRfYnVmZmVyaW5nJywgJ09uJyk7CQkJCQkNCmlmKGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAiIiB8fCBpbmlfZ2V0KCdvdXRwdXRfYnVmZmVyaW5nJykgPT0gJzAnIHx8IGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAiT2ZmIikgew0KCVwkcGRmX21lc3NhZ2UgPSAiPGRpdiBzdHlsZT1cInBhZGRpbmc6MzBweDsgYmFja2dyb3VuZC1jb2xvcjojZjFmMWYxOyBjb2xvcjojNTQ1NDU0OyBmb250LWZhbWlseTogQXJpYWw7IGJvcmRlci1yYWRpdXM6NHB4O1wiPiI7DQoJXCRwZGZfbWVzc2FnZSAuPSAiPGgzPlBERiBjcmVhdGlvbiByZXF1aXJlcyBhIFBIUCBmZWF0dXJlIGNhbGxlZCA8c3Ryb25nPk91dHB1dCBCdWZmZXJpbmc8L3N0cm9uZz4sIHdoaWNoIGlzIG5vdCBlbmFibGVkIG9uIHRoaXMgc2VydmVyLjwvaDM+IjsNCglcJHBkZl9tZXNzYWdlIC49ICImbmJzcDtQbGVhc2UgY2hlY2sgd2l0aCB5b3VyIGhvc3RpbmcgcHJvdmlkZXIgZm9yIGluc3RydWN0aW9ucyBvbiBob3cgdG8gZW5hYmxlLjxici8+PGJyLz4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIlR5cGljYWwgdmFsdWVzIHdpbGwgYmUgPHN0cm9uZz4xPC9zdHJvbmc+IG9yIDxzdHJvbmc+T248L3N0cm9uZz4uIjsNCglcJHBkZl9tZXNzYWdlIC49ICI8L2Rpdj4iOwkJCQkJCQ0KCWRpZShcJHBkZl9tZXNzYWdlKTsNCn0NCm9iX3N0YXJ0KCk7DQoJCQkJCQkNCi8vIFBERiBSZW5kZXJpbmcgRmxhZy4NClwkUEFHRV9JU19QREYgPSB0cnVlOw0KXCRQREZfTElCUkFSWSA9ICJET01QREYiOw0KeyRjb2RlX2Nsb3NlfQ0KPz4NCg0KRU9GOw0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgIGNhc2UgJzEnOiANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKChpbnQpJHBkZi0+b3JpZW50YXRpb24gPT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAkb3JpZW50YXRpb24gPSAnUCc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJG9yaWVudGF0aW9uID0gJ0wnOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRwYWdlX3NpemUgPSAkdGhpcy0+cGRmLT5nZXRfcGFnZV9zaXplX2tleSgoaW50KSRwZGYtPnBhZ2Vfc2l6ZSk7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRjb2RlIC49IDw8PEVPRg0KPD9waHANCg0KeyRjb2RlX29wZW59DQoNCi8vIFRoaXMgY29kZSBhZGRzIGEgYmFzaWMgdGNwZGYgaGVhZGVyIGNhbGwgdG8gYSBwYWdlLg0KDQovLyBGaXJzdCB3ZSBhZGQgc3RhbmRhcmQgdGNwZGYgY2FsbHMgZm9yIHNldHRpbmcgcGFnZSBzaXplIGFuZA0KLy8gZm9udCwgdGhlbiBjYWxsIEFkZFBhZ2UoKS4NCg0KLy8gV2UgZ2VuZXJhbGx5IGRvIG5vdCBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoaXMgYmxvY2sgaW4gdGVybXMNCi8vIG9mIGN1c3RvbWl6YXRpb24sIGV4Y2VwdCBmb3IgdGhlICdzZXQgZG9jdW1lbnQgaW5mb3JtYXRpb24nDQovLyBibG9jayB3aGVyZSB3ZSBjYW4gc2V0IFBERiBuYW1lLCBhdXRob3IsIGFuZCBzbyBvbi4NCg0KLy8gV2UgdGhlbiB0dXJuIG9uIHRoZSBvdXRwdXQgYnVmZmVyIHNvIHRoYXQgYWxsIEhUTUwgb24gdGhpcyBwYWdlDQovLyBjYW4gYmUgY2FwdHVyZWQgYW5kIHR1cm5lZCBpbnRvIGEgUERGLg0KDQovLyBSRVFVSVJFTUVOVFMNCi8vIFdlIG11c3QgZG93bmxvYWQgdGNwZGYgZnJvbToNCi8vIGh0dHA6Ly93d3cudGNwZGYub3JnL2Rvd25sb2FkLnBocA0KLy8gRXh0cmFjdCB0aGUgZmlsZSwgYW5kIHBsYWNlIGludG8gb3VyIGluc3RhbGwgZGlyZWN0b3J5IGF0Og0KLy8gcmFja2Zvcm1zL2FwcC9saWIvDQoNCi8vIExJTktTDQovLyBodHRwOi8vd3d3LnRjcGRmLm9yZy9kb2NzLnBocA0KDQoNCnJlcXVpcmVfb25jZSgnLi4vLi4vLi4vYXBwL2xpYi9wZGYvdGNwZGYvY29uZmlnL3RjcGRmX2NvbmZpZy5waHAnKTsNCnJlcXVpcmVfb25jZSgnLi4vLi4vLi4vYXBwL2xpYi9wZGYvdGNwZGYvdGNwZGYucGhwJyk7DQoNCi8vIGNyZWF0ZSBuZXcgUERGIGRvY3VtZW50DQpcJHBkZiA9IG5ldyBUQ1BERihQREZfUEFHRV9PUklFTlRBVElPTiwgUERGX1VOSVQsIFBERl9QQUdFX0ZPUk1BVCwgdHJ1ZSwgJ1VURi04JywgZmFsc2UpOw0KDQovLyBzZXQgZG9jdW1lbnQgaW5mb3JtYXRpb24NClwkcGRmLT5TZXRDcmVhdG9yKFBERl9DUkVBVE9SKTsNClwkcGRmLT5TZXRBdXRob3IoJ0Zvcm0gQ3JlYXRvcicpOw0KXCRwZGYtPlNldFRpdGxlKCdGb3JtIFBhZ2UnKTsNClwkcGRmLT5TZXRTdWJqZWN0KCdGb3JtIFBERicpOw0KXCRwZGYtPlNldEtleXdvcmRzKCcnKTsgLy8gY29tbWEgZGVsaW1pdGVkIGxpc3QNCg0KLy8gc2V0IGRlZmF1bHQgaGVhZGVyIGRhdGENClwkcGRmLT5TZXRIZWFkZXJEYXRhKFBERl9IRUFERVJfTE9HTywgUERGX0hFQURFUl9MT0dPX1dJRFRILCBQREZfSEVBREVSX1RJVExFLicgMDA2JywgUERGX0hFQURFUl9TVFJJTkcpOw0KDQovLyBzZXQgaGVhZGVyIGFuZCBmb290ZXIgZm9udHMNClwkcGRmLT5zZXRIZWFkZXJGb250KEFycmF5KFBERl9GT05UX05BTUVfTUFJTiwgJycsIFBERl9GT05UX1NJWkVfTUFJTikpOw0KXCRwZGYtPnNldEZvb3RlckZvbnQoQXJyYXkoUERGX0ZPTlRfTkFNRV9EQVRBLCAnJywgUERGX0ZPTlRfU0laRV9EQVRBKSk7DQoNCi8vIHJlbW92ZSBkZWZhdWx0IGhlYWRlci9mb290ZXINClwkcGRmLT5zZXRQcmludEhlYWRlcihmYWxzZSk7DQpcJHBkZi0+c2V0UHJpbnRGb290ZXIoZmFsc2UpOw0KDQovLyBzZXQgZGVmYXVsdCBtb25vc3BhY2VkIGZvbnQNClwkcGRmLT5TZXREZWZhdWx0TW9ub3NwYWNlZEZvbnQoUERGX0ZPTlRfTU9OT1NQQUNFRCk7DQoNCi8vc2V0IG1hcmdpbnMgLSBhbGwgdmFsdWVzIGluIG1pbGxpbWV0ZXJzIHBlciBQREZfVU5JVA0KXCRwZGYtPlNldE1hcmdpbnMoUERGX01BUkdJTl9MRUZULCAxLCBQREZfTUFSR0lOX1JJR0hUKTsgLy8gbGVmdCwgdG9wLCByaWdodA0KXCRwZGYtPlNldEhlYWRlck1hcmdpbihQREZfTUFSR0lOX0hFQURFUik7DQpcJHBkZi0+U2V0Rm9vdGVyTWFyZ2luKFBERl9NQVJHSU5fRk9PVEVSKTsNCg0KLy9zZXQgYXV0byBwYWdlIGJyZWFrcw0KXCRwZGYtPlNldEF1dG9QYWdlQnJlYWsoVFJVRSwgUERGX01BUkdJTl9CT1RUT00pOw0KDQovLyBTZXQgaW1hZ2UvdGV4dCBzY2FsZSBmYWN0b3IgZm9yIHBpeGVscyB0byB1c2VyIHVuaXRzDQovLyBEZWZhdWx0cyBpbiBjb25maWcvdGNwZGZfY29uZmlnLnBocCA6OiBQREZfSU1BR0VfU0NBTEVfUkFUSU8gdG8gMS4yNQ0KXCRwZGYtPnNldEltYWdlU2NhbGUoUERGX0lNQUdFX1NDQUxFX1JBVElPKTsNCg0KDQovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KLy8gc2V0IGZvbnQNClwkcGRmLT5TZXRGb250KCdoZWx2ZXRpY2EnLCAnJywgMTApOw0KDQovLyBhZGQgYSBwYWdlIC0gd2Ugc2V0IHBhZ2Ugc2l6ZSBoZXJlDQpcJHBkZi0+QWRkUGFnZSgneyRvcmllbnRhdGlvbn0nLCAneyRwYWdlX3NpemV9Jyk7DQoNCi8vIHR1cm4gb24gdGhlIG91dHB1dCBidWZmZXIsIHByZXZlbnRzIGFueSBvdXRwdXQsIHdoaWNoIGlzIHJlcXVpcmVkLg0KQGluaV9zZXQoJ291dHB1dF9idWZmZXJpbmcnLCAnT24nKTsNCg0KaWYoaW5pX2dldCgnb3V0cHV0X2J1ZmZlcmluZycpID09ICIiIHx8IGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAnMCcgfHwgaW5pX2dldCgnb3V0cHV0X2J1ZmZlcmluZycpID09ICJPZmYiKSB7DQoJXCRwZGZfbWVzc2FnZSA9ICI8ZGl2IHN0eWxlPVwicGFkZGluZzozMHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiNmMWYxZjE7IGNvbG9yOiM1NDU0NTQ7IGZvbnQtZmFtaWx5OiBBcmlhbDsgYm9yZGVyLXJhZGl1czo0cHg7XCI+IjsNCglcJHBkZl9tZXNzYWdlIC49ICI8aDM+UERGIGNyZWF0aW9uIHJlcXVpcmVzIGEgUEhQIGZlYXR1cmUgY2FsbGVkIDxzdHJvbmc+T3V0cHV0IEJ1ZmZlcmluZzwvc3Ryb25nPiwgd2hpY2ggaXMgbm90IGVuYWJsZWQgb24gdGhpcyBzZXJ2ZXIuPC9oMz4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIiZuYnNwO1BsZWFzZSBjaGVjayB3aXRoIHlvdXIgaG9zdGluZyBwcm92aWRlciBmb3IgaW5zdHJ1Y3Rpb25zIG9uIGhvdyB0byBlbmFibGUuPGJyLz48YnIvPiI7DQoJXCRwZGZfbWVzc2FnZSAuPSAiVHlwaWNhbCB2YWx1ZXMgd2lsbCBiZSA8c3Ryb25nPjE8L3N0cm9uZz4gb3IgPHN0cm9uZz5Pbjwvc3Ryb25nPi4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIjwvZGl2PiI7CQkJCQkJDQoJZGllKFwkcGRmX21lc3NhZ2UpOw0KfQ0Kb2Jfc3RhcnQoKTsNCgkNCi8vIFBERiBSZW5kZXJpbmcgRmxhZ3MuDQpcJFBBR0VfSVNfUERGID0gdHJ1ZTsNClwkUERGX0xJQlJBUlkgPSAiVENQREYiOw0KeyRjb2RlX2Nsb3NlfQ0KPz4NCg0KRU9GOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICBjYXNlICcyJzogDQoNCiAgICAgICAgICAgICAgICAkY29kZSAuPSA8PDxFT0YNCjw/cGhwDQp7JGNvZGVfb3Blbn0NCi8vIG1QREYgSW5jbHVkZS9TdGFydCBMb2dpYw0KICANCi8vIHR1cm4gb24gdGhlIG91dHB1dCBidWZmZXIsIHByZXZlbnRzIGFueSBvdXRwdXQsIHdoaWNoIGlzIHJlcXVpcmVkLg0KQGluaV9zZXQoJ291dHB1dF9idWZmZXJpbmcnLCAnT24nKTsNCmlmKGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAiIiB8fCBpbmlfZ2V0KCdvdXRwdXRfYnVmZmVyaW5nJykgPT0gJzAnIHx8IGluaV9nZXQoJ291dHB1dF9idWZmZXJpbmcnKSA9PSAiT2ZmIikgew0KCVwkcGRmX21lc3NhZ2UgPSAiPGRpdiBzdHlsZT1cInBhZGRpbmc6MzBweDsgYmFja2dyb3VuZC1jb2xvcjojZjFmMWYxOyBjb2xvcjojNTQ1NDU0OyBmb250LWZhbWlseTogQXJpYWw7IGJvcmRlci1yYWRpdXM6NHB4O1wiPiI7DQoJXCRwZGZfbWVzc2FnZSAuPSAiPGgzPlBERiBjcmVhdGlvbiByZXF1aXJlcyBhIFBIUCBmZWF0dXJlIGNhbGxlZCA8c3Ryb25nPk91dHB1dCBCdWZmZXJpbmc8L3N0cm9uZz4sIHdoaWNoIGlzIG5vdCBlbmFibGVkIG9uIHRoaXMgc2VydmVyLjwvaDM+IjsNCglcJHBkZl9tZXNzYWdlIC49ICImbmJzcDtQbGVhc2UgY2hlY2sgd2l0aCB5b3VyIGhvc3RpbmcgcHJvdmlkZXIgZm9yIGluc3RydWN0aW9ucyBvbiBob3cgdG8gZW5hYmxlLjxici8+PGJyLz4iOw0KCVwkcGRmX21lc3NhZ2UgLj0gIlR5cGljYWwgdmFsdWVzIHdpbGwgYmUgPHN0cm9uZz4xPC9zdHJvbmc+IG9yIDxzdHJvbmc+T248L3N0cm9uZz4uIjsNCglcJHBkZl9tZXNzYWdlIC49ICI8L2Rpdj4iOwkJCQkJCQ0KCWRpZShcJHBkZl9tZXNzYWdlKTsNCn0NCm9iX3N0YXJ0KCk7DQoNCi8vIFRoaXMgY29kZSBhZGRzIGEgYmFzaWMgbXBkZiBmb290ZXIgY2FsbCB0byBhIHBhZ2UuDQpyZXF1aXJlX29uY2UoJy4uLy4uLy4uL2NvbXBvc2VyL3ZlbmRvci9hdXRvbG9hZC5waHAnKTsNCgkJCQkJDQovLyBQREYgUmVuZGVyaW5nIEZsYWcuDQpcJFBBR0VfSVNfUERGID0gdHJ1ZTsNClwkUERGX0xJQlJBUlkgPSAiTVBERiI7DQp7JGNvZGVfY2xvc2V9DQo/Pg0KDQpFT0Y7DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfSANCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgaWYgKChpbnQpJHBkZi0+ZW5hYmxlX3BkZiA9PSAxKSB7DQoNCiAgICAgICAgICAgIHJldHVybiAkY29kZTsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgoaW50KSRwZGYtPm91dHB1dF9tb2RlICE9IDQgJiYgKGludCkkcGRmLT5vdXRwdXRfbW9kZSAhPSA1KSB7DQogICAgICAgICAgICAgICAgJGNvZGUgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGNvZGUgLj0gPDw8RU9GDQo8P3BocA0KLy8gUERGIFJlbmRlcmluZyBPdXRwdXQgRmxhZ3MuDQpcJFBBR0VfSVNfUERGID0gZmFsc2U7DQpcJFBERl9MSUJSQVJZID0gIiI7DQoNCj8+DQoJCQ0KRU9GOw0KDQogICAgICAgICAgICByZXR1cm4gJGNvZGU7DQogICAgICAgIH0NCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfcGFnZV9wZGZfZW5kKCRwYWdlKQ0KICAgIHsNCg0KICAgICAgICAkcGRmID0gJHBhZ2UtPnBkZjsNCiAgICAgICAgJHBhZ2V0aXRsZSA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJHBhZ2UtPnRpdGxlLCAxKTsgDQogICAgICAgICRwYWdlbmFtZSA9ICRwYWdlLT5uYW1lOw0KICAgICAgICAkb25zdWNjZXNzID0gJHBhZ2UtPmZvcm0tPm9uc3VjY2VzczsNCg0KICAgICAgICAkY29kZSA9ICIiOw0KDQogICAgICAgIHN3aXRjaCAoKGludCkkcGRmLT5saWJyYXJ5KSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgY2FzZSAnMCc6DQoNCiAgICAgICAgICAgICAgICBzd2l0Y2ggKChpbnQpJHBkZi0+b3V0cHV0X21vZGUpIHsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9tb2RlID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfY29kZSA9ICJcJGRvbXBkZi0+c3RyZWFtKFwieyRwYWdldGl0bGV9LnBkZlwiLCBhcnJheSgnY29tcHJlc3MnID0+IDEsICdBdHRhY2htZW50Jz0+eyRvdXRwdXRfbW9kZX0pKTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfbW9kZSA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X2NvZGUgPSAiXCRkb21wZGYtPnN0cmVhbShcInskcGFnZXRpdGxlfS5wZGZcIiwgYXJyYXkoJ2NvbXByZXNzJyA9PiAxLCAnQXR0YWNobWVudCc9Pnskb3V0cHV0X21vZGV9KSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlIDIgfHwgNDogDQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X21vZGUgPSAyOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X2NvZGUgPSA8PDxFT0YNCg0KLy8gY3JlYXRlIHNhdmUgZGlyZWN0b3J5IGlmIG5lZWRlZC4gKERPTVBERiBFeHBvcnQpDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19Iikpew0KCWlmKCFmaWxlX2V4aXN0cygidG1wIikpIHsNCgkJbWtkaXIoInRtcC8iKTsNCgl9DQoJbWtkaXIoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19Iik7DQoJbWtkaXIoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpOw0KfQ0KDQovLyBjcmVhdGUgcGRmIGZvbGRlcg0KaWYoIWZpbGVfZXhpc3RzKCJ0bXAve1wkX1NFU1NJT05bImVudHJ5X2tleSJdfS9wZGYiKSl7DQoJbWtkaXIoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpOw0KfQ0KDQovLyBzYXZlIHBkZiBmaWxlDQpcJHBkZm91dHB1dCA9IFwkZG9tcGRmLT5vdXRwdXQoKTsNCg0KLy8gU2F2ZSBUbyBTZXNzaW9uIEZvciBUb2tlbiBBY2Nlc3MNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnUERGX1RFTVBMQVRFX0RBVEEnXSA9IFwkcGRmb3V0cHV0Ow0KDQpcJHBkZl9wYWdldGl0bGUgPSBwcmVnX3JlcGxhY2UoIi9bXkEtWmEtejAtOSBdLyIsICcnLCAieyRwYWdldGl0bGV9Iik7DQoNCmlmKGZpbGVfZXhpc3RzKCJ0bXAve1wkX1NFU1NJT05bImVudHJ5X2tleSJdfS9wZGYve1wkcGRmX3BhZ2V0aXRsZX0iKSkgew0KCVwkZmlsZW5hbWUgPSAidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmL3tcJHBkZl9wYWdldGl0bGV9LnBkZiI7DQp9IGVsc2Ugew0KCVwkZmlsZW5hbWUgPSAidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmL3tcJHBkZl9wYWdldGl0bGV9LnBkZiI7DQp9DQoNClwkZnAgPSBmb3BlbihcJGZpbGVuYW1lLCAiYSIpOw0KZndyaXRlKFwkZnAsIFwkcGRmb3V0cHV0KTsNCmZjbG9zZShcJGZwKTsgDQoNCi8vIHJlZGlyZWN0IHRvIG5leHQgcGFnZQ0KaGVhZGVyKCJMb2NhdGlvbjogeyRvbnN1Y2Nlc3N9Iik7DQpleGl0KDApOw0KRU9GOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBjYXNlIDMgfHwgNTogDQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X21vZGUgPSAyOw0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9jb2RlID0gPDw8RU9GDQoNClwkZmlsZV9kYXRhID0gXCRkb21wZGYtPm91dHB1dCgpOw0KDQovLyBTYXZlIFRvIFNlc3Npb24gRm9yIFRva2VuIEFjY2Vzcw0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydQREZfVEVNUExBVEVfREFUQSddID0gXCRmaWxlX2RhdGE7DQoNCi8vIHJlZGlyZWN0IHRvIG5leHQgcGFnZQ0KaGVhZGVyKCJMb2NhdGlvbjogeyRvbnN1Y2Nlc3N9Iik7DQpleGl0KDApOw0KDQpFT0Y7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgIGlmICgoaW50KSRwZGYtPm9yaWVudGF0aW9uID09IDApIHsNCiAgICAgICAgICAgICAgICAgICAgJG9yaWVudGF0aW9uID0gJ3BvcnRyYWl0JzsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkb3JpZW50YXRpb24gPSAnbGFuZHNjYXBlJzsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkcGFnZV9zaXplID0gJHRoaXMtPnBkZi0+Z2V0X3BhZ2Vfc2l6ZV9rZXkoKGludCkkcGRmLT5wYWdlX3NpemUpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkb3B0aW9uX2FsbG93X3JlbW90ZSA9IChpc3NldCgkcGRmLT5hbGxvd19yZW1vdGUpICYmICRwZGYtPmFsbG93X3JlbW90ZSA9PSAiMSIpID8gJyRvcHRpb25zLT5zZXQoXCdpc1JlbW90ZUVuYWJsZWRcJywgdHJ1ZSk7JyA6ICcnOw0KDQogICAgICAgICAgICAgICAgJG9wdGlvbnNfYm9keSA9IDw8PEVPRg0KDQogIC8vIE9wdGlvbnMNCiAgXCRvcHRpb25zID0gbmV3IE9wdGlvbnMoKTsNCiAgXCRvcHRpb25zLT5zZXQoJ2lzSHRtbDVQYXJzZXJFbmFibGVkJywgdHJ1ZSk7DQogIHskb3B0aW9uX2FsbG93X3JlbW90ZX0NCiAgXCRvcHRpb25zLT5zZXQoJ2Nocm9vdCcsICcuLycpOyAvLyBFbHNlIEltYWdlcyBEbyBOb3QgV29yay4NCg0KRU9GOw0KDQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNyeXB0ID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBkZi0+ZW5jcnlwdGlvbikgJiYgKGludCkkcGRmLT5lbmNyeXB0aW9uID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkcGVybWlzc2lvbnNfYXJyYXkgPSAiYXJyYXkoIjsNCg0KICAgICAgICAgICAgICAgICAgICAkaXRlbXMgPSAiIjsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX3ByaW50ID09IDEpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiJ3ByaW50JyI7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX2NvcHkgPT0gMSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRpdGVtcyAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAkaXRlbXMgLj0gIidjb3B5JyI7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX21vZGlmeSA9PSAxKSB7DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJGl0ZW1zICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGl0ZW1zIC49ICIsIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiJ21vZGlmeSciOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgJHBlcm1pc3Npb25zX2FycmF5IC49ICRpdGVtczsNCg0KICAgICAgICAgICAgICAgICAgICAkcGVybWlzc2lvbnNfYXJyYXkgLj0gIikiOw0KDQoNCiAgICAgICAgICAgICAgICAgICAgJGNyeXB0ID0gIlwkZG9tcGRmLT5nZXRfY2FudmFzKCktPmdldF9jcGRmKCktPnNldEVuY3J5cHRpb24oJ3skcGRmLT51c2VyX3B3ZH0nLCd7JHBkZi0+b3duZXJfcHdkfScseyRwZXJtaXNzaW9uc19hcnJheX0pOyI7DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRjb2RlID0gPDw8RU9GDQo8P3BocA0KICANCiAgLy8gVGhpcyBjb2RlIGFkZHMgYSBiYXNpYyBET01QREYgZm9vdGVyIGNhbGwgdG8gYSBwYWdlLg0KICANCiAgLy8gVGhpcyBjb2RlIHRha2VzIHRoZSBvdXRwdXQgYnVmZmVyJ3MgY29udGVudHMNCiAgLy8gY3JlYXRlZCBpbiB0aGUgRE9NUERGIFNpbmdsZSBQYWdlIEhlYWRlciBJbmNsdWRlDQogIC8vIGNvZGUgYmxvY2sgYW5kIG91dHB1dHMgYSBQREYgdG8gdGhlIGJyb3dzZXIgb3IgcHJvbXB0cyBmb3IgZG93bmxvYWQuDQogIA0KICAvLyBjYXB0dXJlIG91dHB1dCBidWZmZXIsIHR1cm4gb2ZmIGJ1ZmZlcmluZw0KICBcJGh0bWwgPSBvYl9nZXRfZmx1c2goKTsNCiAgDQogIC8vIGVyYXNlcyB0aGUgYnVmZmVyLCB0dXJucyBpdCBvZmYNCiAgb2JfY2xlYW4gKCk7DQoNCiAgdXNlIERvbXBkZlxEb21wZGY7DQogIHVzZSBEb21wZGZcT3B0aW9uczsNCiAgDQogIHskb3B0aW9uc19ib2R5fQ0KICANCiAgXCRkb21wZGYgPSBuZXcgRE9NUERGKFwkb3B0aW9ucyk7DQogIA0KICAvLyBkb2N1bWVudCBzaXplDQogIA0KICBcJHdpZHRoID0gJ3skcGRmLT5jdXN0b21feH0nOw0KICBcJGhlaWdodCA9ICd7JHBkZi0+Y3VzdG9tX3l9JzsNCiAgDQogIGlmKFwkd2lkdGggIT0gIiIgJiYgXCRoZWlnaHQgIT0gIiIpew0KICAJXCRkb21wZGYtPnNldFBhcGVyKGFycmF5KDAsMCxcJHdpZHRoLFwkaGVpZ2h0KSk7DQogIH0gZWxzZSB7DQogIAlcJGRvbXBkZi0+c2V0UGFwZXIoJ3skcGFnZV9zaXplfScsICd7JG9yaWVudGF0aW9ufScpOw0KICB9DQoNCiAgXCRkb21wZGYtPmxvYWRIdG1sKFwkaHRtbCk7DQogIA0KICAvLyBcJF9kb21wZGZfd2FybmluZ3MgY29udGFpbnMgYWxsIHBhcnNlIGVycm9ycw0KICAvLyBUbyBzZWUgYW55IHN1Y2ggaXRlbXMsIHVuY29tbWVudCB0aGUgbmV4dCBsaW5lLg0KICAvL3ByaW50X3IoXCRfZG9tcGRmX3dhcm5pbmdzKTsgZGllOw0KICANCiAgXCRkb21wZGYtPnJlbmRlcigpOw0KICB7JGNyeXB0fQ0KICB7JG91dHB1dF9jb2RlfQ0KICANCiAgLy8gT3B0aW9uYWwNCiAgLy9jbGVhcl9mYl9zZXNzaW9uKCk7DQoNCj8+DQpFT0Y7DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGNhc2UgJzEnOiANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBzd2l0Y2ggKChpbnQpJHBkZi0+b3V0cHV0X21vZGUpIHsNCg0KICAgICAgICAgICAgICAgICAgICBjYXNlIDA6DQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X21vZGUgPSAnSSc7DQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X2NvZGUgPSAiXCRwZGYtPk91dHB1dCgneyRwYWdldGl0bGV9LnBkZicsICd7JG91dHB1dF9tb2RlfScpOyI7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9tb2RlID0gJ0QnOw0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9jb2RlID0gIlwkcGRmLT5PdXRwdXQoJ3skcGFnZXRpdGxlfS5wZGYnLCAneyRvdXRwdXRfbW9kZX0nKTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgMiB8fCA0OiANCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfbW9kZSA9ICdGJzsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9jb2RlID0gPDw8RU9GDQoNCi8vIGNyZWF0ZSBzYXZlIGRpcmVjdG9yeSBpZiBuZWVkZWQuIChUQ1BERikNCmlmKCFmaWxlX2V4aXN0cygidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0iKSl7DQoJaWYoIWZpbGVfZXhpc3RzKCJ0bXAiKSkgew0KCQlta2RpcigidG1wLyIpOw0KCX0NCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0iKTsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIGNyZWF0ZSBwZGYgZm9sZGVyDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpKXsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIHNhdmUgcGRmIGZpbGUNClwkcGRmX3BhZ2V0aXRsZSA9IHByZWdfcmVwbGFjZSgiL1teQS1aYS16MC05IF0vIiwgJycsICJ7JHBhZ2V0aXRsZX0iKTsNClwkcGRmLT5PdXRwdXQoX19ESVJfXy4iL3RtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZi97XCRwZGZfcGFnZXRpdGxlfS5wZGYiLCAneyRvdXRwdXRfbW9kZX0nKTsNCg0KLy8gU2F2ZSBUbyBTZXNzaW9uIEZvciBUb2tlbiBBY2Nlc3MNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnUERGX1RFTVBMQVRFX0RBVEEnXSA9IGZpbGVfZ2V0X2NvbnRlbnRzKF9fRElSX18uIi90bXAve1wkX1NFU1NJT05bImVudHJ5X2tleSJdfS9wZGYve1wkcGRmX3BhZ2V0aXRsZX0ucGRmIik7DQoNCi8vIHJlZGlyZWN0IHRvIG5leHQgcGFnZQ0KaGVhZGVyKCJMb2NhdGlvbjogeyRvbnN1Y2Nlc3N9Iik7DQpleGl0KDApOw0KRU9GOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAzIHx8IDU6IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X21vZGUgPSAnRic7DQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X2NvZGUgPSA8PDxFT0YNCg0KLy8gY3JlYXRlIHNhdmUgZGlyZWN0b3J5IGlmIG5lZWRlZC4gKFRDUERGKQ0KaWYoIWZpbGVfZXhpc3RzKCJ0bXAve1wkX1NFU1NJT05bImVudHJ5X2tleSJdfSIpKXsNCglpZighZmlsZV9leGlzdHMoInRtcCIpKSB7DQoJCW1rZGlyKCJ0bXAvIik7DQoJfTsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0iKTsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIGNyZWF0ZSBwZGYgZm9sZGVyDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpKXsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIHNhdmUgcGRmIGZpbGUNClwkcGRmLT5PdXRwdXQoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZi97JHBhZ2V0aXRsZX0ucGRmIiwgJ3skb3V0cHV0X21vZGV9Jyk7DQoNClwkZmlsZV9kYXRhID0gZmlsZV9nZXRfY29udGVudHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZi97JHBhZ2V0aXRsZX0ucGRmIik7DQoJCQkJCQkNCi8vIFNhdmUgVG8gU2Vzc2lvbiBGb3IgVG9rZW4gQWNjZXNzOiBGe1BERl9URU1QTEFURV9EQVRBfQ0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydQREZfVEVNUExBVEVfREFUQSddID0gXCRmaWxlX2RhdGE7DQoNCi8vIHJlZGlyZWN0IHRvIG5leHQgcGFnZQ0KaGVhZGVyKCJMb2NhdGlvbjogeyRvbnN1Y2Nlc3N9Iik7DQpleGl0KDApOw0KCQkJCQkJDQpFT0Y7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgICRjb2RlID0gPDw8RU9GDQo8P3BocA0KDQogIC8vIFRoaXMgY29kZSBhZGRzIGEgYmFzaWMgdGNwZGYgZm9vdGVyIGNhbGwgdG8gYSBwYWdlLg0KICANCiAgLy8gVGhpcyBjb2RlIHRha2VzIHRoZSBvdXRwdXQgYnVmZmVyJ3MgY29udGVudHMNCiAgLy8gY3JlYXRlZCBpbiB0aGUgVENQREYgU2luZ2xlIFBhZ2UgSGVhZGVyIEluY2x1ZGUNCiAgLy8gY29kZSBibG9jayBhbmQgb3V0cHV0cyBhIFBERiB0byB0aGUgYnJvd3Nlci4NCg0KDQogIC8vIGNhcHR1cmUgb3V0cHV0IGJ1ZmZlciwgdHVybiBvZmYgYnVmZmVyaW5nDQogIFwkaHRtbCA9IG9iX2dldF9mbHVzaCgpOw0KICANCiAgLy8gZXJhc2VzIHRoZSBidWZmZXIsIHR1cm5zIGl0IG9mZg0KICBvYl9jbGVhbiAoKTsNCiAgDQogIC8vIG91dHB1dCB0aGUgSFRNTCBjb250ZW50DQogIFwkcGRmLT53cml0ZUhUTUwoXCRodG1sLCB0cnVlLCBmYWxzZSwgdHJ1ZSwgZmFsc2UsICcnKTsNCiAgDQogIC8vIG91dHB1dCBQREYgdG8gYnJvd3Nlcg0KICB7JG91dHB1dF9jb2RlfQ0KICANCiAgLy8gT3B0aW9uYWwNCiAgLy9jbGVhcl9mYl9zZXNzaW9uKCk7DQogIA0KPz4NCkVPRjsNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGNhc2UgJzInOg0KDQogICAgICAgICAgICAgICAgc3dpdGNoICgoaW50KSRwZGYtPm91dHB1dF9tb2RlKSB7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfbW9kZSA9ICdJJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfY29kZSA9ICJcJG1wZGYtPk91dHB1dCgneyRwYWdldGl0bGV9LnBkZicsICd7JG91dHB1dF9tb2RlfScpOyAvLyBwYWdlIHRpdGxlLCBvdXRwdXQgbW9kZSI7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9tb2RlID0gJ0QnOw0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9jb2RlID0gIlwkbXBkZi0+T3V0cHV0KCd7JHBhZ2V0aXRsZX0ucGRmJywgJ3skb3V0cHV0X21vZGV9Jyk7IC8vIHBhZ2UgdGl0bGUsIG91dHB1dCBtb2RlIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlIDIgfHwgNDogDQogICAgICAgICAgICAgICAgICAgICAgICAkb3V0cHV0X21vZGUgPSAnRic7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRvdXRwdXRfY29kZSA9IDw8PEVPRg0KDQovLyBjcmVhdGUgc2F2ZSBkaXJlY3RvcnkgaWYgbmVlZGVkLiAobVBERikNCmlmKCFmaWxlX2V4aXN0cygidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0iKSl7DQoJaWYoIWZpbGVfZXhpc3RzKCJ0bXAiKSkgew0KCQlta2RpcigidG1wLyIpOw0KCX0NCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0iKTsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIGNyZWF0ZSBwZGYgZm9sZGVyDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpKXsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoNCi8vIHNhdmUgcGRmIGZpbGUgd2l0aCBzYW5pdGl6ZWQgZmlsZSBuYW1lLg0KXCRwZGZfcGFnZXRpdGxlID0gcHJlZ19yZXBsYWNlKCIvW15BLVphLXowLTkgXS8iLCAnJywgInskcGFnZXRpdGxlfSIpOw0KXCRtcGRmLT5PdXRwdXQoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZi97XCRwZGZfcGFnZXRpdGxlfS5wZGYiLCAneyRvdXRwdXRfbW9kZX0nKTsgLy8gcGFnZSB0aXRsZSwgb3V0cHV0IG1vZGUNCg0KLy8gU2F2ZSBUbyBTZXNzaW9uIEZvciBUb2tlbiBBY2Nlc3MNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnUERGX1RFTVBMQVRFX0RBVEEnXSA9IGZpbGVfZ2V0X2NvbnRlbnRzKCJ0bXAve1wkX1NFU1NJT05bImVudHJ5X2tleSJdfS9wZGYve1wkcGRmX3BhZ2V0aXRsZX0ucGRmIik7DQoNCi8vIHJlZGlyZWN0IHRvIG5leHQgcGFnZQ0KaGVhZGVyKCJMb2NhdGlvbjogeyRvbnN1Y2Nlc3N9Iik7DQpleGl0KDApOw0KRU9GOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAzIHx8IDU6IA0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9tb2RlID0gJ0YnOw0KICAgICAgICAgICAgICAgICAgICAgICAgJG91dHB1dF9jb2RlID0gPDw8RU9GDQoJCQkJCQ0KLy8gY3JlYXRlIHNhdmUgZGlyZWN0b3J5IGlmIG5lZWRlZC4gKG1QREYpDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19Iikpew0KCWlmKCFmaWxlX2V4aXN0cygidG1wIikpIHsNCgkJbWtkaXIoInRtcC8iKTsNCgl9DQoJbWtkaXIoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19Iik7DQoJbWtkaXIoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpOw0KfQ0KCQkJCQkNCi8vIGNyZWF0ZSBwZGYgZm9sZGVyDQppZighZmlsZV9leGlzdHMoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZiIpKXsNCglta2RpcigidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmIik7DQp9DQoJCQkJCQ0KLy8gc2F2ZSBwZGYgZmlsZQ0KXCRtcGRmLT5PdXRwdXQoInRtcC97XCRfU0VTU0lPTlsiZW50cnlfa2V5Il19L3BkZi97JHBhZ2V0aXRsZX0ucGRmIiwgJ3skb3V0cHV0X21vZGV9Jyk7IC8vIHBhZ2UgdGl0bGUsIG91dHB1dCBtb2RlDQoJCQkJCQ0KXCRmaWxlX2RhdGEgPSBmaWxlX2dldF9jb250ZW50cygidG1wL3tcJF9TRVNTSU9OWyJlbnRyeV9rZXkiXX0vcGRmL3skcGFnZXRpdGxlfS5wZGYiKTsNCgkJCQkJCQ0KLy8gU2F2ZSBUbyBTZXNzaW9uIEZvciBUb2tlbiBBY2Nlc3M6IEZ7UERGX1RFTVBMQVRFX1BBR0V9DQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ1BERl9URU1QTEFURV9EQVRBJ10gPSBcJGZpbGVfZGF0YTsNCg0KLy8gcmVkaXJlY3QgdG8gbmV4dCBwYWdlDQpoZWFkZXIoIkxvY2F0aW9uOiB7JG9uc3VjY2Vzc30iKTsNCmV4aXQoMCk7DQoNCkVPRjsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5vcmllbnRhdGlvbiA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICRvcmllbnRhdGlvbiA9ICdQJzsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkb3JpZW50YXRpb24gPSAnTCc7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJHBhZ2Vfc2l6ZSA9ICR0aGlzLT5wZGYtPmdldF9wYWdlX3NpemVfa2V5KChpbnQpJHBkZi0+cGFnZV9zaXplKTsNCg0KICAgICAgICAgICAgICAgICRwYWdlX3NpemVfdmFsdWVzID0gJHRoaXMtPnBkZi0+Z2V0X3BhcGVyX3NpemVfYnlfbnVtZXJpY19pbmRleCgoaW50KSRwZGYtPnBhZ2Vfc2l6ZSk7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBhcnJheV9zaGlmdCgkcGFnZV9zaXplX3ZhbHVlcyk7DQogICAgICAgICAgICAgICAgYXJyYXlfc2hpZnQoJHBhZ2Vfc2l6ZV92YWx1ZXMpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRwZGYtPmN1c3RvbV94KSAmJiAkcGRmLT5jdXN0b21feCAhPSAnJyAmJiBpc3NldCgkcGRmLT5jdXN0b21feSkgJiYgJHBkZi0+Y3VzdG9tX3kgIT0gJycpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgJHNpemVfYXJyYXkgPSAiYXJyYXkoeyRwZGYtPmN1c3RvbV94fSAqIDAuMjY0NTgzMzMsIHskcGRmLT5jdXN0b21feX0qIDAuMjY0NTgzMzMpIjsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICRzaXplX2FycmF5ID0gJ2FycmF5KCc7DQoNCiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJHBhZ2Vfc2l6ZV92YWx1ZXMgYXMgJGlkeCA9PiAkdmFsdWUpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRpZHggIT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzaXplX2FycmF5IC49ICcsJzsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkc2l6ZV9hcnJheSAuPSAiIHskdmFsdWV9ICogMC4zNTI3IjsgDQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAkc2l6ZV9hcnJheSAuPSAnKSc7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkY3JlYXRlX2NvZGUgPSAiXCRtcGRmPW5ldyBtUERGKCd1dGYtOCcsIHskc2l6ZV9hcnJheX0pOyI7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGNyZWF0ZV9jb2RlID0gPDw8RU9GDQoNClwkbXBkZiA9IG5ldyBcTXBkZlxNcGRmKFsNCiAgICAnbW9kZScgPT4gJ3V0Zi04JywNCiAgICAnZm9ybWF0JyA9PiAneyRwYWdlX3NpemV9JywNCiAgICAnb3JpZW50YXRpb24nID0+ICd7JG9yaWVudGF0aW9ufScsDQogICAgJ21hcmdpbl9sZWZ0JyA9PiB7JHBhZ2UtPnBhZ2VtYXJnaW59LA0KICAgICdtYXJnaW5fcmlnaHQnID0+IHskcGFnZS0+cGFnZW1hcmdpbn0sDQogICAgJ21hcmdpbl90b3AnID0+IHskcGFnZS0+cGFnZW1hcmdpbn0sDQogICAgJ21hcmdpbl9ib3R0b20nID0+IHskcGFnZS0+cGFnZW1hcmdpbn0NCl0pOw0KDQpFT0Y7DQoNCiAgICAgICAgICAgICAgICBpZiAoJHBkZi0+Y3VzdG9tX3ggIT0gIiIgJiYgJHBkZi0+Y3VzdG9tX3kgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkY3JlYXRlX2NvZGUgPSA8PDxFT0YNCgkJCQkNClwkbXBkZiA9IG5ldyBcTXBkZlxNcGRmKFsNCiAgICAnbW9kZScgPT4gJ3V0Zi04JywNCiAgICAnZm9ybWF0JyA9PiB7JHNpemVfYXJyYXl9LA0KICAgICdvcmllbnRhdGlvbicgPT4gJ3skb3JpZW50YXRpb259Jw0KXSk7DQoNCkVPRjsNCiAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNyeXB0ID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBkZi0+ZW5jcnlwdGlvbikgJiYgKGludCkkcGRmLT5lbmNyeXB0aW9uID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkcGVybWlzc2lvbnNfYXJyYXkgPSAiYXJyYXkoIjsNCg0KICAgICAgICAgICAgICAgICAgICAkaXRlbXMgPSAiIjsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX3ByaW50ID09IDEpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiJ3ByaW50JyI7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX2NvcHkgPT0gMSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRpdGVtcyAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAkaXRlbXMgLj0gIidjb3B5JyI7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGRmLT5wZXJtaXNzaW9uX21vZGlmeSA9PSAxKSB7DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJGl0ZW1zICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGl0ZW1zIC49ICIsIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICRpdGVtcyAuPSAiJ21vZGlmeSciOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgJHBlcm1pc3Npb25zX2FycmF5IC49ICRpdGVtczsNCg0KICAgICAgICAgICAgICAgICAgICAkcGVybWlzc2lvbnNfYXJyYXkgLj0gIikiOw0KDQogICAgICAgICAgICAgICAgICAgICRjcnlwdCA9ICJcJG1wZGYtPlNldFByb3RlY3Rpb24oeyRwZXJtaXNzaW9uc19hcnJheX0sICd7JHBkZi0+dXNlcl9wd2R9JywneyRwZGYtPm93bmVyX3B3ZH0nKTsiOw0KICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgJGNvZGUgPSA8PDxFT0YNCjw/cGhwDQogIA0KICAvLyBUaGlzIGNvZGUgdGFrZXMgdGhlIG91dHB1dCBidWZmZXIncyBjb250ZW50cw0KICAvLyBjcmVhdGVkIGluIHRoZSBtUERGIFNpbmdsZSBQYWdlIEhlYWRlciBJbmNsdWRlDQogIC8vIGNvZGUgYmxvY2sgYW5kIG91dHB1dHMgYSBQREYgdG8gdGhlIGJyb3dzZXIuDQoNCiAgLy8gY2FwdHVyZSBvdXRwdXQgYnVmZmVyDQogIFwkaHRtbCA9IG9iX2dldF9mbHVzaCgpOw0KICANCiAgLy8gZXJhc2VzIHRoZSBidWZmZXIsIHR1cm5zIGl0IG9mZg0KICBvYl9jbGVhbiAoKTsNCiAgDQogIC8vIGh0dHBzOi8vbXBkZi5naXRodWIuaW8vcmVmZXJlbmNlL21wZGYtZnVuY3Rpb25zL2NvbnN0cnVjdC5odG1sDQoNCiAgeyRjcmVhdGVfY29kZX0NCiAgDQogIFwkbXBkZi0+U2V0RGlzcGxheU1vZGUoJ2Z1bGxwYWdlJyk7DQogIA0KICAvLyBvcHRpb25zDQogIFwkbXBkZi0+U2V0VGl0bGUoInskcGFnZXRpdGxlfSIpOw0KICANCiAgIC8vIChPcHRpb25hbCkgU2VjdXJpdHkuDQogIHskY3J5cHR9DQoNCiAgXCRtcGRmLT5Xcml0ZUhUTUwoXCRodG1sKTsNCiAgDQogIHskb3V0cHV0X2NvZGV9DQogIA0KICAvLyBPcHRpb25hbA0KICAvL2NsZWFyX2ZiX3Nlc3Npb24oKTsNCiAgDQogIGV4aXQ7DQogIA0KPz4NCkVPRjsNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9IA0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoKGludCkkcGRmLT5lbmFibGVfcGRmID09IDEpIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgoaW50KSRwZGYtPm91dHB1dF9tb2RlID09IDQgfHwgKGludCkkcGRmLT5vdXRwdXRfbW9kZSA9PSA1KSB7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRjb2RlID0gc3RyX3JlcGxhY2UoJzw/cGhwJywgJycsICRjb2RlKTsNCiAgICAgICAgICAgICAgICAkY29kZSA9IHN0cl9yZXBsYWNlKCc/PicsICcnLCAkY29kZSk7DQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjb2RlX3RvcF91c2luZyA9ICcnOw0KDQogICAgICAgICAgICAgICAgaWYoc3Vic3RyX2NvdW50KCRjb2RlLCAndXNlIERvbXBkZlxEb21wZGYnKSAhPSAwKXsNCiAgICAgICAgICAgICAgICAgICAgJGNvZGUgPSBzdHJfcmVwbGFjZSgndXNlIERvbXBkZlxEb21wZGYnLCAnJywgJGNvZGUpOw0KICAgICAgICAgICAgICAgICAgICAkY29kZSA9IHN0cl9yZXBsYWNlKCd1c2UgRG9tcGRmXE9wdGlvbnMnLCAnJywgJGNvZGUpOw0KDQogICAgICAgICAgICAgICAgICAgICRjb2RlX3RvcF91c2luZyA9IDw8PEVPRg0KdXNlIERvbXBkZlxEb21wZGY7DQp1c2UgRG9tcGRmXE9wdGlvbnM7DQpFT0Y7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQoNCg0KICAgICAgICAgICAgICAgICRjb2RlID0gPDw8RU9GDQoNCjw/cGhwDQoNCnskY29kZV90b3BfdXNpbmd9DQoNCmlmKGlzc2V0KFwkX1NFU1NJT05bJ1JGX1JlbmRlcl9Bc19QREZfRW1haWxfVGVtcGxhdGVfT25fU3VibWlzc2lvbiddKSkgew0KDQp1bnNldChcJF9TRVNTSU9OWydSRl9SZW5kZXJfQXNfUERGX0VtYWlsX1RlbXBsYXRlX09uX1N1Ym1pc3Npb24nXSk7DQoNCnskY29kZX0NCg0KfQ0KRU9GOw0KDQogICAgICAgICAgICAgICAgcmV0dXJuICRjb2RlOw0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgcmV0dXJuICRjb2RlOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgcmV0dXJuICIiOw0KICAgICAgICB9DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGdldF9wZGZfcGFnZV9zaXplKCR0eXBlLCAkaWR4KQ0KICAgIHsNCg0KICAgICAgICAkcGFnZV9zaXplX2FycmF5ID0gYXJyYXkoDQogICAgICAgICAgICAwID0+IGFycmF5KCkNCiAgICAgICAgKTsNCiAgICB9IA0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3BhZ2Vfc3RhcnQoDQogICAgICAgICRwYWdlLA0KICAgICAgICAkanNfbGliX21vdmUsDQogICAgICAgICRqc19saWJfbW92ZV9jb25kaXRpb25hbCwNCiAgICAgICAgJGluY2x1ZGVfY2FsZW5kYXJfanMsDQogICAgICAgICR0aW55bWNlLA0KICAgICAgICAkaGFzX2F1dG9fc3VnZ2VzdCwNCiAgICAgICAgJGhhc19jb2xvcnBpY2tlciwNCiAgICAgICAgJGhhc19qc2xpZGVyLA0KICAgICAgICAkY29uZGl0aW9uYWxQYWdlTG9hZENvZGUsDQogICAgICAgICRjb29raWVfYmxvY2ssDQogICAgICAgICRpbmNsdWRlX2ZvbnRfYXdlc29tZQ0KICAgICkgew0KDQogICAgICAgICR0aXRsZSA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJHBhZ2UtPnRpdGxlLCAxKTsNCiAgICAgICAgJGV4cG9ydG1vZGUgPSAoaW50KSRwYWdlLT5leHBvcnRtb2RlOw0KICAgICAgICAkZW5jb2RpbmcgPSAoaW50KSRwYWdlLT5lbmNvZGluZzsNCiAgICAgICAgJGxhbmd1YWdlID0gKHN0cmluZykkcGFnZS0+bGFuZ3VhZ2U7DQogICAgICAgICRhdXRvdG9wID0gJHBhZ2UtPmF1dG90b3A7DQogICAgICAgICRqYXZhc2NyaXB0ID0gJHBhZ2UtPmphdmFzY3JpcHQ7DQogICAgICAgICRqc19vbmxvYWRDb2RlID0gJHBhZ2UtPmpzX29ubG9hZENvZGU7DQogICAgICAgICRib2R5Ymdjb2xvciA9ICRwYWdlLT5ib2R5Ymdjb2xvcjsNCiAgICAgICAgJGJvZHliZ29wYWNpdHkgPSAkcGFnZS0+Ym9keWJnb3BhY2l0eTsgDQogICAgICAgICR1c2Vib2R5Ymdjb2xvciA9IChpbnQpJHBhZ2UtPnVzZWJvZHliZ2NvbG9yOw0KICAgICAgICAkZXJyb3Jjb2xvciA9ICRwYWdlLT5lcnJvcmNvbG9yOw0KICAgICAgICAkdXNlZXJyb3Jjb2xvciA9ICRwYWdlLT51c2VlcnJvcmNvbG9yOw0KICAgICAgICAkcmVxdWlyZWRmaWVsZGNvbG9yID0gJHBhZ2UtPnJlcXVpcmVkZmllbGRjb2xvcjsgDQogICAgICAgICRlcnJvcnN0eWxlID0gJHBhZ2UtPmVycm9yc3R5bGU7DQogICAgICAgICRsaW5rY29sb3IgPSAkcGFnZS0+bGlua2NvbG9yOw0KICAgICAgICAkbGlua3VuZGVybGluZSA9ICRwYWdlLT5saW5rdW5kZXJsaW5lOw0KICAgICAgICAkc2hvd2pzdGV4dCA9ICRwYWdlLT5zaG93anN0ZXh0Ow0KICAgICAgICAkc2hvd2pzYWxlcnQgPSAkcGFnZS0+c2hvd2pzYWxlcnQ7DQogICAgICAgICRzaG93anNkZWZhdWx0ID0gJHBhZ2UtPnNob3dqc2RlZmF1bHQ7DQogICAgICAgICRzaG93anNpbWFnZSA9ICRwYWdlLT5zaG93anNpbWFnZTsNCiAgICAgICAgJHBocGhlYWRlciA9ICRwYWdlLT5waHBoZWFkZXI7DQogICAgICAgICRkZXNjcmlwdGlvbiA9ICRwYWdlLT5kZXNjcmlwdGlvbjsNCiAgICAgICAgJGtleXdvcmRzID0gJHBhZ2UtPmtleXdvcmRzOw0KICAgICAgICAkanNlcnJvcm1lc3NhZ2Vjb2xvciA9ICRwYWdlLT5qc2Vycm9ybWVzc2FnZWNvbG9yOw0KICAgICAgICAkanNwb3B1cF9lcnJvcm1lc3NhZ2UgPSAkcGFnZS0+anNwb3B1cF9lcnJvcm1lc3NhZ2U7DQogICAgICAgICRwYWdlbWFyZ2luID0gJHBhZ2UtPnBhZ2VtYXJnaW47DQogICAgICAgICRwYWdlbmFtZSA9ICRwYWdlLT5uYW1lOw0KICAgICAgICAkcGhwID0gJHBhZ2UtPnBocDsNCiAgICAgICAgJGxheW91dCA9ICRwYWdlLT5sYXlvdXQ7DQogICAgICAgICR0YWJsZW1vZGUgPSAkcGFnZS0+dGFibGVtb2RlOw0KICAgICAgICAkaW50ZXJuYXRpb25hbGl6YXRpb24gPSAkcGFnZS0+aW50ZXJuYXRpb25hbGl6YXRpb247DQogICAgICAgICRnb29nbGVmb250ID0gKHN0cmluZykkcGFnZS0+Z29vZ2xlZm9udDsNCg0KDQogICAgICAgIA0KICAgICAgICAkanNwb3B1cF9lcnJvcm1lc3NhZ2UgPSBzdHJfcmVwbGFjZSgiXHIiLCAiIiwgJGpzcG9wdXBfZXJyb3JtZXNzYWdlKTsNCiAgICAgICAgJGpzcG9wdXBfZXJyb3JtZXNzYWdlID0gc3RyX3JlcGxhY2UoIlxuIiwgIiIsICRqc3BvcHVwX2Vycm9ybWVzc2FnZSk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkZ2xvYmFsX2ZvbnRfaW1wb3J0ID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRwYWdlLT5nbG9iYWxzdHlsZSkgJiYgaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgIT0gMCkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSAxIHx8IGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDIpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNlbnRlcmZvcm0gPSAwOw0KDQogICAgICAgICAgICAgICAgaWYgKGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkY2VudGVyZm9ybSA9IDE7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRwYWdlbWFyZ2luID0gMDsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHVzZWJvZHliZ2NvbG9yID0gMTsNCiAgICAgICAgICAgICAgICAgICAgJGJvZHliZ2NvbG9yID0gJ3JnYigyMjUsIDI0NSwgMjU0KSAhaW1wb3J0YW50JzsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZ29vZ2xlZm9udCA9ICJSb2JvdG8iOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVycm9yc3R5bGUgPSAzOw0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDMgfHwgaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgPT0gNCkgew0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkY2VudGVyZm9ybSA9IDA7DQoNCiAgICAgICAgICAgICAgICBpZiAoaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgPT0gMykgew0KDQogICAgICAgICAgICAgICAgICAgICRjZW50ZXJmb3JtID0gMTsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHBhZ2VtYXJnaW4gPSAwOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdXNlYm9keWJnY29sb3IgPSAxOw0KICAgICAgICAgICAgICAgICAgICAkYm9keWJnY29sb3IgPSAnI2Y3ZjdmNyAhaW1wb3J0YW50JzsNCiAgICAgICAgICAgICAgICB9DQoNCg0KDQogICAgICAgICAgICAgICAgJGdvb2dsZWZvbnQgPSAiU291cmNlIFNhbnMgUHJvIjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRlcnJvcnN0eWxlID0gMzsNCiAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSA1IHx8IGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDYpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNlbnRlcmZvcm0gPSAwOw0KDQogICAgICAgICAgICAgICAgaWYgKGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDUpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkY2VudGVyZm9ybSA9IDE7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRwYWdlbWFyZ2luID0gMDsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHVzZWJvZHliZ2NvbG9yID0gMTsNCiAgICAgICAgICAgICAgICAgICAgJGJvZHliZ2NvbG9yID0gJyNmN2Y3ZjcgIWltcG9ydGFudCc7DQogICAgICAgICAgICAgICAgfQ0KDQoNCg0KICAgICAgICAgICAgICAgICRnb29nbGVmb250ID0gIlJvYm90byI7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZXJyb3JzdHlsZSA9IDM7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSA3IHx8IGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDgpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGNlbnRlcmZvcm0gPSAwOw0KDQogICAgICAgICAgICAgICAgaWYgKGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDcpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkY2VudGVyZm9ybSA9IDE7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRwYWdlbWFyZ2luID0gMDsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHVzZWJvZHliZ2NvbG9yID0gMDsNCiAgICAgICAgICAgICAgICAgICAgJGJvZHliZ2NvbG9yID0gJyc7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVycm9yc3R5bGUgPSAzOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYoaXNzZXQoJHBhZ2UtPmdsb2JhbHN0eWxlKSAmJiAhaXNfbnVtZXJpYygoc3RyaW5nKSRwYWdlLT5nbG9iYWxzdHlsZSkpew0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRlcnJvcnN0eWxlID0gMzsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkcGFnZW1hcmdpbiA9IDA7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkdXNlYm9keWJnY29sb3IgPSAwOw0KICAgICAgICAgICAgICAgICRib2R5Ymdjb2xvciA9ICcnOw0KDQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQoNCg0KDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmIChkZWZpbmVkKCdNT0JJTEVfTU9ERScpKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkYm9keV9iZ19jb2xvciA9ICIiOw0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPnVzZWJvZHliZ2NvbG9yKSAmJiAoaW50KSRwYWdlLT51c2Vib2R5Ymdjb2xvciA9PSAxKSB7DQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRwYWdlLT5ib2R5Ymdjb2xvcikgJiYgJHBhZ2UtPmJvZHliZ2NvbG9yICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRib2R5X2JnX2NvbG9yID0gPDw8RU9GDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJCQkNCiQoIGRvY3VtZW50ICkucmVhZHkoZnVuY3Rpb24oKSB7DQoJJCgnLnVpLW92ZXJsYXktYSwgLnVpLXBhZ2UtdGhlbWUtYSwgLnVpLXBhZ2UtdGhlbWUtYSAudWktcGFuZWwtd3JhcHBlcicpLmNzcyh7YmFja2dyb3VuZENvbG9yOiAneyRwYWdlLT5ib2R5Ymdjb2xvcn0nfSkNCgkJCQ0KfSk7DQoJCQkNCjwvc2NyaXB0Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGNzc19pbmplY3QgPSA8PDxFT0YNCg0KPCEtLSBNb2JpbGUgVmVyc2lvbiBJbmNsdWRlcyAtLT4NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iIiBtZWRpYT0icHJpbnQiIHR5cGU9InRleHQvY3NzIiAvPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIiIG1lZGlhPSJzY3JlZW4gYW5kIChtaW4tZGV2aWNlLXdpZHRoOiA0ODFweCkiIHR5cGU9InRleHQvY3NzIiAvPg0KPGxpbmsgdHlwZT0idGV4dC9jc3MiICBocmVmPSIiIHJlbD0ic3R5bGVzaGVldCIgbWVkaWE9Im9ubHkgc2NyZWVuIGFuZCAobWF4LWRldmljZS13aWR0aDogNDgwcHgpIiAgLz4NCgkJCQ0KPCEtLSBOZXcgQW5kcm9pZCAtLT4NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iIiBtZWRpYT0ic2NyZWVuIGFuZCAoLXdlYmtpdC1kZXZpY2UtcGl4ZWwtcmF0aW86MC43NSkiICAvPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIiIG1lZGlhPSJoYW5kaGVsZCIgdHlwZT0idGV4dC9jc3MiIC8+DQo8IS0tW2lmIElFXT4NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0ic3R5bGUuY3NzIiBtZWRpYT0ic2NyZWVuIiB0eXBlPSJ0ZXh0L2NzcyIgLz4NCjwhW2VuZGlmXS0tPg0KCQkJDQo8IS0tIFRlbGwgaVBob25lIG5vdCB0byBzaHJpbmsgbW9iaWxlIHdlYnNpdGUgLS0+DQo8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9MzIwOyBpbml0aWFsLXNjYWxlPTEuMDsgbWF4aW11bS1zY2FsZT0xLjA7IHVzZXItc2NhbGFibGU9MDsiIC8+IA0KCQkJDQo8IS0tIGpRdWVyeSBNb2JpbGUgLS0+DQo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii8vY29kZS5qcXVlcnkuY29tL21vYmlsZS8xLjQuMi9qcXVlcnkubW9iaWxlLTEuNC4yLm1pbi5jc3MiIC8+DQo8c2NyaXB0IHNyYz0iLy9jb2RlLmpxdWVyeS5jb20vanF1ZXJ5LTEuMTEuMC5taW4uanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCBzcmM9Ii8vY29kZS5qcXVlcnkuY29tL21vYmlsZS8xLjQuMi9qcXVlcnkubW9iaWxlLTEuNC4yLm1pbi5qcyI+PC9zY3JpcHQ+DQoNCjwhLS0gQ3VzdG9tIEJhY2tncm91bmQgQ29sb3IgLS0+DQp7JGJvZHlfYmdfY29sb3J9DQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCiQoIGRvY3VtZW50ICkucmVhZHkoZnVuY3Rpb24oKSB7DQoJCQkNCgkvLyBTdHlsZSBPdmVycmlkZXMuDQoJJCgnLnVpLXJhZGlvIGxhYmVsJykuY3NzKHtjb2xvcjogJyM0NDQ0NDQnfSk7DQoJJCgnLnVpLWNoZWNrYm94IGxhYmVsJykuY3NzKHtjb2xvcjogJyM0NDQ0NDQnfSk7DQoJJCgnLmhlYWRpbmctbWFpbicpLmNzcyh7bWFyZ2luQm90dG9tOiAnOHB4J30pOwkNCg0KfSkNCjwvc2NyaXB0Pg0KDQpFT0Y7DQoNCiAgICAgICAgICAgICRqc19saWJfbW92ZSA9ICRjc3NfaW5qZWN0IC4gJGpzX2xpYl9tb3ZlOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRjb25kaXRpb25hbFBhZ2VMb2FkQ29kZSAhPSAiIikgew0KICAgICAgICAgICAgJGNvbmRpdG9uYWxJbml0Q29kZSA9ICIiOyANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRjb25kaXRvbmFsSW5pdENvZGUgPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGVycm9yc3R5bGUgPT0gIiIpIHsNCiAgICAgICAgICAgICRlcnJvcnN0eWxlID0gMDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRqc19vbmxvYWRDb2RlKSkgew0KICAgICAgICAgICAgJGpzX29ubG9hZENvZGUgPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgICRjb29raWVfYmxvY2sgPSBpc3NldCgkY29va2llX2Jsb2NrKSAmJiAkY29va2llX2Jsb2NrICE9ICIiID8gJGNvb2tpZV9ibG9jayA6IDE7DQoNCiAgICAgICAgJGNvb2tpZV9jb2RlID0gIixjaGVja0Nvb2tpZSgpIjsNCg0KICAgICAgICBpZiAoKGludCkkY29va2llX2Jsb2NrID09IDEpIHsNCiAgICAgICAgICAgICRjb29raWVfY29kZSA9ICIiOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKChpbnQpJGF1dG90b3AgPT0gJzEnIHx8IChpbnQpJGF1dG90b3AgPT0gMikgew0KICAgICAgICAgICAgJGJvZHl0YWcgPSAiPGJvZHkgb25sb2FkPVwic2Nyb2xsRm9ybVRvVG9wKHskYXV0b3RvcH0pOyBpbXBvcnRYTUwoZ2V0WG1sVXJsKCksIHBhcnNlRm9ybVhtbCB7JGNvb2tpZV9jb2RlfSApIHskY29uZGl0b25hbEluaXRDb2RlfTsgeyRqc19vbmxvYWRDb2RlfVwiPiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYm9keXRhZyA9ICI8Ym9keSBvbmxvYWQ9XCJpbXBvcnRYTUwoZ2V0WG1sVXJsKCksIHBhcnNlRm9ybVhtbCB7JGNvb2tpZV9jb2RlfSkgeyRjb25kaXRvbmFsSW5pdENvZGV9OyB7JGpzX29ubG9hZENvZGV9XCI+IjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICRwaHAgPSAoc3RyaW5nKSRwaHA7DQogICAgICAgIHByZWdfbWF0Y2hfYWxsKCcvKF58LnxccnxcbikoI1x7KC4qPylcfSkvJywgJHBocCwgJG1hdGNoZXMpOw0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRwaHAgPSBzdHJfcmVwbGFjZSgnI3snIC4gJG0gLiAnfScsICJcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRtfSddIiwgJHBocCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHBocCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJHBocCwgMCk7DQoNCiAgICAgICAgDQogICAgICAgICRwYWdlbmFtZSA9IHN1YnN0cigkcGFnZW5hbWUsIDAsIHN0cnBvcygkcGFnZW5hbWUsICcuJykpIC4gJy54bWwnOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkc2ltcGxlX2ljb25fbm90aWNlX2JvcmRlciA9ICJib3JkZXItdG9wOiA4cHggc29saWQgeyRlcnJvcmNvbG9yfTsiOw0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgoaW50KSR1c2VlcnJvcmNvbG9yID09IDApIHsNCiAgICAgICAgICAgICRlcnJvcmNvbG9yID0gJyc7DQogICAgICAgICAgICAkc2ltcGxlX2ljb25fbm90aWNlX2JvcmRlciA9ICIiOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVycm9yX3N0eWxlID0gImJhY2tncm91bmQ6IHskZXJyb3Jjb2xvcn07IjsNCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgkc2hvd2pzaW1hZ2UpIHsNCiAgICAgICAgICAgIGNhc2UgJzAnOg0KICAgICAgICAgICAgICAgICRlcnJvcl9zdHlsZSA9ICJiYWNrZ3JvdW5kOiB7JGVycm9yY29sb3J9OyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxJzoNCiAgICAgICAgICAgICAgICAkZXJyb3Jfc3R5bGUgPSAiYmFja2dyb3VuZDogeyRlcnJvcmNvbG9yfSB1cmwoPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/Pmljb25zL3ZhbGlkYXRpb24vc3R5bGUtMi9lcnJvci1pY29uLXJlZC5naWYpIG5vLXJlcGVhdCBzY3JvbGwgcmlnaHQgY2VudGVyOyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAkZXJyb3Jfc3R5bGUgPSAiYmFja2dyb3VuZDogeyRlcnJvcmNvbG9yfSB1cmwoPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/Pmljb25zL3ZhbGlkYXRpb24vc3R5bGUtMi9lcnJvci1pY29uLWJsYWNrLmdpZikgbm8tcmVwZWF0IHNjcm9sbCByaWdodCBjZW50ZXI7IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGRlZmF1bHQ6DQogICAgICAgICAgICAgICAgJGVycm9yX3N0eWxlID0gImJhY2tncm91bmQ6IHskZXJyb3Jjb2xvcn07IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKCFpc3NldCgkcmVxdWlyZWRmaWVsZGNvbG9yKSB8fCAkcmVxdWlyZWRmaWVsZGNvbG9yID09ICIiKSB7DQoNCiAgICAgICAgICAgICRyZXF1aXJlZGZpZWxkY29sb3IgPSAiI2NjMDAwMDsiOw0KICAgICAgICB9DQoNCg0KICAgICAgICAkZXJyb3Jfc3R5bGVzID0gPDw8RU9UDQoNCjwhLS0gY3VzdG9tIHN0eWxlIC0tPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0Kc3Bhbi5lcnJvciB7IHskZXJyb3Jfc3R5bGV9IH0gZGl2LmVycm9yIHsgYmFja2dyb3VuZC1jb2xvcjp7JGVycm9yY29sb3J9OyB9DQoNCi5yZXEtc3RhciB7IGNvbG9yOiB7JHJlcXVpcmVkZmllbGRjb2xvcn0gIH0NCg0KZGl2LnZhbGlkYXRpb24tc3R5bGUtMy1saW5lLCBzcGFuLnZhbGlkYXRpb24tc3R5bGUtMy1saW5lIHsNCiAgeyRzaW1wbGVfaWNvbl9ub3RpY2VfYm9yZGVyfQ0KICBoZWlnaHQ6IDFweDsNCiAgcGFkZGluZy10b3A6IDA7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgdG9wOiAtMTJweDsNCiAgd2lkdGg6IDEwNCU7DQogIHotaW5kZXg6IC0xOw0KfQ0KICAJCQ0KLnZhbGlkYXRpb24tc3R5bGUtMy1pY29uIHsNCiAgYmFja2dyb3VuZC1pbWFnZTogdXJsKCJpY29ucy92YWxpZGF0aW9uL3N0eWxlLTMvd2FybmluZy1pY29uLXNpbXBsZS0xNi5wbmciKTsNCiAgaGVpZ2h0OiAxNnB4Ow0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIHJpZ2h0OiAtMTlweDsNCiAgdG9wOiAtMTdweDsNCiAgd2lkdGg6IDE2cHg7DQp9DQoNCi52YWxpZGF0aW9uLXN0eWxlLTMtbWVzc2FnZSB7IA0KICBwb3NpdGlvbjphYnNvbHV0ZTsgDQogIHRvcDotMTVweDsgDQogIHJpZ2h0OjI2cHg7IA0KICBoZWlnaHQ6MTZweDsgDQogIGZvbnQtc2l6ZToxMHB4OyANCiAgZm9udC13ZWlnaHQ6Ym9sZDsgDQogIGNvbG9yOnskanNlcnJvcm1lc3NhZ2Vjb2xvcn0NCn0NCg0KPC9zdHlsZT4NCg0KPCEtLSBFbmQgQ3VzdG9tIFN0eWxlIC0tPg0KDQpFT1Q7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRqc3BvcHVwX2Vycm9ybWVzc2FnZSkgfHwgJGpzcG9wdXBfZXJyb3JtZXNzYWdlID09ICIiKSB7DQogICAgICAgICAgICAkanNwb3B1cF9lcnJvcm1lc3NhZ2UgPSAnWW91IGhhdmUgbm90IGNvbXBsZXRlZCB0aGlzIGZvcm0gY29ycmVjdGx5LlxuUGxlYXNlIGdvIGJhY2sgYW5kIHJldmlldyB5b3VyIGFuc3dlcnMuJzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGpzcG9wdXBfZXJyb3JtZXNzYWdlID0gc3RyX3JlcGxhY2UoIjxici8+IiwgJ1xcbicsICRqc3BvcHVwX2Vycm9ybWVzc2FnZSk7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRqc3BvcHVwX2Vycm9ybWVzc2FnZSA9IHN0cl9yZXBsYWNlKCI8L2JyPiIsICdcXG4nLCAkanNwb3B1cF9lcnJvcm1lc3NhZ2UpOw0KICAgICAgICAgICAgJGpzcG9wdXBfZXJyb3JtZXNzYWdlID0gc3RyX3JlcGxhY2UoIjxicj4iLCAnXFxuJywgJGpzcG9wdXBfZXJyb3JtZXNzYWdlKTsNCiAgICAgICAgICAgICRqc3BvcHVwX2Vycm9ybWVzc2FnZSA9IHN0cl9yZXBsYWNlKCI8LyBicj4iLCAnXFxuJywgJGpzcG9wdXBfZXJyb3JtZXNzYWdlKTsNCiAgICAgICAgICAgICRqc3BvcHVwX2Vycm9ybWVzc2FnZSA9IHN0cl9yZXBsYWNlKCI8YnIgLz4iLCAnXFxuJywgJGpzcG9wdXBfZXJyb3JtZXNzYWdlKTsNCiAgICAgICAgICAgICRqc3BvcHVwX2Vycm9ybWVzc2FnZSA9IHN0cl9yZXBsYWNlKCciJywgJ1wiJywgJGpzcG9wdXBfZXJyb3JtZXNzYWdlKTsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgICR0bWMgPSAkdGhpcy0+Y3JlYXRlX3RpbnltY2UoJHRpbnltY2UpOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGdvb2dsZWZvbnQpICYmIChzdHJpbmcpJGdvb2dsZWZvbnQgIT0gIjAiICAmJiAoc3RyaW5nKSRnb29nbGVmb250ICE9ICIiKSB7DQogICAgICAgICAgICAkZ29vZ2xlZm9udCA9ICR0aGlzLT5jcmVhdGVHb29nbGVXZWJGb250KCRnb29nbGVmb250KTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRnb29nbGVmb250ID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGNhbGVuZGFyX2pzID0gJyc7DQogICAgICAgIGlmICgkaW5jbHVkZV9jYWxlbmRhcl9qcyA9PSAxKSB7DQogICAgICAgICAgICAkY2FsZW5kYXJfanMgLj0gIjwhLS0gY2FsZW5kYXIgZmlsZXMgLS0+XG4iOw0KICAgICAgICAgICAgJGNhbGVuZGFyX2pzIC49ICI8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIiBzcmM9XCI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvQ2FsZW5kYXJQb3B1cC5qc1wiPjwvc2NyaXB0PiI7DQogICAgICAgICAgICAkY2FsZW5kYXJfanMgLj0gIlxuPGxpbmsgcmVsPVwic3R5bGVzaGVldFwiIHR5cGU9XCJ0ZXh0L2Nzc1wiIGhyZWY9XCI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvY2FsLXN0eWxlLTAuY3NzXCIgLz4iOw0KICAgICAgICAgICAgJGNhbGVuZGFyX2pzIC49ICJcbjwhLS0gZW5kIGNhbGVuZGFyIGZpbGVzIC0tPlxuXG4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkcGFnZW1hcmdpbiA9PSAnJykgew0KICAgICAgICAgICAgJHBhZ2VtYXJnaW4gPSAwOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRwYWdlbWFyZ2luID0gZmlsdGVyX3ZhcigkcGFnZW1hcmdpbiwgRklMVEVSX1NBTklUSVpFX05VTUJFUl9JTlQpOw0KDQogICAgICAgIA0KICAgICAgICAkYm9keWJnb3BhY2l0eV9zdHJpbmcgPSAnJzsNCiAgICAgICAgaWYgKChpbnQpJHVzZWJvZHliZ2NvbG9yKSB7DQogICAgICAgICAgICBpZiAoKHN0cmluZykkYm9keWJnb3BhY2l0eSAhPSAnJykgew0KICAgICAgICAgICAgICAgICRib2R5YmdvcGFjaXR5X3N0cmluZyAuPSAib3BhY2l0eTogeyRib2R5YmdvcGFjaXR5fTsgIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgICRib2R5YmdkZWZpbml0aW9uID0gJyc7DQogICAgICAgIGlmICgkdXNlYm9keWJnY29sb3IgPT0gMSkgew0KICAgICAgICAgICAgJGJvZHliZ2RlZmluaXRpb24gPSA8PDxFT1QNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp7JGJvZHliZ2NvbG9yfTsgbWFyZ2luOnskcGFnZW1hcmdpbn1weDsgeyRib2R5YmdvcGFjaXR5X3N0cmluZ30gZm9udC1mYW1pbHk6ICdIZWx2ZXRpY2EnOyB9DQpodG1sIHsgbWFyZ2luOnskcGFnZW1hcmdpbn1weDsgfQ0KPC9zdHlsZT4NCkVPVDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib2R5YmdkZWZpbml0aW9uID0gPDw8RU9UDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KYm9keSB7IG1hcmdpbjp7JHBhZ2VtYXJnaW59cHg7IHskYm9keWJnb3BhY2l0eV9zdHJpbmd9IGZvbnQtZmFtaWx5OiAnSGVsdmV0aWNhJzsgfQ0KaHRtbCB7IG1hcmdpbjp7JHBhZ2VtYXJnaW59cHg7IH0NCjwvc3R5bGU+DQpFT1Q7DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgDQogICAgICAgICR1bmRlcmxpbmUgPSAkbGlua3VuZGVybGluZSA9PSAwID8gJ25vbmUnIDogJ3VuZGVybGluZSc7DQogICAgICAgICRob3ZlciA9ICRsaW5rdW5kZXJsaW5lID09IDAgPyAndW5kZXJsaW5lJyA6ICdub25lJzsNCg0KICAgICAgICBpZiAoJGhhc19hdXRvX3N1Z2dlc3QgPT0gMSkgew0KICAgICAgICAgICAgJGF1dG9zdWdnZXN0ID0gPDw8RU9UDQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2F1dG9zdWdnZXN0L2pzL2Jzbi5BdXRvU3VnZ2VzdF8yLjEuMy5qcyIgY2hhcnNldD0idXRmLTgiPjwvc2NyaXB0Pg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJqcy9hdXRvc3VnZ2VzdC9jc3MvYXV0b3N1Z2dlc3RfaW5xdWlzaXRvci5jc3MiIHR5cGU9InRleHQvY3NzIiBtZWRpYT0ic2NyZWVuIiBjaGFyc2V0PSJ1dGYtOCIgLz4NCg0KRU9UOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGF1dG9zdWdnZXN0ID0gJyc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCRoYXNfY29sb3JwaWNrZXIgPT0gMSkgew0KICAgICAgICAgICAgJGNvbG9ycGlja2VyID0gPDw8RU9UDQoNCjwhLS0gQ29sb3IgUGlja2VyIC0tPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBtZWRpYT0ic2NyZWVuIiB0eXBlPSJ0ZXh0L2NzcyIgaHJlZj0ianMvY29sb3JwaWNrZXIvY3NzL2NvbG9ycGlja2VyLmNzcyIgLz4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvY29sb3JwaWNrZXIvanMvanF1ZXJ5LmpzIj48L3NjcmlwdD4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2NvbG9ycGlja2VyL2pzL2NvbG9ycGlja2VyLmpzIj48L3NjcmlwdD4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2NvbG9ycGlja2VyL2pzL2V5ZS5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9jb2xvcnBpY2tlci9qcy91dGlscy5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9jb2xvcnBpY2tlci9qcy9sYXlvdXQuanM/dmVyPTEuMC4yIj48L3NjcmlwdD4NCjwhLS0gQ29sb3IgUGlja2VyIC0tPg0KDQpFT1Q7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkY29sb3JwaWNrZXIgPSAnJzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgkaGFzX2pzbGlkZXIgPT0gMSkgew0KICAgICAgICAgICAgJGpzbGlkZXIgPSA8PDxFT1QNCg0KPCEtLSBqU2xpZGVyIC0tPg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvanNsaWRlci9qcy9qcXVlcnktMS43LjEuanMiPjwvc2NyaXB0Pg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJqcy9qc2xpZGVyL2Jpbi9qcXVlcnkuc2xpZGVyLm1pbi5jc3MiIHR5cGU9InRleHQvY3NzIj4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2pzbGlkZXIvYmluL2pxdWVyeS5zbGlkZXIubWluLmpzIj48L3NjcmlwdD4NCjwhLS0galNsaWRlciAtLT4NCg0KRU9UOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGpzbGlkZXIgPSAnJzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgICRsaW5rX3N0eWxlcyA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+dXNlbGlua3N0eWxlcykgJiYgKGludCkkcGFnZS0+dXNlbGlua3N0eWxlcyA9PSAwKSB7DQoNCiAgICAgICAgICAgICRsaW5rX3N0eWxlcyA9IDw8PEVPVA0KDQovKiBsaW5rIGNvbG9ycyAqLw0KLmZvcm0tb3V0cHV0LWRpdiBhOmxpbmsgeyBjb2xvcjp7JGxpbmtjb2xvcn07IHRleHQtZGVjb3JhdGlvbjp7JHVuZGVybGluZX07IH0NCi5mb3JtLW91dHB1dC1kaXYgYTp2aXNpdGVkIHsgY29sb3I6eyRsaW5rY29sb3J9OyB0ZXh0LWRlY29yYXRpb246eyR1bmRlcmxpbmV9OyB9DQouZm9ybS1vdXRwdXQtZGl2IGE6aG92ZXIgeyBjb2xvcjp7JGxpbmtjb2xvcn07IHRleHQtZGVjb3JhdGlvbjp7JGhvdmVyfTsgfQ0KLmZvcm0tb3V0cHV0LWRpdiBhOmFjdGl2ZSB7IGNvbG9yOnskbGlua2NvbG9yfTsgdGV4dC1kZWNvcmF0aW9uOnskdW5kZXJsaW5lfTsgfQ0KDQpFT1Q7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkZm9ybWxpbmtjb2xvciA9IDw8PEVPVA0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCnskbGlua19zdHlsZXN9DQpzcGFuLmVycm9ybXNnIHsgY29sb3I6eyRqc2Vycm9ybWVzc2FnZWNvbG9yfTsgfQ0KPC9zdHlsZT4NCg0KPCEtLVtpZiBsdGUgSUUgOF0+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KLmJ0biB7IAltYXJnaW46IDA7IHBhZGRpbmc6IDAgLjcwZW07IHdpZHRoOiBhdXRvOyBvdmVyZmxvdzogdmlzaWJsZTsgfQ0KPC9zdHlsZT4NCjwhW2VuZGlmXS0tPg0KDQpFT1Q7DQoNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJGpxdWVyeV92YWxpZGF0ZSA9ICcnOw0KDQogICAgICAgIGlmICgoaW50KSRlcnJvcnN0eWxlID09IDMpIHsNCg0KICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyA9ICIiOw0KICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyA9ICIiOw0KDQogICAgICAgICAgICBmb3JlYWNoICgkcGFnZS0+Zm9ybS0+ZmllbGQgYXMgJGYpIHsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZi0+dmFsaWRhdGlvbikpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+bWF4ID09ICcnICYmIChpbnQpJGYtPnZhbGlkYXRpb24tPm1pbiA9PSAnJyAmJiAoc3RyaW5nKSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnJyAmJiAoc3RyaW5nKSRmLT52YWxpZGF0aW9uLT5zYW1lYXMgPT0gJycpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlcSA9PSAxKQ0KICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyAuPSAiXG5cdFx0XHR7JGYtPmlkfTogXCJyZXF1aXJlZFwiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJ7JGYtPmlkfTogeyI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVxID09IDEpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHRyZXF1aXJlZDogdHJ1ZSwiOyANCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPm1heCAhPSAnJyAmJiAoaW50KSRmLT52YWxpZGF0aW9uLT5tYXggIT0gMCl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHZhbCA9IChpbnQpJGYtPnZhbGlkYXRpb24tPm1heDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0bWF4bGVuZ3RoOiB7JHZhbH0sIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPm1pbiAhPSAnJyAmJiAoaW50KSRmLT52YWxpZGF0aW9uLT5taW4gIT0gMCl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHZhbCA9IChpbnQpJGYtPnZhbGlkYXRpb24tPm1pbjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0bWlubGVuZ3RoOiB7JHZhbH0sIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnNhbWVhcyAhPSAnJyl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyAuPSAiXG5cdFx0XHRcdGVxdWFsVG86IFwiI3skZi0+dmFsaWRhdGlvbi0+c2FtZWFzfVwiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVnZXggPT0gJzInKSB7IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHRkaWdpdHM6IHRydWUsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnMycpIHsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyAuPSAiXG5cdFx0XHRcdGxldHRlcnNvbmx5OiB0cnVlLCI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVnZXggPT0gJzQnKSB7IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHRlbWFpbDogdHJ1ZSwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICc1Jyl7IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHR6aXBjb2RlVVM6IHRydWUsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnNicpeyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0cGhvbmVVUzogdHJ1ZSwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICc3Jyl7IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHRhbHBoYW51bWVyaWM6IHRydWUsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnOCcpeyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0dmluVVM6IHRydWUsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnOScpeyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0Y3JlZGl0Y2FyZHR5cGVzOiB0cnVlLCI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVnZXggPT0gJzEwJyl7IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfcnVsZXMgLj0gIlxuXHRcdFx0XHRwaG9uZXNVSzogdHJ1ZSwiOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICcxMScpIHsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyAuPSAiXG5cdFx0XHRcdGRpZ2l0czogdHJ1ZSwiOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoKHN0cmluZykkZi0+dmFsaWRhdGlvbi0+cmVnZXggIT0gIjAiICYmIChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ICE9ICIiKXsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZXNjYXBlZCA9IHN0cl9yZXBsYWNlKCInIiwgIlwnIiwgJGYtPnZhbGlkYXRpb24tPnJlZ2V4KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX3J1bGVzIC49ICJcblx0XHRcdFx0cGF0dGVybjogJ3skZXNjYXBlZH0nLCI7IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9ydWxlcyAuPSAiXG5cdFx0XHR9LCI7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5tYXggPT0gJycgJiYgKGludCkkZi0+dmFsaWRhdGlvbi0+bWluID09ICcnICYmIChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICcnICYmIChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnNhbWVhcyA9PSAnJykgew0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZXEgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZV9tZXNzYWdlID0gIiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZi0+dmFsaWRhdGlvbi0+cmVxdWlyZWRlcnJvcm1lc3NhZ2UpICYmIChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnJlcXVpcmVkZXJyb3JtZXNzYWdlICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZV9tZXNzYWdlID0gKHN0cmluZykkZi0+dmFsaWRhdGlvbi0+cmVxdWlyZWRlcnJvcm1lc3NhZ2U7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHN0cmluZykkZi0+dmFsaWRhdGlvbi0+dmFsZXJyb3JtZXNzYWdlID09ICcnKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc3NldCgkcGFnZS0+cmVxdWlyZWRfZXJyb3JtZXNzYWdlKSAmJiAkcGFnZS0+cmVxdWlyZWRfZXJyb3JtZXNzYWdlICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVfbWVzc2FnZSA9ICRwYWdlLT5yZXF1aXJlZF9lcnJvcm1lc3NhZ2U7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSAiVGhpcyBmaWVsZCBpcyByZXF1aXJlZC4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVfbWVzc2FnZSA9IHN0cl9yZXBsYWNlKCJcclxuIiwgIiIsICRlX21lc3NhZ2UpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSBzdHJfcmVwbGFjZSgiXG4iLCAiIiwgJGVfbWVzc2FnZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVfbWVzc2FnZSA9IHRyaW0oJGVfbWVzc2FnZSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJcblx0XHRcdHskZi0+aWR9OiBcInskZV9tZXNzYWdlfVwiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJ7JGYtPmlkfTogeyI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZXEgIT0gJycpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSAiIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmLT52YWxpZGF0aW9uLT5yZXF1aXJlZGVycm9ybWVzc2FnZSkgJiYgKHN0cmluZykkZi0+dmFsaWRhdGlvbi0+cmVxdWlyZWRlcnJvcm1lc3NhZ2UgIT0gIiIpIHsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSAoc3RyaW5nKSRmLT52YWxpZGF0aW9uLT5yZXF1aXJlZGVycm9ybWVzc2FnZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgeyANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPnJlcXVpcmVkX2Vycm9ybWVzc2FnZSkgJiYgJHBhZ2UtPnJlcXVpcmVkX2Vycm9ybWVzc2FnZSAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVfbWVzc2FnZSA9ICRwYWdlLT5yZXF1aXJlZF9lcnJvcm1lc3NhZ2U7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZV9tZXNzYWdlID0gIlRoaXMgZmllbGQgaXMgcmVxdWlyZWQuIjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSBzdHJfcmVwbGFjZSgiXHJcbiIsICIiLCAkZV9tZXNzYWdlKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZV9tZXNzYWdlID0gc3RyX3JlcGxhY2UoIlxuIiwgIiIsICRlX21lc3NhZ2UpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlX21lc3NhZ2UgPSB0cmltKCRlX21lc3NhZ2UpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyAuPSAiXG5cdFx0XHRcdHJlcXVpcmVkOiBcInskZV9tZXNzYWdlfVwiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPm1heCAhPSAnJykNCiAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRtYXhsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChcIkVudGVyIGxlc3MgdGhhbiB7MH0gY2hhcmFjdGVyc1wiKSwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+bWluICE9ICcnKQ0KICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyAuPSAiXG5cdFx0XHRcdG1pbmxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFwiRW50ZXIgYXQgbGVhc3QgezB9IGNoYXJhY3RlcnNcIiksIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnNhbWVhcyAhPSAnJykNCiAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRlcXVhbFRvOiBcIlBsZWFzZSBlbnRlciB0aGUgc2FtZSB2YWx1ZSBhczogeyRmLT52YWxpZGF0aW9uLT5zYW1lYXN9XCIsIjsNCg0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZV9tZXNzYWdlID0gIiI7IA0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGYtPnZhbGlkYXRpb24tPnZhbGVycm9ybWVzc2FnZSkgJiYgKHN0cmluZykkZi0+dmFsaWRhdGlvbi0+dmFsZXJyb3JtZXNzYWdlICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVfbWVzc2FnZSA9IChzdHJpbmcpJGYtPnZhbGlkYXRpb24tPnZhbGVycm9ybWVzc2FnZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVxID09IDEpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVzY2FwZWQgPSBzdHJfcmVwbGFjZSgiJyIsICJcJyIsICRmLT52YWxpZGF0aW9uLT52YWxlcnJvcm1lc3NhZ2UpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyAuPSAiXG5cdFx0XHRcdHBhdHRlcm46ICd7JGVzY2FwZWR9JywiOyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVnZXggPT0gJzInKSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyAuPSAiXG5cdFx0XHRcdGRpZ2l0czogXCJ7JGVfbWVzc2FnZX1cIiwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICczJykgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRsZXR0ZXJzb25seTogXCJ7JGVfbWVzc2FnZX1cIiwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICc0JykgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRlbWFpbDogXCJ7JGVfbWVzc2FnZX1cIiwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICc1JykgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHR6aXBjb2RlVVM6IFwieyRlX21lc3NhZ2V9XCIsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnNicpIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJcblx0XHRcdFx0cGhvbmVVUzogXCJ7JGVfbWVzc2FnZX1cIiwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICc3JykgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRhbHBoYW51bWVyaWM6IFwieyRlX21lc3NhZ2V9XCIsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnOCcpIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJcblx0XHRcdFx0dmluVVM6IFwieyRlX21lc3NhZ2V9XCIsIjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmLT52YWxpZGF0aW9uLT5yZWdleCA9PSAnOScpIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJcblx0XHRcdFx0Y3JlZGl0Y2FyZHR5cGVzOiBcInskZV9tZXNzYWdlfVwiLCI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZi0+dmFsaWRhdGlvbi0+cmVnZXggPT0gJzEwJykgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXMgLj0gIlxuXHRcdFx0XHRwaG9uZXNVSzogXCJ7JGVfbWVzc2FnZX1cIiwiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGYtPnZhbGlkYXRpb24tPnJlZ2V4ID09ICcxMScpIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkanF1ZXJ5X3ZhbGlkYXRlX21lc3NhZ2VzIC49ICJcblx0XHRcdFx0ZGlnaXRzOiBcInskZV9tZXNzYWdlfVwiLCI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZV9tZXNzYWdlcyAuPSAiXG5cdFx0XHR9LCI7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRmb3JtX2lkID0gc3RyX3JlcGxhY2UoIi4iLCAnJywgJHBhZ2UtPmZvcm0tPmlkKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGpxdWVyeV92YWxpZGF0ZSA9IDw8PEVPRg0KDQo8L3NjcmlwdD4NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KbGFiZWwuZXJyb3Igew0KCWJhY2tncm91bmQtY29sb3I6IHskZXJyb3Jjb2xvcn07DQp9DQoNCjwvc3R5bGU+DQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KLy8NCi8vIGpRdWVyeSBWYWxpZGF0ZQ0KLy8NCg0KaWYodHlwZW9mKFwkaikgIT0gInVuZGVmaW5lZCIpIHsNCgkkID0gXCRqOw0KfQ0KDQokKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsNCgkNCgkvLyB2YWxpZGF0ZSBzaWdudXAgZm9ybSBvbiBrZXl1cCBhbmQgc3VibWl0DQoJdmFyIHZhbGlkYXRvciA9ICQoIiN7JGZvcm1faWR9IikudmFsaWRhdGUoew0KCQ0KCQlfc2hvd21lc3NhZ2U6IHskc2hvd2pzdGV4dH0sDQoJCV9hbmltYXRlc2hvdzogZmFsc2UsDQoJCQ0KCQlydWxlczogew0KCQkJeyRqcXVlcnlfdmFsaWRhdGVfcnVsZXN9DQoJCX0sDQoJCQ0KCQltZXNzYWdlczogew0KCQkJeyRqcXVlcnlfdmFsaWRhdGVfbWVzc2FnZXN9DQoJCX0sDQoJCQ0KCQkvLyB0aGUgZXJyb3JQbGFjZW1lbnQgaGFzIHRvIHRha2UgdGhlIHRhYmxlIGxheW91dCBpbnRvIGFjY291bnQNCgkJZXJyb3JQbGFjZW1lbnQ6IGZ1bmN0aW9uKGVycm9yLCBlbGVtZW50KSB7DQoJCQkNCgkJCWlmICggZWxlbWVudC5pcygiOnJhZGlvIikgKSB7DQoJCQkJDQoJCQkJaWYodGhpcy5fc2hvd21lc3NhZ2UgPT0gMSkgew0KCQkJCQ0KCQkJCQlpZih0aGlzLl9hbmltYXRlc2hvdyA9PSB0cnVlKSB7DQoJCQkJCQ0KCQkJCQkJLy8gQW5pbWF0ZQ0KCQkJCQkJJChlcnJvcikuYW5pbWF0ZSh7b3BhY2l0eTogJzAnfSwwKS5pbnNlcnRBZnRlciggZWxlbWVudC5jbG9zZXN0KCdsYWJlbCcpICkuYW5pbWF0ZSh7b3BhY2l0eTogJzEnfSwxMDApOw0KCQkJCQkNCgkJCQkJfSBlbHNlIHsNCgkJCQkJDQoJCQkJCQkvLyBBcHBlYXINCgkJCQkJCWVycm9yLmluc2VydEFmdGVyKCBlbGVtZW50LmNsb3Nlc3QoJ2xhYmVsJykgKTsNCgkJCQkJDQoJCQkJCX0NCg0KCQkJCX0NCgkJCQkNCgkJCX0gZWxzZSBpZiAoIGVsZW1lbnQuaXMoIjpjaGVja2JveCIpICkgew0KCQkJDQoJCQkJaWYodGhpcy5fc2hvd21lc3NhZ2UgPT0gMSkgew0KCQkJCQ0KCQkJCQlpZih0aGlzLl9hbmltYXRlc2hvdyA9PSB0cnVlKSB7DQoJCQkJCQ0KCQkJCQkJLy8gQW5pbWF0ZQ0KCQkJCQkJJChlcnJvcikuYW5pbWF0ZSh7b3BhY2l0eTogJzAnfSwwKS5pbnNlcnRBZnRlciggZWxlbWVudC5jbG9zZXN0KCdsYWJlbCcpICApLmFuaW1hdGUoe29wYWNpdHk6ICcxJ30sMTAwKTsNCgkJCQkJDQoJCQkJCX0gZWxzZSB7DQoJCQkJCQ0KCQkJCQkJLy8gQXBwZWFyDQoJCQkJCQllcnJvci5pbnNlcnRBZnRlciggZWxlbWVudC5jbG9zZXN0KCdsYWJlbCcpICk7DQoJCQkJCQ0KCQkJCQl9DQoNCgkJCQl9DQoJCQkJDQoJCQl9IGVsc2Ugew0KCQkJDQoJCQkJaWYodGhpcy5fc2hvd21lc3NhZ2UgPT0gMSkgew0KDQoJCQkJCWlmKHRoaXMuX2FuaW1hdGVzaG93ID09IHRydWUpIHsNCgkJCQkJDQoJCQkJCQkvLyBBbmltYXRlDQoJCQkJCQkkKGVycm9yKS5hbmltYXRlKHtvcGFjaXR5OiAnMCd9LDApLmluc2VydEFmdGVyKGVsZW1lbnQpLmFuaW1hdGUoe29wYWNpdHk6ICcxJ30sMTAwKTsNCgkJCQkJDQoJCQkJCX0gZWxzZSB7DQoJCQkJCQ0KCQkJCQkJLy8gQXBwZWFyDQoJCQkJCQllcnJvci5pbnNlcnRBZnRlciggZWxlbWVudCApOw0KCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJLy8gRG8gd2UgaGF2ZSBhbiBvdmVybGFwPw0KCQkJCQkNCgkJCQkJdmFyIGsgPSAkKGVsZW1lbnQpLm5leHQoJ2xhYmVsJyk7IC8vIGVycm9yIGxhYmVsDQoJCQkJCXZhciBqID0gJChlbGVtZW50KS5jbG9zZXN0KCJkaXZbaWRePWZiX2ZsZF0iKS5uZXh0KCk7IC8vIG5leHQgZmllbGQNCgkJCQkJDQoJCQkJCS8vIE5vIGVsZW1lbnQgbmV4dCB0bywgY291bGQgYmUgYmVmb3JlLg0KCQkJCQlpZihqLmxlbmd0aCA9PSAwKSB7DQoJCQkJCQlqID0gJChlbGVtZW50KS5jbG9zZXN0KCJkaXZbaWRePWZiX2ZsZF0iKS5wcmV2KCk7IC8vIHByZXZpb3VzIGZpZWxkDQoJCQkJCX0NCgkJCQkJDQoJCQkJCWlmKGsubGVuZ3RoICE9IDAgJiYgai5sZW5ndGggIT0gMCkgew0KCQkJCQkNCgkJCQkJCXZhciByZWN0MSA9IGsuZ2V0KDApLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyB0aGUgZXJyb3IgbGFiZWxzIGJvdW5kcw0KCQkJCQkJdmFyIHJlY3QyID0gai5nZXQoMCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IC8vIHRoZSBuZXh0IGVsZW1lbnRzIGJvdW5kcw0KCQkJCQkJDQoJCQkJCQl2YXIgb3ZlcmxhcCA9ICEocmVjdDEucmlnaHQgPCByZWN0Mi5sZWZ0IHx8IA0KCQkJCSAgICAgICAgICAgICAgICByZWN0MS5sZWZ0ID4gcmVjdDIucmlnaHQgfHwgDQoJCQkJICAgICAgICAgICAgICAgIHJlY3QxLmJvdHRvbSA8IHJlY3QyLnRvcCB8fCANCgkJCQkgICAgICAgICAgICAgICAgcmVjdDEudG9wID4gcmVjdDIuYm90dG9tKQ0KCQkJCSAgICAgICAgICAgICAgICANCgkJCQkgICAgICAgIGlmKG92ZXJsYXApIHsNCgkJCQkJCQ0KCQkJCQkJCSQoJzxici8+JykuaW5zZXJ0QWZ0ZXIoZWxlbWVudCk7DQoJCQkJCQkJDQoJCQkJCQl9DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQ0KCQkJCX0NCgkJCQkNCgkJCX0NCgkJCQkNCgkJfSwNCgkJDQoJCS8vc3VibWl0SGFuZGxlcjogZnVuY3Rpb24oZm9ybSkgew0KCQkvLwkkKCIjeyRmb3JtX2lkfSIpLnN1Ym1pdCgpDQoJCS8vfSwNCgkJDQoJCWludmFsaWRIYW5kbGVyOiBmdW5jdGlvbihldmVudCwgdmFsaWRhdG9yKSB7DQoJCQlmYi5lbmFibGVfc3VibWl0KCk7IC8vIGFsc28gY2FsbGVkIGJ5IHN0YW5kYXJkL2xlZ2FjeSB2YWxpZGF0aW9uIGxpYnJhcmllcy4NCgkJfSwNCgkJDQoJCS8vIEFkZC9SZW1vdmUgVmFsaWQgYW5kIEludmFsaWQgQ2xhc3NlcyBmcm9tIFdyYXBwZXJzLiANCgkJCQkNCgkJaGlnaGxpZ2h0OiBmdW5jdGlvbihlbGVtZW50LCBlcnJvckNsYXNzKSB7DQoNCgkJCSQoZWxlbWVudCkucGFyZW50KCkuY2xvc2VzdCgnLmZvcm0tZmllbGQtd3JhcHBlcicpLmFkZENsYXNzKCdlcnJvcicpOw0KCQkJJChlbGVtZW50KS5wYXJlbnQoKS5jbG9zZXN0KCcuZm9ybS1maWVsZC13cmFwcGVyJykucmVtb3ZlQ2xhc3MoJ3ZhbGlkJyk7DQoJCQkNCgkJfSwNCg0KCQl1bmhpZ2hsaWdodDogZnVuY3Rpb24oZWxlbWVudCwgZXJyb3JDbGFzcykgew0KDQoJCQkkKGVsZW1lbnQpLnBhcmVudCgpLmNsb3Nlc3QoJy5mb3JtLWZpZWxkLXdyYXBwZXInKS5hZGRDbGFzcygndmFsaWQnKTsNCgkJCSQoZWxlbWVudCkucGFyZW50KCkuY2xvc2VzdCgnLmZvcm0tZmllbGQtd3JhcHBlcicpLnJlbW92ZUNsYXNzKCdlcnJvcicpOw0KCQkJDQoJCX0sDQoJCQ0KCX0pOw0KCQ0KfSk7DQpFT0Y7DQogICAgICAgIH0gDQoNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRqYXZhc2NyaXB0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRqYXZhc2NyaXB0LCA2KTsNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkaW50ZXJuYXRpb25hbGl6YXRpb24pICYmICRpbnRlcm5hdGlvbmFsaXphdGlvbi0+Z2xvYmFsX2RpcmVjdGlvbiAhPSAiIikgew0KICAgICAgICAgICAgc3dpdGNoICgoaW50KSRpbnRlcm5hdGlvbmFsaXphdGlvbi0+Z2xvYmFsX2RpcmVjdGlvbikgew0KICAgICAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAgICAgJGdsb2JhbF9kaXJlY3Rpb24gPSAiIjsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAkZ2xvYmFsX2RpcmVjdGlvbiA9ICdkaXI9InJ0bCInOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRnbG9iYWxfZGlyZWN0aW9uID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVuY29kaW5nID0gJHRoaXMtPnVtLT50cmFuc2xhdGVIVE1MRW5jb2RpbmdUeXBlKCRlbmNvZGluZyk7DQoNCiAgICAgICAgDQogICAgICAgICR0cmFja2luZ19nb29nbGUgPSAiIjsgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJEFQSSA9IFJhY2tGb3Jtc19BUElfTWFuYWdlcjo6Z2V0QVBJKCk7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRBUEktPmdvb2dsZV9hbmFseXRpY3MtPkdvb2dsZV9BbmFseXRpY3NfR29vZ2xlX0FjY291bnQpICYmICRBUEktPmdvb2dsZV9hbmFseXRpY3MtPkdvb2dsZV9BbmFseXRpY3NfR29vZ2xlX0FjY291bnQgIT0gIiIpIHsNCg0KICAgICAgICAgICAgJHRyYWNraW5nX2dvb2dsZSA9ICR0aGlzLT5jcmVhdGVfdHJhY2tpbmdfZ29vZ2xlKCRBUEktPmdvb2dsZV9hbmFseXRpY3MtPkdvb2dsZV9BbmFseXRpY3NfR29vZ2xlX0FjY291bnQsICRBUEktPmdvb2dsZV9hbmFseXRpY3MtPkdvb2dsZV9BbmFseXRpY3NfR29vZ2xlX0RvbWFpbik7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPnRyYWNraW5nLT5nb29nbGUtPmFjY291bnQpICYmICRwYWdlLT50cmFja2luZy0+Z29vZ2xlLT5hY2NvdW50ICE9ICIiKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHRyYWNraW5nX2dvb2dsZSA9ICR0aGlzLT5jcmVhdGVfdHJhY2tpbmdfZ29vZ2xlKCRwYWdlLT50cmFja2luZy0+Z29vZ2xlLT5hY2NvdW50LCAkcGFnZS0+dHJhY2tpbmctPmdvb2dsZS0+ZG9tYWluKTsgDQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRBUEkgPSBSYWNrRm9ybXNfQVBJX01hbmFnZXI6OmdldEFQSSgpOw0KDQogICAgICAgICRnbG9iYWxfaGVhZGVyX2NvZGUgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJEFQSS0+Z2xvYmFsX2hlYWRlcl9jb2RlLT5HbG9iYWxIZWFkZXJDb2RlX0Zvcm0pICYmICRBUEktPmdsb2JhbF9oZWFkZXJfY29kZS0+R2xvYmFsSGVhZGVyQ29kZV9Gb3JtICE9ICIiKSB7DQoNCiAgICAgICAgICAgICRnbG9iYWxfaGVhZGVyX2NvZGUgPSAkQVBJLT5nbG9iYWxfaGVhZGVyX2NvZGUtPkdsb2JhbEhlYWRlckNvZGVfRm9ybTsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRwYWdlLT5nbG9iYWxzdHlsZSkgJiYgIWlzX251bWVyaWMoKHN0cmluZykkcGFnZS0+Z2xvYmFsc3R5bGUpKXsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGZpbGUgPSBmaWxlX2dldF9jb250ZW50cygiLi4vbGliL2dsb2JhbC1zdHlsZXMvdGVtcGxhdGUtbWFuYWdlci97JHBhZ2UtPmdsb2JhbHN0eWxlfSIpOw0KICAgICAgICAgICAgDQogICAgICAgICAgICAkc2VjdGlvbnMgPSBleHBsb2RlKCdbUkZfSEVBREVSX0ZPT1RFUl9TUExJVF0nLCAkZmlsZSk7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZihpc3NldCgkc2VjdGlvbnNbMF0pKXsNCiAgICAgICAgICAgICAgICAkZ2xvYmFsX2hlYWRlcl9jb2RlIC49ICRzZWN0aW9uc1swXTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmKGlzc2V0KCRzZWN0aW9uc1syXSkpew0KICAgICAgICAgICAgICAgICRnbG9iYWxfaGVhZGVyX2NvZGUgLj0gIlxyXG48c3R5bGUgdHlwZT1cInRleHQvY3NzXCI+IiAuICRzZWN0aW9uc1syXSAuICJcclxuPC9zdHlsZT4iOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRmb250YXdlc29tZSA9ICIiOw0KICAgICAgICANCiAgICAgICAgaWYoJGluY2x1ZGVfZm9udF9hd2Vzb21lKXsNCiAgICAgICAgICAgICRmb250YXdlc29tZSA9ICc8bGluayBocmVmPSI8P3BocCBlY2hvICRfU0VTU0lPTltcJ01BWF9QQVRIXCddOyA/PmdseXBoL2ZvbnRhd2Vzb21lLWZyZWUvY3NzL2FsbC5jc3MiIHJlbD0ic3R5bGVzaGVldCI+JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkaHRtbCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGV4cG9ydG1vZGUgPT0gMCkgeyANCg0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT1QNCnskcGhwfTwhRE9DVFlQRSBodG1sPg0KPGh0bWwgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIGxhbmc9InskbGFuZ3VhZ2V9IiB7JGdsb2JhbF9kaXJlY3Rpb259Pg0KPGhlYWQ+DQo8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEiPg0KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9eyRlbmNvZGluZ30iIC8+DQo8bWV0YSBuYW1lPSJkZXNjcmlwdGlvbiIgY29udGVudD0ieyRkZXNjcmlwdGlvbn0iIC8+DQo8bWV0YSBuYW1lPSJrZXl3b3JkcyIgY29udGVudD0ieyRrZXl3b3Jkc30iIC8+DQo8dGl0bGU+PD9waHAgZWNobyAieyR0aXRsZX0iOyA/PjwvdGl0bGU+DQo8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBocmVmPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Zm9ybXBhZ2UuY3NzIiBtZWRpYT0ic2NyZWVuIiAvPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzcyIgaHJlZj0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PnByaW50LmNzcyIgbWVkaWE9InByaW50IiAvPg0KeyRmb250YXdlc29tZX0NCnskanNfbGliX21vdmV9DQp7JGpzX2xpYl9tb3ZlX2NvbmRpdGlvbmFsfQ0KeyRjYWxlbmRhcl9qc30NCjwhLS0gdGlueW1jZSAtLT4NCnskdG1jfQ0KPCEtLSB2YWwgc2NyaXB0IC0tPg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCXZhciBwaHBwYXRoID0gJzw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz4nOw0KCXZhciBwYWdlTmFtZSA9ICd7JHBhZ2VuYW1lfSc7DQoJLy8gZXJyb3IgbG9naWMNCgl2YXIgc2hvd01lc3NhZ2UgPSB7JHNob3dqc3RleHR9Ow0KCXZhciBzaG93QWxlcnQgPSB7JHNob3dqc2FsZXJ0fTsNCgl2YXIgc2hvd0RlZmF1bHQgPSB7JHNob3dqc2RlZmF1bHR9Ow0KCXZhciBlcnJvclN0eWxlID0geyRlcnJvcnN0eWxlfTsNCgl2YXIgZXJyb3JDb2xvciA9ICJ7JGVycm9yY29sb3J9IjsNCgl2YXIganNwb3B1cF9lcnJvcm1lc3NhZ2UgPSAieyRqc3BvcHVwX2Vycm9ybWVzc2FnZX0iOw0KCXZhciBsYXlvdXQgPSB7JGxheW91dH07DQoJdmFyIHRhYmxlbW9kZSA9IHskdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dH07DQoJDQoJeyRqcXVlcnlfdmFsaWRhdGV9DQo8L3NjcmlwdD4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PnhtbGZvcm0uanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmNvbmRpdGlvbmFsLmpzIj48L3NjcmlwdD4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5mb3JtZmxvdy5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+bGliL3V0aWxpdHkuanMiPjwvc2NyaXB0Pg0KDQp7JGdvb2dsZWZvbnR9DQoNCnskYXV0b3N1Z2dlc3R9DQoNCnskY29sb3JwaWNrZXJ9DQoNCnskanNsaWRlcn0NCg0KeyRqYXZhc2NyaXB0fQ0KDQp7JGNvbmRpdGlvbmFsUGFnZUxvYWRDb2RlfQ0KDQp7JGJvZHliZ2RlZmluaXRpb259DQp7JGVycm9yX3N0eWxlc30NCnskZm9ybWxpbmtjb2xvcn0NCnskdHJhY2tpbmdfZ29vZ2xlfQ0KeyRnbG9iYWxfZm9udF9pbXBvcnR9DQp7JGdsb2JhbF9oZWFkZXJfY29kZX0NCjwvaGVhZD4NCnskYm9keXRhZ30NCjxhIGlkPSJ0b3AiPjwvYT4NCg0KDQoNCnskcGhwaGVhZGVyfQ0KRU9UOw0KICAgICAgICB9IA0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGV4cG9ydG1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAkaHRtbCA9IDw8PEVPVA0KeyRwaHB9DQo8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBocmVmPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Zm9ybXBhZ2UuY3NzIiBtZWRpYT0ic2NyZWVuIiAvPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzcyIgaHJlZj0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PnByaW50LmNzcyIgbWVkaWE9InByaW50IiAvPg0KeyRqc19saWJfbW92ZX0NCnskanNfbGliX21vdmVfY29uZGl0aW9uYWx9DQp7JGNhbGVuZGFyX2pzfQ0KPCEtLSB0aW55bWNlIC0tPg0KeyR0bWN9DQo8IS0tIHZhbCBzY3JpcHQgLS0+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJdmFyIHBocHBhdGggPSAnPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/Pic7DQoJdmFyIHBhZ2VOYW1lID0gJ3skcGFnZW5hbWV9JzsNCgkvLyBlcnJvciBsb2dpYw0KCXZhciBzaG93TWVzc2FnZSA9IHskc2hvd2pzdGV4dH07DQoJdmFyIHNob3dBbGVydCA9IHskc2hvd2pzYWxlcnR9Ow0KCXZhciBzaG93RGVmYXVsdCA9IHskc2hvd2pzZGVmYXVsdH07DQoJdmFyIGVycm9yU3R5bGUgPSB7JGVycm9yc3R5bGV9Ow0KCXZhciBlcnJvckNvbG9yID0gInskZXJyb3Jjb2xvcn0iOw0KCXZhciBqc3BvcHVwX2Vycm9ybWVzc2FnZSA9ICJ7JGpzcG9wdXBfZXJyb3JtZXNzYWdlfSI7DQoJdmFyIGxheW91dCA9IHskbGF5b3V0fTsNCgl2YXIgdGFibGVtb2RlID0geyR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0fTsNCgkNCgl7JGpxdWVyeV92YWxpZGF0ZX0NCjwvc2NyaXB0Pg0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+eG1sZm9ybS5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y29uZGl0aW9uYWwuanMiPjwvc2NyaXB0Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmZvcm1mbG93LmpzIj48L3NjcmlwdD4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5saWIvdXRpbGl0eS5qcyI+PC9zY3JpcHQ+DQoNCnskZ29vZ2xlZm9udH0NCgkJDQp7JGF1dG9zdWdnZXN0fQ0KDQp7JGNvbG9ycGlja2VyfQ0KDQp7JGpzbGlkZXJ9DQoNCnskamF2YXNjcmlwdH0NCg0KeyRjb25kaXRpb25hbFBhZ2VMb2FkQ29kZX0NCg0KeyRlcnJvcl9zdHlsZXN9DQp7JGZvcm1saW5rY29sb3J9DQoNCnskcGhwaGVhZGVyfQ0KDQp7JGdsb2JhbF9oZWFkZXJfY29kZX0NCkVPVDsNCiAgICAgICAgfSANCg0KICAgICAgICByZXR1cm4gJGh0bWw7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3BhZ2VfZW5kKCRwYWdlLCAkcGhwZm9vdGVyLCAkcGhwYm90dG9tLCAkZXhwb3J0bW9kZSkNCiAgICB7DQoNCiAgICAgICAgDQogICAgICAgICRwaHBmb290ZXIgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRwaHBmb290ZXIsIDApOw0KDQogICAgICAgIA0KICAgICAgICAkcGhwYm90dG9tID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkcGhwYm90dG9tLCAwKTsNCg0KICAgICAgICANCiAgICAgICAgJGh0bWwgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgJEFQSSA9IFJhY2tGb3Jtc19BUElfTWFuYWdlcjo6Z2V0QVBJKCk7DQoNCiAgICAgICAgJGdsb2JhbF9mb290ZXJfY29kZSA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkQVBJLT5nbG9iYWxfZm9vdGVyX2NvZGUtPkdsb2JhbEZvb3RlckNvZGVfRm9ybSkgJiYgJEFQSS0+Z2xvYmFsX2Zvb3Rlcl9jb2RlLT5HbG9iYWxGb290ZXJDb2RlX0Zvcm0gIT0gIiIpIHsNCg0KICAgICAgICAgICAgJGdsb2JhbF9mb290ZXJfY29kZSA9ICRBUEktPmdsb2JhbF9mb290ZXJfY29kZS0+R2xvYmFsRm9vdGVyQ29kZV9Gb3JtOw0KICAgICAgICAgICAgDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYoaXNzZXQoJHBhZ2UtPmdsb2JhbHN0eWxlKSAmJiAhaXNfbnVtZXJpYygoc3RyaW5nKSRwYWdlLT5nbG9iYWxzdHlsZSkpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZmlsZSA9IGZpbGVfZ2V0X2NvbnRlbnRzKCIuLi9saWIvZ2xvYmFsLXN0eWxlcy90ZW1wbGF0ZS1tYW5hZ2VyL3skcGFnZS0+Z2xvYmFsc3R5bGV9Iik7DQoJCQkNCgkJCWlmKCRmaWxlICE9ICIiKXsNCgkJCQkNCgkJCQkkY29kZSA9IGV4cGxvZGUoJ1tSRl9IRUFERVJfRk9PVEVSX1NQTElUXScsICRmaWxlKTsNCgkJCQkNCgkJCQlpZihpc19hcnJheSgkY29kZSkgJiYgY291bnQoJGNvZGUpID49IDEpew0KCQkJCQkNCgkJCQkJJGdsb2JhbF9mb290ZXJfY29kZSA9IGV4cGxvZGUoJ1tSRl9IRUFERVJfRk9PVEVSX1NQTElUXScsICRmaWxlKVsxXTsNCgkJCQkJDQoJCQkJfQ0KDQoJCQl9DQoJCQkNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGV4cG9ydG1vZGUgPT0gMCkgew0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT1QNCnskcGhwZm9vdGVyfQ0KeyRnbG9iYWxfZm9vdGVyX2NvZGV9DQo8L2JvZHk+DQo8L2h0bWw+DQp7JHBocGJvdHRvbX0NCkVPVDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGV4cG9ydG1vZGUgPT0gMSkgew0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT1QNCnskcGhwZm9vdGVyfQ0KeyRwaHBib3R0b219DQpFT1Q7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGh0bWw7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9mb3JtX3N0YXJ0KCRmb3JtLCAkcGFnZSwgJGpvYm5hbWUpDQogICAgew0KICAgICAgICAkYWN0aW9uID0gJGZvcm0tPmFjdGlvbjsNCiAgICAgICAgJG1ldGhvZCA9ICRmb3JtLT5tZXRob2Q7DQogICAgICAgICRlbmN0eXBlID0gJGZvcm0tPmVuY3R5cGU7DQogICAgICAgICRnZW9kYXRhID0gJGZvcm0tPmdlb2RhdGE7DQogICAgICAgICRuYW1lID0gJGZvcm0tPm5hbWU7DQogICAgICAgICRpZCA9ICRmb3JtLT5pZDsNCiAgICAgICAgJGxheW91dCA9ICRwYWdlLT5sYXlvdXQ7DQogICAgICAgICRkaW0gPSAkcGFnZS0+ZGltOw0KICAgICAgICAkdXNlYmcgPSAkcGFnZS0+dXNlYmc7DQogICAgICAgICRiZ2ZpbGUgPSAkcGFnZS0+YmdmaWxlOw0KICAgICAgICAkYmdyZXBlYXQgPSAkcGFnZS0+YmdyZXBlYXQ7DQogICAgICAgICRmb250ZmFtaWx5ID0gJHBhZ2UtPmZvbnRmYW1pbHk7DQogICAgICAgICRnb29nbGVmb250ID0gJHBhZ2UtPmdvb2dsZWZvbnQ7DQogICAgICAgICRwYWdlYmdjb2xvciA9ICRwYWdlLT5iZ2NvbG9yOw0KICAgICAgICAkYmdvcGFjaXR5ID0gKHN0cmluZykkcGFnZS0+YmdvcGFjaXR5OyANCiAgICAgICAgJHVzZWZvcm1iZ2NvbG9yID0gKGludCkkcGFnZS0+dXNlZm9ybWJnY29sb3I7DQogICAgICAgICRjZW50ZXJmb3JtID0gJHBhZ2UtPmNlbnRlcmZvcm07DQogICAgICAgICRwYWdlcGFkZGluZyA9ICRwYWdlLT5wYWdlcGFkZGluZzsNCiAgICAgICAgJHNvcnRhYmxlaGVpZ2h0bWV0aG9kID0gJHBhZ2UtPnNvcnRhYmxlaGVpZ2h0bWV0aG9kOw0KICAgICAgICAkYm94c2hhZG93ID0gJHBhZ2UtPmJveHNoYWRvdzsNCiAgICAgICAgJGJvcmRlcnJhZGl1cyA9ICRwYWdlLT5ib3JkZXJyYWRpdXM7DQogICAgICAgICRib3JkZXJyYWRpdXN2YWx1ZSA9ICRwYWdlLT5ib3JkZXJyYWRpdXN2YWx1ZTsNCiAgICAgICAgJHRhcmdldCA9ICRwYWdlLT5mb3JtLT50YXJnZXQ7DQoNCiAgICAgICAgJGV4cG9ydG1vZGUgPSAoaW50KSRwYWdlLT5leHBvcnRtb2RlOyANCg0KICAgICAgICAkZWxlbWVudCA9ICcnOw0KDQogICAgICAgIA0KDQogICAgICAgICRib3hzaGFkb3dfdmFsdWUgPSAiYm94LXNoYWRvdzogMCAycHggOHB4ICMxMTExMTE7IjsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGdsb2JhbF9zdHlsZV9pbnNlcnQgPSAkdGhpcy0+Y2UtPkNyZWF0ZUdsb2JhbFN0eWxlQ29kZSgkcGFnZSwgJGpvYm5hbWUpOyANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSAxIHx8IGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDMgfHwgaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgPT0gNSB8fCBpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSA3KSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGNlbnRlcmZvcm0gPSAxOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICR1c2Vmb3JtYmdjb2xvciA9IDE7DQogICAgICAgICAgICAkcGFnZWJnY29sb3IgPSAnI2ZmZmZmZic7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJveHNoYWRvdyA9IDE7DQogICAgICAgICAgICAkYm94c2hhZG93X3ZhbHVlID0gImJveC1zaGFkb3c6IDAgMnB4IDNweCAjYThhOGE4OyI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHBhZ2VwYWRkaW5nID0gNDA7DQoNCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgaWYgKGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDEgfHwgaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgPT0gMil7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGdvb2dsZWZvbnQgPSAiUm9ib3RvIjsNCiAgICAgICAgDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIGlmIChpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSAzIHx8IGludHZhbCgkcGFnZS0+Z2xvYmFsc3R5bGUpID09IDQpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZ29vZ2xlZm9udCA9ICJTb3VyY2UgU2FucyBQcm8iOw0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICBpZiAoaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgPT0gNSB8fCBpbnR2YWwoJHBhZ2UtPmdsb2JhbHN0eWxlKSA9PSA2KSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGdvb2dsZWZvbnQgPSAiUm9ib3RvIjsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgaWYoaXNzZXQoJHBhZ2UtPmdsb2JhbHN0eWxlKSAmJiAhaXNfbnVtZXJpYygoc3RyaW5nKSRwYWdlLT5nbG9iYWxzdHlsZSkpew0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRjZW50ZXJmb3JtID0gMTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkcGFnZXBhZGRpbmcgPSAxNTsgDQogICAgICAgICAgICANCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCg0KDQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkZ29vZ2xlZm9udCkgJiYgJGdvb2dsZWZvbnQgIT0gJzAnKSB7DQogICAgICAgICAgICAkZm9udGZhbWlseSA9ICJmb250LWZhbWlseTogJ3skZ29vZ2xlZm9udH0nLCB7JHRoaXMtPnJldHVybl9mb250KCRmb250ZmFtaWx5KX07IjsgDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkZm9udGZhbWlseSA9ICJmb250LWZhbWlseTogeyR0aGlzLT5yZXR1cm5fZm9udCgkZm9udGZhbWlseSl9OyI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgkbWV0aG9kKSB7DQogICAgICAgICAgICBjYXNlIDA6DQogICAgICAgICAgICAgICAgJG1ldGhvZCA9ICdwb3N0JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAkbWV0aG9kID0gJ2dldCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoaW50KSR0YXJnZXQpIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJ19zZWxmJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJ19ibGFuayc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDI6DQogICAgICAgICAgICAgICAgJHRhcmdldCA9ICdfcGFyZW50JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMzoNCiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJ190b3AnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIHN3aXRjaCAoJGVuY3R5cGUpIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkZW5jdHlwZSA9ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICRlbmN0eXBlID0gJ211bHRpcGFydC9mb3JtLWRhdGEnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGJnc3RyaW5nID0gJyc7DQoNCiAgICAgICAgaWYgKChpbnQpJHVzZWJnKSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRiZ2ZpbGUgPSAoc3RyaW5nKSRiZ2ZpbGU7DQogICAgICAgICAgICAkYmdzdHJpbmcgLj0gIiBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmJhY2tncm91bmQveyRiZ2ZpbGV9KTsgIjsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygnLi4vLi4vb3V0cHV0L2Zvcm1zLycgLiAkam9ibmFtZSAuICcvYmFja2dyb3VuZCcpKSB7DQogICAgICAgICAgICAgICAgbWtkaXIoJy4uLy4uL291dHB1dC9mb3Jtcy8nIC4gJGpvYm5hbWUgLiAnL2JhY2tncm91bmQvJywgRElSRUNUT1JZX01PRCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICgkYmdmaWxlICE9ICcnKSB7DQogICAgICAgICAgICAgICAgJGZpbGVfb3V0cHV0ID0gIi4uLy4uL291dHB1dC9mb3Jtcy8iIC4gKHN0cmluZykkam9ibmFtZSAuICcvYmFja2dyb3VuZC8nIC4gJGJnZmlsZTsNCiAgICAgICAgICAgICAgICBjb3B5KCIuLi8uLi9vdXRwdXQvdXBsb2FkX2JhY2tncm91bmQveyRiZ2ZpbGV9IiwgIi4uLy4uL291dHB1dC9mb3Jtcy97JGpvYm5hbWV9IiAuICcvYmFja2dyb3VuZC8nIC4gJGJnZmlsZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIHN3aXRjaCAoKGludCkkYmdyZXBlYXQpIHsNCiAgICAgICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAgICAgJHJwdCA9ICduby1yZXBlYXQnOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICBjYXNlICcxJzoNCiAgICAgICAgICAgICAgICAgICAgJHJwdCA9ICdyZXBlYXQteCc7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICAgICAkcnB0ID0gJ3JlcGVhdC15JzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAnMyc6DQogICAgICAgICAgICAgICAgICAgICRycHQgPSAncmVwZWF0JzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgICAgICRycHQgPSAnbm8tcmVwZWF0JzsgDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGRlZmF1bHQ6DQogICAgICAgICAgICAgICAgICAgICcnOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgJGJnc3RyaW5nIC49ICIgYmFja2dyb3VuZC1yZXBlYXQ6IHskcnB0fTsgIjsgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgoaW50KSRiZ3JlcGVhdCA9PSA0KSB7DQoNCiAgICAgICAgICAgICAgICAkYmdzdHJpbmcgPSAiIjsNCg0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPRg0KCQkJCQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4gDQoNCmh0bWwgeyANCgliYWNrZ3JvdW5kOiB1cmwoPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmJhY2tncm91bmQveyRiZ2ZpbGV9KSBuby1yZXBlYXQgY2VudGVyIGNlbnRlciBmaXhlZDsgDQoJLXdlYmtpdC1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyOw0KICAJLW1vei1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyOw0KICAJLW8tYmFja2dyb3VuZC1zaXplOiBjb3ZlcjsNCiAgCWJhY2tncm91bmQtc2l6ZTogY292ZXI7CQ0KfQ0KDQo8L3N0eWxlPg0KDQpFT0Y7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkYmdjb2xvcnN0cmluZyA9ICcnOw0KICAgICAgICBpZiAoKGludCkkdXNlZm9ybWJnY29sb3IpIHsNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRwYWdlYmdjb2xvciAhPSAnJykgew0KICAgICAgICAgICAgICAgICRiZ2NvbG9yc3RyaW5nIC49ICJiYWNrZ3JvdW5kLWNvbG9yOiB7JHBhZ2ViZ2NvbG9yfTsgIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkYmdvcGFjaXR5X3N0cmluZyA9ICcnOw0KICAgICAgICBpZiAoKGludCkkdXNlZm9ybWJnY29sb3IpIHsNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRiZ29wYWNpdHkgIT0gJycpIHsNCiAgICAgICAgICAgICAgICAkYmdvcGFjaXR5X3N0cmluZyAuPSAib3BhY2l0eTogeyRiZ29wYWNpdHl9OyAiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmICgoaW50KSR1c2Vmb3JtYmdjb2xvciAmJiBpc3NldCgkcGFnZS0+YmdvcGFjaXR5bWV0aG9kKSAmJiAoc3RyaW5nKSRwYWdlLT5iZ29wYWNpdHltZXRob2QgPT0gIjEiKSB7DQoNCiAgICAgICAgICAgICRiZ29wYWNpdHlfc3RyaW5nID0gIiI7DQoNCiAgICAgICAgICAgICRiZ2NvbG9yc3RyaW5nID0gImJhY2tncm91bmQtY29sb3I6ICIgLiAkdGhpcy0+dW0tPmhleDJyZ2JhKChzdHJpbmcpJHBhZ2ViZ2NvbG9yLCAoZmxvYXQpJGJnb3BhY2l0eSkgLiAiOyI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRwYWdlcGFkZGluZykgfHwgJHBhZ2VwYWRkaW5nID09ICIiKSB7DQogICAgICAgICAgICAkcGFnZXBhZGRpbmcgPSAnMTUnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRjZW50ZXJkZWZpbml0aW9uID0gJyc7DQogICAgICAgIGlmICgkY2VudGVyZm9ybSA9PSAxKSB7DQogICAgICAgICAgICAkY2VudGVycGFkID0gJyc7DQogICAgICAgICAgICBpZiAoKGludCkkbGF5b3V0ID09IDAgfHwgKGludCkkbGF5b3V0ID09IDIpIHsNCiAgICAgICAgICAgICAgICAkY2VudGVycGFkID0gInBhZGRpbmc6eyRwYWdlcGFkZGluZ31weDsiOyANCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmICgkZGltID09ICcnKSB7DQogICAgICAgICAgICAgICAgJGRpbSA9ICc1MDAsMzAwJzsNCiAgICAgICAgICAgIH0gDQogICAgICAgICAgICAkY2VudGVyZGltcyA9IGV4cGxvZGUoJywnLCAkZGltKTsNCiAgICAgICAgICAgICRjZW50ZXJkZWZpbml0aW9uID0gIndpZHRoOnskY2VudGVyZGltc1swXX1weDsgbWFyZ2luLWxlZnQ6YXV0bzsgbWFyZ2luLXJpZ2h0OmF1dG87IHskY2VudGVycGFkfSI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkc29ydGFibGVoZWlnaHRtZXRob2QpIHx8ICRzb3J0YWJsZWhlaWdodG1ldGhvZCA9PSAnJykgew0KICAgICAgICAgICAgJHNvcnRhYmxlaGVpZ2h0bWV0aG9kID0gIjAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGJveHNoYWRvdykgfHwgJGJveHNoYWRvdyA9PSAiIikgew0KICAgICAgICAgICAgJGJveHNoYWRvdyA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChpbnQpJGJveHNoYWRvdyA9PSAxKSB7DQogICAgICAgICAgICAgICAgJGJveHNoYWRvdyA9ICRib3hzaGFkb3dfdmFsdWU7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRib3hzaGFkb3cgPSAiIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghaXNzZXQoJGJvcmRlcnJhZGl1cykgfHwgJGJvcmRlcnJhZGl1cyA9PSAiIikgew0KICAgICAgICAgICAgJGJvcmRlcnJhZGl1cyA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChpbnQpJGJvcmRlcnJhZGl1cyA9PSAxICYmICRib3JkZXJyYWRpdXN2YWx1ZSAhPSAiIiAmJiBpc19udW1lcmljKChpbnQpJGJvcmRlcnJhZGl1c3ZhbHVlKSkgew0KICAgICAgICAgICAgICAgICRib3JkZXJyYWRpdXMgPSAiYm9yZGVyLXJhZGl1czogeyRib3JkZXJyYWRpdXN2YWx1ZX1weDsiOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkYm9yZGVycmFkaXVzID0gIiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJGRpbXMgPSBleHBsb2RlKCcsJywgJGRpbSk7DQogICAgICAgIA0KICAgICAgICAkZGltc1sxXSA9ICRkaW1zWzFdOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoc3Vic3RyX2NvdW50KCRkaW1zWzBdLCAnJScpID09IDApIHsNCiAgICAgICAgICAgICRkaW1zWzBdID0gJGRpbXNbMF0gLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHN1YnN0cl9jb3VudCgkZGltc1sxXSwgJyUnKSA9PSAwKSB7DQogICAgICAgICAgICAkZGltc1sxXSA9ICRkaW1zWzFdIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRwYWdlLT5mdWxsd2lkdGgpICYmIChzdHJpbmcpJHBhZ2UtPmZ1bGx3aWR0aCA9PSAiMSIpIHsNCiAgICAgICAgICAgICRkaW1zWzBdID0gJzEwMCUnOw0KICAgICAgICB9DQoNCiAgICAgICAgJGZvcm1faWQgPSBzdHJfcmVwbGFjZSgiLiIsICcnLCAkaWQpOw0KICAgICAgICAkZm9ybV9uYW1lID0gc3RyX3JlcGxhY2UoIi4iLCAnJywgJG5hbWUpOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGJvcmRlcl9jc3MgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmJvcmRlcnN0eWxlKSAmJiAkcGFnZS0+Ym9yZGVyc3R5bGUgIT0gMCkgew0KDQogICAgICAgICAgICBzd2l0Y2ggKCRwYWdlLT5ib3JkZXJzdHlsZSkgew0KICAgICAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICAgICAkYm9yZGVyX3N0eWxlID0gJ2RvdHRlZCc7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICAgICAkYm9yZGVyX3N0eWxlID0gJ3NvbGlkJzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAnMyc6DQogICAgICAgICAgICAgICAgICAgICRib3JkZXJfc3R5bGUgPSAnZGFzaGVkJzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRib3JkZXJfY3NzID0gImJvcmRlcjogeyRwYWdlLT5ib3JkZXJzaXplfSB7JGJvcmRlcl9zdHlsZX0geyRwYWdlLT5ib3JkZXJjb2xvcn07IjsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkc29ydGFibGVoZWlnaHRtZXRob2QgPT0gMCkgew0KICAgICAgICAgICAgJGhlaWdodCA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGhlaWdodCA9ICJoZWlnaHQ6eyRkaW1zWzFdfTsiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJG1vYmlsZV9wYWRkaW5nID0gIiI7DQoNCiAgICAgICAgaWYgKGRlZmluZWQoJ01PQklMRV9NT0RFJykpIHsNCiAgICAgICAgICAgICRtb2JpbGVfcGFkZGluZyA9ICJwYWRkaW5nOjEwcHg7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICAkb3V0cHV0X2Rpdl9jc3MgPSA8PDxFT0YNCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KI2Zvcm0tb3V0cHV0LWRpdi17JGZvcm1faWR9IHsNCg0KCXskbW9iaWxlX3BhZGRpbmd9DQoJeyRmb250ZmFtaWx5fQ0KCXskYmdzdHJpbmd9DQoJeyRiZ2NvbG9yc3RyaW5nfQ0KCXskYmdvcGFjaXR5X3N0cmluZ30NCgl7JGNlbnRlcmRlZmluaXRpb259DQoJeyRib3hzaGFkb3d9DQoJeyRib3JkZXJyYWRpdXN9DQoJd2lkdGg6eyRkaW1zWzBdfTsNCgl7JGhlaWdodH0NCgl7JGJvcmRlcl9jc3N9DQoJCQ0KfQ0KCQkNCjwvc3R5bGU+DQoJDQpFT0Y7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQoNCg0KICAgICAgICBpZiAoKGludCkkbGF5b3V0ID09IDAgfHwgKGludCkkbGF5b3V0ID09IDIpIHsgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJHNvcnRhYmxlaGVpZ2h0bWV0aG9kID09IDApIHsNCiAgICAgICAgICAgICAgICAkaGVpZ2h0ID0gIiI7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRoZWlnaHQgPSAiaGVpZ2h0OnskZGltc1sxXX07IjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRtb2JpbGVfcGFkZGluZyA9ICIiOw0KDQogICAgICAgICAgICBpZiAoZGVmaW5lZCgnTU9CSUxFX01PREUnKSkgew0KICAgICAgICAgICAgICAgICRtb2JpbGVfcGFkZGluZyA9ICJwYWRkaW5nOjEwcHg7IjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKChpbnQpJGV4cG9ydG1vZGUgIT0gMykgew0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG48IS0tIE9VVFBVVCBTVEFSVCAtLT5cblxuIjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICRnbG9iYWxfc3R5bGVfaW5zZXJ0Ow0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBpZD1cImZvcm0tb3V0cHV0LWRpdi17JGZvcm1faWR9XCIgY2xhc3M9XCJmb3JtLW91dHB1dC1kaXYgdWkgZm9ybVwiIHN0eWxlPVwieyRtb2JpbGVfcGFkZGluZ30geyRmb250ZmFtaWx5fSB7JGJnc3RyaW5nfSB7JGJnY29sb3JzdHJpbmd9IHskYmdvcGFjaXR5X3N0cmluZ30geyRjZW50ZXJkZWZpbml0aW9ufSB7JGJveHNoYWRvd30geyRib3JkZXJyYWRpdXN9IHdpZHRoOnskZGltc1swXX07IHskaGVpZ2h0fSB7JGJvcmRlcl9jc3N9IFwiPiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkZXhwb3J0bW9kZSAhPSAzKSB7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGZvcm0gY2xhc3M9XCJmb3JtLW91dHB1dC1zb3J0YWJsZVwiIGFjdGlvbj1cIjw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz57JGFjdGlvbn08P3BocCBlY2hvIFwkc2lkX3VybDsgPz5cIiBtZXRob2Q9XCJ7JG1ldGhvZH1cIiBlbmN0eXBlPVwieyRlbmN0eXBlfVwiIG5hbWU9XCJ7JGZvcm1fbmFtZX1cIiBpZD1cInskZm9ybV9pZH1cIiB0YXJnZXQ9XCJ7JHRhcmdldH1cIiA+XG4iOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKChpbnQpJGxheW91dCA9PSAxKSB7IA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCgkJDQo8P3BocA0KDQoJXCRjc3Nfd2lkdGggPSAnd2lkdGg6eyRkaW1zWzBdfTsgJzsNCglcJGNzc19oZWlnaHQgPSAnaGVpZ2h0OnskZGltc1sxXX07JzsNCgkJDQoJaWYoXCRQQUdFX0lTX1BERiA9PSB0cnVlKSB7DQoJCQkNCgkJXCRjc3Nfd2lkdGggPSAnJzsNCgkJXCRjc3NfaGVpZ2h0ID0gJyc7DQoJCQ0KCX0NCgkJCQ0KPz4NCgkJCQ0KRU9GOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cbjw/cGhwIGlmKFwkUERGX0xJQlJBUlkgPT0gJ0RPTVBERicgfHwgXCRQQUdFX0lTX1BERiAhPSB0cnVlICYmIFwkUERGX0xJQlJBUlkgIT0gJ01QREYnKSB7ID8+IjsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG48IS0tIEZPUk1fSEVBRF9TVEFSVCAtLT5cblxuIjsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxkaXYgaWQ9XCJmb3JtLW91dHB1dC1kaXYteyRmb3JtX2lkfVwiIGNsYXNzPVwiZm9ybS1vdXRwdXQtZGl2XCIgc3R5bGU9XCJwb3NpdGlvbjpyZWxhdGl2ZTsgeyRmb250ZmFtaWx5fSA8P3BocCBlY2hvIFwkY3NzX3dpZHRoOyBlY2hvIFwkY3NzX2hlaWdodDsgPz57JGJnc3RyaW5nfSB7JGJnY29sb3JzdHJpbmd9IHskYmdvcGFjaXR5X3N0cmluZ30geyRjZW50ZXJkZWZpbml0aW9ufSB7JGJveHNoYWRvd30geyRib3JkZXJyYWRpdXN9IHskYm9yZGVyX2Nzc30gXCI+IjsNCg0KICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cbjxmb3JtIGNsYXNzPVwiZm9ybS1vdXRwdXRcIiBhY3Rpb249XCI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+eyRhY3Rpb259PD9waHAgZWNobyBcJHNpZF91cmw7ID8+XCIgbWV0aG9kPVwieyRtZXRob2R9XCIgZW5jdHlwZT1cInskZW5jdHlwZX1cIiBuYW1lPVwieyRmb3JtX25hbWV9XCIgaWQ9XCJ7JGZvcm1faWR9XCIgdGFyZ2V0PVwieyR0YXJnZXR9XCIgPiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcblxuPCEtLSBGT1JNX0hFQURfRU5EIC0tPlxuXG4iOw0KDQogICAgICAgICAgICANCg0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPD9waHAgfSA/PlxuXG4iOw0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgkYmdzdHJpbmcgIT0gIiIpIHsNCg0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQoNCjw/cGhwDQppZihpc3NldChcJFBBR0VfSVNfUERGKSAmJiBcJFBBR0VfSVNfUERGID09IHRydWUpIHsNCgkJDQoJZWNobyAnPHN0eWxlPic7DQoJZWNobyAiYm9keSB7IGJhY2tncm91bmQtaW1hZ2U6IHVybCh7XCRfU0VTU0lPTlsnTUFYX1BBVEgnXX1iYWNrZ3JvdW5kL3skYmdmaWxlfSk7IGJhY2tncm91bmQtaW1hZ2UtcmVzaXplOjY7IH0iOw0KCWVjaG8gJzwvc3R5bGU+JzsNCgkJDQp9DQo/Pg0KCQkJCQ0KRU9GOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICANCg0KICAgICAgICAkZ2VvX2NvZGUgPSAiIjsNCg0KICAgICAgICBpZiAoJGdlb2RhdGEgIT0gIiIgJiYgKCRnZW9kYXRhID09ICIxIiB8fCAkZ2VvZGF0YSA9PSAiMiIpKSB7DQoNCiAgICAgICAgICAgICR1c2VfZ21hcHMgPSAnZmFsc2UnOw0KDQogICAgICAgICAgICBpZiAoJGdlb2RhdGEgPT0gIjIiKSB7DQogICAgICAgICAgICAgICAgJHVzZV9nbWFwcyA9ICd0cnVlJzsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGdlb19jb2RlID0gPDw8RU9GDQoJCQkNCjwhLS1HZW9EYXRhLS0+DQoNCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Imdlb19sYXQiIGlkPSJnZW9fbGF0IiB2YWx1ZT0iIiAvPg0KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZ2VvX2xvbmciIGlkPSJnZW9fbG9uZyIgdmFsdWU9IiIgLz4NCgkJCQkJDQo8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJnZW9fYWNjdXJhY3kiIGlkPSJnZW9fYWNjdXJhY3kiIHZhbHVlPSIiIC8+CQ0KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZ2VvX2FsdGl0dWRlIiBpZD0iZ2VvX2FsdGl0dWRlIiB2YWx1ZT0iIiAvPg0KCQkJCQkNCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Imdlb19oZWFkaW5nIiBpZD0iZ2VvX2hlYWRpbmciIHZhbHVlPSIiIC8+CQ0KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZ2VvX3NwZWVkIiBpZD0iZ2VvX3NwZWVkIiB2YWx1ZT0iIiAvPg0KCQkJCQkNCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Imdlb190aW1lc3RhbXAiIGlkPSJnZW9fdGltZXN0YW1wIiB2YWx1ZT0iIiAvPgkNCgkJCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9Ii8vbWFwcy5nb29nbGUuY29tL21hcHMvYXBpL2pzP3NlbnNvcj1mYWxzZSI+PC9zY3JpcHQ+DQogICAgPGFydGljbGUgc3R5bGU9ImRpc3BsYXk6YmxvY2s7Ij4NCiAgICAgIDxwPkxvY2F0aW9uIHN0YXR1czogPHNwYW4gaWQ9Imdlb19zdGF0dXMiPmNoZWNraW5nLi4uPC9zcGFuPjwvcD4NCiAgICA8L2FydGljbGU+DQo8c2NyaXB0Pg0KCQkJCQkNCmZ1bmN0aW9uIGdlb19zdWNjZXNzKHBvc2l0aW9uKSB7DQoJCQkJCQ0KCS8vIFBvcHVsYXRlIEhpZGRlbiBGaWVsZCBJdGVtcy4NCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZ2VvX2xhdCIpLnZhbHVlID0gcG9zaXRpb24uY29vcmRzLmxhdGl0dWRlOw0KCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJnZW9fbG9uZyIpLnZhbHVlID0gcG9zaXRpb24uY29vcmRzLmxvbmdpdHVkZTsNCgkJCQkJDQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImdlb19hY2N1cmFjeSIpLnZhbHVlID0gcG9zaXRpb24uY29vcmRzLmFjY3VyYWN5Ow0KCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJnZW9fYWx0aXR1ZGUiKS52YWx1ZSA9IHBvc2l0aW9uLmNvb3Jkcy5hbHRpdHVkZTsNCgkNCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZ2VvX2hlYWRpbmciKS52YWx1ZSA9IHBvc2l0aW9uLmNvb3Jkcy5oZWFkaW5nOw0KCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJnZW9fc3BlZWQiKS52YWx1ZSA9IHBvc2l0aW9uLmNvb3Jkcy5zcGVlZDsNCgkNCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZ2VvX3RpbWVzdGFtcCIpLnZhbHVlID0gcG9zaXRpb24uY29vcmRzLnRpbWVzdGFtcDsNCgkJCQkJDQoJDQoJdmFyIHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjZ2VvX3N0YXR1cycpOw0KICANCglpZiAocy5jbGFzc05hbWUgPT0gJ3N1Y2Nlc3MnKSB7ICANCgkJcmV0dXJuOw0KCX0NCiAgDQoJcy5pbm5lckhUTUwgPSAiTG9jYXRpb24gZm91bmQhIjsNCglzLmNsYXNzTmFtZSA9ICdzdWNjZXNzJzsNCiAgDQoJdmFyIHVzZV9nbWFwcyA9IHskdXNlX2dtYXBzfTsNCgkJCQkJDQoJaWYodXNlX2dtYXBzKXsNCgkJCQ0KCQl2YXIgbWFwY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7DQoJCW1hcGNhbnZhcy5pZCA9ICdtYXBjYW52YXMnOw0KCQltYXBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gJzQwMHB4JzsNCgkJbWFwY2FudmFzLnN0eWxlLndpZHRoID0gJzU2MHB4JzsNCgkgICAgDQoJCWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2FydGljbGUnKS5hcHBlbmRDaGlsZChtYXBjYW52YXMpOw0KCSAgDQoJCXZhciBsYXRsbmcgPSBuZXcgZ29vZ2xlLm1hcHMuTGF0TG5nKHBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSwgcG9zaXRpb24uY29vcmRzLmxvbmdpdHVkZSk7DQoJCXZhciBteU9wdGlvbnMgPSB7DQoJCQl6b29tOiAxNSwNCgkJCWNlbnRlcjogbGF0bG5nLA0KCQkJbWFwVHlwZUNvbnRyb2w6IGZhbHNlLA0KCQkJbmF2aWdhdGlvbkNvbnRyb2xPcHRpb25zOiB7c3R5bGU6IGdvb2dsZS5tYXBzLk5hdmlnYXRpb25Db250cm9sU3R5bGUuU01BTEx9LA0KCQkJbWFwVHlwZUlkOiBnb29nbGUubWFwcy5NYXBUeXBlSWQuUk9BRE1BUA0KCQl9Ow0KCQl2YXIgbWFwID0gbmV3IGdvb2dsZS5tYXBzLk1hcChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibWFwY2FudmFzIiksIG15T3B0aW9ucyk7DQoJICANCgkJdmFyIG1hcmtlciA9IG5ldyBnb29nbGUubWFwcy5NYXJrZXIoew0KCQkJcG9zaXRpb246IGxhdGxuZywgDQoJCQltYXA6IG1hcCwgDQoJCQl0aXRsZToiWW91IGFyZSBoZXJlISAoYXQgbGVhc3Qgd2l0aGluIGEgIitwb3NpdGlvbi5jb29yZHMuYWNjdXJhY3krIiBtZXRlciByYWRpdXMpIg0KCQl9KTsNCgkJCQ0KCX0NCn0NCg0KZnVuY3Rpb24gZXJyb3IobXNnKSB7DQogIHZhciBzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2dlb19zdGF0dXMnKTsNCiAgcy5pbm5lckhUTUwgPSB0eXBlb2YgbXNnID09ICdzdHJpbmcnID8gbXNnIDogImZhaWxlZCI7DQogIHMuY2xhc3NOYW1lID0gJ2ZhaWwnOw0KICANCiAgLy8gY29uc29sZS5sb2coYXJndW1lbnRzKTsNCn0NCg0KZnVuY3Rpb24gZ2VvX2xvY2F0ZSgpew0KCWlmIChuYXZpZ2F0b3IuZ2VvbG9jYXRpb24pIHsNCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImdlb19zdGF0dXMiKS5pbm5lckhUTUwgPSAiY2hlY2tpbmcuLi4iOw0KCQluYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKGdlb19zdWNjZXNzLCBlcnJvcik7DQoJfSBlbHNlIHsNCgkJZXJyb3IoJ25vdCBzdXBwb3J0ZWQnKTsNCgl9DQp9DQoNCi8vIENhbGwgZ2VvIHNlcnZpY2UNCmdlb19sb2NhdGUoKTsNCgkJCQ0KPC9zY3JpcHQ+DQoNCjxzcGFuIGlkPSJnZW9fc3RhdHVzIj48L3NwYW4+DQoJCQkJCQ0KPCEtLUdlb0RhdGEtLT4NCgkJCQ0KRU9GOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICcnOyANCg0KICAgICAgICAkZWxlbWVudCAuPSAkZ2VvX2NvZGU7DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZm9ybV9lbmQoJGxheW91dCwgJHRyYXBoaXQsICR0YWJsZW1vZGUsICRleHBvcnRtb2RlKQ0KICAgIHsNCg0KICAgICAgICAkZWxlbWVudCA9ICcnOw0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjwvZm9ybT4iOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCgkbGF5b3V0ID09IDAgfHwgJGxheW91dCA9PSAyKSAmJiAkdHJhcGhpdCA9PSAwKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+Y3JlYXRlX2Vycm9yX2NhdGNoX3NvcnRhYmxlKCR0YWJsZW1vZGUsICRleHBvcnRtb2RlKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKGludCkkZXhwb3J0bW9kZSAhPSAzKSB7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImNsZWFyaW5nLWRpdlwiIHN0eWxlPVwiY2xlYXI6Ym90aDtcIj48L2Rpdj5cbjwvZGl2PiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0gZWxzZWlmICgkbGF5b3V0ID09IDEgJiYgJHRyYXBoaXQgPT0gMCkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPmNyZWF0ZV9lcnJvcl9jYXRjaF9mcmVlZm9ybSgkdGFibGVtb2RlLCAkZXhwb3J0bW9kZSk7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cbjwvZGl2PjwhLS0gRk9STV9UQUlMX0VORCAtLT4iOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCiAgICANCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZXJyb3J0cmFwKCR0YWJsZW1vZGUsICRleHBvcnRtb2RlKQ0KICAgIHsNCg0KICAgICAgICBpZiAoKGludCkkZXhwb3J0bW9kZSA+IDEpDQogICAgICAgIHJldHVybiAiIjsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG4iIC4gJzw/cGhwIGlmKGlzc2V0KCRfU0VTU0lPTlsiZV9tZXNzYWdlIl0pKXsgID8+JyAuICJcbiI7DQogICAgICAgICRlbGVtZW50IC49ICc8ZGl2IGNsYXNzPSJlcnItbXNnIiBzdHlsZT0iYm9yZGVyOjFweCAjZWZlZmVmIHNvbGlkOyI+PD9waHAgZWNobyBodG1sX2VudGl0eV9kZWNvZGUoJF9TRVNTSU9OWyJlX21lc3NhZ2UiXSwgRU5UX1FVT1RFUyk7ID8+PC9kaXY+JzsNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuIiAuICc8P3BocCB1bnNldCgkX1NFU1NJT05bImVfbWVzc2FnZSJdKTsgfSA/PicgLiAiXG4iOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZXJyb3JfY2F0Y2hfc29ydGFibGUoJHRhYmxlbW9kZSwgJGV4cG9ydG1vZGUpDQogICAgew0KDQogICAgICAgIGlmICgoaW50KSRleHBvcnRtb2RlID4gMSkNCiAgICAgICAgcmV0dXJuICIiOw0KDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGh9OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7XCI+Jm5ic3A7PC9kaXY+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDtcIj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbiIgLiAnPD9waHAgaWYoaXNzZXQoJF9TRVNTSU9OWyJlX21lc3NhZ2UiXSkpeyAgPz4nIC4gIlxuIjsNCiAgICAgICAgJGVsZW1lbnQgLj0gJzxkaXYgY2xhc3M9ImVyci1tc2ciPjw/cGhwIGVjaG8gaHRtbF9lbnRpdHlfZGVjb2RlKCRfU0VTU0lPTlsiZV9tZXNzYWdlIl0sIEVOVF9RVU9URVMpOyA/PjwvZGl2Pic7DQogICAgICAgICRlbGVtZW50IC49ICJcbiIgLiAnPD9waHAgdW5zZXQoJF9TRVNTSU9OWyJlX21lc3NhZ2UiXSk7IH0gPz4nIC4gIlxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9lcnJvcl9jYXRjaF9mcmVlZm9ybSgkdGFibGVtb2RlLCAkZXhwb3J0bW9kZSkNCiAgICB7DQoNCiAgICAgICAgaWYgKChpbnQpJGV4cG9ydG1vZGUgPiAxKQ0KICAgICAgICByZXR1cm4gIiI7DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0O1wiPiZuYnNwOzwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAiXG4iIC4gJzw/cGhwIGlmKGlzc2V0KCRfU0VTU0lPTlsiZV9tZXNzYWdlIl0pKXsgID8+JyAuICJcbiI7DQogICAgICAgICRlbGVtZW50IC49ICc8ZGl2IGNsYXNzPSJlcnItbXNnIiBzdHlsZT0iIGJvcmRlcjowcHggI2VmZWZlZiBzb2xpZDsgcG9zaXRpb246YWJzb2x1dGU7IG1hcmdpbi1ib3R0b206LTVweDsgYm90dG9tOi0xMDBweDsgaGVpZ2h0OjEwMHB4OyBsZWZ0OjIwcHg7Ij48P3BocCBlY2hvIGh0bWxfZW50aXR5X2RlY29kZSgkX1NFU1NJT05bImVfbWVzc2FnZSJdLCBFTlRfUVVPVEVTKTsgPz48L2Rpdj4nOw0KICAgICAgICAkZWxlbWVudCAuPSAiXG4iIC4gJzw/cGhwIHVuc2V0KCRfU0VTU0lPTlsiZV9tZXNzYWdlIl0pOyB9ID8+JyAuICJcbiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfdWxfc3RhcnQoKQ0KICAgIHsNCiAgICAgICAgcmV0dXJuICI8dWw+IjsNCiAgICB9DQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV91bF9lbmQoKQ0KICAgIHsNCiAgICAgICAgcmV0dXJuICI8L3VsPiI7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9idWNrZXRfc3RhcnQoDQogICAgICAgICRmaWVsZCwNCiAgICAgICAgJHZhbGlkX2J1Y2tldF9uYW1lcywNCiAgICAgICAgJGNvbnRhaW5lZF9maWVsZHMsDQogICAgICAgICRjb250YWluZWRfd3JhcHBlcl9jbGFzc2VzLA0KICAgICAgICAkY29udGFpbmVkX2NvbmRpdGlvbmFscywNCiAgICAgICAgJGNvbnRhaW5lZF92YWxpZGF0aW9uDQogICAgKSB7DQoNCiAgICAgICAgJHdyYXBwZXJjbGFzcyA9IChzdHJpbmcpJGZpZWxkLT53cmFwcGVyY2xhc3M7DQoNCg0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICAkYnVja2V0X3dpZHRoID0gIiI7DQoNCiAgICAgICAgJGJ1Y2tldF9oZWlnaHQgPSAoaW50KSRmaWVsZC0+YnVja2V0X2hlaWdodDsNCg0KDQogICAgICAgIA0KICAgICAgICAkcmVwZWF0ZXJfY29udHJvbHMgPSAnJzsNCg0KICAgICAgICANCiAgICAgICAgJHZhbGlkX25hbWVzID0gaW1wbG9kZSgnLCcsICR2YWxpZF9idWNrZXRfbmFtZXMpOw0KDQoNCiAgICAgICAgDQogICAgICAgICRjb250YWluZWRfZmllbGRzX3ZhciA9ICdhcnJheSgnOw0KDQogICAgICAgICRpID0gMDsNCg0KICAgICAgICANCiAgICAgICAgZm9yZWFjaCAoJGNvbnRhaW5lZF9maWVsZHMgYXMgJGtleSA9PiAkY2YpIHsNCg0KICAgICAgICAgICAgaWYgKCRpICE9IDApIHsNCiAgICAgICAgICAgICAgICAkY29udGFpbmVkX2ZpZWxkc192YXIgLj0gJywgJzsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGNvbnRhaW5lZF9maWVsZHNfdmFyIC49ICIneyRrZXl9Jz0+J3skY2Z9JyI7DQoNCiAgICAgICAgICAgICRpKys7DQogICAgICAgIH0NCg0KICAgICAgICAkY29udGFpbmVkX2ZpZWxkc192YXIgLj0gJyk7JzsNCg0KDQogICAgICAgIA0KICAgICAgICAkY29udGFpbmVkX3ZhbGlkYXRpb25fdmFyID0gJ2FycmF5KCc7DQoNCiAgICAgICAgJGkgPSAwOw0KDQogICAgICAgIA0KICAgICAgICBmb3JlYWNoICgkY29udGFpbmVkX3ZhbGlkYXRpb24gYXMgJGtleSA9PiAkY2YpIHsNCg0KICAgICAgICAgICAgaWYgKCRpICE9IDApIHsNCiAgICAgICAgICAgICAgICAkY29udGFpbmVkX3ZhbGlkYXRpb25fdmFyIC49ICcsICc7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRjb250YWluZWRfdmFsaWRhdGlvbl92YXIgLj0gIid7JGtleX0nPT4neyRjZn0nIjsNCg0KICAgICAgICAgICAgJGkrKzsNCiAgICAgICAgfQ0KDQogICAgICAgICRjb250YWluZWRfdmFsaWRhdGlvbl92YXIgLj0gJyk7JzsNCg0KDQoNCiAgICAgICAgDQogICAgICAgICRjb250YWluZWRfd3JhcHBlcl9jbGFzc2VzX3ZhciA9ICdhcnJheSgnOw0KDQogICAgICAgICRpID0gMDsNCg0KICAgICAgICANCiAgICAgICAgZm9yZWFjaCAoJGNvbnRhaW5lZF93cmFwcGVyX2NsYXNzZXMgYXMgJGtleSA9PiAkY2YpIHsNCg0KICAgICAgICAgICAgaWYgKCRpICE9IDApIHsNCiAgICAgICAgICAgICAgICAkY29udGFpbmVkX3dyYXBwZXJfY2xhc3Nlc192YXIgLj0gJywgJzsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGNvbnRhaW5lZF93cmFwcGVyX2NsYXNzZXNfdmFyIC49ICIneyRjZn0nIjsNCg0KICAgICAgICAgICAgJGkrKzsNCiAgICAgICAgfQ0KDQogICAgICAgICRjb250YWluZWRfd3JhcHBlcl9jbGFzc2VzX3ZhciAuPSAnKTsnOw0KDQoNCg0KDQogICAgICAgIA0KDQogICAgICAgICRjb250YWluZWRfY29uZGl0aW9uYWxzX2VvZl92YXIgPSAiIjsNCg0KICAgICAgICAkY29udGFpbmVkX2NvbmRpdGlvbmFsc192YXIgPSAnYXJyYXkoJzsNCg0KICAgICAgICAkaSA9IDA7DQoNCiAgICAgICAgDQogICAgICAgIGZvcmVhY2ggKCRjb250YWluZWRfY29uZGl0aW9uYWxzIGFzICRrZXkgPT4gJGNmKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGNvbnRhaW5lZF9jb25kaXRpb25hbHNfZW9mX3ZhciAuPSAiXG5cJGNvbmRpdGlvbmFsX3ska2V5fSA9IDw8PEVPRlxuIjsNCiAgICAgICAgICAgICRjb250YWluZWRfY29uZGl0aW9uYWxzX2VvZl92YXIgLj0gJGNmOw0KICAgICAgICAgICAgJGNvbnRhaW5lZF9jb25kaXRpb25hbHNfZW9mX3ZhciAuPSAiXG5FT0Y7XG4iOw0KDQogICAgICAgICAgICBpZiAoJGkgIT0gMCkgew0KICAgICAgICAgICAgICAgICRjb250YWluZWRfY29uZGl0aW9uYWxzX3ZhciAuPSAnLCAnOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkY29udGFpbmVkX2NvbmRpdGlvbmFsc192YXIgLj0gIid7JGtleX0nPT5cJGNvbmRpdGlvbmFsX3ska2V5fSI7DQoNCiAgICAgICAgICAgICRpKys7DQogICAgICAgIH0NCg0KICAgICAgICAkY29udGFpbmVkX2NvbmRpdGlvbmFsc192YXIgLj0gJyk7JzsNCg0KDQoNCiAgICAgICAgDQogICAgICAgICRhZGRfYW5pbWF0aW9uID0gJyc7DQogICAgICAgICRyZW1vdmVfYW5pbWF0aW9uID0gJyc7DQoNCiAgICAgICAgc3dpdGNoICgkZmllbGQtPnJlcGVhdGVyLT5hZGRfYW5pbWF0aW9uKSB7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJGFkZF9hbmltYXRpb24gPSAnYmxpbmQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyOg0KICAgICAgICAgICAgICAgICRhZGRfYW5pbWF0aW9uID0gJ2ZhZGUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgc3dpdGNoICgkZmllbGQtPnJlcGVhdGVyLT5yZW1vdmVfYW5pbWF0aW9uKSB7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJHJlbW92ZV9hbmltYXRpb24gPSAnYmxpbmQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyOg0KICAgICAgICAgICAgICAgICRyZW1vdmVfYW5pbWF0aW9uID0gJ2ZhZGUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJGxpbWl0X21lc3NhZ2UgPSAnJzsNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cmVwZWF0ZXItPmxpbWl0bWVzc2FnZSkpIHsNCiAgICAgICAgICAgICRsaW1pdF9tZXNzYWdlID0gc3RyX3JlcGxhY2UoIiciLCAnYCcsICRmaWVsZC0+cmVwZWF0ZXItPmxpbWl0bWVzc2FnZSk7DQogICAgICAgIH0NCg0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPnJlcGVhdGVyKSAmJiAoc3RyaW5nKSRmaWVsZC0+cmVwZWF0ZXItPmVuYWJsZWQgPT0gJzEnKSB7DQoNCiAgICAgICAgICAgICRqcyA9ICIiOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5yZXBlYXRlci0+anMpICYmICRmaWVsZC0+cmVwZWF0ZXItPmpzICE9ICIiKSB7DQogICAgICAgICAgICAgICAgJGpzID0gPDw8RUlGDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoNCi8vIEN1c3RvbSBSZXBlYXRlciBKYXZhU2NyaXB0Lg0KDQp7JGZpZWxkLT5yZXBlYXRlci0+anN9DQoNCjwvc2NyaXB0PgkJCQkNCkVJRjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRvYnNlcnZlX2NvZGUgPSAiIjsNCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5yZXBlYXRlci0+anNsaWJyYXJ5ID09ICIwIikgew0KDQogICAgICAgICAgICAgICAgJG9ic2VydmVfY29kZSA9IDw8PEVPRg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KLy8gQnVja2V0U3RhcnQNCiQoIGRvY3VtZW50ICkucmVhZHkoZnVuY3Rpb24oKSB7DQoJYnVja2V0X3JlcGVhdGVyLmxvYWQoJ3skZmllbGQtPm5hbWV9JywgJ2ZiX2ZsZC17JGZpZWxkLT5uYW1lfScpOw0KfSk7DQovLyBCdWNrZXRFbmQNCjwvc2NyaXB0Pg0KRU9GOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5yZXBlYXRlci0+anNsaWJyYXJ5ID09ICIxIikgew0KDQogICAgICAgICAgICAgICAgJG9ic2VydmVfY29kZSA9IDw8PEVPRg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KLy8gQnVja2V0U3RhcnQNCmRvY3VtZW50Lm9ic2VydmUoJ2RvbTpsb2FkZWQnLCBmdW5jdGlvbihsKXsNCglidWNrZXRfcmVwZWF0ZXIubG9hZCgneyRmaWVsZC0+bmFtZX0nLCAnZmJfZmxkLXskZmllbGQtPm5hbWV9Jyk7DQp9KTsNCi8vIEJ1Y2tldEVuZA0KPC9zY3JpcHQ+DQpFT0Y7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPnJlcGVhdGVyLT5jb250cm9scykpDQogICAgICAgICAgICAkZmllbGQtPnJlcGVhdGVyLT5jb250cm9scyA9ICcwJzsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRjb250cm9sX3N0eWxlID0gImRpc3BsYXk6aW5saW5lOyI7DQogICAgICAgICAgICAkY29udHJvbF9jbGFzcyA9ICJjb250cm9scy12aXNpYmxlIjsNCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+cmVwZWF0ZXItPmNvbnRyb2xzID09IDEpIHsNCiAgICAgICAgICAgICAgICAkY29udHJvbF9zdHlsZSA9ICJkaXNwbGF5Om5vbmU7IjsNCiAgICAgICAgICAgICAgICAkY29udHJvbF9jbGFzcyA9ICJjb250cm9scy1oaWRkZW4iOw0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cmVwZWF0ZXItPmxpbWl0KSAmJiAkZmllbGQtPnJlcGVhdGVyLT5saW1pdCA9PSAiIikNCiAgICAgICAgICAgICRmaWVsZC0+cmVwZWF0ZXItPmxpbWl0ID0gOTk5OTk7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYnV0dG9uX2FkZCA9ICI8aW1nIGNsYXNzPVwiYnVja2V0LWFkZC1idXR0b24geyRjb250cm9sX2NsYXNzfVwiIHN0eWxlPVwiY3Vyc29yOnBvaW50ZXI7IHskY29udHJvbF9zdHlsZX1cIiBzcmM9XCJidWNrZXQtcmVwZWF0ZXIvaW1nL2J1dHRvbi1kdXBsaWNhdGUucG5nXCIgdGl0bGU9XCIoQWRkIEl0ZW0pXCIgb25DbGljaz1cImJ1Y2tldF9yZXBlYXRlci5hZGQoJ3skZmllbGQtPm5hbWV9JywgdGhpcywgJ3skYWRkX2FuaW1hdGlvbn0nKVwiIC8+IjsNCg0KICAgICAgICAgICAgaWYoaXNzZXQoJGZpZWxkLT5yZXBlYXRlci0+YWRkdGV4dCkgJiYgdHJpbSgkZmllbGQtPnJlcGVhdGVyLT5hZGR0ZXh0KSAhPSAiIil7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGJ1dHRvbl9hZGQgPSAiPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidWNrZXQtY29udHJvbC1idXR0b24gYnVja2V0LWNvbnRyb2wtYnV0dG9uLXRleHQtYWRkIHskY29udHJvbF9jbGFzc31cIiBzdHlsZT1cImN1cnNvcjpwb2ludGVyOyB7JGNvbnRyb2xfc3R5bGV9XCIgb25jbGljaz1cImJ1Y2tldF9yZXBlYXRlci5hZGQoJ3skZmllbGQtPm5hbWV9JywgdGhpcywgJ3skYWRkX2FuaW1hdGlvbn0nKVwiPnskZmllbGQtPnJlcGVhdGVyLT5hZGR0ZXh0fTwvYnV0dG9uPiI7DQogDQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgICRidXR0b25fcmVtb3ZlID0gIjwhLS0gYnVja2V0LXJlcGVhdGVyLW1pbnVzLWJ1dHRvbiAtLT48c3BhbiBjbGFzcz1cIlwiID48aW1nIHNyYz1cImJ1Y2tldC1yZXBlYXRlci9pbWcvYnV0dG9uLWJsYW5rLnBuZ1wiIHRpdGxlPVwiXCIgLz48L3NwYW4+IjsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJ1dHRvbl9yZW1vdmVfc2Vzc2lvbl9lbGVtZW50ID0gIiI7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZihpc3NldCgkZmllbGQtPnJlcGVhdGVyLT5yZW1vdmV0ZXh0KSAmJiB0cmltKCRmaWVsZC0+cmVwZWF0ZXItPnJlbW92ZXRleHQpICE9ICIiKXsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkYnV0dG9uX3JlbW92ZSA9ICI8IS0tIGJ1Y2tldC1yZXBlYXRlci1yZW1vdmUtYnV0dG9uIC0tPiI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGJ1dHRvbl9yZW1vdmVfc2Vzc2lvbl9lbGVtZW50ID0gJzxidXR0b24gdHlwZT0iYnV0dG9uIiBzdHlsZT0iY3Vyc29yOnBvaW50ZXI7IiBjbGFzcz0iYnVja2V0LWNvbnRyb2wtYnV0dG9uIGJ1Y2tldC1jb250cm9sLWJ1dHRvbi10ZXh0LXJlbW92ZSIgb25jbGljaz0iYnVja2V0X3JlcGVhdGVyLnJlbW92ZShCVVRUT05fUE9TVF9OQU1FLCBCVVRUT05fQlVDS0VUX05BTUVfUEFUSCwgdGhpcywgQlVUVE9OX0JVQ0tFVF9SRU1PVkVfQU5JTUFUSU9OKSI+JyAuICRmaWVsZC0+cmVwZWF0ZXItPnJlbW92ZXRleHQgLiAnPC9idXR0b24+JzsgDQogICAgICAgICAgICANCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHJlcGVhdGVyX2NvbnRyb2xzID0gPDw8RU9GDQo8P3BocCANCi8vIG1haW4gY29udHJvbA0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYi1idWNrZXQtcmVwZWF0ZXInXSA9IHRydWU7DQoNCi8vIGluaXRpYWxpemUgbWFpbiBkYXRhIGNvbnRhaW5lcg0KaWYoIWlzc2V0KFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnYnVja2V0LXJlcGVhdGVyJ11bInskZmllbGQtPm5hbWV9Il0pKXsNCglcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2J1Y2tldC1yZXBlYXRlciddWyJ7JGZpZWxkLT5uYW1lfSJdID0gYXJyYXkoKTsgDQp9DQoNCi8vIGluaXRpYWxpemUgY29udGFpbmVkIGZpZWxkIG5hbWVzDQpcJGNvbnRhaW5lZF9maWVsZHMgPSB7JGNvbnRhaW5lZF9maWVsZHNfdmFyfQ0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydidWNrZXQtcmVwZWF0ZXInXVsieyRmaWVsZC0+bmFtZX0tY29udGFpbmVkLWZpZWxkcyJdID0gXCRjb250YWluZWRfZmllbGRzOw0KDQovLyBpbml0aWFsaXplIGNvbnRhaW5lZCB2YWxpZGF0aW9uDQpcJGNvbnRhaW5lZF92YWxpZGF0aW9uID0geyRjb250YWluZWRfdmFsaWRhdGlvbl92YXJ9DQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2J1Y2tldC1yZXBlYXRlciddWyJ7JGZpZWxkLT5uYW1lfS1jb250YWluZWQtdmFsaWRhdGlvbiJdID0gXCRjb250YWluZWRfdmFsaWRhdGlvbjsNCg0KLy8gd3JhcHBlciBjbGFzc2VzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGJ1Y2tldA0KXCRjb250YWluZWRfd3JhcHBlcl9jbGFzc2VzID0geyRjb250YWluZWRfd3JhcHBlcl9jbGFzc2VzX3Zhcn0NClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnYnVja2V0LXJlcGVhdGVyJ11bInskZmllbGQtPm5hbWV9LWNvbnRhaW5lZC13cmFwcGVyLWNsYXNzZXMiXSA9IFwkY29udGFpbmVkX3dyYXBwZXJfY2xhc3NlczsNCg0KLy8gY29uZGl0aW9uYWwgY2FsbHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgYnVja2V0DQp7JGNvbnRhaW5lZF9jb25kaXRpb25hbHNfZW9mX3Zhcn0NClwkY29udGFpbmVkX2NvbmRpdGlvbmFscyA9IHskY29udGFpbmVkX2NvbmRpdGlvbmFsc192YXJ9DQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2J1Y2tldC1yZXBlYXRlciddWyJ7JGZpZWxkLT5uYW1lfS1jb250YWluZWQtY29uZGl0aW9uYWxzIl0gPSBcJGNvbnRhaW5lZF9jb25kaXRpb25hbHM7DQoNCi8vIGluaXRpYWxpemUgbGltaXQgbG9naWMNClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnYnVja2V0LXJlcGVhdGVyJ11bInskZmllbGQtPm5hbWV9LWxpbWl0Il0gPSB7JGZpZWxkLT5yZXBlYXRlci0+bGltaXR9Ow0KDQovLyBCdWlsZCA4ODUgLSBDb250cm9scyBsb2dpYw0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydidWNrZXQtcmVwZWF0ZXInXVsieyRmaWVsZC0+bmFtZX0tY29udHJvbHMiXSA9IHskZmllbGQtPnJlcGVhdGVyLT5jb250cm9sc307IA0KDQovLyBsaW1pdCBtZXNzYWdlDQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2J1Y2tldC1yZXBlYXRlciddWyJ7JGZpZWxkLT5uYW1lfS1saW1pdC1tZXNzYWdlIl0gPSAneyRsaW1pdF9tZXNzYWdlfSc7IA0KDQovLyByZW1vdmUgYW5pbWF0aW9uDQpcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ2J1Y2tldC1yZXBlYXRlciddWyJ7JGZpZWxkLT5uYW1lfS1yZW1vdmUtYW5pbWF0aW9uIl0gPSAneyRyZW1vdmVfYW5pbWF0aW9ufSc7IA0KDQovLyB2YWxpZCBidWNrZXQgbmFtZXMsIG11c3QgbWF0Y2ggYW55IHBhc3NlZCB2aWEgQUpBWCBjYWxscw0KXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydmYi12YWxpZC1idWNrZXQtbmFtZXMnXSA9IGFycmF5KHskdmFsaWRfbmFtZXN9KTsNCg0KLy8gQ3VzdG9tIFJlbW92ZSBCdXR0b24NClwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnYnVja2V0LXJlcGVhdGVyJ11bInskZmllbGQtPm5hbWV9LXJlbW92ZS1idXR0b24iXSA9ICd7JGJ1dHRvbl9yZW1vdmVfc2Vzc2lvbl9lbGVtZW50fSc7IA0KPz4NCg0KeyRvYnNlcnZlX2NvZGV9DQoNCnskanN9DQoNCjxkaXYgY2xhc3M9ImJ1Y2tldC1yZXBlYXRlci1jb250cm9scyIgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyByaWdodDowcHg7IHRvcDo4cHg7IGhlaWdodDo1MHB4OyB6LWluZGV4Ojk5OTk5OTk7Ij4NCiAgICB7JGJ1dHRvbl9yZW1vdmV9DQogICAgPHNwYW4gY2xhc3M9ImJ1dHRvbi1jb250cm9sLXNwYWNlciI+PC9zcGFuPg0KICAgIDxzcGFuPg0KICAgICAgICB7JGJ1dHRvbl9hZGR9DQogICAgPC9zcGFuPg0KPC9kaXY+DQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRidWNrZXRfcmVzcG9uc2l2ZV9jbGFzcyA9IGlzc2V0KCRmaWVsZC0+cmVwZWF0ZXItPnJlc3BvbnNpdmUpICYmIChpbnQpJGZpZWxkLT5yZXBlYXRlci0+cmVzcG9uc2l2ZSA9PSAxID8gJ3Jlc3BvbnNpdmUtYnVja2V0JyA6ICdzdGFuZGFyZC1idWNrZXQnOw0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+cmVwZWF0ZXItPmZpZWxkc2V0KSB8fCAoaW50KSRmaWVsZC0+cmVwZWF0ZXItPmZpZWxkc2V0ID09IDApIHsNCg0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT1QNClxuXG48IS0tIGJ1Y2tldCBzdGFydCAtLT4NCjxkaXYgaWQ9InskZmllbGQtPm5hbWV9IiBjbGFzcz0iYnVja2V0IHskYnVja2V0X3Jlc3BvbnNpdmVfY2xhc3N9IiBzdHlsZT0icG9zaXRpb246cmVsYXRpdmU7IGhlaWdodDp7JGJ1Y2tldF9oZWlnaHR9cHg7IHdpZHRoOnskYnVja2V0X3dpZHRofTsgeyRmaWVsZC0+YXR0cmlidXRlc3R5bGV9IiA+DQp7JHJlcGVhdGVyX2NvbnRyb2xzfQ0KRU9UOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cmVwZWF0ZXItPmZpZWxkc2V0KSAmJiAoaW50KSRmaWVsZC0+cmVwZWF0ZXItPmZpZWxkc2V0ID09IDEpIHsNCg0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT1QNClxuXG48IS0tIGJ1Y2tldCBzdGFydCAtLT4NCjxmaWVsZHNldCBpZD0ieyRmaWVsZC0+bmFtZX0iIGNsYXNzPSJidWNrZXQgeyRidWNrZXRfcmVzcG9uc2l2ZV9jbGFzc30gZmllbGRzZXQiIHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZTsgaGVpZ2h0OnskYnVja2V0X2hlaWdodH1weDsgd2lkdGg6eyRidWNrZXRfd2lkdGh9OyB7JGZpZWxkLT5hdHRyaWJ1dGVzdHlsZX0iID4NCgk8bGVnZW5kPnskZmllbGQtPnJlcGVhdGVyLT5sZWdlbmR9PC9sZWdlbmQ+DQp7JHJlcGVhdGVyX2NvbnRyb2xzfQ0KRU9UOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRodG1sOw0KICAgICAgICANCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfYnVja2V0X2VuZCgkZmllbGQsICR1c2VkX2ZpZWxkc2V0KQ0KICAgIHsNCg0KICAgICAgICAkaHRtbCA9ICIiOw0KDQogICAgICAgIA0KDQogICAgICAgICRodG1sIC49ICI8ZGl2IGNsYXNzPVwiY2xlYXJpbmctZGl2XCIgc3R5bGU9XCJjbGVhcjpib3RoO1wiPjwvZGl2PiI7DQoNCiAgICAgICAgaWYgKCR1c2VkX2ZpZWxkc2V0ID09IGZhbHNlKSB7DQogICAgICAgICAgICAkaHRtbCAuPSAiXG48L2Rpdj48IS0tIGJ1Y2tldCBlbmQgLS0+XG5cbiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaHRtbCAuPSAiXG48L2ZpZWxkc2V0PjwhLS0gYnVja2V0IGVuZCAtLT5cblxuIjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkaHRtbDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfYmxvY2soJGZpZWxkLCAkcGFnZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICR0YWJsZW1vZGUgPSAkcGFnZS0+dGFibGVtb2RlOw0KICAgICAgICAkZXhwb3J0bW9kZSA9IChpbnQpJHBhZ2UtPmV4cG9ydG1vZGU7IA0KDQogICAgICAgICRlbHQgPSAnJzsNCg0KICAgICAgICANCg0KICAgICAgICAkYmxvY2tfY29kZSA9ICR0aGlzLT51di0+cmVwbGFjZV9zZXNzaW9uX3Jhd19mb3JfY29kZV9ibG9jaygkZmllbGQtPmJsb2NrLT5jb2RlLCAwKTsgDQogICAgICAgICRibG9ja19jb2RlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkYmxvY2tfY29kZSwgNik7DQogICAgICAgICRibG9ja19jb2RlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2ZpZWxkX3JhdygkYmxvY2tfY29kZSwgMCk7IA0KICAgICAgICAkYmxvY2tfY29kZSA9ICR0aGlzLT51di0+cmVwbGFjZV9nZXRfcmF3KCRibG9ja19jb2RlLCAwKTsgDQogICAgICAgICRibG9ja19jb2RlID0gJHRoaXMtPnV2LT5yZXBsYWNlX3Bvc3RfcmF3KCRibG9ja19jb2RlLCAwKTsgDQogICAgICAgICRibG9ja19jb2RlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2ZpZWxkX2hlcmVkb2MoJGJsb2NrX2NvZGUsIDApOyANCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+YmxvY2stPmNzcykpIHsNCiAgICAgICAgICAgICRmaWVsZC0+YmxvY2stPmNzcyA9ICIiOw0KICAgICAgICB9DQogICAgICAgICRibG9ja19jc3MgPSAkdGhpcy0+dXYtPnJlcGxhY2Vfc2Vzc2lvbl9yYXdfZm9yX2NvZGVfYmxvY2soJGZpZWxkLT5ibG9jay0+Y3NzLCAwKTsNCiAgICAgICAgJGJsb2NrX2NzcyA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGJsb2NrX2NzcywgNik7DQogICAgICAgICRibG9ja19jc3MgPSAkdGhpcy0+dXYtPnJlcGxhY2VfZmllbGRfcmF3KCRibG9ja19jc3MsIDApOw0KICAgICAgICAkYmxvY2tfY3NzID0gJHRoaXMtPnV2LT5yZXBsYWNlX2dldF9yYXcoJGJsb2NrX2NzcywgMCk7DQogICAgICAgICRibG9ja19jc3MgPSAkdGhpcy0+dXYtPnJlcGxhY2VfcG9zdF9yYXcoJGJsb2NrX2NzcywgMCk7DQogICAgICAgICRibG9ja19jc3MgPSAkdGhpcy0+dXYtPnJlcGxhY2VfZmllbGRfaGVyZWRvYygkYmxvY2tfY3NzLCAwKTsNCg0KDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5ibG9jay0+anMpKSB7DQogICAgICAgICAgICAkZmllbGQtPmJsb2NrLT5qcyA9ICIiOw0KICAgICAgICB9DQogICAgICAgICRibG9ja19qcyA9ICR0aGlzLT51di0+cmVwbGFjZV9zZXNzaW9uX3Jhd19mb3JfY29kZV9ibG9jaygkZmllbGQtPmJsb2NrLT5qcywgMCk7DQogICAgICAgICRibG9ja19qcyA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGJsb2NrX2pzLCA2KTsNCiAgICAgICAgJGJsb2NrX2pzID0gJHRoaXMtPnV2LT5yZXBsYWNlX2ZpZWxkX3JhdygkYmxvY2tfanMsIDApOw0KICAgICAgICAkYmxvY2tfanMgPSAkdGhpcy0+dXYtPnJlcGxhY2VfZ2V0X3JhdygkYmxvY2tfanMsIDApOw0KICAgICAgICAkYmxvY2tfanMgPSAkdGhpcy0+dXYtPnJlcGxhY2VfcG9zdF9yYXcoJGJsb2NrX2pzLCAwKTsNCiAgICAgICAgJGJsb2NrX2pzID0gJHRoaXMtPnV2LT5yZXBsYWNlX2ZpZWxkX2hlcmVkb2MoJGJsb2NrX2pzLCAwKTsNCg0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5ibG9jay0+ZW5hYmxlZCA9PSAzKSB7DQoNCiAgICAgICAgICAgIGlmICgkYmxvY2tfY3NzICE9ICIiKSB7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG5cbjwhLS0gQmxvY2sgQ1NTIFN0YXJ0IC0tPlxuIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgJGVsdCAuPSAiPHN0eWxlIHR5cGU9XCJ0ZXh0L2Nzc1wiPlxuIiAuICRibG9ja19jc3MgLiAiXG48L3N0eWxlPiI7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG48IS0tIEJsb2NrIENTUyBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoJGJsb2NrX2pzICE9ICIiKSB7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG5cbjwhLS0gQmxvY2sgSlMgU3RhcnQgLS0+XG4iOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAkZWx0IC49ICI8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj5cbiIgLiAkYmxvY2tfanMgLiAiXG48L3NjcmlwdD4iOw0KICAgICAgICAgICAgICAgIGlmICgkZXhwb3J0bW9kZSAhPSAzKSB7DQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIlxuPCEtLSBCbG9jayBKUyBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICRlbHQgLj0gJGJsb2NrX2NvZGU7DQoNCiAgICAgICAgICAgIHJldHVybiAkZWx0Ow0KICAgICAgICB9DQoNCg0KICAgICAgICBpZiAoKGludCkkZmllbGQtPmJsb2NrLT5lbmFibGVkICE9IDApIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5ibG9jay0+YXV0b2lmcmFtZXJlc2l6ZSkgJiYgKChzdHJpbmcpJGZpZWxkLT5ibG9jay0+YXV0b2lmcmFtZXJlc2l6ZSA9PSAnMCcgfHwgKHN0cmluZykkZmllbGQtPmJsb2NrLT5hdXRvaWZyYW1lcmVzaXplID09ICcxJykpIHsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRoYXNfaWZyYW1lID0gZmFsc2U7DQogICAgICAgICAgICAgICAgJGhhc19pZnJhbWVfaWQgPSBmYWxzZTsNCiAgICAgICAgICAgICAgICAkaWZyYW1lX2lkID0gIiI7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmIChzdWJzdHJfY291bnQoJGJsb2NrX2NvZGUsICdpZnJhbWUnKSAhPSAwKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGhhc19pZnJhbWUgPSB0cnVlOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkaWZyYW1lX3N0YXJ0ID0gc3RycG9zKCRibG9ja19jb2RlLCAnPGlmcmFtZT4nKTsNCiAgICAgICAgICAgICAgICAgICAgJGlmcmFtZV9lbmQgPSBzdHJwb3MoJGJsb2NrX2NvZGUsICc8L2lmcmFtZT4nKTsNCg0KICAgICAgICAgICAgICAgICAgICAkc3ViX3N0cmluZyA9IHN1YnN0cigkYmxvY2tfY29kZSwgJGlmcmFtZV9zdGFydCwgJGlmcmFtZV9lbmQgLSAkaWZyYW1lX3N0YXJ0KTsNCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkaGFzX2lmcmFtZV9pZCA9IHN1YnN0cl9jb3VudCgkc3ViX3N0cmluZywgJ2lkPScpID09IDAgPyBmYWxzZSA6IHRydWU7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgaWYgKCRoYXNfaWZyYW1lICYmICRoYXNfaWZyYW1lX2lkKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgJHRhaWxfb2ZfaWZyYW1lID0gZXhwbG9kZSgnaWQ9JywgJHN1Yl9zdHJpbmcpOw0KDQogICAgICAgICAgICAgICAgICAgIGlmIChpc3NldCgkdGFpbF9vZl9pZnJhbWVbMV0pKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkaWZyYW1lX2lkID0gZXhwbG9kZSgnIicsICR0YWlsX29mX2lmcmFtZVsxXSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRpZnJhbWVfaWQgPSAkaWZyYW1lX2lkWzFdOw0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIGlmICgkaWZyYW1lX2lkICE9ICIiKSB7DQoNCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoNCg0KLy8gU2l6ZSBBZGp1c3RtZW50cw0KdmFyIF9SQUNLRk9STVNfUEFERElOR19IRUlHSFRfID0gMTA7DQp2YXIgX1JBQ0tGT1JNU19QQURESU5HX1dJRFRIXyA9IDIwMDsNCg0KdmFyIF9JRlJBTUVfUkVTSVpFX1RJTUVfID0gNTAwOw0KdmFyIF9JRlJBTUVfUkVTSVpFX1RJTUVfQ0xFQVJfID0gODAwMDsNCg0KdmFyIHdpZHRoX29mZnNldCA9IDA7DQp2YXIgaGVpZ2h0X29mZnNldCA9IDA7DQoNCnZhciBzZXRfaGVpZ2h0ID0gdHJ1ZTsNCnZhciBzZXRfd2lkdGggPSBmYWxzZTsNCg0KDQovLyByZXNpemUgd2luZG93IGxvZ2ljDQpmdW5jdGlvbiByZXNpemVfaWRfeyRmaWVsZC0+aWR9KG9iaikgew0KDQoJdmFyIHJlc2l6ZV9tb2RlID0geyRmaWVsZC0+YmxvY2stPmF1dG9pZnJhbWVyZXNpemV9Ow0KDQoJdmFyIGlmcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRpZnJhbWVfaWR9Jyk7DQoJDQoJaWYoaWZybSA9PSBudWxsKQ0KCQlyZXR1cm47DQoJDQoJaWZybSA9IChpZnJtLmNvbnRlbnRXaW5kb3cpID8gaWZybS5jb250ZW50V2luZG93IDogKGlmcm0uY29udGVudERvY3VtZW50LmRvY3VtZW50KSA/IGlmcm0uY29udGVudERvY3VtZW50LmRvY3VtZW50IDogaWZybS5jb250ZW50RG9jdW1lbnQ7DQoJdmFyIG9Db250ZW50ID0gaWZybS5kb2N1bWVudDsNCiAgICAgICAgICAgIAkJCQkNCglpZihvQ29udGVudC5vYmogPT0gZmFsc2UpDQoJCXJldHVybjsNCiAgICAgICAgICAgIAkJCQkNCgkvLyBSZXNpemUgVG8gaUZyYW1lIENvbnRlbnRzIE9ubHkuDQoJaWYocmVzaXplX21vZGUgPT0gMCl7DQoJCQ0KCQl2YXIgaCA9IHBhcnNlSW50KGdldFJGT3V0cHV0RElWSGVpZ2h0KG9Db250ZW50KSwgMTApOw0KCQl2YXIgdyA9IHBhcnNlSW50KGdldFJGT3V0cHV0RElWSGVpZ2h0KG9Db250ZW50KSwgMTApOw0KCQkNCgl9DQoJDQoJLy8gUmVzaXplIFRvIFVzZSBFbnRpcmUgUGFyZW50IFdpbmRvdy4NCglpZihyZXNpemVfbW9kZSA9PSAxKXsNCgkNCgkJdmFyIG9XaW5TaXplID0gZ2V0V2luU2l6ZSgpOw0KCQkNCgkJdmFyIGggPSBvV2luU2l6ZS5oZWlnaHQgLSBwYXJzZUludChnZXREb2NIZWlnaHQob0NvbnRlbnQpLCAxMCk7DQoJCXZhciB3ID0gb1dpblNpemUud2lkdGggLSBwYXJzZUludChnZXREb2NXaWR0aChvQ29udGVudCksIDEwKTsNCgkJDQoJfQ0KCQkNCgloID0gaCAtIGhlaWdodF9vZmZzZXQ7DQoJdyA9IHcgLSB3aWR0aF9vZmZzZXQ7DQoJCQ0KCWlmIChoID4gMCAmJiB3ID4gMCkgew0KCQlpZihzZXRfaGVpZ2h0KQ0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWZyYW1lX2lkfScpLnN0eWxlLmhlaWdodCA9IGgudG9TdHJpbmcoKSArICJweCI7DQoJCWlmKHNldF93aWR0aCkNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGlmcmFtZV9pZH0nKS5zdHlsZS53aWR0aCA9IHcudG9TdHJpbmcoKSArICJweCI7DQoJfQ0KDQp9Ow0KDQoNCnZhciBpbml0aWFsX3Jlc2l6ZV9pbnRlcnZhbF97JGZpZWxkLT5pZH07DQoNCmZ1bmN0aW9uIGNsZWFyX2luaXRpYWxfcmVzaXplX3RpbWVyX3skZmllbGQtPmlkfSgpew0KCXdpbmRvdy5jbGVhckludGVydmFsKGluaXRpYWxfcmVzaXplX2ludGVydmFsX3skZmllbGQtPmlkfSk7DQp9DQoNCi8vIGhhbmRsZSBvbmxvYWQoKQ0KRG9tUmVhZHkucmVhZHkoZnVuY3Rpb24oKSB7DQoNCgkvLyBhbHdheXMgcmVzaXplIGlmcmFtZSBvbiBwYWdlIGxvYWQNCglpbml0aWFsX3Jlc2l6ZV9pbnRlcnZhbF97JGZpZWxkLT5pZH0gPSBzZXRJbnRlcnZhbChyZXNpemVfaWRfeyRmaWVsZC0+aWR9LCBfSUZSQU1FX1JFU0laRV9USU1FXyk7DQoJDQoJLy8gY2xlYXIgaW5pdGlhbCByZXNpemUgYWZ0ZXIgYSBzZXQgdGltZSAqIEJ1aWxkIDg5MSAtIERpc2FibGVkLg0KCS8vd2luZG93LnNldFRpbWVvdXQoY2xlYXJfaW5pdGlhbF9yZXNpemVfdGltZXJfeyRmaWVsZC0+aWR9LCBfSUZSQU1FX1JFU0laRV9USU1FX0NMRUFSXyk7DQoNCgkvLyBhbHdheXMgZW5hYmxlIHRoZSByZXNpemUgZXZlbnQgaGFuZGxlcg0KCXdpbmRvdy5vbnJlc2l6ZSA9IGZ1bmN0aW9uKCkgeyByZXNpemVfaWRfeyRmaWVsZC0+aWR9KCk7IH07DQoNCn0pOw0KCQkJCQkNCjwvc2NyaXB0Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGVsdCAuPSAkYmxvY2tfY29kZTsNCg0KICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAkZWx0IC49ICJcbjwhLS0gQmxvY2sgQ29kZSBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkYmxvY2tfY3NzICE9ICIiKSB7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG5cbjwhLS0gQmxvY2sgQ1NTIFN0YXJ0IC0tPlxuIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgJGVsdCAuPSAiPHN0eWxlIHR5cGU9XCJ0ZXh0L2Nzc1wiPlxuIiAuICRibG9ja19jc3MgLiAiXG48L3N0eWxlPiI7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG48IS0tIEJsb2NrIENTUyBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoJGJsb2NrX2pzICE9ICIiKSB7DQogICAgICAgICAgICAgICAgaWYgKCRleHBvcnRtb2RlICE9IDMpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG5cbjwhLS0gQmxvY2sgSlMgU3RhcnQgLS0+XG4iOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAkZWx0IC49ICI8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj5cbiIgLiAkYmxvY2tfanMgLiAiXG48L3NjcmlwdD4iOw0KICAgICAgICAgICAgICAgIGlmICgkZXhwb3J0bW9kZSAhPSAzKSB7DQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIlxuPCEtLSBCbG9jayBKUyBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbHQ7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2xpX3N0YXJ0KCRmaWVsZCwgJHdyYXBwZXJjbGFzcywgJGNvbmRpdGlvbmFsLCAkcGFnZSwgJGVsZW1lbnRwb3MgPSAiMCIpDQogICAgew0KICAgICAgICBpZigkd3JhcHBlcmNsYXNzID09IG51bGwpeyAkd3JhcHBlcmNsYXNzID0gIiI7IH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHBhZ2UtPmV4cG9ydG1vZGUgPT0gMyAmJiAoJGZpZWxkLT50eXBlID09ICJxdWVyeSIgfHwgJGZpZWxkLT50eXBlID09ICJibG9jayIpKSB7DQoNCiAgICAgICAgICAgIHJldHVybiAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICJxdWVyeSIgJiYgaXNzZXQoJGZpZWxkLT5jcmVhdGVfZWxlbWVudHMpICYmICRmaWVsZC0+Y3JlYXRlX2VsZW1lbnRzICE9IDEpIHsNCg0KICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICB9DQoNCiAgICAgICAgJGlkID0gbnVsbDsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5pZCkpIHsNCiAgICAgICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7DQogICAgICAgIH0NCg0KICAgICAgICAkdGFibGVtb2RlID0gJHBhZ2UtPnRhYmxlbW9kZTsNCiAgICAgICAgJGRpbXMgPSBleHBsb2RlKCcsJywgJHBhZ2UtPmRpbSk7DQogICAgICAgICR3aWR0aCA9ICRkaW1zWzBdOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoc3Vic3RyX2NvdW50KCR3aWR0aCwgJyUnKSA9PSAwKSB7DQogICAgICAgICAgICAkd2lkdGggPSAkd2lkdGggLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyJzsNCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ2J1Y2tldCcpIHsNCg0KICAgICAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyLWJ1Y2tldCc7DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnJlcGVhdGVyLT53aWR0aCAhPSAiIikgew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICRmaWVsZC0+cmVwZWF0ZXItPndpZHRoOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAkZmllbGQtPmJ1Y2tldF93aWR0aDsgDQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJHdpZHRoKSA9PSB0cnVlKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJ3B4JzsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgICRlbHQgPSAiIjsNCg0KICAgICAgICANCg0KICAgICAgICAkZW5hYmxlZCA9ICcnOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHZpc2libGVfZmxhZyA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlID09ICcwJyA/ICJ2aXNpYmxlX2ZhbHNlIiA6ICJ2aXNpYmxlX3RydWUiOw0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICgkY29uZGl0aW9uYWwgIT0gbnVsbCkgew0KICAgICAgICAgICAgJHZpc2libGUgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmlzaWJsZSA9PSAnMCcgPyAnIGRpc3BsYXk6bm9uZTsgJyA6ICcnOw0KICAgICAgICAgICAgJGVuYWJsZWQgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmlzaWJsZSA9PSAnMCcgPyAnZGlzYWJsZWQ9ImRpc2FibGVkIicgOiAnJzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHZpc2libGUgPSAnZGlzcGxheTpibG9jazsnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkZWx0IC49IDw8PEVPRg0KDQo8P3BocCBcJHZpc2libGUgPSAneyR2aXNpYmxlfSc7IFwkZW5hYmxlZCA9ICd7JGVuYWJsZWR9JzsgPz4NCg0KRU9GOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGNvbmRpdGlvbmFsLT52aXNpYmxlX2ZpZWxkKSAmJiBpc3NldCgkY29uZGl0aW9uYWwtPnZpc2libGVfdmFsdWUpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlX2ZpZWxkICE9ICIiICYmIChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlX3ZhbHVlICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAkX2ZsZCA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlX2ZpZWxkOw0KDQogICAgICAgICAgICAgICAgJHJldmVyc2UgPSBpc3NldCgkY29uZGl0aW9uYWwtPnZpc2libGVfcmV2ZXJzZSkgPyAoaW50KSRjb25kaXRpb25hbC0+dmlzaWJsZV9yZXZlcnNlIDogMDsNCg0KICAgICAgICAgICAgICAgICR2YWwgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlX3ZhbHVlLCA0KTsgDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICgkY29uZGl0aW9uYWwtPnZpc2libGVfdmFsdWUgPT0gJHZhbCkgew0KICAgICAgICAgICAgICAgICAgICAkdmFsID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCAkdmFsKTsNCiAgICAgICAgICAgICAgICAgICAgJHZhbCA9ICInIiAuICR2YWwgLiAiJyI7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgaWYgKCRyZXZlcnNlID09IDApIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KXHJcbjw/cGhwDQovLyBgU2hvdyBGaWVsZCBJZmAgTG9naWMuDQppZihpc3NldChcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCg0KCVwkdmFsX2NoZWNrID0geyR2YWx9Ow0KDQoJaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsneyRfZmxkfSddKSl7DQoJDQoJCWlmKGluX2FycmF5KFwkdmFsX2NoZWNrLCBcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCgkJCVwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQogICAgICAgICAgICBcJGVuYWJsZWQgPSAnJzsNCiAgICAgICAgfQ0KCQ0KCX0gZWxzZSB7DQoNCgkJaWYoXCRfU0VTU0lPTlsneyRfZmxkfSddID09IFwkdmFsX2NoZWNrKXsNCiAgICAgICAgICAgIFwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQogICAgICAgICAgICBcJGVuYWJsZWQgPSAnJzsNCgkJfSBlbHNlIHsNCiAgICAgICAgICAgIFwkdmlzaWJsZSA9ICdkaXNwbGF5Om5vbmU7JzsNCgkJfQ0KCQkJCQ0KCX0NCn0NCj8+DQpFT0Y7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KXHJcbjw/cGhwDQovLyBgU2hvdyBGaWVsZCBJZmAgTG9naWMuDQppZihpc3NldChcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCgkJCQkJDQoJXCR2YWxfY2hlY2sgPSB7JHZhbH07DQoJCQkJCQ0KCWlmKGlzX2FycmF5KFwkX1NFU1NJT05bJ3skX2ZsZH0nXSkpew0KCQkJCQkNCgkJaWYoIWluX2FycmF5KFwkdmFsX2NoZWNrLCBcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCiAgICAgICAgICAgIFwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQogICAgICAgICAgICBcJGVuYWJsZWQgPSAnJzsNCiAgICAgICAgfQ0KCQkJCQkNCgl9IGVsc2Ugew0KCQkJCQkNCgkJaWYoXCRfU0VTU0lPTlsneyRfZmxkfSddICE9IFwkdmFsX2NoZWNrKXsNCiAgICAgICAgICAgIFwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQogICAgICAgICAgICBcJGVuYWJsZWQgPSAnJzsNCgkJfSBlbHNlIHsNCgkJCVwkdmlzaWJsZSA9ICdkaXNwbGF5Om5vbmU7JzsNCgkJfQ0KCQkJCQkNCgl9DQp9DQo/Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfSANCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkaWQgPT0gJycpIHsNCiAgICAgICAgICAgICRpZCA9ICRmaWVsZC0+dHlwZSAuICdfJyAuIHJhbmQoMTAwMDAwLCA5MDAwMDApOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+ZnVsbHdpZHRoKSAmJiAkcGFnZS0+ZnVsbHdpZHRoID09ICIxIikgew0KICAgICAgICAgICAgJHdpZHRoID0gJzEwMCUnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0KSAmJiAoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSAoaW50KSRwYWdlLT5zb3J0YWJsZWl0ZW1tYXJnaW5ib3R0b20gKyA0Ow0KDQogICAgICAgICAgICAkZWx0IC49ICJcbjwhLS0gfn5+fn5+fn5+fn5+fn5+fiAtLT5cbiI7DQogICAgICAgICAgICAkZWx0IC49ICI8IS0tIFNPUlRBQkxFIEZPUk0gRklFTEQgU1RBUlQgLS0+XG4iOw0KICAgICAgICAgICAgJGVsdCAuPSAiPCEtLSB+fn5+fn5+fn5+fn5+fn5+IC0tPlxuXG4iOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJHdpZHRoID0gcHJlZ19yZXBsYWNlKCcvW14wLTldLycsICcnLCAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGgpICsgcHJlZ19yZXBsYWNlKCcvW14wLTldLycsICcnLCAkdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRoKSArIDU7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChzdWJzdHJfY291bnQoJHdpZHRoLCAnJScpID09IDApIHsNCiAgICAgICAgICAgICAgICAkd2lkdGggPSBpbnR2YWwoJHdpZHRoKSAuICdweCc7ICAgIA0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkZmxvYXRfY3NzID0gImZsb2F0OmxlZnQ7IjsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRlbGVtZW50cG9zKSAmJiAkZWxlbWVudHBvcyA9PSAiMiIpIHsNCg0KICAgICAgICAgICAgICAgICRmbG9hdF9jc3MgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRfd2lkdGhfcGF0Y2ggPSAnJzsNCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAnc2VwYXJhdG9yJykgew0KDQogICAgICAgICAgICAgICAgJHdpZHRoID0gJzEwMCUnOw0KICAgICAgICAgICAgICAgICRfd2lkdGhfcGF0Y2ggPSAnd2lkdGg6MTAwJTsnOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAnYmxvY2snKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5maWVsZHdpZHRoID09ICcnKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJyc7DQogICAgICAgICAgICAgICAgICAgICRfd2lkdGhfcGF0Y2ggPSAnJzsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICR3aWR0aCA9IChzdHJpbmcpJGZpZWxkLT5maWVsZHdpZHRoOw0KDQogICAgICAgICAgICAgICAgICAgIGlmIChzdWJzdHJfY291bnQoJGZpZWxkLT5maWVsZHdpZHRoLCAnJScpID09IDApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICR3aWR0aCA9IGludHZhbCgkZmllbGQtPmZpZWxkd2lkdGgpIC4gJ3B4JzsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZ1bGx3aWR0aCkgJiYgJHBhZ2UtPmZ1bGx3aWR0aCA9PSAiMSIpIHsNCiAgICAgICAgICAgICAgICAkX3dpZHRoX3BhdGNoID0gJ3dpZHRoOjEwMCU7JzsNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAnMTAwJSc7IA0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUpICYmIChpbnQpJGZpZWxkLT5zdHlsZS0+YmFubmVybW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICAgICAkX3dpZHRoX3BhdGNoID0gJ3dpZHRoOjEwMCU7JzsNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAnMTAwJSc7IA0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bXVsdGlzZWxlY3RfY29udGFpbmVyX21hcmdpbikgJiYgJGZpZWxkLT5tdWx0aXNlbGVjdF9jb250YWluZXJfbWFyZ2luICE9ICcnKSB7DQoNCiAgICAgICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkZmllbGQtPm11bHRpc2VsZWN0X2NvbnRhaW5lcl9tYXJnaW4pOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWx0IC49ICI8ZGl2IGlkPVwiZmJfZmxkLXskaWR9XCIgcmYtZmllbGQ9XCJ0cnVlXCIgY2xhc3M9XCJ7JGZpZWxkX2NsYXNzX25hbWV9IHRhYmxlbW9kZS13cmFwcGVyLWRpdiB7JHdyYXBwZXJjbGFzc30gdHlwZS17JGZpZWxkLT50eXBlfVwiIHN0eWxlPVwid2lkdGg6eyR3aWR0aH07IGRpc3BsYXk6YmxvY2s7IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBmbG9hdDpsZWZ0OyBjbGVhcjpib3RoOyA8P3BocCBlY2hvIFwkdmlzaWJsZTsgXCR7JHZpc2libGVfZmxhZ307ID8+XCI+IjsNCg0KICAgICAgICAgICAgJGVsdCAuPSAiXG5cbjwhLS0gT3BlbiBDb250YWluZXIgRElWIC0tPiI7DQoNCiAgICAgICAgICAgICRlbHQgLj0gIlxuPGRpdiBzdHlsZT1cInskZmxvYXRfY3NzfSB7JF93aWR0aF9wYXRjaH0gXCIgPlxuIjsNCg0KICAgICAgICAgICAgDQogICAgICAgIH0gZWxzZSB7IA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRtYXJnaW5fYm90dG9tID0gIjEwIjsNCiAgICAgICAgICAgIGlmIChpc3NldCgkcGFnZS0+c29ydGFibGVpdGVtbWFyZ2luYm90dG9tKSAmJiAkcGFnZS0+c29ydGFibGVpdGVtbWFyZ2luYm90dG9tICE9ICIiKSB7DQogICAgICAgICAgICAgICAgJG1hcmdpbl9ib3R0b20gPSAoaW50KSRwYWdlLT5zb3J0YWJsZWl0ZW1tYXJnaW5ib3R0b20gKyA0OyANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPm11bHRpc2VsZWN0X2NvbnRhaW5lcl9tYXJnaW4pICYmICRmaWVsZC0+bXVsdGlzZWxlY3RfY29udGFpbmVyX21hcmdpbiAhPSAnJykgew0KDQogICAgICAgICAgICAgICAgJG1hcmdpbl9ib3R0b20gPSBpbnR2YWwoJGZpZWxkLT5tdWx0aXNlbGVjdF9jb250YWluZXJfbWFyZ2luKTsNCiAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRmbG9hdF9jc3MgPSAiZmxvYXQ6bGVmdDsiOw0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGVsZW1lbnRwb3MpICYmICRlbGVtZW50cG9zID09ICIyIikgew0KDQogICAgICAgICAgICAgICAgJGZsb2F0X2NzcyA9ICIiOw0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ3NlcGFyYXRvcicpIHsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZWxlbWVudHBvcykgJiYgKGludCkkZWxlbWVudHBvcyAhPSAiMCIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAnMTAwJSc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkZmllbGQtPndpZHRoOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZWxlbWVudHBvcykgJiYgKGludCkkZWxlbWVudHBvcyA9PSAiMiIpIHsNCg0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICIiOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAnYmxvY2snKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5maWVsZHdpZHRoID09ICcnKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJyc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAoc3RyaW5nKSRmaWVsZC0+ZmllbGR3aWR0aDsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoc3Vic3RyX2NvdW50KCRmaWVsZC0+ZmllbGR3aWR0aCwgJyUnKSA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSBpbnR2YWwoJGZpZWxkLT5maWVsZHdpZHRoKSAuICdweCc7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCg0KDQogICAgICAgICAgICBpZiAoKGludCkkcGFnZS0+ZXhwb3J0bW9kZSA9PSAzKSB7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlICE9ICJxdWVyeSIgfHwgJGZpZWxkLT50eXBlICE9ICJibG9jayIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICJcbjwhLS0gfn5+fn5+fn5+fn5+fn5+fiAtLT5cbiI7DQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjwhLS0gRk9STSBGSUVMRCBTVEFSVCAtLT5cbiI7DQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjwhLS0gfn5+fn5+fn5+fn5+fn5+fiAtLT5cblxuIjsNCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IGlkPVwiZmJfZmxkLXskaWR9XCIgcmYtZmllbGQ9XCJ0cnVlXCIgY2xhc3M9XCJ7JGZpZWxkX2NsYXNzX25hbWV9IHskd3JhcHBlcmNsYXNzfSB0eXBlLXskZmllbGQtPnR5cGV9XCIgc3R5bGU9XCJ7JGZsb2F0X2Nzc30gd2lkdGg6eyR3aWR0aH07IG1hcmdpbi1ib3R0b206eyRtYXJnaW5fYm90dG9tfXB4OyA8P3BocCBlY2hvIFwkdmlzaWJsZTsgXCR7JHZpc2libGVfZmxhZ307ID8+XCIgPlxuIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgJGVsdCAuPSAiXG48IS0tIH5+fn5+fn5+fn5+fn5+fn4gLS0+XG4iOw0KICAgICAgICAgICAgICAgICRlbHQgLj0gIjwhLS0gRk9STSBGSUVMRCBTVEFSVCAtLT5cbiI7DQogICAgICAgICAgICAgICAgJGVsdCAuPSAiPCEtLSB+fn5+fn5+fn5+fn5+fn5+IC0tPlxuXG4iOw0KDQogICAgICAgICAgICAgICAgJGVsdCAuPSAiPGRpdiBpZD1cImZiX2ZsZC17JGlkfVwiIHJmLWZpZWxkPVwidHJ1ZVwiIGNsYXNzPVwieyRmaWVsZF9jbGFzc19uYW1lfSB7JHdyYXBwZXJjbGFzc30gdHlwZS17JGZpZWxkLT50eXBlfVwiIHN0eWxlPVwieyRmbG9hdF9jc3N9IHdpZHRoOnskd2lkdGh9OyBtYXJnaW4tYm90dG9tOnskbWFyZ2luX2JvdHRvbX1weDsgPD9waHAgZWNobyBcJHZpc2libGU7IFwkeyR2aXNpYmxlX2ZsYWd9OyA/PlwiID5cbiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0gDQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+Y2VudGVyZm9ybSkgJiYgKHN0cmluZykkcGFnZS0+Y2VudGVyZm9ybSA9PSAiMSIpIHsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUpICYmIChpbnQpJGZpZWxkLT5zdHlsZS0+YmFubmVybW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGVsZW1lbnRwb3MpICYmICRlbGVtZW50cG9zICE9ICIwIikgew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdG1wID0gZXhwbG9kZSgnLCcsICRwYWdlLT5kaW0pOw0KDQogICAgICAgICAgICAgICAgICAgICRwYWdlX3dpZHRoID0gJHRtcFswXTsNCg0KICAgICAgICAgICAgICAgICAgICAkZmllbGR3aWR0aCA9ICgoKGludCkkcGFnZS0+cGFnZXBhZGRpbmcgKiAyKSArICRwYWdlX3dpZHRoKSAtICgkZmllbGQtPnN0eWxlLT5wYWRkaW5nbGVmdCArICRmaWVsZC0+c3R5bGUtPnBhZGRpbmdyaWdodCkgLiAncHgnOw0KDQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJ3aWR0aDogeyRmaWVsZHdpZHRofTtcIj4iOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGVsdDsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJGVsZW1lbnRwb3MpICYmIChpbnQpJGVsZW1lbnRwb3MgIT0gIjAiKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJGVsZW1lbnRwb3MgPT0gIjIiKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICJjaGVja2JveCIgfHwgJGZpZWxkLT50eXBlID09ICJyYWRpbyIgfHwgJGZpZWxkLT50eXBlID09ICJlY29tbSIgfHwgJGZpZWxkLT50eXBlID09ICJzdXJ2ZXkiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG48ZGl2IHN0eWxlPVwid2lkdGg6NTAlOyBtYXJnaW46IDAgYXV0bztcIj48IS0tIG9wZW4gYWxpZ25tZW50IGRpdiAtLT5cbiI7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiXG48ZGl2IHN0eWxlPVwiYWxpZ24taXRlbXM6IGNlbnRlcjsgZGlzcGxheTogZmxleDsganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XCI+PCEtLSBvcGVuIGZsZXggYWxpZ25tZW50IGRpdiAtLT5cbiI7DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSAhPSAiYm9keWNvcHkiICYmICRmaWVsZC0+dHlwZSAhPSAic2VjdGlvbmhlYWRlciIgJiYgJGZpZWxkLT50eXBlICE9ICJzZXBhcmF0b3IiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIlxuPGRpdiBjbGFzcz1cImZsZXgtZ3JvdXBpbmctZGl2XCI+PCEtLSBvcGVuIGZsZXgtZ3JvdXBpbmctZGl2IC0tPlxuIjsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICgkZWxlbWVudHBvcyA9PSAiMSIpIHsNCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnRwb3MgPSAwOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRlbHQgLj0gIlxuIjsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPnN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6ICIgLiAkZWxlbWVudHBvcyAuICJweDtcIj48IS0tIE9wZW4gUmlnaHQgQWxpZ25lZCBCYW5uZXIgTW9kZSBJdGVtIC0tPiI7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICJib2R5Y29weSIgfHwgJGZpZWxkLT50eXBlID09ICJzZWN0aW9uaGVhZGVyIiAmJiAkZmllbGQtPnR5cGUgIT0gInNlcGFyYXRvciIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiPGRpdiBzdHlsZT1cIm1hcmdpbi1yaWdodDogIiAuICRlbGVtZW50cG9zIC4gInB4OyB3aWR0aDoxMDAlO1wiPjwhLS0gT3BlbiBSaWdodCBBbGlnbmVkIEl0ZW0gLS0+IjsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSAiPGRpdiBzdHlsZT1cIm1hcmdpbi1yaWdodDogIiAuICRlbGVtZW50cG9zIC4gInB4OyBmbG9hdDpyaWdodDtcIj48IS0tIE9wZW4gUmlnaHQgQWxpZ25lZCBJdGVtIC0tPiI7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkZWx0IC49ICJcbiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0gDQoNCg0KICAgICAgICByZXR1cm4gJGVsdDsNCiAgICB9DQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2xpX3N0YXJ0X2h0bWxfb25seSgkZmllbGQsICR3cmFwcGVyY2xhc3MsICRjb25kaXRpb25hbCwgJHBhZ2UsICRlbGVtZW50cG9zID0gIjAiKQ0KICAgIHsNCiAgICAgICAgaWYgKCR3cmFwcGVyY2xhc3MgPT0gbnVsbCkgew0KICAgICAgICAgICAgJHdyYXBwZXJjbGFzcyA9ICIiOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRhYmxlbW9kZSA9ICRwYWdlLT50YWJsZW1vZGU7DQogICAgICAgICRkaW1zID0gZXhwbG9kZSgnLCcsICRwYWdlLT5kaW0pOw0KICAgICAgICAkd2lkdGggPSAkZGltc1swXTsNCg0KICAgICAgICAkaWQgPSBpc3NldCgkZmllbGQtPmlkKSA/ICRmaWVsZC0+aWQgOiAnJzsNCg0KICAgICAgICANCiAgICAgICAgaWYgKHN1YnN0cl9jb3VudCgkd2lkdGgsICclJykgPT0gMCkgew0KICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyJzsNCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ2J1Y2tldCcpIHsNCg0KICAgICAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyLWJ1Y2tldCc7DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnJlcGVhdGVyLT53aWR0aCAhPSAiIikgew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICRmaWVsZC0+cmVwZWF0ZXItPndpZHRoOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAkZmllbGQtPmJ1Y2tldF93aWR0aDsgDQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJHdpZHRoKSA9PSB0cnVlKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJ3B4JzsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgICRlbHQgPSAiIjsNCg0KDQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+ZnVsbHdpZHRoKSAmJiAkcGFnZS0+ZnVsbHdpZHRoID09ICIxIikgew0KICAgICAgICAgICAgJHdpZHRoID0gJzEwMCUnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGlzc2V0KCR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0KSAmJiAoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCg0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSAoaW50KSRwYWdlLT5zb3J0YWJsZWl0ZW1tYXJnaW5ib3R0b20gKyA0Ow0KDQoNCiAgICAgICAgICAgICR3aWR0aCA9IHByZWdfcmVwbGFjZSgnL1teMC05XS8nLCAnJywgJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoKSArIHByZWdfcmVwbGFjZSgnL1teMC05XS8nLCAnJywgJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aCkgKyA1Ow0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoc3Vic3RyX2NvdW50KCR3aWR0aCwgJyUnKSA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gaW50dmFsKCR3aWR0aCkgLiAncHgnOyAgICANCiAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJGZsb2F0X2NzcyA9ICJmbG9hdDpsZWZ0OyI7DQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZWxlbWVudHBvcykgJiYgJGVsZW1lbnRwb3MgPT0gIjIiKSB7DQoNCiAgICAgICAgICAgICAgICAkZmxvYXRfY3NzID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkX3dpZHRoX3BhdGNoID0gJyc7DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ3NlcGFyYXRvcicpIHsNCg0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICcxMDAlJzsNCiAgICAgICAgICAgICAgICAkX3dpZHRoX3BhdGNoID0gJ3dpZHRoOjEwMCU7JzsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkcGFnZS0+ZnVsbHdpZHRoKSAmJiAkcGFnZS0+ZnVsbHdpZHRoID09ICIxIikgew0KICAgICAgICAgICAgICAgICRfd2lkdGhfcGF0Y2ggPSAnd2lkdGg6MTAwJTsnOw0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICcxMDAlJzsgDQogICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5zdHlsZS0+YmFubmVybW9kZSkgJiYgKGludCkkZmllbGQtPnN0eWxlLT5iYW5uZXJtb2RlID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICRfd2lkdGhfcGF0Y2ggPSAnd2lkdGg6MTAwJTsnOw0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICcxMDAlJzsgDQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5tdWx0aXNlbGVjdF9jb250YWluZXJfbWFyZ2luKSAmJiAkZmllbGQtPm11bHRpc2VsZWN0X2NvbnRhaW5lcl9tYXJnaW4gIT0gJycpIHsNCg0KICAgICAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCRmaWVsZC0+bXVsdGlzZWxlY3RfY29udGFpbmVyX21hcmdpbik7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgaWQ9XCJmYl9mbGQteyRpZH1cIiByZi1maWVsZD1cInRydWVcIiBjbGFzcz1cInskZmllbGRfY2xhc3NfbmFtZX0geyR3cmFwcGVyY2xhc3N9IHRhYmxlbW9kZS13cmFwcGVyLWRpdiB0eXBlLXskZmllbGQtPnR5cGV9XCIgc3R5bGU9XCJ3aWR0aDp7JHdpZHRofTsgZGlzcGxheTpibG9jazsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IGZsb2F0OmxlZnQ7IGNsZWFyOmJvdGg7IFwiPiI7DQoNCiAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJ7JGZsb2F0X2Nzc30geyRfd2lkdGhfcGF0Y2h9IFwiID4iOw0KICAgICAgICB9IGVsc2UgeyANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkbWFyZ2luX2JvdHRvbSA9ICIxMCI7DQogICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPnNvcnRhYmxlaXRlbW1hcmdpbmJvdHRvbSkgJiYgJHBhZ2UtPnNvcnRhYmxlaXRlbW1hcmdpbmJvdHRvbSAhPSAiIikgew0KICAgICAgICAgICAgICAgICRtYXJnaW5fYm90dG9tID0gKGludCkkcGFnZS0+c29ydGFibGVpdGVtbWFyZ2luYm90dG9tICsgNDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPm11bHRpc2VsZWN0X2NvbnRhaW5lcl9tYXJnaW4pICYmICRmaWVsZC0+bXVsdGlzZWxlY3RfY29udGFpbmVyX21hcmdpbiAhPSAnJykgew0KDQogICAgICAgICAgICAgICAgJG1hcmdpbl9ib3R0b20gPSBpbnR2YWwoJGZpZWxkLT5tdWx0aXNlbGVjdF9jb250YWluZXJfbWFyZ2luKTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGZsb2F0X2NzcyA9ICJmbG9hdDpsZWZ0OyI7DQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZWxlbWVudHBvcykgJiYgJGVsZW1lbnRwb3MgPT0gIjIiKSB7DQoNCiAgICAgICAgICAgICAgICAkZmxvYXRfY3NzID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ3NlcGFyYXRvcicpIHsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZWxlbWVudHBvcykgJiYgKGludCkkZWxlbWVudHBvcyAhPSAiMCIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAnMTAwJSc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkZmllbGQtPndpZHRoOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgaWYgKChpbnQpJHBhZ2UtPmV4cG9ydG1vZGUgPT0gMykgew0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSAhPSAicXVlcnkiIHx8ICRmaWVsZC0+dHlwZSAhPSAiYmxvY2siKSB7DQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgY2xhc3M9XCJ7JHdyYXBwZXJjbGFzc31cIiBzdHlsZT1cInskZmxvYXRfY3NzfSB3aWR0aDp7JHdpZHRofTsgbWFyZ2luLWJvdHRvbTp7JG1hcmdpbl9ib3R0b219cHg7IFwiID4iOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IGNsYXNzPVwieyR3cmFwcGVyY2xhc3N9XCIgc3R5bGU9XCJ7JGZsb2F0X2Nzc30gd2lkdGg6eyR3aWR0aH07IG1hcmdpbi1ib3R0b206eyRtYXJnaW5fYm90dG9tfXB4OyBcIiA+IjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfSANCg0KICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmNlbnRlcmZvcm0pICYmIChzdHJpbmcpJHBhZ2UtPmNlbnRlcmZvcm0gPT0gIjEiKSB7DQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPnN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRlbGVtZW50cG9zKSAmJiAkZWxlbWVudHBvcyAhPSAiMCIpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHRtcCA9IGV4cGxvZGUoJywnLCAkcGFnZS0+ZGltKTsNCg0KICAgICAgICAgICAgICAgICAgICAkcGFnZV93aWR0aCA9ICR0bXBbMF07DQoNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAoKChpbnQpJHBhZ2UtPnBhZ2VwYWRkaW5nICogMikgKyAkcGFnZV93aWR0aCkgLSAoJGZpZWxkLT5zdHlsZS0+cGFkZGluZ2xlZnQgKyAkZmllbGQtPnN0eWxlLT5wYWRkaW5ncmlnaHQpIC4gJ3B4JzsNCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IHN0eWxlPVwid2lkdGg6IHskZmllbGR3aWR0aH07XCI+IjsNCg0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGVsdDsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJGVsZW1lbnRwb3MpICYmIChpbnQpJGVsZW1lbnRwb3MgIT0gIjAiKSB7DQoNCiAgICAgICAgICAgIGlmICgkZWxlbWVudHBvcyA9PSAiMiIpIHsNCg0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gImNoZWNrYm94IiB8fCAkZmllbGQtPnR5cGUgPT0gInJhZGlvIiB8fCAkZmllbGQtPnR5cGUgPT0gImVjb21tIiB8fCAkZmllbGQtPnR5cGUgPT0gInN1cnZleSIpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IHN0eWxlPVwid2lkdGg6NTAlOyBtYXJnaW46IDAgYXV0bztcIj4iOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJhbGlnbi1pdGVtczogY2VudGVyOyBkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcIj4iOw0KDQogICAgICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgIT0gImJvZHljb3B5IiAmJiAkZmllbGQtPnR5cGUgIT0gInNlY3Rpb25oZWFkZXIiICYmICRmaWVsZC0+dHlwZSAhPSAic2VwYXJhdG9yIikgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IGNsYXNzPVwiZmxleC1ncm91cGluZy1kaXZcIj4iOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPnN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6ICIgLiAkZWxlbWVudHBvcyAuICJweDtcIj4iOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAiYm9keWNvcHkiIHx8ICRmaWVsZC0+dHlwZSA9PSAic2VjdGlvbmhlYWRlciIgJiYgJGZpZWxkLT50eXBlICE9ICJzZXBhcmF0b3IiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRlbHQgLj0gIjxkaXYgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6ICIgLiAkZWxlbWVudHBvcyAuICJweDsgd2lkdGg6MTAwJTtcIj4iOw0KICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZWx0IC49ICI8ZGl2IHN0eWxlPVwibWFyZ2luLXJpZ2h0OiAiIC4gJGVsZW1lbnRwb3MgLiAicHg7IGZsb2F0OnJpZ2h0O1wiPiI7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0gDQoNCg0KICAgICAgICByZXR1cm4gJGVsdDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfbGlfZW5kKCRwYWdlLCAkZmllbGQsICRlbGVtZW50cG9zID0gIjAiKQ0KICAgIHsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHBhZ2UtPmV4cG9ydG1vZGUgPT0gMyAmJiAoJGZpZWxkLT50eXBlID09ICJxdWVyeSIgfHwgJGZpZWxkLT50eXBlID09ICJibG9jayIpKSB7DQoNCiAgICAgICAgICAgIHJldHVybiAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICJxdWVyeSIgJiYgaXNzZXQoJGZpZWxkLT5jcmVhdGVfZWxlbWVudHMpICYmICRmaWVsZC0+Y3JlYXRlX2VsZW1lbnRzICE9IDEpIHsNCg0KICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRlbGVtZW50cG9zKSAmJiAkZWxlbWVudHBvcyAhPSAiMCIpIHsNCg0KICAgICAgICAgICAgaWYgKCRlbGVtZW50cG9zID09ICIyIikgew0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAiY2hlY2tib3giIHx8ICRmaWVsZC0+dHlwZSA9PSAicmFkaW8iIHx8ICRmaWVsZC0+dHlwZSA9PSAiZWNvbW0iIHx8ICRmaWVsZC0+dHlwZSA9PSAic3VydmV5Iikgew0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjwvZGl2PjwhLS0gY2xvc2UgYWxpZ25tZW50IGRpdiAtLT5cbiI7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPC9kaXY+PCEtLSBjbG9zZSBmbGV4IGFsaWdubWVudCBkaXYgLS0+XG4iOw0KDQogICAgICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgIT0gImJvZHljb3B5IiAmJiAkZmllbGQtPnR5cGUgIT0gInNlY3Rpb25oZWFkZXIiICYmICRmaWVsZC0+dHlwZSAhPSAic2VwYXJhdG9yIikgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48L2Rpdj48IS0tIGNsb3NlIGZsZXgtZ3JvdXBpbmctZGl2IC0tPlxuIjsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGVsZW1lbnRwb3MgPT0gIjEiKSB7DQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50cG9zID0gMDsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48L2Rpdj48IS0tIENsb3NlIFJpZ2h0IEFsaWduZWQgRElWIC0tPlxuIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+dGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCkgJiYgKGludCkkcGFnZS0+dGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxKSB7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjwvZGl2PlxuPC9kaXY+XG48IS0tIFRhYmxlIE1vZGUgRm9ybSBGaWVsZCBFbmQgLS0+XG5cbiI7DQogICAgICAgICAgICANCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPC9kaXY+XG48IS0tIFNvcnRhYmxlIEZvcm0gRmllbGQgRW5kIC0tPlxuXG4iOw0KICAgICAgICAgICAgDQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImNsZWFyaW5nLWRpdlwiIHN0eWxlPVwiY2xlYXI6Ym90aDtcIj48L2Rpdj48IS0tIENsZWFyIERJViAtLT5cblxuIjsNCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9saV9lbmRfaHRtbF9vbmx5KCRwYWdlLCAkZmllbGQsICRlbGVtZW50cG9zID0gIjAiKQ0KICAgIHsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGVsZW1lbnRwb3MpICYmICRlbGVtZW50cG9zICE9ICIwIikgew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCg0KICAgICAgICAgICAgaWYgKCRlbGVtZW50cG9zID09ICIyIikgew0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAiY2hlY2tib3giIHx8ICRmaWVsZC0+dHlwZSA9PSAicmFkaW8iIHx8ICRmaWVsZC0+dHlwZSA9PSAiZWNvbW0iIHx8ICRmaWVsZC0+dHlwZSA9PSAic3VydmV5Iikgew0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KDQogICAgICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgIT0gImJvZHljb3B5IiAmJiAkZmllbGQtPnR5cGUgIT0gInNlY3Rpb25oZWFkZXIiICYmICRmaWVsZC0+dHlwZSAhPSAic2VwYXJhdG9yIikgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChpc3NldCgkcGFnZS0+dGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCkgJiYgKGludCkkcGFnZS0+dGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxKSB7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj48L2Rpdj4iOw0KICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiPGRpdiBjbGFzcz1cImNsZWFyaW5nLWRpdlwiIHN0eWxlPVwiY2xlYXI6Ym90aDtcIj48L2Rpdj4iOw0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVQb3NpdGlvbkRpdlN0YXJ0KCRmaWVsZCwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgIA0KDQogICAgICAgICRjb3JkcyA9ICRmaWVsZC0+Y29yZHM7DQogICAgICAgICRpZCA9IGlzc2V0KCRmaWVsZC0+aWQpICYmICRmaWVsZC0+aWQgIT0gIiIgPyAkZmllbGQtPmlkIDogIiI7DQogICAgICAgICR6aW5kZXggPSBpc3NldCgkZmllbGQtPnppbmRleCkgJiYgJGZpZWxkLT56aW5kZXggIT0gIiIgPyAkZmllbGQtPnppbmRleCA6ICIiOw0KICAgICAgICAkd3JhcHBlcmNsYXNzID0gJGZpZWxkLT53cmFwcGVyY2xhc3M7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkdmlzaWJsZSA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT52aXNpYmxlID09ICcwJyA/ICcgZGlzcGxheTpub25lICcgOiAnZGlzcGxheTpibG9jayc7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkemluZGV4ID09IG51bGwgfHwgIWlzX251bWVyaWMoKGludCkkemluZGV4KSkgew0KICAgICAgICAgICAgJHppbmRleCA9IDE7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICBpZiAoJGlkID09ICcnKSB7DQogICAgICAgICAgICAkaWQgPSAkZmllbGQtPnR5cGUgLiAnXycgLiByYW5kKDEwMDAwMCwgOTAwMDAwKTsNCiAgICAgICAgfQ0KDQogICAgICAgICR4eSA9IGV4cGxvZGUoJywnLCAkY29yZHMpOw0KDQogICAgICAgICR4eVsxXSA9ICR4eVsxXTsNCg0KICAgICAgICANCg0KICAgICAgICAkd2lkdGggPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkKSAmJiBpc3NldCgkZmllbGQtPnN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAkd2lkdGggPSAnd2lkdGg6IDEwMCU7JzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyJzsNCg0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICdidWNrZXQnKSB7DQoNCiAgICAgICAgICAgICRmaWVsZF9jbGFzc19uYW1lID0gJ2Zvcm0tZmllbGQtd3JhcHBlci1idWNrZXQnOw0KDQogICAgICAgICAgICAkYnVja2V0X3JlcGVhdGVyX3dpZHRoID0gKHN0cmluZykkZmllbGQtPnJlcGVhdGVyLT53aWR0aDsNCg0KICAgICAgICAgICAgaWYgKCRidWNrZXRfcmVwZWF0ZXJfd2lkdGggIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gKHN0cmluZykkZmllbGQtPnJlcGVhdGVyLT53aWR0aDsNCg0KICAgICAgICAgICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJGZpZWxkLT5yZXBlYXRlci0+d2lkdGgpID09IHRydWUpIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJ3B4Oyc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJzsnOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAnd2lkdGg6JyAuICRmaWVsZC0+YnVja2V0X3dpZHRoOyANCg0KICAgICAgICAgICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJGZpZWxkLT5idWNrZXRfd2lkdGgpID09IHRydWUpIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJ3B4Oyc7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJHdpZHRoIC4gJzsnOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCiAgICAgICAgJGVsdCA9ICIiOw0KDQogICAgICAgIA0KDQogICAgICAgICRlbmFibGVkID0gJyc7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICR2aXNpYmxlX2ZsYWcgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmlzaWJsZSA9PSAnMCcgPyAidmlzaWJsZV9mYWxzZSIgOiAidmlzaWJsZV90cnVlIjsNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGNvbmRpdGlvbmFsICE9IG51bGwpIHsNCiAgICAgICAgICAgICR2aXNpYmxlID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGUgPT0gJzAnID8gJyBkaXNwbGF5Om5vbmU7ICcgOiAnJzsNCiAgICAgICAgICAgICRlbmFibGVkID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGUgPT0gJzAnID8gJ2Rpc2FibGVkPSJkaXNhYmxlZCInIDogJyc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICR2aXNpYmxlID0gJ2Rpc3BsYXk6YmxvY2s7JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWx0IC49IDw8PEVPRg0KDQo8P3BocCBcJHZpc2libGUgPSAneyR2aXNpYmxlfSc7IFwkZW5hYmxlZD0gJ3skZW5hYmxlZH0nOyA/Pg0KDQpFT0Y7DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkY29uZGl0aW9uYWwtPnZpc2libGVfZmllbGQpICYmIGlzc2V0KCRjb25kaXRpb25hbC0+dmlzaWJsZV92YWx1ZSkpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGVfZmllbGQgIT0gIiIgJiYgKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGVfdmFsdWUgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRfZmxkID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGVfZmllbGQ7DQoNCiAgICAgICAgICAgICAgICAkcmV2ZXJzZSA9IGlzc2V0KCRjb25kaXRpb25hbC0+dmlzaWJsZV9yZXZlcnNlKSA/IChpbnQpJGNvbmRpdGlvbmFsLT52aXNpYmxlX3JldmVyc2UgOiAwOw0KDQogICAgICAgICAgICAgICAgJHZhbCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGVfdmFsdWUsIDQpOyANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKCRjb25kaXRpb25hbC0+dmlzaWJsZV92YWx1ZSA9PSAkdmFsKSB7DQogICAgICAgICAgICAgICAgICAgICR2YWwgPSBzdHJfcmVwbGFjZSgiJyIsICJcJyIsICR2YWwpOw0KICAgICAgICAgICAgICAgICAgICAkdmFsID0gIiciIC4gJHZhbCAuICInIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICBpZiAoJHJldmVyc2UgPT0gMCkgew0KDQogICAgICAgICAgICAgICAgICAgICRlbHQgLj0gPDw8RU9GDQpcclxuPD9waHANCmlmKGlzc2V0KFwkX1NFU1NJT05bJ3skX2ZsZH0nXSkpew0KDQoJXCR2YWxfY2hlY2sgPSB7JHZhbH07DQoNCglpZihpc19hcnJheShcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCgkNCgkJaWYoaW5fYXJyYXkoXCR2YWxfY2hlY2ssIFwkX1NFU1NJT05bJ3skX2ZsZH0nXSkpDQoJCQlcJHZpc2libGUgPSAnZGlzcGxheTpibG9jazsnOw0KCQ0KCX0gZWxzZSB7DQoNCgkJaWYoXCRfU0VTU0lPTlsneyRfZmxkfSddID09IFwkdmFsX2NoZWNrKXsNCgkJCVwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQoJCX0gZWxzZSB7DQoJCQlcJHZpc2libGUgPSAnZGlzcGxheTpub25lOyc7DQoJCX0NCgkJCQkNCgl9DQp9DQo/Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNClxyXG48P3BocA0KaWYoaXNzZXQoXCRfU0VTU0lPTlsneyRfZmxkfSddKSl7DQoJCQkJCQ0KCVwkdmFsX2NoZWNrID0geyR2YWx9Ow0KCQkJCQkNCglpZihpc19hcnJheShcJF9TRVNTSU9OWyd7JF9mbGR9J10pKXsNCgkJCQkJDQoJCWlmKCFpbl9hcnJheShcJHZhbF9jaGVjaywgXCRfU0VTU0lPTlsneyRfZmxkfSddKSkNCgkJCVwkdmlzaWJsZSA9ICdkaXNwbGF5OmJsb2NrOyc7DQoJCQkJCQ0KCX0gZWxzZSB7DQoJCQkJCQ0KCQlpZihcJF9TRVNTSU9OWyd7JF9mbGR9J10gIT0gXCR2YWxfY2hlY2spew0KCQkJXCR2aXNpYmxlID0gJ2Rpc3BsYXk6YmxvY2s7JzsNCgkJfSBlbHNlIHsNCgkJCVwkdmlzaWJsZSA9ICdkaXNwbGF5Om5vbmU7JzsNCgkJfQ0KCQkJCQkNCgl9DQp9DQo/Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfSANCg0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIGlmICgkeHlbMF0gPT0gJ05VTExfUkVTUE9OU0lWRScpIHsNCg0KICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNCg0KPCEtLSB+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4gLS0+DQo8IS0tIFBPU0lUSU9ORUQgRk9STSBGSUVMRCBTVEFSVCAtLT4NCjwhLS0gfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+IC0tPg0KCQkJDQo8ZGl2IGlkPSJmYl9mbGQteyRpZH0iIHJmLWZpZWxkPSJ0cnVlIiBjbGFzcz0ieyRmaWVsZF9jbGFzc19uYW1lfSB7JHdyYXBwZXJjbGFzc30gdHlwZS17JGZpZWxkLT50eXBlfSAiIHN0eWxlPSI8P3BocCBlY2hvIFwkdmlzaWJsZTsgXCR7JHZpc2libGVfZmxhZ307ID8+IGZsb2F0OmxlZnQ7IHdpZHRoOnskeHlbMV19OyBwYWRkaW5nLXRvcDoxMHB4OyB6LWluZGV4OnskemluZGV4fTsgIj4NCg0KRU9GOw0KICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgJHdpZHRoID0gIndpZHRoOjEwMCU7IjsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmZpZWxkd2lkdGgpKQ0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJGZpZWxkLT5maWVsZHdpZHRoIC4gJzsnOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAnYm9keWNvcHknIHx8ICRmaWVsZC0+dHlwZSA9PSAnc2VjdGlvbmhlYWRlcicpIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkZmllbGQtPnN0eWxlLT5maWVsZHdpZHRoIC4gJzsnOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRtYXJnaW5fYm90dG9tID0gJ21hcmdpbi1ib3R0b206MTVweDsnOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPmJvdHRvbW1hcmdpbikgJiYgJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+Ym90dG9tbWFyZ2luICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKGlzX251bWVyaWMoKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5ib3R0b21tYXJnaW4pKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkbWFyZ2luX2JvdHRvbSA9ICdtYXJnaW4tYm90dG9tOicgLiAkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5ib3R0b21tYXJnaW4gLiAncHgnOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNCjwhLS0gQnVja2V0IEl0ZW0gLSBSZXNwb25zaXZlIEZvcm0gRmllbGQgU3RhcnQgLS0+DQoNCjxkaXYgaWQ9ImZiX2ZsZC17JGlkfSIgcmYtZmllbGQ9InRydWUiIGNsYXNzPSJyZXNwb25zaXZlLWJ1Y2tldC1pdGVtIHskZmllbGRfY2xhc3NfbmFtZX0geyR3cmFwcGVyY2xhc3N9IHR5cGUteyRmaWVsZC0+dHlwZX0iIHN0eWxlPSI8P3BocCBlY2hvIFwkdmlzaWJsZTsgXCR7JHZpc2libGVfZmxhZ307ID8+IGZsb2F0OmxlZnQ7IHskd2lkdGh9IHotaW5kZXg6eyR6aW5kZXh9OyB7JG1hcmdpbl9ib3R0b219Ij4NCgkJCQkNCgkJCQ0KRU9GOw0KICAgICAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZ1bGx3aWR0aCkgJiYgJHBhZ2UtPmZ1bGx3aWR0aCA9PSAiMSIpIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOiAxMDAlOyc7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICdzZXBhcmF0b3InKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkZmllbGQtPndpZHRoIC4gJzsnOw0KICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNCg0KPCEtLSB+fn5+fn5+fn5+fn5+fn5+IC0tPg0KPCEtLSBGT1JNIEZJRUxEIFNUQVJUIC0tPg0KPCEtLSB+fn5+fn5+fn5+fn5+fn5+IC0tPg0KDQo8ZGl2IGlkPSJmYl9mbGQteyRpZH0iIHJmLWZpZWxkPSJ0cnVlIiBjbGFzcz0ieyRmaWVsZF9jbGFzc19uYW1lfSB7JHdyYXBwZXJjbGFzc30gdHlwZS17JGZpZWxkLT50eXBlfSIgc3R5bGU9Ijw/cGhwIGVjaG8gXCR2aXNpYmxlOyBcJHskdmlzaWJsZV9mbGFnfTsgPz4gcG9zaXRpb246YWJzb2x1dGU7IGxlZnQ6eyR4eVswXX1weDsgdG9wOnskeHlbMV19cHg7IHskd2lkdGh9IHotaW5kZXg6eyR6aW5kZXh9OyAiPg0KDQoNCkVPRjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0NCg0KDQogICAgDQogICAgZnVuY3Rpb24gY3JlYXRlUG9zaXRpb25EaXZTdGFydF9odG1sX29ubHkoJGZpZWxkKQ0KICAgIHsNCg0KICAgICAgICANCg0KICAgICAgICAkY29yZHMgPSAkZmllbGQtPmNvcmRzOw0KICAgICAgICAkaWQgPSBpc3NldCgkZmllbGQtPmlkKSAmJiAkZmllbGQtPmlkICE9ICIiID8gJGZpZWxkLT5pZCA6ICIiOw0KICAgICAgICAkemluZGV4ID0gaXNzZXQoJGZpZWxkLT56aW5kZXgpICYmICRmaWVsZC0+emluZGV4ICE9ICIiID8gJGZpZWxkLT56aW5kZXggOiAiIjsNCiAgICAgICAgJHdyYXBwZXJjbGFzcyA9ICRmaWVsZC0+d3JhcHBlcmNsYXNzOw0KICAgICAgICAkY29uZGl0aW9uYWwgPSAkZmllbGQtPmNvbmRpdGlvbmFsOw0KDQogICAgICAgICR2aXNpYmxlID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGUgPT0gJzAnID8gJyBkaXNwbGF5Om5vbmUgJyA6ICdkaXNwbGF5OmJsb2NrJzsNCg0KICAgICAgICBpZiAoJHppbmRleCA9PSBudWxsIHx8ICFpc19udW1lcmljKChpbnQpJHppbmRleCkpIHsNCiAgICAgICAgICAgICR6aW5kZXggPSAxOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRpZCA9PSAnJykgew0KICAgICAgICAgICAgJGlkID0gcmFuZCgxMDAwMDAsIDkwMDAwMCk7DQogICAgICAgIH0NCiAgICAgICAgJHh5ID0gZXhwbG9kZSgnLCcsICRjb3Jkcyk7DQoNCiAgICAgICAgJHh5WzFdID0gJHh5WzFdOw0KDQogICAgICAgICR3aWR0aCA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQpICYmIGlzc2V0KCRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUpICYmIChpbnQpJGZpZWxkLT5zdHlsZS0+YmFubmVybW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDogMTAwJTsnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyJzsNCg0KDQogICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ2J1Y2tldCcpIHsNCg0KICAgICAgICAgICAgJGZpZWxkX2NsYXNzX25hbWUgPSAnZm9ybS1maWVsZC13cmFwcGVyLWJ1Y2tldCc7DQoNCiAgICAgICAgICAgICRidWNrZXRfcmVwZWF0ZXJfd2lkdGggPSAoc3RyaW5nKSRmaWVsZC0+cmVwZWF0ZXItPndpZHRoOw0KDQogICAgICAgICAgICBpZiAoJGJ1Y2tldF9yZXBlYXRlcl93aWR0aCAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAoc3RyaW5nKSRmaWVsZC0+cmVwZWF0ZXItPndpZHRoOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzX251bWVyaWMoKHN0cmluZykkZmllbGQtPnJlcGVhdGVyLT53aWR0aCkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkd2lkdGggLiAncHg7JzsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkd2lkdGggLiAnOyc7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJGZpZWxkLT5idWNrZXRfd2lkdGg7IA0KDQogICAgICAgICAgICAgICAgaWYgKGlzX251bWVyaWMoKHN0cmluZykkZmllbGQtPmJ1Y2tldF93aWR0aCkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkd2lkdGggLiAncHg7JzsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAkd2lkdGggLiAnOyc7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICAkZWx0ID0gIiI7DQoNCiAgICAgICAgJGVuYWJsZWQgPSAnJzsNCg0KICAgICAgICBpZiAoJGNvbmRpdGlvbmFsICE9IG51bGwpIHsNCiAgICAgICAgICAgICR2aXNpYmxlID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGUgPT0gJzAnID8gJyBkaXNwbGF5Om5vbmU7ICcgOiAnJzsNCiAgICAgICAgICAgICRlbmFibGVkID0gKHN0cmluZykkY29uZGl0aW9uYWwtPnZpc2libGUgPT0gJzAnID8gJ2Rpc2FibGVkPSJkaXNhYmxlZCInIDogJyc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICR2aXNpYmxlID0gJ2Rpc3BsYXk6YmxvY2s7JzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgaWYgKCR4eVswXSA9PSAnTlVMTF9SRVNQT05TSVZFJykgew0KDQogICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KPGRpdiBpZD0iZmJfZmxkLXskaWR9IiByZi1maWVsZD0idHJ1ZSIgY2xhc3M9InskZmllbGRfY2xhc3NfbmFtZX0geyR3cmFwcGVyY2xhc3N9IHR5cGUteyRmaWVsZC0+dHlwZX0iIHN0eWxlPSJmbG9hdDpsZWZ0OyB3aWR0aDp7JHh5WzFdfTsgcGFkZGluZy10b3A6MTBweDsgei1pbmRleDp7JHppbmRleH07ICI+DQpFT0Y7DQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRidWNrZXRfbm9kZSkgJiYgJGJ1Y2tldF9ub2RlICE9ICIiICYmIChpbnQpJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+cmVzcG9uc2l2ZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICAgICAkd2lkdGggPSAid2lkdGg6MTAwJTsiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZmllbGR3aWR0aCkpDQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkZmllbGQtPmZpZWxkd2lkdGggLiAnOyc7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICdib2R5Y29weScgfHwgJGZpZWxkLT50eXBlID09ICdzZWN0aW9uaGVhZGVyJykgew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAnd2lkdGg6JyAuICRmaWVsZC0+c3R5bGUtPmZpZWxkd2lkdGggLiAnOyc7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJG1hcmdpbl9ib3R0b20gPSAnbWFyZ2luLWJvdHRvbToxNXB4Oyc7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+Ym90dG9tbWFyZ2luKSAmJiAkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5ib3R0b21tYXJnaW4gIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoaXNfbnVtZXJpYygoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPmJvdHRvbW1hcmdpbikpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRtYXJnaW5fYm90dG9tID0gJ21hcmdpbi1ib3R0b206JyAuICRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPmJvdHRvbW1hcmdpbiAuICdweCc7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KPGRpdiBpZD0iZmJfZmxkLXskaWR9IiByZi1maWVsZD0idHJ1ZSIgY2xhc3M9InskZmllbGRfY2xhc3NfbmFtZX0geyR3cmFwcGVyY2xhc3N9IHR5cGUteyRmaWVsZC0+dHlwZX0iIHN0eWxlPSJmbG9hdDpsZWZ0OyB7JHdpZHRofSB6LWluZGV4OnskemluZGV4fTsgeyRtYXJnaW5fYm90dG9tfSI+DQpFT0Y7DQogICAgICAgICAgICB9IGVsc2UgeyANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkcGFnZS0+ZnVsbHdpZHRoKSAmJiAkcGFnZS0+ZnVsbHdpZHRoID09ICIxIikgew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAnd2lkdGg6IDEwMCU7JzsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgPT0gJ3NlcGFyYXRvcicpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAnd2lkdGg6JyAuICRmaWVsZC0+d2lkdGggLiAnOyc7DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICAkZWx0IC49IDw8PEVPRg0KPGRpdiBpZD0iZmJfZmxkLXskaWR9IiByZi1maWVsZD0idHJ1ZSIgY2xhc3M9InskZmllbGRfY2xhc3NfbmFtZX0geyR3cmFwcGVyY2xhc3N9IHR5cGUteyRmaWVsZC0+dHlwZX0iIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTsgbGVmdDp7JHh5WzBdfXB4OyB0b3A6eyR4eVsxXX1weDsgeyR3aWR0aH0gei1pbmRleDp7JHppbmRleH07ICI+DQpFT0Y7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsdDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVQb3NpdGlvbkRpdkVuZCgpDQogICAgew0KICAgICAgICByZXR1cm4gIlxuPC9kaXY+XG48IS0tIFBvc2l0aW9uZWQgRm9ybSBGaWVsZCBFbmQgLS0+XG5cbiI7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZVBvc2l0aW9uRGl2RW5kX2h0bWxfb25seSgpDQogICAgew0KICAgICAgICByZXR1cm4gIjwvZGl2PjwhLS0gUG9zaXRpb25lZCAoSFRNTCBPbmx5KSBGb3JtIEZpZWxkIEVuZCAtLT4iOw0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVUYWJsZU1vZGVMYWJlbCgkZWxlbWVudCwgJHRhYmxlbW9kZSkNCiAgICB7DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCiAgICAgICAgICAgICR0bXAgPSA8PDxFT1QNCg0KPGRpdiBzdHlsZT0id2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7Ij4NCgl7JGVsZW1lbnR9DQo8L2Rpdj4NCkVPVDsNCiAgICAgICAgICAgIHJldHVybiAkdG1wOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgICAgICB9DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZVRhYmxlTW9kZUVsZW1lbnQoJGVsZW1lbnQsICR0YWJsZW1vZGUpDQogICAgew0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxKSB7DQogICAgICAgICAgICAkdG1wID0gPDw8RU9UDQoNCjxkaXYgc3R5bGU9IndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsiPg0KCXskZWxlbWVudH0NCjwvZGl2Pg0KDQoNCkVPVDsNCiAgICAgICAgICAgIHJldHVybiAkdG1wOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgICAgICB9DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2FqYXgoJGZpZWxkLCAkam9icGF0aCwgJGJpbmRfY291bnQsICRiaW5kX2luZGV4KQ0KICAgIHsNCiAgICAgICAgDQogICAgICAgICR0aGlzLT51bS0+cHVsbEN1c3RvbUNvbm5lY3RvckZpbGUoKHN0cmluZykkZmllbGQtPmRiY29ubmVjdG9yKTsNCg0KDQogICAgICAgIA0KICAgICAgICAkcGFnZV9jb2RlID0gIiI7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICR0bXAgPSBhcnJheSgpOw0KICAgICAgICBmb3JlYWNoICgkZmllbGQtPnNlbGVjdGl0ZW1zIGFzICRzKSB7DQogICAgICAgICAgICAkcyA9IChhcnJheSkkczsNCiAgICAgICAgICAgIGlmIChpc19hcnJheSgkcykpIHsNCiAgICAgICAgICAgICAgICAkdG1wW10gPSAkczsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGpzb25fZWxlbWVudHMgPSAkdGhpcy0+dW0tPnBocF9qc29uX2VuY29kZSgkdG1wKTsNCg0KICAgICAgICANCiAgICAgICAgJGZpcnN0X2JvdW5kX2ZpZWxkID0gaXNzZXQoJHRtcFswXVsnZmllbGRCaW5kaW5nJ10pID8gJHRtcFswXVsnZmllbGRCaW5kaW5nJ10gOiAnJzsNCiAgICAgICAgJHNlY29uZF9ib3VuZF9maWVsZCA9IGlzc2V0KCR0bXBbMV1bJ2ZpZWxkQmluZGluZyddKSA/ICR0bXBbMV1bJ2ZpZWxkQmluZGluZyddIDogJyc7DQogICAgICAgICR0aGlyZF9ib3VuZF9maWVsZCA9IGlzc2V0KCR0bXBbMl1bJ2ZpZWxkQmluZGluZyddKSA/ICR0bXBbMl1bJ2ZpZWxkQmluZGluZyddIDogJyc7DQogICAgICAgICRmb3VydGhfYm91bmRfZmllbGQgPSBpc3NldCgkdG1wWzNdWydmaWVsZEJpbmRpbmcnXSkgPyAkdG1wWzNdWydmaWVsZEJpbmRpbmcnXSA6ICcnOw0KICAgICAgICAkZmlmdGhfYm91bmRfZmllbGQgPSBpc3NldCgkdG1wWzRdWydmaWVsZEJpbmRpbmcnXSkgPyAkdG1wWzRdWydmaWVsZEJpbmRpbmcnXSA6ICcnOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5hamF4X2NvZGVfYmVmb3JlX3F1ZXJ5KSkgew0KICAgICAgICAgICAgJGZpZWxkLT5hamF4X2NvZGVfYmVmb3JlX3F1ZXJ5ID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPmFqYXhfY29kZV9hZnRlcl9xdWVyeSkpIHsNCiAgICAgICAgICAgICRmaWVsZC0+YWpheF9jb2RlX2FmdGVyX3F1ZXJ5ID0gIiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkYWpheF9wcm9jZXNzaW5nX21vZGUgPSAnc3RkJzsNCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5hamF4X3Byb2Nlc3NpbmdfbW9kZSkgew0KICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICRhamF4X3Byb2Nlc3NpbmdfbW9kZSA9ICdzdGQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICRhamF4X3Byb2Nlc3NpbmdfbW9kZSA9ICdwcm9jJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkYWpheF9lcnJvcl9tb2RlID0gJ2ZhbHNlJzsNCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5hamF4X2Vycm9yX21vZGUpIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkYWpheF9lcnJvcl9tb2RlID0gJ3RydWUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICRhamF4X2Vycm9yX21vZGUgPSAnZmFsc2UnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGFqYXhfY2xlYXJfdGV4dF9maWVsZHMgPSAidHJ1ZSI7DQoNCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+YWpheF9jbGVhcl90ZXh0X2ZpZWxkcykgew0KICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICRhamF4X2NsZWFyX3RleHRfZmllbGRzID0gJ3RydWUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICRhamF4X2NsZWFyX3RleHRfZmllbGRzID0gJ2ZhbHNlJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF8yKSkgew0KICAgICAgICAgICAgJGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF8yID0gJyc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkXzMpKSB7DQogICAgICAgICAgICAkZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkXzMgPSAnJzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGRfNCkpIHsNCiAgICAgICAgICAgICRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGRfNCA9ICcnOw0KICAgICAgICB9DQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF81KSkgew0KICAgICAgICAgICAgJGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF81ID0gJyc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRsaWJyYXJ5ID0gaXNzZXQoJGZpZWxkLT5hamF4X3Byb2Nlc3NpbmdfbGlicmFyeSkgPyAkZmllbGQtPmFqYXhfcHJvY2Vzc2luZ19saWJyYXJ5IDogIjEiOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJGxpc3RlbmVycyA9ICIiOw0KDQogICAgICAgIGZvciAoJF9pID0gMDsgJF9pIDwgJGJpbmRfY291bnQ7ICRfaSsrKSB7DQogICAgICAgICAgICAkbGlzdGVuZXJzIC49ICJcdGhhbmRsZV9GQl9BSkFYX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KCk7XHJcbiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoJGxpYnJhcnkgPT0gIjAiKSB7IA0KDQogICAgICAgICAgICAkcGFnZV9jb2RlIC49IDw8PEVPRg0KDQo8ZGl2IHN0eWxlPSJkaXNwbGF5Om5vbmU7IiBpZD0ibG9hZC1zdGF0dXMteyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0iIGNsYXNzPSJmYi1hamF4LWxvYWRlciI+TG9hZGluZy4uLjwvZGl2Pg0KCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KLy8gUmFja0Zvcm1zIEFKQVggQ29kZSAtIGpRdWVyeQ0KDQppZih0eXBlb2YoXCRqKSAhPSAidW5kZWZpbmVkIikgew0KCSQgPSBcJGo7DQp9DQoNCi8vIENhbGwgT24gTG9hZC4uLg0KJChmdW5jdGlvbigpew0KICAgIGJpbmRBamF4X3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KCk7DQp9KTsNCg0KLy8gT3IgQ2FsbCBGcm9tIEFueXdoZXJlLg0KZnVuY3Rpb24gYmluZEFqYXhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKSB7DQoNCgkvLyBiaW5kIGV2ZW50IGxpc3RlbmVyKHMpDQoNCgkvLyB3aGF0IHR5cGUgb2YgZWxlbWVudCBpcyB0aGlzIGNoZWNrDQoJaXNfc2VsZWN0X29yX3RleHQgPSBmYWxzZTsNCglpc19vdGhlciA9IGZhbHNlOw0KDQoJaXNfc2VsZWN0X29yX3RleHQgPSAkKCcjeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9JykubGVuZ3RoOw0KDQoJaWYoaXNfc2VsZWN0X29yX3RleHQgPT0gMCl7DQoJCWlzX290aGVyID0gdHJ1ZTsNCgl9IGVsc2Ugew0KCQlpc19zZWxlY3Rfb3JfdGV4dCA9IHRydWU7DQoJfQ0KDQoJaWYoaXNfc2VsZWN0X29yX3RleHQpew0KCQkkKCcjeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9JykueyR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFqYXhFdmVudCgkZmllbGQtPmFqYXhfZXZlbnQpfShmdW5jdGlvbigpew0KICAgICAgICAgICAgaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKTsNCgkJfSk7DQoJfQ0KCQ0KCWlmKGlzX290aGVyKXsNCgkJeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH1faXRlbXMgPSAkKCcjZmJfZmxkLXskZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfSBJTlBVVCcpOw0KCQ0KCQkvLyBiaW5kIGV2ZW50IGxpc3RlbmVycw0KCQl7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fV9pdGVtcy5lYWNoKGZ1bmN0aW9uKHQpew0KCQkNCgkJCSQodGhpcykuYmluZCAoDQoJCQkJInskdGhpcy0+dHJhbnNsYXRlQ29uZGl0aW9uYWxBamF4RXZlbnQoJGZpZWxkLT5hamF4X2V2ZW50KX0iLA0KCQkJCWZ1bmN0aW9uKCl7DQoJCQkJCWhhbmRsZV9GQl9BSkFYX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KCk7DQoJCQkJfQ0KCQkJDQoJCQkpDQoJCQ0KLy8gCQkJdC57JHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsQWpheEV2ZW50KCRmaWVsZC0+YWpheF9ldmVudCl9KGZ1bmN0aW9uKCl7DQovLyAJCQkJaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKTsNCi8vIAkJCX0pOw0KCQl9KTsNCgl9DQoNCiAgICAvLyBldmFsIGl0ZW1zDQogICAganNvbl97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fSA9ICRqc29uX2VsZW1lbnRzOw0KCWV2YWwoanNvbl97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fSk7DQoJDQoJLy8gQ2FsbCBmb3IgcGFnZSBsb2FkIGlmIGEgdmFsdWUgaGFzIGJlZW4gc2VsZWN0ZWQuDQoJaWYoJCgiI3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfSIpLnZhbCgpICE9ICIiKXsNCgkJaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKTsNCgl9DQogICAgDQp9Ow0KDQovLyBmZXRjaCBhIGR5bmFtaWMgZmllbGQgdmFsdWUNCmZ1bmN0aW9uIGZldGNoX2FqYXhfYXJnKGZpZWxkKXsNCg0KCWlmKGZpZWxkID09ICIiKXsNCgkJcmV0dXJuICIiOw0KCX0NCg0KCS8vIHdoYXQgdHlwZSBvZiBlbGVtZW50IGlzIHRoaXMgY2hlY2sNCglpc19zZWxlY3Rfb3JfdGV4dCA9IGZhbHNlOw0KCWlzX290aGVyID0gZmFsc2U7DQoNCglpc19zZWxlY3Rfb3JfdGV4dCA9ICQoJyMnICsgZmllbGQpLmxlbmd0aDsNCg0KCWlmKGlzX3NlbGVjdF9vcl90ZXh0ID09IDApew0KCQlpc19vdGhlciA9IHRydWU7DQoJfSBlbHNlIHsNCgkJaXNfc2VsZWN0X29yX3RleHQgPSB0cnVlOw0KCX0NCg0KCWlmKGlzX3NlbGVjdF9vcl90ZXh0KXsNCgkJcmV0dXJuICQoJyMnICsgZmllbGQpLnZhbCgpOw0KCX0NCgkNCglpZihpc19vdGhlcil7DQoJCXZhciBpdGVtcyA9ICQoJyNmYl9mbGQtJyArIGZpZWxkICsgJyBJTlBVVCcpOw0KDQoJCXZhciB2YWwgPSAnJzsNCgkJDQoJCS8vIGJpbmQgZXZlbnQgbGlzdGVuZXJzDQoJCSQoaXRlbXMpLmVhY2goZnVuY3Rpb24odCwgZWx0KXsNCgkJCWlmKCQodGhpcykucHJvcCgnY2hlY2tlZCcpKXsNCgkJCQl2YWwgPSAkKHRoaXMpLnZhbCgpOw0KCQkJfQ0KCQl9KTsNCg0KCQlyZXR1cm4gdmFsOw0KCX0JDQp9Ow0KDQpmdW5jdGlvbiBoYW5kbGVfRkJfQUpBWF97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fSgpew0KCQ0KCS8vIHVzZXIgY29kZSBiZWZvcmUgcXVlcnkNCgl7JGZpZWxkLT5hamF4X2NvZGVfYmVmb3JlX3F1ZXJ5fQ0KCQ0KCS8vIGNvbGxlY3QgcGFyYW1zDQoJdmFyIHBhcmFtcyA9IHsNCgkJYXJnMTogZmV0Y2hfYWpheF9hcmcoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfScpLA0KCQlhcmcyOiBmZXRjaF9hamF4X2FyZygneyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGRfMn0nKSwNCgkJYXJnMzogZmV0Y2hfYWpheF9hcmcoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkXzN9JyksDQoJCWFyZzQ6IGZldGNoX2FqYXhfYXJnKCd7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF80fScpLA0KCQlhcmc1OiBmZXRjaF9hamF4X2FyZygneyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGRfNX0nKSwNCgkJYWN0aW9uOiAneyRhamF4X3Byb2Nlc3NpbmdfbW9kZX0nCQ0KCX07DQoJDQoJY2xlYXJfdGV4dF9maWVsZHMgPSB7JGFqYXhfY2xlYXJfdGV4dF9maWVsZHN9Ow0KDQoJJC5hamF4KHsNCgkJdHlwZTogIlBPU1QiLA0KCQl1cmw6ICdsaWIvYWpheC9mYl9hamF4X3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9LnBocCcsDQoJCWRhdGE6IHBhcmFtcywNCgkJYmVmb3JlU2VuZDogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKXsNCgkJCSQoJ2xvYWQtc3RhdHVzLXskZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9Jykuc2hvdygpOw0KCQl9LA0KCQllcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKXsNCgkJCWVycm9yX21vZGUgPSB7JGFqYXhfZXJyb3JfbW9kZX07DQoJCQ0KCQkJaWYoZXJyb3JfbW9kZSl7DQoJCQkJbWVzc2FnZSA9ICdBSkFYIEV4Y2VwdGlvbjogJyArIGVycm9yVGhyb3duOw0KCQkJCW1lc3NhZ2UgKz0gJ1xcblxcbllvdSBtYXkgd2lzaCB0byBlbmFibGUgeW91ciBicm93c2VycyBDb25zb2xlIHRvIHNlZSBhIG1vcmUgZGV0YWlsZWQgcmVhc29uIHdoeSB0aGlzIGVycm9yIG9jY3VycmVkLiAnOw0KCQkJCW1lc3NhZ2UgKz0gJ0ZvciBtb3N0IGJyb3dzZXJzIHRoaXMgaXMgdGhlIEYxMiBrZXksIG9yIGlmIGluIEZpcmVmb3ggd2l0aCBGaXJlYnVnIGluc3RhbGxlZCwgYnkgdXNpbmcgRmlyZWJ1Z1wncyBDb25zb2xlLic7DQoJCQkJbWVzc2FnZSArPSAnXFxuXFxuRm9ybSBDcmVhdG9yczogVGhpcyBjbGFzcyBvZiBpc3N1ZSB1c3VhbGx5IGluZGljYXRlcyBhIGRhdGFiYXNlIGVycm9yLic7DQoJCQkJbWVzc2FnZSArPSAnXFxuXFxuUGxlYXNlIGNoZWNrIHlvdXIgU1FMIENvZGUgYmxvY2sgdG8gZW5zdXJlIGEgcHJvcGVyIHF1ZXJ5LCBhbmQgaWYgYmVpbmcgdXNlZCwgdGhlIERhdGEgU291cmNlIHByb3BlcnRpZXMgZm9yIHByb3BlciBjb25uZWN0aW9uIGRldGFpbHMuJzsNCgkJCQlhbGVydChtZXNzYWdlKTsgLy8gZXJyb3IsIGV4Y2VwdGlvbiBtZXNzYWdlDQoJCQl9DQoJCX0NCgl9KQ0KCS5kb25lKGZ1bmN0aW9uKCByZXMgKSB7DQoJCQkNCgkJCWlmKHJlcyA9PT0gdW5kZWZpbmVkKQ0KCQkJCXJldHVybjsNCgkJCQkNCgkJCSQoJyNsb2FkLXN0YXR1cy17JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fScpLmhpZGUoKTsNCg0KCQkJJChqc29uX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KS5lYWNoKGZ1bmN0aW9uKGlkeCwgZil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICAgICAvLw0KCQkJCS8vIENsZWFyIEFueSBSZXF1ZXN0ZWQgRmllbGRzLg0KCQkJCS8vDQoJCQkJDQoJCQkJaWYoZi5maWVsZENsZWFyICE9ICIiKXsNCgkJCQkJDQoJCQkJCXZhciB0eXBlID0gIiI7DQoNCgkJCQkJaWYoJCgiIyIgKyBmLmZpZWxkQ2xlYXIpICYmICQoIiMiICsgZi5maWVsZENsZWFyKS5sZW5ndGggIT0gMCl7DQoJCQkJCQkNCgkJCQkJCXZhciBpdGVtcyA9ICQoIiMiICsgZi5maWVsZENsZWFyKS5tYXAoZnVuY3Rpb24oaW5kZXgsIGVsbSkgew0KCQkJCQkJCXJldHVybiB7bmFtZTogZWxtLm5hbWUsIHR5cGU6ZWxtLnR5cGUsIHZhbHVlOiAkKGVsbSkudmFsKCl9Ow0KCQkJCQkJfSk7DQoNCgkJCQkJCXZhciB0eXBlID0gaXRlbXNbMF0udHlwZTsNCgkJCQkJCQ0KCQkJCQkJLy8gU3VwcG9ydCBGb3IgQUpBWCBVcGRhdGVzIE9uIEFsbCBGaWVsZHMNCgkJCQkJCWlmKHR5cGUgPT09IHVuZGVmaW5lZCl7DQoJCQkJCQkJdmFyIHR5cGUgPSAnZGlzcGxheS1lbGVtZW50JzsNCgkJCQkJCX0NCg0KCQkJCQl9IGVsc2Ugew0KDQoJCQkJCQkvLyBjaGVja2JveGVzLCByYWRpbywgY2FsZW5kYXINCgkJCQkJCQ0KCQkJCQkJaWYoJCgiIyIgKyAiZGF0ZS0iICsgZi5maWVsZENsZWFyICsgJy0xJykgJiYgJCgiIyIgKyAiZGF0ZS0iICsgZi5maWVsZENsZWFyICsgIi0xIikubGVuZ3RoICE9IDApew0KCQkJCQkJCQ0KCQkJCQkJCS8vIENhbGVuZGFyIGl0ZW0NCgkJCQkJCQl2YXIgdHlwZSA9ICd0ZXh0JzsNCgkJCQkJCQlmLmZpZWxkQ2xlYXIgPSAiZGF0ZS0iICsgZi5maWVsZENsZWFyICsgIi0xIjsNCgkJCQkJCQ0KCQkJCQkJfSBlbHNlIHsNCgkJCQkJCQ0KCQkJCQkJCXZhciBpID0gMDsgDQoJCQkJCQkJDQoJCQkJCQkJLy8gc2V0IHRoZSBpbmRleCBmb3IgdGhlIGl0ZW1zIHRvIGFkZA0KCQkJCQkJCXdoaWxlKCQoIiMiICsgZi5maWVsZENsZWFyICsgaSkubGVuZ3RoICE9IDAgfHwgaSA+IDEwMDApew0KCQkJCQkJCQlpKys7DQoJCQkJCQkJfQ0KCQkJCQkJCQ0KCQkJCQkJCS8vIEJ1aWxkIDcyNyAtIGdldCBmaWVsZCB0eXBlIGV2ZW4gaWYgbm8gaXRlbXMgYXJlIHByZXNlbnQNCgkJCQkJCQlpZigkKCIjIiArIGYuZmllbGRDbGVhciArIChpIC0gMSkpLmxlbmd0aCAhPSAwKXsNCgkJCQkJCQkNCgkJCQkJCQkJaXRlbXMgPSAkKCIjIiArIGYuZmllbGRDbGVhciArIChpIC0gMSkpLm1hcChmdW5jdGlvbihpbmRleCwgZWxtKSB7DQoJCQkJCQkJCQlyZXR1cm4ge25hbWU6IGVsbS5uYW1lLCB0eXBlOmVsbS50eXBlLCB2YWx1ZTogJChlbG0pLnZhbCgpfTsNCgkJCQkJCQkJfSk7DQoJCQkJCQkJDQoJCQkJCQkJCXR5cGUgPSBpdGVtc1swXS50eXBlOw0KCQkJCQkJCQkNCgkJCQkJCQl9IGVsc2Ugew0KDQoJCQkJCQkJCS8vIG5vIGl0ZW1zIHNldCwgc28gZ2V0IHRoZSB0eXBlIGZyb20gdGhlIGNvbHVtbnMgY2xhc3MgDQoJCQkJCQkJCQ0KCQkJCQkJCQlpZih0eXBlb2YoJCgnI2ZiX2ZsZC0nICsgZi5maWVsZENsZWFyKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykpICE9ICJ1bmRlZmluZWQiICYmICQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3MoJ2NoZWNrYm94LWNvbHVtbicpKXsNCgkJCQkJCQkJDQoJCQkJCQkJCQl0eXBlID0gJ2NoZWNrYm94JzsNCgkJCQkJCQkJDQoJCQkJCQkJCX0gZWxzZSBpZih0eXBlb2YoJCgnI2ZiX2ZsZC0nICsgZi5maWVsZENsZWFyKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykpICE9ICJ1bmRlZmluZWQiICYmICQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3MoJ3JhZGlvLWNvbHVtbicpKXsNCgkJCQkJCQkJDQoJCQkJCQkJCQl0eXBlID0gJ3JhZGlvJzsNCg0KCQkJCQkJCQl9IGVsc2Ugew0KDQoJCQkJCQkJCQlpZigkKCIjZmJfZmxkLSIgKyBmLmZpZWxkQ2xlYXIpICYmICQoIiNmYl9mbGQtIiArIGYuZmllbGRDbGVhcikubGVuZ3RoICE9IDApew0KDQoJCQkJCQkJCQkJLy8gRGlzcGxheSBJdGVtcyBVc2luZyBOYXRpdmUgUmFja0Zvcm1zIEZpZWxkIElkLg0KCQkJCQ0KCQkJCQkJCQkJCXR5cGUgPSAnZGlzcGxheS1lbGVtZW50JzsNCgkJCQkNCgkJCQkJCQkJCX0NCgkJCQkJCQkJfQ0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCX0NCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICdzZWxlY3Qtb25lJyl7DQoJCQkJCQkNCgkJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRDbGVhcikub3B0aW9ucy5sZW5ndGggPSAwOw0KDQoJCQkJCQl2YXIgb3B0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb3B0aW9uJyk7DQoJCQkJCQlvcHQudmFsdWUgPSAnJzsNCgkJCQkJCW9wdC5pbm5lckhUTUwgPSAnLS0gU2VsZWN0IC0tJzsNCgkJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRDbGVhcikuYXBwZW5kQ2hpbGQob3B0KTsNCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICd0ZXh0Jyl7DQoJCQkJCQkNCgkJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRDbGVhcikudmFsdWUgPSAiIjsNCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICdjaGVja2JveCcpew0KCQkJCQkJDQoJCQkJCQl2YXIgaXRlbXMgPSAkKCcjZmJfZmxkLScgKyBmLmZpZWxkQ2xlYXIgKyAnIGlucHV0Jyk7DQoJCQkJCQkJDQoJCQkJCQlpdGVtcy5lYWNoKGZ1bmN0aW9uKGlkeCwgdCl7DQoJCQkJCQkJaXRlbXNbaWR4XSA9ICQodCkudmFsKCk7DQoJCQkJCQl9KTsNCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICdyYWRpbycpew0KCQkJCQkJDQoJCQkJCQl2YXIgaXRlbXMgPSAkKCcjZmJfZmxkLScgKyBmLmZpZWxkQ2xlYXIgKyAnIGlucHV0Jyk7DQoJCQkJCQkJDQoJCQkJCQlpdGVtcy5lYWNoKGZ1bmN0aW9uKGlkeCwgdCl7DQoJCQkJCQkJaXRlbXNbaWR4XSA9ICQodCkudmFsKCk7DQoJCQkJCQl9KTsNCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICdkaXNwbGF5LWVsZW1lbnQnKXsNCgkJCQkJCQ0KCQkJCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZi5maWVsZENsZWFyKS5pbm5lckhUTUwgPSAiIjsNCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQlpZih0eXBlID09ICdoaWRkZW4nKXsNCgkJCQkJCQ0KCQkJCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZi5maWVsZENsZWFyKS52YWx1ZSA9ICIiOw0KCQkJCQkJDQoJCQkJCX0NCgkJCQkJDQoJCQkJCQ0KCQkJCX0gLy8gSGFzIGBmaWVsZENsZWFyYC4gDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgLy8NCgkJCQkvLyBQcm9jZXNzIEZpZWxkIEJpbmRpbmdzLg0KICAgICAgICAgICAgICAgIC8vDQoNCgkJCQlpZihmLmZpZWxkQmluZGluZyAhPSAiIil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogSWYgbm8gYmluZGluZywgc2tpcCBwcm9jZXNzaW5nIGNvZGUgYW5kIGp1c3QgcnVuIGFueSBjb2RlIGFmdGVyIGJsb2NrLg0KICAgICAgICAgICAgICAgICAgICANCgkJCQkJLy8gV2hhdCBLaW5kIE9mIEZpZWxkIElzIFRoaXM/DQoNCgkJCQkJdmFyIHR5cGUgPSAnJzsNCg0KCQkJCQlpZigkKCIjIiArIGYuZmllbGRCaW5kaW5nKSAmJiAkKCIjIiArIGYuZmllbGRCaW5kaW5nKS5sZW5ndGggIT0gMCl7DQoJCQkJCQkNCgkJCQkJCXZhciBpdGVtcyA9ICQoIiMiICsgZi5maWVsZEJpbmRpbmcpLm1hcChmdW5jdGlvbihpbmRleCwgZWxtKSB7DQoJCQkJCQkJcmV0dXJuIHtuYW1lOiBlbG0ubmFtZSwgdHlwZTplbG0udHlwZSwgdmFsdWU6ICQoZWxtKS52YWwoKX07DQoJCQkJCQl9KTsNCg0KCQkJCQkJdmFyIHR5cGUgPSBpdGVtc1swXS50eXBlOw0KCQkJCQkJDQoJCQkJCQkvLyBTdXBwb3J0IEZvciBBSkFYIFVwZGF0ZXMgT24gQWxsIEZpZWxkcw0KCQkJCQkJaWYodHlwZSA9PT0gdW5kZWZpbmVkKXsNCgkJCQkJCQl2YXIgdHlwZSA9ICdkaXNwbGF5LWVsZW1lbnQnOw0KCQkJCQkJfQ0KDQoJCQkJCX0gZWxzZSB7DQoNCgkJCQkJCS8vIGNoZWNrYm94ZXMsIHJhZGlvLCBjYWxlbmRhcg0KCQkJCQkJDQoJCQkJCQlpZigkKCIjIiArICJkYXRlLSIgKyBmLmZpZWxkQmluZGluZyArICctMScpICYmICQoIiMiICsgImRhdGUtIiArIGYuZmllbGRCaW5kaW5nICsgIi0xIikubGVuZ3RoICE9IDApew0KCQkJCQkJCQ0KCQkJCQkJCS8vIENhbGVuZGFyIGl0ZW0NCgkJCQkJCQl2YXIgdHlwZSA9ICd0ZXh0JzsNCgkJCQkJCQlmLmZpZWxkQmluZGluZyA9ICJkYXRlLSIgKyBmLmZpZWxkQmluZGluZyArICItMSI7DQoJCQkJCQkNCgkJCQkJCX0gZWxzZSB7DQoJCQkJCQkNCgkJCQkJCQl2YXIgaSA9IDA7IA0KCQkJCQkJCQ0KCQkJCQkJCS8vIHNldCB0aGUgaW5kZXggZm9yIHRoZSBpdGVtcyB0byBhZGQNCgkJCQkJCQl3aGlsZSgkKCIjIiArIGYuZmllbGRCaW5kaW5nICsgaSkubGVuZ3RoICE9IDAgfHwgaSA+IDEwMDApew0KCQkJCQkJCQlpKys7DQoJCQkJCQkJfQ0KCQkJCQkJCQ0KCQkJCQkJCS8vIEJ1aWxkIDcyNyAtIGdldCBmaWVsZCB0eXBlIGV2ZW4gaWYgbm8gaXRlbXMgYXJlIHByZXNlbnQNCgkJCQkJCQlpZigkKCIjIiArIGYuZmllbGRCaW5kaW5nICsgKGkgLSAxKSkubGVuZ3RoICE9IDApew0KCQkJCQkJCQ0KCQkJCQkJCQlpdGVtcyA9ICQoIiMiICsgZi5maWVsZEJpbmRpbmcgKyAoaSAtIDEpKS5tYXAoZnVuY3Rpb24oaW5kZXgsIGVsbSkgew0KCQkJCQkJCQkJcmV0dXJuIHtuYW1lOiBlbG0ubmFtZSwgdHlwZTplbG0udHlwZSwgdmFsdWU6ICQoZWxtKS52YWwoKX07DQoJCQkJCQkJCX0pOw0KCQkJCQkJCQ0KCQkJCQkJCQl0eXBlID0gaXRlbXNbMF0udHlwZTsNCgkJCQkJCQkJDQoJCQkJCQkJfSBlbHNlIHsNCg0KCQkJCQkJCQkvLyBubyBpdGVtcyBzZXQsIHNvIGdldCB0aGUgdHlwZSBmcm9tIHRoZSBjb2x1bW5zIGNsYXNzIA0KCQkJCQkJCQkNCgkJCQkJCQkJaWYodHlwZW9mKCQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykpICE9ICJ1bmRlZmluZWQiICYmICQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3MoJ2NoZWNrYm94LWNvbHVtbicpKXsNCgkJCQkJCQkJDQoJCQkJCQkJCQl0eXBlID0gJ2NoZWNrYm94JzsNCgkJCQkJCQkJDQoJCQkJCQkJCX0gZWxzZSBpZih0eXBlb2YoJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmZpbmQoJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKSkgIT0gInVuZGVmaW5lZCIgJiYgJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmZpbmQoJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKS5oYXNDbGFzcygncmFkaW8tY29sdW1uJykpew0KCQkJCQkJCQkNCgkJCQkJCQkJCXR5cGUgPSAncmFkaW8nOw0KDQoJCQkJCQkJCX0gZWxzZSB7DQoNCgkJCQkJCQkJCWlmKCQoIiNmYl9mbGQtIiArIGYuZmllbGRCaW5kaW5nKSAmJiAkKCIjZmJfZmxkLSIgKyBmLmZpZWxkQmluZGluZykubGVuZ3RoICE9IDApew0KDQoJCQkJCQkJCQkJLy8gRGlzcGxheSBJdGVtcyBVc2luZyBOYXRpdmUgUmFja0Zvcm1zIEZpZWxkIElkLg0KCQkJCQ0KCQkJCQkJCQkJCXR5cGUgPSAnZGlzcGxheS1lbGVtZW50JzsNCgkJCQkNCgkJCQkJCQkJCX0NCgkJCQkJCQkJfQ0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCX0NCgkJCQkJCQ0KCQkJCQl9DQoJCQkJCQ0KCQkJCQkvLyBwcm9jZXNzIGZpZWxkcyAoalF1ZXJ5KQ0KCQkJCQlzd2l0Y2godHlwZSl7CQ0KCQkJCQkNCgkJCQkJCWNhc2UgJ3NlbGVjdC1vbmUnIDoNCgkJCQkJCQ0KCQkJCQkJCXZhciBfaXRlbSA9ICQoIiMiICsgZi5maWVsZEJpbmRpbmcpOw0KCQkJCQkJDQoJCQkJCQkJX2l0ZW1bMF0ub3B0aW9ucy5sZW5ndGggPSAwOw0KCQkJCQkJCQ0KCQkJCQkJCWlmKHJlcyAhPSBmYWxzZSl7DQoJCQkJCQkJCSQocmVzKS5lYWNoKGZ1bmN0aW9uKGlkeCwgaSl7DQoJCQkJCQkJCQl2YXIgbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCXZhciB2YWx1ZSA9IGlbZi5kYlZhbHVlQmluZGluZ10gPT09IHVuZGVmaW5lZCA/IGkuZmJfYXBwZW5kID09PSB1bmRlZmluZWQgPyAnJyA6IGlbMV0gOiBpW2YuZGJWYWx1ZUJpbmRpbmddOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlsYWJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChsYWJlbCk7DQoJCQkJCQkJCQl2YWx1ZSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7DQoJCQkJCQkJCQkNCgkJCQkJCQkJCWlmKHZhbHVlID09PSB1bmRlZmluZWQpIHsgdmFsdWUgPSBsYWJlbDsgfQ0KCQkJCQkJCQkJc2VsID0gZmFsc2U7DQoJCQkJCQkJCQlfaXRlbVswXS5vcHRpb25zW19pdGVtWzBdLm9wdGlvbnMubGVuZ3RoXSA9IG5ldyBPcHRpb24obGFiZWwsIHZhbHVlLCBzZWwpOw0KCQkJCQkJCQl9KTsNCgkJCQkJCQl9DQoJCQkJCQkJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJlLXBvcHVsYXRlIGZyb20gcHJldmlvdXMgY2FsbCBpZiBwb3NzaWJsZS4gLSBOb3QgVXNlZCBBdCBUaGUgTW9tZW50Lg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qDQoJCQkJCQkJdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KCQkJCQkJCQ0KCQkJCQkJCWlmKF90ZXN0ICE9ICIiKXsNCgkJCQkJCQkJJCgnI3skZmlyc3RfYm91bmRfZmllbGR9JykudmFsKF90ZXN0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKi8NCgkJCQkJCQkNCgkJCQkJCQkvLyBJZiBNb2JpbGUgTW9kZS4uLg0KCQkJCQkJCWlmICggJC5tb2JpbGUgKSB7DQoJCQkJCQkJCSQoJ3NlbGVjdCcpLnNlbGVjdG1lbnUoJ3JlZnJlc2gnKTsNCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJYnJlYWs7DQoJCQkJCQkJDQoJCQkJCQljYXNlICd0ZXh0JyA6DQoJCQkJCQkJLy8gU2V0IHRleHQgdG8gYmxhbmsgaWYgbm8gdmFsdWUgaXMgZm91bmQsIGNsZWFycyB2YWx1ZXMuDQoJCQkJCQkJaWYoY2xlYXJfdGV4dF9maWVsZHMpew0KCQkJCQkJCQkkKCIjIiArIGYuZmllbGRCaW5kaW5nKS52YWwoIiIpOw0KCQkJCQkJCX0NCgkNCgkJCQkJCQlpZihyZXMgIT0gZmFsc2Upew0KCQkJCQkJCQkkKHJlcykuZWFjaChmdW5jdGlvbihpZHgsIGkpew0KCQkJCQkJCQkJbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJbGFiZWwgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOwkJCQkJCQkJCQ0KCQkJCQkJCQkJDQoJCQkJCQkJCQlpZih0eXBlb2YobGFiZWwpICE9ICJ1bmRlZmluZWQiKXsNCgkJCQkJCQkJCQl2YXIgX2N1cnJlbnQgPSAkKCIjIiArIGYuZmllbGRCaW5kaW5nKS52YWwoKTsNCgkJCQkJCQkJCQlfY3VycmVudCArPSBsYWJlbDsNCgkJCQkJCQkJCQkkKCIjIiArIGYuZmllbGRCaW5kaW5nKS52YWwoX2N1cnJlbnQpOw0KCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCX0pOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQlicmVhazsNCgkJCQkJCQkNCgkJCQkJCWNhc2UgJ2NoZWNrYm94JyA6DQoJCQkJCQkJdmFyIGlkdCA9IGk7DQoJCQkJCQkJDQoJCQkJCQkJdmFyIGl0ZW1zID0gJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcgKyAnIGlucHV0Jyk7DQoJCQkJCQkJDQoJCQkJCQkJaXRlbXMuZWFjaChmdW5jdGlvbihpZHgsIHQpew0KCQkJCQkJCQlpdGVtc1tpZHhdID0gJCh0KS52YWwoKTsNCgkJCQkJCQl9KTsNCgkJCQkJCQkNCgkJCQkJCQlpZihjbGVhcl90ZXh0X2ZpZWxkcyl7DQoJCQkJCQkJCSQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaHRtbCgnJyk7DQoJCQkJCQkJfQ0KCQkJCQkJCQ0KCQkJCQkJCWlmKHJlcyAhPSBmYWxzZSl7DQoJCQkJCQkJCSQocmVzKS5lYWNoKGZ1bmN0aW9uKGlkeCwgaSl7DQoJCQkJCQkJCQl2YXIgbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCXZhciB2YWx1ZSA9IGlbZi5kYlZhbHVlQmluZGluZ10gPT09IHVuZGVmaW5lZCA/IGkuZmJfYXBwZW5kID09PSB1bmRlZmluZWQgPyAnJyA6IGlbMV0gOiBpW2YuZGJWYWx1ZUJpbmRpbmddOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlsYWJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChsYWJlbCk7DQoJCQkJCQkJCQl2YWx1ZSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7DQoJCQkJCQkJCQkNCgkJCQkJCQkJCWlmKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT0gJycpIHsgdmFsdWUgPSBsYWJlbDsgfQ0KCQkJCQkJCQkJaWYodHlwZW9mKGl0ZW1zLmluZGV4T2YpID09ICd1bmRlZmluZWQnIHx8IGl0ZW1zLmlzKHZhbHVlKSA9PSBmYWxzZSl7DQoJCQkJCQkJCQkJLy8gY3JlYXRlIGVsZW1lbnRzDQoJCQkJCQkJCQkJDQoJCQkJCQkJCQkJLy8gUHJlLXBvcHVsYXRlIGZyb20gcHJldmlvdXMgY2FsbCBpZiBwb3NzaWJsZS4NCgkJCQkJCQkJCQl2YXIgX3Rlc3QgPSAiPD9waHAgZWNobyBpc3NldChcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddKSA/IFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10gOiAnJyA/PiI7DQoJCQkJCQkJCQkJDQoJCQkJCQkJCQkJdmFyIF9jaGVja2VkID0gIiI7DQoJCQkJCQkJCQkJDQoJCQkJCQkJCQkJaWYoX3Rlc3QgIT0gIiIgJiYgX3Rlc3QgPT0gdmFsdWUpew0KCQkJCQkJCQkJCQlfY2hlY2tlZCA9ICJjaGVja2VkPVwiY2hlY2tlZFwiIjsNCgkJCQkJCQkJCQl9DQoJCQkJCQkJCQkJDQoJCQkJCQkJCQkJdmFyIGEgPSAkKCc8aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9IicrZi5maWVsZEJpbmRpbmcrJ1tdIiBpZD0iJytmLmZpZWxkQmluZGluZyArIGlkdCsnIiB2YWx1ZT0iJyt2YWx1ZSsnIiAnICsgX2NoZWNrZWQgKyAnPicpOw0KCQkJCQkJCQkJCXZhciBiID0gJCgnPGxhYmVsIGZvcj0iJytmLmZpZWxkQmluZGluZyArIGlkdCsnIj4nK2xhYmVsKyc8L2xhYmVsPicpOw0KCQkJCQkJCQkJCXZhciBjID0gJCgnPGJyLz4nKTsNCgkJCQkJCQkJCQkvLyBhcHBlbmQgdG8gc3Bhbg0KCQkJCQkJCQkJCWEuYXBwZW5kVG8oJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmZpbmQoJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKSk7DQoJCQkJCQkJCQkJYi5hcHBlbmRUbygkKCcjZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZmluZCgnLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKTsNCgkJCQkJCQkJCQljLmFwcGVuZFRvKCQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykpOw0KCQkJCQkJCQkJCWlkdCsrOw0KCQkJCQkJCQkJfQ0KCQkJCQkJCQl9KTsNCgkJCQkJCQl9DQoJCQkJCQkJYnJlYWs7DQoJCQkJCQkJDQoJCQkJCQljYXNlICdyYWRpbycgOg0KCQkJCQkJCXZhciBpZHQgPSBpOw0KCQkJCQkJCQ0KCQkJCQkJCXZhciBpdGVtcyA9ICQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nICsgJyBpbnB1dCcpOw0KCQkJCQkJCQ0KCQkJCQkJCWl0ZW1zLmVhY2goZnVuY3Rpb24oaWR4LCB0KXsNCgkJCQkJCQkJaXRlbXNbaWR4XSA9ICQodCkudmFsKCk7DQoJCQkJCQkJfSk7DQoJCQkJCQkJDQoJCQkJCQkJaWYoY2xlYXJfdGV4dF9maWVsZHMpew0KCQkJCQkJCQkkKCcjZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZmluZCgnLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpLmh0bWwoJycpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQlpZihyZXMgIT0gZmFsc2Upew0KCQkJCQkJCQkkKHJlcykuZWFjaChmdW5jdGlvbihpZHgsIGkpew0KCQkJCQkJCQkJdmFyIGxhYmVsID0gaVtmLmRiTGFiZWxCaW5kaW5nXSA9PT0gdW5kZWZpbmVkID8gaVswXSA6IGlbZi5kYkxhYmVsQmluZGluZ107DQoJCQkJCQkJCQl2YXIgdmFsdWUgPSBpW2YuZGJWYWx1ZUJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpLmZiX2FwcGVuZCA9PT0gdW5kZWZpbmVkID8gJycgOiBpWzFdIDogaVtmLmRiVmFsdWVCaW5kaW5nXTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJbGFiZWwgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOw0KCQkJCQkJCQkJdmFsdWUgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlpZih2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09ICcnKSB7IHZhbHVlID0gbGFiZWw7IH0NCgkJCQkJCQkJCWlmKHR5cGVvZihpdGVtcy5pbmRleE9mKSA9PSAndW5kZWZpbmVkJyB8fCBpdGVtcy5pcyh2YWx1ZSkgPT0gZmFsc2Upew0KCQkJCQkJCQkJCS8vIGNyZWF0ZSBlbGVtZW50cw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCS8vIFByZS1wb3B1bGF0ZSBmcm9tIHByZXZpb3VzIGNhbGwgaWYgcG9zc2libGUuDQoJCQkJCQkJCQkJdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCXZhciBfY2hlY2tlZCA9ICIiOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCWlmKF90ZXN0ICE9ICIiICYmIF90ZXN0ID09IHZhbHVlKXsNCgkJCQkJCQkJCQkJX2NoZWNrZWQgPSAiY2hlY2tlZD1cImNoZWNrZWRcIiI7DQoJCQkJCQkJCQkJfQ0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCXZhciBhID0gJCgnPGlucHV0IHR5cGU9InJhZGlvIiBuYW1lPSInK2YuZmllbGRCaW5kaW5nKyciIGlkPSInK2YuZmllbGRCaW5kaW5nICsgaWR0KyciIHZhbHVlPSInK3ZhbHVlKyciICcgKyBfY2hlY2tlZCArICc+Jyk7DQoJCQkJCQkJCQkJdmFyIGIgPSAkKCc8bGFiZWwgZm9yPSInK2YuZmllbGRCaW5kaW5nICsgaWR0KyciPicrbGFiZWwrJzwvbGFiZWw+Jyk7DQoJCQkJCQkJCQkJdmFyIGMgPSAkKCc8YnIvPicpOw0KCQkJCQkJCQkJCS8vIGFwcGVuZCB0byBzcGFuDQoJCQkJCQkJCQkJYS5hcHBlbmRUbygkKCcjZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZmluZCgnLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKTsNCgkJCQkJCQkJCQliLmFwcGVuZFRvKCQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5maW5kKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykpOw0KCQkJCQkJCQkJCWMuYXBwZW5kVG8oJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmZpbmQoJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKSk7DQoJCQkJCQkJCQkJaWR0Kys7DQoJCQkJCQkJCQl9DQoJCQkJCQkJCX0pOw0KCQkJCQkJCX0NCgkJCQkJCQlicmVhazsNCgkJCQkJCQkNCgkJCQkJCWNhc2UgJ2Rpc3BsYXktZWxlbWVudCcgOiAvLyB1c2VkIHdoZW4gYSBub24tZm9ybSBlbGVtZW50IGlzIGRlZmluZWQNCgkJCQkJCQ0KCQkJCQkJCXZhciBfc2VsZWN0b3JQcmVmaXggPSAiIjsNCg0KCQkJCQkJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRCaW5kaW5nKSA9PSBudWxsKXsNCgkJCQkJCQkJX3NlbGVjdG9yUHJlZml4ID0gImZiX2ZsZC0iOw0KCQkJCQkJCX0NCg0KCQkJCQkJCWlmKGNsZWFyX3RleHRfZmllbGRzKXsNCgkJCQkJCQkJJCgiIyIgKyBfc2VsZWN0b3JQcmVmaXggKyBmLmZpZWxkQmluZGluZykuZW1wdHkoKTsNCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJaWYocmVzICE9IGZhbHNlKXsNCg0KCQkJCQkJCQl2YXIgX251bUNvbHVtbnMgPSByZXMubGVuZ3RoICE9IDAgPyBPYmplY3Qua2V5cyhyZXNbMF0pLmxlbmd0aCAvIDIgOiAwOyAvLyBGaXJzdCBDb2x1bW4uDQoNCgkJCQkJCQkJdmFyIF9jb2x1bW5OYW1lcyA9IFtdOw0KDQoJCQkJCQkJCWlmKF9udW1Db2x1bW5zICE9IDApew0KDQoJCQkJCQkJCQkvLyBGb3IgRWFjaCBQcm9wZXJ0eSBDaGVjayBUbyBTZWUgSWYgSXQncyBPdXIgTnVtYmVyIEluZGV4IE9yIEFjdHVhbCBOYW1lLiANCg0KCQkJCQkJCQkJZm9yICh2YXIgcHJvcGVydHkgaW4gcmVzWzBdKSB7DQoNCgkJCQkJCQkJCQlpZiAocmVzWzBdLmhhc093blByb3BlcnR5KHByb3BlcnR5KSkgew0KCQkJCQkJCQkJCQkNCgkJCQkJCQkJCQkJdmFyIF90ZXN0ID0gcGFyc2VJbnQocHJvcGVydHkpOw0KDQoJCQkJCQkJCQkJCWlmKF90ZXN0ICE9IHByb3BlcnR5KXsNCgkJCQkJCQkJCQkJCV9jb2x1bW5OYW1lcy5wdXNoKHByb3BlcnR5KTsNCgkJCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCQkJfQ0KCQkJCQkJCQkJfQ0KCQkJCQkJCQl9DQoNCgkJCQkJCQkJLy8gU3RhcnQgRGlzcGxheSBXcmFwcGVyLg0KDQoJCQkJCQkJCXZhciBfaHRtbCA9ICc8ZGl2IGNsYXNzPSJhamF4LWRpc3BsYXktdGFibGUiPic7DQoNCgkJCQkJCQkJLy8gQ3JlYXRlIENvbHVtbiBIZWFkZXIocykuDQoNCgkJCQkJCQkJJChfY29sdW1uTmFtZXMpLmVhY2goZnVuY3Rpb24oaSwgaGVhZGVyKXsNCg0KCQkJCQkJCQkJX2h0bWwgKz0gJzxkaXYgY2xhc3M9ImFqYXgtZGlzcGxheS1oZWFkZXIiPicgKyBkZWNvZGVVUklDb21wb25lbnQoaGVhZGVyKSArICc8L2Rpdj4nOw0KDQoJCQkJCQkJCX0pOw0KDQoJCQkJCQkJCS8vIEFkZCBDbGVhcmluZyBEaXYgVG8gU2VwYXJhdGUgSGVhZGVyIEFuZCBDb250ZW50Lg0KDQoJCQkJCQkJCV9odG1sICs9ICc8ZGl2IGNsYXNzPSJhamF4LWRpc3BsYXktY2xlYXItaGVhZGVyIj48L2Rpdj4nOw0KDQoJCQkJCQkJCS8vIExvb3AgT3ZlciBJdGVtcywgQWRkIFRvIE1haW4gVGVtcGxhdGUuDQoNCgkJCQkJCQkJJChyZXMpLmVhY2goZnVuY3Rpb24oaWR4LCBfaXRlbSl7DQoNCgkJCQkJCQkJCWZvciAodmFyIHByb3BlcnR5IGluIF9pdGVtKSB7DQoNCgkJCQkJCQkJCQlpZiAoX2l0ZW0uaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7DQoNCgkJCQkJCQkJCQkJaWYoX2NvbHVtbk5hbWVzLmluZGV4T2YocHJvcGVydHkpICE9IC0xKXsNCg0KCQkJCQkJCQkJCQkJX2h0bWwgKz0gJzxkaXYgY2xhc3M9ImFqYXgtZGlzcGxheS1lbGVtZW50Ij4nICsgZGVjb2RlVVJJQ29tcG9uZW50KF9pdGVtW3Byb3BlcnR5XSkgKyAnPC9kaXY+JzsNCg0KCQkJCQkJCQkJCQl9DQoNCgkJCQkJCQkJCQl9DQoNCgkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJX2h0bWwgKz0gJzxkaXYgY2xhc3M9ImFqYXgtZGlzcGxheS1jbGVhci1yb3ciPjwvZGl2Pic7DQoJCQkJCQkJCQkNCgkJCQkJCQkJfSk7DQoNCgkJCQkJCQkJLy8gQ2xvc2UgRGlzcGxheSBXcmFwcGVyLg0KDQoJCQkJCQkJCV9odG1sID0gX2h0bWwgKyAnPC9kaXY+JzsgDQoNCgkJCQkJCQkJJCgiIyIgKyBfc2VsZWN0b3JQcmVmaXggKyBmLmZpZWxkQmluZGluZykuaHRtbChfaHRtbCk7DQoJCQkJCQkJfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQcmUtcG9wdWxhdGUgZnJvbSBwcmV2aW91cyBjYWxsIGlmIHBvc3NpYmxlLg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKF90ZXN0ICE9ICIiKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJyN7JGZpcnN0X2JvdW5kX2ZpZWxkfScpLnZhbChfdGVzdCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KCQ0KCQkJCQkJCQ0KCQkJCQkJCQ0KCQkJCQkJCWJyZWFrOw0KCQkJCQkJCQ0KCQkJCQkJY2FzZSAnaGlkZGVuJyA6DQoNCgkJCQkJCQlpZihyZXMgIT09IHVuZGVmaW5lZCAmJiByZXMgIT0gZmFsc2Upew0KCQkJCQkJCQkkKHJlcykuZWFjaChmdW5jdGlvbihpZHgsIGkpew0KCQkJCQkJCQkJdmFyIGxhYmVsID0gaVtmLmRiTGFiZWxCaW5kaW5nXSA9PT0gdW5kZWZpbmVkID8gaVswXSA6IGlbZi5kYkxhYmVsQmluZGluZ107DQoJCQkJCQkJCQlsYWJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChsYWJlbCk7IC8vIEJ1aWxkIDg2NA0KCQkJCQkJCQkJJCgiIyIgKyBmLmZpZWxkQmluZGluZykudmFsKGxhYmVsKTsNCgkJCQkJCQkJfSk7DQoJCQkJCQkJfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJlLXBvcHVsYXRlIGZyb20gcHJldmlvdXMgY2FsbCBpZiBwb3NzaWJsZS4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoX3Rlc3QgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90ZXN0ID0gZGVjb2RlVVJJQ29tcG9uZW50KF90ZXN0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcjeyRmaXJzdF9ib3VuZF9maWVsZH0nKS52YWwoX3Rlc3QpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KCQkJCQkJCQ0KCQkJCQkJCQ0KCQkJCQkJCQ0KCQkJCQkJCWJyZWFrOw0KCQkJCQkJDQoJCQkJCQlkZWZhdWx0IDoNCgkJCQkJCQ0KCQkJCQkJCWlmKHJlcyAhPT0gdW5kZWZpbmVkICYmIHJlcyAhPSBmYWxzZSl7DQoJCQkJCQkJCSQocmVzKS5lYWNoKGZ1bmN0aW9uKGlkeCwgaSl7DQoJCQkJCQkJCQlsYWJlbCA9IGlbZi5kYkxhYmVsQmluZGluZ10gPT09IHVuZGVmaW5lZCA/IGlbMF0gOiBpW2YuZGJMYWJlbEJpbmRpbmddOw0KCQkJCQkJCQkJbGFiZWwgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOw0KCQkJCQkJCQkJJCgiIyIgKyBmLmZpZWxkQmluZGluZykuaHRtbChsYWJlbCk7DQoJCQkJCQkJCX0pOw0KCQkJCQkJCQkNCgkJCQkJCQkJLy8gUHJlLXBvcHVsYXRlIGZyb20gcHJldmlvdXMgY2FsbCBpZiBwb3NzaWJsZS4NCgkJCQkJCQkJdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KCQkJCQkJCQkNCgkJCQkJCQkJaWYoX3Rlc3QgIT0gIiIpew0KCQkJCQkJCQkJJCgnI3skZmlyc3RfYm91bmRfZmllbGR9JykudmFsKF90ZXN0KTsNCgkJCQkJCQkJfQ0KCQkJCQkJCQ0KCQkJCQkJCX0NCgkJCQkJCQlicmVhazsNCgkJCQkJfQ0KCQkJCQkNCgkJCQl9IC8vIGlmIGJpbmRpbmcNCgkJCQkNCgkJCX0pOyAvLyBlYWNoDQoJCQkNCgkJCS8vIHVzZXIgY29kZSBhZnRlciBxdWVyeQ0KCQkJeyRmaWVsZC0+YWpheF9jb2RlX2FmdGVyX3F1ZXJ5fQ0KCQkNCgl9KTsNCg0KfQ0KDQo8L3NjcmlwdD4NCg0KRU9GOw0KICAgICAgICB9IGVsc2UgeyANCg0KDQogICAgICAgICAgICAkcGFnZV9jb2RlIC49IDw8PEVPRg0KDQo8ZGl2IHN0eWxlPSJkaXNwbGF5Om5vbmU7IiBpZD0ibG9hZC1zdGF0dXMteyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0iIGNsYXNzPSJmYi1hamF4LWxvYWRlciI+TG9hZGluZy4uLjwvZGl2Pg0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoNCi8vIFJhY2tGb3JtcyBBSkFYIENvZGUgLSBQcm90b3R5cGUuanMNCg0KZG9jdW1lbnQub2JzZXJ2ZSgnZG9tOmxvYWRlZCcsIGZ1bmN0aW9uKGwpew0KICAgIGJpbmRBamF4X3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KCk7DQp9KTsNCg0KZnVuY3Rpb24gYmluZEFqYXhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKSB7DQoNCgkvLyBiaW5kIGV2ZW50IGxpc3RlbmVyKHMpDQoNCgkvLyB3aGF0IHR5cGUgb2YgZWxlbWVudCBpcyB0aGlzIGNoZWNrDQoJaXNfc2VsZWN0X29yX3RleHQgPSBmYWxzZTsNCglpc19vdGhlciA9IGZhbHNlOw0KDQoJaXNfc2VsZWN0X29yX3RleHQgPSAkKCd7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH0nKTsNCg0KCWlmKGlzX3NlbGVjdF9vcl90ZXh0ID09PSBudWxsKXsNCgkJaXNfb3RoZXIgPSB0cnVlOw0KCX0gZWxzZSB7DQoJCWlzX3NlbGVjdF9vcl90ZXh0ID0gdHJ1ZTsNCgl9DQoNCglpZihpc19zZWxlY3Rfb3JfdGV4dCl7DQoJCSQoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfScpLm9ic2VydmUoJ3skdGhpcy0+dHJhbnNsYXRlQ29uZGl0aW9uYWxBamF4RXZlbnQoJGZpZWxkLT5hamF4X2V2ZW50KX0nLA0KICAgICAgICAgICAgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgKTsNCgl9DQoJDQoJaWYoaXNfb3RoZXIpew0KCQl7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fV9pdGVtcyA9ICQkKCcjZmJfZmxkLXskZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfSBJTlBVVCcpOw0KCQ0KCQkvLyBiaW5kIGV2ZW50IGxpc3RlbmVycw0KCQl7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fV9pdGVtcy5lYWNoKGZ1bmN0aW9uKHQpew0KCQkJdC5vYnNlcnZlKCd7JHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsQWpheEV2ZW50KCRmaWVsZC0+YWpheF9ldmVudCl9JywNCiAgICAgICAgICAgICAgICBmdW5jdGlvbigpew0KICAgICAgICAgICAgICAgICAgICBoYW5kbGVfRkJfQUpBWF97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fSgpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICk7DQoJCX0pOw0KCX0NCg0KICAgIA0KICAgIC8vIGV2YWwgaXRlbXMNCiAgICBqc29uX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9ID0gJGpzb25fZWxlbWVudHM7DQoJZXZhbChqc29uX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9KTsNCgkNCgkvLyBDYWxsIGZvciBwYWdlIGxvYWQgaWYgYSB2YWx1ZSBoYXMgYmVlbiBzZWxlY3RlZC4NCglpZihcJEYoInskZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfSIpICE9ICIiKXsNCgkJaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKTsNCgl9DQogICAgDQp9Ow0KDQovLyBmZXRjaCBhIGR5bmFtaWMgZmllbGQgdmFsdWUNCmZ1bmN0aW9uIGZldGNoX2FqYXhfYXJnKGZpZWxkKXsNCg0KCS8vIHdoYXQgdHlwZSBvZiBlbGVtZW50IGlzIHRoaXMgY2hlY2sNCglpc19zZWxlY3Rfb3JfdGV4dCA9IGZhbHNlOw0KCWlzX290aGVyID0gZmFsc2U7DQoNCglpc19zZWxlY3Rfb3JfdGV4dCA9ICQoZmllbGQpOw0KDQoJaWYoaXNfc2VsZWN0X29yX3RleHQgPT09IG51bGwpew0KCQlpc19vdGhlciA9IHRydWU7DQoJfSBlbHNlIHsNCgkJaXNfc2VsZWN0X29yX3RleHQgPSB0cnVlOw0KCX0NCg0KCWlmKGlzX3NlbGVjdF9vcl90ZXh0KXsNCgkJcmV0dXJuIFwkRihmaWVsZCk7DQoJfQ0KCQ0KCWlmKGlzX290aGVyKXsNCgkJaXRlbXMgPSAkJCgnI2ZiX2ZsZC0nICsgZmllbGQgKyAnIElOUFVUJyk7DQoNCgkJdmFyIHZhbCA9ICcnOw0KCQkNCgkJLy8gYmluZCBldmVudCBsaXN0ZW5lcnMNCgkJaXRlbXMuZWFjaChmdW5jdGlvbih0KXsNCgkJCWlmKHQuY2hlY2tlZCl7DQoJCQkJdmFsID0gdC52YWx1ZTsNCgkJCX0NCgkJfSk7DQoNCgkJcmV0dXJuIHZhbDsNCgl9CQ0KfTsNCg0KZnVuY3Rpb24gaGFuZGxlX0ZCX0FKQVhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0oKXsNCg0KCS8vIHVzZXIgY29kZSBiZWZvcmUgcXVlcnkNCgl7JGZpZWxkLT5hamF4X2NvZGVfYmVmb3JlX3F1ZXJ5fQ0KCQ0KCS8vIGNvbGxlY3QgcGFyYW1zDQoJdmFyIHBhcmFtcyA9IHt9Ow0KCQ0KCXBhcmFtc1snYXJnMSddID0gZmV0Y2hfYWpheF9hcmcoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfScpOw0KCXBhcmFtc1snYXJnMiddID0gZmV0Y2hfYWpheF9hcmcoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkXzJ9Jyk7DQoJcGFyYW1zWydhcmczJ10gPSBmZXRjaF9hamF4X2FyZygneyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGRfM30nKTsNCglwYXJhbXNbJ2FyZzQnXSA9IGZldGNoX2FqYXhfYXJnKCd7JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZF80fScpOw0KCXBhcmFtc1snYXJnNSddID0gZmV0Y2hfYWpheF9hcmcoJ3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkXzV9Jyk7DQoJDQoJcGFyYW1zWydhY3Rpb24nXSA9ICd7JGFqYXhfcHJvY2Vzc2luZ19tb2RlfSc7DQoJY2xlYXJfdGV4dF9maWVsZHMgPSB7JGFqYXhfY2xlYXJfdGV4dF9maWVsZHN9Ow0KCQ0KCW5ldyBBamF4LlJlcXVlc3QoJ2xpYi9hamF4L2ZiX2FqYXhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0ucGhwJywgew0KCQltZXRob2Q6J3Bvc3QnLA0KCQlldmFsSlNPTjogdHJ1ZSwNCgkJcGFyYW1ldGVyczogcGFyYW1zLA0KCQlvbkNyZWF0ZTogZnVuY3Rpb24oKSB7ICQoJ2xvYWQtc3RhdHVzLXskZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9Jykuc2hvdygpOyB9LA0KCQlvbkNvbXBsZXRlOiBmdW5jdGlvbihyZXNwb25zZSkgew0KCQkJLy8gQnVpbGQgNjkyDQoJCQlpZihyZXNwb25zZS5yZXNwb25zZUpTT04gPT0gbnVsbCl7DQoJCQkJcmVzID0gZXZhbChyZXNwb25zZS5yZXNwb25zZVRleHQpOw0KCQkJfSBlbHNlIHsNCgkJCQlyZXMgPSByZXNwb25zZS5yZXNwb25zZUpTT047DQoJCQl9DQoJCQkNCgkJCS8vIEJ1aWxkIDc2NCAtIElmIHdlIHN0aWxsIGhhdmUgbm8gcmVzIHZhbHVlLCByZXR1cm4gKGhhcHBlbnMgd2hlbiB3ZSBzZWxlY3QgLS1TZWxlY3QtLQ0KCQkJaWYocmVzID09PSB1bmRlZmluZWQpDQoJCQkJcmV0dXJuOw0KCQkJCQ0KCQkJJCgnbG9hZC1zdGF0dXMteyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0nKS5oaWRlKCk7DQoJCQkNCiAgICAgICAgICAgIC8vIHJlYnVpbGQgdGFyZ2V0IGVsZW1lbnRzLi4uDQoJCQlqc29uX3skZmllbGQtPmFqYXhfc291cmNlX2ZpZWxkfV97JGJpbmRfaW5kZXh9LmVhY2goZnVuY3Rpb24oZil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAvLw0KCQkJCS8vIENsZWFyIEFueSBSZXF1ZXN0ZWQgRmllbGRzLg0KICAgICAgICAgICAgICAgIC8vDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYoZi5maWVsZENsZWFyICE9ICIiKXsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gIiI7DQoJCQkJCQ0KCQkJCQlpZigkKGYuZmllbGRCaW5kaW5nKSl7DQoJCQkJCQl2YXIgdHlwZSA9ICQoZi5maWVsZEJpbmRpbmcpLnR5cGU7DQoJCQkJCQkvLyBCdWlsZCA3MDAgLSBTdXBwb3J0IEZvciBBSkFYIFVwZGF0ZXMgT24gQWxsIEZpZWxkcw0KCQkJCQkJaWYodHlwZSA9PT0gdW5kZWZpbmVkKXsNCgkJCQkJCQl2YXIgdHlwZSA9ICdkaXNwbGF5LWVsZW1lbnQnOw0KCQkJCQkJfQ0KCQkJCQkJDQoJCQkJCX0gZWxzZSB7DQoJCQkJCQ0KCQkJCQkJLy8gY2hlY2tib3hlcywgcmFkaW8sIGNhbGVuZGFyDQoJCQkJCQkNCgkJCQkJCWlmKCQoIiMiICsgImRhdGUtIiArIGYuZmllbGRCaW5kaW5nICsgJy0xJykgJiYgJCgiIyIgKyAiZGF0ZS0iICsgZi5maWVsZEJpbmRpbmcgKyAiLTEiKS5sZW5ndGggIT0gMCl7DQoJCQkJCQkJDQoJCQkJCQkJLy8gQ2FsZW5kYXIgaXRlbQ0KCQkJCQkJCXZhciB0eXBlID0gJ3RleHQnOw0KCQkJCQkJCWYuZmllbGRCaW5kaW5nID0gImRhdGUtIiArIGYuZmllbGRCaW5kaW5nICsgIi0xIjsNCgkJCQkJCQ0KCQkJCQkJfSBlbHNlIHsNCg0KCQkJCQkJCXZhciBpID0gMDsgDQoJCQkJCQkJDQoJCQkJCQkJLy8gc2V0IHRoZSBpbmRleCBmb3IgdGhlIGl0ZW1zIHRvIGFkZA0KCQkJCQkJCXdoaWxlKCQoZi5maWVsZEJpbmRpbmcgKyBpKSB8fCBpID4gMTAwMCl7DQoJCQkJCQkJCWkrKzsNCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJLy8gQnVpbGQgNzI3IC0gZ2V0IGZpZWxkIHR5cGUgZXZlbiBpZiBubyBpdGVtcyBhcmUgcHJlc2VudA0KCQkJCQkJCWlmKCQoZi5maWVsZEJpbmRpbmcgKyAoaSAtIDEpKSl7DQoJCQkJCQkJCQ0KCQkJCQkJCQl0eXBlID0gJChmLmZpZWxkQmluZGluZyArIChpIC0gMSkpLnR5cGU7IC8vIHdlIGZvdW5kIGEgbWF0Y2gNCgkJCQkJCQkNCgkJCQkJCQl9IGVsc2Ugew0KCQkJCQkJCQkNCgkJCQkJCQkJLy8gbm8gaXRlbXMgc2V0LCBzbyBnZXQgdGhlIHR5cGUgZnJvbSB0aGUgY29sdW1ucyBjbGFzcyANCg0KCQkJCQkJCQlpZih0eXBlb2YoJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKSAhPSAidW5kZWZpbmVkIiAmJiAkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3NOYW1lKCdjaGVja2JveC1jb2x1bW4nKSkgew0KCQkJCQkJCQkJDQoJCQkJCQkJCQl0eXBlID0gJ2NoZWNrYm94JzsNCgkJCQkJCQkJDQoJCQkJCQkJCX0gZWxzZSBpZih0eXBlb2YoJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKSAhPSAidW5kZWZpbmVkIiAmJiAkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3NOYW1lKCdyYWRpby1jb2x1bW4nKSkgew0KCQkJCQkJCQkNCgkJCQkJCQkJCXR5cGUgPSAncmFkaW8nOw0KCQkJCQkJCQkNCgkJCQkJCQkJfSBlbHNlIHsNCgkJCQkJCQkJDQoJCQkJCQkJCQlpZigkKCJmYl9mbGQtIiArIGYuZmllbGRCaW5kaW5nKSAmJiAkKCJmYl9mbGQtIiArIGYuZmllbGRCaW5kaW5nKS5sZW5ndGggIT0gMCkgew0KDQoJCQkJCQkJCQkJLy8gRGlzcGxheSBJdGVtcyBVc2luZyBOYXRpdmUgUmFja0Zvcm1zIEZpZWxkIElkLg0KCQkJCQ0KCQkJCQkJCQkJCXR5cGUgPSAnZGlzcGxheS1lbGVtZW50JzsNCgkJCQkNCgkJCQkJCQkJCX0NCgkJCQkJCQkJDQoJCQkJCQkJCX0NCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQl9DQoJCQkJCQkNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgaWYodHlwZSA9PSAnc2VsZWN0LW9uZScpew0KCQkJCQkJDQoJCQkJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZChmLmZpZWxkQ2xlYXIpLm9wdGlvbnMubGVuZ3RoID0gMDsNCg0KCQkJCQkJdmFyIG9wdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGlvbicpOw0KCQkJCQkJb3B0LnZhbHVlID0gJyc7DQoJCQkJCQlvcHQuaW5uZXJIVE1MID0gJy0tIFNlbGVjdCAtLSc7DQoJCQkJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZChmLmZpZWxkQ2xlYXIpLmFwcGVuZENoaWxkKG9wdCk7DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJaWYodHlwZSA9PSAndGV4dCcpew0KCQkJCQkJDQoJCQkJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZChmLmZpZWxkQ2xlYXIpLnZhbHVlID0gIiI7DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJaWYodHlwZSA9PSAnY2hlY2tib3gnKXsNCgkJCQkJCQ0KCQkJCQkJdmFyIGl0ZW1zID0gJCgnI2ZiX2ZsZC0nICsgZi5maWVsZENsZWFyICsgJyBpbnB1dCcpOw0KCQkJCQkJCQ0KCQkJCQkJaXRlbXMuZWFjaChmdW5jdGlvbihpZHgsIHQpew0KCQkJCQkJCWl0ZW1zW2lkeF0gPSAkKHQpLnZhbCgpOw0KCQkJCQkJfSk7DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJaWYodHlwZSA9PSAncmFkaW8nKXsNCgkJCQkJCQ0KCQkJCQkJdmFyIGl0ZW1zID0gJCgnI2ZiX2ZsZC0nICsgZi5maWVsZENsZWFyICsgJyBpbnB1dCcpOw0KCQkJCQkJCQ0KCQkJCQkJaXRlbXMuZWFjaChmdW5jdGlvbihpZHgsIHQpew0KCQkJCQkJCWl0ZW1zW2lkeF0gPSAkKHQpLnZhbCgpOw0KCQkJCQkJfSk7DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJaWYodHlwZSA9PSAnZGlzcGxheS1lbGVtZW50Jyl7DQoJCQkJCQkNCgkJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRDbGVhcikuaW5uZXJIVE1MID0gIiI7DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJaWYodHlwZSA9PSAnaGlkZGVuJyl7DQoJCQkJCQkNCgkJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGYuZmllbGRDbGVhcikudmFsdWUgPSAiIjsNCgkJCQkJCQ0KCQkJCQl9DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIH0gLy8gSGFzIGBmaWVsZENsZWFyYC4gDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgLy8NCgkJCQkvLyBQcm9jZXNzIEZpZWxkIEJpbmRpbmdzLg0KICAgICAgICAgICAgICAgIC8vDQogICAgICAgICAgICAgICAgDQoJCQkJaWYoZi5maWVsZEJpbmRpbmcgIT0gIiIpew0KCQkJDQoJCQkJCS8vIE5vdGU6IElmIG5vIGJpbmRpbmcsIHNraXAgcHJvY2Vzc2luZyBjb2RlIGFuZCBqdXN0IHJ1biBhbnkgY29kZSBhZnRlciBibG9jay4NCiAgICAgICAgICAgICAgICAgICAgDQoJCQkJCS8vIFdoYXQgS2luZCBPZiBGaWVsZCBJcyBUaGlzPw0KDQoJCQkJCXZhciB0eXBlID0gIiI7DQoJCQkJCQ0KCQkJCQlpZigkKGYuZmllbGRCaW5kaW5nKSl7DQoJCQkJCQl2YXIgdHlwZSA9ICQoZi5maWVsZEJpbmRpbmcpLnR5cGU7DQoJCQkJCQkvLyBCdWlsZCA3MDAgLSBTdXBwb3J0IEZvciBBSkFYIFVwZGF0ZXMgT24gQWxsIEZpZWxkcw0KCQkJCQkJaWYodHlwZSA9PT0gdW5kZWZpbmVkKXsNCgkJCQkJCQl2YXIgdHlwZSA9ICdkaXNwbGF5LWVsZW1lbnQnOw0KCQkJCQkJfQ0KCQkJCQkJDQoJCQkJCX0gZWxzZSB7DQoJCQkJCQ0KCQkJCQkJLy8gY2hlY2tib3hlcywgcmFkaW8sIGNhbGVuZGFyDQoJCQkJCQkNCgkJCQkJCWlmKCQoIiMiICsgImRhdGUtIiArIGYuZmllbGRCaW5kaW5nICsgJy0xJykgJiYgJCgiIyIgKyAiZGF0ZS0iICsgZi5maWVsZEJpbmRpbmcgKyAiLTEiKS5sZW5ndGggIT0gMCl7DQoJCQkJCQkJDQoJCQkJCQkJLy8gQ2FsZW5kYXIgaXRlbQ0KCQkJCQkJCXZhciB0eXBlID0gJ3RleHQnOw0KCQkJCQkJCWYuZmllbGRCaW5kaW5nID0gImRhdGUtIiArIGYuZmllbGRCaW5kaW5nICsgIi0xIjsNCgkJCQkJCQ0KCQkJCQkJfSBlbHNlIHsNCg0KCQkJCQkJCXZhciBpID0gMDsgDQoJCQkJCQkJDQoJCQkJCQkJLy8gc2V0IHRoZSBpbmRleCBmb3IgdGhlIGl0ZW1zIHRvIGFkZA0KCQkJCQkJCXdoaWxlKCQoZi5maWVsZEJpbmRpbmcgKyBpKSB8fCBpID4gMTAwMCl7DQoJCQkJCQkJCWkrKzsNCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJLy8gQnVpbGQgNzI3IC0gZ2V0IGZpZWxkIHR5cGUgZXZlbiBpZiBubyBpdGVtcyBhcmUgcHJlc2VudA0KCQkJCQkJCWlmKCQoZi5maWVsZEJpbmRpbmcgKyAoaSAtIDEpKSl7DQoJCQkJCQkJCQ0KCQkJCQkJCQl0eXBlID0gJChmLmZpZWxkQmluZGluZyArIChpIC0gMSkpLnR5cGU7IC8vIHdlIGZvdW5kIGEgbWF0Y2gNCgkJCQkJCQkNCgkJCQkJCQl9IGVsc2Ugew0KCQkJCQkJCQkNCgkJCQkJCQkJLy8gbm8gaXRlbXMgc2V0LCBzbyBnZXQgdGhlIHR5cGUgZnJvbSB0aGUgY29sdW1ucyBjbGFzcyANCg0KCQkJCQkJCQlpZih0eXBlb2YoJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKSAhPSAidW5kZWZpbmVkIiAmJiAkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3NOYW1lKCdjaGVja2JveC1jb2x1bW4nKSkgew0KCQkJCQkJCQkJDQoJCQkJCQkJCQl0eXBlID0gJ2NoZWNrYm94JzsNCgkJCQkJCQkJDQoJCQkJCQkJCX0gZWxzZSBpZih0eXBlb2YoJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpKSAhPSAidW5kZWZpbmVkIiAmJiAkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaGFzQ2xhc3NOYW1lKCdyYWRpby1jb2x1bW4nKSkgew0KCQkJCQkJCQkNCgkJCQkJCQkJCXR5cGUgPSAncmFkaW8nOw0KCQkJCQkJCQkNCgkJCQkJCQkJfSBlbHNlIHsNCgkJCQkJCQkJDQoJCQkJCQkJCQlpZigkKCJmYl9mbGQtIiArIGYuZmllbGRCaW5kaW5nKSAmJiAkKCJmYl9mbGQtIiArIGYuZmllbGRCaW5kaW5nKS5sZW5ndGggIT0gMCkgew0KDQoJCQkJCQkJCQkJLy8gRGlzcGxheSBJdGVtcyBVc2luZyBOYXRpdmUgUmFja0Zvcm1zIEZpZWxkIElkLg0KCQkJCQ0KCQkJCQkJCQkJCXR5cGUgPSAnZGlzcGxheS1lbGVtZW50JzsNCgkJCQkNCgkJCQkJCQkJCX0NCgkJCQkJCQkJDQoJCQkJCQkJCX0NCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQl9DQoJCQkJCQkNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJLy8gcHJvY2VzcyBmaWVsZHMNCgkJCQkJc3dpdGNoKHR5cGUpewkNCgkJCQkJDQoJCQkJCQljYXNlICdzZWxlY3Qtb25lJyA6DQoJCQkJCQkJJChmLmZpZWxkQmluZGluZykub3B0aW9ucy5sZW5ndGggPSAwOw0KCQkJCQkJCQ0KCQkJCQkJCWlmKHJlcyAhPSBmYWxzZSl7DQoJCQkJCQkJCXJlcy5lYWNoKGZ1bmN0aW9uKGkpew0KCQkJCQkJCQkJdmFyIGxhYmVsID0gaVtmLmRiTGFiZWxCaW5kaW5nXSA9PT0gdW5kZWZpbmVkID8gaVswXSA6IGlbZi5kYkxhYmVsQmluZGluZ107DQoJCQkJCQkJCQl2YXIgdmFsdWUgPSBpW2YuZGJWYWx1ZUJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpLmZiX2FwcGVuZCA9PT0gdW5kZWZpbmVkID8gJycgOiBpWzFdIDogaVtmLmRiVmFsdWVCaW5kaW5nXTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJbGFiZWwgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOw0KCQkJCQkJCQkJdmFsdWUgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlpZih2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7IHZhbHVlID0gbGFiZWw7IH0NCgkJCQkJCQkJCXNlbCA9IGZhbHNlOw0KCQkJCQkJCQkJJChmLmZpZWxkQmluZGluZykub3B0aW9uc1skKGYuZmllbGRCaW5kaW5nKS5vcHRpb25zLmxlbmd0aF0gPSBuZXcgT3B0aW9uKGxhYmVsLCB2YWx1ZSwgc2VsKTsNCgkJCQkJCQkJfS5iaW5kKGYpKTsNCgkJCQkJCQl9DQoJCQkJCQkJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJlLXBvcHVsYXRlIGZyb20gcHJldmlvdXMgY2FsbCBpZiBwb3NzaWJsZS4gTm90IFVzZWQgQXQgVGhlIE1vbWVudC4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKg0KCQkJCQkJCXZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCgkJCQkJCQkNCgkJCQkJCQlpZihfdGVzdCAhPSAiIil7DQoJCQkJCQkJCSQoJ3skZmlyc3RfYm91bmRfZmllbGR9Jykuc2V0VmFsdWUoX3Rlc3QpOw0KCQkJCQkJCX0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkJCQkJCS8vIElmIE1vYmlsZSBNb2RlLi4uDQoJCQkJCQkJaWYgKCAkLm1vYmlsZSApIHsNCgkJCQkJCQkJJCgnc2VsZWN0Jykuc2VsZWN0bWVudSgncmVmcmVzaCcpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQlicmVhazsNCgkJCQkJCQkNCgkJCQkJCWNhc2UgJ3RleHQnIDoNCgkJCQkJCQkvLyBTZXQgdGV4dCB0byBibGFuayBpZiBubyB2YWx1ZSBpcyBmb3VuZCwgY2xlYXJzIHZhbHVlcy4NCgkJCQkJCQlpZihjbGVhcl90ZXh0X2ZpZWxkcyl7DQoJCQkJCQkJCSQoZi5maWVsZEJpbmRpbmcpLnZhbHVlID0gIiI7DQoJCQkJCQkJfQ0KCQ0KCQkJCQkJCWlmKHJlcyAhPSBmYWxzZSl7DQoJCQkJCQkJCXJlcy5lYWNoKGZ1bmN0aW9uKGkpew0KCQkJCQkJCQkJbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJbGFiZWwgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQkkKGYuZmllbGRCaW5kaW5nKS52YWx1ZSA9IGxhYmVsOw0KCQkJCQkJCQl9LmJpbmQoZikpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQkvLyBQcmUtcG9wdWxhdGUgZnJvbSBwcmV2aW91cyBjYWxsIGlmIHBvc3NpYmxlLg0KCQkJCQkJCS8vIEJ1aWxkIDg2NiAtIE5vdCBuZWVkZWQsIGNhdXNlcyBhbnkgc3VibWl0dGVkIGZvcm0gdG8gcmV0YWluIHZhbHVlcy4NCgkJCQkJCQkvKg0KCQkJCQkJCXZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCgkJCQkJCQkNCgkJCQkJCQlpZihfdGVzdCAhPSAiIil7DQoJCQkJCQkJCSQoJ3skZmlyc3RfYm91bmRfZmllbGR9Jykuc2V0VmFsdWUoX3Rlc3QpOw0KCQkJCQkJCX0NCgkJCQkJCQkqLw0KCQkJCQkJCQ0KCQkJCQkJCWJyZWFrOw0KCQkJCQkJCQ0KCQkJCQkJY2FzZSAnY2hlY2tib3gnIDoNCgkJCQkJCQl2YXIgaWR0ID0gaTsNCgkJCQkJCQkNCgkJCQkJCQl2YXIgaXRlbXMgPSAkJCgnI2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcgKyAnIGlucHV0Jyk7DQoJCQkJCQkJaXRlbXMgPSBpdGVtcy5wbHVjaygndmFsdWUnKTsNCgkJCQkJCQkNCgkJCQkJCQkvLyBoYW5kbGUgY2FzZXMgd2hlcmUgZXhpc2l0bmcgdmFsdWVzIChpbnRzKSBhcmUgaW1wbGljaXRseSBjaGFuZ2VkIHRvIHN0cmluZ3MuDQoJCQkJCQkJaXRlbXMuZWFjaChmdW5jdGlvbih0LCBpbmRleCl7DQoJCQkJCQkJCWlmKHBhcnNlSW50KHQpICE9PSBOYU4pew0KCQkJCQkJCQkJaXRlbXNbaW5kZXhdID0gcGFyc2VJbnQodCk7DQoJCQkJCQkJCX0NCgkJCQkJCQl9KTsNCgkJCQkJCQkNCgkJCQkJCQlpZihjbGVhcl90ZXh0X2ZpZWxkcyl7DQoJCQkJCQkJCSQoJ2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmRvd24oJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKS51cGRhdGUoJycpOw0KCQkJCQkJCX0NCgkJDQoJCQkJCQkJaWYocmVzICE9IGZhbHNlKXsNCgkJCQkJCQkJcmVzLmVhY2goZnVuY3Rpb24oaSl7DQoJCQkJCQkJCQl2YXIgbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCXZhciB2YWx1ZSA9IGlbZi5kYlZhbHVlQmluZGluZ10gPT09IHVuZGVmaW5lZCA/IGkuZmJfYXBwZW5kID09PSB1bmRlZmluZWQgPyAnJyA6IGlbMV0gOiBpW2YuZGJWYWx1ZUJpbmRpbmddOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlsYWJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChsYWJlbCk7DQoJCQkJCQkJCQl2YWx1ZSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7DQoJCQkJCQkJCQkNCgkJCQkJCQkJCWlmKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT0gJycpIHsgdmFsdWUgPSBsYWJlbDsgfQ0KCQkJCQkJCQkJaWYodHlwZW9mKGl0ZW1zLmluZGV4T2YpID09ICd1bmRlZmluZWQnIHx8IGl0ZW1zLmluZGV4T2YodmFsdWUpID09IC0xKXsNCgkJCQkJCQkJCQkvLyBjcmVhdGUgZWxlbWVudA0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCS8vIFByZS1wb3B1bGF0ZSBmcm9tIHByZXZpb3VzIGNhbGwgaWYgcG9zc2libGUuDQoJCQkJCQkJCQkJdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCXZhciBfY2hlY2tlZCA9IGZhbHNlOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCWlmKF90ZXN0ICE9ICIiICYmIF90ZXN0ID09IHZhbHVlKXsNCgkJCQkJCQkJCQkJX2NoZWNrZWQgPSB0cnVlOw0KCQkJCQkJCQkJCX0NCgkJCQkJCQkJCQkNCgkJCQkJCQkJCQl2YXIgYSA9IG5ldyBFbGVtZW50KCdpbnB1dCcsIHsgJ3R5cGUnOiAnY2hlY2tib3gnLCAndmFsdWUnOiB2YWx1ZSwgJ25hbWUnIDogZi5maWVsZEJpbmRpbmcgKyAnW10nLCAnaWQnIDogZi5maWVsZEJpbmRpbmcgKyBpZHQsIGNoZWNrZWQ6IF9jaGVja2VkIH0pOw0KCQkJCQkJCQkJCXZhciBiID0gbmV3IEVsZW1lbnQoJ2xhYmVsJywgeyAnZm9yJzogZi5maWVsZEJpbmRpbmcgKyBpZHQgfSk7IGIudXBkYXRlKCcmbmJzcDsnICsgbGFiZWwpOw0KCQkJCQkJCQkJCXZhciBjID0gbmV3IEVsZW1lbnQoJ2JyJywgeyB9KTsNCgkJCQkJCQkJCQkvLyBhcHBlbmQgdG8gc3Bhbg0KCQkJCQkJCQkJCSQoJ2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmRvd24oJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKS5pbnNlcnQoYSk7DQoJCQkJCQkJCQkJJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpLmluc2VydChiKTsNCgkJCQkJCQkJCQkkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaW5zZXJ0KGMpOw0KCQkJCQkJCQkJCWlkdCsrOw0KCQkJCQkJCQkJfQ0KCQkJCQkJCQl9LmJpbmQoZikpOw0KCQkJCQkJCX0NCgkJCQkJCQlicmVhazsNCgkJCQkJCQkNCgkJCQkJCWNhc2UgJ3JhZGlvJyA6DQoJCQkJCQkJdmFyIGlkdCA9IGk7DQoJCQkJCQkJDQoJCQkJCQkJdmFyIGl0ZW1zID0gJCQoJyNmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nICsgJyBpbnB1dCcpOw0KCQkJCQkJCWl0ZW1zID0gaXRlbXMucGx1Y2soJ3ZhbHVlJyk7DQoJCQkJCQkJDQoJCQkJCQkJLy8gaGFuZGxlIGNhc2VzIHdoZXJlIGV4aXNpdG5nIHZhbHVlcyAoaW50cykgYXJlIGltcGxpY2l0bHkgY2hhbmdlZCB0byBzdHJpbmdzLg0KCQkJCQkJCWl0ZW1zLmVhY2goZnVuY3Rpb24odCwgaW5kZXgpew0KCQkJCQkJCQlpZihwYXJzZUludCh0KSAhPT0gTmFOKXsNCgkJCQkJCQkJCWl0ZW1zW2luZGV4XSA9IHBhcnNlSW50KHQpOw0KCQkJCQkJCQl9DQoJCQkJCQkJfSk7DQoJCQkJCQkJDQoJCQkJCQkJaWYoY2xlYXJfdGV4dF9maWVsZHMpew0KCQkJCQkJCQkkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykudXBkYXRlKCcnKTsNCgkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJaWYocmVzICE9IGZhbHNlKXsNCgkJCQkJCQkJcmVzLmVhY2goZnVuY3Rpb24oaSl7DQoJCQkJCQkJCQl2YXIgbGFiZWwgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCXZhciB2YWx1ZSA9IGlbZi5kYlZhbHVlQmluZGluZ10gPT09IHVuZGVmaW5lZCA/IGkuZmJfYXBwZW5kID09PSB1bmRlZmluZWQgPyAnJyA6IGlbMV0gOiBpW2YuZGJWYWx1ZUJpbmRpbmddOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQlsYWJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChsYWJlbCk7DQoJCQkJCQkJCQl2YWx1ZSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7DQoJCQkJCQkJCQkNCgkJCQkJCQkJCWlmKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT0gJycpIHsgdmFsdWUgPSBsYWJlbDsgfQ0KCQkJCQkJCQkJaWYodHlwZW9mKGl0ZW1zLmluZGV4T2YpID09ICd1bmRlZmluZWQnIHx8IGl0ZW1zLmluZGV4T2YodmFsdWUpID09IC0xKXsNCgkJCQkJCQkJCQkvLyBjcmVhdGUgZWxlbWVudA0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCS8vIFByZS1wb3B1bGF0ZSBmcm9tIHByZXZpb3VzIGNhbGwgaWYgcG9zc2libGUuDQoJCQkJCQkJCQkJdmFyIF90ZXN0ID0gIjw/cGhwIGVjaG8gaXNzZXQoXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSkgPyBcJF9TRVNTSU9OWyd7JGZpcnN0X2JvdW5kX2ZpZWxkfSddIDogJycgPz4iOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCXZhciBfY2hlY2tlZCA9IGZhbHNlOw0KCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCWlmKF90ZXN0ICE9ICIiICYmIF90ZXN0ID09IHZhbHVlKXsNCgkJCQkJCQkJCQkJX2NoZWNrZWQgPSB0cnVlOw0KCQkJCQkJCQkJCX0NCgkJCQkJCQkJCQkNCgkJCQkJCQkJCQl2YXIgYSA9IG5ldyBFbGVtZW50KCdpbnB1dCcsIHsgJ3R5cGUnOiAncmFkaW8nLCAndmFsdWUnOiB2YWx1ZSwgJ25hbWUnIDogZi5maWVsZEJpbmRpbmcsICdpZCcgOiBmLmZpZWxkQmluZGluZyArIGlkdCwgY2hlY2tlZDogX2NoZWNrZWQgIH0pOw0KCQkJCQkJCQkJCXZhciBiID0gbmV3IEVsZW1lbnQoJ2xhYmVsJywgeyAnZm9yJzogZi5maWVsZEJpbmRpbmcgKyBpZHQgfSk7IGIudXBkYXRlKGxhYmVsKTsNCgkJCQkJCQkJCQl2YXIgYyA9IG5ldyBFbGVtZW50KCdicicsIHsgfSk7DQoJCQkJCQkJCQkJLy8gYXBwZW5kIHRvIHNwYW4NCgkJCQkJCQkJCQkkKCdmYl9mbGQtJyArIGYuZmllbGRCaW5kaW5nKS5kb3duKCcuZmItbXVsdGlzZWxlY3QtY29sdW1uJykuaW5zZXJ0KGEpOw0KCQkJCQkJCQkJCSQoJ2ZiX2ZsZC0nICsgZi5maWVsZEJpbmRpbmcpLmRvd24oJy5mYi1tdWx0aXNlbGVjdC1jb2x1bW4nKS5pbnNlcnQoYik7DQoJCQkJCQkJCQkJJCgnZmJfZmxkLScgKyBmLmZpZWxkQmluZGluZykuZG93bignLmZiLW11bHRpc2VsZWN0LWNvbHVtbicpLmluc2VydChjKTsNCgkJCQkJCQkJCQlpZHQrKzsNCgkJCQkJCQkJCX0NCgkJCQkJCQkJfS5iaW5kKGYpKTsNCgkJCQkJCQl9DQoJCQkJCQkJYnJlYWs7DQoJCQkJCQkJDQoJCQkJCQljYXNlICdkaXNwbGF5LWVsZW1lbnQnIDogLy8gdXNlZCB3aGVuIGEgbm9uLWZvcm0gZWxlbWVudCBpcyBkZWZpbmVkDQoJCQkJCQkNCgkJCQkJCQl2YXIgX3NlbGVjdG9yUHJlZml4ID0gIiI7DQoNCgkJCQkJCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZChmLmZpZWxkQmluZGluZykgPT0gbnVsbCl7DQoJCQkJCQkJCV9zZWxlY3RvclByZWZpeCA9ICJmYl9mbGQtIjsNCgkJCQkJCQl9DQoNCgkJCQkJCQlpZihjbGVhcl90ZXh0X2ZpZWxkcyl7DQoJCQkJCQkJCSQoX3NlbGVjdG9yUHJlZml4ICsgZi5maWVsZEJpbmRpbmcpLmVtcHR5KCk7DQoJCQkJCQkJfQ0KCQkJCQkJCQ0KCQkJCQkJCWlmKHJlcyAhPSBmYWxzZSl7DQoNCgkJCQkJCQkJdmFyIF9udW1Db2x1bW5zID0gcmVzLmxlbmd0aCAhPSAwID8gT2JqZWN0LmtleXMocmVzWzBdKS5sZW5ndGggLyAyIDogMDsgLy8gRmlyc3QgQ29sdW1uLg0KDQoJCQkJCQkJCXZhciBfY29sdW1uTmFtZXMgPSBbXTsNCg0KCQkJCQkJCQlpZihfbnVtQ29sdW1ucyAhPSAwKXsNCg0KCQkJCQkJCQkJLy8gRm9yIEVhY2ggUHJvcGVydHkgQ2hlY2sgVG8gU2VlIElmIEl0J3MgT3VyIE51bWJlciBJbmRleCBPciBBY3R1YWwgTmFtZS4gDQoNCgkJCQkJCQkJCWZvciAodmFyIHByb3BlcnR5IGluIHJlc1swXSkgew0KDQoJCQkJCQkJCQkJaWYgKHJlc1swXS5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHsNCgkJCQkJCQkJCQkJDQoJCQkJCQkJCQkJCXZhciBfdGVzdCA9IHBhcnNlSW50KHByb3BlcnR5KTsNCg0KCQkJCQkJCQkJCQlpZihfdGVzdCAhPSBwcm9wZXJ0eSl7DQoJCQkJCQkJCQkJCQlfY29sdW1uTmFtZXMucHVzaChwcm9wZXJ0eSk7DQoJCQkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJCX0NCgkJCQkJCQkJCX0NCgkJCQkJCQkJfQ0KDQoJCQkJCQkJCS8vIFN0YXJ0IERpc3BsYXkgV3JhcHBlci4NCg0KCQkJCQkJCQl2YXIgX2h0bWwgPSAnPGRpdiBjbGFzcz0iYWpheC1kaXNwbGF5LXRhYmxlIj4nOw0KDQoJCQkJCQkJCS8vIENyZWF0ZSBDb2x1bW4gSGVhZGVyKHMpLg0KDQoJCQkJCQkJCSQoX2NvbHVtbk5hbWVzKS5lYWNoKGZ1bmN0aW9uKGhlYWRlcil7DQoNCgkJCQkJCQkJCV9odG1sICs9ICc8ZGl2IGNsYXNzPSJhamF4LWRpc3BsYXktaGVhZGVyIj4nICsgZGVjb2RlVVJJQ29tcG9uZW50KGhlYWRlcikgKyAnPC9kaXY+JzsNCg0KCQkJCQkJCQl9KTsNCg0KCQkJCQkJCQkvLyBBZGQgQ2xlYXJpbmcgRGl2IFRvIFNlcGFyYXRlIEhlYWRlciBBbmQgQ29udGVudC4NCg0KCQkJCQkJCQlfaHRtbCArPSAnPGRpdiBjbGFzcz0iYWpheC1kaXNwbGF5LWNsZWFyLWhlYWRlciI+PC9kaXY+JzsNCg0KCQkJCQkJCQkvLyBMb29wIE92ZXIgSXRlbXMsIEFkZCBUbyBNYWluIFRlbXBsYXRlLg0KDQoJCQkJCQkJCSQocmVzKS5lYWNoKGZ1bmN0aW9uKF9pdGVtKXsNCg0KCQkJCQkJCQkJZm9yICh2YXIgcHJvcGVydHkgaW4gX2l0ZW0pIHsNCg0KCQkJCQkJCQkJCWlmIChfaXRlbS5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHsNCg0KCQkJCQkJCQkJCQlpZihfY29sdW1uTmFtZXMuaW5kZXhPZihwcm9wZXJ0eSkgIT0gLTEpew0KDQoJCQkJCQkJCQkJCQlfaHRtbCArPSAnPGRpdiBjbGFzcz0iYWpheC1kaXNwbGF5LWVsZW1lbnQiPicgKyBkZWNvZGVVUklDb21wb25lbnQoX2l0ZW1bcHJvcGVydHldKSArICc8L2Rpdj4nOw0KDQoJCQkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCQlfaHRtbCArPSAnPGRpdiBjbGFzcz0iYWpheC1kaXNwbGF5LWNsZWFyLXJvdyI+PC9kaXY+JzsNCgkJCQkJCQkJCQ0KCQkJCQkJCQl9KTsNCg0KCQkJCQkJCQkvLyBDbG9zZSBEaXNwbGF5IFdyYXBwZXIuDQoNCgkJCQkJCQkJX2h0bWwgPSBfaHRtbCArICc8L2Rpdj4nOyANCg0KCQkJCQkJCQkkKF9zZWxlY3RvclByZWZpeCArIGYuZmllbGRCaW5kaW5nKS51cGRhdGUoX2h0bWwpOw0KCQkJCQkJCX0NCgkNCgkJCQkJCQkvLyBQcmUtcG9wdWxhdGUgZnJvbSBwcmV2aW91cyBjYWxsIGlmIHBvc3NpYmxlLg0KCQkJCQkJCXZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCgkJCQkJCQkNCgkJCQkJCQlpZihfdGVzdCAhPSAiIil7DQoJCQkJCQkJCSQoJ3skZmlyc3RfYm91bmRfZmllbGR9Jykuc2V0VmFsdWUoX3Rlc3QpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQlicmVhazsNCgkJCQkJCQkNCgkJCQkJCWNhc2UgJ2hpZGRlbicgOg0KDQoJCQkJCQkJaWYocmVzICE9PSB1bmRlZmluZWQgJiYgcmVzICE9IGZhbHNlKXsNCgkJCQkJCQkJcmVzLmVhY2goZnVuY3Rpb24oaSl7DQoJCQkJCQkJCQl2YXIgdmFsdWUgPSBpW2YuZGJMYWJlbEJpbmRpbmddID09PSB1bmRlZmluZWQgPyBpWzBdIDogaVtmLmRiTGFiZWxCaW5kaW5nXTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJdmFsdWUgPSBkZWNvZGVVUklDb21wb25lbnQobGFiZWwpOw0KCQkJCQkJCQkJDQoJCQkJCQkJCQkkKGYuZmllbGRCaW5kaW5nKS52YWx1ZSA9IHZhbHVlOw0KCQkJCQkJCQl9LmJpbmQoZikpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQkvLyBQcmUtcG9wdWxhdGUgZnJvbSBwcmV2aW91cyBjYWxsIGlmIHBvc3NpYmxlLg0KCQkJCQkJCXZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCgkJCQkJCQkNCgkJCQkJCQlpZihfdGVzdCAhPSAiIil7DQoJCQkJCQkJCSQoJ3skZmlyc3RfYm91bmRfZmllbGR9Jykuc2V0VmFsdWUoX3Rlc3QpOw0KCQkJCQkJCX0NCgkJCQkJCQkNCgkJCQkJCQlicmVhazsNCgkJCQkJCQ0KCQkJCQkJZGVmYXVsdCA6DQoJCQkJCQkNCgkJCQkJCQlpZihyZXMgIT09IHVuZGVmaW5lZCAmJiByZXMgIT0gZmFsc2Upew0KCQkJCQkJCQlyZXMuZWFjaChmdW5jdGlvbihpKXsNCgkJCQkJCQkJCWxhYmVsID0gaVtmLmRiTGFiZWxCaW5kaW5nXSA9PT0gdW5kZWZpbmVkID8gaVswXSA6IGlbZi5kYkxhYmVsQmluZGluZ107DQoJCQkJCQkJCQkNCgkJCQkJCQkJCWxhYmVsID0gZGVjb2RlVVJJQ29tcG9uZW50KGxhYmVsKTsNCgkJCQkJCQkJCQ0KCQkJCQkJCQkJJChmLmZpZWxkQmluZGluZykudmFsdWUgPSBsYWJlbDsNCgkJCQkJCQkJfS5iaW5kKGYpKTsNCgkJCQkJCQkJDQoJCQkJCQkJCS8vIFByZS1wb3B1bGF0ZSBmcm9tIHByZXZpb3VzIGNhbGwgaWYgcG9zc2libGUuDQoJCQkJCQkJCXZhciBfdGVzdCA9ICI8P3BocCBlY2hvIGlzc2V0KFwkX1NFU1NJT05bJ3skZmlyc3RfYm91bmRfZmllbGR9J10pID8gXCRfU0VTU0lPTlsneyRmaXJzdF9ib3VuZF9maWVsZH0nXSA6ICcnID8+IjsNCgkJCQkJCQkJDQoJCQkJCQkJCWlmKF90ZXN0ICE9ICIiKXsNCgkJCQkJCQkJCSQoJ3skZmlyc3RfYm91bmRfZmllbGR9Jykuc2V0VmFsdWUoX3Rlc3QpOw0KCQkJCQkJCQl9DQoJCQkJCQkJDQoJCQkJCQkJfQ0KCQkJCQkJCWJyZWFrOw0KCQkJCQl9DQoJCQkJCQ0KCQkJCX0gLy8gaWYgYmluZGluZw0KCQkJCQ0KCQkJfSk7IC8vIGVhY2gNCgkJCQ0KCQkJLy8gdXNlciBjb2RlIGFmdGVyIHF1ZXJ5DQoJCQl7JGZpZWxkLT5hamF4X2NvZGVfYWZ0ZXJfcXVlcnl9DQoJCX0sDQoJCQ0KCQkvLyBCdWlsZCA3NDcNCgkJb25FeGNlcHRpb246IGZ1bmN0aW9uKGUsIGV4Y2VwdGlvbk9iamVjdCl7DQoJCQ0KCQkJZXJyb3JfbW9kZSA9IHskYWpheF9lcnJvcl9tb2RlfTsNCgkJDQoJCQlpZihlcnJvcl9tb2RlKXsNCgkJCQltZXNzYWdlID0gJ0FKQVggRXhjZXB0aW9uOiAnICsgZXhjZXB0aW9uT2JqZWN0Lm1lc3NhZ2U7DQoJCQkJbWVzc2FnZSArPSAnXFxuXFxuWW91IG1heSB3aXNoIHRvIGVuYWJsZSB5b3VyIGJyb3dzZXJzIENvbnNvbGUgdG8gc2VlIGEgbW9yZSBkZXRhaWxlZCByZWFzb24gd2h5IHRoaXMgZXJyb3Igb2NjdXJyZWQuICc7DQoJCQkJbWVzc2FnZSArPSAnRm9yIG1vc3QgYnJvd3NlcnMgdGhpcyBpcyB0aGUgRjEyIGtleSwgb3IgaWYgaW4gRmlyZWZveCB3aXRoIEZpcmVidWcgaW5zdGFsbGVkLCBieSB1c2luZyBGaXJlYnVnXCdzIENvbnNvbGUuJzsNCgkJCQltZXNzYWdlICs9ICdcXG5cXG5Gb3JtIENyZWF0b3JzOiBUaGlzIGNsYXNzIG9mIGlzc3VlIHVzdWFsbHkgaW5kaWNhdGVzIGEgZGF0YWJhc2UgZXJyb3IuJzsNCgkJCQltZXNzYWdlICs9ICdcXG5cXG5QbGVhc2UgY2hlY2sgeW91ciBTUUwgQ29kZSBibG9jayB0byBlbnN1cmUgYSBwcm9wZXIgcXVlcnksIGFuZCBpZiBiZWluZyB1c2VkLCB0aGUgRGF0YSBTb3VyY2UgcHJvcGVydGllcyBmb3IgcHJvcGVyIGNvbm5lY3Rpb24gZGV0YWlscy4nOw0KCQkJCWFsZXJ0KG1lc3NhZ2UpOyAvLyBlcnJvciwgZXhjZXB0aW9uIG1lc3NhZ2UNCgkJCX0NCgkJCQkJDQoJCX0NCgkJCQ0KCX0pOyAvLyBhamF4IGNhbGwNCn0NCg0KPC9zY3JpcHQ+DQoNCg0KRU9GOw0KICAgICAgICB9IA0KDQoNCiAgICAgICAgDQogICAgICAgICRsaWJfY29kZSA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+ZGJkc24pKSB7DQogICAgICAgICAgICAkZmllbGQtPmRiZHNuID0gIiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkYWpheF9pZ25vcmVfZmlyc3QgPSAiZmFsc2UiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmFqYXhfaWdub3JlX2ZpcnN0KSAmJiAkZmllbGQtPmFqYXhfaWdub3JlX2ZpcnN0ID09ICIxIikgew0KICAgICAgICAgICAgJGFqYXhfaWdub3JlX2ZpcnN0ID0gInRydWUiOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCg0KICAgICAgICAkZGJob3N0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGQtPmRiaG9zdCwgOCk7DQogICAgICAgICRkYnNvY2tldCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGZpZWxkLT5kYnNvY2tldCwgOCk7DQogICAgICAgICRkYnBvcnQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJwb3J0LCA4KTsNCiAgICAgICAgJGRiZHNuID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGQtPmRiZHNuLCA4KTsNCiAgICAgICAgJGRidXNlciA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGZpZWxkLT5kYnVzZXIsIDgpOw0KICAgICAgICAkZGJwd2QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJwd2QsIDgpOw0KICAgICAgICAkZGJzY2hlbWEgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJzY2hlbWEsIDgpOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkbGliX2NvZGUgLj0gPDw8RU9UDQo8P3BocA0KLyoqDQogKiBSYWNrRm9ybXMgRm9ybSBMaWJyYXJ5IEZpbGVzIC0gZmJfYWpheF97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fS5waHANCiAqIEB2ZXJzaW9uIDEuNw0KICogQGF1dGhvciBSYWNrRm9ybXMNCiAqIEBjYXRlZ29yeSBEYXRhYmFzZQ0KICogQG5hbWUgZmJfYWpheF97JGZpZWxkLT5hamF4X3NvdXJjZV9maWVsZH1feyRiaW5kX2luZGV4fS5waHANCiAqLw0KIA0KaWYoIXNlc3Npb25faWQoKSkgeyBzZXNzaW9uX3N0YXJ0KCk7IH0NCiANCmlmKGZ1bmN0aW9uX2V4aXN0cygnaW5pX3NldCcpKXsNCglpbmlfc2V0KCdkaXNwbGF5X2Vycm9ycycsIDApOyAvLyBDaGFuZ2UgdG8gMSB0byBkaXNwbGF5IGFsbCBlcnJvciBtZXNzYWdlcy4NCglpbmlfc2V0KCdlcnJvcl9yZXBvcnRpbmcnLCBFX0FMTCk7DQp9DQoJDQppbmNsdWRlICcuLi91dGlsaXR5LnBocCc7DQoNClwkYXJnMSA9IGlzc2V0KFwkX1BPU1RbJ2FyZzEnXSkgJiYgXCRfUE9TVFsnYXJnMSddICE9ICcnID8gXCRfUE9TVFsnYXJnMSddIDogLTE7DQpcJGFyZzIgPSBpc3NldChcJF9QT1NUWydhcmcyJ10pICYmIFwkX1BPU1RbJ2FyZzInXSAhPSAnJyA/IFwkX1BPU1RbJ2FyZzInXSA6ICcnOw0KXCRhcmczID0gaXNzZXQoXCRfUE9TVFsnYXJnMyddKSAmJiBcJF9QT1NUWydhcmczJ10gIT0gJycgPyBcJF9QT1NUWydhcmczJ10gOiAnJzsNClwkYXJnNCA9IGlzc2V0KFwkX1BPU1RbJ2FyZzQnXSkgJiYgXCRfUE9TVFsnYXJnNCddICE9ICcnID8gXCRfUE9TVFsnYXJnNCddIDogJyc7DQpcJGFyZzUgPSBpc3NldChcJF9QT1NUWydhcmc1J10pICYmIFwkX1BPU1RbJ2FyZzUnXSAhPSAnJyA/IFwkX1BPU1RbJ2FyZzUnXSA6ICcnOw0KDQpcJGFjdGlvbiA9IGlzc2V0KFwkX1BPU1RbJ2FjdGlvbiddKSA/IFwkX1BPU1RbJ2FjdGlvbiddIDogLTE7DQoNCmlmKFwkYXJnMSAhPSAtMSl7DQoJDQoJXCRkYl9ob3N0ID0gInskZGJob3N0fSI7DQoJXCRkYl90eXBlID0gInskdGhpcy0+dW0tPnRyYW5zbGF0ZVNvdXJjZVR5cGUoJGZpZWxkLT5zb3VyY2V0eXBlKX0iOw0KCVwkbXlzcWxfc29ja2V0ID0gInskZGJzb2NrZXR9IjsNCglcJG15c3FsX3BvcnQgPSAieyRkYnBvcnR9IjsNCglcJGRiZHNuID0gInskZGJkc259IjsNCglcJGRiX3VzZXIgPSAieyRkYnVzZXJ9IjsNCglcJGRiX3Bhc3MgPSAieyRkYnB3ZH0iOw0KCVwkZGJfY2F0YWxvZyA9ICJ7JGRic2NoZW1hfSI7DQoJXCRyZXR1cm5fdHJ1ZSA9IDA7DQoJDQoJXCRkYl9zc2xfa2V5ID0gJ3skZmllbGQtPmRic3Nsa2V5fSc7DQoJXCRkYl9zc2xfY2VydGlmaWNhdGUgPSAneyRmaWVsZC0+ZGJzc2xjZXJ0aWZpY2F0ZX0nOw0KCVwkZGJfc3NsX2NhX2NlcnQgPSAneyRmaWVsZC0+ZGJzc2xjYWNlcnR9JzsNCglcJGRiX3NzbF92ZXJpZnlfY2VydCA9ICd7JGZpZWxkLT5kYnNzbHZlcmlmeWNlcnR9JzsNCglcJGRiX3NzbF9jaXBoZXIgPSAneyRmaWVsZC0+ZGJzc2xjaXBoZXJ9JzsNCgkNCglcJGRlYnVnID0geyRmaWVsZC0+cXVlcnlfZGVidWdfbGV2ZWx9Ow0KCQ0KCVwkaWdub3JlX2ZpcnN0X3BhcmFtID0geyRhamF4X2lnbm9yZV9maXJzdH07DQoJDQoJXCRzcWwgPSAieyRmaWVsZC0+cXVlcnlfc3FsfSI7DQoJDQoJLy8gcGFyYW1ldGVycw0KCVwkYXJncyA9IGFycmF5KCk7DQoNCgkvLyBhbHdheXMgcHVzaCBiYXNlIHBhcmFtZXRlciBpZiBhc2tlZA0KCWlmKFwkaWdub3JlX2ZpcnN0X3BhcmFtICE9IHRydWUpDQoJCWFycmF5X3B1c2goXCRhcmdzLCBcJGFyZzEpOw0KCQ0KCS8vIHB1c2ggZXh0cmEgcGFyYW1ldGVycyBhcyBuZWVkZWQNCglcJGN0ID0gc3Vic3RyX2NvdW50KFwkc3FsLCAnPycpOw0KCQ0KCS8vIGlmIHdlIGlnbm9yZSBmaXJzdCBwYXJhbSwgaW5jcmVtZW50IGN0DQoJaWYoXCRpZ25vcmVfZmlyc3RfcGFyYW0pDQoJCVwkY3QrKzsNCgkNCglpZihcJGN0ID4gMSl7IGFycmF5X3B1c2goXCRhcmdzLCBcJGFyZzIpOyB9DQoJaWYoXCRjdCA+IDIpeyBhcnJheV9wdXNoKFwkYXJncywgXCRhcmczKTsgfQ0KCWlmKFwkY3QgPiAzKXsgYXJyYXlfcHVzaChcJGFyZ3MsIFwkYXJnNCk7IH0NCglpZihcJGN0ID4gNCl7IGFycmF5X3B1c2goXCRhcmdzLCBcJGFyZzUpOyB9DQoJDQoJXCRwYXJhbXMgPSBcJGFyZ3M7DQoJDQoJaW5jbHVkZSAnLi4vLi4vRGF0YWJhc2UucGhwJzsNCgkNCgkvLyBPcHRpb25hbCBjb25uZWN0b3Igc2NyaXB0IC0gbm90ZSB3ZSBhdXRvbWF0aWNhbGx5IGJhY2sgdXAgdHdvIGRpcmVjdG9yaWVzLCB3aGljaCBkaWZmZXJzIGZyb20gb3RoZXIgY2FsbHMuDQoJXCRjb25uZWN0b3IgPSAiLi4vLi4veyRmaWVsZC0+ZGJjb25uZWN0b3J9IjsNCglpZihcJGNvbm5lY3RvciAhPSAiLi4vLi4vIiAmJiBmaWxlX2V4aXN0cyhcJGNvbm5lY3Rvcikpew0KCQlAaW5jbHVkZSBcJGNvbm5lY3RvcjsNCgl9DQoNCglcJGRiaCA9IG5ldyBEYXRhYmFzZSgpOw0KDQoJc3dpdGNoKFwkYWN0aW9uKXsNCgkNCgkJY2FzZSAnc3RkJyA6DQoJCQ0KCQkJLy8gU2V0IE9wdGlvbmFsIE15U1FMIFNTTCBQcm9wZXJ0aWVzLg0KCQ0KCQkJXCRkYmgtPnNldE15U1FMU1NMUHJvcGVydGllcyhcJGRiX3NzbF9rZXksIFwkZGJfc3NsX2NlcnRpZmljYXRlLCBcJGRiX3NzbF9jYV9jZXJ0LCBcJGRiX3NzbF92ZXJpZnlfY2VydCwgXCRkYl9zc2xfY2lwaGVyKTsNCgkJDQoJCQlcJHJlc3VsdCA9IFwkZGJoLT5wZG9fcHJvY2VkdXJlX3BhcmFtcyhcJGRlYnVnLA0KCQkJCQkJCQkJCQkJCVwkc3FsLA0KCQkJCQkJCQkJCQkJCVwkZGJfaG9zdCwNCgkJCQkJCQkJCQkJCQlcJGRiX3R5cGUsDQoJCQkJCQkJCQkJCQkJXCRteXNxbF9zb2NrZXQsDQoJCQkJCQkJCQkJCQkJXCRteXNxbF9wb3J0LA0KCQkJCQkJCQkJCQkJCVwkZGJkc24sDQoJCQkJCQkJCQkJCQkJXCRkYl91c2VyLA0KCQkJCQkJCQkJCQkJCVwkZGJfcGFzcywNCgkJCQkJCQkJCQkJCQlcJGRiX2NhdGFsb2csDQoJCQkJCQkJCQkJCQkJXCRwYXJhbXMsDQoJCQkJCQkJCQkJCQkJXCRyZXR1cm5fdHJ1ZSk7DQoJCQkNCg0KICAgICAgICAgICAgaWYoXCRyZXN1bHQgPT0gZmFsc2Upew0KICAgICAgICAgICAgICAgIGhlYWRlcignQ2FjaGUtQ29udHJvbDogbm8tY2FjaGUsIG11c3QtcmV2YWxpZGF0ZScpOw0KICAgICAgICAgICAgICAgIGhlYWRlcignRXhwaXJlczogTW9uLCAyNiBKdWwgMTk5NyAwNTowMDowMCBHTVQnKTsNCiAgICAgICAgICAgICAgICBoZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vanNvbicpOwkNCiAgICAgICAgICAgICAgICBlY2hvICJbXSI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICB9DQoNCgkJCVwkYXBwZW5kID0gIiI7DQoJCQlzd2l0Y2goKGludCl7JGZpZWxkLT5xdWVyeV9hcHBlbmRfcG9zaXRpb259KSB7DQoJCQkJY2FzZSAxIDoNCgkJCQkJXCRhcHBlbmQgPSBhcnJheV91bnNoaWZ0KFwkcmVzdWx0LCBhcnJheSgwPT4neyRmaWVsZC0+cXVlcnlfYXBwZW5kX2xhYmVsfScsIDE9Pid7JGZpZWxkLT5xdWVyeV9hcHBlbmRfdmFsdWV9JywgJ2ZiX2FwcGVuZCc9Pid0cnVlJykpOw0KCQkJCQlicmVhazsNCgkJCQljYXNlIDIgOg0KCQkJCQlcJGFwcGVuZCA9IGFycmF5X3B1c2goXCRyZXN1bHQsIGFycmF5KDA9Pid7JGZpZWxkLT5xdWVyeV9hcHBlbmRfbGFiZWx9JywgMT0+J3skZmllbGQtPnF1ZXJ5X2FwcGVuZF92YWx1ZX0nLCAnZmJfYXBwZW5kJz0+J3RydWUnKSk7DQoJCQkJCWJyZWFrOw0KCQkJfQ0KDQoJCQkvLyBCdWlsZCA3ODkgLSBFbmNvZGUgT3V0cHV0Lg0KCQkJZm9yZWFjaChcJHJlc3VsdCBhcyBcJG91dGVyX2tleT0+XCRyb3cpew0KDQoJCQkJZm9yZWFjaChcJHJvdyBhcyBcJGlubmVyX2tleT0+XCRmaWVsZCl7DQoJCQkJCQkNCgkJCQkJLy8gRW5jb2RlIEl0ZW1zDQoJCQkJCVwkcmVzdWx0WyJ7XCRvdXRlcl9rZXl9Il1bIntcJGlubmVyX2tleX0iXSA9IHJhd3VybGVuY29kZShcJHJlc3VsdFsie1wkb3V0ZXJfa2V5fSJdWyJ7XCRpbm5lcl9rZXl9Il0pOw0KCQkJCQkJDQoJCQkJfQ0KCQkJDQoJCQl9DQoJCQ0KCQkJaGVhZGVyKCdDYWNoZS1Db250cm9sOiBuby1jYWNoZSwgbXVzdC1yZXZhbGlkYXRlJyk7DQoJCQloZWFkZXIoJ0V4cGlyZXM6IE1vbiwgMjYgSnVsIDE5OTcgMDU6MDA6MDAgR01UJyk7DQoJCQloZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vanNvbicpOwkJCQ0KCQkJZWNobyBwaHBfanNvbl9lbmNvZGUoXCRyZXN1bHQpOw0KCQkJYnJlYWs7DQoJCQkNCgkJY2FzZSAncHJvYycgOg0KCQkNCgkJCWlmKCFzZXNzaW9uX2lkKCkpIHsgc2Vzc2lvbl9zdGFydCgpOyB9DQoJCQkJCQkJDQoJCQkvLyBTZXQgT3B0aW9uYWwgTXlTUUwgU1NMIFByb3BlcnRpZXMuDQoJDQoJCQlcJGRiaC0+c2V0TXlTUUxTU0xQcm9wZXJ0aWVzKFwkZGJfc3NsX2tleSwgXCRkYl9zc2xfY2VydGlmaWNhdGUsIFwkZGJfc3NsX2NhX2NlcnQsIFwkZGJfc3NsX3ZlcmlmeV9jZXJ0LCBcJGRiX3NzbF9jaXBoZXIpOw0KCQkJDQoJCQlcJHJlc3VsdCA9IFwkZGJoLT5wZG9fcHJvY2VkdXJlX3BhcmFtcyhcJGRlYnVnLA0KCQkJCQkJCQkJCQkJCVwkc3FsLA0KCQkJCQkJCQkJCQkJCVwkZGJfaG9zdCwNCgkJCQkJCQkJCQkJCQlcJGRiX3R5cGUsDQoJCQkJCQkJCQkJCQkJXCRteXNxbF9zb2NrZXQsDQoJCQkJCQkJCQkJCQkJXCRteXNxbF9wb3J0LA0KCQkJCQkJCQkJCQkJCVwkZGJkc24sDQoJCQkJCQkJCQkJCQkJXCRkYl91c2VyLA0KCQkJCQkJCQkJCQkJCVwkZGJfcGFzcywNCgkJCQkJCQkJCQkJCQlcJGRiX2NhdGFsb2csDQoJCQkJCQkJCQkJCQkJXCRwYXJhbXMsDQoJCQkJCQkJCQkJCQkJXCRyZXR1cm5fdHJ1ZSk7DQoJCQkNCgkJCQ0KCQkJLy8gcHJvY2VzcyByZXN1bHQgdG9rZW5zDQoNCgkJCVwkbWF0Y2hlcyA9IGFycmF5KCk7DQoNCgkJCWZvcmVhY2goXCRyZXN1bHQgYXMgXCRvdXRlcl9rZXk9Plwkcm93KXsNCg0KCQkJCWZvcmVhY2goXCRyb3cgYXMgXCRpbm5lcl9rZXk9PlwkZmllbGQpew0KCQkJCQkNCgkJCQkJLy8gZm9ybSBmaWVsZHMNCgkJCQkJDQoJCQkJCXByZWdfbWF0Y2hfYWxsKCcvKF58LnxcXHJ8XFxuKShGXHsoLio/KVxcfSkvJywgXCRmaWVsZCwgXCRtYXRjaGVzKTsNCgkJDQoJCQkJCVwkYXJyYXlfdmFycyA9IGFycmF5KCk7DQoJCQkJCWlmKGlzc2V0KFwkbWF0Y2hlc1szXSkpew0KCQkJCQkJZm9yZWFjaChcJG1hdGNoZXNbM10gYXMgXCRtKXsNCgkJCQkJCQlcJHJlc3VsdFsie1wkb3V0ZXJfa2V5fSJdWyJ7XCRpbm5lcl9rZXl9Il0gPSBzdHJfcmVwbGFjZSgnRnsnLlwkbS4nfScsIFwkX1NFU1NJT05bJ2VudHJ5X2tleSddWyJ7XCRtfSJdLCBcJGZpZWxkKTsNCgkJCQkJCX0NCgkJCQkJfQ0KCQkJCQkNCgkJCQkJDQoJCQkJCS8vIHNlc3Npb24gZWxlbWVudHMNCgkJCQkJDQoJCQkJCXByZWdfbWF0Y2hfYWxsKCcvKF58LnxcXHJ8XFxuKShTXHsoLio/KVxcfSkvJywgXCRmaWVsZCwgXCRtYXRjaGVzKTsNCgkJDQoJCQkJCVwkYXJyYXlfdmFycyA9IGFycmF5KCk7DQoJCQkJCWlmKGlzc2V0KFwkbWF0Y2hlc1szXSkpew0KCQkJCQkJZm9yZWFjaChcJG1hdGNoZXNbM10gYXMgXCRtKXsNCgkJCQkJCQlcJHJlc3VsdFsie1wkb3V0ZXJfa2V5fSJdWyJ7XCRpbm5lcl9rZXl9Il0gPSBzdHJfcmVwbGFjZSgnU3snLlwkbS4nfScsIFwkX1NFU1NJT05bIntcJG19Il0sIFwkZmllbGQpOw0KCQkJCQkJfQ0KCQkJCQl9DQoJCQkJCQkJDQoJCQkJCS8vIEJ1aWxkIDc4OSAtIEVuY29kZSBJdGVtcw0KCQkJCQlcJHJlc3VsdFsie1wkb3V0ZXJfa2V5fSJdWyJ7XCRpbm5lcl9rZXl9Il0gPSByYXd1cmxlbmNvZGUoXCRyZXN1bHRbIntcJG91dGVyX2tleX0iXVsie1wkaW5uZXJfa2V5fSJdKTsNCgkJCQkJDQoJCQkJfQ0KCQkJCQ0KCQkJfQ0KCQkJCQ0KDQoJCQloZWFkZXIoJ0NhY2hlLUNvbnRyb2w6IG5vLWNhY2hlLCBtdXN0LXJldmFsaWRhdGUnKTsNCgkJCWhlYWRlcignRXhwaXJlczogTW9uLCAyNiBKdWwgMTk5NyAwNTowMDowMCBHTVQnKTsNCgkJCWhlYWRlcignQ29udGVudC10eXBlOiBhcHBsaWNhdGlvbi9qc29uJyk7CQkJDQoJCQllY2hvIHBocF9qc29uX2VuY29kZShcJHJlc3VsdCk7DQoJCQkNCgkJCWJyZWFrOw0KDQoJfQ0KCQ0KCWV4aXQoMCk7DQoNCn0gZWxzZSB7DQoJZXhpdCgwKTsJDQp9DQoNCj8+DQoJDQpFT1Q7DQoNCiAgICAgICAgDQogICAgICAgIGZpbGVfcHV0X2NvbnRlbnRzKCRqb2JwYXRoIC4gImZiX2FqYXhfeyRmaWVsZC0+YWpheF9zb3VyY2VfZmllbGR9X3skYmluZF9pbmRleH0ucGhwIiwgJGxpYl9jb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAkcGFnZV9jb2RlOw0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgICAgIA0KICAgIH0gDQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9jYWxjdWxhdGlvbigkZmllbGQsICRwYWdlKQ0KICAgIHsNCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5saWJyYXJ5KSB8fCAkZmllbGQtPmxpYnJhcnkgPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZC0+bGlicmFyeSA9ICdqcXVlcnknOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkbnVtYmVydHlwZSA9IGlzc2V0KCRmaWVsZC0+bnVtYmVydHlwZSkgPyAkZmllbGQtPm51bWJlcnR5cGUgOiAiMCI7DQogICAgICAgICRudW1iZXJ0eXBlVmFsdWUgPSAiaW50IjsNCg0KICAgICAgICBpZiAoJG51bWJlcnR5cGUgPT0gIjAiKSB7DQogICAgICAgICAgICAkbnVtYmVydHlwZVZhbHVlID0gIkludCI7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoJG51bWJlcnR5cGUgPT0gIjEiKSB7DQogICAgICAgICAgICAkbnVtYmVydHlwZVZhbHVlID0gIkZsb2F0IjsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkZmllbGQtPmxpYnJhcnkgPT0gImpxdWVyeSIpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZXF1YXRpb24gPSAkZmllbGQtPmVxdWF0aW9uOw0KICAgICAgICAgICAgJGRlc3RpbmF0aW9uX2Zvcm1fZmllbGQgPSAkZmllbGQtPmRlc3RpbmF0aW9uX2Zvcm1fZmllbGQ7DQogICAgICAgICAgICAkZGVzdGluYXRpb25fcGhwX3ZhciA9ICRmaWVsZC0+ZGVzdGluYXRpb25fcGhwX3ZhcjsNCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCg0KICAgICAgICAgICAgJHRva2VucyA9IGFycmF5KCk7DQoNCiAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgPSAiXG4vLyBFcXVhdGlvbiBQYXJhbWV0ZXJzIjsNCiAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlID0gJGVxdWF0aW9uOw0KDQogICAgICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pPyhGXHsoLio/KVx9KS8nLCAoc3RyaW5nKSRlcXVhdGlvbiwgJG1hdGNoZXMpOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRmaWx0ZXIgPSAiIjsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdWzBdKSkgew0KDQogICAgICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJGluZGV4ID0+ICRtYXRjaCkgew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdHlwZSA9ICIiOw0KDQogICAgICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRwYWdlLT5mb3JtLT5maWVsZCBhcyAkZikgew0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGYtPmlkKSAmJiAkbWF0Y2ggPT0gKHN0cmluZykkZi0+aWQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZigoc3RyaW5nKSRmLT50eXBlICE9ICJ0ZXh0IiAmJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdHJpbmcpJGYtPnR5cGUgIT0gInNlbGVjdCIgJiYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0cmluZykkZi0+dHlwZSAhPSAicmFkaW8iICYmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdHJpbmcpJGYtPnR5cGUgIT0gImNoZWNrYm94IiAmJiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RyaW5nKSRmLT50eXBlICE9ICJ0ZXh0YXJlYSIgJiYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0cmluZykkZi0+dHlwZSAhPSAiY2FsZW5kYXIiKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0eXBlID0gKHN0cmluZykkZi0+dHlwZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZiAoJGluZGV4ID09IDApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfcGFyYW10ZXJzIC49ICJcbnskbWF0Y2h9ID0gMDsiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSA9IHN0cl9yZXBsYWNlKCdGeycgLiAkbWF0Y2ggLiAnfScsICRtYXRjaCwgJGVxdWF0aW9uX2pzX2NvZGUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKCR0eXBlKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd0ZXh0JzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSAiXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjeyRtYXRjaH0nKS52YWwoKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjeyRtYXRjaH0nKS52YWwoKSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0JzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSAiXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjeyRtYXRjaH0nKS52YWwoKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjeyRtYXRjaH0nKS52YWwoKSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyYWRpbyc6IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfcGFyYW10ZXJzIC49IDw8PEVPRg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQovLyBsb29wIHRob3VnaCByYWRpbyBpdGVtcyB1bnRpbCBhY3RpdmUgdmFsdWUgaXMgZm91bmQNCnskbWF0Y2h9ID0gMDsgLy8gZGVmYXVsdA0KZm9yKGkgPSAwOyBpIDwgMTAwMDsgaSsrKXsNCglpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRtYXRjaH0nICsgaSkgIT09IG51bGwpew0KCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRtYXRjaH0nICsgaSkuY2hlY2tlZCl7DQoJCQl7JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjeyRtYXRjaH0nICsgaSkudmFsKCkpKSA/IDAgOiBwYXJzZXskbnVtYmVydHlwZVZhbHVlfShcJCgnI3skbWF0Y2h9JyArIGkpLnZhbCgpKTsNCgkJCQ0KCQkJYnJlYWs7DQoJCX0NCgl9DQp9DQpFT0Y7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnY2hlY2tib3gnOiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSA8PDxFT0YNCg0KLy8gbG9vcCB0aG91Z2ggY2hlY2tib3ggaXRlbXMgdW50aWwgYWxsIGFjdGl2ZSB2YWx1ZSBhcmUgZm91bmQNCnskbWF0Y2h9ID0gMDsgLy8gZGVmYXVsdA0KZm9yKGkgPSAwOyBpIDwgMTAwMDsgaSsrKXsNCglpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRtYXRjaH0nICsgaSkgIT09IG51bGwpew0KCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRtYXRjaH0nICsgaSkuY2hlY2tlZCl7DQoJCQl7JG1hdGNofSArPSBpc05hTihwYXJzZXskbnVtYmVydHlwZVZhbHVlfShcJCgnI3skbWF0Y2h9JyArIGkpLnZhbCgpKSkgPyAwIDogcGFyc2V7JG51bWJlcnR5cGVWYWx1ZX0oXCQoJyN7JG1hdGNofScgKyBpKS52YWwoKSk7DQoJCX0NCgl9DQp9DQpFT0Y7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3RleHRhcmVhJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSAiXG57JG1hdGNofSA9IFwkKCcjeyRtYXRjaH0nKS52YWwoKS5zcGxpdCgvW1xzXC4sO10rLykubGVuZ3RoOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NhbGVuZGFyJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSAiXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkKCcjZGF0ZS17JG1hdGNofS0xJykudmFsKCkpKSA/IDAgOiBwYXJzZXskbnVtYmVydHlwZVZhbHVlfShcJCgnI3skbWF0Y2h9JykudmFsKCkpOyI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSA8PDxFT0YNClxuDQovLyBDaGVjayBmb3IgZGF0ZSB2YWx1ZSBhbmQgdXNlIGlmIHZhbGlkLg0KaWYoIWlzTmFOKERhdGUucGFyc2UoIFwkKCcjZGF0ZS17JG1hdGNofS0xJykudmFsKCkgKSkgKXsNCgl7JG1hdGNofSA9IERhdGUucGFyc2UoIFwkKCcjZGF0ZS17JG1hdGNofS0xJykudmFsKCkgKTsNCn0NCgkJCQkJCQkJDQpFT0Y7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX3BhcmFtdGVycyAuPSAiXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KDw/cGhwIGVjaG8gXCRfU0VTU0lPTlsneyRtYXRjaH0nXTsgPz4pKSA/IDAgOiBwYXJzZXskbnVtYmVydHlwZVZhbHVlfSg8P3BocCBlY2hvIFwkX1NFU1NJT05bJ3skbWF0Y2h9J107ID8+KTsiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgPSBzdHJfcmVwbGFjZSgnRnsnIC4gJG1hdGNoIC4gJ30nLCAkbWF0Y2gsICRlcXVhdGlvbl9qc19jb2RlKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdG9rZW5zW10gPSBhcnJheSgnbmFtZScgPT4gKHN0cmluZykkbWF0Y2gsICd0eXBlJyA9PiAoc3RyaW5nKSR0eXBlKTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIHN3aXRjaCAoKGludCkkZmllbGQtPmVxdWF0aW9uX2ZpbHRlcikgew0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IE1hdGguZmxvb3IoeyRtYXRjaGVzWzNdWzBdfSk7DQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gTWF0aC5jZWlsKHskbWF0Y2hlc1szXVswXX0pOw0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICBjYXNlICczJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gTWF0aC5yb3VuZCh7JG1hdGNoZXNbM11bMF19KTsNCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gRkJfQ2FsY3VsYXRpb24uZm9ybWF0X0N1cnJlbmN5X1VTKHskbWF0Y2hlc1szXVswXX0pOw0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnNSc6DQogICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IEZCX0NhbGN1bGF0aW9uLmZvcm1hdF9DdXJyZW5jeV9HQlAoeyRtYXRjaGVzWzNdWzBdfSk7DQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgJzYnOg0KICAgICAgICAgICAgICAgICAgICAgICAgJGZpbHRlciA9IDw8PEVPRg0KXG5cbi8vIGZpbHRlciByZXN1bHQNCnskbWF0Y2hlc1szXVswXX0gPSBGQl9DYWxjdWxhdGlvbi5mb3JtYXRfQ3VycmVuY3lfRXVybyh7JG1hdGNoZXNbM11bMF19KTsNCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnNyc6DQogICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IE1hdGgucm91bmQoeyRtYXRjaGVzWzNdWzBdfSAqIDEwKSAvIDEwOw0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICBjYXNlICc4JzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IHskbWF0Y2hlc1szXVswXX0udG9GaXhlZCgyKTsNCkVPRjsNCiAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgLj0gJGZpbHRlcjsNCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICghaXNzZXQoJHRva2Vuc1swXSkpIHsNCiAgICAgICAgICAgICAgICByZXR1cm47DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBzd2l0Y2ggKCR0b2tlbnNbMF1bJ3R5cGUnXSkgew0KDQogICAgICAgICAgICAgICAgY2FzZSAndGV4dCc6DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZmllbGQtPmVxdWF0aW9uX2ZpbHRlciA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSAuPSA8PDxFT0YNClxuXG4vLyBTZXQgdGV4dCBmaWVsZCBpdGVtIHdpdGggdmFsdWUuDQp2YXIgX3ZhbCA9IGlzTmFOKHskdG9rZW5zWzBdWyduYW1lJ119KSA/ICcnIDogeyR0b2tlbnNbMF1bJ25hbWUnXX07DQpcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykudmFsKF92YWwpOw0KXCQoJyN7JHRva2Vuc1swXVsnbmFtZSddfScpLnRyaWdnZXIoJ2NoYW5nZScpOyANCkVPRjsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlIC49IDw8PEVPRg0KXG5cbi8vIHNldCB0ZXh0IGZpZWxkIGl0ZW0gd2l0aCB2YWx1ZQ0KXCQoJyN7JHRva2Vuc1swXVsnbmFtZSddfScpLnZhbCh7JHRva2Vuc1swXVsnbmFtZSddfSk7DQpcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykudHJpZ2dlcignY2hhbmdlJyk7IA0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICBjYXNlICdoaWRkZW4nOg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5lcXVhdGlvbl9maWx0ZXIgPT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgLj0gPDw8RU9GDQpcblxuLy8gc2V0IGhpZGRlbiBmaWVsZCBpdGVtIHdpdGggdmFsdWUNCnZhciBfdmFsID0gaXNOYU4oeyR0b2tlbnNbMF1bJ25hbWUnXX0pID8gJycgOiB7JHRva2Vuc1swXVsnbmFtZSddfTsNClwkKCcjeyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWwoX3ZhbCk7DQpcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykudHJpZ2dlcignY2hhbmdlJyk7IA0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgLj0gPDw8RU9GDQpcblxuLy8gc2V0IGhpZGRlbiBmaWVsZCBpdGVtIHdpdGggdmFsdWUNClwkKCcjeyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWwoeyR0b2tlbnNbMF1bJ25hbWUnXX0pOw0KXCQoJyN7JHRva2Vuc1swXVsnbmFtZSddfScpLnRyaWdnZXIoJ2NoYW5nZScpOyANCkVPRjsNCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBkZWZhdWx0Og0KDQogICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+ZXF1YXRpb25fZmlsdGVyID09IDApIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgLj0gPDw8RU9GDQpcblxuLy8gc2V0IGRlZmF1bHQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQp2YXIgX3ZhbCA9IGlzTmFOKHskdG9rZW5zWzBdWyduYW1lJ119KSA/ICcnIDogeyR0b2tlbnNbMF1bJ25hbWUnXX07DQppZihcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykudmFsdWUgPT09IHVuZGVmaW5lZCl7DQoJXCQoJyN7JHRva2Vuc1swXVsnbmFtZSddfScpLmh0bWwoX3ZhbCk7DQp9IGVsc2Ugew0KCVwkKCcjeyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWwoX3ZhbCk7DQp9DQpcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykudHJpZ2dlcignY2hhbmdlJyk7IA0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgLj0gPDw8RU9GDQpcblxuLy8gc2V0IGRlZmF1bHQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQoNCmlmKFwkKCcjeyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWx1ZSA9PT0gdW5kZWZpbmVkKXsNCglcJCgnI3skdG9rZW5zWzBdWyduYW1lJ119JykuaHRtbCh7JHRva2Vuc1swXVsnbmFtZSddfSk7DQp9IGVsc2Ugew0KCVwkKCcjeyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWwoeyR0b2tlbnNbMF1bJ25hbWUnXX0pOw0KfQ0KXCQoJyN7JHRva2Vuc1swXVsnbmFtZSddfScpLnRyaWdnZXIoJ2NoYW5nZScpOyANCg0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRvbV9vYnNlcnZlID0gPDw8RU9GDQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCi8vIERPTSBPYnNlcnZlIENhbGxzIEZvciBSYWNrRm9ybXMgRmllbGQgQ2FsY3VsYXRpb25zLg0KJCggZG9jdW1lbnQgKS5yZWFkeShmdW5jdGlvbigpIHsNCgkvLyBiaW5kIGV2ZW50IGxpc3RlbmVyKHMpDQpFT0Y7DQoNCiAgICAgICAgICAgIGZvcmVhY2ggKCR0b2tlbnMgYXMgJGluZGV4ID0+ICR0b2tlbikgew0KDQogICAgICAgICAgICAgICAgaWYgKCRpbmRleCAhPSAwKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICgkdG9rZW5bJ3R5cGUnXSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndGV4dCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnI3skdG9rZW5bJ25hbWUnXX0nKS5iaW5kKCdrZXl1cCcsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnI3skdG9rZW5bJ25hbWUnXX0nKS5jaGFuZ2UoaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnI3skdG9rZW5bJ25hbWUnXX0nKS5iaW5kKCdjaGFuZ2UnLCBoYW5kbGVDYWxjdWxhdGlvbl97JGZpZWxkLT5ET01faWR9KTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAncmFkaW8nOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG5cdCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBJTlBVVCcpLmJpbmQoJ2NsaWNrJywgaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZG9tX29ic2VydmUgLj0gIlxuXHQkKCcjZmJfZmxkLXskdG9rZW5bJ25hbWUnXX0gSU5QVVQnKS5iaW5kKCdjaGFuZ2UnLCBoYW5kbGVDYWxjdWxhdGlvbl97JGZpZWxkLT5ET01faWR9KTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnY2hlY2tib3gnOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG5cdCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBJTlBVVCcpLmJpbmQoJ2NsaWNrJywgaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZG9tX29ic2VydmUgLj0gIlxuXHQkKCcjZmJfZmxkLXskdG9rZW5bJ25hbWUnXX0gSU5QVVQnKS5iaW5kKCdjaGFuZ2UnLCBoYW5kbGVDYWxjdWxhdGlvbl97JGZpZWxkLT5ET01faWR9KTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndGV4dGFyZWEnOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG5cdCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBURVhUQVJFQScpLmJpbmQoJ2tleXVwJywgaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnI2ZiX2ZsZC17JHRva2VuWyduYW1lJ119IFRFWFRBUkVBJykuYmluZCgnY2hhbmdlJywgaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdjYWxlbmRhcic6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnI2RhdGUteyR0b2tlblsnbmFtZSddfS0xJykuYmluZCgnZm9jdXMnLCBoYW5kbGVDYWxjdWxhdGlvbl97JGZpZWxkLT5ET01faWR9KTsiOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG5cdCQoJyNkYXRlLXskdG9rZW5bJ25hbWUnXX0tMScpLmJpbmQoJ2NoYW5nZScsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG5oYW5kbGVDYWxjdWxhdGlvbl97JGZpZWxkLT5ET01faWR9KG51bGwpO1xuIjsNCg0KICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcbn0pO1xuIjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkanNfZXF1YXRpb24gPSA8PDxFT0YNCg0KZnVuY3Rpb24gaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfShldmVudCl7DQoNCi8vIGdldCBzcmMgZWxlbWVudA0KaWYoZXZlbnQgIT0gbnVsbCkgew0KCXZhciBlbHQgPSBGQl9DYWxjdWxhdGlvbi5nZXRTcmNFbGVtZW50KGV2ZW50KTsNCn0NCg0KeyRlcXVhdGlvbl9qc19wYXJhbXRlcnN9DQoNCi8vIGNvcmUgY29kZSBibG9jaw0KeyRlcXVhdGlvbl9qc19jb2RlfQ0KfQ0KPC9zY3JpcHQ+DQoNCkVPRjsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIHJldHVybiAkZG9tX29ic2VydmUgLiAkanNfZXF1YXRpb247DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICB9IGVsc2Ugew0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZXF1YXRpb24gPSAkZmllbGQtPmVxdWF0aW9uOw0KICAgICAgICAgICAgJGRlc3RpbmF0aW9uX2Zvcm1fZmllbGQgPSAkZmllbGQtPmRlc3RpbmF0aW9uX2Zvcm1fZmllbGQ7DQogICAgICAgICAgICAkZGVzdGluYXRpb25fcGhwX3ZhciA9ICRmaWVsZC0+ZGVzdGluYXRpb25fcGhwX3ZhcjsNCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCg0KICAgICAgICAgICAgJHRva2VucyA9IGFycmF5KCk7DQoNCiAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgPSAiXG4vLyBDYWxjdWxhdGlvbiBQYXJhbWV0ZXJzIjsNCiAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlID0gJGVxdWF0aW9uOw0KDQogICAgICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pPyhGXHsoLio/KVx9KS8nLCAoc3RyaW5nKSRlcXVhdGlvbiwgJG1hdGNoZXMpOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRmaWx0ZXIgPSAiIjsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdWzBdKSkgew0KDQogICAgICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJGluZGV4ID0+ICRtYXRjaCkgew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdHlwZSA9ICIiOw0KDQogICAgICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRwYWdlLT5mb3JtLT5maWVsZCBhcyAkZikgew0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGYtPmlkKSAmJiAkbWF0Y2ggPT0gKHN0cmluZykkZi0+aWQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdHlwZSA9IChzdHJpbmcpJGYtPnR5cGU7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgaWYgKCRpbmRleCA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gIlxueyRtYXRjaH0gPSAwOyI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlID0gc3RyX3JlcGxhY2UoJ0Z7JyAuICRtYXRjaCAuICd9JywgJG1hdGNoLCAkZXF1YXRpb25fanNfY29kZSk7DQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICgkdHlwZSkgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndGV4dCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gIlxuXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nKSk7IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gIlxuXG57JG1hdGNofSA9IGlzTmFOKHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nKSk7IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3JhZGlvJzogDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gPDw8RU9GDQpcbi8vIGxvb3AgdGhvdWdoIHJhZGlvIGl0ZW1zIHVudGlsIGFjdGl2ZSB2YWx1ZSBpcyBmb3VuZA0KeyRtYXRjaH0gPSAwOyAvLyBkZWZhdWx0DQpmb3IoaSA9IDA7IGkgPCAxMDAwOyBpKyspew0KCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JG1hdGNofScgKyBpKSAhPT0gbnVsbCl7DQoJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JG1hdGNofScgKyBpKS5jaGVja2VkKXsNCgkJCXskbWF0Y2h9ID0gaXNOYU4ocGFyc2V7JG51bWJlcnR5cGVWYWx1ZX0oXCRGKCd7JG1hdGNofScgKyBpKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nICsgaSkpOw0KCQkNCgkJCWJyZWFrOw0KCQl9DQoJfQ0KfQ0KRU9GOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNrYm94JzogDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gPDw8RU9GDQpcbi8vIGxvb3AgdGhvdWdoIGNoZWNrYm94IGl0ZW1zIHVudGlsIGFsbCBhY3RpdmUgdmFsdWUgYXJlIGZvdW5kDQp7JG1hdGNofSA9IDA7IC8vIGRlZmF1bHQNCmZvcihpID0gMDsgaSA8IDEwMDA7IGkrKyl7DQoJaWYoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skbWF0Y2h9JyArIGkpICE9PSBudWxsKXsNCgkJaWYoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skbWF0Y2h9JyArIGkpLmNoZWNrZWQpew0KCQkJeyRtYXRjaH0gKz0gaXNOYU4ocGFyc2V7JG51bWJlcnR5cGVWYWx1ZX0oXCRGKCd7JG1hdGNofScgKyBpKSkpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KFwkRigneyRtYXRjaH0nICsgaSkpOw0KCQl9DQoJfQ0KfQ0KRU9GOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd0ZXh0YXJlYSc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19wYXJhbXRlcnMgLj0gIlxuXG57JG1hdGNofSA9IFwkRigneyRtYXRjaH0nKS5zcGxpdCgvW1xzXC4sO10rLykubGVuZ3RoOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnY2FsZW5kYXInOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfcGFyYW10ZXJzIC49ICJcblxueyRtYXRjaH0gPSBpc05hTihwYXJzZXskbnVtYmVydHlwZVZhbHVlfShcJEYoJ2RhdGUteyRtYXRjaH0tMScpKSkgPyAwIDogcGFyc2V7JG51bWJlcnR5cGVWYWx1ZX0oXCRGKCdkYXRlLXskbWF0Y2h9LTEnKSk7IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfcGFyYW10ZXJzIC49IDw8PEVPRg0KXG4NCi8vIENoZWNrIGZvciBkYXRlIHZhbHVlIGFuZCB1c2UgaWYgdmFsaWQuDQppZighaXNOYU4oRGF0ZS5wYXJzZSggXCRGKCdkYXRlLXskbWF0Y2h9LTEnKSApKSApew0KCXskbWF0Y2h9ID0gRGF0ZS5wYXJzZSggXCRGKCdkYXRlLXskbWF0Y2h9LTEnKSApOw0KfQ0KCQkJCQkJCQkNCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDogDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfcGFyYW10ZXJzIC49ICJcbnskbWF0Y2h9ID0gaXNOYU4ocGFyc2V7JG51bWJlcnR5cGVWYWx1ZX0oPD9waHAgZWNobyBcJF9TRVNTSU9OWyd7JG1hdGNofSddOyA/PikpID8gMCA6IHBhcnNleyRudW1iZXJ0eXBlVmFsdWV9KDw/cGhwIGVjaG8gXCRfU0VTU0lPTlsneyRtYXRjaH0nXTsgPz4pOyI7DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJGVxdWF0aW9uX2pzX2NvZGUgPSBzdHJfcmVwbGFjZSgnRnsnIC4gJG1hdGNoIC4gJ30nLCAkbWF0Y2gsICRlcXVhdGlvbl9qc19jb2RlKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkdG9rZW5zW10gPSBhcnJheSgnbmFtZScgPT4gKHN0cmluZykkbWF0Y2gsICd0eXBlJyA9PiAoc3RyaW5nKSR0eXBlKTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIHN3aXRjaCAoKGludCkkZmllbGQtPmVxdWF0aW9uX2ZpbHRlcikgew0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IE1hdGguZmxvb3IoeyRtYXRjaGVzWzNdWzBdfSk7DQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gTWF0aC5jZWlsKHskbWF0Y2hlc1szXVswXX0pOw0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICBjYXNlICczJzoNCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gTWF0aC5yb3VuZCh7JG1hdGNoZXNbM11bMF19KTsNCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWx0ZXIgPSA8PDxFT0YNClxuXG4vLyBmaWx0ZXIgcmVzdWx0DQp7JG1hdGNoZXNbM11bMF19ID0gRkJfQ2FsY3VsYXRpb24uZm9ybWF0X0N1cnJlbmN5X1VTKHskbWF0Y2hlc1szXVswXX0pOw0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnNSc6DQogICAgICAgICAgICAgICAgICAgICAgICAkZmlsdGVyID0gPDw8RU9GDQpcblxuLy8gZmlsdGVyIHJlc3VsdA0KeyRtYXRjaGVzWzNdWzBdfSA9IEZCX0NhbGN1bGF0aW9uLmZvcm1hdF9DdXJyZW5jeV9HQlAoeyRtYXRjaGVzWzNdWzBdfSk7DQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgJzYnOg0KICAgICAgICAgICAgICAgICAgICAgICAgJGZpbHRlciA9IDw8PEVPRg0KXG5cbi8vIGZpbHRlciByZXN1bHQNCnskbWF0Y2hlc1szXVswXX0gPSBGQl9DYWxjdWxhdGlvbi5mb3JtYXRfQ3VycmVuY3lfRXVybyh7JG1hdGNoZXNbM11bMF19KTsNCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlIC49ICRmaWx0ZXI7DQoNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoIWlzc2V0KCR0b2tlbnNbMF0pKSB7DQogICAgICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIHN3aXRjaCAoJHRva2Vuc1swXVsndHlwZSddKSB7DQoNCiAgICAgICAgICAgICAgICBjYXNlICd0ZXh0JzoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+ZXF1YXRpb25fZmlsdGVyID09IDApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlIC49IDw8PEVPRg0KXG5cbi8vIHNldCBmaWVsZCBpdGVtIHdpdGggdmFsdWUNClwkKCd7JHRva2Vuc1swXVsnbmFtZSddfScpLnZhbHVlID0gaXNOYU4oeyR0b2tlbnNbMF1bJ25hbWUnXX0pID8gJycgOiB7JHRva2Vuc1swXVsnbmFtZSddfTsNCkVPRjsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRlcXVhdGlvbl9qc19jb2RlIC49IDw8PEVPRg0KXG5cbi8vIHNldCBmaWVsZCBpdGVtIHdpdGggdmFsdWUNClwkKCd7JHRva2Vuc1swXVsnbmFtZSddfScpLnZhbHVlID0geyR0b2tlbnNbMF1bJ25hbWUnXX07DQpFT0Y7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgIGNhc2UgJ2hpZGRlbic6DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZmllbGQtPmVxdWF0aW9uX2ZpbHRlciA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSAuPSA8PDxFT0YNClxuXG4vLyBzZXQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQpcJCgneyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWx1ZSA9IGlzTmFOKHskdG9rZW5zWzBdWyduYW1lJ119KSA/ICcnIDogeyR0b2tlbnNbMF1bJ25hbWUnXX07DQpFT0Y7DQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSAuPSA8PDxFT0YNClxuXG4vLyBzZXQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQpcJCgneyR0b2tlbnNbMF1bJ25hbWUnXX0nKS52YWx1ZSA9IHskdG9rZW5zWzBdWyduYW1lJ119Ow0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgZGVmYXVsdDoNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkZmllbGQtPmVxdWF0aW9uX2ZpbHRlciA9PSAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSAuPSA8PDxFT0YNClxuXG4vLyBzZXQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQpcJCgneyR0b2tlbnNbMF1bJ25hbWUnXX0nKS51cGRhdGUoaXNOYU4oeyR0b2tlbnNbMF1bJ25hbWUnXX0pID8gJycgOiB7JHRva2Vuc1swXVsnbmFtZSddfSk7DQpFT0Y7DQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkZXF1YXRpb25fanNfY29kZSAuPSA8PDxFT0YNClxuXG4vLyBzZXQgZmllbGQgaXRlbSB3aXRoIHZhbHVlDQpcJCgneyR0b2tlbnNbMF1bJ25hbWUnXX0nKS51cGRhdGUoeyR0b2tlbnNbMF1bJ25hbWUnXX0pOw0KRU9GOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRvbV9vYnNlcnZlID0gPDw8RU9GDQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCi8vIERPTSBPYnNlcnZlIENhbGxzIEZvciBSYWNrRm9ybXMgRmllbGQgQ2FsY3VsYXRpb25zLg0KZG9jdW1lbnQub2JzZXJ2ZSgnZG9tOmxvYWRlZCcsIGZ1bmN0aW9uKGwpew0KCS8vIGJpbmQgZXZlbnQgbGlzdGVuZXIocykNCkVPRjsNCg0KICAgICAgICAgICAgZm9yZWFjaCAoJHRva2VucyBhcyAkaW5kZXggPT4gJHRva2VuKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGluZGV4ICE9IDApIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICgkdG9rZW5bJ3R5cGUnXSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndGV4dCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgneyR0b2tlblsnbmFtZSddfScpLm9ic2VydmUoJ2tleXVwJywgaGFuZGxlQ2FsY3VsYXRpb25feyRmaWVsZC0+RE9NX2lkfSk7IjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgneyR0b2tlblsnbmFtZSddfScpLm9ic2VydmUoJ2NoYW5nZScsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyYWRpbyc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBJTlBVVCcpLmludm9rZSgnb2JzZXJ2ZScsICdjbGljaycsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdjaGVja2JveCc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBJTlBVVCcpLmludm9rZSgnb2JzZXJ2ZScsICdjbGljaycsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd0ZXh0YXJlYSc6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCQoJyNmYl9mbGQteyR0b2tlblsnbmFtZSddfSBURVhUQVJFQScpLmludm9rZSgnb2JzZXJ2ZScsICdrZXl1cCcsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdjYWxlbmRhcic6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRvbV9vYnNlcnZlIC49ICJcblx0JCgnZGF0ZS17JHRva2VuWyduYW1lJ119LTEnKS5vYnNlcnZlKCdmb2N1cycsIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0pOyI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRkb21fb2JzZXJ2ZSAuPSAiXG59KTtcbiI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGpzX2VxdWF0aW9uID0gPDw8RU9GDQoNCmZ1bmN0aW9uIGhhbmRsZUNhbGN1bGF0aW9uX3skZmllbGQtPkRPTV9pZH0oZXZlbnQpew0KDQovLyBnZXQgc3JjIGVsZW1lbnQNCnZhciBlbHQgPSBGQl9DYWxjdWxhdGlvbi5nZXRTcmNFbGVtZW50KGV2ZW50KTsNCg0KeyRlcXVhdGlvbl9qc19wYXJhbXRlcnN9DQoNCi8vIGNvcmUgY29kZSBibG9jaw0KeyRlcXVhdGlvbl9qc19jb2RlfQ0KfQ0KPC9zY3JpcHQ+DQoNCkVPRjsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIHJldHVybiAkZG9tX29ic2VydmUgLiAkanNfZXF1YXRpb247DQogICAgICAgIH0gDQogICAgICAgIA0KICAgIH0gDQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9zZXBhcmF0b3IoJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT57J2NvbG9yJ307DQogICAgICAgICR3aWR0aCA9ICRmaWVsZC0+d2lkdGg7DQogICAgICAgICRzZXBhcmF0b3Jfc3R5bGUgPSAkZmllbGQtPnNlcGFyYXRvcl9zdHlsZTsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIHN3aXRjaCAoJHNlcGFyYXRvcl9zdHlsZSkgew0KICAgICAgICAgICAgY2FzZSAnMCc6DQogICAgICAgICAgICAgICAgJHNlcGFyYXRvcl9zdHlsZSA9ICdkb3R0ZWQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJHNlcGFyYXRvcl9zdHlsZSA9ICdzb2xpZCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAkc2VwYXJhdG9yX3N0eWxlID0gJ2Rhc2hlZCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICAgICRzZXBhcmF0b3Jfc3R5bGUgPSAnZG90dGVkJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICBpZiAoIWlzc2V0KCRzdHlsZS0+dGFibGVtb2Rlc3BhbikpIHsNCiAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gZmFsc2U7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBpZiAoKGludCkkc3R5bGUtPnRhYmxlbW9kZXNwYW4gPT0gMCkgew0KICAgICAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gdHJ1ZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBoZWlnaHQ6MnB4OyBmbG9hdDpsZWZ0OyBcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGhlaWdodDoycHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4O1wiID5cbiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDApIHsNCiAgICAgICAgICAgICR3aWR0aCA9ICcnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRidWNrZXRfbm9kZSkgJiYgJGJ1Y2tldF9ub2RlICE9ICIiICYmIChpbnQpJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+cmVzcG9uc2l2ZSA9PSAxKSB7DQogICAgICAgICAgICAkd2lkdGggPSAnODUlJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCAhPSAxICYmICEkdGFibGVtb2Rlc3Bhbikgew0KICAgICAgICAgICAgJHdpZHRoID0gIjEwMCU7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmVsZW1lbnRwb3MpICYmIChpbnQpJGZpZWxkLT5lbGVtZW50cG9zICE9ICIwIikgew0KDQogICAgICAgICAgICAkd2lkdGggPSAkZmllbGQtPndpZHRoOw0KICAgICAgICB9DQoNCg0KDQogICAgICAgICRlbGVtZW50IC49ICI8ZGl2IGNsYXNzPVwic2VwYXJhdG9yXCIgc3R5bGU9XCJoZWlnaHQ6MXB4OyBib3JkZXItYm90dG9tOjFweCB7JGNvbG9yfSB7JHNlcGFyYXRvcl9zdHlsZX07IHdpZHRoOnskd2lkdGh9O1wiPiZuYnNwOzwvZGl2PiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0gDQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfc3BhY2VyKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRoZWlnaHQgPSAkZmllbGQtPmhlaWdodDsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQoNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4O1wiID5cbiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGhlaWdodCArPSA0Ow0KDQogICAgICAgICRmaWVsZHdpZHRoID0gJyB3aWR0aDoxcHg7JzsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAnOTUlJzsNCiAgICAgICAgfQ0KDQogICAgICAgICRlbGVtZW50IC49ICI8ZGl2IGNsYXNzPVwic3BhY2VyXCIgc3R5bGU9XCJoZWlnaHQ6eyRoZWlnaHR9cHg7IHskZmllbGR3aWR0aH1cIj4mbmJzcDs8L2Rpdj4iOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfYmFyY29kZSgkZmllbGQsICR0YWJsZW1vZGUsICRidWNrZXRfbm9kZSA9ICIiKQ0KICAgIHsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07ICBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5jb2RldHlwZSkgew0KICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQkNfVFlQRV9DT0RFMzkiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQkNfVFlQRV9JTlRFUjI1IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjoNCiAgICAgICAgICAgICAgICAkYmFyY29kZV90eXBlID0gIkJDX1RZUEVfU1REMjUiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAzOg0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQkNfVFlQRV9DT0RFOTMiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSA0Og0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQkNfVFlQRV9ST1lNQUlMNCI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDU6DQogICAgICAgICAgICAgICAgJGJhcmNvZGVfdHlwZSA9ICJCQ19UWVBFX1BPU1RORVQiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICBjYXNlIDY6DQogICAgICAgICAgICAgICAgJGJhcmNvZGVfdHlwZSA9ICJDMTI4QSI7IA0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSA3Og0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQzEyOEIiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSA4Og0KICAgICAgICAgICAgICAgICRiYXJjb2RlX3R5cGUgPSAiQzEyOEMiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+cm90YXRpb24pIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkYmFyY29kZV9yb3RhdGlvbiA9ICJCQ19ST1RBVEVfMCI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJGJhcmNvZGVfcm90YXRpb24gPSAiQkNfUk9UQVRFXzkwIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjoNCiAgICAgICAgICAgICAgICAkYmFyY29kZV9yb3RhdGlvbiA9ICJCQ19ST1RBVEVfMTgwIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMzoNCiAgICAgICAgICAgICAgICAkYmFyY29kZV9yb3RhdGlvbiA9ICJCQ19ST1RBVEVfMjcwIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgICRmaWVsZC0+Y2hlY2tkaWdpdCA9IChpbnQpJGZpZWxkLT5jaGVja2RpZ2l0OyANCg0KICAgICAgICANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJGZpZWxkLT50ZXh0LCA0KTsgDQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGQtPnRleHQgPT0gJHRleHQpIHsNCiAgICAgICAgICAgICR0ZXh0ID0gJyInIC4gJHRleHQgLiAnIic7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoJHRleHQgPT0gIiIpIHsNCiAgICAgICAgICAgICR0ZXh0ID0gIjEwMSI7DQogICAgICAgIH0gDQoNCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5zaG93dGV4dCkgew0KICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICRzaG93X2xhYmVsID0gJ04nOw0KICAgICAgICAgICAgICAgICRzaG93X2xhYmVsX2NvZGUxMjggPSAnMCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJHNob3dfbGFiZWwgPSAnWSc7DQogICAgICAgICAgICAgICAgJHNob3dfbGFiZWxfY29kZTEyOCA9ICdvbic7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICAgICAgDQoNCg0KICAgICAgICANCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkZmllbGQtPmNvZGV0eXBlIDwgNikgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT53aWR0aCkgfHwgJGZpZWxkLT53aWR0aCA9PSAiIikgew0KICAgICAgICAgICAgICAgICRmaWVsZC0+d2lkdGggPSAnMSc7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KPD9waHAgDQpcJGVuYWJsZWQgPSB7JGZpZWxkLT5lbmFibGVkfTsNCg0KaW5jbHVkZV9vbmNlICJsaWIvYmFyY29kZS9zZXQxL2NvcmUucGhwIjsNCi8vYmFyQ29kZShCQ19UWVBFX0NPREUzOSwgIjEyMzQ1Njc4OTAiLCAxLCAzLCAxLCBGQUxTRSwgMTAwLCBCQ19JTUdfVFlQRV9QTkcsIFRSVUUsIEJDX1JPVEFURV8wLCBUUlVFLCBGQUxTRSwgInRlc3QiKTsNCg0KXCRiYXJjb2RlX3R5cGUgPSB7JGJhcmNvZGVfdHlwZX07DQpcJHBfdGV4dCA9IHskdGV4dH07DQpcJGR5bl9jaGFyX2hlaWdodCA9IHskZmllbGQtPmhlaWdodH07DQpcJGR5bl9jaGFyX3dpZHRoID0geyRmaWVsZC0+d2lkdGh9Ow0KXCRiYXJjb2RlX3Nob3dfdGV4dCA9ICd7JHNob3dfbGFiZWx9JzsNClwkcF9yb3RBbmdsZSA9IHskYmFyY29kZV9yb3RhdGlvbn07DQpcJHBfY2hlY2tEaWdpdCA9IHskZmllbGQtPmNoZWNrZGlnaXR9Ow0KCQkNCmlmKGlzc2V0KFwkUEFHRV9JU19QREYpICYmIFwkUEFHRV9JU19QREYgPT0gdHJ1ZSAmJiBcJFBERl9MSUJSQVJZID09ICJET01QREYiKXsNCgkJDQoJLy8gTXVzdCBSZW5kZXIgQXMgQmFzZTY0IEZvciBET01QREYuDQoJCQ0KCW9iX3N0YXJ0KCk7DQoNCglcJHJhdyA9IGJhckNvZGUoXCRiYXJjb2RlX3R5cGUsIC8vIFR5cGUgb2YgYmFyY29kZSB0byBiZSBnZW5lcmF0ZWQNCgkJXCRwX3RleHQsICAvLyBUZXh0IHRvIGJlIGdlbmVyYXRlZCBhcyBiYXJjb2RlDQoJCVwkZHluX2NoYXJfd2lkdGgsIC8vIHBfeERpbSAtIHNtYWxsZXN0IGVsZW1lbnQgd2lkdGgNCgkJMywgLy8gd2lkZSB0byBuYXJyb3cgZmFjdG9yDQoJCVwkZHluX2NoYXJfd2lkdGgsICAvLyBJbnRlcmNoYXJhY3RlciBnYXAgd2lkdGguIHVzdWFsbHkgdGhlIHNhbWUgYXMgeERpbQ0KCQlGQUxTRSwgLy8gV2hldGhlciBvciBub3QgaW52ZXJ0IHN0YXJ0aW5nIGJhciBjb2xvcnMgDQoJCVwkZHluX2NoYXJfaGVpZ2h0LCAvLyBoZWlnaHQgaW4gcGl4ZWxzIG9mIGEgc2luZ2xlIGNoYXJhY3Rlcg0KCQlCQ19PVVRQVVRfVFlQRV9SQVdfUE5HX0RBVEEsIC8vIGltYWdlIHR5cGUgb3V0cHV0DQoJCVwkYmFyY29kZV9zaG93X3RleHQsIC8vIFdoZXRoZXIgb3Igbm90IGluY2x1ZGUgYSB0ZXh0IGxhYmVsIGJlbG93IGJhcmNvZGUNCgkJXCRwX3JvdEFuZ2xlLC8vIEJhcmNvZGUgSW1hZ2Ugcm90YXRpb24gYW5nbGUgDQoJCVwkcF9jaGVja0RpZ2l0LCAvLyBXaGV0aGVyIG9yIG5vdCBpbmNsdWRlIGNoZWNrIGRpZ2l0DQoJCUZBTFNFLCAvLyBXaGV0aGVyIG9yIG5vdCB3cml0ZSB0byBmaWxlDQoJCSJ0ZXN0Ig0KCSk7DQoJCQ0KCVwkYmFyX2NvZGVfZGF0YSA9IG9iX2dldF9jbGVhbigpOw0KICANCgllY2hvICc8aW1nIHNyYz0iJzsNCgllY2hvICJkYXRhOmltYWdlL3BuZztiYXNlNjQsIg0KICAgICAgICAgICAgLnN0cl9yZXBsYWNlICgiXFxuIiwgIiIsIGJhc2U2NF9lbmNvZGUgKFwkYmFyX2NvZGVfZGF0YSkpOw0KCWVjaG8gJyIgPic7DQoJCQ0KfSBlbHNlIHsNCg0KCVwkaW1nX2NhbGwgPSAiPGltZyBzcmM9XCJsaWIvYmFyY29kZS9zZXQxL3dyYXBwZXIucGhwP3BfYmNUeXBlPXtcJGJhcmNvZGVfdHlwZX0mcF90eXBlPTMmcF90ZXh0PXtcJHBfdGV4dH0mcF94RGltPXtcJGR5bl9jaGFyX3dpZHRofSZwX3cybj0zJnBfaW52ZXJ0PU4NCgkmcF9jaGFySGVpZ2h0PXtcJGR5bl9jaGFyX2hlaWdodH0mcF9sYWJlbD17XCRiYXJjb2RlX3Nob3dfdGV4dH0mcF9yb3RBbmdsZT17XCRwX3JvdEFuZ2xlfSZwX2NoZWNrRGlnaXQ9e1wkcF9jaGVja0RpZ2l0fVwiIGFsdD1cIkJhcmNvZGVcIj4iOw0KCQkJDQp9DQoNCiAgDQo/Pg0KDQo8cD48P3BocCBpZihcJGVuYWJsZWQpIHsgIGVjaG8gXCRpbWdfY2FsbDsgfSA/PjwvcD4NCg0KRU9UOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5jb2RldHlwZSA+PSA2ICYmIChpbnQpJGZpZWxkLT5jb2RldHlwZSA8PSA4KSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPndpZHRoKSB8fCAkZmllbGQtPndpZHRoID09ICIiKSB7DQogICAgICAgICAgICAgICAgJGZpZWxkLT53aWR0aCA9ICcxMjAnOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCjw/cGhwIA0KXCRlbmFibGVkID0geyRmaWVsZC0+ZW5hYmxlZH07DQoNCmRlZmluZSAoIl9fVFJBQ0VfRU5BQkxFRF9fIiwgZmFsc2UpOw0KZGVmaW5lICgiX19ERUJVR19FTkFCTEVEX18iLCBmYWxzZSk7DQoNCnJlcXVpcmUoImxpYi9iYXJjb2RlL3NldDIvYmFyY29kZS5waHAiKTsNCnJlcXVpcmUoImxpYi9iYXJjb2RlL3NldDIvaTI1b2JqZWN0LnBocCIpOw0KcmVxdWlyZSgibGliL2JhcmNvZGUvc2V0Mi9jMzlvYmplY3QucGhwIik7DQpyZXF1aXJlKCJsaWIvYmFyY29kZS9zZXQyL2MxMjhhb2JqZWN0LnBocCIpOw0KcmVxdWlyZSgibGliL2JhcmNvZGUvc2V0Mi9jMTI4Ym9iamVjdC5waHAiKTsNCnJlcXVpcmUoImxpYi9iYXJjb2RlL3NldDIvYzEyOGNvYmplY3QucGhwIik7DQoNClwkb3V0cHV0ID0gInBuZyI7IA0KXCRiYXJjb2RlID0geyR0ZXh0fTsgDQpcJHR5cGUgPSAneyRiYXJjb2RlX3R5cGV9JzsgDQpcJHdpZHRoID0geyRmaWVsZC0+d2lkdGh9OyANClwkaGVpZ2h0ID0geyRmaWVsZC0+aGVpZ2h0fTsgDQpcJHhyZXMgPSAiMiI7IA0KXCRmb250ID0gIjUiOyANCg0KLy8gc3R5bGUgYXR0cmlidXRlcw0KXCRib3JkZXIgPSAib2ZmIjsNClwkZHJhd3RleHQgPSAneyRzaG93X2xhYmVsX2NvZGUxMjh9JzsNClwkc3RyZXRjaHRleHQgPSAib2ZmIjsNClwkbmVnYXRpdmUgPSAib2ZmIjsgDQoNClwkU3RhclNpemUgPSAwOw0KDQpcJHN0eWxlICA9IEJDU19BTElHTl9DRU5URVI7CQkJCQkgICAgICAgDQpcJHN0eWxlIHw9IChcJG91dHB1dCAgPT0gInBuZyIgKSA/IEJDU19JTUFHRV9QTkcgIDogMDsgDQpcJHN0eWxlIHw9IChcJG91dHB1dCAgPT0gImpwZWciKSA/IEJDU19JTUFHRV9KUEVHIDogMDsgDQpcJHN0eWxlIHw9IChcJGJvcmRlciAgPT0gIm9uIiAgKSA/IEJDU19CT1JERVIgCSAgOiAwOyANClwkc3R5bGUgfD0gKFwkZHJhd3RleHQ9PSAib24iICApID8gQkNTX0RSQVdfVEVYVCAgOiAwOyANClwkc3R5bGUgfD0gKFwkc3RyZXRjaHRleHQ9PSAib24iICkgPyBCQ1NfU1RSRVRDSF9URVhUICA6IDA7IA0KXCRzdHlsZSB8PSAoXCRuZWdhdGl2ZT09ICJvbiIgICkgPyBCQ1NfUkVWRVJTRV9DT0xPUiAgOiAwOyANCg0KaWYoXCRlbmFibGVkKSB7IA0KDQoJc3dpdGNoIChcJHR5cGUpIHsNCgkgICAgY2FzZSAiSTI1IjoNCgkJCQkgIFwkb2JqID0gbmV3IEkyNU9iamVjdChcJHdpZHRoLCBcJGhlaWdodCwgXCRzdHlsZSwgXCRiYXJjb2RlLCBcJFN0YXJTaXplKTsNCgkJCQkgIGJyZWFrOw0KCSAgICBjYXNlICJDMzkiOg0KCQkJCSAgXCRvYmogPSBuZXcgQzM5T2JqZWN0KFwkd2lkdGgsIFwkaGVpZ2h0LCBcJHN0eWxlLCBcJGJhcmNvZGUpOw0KCQkJCSAgYnJlYWs7DQoJICAgIGNhc2UgIkMxMjhBIjoNCgkJCQkgIFwkb2JqID0gbmV3IEMxMjhBT2JqZWN0KFwkd2lkdGgsIFwkaGVpZ2h0LCBcJHN0eWxlLCBcJGJhcmNvZGUpOw0KCQkJCSAgYnJlYWs7DQoJICAgIGNhc2UgIkMxMjhCIjoNCgkJCQkgIFwkb2JqID0gbmV3IEMxMjhCT2JqZWN0KFwkd2lkdGgsIFwkaGVpZ2h0LCBcJHN0eWxlLCBcJGJhcmNvZGUpOw0KCQkJCSAgYnJlYWs7DQoJICAgIGNhc2UgIkMxMjhDIjoNCgkgICAgICAgICAgICAgIFwkb2JqID0gbmV3IEMxMjhDT2JqZWN0KFwkd2lkdGgsIFwkaGVpZ2h0LCBcJHN0eWxlLCBcJGJhcmNvZGUpOw0KCQkJCSAgYnJlYWs7DQoJCWRlZmF1bHQ6DQoJCQkJXCRvYmogPSBmYWxzZTsNCgl9DQoJDQp9DQoNCmlmKGlzc2V0KFwkUEFHRV9JU19QREYpICYmIFwkUEFHRV9JU19QREYgPT0gdHJ1ZSAmJiBcJFBERl9MSUJSQVJZID09ICJET01QREYiKXsNCgkJDQoJLy8gTXVzdCBSZW5kZXIgQXMgQmFzZTY0IEZvciBET01QREYuDQoJCQ0KCW9iX3N0YXJ0KCk7DQoJCQ0KCQkNCglcJGJhcl9jb2RlX2RhdGEgPSBvYl9nZXRfY2xlYW4oKTsNCiAgDQoJZWNobyAnPGltZyBzcmM9Iic7DQoJZWNobyAiZGF0YTppbWFnZS9wbmc7YmFzZTY0LCINCiAgICAgICAgICAgIC5zdHJfcmVwbGFjZSAoIlxcbiIsICIiLCBiYXNlNjRfZW5jb2RlIChcJGJhcl9jb2RlX2RhdGEpKTsNCgllY2hvICciID4nOw0KCQkNCn0gZWxzZSB7DQoJCQ0KCWlmIChcJG9iaikgew0KCSAgIGlmIChcJG9iai0+RHJhd09iamVjdChcJHhyZXMsIFwkU3RhclNpemUpKSB7DQoJICAgICAgIGVjaG8gIjxpbWcgc3JjPSdsaWIvYmFyY29kZS9zZXQyL2ltYWdlLnBocD9jb2RlPXtcJGJhcmNvZGV9JnN0eWxlPXtcJHN0eWxlfSZ0eXBlPXtcJHR5cGV9JndpZHRoPXtcJHdpZHRofSZoZWlnaHQ9e1wkaGVpZ2h0fSZ4cmVzPTImZm9udD17XCRmb250fSc+IjsNCgkgICB9IGVsc2UgZWNobyAiPGZvbnQgY29sb3I9JyNGRjAwMDAnPiIuKFwkb2JqLT5HZXRFcnJvcigpKS4iPC9mb250PiI7DQoJfQ0KCQkNCn0NCgkJDQoNCiAgDQo/Pg0KDQpFT1Q7DQogICAgICAgIH0NCg0KDQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5tYXRyaXhzaXplKSB8fCAkZmllbGQtPm1hdHJpeHNpemUgPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZC0+bWF0cml4c2l6ZSA9ICcxJzsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgoaW50KSRmaWVsZC0+Y29kZXR5cGUgPT0gOSkgew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCjw/cGhwIA0KXCRlbmFibGVkID0geyRmaWVsZC0+ZW5hYmxlZH07DQoNCglcJHJlcXVlc3RfbGV2ZWwgPSAwOw0KCVwkcmVxdWVzdF9tYXRyaXhfc2l6ZSA9IHskZmllbGQtPm1hdHJpeHNpemV9Ow0KCVwkcmVxdWVzdF9kYXRhID0geyR0ZXh0fTsNCgkNCg0KCS8vc2V0IGl0IHRvIHdyaXRhYmxlIGxvY2F0aW9uLCBhIHBsYWNlIGZvciB0ZW1wIGdlbmVyYXRlZCBQTkcgZmlsZXMNCgkvLyBCdWlsZCA3ODQgLSBFbmNvZGluZyB3YXMgdHJhbnNmb3JpbmcgX19GSUxFIGludG8gdGhlIHBhdGggb2YgdGhlIHNjcmlwdCwgbm90IHN1cmUgd2h5ISANCiAgICBcJFBOR19URU1QX0RJUiA9ICcuLycuRElSRUNUT1JZX1NFUEFSQVRPUi4ndGVtcCcuRElSRUNUT1JZX1NFUEFSQVRPUjsNCiAgICANCiAgICAvL2h0bWwgUE5HIGxvY2F0aW9uIHByZWZpeA0KICAgIFwkUE5HX1dFQl9ESVIgPSAndGVtcC8nOw0KDQogICAgaW5jbHVkZSAibGliL2JhcmNvZGUvcGhwcXJjb2RlL3FybGliLnBocCI7ICAgIA0KICAgIA0KICAgIC8vb2Zjb3Vyc2Ugd2UgbmVlZCByaWdodHMgdG8gY3JlYXRlIHRlbXAgZGlyDQogICAgaWYgKCFmaWxlX2V4aXN0cyhcJFBOR19URU1QX0RJUikpDQogICAgICAgIG1rZGlyKFwkUE5HX1RFTVBfRElSKTsNCiAgICANCiAgICANCiAgICBcJGZpbGVuYW1lID0gXCRQTkdfVEVNUF9ESVIuJ3Rlc3QucG5nJzsNCiAgICANCiAgICAvL3Byb2Nlc3NpbmcgZm9ybSBpbnB1dA0KICAgIC8vcmVtZW1iZXIgdG8gc2FuaXRpemUgdXNlciBpbnB1dCBpbiByZWFsLWxpZmUgc29sdXRpb24gISEhDQogICAgXCRlcnJvckNvcnJlY3Rpb25MZXZlbCA9ICdMJzsNCiAgICBpZiAoaXNzZXQoXCRyZXF1ZXN0X2xldmVsKSAmJiBpbl9hcnJheShcJHJlcXVlc3RfbGV2ZWwsIGFycmF5KCdMJywnTScsJ1EnLCdIJykpKQ0KICAgICAgICBcJGVycm9yQ29ycmVjdGlvbkxldmVsID0gXCRyZXF1ZXN0X2xldmVsOyAgICANCg0KICAgIFwkbWF0cml4UG9pbnRTaXplID0gNDsNCiAgICBpZiAoaXNzZXQoXCRyZXF1ZXN0X21hdHJpeF9zaXplKSkNCiAgICAgICAgXCRtYXRyaXhQb2ludFNpemUgPSBtaW4obWF4KChpbnQpXCRyZXF1ZXN0X21hdHJpeF9zaXplLCAxKSwgMTApOw0KDQogICAgICAgIA0KICAgIGlmIChpc3NldChcJHJlcXVlc3RfZGF0YSkgJiYgXCRlbmFibGVkKSB7IA0KICAgIA0KICAgICAgICAvL2l0J3MgdmVyeSBpbXBvcnRhbnQhDQogICAgICAgIGlmICh0cmltKFwkcmVxdWVzdF9kYXRhKSA9PSAnJykNCiAgICAgICAgICAgIGRpZSgnZGF0YSBjYW5ub3QgYmUgZW1wdHkhIDxhIGhyZWY9Ij8iPmJhY2s8L2E+Jyk7DQogICAgICAgICAgICANCiAgICAgICAgLy8gdXNlciBkYXRhDQogICAgICAgIFwkZmlsZW5hbWUgPSBcJFBOR19URU1QX0RJUi4ndGVzdCcubWQ1KFwkcmVxdWVzdF9kYXRhLid8Jy5cJGVycm9yQ29ycmVjdGlvbkxldmVsLid8Jy5cJG1hdHJpeFBvaW50U2l6ZSkuJy5wbmcnOw0KICAgICAgICBRUmNvZGU6OnBuZyhcJHJlcXVlc3RfZGF0YSwgXCRmaWxlbmFtZSwgXCRlcnJvckNvcnJlY3Rpb25MZXZlbCwgXCRtYXRyaXhQb2ludFNpemUsIDIpOw0KDQogICAgICAgICAgICAgICAgDQoJICAgIC8vIGRpc3BsYXkgZ2VuZXJhdGVkIGZpbGUNCgkgICAgZWNobyAnPGltZyBzcmM9IicuXCRQTkdfV0VCX0RJUi5iYXNlbmFtZShcJGZpbGVuYW1lKS4nIiAvPic7IA0KICAgICAgICANCiAgICB9ICANCiANCj8+DQoNCkVPVDsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV93ZWJjYW0oJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmVuYWJsZWQpICYmICRmaWVsZC0+ZW5hYmxlZCA9PSAiMCIpIHsNCg0KICAgICAgICAgICAgcmV0dXJuICIiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0O1wiPiZuYnNwOzwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgIG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCiAgICAgICAgJHdpZHRoID0gJGZpZWxkLT53aWR0aDsNCiAgICAgICAgJGhlaWdodCA9ICRmaWVsZC0+aGVpZ2h0Ow0KDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNfbnVtZXJpYygkd2lkdGgpKSB7DQogICAgICAgICAgICAkd2lkdGggPSBpbnR2YWwoJHdpZHRoKTsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoIWlzX251bWVyaWMoJGhlaWdodCkpIHsNCiAgICAgICAgICAgICRoZWlnaHQgPSBpbnR2YWwoJGhlaWdodCk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAodHJpbSgkd2lkdGgpID09ICIiIHx8ICR3aWR0aCA9PSAwKSB7DQogICAgICAgICAgICAkd2lkdGggPSAiMzIwIjsNCiAgICAgICAgfQ0KICAgICAgICBpZiAodHJpbSgkaGVpZ2h0KSA9PSAiIiB8fCAkaGVpZ2h0ID09IDApIHsNCiAgICAgICAgICAgICRoZWlnaHQgPSAiMjQwIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZGVzdGluYXRpb25fd2lkdGggPSAkZmllbGQtPmRlc3RpbmF0aW9uX3dpZHRoOw0KICAgICAgICAkZGVzdGluYXRpb25faGVpZ2h0ID0gJGZpZWxkLT5kZXN0aW5hdGlvbl9oZWlnaHQ7DQoNCg0KICAgICAgICANCg0KICAgICAgICAkc25hcHNob3RfcHJldmlld193aWR0aCA9ICRmaWVsZC0+c25hcHNob3RfcHJldmlld193aWR0aDsNCiAgICAgICAgJHNuYXBzaG90X3ByZXZpZXdfaGVpZ2h0ID0gJGZpZWxkLT5zbmFwc2hvdF9wcmV2aWV3X2hlaWdodDsNCg0KICAgICAgICBpZiAoIWlzX251bWVyaWMoJHNuYXBzaG90X3ByZXZpZXdfd2lkdGgpKSB7DQogICAgICAgICAgICAkc25hcHNob3RfcHJldmlld193aWR0aCA9IGludHZhbCgkc25hcHNob3RfcHJldmlld193aWR0aCk7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCFpc19udW1lcmljKCRzbmFwc2hvdF9wcmV2aWV3X2hlaWdodCkpIHsNCiAgICAgICAgICAgICRzbmFwc2hvdF9wcmV2aWV3X2hlaWdodCA9IGludHZhbCgkc25hcHNob3RfcHJldmlld19oZWlnaHQpOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHRyaW0oJHNuYXBzaG90X3ByZXZpZXdfd2lkdGgpID09ICIiKSB7DQogICAgICAgICAgICAkc25hcHNob3RfcHJldmlld193aWR0aCA9ICIzMjAiOw0KICAgICAgICB9DQogICAgICAgIGlmICh0cmltKCRzbmFwc2hvdF9wcmV2aWV3X2hlaWdodCkgPT0gIiIpIHsNCiAgICAgICAgICAgICRzbmFwc2hvdF9wcmV2aWV3X2hlaWdodCA9ICIyNDAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkc25hcHNob3RfcHJldmlld193aWR0aCA9PSAwKSB7DQogICAgICAgICAgICAkc25hcHNob3RfcHJldmlld193aWR0aCA9ICIiOw0KICAgICAgICB9DQogICAgICAgIGlmICgkc25hcHNob3RfcHJldmlld19oZWlnaHQgPT0gMCkgew0KICAgICAgICAgICAgJHNuYXBzaG90X3ByZXZpZXdfaGVpZ2h0ID0gIiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNfbnVtZXJpYygkZGVzdGluYXRpb25fd2lkdGgpKSB7DQogICAgICAgICAgICAkZGVzdGluYXRpb25fd2lkdGggPSBpbnR2YWwoJGRlc3RpbmF0aW9uX3dpZHRoKTsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoIWlzX251bWVyaWMoJGRlc3RpbmF0aW9uX2hlaWdodCkpIHsNCiAgICAgICAgICAgICRkZXN0aW5hdGlvbl9oZWlnaHQgPSBpbnR2YWwoJGRlc3RpbmF0aW9uX2hlaWdodCk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAodHJpbSgkZGVzdGluYXRpb25fd2lkdGgpID09ICIiIHx8ICRkZXN0aW5hdGlvbl93aWR0aCA9PSAwKSB7DQogICAgICAgICAgICAkZGVzdGluYXRpb25fd2lkdGggPSAkd2lkdGg7DQogICAgICAgIH0NCiAgICAgICAgaWYgKHRyaW0oJGRlc3RpbmF0aW9uX2hlaWdodCkgPT0gIiIgfHwgJGRlc3RpbmF0aW9uX2hlaWdodCA9PSAwKSB7DQogICAgICAgICAgICAkZGVzdGluYXRpb25faGVpZ2h0ID0gJGhlaWdodDsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZvcm1hdCA9ICJwbmciOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmZvcm1hdCkpIHsNCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+Zm9ybWF0ID09ICIwIikgew0KICAgICAgICAgICAgICAgICRmb3JtYXQgPSAianBlZyI7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAoJGZpZWxkLT5mb3JtYXQgPT0gIjEiKSB7DQogICAgICAgICAgICAgICAgJGZvcm1hdCA9ICJwbmciOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJHF1YWxpdHkgPSAkZmllbGQtPnF1YWxpdHk7DQogICAgICAgIGlmICghaXNfbnVtZXJpYygkcXVhbGl0eSkpIHsNCiAgICAgICAgICAgICRxdWFsaXR5ID0gaW50dmFsKCRxdWFsaXR5KTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkcXVhbGl0eSA9PSAiIikgew0KICAgICAgICAgICAgJHF1YWxpdHkgPSA4MDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkY2FwdHVyZV9tZXNzYWdlID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCAkZmllbGQtPmNhcHR1cmVfbWVzc2FnZSk7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoNCjxzY3JpcHQgc3JjPSJqcy93ZWJjYW0vd2ViY2FtLmpzIj48L3NjcmlwdD4NCg0KICAgIDxkaXYgY2xhc3M9IndlYmNhbS12aWV3ZXIiIGlkPSJteV9jYW1lcmFfeyRmaWVsZC0+bmFtZX0iIHN0eWxlPSJ3aWR0aDp7JHdpZHRofXB4OyBoZWlnaHQ6eyRoZWlnaHR9cHg7Ij48L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPSJ3ZWJjYW0tc25hcHNob3QiIGlkPSJteV9yZXN1bHRfeyRmaWVsZC0+bmFtZX0iPjwvZGl2Pg0KICAgIA0KCTxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJ7JGZpZWxkLT5pZH0iIG5hbWU9InskZmllbGQtPm5hbWV9IiAvPg0KCQkJCQ0KICAgIDxzY3JpcHQgbGFuZ3VhZ2U9IkphdmFTY3JpcHQiPg0KICAgIA0KICAgICAgICBXZWJjYW0uYXR0YWNoKCAnI215X2NhbWVyYV97JGZpZWxkLT5uYW1lfScgKTsNCiAgICAJCQ0KICAgIAlXZWJjYW0uc2V0KHsNCgkgICAgICAgIHdpZHRoOiB7JHdpZHRofSwNCgkgICAgICAgIGhlaWdodDogeyRoZWlnaHR9LA0KCSAgICAgICAgZGVzdF93aWR0aDogeyRkZXN0aW5hdGlvbl93aWR0aH0sDQoJICAgICAgICBkZXN0X2hlaWdodDogeyRkZXN0aW5hdGlvbl9oZWlnaHR9LA0KCSAgICAgICAgaW1hZ2VfZm9ybWF0OiAneyRmb3JtYXR9JywNCgkgICAgICAgIGpwZWdfcXVhbGl0eTogeyRxdWFsaXR5fSwNCgkgICAgICAgIGZvcmNlX2ZsYXNoOiBmYWxzZSwNCgkgICAgICAgIGZsaXBfaG9yaXo6IGZhbHNlLA0KCSAgICAgICAgZnBzOiA0NQ0KICAgIAl9KTsNCg0KICAgICAgICBmdW5jdGlvbiB0YWtlX3NuYXBzaG90KCkgew0KICAgICAgICAgICAgV2ViY2FtLnNuYXAoIGZ1bmN0aW9uKGRhdGFfdXJpKSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgIAlpZih7JGZpZWxkLT5wcmV2aWV3X21vZGV9ID09IDApIHsNCiAgICAgICAgICAgIAkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ215X3Jlc3VsdF97JGZpZWxkLT5uYW1lfScpLmlubmVySFRNTCA9ICc8aW1nIHdpZHRoPSJ7JHNuYXBzaG90X3ByZXZpZXdfd2lkdGh9IiBoZWlnaHQ9Inskc25hcHNob3RfcHJldmlld19oZWlnaHR9IiBzcmM9IicrZGF0YV91cmkrJyIvPic7DQogICAgICAgICAgICAJfQ0KICAgICAgICAgICAgCQ0KICAgICAgICAgICAgCWlmKHskZmllbGQtPnByZXZpZXdfbW9kZX0gPT0gMSkgew0KICAgICAgICAgICAgCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbXlfcmVzdWx0X3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MID0gJ3skY2FwdHVyZV9tZXNzYWdlfSc7DQogICAgICAgICAgICAJfQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgCS8vIFNhdmUgRGF0YS4NCgkJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRmaWVsZC0+bmFtZX0nKS52YWx1ZSA9IGRhdGFfdXJpLnJlcGxhY2UoL15kYXRhOmltYWdlXC8ocG5nfGpwZ3xqcGVnKTtiYXNlNjQsLywgIiIpOw0KCQkJCQ0KICAgICAgICAgICAgfSk7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgPC9zY3JpcHQ+DQoNCiAgICA8YSBjbGFzcz0id2ViY2FtLWFjdGlvbi1idXR0b24iIGhyZWY9ImphdmFzY3JpcHQ6dm9pZCh0YWtlX3NuYXBzaG90KCkpIj57JGZpZWxkLT5hY3Rpb25fbWVzc2FnZX08L2E+DQoNCkVPVDsNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9zaWduYXR1cmUoJHBhZ2UsICRlbmFibGVfcGRmLCAkZmllbGQsICR0YWJsZW1vZGUsICRidWNrZXRfbm9kZSA9ICIiKQ0KICAgIHsNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICAkc3R5bGUgPSAkZmllbGQtPnN0eWxlOw0KDQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQoNCiAgICAgICAgJGluaGVyaXRzdHlsZSA9ICRmaWVsZC0+aW5oZXJpdHN0eWxlOw0KDQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQoNCiAgICAgICAgJGxhYmVsc3R5bGUgPSAic3R5bGU9XCJmb250LXNpemU6eyRmb250c2l6ZX07IGNvbG9yOnskY29sb3J9O1wiICI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRpbmhlcml0c3R5bGUpICYmIChpbnQpJGluaGVyaXRzdHlsZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAic3R5bGU9XCJmb250LXNpemU6eyRmb250c2l6ZX07IGNvbG9yOnskaW5wdXRfY29sb3J9OyBmb250LWZhbWlseTppbmhlcml0O1wiICI7DQoNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICJzdHlsZT1cImNvbG9yOnskaW5wdXRfY29sb3J9O1wiICI7DQoNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgaWYgKCFpc3NldCgkc3R5bGUtPnRhYmxlbW9kZXNwYW4pKSB7DQogICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICB9IGVsc2UgeyANCiAgICAgICAgICAgIGlmICgoaW50KSRzdHlsZS0+dGFibGVtb2Rlc3BhbiA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSB0cnVlOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgJGZpZWxkX3dpZHRoID0gJyc7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRzdHlsZS0+ZmllbGR3aWR0aCkpIHsNCiAgICAgICAgICAgICRmaWVsZF93aWR0aCA9ICRzdHlsZS0+ZmllbGR3aWR0aDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkc3R5bGUtPnRhYmxlbW9kZXNwYW4gPT0gMSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxkaXYgY2xhc3M9XCJ0YWJsZW1vZGUtc3Bhbi13aWR0aFwiIHN0eWxlPVwid2lkdGg6eyRmaWVsZF93aWR0aH1cIj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0O1wiPiZuYnNwOzwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgIG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+aW5wdXR0eXBlKSB7DQogICAgICAgICAgICBjYXNlIDA6IA0KICAgICAgICAgICAgICAgICRpbnB1dHR5cGUgPSAiLCBkcmF3T25seTp0cnVlIjsNCiAgICAgICAgICAgICAgICAkaW5wdXRfZmllbGQgPSAiIjsNCiAgICAgICAgICAgICAgICAkZHJhd19pdF9jb250cm9sID0gIjxsaSBjbGFzcz1cImRyYXdJdFwiPjxhIGhyZWY9XCIjZHJhdy1pdFwiID57JGZpZWxkLT5zaWduYXR1cmVfZHJhd2l0X3RleHR9PC9hPjwvbGk+IjsgDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgIGNhc2UgMTogDQogICAgICAgICAgICAgICAgJGlucHV0dHlwZSA9ICIsIGRyYXdPbmx5OmZhbHNlIjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRpbnB1dF9maWVsZCA9ICI8bGFiZWwgYXJpYS1sYWJlbD1cIlNpZ25hdHVyZSBJbnB1dFwiIGZvcj1cIm5hbWVcIiB7JGxhYmVsc3R5bGV9PnskZmllbGQtPnNpZ25hdHVyZV90eXBlaXRfdGV4dH08L2xhYmVsPiI7DQoNCiAgICAgICAgICAgICAgICAkdmFsdWUgPSAiPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3NpZ25hdHVyZXMnXVtcInskZmllbGQtPmlkfVwiXVsnc2lnbmF0b3InXSkpIHsgZWNobyBcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsnc2lnbmF0dXJlcyddW1wieyRmaWVsZC0+aWR9XCJdWydzaWduYXRvciddOyB9ID8+IjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRpbnB1dF9maWVsZCAuPSAiPGlucHV0IHR5cGU9XCJ0ZXh0XCIgeyRpbmhlcml0c3R5bGV9IG5hbWU9XCJzaWduYXR1cmVfaW5wdXRfZmllbGRfeyRmaWVsZC0+bmFtZX1cIiAgaWQ9XCJzaWduYXR1cmUtX2lucHV0X2ZpZWxkX3skZmllbGQtPmlkfVwiIGNsYXNzPVwibmFtZVwiIHZhbHVlPVwieyR2YWx1ZX1cIiBvbmtleXVwPVwiZHJhd190eXBlZF9zaWduYXR1cmVfeyRmaWVsZC0+aWR9KHRoaXMudmFsdWUpOyBnZW5lcmF0ZV90ZXh0X2NhbnZhc19pbWFnZV97JGZpZWxkLT5pZH0oJ3NpZ25hdHVyZS1faW5wdXRfZmllbGRfeyRmaWVsZC0+aWR9Jyk7XCI+IjsNCg0KICAgICAgICAgICAgICAgICRpbnB1dF9maWVsZCAuPSAiPGJyIC8+PGJyLz4iOw0KDQogICAgICAgICAgICAgICAgJGRyYXdfaXRfY29udHJvbCA9ICcnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICBjYXNlIDI6IA0KICAgICAgICAgICAgICAgICRpbnB1dHR5cGUgPSAiLCBkcmF3T25seTp0cnVlIjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRpbnB1dF9maWVsZCA9ICI8bGFiZWwgYXJpYS1sYWJlbD1cIlNpZ25hdHVyZVwiIGZvcj1cIm5hbWVcIiB7JGxhYmVsc3R5bGV9PnskZmllbGQtPnNpZ25hdHVyZV90eXBlaXRfdGV4dH08L2xhYmVsPiI7DQoNCiAgICAgICAgICAgICAgICAkdmFsdWUgPSAiPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3NpZ25hdHVyZXMnXVtcInskZmllbGQtPmlkfVwiXVsnc2lnbmF0b3InXSkpIHsgZWNobyBcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsnc2lnbmF0dXJlcyddW1wieyRmaWVsZC0+aWR9XCJdWydzaWduYXRvciddOyB9ID8+IjsNCiAgICAgICAgICAgICAgICAkaW5wdXRfZmllbGQgLj0gIjxpbnB1dCB0eXBlPVwidGV4dFwiIHskaW5oZXJpdHN0eWxlfSBuYW1lPVwic2lnbmF0dXJlX2lucHV0X2ZpZWxkX3skZmllbGQtPm5hbWV9XCIgaWQ9XCJzaWduYXR1cmVfaW5wdXRfZmllbGRfeyRmaWVsZC0+aWR9XCIgY2xhc3M9XCJuYW1lXCIgdmFsdWU9XCJ7JHZhbHVlfVwiIHNpemU9XCIzMFwiPiI7DQoNCiAgICAgICAgICAgICAgICAkZHJhd19pdF9jb250cm9sID0gIjxsaSBjbGFzcz1cImRyYXdJdFwiPjxhIGhyZWY9XCIjZHJhdy1pdFwiID57JGZpZWxkLT5zaWduYXR1cmVfZHJhd2l0X3RleHR9PC9hPjwvbGk+IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgY2FzZSAzOiANCiAgICAgICAgICAgICAgICAkaW5wdXR0eXBlID0gIiwgZGlzcGxheU9ubHk6dHJ1ZSI7DQoNCiAgICAgICAgICAgICAgICAkaW5wdXRfZmllbGQgPSAiIjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICR2YWx1ZSA9ICI8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsnc2lnbmF0dXJlcyddW1wieyRmaWVsZC0+aWR9XCJdWydzaWduYXRvciddKSkgeyBlY2hvIFwkX1NFU1NJT05bJ3FzJ11bXCJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119XCJdWydzaWduYXR1cmVzJ11bXCJ7JGZpZWxkLT5pZH1cIl1bJ3NpZ25hdG9yJ107IH0gPz4iOw0KICAgICAgICAgICAgICAgICRpbnB1dF9maWVsZCAuPSAiPGJyPjxpbnB1dCB0eXBlPVwidGV4dFwiIHN0eWxlPVwiZm9udC1zaXplOnskZm9udHNpemV9O1wiIG5hbWU9XCJzaWduYXR1cmVfaW5wdXRfZmllbGRfeyRmaWVsZC0+bmFtZX1cIiBpZD1cInNpZ25hdHVyZV9pbnB1dF9maWVsZF97JGZpZWxkLT5pZH1cIiBjbGFzcz1cIm5hbWVcIiB2YWx1ZT1cInskdmFsdWV9XCIgc2l6ZT1cIjMwXCI+PGJyPjxicj4iOw0KDQogICAgICAgICAgICAgICAgJGRyYXdfaXRfY29udHJvbCA9ICI8bGkgY2xhc3M9XCJkcmF3SXRcIj48YSBocmVmPVwiI2RyYXctaXRcIiA+eyRmaWVsZC0+c2lnbmF0dXJlX2RyYXdpdF90ZXh0fTwvYT48L2xpPiI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+d2lkdGgpIHx8ICRmaWVsZC0+d2lkdGggPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZC0+d2lkdGggPSAnMSc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfd2lkdGgpIHx8ICRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc193aWR0aCA9PSAiIikgew0KICAgICAgICAgICAgJGZpZWxkLT5zaWduYXR1cmVfY2FudmFzX3dpZHRoID0gJzQwMCc7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHQpIHx8ICRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHQgPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHQgPSAnNjUnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5zaWduYXR1cmVfbGluZV93aWR0aCkgfHwgJGZpZWxkLT5zaWduYXR1cmVfbGluZV93aWR0aCA9PSAiIikgew0KICAgICAgICAgICAgJGZpZWxkLT5zaWduYXR1cmVfbGluZV93aWR0aCA9ICcwJzsNCiAgICAgICAgfQ0KDQogICAgICAgICRsaW5lVG9wID0gKGludCkkZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfaGVpZ2h0IC0gNTsNCiAgICAgICAgJHdyYXBwZXJIZWlnaHQgPSAoaW50KSRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHQgKyAxMDsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRmaWVsZC0+c2lnbmF0dXJlX2xpbmVfd2lkdGggPT0gMCkgew0KICAgICAgICAgICAgJHdyYXBwZXJIZWlnaHQgPSAkd3JhcHBlckhlaWdodCAtIDEwOw0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRzaWduYXR1cmVQYWRXaWR0aCA9IGludHZhbCgkZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfd2lkdGgpOw0KICAgICAgICANCiAgICAgICAgaWYoaXNzZXQoJHBhZ2UtPmdsb2JhbHN0eWxlKSAmJiAoaW50dmFsKCRwYWdlLT5nbG9iYWxzdHlsZSkgIT0gMCB8fCAhaXNfbnVtZXJpYygoc3RyaW5nKSRwYWdlLT5nbG9iYWxzdHlsZSkpICl7DQogICAgICAgICAgICANCiAgICAgICAgICAgICR3cmFwcGVySGVpZ2h0ID0gKGludCkkZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfaGVpZ2h0ICsgMTA7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRzaWduYXR1cmVQYWRXaWR0aCA9IGludHZhbCgkZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfd2lkdGgpICsgMTU7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KICAgICAgICANCg0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWQpICYmIChpbnQpJGZpZWxkLT5yZXF1aXJlZCA9PSAwID8gJ3RydWUnIDogJ2ZhbHNlJzsNCg0KICAgICAgICBpZiAoKGludCkkZmllbGQtPmlucHV0dHlwZSAhPSAzKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoJGZpZWxkLT5zaWduYXR1cmVfY2FudmFzX3dpZHRoIDwgMTkwKSB7DQoNCiAgICAgICAgICAgICAgICAkZHJhd19pdF9jb250cm9sID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KDQp7JGlucHV0X2ZpZWxkfQ0KCQ0KPHAgY2xhc3M9ImRyYXdJdERlc2MiPiZuYnNwOzwvcD4NCg0KDQoJDQo8ZGl2IGNsYXNzPSJzaWcgc2lnV3JhcHBlciBzaWdXcmFwcGVyX3skZmllbGQtPmlkfSI+DQoNCgk8dWwgY2xhc3M9InNpZ05hdiIgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyB0b3A6IC0yOXB4OyBtYXJnaW46LTFweDsiPg0KCQl7JGRyYXdfaXRfY29udHJvbH0NCgkJPGxpIGNsYXNzPSJjbGVhckJ1dHRvbiI+PGEgaHJlZj0iI2NsZWFyIj5DbGVhcjwvYT48L2xpPg0KCTwvdWw+DQoJDQoJPCEtLSBob2xkcyB0aGUgdHlwZWQgdmVyc2lvbiBvZiBhIHNpZ25hdHVyZSwgbGF5ZWQgb24gdG9wIG9mIHRoZSBjYW52YXMsIG9ubHkgdXNlZCBpbiAndHlwZSBvbmx5JyB2ZXJzaW9ucywgYWxzbyBkZWZpbmVzIGZvbnQgc2l6ZSB1c2VkIGZvciBkaXNwbGF5IC0tPg0KCTxkaXYgY2xhc3M9InR5cGVkIHR5cGVkLXskZmllbGQtPmlkfSIgc3R5bGU9ImZvbnQtc2l6ZToyMnB0OyI+PC9kaXY+DQoJDQoJPGNhbnZhcyBpZD0iY2FudmFzX3NpZ25hdHVyZV9vdXRwdXRfeyRmaWVsZC0+aWR9IiBjbGFzcz0icGFkIiB3aWR0aD0ieyRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc193aWR0aH0iIGhlaWdodD0ieyRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHR9Ij48L2NhbnZhcz4NCgkNCgk8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJzaWduYXR1cmVfb3V0cHV0X3skZmllbGQtPmlkfSIgY2xhc3M9InNpZ25hdHVyZV9vdXRwdXRfeyRmaWVsZC0+aWR9Ij4NCgkNCgk8IS0tIGhvbGRzIHRoZSBpbWFnZSBkYXRhIG9mIGEgJ3R5cGVkIG9ubHknIHNpZ25hdHVyZSAtLT4NCgk8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJzaWduYXR1cmVfb3V0cHV0X2ltYWdlX3skZmllbGQtPmlkfSIgaWQ9InNpZ25hdHVyZV9vdXRwdXRfaW1hZ2VfeyRmaWVsZC0+aWR9IiBjbGFzcz0ic2lnbmF0dXJlX291dHB1dF9pbWFnZV97JGZpZWxkLT5pZH0iPg0KDQoJPC9kaXY+DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQovKiBvdmVycmlkZXMgdmVyc2lvbiBpbiBjc3MgZmlsZSAqLw0KLnNpZ1BhZF97JGZpZWxkLT5pZH0gew0KICBtYXJnaW46IDA7DQogIHBhZGRpbmc6IDA7DQogIHdpZHRoOiB7JGZpZWxkLT5zaWduYXR1cmVfY2FudmFzX3dpZHRofXB4Ow0KfQ0KDQouc2lnV3JhcHBlcl97JGZpZWxkLT5pZH0gew0KICBjbGVhcjogYm90aDsNCiAgaGVpZ2h0OiB7JHdyYXBwZXJIZWlnaHR9cHg7IC8qIHNob3VsZCBiZSAxMCBwaXhlbHMgaGlnaGVyIHRoYW4gY2FudmFzIGhlaWdodCBpZiBib3R0b20gbGluZSA9PSAwICovDQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgd2lkdGg6IHskZmllbGQtPnNpZ25hdHVyZVBhZFdpZHRofXB4Ow0KfQ0KPC9zdHlsZT4NCg0KPHNjcmlwdD4NCg0KZnVuY3Rpb24gZ2VuZXJhdGVfdGV4dF9jYW52YXNfaW1hZ2VfeyRmaWVsZC0+aWR9KGlkKXsNCgl2YXIgdGVtcENhbnZhc0h0bWwgPSAnPGNhbnZhcyBpZD0idGVtcF9jYW52YXNfeyRmaWVsZC0+aWR9IiBzdHlsZT0iZGlzcGxheTpub25lOyIgd2lkdGg9InskZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfd2lkdGh9IiBoZWlnaHQ9InskZmllbGQtPnNpZ25hdHVyZV9jYW52YXNfaGVpZ2h0fSI+PC9jYW52YXM+JzsNCglcJGooImJvZHkiKS5hcHBlbmQodGVtcENhbnZhc0h0bWwpOw0KCXZhciB0ZW1wQ2FudmFzID0gXCRqKCIjdGVtcF9jYW52YXNfeyRmaWVsZC0+aWR9IikuZ2V0KDApOw0KCXZhciB0ZW1wQ3R4ID0gdGVtcENhbnZhcy5nZXRDb250ZXh0KCIyZCIpOw0KCXRlbXBDdHguZm9udCA9ICIyLjQ1ZW0vNTBweCAnSm91cm5hbCcsR2VvcmdpYSxUaW1lcyxzZXJpZiI7DQoJdGVtcEN0eC5maWxsU3R5bGUgPSAneyRmaWVsZC0+c2lnbmF0dXJlX3Blbl9jb2xvcn0nOw0KCXRlbXBDdHguZmlsbFRleHQoXCRqKCIjc2lnbmF0dXJlLV9pbnB1dF9maWVsZF97JGZpZWxkLT5pZH0iKS52YWwoKSwgNSwgNTApOw0KCQ0KCVwkaignI3NpZ25hdHVyZV9vdXRwdXRfaW1hZ2VfeyRmaWVsZC0+aWR9JykudmFsKHRlbXBDYW52YXMudG9EYXRhVVJMKCJpbWFnZS9wbmciKSkNCgl0ZW1wQ2FudmFzLnJlbW92ZSgpOw0KfQ0KCQ0KXCRqKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbiAoKSB7DQoJDQoJdmFyIG9wdGlvbnMgPSB7DQoJICBiZ0NvbG91ciA6ICd7JGZpZWxkLT5zaWduYXR1cmVfYmdfY29sb3J9Jw0KCSAgLCBwZW5Db2xvdXIgOiAneyRmaWVsZC0+c2lnbmF0dXJlX3Blbl9jb2xvcn0nDQoJICAsIHBlbldpZHRoOiB7JGZpZWxkLT5zaWduYXR1cmVfcGVuX3dpZHRofQ0KCSAgLCBsaW5lV2lkdGg6IHskZmllbGQtPnNpZ25hdHVyZV9saW5lX3dpZHRofQ0KCSAgLCBsaW5lVG9wOiB7JGxpbmVUb3B9IC8vIHNob3VsZCBiZSA1cHggbG93ZXIgdGhhbiBjYW52YXMgaGVpZ2h0DQoJICB7JGlucHV0dHlwZX0NCgkgICwgb3V0cHV0Oicuc2lnbmF0dXJlX291dHB1dF97JGZpZWxkLT5pZH0nIC8vIG11c3QgYmUgYSBjbGFzcyBuYW1lIQ0KCSAgLCB0eXBlZDogJy50eXBlZC17JGZpZWxkLT5pZH0nDQoJICAsIGVycm9yTWVzc2FnZTogJ3skZmllbGQtPnNpZ25hdHVyZV9lcnJvcl90ZXh0X2dlbmVyYWx9Jw0KCSAgLCBlcnJvck1lc3NhZ2VEcmF3OiAneyRmaWVsZC0+c2lnbmF0dXJlX2Vycm9yX3RleHRfZHJhd2l0fScNCgkgICwgcmVxdWlyZWQ6IHskcmVxdWlyZWR9DQoJfTsNCgkNCgkvLyBnZW5lcmF0ZSBjb250cm9sDQoJc2lnbmF0dXJlUGFkQVBJX3skZmllbGQtPmlkfSA9IFwkaignI2ZiX2ZsZC17JGZpZWxkLT5pZH0nKS5zaWduYXR1cmVQYWQob3B0aW9ucyk7DQoJDQoJLy8gaWYgaW4gdGV4dCBvbmx5IG1vZGUsIHJlZHJhdyBzaWduYXR1cmUgd2hlbiBwYWdlIGxvYWRzIHRvIGdldCBpbWFnZSBkYXRhLg0KCXZhciBtb2RlID0gJGZpZWxkLT5pbnB1dHR5cGU7DQoJaWYobW9kZSA9PSAxKXsNCgkJZ2VuZXJhdGVfdGV4dF9jYW52YXNfaW1hZ2VfeyRmaWVsZC0+aWR9KCdzaWduYXR1cmUtX2lucHV0X2ZpZWxkX3skZmllbGQtPmlkfScpOw0KCX0NCgkNCgkvLyByZWRyYXcgZXhpc3Rpbmcgc2lnbmF0dXJlIGlmIG5lZWRlZA0KCXZhciBzaWcgPSAnPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydzaWduYXR1cmVzJ11bInskZmllbGQtPmlkfSJdWydzaWduYXR1cmUnXSkpIHsgZWNobyBcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ3NpZ25hdHVyZXMnXVsieyRmaWVsZC0+aWR9Il1bJ3NpZ25hdHVyZSddOyB9IGVsc2UgeyBlY2hvICdbXSc7IH0gPz4nOw0KCWlmKHNpZyAhPSAnW10nKXsNCgkJc2lnbmF0dXJlUGFkQVBJX3skZmllbGQtPmlkfS5yZWdlbmVyYXRlKHNpZyk7DQoJfQ0KCQ0KCS8vIHByZS1wb3B1bGF0ZSB0eXBlZCBvbmx5IGVudGlyZXMNCgl2YXIgdHlwZWRfZGF0YSA9ICc8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ3NpZ25hdHVyZXMnXVsieyRmaWVsZC0+aWR9Il1bJ3NpZ25hdG9yJ10pKSB7IGVjaG8gXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydzaWduYXR1cmVzJ11bInskZmllbGQtPmlkfSJdWydzaWduYXRvciddOyB9ID8+JzsNCglpZih0eXBlZF9kYXRhICE9ICcnICYmIFwkaignLnR5cGVkLXskZmllbGQtPmlkfScpKXsNCgkJXCRqKCcudHlwZWQteyRmaWVsZC0+aWR9JykuaHRtbCh0eXBlZF9kYXRhKTsNCgl9DQoJDQp9KTsNCg0KLy8gaGVscGVyIGZ1bmN0aW9uIHRvIGRyYXcgdGV4dCBvbmx5IHNpZ25hdHVyZXMsIHRob3VnaCBub3QgeWV0IGltcGxlbWVudGVkLg0KZnVuY3Rpb24gZHJhd190eXBlZF9zaWduYXR1cmVfeyRmaWVsZC0+aWR9KHZhbCl7DQoNCgkvL1wkaignI3NpZ25hdHVyZV9vdXRwdXRfaW1hZ2VfeyRmaWVsZC0+aWR9JykuaHRtbChzaWduYXR1cmVQYWRBUElfeyRmaWVsZC0+aWR9LmdldFNpZ25hdHVyZUltYWdlKCkpOw0KDQp9DQoJDQo8L3NjcmlwdD4NCg0KRU9UOw0KICAgICAgICB9IA0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSRmaWVsZC0+aW5wdXR0eXBlID09IDMpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZmllbGQtPnNpZ25hdHVyZV9iZ19jb2xvciA9IHN0cl9yZXBsYWNlKCcjJywgJycsICRmaWVsZC0+c2lnbmF0dXJlX2JnX2NvbG9yKTsNCiAgICAgICAgICAgICRmaWVsZC0+c2lnbmF0dXJlX3Blbl9jb2xvciA9IHN0cl9yZXBsYWNlKCcjJywgJycsICRmaWVsZC0+c2lnbmF0dXJlX3Blbl9jb2xvcik7DQoNCiAgICAgICAgICAgICRlbGVtZW50ID0gICAgIDw8PEVPRg0KPD9waHANCg0KXCRlbmFibGVfcGRmID0gaXNzZXQoXCRQQUdFX0lTX1BERikgPyAxIDogeyRlbmFibGVfcGRmfTsNCg0KLy8gZHJhdyBzaWduYXR1cmUgaWYgaXQgZXhpc3RzDQppZihpc3NldChcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ3NpZ25hdHVyZXMnXVsieyRmaWVsZC0+c2lnbmF0dXJlX2Rpc3BsYXlfZmllbGR9Il1bJ3NpZ25hdHVyZSddKSkgew0KDQoJLy8gZGlzcGxheSBvcHRpb25zDQoJXCRvcHRpb25zID0gIiZiZ0NvbG91cj17JGZpZWxkLT5zaWduYXR1cmVfYmdfY29sb3J9JnBlbldpZHRoPXskZmllbGQtPnNpZ25hdHVyZV9wZW5fd2lkdGh9JnBlbkNvbG91cj17JGZpZWxkLT5zaWduYXR1cmVfcGVuX2NvbG9yfSZjYW52YXNXaWR0aD17JGZpZWxkLT5zaWduYXR1cmVfY2FudmFzX3dpZHRofSZjYW52YXNIZWlnaHQ9eyRmaWVsZC0+c2lnbmF0dXJlX2NhbnZhc19oZWlnaHR9IjsNCgkNCglpZihcJGVuYWJsZV9wZGYgPT0gMCl7DQoJDQoJCS8vIElmIGVtcHR5IGFycmF5LCB3ZSdyZSBpbiB0ZXh0IG1vZGUuDQoJCWlmKFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnc2lnbmF0dXJlcyddWyJ7JGZpZWxkLT5zaWduYXR1cmVfZGlzcGxheV9maWVsZH0iXVsnc2lnbmF0dXJlJ10gPT0gIltdIil7DQoJCQ0KCQkJZWNobyAiPGltZyBzcmM9J2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCwiLmJhc2U2NF9lbmNvZGUoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydzaWduYXR1cmVzJ11bInskZmllbGQtPnNpZ25hdHVyZV9kaXNwbGF5X2ZpZWxkfSJdWydzaWduYXR1cmVfaW1hZ2UnXSkuIicgLz4iOw0KCQkJDQoJCX0gZWxzZSB7DQoJCQ0KCQkJXCRyYW5kID0gbWQ1KHJhbmQoMTAwMCwgNTAwMCkpOw0KCQkNCgkJCS8vIHN0YW5kYXJkIGltYWdlIGZpbGUgaW5jbHVkZS4NCgkJCWVjaG8gIjxpbWcgc3JjPVwibGliL3NpZ25hdHVyZS1wYWQvZGlzcGxheS1zaWduYXR1cmUucGhwP3NpZ25hdHVyZS1pZD17JGZpZWxkLT5zaWduYXR1cmVfZGlzcGxheV9maWVsZH17XCRvcHRpb25zfSZyYW5kPXtcJHJhbmR9XCIgdGl0bGU9XCJcIiBhbHQ9XCJcIiAvPiI7DQoJCQkNCgkJfQ0KCQ0KCX0gZWxzZSB7DQoJDQoJCS8vIGFsdGVybmF0ZSwgZGlyZWN0IG91dHB1dCB0byBicm93c2VyIG1vZGUgZm9yIFBERiBjb25zdW1wdGlvbiAobm90IHN0eWxlZCkuDQoJCWVjaG8gIjxpbWcgc3JjPSdkYXRhOmltYWdlL3BuZztiYXNlNjQsIi5iYXNlNjRfZW5jb2RlKFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsnc2lnbmF0dXJlcyddWyJ7JGZpZWxkLT5zaWduYXR1cmVfZGlzcGxheV9maWVsZH0iXVsnc2lnbmF0dXJlX2ltYWdlJ10pLiInIC8+IjsNCgkJDQoJfQ0KDQp9DQo/PgkJDQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHN0eWxlLT50YWJsZW1vZGVzcGFuID09IDEpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4gPCEtLSB0YWJsZW1vZGUgc3BhbiB3aWR0aCAtLT4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICAgICAgDQogICAgfSANCg0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2ltYWdlKCRmaWVsZCwgJGpvYm5hbWUsICRmb3JtbmFtZSwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KICAgICAgICAkdGV4dCA9ICRmaWVsZC0+eydsYWJlbCd9Ow0KICAgICAgICAkc3JjID0gJGZpZWxkLT5zcmM7DQogICAgICAgICRsaW5rX2FkZHJlc3MgPSAkZmllbGQtPmxpbmtfYWRkcmVzczsNCiAgICAgICAgJGxpbmtfdGFyZ2V0ID0gJGZpZWxkLT5saW5rX3RhcmdldDsNCiAgICAgICAgJGxpbmtfdGl0bGUgPSAkZmllbGQtPmxpbmtfdGl0bGU7DQogICAgICAgICRsaW5rX3N1Ym1pdCA9ICRmaWVsZC0+bGlua19zdWJtaXQ7DQoNCiAgICAgICAgDQogICAgICAgICRkYXRhYmFzZV9pbWFnZV9lbmFibGUgPSAkZmllbGQtPmRhdGFiYXNlX2ltYWdlX2VuYWJsZTsNCiAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2RlYnVnX2xldmVsID0gaXNzZXQoJGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9kZWJ1Z19sZXZlbCkgPyAkZmllbGQtPmRhdGFiYXNlX2ltYWdlX2RlYnVnX2xldmVsIDogJzAnOw0KICAgICAgICAkZGF0YWJhc2VfaW1hZ2VfdGFibGUgPSAkZmllbGQtPmRhdGFiYXNlX2ltYWdlX3RhYmxlOw0KICAgICAgICAkZGF0YWJhc2VfaW1hZ2VfY29sdW1uID0gJGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9jb2x1bW47DQoNCiAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2NvbHVtbl9pZCA9ICRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfY29sdW1uX2lkOw0KICAgICAgICAkZGF0YWJhc2VfaW1hZ2VfaWQgPSAkZmllbGQtPmRhdGFiYXNlX2ltYWdlX2lkOw0KDQogICAgICAgICRkYXRhYmFzZV9pbWFnZV9jb2x1bW5fZW50cnlpZCA9ICRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfY29sdW1uX2VudHJ5aWQ7DQogICAgICAgICRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZCA9ICRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfZW50cnlpZDsNCiAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2VudHJ5X2lkX29yaWdpbmFsID0gJGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9lbnRyeWlkOw0KDQogICAgICAgICRkYXRhYmFzZV9pbWFnZV9zaXplID0gJGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9zaXplOw0KICAgICAgICAkZGF0YWJhc2VfaW1hZ2VfbWF4X3dpZHRoID0gJGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9tYXhfd2lkdGg7DQoNCiAgICAgICAgJGF0dHJpYnV0ZSA9ICRmaWVsZC0+YXR0cmlidXRlOw0KICAgICAgICAkYXR0cmlidXRlc3R5bGUgPSAkZmllbGQtPmF0dHJpYnV0ZXN0eWxlOw0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+bmFtZTsNCiAgICAgICAgJGlkID0gJGZpZWxkLT5pZDsNCiAgICAgICAgJHJvdXRlID0gJGZpZWxkLT5yb3V0ZTsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgkYXR0cmlidXRlc3R5bGUgPT0gIiIpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gJyBzdHlsZT0iJyAuICRhdHRyaWJ1dGVzdHlsZSAuICciICc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGxpbmtfYWRkcmVzcyA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGxpbmtfYWRkcmVzcywgNik7DQoNCg0KICAgICAgICANCiAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgaWYgKCFpc3NldCgkc3R5bGUtPnRhYmxlbW9kZXNwYW4pKSB7DQogICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChpbnQpJHN0eWxlLT50YWJsZW1vZGVzcGFuID09IDApIHsNCiAgICAgICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IHRydWU7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBzd2l0Y2ggKChpbnQpJGxpbmtfdGFyZ2V0KSB7DQogICAgICAgICAgICBjYXNlIDA6DQogICAgICAgICAgICAgICAgJGxpbmtfdGFyZ2V0ID0gJ19ibGFuayc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJGxpbmtfdGFyZ2V0ID0gJ19wYXJlbnQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyOg0KICAgICAgICAgICAgICAgICRsaW5rX3RhcmdldCA9ICdfc2VsZic7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDM6DQogICAgICAgICAgICAgICAgJGxpbmtfdGFyZ2V0ID0gJ190b3AnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCFpc19kaXIoJy4uLy4uL291dHB1dC9mb3Jtcy8nIC4gJGpvYm5hbWUgLiAnL2ltYWdlcycpKSB7DQogICAgICAgICAgICBAbWtkaXIoJy4uLy4uL291dHB1dC9mb3Jtcy8nIC4gJGpvYm5hbWUgLiAnL2ltYWdlcy8nLCBESVJFQ1RPUllfTU9EKTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoZmlsZV9leGlzdHMoIi4uLy4uL291dHB1dC91cGxvYWRfaW1hZ2VzL3skc3JjfSIpKSB7DQogICAgICAgICAgICBjb3B5KCIuLi8uLi9vdXRwdXQvdXBsb2FkX2ltYWdlcy97JHNyY30iLCAiLi4vLi4vb3V0cHV0L2Zvcm1zL3skam9ibmFtZX0iIC4gJy9pbWFnZXMvJyAuICRzcmMpOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGh9OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7XCI+Jm5ic3A7PC9kaXY+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KDQogICAgICAgICRzcmNfaHRtbCA9ICIiOw0KICAgICAgICAkd2lkdGhfaHRtbCA9ICIiOw0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICBpZiAoaXNzZXQoJGRhdGFiYXNlX2ltYWdlX2VuYWJsZSkgJiYgJGRhdGFiYXNlX2ltYWdlX2VuYWJsZSA9PSAiMSIpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJGZpZWxkLT5kYmNvbm5lY3RvciA9PSAnJyAmJiAhZmlsZV9leGlzdHMoIi4uLy4uL291dHB1dC9mb3Jtcy97JGpvYm5hbWV9IiAuICcvJyAuICdjb25maWcucGhwJykpIHsNCiAgICAgICAgICAgICAgICBjb3B5KCIuLi9tb3ZlZmlsZXMvY29uZmlnLnBocCIsICIuLi8uLi9vdXRwdXQvZm9ybXMveyRqb2JuYW1lfSIgLiAnLycgLiAnY29uZmlnLnBocCcpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICR0aGlzLT51bS0+cHVsbEN1c3RvbUNvbm5lY3RvckZpbGUoKHN0cmluZykkZmllbGQtPmRiY29ubmVjdG9yKTsNCg0KICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygiLi4vLi4vb3V0cHV0L2Zvcm1zL3skam9ibmFtZX0iIC4gJy8nIC4gJ0RhdGFiYXNlLnBocCcpKSB7DQogICAgICAgICAgICAgICAgY29weSgiLi4vbW92ZWZpbGVzL0RhdGFiYXNlLnBocCIsICIuLi8uLi9vdXRwdXQvZm9ybXMveyRqb2JuYW1lfSIgLiAnLycgLiAnRGF0YWJhc2UucGhwJyk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRiX3R5cGUgPSBpc3NldCgkZmllbGQtPnNvdXJjZXR5cGUpID8gJHRoaXMtPnVtLT50cmFuc2xhdGVTb3VyY2VUeXBlKChpbnQpJGZpZWxkLT5zb3VyY2V0eXBlKSA6ICcnOw0KICAgICAgICAgICAgJGRiX2hvc3QgPSBpc3NldCgkZmllbGQtPmRiaG9zdCkgPyAoc3RyaW5nKSRmaWVsZC0+ZGJob3N0IDogJyc7DQogICAgICAgICAgICAkbXlzcWxfc29ja2V0ID0gaXNzZXQoJGZpZWxkLT5kYnNvY2tldCkgPyAoc3RyaW5nKSRmaWVsZC0+ZGJzb2NrZXQgOiAnJzsNCiAgICAgICAgICAgICRteXNxbF9wb3J0ID0gaXNzZXQoJGZpZWxkLT5kYnBvcnQpID8gKGludCkkZmllbGQtPmRicG9ydCA6ICcnOw0KICAgICAgICAgICAgJGRiZHNuID0gaXNzZXQoJGZpZWxkLT5kYmRzbikgPyAoc3RyaW5nKSRmaWVsZC0+ZGJkc24gOiAnJzsNCiAgICAgICAgICAgICRkYl91c2VyID0gaXNzZXQoJGZpZWxkLT5kYnVzZXIpID8gKHN0cmluZykkZmllbGQtPmRidXNlciA6ICcnOw0KICAgICAgICAgICAgJGRiX3Bhc3MgPSBpc3NldCgkZmllbGQtPmRicHdkKSA/IChzdHJpbmcpJGZpZWxkLT5kYnB3ZCA6ICcnOw0KICAgICAgICAgICAgJGRiX2NhdGFsb2cgPSBpc3NldCgkZmllbGQtPmRic2NoZW1hKSA/IChzdHJpbmcpJGZpZWxkLT5kYnNjaGVtYSA6ICcnOw0KICAgICAgICAgICAgJGRiZGVidWdsZXZlbCA9IGlzc2V0KCRmaWVsZC0+ZGJkZWJ1Z2xldmVsKSA/IChpbnQpJGZpZWxkLT5kYmRlYnVnbGV2ZWwgOiAnJzsNCiAgICAgICAgICAgICRkYmNvbm5lY3RvciA9IGlzc2V0KCRmaWVsZC0+ZGJjb25uZWN0b3IpID8gKHN0cmluZykkZmllbGQtPmRiY29ubmVjdG9yIDogJyc7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRiX2Nvbm5lY3Rpb24gPSA8PDxFT0YNCjw/cGhwDQppZigneyRkYl9ob3N0fScgIT0gJycpew0KICAgIFwkZGJfdHlwZSA9ICd7JGRiX3R5cGV9JzsNCiAgICBcJGRiX2hvc3QgPSAneyRkYl9ob3N0fSc7DQogICAgXCRteXNxbF9zb2NrZXQgPSAneyRteXNxbF9zb2NrZXR9JzsNCiAgICBcJG15c3FsX3BvcnQgPSAneyRteXNxbF9wb3J0fSc7DQogICAgXCRkYmRzbiA9ICd7JGRiZHNufSc7DQogICAgXCRkYl91c2VyID0gJ3skZGJfdXNlcn0nOw0KICAgIFwkZGJfcGFzcyA9ICd7JGRiX3Bhc3N9JzsNCiAgICBcJGRiX2NhdGFsb2cgPSAneyRkYl9jYXRhbG9nfSc7DQp9DQoNCg0KXCRkYl9zc2xfa2V5ID0gJ3skZmllbGQtPmRic3Nsa2V5fSc7DQpcJGRiX3NzbF9jZXJ0aWZpY2F0ZSA9ICd7JGZpZWxkLT5kYnNzbGNlcnRpZmljYXRlfSc7DQpcJGRiX3NzbF9jYV9jZXJ0ID0gJ3skZmllbGQtPmRic3NsY2FjZXJ0fSc7DQpcJGRiX3NzbF92ZXJpZnlfY2VydCA9ICd7JGZpZWxkLT5kYnNzbHZlcmlmeWNlcnR9JzsNClwkZGJfc3NsX2NpcGhlciA9ICd7JGZpZWxkLT5kYnNzbGNpcGhlcn0nOw0KDQppbmNsdWRlX29uY2UgJ0RhdGFiYXNlLnBocCc7DQoNClwkZGVidWcgPSB7JGRiZGVidWdsZXZlbH07IC8vIFVJIG92ZXJyaWRlDQovLyBPcHRpb25hbCBEQiBDb25uZWN0b3IgRmlsZSAtIGlmIG5vdCBzcGVjaWZpZWQgUmFja0Zvcm1zIHdpbGwgdXNlIGNvbmZpZy5waHAgdmlhIERhdGFiYXNlLnBocCBpbmNsdWRlDQppZihmaWxlX2V4aXN0cygneyRkYmNvbm5lY3Rvcn0nKSl7DQoJaW5jbHVkZSAneyRkYmNvbm5lY3Rvcn0nOw0KfQ0KPz4NCkVPRjsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gJGRiX2Nvbm5lY3Rpb247DQoNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2lkID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGF0YWJhc2VfaW1hZ2VfaWQsIDQpOw0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfaWQgPT0gJGRhdGFiYXNlX2ltYWdlX2lkKSB7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICghaXNfaW50KCRkYXRhYmFzZV9pbWFnZV9pZCkpIHsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2lkID0gJyInIC4gc3RyX3JlcGxhY2UoJyInLCAnXCInLCAkZGF0YWJhc2VfaW1hZ2VfaWQpIC4gJyInOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcblxuPD9waHAgXCRfU0VTU0lPTlsnZm9ybV9pbWFnZV90b2tlbiddID0gdHJ1ZTsgPz5cblxuIjsNCg0KICAgICAgICAgICAgJHNpemUgPSAibm9ybWFsIjsNCg0KICAgICAgICAgICAgaWYgKCRkYXRhYmFzZV9pbWFnZV9zaXplID09ICIxIikNCiAgICAgICAgICAgICRzaXplID0gInRodW1iIjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkdGFibGUgPSAiIjsNCiAgICAgICAgICAgICRjb2x1bW4gPSAiaW1hZ2VfZGF0YSI7DQogICAgICAgICAgICAkY29sdW1uaWQgPSAiaW1hZ2VfaWQiOw0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRkYXRhYmFzZV9pbWFnZV90YWJsZSkgJiYgJGRhdGFiYXNlX2ltYWdlX3RhYmxlICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAkdGFibGUgPSAkZGF0YWJhc2VfaW1hZ2VfdGFibGU7DQogICAgICAgICAgICAgICAgJGNvbHVtbiA9ICJpbWFnZV9kYXRhIjsNCiAgICAgICAgICAgICAgICAkY29sdW1uaWQgPSAiaW1hZ2VfaWQiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRkYXRhYmFzZV9pbWFnZV9jb2x1bW4pICYmICRkYXRhYmFzZV9pbWFnZV9jb2x1bW4gIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAgICAgJGNvbHVtbiA9ICRkYXRhYmFzZV9pbWFnZV9jb2x1bW47DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRkYXRhYmFzZV9pbWFnZV9jb2x1bW5faWQpICYmICRkYXRhYmFzZV9pbWFnZV9jb2x1bW5faWQgIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAgICAgJGNvbHVtbmlkID0gJGRhdGFiYXNlX2ltYWdlX2NvbHVtbl9pZDsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoJGRhdGFiYXNlX2ltYWdlX2lkICE9ICIiICYmICRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZCA9PSAiIikgew0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPRg0KXG5cbjw/cGhwDQppbmNsdWRlX29uY2UgJy4vRGF0YWJhc2UucGhwJzsNClwkZGJoX2ltZyA9IG5ldyBEYXRhYmFzZSgpOw0KDQpcJHJhbmQgPSBtZDUocmFuZCgxMDAwLCAxMDAwMDApKTsNCgkJCQkNCi8vIEN1c3RvbSBJbWFnZSBDYWxsIEZvciBTaW5nbGUgSW1hZ2VzLg0KXCRfU0VTU0lPTlsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWyJ7XCRyYW5kfSJdWydpbWFnZWNhbGxfdGFibGVfbmFtZSddID0gInskdGFibGV9IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2NvbHVtbl9uYW1lJ10gPSAieyRjb2x1bW59IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2NvbHVtbl9pZCddID0gInskY29sdW1uaWR9IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2RhdGFiYXNlX2ltYWdlX2lkJ10gPSB7JGRhdGFiYXNlX2ltYWdlX2lkfTsNCg0KDQppZihpc3NldChcJFBBR0VfSVNfUERGKSAmJiBcJFBBR0VfSVNfUERGID09IHRydWUpIHsNCg0KCS8vIElubGluZSBJbWFnZXMgRm9yIFBERi4NCgkNCglpbmNsdWRlX29uY2UgImxpYi9nZXRfZm9ybV9pbWFnZV9pbmxpbmUucGhwIjsNCgkNCglcJGRiID0gYXJyYXkoXCRkYl90eXBlLCBcJGRiX2hvc3QsIFwkbXlzcWxfc29ja2V0LCBcJG15c3FsX3BvcnQsIFwkZGJkc24sIFwkZGJfdXNlciwgXCRkYl9wYXNzLCBcJGRiX2NhdGFsb2csIFwkZGVidWcpOw0KCQ0KCVwkaW1nRGF0YSA9IGdldF9pbmxpbmVfaW1hZ2UoIm51bGwiLCAibm9ybWFsIiwgIiIsICIiLCBcJHJhbmQsIFwkZGIpOw0KCQ0KCWlmKFwkaW1nRGF0YVsxXSAhPSAiIikgew0KDQoJCVwkcmF3RGF0YSA9IGJhc2U2NF9lbmNvZGUoXCRpbWdEYXRhWzFdKTsNCgkJDQoJCWVjaG8gJzxpbWcgY2xhc3M9ImZvcm0taW1hZ2UgeyRleHRyYWNsYXNzbmFtZXN9IiBzcmM9ImRhdGE6aW1hZ2UvJyAuIFwkaW1nRGF0YVswXSAuICc7YmFzZTY0LCcgLiBcJHJhd0RhdGEgLiAnIiB7JGluaGVyaXRzdHlsZX0gd2lkdGg9InskZmllbGQtPmRhdGFiYXNlX2ltYWdlX21heF93aWR0aH0iIGNsYXNzPSJyZi1mb3JtLWltYWdlIiAvPic7DQoNCgl9DQoJDQp9IGVsc2Ugew0KDQoJLy8gT3JpZ2luYWwsIElubGluZSBJbWFnZSBFY2hvLg0KDQogICAgaWYoXCRkYl9ob3N0ID09ICIiKXsNCg0KICAgICAgICBcJHN0eWxlcyA9ICd7JGluaGVyaXRzdHlsZX0nOw0KDQogICAgICAgIC8vIEVzY2FwZSBFeHRyYSBTdHlsZXMuDQoNCiAgICAgICAgLy8kaW5oZXJpdHN0eWxlID0gc3RyX3JlcGxhY2UoJyInLCAnXCInLCAkaW5oZXJpdHN0eWxlKTsNCg0KICAgICAgICBlY2hvICc8aW1nIGNsYXNzPSJmb3JtLWltYWdlIHskZXh0cmFjbGFzc25hbWVzfSIgc3JjPSJsaWIvZ2V0X2Zvcm1faW1hZ2UucGhwP2lkPW51bGwmc2l6ZT17JHNpemV9JnJhbmQ9JyAuIFwkcmFuZCAuICciIHdpZHRoPSJ7JGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9tYXhfd2lkdGh9IiB0aXRsZT0iJHRleHQiIHskYXR0cmlidXRlfSB7JGluaGVyaXRzdHlsZX0gbmFtZT0ieyRuYW1lfSIgaWQ9InskaWR9IiBjbGFzcz0icmYtZm9ybS1pbWFnZSIgLz4nOw0KDQogICAgfSBlbHNlIHsNCg0KICAgICAgICAvLyBJbWFnZSBQdWxsIFVzaW5nIChPcHRpb25hbCkgRHluYW1pYyBEYXRhYmFzZSBEZXRhaWxzLg0KDQogICAgICAgIGluY2x1ZGVfb25jZSAibGliL2dldF9mb3JtX2ltYWdlX2lubGluZS5waHAiOw0KICAgICAgICANCiAgICAgICAgXCRkYiA9IGFycmF5KFwkZGJfdHlwZSwgXCRkYl9ob3N0LCBcJG15c3FsX3NvY2tldCwgXCRteXNxbF9wb3J0LCBcJGRiZHNuLCBcJGRiX3VzZXIsIFwkZGJfcGFzcywgXCRkYl9jYXRhbG9nLCBcJGRlYnVnKTsNCiAgICAgICAgDQogICAgICAgIFwkaW1nRGF0YSA9IGdldF9pbmxpbmVfaW1hZ2UoIm51bGwiLCAibm9ybWFsIiwgIiIsICIiLCBcJHJhbmQsIFwkZGIpOw0KICAgICAgICANCiAgICAgICAgaWYoXCRpbWdEYXRhWzFdICE9ICIiKSB7DQoNCiAgICAgICAgICAgIFwkcmF3RGF0YSA9IGJhc2U2NF9lbmNvZGUoXCRpbWdEYXRhWzFdKTsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgZWNobyAnPGltZyBjbGFzcz0iZm9ybS1pbWFnZSB7JGV4dHJhY2xhc3NuYW1lc30iIHNyYz0iZGF0YTppbWFnZS8nIC4gXCRpbWdEYXRhWzBdIC4gJztiYXNlNjQsJyAuIFwkcmF3RGF0YSAuICciIHskaW5oZXJpdHN0eWxlfSB3aWR0aD0ieyRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfbWF4X3dpZHRofSIgY2xhc3M9InJmLWZvcm0taW1hZ2UiIC8+JzsNCg0KICAgICAgICB9DQoNCiAgICB9DQp9DQoNCg0KPz4NCkVPRjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICgkZGF0YWJhc2VfaW1hZ2VfZW50cnlfaWQgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGRhdGFiYXNlX2ltYWdlX2VudHJ5X2lkID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGF0YWJhc2VfaW1hZ2VfZW50cnlfaWQsIDQpOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZW50cnlfaWRfY29sdW1uX25hbWUgPSAiZW50cnlfaWQiOw0KDQogICAgICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZGF0YWJhc2VfaW1hZ2VfY29sdW1uX2VudHJ5aWQpICYmICRkYXRhYmFzZV9pbWFnZV9jb2x1bW5fZW50cnlpZCAhPSAiIil7DQogICAgICAgICAgICAgICAgICAgICAgICAkZW50cnlfaWRfY29sdW1uX25hbWUgPSAkZGF0YWJhc2VfaW1hZ2VfY29sdW1uX2VudHJ5aWQ7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAkaW1hZ2VfcGFyYW1zID0gIlwkcGFyYW1zID0gYXJyYXkoeyRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZH0pOyI7IA0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIGlmKCRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZF9vcmlnaW5hbCA9PSAkZGF0YWJhc2VfaW1hZ2VfZW50cnlfaWQpew0KDQogICAgICAgICAgICAgICAgICAgICAgICAkaW1hZ2VfcGFyYW1zID0gIlwkcGFyYW1zID0gYXJyYXkoJ3skZGF0YWJhc2VfaW1hZ2VfZW50cnlfaWR9Jyk7IjsgDQoNCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPRg0KXG5cbjw/cGhwDQppbmNsdWRlX29uY2UgJy4vRGF0YWJhc2UucGhwJzsNClwkZGJoX2ltZyA9IG5ldyBEYXRhYmFzZSgpOw0KCQkJCQkNClwkc3FsX2ltZyA9ICJTRUxFQ1QgeyRjb2x1bW5pZH0gRlJPTSB7JHRhYmxlfSBXSEVSRSB7JGVudHJ5X2lkX2NvbHVtbl9uYW1lfSA9ID8iOw0KeyRpbWFnZV9wYXJhbXN9DQoNCi8vIFNldCBPcHRpb25hbCBNeVNRTCBTU0wgUHJvcGVydGllcy4NCg0KXCRkYmhfaW1nLT5zZXRNeVNRTFNTTFByb3BlcnRpZXMoXCRkYl9zc2xfa2V5LCBcJGRiX3NzbF9jZXJ0aWZpY2F0ZSwgXCRkYl9zc2xfY2FfY2VydCwgXCRkYl9zc2xfdmVyaWZ5X2NlcnQsIFwkZGJfc3NsX2NpcGhlcik7DQoNClwkcmVzdWx0X2ltZ19lbnRyaWVzID0gXCRkYmhfaW1nLT5wZG9fcHJvY2VkdXJlX3BhcmFtcyh7JGRhdGFiYXNlX2ltYWdlX2RlYnVnX2xldmVsfSwgXCRzcWxfaW1nLCBcJGRiX2hvc3QsIFwkZGJfdHlwZSwgXCRteXNxbF9zb2NrZXQsIFwkbXlzcWxfcG9ydCwgXCRkYmRzbiwgXCRkYl91c2VyLCBcJGRiX3Bhc3MsIFwkZGJfY2F0YWxvZywgXCRwYXJhbXMsIFwkcmV0dXJuX3RydWUgPSAwKTsNCgkJCQkJDQovLyBGb3IgZXZlcnkgbWF0Y2hpbmcgcm93LCBlY2hvIG91dCBhbiBpbWFnZS4NCg0KXCRjdCA9IDA7DQoNCmZvcmVhY2goXCRyZXN1bHRfaW1nX2VudHJpZXMgYXMgXCRlbnRyeSl7DQoNCglcJHJhbmQgPSBtZDUocmFuZCgxMDAwLCAxMDAwMDApKTsNCg0KCS8vIEN1c3RvbSBJbWFnZSBDYWxsLg0KCVwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX3RhYmxlX25hbWUnXSA9ICJ7JHRhYmxlfSI7DQoJXCRfU0VTU0lPTlsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWyJ7XCRyYW5kfSJdWydpbWFnZWNhbGxfY29sdW1uX25hbWUnXSA9ICJ7JGNvbHVtbn0iOw0KCVwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2NvbHVtbl9pZCddID0gInskY29sdW1uaWR9IjsNCglcJF9TRVNTSU9OWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bIntcJHJhbmR9Il1bJ2ltYWdlY2FsbF9kYXRhYmFzZV9pbWFnZV9pZCddID0gXCRlbnRyeVsieyRjb2x1bW5pZH0iXTsNCgkNCgkNCglpZihpc3NldChcJFBBR0VfSVNfUERGKSAmJiBcJFBBR0VfSVNfUERGID09IHRydWUpIHsNCgkNCgkJLy8gSW5saW5lIEltYWdlcyBGb3IgUERGLg0KCQ0KCQlpbmNsdWRlX29uY2UgImxpYi9nZXRfZm9ybV9pbWFnZV9pbmxpbmUucGhwIjsNCgkNCgkJXCRkYiA9IGFycmF5KFwkZGJfdHlwZSwgXCRkYl9ob3N0LCBcJG15c3FsX3NvY2tldCwgXCRteXNxbF9wb3J0LCBcJGRiZHNuLCBcJGRiX3VzZXIsIFwkZGJfcGFzcywgXCRkYl9jYXRhbG9nLCBcJGRlYnVnKTsNCgkNCgkJXCRpbWdEYXRhID0gZ2V0X2lubGluZV9pbWFnZSgibnVsbCIsICJub3JtYWwiLCAiIiwgIiIsIFwkcmFuZCwgXCRkYik7DQoJDQoJCWlmKFwkaW1nRGF0YVsxXSAhPSAiIikgew0KCQkNCgkJCVwkcmF3RGF0YSA9IGJhc2U2NF9lbmNvZGUoXCRpbWdEYXRhWzFdKTsNCgkJDQoJCQllY2hvICc8aW1nIGNsYXNzPVwiZm9ybS1pbWFnZSB7JGV4dHJhY2xhc3NuYW1lc31cIiBzcmM9ImRhdGE6aW1hZ2UvJyAuIFwkaW1nRGF0YVswXSAuICc7YmFzZTY0LCcgLiBcJHJhd0RhdGEgLiAnIiB3aWR0aD1cInskZmllbGQtPmRhdGFiYXNlX2ltYWdlX21heF93aWR0aH1cIiB7JGluaGVyaXRzdHlsZX0gY2xhc3M9XCJyZi1mb3JtLWltYWdlXCIgLz4nOw0KCQkNCgkJfQ0KCQ0KCX0gZWxzZSB7DQoNCgkJZWNobyAiPGltZyBjbGFzcz1cImZvcm0taW1hZ2UgeyRleHRyYWNsYXNzbmFtZXN9XCIgc3JjPVwibGliL2dldF9mb3JtX2ltYWdlLnBocD9pZD1udWxsJnNpemU9eyRzaXplfSZyYW5kPXtcJHJhbmR9XCIgd2lkdGg9XCJ7JGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9tYXhfd2lkdGh9XCIgdGl0bGU9XCIkdGV4dFwiIHskYXR0cmlidXRlfSB7JGluaGVyaXRzdHlsZX0gaWQ9XCJ7JGlkfV97XCRjdH1cIiBjbGFzcz1cInJmLWZvcm0taW1hZ2VcIiAvPiI7DQoJCQ0KCX0NCgkJDQoJXCRjdCsrOw0KfQ0KCQkJCQkNCj8+DQoJCQkJCQ0KRU9GOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZGF0YWJhc2VfaW1hZ2VfaWRfc3RhdGljID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGQtPmRhdGFiYXNlX2ltYWdlX2lkLCA2KTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmICgkZGF0YWJhc2VfaW1hZ2VfaWQgIT0gIiIpIHsNCg0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPRg0KXG5cbjw/cGhwDQppbmNsdWRlX29uY2UgJy4vRGF0YWJhc2UucGhwJzsNClwkZGJoX2ltZyA9IG5ldyBEYXRhYmFzZSgpOw0KCQkJCQkNClwkcmFuZCA9IG1kNShyYW5kKDEwMDAsIDEwMDAwMCkpOw0KCQkJCQkNCi8vIEN1c3RvbSBJbWFnZSBDYWxsIEZvciBTaW5nbGUgSW1hZ2VzLg0KXCRfU0VTU0lPTlsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWyJ7XCRyYW5kfSJdWydpbWFnZWNhbGxfdGFibGVfbmFtZSddID0gInskdGFibGV9IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2NvbHVtbl9uYW1lJ10gPSAieyRjb2x1bW59IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2NvbHVtbl9pZCddID0gInskY29sdW1uaWR9IjsNClwkX1NFU1NJT05bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsie1wkcmFuZH0iXVsnaW1hZ2VjYWxsX2RhdGFiYXNlX2ltYWdlX2lkJ10gPSB7JGRhdGFiYXNlX2ltYWdlX2lkfTsNCgkJCQkJDQoJCQkJCQ0KaWYoaXNzZXQoXCRQQUdFX0lTX1BERikgJiYgXCRQQUdFX0lTX1BERiA9PSB0cnVlKSB7DQoJCQkJCQ0KCS8vIElubGluZSBJbWFnZXMgRm9yIFBERi4NCgkJCQkJDQoJaW5jbHVkZV9vbmNlICJsaWIvZ2V0X2Zvcm1faW1hZ2VfaW5saW5lLnBocCI7DQoJCQkJCQ0KCVwkZGIgPSBhcnJheShcJGRiX3R5cGUsIFwkZGJfaG9zdCwgXCRteXNxbF9zb2NrZXQsIFwkbXlzcWxfcG9ydCwgXCRkYmRzbiwgXCRkYl91c2VyLCBcJGRiX3Bhc3MsIFwkZGJfY2F0YWxvZywgXCRkZWJ1Zyk7DQoJCQkJCQ0KCVwkaW1nRGF0YSA9IGdldF9pbmxpbmVfaW1hZ2UoeyRkYXRhYmFzZV9pbWFnZV9pZH0sICJub3JtYWwiLCAiIiwgIiIsIFwkcmFuZCwgXCRkYik7DQoJCQkJCQ0KCWlmKFwkaW1nRGF0YVsxXSAhPSAiIikgew0KCQkJCQkNCgkJXCRyYXdEYXRhID0gYmFzZTY0X2VuY29kZShcJGltZ0RhdGFbMV0pOw0KCQkJCQkNCgkJZWNobyAnPGltZyBjbGFzcz1cImZvcm0taW1hZ2UgeyRleHRyYWNsYXNzbmFtZXN9XCIgc3JjPSJkYXRhOmltYWdlLycgLiBcJGltZ0RhdGFbMF0gLiAnO2Jhc2U2NCwnIC4gXCRyYXdEYXRhIC4gJyIgeyRpbmhlcml0c3R5bGV9IHdpZHRoPVwieyRmaWVsZC0+ZGF0YWJhc2VfaW1hZ2VfbWF4X3dpZHRofVwiIGNsYXNzPVwicmYtZm9ybS1pbWFnZVwiIC8+JzsNCgkJCQkJDQoJfQ0KCQkJCQkNCn0gZWxzZSB7DQoJCQkJCQ0KCS8vIE9yaWdpbmFsLCBJbmxpbmUgSW1hZ2UgRWNoby4NCgkNCglcJHZhbCA9IHskZGF0YWJhc2VfaW1hZ2VfaWR9Ow0KCQkJCQkNCgllY2hvICI8aW1nIGNsYXNzPVwiZm9ybS1pbWFnZSB7JGV4dHJhY2xhc3NuYW1lc31cIiBzcmM9XCJsaWIvZ2V0X2Zvcm1faW1hZ2UucGhwP2lkPXtcJHZhbH0mc2l6ZT17JHNpemV9XCIgd2lkdGg9XCJ7JGZpZWxkLT5kYXRhYmFzZV9pbWFnZV9tYXhfd2lkdGh9XCIgdGl0bGU9XCIkdGV4dFwiIHskYXR0cmlidXRlfSB7JGluaGVyaXRzdHlsZX0gbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgY2xhc3M9XCJyZi1mb3JtLWltYWdlXCIgLz4iOw0KCQkJCQkNCn0NCgkJCQkJDQoJCQkJCQ0KPz4NCkVPRjsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGRhdGFiYXNlX2ltYWdlX2VudHJ5X2lkICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRhdGFiYXNlX2ltYWdlX2VudHJ5X2lkLCA0KTsNCg0KICAgICAgICAgICAgICAgICAgICAkaW1hZ2VfcGFyYW1zID0gIlwkcGFyYW1zID0gYXJyYXkoeyRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZH0pOyI7IA0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIGlmICgkZGF0YWJhc2VfaW1hZ2VfZW50cnlfaWRfb3JpZ2luYWwgPT0gJGRhdGFiYXNlX2ltYWdlX2VudHJ5X2lkKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRpbWFnZV9wYXJhbXMgPSAiXCRwYXJhbXMgPSBhcnJheSgneyRkYXRhYmFzZV9pbWFnZV9lbnRyeV9pZH0nKTsiOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQpcblxuPD9waHANCmluY2x1ZGVfb25jZSAnLi9EYXRhYmFzZS5waHAnOw0KXCRkYmhfaW1nID0gbmV3IERhdGFiYXNlKCk7DQoNClwkc3FsX2ltZyA9ICJTRUxFQ1QgaW1hZ2VfaWQgRlJPTSBmYl9pbWFnZXMgV0hFUkUgZW50cnlfaWQgPSA/IjsNCnskaW1hZ2VfcGFyYW1zfQ0KDQovLyBTZXQgT3B0aW9uYWwgTXlTUUwgU1NMIFByb3BlcnRpZXMuDQpcJGRiaF9pbWctPnNldE15U1FMU1NMUHJvcGVydGllcyhcJGRiX3NzbF9rZXksIFwkZGJfc3NsX2NlcnRpZmljYXRlLCBcJGRiX3NzbF9jYV9jZXJ0LCBcJGRiX3NzbF92ZXJpZnlfY2VydCwgXCRkYl9zc2xfY2lwaGVyKTsNCg0KXCRyZXN1bHRfaW1nX2VudHJpZXMgPSBcJGRiaF9pbWctPnBkb19wcm9jZWR1cmVfcGFyYW1zKDAsIFwkc3FsX2ltZywgXCRkYl9ob3N0LCBcJGRiX3R5cGUsIFwkbXlzcWxfc29ja2V0LCBcJG15c3FsX3BvcnQsIFwkZGJkc24sIFwkZGJfdXNlciwgXCRkYl9wYXNzLCBcJGRiX2NhdGFsb2csIFwkcGFyYW1zLCBcJHJldHVybl90cnVlID0gMCk7DQoJCQ0KLy8gRm9yIGV2ZXJ5IG1hdGNoaW5nIHJvdywgZWNobyBvdXQgaW1hZ2UuDQoJCQ0KZm9yZWFjaChcJHJlc3VsdF9pbWdfZW50cmllcyBhcyBcJGVudHJ5KXsNCgllY2hvICI8aW1nIGNsYXNzPVwiZm9ybS1pbWFnZSB7JGV4dHJhY2xhc3NuYW1lc31cIiBzcmM9XCJsaWIvZ2V0X2Zvcm1faW1hZ2UucGhwP2lkPXtcJGVudHJ5WydpbWFnZV9pZCddfSZzaXplPXskc2l6ZX1cIiB3aWR0aD1cInskZmllbGQtPmRhdGFiYXNlX2ltYWdlX21heF93aWR0aH1cIiB0aXRsZT1cIiR0ZXh0XCIgeyRhdHRyaWJ1dGV9IHskaW5oZXJpdHN0eWxlfSBuYW1lPVwieyRuYW1lfVwiIGlkPVwieyRpZH1cIiBjbGFzcz1cInJmLWZvcm0taW1hZ2VcIiAvPiI7CQkNCn0NCg0KPz4NCg0KRU9GOw0KICAgICAgICAgICAgICAgIH0gDQogICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cbjw/cGhwIHVuc2V0KFwkX1NFU1NJT05bJ2Zvcm1faW1hZ2VfdG9rZW4nXSk7ID8+XG5cbiI7DQogICAgICAgIH0gZWxzZSB7IA0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxpbWcgY2xhc3M9XCJmb3JtLWltYWdlIHskZXh0cmFjbGFzc25hbWVzfVwiIHNyYz1cIjw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5pbWFnZXMvJHNyY1wiIHRpdGxlPVwiJHRleHRcIiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IG5hbWU9XCJ7JG5hbWV9XCIgaWQ9XCJ7JGlkfVwiIC8+IjsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJGxpbmtfc3VibWl0ID09IDEpIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50ID0gIjxpbnB1dCB0eXBlPVwiaW1hZ2VcIiB0YXJnZXQ9XCJ7JGxpbmtfdGFyZ2V0fVwiIHRpdGxlPVwieyRsaW5rX3RpdGxlfVwiIHNyYz1cIjw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5pbWFnZXMveyRzcmN9XCIgbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgeyRhdHRyaWJ1dGV9IHskaW5oZXJpdHN0eWxlfSB2YWx1ZT1cInskdGV4dH1cIiAvPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCRsaW5rX2FkZHJlc3MgIT0gJycpIHsNCiAgICAgICAgICAgICRlbGVtZW50ID0gIjxhIGhyZWY9XCJ7JGxpbmtfYWRkcmVzc31cIiB0YXJnZXQ9XCJ7JGxpbmtfdGFyZ2V0fVwiIHRpdGxlPVwieyRsaW5rX3RpdGxlfVwiPjxpbWcgY2xhc3M9XCJmb3JtLWltYWdlIHskZXh0cmFjbGFzc25hbWVzfVwiIHNyYz1cIjw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5pbWFnZXMveyRzcmN9XCIgbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgdGl0bGU9XCJ7JHRleHR9XCIgYm9yZGVyPVwiMFwiIHskYXR0cmlidXRlfSB7JGluaGVyaXRzdHlsZX0gLz48L2E+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJHJvdXRlICE9ICcnKSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgPSAiPGlucHV0IHR5cGU9XCJpbWFnZVwiIHRpdGxlPVwieyRsaW5rX3RpdGxlfVwiIHRhcmdldD1cInskbGlua190YXJnZXR9XCIgc3JjPVwiPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmltYWdlcy97JHNyY31cIiBuYW1lPVwieyRuYW1lfVwiIGlkPVwieyRpZH1cIiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IHZhbHVlPVwieyR0ZXh0fVwiIC8+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV92aWRlbygkZmllbGQsICRqb2JuYW1lLCAkZm9ybW5hbWUsICR0YWJsZW1vZGUsICRidWNrZXRfbm9kZSA9ICIiKQ0KICAgIHsNCg0KICAgICAgICAkdXJsID0gJGZpZWxkLT51cmw7DQoNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkdXJsID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkdXJsLCA2KTsNCg0KDQogICAgICAgIA0KICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICBpZiAoIWlzc2V0KCRzdHlsZS0+dGFibGVtb2Rlc3BhbikpIHsNCiAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gZmFsc2U7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBpZiAoKGludCkkc3R5bGUtPnRhYmxlbW9kZXNwYW4gPT0gMCkgew0KICAgICAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gdHJ1ZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0O1wiPiZuYnNwOzwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICR1cmxfcmF3X2ZpbGVfbmFtZSA9IGV4cGxvZGUoJy8nLCAkdXJsKTsNCiAgICAgICAgJHVybF9yYXdfZmlsZV9uYW1lID0gZXhwbG9kZSgnLicsICR1cmxfcmF3X2ZpbGVfbmFtZVtjb3VudCgkdXJsX3Jhd19maWxlX25hbWUpIC0gMV0pOw0KICAgICAgICBhcnJheV9wb3AoJHVybF9yYXdfZmlsZV9uYW1lKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkdXJsX3Jhd19maWxlX25hbWVbMF0pKSB7DQogICAgICAgICAgICByZXR1cm4gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJhd19uYW1lID0gJHVybF9yYXdfZmlsZV9uYW1lWzBdOw0KDQoNCiAgICAgICAgJHVybF9wYXJ0cyA9IGV4cGxvZGUoIi8iLCAkdXJsKTsNCg0KICAgICAgICAkdXJsX2Zvcm1hdHRlZCA9ICIvLyI7DQoNCiAgICAgICAgZm9yZWFjaCAoJHVybF9wYXJ0cyBhcyAkaWR4ID0+ICRwYXJ0KSB7DQoNCiAgICAgICAgICAgIGlmICgkaWR4ID09IGNvdW50KCR1cmxfcGFydHMpIC0gMSkgew0KICAgICAgICAgICAgICAgICR1cmxfZm9ybWF0dGVkIC49ICcvJyAuICRyYXdfbmFtZTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgaWYgKCRpZHggPiAyKQ0KICAgICAgICAgICAgICAgICR1cmxfZm9ybWF0dGVkIC49ICcvJzsNCg0KICAgICAgICAgICAgICAgIGlmICgkcGFydCAhPSAnaHR0cDonKQ0KICAgICAgICAgICAgICAgICR1cmxfZm9ybWF0dGVkIC49ICRwYXJ0Ow0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJHBvc3RlciA9ICIiOw0KDQogICAgICAgIGlmICgkZmllbGQtPnBvc3RlciAhPSAiIikgew0KICAgICAgICAgICAgJHBvc3RlciA9ICJwb3N0ZXI9XCJ7JGZpZWxkLT5wb3N0ZXJ9XCIiOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQo8bGluayBocmVmPSJqcy92aWRlby1qcy92aWRlby1qcy5jc3MiIHJlbD0ic3R5bGVzaGVldCIgdHlwZT0idGV4dC9jc3MiPg0KPHNjcmlwdCBzcmM9ImpzL3ZpZGVvLWpzL3ZpZGVvLmpzIj48L3NjcmlwdD4NCg0KPHNjcmlwdD4NCgl2aWRlb2pzLm9wdGlvbnMuZmxhc2guc3dmID0gImpzL3ZpZGVvLWpzL3ZpZGVvLWpzLnN3ZiI7DQo8L3NjcmlwdD4NCg0KPHZpZGVvIGlkPSJ7JGZpZWxkLT5pZH0iIGNsYXNzPSJ2aWRlby1qcyB2anMtZGVmYXVsdC1za2luIiBjb250cm9scyBwcmVsb2FkPSJub25lIiB3aWR0aD0ieyRmaWVsZC0+d2lkdGh9IiBoZWlnaHQ9InskZmllbGQtPmhlaWdodH0iDQogICAgICB7JHBvc3Rlcn0NCiAgICAgIGRhdGEtc2V0dXA9Int9Ij4NCgk8c291cmNlIHNyYz0ieyR1cmx9IiB0eXBlPSd2aWRlby9tcDQnIC8+DQoJPHNvdXJjZSBzcmM9InskdXJsfS53ZWJtIiB0eXBlPSd2aWRlby93ZWJtJyAvPg0KCTxzb3VyY2Ugc3JjPSJ7JHVybF9mb3JtYXR0ZWR9Lm9ndiIgdHlwZT0ndmlkZW8vb2dnJyAvPg0KCTx0cmFjayBraW5kPSJjYXB0aW9ucyIgc3JjPSJ7JGZpZWxkLT5jYXB0aW9uc30iIHNyY2xhbmc9ImVuIiBsYWJlbD0iRW5nbGlzaCIgLz4NCiAgICBQbGVhc2UgdXBkYXRlIHlvdXIgYnJvd3NlciB0byB2aWV3IHRoaXMgdmlkZW8uDQo8L3ZpZGVvPg0KRU9GOw0KDQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAkdGFibGVtb2Rlc3BhbiAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9zZWN0aW9uX3RleHQoJGZpZWxkLCAkcGFnZSwgJGRhdGFncmlkX2l0ZW1zLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJHRleHQgPSAkZmllbGQtPnsnbGFiZWwnfTsNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT5jb2xvcjsNCiAgICAgICAgJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCg0KICAgICAgICAkdGFibGVtb2RlID0gJHBhZ2UtPnRhYmxlbW9kZTsNCiAgICAgICAgJHBhZ2VwYWRkaW5nID0gJHBhZ2UtPnBhZ2VwYWRkaW5nOw0KICAgICAgICAkZGltID0gJHBhZ2UtPmRpbTsNCg0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRzdHlsZSk7DQoNCiAgICAgICAgDQogICAgICAgICR0ZXh0ID0gJHRoaXMtPmNyZWF0ZV9pbmxpbmVfZ2V0X3ZhcnMoJHRleHQpOyANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+Y3JlYXRlX2lubGluZV9wb3N0X3ZhcnMoJHRleHQsICcsICcpOyANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+Y3JlYXRlX2lubGluZV9zZXNzaW9uX3ZhcnMoJHRleHQsICcsICcpOyANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+Y3JlYXRlX2lubGluZV9waHBfdmFycygkdGV4dCwgJywgJyk7IA0KDQogICAgICAgIA0KICAgICAgICAkdGV4dCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJHRleHQsIDYuMSk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfZmllbGRfcmF3KCR0ZXh0LCAwKTsNCg0KICAgICAgICANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfZmllbGRfbmV3bGluZSgkdGV4dCwgMCk7DQoNCiAgICAgICAgDQogICAgICAgICR0ZXh0ID0gJHRoaXMtPmNyZWF0ZV9pbmxpbmVfZmllbGRfdmFycygkdGV4dCk7IA0KDQogICAgICAgICRlbGVtZW50ID0gJHRleHRbMV07DQoNCg0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGRhdGFncmlkX2l0ZW1zX3BocCA9ICcnOw0KICAgICAgICAkZGF0YWdyaWRfaXRlbXNfcmF3ID0gYXJyYXkoKTsNCg0KICAgICAgICBpZiAoaXNzZXQoJGRhdGFncmlkX2l0ZW1zKSAmJiBjb3VudCgkZGF0YWdyaWRfaXRlbXMpICE9IDApIHsNCiAgICAgICAgICAgICRkYXRhZ3JpZF9pdGVtc19waHAgPSBpbXBsb2RlKCcsJywgJGRhdGFncmlkX2l0ZW1zKTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBmb3JlYWNoICgkZGF0YWdyaWRfaXRlbXMgYXMgJGdyaWRfaXRlbSkgew0KICAgICAgICAgICAgJHJhdyA9IGV4cGxvZGUoJ3wnLCAkZ3JpZF9pdGVtKTsNCiAgICAgICAgICAgICRkYXRhZ3JpZF9pdGVtc19yYXdbXSA9ICRyYXdbMF0gLiAiJyI7ICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc19hcnJheSgkZGF0YWdyaWRfaXRlbXNfcmF3KSkgew0KICAgICAgICAgICAgJGRhdGFncmlkX2l0ZW1zX3JhdyA9IGltcGxvZGUoJywnLCAkZGF0YWdyaWRfaXRlbXNfcmF3KTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkZGF0YWdyaWRfaXRlbXNfcmF3ICE9ICIiKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCg0KPD9waHANCi8vIERhdGFncmlkIFByb2Nlc3NpbmcuDQpcJGRhdGFncmlkX2l0ZW1zID0gYXJyYXkoeyRkYXRhZ3JpZF9pdGVtc19waHB9KTsNClwkZGF0YWdyaWRfaXRlbXNfcmF3ID0gYXJyYXkoeyRkYXRhZ3JpZF9pdGVtc19yYXd9KTsNCgkJDQppZighaXNzZXQoXCRkYXRhZ3JpZF9pdGVtc19kaXNwbGF5ZWQpKSB7DQoJXCRkYXRhZ3JpZF9pdGVtc19kaXNwbGF5ZWQgPSBhcnJheSgpOw0KfQ0KPz4NCg0KDQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KDQoNCg0KICAgICAgICANCiAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgaWYgKCFpc3NldCgkc3R5bGUtPnRhYmxlbW9kZXNwYW4pKSB7DQogICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChpbnQpJHN0eWxlLT50YWJsZW1vZGVzcGFuID09IDApIHsNCiAgICAgICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IHRydWU7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGh9OyBwYWRkaW5nLXRvcDozcHg7IGhlaWdodDoxNXB4OyBmbG9hdDpsZWZ0O1wiPiZuYnNwOzwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5zdHlsZS0+ZmllbGR3aWR0aCkgfHwgKHN0cmluZykkZmllbGQtPnN0eWxlLT5maWVsZHdpZHRoID09ICIiKSB7DQogICAgICAgICAgICAkZmllbGR3aWR0aCA9ICIxMDAlIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gKHN0cmluZykkZmllbGQtPnN0eWxlLT5maWVsZHdpZHRoOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRidWNrZXRfbm9kZSkgJiYgJGJ1Y2tldF9ub2RlICE9ICIiICYmIChpbnQpJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+cmVzcG9uc2l2ZSA9PSAxKSB7DQogICAgICAgICAgICAkZmllbGR3aWR0aCA9ICc5NSUnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5zdHlsZS0+ZmllbGRoZWlnaHQpKSB7DQogICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+ZmllbGRoZWlnaHQ7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPmJvcmRlcnJhZGl1cykgfHwgKHN0cmluZykkZmllbGQtPnN0eWxlLT5ib3JkZXJyYWRpdXMgPT0gIiIpIHsNCiAgICAgICAgICAgICRib3JkZXJyYWRpdXMgPSAiMCI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYm9yZGVycmFkaXVzID0gKHN0cmluZykkZmllbGQtPnN0eWxlLT5ib3JkZXJyYWRpdXM7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPnRleHRhbGlnbm1lbnQpIHx8IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+dGV4dGFsaWdubWVudCA9PSAiIikgew0KICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAwOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAoaW50KSRmaWVsZC0+c3R5bGUtPnRleHRhbGlnbm1lbnQ7DQogICAgICAgIH0NCg0KICAgICAgICAkdGV4dGFsaWdubWVudCA9ICR0aGlzLT51bS0+dHJhbnNsYXRlVGV4dEFsaWdubWVudCgkdGV4dGFsaWdubWVudCk7DQoNCg0KICAgICAgICANCg0KICAgICAgICAkYmFubmVybW9kZV9tYXJnaW5fbGVmdCA9ICIiOw0KICAgICAgICAkYmFubmVybW9kZV9tYXJnaW5fdmVydGljYWwgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJHN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRzdHlsZS0+YmFubmVybW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZ1bGx3aWR0aCkgJiYgKHN0cmluZykkcGFnZS0+ZnVsbHdpZHRoICE9ICIxIikgew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Y2UtPmNyZWF0ZUJhbm5lck1vZGVCbG9jaygkZGltLCAkcGFnZXBhZGRpbmcsICRmaWVsZCwgJHBhZ2UsICRmaWVsZHdpZHRoLCAkZmllbGRoZWlnaHQsICRiYW5uZXJtb2RlX21hcmdpbl9sZWZ0LCAkYmFubmVybW9kZV9tYXJnaW5fdmVydGljYWwsIChpbnQpJHBhZ2UtPmNlbnRlcmZvcm0pOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRwYWdlLT5mdWxsd2lkdGgpICYmIChzdHJpbmcpJHBhZ2UtPmZ1bGx3aWR0aCA9PSAiMSIpIHsNCg0KICAgICAgICAgICAgICAgICAgICBpZiAoKGludCkkcGFnZS0+Y2VudGVyZm9ybSAhPSAxKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZHdpZHRoID0gIjEwMCUiOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKGRlZmluZWQoJ01PQklMRV9NT0RFJykpIHsNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAiIjsNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7IA0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRjb2xvcikgfHwgKHN0cmluZykkZmllbGQtPnN0eWxlLT51c2ViYWNrZ3JvdW5kY29sb3IgPT0gIiIpIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAnJzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRjb2xvciA9PSAxICYmICRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRjb2xvciAhPSAiIikgew0KICAgICAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAoc3RyaW5nKSRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRjb2xvcjsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGJhY2tncm91bmRjb2xvciA9ICIiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJGdyYWRpZW50X3NlbGVjdG9yID0gJyc7DQoNCiAgICAgICAgaWYgKA0KICAgICAgICAgICAgaXNzZXQoJGZpZWxkLT5zdHlsZS0+dXNlYmFja2dyb3VuZGdyYWRpZW50KQ0KICAgICAgICAgICAgJiYgIChpbnQpJGZpZWxkLT5zdHlsZS0+dXNlYmFja2dyb3VuZGdyYWRpZW50ID09IDEgJiYgJGZpZWxkLT5zdHlsZS0+YmFja2dyb3VuZGdyYWRpZW50dG9wICE9ICIiICYmICRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRncmFkaWVudGJvdHRvbSAhPSAiIg0KICAgICAgICApIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGdyYWRpZW50X3NlbGVjdG9yID0gJ2dyYWRpZW50XycgLiBzdWJzdHIobWQ1KHJhbmQoMTAsIDQwKSksIDAsIDEwKTsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICR0aGlzLT50cmFuc2xhdGVHcmFkaWVudCgkZ3JhZGllbnRfc2VsZWN0b3IsIChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+YmFja2dyb3VuZGdyYWRpZW50dG9wLCAoc3RyaW5nKSRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRncmFkaWVudGJvdHRvbSk7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGJvcmRlcl9zdHlsZSA9ICcnOw0KICAgICAgICBpZiAoKGludCkkZmllbGQtPnN0eWxlLT51c2Vib3JkZXIgPT0gMSkgew0KICAgICAgICAgICAgJGJvcmRlcl9zdHlsZSA9ICIgYm9yZGVyOiB7JGZpZWxkLT5zdHlsZS0+Ym9yZGVyd2lkdGh9ICIgLiAkdGhpcy0+dHJhbnNsYXRlQm9yZGVyU3R5bGUoKGludCkkZmllbGQtPnN0eWxlLT5ib3JkZXJzdHlsZSkgLiAiIHskZmllbGQtPnN0eWxlLT5ib3JkZXJjb2xvcn07ICI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPnBhZGRpbmdsZWZ0KSkgew0KICAgICAgICAgICAgJHBhZGRpbmcgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRwYWRkaW5nID0gIiI7DQogICAgICAgICAgICBpZiAoaXNfbnVtZXJpYygoaW50KSRmaWVsZC0+c3R5bGUtPnBhZGRpbmdsZWZ0KSkgew0KICAgICAgICAgICAgICAgICRwYWRkaW5nIC49ICIgcGFkZGluZy1sZWZ0OnskZmllbGQtPnN0eWxlLT5wYWRkaW5nbGVmdH1weDsgIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChpbnQpJGZpZWxkLT5zdHlsZS0+cGFkZGluZ3JpZ2h0KSkgew0KICAgICAgICAgICAgICAgICRwYWRkaW5nIC49ICIgcGFkZGluZy1yaWdodDp7JGZpZWxkLT5zdHlsZS0+cGFkZGluZ3JpZ2h0fXB4OyAiOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKGlzX251bWVyaWMoKGludCkkZmllbGQtPnN0eWxlLT5wYWRkaW5ndG9wKSkgew0KICAgICAgICAgICAgICAgICRwYWRkaW5nIC49ICIgcGFkZGluZy10b3A6eyRmaWVsZC0+c3R5bGUtPnBhZGRpbmd0b3B9cHg7ICI7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAoaXNfbnVtZXJpYygoaW50KSRmaWVsZC0+c3R5bGUtPnBhZGRpbmdib3R0b20pKSB7DQogICAgICAgICAgICAgICAgJHBhZGRpbmcgLj0gIiBwYWRkaW5nLWJvdHRvbTp7JGZpZWxkLT5zdHlsZS0+cGFkZGluZ2JvdHRvbX1weDsgIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkc3R5bGUtPmJhbm5lcm1vZGUpICYmIChpbnQpJHN0eWxlLT5iYW5uZXJtb2RlID09IDEpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRwYWdlLT5jZW50ZXJmb3JtKSAmJiAoc3RyaW5nKSRwYWdlLT5jZW50ZXJmb3JtID09ICIwIikgew0KDQogICAgICAgICAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJyc7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGRoZWlnaHQgPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gImhlaWdodDp7JGZpZWxkaGVpZ2h0fTsiOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRiYWNrZ3JvdW5kY29sb3IgPT0gIiIpIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAiYmFja2dyb3VuZC1jb2xvcjp7JGJhY2tncm91bmRjb2xvcn07IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5lbGVtZW50cG9zKSAmJiAkZmllbGQtPmVsZW1lbnRwb3MgIT0gIjAiKSB7DQoNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJzEwMCUnOw0KDQogICAgICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5lbGVtZW50cG9zKSB7DQogICAgICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICAgICAkdGV4dGFsaWdubWVudCA9ICdsZWZ0JzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAkdGV4dGFsaWdubWVudCA9ICdyaWdodCc7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgMjoNCiAgICAgICAgICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAnY2VudGVyJzsgDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBhcmlhLWxhYmVsPVwiU2VjdGlvbiBUZXh0XCIgY2xhc3M9XCJzZWN0aW9uLWhlYWQgeyRncmFkaWVudF9zZWxlY3Rvcn1cIiBzdHlsZT1cImNvbG9yOnskY29sb3J9OyBmb250LXNpemU6eyRmb250c2l6ZX07IGZvbnQtd2VpZ2h0Onskc3R5bGVzWydmb250d2VpZ2h0J119OyB3aWR0aDp7JGZpZWxkd2lkdGh9OyB7JGZpZWxkaGVpZ2h0fSB7JGJhbm5lcm1vZGVfbWFyZ2luX2xlZnR9IHskYmFubmVybW9kZV9tYXJnaW5fdmVydGljYWx9IGJvcmRlci1yYWRpdXM6eyRib3JkZXJyYWRpdXN9cHg7IHskYm9yZGVyX3N0eWxlfSB0ZXh0LWFsaWduOnskdGV4dGFsaWdubWVudH07IHskYmFja2dyb3VuZGNvbG9yfSB7JHBhZGRpbmd9IFwiPlxueyR0ZXh0WzBdfVxuPC9kaXY+XG4iOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfYm9keV9jb3B5KCRmaWVsZCwgJHBhZ2UsICRkYXRhZ3JpZF9pdGVtcywgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICR0ZXh0ID0gJGZpZWxkLT57J2xhYmVsJ307DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQoNCiAgICAgICAgJHRhYmxlbW9kZSA9ICRwYWdlLT50YWJsZW1vZGU7DQogICAgICAgICRwYWdlcGFkZGluZyA9ICRwYWdlLT5wYWdlcGFkZGluZzsNCiAgICAgICAgJGRpbSA9ICRwYWdlLT5kaW07DQoNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICAkdGV4dCA9ICR0aGlzLT5jcmVhdGVfaW5saW5lX2dldF92YXJzKCR0ZXh0KTsgDQogICAgICAgICR0ZXh0ID0gJHRoaXMtPmNyZWF0ZV9pbmxpbmVfcG9zdF92YXJzKCR0ZXh0LCAnLCAnKTsgDQogICAgICAgICR0ZXh0ID0gJHRoaXMtPmNyZWF0ZV9pbmxpbmVfc2Vzc2lvbl92YXJzKCR0ZXh0LCAnLCAnKTsgDQogICAgICAgICR0ZXh0ID0gJHRoaXMtPmNyZWF0ZV9pbmxpbmVfcGhwX3ZhcnMoJHRleHQsICcsICcpOyANCg0KICAgICAgICANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCR0ZXh0LCA2LjEpOw0KDQogICAgICAgIA0KICAgICAgICAkdGV4dCA9ICR0aGlzLT51di0+cmVwbGFjZV9maWVsZF9yYXcoJHRleHQsIDApOw0KDQogICAgICAgIA0KICAgICAgICAkdGV4dCA9ICR0aGlzLT51di0+cmVwbGFjZV9maWVsZF9uZXdsaW5lKCR0ZXh0LCAwKTsNCg0KICAgICAgICANCiAgICAgICAgJHRleHQgPSAkdGhpcy0+Y3JlYXRlX2lubGluZV9maWVsZF92YXJzKCR0ZXh0KTsgDQoNCiAgICAgICAgJGVsZW1lbnQgPSAkdGV4dFsxXTsNCg0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGRhdGFncmlkX2l0ZW1zX3BocCA9ICcnOw0KICAgICAgICAkZGF0YWdyaWRfaXRlbXNfcmF3ID0gYXJyYXkoKTsNCg0KICAgICAgICBpZiAoaXNzZXQoJGRhdGFncmlkX2l0ZW1zKSAmJiBjb3VudCgkZGF0YWdyaWRfaXRlbXMpICE9IDApIHsNCiAgICAgICAgICAgICRkYXRhZ3JpZF9pdGVtc19waHAgPSBpbXBsb2RlKCcsJywgJGRhdGFncmlkX2l0ZW1zKTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBmb3JlYWNoICgkZGF0YWdyaWRfaXRlbXMgYXMgJGdyaWRfaXRlbSkgew0KICAgICAgICAgICAgJHJhdyA9IGV4cGxvZGUoJ3wnLCAkZ3JpZF9pdGVtKTsNCiAgICAgICAgICAgICRkYXRhZ3JpZF9pdGVtc19yYXdbXSA9ICRyYXdbMF0gLiAiJyI7ICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc19hcnJheSgkZGF0YWdyaWRfaXRlbXNfcmF3KSkgew0KICAgICAgICAgICAgJGRhdGFncmlkX2l0ZW1zX3JhdyA9IGltcGxvZGUoJywnLCAkZGF0YWdyaWRfaXRlbXNfcmF3KTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkZGF0YWdyaWRfaXRlbXNfcmF3ICE9ICIiKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCgkJDQo8P3BocA0KLy8gRGF0YWdyaWQgUHJvY2Vzc2luZy4NClwkZGF0YWdyaWRfaXRlbXMgPSBhcnJheSh7JGRhdGFncmlkX2l0ZW1zX3BocH0pOw0KXCRkYXRhZ3JpZF9pdGVtc19yYXcgPSBhcnJheSh7JGRhdGFncmlkX2l0ZW1zX3Jhd30pOw0KCQkNCmlmKCFpc3NldChcJGRhdGFncmlkX2l0ZW1zX2Rpc3BsYXllZCkpIHsNCglcJGRhdGFncmlkX2l0ZW1zX2Rpc3BsYXllZCA9IGFycmF5KCk7DQp9DQo/Pg0KCQkNCgkJDQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KDQoNCiAgICAgICAgDQogICAgICAgICR0YWJsZW1vZGVzcGFuID0gZmFsc2U7DQogICAgICAgIGlmICghaXNzZXQoJHN0eWxlLT50YWJsZW1vZGVzcGFuKSkgew0KICAgICAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmICgoaW50KSRzdHlsZS0+dGFibGVtb2Rlc3BhbiA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSB0cnVlOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRofTsgcGFkZGluZy10b3A6M3B4OyBoZWlnaHQ6MTVweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdwdCcpOw0KICAgICAgICAkY3QyID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHgnKTsNCg0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJGZvbnRzaXplID0gJGZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPmZpZWxkd2lkdGgpIHx8IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+ZmllbGR3aWR0aCA9PSAiIikgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAiMTAwJSI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkZmllbGR3aWR0aCA9IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+ZmllbGR3aWR0aDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAnOTUlJzsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5zdHlsZS0+ZmllbGRoZWlnaHQpKSB7DQogICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+ZmllbGRoZWlnaHQ7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPmJvcmRlcnJhZGl1cykgfHwgKHN0cmluZykkZmllbGQtPnN0eWxlLT5ib3JkZXJyYWRpdXMgPT0gIiIpIHsNCiAgICAgICAgICAgICRib3JkZXJyYWRpdXMgPSAiMCI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYm9yZGVycmFkaXVzID0gKHN0cmluZykkZmllbGQtPnN0eWxlLT5ib3JkZXJyYWRpdXM7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPnRleHRhbGlnbm1lbnQpIHx8IChzdHJpbmcpJGZpZWxkLT5zdHlsZS0+dGV4dGFsaWdubWVudCA9PSAiIikgew0KICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAwOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAoaW50KSRmaWVsZC0+c3R5bGUtPnRleHRhbGlnbm1lbnQ7DQogICAgICAgIH0NCg0KICAgICAgICAkdGV4dGFsaWdubWVudCA9ICR0aGlzLT51bS0+dHJhbnNsYXRlVGV4dEFsaWdubWVudCgkdGV4dGFsaWdubWVudCk7DQoNCg0KICAgICAgICANCg0KICAgICAgICAkYmFubmVybW9kZV9tYXJnaW5fbGVmdCA9ICIiOw0KICAgICAgICAkYmFubmVybW9kZV9tYXJnaW5fdmVydGljYWwgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJHN0eWxlLT5iYW5uZXJtb2RlKSAmJiAoaW50KSRzdHlsZS0+YmFubmVybW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+c3R5bGUtPmJhbm5lcm1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZ1bGx3aWR0aCkgJiYgKHN0cmluZykkcGFnZS0+ZnVsbHdpZHRoICE9ICIxIikgew0KDQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5jZS0+Y3JlYXRlQmFubmVyTW9kZUJsb2NrKCRkaW0sICRwYWdlcGFkZGluZywgJGZpZWxkLCAkcGFnZSwgJGZpZWxkd2lkdGgsICRmaWVsZGhlaWdodCwgJGJhbm5lcm1vZGVfbWFyZ2luX2xlZnQsICRiYW5uZXJtb2RlX21hcmdpbl92ZXJ0aWNhbCwgKGludCkkcGFnZS0+Y2VudGVyZm9ybSk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHBhZ2UtPmZ1bGx3aWR0aCkgJiYgKHN0cmluZykkcGFnZS0+ZnVsbHdpZHRoID09ICIxIikgew0KDQogICAgICAgICAgICAgICAgICAgIGlmICgoaW50KSRwYWdlLT5jZW50ZXJmb3JtICE9IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAiMTAwJSI7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkcGFnZS0+Y2VudGVyZm9ybSkgJiYgKHN0cmluZykkcGFnZS0+Y2VudGVyZm9ybSA9PSAiMCIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZmllbGR3aWR0aCA9ICcnOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmIChkZWZpbmVkKCdNT0JJTEVfTU9ERScpKSB7DQogICAgICAgICAgICAgICAgICAgICRmaWVsZHdpZHRoID0gIiI7DQogICAgICAgICAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOyANCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRjb2xvcikgfHwgKHN0cmluZykkZmllbGQtPnN0eWxlLT51c2ViYWNrZ3JvdW5kY29sb3IgPT0gIiIpIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAnJzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRjb2xvciA9PSAxICYmICRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRjb2xvciAhPSAiIikgew0KICAgICAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAoc3RyaW5nKSRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRjb2xvcjsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGJhY2tncm91bmRjb2xvciA9ICIiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRncmFkaWVudF9zZWxlY3RvciA9ICcnOw0KDQogICAgICAgIGlmICgNCiAgICAgICAgICAgIGlzc2V0KCRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRncmFkaWVudCkNCiAgICAgICAgICAgICYmICAoaW50KSRmaWVsZC0+c3R5bGUtPnVzZWJhY2tncm91bmRncmFkaWVudCA9PSAxICYmICRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRncmFkaWVudHRvcCAhPSAiIiAmJiAkZmllbGQtPnN0eWxlLT5iYWNrZ3JvdW5kZ3JhZGllbnRib3R0b20gIT0gIiINCiAgICAgICAgKSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRncmFkaWVudF9zZWxlY3RvciA9ICdncmFkaWVudF8nIC4gc3Vic3RyKG1kNShyYW5kKDEwLCA0MCkpLCAwLCAxMCk7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+dHJhbnNsYXRlR3JhZGllbnQoJGdyYWRpZW50X3NlbGVjdG9yLCAoc3RyaW5nKSRmaWVsZC0+c3R5bGUtPmJhY2tncm91bmRncmFkaWVudHRvcCwgKHN0cmluZykkZmllbGQtPnN0eWxlLT5iYWNrZ3JvdW5kZ3JhZGllbnRib3R0b20pOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRib3JkZXJfc3R5bGUgPSAnJzsNCiAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5zdHlsZS0+dXNlYm9yZGVyID09IDEpIHsNCiAgICAgICAgICAgICRib3JkZXJfc3R5bGUgPSAiIGJvcmRlcjogeyRmaWVsZC0+c3R5bGUtPmJvcmRlcndpZHRofSAiIC4gJHRoaXMtPnRyYW5zbGF0ZUJvcmRlclN0eWxlKChpbnQpJGZpZWxkLT5zdHlsZS0+Ym9yZGVyc3R5bGUpIC4gIiB7JGZpZWxkLT5zdHlsZS0+Ym9yZGVyY29sb3J9OyAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5zdHlsZS0+cGFkZGluZ2xlZnQpKSB7DQoNCiAgICAgICAgICAgICRwYWRkaW5nID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICRwYWRkaW5nID0gIiI7DQoNCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChpbnQpJGZpZWxkLT5zdHlsZS0+cGFkZGluZ2xlZnQpKSB7DQogICAgICAgICAgICAgICAgJHBhZGRpbmcgLj0gIiBwYWRkaW5nLWxlZnQ6eyRmaWVsZC0+c3R5bGUtPnBhZGRpbmdsZWZ0fXB4OyAiOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKGlzX251bWVyaWMoKGludCkkZmllbGQtPnN0eWxlLT5wYWRkaW5ncmlnaHQpKSB7DQogICAgICAgICAgICAgICAgJHBhZGRpbmcgLj0gIiBwYWRkaW5nLXJpZ2h0OnskZmllbGQtPnN0eWxlLT5wYWRkaW5ncmlnaHR9cHg7ICI7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAoaXNfbnVtZXJpYygoaW50KSRmaWVsZC0+c3R5bGUtPnBhZGRpbmd0b3ApKSB7DQogICAgICAgICAgICAgICAgJHBhZGRpbmcgLj0gIiBwYWRkaW5nLXRvcDp7JGZpZWxkLT5zdHlsZS0+cGFkZGluZ3RvcH1weDsgIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChpbnQpJGZpZWxkLT5zdHlsZS0+cGFkZGluZ2JvdHRvbSkpIHsNCiAgICAgICAgICAgICAgICAkcGFkZGluZyAuPSAiIHBhZGRpbmctYm90dG9tOnskZmllbGQtPnN0eWxlLT5wYWRkaW5nYm90dG9tfXB4OyAiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGRoZWlnaHQgPT0gIiIpIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gImhlaWdodDp7JGZpZWxkaGVpZ2h0fTsiOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRiYWNrZ3JvdW5kY29sb3IgPT0gIiIpIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRiYWNrZ3JvdW5kY29sb3IgPSAiYmFja2dyb3VuZC1jb2xvcjp7JGJhY2tncm91bmRjb2xvcn07IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5lbGVtZW50cG9zKSAmJiAkZmllbGQtPmVsZW1lbnRwb3MgIT0gIjAiKSB7DQoNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJyc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZWxlbWVudHBvcykgJiYgJGZpZWxkLT5lbGVtZW50cG9zICE9ICIwIikgew0KDQogICAgICAgICAgICAkZmllbGR3aWR0aCA9ICcxMDAlJzsNCg0KICAgICAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+ZWxlbWVudHBvcykgew0KICAgICAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAnbGVmdCc7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAncmlnaHQnOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICBjYXNlIDI6DQogICAgICAgICAgICAgICAgICAgICR0ZXh0YWxpZ25tZW50ID0gJ2NlbnRlcic7IA0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBhcmlhLWxhYmVsPVwiQm9keSBDb3B5XCIgY2xhc3M9XCJib2R5LWNvcHkgeyRncmFkaWVudF9zZWxlY3Rvcn1cIiBzdHlsZT1cImNvbG9yOnskY29sb3J9OyBmb250LXNpemU6eyRmb250c2l6ZX07IGZvbnQtd2VpZ2h0Onskc3R5bGVzWydmb250d2VpZ2h0J119OyB3aWR0aDp7JGZpZWxkd2lkdGh9OyB7JGZpZWxkaGVpZ2h0fSB7JGJhbm5lcm1vZGVfbWFyZ2luX2xlZnR9IHskYmFubmVybW9kZV9tYXJnaW5fdmVydGljYWx9IGJvcmRlci1yYWRpdXM6eyRib3JkZXJyYWRpdXN9cHg7IHskYm9yZGVyX3N0eWxlfSB0ZXh0LWFsaWduOnskdGV4dGFsaWdubWVudH07IHskYmFja2dyb3VuZGNvbG9yfSB7JHBhZGRpbmd9IFwiPlxueyR0ZXh0WzBdfVxuPC9kaXY+XG4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZGVmYXVsdF92YWx1ZV90b2tlbnMoJGRlZmF1bHR2YWx1ZSkNCiAgICB7DQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKHN1YnN0cl9jb3VudCgkZGVmYXVsdHZhbHVlLCAnLT4nKSA9PSAwKSB7DQogICAgICAgICAgICAkZGVmYXVsdHZhbHVlID0gaHRtbGVudGl0aWVzKCRkZWZhdWx0dmFsdWUsIEVOVF9DT01QQVQsICdVVEYtOCcpOw0KICAgICAgICB9DQoNCiAgICAgICAgJGhhc19tYXRjaCA9IDA7DQoNCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKShcQFx7KC4qPylcfSkvJywgJGRlZmF1bHR2YWx1ZSwgJG1hdGNoZXMpOw0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRoYXNfbWF0Y2ggPSAxOw0KICAgICAgICAgICAgICAgICRkZWZhdWx0dmFsdWUgPSBzdHJfcmVwbGFjZSgnQHsnIC4gJG0gLiAnfScsICJpc3NldChcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRtfSddKSA/IFwkX1NFU1NJT05bJ3FzJ11bXCJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119XCJdWyd7JG19J10gOiAnJyIsICRkZWZhdWx0dmFsdWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKSgjXHsoLio/KVx9KS8nLCAkZGVmYXVsdHZhbHVlLCAkbWF0Y2hlcyk7DQogICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1szXSkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRtYXRjaGVzWzNdIGFzICRtKSB7DQogICAgICAgICAgICAgICAgJGhhc19tYXRjaCA9IDE7DQogICAgICAgICAgICAgICAgJGRlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCcjeycgLiAkbSAuICd9JywgImlzc2V0KFwkX0dFVFsneyRtfSddKSA/IFwkX0dFVFsneyRtfSddIDogJyciLCAkZGVmYXVsdHZhbHVlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgIHByZWdfbWF0Y2hfYWxsKCcvKF58LnxccnxcbikoXCpceyguKj8pXH0pLycsICRkZWZhdWx0dmFsdWUsICRtYXRjaGVzKTsNCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkaGFzX21hdGNoID0gMTsNCiAgICAgICAgICAgICAgICAkZGVmYXVsdHZhbHVlID0gc3RyX3JlcGxhY2UoJyp7JyAuICRtIC4gJ30nLCAiaXNzZXQoXCRfUE9TVFsneyRtfSddKSA/IFwkX1BPU1RbJ3skbX0nXSA6ICcnIiwgJGRlZmF1bHR2YWx1ZSk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pKFxeXHsoLio/KVx9KS8nLCAkZGVmYXVsdHZhbHVlLCAkbWF0Y2hlcyk7DQogICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1szXSkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRtYXRjaGVzWzNdIGFzICRtKSB7DQogICAgICAgICAgICAgICAgJGhhc19tYXRjaCA9IDE7DQogICAgICAgICAgICAgICAgJGRlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCdeeycgLiAkbSAuICd9JywgImlzc2V0KFwkX1NFU1NJT05bJ3skbX0nXSkgPyBcJF9TRVNTSU9OWyd7JG19J10gOiAnJyIsICRkZWZhdWx0dmFsdWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oUEhQXHsoLio/KVx9KS8nLCAkZGVmYXVsdHZhbHVlLCAkbWF0Y2hlcyk7DQogICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1szXSkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRtYXRjaGVzWzNdIGFzICRtKSB7DQogICAgICAgICAgICAgICAgJGhhc19tYXRjaCA9IDE7DQogICAgICAgICAgICAgICAgJGRlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCdQSFB7JyAuICRtIC4gJ30nLCAiaXNzZXQoXCR7JG19KSA/IChpc19hKFwkeyRtfSwgJ0RhdGVUaW1lJykgPyBcJHskbX0tPmZvcm1hdCgnbS9kL1knKSA6ICggdmFsaWRhdGVEYXRlKFwkeyRtfSkgPyBwcmludFZhbGlkYXRlZERhdGUoXCR7JG19LCAnWS1tLWQgSDppOnMnLCAnbS9kL1knKSA6IFwkeyRtfSApICkgOiAnJyIsICRkZWZhdWx0dmFsdWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRkZWZhdWx0dmFsdWVfbmV3ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGVmYXVsdHZhbHVlLCA0KTsNCg0KICAgICAgICANCg0KICAgICAgICBpZiAoJGRlZmF1bHR2YWx1ZV9uZXcgIT0gJGRlZmF1bHR2YWx1ZSkgew0KICAgICAgICAgICAgJGhhc19tYXRjaCA9IDE7DQogICAgICAgIH0NCg0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGRlZmF1bHR2YWx1ZV9uZXc7DQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICBpZiAoISRoYXNfbWF0Y2gpIHsNCiAgICAgICAgICAgICRkZWZhdWx0dmFsdWUgPSAnIicgLiAkZGVmYXVsdHZhbHVlIC4gJyInOw0KICAgICAgICB9DQoNCg0KICAgICAgICByZXR1cm4gJGRlZmF1bHR2YWx1ZTsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfdGV4dCgkcGFnZSwgJGZpZWxkLCAkZGF0YXNvdXJjZSwgJHNhdmVwYXRoLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+eydsYWJlbCd9Ow0KICAgICAgICAkaHRtbDV0eXBlID0gJGZpZWxkLT5odG1sNXR5cGU7IA0KICAgICAgICAkZm9ybWF0YXMgPSAkZmllbGQtPmZvcm1hdGFzOyANCiAgICAgICAgJHBsYWNlaG9sZGVyID0gJGZpZWxkLT5wbGFjZWhvbGRlcjsgDQogICAgICAgICR0YWlsdGV4dCA9ICRmaWVsZC0+dGFpbHRleHQ7DQogICAgICAgICRuYW1lID0gJGZpZWxkLT57J25hbWUnfTsNCiAgICAgICAgJGlkID0gJGZpZWxkLT57J2lkJ307DQogICAgICAgICRyZXEgPSAkZmllbGQtPnZhbGlkYXRpb24tPnJlcTsNCiAgICAgICAgJGZpZWxkd2lkdGggPSAkZmllbGQtPmZpZWxkd2lkdGg7DQogICAgICAgICRmaWVsZGhlaWdodCA9ICRmaWVsZC0+ZmllbGRoZWlnaHQ7IA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGZpZWxkLT5kZWZhdWx0dmFsdWU7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KICAgICAgICAkbWF4bGVuZ3RoID0gJGZpZWxkLT52YWxpZGF0aW9uLT5tYXg7DQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRwb3B1bGF0ZWRlZmF1bHQpID8gJGZpZWxkLT5maWVsZHBvcHVsYXRlZGVmYXVsdCA6IDE7IA0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICRhdXRvc3VnZ2VzdCA9ICRmaWVsZC0+YXV0b3N1Z2dlc3Q7DQogICAgICAgICRjb2xvcnBpY2tlciA9ICRmaWVsZC0+Y29sb3JwaWNrZXI7DQogICAgICAgICRqc2xpZGVyID0gJGZpZWxkLT5qc2xpZGVyOw0KICAgICAgICAkc3R5bGUgPSAkZmllbGQtPnN0eWxlOw0KICAgICAgICAkdG9vbHRpcCA9ICRmaWVsZC0+dG9vbHRpcDsNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCg0KICAgICAgICANCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGxhYmVsID09ICIiKSB7DQogICAgICAgICAgICAkbGFiZWwgPSAiJm5ic3A7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghaXNzZXQoJHBsYWNlaG9sZGVyKSkgew0KICAgICAgICAgICAgJHBsYWNlaG9sZGVyID0gIiI7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCFpc3NldCgkdGFpbHRleHQpKSB7DQogICAgICAgICAgICAkdGFpbHRleHQgPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgICRzdHlsZXMgPSAkdGhpcy0+dHJhbnNsYXRlRmllbGRTdHlsZXMoJHN0eWxlKTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkdG9vbHRpcF9lbGVtZW50ID0gJHRoaXMtPnRyYW5zbGF0ZVRvb2x0aXAoJHRvb2x0aXAsICRpZCk7DQoNCiAgICAgICAgDQogICAgICAgICRjb2xvcnBpY2tlciA9ICR0aGlzLT50cmFuc2xhdGVDb2xvcnBpY2tlcigkY29sb3JwaWNrZXIsICRpZCk7IA0KDQogICAgICAgIA0KICAgICAgICAkanNsaWRlciA9ICR0aGlzLT50cmFuc2xhdGVKc2xpZGVyKCRqc2xpZGVyLCAkaWQpOyANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRodG1sNV9yYW5nZSA9ICIiOw0KDQogICAgICAgIGlmICgkaHRtbDV0eXBlID09ICJyYW5nZSIpIHsNCiAgICAgICAgICAgICRyYW5nZV9taW4gPSAkZmllbGQtPmh0bWw1X3JhbmdlX21pbiA9PSAiIiA/IDAgOiAkZmllbGQtPmh0bWw1X3JhbmdlX21pbjsNCiAgICAgICAgICAgICRyYW5nZV9tYXggPSAkZmllbGQtPmh0bWw1X3JhbmdlX21heCA9PSAiIiA/IDAgOiAkZmllbGQtPmh0bWw1X3JhbmdlX21heDsNCg0KICAgICAgICAgICAgJGh0bWw1X3JhbmdlID0gIm1pbj1cInskcmFuZ2VfbWlufVwiIG1heD1cInskcmFuZ2VfbWF4fVwiIGRhdGEtaGlnaGxpZ2h0PVwidHJ1ZVwiIjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgJGVsZW1lbnQgPSAnJzsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQogICAgICAgIA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJHRoaXMtPmNyZWF0ZV9kZWZhdWx0X3ZhbHVlX3Rva2VucygkZGVmYXVsdHZhbHVlKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGRoZWlnaHQpKSB7DQogICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZGhlaWdodCA9PSAiIikgew0KICAgICAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOyANCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gImhlaWdodDp7JGZpZWxkaGVpZ2h0fXB4OyI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRmb250c2l6ZSA9ICRmb250c2l6ZSAuICdweCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJGZpZWxkd2lkdGgpID09IHRydWUpIHsNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJGZpZWxkd2lkdGggLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRidWNrZXRfbm9kZSkgJiYgJGJ1Y2tldF9ub2RlICE9ICIiICYmIChpbnQpJGJ1Y2tldF9ub2RlLT5yZXBlYXRlci0+cmVzcG9uc2l2ZSA9PSAxKSB7DQogICAgICAgICAgICAkZmllbGR3aWR0aCA9ICc4OSUnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGlzc2V0KCRwYWdlKSAmJiAkcGFnZS0+anNsaWJyYXJ5ID09ICIxNCIpIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KICAgICAgICAgICAgDQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHRlc3QgPSAoaW50KSRpbmhlcml0c3R5bGU7DQogICAgICAgIGlmICgkdGVzdCAhPSAxKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gMDsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoJGluaGVyaXRzdHlsZSA9PSAxKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cImZvbnQtc2l6ZTp7JGZvbnRzaXplfTsgY29sb3I6eyRpbnB1dF9jb2xvcn07IGZvbnQtZmFtaWx5OmluaGVyaXQ7IHdpZHRoOnskZmllbGR3aWR0aH07IHskZmllbGRoZWlnaHR9IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cIiBjb2xvcjp7JGlucHV0X2NvbG9yfTsgd2lkdGg6eyRmaWVsZHdpZHRofTsgeyRmaWVsZGhlaWdodH0geyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5sZWZ0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyRmaXhlZF93aWR0aH1weDsgbWFyZ2luLXJpZ2h0OjhweDsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259XCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoJG1heGxlbmd0aCAhPSAnJykgew0KICAgICAgICAgICAgJG1heCA9ICJtYXhsZW5ndGg9XCJ7JG1heGxlbmd0aH1cIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkbWF4ID0gJyc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKChzdHJpbmcpJGxhYmVsICE9ICImbmJzcDsiIHx8ICR0aGlzLT5nZXRfbGFiZWxfcG9zKCRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUpICE9ICJmbG9hdDpsZWZ0OyIpIHsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgJHJlcSwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsICRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUsICR0b29sdGlwLCAkZmllbGQtPmZpZWxkaGVpZ2h0LCAkdGFibGVtb2RlKTsNCiAgICAgICAgDQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgKHN0cmluZykkZmllbGQtPmJ1Y2tldCAhPSAnJykgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwiZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkaHRtbDV0eXBlID09ICIiKSB7DQogICAgICAgICAgICAkaHRtbDV0eXBlID0gInRleHQiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmV4dHJhY2xhc3NuYW1lKSAmJiAkZmllbGQtPmV4dHJhY2xhc3NuYW1lICE9ICIiKSB7DQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gJGZpZWxkLT5leHRyYWNsYXNzbmFtZTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRfcGggPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJHBsYWNlaG9sZGVyKSAmJiAkcGxhY2Vob2xkZXIgIT0gIiIpIHsNCiAgICAgICAgICAgICRfcGggPSAiIHBsYWNlaG9sZGVyPVwieyRwbGFjZWhvbGRlcn1cIiAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfdGFibGVfbW9kZV9tb2JpbGVfbGFiZWwoJGZpZWxkLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRmaWVsZC0+YnVja2V0KSAmJiAkZmllbGQtPmJ1Y2tldCAhPSAiIil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgLj0gIiBidWNrZXQtY29udGFpbmVkLWZpZWxkIjsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZvcm1hdF90cmlnZ2VyID0gIiI7DQoNCiAgICAgICAgJGZvcm1hdF9zY3JpcHQgPSAiIjsNCg0KICAgICAgICBpZihpc3NldCgkZm9ybWF0YXMpICYmIChzdHJpbmcpJGZvcm1hdGFzICE9ICIiKXsNCg0KICAgICAgICAgICAgc3dpdGNoKChzdHJpbmcpJGZvcm1hdGFzKXsNCg0KICAgICAgICAgICAgY2FzZSAidXNwaG9uZSIgOg0KDQogICAgICAgICAgICAgICAgICAgICRmb3JtYXRfdHJpZ2dlciA9ICJvbmtleWRvd249XCJwaG9uZU51bWJlckZvcm1hdHRlcigpXCIiOw0KDQogICAgICAgICAgICAgICAgICAgICRmb3JtYXRfc2NyaXB0ID0gPDw8RU9GDQo8c2NyaXB0Pg0KZnVuY3Rpb24gZm9ybWF0UGhvbmVOdW1iZXIodmFsdWUpIHsNCiAgICBpZiAoIXZhbHVlKSByZXR1cm4gdmFsdWU7DQogICAgY29uc3QgcGhvbmVOdW1iZXIgPSB2YWx1ZS5yZXBsYWNlKC9bXlxkXS9nLCAiIik7DQogICAgY29uc3QgcGhvbmVOdW1iZXJMZW5ndGggPSBwaG9uZU51bWJlci5sZW5ndGg7DQogICAgaWYgKHBob25lTnVtYmVyTGVuZ3RoIDwgNCkgcmV0dXJuIHBob25lTnVtYmVyOw0KICAgIGlmIChwaG9uZU51bWJlckxlbmd0aCA8IDcpIHsNCiAgICAgICAgcmV0dXJuIGAoXCR7cGhvbmVOdW1iZXIuc2xpY2UoMCwgMyl9KSBcJHtwaG9uZU51bWJlci5zbGljZSgzKX1gOw0KICAgIH0NCiAgICByZXR1cm4gYChcJHtwaG9uZU51bWJlci5zbGljZSgwLCAzKX0pIFwke3Bob25lTnVtYmVyLnNsaWNlKA0KICAgICAgICAzLA0KICAgICAgICA2DQogICAgKX0tXCR7cGhvbmVOdW1iZXIuc2xpY2UoNiwgMTApfWA7DQogICAgfQ0KICAgIA0KZnVuY3Rpb24gcGhvbmVOdW1iZXJGb3JtYXR0ZXIoKSB7DQogICAgY29uc3QgaW5wdXRGaWVsZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGZpZWxkLT5pZH0nKTsNCiAgICBjb25zdCBmb3JtYXR0ZWRJbnB1dFZhbHVlID0gZm9ybWF0UGhvbmVOdW1iZXIoaW5wdXRGaWVsZC52YWx1ZSk7DQogICAgaW5wdXRGaWVsZC52YWx1ZSA9IGZvcm1hdHRlZElucHV0VmFsdWU7DQp9DQo8L3NjcmlwdD4NCkVPRjsNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgY2FzZSAidXBwZXJjYXNlIiA6DQoNCiAgICAgICAgICAgICAgICAgICAgJGZvcm1hdF90cmlnZ2VyID0gIm9ua2V5dXA9XCJ0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS50b1VwcGVyQ2FzZSgpXCIiOw0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICBjYXNlICJsb3dlcmNhc2UiIDoNCg0KICAgICAgICAgICAgICAgICAgICAkZm9ybWF0X3RyaWdnZXIgPSAib25rZXl1cD1cInRoaXMudmFsdWUgPSB0aGlzLnZhbHVlLnRvTG93ZXJDYXNlKClcIiI7DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgIGNhc2UgInVzc3NuIiA6DQoNCiAgICAgICAgICAgICAgICAgICAgJGZvcm1hdF90cmlnZ2VyID0gIm9ua2V5dXA9XCJmb3JtYXRVU1NTTih0aGlzKVwiIjsNCg0KICAgICAgICAgICAgICAgICAgICAkZm9ybWF0X3NjcmlwdCA9IDw8PEVPRg0KPHNjcmlwdD4NCmZ1bmN0aW9uIGZvcm1hdFVTU1NOKGVsdCl7DQogICAgdmFyIHZhbCA9IGVsdC52YWx1ZS5yZXBsYWNlKC9cRC9nLCAnJyk7DQogICAgdmFyIG5ld1ZhbCA9ICcnOw0KICAgIGlmKHZhbC5sZW5ndGggPiA0KSB7DQogICAgICAgIHRoaXMudmFsdWUgPSB2YWw7DQogICAgfQ0KICAgIGlmKCh2YWwubGVuZ3RoID4gMykgJiYgKHZhbC5sZW5ndGggPCA2KSkgew0KICAgICAgICBuZXdWYWwgKz0gdmFsLnN1YnN0cigwLCAzKSArICctJzsNCiAgICAgICAgdmFsID0gdmFsLnN1YnN0cigzKTsNCiAgICB9DQogICAgaWYgKHZhbC5sZW5ndGggPiA1KSB7DQogICAgICAgIG5ld1ZhbCArPSB2YWwuc3Vic3RyKDAsIDMpICsgJy0nOw0KICAgICAgICBuZXdWYWwgKz0gdmFsLnN1YnN0cigzLCAyKSArICctJzsNCiAgICAgICAgdmFsID0gdmFsLnN1YnN0cig1KTsNCiAgICB9DQogICAgbmV3VmFsICs9IHZhbDsNCiAgICBlbHQudmFsdWUgPSBuZXdWYWwuc3Vic3RyaW5nKDAsIDExKTsNCn0NCjwvc2NyaXB0Pg0KRU9GOw0KDQogICAgICAgICAgICB9DQoNCiAgICAgICAgfSANCg0KICAgICAgICAkZWxlbWVudCAuPSAkZm9ybWF0X3NjcmlwdDsgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYoaXNzZXQoJGZpZWxkcG9wdWxhdGVkZWZhdWx0KSAmJiAkZmllbGRwb3B1bGF0ZWRlZmF1bHQgPT0gMSl7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IHskX3BofSBjbGFzcz1cImZvcm0tY29udHJvbCB7JGV4dHJhY2xhc3NuYW1lc31cIiB0eXBlPVwieyRodG1sNXR5cGV9XCIgeyRodG1sNV9yYW5nZX0geyRtYXh9IG5hbWU9XCJ7JG5hbWV9XCIgaWQ9XCJ7JGlkfVwiIHskdGFiaHRtbH0gIiAuICcgdmFsdWU9Ijw/cGhwIGlzc2V0KCRfU0VTU0lPTlsnIC4gIid7JG5hbWV9J10pID8gcHJpbnQgIiAuICdodG1sZW50aXRpZXMoJF9TRVNTSU9OWycgLiAiJ3skbmFtZX0nXSwgRU5UX0NPTVBBVCwgJ1VURi04JykgOiBwcmludCAiIC4gJGRlZmF1bHR2YWx1ZSAuICI7ID8+IiAuICciICcgLiAkaW5oZXJpdHN0eWxlIC4gJGF0dHJpYnV0ZSAuICRjb25kaXRpb25hbF9jYWxsX2lubGluZSAuICRlbmFibGVkIC4gJHJlYWRvbmx5IC4gJGZvcm1hdF90cmlnZ2VyIC4gJyAvPic7DQoNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4geyRfcGh9IGNsYXNzPVwiZm9ybS1jb250cm9sIHskZXh0cmFjbGFzc25hbWVzfVwiIHR5cGU9XCJ7JGh0bWw1dHlwZX1cIiB7JGh0bWw1X3JhbmdlfSB7JG1heH0gbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgeyR0YWJodG1sfSAgIiAuICcgdmFsdWU9Ijw/cGhwIHByaW50ICcgLiAkZGVmYXVsdHZhbHVlIC4gIjsgPz4iIC4gJyIgJyAuICRpbmhlcml0c3R5bGUgLiAkYXR0cmlidXRlIC4gJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lIC4gJGVuYWJsZWQgLiAkcmVhZG9ubHkgLiAnIC8+JzsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQogICAgICAgIA0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbjxzcGFuIGNsYXNzPVwidGFpbHRleHRcIj57JHRhaWx0ZXh0fTwvc3Bhbj5cbiI7DQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKCR0b29sdGlwICE9ICIiICYmICR0aGlzLT5nZXRfbGFiZWxfcG9zKCRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUpID09ICJmbG9hdDpsZWZ0OyIpIHsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPmNyZWF0ZV90b29sdGlwX2h0bWwoJHRvb2x0aXAsICRuYW1lKTsNCiAgICAgICAgfQ0KDQogICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYnRvb2x0aXAteyRpZH0gZmJ0b29sdGlwXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmU7XCI+eyR0b29sdGlwX2VsZW1lbnQtPnRleHR9PC9kaXY+XG4iOw0KICAgICAgICAkZWxlbWVudCAuPSAkdG9vbHRpcF9lbGVtZW50LT5qczsNCg0KDQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICRjb2xvcnBpY2tlci0+anNjb2RlOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAkanNsaWRlci0+anNjb2RlOw0KDQogICAgICAgIGlmICgkaGVscGVyICE9ICcnKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48YnIvPjxkaXYgY2xhc3M9XCJoZWxwZXJcIiBzdHlsZT1cImNvbG9yOnskaGVscGVyY29sb3J9O1wiPnskaGVscGVyfTwvZGl2PlxuIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxiciAvPlxuIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkYXV0b3N1Z2dlc3QtPmVuYWJsZSA9PSAxICYmICRhdXRvc3VnZ2VzdC0+bW9kZSA9PSAwKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkcGFyYW1zID0gJyRwYXJhbXMgPSBhcnJheSgnOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRwYXJhbXMgLj0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRkYXRhc291cmNlLT5zb3VyY2VzcWxwYXJhbXMsIDQpOyANCg0KICAgICAgICAgICAgJHBhcmFtcyAuPSAnKTsnOw0KDQogICAgICAgICAgICAkY2FsbF9jb2RlID0gIlwkZGJoLT5zZXRNeVNRTFNTTFByb3BlcnRpZXMoXCRkYl9zc2xfa2V5LCBcJGRiX3NzbF9jZXJ0aWZpY2F0ZSwgXCRkYl9zc2xfY2FfY2VydCwgXCRkYl9zc2xfdmVyaWZ5X2NlcnQsIFwkZGJfc3NsX2NpcGhlcik7XHJcbiI7DQoNCiAgICAgICAgICAgICRjYWxsX2NvZGUgLj0gIlwkcmVzdWx0X3skbmFtZX0gPSBcJGRiaC0+cGRvX3Byb2NlZHVyZV9wYXJhbXMoXCRxdWVyeV9kZWJ1ZywgXCRzcWxfeyRuYW1lfSwgXCRkYl9ob3N0LCBcJGRiX3R5cGUsIFwkbXlzcWxfc29ja2V0LCBcJG15c3FsX3BvcnQsIFwkZGJkc24sIFwkZGJfdXNlciwgXCRkYl9wYXNzLCBcJGRiX2NhdGFsb2csIFwkcGFyYW1zLCAwLCAwKTsiOw0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkc291cmNldHlwZSA9ICR0aGlzLT51bS0+dHJhbnNsYXRlU291cmNlVHlwZSgoaW50KSRkYXRhc291cmNlLT5zb3VyY2V0eXBlKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoIWlzc2V0KCRkYXRhc291cmNlLT5kYmRzbikpIHsNCiAgICAgICAgICAgICAgICAkZGF0YXNvdXJjZS0+ZGJkc24gPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRkYXRhc291cmNlLT5kYmhvc3QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYXRhc291cmNlLT5kYmhvc3QsIDgpOw0KICAgICAgICAgICAgJGRhdGFzb3VyY2UtPmRidXNlciA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRhdGFzb3VyY2UtPmRidXNlciwgOCk7DQogICAgICAgICAgICAkZGF0YXNvdXJjZS0+ZGJwd2QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYXRhc291cmNlLT5kYnB3ZCwgOCk7DQogICAgICAgICAgICAkZGF0YXNvdXJjZS0+ZGJzY2hlbWEgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYXRhc291cmNlLT5kYnNjaGVtYSwgOCk7DQogICAgICAgICAgICAkZGF0YXNvdXJjZS0+ZGJzb2NrZXQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYXRhc291cmNlLT5kYnNvY2tldCwgOCk7DQogICAgICAgICAgICAkZGF0YXNvdXJjZS0+ZGJwb3J0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGF0YXNvdXJjZS0+ZGJwb3J0LCA4KTsNCiAgICAgICAgICAgICRkYXRhc291cmNlLT5kYmRzbiA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRhdGFzb3VyY2UtPmRiZHNuLCA4KTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkdGhpcy0+dW0tPnB1bGxDdXN0b21Db25uZWN0b3JGaWxlKCRmaWVsZC0+ZGJjb25uZWN0b3IpOw0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJGNhbGxfcGFnZSA9IDw8PEVPWQ0KPD9waHANCmlmKCFzZXNzaW9uX2lkKCkpIHsgc2Vzc2lvbl9zdGFydCgpOyB9DQoNCi8vIFBlcmZvcm0gYXV0by1zdWdnZXN0IHNxbCBxdWVyeSBmb3IgeyRuYW1lfQ0KXCRxdWVyeV9kZWJ1ZyA9ICRkYXRhc291cmNlLT5kYmRlYnVnbGV2ZWw7IC8vIGNoYW5nZSB0byAxIHRvIHNlZSBkZWJ1ZyBpbmZvIGlmIHlvdSBydW4gaW50byBwcm9ibGVtcyBleGVjdXRpbmcgeW91ciBxdWVyeSAobWF5IG5lZWQgdG8gbG9vayBhdCBodG1sIHBhZ2Ugc291cmNlIHRvIHNlZSBlcnJvcikuDQpcJGRiX3NjaGVtYV9jaGVjayA9ICJ7JGRhdGFzb3VyY2UtPmRic2NoZW1hfSI7DQpcJGRiX2Rzbl9jaGVjayA9ICJ7JGRhdGFzb3VyY2UtPmRiZHNufSI7DQoNCmlmKFwkZGJfc2NoZW1hX2NoZWNrICE9ICcnIHx8IFwkZGJfZHNuX2NoZWNrICE9ICcnKXsNCglcJGRiX2hvc3QgPSAieyRkYXRhc291cmNlLT5kYmhvc3R9IjsNCglcJGRiX3R5cGUgPSAieyRzb3VyY2V0eXBlfSI7DQoJXCRkYl91c2VyID0gInskZGF0YXNvdXJjZS0+ZGJ1c2VyfSI7DQoJXCRkYl9wYXNzID0gInskZGF0YXNvdXJjZS0+ZGJwd2R9IjsNCglcJGRiX2NhdGFsb2cgPSAieyRkYXRhc291cmNlLT5kYnNjaGVtYX0iOw0KCVwkbXlzcWxfc29ja2V0ID0gInskZGF0YXNvdXJjZS0+ZGJzb2NrZXR9IjsNCglcJG15c3FsX3BvcnQgPSAieyRkYXRhc291cmNlLT5kYnBvcnR9IjsNCglcJGRiZHNuID0gInskZGF0YXNvdXJjZS0+ZGJkc259IjsNCgkNCglcJGRiX3NzbF9rZXkgPSAneyRmaWVsZC0+ZGJzc2xrZXl9JzsNCglcJGRiX3NzbF9jZXJ0aWZpY2F0ZSA9ICd7JGZpZWxkLT5kYnNzbGNlcnRpZmljYXRlfSc7DQoJXCRkYl9zc2xfY2FfY2VydCA9ICd7JGZpZWxkLT5kYnNzbGNhY2VydH0nOw0KCVwkZGJfc3NsX3ZlcmlmeV9jZXJ0ID0gJ3skZmllbGQtPmRic3NsdmVyaWZ5Y2VydH0nOw0KCVwkZGJfc3NsX2NpcGhlciA9ICd7JGZpZWxkLT5kYnNzbGNpcGhlcn0nOw0KfQ0KDQpAaW5jbHVkZV9vbmNlICIuLi8uLi9EYXRhYmFzZS5waHAiOw0KDQppZighc2Vzc2lvbl9pZCgpKSB7IHNlc3Npb25fc3RhcnQoKTsgfQ0KDQoNCi8vIG9wdGlvbmFsIGNvbm5lY3RvciBzY3JpcHQNCmlmKGZpbGVfZXhpc3RzKCIuLi8uLi97JGRhdGFzb3VyY2UtPmRiY29ubmVjdG9yfSIpICYmIGlzX3JlYWRhYmxlKCIuLi8uLi97JGRhdGFzb3VyY2UtPmRiY29ubmVjdG9yfSIpKXsNCgkvLyBCdWlsZCA2OTUgLSBQcmV2ZW50IExvb2t1cHMgb2YgbnVsbCBmaWxlcw0KCWlmKCIuLi8uLi97JGRhdGFzb3VyY2UtPmRiY29ubmVjdG9yfSIgIT0gIi4uLy4uLyIpew0KCQlAaW5jbHVkZSAiLi4vLi4veyRkYXRhc291cmNlLT5kYmNvbm5lY3Rvcn0iOw0KCX0NCn0NCg0KLy8gQ3JlYXRlIFRleHQgUXVlcnkNClwkc3FsX3skbmFtZX0gPSAieyRkYXRhc291cmNlLT5zb3VyY2VzcWx9IjsNClwkZGJoID0gbmV3IERhdGFiYXNlKCk7DQp7JHBhcmFtc30NCnskY2FsbF9jb2RlfQ0KDQoNClwkaW5wdXQgPSBzdHJ0b2xvd2VyKCBcJF9HRVRbJ2lucHV0J10gKTsNClwkbGVuID0gc3RybGVuKFwkaW5wdXQpOw0KXCRsaW1pdCA9IGlzc2V0KFwkX0dFVFsnbGltaXQnXSkgPyAoaW50KSBcJF9HRVRbJ2xpbWl0J10gOiAwOw0KDQoNClwkYVJlc3VsdHMgPSBhcnJheSgpOw0KXCRhSW5mbyA9IGFycmF5X2ZpbGwoMCwgY291bnQoXCRyZXN1bHRfeyRuYW1lfSksICcnKTsNClwkY291bnQgPSAwOw0KDQppZiAoXCRsZW4pDQp7DQoJZm9yIChcJGk9MDtcJGk8Y291bnQoXCRyZXN1bHRfeyRuYW1lfSk7XCRpKyspDQoJew0KCQkvLyBoYWQgdG8gdXNlIHV0Zl9kZWNvZGUsIGhlcmUNCgkJLy8gbm90IG5lY2Vzc2FyeSBpZiB0aGUgcmVzdWx0cyBhcmUgY29taW5nIGZyb20gbXlzcWwNCgkJLy8NCgkJaWYgKHN0cnRvbG93ZXIoc3Vic3RyKHV0ZjhfZGVjb2RlKFwkcmVzdWx0X3skbmFtZX1bXCRpXVswXSksMCxcJGxlbikpID09IFwkaW5wdXQpDQoJCXsNCgkJCVwkY291bnQrKzsNCgkJCVwkYVJlc3VsdHNbXSA9IGFycmF5KCAiaWQiPT4oXCRpKzEpICwidmFsdWUiPT5odG1sc3BlY2lhbGNoYXJzKFwkcmVzdWx0X3skbmFtZX1bXCRpXVswXSksICJpbmZvIj0+aHRtbHNwZWNpYWxjaGFycyhcJGFJbmZvW1wkaV0pICk7DQoJCX0NCgkJDQoJCWlmIChcJGxpbWl0ICYmIFwkY291bnQ9PVwkbGltaXQpDQoJCQlicmVhazsNCgl9DQp9DQoJDQovLyBzZW5kIGNvbnRlbnQgaGVhZGVycw0KaGVhZGVyICgiRXhwaXJlczogTW9uLCAyNiBKdWwgMTk5NyAwNTowMDowMCBHTVQiKTsgLy8gRGF0ZSBpbiB0aGUgcGFzdA0KaGVhZGVyICgiTGFzdC1Nb2RpZmllZDogIiAuIGdtZGF0ZSgiRCwgZCBNIFkgSDppOnMiKSAuICIgR01UIik7IC8vIGFsd2F5cyBtb2RpZmllZA0KaGVhZGVyICgiQ2FjaGUtQ29udHJvbDogbm8tY2FjaGUsIG11c3QtcmV2YWxpZGF0ZSIpOyAvLyBIVFRQLzEuMQ0KaGVhZGVyICgiUHJhZ21hOiBuby1jYWNoZSIpOyAvLyBIVFRQLzEuMA0KDQppZiAoaXNzZXQoXCRfUkVRVUVTVFsnanNvbiddKSkNCnsNCgloZWFkZXIoIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIpOw0KDQoJZWNobyAie1xcInJlc3VsdHNcXCI6IFsiOw0KCVwkYXJyID0gYXJyYXkoKTsNCglmb3IgKFwkaT0wO1wkaTxjb3VudChcJGFSZXN1bHRzKTtcJGkrKykNCgl7DQoJCVwkYXJyW10gPSAie1xcImlkXCI6IFxcIiIuXCRhUmVzdWx0c1tcJGldWydpZCddLiJcXCIsIFxcInZhbHVlXFwiOiBcIiIuXCRhUmVzdWx0c1tcJGldWyd2YWx1ZSddLiJcXCIsIFxcImluZm9cXCI6IFxcIlxcIn0iOw0KCX0NCgllY2hvIGltcGxvZGUoIiwgIiwgXCRhcnIpOw0KCWVjaG8gIl19IjsNCn0NCgkJCQ0KPz4NCgkJDQpFT1k7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgZmlsZV9wdXRfY29udGVudHMoJHNhdmVwYXRoIC4gJG5hbWUgLiAnLnBocCcsICRjYWxsX3BhZ2UpOw0KICAgICAgICAgICAgY2htb2QoJHNhdmVwYXRoIC4gJG5hbWUgLiAnLnBocCcsIEZJTEVfTU9EKTsNCg0KICAgICAgICAgICAgaWYgKCFpc3NldCgkYXV0b3N1Z2dlc3QtPmNhbGxiYWNrKSkgew0KICAgICAgICAgICAgICAgICRhdXRvc3VnZ2VzdC0+Y2FsbGJhY2sgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoIWlzc2V0KCRhdXRvc3VnZ2VzdC0+Y2FjaGVtb2RlKSkgew0KICAgICAgICAgICAgICAgICRhdXRvc3VnZ2VzdC0+Y2FjaGVtb2RlID0gMDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgaWYgKChpbnQpJGF1dG9zdWdnZXN0LT5jYWNoZW1vZGUgPT0gMCkgew0KICAgICAgICAgICAgICAgICRhdXRvc3VnZ2VzdC0+Y2FjaGVtb2RlID0gJ3RydWUnOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkYXV0b3N1Z2dlc3QtPmNhY2hlbW9kZSA9ICdmYWxzZSc7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPSA0KCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCglhc19maWVsZCA9ICJ7JGlkfSI7DQoJdmFyIG9wdGlvbnMgPSB7DQoJCXNjcmlwdDoianMvYXV0b3N1Z2dlc3QveyRuYW1lfS5waHA/anNvbj10cnVlJmxpbWl0PXskYXV0b3N1Z2dlc3QtPnN1Z2dlc3Rpb25zfSYiLA0KCQl2YXJuYW1lOiJpbnB1dCIsDQoJCWpzb246dHJ1ZSwNCgkJY2FjaGU6eyRhdXRvc3VnZ2VzdC0+Y2FjaGVtb2RlfSwNCgkJc2hvd25vcmVzdWx0czpmYWxzZSwNCgkJbWluY2hhcnM6eyRhdXRvc3VnZ2VzdC0+bWluY2hhcnN9LA0KCQltYXhlbnRyaWVzOnskYXV0b3N1Z2dlc3QtPnN1Z2dlc3Rpb25zfSwNCgkJZGVsYXk6eyRhdXRvc3VnZ2VzdC0+ZGVsYXl9LA0KCQl0aW1lb3V0OnskYXV0b3N1Z2dlc3QtPnRpbWVvdXR9LA0KCQljYWxsYmFjazogZnVuY3Rpb24oZSl7DQoJCQkvLyBZb3VyIGN1c3RvbSBjYWxsYmFjayBjb2RlIGhlcmUuLi4NCgkJCXskYXV0b3N1Z2dlc3QtPmNhbGxiYWNrfQ0KCQl9DQoJfTsNCgl2YXIgYXNfanNvbiA9IG5ldyBic24uQXV0b1N1Z2dlc3QoJ3skaWR9Jywgb3B0aW9ucyk7DQo8L3NjcmlwdD4NCg0KRU9IOw0KICAgICAgICB9DQoNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkYXV0b3N1Z2dlc3QtPmVuYWJsZSA9PSAxICYmICRhdXRvc3VnZ2VzdC0+bW9kZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICRjYWxsX3BhZ2UgPSA8PDxFT1UNCjw/cGhwDQoNCi8vIHJlYWQgaW4geG1sIGZpbGUNClwkeG1sZGF0YSA9IGZpbGVfZ2V0X2NvbnRlbnRzKCcuLi8uLi8nIC4gJ3skYXV0b3N1Z2dlc3QtPnhtbGZpbGVsb2NhdGlvbn0nKTsNCi8vIGxvYWQvcGFyc2UgeG1sDQpcJHJvb3QgPSBzaW1wbGV4bWxfbG9hZF9zdHJpbmcoXCR4bWxkYXRhKTsNClwkcmVzdWx0X3skbmFtZX0gPSBnZXRfb2JqZWN0X3ZhcnMoXCRyb290KTsNCg0KXCRpbnB1dCA9IHN0cnRvbG93ZXIoIFwkX0dFVFsnaW5wdXQnXSApOw0KXCRsZW4gPSBzdHJsZW4oXCRpbnB1dCk7DQpcJGxpbWl0ID0gaXNzZXQoXCRfR0VUWydsaW1pdCddKSA/IChpbnQpIFwkX0dFVFsnbGltaXQnXSA6IDA7DQoNClwkYVJlc3VsdHMgPSBhcnJheSgpOw0KXCRhSW5mbyA9IGFycmF5X2ZpbGwoMCwgY291bnQoXCRyZXN1bHRfeyRuYW1lfVsncnMnXSksICcnKTsNClwkY291bnQgPSAwOw0KDQppZiAoXCRsZW4pDQp7DQoJZm9yIChcJGk9MDtcJGk8Y291bnQoXCRyZXN1bHRfeyRuYW1lfVsncnMnXSk7XCRpKyspDQoJew0KCQkvLyBoYWQgdG8gdXNlIHV0Zl9kZWNvZGUsIGhlcmUNCgkJLy8gbm90IG5lY2Vzc2FyeSBpZiB0aGUgcmVzdWx0cyBhcmUgY29taW5nIGZyb20gbXlzcWwNCgkJLy8NCgkJaWYgKHN0cnRvbG93ZXIoc3Vic3RyKHV0ZjhfZGVjb2RlKFwkcmVzdWx0X3skbmFtZX1bJ3JzJ11bXCRpXSksMCxcJGxlbikpID09IFwkaW5wdXQpDQoJCXsNCgkJCVwkY291bnQrKzsNCgkJCVwkYVJlc3VsdHNbXSA9IGFycmF5KCAiaWQiPT4oXCRpKzEpICwidmFsdWUiPT5odG1sc3BlY2lhbGNoYXJzKChzdHJpbmcpXCRyZXN1bHRfeyRuYW1lfVsncnMnXVtcJGldKSwgImluZm8iPT5odG1sc3BlY2lhbGNoYXJzKFwkYUluZm9bXCRpXSkgKTsNCgkJfQ0KCQkNCgkJaWYgKFwkbGltaXQgJiYgXCRjb3VudD09XCRsaW1pdCkNCgkJCWJyZWFrOw0KCX0NCn0NCgkNCi8vIHNlbmQgY29udGVudCBoZWFkZXJzDQpoZWFkZXIgKCJFeHBpcmVzOiBNb24sIDI2IEp1bCAxOTk3IDA1OjAwOjAwIEdNVCIpOyAvLyBEYXRlIGluIHRoZSBwYXN0DQpoZWFkZXIgKCJMYXN0LU1vZGlmaWVkOiAiIC4gZ21kYXRlKCJELCBkIE0gWSBIOmk6cyIpIC4gIiBHTVQiKTsgLy8gYWx3YXlzIG1vZGlmaWVkDQpoZWFkZXIgKCJDYWNoZS1Db250cm9sOiBuby1jYWNoZSwgbXVzdC1yZXZhbGlkYXRlIik7IC8vIEhUVFAvMS4xDQpoZWFkZXIgKCJQcmFnbWE6IG5vLWNhY2hlIik7IC8vIEhUVFAvMS4wDQoNCmlmIChpc3NldChcJF9SRVFVRVNUWyd4bWwnXSkpDQp7DQoJaGVhZGVyKCJDb250ZW50LVR5cGU6IHRleHQveG1sIik7DQoNCgllY2hvICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJ1dGYtOFwiID8+PHJlc3VsdHM+IjsNCglmb3IgKFwkaT0wO1wkaTxjb3VudChcJGFSZXN1bHRzKTtcJGkrKykNCgl7DQoJCWVjaG8gIjxycyBpZD1cXCIiLlwkYVJlc3VsdHNbXCRpXVsnaWQnXS4iXFwiIGluZm89XFwiIi5cJGFSZXN1bHRzW1wkaV1bJ2luZm8nXS4iXFwiPiIuXCRhUmVzdWx0c1tcJGldWyd2YWx1ZSddLiI8L3JzPiI7DQoJfQ0KCWVjaG8gIjwvcmVzdWx0cz4iOw0KfQ0KPz4NCkVPVTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBmaWxlX3B1dF9jb250ZW50cygkc2F2ZXBhdGggLiAkbmFtZSAuICcucGhwJywgJGNhbGxfcGFnZSk7DQogICAgICAgICAgICBjaG1vZCgkc2F2ZXBhdGggLiAkbmFtZSAuICcucGhwJywgRklMRV9NT0QpOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPSA0KCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCgl2YXIgb3B0aW9ucyA9IHsNCgkJc2NyaXB0OiJqcy9hdXRvc3VnZ2VzdC97JG5hbWV9LnBocD94bWw9dHJ1ZSZsaW1pdD17JGF1dG9zdWdnZXN0LT5zdWdnZXN0aW9uc30mIiwNCgkJdmFybmFtZToiaW5wdXQiLA0KCQlqc29uOmZhbHNlLA0KCQlzaG93bm9yZXN1bHRzOmZhbHNlLA0KCQltaW5jaGFyczp7JGF1dG9zdWdnZXN0LT5taW5jaGFyc30sDQoJCW1heHJlc3VsdHM6eyRhdXRvc3VnZ2VzdC0+c3VnZ2VzdGlvbnN9LA0KCQlkZWxheTp7JGF1dG9zdWdnZXN0LT5kZWxheX0sDQoJCXRpbWVvdXQ6eyRhdXRvc3VnZ2VzdC0+dGltZW91dH0sDQoJCWNhbGxiYWNrOiBmdW5jdGlvbihlKXsNCgkJCS8vIE1ha2Ugc3VyZSBBSkFYIGNhbGxzIGhhdmUgYW4gZXZlbnQgKG9uYmx1cikgdG8gYmluZCB0by4uLg0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lucHV0JylbKGRvY3VtZW50LmZvcm1zWzBdLmxlbmd0aCAtIDEpXS5mb2N1cygpOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWR9JykuZm9jdXMoKTsNCgkJCS8vIFlvdXIgY3VzdG9tIGNhbGxiYWNrIGNvZGUgaGVyZS4uLg0KCQl9DQoJfTsNCgl2YXIgYXNfeG1sID0gbmV3IGJzbi5BdXRvU3VnZ2VzdCgneyRpZH0nLCBvcHRpb25zKTsNCjwvc2NyaXB0Pg0KDQpFT0g7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9wYXNzd29yZCgkcGFnZSwgJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT57J2xhYmVsJ307DQogICAgICAgICRuYW1lID0gJGZpZWxkLT57J25hbWUnfTsNCiAgICAgICAgJGlkID0gJGZpZWxkLT57J2lkJ307DQogICAgICAgICRyZXEgPSAkZmllbGQtPnZhbGlkYXRpb24tPnJlcTsNCiAgICAgICAgJGZpZWxkd2lkdGggPSAkZmllbGQtPmZpZWxkd2lkdGg7DQogICAgICAgICRmaWVsZGhlaWdodCA9ICRmaWVsZC0+ZmllbGRoZWlnaHQ7IA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGZpZWxkLT5kZWZhdWx0dmFsdWU7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KICAgICAgICAkbWF4bGVuZ3RoID0gJGZpZWxkLT52YWxpZGF0aW9uLT5tYXg7DQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRwb3B1bGF0ZWRlZmF1bHQpID8gJGZpZWxkLT5maWVsZHBvcHVsYXRlZGVmYXVsdCA6IDE7IA0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICR0b29sdGlwID0gJGZpZWxkLT50b29sdGlwOw0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICR0b29sdGlwX2VsZW1lbnQgPSAkdGhpcy0+dHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGlkKTsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQogICAgICAgIA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJHRoaXMtPmNyZWF0ZV9kZWZhdWx0X3ZhbHVlX3Rva2VucygkZGVmYXVsdHZhbHVlKTsNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZGhlaWdodCkpIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkaGVpZ2h0ID09ICIiKSB7DQogICAgICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7IA0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiaGVpZ2h0OnskZmllbGRoZWlnaHR9cHg7IjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdwdCcpOw0KICAgICAgICAkY3QyID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHgnKTsNCg0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJGZvbnRzaXplID0gJGZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzX251bWVyaWMoKHN0cmluZykkZmllbGR3aWR0aCkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAkZmllbGR3aWR0aCAuICdweCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlKSAmJiAkYnVja2V0X25vZGUgIT0gIiIgJiYgKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5yZXNwb25zaXZlID09IDEpIHsNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJzg1JSc7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJHBhZ2UpICYmICRwYWdlLT5qc2xpYnJhcnkgPT0gIjE0Iikgew0KICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdGVzdCA9IChpbnQpJGluaGVyaXRzdHlsZTsNCiAgICAgICAgaWYgKCR0ZXN0ICE9IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAwOw0KICAgICAgICB9DQogICAgICAgIGlmICgkaW5oZXJpdHN0eWxlID09IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiZm9udC1zaXplOnskZm9udHNpemV9OyBjb2xvcjp7JGlucHV0X2NvbG9yfTsgZm9udC1mYW1pbHk6aW5oZXJpdDsgd2lkdGg6eyRmaWVsZHdpZHRofTsgeyRmaWVsZGhlaWdodH0geyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiIGNvbG9yOnskaW5wdXRfY29sb3J9OyB3aWR0aDp7JGZpZWxkd2lkdGh9OyB7JGZpZWxkaGVpZ2h0fSB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRtYXhsZW5ndGggIT0gJycpIHsNCiAgICAgICAgICAgICRtYXggPSAgIm1heGxlbmd0aD1cInskbWF4bGVuZ3RofVwiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRtYXggPSAnJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5sZWZ0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JGZpeGVkX3dpZHRofXB4OyBtYXJnaW4tcmlnaHQ6OHB4OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn1cIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJHJlcXVpcmVkX3RleHQgPSBpc3NldCgkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIpID8gJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyIDogIiYjNDI7IjsNCg0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+X2hlbHBlcl9maWVsZF9sYWJlbCgkZmllbGQsICRuYW1lLCAkcmVxLCAkcmVxdWlyZWRfdGV4dCwgJGNvbG9yLCAkZm9udHNpemUsICRzdHlsZXMsICRsYWJlbCwgJGxhYmVscG9zLCAoc3RyaW5nKSRmaWVsZC0+dHlwZSwgJHRvb2x0aXAsICcnLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbnskY29uZGl0aW9uYWxfY2FsbF9zY3JpcHR9XG4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgKHN0cmluZykkZmllbGQtPmJ1Y2tldCAhPSAnJykgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwiZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICANCg0KICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZXh0cmFjbGFzc25hbWUpICYmICRmaWVsZC0+ZXh0cmFjbGFzc25hbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAkZmllbGQtPmV4dHJhY2xhc3NuYW1lOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfdGFibGVfbW9kZV9tb2JpbGVfbGFiZWwoJGZpZWxkLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZihpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgJGZpZWxkLT5idWNrZXQgIT0gIiIpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzIC49ICIgYnVja2V0LWNvbnRhaW5lZC1maWVsZCI7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZihpc3NldCgkZmllbGRwb3B1bGF0ZWRlZmF1bHQpICYmICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9PSAxKXsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9XCJmb3JtLWNvbnRyb2wgeyRleHRyYWNsYXNzbmFtZXN9XCIgdHlwZT1cInBhc3N3b3JkXCIgeyRtYXh9IG5hbWU9XCJ7JG5hbWV9XCIgaWQ9XCJ7JGlkfVwiIHskdGFiaHRtbH0gIiAuICcgdmFsdWU9Ijw/cGhwIGlzc2V0KCRfU0VTU0lPTlsnIC4gIid7JG5hbWV9J10pID8gcHJpbnQgIiAuICdodG1sZW50aXRpZXMoJF9TRVNTSU9OWycgLiAiJ3skbmFtZX0nXSwgRU5UX0NPTVBBVCwgJ1VURi04JykgOiBwcmludCAiIC4gJGRlZmF1bHR2YWx1ZSAuICI7ID8+IiAuICciICcgLiAkaW5oZXJpdHN0eWxlIC4gJGF0dHJpYnV0ZSAuICRjb25kaXRpb25hbF9jYWxsX2lubGluZSAuICRlbmFibGVkIC4gJHJlYWRvbmx5IC4gIiAvPiI7DQoNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9XCJmb3JtLWNvbnRyb2wgeyRleHRyYWNsYXNzbmFtZXN9XCIgdHlwZT1cInBhc3N3b3JkXCIgeyRtYXh9IG5hbWU9XCJ7JG5hbWV9XCIgaWQ9XCJ7JGlkfVwiIHskdGFiaHRtbH0gdmFsdWU9XCJcIiAiIC4gJGluaGVyaXRzdHlsZSAuICRhdHRyaWJ1dGUgLiAkY29uZGl0aW9uYWxfY2FsbF9pbmxpbmUgLiAkZW5hYmxlZCAuICRyZWFkb25seSAuICIgLz4iOw0KICAgICAgICAgICAgDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYnRvb2x0aXAteyRpZH0gZmJ0b29sdGlwXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmU7XCI+eyR0b29sdGlwX2VsZW1lbnQtPnRleHR9PC9kaXY+XG4iOw0KICAgICAgICAkZWxlbWVudCAuPSAkdG9vbHRpcF9lbGVtZW50LT5qczsNCg0KICAgICAgICBpZiAoJGhlbHBlciAhPSAnJykgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGJyLz48ZGl2IGNsYXNzPVwiaGVscGVyXCIgc3R5bGU9XCJjb2xvcjp7JGhlbHBlcmNvbG9yfTtcIj57JGhlbHBlcn08L2Rpdj5cbiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48YnIgLz5cbiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT52YWxpZGF0aW9uLT5wYXNzd29yZHN0cmVuZ3RoKSAmJiAoaW50KSRmaWVsZC0+dmFsaWRhdGlvbi0+cGFzc3dvcmRzdHJlbmd0aCA9PSAxKSB7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPRg0KDQo8ZGl2IGlkPSJwd3NfcHJvZ3Jlc3NiYXIiPjxkaXYgaWQ9InB3c19wcm9ncmVzcyI+PC9kaXY+PC9kaXY+DQo8ZGl2IGlkPSJwd3Nfc3RhdHVzIj4NCgk8ZGl2IGlkPSJwd3NfY29tcGxleGl0eSI+MCU8L2Rpdj4NCgk8ZGl2IGlkPSJwd3NfY29tcGxleGl0eUxhYmVsIj5Db21wbGV4aXR5PC9kaXY+DQo8L2Rpdj4NCiAgICANCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCnZhciBwYXNzd29yZF9vcHRpb25zID0geyBtaW5pbXVtQ2hhcnM6IDgsIHN0cmVuZ3RoU2NhbGVGYWN0b3I6IC41IH0NCg0KJChmdW5jdGlvbiAoKSB7DQogICAgJCgiI3skaWR9IikuY29tcGxleGlmeShwYXNzd29yZF9vcHRpb25zLCBmdW5jdGlvbiAodmFsaWQsIGNvbXBsZXhpdHkpIHsNCiAgICAgICAgaWYgKCF2YWxpZCkgew0KICAgICAgICAgICAgJCgnI3B3c19wcm9ncmVzcycpLmNzcyh7J3dpZHRoJzpjb21wbGV4aXR5ICsgJyUnfSkucmVtb3ZlQ2xhc3MoJ3B3c19wcm9ncmVzc2JhclZhbGlkJykuYWRkQ2xhc3MoJ3B3c19wcm9ncmVzc2JhckludmFsaWQnKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICQoJyNwd3NfcHJvZ3Jlc3MnKS5jc3Moeyd3aWR0aCc6Y29tcGxleGl0eSArICclJ30pLnJlbW92ZUNsYXNzKCdwd3NfcHJvZ3Jlc3NiYXJJbnZhbGlkJykuYWRkQ2xhc3MoJ3B3c19wcm9ncmVzc2JhclZhbGlkJyk7DQogICAgICAgIH0NCiAgICAgICAgJCgnI3B3c19jb21wbGV4aXR5JykuaHRtbChNYXRoLnJvdW5kKGNvbXBsZXhpdHkpICsgJyUnKTsNCiAgICB9KTsNCn0pOw0KDQo8L3NjcmlwdD4NCgkJDQpFT0Y7DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0gDQoNCg0KICAgIA0KICAgIA0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfdGV4dGFyZWEoJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJHBsYWNlaG9sZGVyID0gJGZpZWxkLT5wbGFjZWhvbGRlcjsgDQogICAgICAgICRuYW1lID0gJGZpZWxkLT5uYW1lOw0KICAgICAgICAkaWQgPSAkZmllbGQtPmlkOw0KICAgICAgICAkZmllbGR3aWR0aCA9ICRmaWVsZC0+ZmllbGR3aWR0aDsNCiAgICAgICAgJGZpZWxkaGVpZ2h0ID0gJGZpZWxkLT5maWVsZGhlaWdodDsNCiAgICAgICAgJHJlcSA9ICRmaWVsZC0+dmFsaWRhdGlvbi0+cmVxOw0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGZpZWxkLT5kZWZhdWx0dmFsdWU7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KICAgICAgICAkbWF4bGVuZ3RoID0gJGZpZWxkLT52YWxpZGF0aW9uLT5tYXg7DQogICAgICAgICRjb3VudGl0ZW1zID0gJGZpZWxkLT52YWxpZGF0aW9uLT52YWxjb3VudGl0ZW1zOw0KICAgICAgICAkY291bnRpdGVtc2NvbG9yID0gJGZpZWxkLT52YWxpZGF0aW9uLT5jb3VudGl0ZW1zY29sb3I7IA0KICAgICAgICAkcmVhZG9ubHkgPSBpc3NldCgkZmllbGQtPnJlYWRvbmx5KSA/ICRmaWVsZC0+cmVhZG9ubHkgOiAwOw0KICAgICAgICAkZmllbGRlbmFibGVkID0gaXNzZXQoJGZpZWxkLT5maWVsZGVuYWJsZWQpID8gJGZpZWxkLT5maWVsZGVuYWJsZWQgOiAxOw0KICAgICAgICAkZmllbGRwb3B1bGF0ZWRlZmF1bHQgPSBpc3NldCgkZmllbGQtPmZpZWxkcG9wdWxhdGVkZWZhdWx0KSA/ICRmaWVsZC0+ZmllbGRwb3B1bGF0ZWRlZmF1bHQgOiAxOyANCiAgICAgICAgJGF0dHJpYnV0ZSA9ICRmaWVsZC0+YXR0cmlidXRlOw0KICAgICAgICAkYXR0cmlidXRlc3R5bGUgPSAkZmllbGQtPmF0dHJpYnV0ZXN0eWxlOw0KICAgICAgICAkdGlueW1jZSA9ICRmaWVsZC0+dGlueW1jZTsNCiAgICAgICAgJGNvbmRpdGlvbmFsID0gJGZpZWxkLT5jb25kaXRpb25hbDsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCiAgICAgICAgJHRvb2x0aXAgPSAkZmllbGQtPnRvb2x0aXA7DQogICAgICAgICR0YWJpbmRleCA9ICRmaWVsZC0+dGFiaW5kZXg7DQoNCg0KICAgICAgICANCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGxhYmVsID09ICIiKSB7DQogICAgICAgICAgICAkbGFiZWwgPSAiJm5ic3A7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRwbGFjZWhvbGRlcikpIHsNCiAgICAgICAgICAgICRwbGFjZWhvbGRlciA9ICIiOw0KICAgICAgICB9DQoNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRzdHlsZSk7DQoNCiAgICAgICAgDQogICAgICAgICR0b29sdGlwX2VsZW1lbnQgPSAkdGhpcy0+dHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGlkKTsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQogICAgICAgIA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJHRoaXMtPmNyZWF0ZV9kZWZhdWx0X3ZhbHVlX3Rva2VucygkZGVmYXVsdHZhbHVlKTsNCg0KDQogICAgICAgIA0KDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdwdCcpOw0KICAgICAgICAkY3QyID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHgnKTsNCg0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJGZvbnRzaXplID0gJGZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKGlzX251bWVyaWMoKHN0cmluZykkZmllbGR3aWR0aCkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAkZmllbGR3aWR0aCAuICdweCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlKSAmJiAkYnVja2V0X25vZGUgIT0gIiIgJiYgKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5yZXNwb25zaXZlID09IDEpIHsNCiAgICAgICAgICAgICRmaWVsZHdpZHRoID0gJzk1JSc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHRlc3QgPSAoaW50KSRpbmhlcml0c3R5bGU7DQogICAgICAgIGlmICgkdGVzdCAhPSAxKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gMDsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoJGluaGVyaXRzdHlsZSA9PSAxKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cImZvbnQtc2l6ZTp7JGZvbnRzaXplfTsgY29sb3I6eyRpbnB1dF9jb2xvcn07IGZvbnQtZmFtaWx5OmluaGVyaXQ7IHdpZHRoOnskZmllbGR3aWR0aH07IGhlaWdodDp7JGZpZWxkaGVpZ2h0fXB4OyB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCIgY29sb3I6eyRpbnB1dF9jb2xvcn07IHdpZHRoOnskZmllbGR3aWR0aH07IGhlaWdodDp7JGZpZWxkaGVpZ2h0fXB4OyB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRtYXhsZW5ndGggPSAkbWF4bGVuZ3RoICE9ICcnID8gJG1heGxlbmd0aCA6IDUwMDsNCiAgICAgICAgJGN0X3RleHQgPSAnJzsNCiAgICAgICAgaWYgKCRjb3VudGl0ZW1zID09IDEgfHwgJGNvdW50aXRlbXMgPT0gMikgew0KICAgICAgICAgICAgJGFjdGlvbiA9ICRjb3VudGl0ZW1zID09IDEgPyAnY250V29yZHMnIDogJ2NudENoYXJzJzsNCiAgICAgICAgICAgICRjdF90ZXh0ID0gIm9ua2V5dXA9XCJ7JGFjdGlvbn0odGhpcyx0aGlzLmlkLHskbWF4bGVuZ3RofSlcIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHRpbnlfbWNlID0gJyc7DQogICAgICAgICR0aW55X21jZV9lbnRpdGllc19zdGFydCA9ICcnOw0KICAgICAgICAkdGlueV9tY2VfZW50aXRpZXNfZW5kID0gJyc7DQogICAgICAgIGlmICgkdGlueW1jZSAhPSAwKSB7DQogICAgICAgICAgICAkdGlueV9tY2UgPSAnY2xhc3M9Im1jZUVkaXRvciInOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHRpbnlfbWNlX2VudGl0aWVzX3N0YXJ0ID0gJ2h0bWxlbnRpdGllcygnOw0KICAgICAgICAgICAgJHRpbnlfbWNlX2VudGl0aWVzX2VuZCA9ICcsIG51bGwsICJVVEYtOCIpJzsgDQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+bGVmdGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyRmaXhlZF93aWR0aH1weDsgbWFyZ2luLXJpZ2h0OjhweDsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259XCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgJHJlcSwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsICRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUsICR0b29sdGlwLCAnJywgJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmV4dHJhY2xhc3NuYW1lKSAmJiAkZmllbGQtPmV4dHJhY2xhc3NuYW1lICE9ICIiKSB7DQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gJGZpZWxkLT5leHRyYWNsYXNzbmFtZTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRfcGggPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJHBsYWNlaG9sZGVyKSAmJiAkcGxhY2Vob2xkZXIgIT0gIiIpIHsNCiAgICAgICAgICAgICRfcGggPSAiIHBsYWNlaG9sZGVyPVwieyRwbGFjZWhvbGRlcn1cIiAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfdGFibGVfbW9kZV9tb2JpbGVfbGFiZWwoJGZpZWxkLCR0YWJsZW1vZGUpOw0KDQogICAgICAgIA0KICAgICAgICAkcmVhZG9ubHkgPSBpc3NldCgkcmVhZG9ubHkpID8gJHJlYWRvbmx5ID09IDEgPyAiIHJlYWRvbmx5ICIgOiAiIiA6ICIiOw0KICAgICAgICAkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZGVuYWJsZWQpID8gJGZpZWxkZW5hYmxlZCA9PSAwID8gIiBkaXNhYmxlZCAiIDogIiIgOiAiIjsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRmaWVsZC0+YnVja2V0KSAmJiAkZmllbGQtPmJ1Y2tldCAhPSAiIil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgLj0gIiBidWNrZXQtY29udGFpbmVkLWZpZWxkIjsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRmaWVsZHBvcHVsYXRlZGVmYXVsdCkgJiYgJGZpZWxkcG9wdWxhdGVkZWZhdWx0ID09IDEpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPHRleHRhcmVhIDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiB7JHRpbnlfbWNlfSBuYW1lPVwieyRuYW1lfVwiIHskX3BofSBjbGFzcz1cImZvcm0tY29udHJvbCB7JGV4dHJhY2xhc3NuYW1lc31cIiBpZD1cInskaWR9XCIgeyR0YWJodG1sfSB7JGN0X3RleHR9IHskaW5oZXJpdHN0eWxlfSB7JGF0dHJpYnV0ZX0geyRjb25kaXRpb25hbF9jYWxsX2lubGluZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSA+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICc8P3BocCBpc3NldCgkX1NFU1NJT05bJyAuICIneyRuYW1lfSddKSA/IHByaW50ICIgLiAkdGlueV9tY2VfZW50aXRpZXNfc3RhcnQgLiAnJF9TRVNTSU9OWycgLiAiJ3skbmFtZX0nXSIgLiAkdGlueV9tY2VfZW50aXRpZXNfZW5kIC4gIiA6IHByaW50IHskZGVmYXVsdHZhbHVlfTsgPz4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvdGV4dGFyZWE+IjsNCiAgICAgICAgICAgIA0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPHRleHRhcmVhIDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiB7JHRpbnlfbWNlfSBuYW1lPVwieyRuYW1lfVwiIHskX3BofSBjbGFzcz1cImZvcm0tY29udHJvbCB7JGV4dHJhY2xhc3NuYW1lc31cIiBpZD1cInskaWR9XCIgeyR0YWJodG1sfSB7JGN0X3RleHR9IHskaW5oZXJpdHN0eWxlfSB7JGF0dHJpYnV0ZX0geyRjb25kaXRpb25hbF9jYWxsX2lubGluZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSA+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICc8P3BocCBwcmludCAnIC4gJGRlZmF1bHR2YWx1ZSAuICI7ID8+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L3RleHRhcmVhPiI7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZidG9vbHRpcC17JGlkfSBmYnRvb2x0aXBcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj57JHRvb2x0aXBfZWxlbWVudC0+dGV4dH08L2Rpdj5cbiI7DQogICAgICAgICRlbGVtZW50IC49ICR0b29sdGlwX2VsZW1lbnQtPmpzOw0KDQoNCiAgICAgICAgaWYgKCRjb3VudGl0ZW1zICE9IDApIHsNCiAgICAgICAgICAgICRhY3Rpb24gPSAkY291bnRpdGVtcyA9PSAxID8gJ1dvcmRzIFR5cGVkJyA6ICdDaGFyYWN0ZXJzIEVudGVyZWQnOw0KDQogICAgICAgICAgICAkY29sb3IgPSAiY29sb3I6ICM4ODg4ODg7IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJGNvdW50aXRlbXNjb2xvcikgJiYgJGNvdW50aXRlbXNjb2xvciAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgJGNvbG9yID0gImNvbG9yOiB7JGNvdW50aXRlbXNjb2xvcn07IjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQo8YnIvPg0KPGRpdiBzdHlsZT0ieyRjb2xvcn0gZGlzcGxheTppbmxpbmU7IiBjbGFzcz0iY291bnQtaGVscGVyIj57JGFjdGlvbn06PC9kaXY+PGRpdiBzdHlsZT0ieyRjb2xvcn0gZGlzcGxheTppbmxpbmU7IiBjbGFzcz0iY291bnQtaGVscGVyLWJvbGQiIG5hbWU9ImNvdW50X3skaWR9IiBpZD0iY291bnRfeyRpZH0iPjwvZGl2Pg0KPGRpdiBzdHlsZT0ieyRjb2xvcn0gZGlzcGxheTppbmxpbmU7IiBjbGFzcz0iY291bnQtaGVscGVyIj5SZW1haW5pbmc6PC9kaXY+PGRpdiBzdHlsZT0ieyRjb2xvcn0gZGlzcGxheTppbmxpbmU7IiBjbGFzcz0iY291bnQtaGVscGVyLWJvbGQiIG5hbWU9ImxlZnRfeyRpZH0iIGlkPSJsZWZ0X3skaWR9Ij48L2Rpdj4NCjxkaXYgc3R5bGU9InskY29sb3J9IGRpc3BsYXk6aW5saW5lOyIgaWQ9InskaWR9X2VyciIgY2xhc3M9ImNvdW50LWhlbHBlci1lcnJvciI+PC9kaXY+DQpFT1Q7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoJGhlbHBlciAhPSAnJykgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxici8+PGRpdiBjbGFzcz1cImhlbHBlclwiIHN0eWxlPVwiY29sb3I6eyRoZWxwZXJjb2xvcn07XCI+eyRoZWxwZXJ9PC9kaXY+IjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8YnIgLz4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9zdWJtaXRfYnV0dG9uKCRmaWVsZCwgJHNlY3VyaXR5X2FycmF5LCAkdGFibGVtb2RlLCAkcGVyc2lzdGFuY2UsICRwZXJzaXN0YW5jZWxhbmd1YWdlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJGNhcHRjaGEgPSAkZmllbGQtPmNhcHRjaGE7DQogICAgICAgICRjaGFyYWN0ZXJzID0gJGZpZWxkLT5jaGFyYWN0ZXJzOw0KICAgICAgICAkd2lkdGggPSAkZmllbGQtPmZpZWxkd2lkdGg7DQogICAgICAgICRoZWlnaHQgPSAkZmllbGQtPmhlaWdodDsNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT5jb2xvcjsNCiAgICAgICAgJGNhcHRjaGF0ZXh0ID0gJGZpZWxkLT5jYXB0Y2hhdGV4dDsNCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJGZpZWxkLT5yZWFkb25seSkgPyAkZmllbGQtPnJlYWRvbmx5IDogMDsNCiAgICAgICAgJGZpZWxkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRlbmFibGVkKSA/ICRmaWVsZC0+ZmllbGRlbmFibGVkIDogMTsNCiAgICAgICAgJGF0dHJpYnV0ZSA9ICRmaWVsZC0+YXR0cmlidXRlOw0KICAgICAgICAkYXR0cmlidXRlc3R5bGUgPSAkZmllbGQtPmF0dHJpYnV0ZXN0eWxlOw0KICAgICAgICAkcmVwdWJsaWNrZXkgPSAkZmllbGQtPnJlcHVibGlja2V5Ow0KICAgICAgICAkcmVzc2wgPSAkZmllbGQtPnJlc3NsOw0KICAgICAgICAkcmVzdHlsZSA9ICRmaWVsZC0+cmVzdHlsZTsNCiAgICAgICAgJHJlbGFuZyA9ICRmaWVsZC0+cmVsYW5nOw0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+bmFtZTsNCiAgICAgICAgJGlkID0gJGZpZWxkLT5pZDsNCiAgICAgICAgJGNoYWxsZW5lZ2VxdWVzdGlvbiA9ICRmaWVsZC0+Y2hhbGxlbmdlcXVlc3Rpb247DQogICAgICAgICRjaGFsbGVuZ2VhbnN3ZXIgPSAkZmllbGQtPmNoYWxsZW5nZWFuc3dlcjsNCiAgICAgICAgJGNoYWxsZW5nZWNvbG9yID0gJGZpZWxkLT5jaGFsbGVuZ2Vjb2xvcjsNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCiAgICAgICAgJGN1c3RvbV9jc3MgPSAkZmllbGQtPmN1c3RvbV9jc3M7IA0KDQogICAgICAgIA0KICAgICAgICAkbm9jYXB0Y2hhcmVjYXB0Y2hhX3NpdGVrZXkgPSAkZmllbGQtPm5vY2FwdGNoYXJlY2FwdGNoYV9zaXRla2V5Ow0KICAgICAgICAkbm9jYXB0Y2hhcmVjYXB0Y2hhX3NlY3JldCA9ICRmaWVsZC0+bm9jYXB0Y2hhcmVjYXB0Y2hhX3NlY3JldDsNCiAgICAgICAgJG5vY2FwdGNoYXJlY2FwdGNoYV9sYW5ndWFnZSA9ICRmaWVsZC0+bm9jYXB0Y2hhcmVjYXB0Y2hhX2xhbmd1YWdlOyANCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHBlcnNpc3RhbmNlID09ICIiKSB7DQogICAgICAgICAgICAkcGVyc2lzdGFuY2UgPSAwOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoc3RyaW5nKSRwZXJzaXN0YW5jZWxhbmd1YWdlID09ICIiKSB7DQogICAgICAgICAgICAkcGVyc2lzdGFuY2VsYW5ndWFnZSA9IDA7DQogICAgICAgIH0NCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfY3VzdG9tX2Nzc19ibG9jaygkaWQsICRjdXN0b21fY3NzKTsNCg0KDQogICAgICAgIA0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGFjdGl2ZSA9IChpbnQpJHNlY3VyaXR5X2FycmF5LT5hY3RpdmU7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkYXR0cmlidXRlc3R5bGUgPT0gIiIpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwieyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGh9OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7XCI+Jm5ic3A7PC9kaXY+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkcmVzc2wpIHx8ICRyZXNzbCA9PSAiIikgew0KICAgICAgICAgICAgJHJlc3NsID0gMDsNCiAgICAgICAgfQ0KDQogICAgICAgIHN3aXRjaCAoJHJlc3NsKSB7DQogICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAkcmVzc2wgPSAnZmFsc2UnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJHJlc3NsID0gJ3RydWUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJHJlc3R5bGUpIHx8ICRyZXN0eWxlID09ICIiKSB7DQogICAgICAgICAgICAkcmVzdHlsZSA9IDA7DQogICAgICAgIH0NCg0KICAgICAgICBzd2l0Y2ggKCRyZXN0eWxlKSB7DQoNCiAgICAgICAgICAgIGNhc2UgJzAnOg0KICAgICAgICAgICAgICAgICRyZXN0eWxlX2NvZGUgPSAncmVkJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICRyZXN0eWxlX2NvZGUgPSAnd2hpdGUnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMic6DQogICAgICAgICAgICAgICAgJHJlc3R5bGVfY29kZSA9ICdibGFja2dsYXNzJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzMnOg0KICAgICAgICAgICAgICAgICRyZXN0eWxlX2NvZGUgPSAnY2xlYW4nOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCFpc3NldCgkY2FwdGNoYXRleHQpIHx8ICRjYXB0Y2hhdGV4dCA9PSAiIikgew0KICAgICAgICAgICAgJGNhcHRjaGF0ZXh0ID0gIkVudGVyIENvZGU6IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRyZWxhbmcpIHx8ICRyZWxhbmcgPT0gIiIpIHsNCiAgICAgICAgICAgICRyZWxhbmcgPSAiZW4iOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHJlbGFuZyA9ICR0aGlzLT51bS0+dHJhbnNsYXRlUmVjYXB0Y2hhTGFuZ3VhZ2UoJHJlbGFuZyk7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkY3VzdG9tX2Nzcy0+YWxsKSAmJiAkY3VzdG9tX2Nzcy0+YWxsICE9ICIiICYmICRjdXN0b21fY3NzLT5hbGwgIT0gJzxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT4nKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICAgICBwcmVnX21hdGNoX2FsbCgnL1sjLl1bYS16LUEtWjAtOV9dKy8nLCAoc3RyaW5nKSRjdXN0b21fY3NzLT5hbGwsICRtYXRjaGVzKTsgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzBdKSAmJiBpc3NldCgkbWF0Y2hlc1swXVswXSkgJiYgJG1hdGNoZXNbMF1bMF0gIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRfY3VzdG9tX3NlbGVjdG9yID0gJG1hdGNoZXNbMF1bMF07DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcuJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcjJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCg0KICAgICAgICANCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHdpZHRoLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSR3aWR0aCwgJ3B4Jyk7DQogICAgICAgICRjdDMgPSBzdWJzdHJfY291bnQoKHN0cmluZykkd2lkdGgsICclJyk7DQoNCiAgICAgICAgaWYgKHRyaW0oJHdpZHRoKSA9PSAiIikgew0KDQogICAgICAgICAgICAkd2lkdGggPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDAgJiYgJGN0MyA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAncHg7JzsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAnOyc7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgc3dpdGNoICgkY2FwdGNoYSkgew0KDQogICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48aW5wdXQgbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgc3R5bGU9XCJ7JHdpZHRofVwiIGNsYXNzPVwibm9sYWJlbCBidG4gYnRuLXByaW1hcnkgeyRfY3VzdG9tX3NlbGVjdG9yfSB7JGV4dHJhY2xhc3NuYW1lc31cIiB0eXBlPVwic3VibWl0XCIgeyR0YWJodG1sfSB2YWx1ZT1cInskbGFiZWx9XCIgeyRhdHRyaWJ1dGV9IG9uY2xpY2s9XCJmYi5kaXNhYmxlX3N1Ym1pdChldmVudCk7XCIgeyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPlxuIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgY2FzZSAnMSc6DQoNCiAgICAgICAgICAgICAgICAkX3dpZHRoID0gKGludCkkZmllbGQtPndpZHRoOw0KICAgICAgICAgICAgICAgICRfaGVpZ2h0ID0gKGludCkkZmllbGQtPmhlaWdodDsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmICh0cmltKCRfd2lkdGgpID09ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRfd2lkdGggPSAxNDA7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgaWYgKHRyaW0oJF9oZWlnaHQpID09ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRfaGVpZ2h0ID0gMTQwOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KXG48ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOi03cHg7Ij48aW1nIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PnNlY3VyaXR5L0NhcHRjaGEvQ2FwdGNoYVNlY3VyaXR5SW1hZ2VzLnBocD93aWR0aD17JF93aWR0aH0maGVpZ2h0PXskX2hlaWdodH0mY2hhcmFjdGVycz17JGNoYXJhY3RlcnN9IiAvPjwvZGl2Pjxici8+DQo8c3BhbiBjbGFzcz0iaGVhZGluZy1tYWluIiBzdHlsZT0iY29sb3I6eyRjb2xvcn07Ij57JGNhcHRjaGF0ZXh0fTwvc3Bhbj4NCjxpbnB1dCBpZD0ic2VjdXJpdHlfY29kZSIgbmFtZT0ic2VjdXJpdHlfY29kZSIgdHlwZT0idGV4dCIgc2l6ZT0iNyIgYXV0b2NvbXBsZXRlPSJvZmYiIC8+PGJyLz48YnIvPg0KPGlucHV0IGNsYXNzPSJub2xhYmVsIGJ0bi1kZWZhdWx0IHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9IiB0eXBlPSJzdWJtaXQiIG5hbWU9InN1Ym1pdCIgaWQ9InN1Ym1pdCIgdmFsdWU9InskbGFiZWx9IiBvbmNsaWNrPSJmYi5kaXNhYmxlX3N1Ym1pdChldmVudCk7IiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IC8+DQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNClxuPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCXZhciBSZWNhcHRjaGFPcHRpb25zID0gew0KICAgIAl0aGVtZSA6ICd7JHJlc3R5bGVfY29kZX0nLA0KICAgIAlsYW5nOiAneyRyZWxhbmd9Jw0KCX07DQo8L3NjcmlwdD4NCiANCiA8P3BocA0KLy8gdGhpcyB2YWx1ZSBpcyBzZXQgZnJvbSB0aGUgUmFja0Zvcm1zIGVkaXRvciwgaXQgbWF5IGJlIGJsYW5rLCBhdCB3aGljaCBwb2ludCB0aGUgdmFsdWUgc2V0IGluIHlvdXIgY29uZmlnLnBocCBmaWxlIHdpbGwgYmUgdXNlZC4NClwkcHVibGlja2V5ID0gInskcmVwdWJsaWNrZXl9IjsgLy8geW91IGdvdCB0aGlzIGZyb20gdGhlIHNpZ251cCBwYWdlDQoNCi8vIE9wdGlvbmFsIGNvbm5lY3RvciBzY3JpcHQgZm9yIHJlQ0FQVENIQSBwdWJsaWMga2V5IHZhbHVlDQovLyBpZiB0aGUgaW5jbHVkZWQgdmFsdWUgb2YgXCRwcml2YXRla2V5IGlzIGJsYW5rLCB3ZSB1c2UgdGhlIHZhbHVlIHBhc3NlZCBpbiBmcm9tIHRoZSBlZGl0b3IuDQpcJGFjdGl2ZSA9IHskYWN0aXZlfTsNCkBpbmNsdWRlX29uY2UgIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfXNlY3VyaXR5L3NlY3VyZV9zdWJtaXQucGhwIjsNCmlmKGlzc2V0KFwkcHVibGlja2V5KSAmJiBcJHB1YmxpY2tleSAhPSAnJyl7DQoJLy8gUHVibGljIGtleSBoYXMgYmVlbiBzZXQgZnJvbSBjb25maWcucGhwDQp9IGVsc2Ugew0KCVwkcHVibGlja2V5ID0gInskcmVwdWJsaWNrZXl9IjsgLy8gcmVDQVBUQ0hBIHB1YmxpYyBrZXkgZnJvbSBzaWdudXAgcHJvY2Vzcw0KfQ0KcmVxdWlyZV9vbmNlKCJ7XCRfU0VTU0lPTlsnTUFYX1BBVEgnXX1zZWN1cml0eS9yZUNhcHRjaGEvcmVjYXB0Y2hhbGliLnBocCIpOw0KZWNobyByZWNhcHRjaGFfZ2V0X2h0bWwoXCRwdWJsaWNrZXksICcnLCB7JHJlc3NsfSk7DQo/Pg0KJm5ic3A7PGlucHV0IGNsYXNzPSJub2xhYmVsIGJ0bi1kZWZhdWx0IHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9IiB0eXBlPSJzdWJtaXQiIG5hbWU9InN1Ym1pdCIgaWQ9InN1Ym1pdCIgdmFsdWU9InskbGFiZWx9IiBvbmNsaWNrPSJmYi5kaXNhYmxlX3N1Ym1pdChldmVudCk7IiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IC8+DQpFT1Q7DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgY2FzZSAnMyc6DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQo8P3BocCBAaW5jbHVkZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119c2VjdXJpdHkvM0RDYXB0Y2hhL1RleHRHZW4ucGhwIjsgPz4NCjxkaXYgc3R5bGU9Im1hcmdpbi1ib3R0b206LTdweDsiPiA8aW1nIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PnNlY3VyaXR5LzNEQ2FwdGNoYS8zRENhcHRjaGEucGhwIiBhbHQ9IkNhcHRjaGEiPiA8L2Rpdj4NCjxiciAvPg0KPHNwYW4gY2xhc3M9ImhlYWRpbmctbWFpbiIgc3R5bGU9ImNvbG9yOnskY29sb3J9OyI+eyRjYXB0Y2hhdGV4dH08L3NwYW4+IA0KPGlucHV0IGlkPSIzRENhcHRjaGFUZXh0IiBuYW1lPSIzRENhcHRjaGFUZXh0IiB0eXBlPSJ0ZXh0IiBzaXplPSI3IiBhdXRvY29tcGxldGU9Im9mZiIgLz48YnIgLz4NCjxiciAvPg0KPGlucHV0IGNsYXNzPSJub2xhYmVsIGJ0bi1kZWZhdWx0IHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9IiB0eXBlPSJzdWJtaXQiIG5hbWU9InN1Ym1pdCIgaWQ9InN1Ym1pdCIgdmFsdWU9InskbGFiZWx9IiBvbmNsaWNrPSJmYi5kaXNhYmxlX3N1Ym1pdChldmVudCk7IiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IC8+DQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIGNhc2UgJzQnOg0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJPD9waHAgXCRfU0VTU0lPTlsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWydjaGFsbGVuZ2VfYW5zd2VyJ10gPSAneyRjaGFsbGVuZ2VhbnN3ZXJ9JzsgPz4NCgk8c3BhbiBjbGFzcz0iaGVhZGluZy1tYWluIiBzdHlsZT0iY29sb3I6eyRjaGFsbGVuZ2Vjb2xvcn07Ij5TZWN1cml0eSBRdWVzdGlvbjo8L3NwYW4+PGJyIC8+DQoJPHNwYW4gY2xhc3M9ImhlYWRpbmctc3ViIiBzdHlsZT0iY29sb3I6eyRjaGFsbGVuZ2Vjb2xvcn07Ij57JGNoYWxsZW5lZ2VxdWVzdGlvbn08L3NwYW4+PGJyIC8+DQoJPGlucHV0IGlkPSJjaGFsbGVuZ2VfYW5zd2VyIiBuYW1lPSJjaGFsbGVuZ2VfYW5zd2VyIiB0eXBlPSJ0ZXh0IiBzaXplPSIyMCIgYXV0b2NvbXBsZXRlPSJvZmYiIC8+PGJyIC8+PGJyIC8+DQoJPGlucHV0IGNsYXNzPSJub2xhYmVsIGJ0bi1kZWZhdWx0IHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9IiB0eXBlPSJzdWJtaXQiIG5hbWU9InN1Ym1pdCIgaWQ9InN1Ym1pdCIgdmFsdWU9InskbGFiZWx9IiBvbmNsaWNrPSJmYi5kaXNhYmxlX3N1Ym1pdChldmVudCk7IiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IC8+DQpFT1Q7DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgY2FzZSAnNSc6DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRub2NhcHRjaGFyZWNhcHRjaGFfbGFuZ3VhZ2UpICYmICRub2NhcHRjaGFyZWNhcHRjaGFfbGFuZ3VhZ2UgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCXZhciBvbmxvYWRDYWxsYmFjayA9IGZ1bmN0aW9uKCkgew0KCQlncmVjYXB0Y2hhLnJlbmRlcigneyRmaWVsZC0+aWR9Jywgew0KCQkJJ3NpdGVrZXknIDogJ3skbm9jYXB0Y2hhcmVjYXB0Y2hhX3NpdGVrZXl9JywNCgkJCSdobCcgOiAneyRub2NhcHRjaGFyZWNhcHRjaGFfbGFuZ3VhZ2V9Jw0KCQl9KTsNCgl9Ow0KPC9zY3JpcHQ+DQoJCQkJCQ0KPHNjcmlwdCBzcmM9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vcmVjYXB0Y2hhL2FwaS5qcz9vbmxvYWQ9b25sb2FkQ2FsbGJhY2smcmVuZGVyPWV4cGxpY2l0IiANCglhc3luYyBkZWZlcj4NCjwvc2NyaXB0Pg0KDQo8ZGl2IGlkPSJ7JGZpZWxkLT5pZH0iIGNsYXNzPSJnLXJlY2FwdGNoYSIgZGF0YS1zaXRla2V5PSJ7JG5vY2FwdGNoYXJlY2FwdGNoYV9zaXRla2V5fSI+PC9kaXY+PGJyIC8+DQoNCjxpbnB1dCBjbGFzcz0ibm9sYWJlbCBidG4tZGVmYXVsdCB7JF9jdXN0b21fc2VsZWN0b3J9IHskZXh0cmFjbGFzc25hbWVzfSIgdHlwZT0ic3VibWl0IiBuYW1lPSJzdWJtaXQiIGlkPSJzdWJtaXQiIG9uY2xpY2s9ImZiLmRpc2FibGVfc3VibWl0KGV2ZW50KTsiIHZhbHVlPSJ7JGxhYmVsfSIgeyRhdHRyaWJ1dGV9IHskaW5oZXJpdHN0eWxlfSAvPg0KRU9UOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQo8c2NyaXB0IHNyYz0iaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9yZWNhcHRjaGEvYXBpLmpzIiBhc3luYyBkZWZlcj48L3NjcmlwdD4NCjxkaXYgY2xhc3M9ImctcmVjYXB0Y2hhIiBkYXRhLXNpdGVrZXk9Inskbm9jYXB0Y2hhcmVjYXB0Y2hhX3NpdGVrZXl9Ij48L2Rpdj48YnIgLz4NCjxpbnB1dCBjbGFzcz0ibm9sYWJlbCBidG4tZGVmYXVsdCB7JF9jdXN0b21fc2VsZWN0b3J9IHskZXh0cmFjbGFzc25hbWVzfSIgdHlwZT0ic3VibWl0IiBuYW1lPSJzdWJtaXQiIGlkPSJzdWJtaXQiIHZhbHVlPSJ7JGxhYmVsfSIgeyRhdHRyaWJ1dGV9IHskaW5oZXJpdHN0eWxlfSAvPg0KRU9UOw0KICAgICAgICAgICAgICAgIH0NCg0KDQoNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJHBlcnNpc3RhbmNlID09IDMgJiYgJGZpZWxkLT5yb3V0ZSA9PSAiIikgew0KDQogICAgICAgICAgICAkc3VibWl0X3RleHQgPSAiU2F2ZSBhbmQgUmV0dXJuIExhdGVyIjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJHBlcnNpc3RhbmNlbGFuZ3VhZ2UpKSB7DQogICAgICAgICAgICAgICAgc3dpdGNoICgoaW50KSRwZXJzaXN0YW5jZWxhbmd1YWdlKSB7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAgICAgICAgICRzdWJtaXRfdGV4dCA9ICJPcHNsYWFuIGVuIGxhdGVyIGJld2Vya2VuIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOyANCiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOg0KICAgICAgICAgICAgICAgICAgICAgICAgJHN1Ym1pdF90ZXh0ID0gIlp1IHNwZWljaGVybiB1bmQgc3DDpHRlciI7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsgDQogICAgICAgICAgICAgICAgICAgIGNhc2UgMzoNCiAgICAgICAgICAgICAgICAgICAgICAgICRzdWJtaXRfdGV4dCA9ICJTYWx2YXJlIGUgdG9ybmFyZSBwacO5IHRhcmRpIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOyANCiAgICAgICAgICAgICAgICAgICAgY2FzZSA0Og0KICAgICAgICAgICAgICAgICAgICAgICAgJHN1Ym1pdF90ZXh0ID0gIkd1YXJkYXIgeSB2b2x2ZXIgbcOhcyB0YXJkZSI7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsgDQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJHBlcnNpc3RhbmNlbGFuZ3VhZ2UgPSAoaW50KSRwZXJzaXN0YW5jZWxhbmd1YWdlOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkcGVyc2lzdGFuY2VsYW5ndWFnZSA9ICIwIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InJmX3NhdmVfYW5kX3JldHVybiIgaWQ9InJmX3NhdmVfYW5kX3JldHVybiIgdmFsdWU9ImZhbHNlIiAvPg0KCQkJCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJCQkJCWZ1bmN0aW9uIHVwZGF0ZVNhdmVSZXR1cm4oKSB7IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyZl9zYXZlX2FuZF9yZXR1cm4nKS52YWx1ZT0ndHJ1ZSc7IH0NCiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3JmX3NhdmVfYW5kX3JldHVybicpLnZhbHVlID0gJ2ZhbHNlJzsgLy8gUmVzZXQgT24gUGFnZSBMb2FkLg0KCQkJCQk8L3NjcmlwdD4NCjxpbnB1dCBjbGFzcz0ibm9sYWJlbCBidG4gYnRuLXByaW1hcnkgZmxkLWZ1bGwgbXVpLWJ0biBtdWktYnRuLS1wcmltYXJ5IiB0eXBlPSJidXR0b24iIHZhbHVlPSJ7JHN1Ym1pdF90ZXh0fSIgb25jbGljaz0idXBkYXRlU2F2ZVJldHVybigpOyBkb2N1bWVudC5mb3Jtc1swXS5zdWJtaXQoKTsiIC8+DQo8P3BocCBcJF9TRVNTSU9OWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bJ1NBVkVfQU5EX1JFU1VNRV9MQU5HVUFHRSddID0gJ3skcGVyc2lzdGFuY2VsYW5ndWFnZX0nOyA/Pg0KRU9GOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCgkJDQoJCQ0KCQkNCgkJDQoJCQ0KCQkNCgkJDQoJCQ0KCQkNCgkJDQoJCQ0KCQkNCgkJDQoJCQ0KCQkkZWxlbWVudCAuPSA8PDxFT0YNCiAgICAgICAgPD9waHANCiAgICAgICAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnRkJfV09SS0ZMT1cnXVsnSVNfRk9STUJPU1NfV09SS0ZMT1dfTE9BREVSJ10pICYmIFwkX1NFU1NJT05bJ0ZCX1dPUktGTE9XJ11bJ0lTX0ZPUk1CT1NTX1dPUktGTE9XX0xPQURFUiddID09IHRydWUpew0KICAgICAgICAgICAgDQogICAgICAgIFwkaHRtbCA9IDw8PEVPSg0KICAgICAgICA8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSIuLi8uLi8uLi9hcHAvanMvcHJvdG90eXBlLmpzIj48L3NjcmlwdD4NCiAgICAgICAgPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KICAgICAgICAgICAgDQogICAgICAgICAgICBkb2N1bWVudC5vYnNlcnZlKCdkb206bG9hZGVkJywgZnVuY3Rpb24obCl7DQogICAgICAgICAgICANCiAgICAgICAgICAgIHZhciBpZnJhbWVfcGFyZW50X2RpdiA9IHdpbmRvdy5mcmFtZUVsZW1lbnQgPyB3aW5kb3cuZnJhbWVFbGVtZW50LnBhcmVudE5vZGUgOiBudWxsOw0KICAgICAgICAgICAgDQogICAgICAgICAgICB2YXIgY29udHJvbF9oZWFkZXIgPSAoJChpZnJhbWVfcGFyZW50X2RpdikuYWRqYWNlbnQoJy5qb2Itdmlld2VyLWhlYWRlcicpKTsNCiAgICAgICAgICAgIHZhciBjb250cm9sc193cmFwcGVyID0gJChjb250cm9sX2hlYWRlclswXSkuZG93bignLmpvYi12aWV3ZXItdGFzay1jb250cm9scy13cmFwcGVyJyk7DQogICAgICAgICAgICANCiAgICAgICAgICAgIGN1cnJlbnRfdGFza19tYXN0ZXJfaWRfdmFsID0gJChjb250cm9sc193cmFwcGVyKS5kb3duKCdJTlBVVCcsIDApLnZhbHVlOw0KICAgICAgICAgICAgY3VycmVudF9hY3RpdmVfdGFza19pZF92YWwgPSAkKGNvbnRyb2xzX3dyYXBwZXIpLmRvd24oJ0lOUFVUJywgMSkudmFsdWU7DQogICAgICAgICAgICBjdXJyZW50X3N0YWdlX25hbWVfdmFsID0gJChjb250cm9sc193cmFwcGVyKS5kb3duKCdJTlBVVCcsIDIpLnZhbHVlOw0KICAgICAgICAgICAgd29ya2Zsb3dfam9iX2lkX3ZhbCA9ICQoY29udHJvbHNfd3JhcHBlcikuZG93bignSU5QVVQnLCAzKS52YWx1ZTsNCiAgICAgICAgICAgIHRpbWVsaW5lX2xvYWQgPSAkKGNvbnRyb2xzX3dyYXBwZXIpLmRvd24oJ0lOUFVUJywgNCkudmFsdWU7DQogICAgICAgICAgICANCiAgICAgICAgICAgICQoJ0ZPUk1CT1NTX1dPUktGTE9XX0NVUlJFTlRfVEFTS19NQVNURVJfSUQnKS52YWx1ZSA9IGN1cnJlbnRfdGFza19tYXN0ZXJfaWRfdmFsOw0KICAgICAgICAgICAgJCgnRk9STUJPU1NfV09SS0ZMT1dfQ1VSUkVOVF9BQ1RJVkVfVEFTS19JRCcpLnZhbHVlID0gY3VycmVudF9hY3RpdmVfdGFza19pZF92YWw7DQogICAgICAgICAgICAkKCdGT1JNQk9TU19XT1JLRkxPV19DVVJSRU5UX1NUQUdFX05BTUUnKS52YWx1ZSA9IGN1cnJlbnRfc3RhZ2VfbmFtZV92YWw7DQogICAgICAgICAgICAkKCdGT1JNQk9TU19XT1JLRkxPV19KT0JfSUQnKS52YWx1ZSA9IHdvcmtmbG93X2pvYl9pZF92YWw7DQogICAgICAgICAgICAkKCdGT1JNQk9TU19XT1JLRkxPV19USU1FTElORV9MT0FEJykudmFsdWUgPSB0aW1lbGluZV9sb2FkOw0KICAgICAgICAgICAgDQogICAgICAgICAgICAvLyBhZGQgZHluYW1pYyBvbmNsaWNrIHByb3BlcnR5IGNhbGxiYWNrIHRvIHRoZSBmb3JtcyBzdWJtaXQgYnV0dG9uDQogICAgICAgICAgICAkKCd7JGlkfScpLndyaXRlQXR0cmlidXRlKCdvbmNsaWNrJywgJ3dvcmtmbG93X3N1Ym1pdF9jbGlja2VkKCk7Jyk7DQogICAgICAgICAgICANCiAgICAgICAgfSk7ICANCiAgICAgICAgDQogICAgICAgIGZ1bmN0aW9uIHdvcmtmbG93X3N1Ym1pdF9jbGlja2VkKCl7DQogICAgICAgICAgICANCiAgICAgICAgICAgIHZhciBpZnJhbWVfcGFyZW50X2RpdiA9IHdpbmRvdy5mcmFtZUVsZW1lbnQgPyB3aW5kb3cuZnJhbWVFbGVtZW50LnBhcmVudE5vZGUgOiBudWxsOw0KICAgICAgICAgICAgDQogICAgICAgICAgICB2YXIgdGFza19tYW5hZ2VtZW50X3dyYXBwZXIgPSAoJChpZnJhbWVfcGFyZW50X2RpdikuYWRqYWNlbnQoJy50YXNrLW1hbmFnZW1lbnQtd3JhcHBlcicpKTsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYoJCh0YXNrX21hbmFnZW1lbnRfd3JhcHBlclswXSkgIT09IHVuZGVmaW5lZCl7IC8vIG5vdCBhbHdheXMgcHJlc2VudC4uLg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIC8vIG5vdGUgLmFkamFjZW50IHJldHVybnMgYSBjb2xsZWN0aW9uLCBzbyB3ZSBtdXN0IHNwZWNpZnkgWzBdDQogICAgICAgICAgICAgICAgJCgnRk9STUJPU1NfV09SS0ZMT1dfVEFTS19NQU5BR0VNRU5UX1RBU0tfQ09NTUVOVCcpLnZhbHVlID0gJCh0YXNrX21hbmFnZW1lbnRfd3JhcHBlclswXSkuZG93bignLnRhc2stbWFuYWdlbWVudC1jb21tZW50JykudmFsdWU7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgLy8gc3RhZ2Ugc2VsZWN0IGxvZ2ljDQogICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZigkKHRhc2tfbWFuYWdlbWVudF93cmFwcGVyWzBdKS5kb3duKCcudGFzay1tYW5hZ2VtZW50LXN0YWdlLXNlbGVjdCcpICE9PSB1bmRlZmluZWQpeyAvLyBub3QgYWx3YXlzIHByZXNlbnQgZXZlbiBpZiBjb21tZW50cyBhcmUuLi4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIGJ1ZyAtIGdyYWJzIGRpc3BsYXkgdmFsdWUgaW5zdGVhZCBvZiB2YWx1ZSBwcm9lcHJ0eQ0KICAgICAgICAgICAgICAgICAgICB2YWxfdGVzdCA9ICQodGFza19tYW5hZ2VtZW50X3dyYXBwZXJbMF0pLmRvd24oJy50YXNrLW1hbmFnZW1lbnQtc3RhZ2Utc2VsZWN0JykudmFsdWU7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZih2YWxfdGVzdCA9PSAnLS1TRUxFQ1QgQSBTVEFHRS0tJykNCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbF90ZXN0ID0gJyc7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJCgnRk9STUJPU1NfV09SS0ZMT1dfVEFTS19NQU5BR0VNRU5UX1NUQUdFX1NFTEVDVCcpLnZhbHVlID0gdmFsX3Rlc3Q7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgPC9zY3JpcHQ+DQogICAgICAgIA0KRU9KOw0KICAgICAgICANCiAgICAgICAgICAgICAgICBlY2hvIFwkaHRtbDsNCiAgICAgICAgDQogICAgICAgIH0NCiAgICAgICAgPz4NCkVPRjsNCiAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBpZD1cIkZPUk1CT1NTX1dPUktGTE9XX0NVUlJFTlRfVEFTS19NQVNURVJfSURcIiBuYW1lPVwiRk9STUJPU1NfV09SS0ZMT1dfQ1VSUkVOVF9UQVNLX01BU1RFUl9JRFwiIHZhbHVlPVwiXCIgLz5cbiI7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBpZD1cIkZPUk1CT1NTX1dPUktGTE9XX0NVUlJFTlRfQUNUSVZFX1RBU0tfSURcIiBuYW1lPVwiRk9STUJPU1NfV09SS0ZMT1dfQ1VSUkVOVF9BQ1RJVkVfVEFTS19JRFwiIHZhbHVlPVwiXCIgLz5cbiI7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBpZD1cIkZPUk1CT1NTX1dPUktGTE9XX0NVUlJFTlRfU1RBR0VfTkFNRVwiIG5hbWU9XCJGT1JNQk9TU19XT1JLRkxPV19DVVJSRU5UX1NUQUdFX05BTUVcIiB2YWx1ZT1cIlwiIC8+XG4iOw0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJGT1JNQk9TU19XT1JLRkxPV19KT0JfSURcIiBuYW1lPVwiRk9STUJPU1NfV09SS0ZMT1dfSk9CX0lEXCIgdmFsdWU9XCJcIiAvPlxuIjsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiRk9STUJPU1NfV09SS0ZMT1dfVElNRUxJTkVfTE9BRFwiIG5hbWU9XCJGT1JNQk9TU19XT1JLRkxPV19USU1FTElORV9MT0FEXCIgdmFsdWU9XCJcIiAvPlxuIjsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiRk9STUJPU1NfV09SS0ZMT1dfVEFTS19NQU5BR0VNRU5UX1RBU0tfQ09NTUVOVFwiIG5hbWU9XCJGT1JNQk9TU19XT1JLRkxPV19UQVNLX01BTkFHRU1FTlRfVEFTS19DT01NRU5UXCIgdmFsdWU9XCJcIiAvPlxuIjsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiRk9STUJPU1NfV09SS0ZMT1dfVEFTS19NQU5BR0VNRU5UX1NUQUdFX1NFTEVDVFwiIG5hbWU9XCJGT1JNQk9TU19XT1JLRkxPV19UQVNLX01BTkFHRU1FTlRfU1RBR0VfU0VMRUNUXCIgdmFsdWU9XCJcIiAvPlxuIjsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHByaW50X2VsdF9vcGVuID0gIlxuIiAuICc8P3BocCBpZighaXNzZXQoJF9HRVRbXCdmYi13b3JrZmxvdy1wcmludC12aWV3XCddKSkgeyA/PicgLiAiXG4iOw0KICAgICAgICAgICAgICAgICRwcmludF9lbHRfY2xvc2UgPSAiXG4iIC4gJzw/cGhwIH0gPz4nIC4gIlxuIjsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICByZXR1cm4gJHByaW50X2VsdF9vcGVuIC4gJGVsZW1lbnQgLiAkcHJpbnRfZWx0X2Nsb3NlOw0KDQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9yZXNldF9idXR0b24oJGZvcm0sICRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+bGFiZWw7DQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRhdHRyaWJ1dGUgPSAkZmllbGQtPmF0dHJpYnV0ZTsNCiAgICAgICAgJGF0dHJpYnV0ZXN0eWxlID0gJGZpZWxkLT5hdHRyaWJ1dGVzdHlsZTsNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCiAgICAgICAgJHdpZHRoID0gJGZpZWxkLT5maWVsZHdpZHRoOw0KDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGF0dHJpYnV0ZXN0eWxlID09ICIiKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cInskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZXh0cmFjbGFzc25hbWUpICYmICRmaWVsZC0+ZXh0cmFjbGFzc25hbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAkZmllbGQtPmV4dHJhY2xhc3NuYW1lOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSR3aWR0aCwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkd2lkdGgsICdweCcpOw0KICAgICAgICAkY3QzID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHdpZHRoLCAnJScpOw0KDQogICAgICAgIGlmICh0cmltKCR3aWR0aCkgPT0gIiIpIHsNCg0KICAgICAgICAgICAgJHdpZHRoID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwICYmICRjdDMgPT0gMCkgew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJHdpZHRoIC4gJ3B4Oyc7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJHdpZHRoIC4gJzsnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRyZWFkb25seSkgPyAkcmVhZG9ubHkgPT0gMSA/ICIgcmVhZG9ubHkgIiA6ICIiIDogIiI7DQogICAgICAgICRlbmFibGVkID0gaXNzZXQoJGZpZWxkZW5hYmxlZCkgPyAkZmllbGRlbmFibGVkID09IDAgPyAiIGRpc2FibGVkICIgOiAiIiA6ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiPGlucHV0IHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIm5vbGFiZWwgYnRuIHskZXh0cmFjbGFzc25hbWVzfVwiIG9uY2xpY2s9XCJjbGVhckZvcm0oeyRmb3JtLT5pZH0pXCIgdmFsdWU9XCJ7JGxhYmVsfVwiIHN0eWxlPVwieyR3aWR0aH1cIiBuYW1lPVwicmVzZXRcIiBpZD1cInJlc2V0XCIgeyR0YWJodG1sfSB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9idXR0b25fYnV0dG9uKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KICAgICAgICAkbGFiZWwgPSAkZmllbGQtPmxhYmVsOw0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+bmFtZTsNCiAgICAgICAgJGlkID0gJGZpZWxkLT5pZDsNCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJGZpZWxkLT5yZWFkb25seSkgPyAkZmllbGQtPnJlYWRvbmx5IDogMDsNCiAgICAgICAgJGZpZWxkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRlbmFibGVkKSA/ICRmaWVsZC0+ZmllbGRlbmFibGVkIDogMTsNCiAgICAgICAgJGF0dHJpYnV0ZSA9ICRmaWVsZC0+YXR0cmlidXRlOw0KICAgICAgICAkYXR0cmlidXRlc3R5bGUgPSAkZmllbGQtPmF0dHJpYnV0ZXN0eWxlOw0KICAgICAgICAkY29uZGl0aW9uYWwgPSAkZmllbGQtPmNvbmRpdGlvbmFsOw0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KICAgICAgICAkY3VzdG9tX2NzcyA9ICRmaWVsZC0+Y3VzdG9tX2NzczsgDQogICAgICAgICR3aWR0aCA9ICRmaWVsZC0+ZmllbGR3aWR0aDsNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+Y3JlYXRlX2N1c3RvbV9jc3NfYmxvY2soJGlkLCAkY3VzdG9tX2Nzcyk7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF9jYWxsID0gJHRoaXMtPl9jcmVhdGVDb25kaXRpb25hbEV2ZW50KCRjb25kaXRpb25hbCwgJG5hbWUsICRpZCk7DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICRjb25kaXRpb25hbF9jYWxsWzBdOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAkY29uZGl0aW9uYWxfY2FsbFsxXTsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxueyRjb25kaXRpb25hbF9jYWxsX3NjcmlwdH1cbiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGF0dHJpYnV0ZXN0eWxlID09ICIiKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cInskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkY3VzdG9tX2Nzcy0+YWxsKSAmJiAkY3VzdG9tX2Nzcy0+YWxsICE9ICIiICYmICRjdXN0b21fY3NzLT5hbGwgIT0gJzxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT4nKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICAgICBwcmVnX21hdGNoX2FsbCgnL1sjLl1bYS16LUEtWjAtOV9dKy8nLCAoc3RyaW5nKSRjdXN0b21fY3NzLT5hbGwsICRtYXRjaGVzKTsgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzBdKSAmJiBpc3NldCgkbWF0Y2hlc1swXVswXSkgJiYgJG1hdGNoZXNbMF1bMF0gIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRfY3VzdG9tX3NlbGVjdG9yID0gJG1hdGNoZXNbMF1bMF07DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcuJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcjJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHdpZHRoLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSR3aWR0aCwgJ3B4Jyk7DQogICAgICAgICRjdDMgPSBzdWJzdHJfY291bnQoKHN0cmluZykkd2lkdGgsICclJyk7DQoNCiAgICAgICAgaWYgKHRyaW0oJHdpZHRoKSA9PSAiIikgew0KDQogICAgICAgICAgICAkd2lkdGggPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDAgJiYgJGN0MyA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAncHg7JzsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAnOyc7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIjxpbnB1dCBjbGFzcz1cIm5vbGFiZWwgYnRuIHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9XCIgc3R5bGU9XCJ7JHdpZHRofVwiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwieyRuYW1lfVwiIGlkPVwieyRpZH1cIiB7JHRhYmh0bWx9IHZhbHVlPVwieyRsYWJlbH1cIiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9idXR0b25fcHJpbnQoJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQoJCSRpZCA9ICRmaWVsZC0+aWQ7DQoJCSRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRhdHRyaWJ1dGUgPSAkZmllbGQtPmF0dHJpYnV0ZTsNCiAgICAgICAgJGF0dHJpYnV0ZXN0eWxlID0gJGZpZWxkLT5hdHRyaWJ1dGVzdHlsZTsNCiAgICAgICAgJGNvbmRpdGlvbmFsID0gJGZpZWxkLT5jb25kaXRpb25hbDsNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCiAgICAgICAgJGN1c3RvbV9jc3MgPSAkZmllbGQtPmN1c3RvbV9jc3M7IA0KICAgICAgICAkd2lkdGggPSAkZmllbGQtPmZpZWxkd2lkdGg7DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPmNyZWF0ZV9jdXN0b21fY3NzX2Jsb2NrKCRpZCwgJGN1c3RvbV9jc3MpOw0KDQogICAgICAgIA0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQogICAgICAgIA0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbCA9ICR0aGlzLT5fY3JlYXRlQ29uZGl0aW9uYWxFdmVudCgkY29uZGl0aW9uYWwsICRuYW1lLCAkaWQpOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9pbmxpbmUgPSAkY29uZGl0aW9uYWxfY2FsbFswXTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0ID0gJGNvbmRpdGlvbmFsX2NhbGxbMV07DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50ID0gIlxueyRjb25kaXRpb25hbF9jYWxsX3NjcmlwdH1cbiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGF0dHJpYnV0ZXN0eWxlID09ICIiKSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cInskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkY3VzdG9tX2Nzcy0+YWxsKSAmJiAkY3VzdG9tX2Nzcy0+YWxsICE9ICIiICYmICRjdXN0b21fY3NzLT5hbGwgIT0gJzxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT4nKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICAgICBwcmVnX21hdGNoX2FsbCgnL1sjLl1bYS16LUEtWjAtOV9dKy8nLCAoc3RyaW5nKSRjdXN0b21fY3NzLT5hbGwsICRtYXRjaGVzKTsgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzBdKSAmJiBpc3NldCgkbWF0Y2hlc1swXVswXSkgJiYgJG1hdGNoZXNbMF1bMF0gIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRfY3VzdG9tX3NlbGVjdG9yID0gJG1hdGNoZXNbMF1bMF07DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcuJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9IHN0cl9yZXBsYWNlKCcjJywgJycsICRfY3VzdG9tX3NlbGVjdG9yKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHdpZHRoLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSR3aWR0aCwgJ3B4Jyk7DQogICAgICAgICRjdDMgPSBzdWJzdHJfY291bnQoKHN0cmluZykkd2lkdGgsICclJyk7DQoNCiAgICAgICAgaWYgKHRyaW0oJHdpZHRoKSA9PSAiIikgew0KDQogICAgICAgICAgICAkd2lkdGggPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDAgJiYgJGN0MyA9PSAwKSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAncHg7JzsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHdpZHRoID0gJ3dpZHRoOicgLiAkd2lkdGggLiAnOyc7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIjxpbnB1dCBjbGFzcz1cIm5vbGFiZWwgYnRuIHskX2N1c3RvbV9zZWxlY3Rvcn0geyRleHRyYWNsYXNzbmFtZXN9XCIgc3R5bGU9XCJ7JHdpZHRofVwiIHR5cGU9XCJidXR0b25cIiBuYW1lPVwieyRuYW1lfVwiIGlkPVwieyRpZH1cIiB7JHRhYmh0bWx9IHZhbHVlPVwieyRsYWJlbH1cIiB7JGF0dHJpYnV0ZX0geyRpbmhlcml0c3R5bGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IG9uY2xpY2s9XCJ3aW5kb3cucHJpbnQoKTtcIiB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+IjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfYnV0dG9uX3NhdmUoJGZpZWxkLCAkcGFnZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+bGFiZWw7DQogICAgICAgICRuYW1lID0gJGZpZWxkLT5uYW1lOw0KICAgICAgICAkaWQgPSAkZmllbGQtPmlkOw0KICAgICAgICAkcmVhZG9ubHkgPSBpc3NldCgkZmllbGQtPnJlYWRvbmx5KSA/ICRmaWVsZC0+cmVhZG9ubHkgOiAwOw0KICAgICAgICAkZmllbGRlbmFibGVkID0gaXNzZXQoJGZpZWxkLT5maWVsZGVuYWJsZWQpID8gJGZpZWxkLT5maWVsZGVuYWJsZWQgOiAxOw0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICR0YWJpbmRleCA9ICRmaWVsZC0+dGFiaW5kZXg7DQogICAgICAgICRjdXN0b21fY3NzID0gJGZpZWxkLT5jdXN0b21fY3NzOyANCiAgICAgICAgJHdpZHRoID0gJGZpZWxkLT5maWVsZHdpZHRoOw0KDQogICAgICAgICR0YWJsZW1vZGUgPSAkcGFnZS0+dGFibGVtb2RlOw0KDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfY3VzdG9tX2Nzc19ibG9jaygkaWQsICRjdXN0b21fY3NzKTsNCg0KICAgICAgICANCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCA9ICJcbnskY29uZGl0aW9uYWxfY2FsbF9zY3JpcHR9XG4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGh9OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7XCI+Jm5ic3A7PC9kaXY+IjsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCRhdHRyaWJ1dGVzdHlsZSA9PSAiIikgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCJ7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJF9jdXN0b21fc2VsZWN0b3IgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGN1c3RvbV9jc3MtPmFsbCkgJiYgJGN1c3RvbV9jc3MtPmFsbCAhPSAiIiAmJiAkY3VzdG9tX2Nzcy0+YWxsICE9ICc8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwvc3R5bGU+Jykgew0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy9bIy5dW2Etei1BLVowLTlfXSsvJywgKHN0cmluZykkY3VzdG9tX2Nzcy0+YWxsLCAkbWF0Y2hlcyk7IA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1swXSkgJiYgaXNzZXQoJG1hdGNoZXNbMF1bMF0pICYmICRtYXRjaGVzWzBdWzBdICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAkX2N1c3RvbV9zZWxlY3RvciA9ICRtYXRjaGVzWzBdWzBdOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJF9jdXN0b21fc2VsZWN0b3IgPSBzdHJfcmVwbGFjZSgnLicsICcnLCAkX2N1c3RvbV9zZWxlY3Rvcik7DQogICAgICAgICAgICAgICAgJF9jdXN0b21fc2VsZWN0b3IgPSBzdHJfcmVwbGFjZSgnIycsICcnLCAkX2N1c3RvbV9zZWxlY3Rvcik7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KDQpmdW5jdGlvbiBmaW5pc2hfc2F2ZV97JG5hbWV9KCkgew0KCWFsZXJ0KCdGb3JtIERhdGEgU2F2ZWQuJyk7DQp9DQoNCmZ1bmN0aW9uIHNhdmVfeyRuYW1lfSgpIHsNCgkNCgkvLyBTaGFkZSBTY3JlZW4NCg0KCS8vIFByb2Nlc3MgRm9ybSBTdWJtaXNzaW9uLg0KCWFqYXgoJ3skcGFnZS0+Zm9ybS0+YWN0aW9ufScsIGZpbmlzaF9zYXZlX1NhdmUsIGFqYXguc2VyaWFsaXplKHRoaXMuZm9ybSksIG51bGwpOw0KDQp9DQoJCQkNCjwvc2NyaXB0Pg0KCQkNCkVPRjsNCg0KICAgICAgICANCg0KICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZXh0cmFjbGFzc25hbWUpICYmICRmaWVsZC0+ZXh0cmFjbGFzc25hbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAkZmllbGQtPmV4dHJhY2xhc3NuYW1lOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSR3aWR0aCwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkd2lkdGgsICdweCcpOw0KICAgICAgICAkY3QzID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHdpZHRoLCAnJScpOw0KDQogICAgICAgIGlmICh0cmltKCR3aWR0aCkgPT0gIiIpIHsNCg0KICAgICAgICAgICAgJHdpZHRoID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwICYmICRjdDMgPT0gMCkgew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJHdpZHRoIC4gJ3B4Oyc7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICR3aWR0aCA9ICd3aWR0aDonIC4gJHdpZHRoIC4gJzsnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRyZWFkb25seSkgPyAkcmVhZG9ubHkgPT0gMSA/ICIgcmVhZG9ubHkgIiA6ICIiIDogIiI7DQogICAgICAgICRlbmFibGVkID0gaXNzZXQoJGZpZWxkZW5hYmxlZCkgPyAkZmllbGRlbmFibGVkID09IDAgPyAiIGRpc2FibGVkICIgOiAiIiA6ICIiOw0KDQogICAgICAgICRlbGVtZW50IC49ICI8aW5wdXQgY2xhc3M9XCJub2xhYmVsIGJ0biB7JF9jdXN0b21fc2VsZWN0b3J9IHskZXh0cmFjbGFzc25hbWVzfVwiIHN0eWxlPVwieyR3aWR0aH1cIiB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgeyR0YWJodG1sfSB2YWx1ZT1cInskbGFiZWx9XCIgeyRhdHRyaWJ1dGV9IHskaW5oZXJpdHN0eWxlfSB7JGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lfSBvbmNsaWNrPVwic2F2ZV97JG5hbWV9KCk7XCIgeyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfaGlkZGVuKCRsYWJlbCwgJG5hbWUsICRpZCwgJGRlZmF1bHR2YWx1ZSkNCiAgICB7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICRkZWZhdWx0dmFsdWUgPSAoc3RyaW5nKSRkZWZhdWx0dmFsdWU7DQoNCg0KICAgICAgICANCiAgICAgICAgJGRlZmF1bHR2YWx1ZSA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRlZmF1bHR2YWx1ZSwgNik7DQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIHByZWdfbWF0Y2hfYWxsKCcvKF58LnxccnxcbikoI1x7KC4qPylcfSkvJywgJGRlZmF1bHR2YWx1ZSwgJG1hdGNoZXMpOw0KDQogICAgICAgICRhcnJheV92YXJzID0gYXJyYXkoKTsgDQogICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1szXSkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRtYXRjaGVzWzNdIGFzICRtKSB7DQogICAgICAgICAgICAgICAgJGFycmF5X3ZhcnNbXSA9ICInJG0nIjsgDQogICAgICAgICAgICAgICAgJGRlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCcjeycgLiAkbSAuICd9JywgIjw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ3FzJ11bXCJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119XCJdWyd7JG19J10pKSB7IGVjaG8gXCJ7XCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3skbX0nXX1cIjsgfT8+IiwgJGRlZmF1bHR2YWx1ZSk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRkeW5fdmFycyA9IGltcGxvZGUoJywnLCAkYXJyYXlfdmFycyk7IA0KDQogICAgICAgICRzZXBhcmF0b3IgPSAnLCAnOw0KICAgICAgICAkZWxlbWVudCA9IDw8PEVPVA0KXG48P3BocA0KaWYoIWlzc2V0KFwkYXJyYXlfdmFyc19wcm9jZXNzZWQpKXsgDQoJLy8gY2hlY2sgZm9yIGFuZCByZXBsYWNlIGFycmF5IGJhc2VkIHZhcmlhYmxlcyBpZiBub3QgYWxyZWFkeSBkb25lDQoJXCR2YXJzID0gYXJyYXkoeyRkeW5fdmFyc30pOw0KCWZvcmVhY2goXCR2YXJzIGFzIFwkdmFyKXsNCgkJaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdW1wkdmFyXSkpew0KCQkJaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdW1wkdmFyXSkpew0KCQkJCVwkZmllbGRfaXRlbXMgPSAnJzsNCgkJCQlmb3JlYWNoKFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVtcJHZhcl0gYXMgXCRrZXk9Plwkdil7DQoJCQkJCWlmKFwka2V5ICE9IDApeyBcJGZpZWxkX2l0ZW1zIC49ICd7JHNlcGFyYXRvcn0nOyB9DQoJCQkJCVwkZmllbGRfaXRlbXMgLj0gXCR2Ow0KCQkJCX0NCgkJCQlcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bXCR2YXJdID0gXCRmaWVsZF9pdGVtczsNCgkJCX0NCgkJfQ0KCX0NCglcJGFycmF5X3ZhcnNfcHJvY2Vzc2VkID0gdHJ1ZTsNCn0NCj8+DQoNCkVPVDsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSA8PDxFT1QNClxuPD9waHANCi8vIFByb2Nlc3MgQXJyYXkgVmFyaWFibGVzLg0KaWYoIWlzc2V0KFwkYXJyYXlfdmFyc19wcm9jZXNzZWQpKXsgXCR2YXJzID0gYXJyYXkoeyRkeW5fdmFyc30pOyBwcm9jZXNzX2FycmF5X3ZhcmlhYmxlcyhcJHZhcnMsICd7JHNlcGFyYXRvcn0nKTsgXCRhcnJheV92YXJzX3Byb2Nlc3NlZCA9IHRydWU7IH0NCj8+DQoJCQ0KRU9UOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwieyRuYW1lfVwiIGlkPVwieyRpZH1cIiB2YWx1ZT1cInskZGVmYXVsdHZhbHVlfVwiIC8+IjsNCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3NlbGVjdCgkaXRlbXNfYXJyYXksICRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KICAgICAgICAkbGFiZWwgPSAkZmllbGQtPmxhYmVsOw0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+eyJuYW1lIn07DQogICAgICAgICRpZCA9ICRmaWVsZC0+eyJpZCJ9Ow0KICAgICAgICAkZGF0YXNvdXJjZSA9ICRmaWVsZC0+eyJkYXRhc291cmNlIn07DQogICAgICAgICRzb3VyY2V0eXBlID0gJGZpZWxkLT57InNvdXJjZXR5cGUifTsNCiAgICAgICAgJHNvdXJjZXNxbCA9ICRmaWVsZC0+eyJzb3VyY2VzcWwifTsNCiAgICAgICAgJHNvdXJjZXNxbHBhcmFtcyA9ICRmaWVsZC0+eyJzb3VyY2VzcWxwYXJhbXMifTsNCiAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gJGZpZWxkLT5kYmRlZmF1bHRzZWxlY3R2YWx1ZTsNCiAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlID0gJGZpZWxkLT5iYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZTsNCiAgICAgICAgJGRiaG9zdCA9IChzdHJpbmcpJGZpZWxkLT5kYmhvc3Q7DQogICAgICAgICRkYnNjaGVtYSA9IChzdHJpbmcpJGZpZWxkLT5kYnNjaGVtYTsNCiAgICAgICAgJGRidXNlciA9IChzdHJpbmcpJGZpZWxkLT5kYnVzZXI7DQogICAgICAgICRkYnB3ZCA9IChzdHJpbmcpJGZpZWxkLT5kYnB3ZDsNCiAgICAgICAgJGRic29ja2V0ID0gKHN0cmluZykkZmllbGQtPmRic29ja2V0Ow0KICAgICAgICAkZGJwb3J0ID0gKHN0cmluZykkZmllbGQtPmRicG9ydDsNCiAgICAgICAgJGRiZHNuID0gKHN0cmluZykkZmllbGQtPmRiZHNuOw0KICAgICAgICAkY29ubmVjdG9yID0gKHN0cmluZykkZmllbGQtPmRiY29ubmVjdG9yOw0KICAgICAgICAkcmVxID0gJGZpZWxkLT52YWxpZGF0aW9uLT5yZXE7DQogICAgICAgICRmaWVsZHdpZHRoID0gJGZpZWxkLT5maWVsZHdpZHRoOw0KICAgICAgICAkY29sb3IgPSAkZmllbGQtPmNvbG9yOw0KICAgICAgICAkaW5wdXRfY29sb3IgPSAkZmllbGQtPmlucHV0X2NvbG9yOw0KICAgICAgICAkZm9udHNpemUgPSAkZmllbGQtPmZvbnRzaXplOw0KICAgICAgICAkbGFiZWxwb3MgPSAkZmllbGQtPmxhYmVscG9zOw0KICAgICAgICAkaW5oZXJpdHN0eWxlID0gJGZpZWxkLT5pbmhlcml0c3R5bGU7DQogICAgICAgICRoZWxwZXIgPSAkZmllbGQtPmhlbHBlcjsNCgkJJGhlbHBlcmNvbG9yID0gJGZpZWxkLT5oZWxwZXJjb2xvcjsNCgkJJHJlYWRvbmx5ID0gaXNzZXQoJGZpZWxkLT5yZWFkb25seSkgPyAkZmllbGQtPnJlYWRvbmx5IDogMDsNCiAgICAgICAgJGZpZWxkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRlbmFibGVkKSA/ICRmaWVsZC0+ZmllbGRlbmFibGVkIDogMTsNCiAgICAgICAgJGZpZWxkcG9wdWxhdGVkZWZhdWx0ID0gaXNzZXQoJGZpZWxkLT5maWVsZHBvcHVsYXRlZGVmYXVsdCkgPyAkZmllbGQtPmZpZWxkcG9wdWxhdGVkZWZhdWx0IDogMTsgDQogICAgICAgICRhdHRyaWJ1dGUgPSAkZmllbGQtPmF0dHJpYnV0ZTsNCiAgICAgICAgJGF0dHJpYnV0ZXN0eWxlID0gJGZpZWxkLT5hdHRyaWJ1dGVzdHlsZTsNCiAgICAgICAgJGRiZGVidWdsZXZlbCA9ICRmaWVsZC0+ZGJkZWJ1Z2xldmVsOw0KICAgICAgICAkY29uZGl0aW9uYWwgPSAkZmllbGQtPmNvbmRpdGlvbmFsOw0KICAgICAgICAkcmFuZ2VvcHRpb25zID0gJGZpZWxkLT5yYW5nZW9wdGlvbnM7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICRzZWxlY3RfbXVsdGlwbGUgPSAkZmllbGQtPnNlbGVjdF9tdWx0aXBsZTsNCiAgICAgICAgJHNlbGVjdF9zaXplID0gJGZpZWxkLT5zZWxlY3Rfc2l6ZTsNCiAgICAgICAgJHNlbGVjdF9mb3JjZV9ibGFuayA9ICRmaWVsZC0+c2VsZWN0X2ZvcmNlX2JsYW5rOyANCiAgICAgICAgJHNlbGVjdF9mb3JjZV9lbXB0eSA9ICRmaWVsZC0+c2VsZWN0X2ZvcmNlX2VtcHR5OyANCiAgICAgICAgJHRvb2x0aXAgPSAkZmllbGQtPnRvb2x0aXA7DQogICAgICAgICR0YWJpbmRleCA9ICRmaWVsZC0+dGFiaW5kZXg7DQoNCiAgICAgICAgDQogICAgICAgICR0aGlzLT51bS0+cHVsbEN1c3RvbUNvbm5lY3RvckZpbGUoKHN0cmluZykkZmllbGQtPmRiY29ubmVjdG9yKTsNCg0KICAgICAgICANCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGxhYmVsID09ICIiKSB7DQogICAgICAgICAgICAkbGFiZWwgPSAiJm5ic3A7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkYXJyYXlfYnJhY2UgPSAiIjsgDQoNCiAgICAgICAgaWYgKCFpc3NldCgkc2VsZWN0X211bHRpcGxlKSB8fCAoaW50KSRzZWxlY3RfbXVsdGlwbGUgPT0gIjAiIHx8IChzdHJpbmcpJHNlbGVjdF9tdWx0aXBsZSA9PSAiIikgew0KICAgICAgICAgICAgJHNlbGVjdF9tdWx0aXBsZSA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHNlbGVjdF9tdWx0aXBsZSA9ICJtdWx0aXBsZSI7DQogICAgICAgICAgICAkYXJyYXlfYnJhY2UgPSAiW10iOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCFpc3NldCgkc2VsZWN0X3NpemUpIHx8ICRzZWxlY3Rfc2l6ZSA9PSAiIikgew0KICAgICAgICAgICAgJHNlbGVjdF9zaXplID0gInNpemU9MSI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkc2VsZWN0X3NpemUgPSAic2l6ZT17JHNlbGVjdF9zaXplfSI7DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICAkdG9vbHRpcF9lbGVtZW50ID0gJHRoaXMtPnRyYW5zbGF0ZVRvb2x0aXAoJHRvb2x0aXAsICRpZCk7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF9jYWxsID0gJHRoaXMtPl9jcmVhdGVDb25kaXRpb25hbEV2ZW50KCRjb25kaXRpb25hbCwgJG5hbWUsICRpZCk7DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICRjb25kaXRpb25hbF9jYWxsWzBdOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAkY29uZGl0aW9uYWxfY2FsbFsxXTsNCg0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkc291cmNlc3FsID0gc3RyX3JlcGxhY2UoJyInLCAnXCInLCAkc291cmNlc3FsKTsNCg0KICAgICAgICANCiAgICAgICAgJHN0cnMgPSBleHBsb2RlKCcsJywgJHNvdXJjZXNxbHBhcmFtcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOw0KDQogICAgICAgICRwYXJhbXMgPSAnJHBhcmFtcyA9IGFycmF5KCc7DQoNCiAgICAgICAgDQogICAgICAgICRwYXJhbXMgLj0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRzb3VyY2VzcWxwYXJhbXMsIDQpOyANCg0KICAgICAgICAkcGFyYW1zIC49ICcpOyc7DQoNCiAgICAgICAgJGNhbGxfY29kZSA9ICJcJGRiaC0+c2V0TXlTUUxTU0xQcm9wZXJ0aWVzKFwkZGJfc3NsX2tleSwgXCRkYl9zc2xfY2VydGlmaWNhdGUsIFwkZGJfc3NsX2NhX2NlcnQsIFwkZGJfc3NsX3ZlcmlmeV9jZXJ0LCBcJGRiX3NzbF9jaXBoZXIpO1xyXG4iOw0KDQogICAgICAgICRjYWxsX2NvZGUgLj0gIlwkcmVzdWx0X3skbmFtZX0gPSBcJGRiaC0+cGRvX3Byb2NlZHVyZV9wYXJhbXMoXCRxdWVyeV9kZWJ1ZywgXCRzcWxfeyRuYW1lfSwgXCRkYl9ob3N0LCBcJGRiX3R5cGUsIFwkbXlzcWxfc29ja2V0LCBcJG15c3FsX3BvcnQsIFwkZGJkc24sIFwkZGJfdXNlciwgXCRkYl9wYXNzLCBcJGRiX2NhdGFsb2csIFwkcGFyYW1zLCAwLCAwKTsiOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoaXNfbnVtZXJpYygoc3RyaW5nKSRmaWVsZHdpZHRoKSA9PSB0cnVlKSB7DQogICAgICAgICAgICAkZmllbGR3aWR0aCA9ICRmaWVsZHdpZHRoIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAnODYlJzsNCiAgICAgICAgfQ0KDQogICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5maWVsZGhlaWdodCkgJiYgKHN0cmluZykkZmllbGQtPmZpZWxkaGVpZ2h0ICE9ICIxNiIgJiYgKHN0cmluZykkZmllbGQtPmZpZWxkaGVpZ2h0ICE9ICIiKSB7DQoNCiAgICAgICAgICAgIGlmIChpc19udW1lcmljKChzdHJpbmcpJGZpZWxkLT5maWVsZGhlaWdodCkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICdoZWlnaHQ6JyAuICRmaWVsZC0+ZmllbGRoZWlnaHQgLiAncHg7JzsgDQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgIGRpZTsNCiAgICAgICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAnaGVpZ2h0OicgLiAkZmllbGQtPmZpZWxkaGVpZ2h0IC4gJzsnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICR0ZXN0ID0gKGludCkkaW5oZXJpdHN0eWxlOw0KICAgICAgICBpZiAoJHRlc3QgIT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9IDA7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCRpbmhlcml0c3R5bGUgPT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCJmb250LXNpemU6eyRmb250c2l6ZX07IGNvbG9yOnskaW5wdXRfY29sb3J9OyBmb250LWZhbWlseTppbmhlcml0OyB3aWR0aDp7JGZpZWxkd2lkdGh9OyB7JGZpZWxkaGVpZ2h0fSB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCIgY29sb3I6eyRpbnB1dF9jb2xvcn07IHdpZHRoOnskZmllbGR3aWR0aH07IHskZmllbGRoZWlnaHR9IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KICAgICAgICAkZWxlbWVudCA9ICcnOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5sZWZ0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JGZpeGVkX3dpZHRofXB4OyBwYWRkaW5nLXRvcDozcHg7IG1hcmdpbi1yaWdodDo4cHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn1cIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJHJlcXVpcmVkX3RleHQgPSBpc3NldCgkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIpID8gJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyIDogIiYjNDI7IjsNCg0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+X2hlbHBlcl9maWVsZF9sYWJlbCgkZmllbGQsICRuYW1lLCAkcmVxLCAkcmVxdWlyZWRfdGV4dCwgJGNvbG9yLCAkZm9udHNpemUsICRzdHlsZXMsICRsYWJlbCwgJGxhYmVscG9zLCAoc3RyaW5nKSRmaWVsZC0+dHlwZSwgJHRvb2x0aXAsICcnLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbnskY29uZGl0aW9uYWxfY2FsbF9zY3JpcHR9XG4iOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgKHN0cmluZykkZmllbGQtPmJ1Y2tldCAhPSAnJykgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwiZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmV4dHJhY2xhc3NuYW1lKSAmJiAkZmllbGQtPmV4dHJhY2xhc3NuYW1lICE9ICIiKSB7DQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gJGZpZWxkLT5leHRyYWNsYXNzbmFtZTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+Y3JlYXRlX3RhYmxlX21vZGVfbW9iaWxlX2xhYmVsKCRmaWVsZCwkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZihpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgJGZpZWxkLT5idWNrZXQgIT0gIiIpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzIC49ICIgYnVja2V0LWNvbnRhaW5lZC1maWVsZCI7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICI8c2VsZWN0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiBjbGFzcz1cImZvcm0tY29udHJvbCB7JGV4dHJhY2xhc3NuYW1lc31cIiB7JHNlbGVjdF9tdWx0aXBsZX0gbmFtZT1cInskbmFtZX17JGFycmF5X2JyYWNlfVwiIGlkPVwieyRpZH1cIiB7JHRhYmh0bWx9IHskaW5oZXJpdHN0eWxlfSB7JGF0dHJpYnV0ZX0geyRjb25kaXRpb25hbF9jYWxsX2lubGluZX0geyRzZWxlY3Rfc2l6ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSA+IjsNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gJzw/cGhwICRfU0VTU0lPTlsnIC4gIiciIC4gJG5hbWUgLiAiJyIgLiAnXSA9IGlzc2V0KCRfU0VTU0lPTlsnIC4gIiciIC4gJG5hbWUgLiAiJyIgLiAnXSkgPyAkX1NFU1NJT05bJyAuICInIiAuICRuYW1lIC4gIiciIC4gJ10gOiAiIjsgPz4nIC4gIlxuIjsNCiAgICAgICAgJGVsZW1lbnQgLj0gJzw/cGhwIGlmKCFpc3NldCgkX1NFU1NJT05bJyAuICIneyRuYW1lfV9pcyciIC4gJ10pKSB7ICRfU0VTU0lPTlsnIC4gIid7JG5hbWV9X2lzJyIgLiAnXSA9IDE7IH0gPz4nOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlKSkgew0KICAgICAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlX29yaWdpbmFsID0gJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlOw0KICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWVfaGFzX3Rva2VuID0gJ2ZhbHNlJzsNCg0KICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlLCA0KTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICgkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPT0gJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlX29yaWdpbmFsKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUpOw0KDQogICAgICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPSAiJyIgLiAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgLiAiJyI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSA9ICIoIiAuICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSAuICIpIjsNCiAgICAgICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9oYXNfdG9rZW4gPSAndHJ1ZSc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlKSkgew0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9ICRmaWVsZC0+c2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWVfb3JpZ2luYWwgPSAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlOw0KDQogICAgICAgICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWUgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSwgNCk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9PSAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlX29yaWdpbmFsKSB7DQogICAgICAgICAgICAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlID0gIiciIC4gJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSAuICInIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9ICIoIiAuICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWUgLiAiKSI7DQogICAgICAgIH0NCg0KDQoNCg0KICAgICAgICANCiAgICAgICAgJG9wdGlvbl9pbmRleCA9IDA7DQoNCiAgICAgICAgDQogICAgICAgIGZvcmVhY2ggKCRpdGVtc19hcnJheSBhcyAka2V5ID0+ICR2YWwpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkdmFsLT52YWx1ZSA9IGh0bWxlbnRpdGllcygkdmFsLT52YWx1ZSwgRU5UX1FVT1RFUywgJ1VURi04Jyk7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCRvcHRpb25faW5kZXggPT0gMCAmJiBpc3NldCgkc2VsZWN0X2ZvcmNlX2JsYW5rKSAmJiAoaW50KSRzZWxlY3RfZm9yY2VfYmxhbmsgPT0gMSkgew0KICAgICAgICAgICAgICAgICR2YWwtPnZhbHVlID0gIiI7DQogICAgICAgICAgICAgICAgJHZhbC0+bmFtZSA9ICIiOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICgkb3B0aW9uX2luZGV4ID09IDAgJiYgaXNzZXQoJHNlbGVjdF9mb3JjZV9lbXB0eSkgJiYgKGludCkkc2VsZWN0X2ZvcmNlX2VtcHR5ID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICR2YWwtPnZhbHVlID0gIiI7DQoNCiAgICAgICAgICAgICAgICAkb3B0aW9uX2luZGV4Kys7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoc3Vic3RyX2NvdW50KCR2YWwtPnZhbHVlLCAiT1BUR1JPVVA9IikgIT0gMCkgew0KICAgICAgICAgICAgICAgICRvcHRncm91cGxhYmVsID0gZXhwbG9kZSgnPScsICR2YWwtPnZhbHVlKTsNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJG9wdGdyb3VwbGFiZWxbMV0pKSB7DQogICAgICAgICAgICAgICAgICAgICRvcHRncm91cGxhYmVsID0gJG9wdGdyb3VwbGFiZWxbMV07DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJG9wdGdyb3VwbGFiZWwgPSAiIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxvcHRncm91cCBsYWJlbD0neyRvcHRncm91cGxhYmVsfSc+IjsNCiAgICAgICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgaWYgKHN1YnN0cl9jb3VudCgkdmFsLT52YWx1ZSwgIk9QVEdST1VQIikgIT0gMCkgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8L29wdGdyb3VwPiI7DQogICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRvcHRpb25faW5kZXgrKzsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJHZhbC0+c2VsZWN0ZWQgPT0gMSkgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PERPQw0KDQo8b3B0aW9uIHZhbHVlPSJ7JHZhbC0+dmFsdWV9Ig0KCTw/cGhwDQoJaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsneyRuYW1lfSddKSl7DQoJCWlmKGluX2FycmF5KGh0bWxfZW50aXR5X2RlY29kZSgieyR2YWwtPnZhbHVlfSIpLCBcJF9TRVNTSU9OWyd7JG5hbWV9J10pIHx8IFwkX1NFU1NJT05bJ3skbmFtZX1faXMnXSA9PSAxKXsNCgkJCWVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOw0KCQl9DQoJfSBlbHNlIHsNCgkJaWYoXCRfU0VTU0lPTlsneyRuYW1lfSddID09IGh0bWxfZW50aXR5X2RlY29kZSgneyR2YWwtPnZhbHVlfScsIEVOVF9RVU9URVMpIHx8IFwkX1NFU1NJT05bJ3skbmFtZX1faXMnXSA9PSAxKSB7DQoJCQllY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsNCgkJfQ0KCX0NCgk/PiA+eyR2YWwtPm5hbWV9PC9vcHRpb24+DQpET0M7DQogICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgJGZpZWxkLT5idWNrZXQgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxET0MNCiA8b3B0aW9uIHZhbHVlPSJ7JHZhbC0+dmFsdWV9Ig0KCTw/cGhwDQoJaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsneyRuYW1lfSddKSl7DQoJCWlmKGluX2FycmF5KGh0bWxfZW50aXR5X2RlY29kZSgieyR2YWwtPnZhbHVlfSIpLCBcJF9TRVNTSU9OWyd7JG5hbWV9J10pKXsNCgkJCWVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOw0KCQl9DQoJfSBlbHNlIHsNCgkNCgkJXCR2YWwgPSB7JGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlfTsNCgkJXCRkeW5hbWljX2FycmF5ID0gZXhwbG9kZSgnfCcsIFwkdmFsKTsNCgkJDQoJCWlmKGlzX2FycmF5KFwkZHluYW1pY19hcnJheSkgJiYgY291bnQoXCRkeW5hbWljX2FycmF5KSA+IDEpew0KCQkJDQoJCQlpZihcJF9TRVNTSU9OWyd7JG5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlKCJ7JHZhbC0+dmFsdWV9IiwgRU5UX1FVT1RFUykgfHwgaW5fYXJyYXkoInskdmFsLT52YWx1ZX0iLCBcJGR5bmFtaWNfYXJyYXkpKSB7DQoJCQkJZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7DQoJCQl9DQoJCQkNCgkJfSBlbHNlIHsNCgkJDQoJCQlpZihcJF9TRVNTSU9OWyd7JG5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlKCJ7JHZhbC0+dmFsdWV9IiwgRU5UX1FVT1RFUykgfHwgInskdmFsLT52YWx1ZX0iID09IHskYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWV9KSB7DQoJCQkJZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7DQoJCQl9DQoJCQkNCgkJCWlmKFwkX1NFU1NJT05bJ3skbmFtZX0nXSA9PSBodG1sX2VudGl0eV9kZWNvZGUoInskdmFsLT52YWx1ZX0iLCBFTlRfUVVPVEVTKSB8fCAieyR2YWwtPnZhbHVlfSIgPT0geyRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWV9KSB7DQoJCQkJZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7DQoJCQl9DQoJCQkNCgkJfQ0KCQkNCgl9DQoJPz4gPnskdmFsLT5uYW1lfTwvb3B0aW9uPg0KRE9DOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRlc2NhcGVkX3ZhbCA9IHN0cl9yZXBsYWNlKCInIiwgIlwnIiwgJHZhbC0+dmFsdWUpOw0KDQogICAgICAgICAgICAgICAgICAgICRfdmFsX25hbWUgPSBzdHJfcmVwbGFjZSgiJyIsICJcJyIsICR2YWwtPm5hbWUpOyANCg0KICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxET0MNClxyXG48P3BocCBlY2hvIGNyZWF0ZV9zZWxlY3RfaXRlbSgneyRfdmFsX25hbWV9JywgJ3skZXNjYXBlZF92YWx9JywgJ3skbmFtZX0nLCB7JGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlfSwgeyRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWV9LCB7JGZpZWxkcG9wdWxhdGVkZWZhdWx0fSk7ICA/Pg0KRE9DOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKHN0cmluZykkcmFuZ2VvcHRpb25zLT5leHByZXNzaW9uICE9ICcnIHx8IChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+YXJyYXkgIT0gJycpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoc3Vic3RyX2NvdW50KChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+ZGVmYXVsdHZhbHVlLCAnJCcpID09IDEpIHsNCiAgICAgICAgICAgICAgICAkcmFuZ2VfZGVmYXVsdCA9ICRyYW5nZW9wdGlvbnMtPmRlZmF1bHR2YWx1ZTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHJhbmdlX2RlZmF1bHQgPSAiJyIgLiAkcmFuZ2VvcHRpb25zLT5kZWZhdWx0dmFsdWUgLiAiJyI7DQogICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+ZXhwcmVzc2lvbiAhPSAnJykgew0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9IDQo8P3BocA0KZm9yZWFjaCh7JHJhbmdlb3B0aW9ucy0+ZXhwcmVzc2lvbn0gYXMgXCRpKSB7ID8+DQo8b3B0aW9uIHZhbHVlPSI8P3BocCBlY2hvIFwkaTs/PiIgPD9waHAgaWYoXCRfU0VTU0lPTlsneyRuYW1lfSddID09IGh0bWxfZW50aXR5X2RlY29kZSgie1wkaX0iLCBFTlRfUVVPVEVTKSB8fCBcJGkgPT0geyRyYW5nZV9kZWZhdWx0fSkgeyA/PiBzZWxlY3RlZD0ic2VsZWN0ZWQiIDw/cGhwIH0gPz4+PD9waHAgZWNobyBcJGk7ID8+PC9vcHRpb24+Ow0KPD9waHAgfSA/Pg0KRU9IOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoKHN0cmluZykkcmFuZ2VvcHRpb25zLT5hcnJheSAhPSAnJykgew0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPSA0KPD9waHANCmZvcmVhY2goeyRyYW5nZW9wdGlvbnMtPmFycmF5fSBhcyBcJHQpIHsgDQoJaWYoaXNfYXJyYXkoXCR0KSl7DQoJCS8vIHR5cGljYWwgZGF0YWJhc2UgcXVlcnkgLT4gYXJyYXlbYXJyYXlbXSwgYXJyYXlbXV0NCgkJaWYoIWlzc2V0KFwkdFsxXSkgfHwgXCR0WzFdID09ICcnKSB7DQoJCQlcJGxhYmVsID0gXCR0WzBdOw0KCQkJXCR2YWx1ZSA9IFwkdFswXTsgDQoJCX0gZWxzZSB7DQoJCQlcJGxhYmVsID0gXCR0WzBdOw0KCQkJXCR2YWx1ZSA9IFwkdFsxXTsNCgkJfQ0KCX0gZWxzZSB7IC8vIHNpbXBsZSBhcnJheSAtPiBhcnJheVtuLG4sbl0NCgkJXCRsYWJlbCA9IFwkdDsNCgkJXCR2YWx1ZSA9IFwkdDsNCgl9DQo/Pg0KPG9wdGlvbiB2YWx1ZT0iPD9waHAgZWNobyBcJHZhbHVlOz8+IiA8P3BocCBpZihcJF9TRVNTSU9OWyd7JG5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlKCJ7XCR2YWx1ZX0iLCBFTlRfUVVPVEVTKSB8fCBcJHZhbHVlID09IHskcmFuZ2VfZGVmYXVsdH0pIHsgPz4gc2VsZWN0ZWQ9InNlbGVjdGVkIiA8P3BocCB9ID8+Pjw/cGhwIGVjaG8gXCRsYWJlbDsgPz48L29wdGlvbj47DQo8P3BocCB9ID8+DQpFT0g7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIGlmICgkZGF0YXNvdXJjZSAhPSAnMCcgJiYgJHNvdXJjZXNxbCAhPSAiIikgew0KDQogICAgICAgICAgICBpZiAoJGNvbm5lY3RvciAhPSAnJykgew0KICAgICAgICAgICAgICAgICRjb25uZWN0b3IgPSBzdHJfcmVwbGFjZSgnXFwnLCAnXFxcXCcsICRjb25uZWN0b3IpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCRkYmRlYnVnbGV2ZWwgPT0gJycpIHsNCiAgICAgICAgICAgICAgICAkZGJkZWJ1Z2xldmVsID0gJzAnOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYoaW50dmFsKCRkYmRlYnVnbGV2ZWwpID09IDEgfHwgaW50dmFsKCRkYmRlYnVnbGV2ZWwpID09IDIpew0KICAgICAgICAgICAgICAgICRkYmRlYnVnbGV2ZWwgPSAzOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRkYl90eXBlID0gJHRoaXMtPnVtLT50cmFuc2xhdGVTb3VyY2VUeXBlKChpbnQpJHNvdXJjZXR5cGUpOw0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCFpc3NldCgkZGJkZWZhdWx0c2VsZWN0dmFsdWUpKSB7DQogICAgICAgICAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlX29yaWdpbmFsID0gKHN0cmluZykkZGJkZWZhdWx0c2VsZWN0dmFsdWU7DQoNCiAgICAgICAgICAgICRkYmRlZmF1bHRzZWxlY3R2YWx1ZSA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZGJkZWZhdWx0c2VsZWN0dmFsdWUsIDQpOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCRkYmRlZmF1bHRzZWxlY3R2YWx1ZSA9PSAkZGJkZWZhdWx0c2VsZWN0dmFsdWVfb3JpZ2luYWwpIHsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRkYmRlZmF1bHRzZWxlY3R2YWx1ZSA9IHN0cl9yZXBsYWNlKCInIiwgIlwnIiwgJGRiZGVmYXVsdHNlbGVjdHZhbHVlKTsNCg0KICAgICAgICAgICAgICAgICRkYmRlZmF1bHRzZWxlY3R2YWx1ZSA9ICInIiAuICRkYmRlZmF1bHRzZWxlY3R2YWx1ZSAuICInIjsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gIigiIC4gJGRiZGVmYXVsdHNlbGVjdHZhbHVlIC4gIikiOw0KICAgICAgICAgICAgfQ0KDQoNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkb3JkZXJfbCA9IDA7DQogICAgICAgICAgICAkb3JkZXJfdiA9IDE7DQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPnBhcmFtZXRlcm9yZGVyKSAmJiAkZmllbGQtPnBhcmFtZXRlcm9yZGVyICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoKGludCkkZmllbGQtPnBhcmFtZXRlcm9yZGVyID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkb3JkZXJfbCA9IDE7DQogICAgICAgICAgICAgICAgICAgICRvcmRlcl92ID0gMDsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkZGJob3N0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGJob3N0LCA4KTsNCiAgICAgICAgICAgICRkYnVzZXIgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYnVzZXIsIDgpOw0KICAgICAgICAgICAgJGRicHdkID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGJwd2QsIDgpOw0KICAgICAgICAgICAgJGRic2NoZW1hID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGJzY2hlbWEsIDgpOw0KICAgICAgICAgICAgJGRicG9ydCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRicG9ydCwgOCk7DQogICAgICAgICAgICAkZGJkc24gPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYmRzbiwgOCk7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCjwhLS0gUG9wdWxhdGUgRmllbGQgU3RhcnQgeyRuYW1lfSAtLT4NCjw/cGhwDQovLyBQZXJmb3JtIFNxbCBRdWVyeSBGb3IgeyRuYW1lfQ0KDQpcJHF1ZXJ5X2RlYnVnID0geyRkYmRlYnVnbGV2ZWx9OyAvLyBEZWZhdWx0IDAsIENoYW5nZSB0byAzIFRvIFNlZSBEZWJ1ZyBNZXNzYWdlcy4NCg0KXCRkYl9zY2hlbWFfY2hlY2sgPSAneyRkYnNjaGVtYX0nOw0KDQpcJGRiX2Rzbl90ZXN0ID0gJ3skZGJkc259JzsNCg0KaWYoXCRkYl9zY2hlbWFfY2hlY2sgIT0gJycgfHwgXCRkYl9kc25fdGVzdCAhPSAnJyl7DQoJXCRkYl9ob3N0ID0gInskZGJob3N0fSI7DQoJXCRkYl90eXBlID0gInskZGJfdHlwZX0iOw0KCVwkZGJfdXNlciA9ICJ7JGRidXNlcn0iOw0KCVwkZGJfcGFzcyA9ICJ7JGRicHdkfSI7DQoJXCRkYl9jYXRhbG9nID0gInskZGJzY2hlbWF9IjsNCglcJG15c3FsX3NvY2tldCA9ICJ7JGRic29ja2V0fSI7DQoJXCRteXNxbF9wb3J0ID0gInskZGJwb3J0fSI7DQoJXCRkYmRzbiA9ICJ7JGRiZHNufSI7DQp9IGVsc2Ugew0KCXVuc2V0KFwkZGJfY2F0YWxvZyk7DQp9DQoNClwkZGJfc3NsX2tleSA9ICd7JGZpZWxkLT5kYnNzbGtleX0nOw0KXCRkYl9zc2xfY2VydGlmaWNhdGUgPSAneyRmaWVsZC0+ZGJzc2xjZXJ0aWZpY2F0ZX0nOw0KXCRkYl9zc2xfY2FfY2VydCA9ICd7JGZpZWxkLT5kYnNzbGNhY2VydH0nOw0KXCRkYl9zc2xfdmVyaWZ5X2NlcnQgPSAneyRmaWVsZC0+ZGJzc2x2ZXJpZnljZXJ0fSc7DQpcJGRiX3NzbF9jaXBoZXIgPSAneyRmaWVsZC0+ZGJzc2xjaXBoZXJ9JzsNCg0KQGluY2x1ZGUgIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfURhdGFiYXNlLnBocCI7DQoNCi8vIG9wdGlvbmFsIGNvbm5lY3RvciBzY3JpcHQNCmlmKGZpbGVfZXhpc3RzKCJ7XCRfU0VTU0lPTlsnTUFYX1BBVEgnXX17JGNvbm5lY3Rvcn0iKSl7DQoJQGluY2x1ZGUgIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfXskY29ubmVjdG9yfSI7DQp9DQoNCi8vIFN0YXJ0IFNlbGVjdCBJdGVtIFF1ZXJ5Lg0KXCRzcWxfeyRuYW1lfSA9ICJ7JHNvdXJjZXNxbH0iOw0KXCRkYmggPSBuZXcgRGF0YWJhc2UoKTsNCnskcGFyYW1zfQ0KeyRjYWxsX2NvZGV9DQoNCi8vIENyZWF0ZSBvdXIgc2VsZWN0IGl0ZW0uDQppZihjb3VudChcJHJlc3VsdF97JG5hbWV9KSAhPSAwKXsgDQoJZm9yZWFjaCAoXCRyZXN1bHRfeyRuYW1lfSBhcyBcJHQpeyBpZighaXNzZXQoXCR0W3skb3JkZXJfdn1dKSB8fCBcJHRbeyRvcmRlcl92fV0gPT0gJycpIHsgXCR2YWx1ZSA9IFwkdFt7JG9yZGVyX2x9XTsgfSBlbHNlIHsgXCR2YWx1ZSA9IFwkdFt7JG9yZGVyX3Z9XTsgfSA/Pg0KCTxvcHRpb24gdmFsdWU9Ijw/cGhwIGVjaG8gaHRtbGVudGl0aWVzKFwkdmFsdWUpOyA/PiI8P3BocCANCglpZihpc3NldChcJF9TRVNTSU9OWyd7JG5hbWV9J10pICYmIGlzX2FycmF5KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkpew0KCQlpZihpbl9hcnJheShodG1sX2VudGl0eV9kZWNvZGUoIiIpLCBcJF9TRVNTSU9OWyd7JG5hbWV9J10pKXsNCgkJCWVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOw0KCQl9DQoJfSBlbHNlIHsNCgkJXCR2YWwgPSB7JGRiZGVmYXVsdHNlbGVjdHZhbHVlfTsNCgkJXCRkeW5hbWljX2FycmF5ID0gZXhwbG9kZSgnfCcsIFwkdmFsKTsNCgkJaWYoaXNfYXJyYXkoXCRkeW5hbWljX2FycmF5KSAmJiBjb3VudChcJGR5bmFtaWNfYXJyYXkpID4gMSl7DQoJCQlpZihpc3NldChcJF9TRVNTSU9OWyd7JG5hbWV9J10pICYmIFwkX1NFU1NJT05bJ3skbmFtZX0nXSA9PSBodG1sX2VudGl0eV9kZWNvZGUoXCR2YWx1ZSwgRU5UX1FVT1RFUykgfHwgaW5fYXJyYXkoaHRtbF9lbnRpdHlfZGVjb2RlKFwkdmFsdWUsIEVOVF9RVU9URVMpLCBcJGR5bmFtaWNfYXJyYXkpKSB7DQoJCQkJZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7DQoJCQl9DQoJCX0gZWxzZSB7DQoJCQlpZihpc3NldChcJF9TRVNTSU9OWyd7JG5hbWV9J10pICYmIFwkX1NFU1NJT05bJ3skbmFtZX0nXSA9PSBodG1sX2VudGl0eV9kZWNvZGUoXCR2YWx1ZSwgRU5UX1FVT1RFUykgfHwgaHRtbF9lbnRpdHlfZGVjb2RlKFwkdmFsdWUsIEVOVF9RVU9URVMpID09IHskZGJkZWZhdWx0c2VsZWN0dmFsdWV9KSB7DQoJCQkJZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7DQoJCQl9CQ0KCQl9DQoJfT8+Pjw/cGhwIGVjaG8gaHRtbGVudGl0aWVzKFwkdFt7JG9yZGVyX2x9XSk7ID8+PC9vcHRpb24+DQo8P3BocCB9IH0gLy8gRW5kIFNxbCBRdWVyeSBGb3IgeyRuYW1lfS4gPz4NCjwhLS0gUG9wdWxhdGUgRmllbGQgRW5kIHskbmFtZX0gLS0+DQoNCkVPVDsNCiAgICAgICAgfSANCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgaWYoaXNzZXQoJGZpZWxkLT53ZWJzZXJ2aWNlX3VybCkgJiYgKHN0cmluZykkZmllbGQtPndlYnNlcnZpY2VfdXJsICE9ICIiKXsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkY3VybF9wb3N0X3BhcmFtZXRlcnMgPSAiIjsNCg0KICAgICAgICAgICAgJGN1cmxfZ2V0X3BhcmFtZXRlcnMgPSAiIjsNCg0KICAgICAgICAgICAgaWYoaXNzZXQoJGZpZWxkLT53ZWJzZXJ2aWNlX3F1ZXJ5X3BhcmFtZXRlcnMpICYmICRmaWVsZC0+d2Vic2VydmljZV9xdWVyeV9wYXJhbWV0ZXJzICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRwYXJhbV9hcnJheSA9IGFycmF5KCk7DQoNCiAgICAgICAgICAgICAgICBmb3JlYWNoICgkZmllbGQtPndlYnNlcnZpY2VfcXVlcnlfcGFyYW1ldGVycyBhcyAka2V5ID0+ICR2YWwpIHsNCg0KICAgICAgICAgICAgICAgICAgICAka2V5ID0gKHN0cmluZykkdmFsLT5rZXk7DQoNCiAgICAgICAgICAgICAgICAgICAgJHZhbHVlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSR2YWwtPnZhbHVlLCAxKTsNCg0KICAgICAgICAgICAgICAgICAgICAkcGFyYW1fYXJyYXlbInska2V5fSJdID0gJHZhbHVlOyANCg0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRxdWVyeV9zdHJpbmcgPSBodHRwX2J1aWxkX3F1ZXJ5KCRwYXJhbV9hcnJheSk7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRxdWVyeV9zdHJpbmcgPSBzdHJfcmVwbGFjZSgnJTdCJywgJ3snLCAkcXVlcnlfc3RyaW5nKTsNCiAgICAgICAgICAgICAgICAkcXVlcnlfc3RyaW5nID0gc3RyX3JlcGxhY2UoJyU3RCcsICd9JywgJHF1ZXJ5X3N0cmluZyk7DQoNCiAgICAgICAgICAgICAgICAkcXVlcnlfc3RyaW5nID0gc3RyX3JlcGxhY2UoJyUyNCcsICckJywgJHF1ZXJ5X3N0cmluZyk7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmKChpbnQpJGZpZWxkLT53ZWJzZXJ2aWNlX21ldGhvZCA9PSAwKXsNCg0KICAgICAgICAgICAgICAgICAgICAkY3VybF9wb3N0X3BhcmFtZXRlcnMgPSAiY3VybF9zZXRvcHQoXCRjaCwgQ1VSTE9QVF9QT1NURklFTERTLCBcInskcXVlcnlfc3RyaW5nfVwiKTsiOw0KDQogICAgICAgICAgICAgICAgfSBlbHNlIGlmKChpbnQpJGZpZWxkLT53ZWJzZXJ2aWNlX21ldGhvZCA9PSAxKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGN1cmxfZ2V0X3BhcmFtZXRlcnMgPSAieyRxdWVyeV9zdHJpbmd9IjsNCg0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRjdXJsX2hlYWRlciA9ICIiOw0KDQogICAgICAgICAgICBpZihpc3NldCgkZmllbGQtPndlYnNlcnZpY2VfaGVhZGVycykgJiYgJGZpZWxkLT53ZWJzZXJ2aWNlX2hlYWRlcnMgIT0gIiIpIHsNCgkJCQkNCiAgICAgICAgICAgICAgICAkY3VybF9oZWFkZXIgPSAiXG5cdC8vIEN1c3RvbSBjVVJMIEhlYWRlcihzKVxuIjsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGhlYWRlcl9lbGVtZW50cyA9ICcnOw0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRmaWVsZC0+d2Vic2VydmljZV9oZWFkZXJzIGFzICRrZXkgPT4gJHZhbCkgew0KDQogICAgICAgICAgICAgICAgICAgICRrID0gKHN0cmluZykkdmFsLT5rZXk7DQogICAgICAgICAgICAgICAgICAgICR2ID0gKHN0cmluZykkdmFsLT52YWx1ZTsNCg0KICAgICAgICAgICAgICAgICAgICBpZigkayAhPSAiIiAmJiAkdiAhPSAiIil7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCRoZWFkZXJfZWxlbWVudHMgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoZWFkZXJfZWxlbWVudHMgLj0gIixcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkaGVhZGVyX2VsZW1lbnRzIC49ICJcdFx0J3ska306eyR2fSciOw0KDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjdXJsX2hlYWRlciAuPSAiXG5cdFwkaGVhZGVycyA9IGFycmF5KFxuIjsNCg0KICAgICAgICAgICAgICAgICRjdXJsX2hlYWRlciAuPSAiJHtoZWFkZXJfZWxlbWVudHN9IjsNCg0KICAgICAgICAgICAgICAgICRjdXJsX2hlYWRlciAuPSAiXG5cdCk7XG4iOw0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjdXJsX2hlYWRlciAuPSAiXG5cdGN1cmxfc2V0b3B0KFwkY2gsIENVUkxPUFRfSFRUUEhFQURFUiwgXCRoZWFkZXJzKTtcbiI7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjdXJsX2hlYWRlciAuPSAiXG5cdC8vIEVuZCBDdXN0b20gY1VSTCBIZWFkZXIocylcbiI7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkbWV0aG9kID0gKGludCkkZmllbGQtPndlYnNlcnZpY2VfbWV0aG9kID09IDAgPyAnY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1BPU1QsIHRydWUpOycgOiAnJzsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KJGh0dHBfcmVxdWVzdF9jb2RlID0gPDw8RU9GDQoNCi8vDQovLyBQdWxsIERhdGEgRnJvbSBXZWIgU2VydmljZS4NCi8vDQoNCnRyeSB7DQoNCiAgICBcJGNvbmZpcm1faHR0cF9jdXJsX3Nob3dfZGVidWcgPSBmYWxzZTsNCg0KICAgIC8vIEdldCB0aGUgY3VybCBzZXNzaW9uIG9iamVjdC4NCg0KICAgIFwkY2ggPSBjdXJsX2luaXQoInskZmllbGQtPndlYnNlcnZpY2VfdXJsfT97JGN1cmxfZ2V0X3BhcmFtZXRlcnN9Iik7DQogICAgDQogICAgXCRodHRwQWdlbnQgPSAiTW96aWxsYS81LjAgKFdpbmRvd3M7IFU7IFdpbmRvd3MgTlQgNS4xOyBlbi1VUzsgcnY6MS44LjEuOSkgR2Vja28vMjAwNzEwMjUgRmlyZWZveC8yLjAuMC45IjsNCg0KICAgIC8vIFNldCB0aGUgR0VUIG9wdGlvbnMuIEZ1bGwgbGlzdCBhdDogaHR0cDovL3VzMi5waHAubmV0L21hbnVhbC9lbi9mdW5jdGlvbi5jdXJsLXNldG9wdC5waHANCg0KICAgIGN1cmxfc2V0b3B0KFwkY2gsIENVUkxPUFRfVVNFUkFHRU5ULCBcJGh0dHBBZ2VudCk7DQogICAgY3VybF9zZXRvcHQoXCRjaCwgQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUiwgdHJ1ZSk7DQogICAgY3VybF9zZXRvcHQoXCRjaCwgQ1VSTE9QVF9GUkVTSF9DT05ORUNULCBUUlVFKTsNCiAgICBjdXJsX3NldG9wdChcJGNoLCBDVVJMT1BUX1NTTF9WRVJJRllQRUVSLCAwKTsgLy8gc2V0IHRvIGZhbHNlICgwKSBmb3IgbW9zdCB1c2VzLCBhcyB3ZSB3b24ndCBoYXZlIHZhbGlkIGNlcnQgZmlsZXMNCiAgICBjdXJsX3NldG9wdChcJGNoLCBDVVJMT1BUX1NTTF9WRVJJRllIT1NULCAyKTsNCiAgICB7JG1ldGhvZH0NCiAgICBjdXJsX3NldG9wdChcJGNoLCBDVVJMT1BUX0NBUEFUSCwgIi4vc2VjdXJpdHkvY1VSTC9jYWNlcnQucGVtIik7DQogICAgDQogICAgeyRjdXJsX2hlYWRlcn0NCg0KICAgIHskY3VybF9wb3N0X3BhcmFtZXRlcnN9DQogICAgDQogICAgLy8gUXVlcnkgQW5kIFJldHVybiBSZXNwb25zZS4NCg0KICAgIFwkcmVzcG9uc2UgPSBjdXJsX2V4ZWMoXCRjaCk7DQoNCiAgICBpZiAoXCRyZXNwb25zZSA9PSBmYWxzZSl7DQoNCiAgICAgICAgaWYoXCRjb25maXJtX2h0dHBfY3VybF9zaG93X2RlYnVnKXsNCiAgICAgICAgICAgIGVjaG8gY3VybF9lcnJvcihcJGNoKTsNCiAgICAgICAgICAgIGVjaG8gY3VybF9lcnJubyhcJGNoKTsNCiAgICAgICAgICAgIGVjaG8gIjwvc2VsZWN0PjxwcmU+IjsgcHJpbnRfcihjdXJsX2dldGluZm8oXCRjaCkpOyBlY2hvICI8L3ByZT4iOw0KICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbihjdXJsX2Vycm9yKFwkY2gpLCBjdXJsX2Vycm5vKFwkY2gpKTsNCiAgICAgICAgfQ0KDQogICAgICAgIGN1cmxfY2xvc2UoXCRjaCk7DQoNCiAgICB9IGVsc2Ugew0KICAgIA0KICAgICAgICAvLyBQcm9jZXNzIFJlc3VsdC4NCg0KICAgICAgICBjdXJsX2Nsb3NlKFwkY2gpOw0KDQogICAgICAgIGlmKFwkcmVzcG9uc2UgIT0gIiIpew0KDQogICAgICAgICAgICAvLyBJZiBYTUwsIEZpcnN0IENvbnZlcnQgVG8gSlNPTi4NCg0KICAgICAgICAgICAgaWYoc2ltcGxleG1sX2xvYWRfc3RyaW5nKFwkcmVzcG9uc2UpKXsNCg0KICAgICAgICAgICAgICAgIFwkeG1sID0gc2ltcGxleG1sX2xvYWRfc3RyaW5nKFwkcmVzcG9uc2UpOw0KDQogICAgICAgICAgICAgICAgXCRyZXNwb25zZSA9IGpzb25fZW5jb2RlKFwkeG1sKTsNCg0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZihqc29uX2RlY29kZShcJHJlc3BvbnNlKSl7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgLy8gUHJvY2VzcyBKU09ODQoNCiAgICAgICAgICAgICAgICBcJHJlc3BvbnNlID0gc3RyX3JlcGxhY2UoJ1xcclxcbicsICcnLCBcJHJlc3BvbnNlKTsNCiAgICAgICAgICAgICAgICBcJHJlc3BvbnNlID0gc3RyX3JlcGxhY2UoJ1wiJywgJyInLCBcJHJlc3BvbnNlKTsNCiAgICAgICAgICAgICAgICBcJHJlc3BvbnNlID0gc3RyX3JlcGxhY2UoJyJbJywgJ1snLCBcJHJlc3BvbnNlKTsNCiAgICAgICAgICAgICAgICBcJHJlc3BvbnNlID0gc3RyX3JlcGxhY2UoJ10iJywgJ10nLCBcJHJlc3BvbnNlKTsNCg0KICAgICAgICAgICAgICAgIFwkZGVidWdfcmF3ID0gZmFsc2U7DQoNCiAgICAgICAgICAgICAgICBpZihcJGRlYnVnX3Jhdyl7DQoNCiAgICAgICAgICAgICAgICAgICAgZWNobyAnPC9zZWxlY3Q+PHByZT5XZWIgU2VydmljZSBEZWJ1ZyBGb3IgVGhlIGA8c3Ryb25nPnskZmllbGQtPm5hbWV9PC9zdHJvbmc+YCBGaWVsZC48L3ByZT4nOw0KDQogICAgICAgICAgICAgICAgICAgIGVjaG8gIjxwcmU+UmF3IFJlc3BvbnNlOlxcclxcbiI7IHZhcl9kdW1wKCBcJHJlc3BvbnNlICk7IGVjaG8gJzwvcHJlPic7DQoNCiAgICAgICAgICAgICAgICAgICAgXCRqc29uID0ganNvbl9kZWNvZGUoXCRyZXNwb25zZSwgdHJ1ZSk7DQoNCiAgICAgICAgICAgICAgICAgICAgZWNobyAiPHByZT5EZWNvZGVkIEpTT046XFxyXFxuIjsgdmFyX2R1bXAoIFwkanNvbiApOyBlY2hvICc8L3ByZT4nOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIFwkanNvbkl0ZXJhdG9yID0gbmV3IFJlY3Vyc2l2ZUl0ZXJhdG9ySXRlcmF0b3IoDQogICAgICAgICAgICAgICAgICAgIG5ldyBSZWN1cnNpdmVBcnJheUl0ZXJhdG9yKGpzb25fZGVjb2RlKFwkcmVzcG9uc2UsIFRSVUUpKSwNCiAgICAgICAgICAgICAgICAgICAgUmVjdXJzaXZlSXRlcmF0b3JJdGVyYXRvcjo6U0VMRl9GSVJTVCk7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgZm9yZWFjaCAoXCRqc29uSXRlcmF0b3IgYXMgXCRrZXkgPT4gXCR2YWwpIHsNCg0KICAgICAgICAgICAgICAgICAgICAvLyBTZWxlY3RlZCBTdGF0dXMuDQoNCiAgICAgICAgICAgICAgICAgICAgXCRzZWxlY3RlZCA9ICIiOw0KDQogICAgICAgICAgICAgICAgICAgIGlmKGlzX2FycmF5KFwkdmFsKSkgew0KDQogICAgICAgICAgICAgICAgICAgICAgICAvL2VjaG8gIlwka2V5OiI7DQoNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgaWYoXCRfU0VTU0lPTlsneyRuYW1lfSddID09IGh0bWxfZW50aXR5X2RlY29kZShcJHZhbCwgRU5UX1FVT1RFUykgKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgXCRzZWxlY3RlZCA9ICdzZWxlY3RlZD1cInNlbGVjdGVkXCInOw0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICBpZihnZXR0eXBlKFwkdmFsKSA9PSAiYm9vbGVhbiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwkdmFsID0gdmFyX2V4cG9ydChcJHZhbCwgdHJ1ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGVjaG8gIjxvcHRpb24gdmFsdWU9XCJ7XCR2YWx9XCI+e1wka2V5fTwvb3B0aW9uPiI7DQoNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgfSANCg0KICAgICAgICB9DQoNCiAgICAgICAgaWYoXCRjb25maXJtX2h0dHBfY3VybF9zaG93X2RlYnVnKXsNCg0KICAgICAgICAgICAgZWNobyAiPC9zZWxlY3Q+PGJyLz48YnIvPlxuPHByZT5jVVJMIERlYnVnIEZvcjogeyRmaWVsZC0+d2Vic2VydmljZV91cmx9XG4iOyBwcmludF9yKGN1cmxfZ2V0aW5mbyhcJGNoKSk7IGVjaG8gIjwvcHJlPiI7DQogICAgICAgIA0KICAgICAgICB9DQogICAgDQogICAgfQ0KDQp9IGNhdGNoKEV4Y2VwdGlvbiBcJGUpIHsNCg0KICAgIC8vIFVuY29tbWVudCBuZXh0IGxpbmUgdG8gc2hvdyBjVVJMIGVycm9ycy4gDQoNCiAgICAvL3RyaWdnZXJfZXJyb3Ioc3ByaW50ZignPC9zZWxlY3Q+Q3VybCBmYWlsZWQgd2l0aCBlcnJvciAjJWQ6ICVzJywgXCRlLT5nZXRDb2RlKCksIFwkZS0+Z2V0TWVzc2FnZSgpKSwgRV9VU0VSX0VSUk9SKTsNCg0KfQ0KRU9GOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cbjw/cGhwXG4iIC4gJGh0dHBfcmVxdWVzdF9jb2RlIC4gIlxuPz5cbiI7DQoNCiAgICAgICAgfSANCg0KDQogICAgICAgICRlbGVtZW50IC49ICJcbjwvc2VsZWN0PlxuIjsNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmJ0b29sdGlwLXskaWR9IGZidG9vbHRpcFwiIHN0eWxlPVwiZGlzcGxheTpub25lO1wiPnskdG9vbHRpcF9lbGVtZW50LT50ZXh0fTwvZGl2PlxuIjsNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRvb2x0aXBfZWxlbWVudC0+anM7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGhlbHBlciAhPSAnJykgew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48YnIvPjxkaXYgY2xhc3M9XCJoZWxwZXJcIiBzdHlsZT1cImNvbG9yOnskaGVscGVyY29sb3J9O1wiPnskaGVscGVyfTwvZGl2PlxuIjsNCg0KICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48YnIgLz5cbiI7DQoNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQoNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICAgICAgDQogICAgfSANCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9tdWx0aXNlbGVjdCgkaXRlbXNfYXJyYXksICRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlLCAkanNsaWJyYXJ5KQ0KICAgIHsNCiAgICAgICAgaWYoJGJ1Y2tldF9ub2RlID09IG51bGwpew0KICAgICAgICAgICAgJGJ1Y2tldF9ub2RlID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICAkbGFiZWwgPSAkZmllbGQtPmxhYmVsOw0KICAgICAgICAkbGFiZWxwb3MgPSAkZmllbGQtPmxhYmVscG9zOw0KICAgICAgICAkaW5saW5lX2xhYmVsX3BvcyA9ICR0aGlzLT5nZXRfaW5saW5lX2xhYmVsX3BvcygkZmllbGQtPmxhYmVscG9zKTsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQogICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7IA0KDQogICAgICAgICRyZXEgPSAkZmllbGQtPnZhbGlkYXRpb24tPnJlcTsNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT5jb2xvcjsNCgkJJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCgkJDQoJCSRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgIA0KICAgICAgICAkZmllbGRwb3B1bGF0ZWRlZmF1bHQgPSBpc3NldCgkZmllbGQtPmZpZWxkcG9wdWxhdGVkZWZhdWx0KSA/ICRmaWVsZC0+ZmllbGRwb3B1bGF0ZWRlZmF1bHQgOiAxOyANCg0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQoNCiAgICAgICAgJG9wdGlvbmZvbnRzaXplID0gJGZpZWxkLT5vcHRpb25mb250c2l6ZTsgDQogICAgICAgICRvcHRpb25mb250d2VpZ2h0ID0gJGZpZWxkLT5zdHlsZS0+b3B0aW9uZm9udHdlaWdodDsNCg0KICAgICAgICAkaW5wdXRfY29sb3IgPSAkZmllbGQtPmlucHV0X2NvbG9yOw0KDQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsgDQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQoNCiAgICAgICAgJGRhdGFzb3VyY2UgPSAkZmllbGQtPmRhdGFzb3VyY2U7DQogICAgICAgICRzb3VyY2V0eXBlID0gJGZpZWxkLT5zb3VyY2V0eXBlOw0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRzb3VyY2VzcWwgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+c291cmNlc3FsLCAxKTsNCiAgICAgICAgDQogICAgICAgICRzb3VyY2VzcWwgPSBzdHJfcmVwbGFjZSgnIicsICdcIicsICRzb3VyY2VzcWwpOyANCg0KICAgICAgICAkdG9vbHRpcCA9ICRmaWVsZC0+dG9vbHRpcDsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPmRiZGVmYXVsdHNlbGVjdHZhbHVlKSkgew0KICAgICAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkZGJkZWZhdWx0c2VsZWN0dmFsdWUgPSAkZmllbGQtPmRiZGVmYXVsdHNlbGVjdHZhbHVlOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkLT5iYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSkpIHsNCiAgICAgICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlID0gJGZpZWxkLT5iYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+c2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlKSkgew0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9ICRmaWVsZC0+c2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGRiaG9zdCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGZpZWxkLT5kYmhvc3QsIDgpOw0KICAgICAgICAkZGJzb2NrZXQgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJzb2NrZXQsIDgpOw0KICAgICAgICAkZGJwb3J0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGQtPmRicG9ydCwgOCk7DQoNCiAgICAgICAgJGRidXNlciA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGZpZWxkLT5kYnVzZXIsIDgpOw0KICAgICAgICAkZGJwd2QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJwd2QsIDgpOw0KICAgICAgICAkZGJzY2hlbWEgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRmaWVsZC0+ZGJzY2hlbWEsIDgpOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZC0+ZGJkc24pKSB7DQogICAgICAgICAgICAkZmllbGQtPmRiZHNuID0gIiI7DQogICAgICAgIH0NCiAgICAgICAgJGRiZHNuID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGQtPmRiZHNuLCA4KTsNCg0KICAgICAgICAkY29ubmVjdG9yID0gJGZpZWxkLT5jb25uZWN0b3I7DQogICAgICAgICRkYmRlYnVnbGV2ZWwgPSAkZmllbGQtPmRiZGVidWdsZXZlbDsNCg0KICAgICAgICAkc2VsZWN0X3VzZV9ib29sZWFuID0gJGZpZWxkLT5zZWxlY3RfdXNlX2Jvb2xlYW47DQogICAgICAgICRyb3djb3VudCA9ICRmaWVsZC0+cm93Y291bnQ7DQoNCiAgICAgICAgJGNvbHVtbndpZHRoID0gJGZpZWxkLT5jb2x1bW53aWR0aDsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoY3R5cGVfZGlnaXQoKHN0cmluZykkY29sdW1ud2lkdGgpKSB7DQogICAgICAgICAgICAkY29sdW1ud2lkdGggPSAieyRjb2x1bW53aWR0aH1weDsgIjsgDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkY29sdW1ud2lkdGggPSAieyRjb2x1bW53aWR0aH07ICI7IA0KICAgICAgICB9DQoNCiAgICAgICAgJHJhbmdlb3B0aW9ucyA9ICRmaWVsZC0+cmFuZ2VvcHRpb25zOw0KDQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQoNCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkZmllbGQtPnN0eWxlKTsNCg0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KDQogICAgICAgIA0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRsYWJlbF9tYXJnaW4gPSAiIjsNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGluaGVyaXRzdHlsZSA9PSAxKSB7DQoNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiZm9udC1zaXplOnskZm9udHNpemV9OyBjb2xvcjp7JGNvbG9yfTsgZm9udC1mYW1pbHk6aW5oZXJpdDsgeyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJG9wdGlvbmZvbnRzaXplKSAmJiAkb3B0aW9uZm9udHNpemUgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkb3B0aW9uZm9udHNpemUsICdwdCcpOw0KICAgICAgICAgICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkb3B0aW9uZm9udHNpemUsICdweCcpOw0KDQogICAgICAgICAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICAgICAgICAgJG9wdGlvbmZvbnRzaXplID0gJG9wdGlvbmZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRmb250d2VpZ2h0ID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJG9wdGlvbmZvbnR3ZWlnaHQpICYmICRvcHRpb25mb250d2VpZ2h0ID09ICIxIikgew0KDQogICAgICAgICAgICAgICAgICAgICRmb250d2VpZ2h0ID0gIiBmb250LXdlaWdodDogYm9sZDsgIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRfY29sb3IgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkaW5wdXRfY29sb3IpICYmICRpbnB1dF9jb2xvciAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgICAgICRfY29sb3IgPSAiIGNvbG9yOiB7JGlucHV0X2NvbG9yfTsgIjsNCiAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiZm9udC1zaXplOnskb3B0aW9uZm9udHNpemV9OyB7JGZvbnR3ZWlnaHR9IHskX2NvbG9yfSBcIiAiOw0KICAgICAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cIiBjb2xvcjp7JGNvbG9yfTsgeyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbCA9ICR0aGlzLT5fY3JlYXRlQ29uZGl0aW9uYWxFdmVudCgkY29uZGl0aW9uYWwsICRuYW1lLCAkaWQpOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9pbmxpbmUgPSAkY29uZGl0aW9uYWxfY2FsbFswXTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0ID0gJGNvbmRpdGlvbmFsX2NhbGxbMV07DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50ID0gIlxuXG5cdDwhLS0gRm9ybSBFbGVtZW50IFN0YXJ0IC0tPiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG4iOw0KICAgICAgICAkZWxlbWVudCAuPSAnPGZpZWxkc2V0IGRhdGEtcm9sZT0iY29udHJvbGdyb3VwIiBzdHlsZT0iYm9yZGVyOjA7IHBhZGRpbmc6MHB4OyBtYXJnaW46MHB4OyI+JzsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPnN0eWxlLT50YWJsZW1vZGVzcGFuKSkgew0KICAgICAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+c3R5bGUtPnRhYmxlbW9kZXNwYW4gPT0gMSkgew0KICAgICAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gdHJ1ZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmxlZnRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgISR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JGZpeGVkX3dpZHRofXB4OyBtYXJnaW4tcmlnaHQ6OHB4OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn1cIiA+IjsNCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJG5hbWUsICRyZXEsICRyZXF1aXJlZF90ZXh0LCAkY29sb3IsICRmb250c2l6ZSwgJHN0eWxlcywgJGxhYmVsLCAkbGFiZWxwb3MsIChzdHJpbmcpJGZpZWxkLT50eXBlLCAkdG9vbHRpcCwgJycsICR0YWJsZW1vZGUpOw0KDQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuXHQiIC4gJzw/cGhwICRfU0VTU0lPTlsnIC4gIiciIC4gJG5hbWUgLiAiJyIgLiAnXSA9IGlzc2V0KCRfU0VTU0lPTlsnIC4gIiciIC4gJG5hbWUgLiAiJyIgLiAnXSkgPyAkX1NFU1NJT05bJyAuICInIiAuICRuYW1lIC4gIiciIC4gJ10gOiBhcnJheSgiIik7ID8+JyAuICJcbiI7DQogICAgICAgICRlbGVtZW50IC49ICJcblx0IiAuICc8P3BocCBpZighaXNzZXQoJF9TRVNTSU9OWycgLiAiJ3skbmFtZX1faXMnIiAuICddKSkgeyAkX1NFU1NJT05bJyAuICIneyRuYW1lfV9pcyciIC4gJ10gPSAxOyB9ID8+JzsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcblx0IiAuICc8P3BocCBpZighaXNzZXQoJF9TRVNTSU9OWycgLiAiJ3skbmFtZX1fcHJvY2Vzc2VkJyIgLiAnXSkpIHsgJF9TRVNTSU9OWycgLiAiJ3skbmFtZX1fcHJvY2Vzc2VkJyIgLiAnXSA9IGZhbHNlOyB9ID8+JyAuICJcblxuIjsNCg0KDQogICAgICAgIA0KDQoNCiAgICAgICAgDQogICAgICAgICRjbGFzc19kZWZpbml0aW9uID0gIiI7DQoNCiAgICAgICAgJHJlcXVpcmVkX2NsYXNzID0gIiI7DQoNCiAgICAgICAgaWYgKChpbnQpJGZpZWxkLT52YWxpZGF0aW9uLT5yZXEgPT0gMSkgew0KICAgICAgICAgICAgJHJlcXVpcmVkX2NsYXNzID0gInJlcXVpcmVkIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRmaWVsZC0+YnVja2V0KSAmJiAkZmllbGQtPmJ1Y2tldCAhPSAiIil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgLj0gIiBidWNrZXQtY29udGFpbmVkLWZpZWxkIjsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGNsYXNzX2RlZmluaXRpb24gPSAiY2xhc3M9XCJ7JHJlcXVpcmVkX2NsYXNzfSB7JGV4dHJhY2xhc3NuYW1lc31cIiI7DQoNCg0KICAgICAgICANCg0KICAgICAgICAkc2VtYW50aWNfY2xhc3NfbmFtZSA9ICJ1aSBjaGVja2JveCI7DQoNCiAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSA9PSAicmFkaW8iKSB7DQogICAgICAgICAgICAkc2VtYW50aWNfY2xhc3NfbmFtZSA9ICJ1aSByYWRpbyBjaGVja2JveCI7DQogICAgICAgIH0NCg0KICAgICAgICAkc2VtYW50aWNfZ3JvdXBfY2xhc3NfbmFtZSA9ICJncm91cGVkIGZpZWxkcyI7DQoNCiAgICAgICAgaWYgKCRpbmxpbmVfbGFiZWxfcG9zID09ICIiKSB7DQogICAgICAgICAgICAkc2VtYW50aWNfZ3JvdXBfY2xhc3NfbmFtZSA9ICJmaWVsZHMiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkanNsaWJyYXJ5KSAmJiAkanNsaWJyYXJ5ID09ICIxNCIpIHsNCiAgICAgICAgICAgICRpbmxpbmVfbGFiZWxfcG9zID0gIiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgICR0b29sdGlwX2VsZW1lbnQgPSAkdGhpcy0+dHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGZpZWxkLT5pZCk7DQoNCg0KICAgICAgICANCiAgICAgICAgDQoNCg0KICAgICAgICANCg0KICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmJ0b29sdGlwLXskZmllbGQtPmlkfSBmYnRvb2x0aXBcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj57JHRvb2x0aXBfZWxlbWVudC0+dGV4dH08L2Rpdj5cbiI7DQogICAgICAgICRlbGVtZW50IC49ICR0b29sdGlwX2VsZW1lbnQtPmpzOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgISR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PjwhLS0gQ2xvc2UgVGFibGUgTW9kZSBESVYgLS0+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJHRhYmxlbW9kZXNwYW4gfHwgaXNzZXQoJGZpZWxkLT5idWNrZXQpICYmIChzdHJpbmcpJGZpZWxkLT5idWNrZXQgIT0gJycpIHsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cImZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPmNyZWF0ZV90YWJsZV9tb2RlX21vYmlsZV9sYWJlbCgkZmllbGQsICR0YWJsZW1vZGUpOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCg0KDQogICAgICAgIA0KICAgICAgICAkY3QgPSAoaW50KSRyb3djb3VudDsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRjdCA9PSAwKSB7DQogICAgICAgICAgICAkY3QgPSAxMDsNCiAgICAgICAgfQ0KICAgICAgICAkZWxlbWVudCAuPSAiXG48P3BocCBcJHJvd2NvdW50X3skbmFtZX0gPSB7JGN0fTsgXCRjb3VudF9yb3dfeyRuYW1lfSA9IDA7ID8+IjsNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlX29yaWdpbmFsID0gKHN0cmluZykkZGJkZWZhdWx0c2VsZWN0dmFsdWU7DQoNCiAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRkYmRlZmF1bHRzZWxlY3R2YWx1ZSwgNCk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGRiZGVmYXVsdHNlbGVjdHZhbHVlID09ICRkYmRlZmF1bHRzZWxlY3R2YWx1ZV9vcmlnaW5hbCkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRkYmRlZmF1bHRzZWxlY3R2YWx1ZSA9IHN0cl9yZXBsYWNlKCInIiwgIlwnIiwgJGRiZGVmYXVsdHNlbGVjdHZhbHVlKTsNCg0KICAgICAgICAgICAgJGRiZGVmYXVsdHNlbGVjdHZhbHVlID0gIiciIC4gJGRiZGVmYXVsdHNlbGVjdHZhbHVlIC4gIiciOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZGJkZWZhdWx0c2VsZWN0dmFsdWUgPSAiKCIgLiAkZGJkZWZhdWx0c2VsZWN0dmFsdWUgLiAiKSI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9vcmlnaW5hbCA9IChzdHJpbmcpJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlOw0KICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWVfaGFzX3Rva2VuID0gJ2ZhbHNlJzsNCg0KICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlLCA0KTsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICgkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPT0gJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlX29yaWdpbmFsKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUpOw0KDQogICAgICAgICAgICAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgPSAiJyIgLiAkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWUgLiAiJyI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSA9ICIoIiAuICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSAuICIpIjsNCiAgICAgICAgICAgICRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9oYXNfdG9rZW4gPSAndHJ1ZSc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWVfb3JpZ2luYWwgPSAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlOw0KDQogICAgICAgICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWUgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSwgNCk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9PSAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlX29yaWdpbmFsKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCInIiwgIlwnIiwgJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSk7DQoNCiAgICAgICAgICAgICRzZWxlY3RfdGV4dF9kZWZhdWx0dmFsdWUgPSAiJyIgLiAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlIC4gIiciOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlID0gIigiIC4gJHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZSAuICIpIjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoc3RyaW5nKSRmaWVsZC0+dHlwZSkgew0KICAgICAgICAgICAgY2FzZSAiY2hlY2tib3giOg0KICAgICAgICAgICAgICAgICRicmFjZSA9ICJbXSI7DQogICAgICAgICAgICAgICAgJHNlbGVjdGVkX2NvZGVfZGF0YWJhc2UgPSA8PDxFT1UNCgkJCQkJCQ0KPD9waHAgDQovLyBFeHBsb2RlIHRoZSB0b2tlbiBpZiBwb3NzaWJsZSBmb3IgbXVsdGlwbGUgZGVmYXVsdCB2YWx1ZXMuDQoNClwkZHluYW1pY19hcnJheSA9IGFycmF5KCk7DQoNClwkZHluYW1pY19pdGVtcyA9IHskZGJkZWZhdWx0c2VsZWN0dmFsdWV9Ow0KDQovLyBDb252ZXJ0IFRvIEFycmF5IElmIE5lZWRlZC4gDQoNCmlmKCFpc19hcnJheShcJGR5bmFtaWNfaXRlbXMpKXsNCiAgICBcJGR5bmFtaWNfYXJyYXkgPSBleHBsb2RlKCd8JywgXCRkeW5hbWljX2l0ZW1zKTsNCn0gZWxzZSB7DQoJXCRkeW5hbWljX2FycmF5ID0gXCRkeW5hbWljX2l0ZW1zOw0KfQ0KDQovLyBzZXQgYW55IGR5bmFtaWMgZGVmYXVsdCB2YWx1ZXMNCmlmKGlzX2FycmF5KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgJiYgaW5fYXJyYXkoaHRtbF9lbnRpdHlfZGVjb2RlKFwkdmFsdWUsIEVOVF9RVU9URVMpLCBcJF9TRVNTSU9OWyd7JG5hbWV9J10pDQoJCXx8ICghaXNfYXJyYXkoXCRkeW5hbWljX2l0ZW1zKSAmJiBpbl9hcnJheShodG1sX2VudGl0eV9kZWNvZGUoeyRkYmRlZmF1bHRzZWxlY3R2YWx1ZX0sIEVOVF9RVU9URVMpLCBcJHQpICkgfHwNCgkJKGlzX2FycmF5KFwkZHluYW1pY19hcnJheSkgJiYgaW5fYXJyYXkoXCR2YWx1ZSwgXCRkeW5hbWljX2FycmF5KSkpIHsgDQoJZWNobyAnY2hlY2tlZD0iY2hlY2tlZCInOyANCn0NCj8+IA0KRU9VOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAicmFkaW8iOg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRicmFjZSA9ICIiOw0KICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX2RhdGFiYXNlID0gPDw8RU9VDQoNCjw/cGhwIA0KLy8gU2V0IGFueSBkeW5hbWljIGRlZmF1bHQgdmFsdWVzIGZvciB0aGlzIHJhZGlvIGl0ZW0uDQppZihcJF9TRVNTSU9OWyd7JG5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlKFwkdmFsdWUsIEVOVF9RVU9URVMpIHx8IFwkdmFsdWUgPT0geyRkYmRlZmF1bHRzZWxlY3R2YWx1ZX0pIHsgDQoJZWNobyAiY2hlY2tlZD1cImNoZWNrZWRcIiI7IH0NCj8+IA0KRU9VOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0ID0gIiI7DQogICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX2VuZCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkZmllbGQtPm11bHRpc2VsZWN0X2xheW91dG1vZGUgPT0gMCkgew0KDQogICAgICAgICAgICAkcGFkZGluZyA9ICIiOw0KICAgICAgICAgICAgJG1hcmdpbiA9ICIiOw0KICAgICAgICAgICAgJGFsaWdubWVudCA9ICIiOw0KICAgICAgICAgICAgJGJhY2tncm91bmRfY29sb3IgPSAiIjsNCg0KICAgICAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX3BhZGRpbmcgIT0gJycpDQogICAgICAgICAgICAkcGFkZGluZyA9ICIgcGFkZGluZzogeyRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9wYWRkaW5nfXB4OyAiOw0KDQogICAgICAgICAgICBpZiAoKGludCkkZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fbWFyZ2luICE9ICcnKQ0KICAgICAgICAgICAgJG1hcmdpbiA9ICIgbWFyZ2luOiB7JGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX21hcmdpbn1weDsgIjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKHN0cmluZykkZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fYWxpZ25tZW50ICE9ICcnKQ0KICAgICAgICAgICAgJGFsaWdubWVudCA9ICJhbGlnbjp7JGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX2FsaWdubWVudH07ICI7DQoNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9iYWNrZ3JvdW5kX2NvbG9yICE9ICcnKQ0KICAgICAgICAgICAgJGJhY2tncm91bmRfY29sb3IgPSAiIGJhY2tncm91bmQtY29sb3I6IHskZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fYmFja2dyb3VuZF9jb2xvcn07ICI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICgoaW50KSRsYWJlbHBvcyA9PSAwKSB7DQogICAgICAgICAgICAgICAgJGNsZWFyID0gImNsZWFyOmJvdGg7IjsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5yb3djb3VudCA9PSAnJykgew0KICAgICAgICAgICAgICAgICAgICAkY2xlYXIgPSAiZmxvYXQ6bGVmdDsiOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICRjbGVhciA9ICJjbGVhcjpib3RoOyI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkdXNlX2FsdGVybmF0aW5nID0gJ2ZhbHNlJzsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9iYWNrZ3JvdW5kX2NvbG9yX2FsdGVybmF0ZSkgJiYgKGludCkkZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fYmFja2dyb3VuZF9jb2xvcl9hbHRlcm5hdGUgPT0gJzEnKSB7DQoNCiAgICAgICAgICAgICAgICAkdXNlX2FsdGVybmF0aW5nID0gJ3RydWUnOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJG11bHRpc2VsZWN0X2l0ZW1fc3RhcnQgPSAiXG48P3BocCBpZihcJGNvdW50X3skbmFtZX0gJSAyID09IDAgJiYgeyR1c2VfYWx0ZXJuYXRpbmd9KSB7IFwkYWx0ZXJuYXRlX3JvdyA9IHRydWU7IH0gZWxzZSB7IFwkYWx0ZXJuYXRlX3JvdyA9IGZhbHNlOyB9ID8+XG4iOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkanNsaWJyYXJ5KSAmJiAkanNsaWJyYXJ5ID09ICIxNCIpIHsNCiAgICAgICAgICAgICAgICAkbWFyZ2luID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0IC49ICI8ZGl2IGNsYXNzPVwibXVsdGlzZWxlY3QtaXRlbSBmaWVsZFwiIHN0eWxlPVwiIHskcGFkZGluZ30geyRtYXJnaW59IHskYWxpZ25tZW50fSA8P3BocCBpZih7JHVzZV9hbHRlcm5hdGluZ30gJiYgXCRhbHRlcm5hdGVfcm93KSB7ID8+eyRiYWNrZ3JvdW5kX2NvbG9yfSA8P3BocCB9IGVsc2UgaWYoIXskdXNlX2FsdGVybmF0aW5nfSkgeyBlY2hvICd7JGJhY2tncm91bmRfY29sb3J9JzsgfSA/PiB7JGNsZWFyfSBcIj4iOw0KDQogICAgICAgICAgICAkbXVsdGlzZWxlY3RfaXRlbV9lbmQgPSAiPC9kaXY+PCEtLSBDbG9zZSBOb24tTXVsdGktU2VsZWN0IERJViAtLT4iOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlKSAmJiAkYnVja2V0X25vZGUgIT0gIiIgJiYgKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5yZXNwb25zaXZlID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0ID0gIiI7DQogICAgICAgICAgICAgICAgJG11bHRpc2VsZWN0X2l0ZW1fZW5kID0gIiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoKGludCkkZmllbGQtPm11bHRpc2VsZWN0X2xheW91dG1vZGUgPT0gMSkgew0KDQogICAgICAgICAgICAkd2lkdGggPSAnJzsNCiAgICAgICAgICAgICRwYWRkaW5nID0gIiI7DQogICAgICAgICAgICAkbWFyZ2luID0gIiI7DQogICAgICAgICAgICAkYWxpZ25tZW50ID0gIiI7DQogICAgICAgICAgICAkYmFja2dyb3VuZF9jb2xvciA9ICIiOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV93aWR0aCAhPSAnJykgew0KICAgICAgICAgICAgICAgIGlmIChjdHlwZV9kaWdpdCgoc3RyaW5nKSRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV93aWR0aCkpIHsNCiAgICAgICAgICAgICAgICAgICAgJHdpZHRoID0gIiB3aWR0aDogeyRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV93aWR0aH1weDsgIjsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkd2lkdGggPSAiIHdpZHRoOiB7JGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX3dpZHRofTsgIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9wYWRkaW5nICE9ICcnKQ0KICAgICAgICAgICAgJHBhZGRpbmcgPSAiIHBhZGRpbmc6IHskZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fcGFkZGluZ31weDsgIjsNCg0KICAgICAgICAgICAgaWYgKChpbnQpJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX21hcmdpbiAhPSAnJykNCiAgICAgICAgICAgICRtYXJnaW4gPSAiIG1hcmdpbjogeyRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9tYXJnaW59cHg7ICI7DQoNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9hbGlnbm1lbnQgIT0gJycpDQogICAgICAgICAgICAkYWxpZ25tZW50ID0gIiBhbGlnbj1cInskZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fYWxpZ25tZW50fVwiIjsNCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX2JhY2tncm91bmRfY29sb3IgIT0gJycpDQogICAgICAgICAgICAkYmFja2dyb3VuZF9jb2xvciA9ICIgYmFja2dyb3VuZC1jb2xvcjogeyRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9iYWNrZ3JvdW5kX2NvbG9yfTsgIjsNCg0KICAgICAgICAgICAgJHVzZV9hbHRlcm5hdGluZyA9ICdmYWxzZSc7DQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPm11bHRpc2VsZWN0X2l0ZW1fYmFja2dyb3VuZF9jb2xvcl9hbHRlcm5hdGUpICYmIChpbnQpJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX2JhY2tncm91bmRfY29sb3JfYWx0ZXJuYXRlID09ICcxJykgew0KDQogICAgICAgICAgICAgICAgJHVzZV9hbHRlcm5hdGluZyA9ICd0cnVlJzsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkbXVsdGlzZWxlY3RfaXRlbV9zdGFydCA9ICJcbjw/cGhwIGlmKFwkY291bnRfeyRuYW1lfSAlIDIgPT0gMCAmJiB7JHVzZV9hbHRlcm5hdGluZ30pIHsgXCRhbHRlcm5hdGVfcm93ID0gdHJ1ZTsgfSBlbHNlIHsgXCRhbHRlcm5hdGVfcm93ID0gZmFsc2U7IH0gPz5cbiI7DQoNCiAgICAgICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0IC49ICI8ZGl2IHskYWxpZ25tZW50fSBjbGFzcz1cIm11bHRpc2VsZWN0LXN1cnZleS1pdGVtXCIgc3R5bGU9XCJ7JHdpZHRofSB7JHBhZGRpbmd9IHskbWFyZ2lufSA8P3BocCBpZih7JHVzZV9hbHRlcm5hdGluZ30gJiYgXCRhbHRlcm5hdGVfcm93KSB7ID8+eyRiYWNrZ3JvdW5kX2NvbG9yfSA8P3BocCB9IGVsc2UgaWYoIXskdXNlX2FsdGVybmF0aW5nfSkgeyBlY2hvICd7JGJhY2tncm91bmRfY29sb3J9JzsgfSA/PiBmbG9hdDpsZWZ0OyAgXCI+IjsNCg0KICAgICAgICAgICAgJG11bHRpc2VsZWN0X2l0ZW1fZW5kID0gIjwvZGl2PjwhLS0gQ2xvc2UgTXVsdGktU2VsZWN0IERJViAtLT4iOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlKSAmJiAkYnVja2V0X25vZGUgIT0gIiIgJiYgKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5yZXNwb25zaXZlID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0ID0gIiI7DQogICAgICAgICAgICAgICAgJG11bHRpc2VsZWN0X2l0ZW1fZW5kID0gIiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJGZiX211bHRpc2VsZWN0X2NvbHVtbl9mbG9hdCA9ICdmbG9hdDpsZWZ0Oyc7DQoNCiAgICAgICAgaWYgKGRlZmluZWQoJ01PQklMRV9NT0RFJykpIHsNCiAgICAgICAgICAgICRmYl9tdWx0aXNlbGVjdF9jb2x1bW5fZmxvYXQgPSAnJzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgICRsYWJlbF9jbGFzc19jb2RlID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bXVsdGlzZWxlY3RfaXRlbV9jdXN0b21fbGFiZWxfY29kZSkgJiYgJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX2N1c3RvbV9sYWJlbF9jb2RlICE9ICIiKSB7DQoNCiAgICAgICAgICAgICRsYWJlbF9jbGFzc19jb2RlID0gJGZpZWxkLT5tdWx0aXNlbGVjdF9pdGVtX2N1c3RvbV9sYWJlbF9jb2RlOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQogICAgICAgICAgICAgICAgDQogICAgICAgIA0KICAgICAgICBmb3JlYWNoICgkaXRlbXNfYXJyYXkgYXMgJHZhbCkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoKGludCkkZGF0YXNvdXJjZSAhPSAnMScgJiYgJHZhbC0+bmFtZSA9PSAiQWRkIGEgcmFkaW8gb3B0aW9uIikgew0KICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkdmFsLT52YWx1ZSA9IGh0bWxlbnRpdGllcygkdmFsLT52YWx1ZSwgRU5UX1FVT1RFUywgJ1VURi04Jyk7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkZmllbGRfdmFsdWVfZm9yX3ZhbHVlX2h0bWxfcHJvcGVydHkgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCR2YWwtPnZhbHVlLCAzKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKGludCkkc2VsZWN0X3VzZV9ib29sZWFuID09IDEpIHsNCiAgICAgICAgICAgICAgICAkZmllbGRfdmFsdWVfZm9yX3ZhbHVlX2h0bWxfcHJvcGVydHkgPSAxOw0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICR2YWx1ZV9vcmlnaW5hbCA9IHN0cnRvbG93ZXIoJHZhbC0+dmFsdWUpOw0KDQogICAgICAgICAgICAkdmFsdWVfYWZ0ZXJfZHluYW1pY192YXJpYWJsZXMgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCR2YWwtPnZhbHVlLCAzKTsNCg0KICAgICAgICAgICAgaWYoJHZhbHVlX29yaWdpbmFsICE9IHN0cnRvbG93ZXIoJHZhbHVlX2FmdGVyX2R5bmFtaWNfdmFyaWFibGVzKSl7DQogICAgICAgICAgICAgICAgJHZhbC0+dmFsdWUgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCR2YWwtPnZhbHVlLCAxKTsNCiAgICAgICAgICAgICAgICAkdmFsLT52YWx1ZSA9ICInLlwiIiAuICR2YWwtPnZhbHVlIC4gIn1cIi4nIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgoc3RyaW5nKSR2YWwtPm5hbWUgIT0gIkFkZCBhIHskZmllbGQtPnR5cGV9IG9wdGlvbiIpIHsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZmllbGRfdmFsdWUgPSAkdmFsLT52YWx1ZTsNCg0KICAgICAgICAgICAgICAgICRmaWVsZF92YWx1ZV9lc2NhcGVkID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCAkZmllbGRfdmFsdWUpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKChpbnQpJHNlbGVjdF91c2VfYm9vbGVhbiA9PSAxKSB7DQogICAgICAgICAgICAgICAgICAgICRmaWVsZF92YWx1ZSA9IDE7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgc3dpdGNoICgoc3RyaW5nKSRmaWVsZC0+dHlwZSkgew0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgImNoZWNrYm94IjoNCiAgICAgICAgICAgICAgICAgICAgICAgICRicmFjZSA9ICJbXSI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICBpZihpc3NldCgkZmllbGRwb3B1bGF0ZWRlZmF1bHQpICYmICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9PSAxKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2VsZWN0ZWRfY29kZSA9IDw8PEVPVA0KCQkJCQkJDQo8P3BocCANClwkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWVfaGFzX3Rva2VuID0geyRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9oYXNfdG9rZW59Ow0KDQpcJGR5bmFtaWNfYXJyYXkgPSBhcnJheSgpOw0KDQovLyBFeHBsb2RlIGRlZmF1bHQgdG9rZW4vdmFsdWUgaWYgcG9zc2libGUgZm9yIG11bHRpcGxlIGRlZmF1bHQgdmFsdWVzLg0KDQppZigneyRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9oYXNfdG9rZW59JyA9PSAnZmFsc2UnKXsNCiAgICBcJGR5bmFtaWNfYXJyYXkgPSBleHBsb2RlKCd8JywgeyRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZX0pOw0KfQ0KDQpcJGR5bmFtaWNfYXJyYXlfbGlzdCA9IGV4cGxvZGUoJ3wnLCB7JHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZX0pOw0KDQovLyBzZXQgZGVmYXVsdCB2YWx1ZShzKQ0KDQppZihpc19hcnJheShcJF9TRVNTSU9OWyd7JG5hbWV9J10pICYmIGluX2FycmF5KGh0bWxfZW50aXR5X2RlY29kZSgieyRmaWVsZF92YWx1ZX0iLCBFTlRfUVVPVEVTKSwgXCRfU0VTU0lPTlsneyRuYW1lfSddKSkgeyAvLyBUaGlzIGZpZWxkJ3MgZXhpc3Rpbmcgc2VsZWN0aW9uIHNldC4NCgllY2hvICdjaGVja2VkPSJjaGVja2VkIic7IA0KfQ0KDQppZighXCRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZV9oYXNfdG9rZW4gJiYgJ3skZmllbGRfdmFsdWV9JyA9PSBodG1sZW50aXRpZXMoJGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlLCBFTlRfUVVPVEVTKSANCiAgICAmJiBcJF9TRVNTSU9OWyd7JG5hbWV9X3Byb2Nlc3NlZCddID09IGZhbHNlKSB7IA0KCWVjaG8gJ2NoZWNrZWQ9ImNoZWNrZWQiJzsgDQp9DQoNCmlmKFwkYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWVfaGFzX3Rva2VuICYmIFwkX1NFU1NJT05bJ3skbmFtZX1fcHJvY2Vzc2VkJ10gPT0gZmFsc2UpeyAvLyBUb2tlbiB3aXRoIGRlZmF1bHQgc2VsZWN0IHZhbHVlLg0KICAgIGlmKGlzX2FycmF5KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgJiYgaXNfYXJyYXkoZXhwbG9kZSgnfCcsIHskYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWV9KSkpew0KICAgICAgICBpZihpbl9hcnJheShodG1sX2VudGl0eV9kZWNvZGUoInskZmllbGRfdmFsdWV9IiwgRU5UX1FVT1RFUyksIGV4cGxvZGUoJ3wnLCB7JGJhc2ljZGVmYXVsdHNlbGVjdHZhbHVlfSkpICYmIFwkX1NFU1NJT05bJ3skbmFtZX1fcHJvY2Vzc2VkJ10gPT0gZmFsc2Upew0KICAgICAgICAgICAgZWNobyAnY2hlY2tlZD0iY2hlY2tlZCInOyANCiAgICAgICAgfQ0KICAgIH0NCn0NCg0KaWYoJ3skZmllbGRfdmFsdWV9JyA9PSB7JHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZX0gJiYgXCRfU0VTU0lPTlsneyRuYW1lfV9wcm9jZXNzZWQnXSA9PSBmYWxzZSkgeyANCgllY2hvICdjaGVja2VkPSJjaGVja2VkIic7IA0KfQ0KDQppZiggKGlzX2FycmF5KFwkZHluYW1pY19hcnJheSkgJiYgaW5fYXJyYXkoInskZmllbGRfdmFsdWV9IiwgXCRkeW5hbWljX2FycmF5KSB8fCBpc19hcnJheShcJGR5bmFtaWNfYXJyYXlfbGlzdCkgJiYgaW5fYXJyYXkoInskZmllbGRfdmFsdWV9IiwgXCRkeW5hbWljX2FycmF5X2xpc3QpICkgJiYgDQoJXCRfU0VTU0lPTlsneyRuYW1lfV9wcm9jZXNzZWQnXSA9PSBmYWxzZSkgeyANCgllY2hvICdjaGVja2VkPSJjaGVja2VkIic7IA0KfQ0KDQo/PgkNCkVPVDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNlbGVjdGVkX2NvZGUgPSA8PDxFT1QNCgkJCQkJCQ0KPD9waHAgDQovLyBleHBsb2RlIGRlZmF1bHQgdG9rZW4vdmFsdWUgaWYgcG9zc2libGUgZm9yIG11bHRpcGxlIGRlZmF1bHQgdmFsdWVzLg0KXCRkeW5hbWljX2FycmF5ID0gZXhwbG9kZSgnfCcsIHskYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWV9KTsNClwkZHluYW1pY19hcnJheV9saXN0ID0gZXhwbG9kZSgnfCcsIHskc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlfSk7DQoNCi8vIHNldCBkZWZhdWx0IHZhbHVlcw0KaWYoKCd7JGZpZWxkX3ZhbHVlfScgPT0gaHRtbGVudGl0aWVzKCRiYXNpY2RlZmF1bHRzZWxlY3R2YWx1ZSwgRU5UX1FVT1RFUykgfHwgJ3skZmllbGRfdmFsdWV9JyA9PSB7JHNlbGVjdF90ZXh0X2RlZmF1bHR2YWx1ZX0gfHwNCgkoaXNfYXJyYXkoXCRkeW5hbWljX2FycmF5KSAmJiBpbl9hcnJheSgieyRmaWVsZF92YWx1ZX0iLCBcJGR5bmFtaWNfYXJyYXkpIHx8IGlzX2FycmF5KFwkZHluYW1pY19hcnJheV9saXN0KSAmJiBpbl9hcnJheSgieyRmaWVsZF92YWx1ZX0iLCBcJGR5bmFtaWNfYXJyYXlfbGlzdCkgKSAmJiANCglcJF9TRVNTSU9OWyd7JG5hbWV9X3Byb2Nlc3NlZCddID09IGZhbHNlKSkgeyANCgllY2hvICdjaGVja2VkPSJjaGVja2VkIic7IA0KfQ0KPz4JDQpFT1Q7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkc2VsZWN0ZWRfY29kZV9zZWxlY3RlZCA9IDw8PEVPWQ0KPD9waHAgaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsneyRuYW1lfSddKSAmJiBpbl9hcnJheShodG1sX2VudGl0eV9kZWNvZGUoInskZmllbGRfdmFsdWV9IiwgRU5UX1FVT1RFUyksIFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgfHwgXCRfU0VTU0lPTlsneyRuYW1lfV9pcyddID09IDEpIHsgDQoJZWNobyAnY2hlY2tlZD0iY2hlY2tlZCInOyANCn0NCj8+DQpFT1k7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX2RhdGFiYXNlID0gPDw8RU9VDQoNCjw/cGhwDQoNCi8vIGV4cGxvZGUgdGhlIHRva2VuIGlmIHBvc3NpYmxlIGZvciBtdWx0aXBsZSBkZWZhdWx0IHZhbHVlcy4NClwkZHluYW1pY19hcnJheSA9IGV4cGxvZGUoJ3wnLCB7JGRiZGVmYXVsdHNlbGVjdHZhbHVlfSk7DQoNCi8vIFNlbGVjdCBDb2RlIEZvciBEYXRhYmFzZSBDaGVja2JveCBJdGVtcy4NCmlmKGlzX2FycmF5KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgJiYgaW5fYXJyYXkoaHRtbF9lbnRpdHlfZGVjb2RlKFwkdmFsdWUsIEVOVF9RVU9URVMpLCBcJF9TRVNTSU9OWyd7JG5hbWV9J10pIHx8DQoJKGlzX2FycmF5KFwkZHluYW1pY19hcnJheSkgJiYgaW5fYXJyYXkoXCR2YWx1ZSwgXCRkeW5hbWljX2FycmF5KSkpIHsgDQoJCWVjaG8gJ2NoZWNrZWQ9ImNoZWNrZWQiJzsgDQp9DQo/PiANCkVPVTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgIGNhc2UgInJhZGlvIjoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkYnJhY2UgPSAiIjsNCiAgICAgICAgICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlID0gPDw8RU9UDQoJCQkJCQkJCQ0KPD9waHAgaWYoXCRfU0VTU0lPTlsneyRuYW1lfSddID09IGh0bWxfZW50aXR5X2RlY29kZSgneyR2YWwtPnZhbHVlfScsIEVOVF9RVU9URVMpIHx8IA0KCSggKCd7JGZpZWxkX3ZhbHVlfScgPT0gaHRtbGVudGl0aWVzKHskYmFzaWNkZWZhdWx0c2VsZWN0dmFsdWV9LCBFTlRfUVVPVEVTKSB8fCAneyRmaWVsZF92YWx1ZX0nID09IHskc2VsZWN0X3RleHRfZGVmYXVsdHZhbHVlfSkgJiYgXCRfU0VTU0lPTlsneyRuYW1lfV9wcm9jZXNzZWQnXSA9PSBmYWxzZSkpIHsgDQoJZWNobyAiY2hlY2tlZD1cImNoZWNrZWRcIiI7IH0NCj8+DQpFT1Q7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX3NlbGVjdGVkID0gPDw8RU9UDQoJCQkJCQkJCQkNCjw/cGhwIGlmKFwkX1NFU1NJT05bJ3skbmFtZX0nXSA9PSBodG1sX2VudGl0eV9kZWNvZGUoJ3skdmFsLT52YWx1ZX0nLCBFTlRfUVVPVEVTKSB8fCBcJF9TRVNTSU9OWyd7JG5hbWV9X2lzJ10gPT0gMSkgeyANCgkvLyBSYWRpbyBTZWxlY3RlZCBDb2RlLg0KCWVjaG8gImNoZWNrZWQ9XCJjaGVja2VkXCIiOyB9DQo/Pg0KRU9UOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9IA0KDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJHZhbC0+cm93YnJlYWspICYmICR2YWwtPnJvd2JyZWFrID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG48P3BocCBcJGNvdW50X3skbmFtZX0gPSAxOyA/PlxuXG4iOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvc3Bhbj48IS0tIENsb3NlIFJvd0JyZWFrIFNQQU4gLS0+XG48ZGl2IGNsYXNzPVwiZmItbXVsdGlzZWxlY3QtY29sdW1uIHskZmllbGQtPnR5cGV9LWNvbHVtblwiIHN0eWxlPVwid2lkdGg6eyRjb2x1bW53aWR0aH07IGNsZWFyOmJvdGg7XCI+PC9kaXY+IjsNCg0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRmaWVsZF9sYWJlbCA9IGh0bWxfZW50aXR5X2RlY29kZSgkdmFsLT5uYW1lKTsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGZpZWxkX2xhYmVsID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZmllbGRfbGFiZWwsIDMpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHZhbC0+bmFtZSA9IGh0bWxlbnRpdGllcygkdmFsLT5uYW1lKTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRsYWJlbF9tYXJnaW4gPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmxhYmVsX21hcmdpbikgJiYgJGZpZWxkLT5sYWJlbF9tYXJnaW4gIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAgICAgJF92YWwgPSBpbnR2YWwoJGZpZWxkLT5sYWJlbF9tYXJnaW4pOw0KICAgICAgICAgICAgICAgICAgICAkbGFiZWxfbWFyZ2luID0gIiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiB7JF92YWx9cHg7XCIgIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGxhYmVscG9zX2NsYXNzID0gKGludCkkZmllbGQtPmxhYmVscG9zID09IDAgPyAnbGFiZWxwb3MtdG9wJyA6ICdsYWJlbHBvcy1pbmxpbmUnOw0KDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRtdWx0aV9zZWxlY3Rfc3Bhbl93cmFwcGVyID0gIjxzcGFuIGNsYXNzPVwicmYtbXVsdGlzZWxlY3QtaXRlbS1sYWJlbFwiIHskbGFiZWxfbWFyZ2lufT57JGZpZWxkX2xhYmVsfTwvc3Bhbj4iOw0KDQogICAgICAgICAgICAgICAgJG11bHRpX3NlbGVjdF9zcGFuX2NzcyA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYoc3Vic3RyX2NvdW50KCRmaWVsZF9sYWJlbCwgIjxpbWciKSAhPSAwKXsNCg0KICAgICAgICAgICAgICAgICAgICAkbXVsdGlfc2VsZWN0X3NwYW5fd3JhcHBlciA9ICJ7JGZpZWxkX2xhYmVsfSI7DQoNCiAgICAgICAgICAgICAgICAgICAgJG11bHRpX3NlbGVjdF9zcGFuX2NzcyA9IDw8PEVPRg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCi8qIEhJREUgUkFESU8gKi8NCiN7JG5hbWV9eyR2YWwtPmlkfSB7IA0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIG9wYWNpdHk6IDA7DQogIHdpZHRoOiAwOw0KICBoZWlnaHQ6IDA7DQp9DQoNCi8qIElNQUdFIFNUWUxFUyAqLw0KI3skbmFtZX17JHZhbC0+aWR9ICsgaW1nIHsNCiAgY3Vyc29yOiBwb2ludGVyOw0KfQ0KDQovKiBDSEVDS0VEIFNUWUxFUyAqLw0KI3skbmFtZX17JHZhbC0+aWR9OmNoZWNrZWQgKyBpbWcgew0KICBvdXRsaW5lOiAxcHggZG90dGVkICNiNWI1YjU7DQp9DQo8L3N0eWxlPg0KRU9GOw0KDQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKCR2YWwtPnNlbGVjdGVkID09IDEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCg0KPD9waHANCiFpc3NldChcJGNvdW50X3skbmFtZX0pID8gXCRjb3VudF97JG5hbWV9ID0gMSA6IFwkY291bnRfeyRuYW1lfSsrOw0KXCRjb3VudF9yb3dfeyRuYW1lfSsrOw0KXCRjb3VudF97JG5hbWV9ID09IDEgfHwgXCRjb3VudF9yb3dfeyRuYW1lfSA9PSAxID8gcHJpbnQgJzxkaXYgY2xhc3M9ImZiLW11bHRpc2VsZWN0LWNvbHVtbiB7JGxhYmVscG9zX2NsYXNzfSB7JHNlbWFudGljX2dyb3VwX2NsYXNzX25hbWV9IHskZmllbGQtPnR5cGV9LWNvbHVtbiIgc3R5bGU9IndpZHRoOnskY29sdW1ud2lkdGh9OyB7JGZiX211bHRpc2VsZWN0X2NvbHVtbl9mbG9hdH0iPicgOiBwcmludCAnJzsNCj8+DQoNCnskbXVsdGlzZWxlY3RfaXRlbV9zdGFydH0NCjxkaXYgY2xhc3M9Inskc2VtYW50aWNfY2xhc3NfbmFtZX0iPg0KPGxhYmVsIGFyaWEtbGFiZWwgZm9yPSJ7JG5hbWV9eyR2YWwtPmlkfSIgY2xhc3M9InskZmllbGQtPnR5cGV9LWlubGluZSB7JHNlbWFudGljX2NsYXNzX25hbWV9IDw/cGhwIFwkdmFsdWUgPSAneyRmaWVsZF92YWx1ZV9lc2NhcGVkfSc7ID8+IHskbGFiZWxfY2xhc3NfY29kZX0iIHskaW5oZXJpdHN0eWxlfSA+DQp7JG11bHRpX3NlbGVjdF9zcGFuX2Nzc30NCjxpbnB1dCB0eXBlPSJ7JGZpZWxkLT50eXBlfSIgbmFtZT0ieyRuYW1lfXskYnJhY2V9IiBpZD0ieyRpZH17JHZhbC0+aWR9IiB7JHRhYmh0bWx9IHZhbHVlPSJ7JGZpZWxkX3ZhbHVlX2Zvcl92YWx1ZV9odG1sX3Byb3BlcnR5fSIgeyRpbmhlcml0c3R5bGV9IHskY2xhc3NfZGVmaW5pdGlvbn0geyRlbmFibGVkfSB7JHJlYWRvbmx5fQ0KeyRzZWxlY3RlZF9jb2RlX3NlbGVjdGVkfQ0KeyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IC8+DQp7JG11bHRpX3NlbGVjdF9zcGFuX3dyYXBwZXJ9DQo8L2xhYmVsPiB7JGlubGluZV9sYWJlbF9wb3N9DQo8L2Rpdj48IS0tIENsb3NlIFNlbGVjdGVkIERJViAtLT4NCnskbXVsdGlzZWxlY3RfaXRlbV9lbmR9DQo8P3BocCBpZihcJGNvdW50X3Jvd197JG5hbWV9ID09IFwkcm93Y291bnRfeyRuYW1lfSkgeyBlY2hvICc8L2Rpdj4nOyBcJGNvdW50X3Jvd197JG5hbWV9ID0gMDsgfSA/Pg0KRU9GOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQoNCjw/cGhwDQohaXNzZXQoXCRjb3VudF97JG5hbWV9KSA/IFwkY291bnRfeyRuYW1lfSA9IDEgOiBcJGNvdW50X3skbmFtZX0rKzsNClwkY291bnRfcm93X3skbmFtZX0rKzsNClwkY291bnRfeyRuYW1lfSA9PSAxIHx8IFwkY291bnRfcm93X3skbmFtZX0gPT0gMSA/IHByaW50ICc8ZGl2IGNsYXNzPSJmYi1tdWx0aXNlbGVjdC1jb2x1bW4geyRsYWJlbHBvc19jbGFzc30geyRzZW1hbnRpY19ncm91cF9jbGFzc19uYW1lfSB7JGZpZWxkLT50eXBlfS1jb2x1bW4iIHN0eWxlPSJ3aWR0aDp7JGNvbHVtbndpZHRofTsgeyRmYl9tdWx0aXNlbGVjdF9jb2x1bW5fZmxvYXR9Ij4nIDogcHJpbnQgJyc7DQo/Pg0KeyRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0fQ0KPGRpdiBjbGFzcz0ieyRzZW1hbnRpY19jbGFzc19uYW1lfSI+DQo8bGFiZWwgZm9yPSJ7JG5hbWV9eyR2YWwtPmlkfSIgY2xhc3M9InskZmllbGQtPnR5cGV9LWlubGluZSB7JHNlbWFudGljX2NsYXNzX25hbWV9IDw/cGhwIFwkdmFsdWUgPSAneyRmaWVsZF92YWx1ZV9lc2NhcGVkfSc7ID8+IHskbGFiZWxfY2xhc3NfY29kZX0iIHskaW5oZXJpdHN0eWxlfSA+DQp7JG11bHRpX3NlbGVjdF9zcGFuX2Nzc30NCjxpbnB1dCB0eXBlPSJ7JGZpZWxkLT50eXBlfSIgbmFtZT0ieyRuYW1lfXskYnJhY2V9IiBpZD0ieyRpZH17JHZhbC0+aWR9IiB7JHRhYmh0bWx9IHZhbHVlPSJ7JGZpZWxkX3ZhbHVlX2Zvcl92YWx1ZV9odG1sX3Byb3BlcnR5fSIgeyRpbmhlcml0c3R5bGV9IHskY2xhc3NfZGVmaW5pdGlvbn0geyRlbmFibGVkfSB7JHJlYWRvbmx5fQ0KeyRzZWxlY3RlZF9jb2RlfQ0KeyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IC8+DQp7JG11bHRpX3NlbGVjdF9zcGFuX3dyYXBwZXJ9DQo8L2xhYmVsPiB7JGlubGluZV9sYWJlbF9wb3N9DQo8L2Rpdj48IS0tIENsb3NlIE5vbi1TZWxlY3RlZCBESVYgLS0+DQp7JG11bHRpc2VsZWN0X2l0ZW1fZW5kfQ0KPD9waHAgaWYoXCRjb3VudF9yb3dfeyRuYW1lfSA9PSBcJHJvd2NvdW50X3skbmFtZX0pIHsgZWNobyAnPC9kaXY+PCEtLSBDbG9zZSBSb3cgRElWIC0tPic7IFwkY291bnRfcm93X3skbmFtZX0gPSAwOyB9ID8+DQoNCkVPRjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IA0KICAgICAgICB9IA0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGRhdGFzb3VyY2UgIT0gJzAnICYmICRzb3VyY2VzcWwgIT0gIiIpIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmxhYmVsX21hcmdpbikgJiYgJGZpZWxkLT5sYWJlbF9tYXJnaW4gIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAkX3ZhbCA9IGludHZhbCgkZmllbGQtPmxhYmVsX21hcmdpbik7DQogICAgICAgICAgICAgICAgJGxhYmVsX21hcmdpbiA9ICIgc3R5bGU9XCJtYXJnaW4tbGVmdDogeyRfdmFsfXB4O1wiICI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkY29ubmVjdG9yICE9ICcnKSB7DQogICAgICAgICAgICAgICAgJGNvbm5lY3RvciA9IHN0cl9yZXBsYWNlKCdcXCcsICdcXFxcJywgJGNvbm5lY3Rvcik7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJGRiZGVidWdsZXZlbCA9PSAnJykgew0KICAgICAgICAgICAgICAgICRkYmRlYnVnbGV2ZWwgPSAnMCc7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZGJfdHlwZSA9ICR0aGlzLT51bS0+dHJhbnNsYXRlU291cmNlVHlwZSgoaW50KSRzb3VyY2V0eXBlKTsNCg0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRvcmRlcl9sID0gMDsNCiAgICAgICAgICAgICRvcmRlcl92ID0gMTsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cGFyYW1ldGVyb3JkZXIpICYmICRmaWVsZC0+cGFyYW1ldGVyb3JkZXIgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+cGFyYW1ldGVyb3JkZXIgPT0gMSkgew0KDQogICAgICAgICAgICAgICAgICAgICRvcmRlcl9sID0gMTsNCiAgICAgICAgICAgICAgICAgICAgJG9yZGVyX3YgPSAwOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRkYmhvc3QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYmhvc3QsIDgpOw0KICAgICAgICAgICAgJGRidXNlciA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRidXNlciwgOCk7DQogICAgICAgICAgICAkZGJwd2QgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYnB3ZCwgOCk7DQogICAgICAgICAgICAkZGJzY2hlbWEgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRkYnNjaGVtYSwgOCk7DQogICAgICAgICAgICAkZGJwb3J0ID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGJwb3J0LCA4KTsNCiAgICAgICAgICAgICRkYmRzbiA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRiZHNuLCA4KTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KPCEtLSBQb3B1bGF0ZSBGaWVsZCBTdGFydCB7JG5hbWV9IC0tPg0KPD9waHANCi8vIHBlcmZvcm0gc3FsIHF1ZXJ5IGZvciB7JG5hbWV9DQoNCi8vIENoYW5nZSB0byAxIHRvIHNlZSBkZWJ1ZyBpbmZvIGlmIHlvdSBydW4gaW50byBwcm9ibGVtcyBleGVjdXRpbmcgeW91ciBxdWVyeSAobWF5IG5lZWQgdG8gbG9vayBhdCBodG1sIHBhZ2Ugc291cmNlIHRvIHNlZSBlcnJvcikuDQpcJHF1ZXJ5X2RlYnVnID0geyRkYmRlYnVnbGV2ZWx9OyANCg0KXCRkYl9zY2hlbWFfY2hlY2sgPSAneyRkYnNjaGVtYX0nOw0KXCRkYl9kc25fdGVzdCA9ICd7JGRiZHNufSc7IC8vIEJ1aWxkIDcxMA0KDQppZihcJGRiX3NjaGVtYV9jaGVjayAhPSAnJyB8fCBcJGRiX2Rzbl90ZXN0ICE9ICcnKXsNCglcJGRiX2hvc3QgPSAieyRkYmhvc3R9IjsNCglcJGRiX3R5cGUgPSAieyRkYl90eXBlfSI7DQoJXCRkYl91c2VyID0gInskZGJ1c2VyfSI7DQoJXCRkYl9wYXNzID0gInskZGJwd2R9IjsNCglcJGRiX2NhdGFsb2cgPSAieyRkYnNjaGVtYX0iOw0KCVwkbXlzcWxfc29ja2V0ID0gInskZGJzb2NrZXR9IjsNCglcJG15c3FsX3BvcnQgPSAieyRkYnBvcnR9IjsNCglcJGRiZHNuID0gInskZGJkc259IjsNCn0NCg0KQGluY2x1ZGVfb25jZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119RGF0YWJhc2UucGhwIjsNCg0KLy8gb3B0aW9uYWwgY29ubmVjdG9yIHNjcmlwdA0KaWYoZmlsZV9leGlzdHMoIntcJF9TRVNTSU9OWydNQVhfUEFUSCddfXskY29ubmVjdG9yfSIpKXsNCglAaW5jbHVkZSAie1wkX1NFU1NJT05bJ01BWF9QQVRIJ119eyRjb25uZWN0b3J9IjsNCn0NCg0KLy8gTXVsdGktU2VsZWN0IEl0ZW0gUXVlcnkuDQpcJHNxbF97JG5hbWV9ID0gInskc291cmNlc3FsfSI7DQpcJGRiaCA9IG5ldyBEYXRhYmFzZSgpOw0KDQpcJHJlc3VsdF97JG5hbWV9ID0gIiI7DQoNCmlmKFwkc3FsX3skbmFtZX0gIT0gIiIpew0KDQoJXCRyZXN1bHRfeyRuYW1lfSA9IFwkZGJoLT5pbmxpbmVfcGRvX3F1ZXJ5KFwkcXVlcnlfZGVidWcsIFwkc3FsX3skbmFtZX0sIFwkZGJfaG9zdCwgXCRkYl90eXBlLCBcJG15c3FsX3NvY2tldCwgXCRteXNxbF9wb3J0LCBcJGRiZHNuLCBcJGRiX3VzZXIsIFwkZGJfcGFzcywgXCRkYl9jYXRhbG9nLCBcJHJldHVybl90cnVlID0gMCk7DQp9DQoNCi8vIGRvIHdlIGhhdmUgYSByZXN1bHQgdG8gcGFzcz8NCmlmKFwkcmVzdWx0X3skbmFtZX1bMF0pew0KDQoJLy8gbG9vcCB0aHJvdWdoIHJlc3VsdHMNCglmb3JlYWNoIChcJHJlc3VsdF97JG5hbWV9WzFdIGFzIFwkdCl7IA0KCQ0KCQlpZighaXNzZXQoXCR0W3skb3JkZXJfdn1dKSB8fCBcJHRbeyRvcmRlcl92fV0gPT0gJycpIHsgDQoJCQlcJHZhbHVlID0gXCR0W3skb3JkZXJfbH1dOyANCgkJfSBlbHNlIHsgDQoJCQlcJHZhbHVlID0gXCR0W3skb3JkZXJfdn1dOyANCgkJfQ0KCQkNCgkJLy8gc2V0IGNvdW50IHJvdyBsb2dpYw0KCQkhaXNzZXQoXCRjb3VudF97JG5hbWV9KSA/IFwkY291bnRfeyRuYW1lfSA9IDEgOiBcJGNvdW50X3skbmFtZX0rKzsNCgkNCgkJXCRjb3VudF9yb3dfeyRuYW1lfSsrOw0KCQlcJGNvdW50X3skbmFtZX0gPT0gMSB8fCBcJGNvdW50X3Jvd197JG5hbWV9ID09IDEgPyBwcmludCAnPGRpdiBjbGFzcz0iZmItbXVsdGlzZWxlY3QtY29sdW1uIHskc2VtYW50aWNfZ3JvdXBfY2xhc3NfbmFtZX0geyRmaWVsZC0+dHlwZX0tY29sdW1uIiBzdHlsZT0id2lkdGg6eyRjb2x1bW53aWR0aH07IHskZmJfbXVsdGlzZWxlY3RfY29sdW1uX2Zsb2F0fSI+JyA6IHByaW50ICcnOw0KCQk/Pg0KCQkNCgkJeyRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0fQ0KCQk8ZGl2IGNsYXNzPSJ7JHNlbWFudGljX2NsYXNzX25hbWV9Ij4gDQoJCTxsYWJlbCBmb3I9InskbmFtZX08P3BocCBlY2hvIFwkY291bnRfeyRuYW1lfTs/PiIgY2xhc3M9InskZmllbGQtPnR5cGV9LWlubGluZSB7JHNlbWFudGljX2NsYXNzX25hbWV9IHskbGFiZWxfY2xhc3NfY29kZX0iIHskaW5oZXJpdHN0eWxlfSA+DQoJCTxpbnB1dCB0eXBlPSJ7JGZpZWxkLT50eXBlfSIgbmFtZT0ieyRuYW1lfXskYnJhY2V9IiBpZD0ieyRpZH08P3BocCBlY2hvIFwkY291bnRfeyRuYW1lfTs/PiIgeyR0YWJodG1sfSB2YWx1ZT0iPD9waHAgZWNobyBcJHZhbHVlOyA/PiIgeyRpbmhlcml0c3R5bGV9IHskY2xhc3NfZGVmaW5pdGlvbn0geyRlbmFibGVkfSB7JHJlYWRvbmx5fQ0KCQkNCgkJeyRzZWxlY3RlZF9jb2RlX2RhdGFiYXNlfQ0KCQl7JGF0dHJpYnV0ZX0geyRjb25kaXRpb25hbF9jYWxsX2lubGluZX0gLz4NCgkJPHNwYW4gY2xhc3M9InJmLW11bHRpc2VsZWN0LWl0ZW0tbGFiZWwiIHskbGFiZWxfbWFyZ2lufT48P3BocCBlY2hvIGh0bWxlbnRpdGllcyhcJHRbeyRvcmRlcl9sfV0pOyA/Pjwvc3Bhbj4NCgkJPC9sYWJlbD4geyRpbmxpbmVfbGFiZWxfcG9zfQ0KCQk8L2Rpdj4NCgkJeyRtdWx0aXNlbGVjdF9pdGVtX2VuZH0NCgkJDQoJCTw/cGhwIA0KCQkJaWYoXCRjb3VudF9yb3dfeyRuYW1lfSA9PSBcJHJvd2NvdW50X3skbmFtZX0pIHsgDQoJCQkJZWNobyAnPC9kaXY+JzsgDQoJCQkJXCRjb3VudF9yb3dfeyRuYW1lfSA9IDA7IA0KCQkJfQ0KCQkJDQoJfSAvLyBmb3JlYWNoIGxvb3ANCgkNCn0gLy8gaWYgcmVzdWx0DQoNCj8+DQo8IS0tIFBvcHVsYXRlIEZpZWxkIEVuZCB7JG5hbWV9IC0tPg0KDQpFT1Q7DQogICAgICAgIH0gDQoNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKHN0cmluZykkcmFuZ2VvcHRpb25zLT5leHByZXNzaW9uICE9ICcnIHx8IChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+YXJyYXkgIT0gJycpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoc3Vic3RyX2NvdW50KChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+ZGVmYXVsdHZhbHVlLCAnJCcpID09IDEpIHsNCiAgICAgICAgICAgICAgICAkcmFuZ2VfZGVmYXVsdCA9ICRyYW5nZW9wdGlvbnMtPmRlZmF1bHR2YWx1ZTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHJhbmdlX2RlZmF1bHQgPSAiJyIgLiAkcmFuZ2VvcHRpb25zLT5kZWZhdWx0dmFsdWUgLiAiJyI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX3JhbmdlID0gIiI7DQogICAgICAgICAgICAkc2VsZWN0ZWRfY29kZV9hcnJheSA9ICIiOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIHN3aXRjaCAoKHN0cmluZykkZmllbGQtPnR5cGUpIHsNCiAgICAgICAgICAgICAgICBjYXNlICJjaGVja2JveCI6DQogICAgICAgICAgICAgICAgICAgICRicmFjZSA9ICJbXSI7DQogICAgICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX3JhbmdlID0gPDw8RU9IDQo8P3BocA0KaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsneyRuYW1lfSddKSAmJiBpbl9hcnJheShodG1sX2VudGl0eV9kZWNvZGUoXCRpLCBFTlRfUVVPVEVTKSwgXCRfU0VTU0lPTlsneyRuYW1lfSddKSB8fCBcJGkgPT0geyRyYW5nZV9kZWZhdWx0fSAmJiBcJF9TRVNTSU9OWyd7JG5hbWV9X2lzJ10gPT0gMSkgeyANCgllY2hvICdjaGVja2VkPSJjaGVja2VkIic7IA0KfQ0KPz4JCQkJDQpFT0g7DQoNCiAgICAgICAgICAgICAgICAgICAgJHNlbGVjdGVkX2NvZGVfYXJyYXkgPSA8PDxFT0gNCjw/cGhwDQppZihpc19hcnJheShcJF9TRVNTSU9OWyd7JG5hbWV9J10pICYmIGluX2FycmF5KGh0bWxfZW50aXR5X2RlY29kZShcJHZhbHVlLCBFTlRfUVVPVEVTKSwgXCRfU0VTU0lPTlsneyRuYW1lfSddKSB8fCBcJHZhbHVlID09IHskcmFuZ2VfZGVmYXVsdH0gJiYgXCRfU0VTU0lPTlsneyRuYW1lfV9pcyddID09IDEpIHsgDQoJZWNobyAnY2hlY2tlZD0iY2hlY2tlZCInOyANCn0NCj8+CQkJCQ0KRU9IOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgIGNhc2UgInJhZGlvIjoNCiAgICAgICAgICAgICAgICAgICAgJGJyYWNlID0gIiI7DQogICAgICAgICAgICAgICAgICAgICRzZWxlY3RlZF9jb2RlX3JhbmdlID0gPDw8RU9IDQo8P3BocA0KaWYoXCRfU0VTU0lPTlsneyRuYW1lfSddID09IGh0bWxfZW50aXR5X2RlY29kZShcJGksIEVOVF9RVU9URVMpIHx8IFwkaSA9PSB7JHJhbmdlX2RlZmF1bHR9ICYmIFwkX1NFU1NJT05bJ3skbmFtZX1faXMnXSA9PSAxKSB7IA0KCWVjaG8gJ2NoZWNrZWQ9ImNoZWNrZWQiJzsgDQp9DQo/PgkJCQkNCkVPSDsNCg0KICAgICAgICAgICAgICAgICAgICAkc2VsZWN0ZWRfY29kZV9hcnJheSA9IDw8PEVPSA0KPD9waHANCmlmKFwkX1NFU1NJT05bJ3skbmFtZX0nXSA9PSBodG1sX2VudGl0eV9kZWNvZGUoXCR2YWx1ZSwgRU5UX1FVT1RFUykgfHwgXCR2YWx1ZSA9PSB7JHJhbmdlX2RlZmF1bHR9ICYmIFwkX1NFU1NJT05bJ3skbmFtZX1faXMnXSA9PSAxKSB7IA0KCWVjaG8gJ2NoZWNrZWQ9ImNoZWNrZWQiJzsgDQp9DQo/PgkJCQkNCkVPSDsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJHJhbmdlb3B0aW9ucy0+ZXhwcmVzc2lvbiAhPSAnJykgew0KDQogICAgICAgICAgICAgICAgJHJhbmdlb3B0aW9ucy0+ZXhwcmVzc2lvbiA9IHN0cl9yZXBsYWNlKCdQSFB7JywgJyR7JywgJHJhbmdlb3B0aW9ucy0+ZXhwcmVzc2lvbik7DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0gNCjxkaXY+IDwhLS0gb3BlbiBtdWx0aS1zZWxlY3QgZGl2IC0tPg0KXG48P3BocA0KLy8gTG9vcCBUaHJvdWdoIFJhbmdlIEV4cHJlc3Npb24gUmVzdWx0cy4NCmZvcmVhY2ggKHskcmFuZ2VvcHRpb25zLT5leHByZXNzaW9ufSBhcyBcJGkpeyANCgkNCgkvLyBzZXQgY291bnQgcm93IGxvZ2ljDQoJIWlzc2V0KFwkY291bnRfeyRuYW1lfSkgPyBcJGNvdW50X3skbmFtZX0gPSAxIDogXCRjb3VudF97JG5hbWV9Kys7DQoNCglcJGNvdW50X3Jvd197JG5hbWV9Kys7DQoJXCRjb3VudF97JG5hbWV9ID09IDEgfHwgXCRjb3VudF9yb3dfeyRuYW1lfSA9PSAxID8gcHJpbnQgJzxzcGFuIGNsYXNzPSJmYi1tdWx0aXNlbGVjdC1jb2x1bW4geyRzZW1hbnRpY19ncm91cF9jbGFzc19uYW1lfSB7JGZpZWxkLT50eXBlfS1jb2x1bW4iIHN0eWxlPSJ3aWR0aDp7JGNvbHVtbndpZHRofTsgeyRmYl9tdWx0aXNlbGVjdF9jb2x1bW5fZmxvYXR9Ij4nIDogcHJpbnQgJyc7DQoJPz4NCgkNCgl7JG11bHRpc2VsZWN0X2l0ZW1fc3RhcnR9DQoJPGRpdiBjbGFzcz0ieyRzZW1hbnRpY19jbGFzc19uYW1lfSI+DQoJPGxhYmVsIGZvcj0ieyRuYW1lfTw/cGhwIGVjaG8gXCRjb3VudF97JG5hbWV9Oz8+IiBjbGFzcz0ieyRmaWVsZC0+dHlwZX0taW5saW5lIHskc2VtYW50aWNfY2xhc3NfbmFtZX0gPD9waHAgXCR2YWx1ZSA9IFwkaTsgPz4geyRsYWJlbF9jbGFzc19jb2RlfSIgeyRpbmhlcml0c3R5bGV9ID4NCgk8aW5wdXQgdHlwZT0ieyRmaWVsZC0+dHlwZX0iIG5hbWU9InskbmFtZX17JGJyYWNlfSIgaWQ9InskaWR9PD9waHAgZWNobyBcJGNvdW50X3skbmFtZX07Pz4iIHskdGFiaHRtbH0gdmFsdWU9Ijw/cGhwIGVjaG8gXCRpOz8+IiB7JGluaGVyaXRzdHlsZX0geyRjbGFzc19kZWZpbml0aW9ufSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9DQoJDQoJeyRzZWxlY3RlZF9jb2RlX3JhbmdlfQ0KCXskYXR0cmlidXRlfSB7JGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lfSAvPg0KCTxzcGFuIGNsYXNzPSJyZi1tdWx0aXNlbGVjdC1pdGVtLWxhYmVsIHJhbmdlLWV4cHJlc3Npb24iIHskbGFiZWxfbWFyZ2lufT48P3BocCBlY2hvIFwkaTsgPz48L3NwYW4+DQoJPC9sYWJlbD4geyRpbmxpbmVfbGFiZWxfcG9zfQ0KCTwvZGl2Pg0KCXskbXVsdGlzZWxlY3RfaXRlbV9lbmR9DQoJCQkJDQoJPD9waHAgDQoJCWlmKFwkY291bnRfcm93X3skbmFtZX0gPT0gXCRyb3djb3VudF97JG5hbWV9KSB7IA0KCQkJZWNobyAnPC9kaXY+JzsgDQoJCQlcJGNvdW50X3Jvd197JG5hbWV9ID0gMDsgDQoJCX0NCgkJDQp9IC8vIGZvcmVhY2ggbG9vcA0KPz5cbgkNCkVPSDsNCiAgICAgICAgICAgIH0gDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKHN0cmluZykkcmFuZ2VvcHRpb25zLT5hcnJheSAhPSAnJykgew0KDQogICAgICAgICAgICAgICAgJHJhbmdlb3B0aW9ucy0+YXJyYXkgPSBzdHJfcmVwbGFjZSgnUEhQeycsICckeycsICRyYW5nZW9wdGlvbnMtPmFycmF5KTsNCg0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPSA0KPGRpdj4gPCEtLSBvcGVuIG11bHRpLXNlbGVjdCBkaXYgLS0+DQpcbjw/cGhwDQovLyBMb29wIFRocm91Z2ggUmFuZ2UgQXJyYXkgUmVzdWx0cy4NCmZvcmVhY2goeyRyYW5nZW9wdGlvbnMtPmFycmF5fSBhcyBcJHQpIHsgDQoJaWYoaXNfYXJyYXkoXCR0KSl7DQoJCS8vIHR5cGljYWwgZGF0YWJhc2UgcXVlcnkgLT4gYXJyYXlbYXJyYXlbXSwgYXJyYXlbXV0NCgkJaWYoIWlzc2V0KFwkdFsxXSkgfHwgXCR0WzFdID09ICcnKSB7DQoJCQlcJGxhYmVsID0gXCR0WzBdOw0KCQkJXCR2YWx1ZSA9IFwkdFswXTsgDQoJCX0gZWxzZSB7DQoJCQlcJGxhYmVsID0gXCR0WzBdOw0KCQkJXCR2YWx1ZSA9IFwkdFsxXTsNCgkJfQ0KCX0gZWxzZSB7IC8vIHNpbXBsZSBhcnJheSAtPiBhcnJheVtuLG4sbl0NCgkJXCRsYWJlbCA9IFwkdDsNCgkJXCR2YWx1ZSA9IFwkdDsNCgl9IA0KCQ0KCS8vIHNldCBjb3VudCByb3cgbG9naWMNCgkhaXNzZXQoXCRjb3VudF97JG5hbWV9KSA/IFwkY291bnRfeyRuYW1lfSA9IDEgOiBcJGNvdW50X3skbmFtZX0rKzsNCg0KCVwkY291bnRfcm93X3skbmFtZX0rKzsNCglcJGNvdW50X3skbmFtZX0gPT0gMSB8fCBcJGNvdW50X3Jvd197JG5hbWV9ID09IDEgPyBwcmludCAnPHNwYW4gY2xhc3M9ImZiLW11bHRpc2VsZWN0LWNvbHVtbnskc2VtYW50aWNfZ3JvdXBfY2xhc3NfbmFtZX0geyRmaWVsZC0+dHlwZX0tY29sdW1uIiBzdHlsZT0id2lkdGg6eyRjb2x1bW53aWR0aH07IHskZmJfbXVsdGlzZWxlY3RfY29sdW1uX2Zsb2F0fSI+JyA6IHByaW50ICcnOw0KCT8+DQoJDQoJeyRtdWx0aXNlbGVjdF9pdGVtX3N0YXJ0fQ0KCTxkaXYgY2xhc3M9Inskc2VtYW50aWNfY2xhc3NfbmFtZX0iPg0KCTxsYWJlbCBmb3I9InskbmFtZX08P3BocCBlY2hvIFwkY291bnRfeyRuYW1lfTs/PiIgY2xhc3M9InskZmllbGQtPnR5cGV9LWlubGluZSB7JHNlbWFudGljX2NsYXNzX25hbWV9IHskbGFiZWxfY2xhc3NfY29kZX0iIHskaW5oZXJpdHN0eWxlfSA+DQoJPGlucHV0IHR5cGU9InskZmllbGQtPnR5cGV9IiBuYW1lPSJ7JG5hbWV9eyRicmFjZX0iIGlkPSJ7JGlkfTw/cGhwIGVjaG8gXCRjb3VudF97JG5hbWV9Oz8+IiB7JHRhYmh0bWx9IHZhbHVlPSI8P3BocCBlY2hvIGFkZHNsYXNoZXMoXCR2YWx1ZSk7Pz4iIHskaW5oZXJpdHN0eWxlfSB7JGNsYXNzX2RlZmluaXRpb259IHskZW5hYmxlZH0geyRyZWFkb25seX0NCgkNCgl7JHNlbGVjdGVkX2NvZGVfYXJyYXl9DQoJeyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IC8+DQoJPHNwYW4gY2xhc3M9InJmLW11bHRpc2VsZWN0LWl0ZW0tbGFiZWwgcmFuZ2UtYXJyYXkiIHskbGFiZWxfbWFyZ2lufT48P3BocCBlY2hvIGh0bWxlbnRpdGllcyhcJGxhYmVsKTsgPz48L3NwYW4+IA0KCTwvbGFiZWw+IHskaW5saW5lX2xhYmVsX3Bvc30NCgk8L2Rpdj4NCgl7JG11bHRpc2VsZWN0X2l0ZW1fZW5kfQ0KCQkJCQ0KCTw/cGhwIA0KCQlpZihcJGNvdW50X3Jvd197JG5hbWV9ID09IFwkcm93Y291bnRfeyRuYW1lfSkgeyANCgkJCWVjaG8gJzwvZGl2Pic7IA0KCQkJXCRjb3VudF9yb3dfeyRuYW1lfSA9IDA7IA0KCQl9DQoJCQ0KfSAvLyBmb3JlYWNoIGxvb3ANCj8+XG4NCkVPSDsNCiAgICAgICAgICAgIH0gDQogICAgICAgIH0gDQoNCg0KDQoNCg0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG48P3BocCBpZihcJGNvdW50X3Jvd197JG5hbWV9ICE9IDApIHsgZWNobyAnPC9kaXY+JzsgfSA/PiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQo8P3BocA0KLy8gRXZlbiBpZiB3ZSBoYXZlIG5vIHJlc3VsdHMgd2Ugc3RpbGwgY3JlYXRlIGEgY29sdW1uIGZvciBBSkFYIGNhbGxzLg0KaWYoXCRjb3VudF9yb3dfeyRuYW1lfSA9PSAwKXsNCgllY2hvICI8ZGl2IGNsYXNzPVwiZmItbXVsdGlzZWxlY3QtY29sdW1uIHskZmllbGQtPnR5cGV9LWNvbHVtblwiIHN0eWxlPVwid2lkdGg6eyRjb2x1bW53aWR0aH07IHskZmJfbXVsdGlzZWxlY3RfY29sdW1uX2Zsb2F0fVwiID48L2Rpdj4iOw0KfQ0KPz4NCg0KRU9GOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG4iIC4gJzxkaXYgY2xhc3M9ImZiLWNoZWNrYm94LWNsZWFyIiBzdHlsZT0iY2xlYXI6Ym90aDsiPjwvZGl2PicgLiAiXG4iOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgISR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PjwhLS0gQ2xvc2UgVGFibGUgTW9kZSAtLT4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICc8L2ZpZWxkc2V0Pic7DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KDQogICAgfSANCg0KDQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZmlsZV91cGxvYWRfc3BlYygkbWF4LCAkbW9kZSkNCiAgICB7DQogICAgICAgIHN3aXRjaCAoJG1heCkgew0KICAgICAgICAgICAgY2FzZSAnMCc6DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJG1heCA9ICR0aGlzLT5yZXR1cm5fYnl0ZXMoaW5pX2dldCgndXBsb2FkX21heF9maWxlc2l6ZScpKTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzEnOiANCiAgICAgICAgICAgICAgICAkbWF4ID0gNjU1MzY7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzogDQogICAgICAgICAgICAgICAgJG1heCA9IDEzMTA3MjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzMnOiANCiAgICAgICAgICAgICAgICAkbWF4ID0gMjYyMTQ0Ow0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNCc6IA0KICAgICAgICAgICAgICAgICRtYXggPSA1MjQyODg7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc1JzogDQogICAgICAgICAgICAgICAgJG1heCA9IDEwNDg1NzY7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc2JzogDQogICAgICAgICAgICAgICAgJG1heCA9IDIwOTcxNTI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc3JzogDQogICAgICAgICAgICAgICAgJG1heCA9IDMxNDU3Mjg7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc4JzogDQogICAgICAgICAgICAgICAgJG1heCA9IDUyNDI4ODA7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc5JzogDQogICAgICAgICAgICAgICAgJG1heCA9IDgzODg2MDg7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxMCc6IA0KICAgICAgICAgICAgICAgICRtYXggPSAxNTcyODY0MDsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkbW9kZSA9PSAnZnVsbCcpIHsNCiAgICAgICAgICAgICRlbGVtZW50ID0gIjxpbnB1dCBuYW1lPVwiTUFYX0ZJTEVfU0laRVwiIHR5cGU9XCJoaWRkZW5cIiB2YWx1ZT1cInskbWF4fVwiIC8+IjsNCiAgICAgICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHJldHVybiAkbWF4Ow0KICAgICAgICB9DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9maWxlKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+bGFiZWw7DQogICAgICAgICRuYW1lID0gJGZpZWxkLT5uYW1lOw0KICAgICAgICAkaWQgPSAkZmllbGQtPmlkOw0KICAgICAgICAkcmVxID0gJGZpZWxkLT52YWxpZGF0aW9uLT5yZXE7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGZpZWxkd2lkdGggPSAkZmllbGQtPmZpZWxkd2lkdGg7DQogICAgICAgICRoZWxwZXIgPSAkZmllbGQtPmhlbHBlcjsNCgkJJGhlbHBlcmNvbG9yID0gJGZpZWxkLT5oZWxwZXJjb2xvcjsNCgkJJHJlYWRvbmx5ID0gaXNzZXQoJGZpZWxkLT5yZWFkb25seSkgPyAkZmllbGQtPnJlYWRvbmx5IDogMDsNCiAgICAgICAgJGZpZWxkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRlbmFibGVkKSA/ICRmaWVsZC0+ZmllbGRlbmFibGVkIDogMTsNCiAgICAgICAgJGF0dHJpYnV0ZSA9ICRmaWVsZC0+YXR0cmlidXRlOw0KICAgICAgICAkYXR0cmlidXRlc3R5bGUgPSAkZmllbGQtPmF0dHJpYnV0ZXN0eWxlOw0KICAgICAgICAkY29uZGl0aW9uYWwgPSAkZmllbGQtPmNvbmRpdGlvbmFsOw0KICAgICAgICAkc3R5bGUgPSAkZmllbGQtPnN0eWxlOw0KICAgICAgICAkdG9vbHRpcCA9ICRmaWVsZC0+dG9vbHRpcDsNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCg0KDQogICAgICAgIA0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYgKCRsYWJlbCA9PSAiIikgew0KICAgICAgICAgICAgJGxhYmVsID0gIiZuYnNwOyI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICAkdG9vbHRpcF9lbGVtZW50ID0gJHRoaXMtPnRyYW5zbGF0ZVRvb2x0aXAoJHRvb2x0aXAsICRpZCk7DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF9jYWxsID0gJHRoaXMtPl9jcmVhdGVDb25kaXRpb25hbEV2ZW50KCRjb25kaXRpb25hbCwgJG5hbWUsICRpZCk7DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICRjb25kaXRpb25hbF9jYWxsWzBdOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAkY29uZGl0aW9uYWxfY2FsbFsxXTsNCg0KDQogICAgICAgIA0KDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdwdCcpOw0KICAgICAgICAkY3QyID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHgnKTsNCg0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJGZvbnRzaXplID0gJGZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdGVzdCA9IChpbnQpJGluaGVyaXRzdHlsZTsNCiAgICAgICAgaWYgKCR0ZXN0ICE9IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAwOw0KICAgICAgICB9DQogICAgICAgIGlmICgkaW5oZXJpdHN0eWxlID09IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiZm9udC1zaXplOnskZm9udHNpemV9OyBjb2xvcjp7JGlucHV0X2NvbG9yfTsgZm9udC1mYW1pbHk6aW5oZXJpdDsgeyRhdHRyaWJ1dGVzdHlsZX0gXCIgIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiIGNvbG9yOnskaW5wdXRfY29sb3J9OyB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmxlZnRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskZml4ZWRfd2lkdGh9cHg7IG1hcmdpbi1yaWdodDo4cHg7IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufVwiID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJG5hbWUsICRyZXEsICRyZXF1aXJlZF90ZXh0LCAkY29sb3IsICRmb250c2l6ZSwgJHN0eWxlcywgJGxhYmVsLCAkbGFiZWxwb3MsIChzdHJpbmcpJGZpZWxkLT50eXBlLCAkdG9vbHRpcCwgJycsICR0YWJsZW1vZGUpOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxueyRjb25kaXRpb25hbF9jYWxsX3NjcmlwdH1cbiI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkbWF4X2ZpbGVfc2l6ZSA9ICR0aGlzLT5jcmVhdGVfZmlsZV91cGxvYWRfc3BlYygkZmllbGQtPm1heGZpbGVzaXplLCAnc2hvcnQnKTsgDQoNCiAgICAgICAgJGpzX2NoZWNrID0gPDw8RU9GDQpcbjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCmZ1bmN0aW9uIGNoZWNrU2l6ZV97JGZpZWxkLT5uYW1lfSgpDQp7DQogICAgdmFyIGlucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInskbmFtZX0iKTsNCiAgICANCiAgICAvLyBjaGVjayBmb3IgYnJvd3NlciBzdXBwb3J0IChtYXkgbmVlZCB0byBiZSBtb2RpZmllZCkNCiAgICANCiAgICBpZihpbnB1dC5maWxlcyAmJiBpbnB1dC5maWxlcy5sZW5ndGggPT0gMSkNCiAgICB7ICAgICAgICAgICANCiAgICAgICAgY29uc29sZS5sb2coJ0ZpbGUgRGVidWc6IE1heCBTaXplIChCeXRlcyk6JywgeyRtYXhfZmlsZV9zaXplfSwgJ0FjdHVhbCBGaWxlIFNpemUgKEJ5dGVzKTonLCBpbnB1dC5maWxlc1swXS5zaXplKTsNCiAgICAgICAgDQogICAgICAgIGlmIChpbnB1dC5maWxlc1swXS5zaXplID4geyRtYXhfZmlsZV9zaXplfSkgDQogICAgICAgIHsNCiAgICAgICAgICAgIGFsZXJ0KCJUaGUgZmlsZSBtdXN0IGJlIGxlc3MgdGhhbiAiICsgKHskbWF4X2ZpbGVfc2l6ZX0gLyAxMDI0IC8gMTAyNCkgKyAiIE1CIik7DQoNCiAgICAgICAgICAgIGlucHV0LnZhbHVlID0gIiI7DQoNCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsNCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIHJldHVybiB0cnVlOw0KfQ0KPC9zY3JpcHQ+DQoNCkVPRjsNCg0KDQogICAgICAgICRlbGVtZW50IC49ICRqc19jaGVjazsNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAnODUlJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5leHRyYWNsYXNzbmFtZSkgJiYgJGZpZWxkLT5leHRyYWNsYXNzbmFtZSAhPSAiIikgew0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICRmaWVsZC0+ZXh0cmFjbGFzc25hbWU7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPmNyZWF0ZV90YWJsZV9tb2RlX21vYmlsZV9sYWJlbCgkZmllbGQsJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRyZWFkb25seSkgPyAkcmVhZG9ubHkgPT0gMSA/ICIgcmVhZG9ubHkgIiA6ICIiIDogIiI7DQogICAgICAgICRlbmFibGVkID0gaXNzZXQoJGZpZWxkZW5hYmxlZCkgPyAkZmllbGRlbmFibGVkID09IDAgPyAiIGRpc2FibGVkICIgOiAiIiA6ICIiOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgaWYoaXNzZXQoJGZpZWxkLT5idWNrZXQpICYmICRmaWVsZC0+YnVja2V0ICE9ICIiKXsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyAuPSAiIGJ1Y2tldC1jb250YWluZWQtZmllbGQiOw0KICAgICAgICAgICAgDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcbjxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gc2l6ZT1cInskZmllbGR3aWR0aH1cIiBjbGFzcz1cInskZXh0cmFjbGFzc25hbWVzfVwiIHR5cGU9XCJmaWxlXCIgbmFtZT1cInskbmFtZX1cIiBpZD1cInskaWR9XCIgeyR0YWJodG1sfSB7JGluaGVyaXRzdHlsZX0geyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IG9uY2hhbmdlPVwiY2hlY2tTaXplX3skZmllbGQtPm5hbWV9KCk7XCIgeyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPlxuIjsNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZidG9vbHRpcC17JGlkfSBmYnRvb2x0aXBcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj57JHRvb2x0aXBfZWxlbWVudC0+dGV4dH08L2Rpdj5cbiI7DQogICAgICAgICRlbGVtZW50IC49ICR0b29sdGlwX2VsZW1lbnQtPmpzOw0KDQogICAgICAgIGlmICgkaGVscGVyICE9ICcnKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPGJyLz48ZGl2IGNsYXNzPVwiaGVscGVyXCIgc3R5bGU9XCJjb2xvcjp7JGhlbHBlcmNvbG9yfTtcIj57JGhlbHBlcn08L2Rpdj4iOw0KICAgICAgICB9DQogICAgICAgICRlbGVtZW50IC49ICc8YnIgLz4nOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9qcXVlcnlfZmlsZSgkZmllbGQsICRwYWdlLCAkeG1sLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJHRhYmxlbW9kZSA9ICRwYWdlLT50YWJsZW1vZGU7DQoNCiAgICAgICAgJGZvcm1uYW1lID0gJHBhZ2UtPmZvcm0tPm5hbWU7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQogICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7DQogICAgICAgICRyZXEgPSAkZmllbGQtPnZhbGlkYXRpb24tPnJlcTsNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT5jb2xvcjsNCiAgICAgICAgJGlucHV0X2NvbG9yID0gJGZpZWxkLT5pbnB1dF9jb2xvcjsNCiAgICAgICAgJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCiAgICAgICAgJGxhYmVscG9zID0gJGZpZWxkLT5sYWJlbHBvczsNCiAgICAgICAgJGluaGVyaXRzdHlsZSA9ICRmaWVsZC0+aW5oZXJpdHN0eWxlOw0KICAgICAgICAkZmllbGR3aWR0aCA9ICRmaWVsZC0+ZmllbGR3aWR0aDsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICR0b29sdGlwID0gJGZpZWxkLT50b29sdGlwOw0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KDQogICAgICAgIA0KICAgICAgICAkdGhpcy0+dW0tPnB1bGxDdXN0b21Db25uZWN0b3JGaWxlKChzdHJpbmcpJGZpZWxkLT5kYmNvbm5lY3Rvcik7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGxhYmVsID09ICIiKSB7DQogICAgICAgICAgICAkbGFiZWwgPSAiJm5ic3A7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRzdHlsZSk7DQoNCiAgICAgICAgDQogICAgICAgICR0b29sdGlwX2VsZW1lbnQgPSAkdGhpcy0+dHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGlkKTsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICR0ZXN0ID0gKGludCkkaW5oZXJpdHN0eWxlOw0KICAgICAgICBpZiAoJHRlc3QgIT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9IDA7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCRpbmhlcml0c3R5bGUgPT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCJmb250LXNpemU6eyRmb250c2l6ZX07IGNvbG9yOnskaW5wdXRfY29sb3J9OyBmb250LWZhbWlseTppbmhlcml0OyB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCIgY29sb3I6eyRpbnB1dF9jb2xvcn07IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+bGVmdGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyRmaXhlZF93aWR0aH1weDsgbWFyZ2luLXJpZ2h0OjhweDsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259XCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgJHJlcSwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsICRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUsICR0b29sdGlwLCAnJywgJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRtYXhfZmlsZV9zaXplID0gJHRoaXMtPmNyZWF0ZV9maWxlX3VwbG9hZF9zcGVjKCRmaWVsZC0+bWF4ZmlsZXNpemUsICdzaG9ydCcpOyANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgICRhY2NlcHRlZF90eXBlc19qcyA9ICIvKFxcLnxcXC8pKGdpZnxqcGU/Z3xwbmcpJC9pIjsgDQogICAgICAgICRhY2NlcHRlZF90eXBlc19waHAgPSAiJy8uKyQvaSciOw0KDQogICAgICAgIA0KICAgICAgICAkbWF4X2ZpbGVfc2l6ZV9qcyA9ICR0aGlzLT5waHBfZWxlbWVudHMtPnRyYW5zbGF0ZU1heFZhbHVlKCRmaWVsZC0+bWF4ZmlsZXNpemUpOw0KICAgICAgICAkbWF4X2ZpbGVfc2l6ZV9waHAgPSAkbWF4X2ZpbGVfc2l6ZV9qczsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIHN3aXRjaCAoJGZpZWxkLT5hbGxvd2VkKSB7DQogICAgICAgICAgICBjYXNlICcwJzogDQogICAgICAgICAgICAgICAgJGFjY2VwdGVkX3R5cGVzX2pzID0gJy8oXC58XC8pKCg/IXBocHxwaHBcZHxleGV8YXBwKS4pKiQvaSc7DQogICAgICAgICAgICAgICAgJGFjY2VwdGVkX3R5cGVzX3BocCA9ICcvKFwufFwvKSgoPyFwaHB8cGhwXGR8ZXhlfGFwcCkuKSokL2knOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6IA0KICAgICAgICAgICAgICAgICRhY2NlcHRlZF90eXBlc19qcyA9ICcvKFwufFwvKShnaWZ8anBlP2d8cG5nKSQvaSc7DQogICAgICAgICAgICAgICAgJGFjY2VwdGVkX3R5cGVzX3BocCA9ICcvXC4oZ2lmfGpwZT9nfHBuZykkL2knOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMic6IA0KICAgICAgICAgICAgICAgICRhY2NlcHRlZF90eXBlc19qcyA9ICcvKFwufFwvKSgoPyFnaWZ8anBlP2d8cG5nfHBocHxwaHBcZHxleGV8YXBwKS4pKiQvaWcnOw0KICAgICAgICAgICAgICAgICRhY2NlcHRlZF90eXBlc19waHAgPSAnLyhcLnxcLykoKD8hZ2lmfGpwZT9nfHBuZ3xwaHB8cGhwXGR8ZXhlfGFwcCkuKSokL2knOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMyc6IA0KICAgICAgICAgICAgICAgICRhY2NlcHRlZF90eXBlc19qcyA9ICcvKFwufFwvKShwZGYpJC9pJzsNCiAgICAgICAgICAgICAgICAkYWNjZXB0ZWRfdHlwZXNfcGhwID0gJy9cLihwZGYpJC9pJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzQnOiANCiAgICAgICAgICAgICAgICAkYWNjZXB0ZWRfdHlwZXNfanMgPSAnLyhcLnxcLykoemlwKSQvaSc7DQogICAgICAgICAgICAgICAgJGFjY2VwdGVkX3R5cGVzX3BocCA9ICcvXC4oemlwKSQvaSc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc1JzogDQogICAgICAgICAgICAgICAgJGFjY2VwdGVkX3R5cGVzX2pzID0gJy8oXC58XC8pKGRvY3xkb2N4fHhsc3x4bHN4fHBkZnxjc3YpJC9pJzsNCiAgICAgICAgICAgICAgICAkYWNjZXB0ZWRfdHlwZXNfcGhwID0gJy9cLihkb2N8ZG9jeHx4bHN8eGxzeHxwZGZ8Y3N2KSQvaSc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0gDQoNCg0KICAgICAgICAkY29yZV9pbmNsdWRlcyA9IDw8PEVPRg0KDQo8IS0tIEJvb3RzdHJhcCBzdHlsZXMgLS0+DQo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImxpYi9qcXVlcnktdXBsb2FkL2Nzcy9ib290c3RyYXAzLWdyaWQrYnV0dG9ucy5jc3MiPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJsaWIvanF1ZXJ5LXVwbG9hZC9jc3MvZ2x5cGhpY29ucy5jc3MiPg0KCQkNCjwhLS0gR2VuZXJpYyBwYWdlIHN0eWxlcyAtLT4NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0ibGliL2pxdWVyeS11cGxvYWQvY3NzL3N0eWxlLmNzcyI+DQoJCQkJDQo8IS0tIGJsdWVpbXAgR2FsbGVyeSBzdHlsZXMgLS0+DQo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii8vYmx1ZWltcC5naXRodWIuaW8vR2FsbGVyeS9jc3MvYmx1ZWltcC1nYWxsZXJ5Lm1pbi5jc3MiPg0KCQkJCQ0KPCEtLSBDU1MgdG8gc3R5bGUgdGhlIGZpbGUgaW5wdXQgZmllbGQgYXMgYnV0dG9uIGFuZCBhZGp1c3QgdGhlIEJvb3RzdHJhcCBwcm9ncmVzcyBiYXJzIC0tPg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJsaWIvanF1ZXJ5LXVwbG9hZC9jc3MvanF1ZXJ5LmZpbGV1cGxvYWQuY3NzIj4NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0ibGliL2pxdWVyeS11cGxvYWQvY3NzL2pxdWVyeS5maWxldXBsb2FkLXVpLmNzcyI+DQoJCQkJDQo8IS0tIENTUyBhZGp1c3RtZW50cyBmb3IgYnJvd3NlcnMgd2l0aCBKYXZhU2NyaXB0IGRpc2FibGVkIC0tPg0KPG5vc2NyaXB0PjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0ibGliL2pxdWVyeS11cGxvYWQvY3NzL2pxdWVyeS5maWxldXBsb2FkLW5vc2NyaXB0LmNzcyI+PC9ub3NjcmlwdD4NCjxub3NjcmlwdD48bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImxpYi9qcXVlcnktdXBsb2FkL2Nzcy9qcXVlcnkuZmlsZXVwbG9hZC11aS1ub3NjcmlwdC5jc3MiPjwvbm9zY3JpcHQ+DQoJDQpFT0Y7DQoNCg0KICAgICAgICAkZWxlbWVudCAuPSAkY29yZV9pbmNsdWRlczsNCg0KICAgICAgICAkYXV0b3VwbG9hZF9odG1sID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+anF1ZXJ5YXV0bykgJiYgJGZpZWxkLT5qcXVlcnlhdXRvID09IDEpIHsNCiAgICAgICAgICAgICRhdXRvdXBsb2FkX2h0bWwgPSA8PDxFT0YNCjxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IHN0YXJ0Ij4NCgk8aSBjbGFzcz0iZ2x5cGhpY29uIGdseXBoaWNvbi11cGxvYWQiPjwvaT4NCgk8c3Bhbj5TdGFydCB1cGxvYWQ8L3NwYW4+DQo8L2J1dHRvbj4NCjxidXR0b24gdHlwZT0icmVzZXQiIGNsYXNzPSJidG4gYnRuLXdhcm5pbmcgY2FuY2VsIj4NCgk8aSBjbGFzcz0iZ2x5cGhpY29uIGdseXBoaWNvbi1iYW4tY2lyY2xlIj48L2k+DQoJPHNwYW4+Q2FuY2VsIHVwbG9hZDwvc3Bhbj4NCjwvYnV0dG9uPg0KRU9GOw0KICAgICAgICB9DQoNCg0KICAgICAgICAkYm9keV9pbmNsdWRlcyA9IDw8PEVPRg0KDQo8IS0tIFJlZGlyZWN0IGJyb3dzZXJzIHdpdGggSmF2YVNjcmlwdCBkaXNhYmxlZCB0byB0aGUgb3JpZ2luIHBhZ2UgLS0+DQoNCjwhLS0gVGhlIGZpbGV1cGxvYWQtYnV0dG9uYmFyIGNvbnRhaW5zIGJ1dHRvbnMgdG8gYWRkL2RlbGV0ZSBmaWxlcyBhbmQgc3RhcnQvY2FuY2VsIHRoZSB1cGxvYWQgLS0+DQo8ZGl2IGNsYXNzPSJyb3cgZmlsZXVwbG9hZC1idXR0b25iYXIiPg0KCTxkaXYgY2xhc3M9ImNvbC1sZy03IHRvcC14bCI+DQoJCTwhLS0gVGhlIGZpbGVpbnB1dC1idXR0b24gc3BhbiBpcyB1c2VkIHRvIHN0eWxlIHRoZSBmaWxlIGlucHV0IGZpZWxkIGFzIGJ1dHRvbiAtLT4NCgkJPHNwYW4gY2xhc3M9ImJ0biBidG4tc3VjY2VzcyBmaWxlaW5wdXQtYnV0dG9uIj4NCgkJCTxpIGNsYXNzPSJnbHlwaGljb24gZ2x5cGhpY29uLXBsdXMiPjwvaT4NCgkJCTxzcGFuPkFkZCBmaWxlcy4uLjwvc3Bhbj4NCgkJCTxpbnB1dCB0eXBlPSJmaWxlIiBuYW1lPSJmaWxlc1tdIiBtdWx0aXBsZT4NCgkJPC9zcGFuPg0KCQl7JGF1dG91cGxvYWRfaHRtbH0NCgkJPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLWRhbmdlciBkZWxldGUiPg0KCQkJPGkgY2xhc3M9ImdseXBoaWNvbiBnbHlwaGljb24tdHJhc2giPjwvaT4NCgkJCTxzcGFuPkRlbGV0ZTwvc3Bhbj4NCgkJPC9idXR0b24+DQoJCTxpbnB1dCB0eXBlPSJjaGVja2JveCIgY2xhc3M9InRvZ2dsZSI+DQoJCTwhLS0gVGhlIGdsb2JhbCBmaWxlIHByb2Nlc3Npbmcgc3RhdGUgLS0+DQoJCTxzcGFuIGNsYXNzPSJmaWxldXBsb2FkLXByb2Nlc3MiPjwvc3Bhbj4NCiAgICA8L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPSJjb2wtbGctNyB0b3AteGwiPg0KICAgICAgICA8aT5IaW50OiBEcmFnIEZpbGVzIEFueXdoZXJlIE9uIFRoaXMgUGFnZSBUbyBVcGxvYWQhPC9pPg0KICAgIDwvZGl2Pg0KCTwhLS0gVGhlIGdsb2JhbCBwcm9ncmVzcyBzdGF0ZSAtLT4NCgk8ZGl2IGNsYXNzPSJjb2wtbGctNSBmaWxldXBsb2FkLXByb2dyZXNzIGZhZGUiPg0KCQk8IS0tIFRoZSBnbG9iYWwgcHJvZ3Jlc3MgYmFyIC0tPg0KCQk8ZGl2IGNsYXNzPSJwcm9ncmVzcyBwcm9ncmVzcy1zdHJpcGVkIGFjdGl2ZSIgcm9sZT0icHJvZ3Jlc3NiYXIiIGFyaWEtdmFsdWVtaW49IjAiIGFyaWEtdmFsdWVtYXg9IjEwMCI+DQoJCQk8ZGl2IGNsYXNzPSJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3MiIHN0eWxlPSJ3aWR0aDowJTsiPjwvZGl2Pg0KCQk8L2Rpdj4NCgkJPCEtLSBUaGUgZXh0ZW5kZWQgZ2xvYmFsIHByb2dyZXNzIHN0YXRlIC0tPg0KCQk8ZGl2IGNsYXNzPSJwcm9ncmVzcy1leHRlbmRlZCI+Jm5ic3A7PC9kaXY+DQoJPC9kaXY+DQo8L2Rpdj4NCjwhLS0gVGhlIHRhYmxlIGxpc3RpbmcgdGhlIGZpbGVzIGF2YWlsYWJsZSBmb3IgdXBsb2FkL2Rvd25sb2FkIC0tPg0KPHRhYmxlIHJvbGU9InByZXNlbnRhdGlvbiIgY2xhc3M9InRhYmxlIHRhYmxlLXN0cmlwZWQiPjx0Ym9keSBjbGFzcz0iZmlsZXMiPjwvdGJvZHk+PC90YWJsZT4NCgkNCkVPRjsNCg0KICAgICAgICAkZWxlbWVudCAuPSAkYm9keV9pbmNsdWRlczsNCg0KDQogICAgICAgICR3aWRnZXRfaW5jbHVkZXMgPSA8PDxFT0YNCg0KPCEtLSBUaGUgYmx1ZWltcCBHYWxsZXJ5IHdpZGdldCAtLT4NCjxkaXYgaWQ9ImJsdWVpbXAtZ2FsbGVyeSIgY2xhc3M9ImJsdWVpbXAtZ2FsbGVyeSBibHVlaW1wLWdhbGxlcnktY29udHJvbHMiIGRhdGEtZmlsdGVyPSI6ZXZlbiI+DQogICAgPGRpdiBjbGFzcz0ic2xpZGVzIj48L2Rpdj4NCiAgICA8aDMgY2xhc3M9InRpdGxlIj48L2gzPg0KICAgIDxhIGNsYXNzPSJwcmV2Ij7igLk8L2E+DQogICAgPGEgY2xhc3M9Im5leHQiPuKAujwvYT4NCiAgICA8YSBjbGFzcz0iY2xvc2UiPsOXPC9hPg0KICAgIDxhIGNsYXNzPSJwbGF5LXBhdXNlIj48L2E+DQogICAgPG9sIGNsYXNzPSJpbmRpY2F0b3IiPjwvb2w+DQo8L2Rpdj4NCjwhLS0gVGhlIHRlbXBsYXRlIHRvIGRpc3BsYXkgZmlsZXMgYXZhaWxhYmxlIGZvciB1cGxvYWQgLS0+DQo8c2NyaXB0IGlkPSJ0ZW1wbGF0ZS11cGxvYWQiIHR5cGU9InRleHQveC10bXBsIj4NCnslIGZvciAodmFyIGk9MCwgZmlsZTsgZmlsZT1vLmZpbGVzW2ldOyBpKyspIHsgJX0NCiAgICA8dHIgY2xhc3M9InRlbXBsYXRlLXVwbG9hZCBmYWRlIj4NCiAgICAgICAgPHRkPg0KICAgICAgICAgICAgPHNwYW4gY2xhc3M9InByZXZpZXciPjwvc3Bhbj4NCiAgICAgICAgPC90ZD4NCiAgICAgICAgPHRkPg0KICAgICAgICAgICAgPHAgY2xhc3M9Im5hbWUiPnslPWZpbGUubmFtZSV9PC9wPg0KICAgICAgICAgICAgPHN0cm9uZyBjbGFzcz0iZXJyb3IgdGV4dC1kYW5nZXIiPjwvc3Ryb25nPg0KICAgICAgICA8L3RkPg0KICAgICAgICA8dGQ+DQogICAgICAgICAgICA8cCBjbGFzcz0ic2l6ZSI+UHJvY2Vzc2luZy4uLjwvcD4NCiAgICAgICAgICAgIDxkaXYgY2xhc3M9InByb2dyZXNzIHByb2dyZXNzLXN0cmlwZWQgYWN0aXZlIiByb2xlPSJwcm9ncmVzc2JhciIgYXJpYS12YWx1ZW1pbj0iMCIgYXJpYS12YWx1ZW1heD0iMTAwIiBhcmlhLXZhbHVlbm93PSIwIj48ZGl2IGNsYXNzPSJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3MiIHN0eWxlPSJ3aWR0aDowJTsiPjwvZGl2PjwvZGl2Pg0KICAgICAgICA8L3RkPg0KICAgICAgICA8dGQ+DQogICAgICAgICAgICB7JSBpZiAoIWkgJiYgIW8ub3B0aW9ucy5hdXRvVXBsb2FkKSB7ICV9DQogICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IHN0YXJ0IiBkaXNhYmxlZD4NCiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9ImdseXBoaWNvbiBnbHlwaGljb24tdXBsb2FkIj48L2k+DQogICAgICAgICAgICAgICAgICAgIDxzcGFuPlN0YXJ0PC9zcGFuPg0KICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgeyUgfSAlfQ0KICAgICAgICAgICAgeyUgaWYgKCFpKSB7ICV9DQogICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi13YXJuaW5nIGNhbmNlbCI+DQogICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPSJnbHlwaGljb24gZ2x5cGhpY29uLWJhbi1jaXJjbGUiPjwvaT4NCiAgICAgICAgICAgICAgICAgICAgPHNwYW4+Q2FuY2VsPC9zcGFuPg0KICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgeyUgfSAlfQ0KICAgICAgICA8L3RkPg0KICAgIDwvdHI+DQp7JSB9ICV9DQo8L3NjcmlwdD4NCjwhLS0gVGhlIHRlbXBsYXRlIHRvIGRpc3BsYXkgZmlsZXMgYXZhaWxhYmxlIGZvciBkb3dubG9hZCAtLT4NCjxzY3JpcHQgaWQ9InRlbXBsYXRlLWRvd25sb2FkIiB0eXBlPSJ0ZXh0L3gtdG1wbCI+DQp7JSBmb3IgKHZhciBpPTAsIGZpbGU7IGZpbGU9by5maWxlc1tpXTsgaSsrKSB7ICV9DQogICAgPHRyIGNsYXNzPSJ0ZW1wbGF0ZS1kb3dubG9hZCBmYWRlIj4NCiAgICAgICAgPHRkPg0KICAgICAgICAgICAgPHNwYW4gY2xhc3M9InByZXZpZXciPg0KICAgICAgICAgICAgICAgIHslIGlmIChmaWxlLnRodW1ibmFpbFVybCkgeyAlfQ0KICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSJ7JT1maWxlLnVybCV9IiB0aXRsZT0ieyU9ZmlsZS5uYW1lJX0iIGRvd25sb2FkPSJ7JT1maWxlLm5hbWUlfSIgZGF0YS1nYWxsZXJ5PjxpbWcgc3JjPSJ7JT1maWxlLnRodW1ibmFpbFVybCV9Ij48L2E+DQogICAgICAgICAgICAgICAgeyUgfSAlfQ0KICAgICAgICAgICAgPC9zcGFuPg0KICAgICAgICA8L3RkPg0KICAgICAgICA8dGQ+DQogICAgICAgICAgICA8cCBjbGFzcz0ibmFtZSI+DQogICAgICAgICAgICAgICAgeyUgaWYgKGZpbGUudXJsKSB7ICV9DQogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9InslPWZpbGUudXJsJX0iIHRpdGxlPSJ7JT1maWxlLm5hbWUlfSIgZG93bmxvYWQ9InslPWZpbGUubmFtZSV9IiB7JT1maWxlLnRodW1ibmFpbFVybD8nZGF0YS1nYWxsZXJ5JzonJyV9PnslPWZpbGUubmFtZSV9PC9hPg0KICAgICAgICAgICAgICAgIHslIH0gZWxzZSB7ICV9DQogICAgICAgICAgICAgICAgICAgIDxzcGFuPnslPWZpbGUubmFtZSV9PC9zcGFuPg0KICAgICAgICAgICAgICAgIHslIH0gJX0NCiAgICAgICAgICAgIDwvcD4NCiAgICAgICAgICAgIHslIGlmIChmaWxlLmVycm9yKSB7ICV9DQogICAgICAgICAgICAgICAgPGRpdj48c3BhbiBjbGFzcz0ibGFiZWwgbGFiZWwtZGFuZ2VyIj5FcnJvcjwvc3Bhbj4geyU9ZmlsZS5lcnJvciV9PC9kaXY+DQogICAgICAgICAgICB7JSB9ICV9DQogICAgICAgIDwvdGQ+DQogICAgICAgIDx0ZD4NCiAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJzaXplIj57JT1vLmZvcm1hdEZpbGVTaXplKGZpbGUuc2l6ZSklfTwvc3Bhbj4NCiAgICAgICAgPC90ZD4NCiAgICAgICAgPHRkPg0KICAgICAgICAgICAgeyUgaWYgKGZpbGUuZGVsZXRlVXJsKSB7ICV9DQogICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1kYW5nZXIgZGVsZXRlIiBkYXRhLXR5cGU9InslPWZpbGUuZGVsZXRlVHlwZSV9IiBkYXRhLXVybD0ieyU9ZmlsZS5kZWxldGVVcmwlfSJ7JSBpZiAoZmlsZS5kZWxldGVXaXRoQ3JlZGVudGlhbHMpIHsgJX0gZGF0YS14aHItZmllbGRzPSd7IndpdGhDcmVkZW50aWFscyI6dHJ1ZX0neyUgfSAlfT4NCiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9ImdseXBoaWNvbiBnbHlwaGljb24tdHJhc2giPjwvaT4NCiAgICAgICAgICAgICAgICAgICAgPHNwYW4+RGVsZXRlPC9zcGFuPg0KICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0iZGVsZXRlIiB2YWx1ZT0iMSIgY2xhc3M9InRvZ2dsZSI+DQogICAgICAgICAgICB7JSB9IGVsc2UgeyAlfQ0KICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9ImJ0biBidG4td2FybmluZyBjYW5jZWwiPg0KICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz0iZ2x5cGhpY29uIGdseXBoaWNvbi1iYW4tY2lyY2xlIj48L2k+DQogICAgICAgICAgICAgICAgICAgIDxzcGFuPkNhbmNlbDwvc3Bhbj4NCiAgICAgICAgICAgICAgICA8L2J1dHRvbj4NCiAgICAgICAgICAgIHslIH0gJX0NCiAgICAgICAgPC90ZD4NCiAgICA8L3RyPg0KeyUgfSAlfQ0KPC9zY3JpcHQ+DQoJDQpFT0Y7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHdpZGdldF9pbmNsdWRlczsNCg0KDQogICAgICAgIA0KICAgICAgICAkYXV0b3VwbG9hZF9vcHRpb24gPSAnZmFsc2UnOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmpxdWVyeWF1dG8pICYmICRmaWVsZC0+anF1ZXJ5YXV0byA9PSAwKSB7DQogICAgICAgICAgICAkYXV0b3VwbG9hZF9vcHRpb24gPSAndHJ1ZSc7DQogICAgICAgIH0NCg0KICAgICAgICAkcG9zdGJvZHlfaW5jbHVkZXMgPSA8PDxFT0YNCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KKGZ1bmN0aW9uKCkgeyAvLyBMb2FkIGpRdWVyeSBJZiBOZWVkZWQuDQogICAgaWYgKCF3aW5kb3cualF1ZXJ5KSB7ICANCiAgICAgICAgdmFyIHNyYyA9ICIvL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjMvanF1ZXJ5LmpzIjsNCiAgICAgICAgZG9jdW1lbnQud3JpdGUoJzxzY3JpcHQgc3JjPSInICsgc3JjICsgJyI+PFwvc2NyaXB0PicpOw0KICAgIH0NCn0pKCk7DQo8L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIGpRdWVyeSBVSSB3aWRnZXQgZmFjdG9yeSwgY2FuIGJlIG9taXR0ZWQgaWYgalF1ZXJ5IFVJIGlzIGFscmVhZHkgaW5jbHVkZWQgLS0+DQo8c2NyaXB0IHNyYz0ibGliL2pxdWVyeS11cGxvYWQvanMvdmVuZG9yL2pxdWVyeS51aS53aWRnZXQuanMiPjwvc2NyaXB0Pg0KCQkJCQ0KPCEtLSBUaGUgVGVtcGxhdGVzIHBsdWdpbiBpcyBpbmNsdWRlZCB0byByZW5kZXIgdGhlIHVwbG9hZC9kb3dubG9hZCBsaXN0aW5ncyAtLT4NCjxzY3JpcHQgc3JjPSIvL2JsdWVpbXAuZ2l0aHViLmlvL0phdmFTY3JpcHQtVGVtcGxhdGVzL2pzL3RtcGwubWluLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIExvYWQgSW1hZ2UgcGx1Z2luIGlzIGluY2x1ZGVkIGZvciB0aGUgcHJldmlldyBpbWFnZXMgYW5kIGltYWdlIHJlc2l6aW5nIGZ1bmN0aW9uYWxpdHkgLS0+DQo8c2NyaXB0IHNyYz0ibGliL2pxdWVyeS11cGxvYWQvanMvbG9hZC1pbWFnZS5hbGwubWluLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIENhbnZhcyB0byBCbG9iIHBsdWdpbiBpcyBpbmNsdWRlZCBmb3IgaW1hZ2UgcmVzaXppbmcgZnVuY3Rpb25hbGl0eSAtLT4NCjxzY3JpcHQgc3JjPSJsaWIvanF1ZXJ5LXVwbG9hZC9qcy9jYW52YXMtdG8tYmxvYi5taW4uanMiPjwvc2NyaXB0Pg0KCQkJCQ0KPCEtLSBUaGUgSWZyYW1lIFRyYW5zcG9ydCBpcyByZXF1aXJlZCBmb3IgYnJvd3NlcnMgd2l0aG91dCBzdXBwb3J0IGZvciBYSFIgZmlsZSB1cGxvYWRzIC0tPg0KPHNjcmlwdCBzcmM9ImxpYi9qcXVlcnktdXBsb2FkL2pzL2pxdWVyeS5pZnJhbWUtdHJhbnNwb3J0LmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIGJhc2ljIEZpbGUgVXBsb2FkIHBsdWdpbiAtLT4NCjxzY3JpcHQgc3JjPSJsaWIvanF1ZXJ5LXVwbG9hZC9qcy9qcXVlcnkuZmlsZXVwbG9hZC5qcyI+PC9zY3JpcHQ+DQoJCQkJDQo8IS0tIFRoZSBGaWxlIFVwbG9hZCBwcm9jZXNzaW5nIHBsdWdpbiAtLT4NCjxzY3JpcHQgc3JjPSJsaWIvanF1ZXJ5LXVwbG9hZC9qcy9qcXVlcnkuZmlsZXVwbG9hZC1wcm9jZXNzLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIEZpbGUgVXBsb2FkIGltYWdlIHByZXZpZXcgJiByZXNpemUgcGx1Z2luIC0tPg0KPHNjcmlwdCBzcmM9ImxpYi9qcXVlcnktdXBsb2FkL2pzL2pxdWVyeS5maWxldXBsb2FkLWltYWdlLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIEZpbGUgVXBsb2FkIGF1ZGlvIHByZXZpZXcgcGx1Z2luIC0tPg0KPHNjcmlwdCBzcmM9ImxpYi9qcXVlcnktdXBsb2FkL2pzL2pxdWVyeS5maWxldXBsb2FkLWF1ZGlvLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIEZpbGUgVXBsb2FkIHZpZGVvIHByZXZpZXcgcGx1Z2luIC0tPg0KPHNjcmlwdCBzcmM9ImxpYi9qcXVlcnktdXBsb2FkL2pzL2pxdWVyeS5maWxldXBsb2FkLXZpZGVvLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIEZpbGUgVXBsb2FkIHZhbGlkYXRpb24gcGx1Z2luIC0tPg0KPHNjcmlwdCBzcmM9ImxpYi9qcXVlcnktdXBsb2FkL2pzL2pxdWVyeS5maWxldXBsb2FkLXZhbGlkYXRlLmpzIj48L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIEZpbGUgVXBsb2FkIHVzZXIgaW50ZXJmYWNlIHBsdWdpbiAtLT4NCjxzY3JpcHQgc3JjPSJsaWIvanF1ZXJ5LXVwbG9hZC9qcy9qcXVlcnkuZmlsZXVwbG9hZC11aS5qcyI+PC9zY3JpcHQ+DQoJCQkJDQo8IS0tIFRoZSBtYWluIGFwcGxpY2F0aW9uIHNjcmlwdCAtLT4NCjxzY3JpcHQgc3JjPSJsaWIvanF1ZXJ5LXVwbG9hZC9qcy9tYWluLmpzIj48L3NjcmlwdD4NCgkJCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KLy8gU2V0IFByb3BlcnRpZXMgVXNlZCBCeSBUaGUgVXBsb2FkIFByb2Nlc3MgSW46IGxpYi9qcXVlcnktdXBsb2FkL21haW4uanMNCg0KdmFyIGZvcm1uYW1lID0gInskZm9ybW5hbWV9IjsNCnZhciBtYXhfZmlsZV9zaXplID0geyRtYXhfZmlsZV9zaXplX2pzfTsNCnZhciBhY2NlcHRlZF90eXBlcyA9IHskYWNjZXB0ZWRfdHlwZXNfanN9Ow0KCQkNCnZhciBtYXhfaW1hZ2Vfd2lkdGggPSAieyRmaWVsZC0+bWF4d2lkdGh9IjsNCnZhciBtYXhfaW1hZ2VfaGVpZ2h0ID0gInskZmllbGQtPm1heGhlaWdodH0iOw0KCQkNCnZhciBhdXRvdXBsb2FkID0geyRhdXRvdXBsb2FkX29wdGlvbn07DQoJCQkJDQo8L3NjcmlwdD4NCgkJCQkNCjwhLS0gVGhlIFhEb21haW5SZXF1ZXN0IFRyYW5zcG9ydCBpcyBpbmNsdWRlZCBmb3IgY3Jvc3MtZG9tYWluIGZpbGUgZGVsZXRpb24gZm9yIElFIDggYW5kIElFIDkgLS0+DQo8IS0tW2lmIChndGUgSUUgOCkmKGx0IElFIDEwKV0+DQo8c2NyaXB0IHNyYz0ibGliL2pxdWVyeS11cGxvYWQvanMvY29ycy9qcXVlcnkueGRyLXRyYW5zcG9ydC5qcyI+PC9zY3JpcHQ+DQo8IVtlbmRpZl0tLT4NCgkNCkVPRjsNCg0KICAgICAgICAkZWxlbWVudCAuPSAkcG9zdGJvZHlfaW5jbHVkZXM7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGQtPmZmZGVzdGluYXRpb24gPT0gJycpIHsNCiAgICAgICAgICAgICRkZXN0aW5hdGlvbiA9ICd1cGxvYWQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGRlc3RpbmF0aW9uID0gJGZpZWxkLT5mZmRlc3RpbmF0aW9uOw0KICAgICAgICB9DQogICAgICAgIGlmICgkZmllbGQtPnRodW1iZGVzdGluYXRpb24gPT0gJycpIHsNCiAgICAgICAgICAgICR0aHVtYmRlc3RpbmF0aW9uID0gJ3VwbG9hZCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkdGh1bWJkZXN0aW5hdGlvbiA9ICRmaWVsZC0+dGh1bWJkZXN0aW5hdGlvbjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdHJhbnNmZXIgPSAiIjsNCiAgICAgICAgaWYgKCRmaWVsZC0+ZmxhdGZpbGUgPT0gJzEnKSB7DQogICAgICAgICAgICAkdHJhbnNmZXIgLj0gJ2ZsYXRmaWxlJzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoJGZpZWxkLT5kYXRhYmFzZSA9PSAnMScpIHsNCiAgICAgICAgICAgIGlmICgkdHJhbnNmZXIgIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAkdHJhbnNmZXIgLj0gInwiOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgJHRyYW5zZmVyIC49ICdkYXRhYmFzZSc7DQogICAgICAgIH0NCg0KICAgICAgICAkcGhwX3RyYW5zZmVyID0gPDw8RU9GDQo8P3BocA0KLy8gVmFyaWFibGVzIHVzZWQgdG8gcHJvY2VzcyBQSFAgdXBsb2Fkcy4NCg0KaW5jbHVkZV9vbmNlICdjb25maWcucGhwJzsNCg0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJqb2JuYW1lIl0JCQkJPSAneyR4bWwtPmpvYm5hbWV9JzsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsiYWNjZXB0ZWRfdHlwZXMiXQkJPSAneyRhY2NlcHRlZF90eXBlc19waHB9JzsNCg0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJkYnR5cGUiXQkJCQk9ICJ7JGZpZWxkLT5kYnR5cGV9IjsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsiZW1haWwiXQkJCQk9ICJ7JGZpZWxkLT5lbWFpbH0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJkZXN0aW5hdGlvbiJdCQkJPSAieyRkZXN0aW5hdGlvbn0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJwcmVwZW5kIl0JCQkJPSAieyRmaWVsZC0+cHJlcGVuZH0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJhcHBlbmQiXQkJCQk9ICJ7JGZpZWxkLT5hcHBlbmR9IjsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsibmFtZSJdCQkJCT0gInskZmllbGQtPm5hbWV9IjsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsibGFiZWwiXQkJCQk9ICJ7JGZpZWxkLT5sYWJlbH0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJtYXhmaWxlc2l6ZSJdCQkJPSAieyRtYXhfZmlsZV9zaXplX3BocH0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJtYXh3aWR0aCJdCQkJPSAieyRmaWVsZC0+bWF4d2lkdGh9IjsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsibWF4aGVpZ2h0Il0JCQk9ICJ7JGZpZWxkLT5tYXhoZWlnaHR9IjsNClwkX1NFU1NJT05bJ3FzJ11bXCRfU0VTU0lPTlsnZW50cnlfa2V5J11dWyJqcXVlcnlfZmlsZV91cGxvYWRfdHJhbnNmZXIiXVsicmVxdWlyZWQiXQkJCT0gInskZmllbGQtPnZhbGlkYXRpb24tPnJlcX0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJ0cmFuc2ZlciJdCQkJPSAieyR0cmFuc2Zlcn0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJkYl9rZXkiXQkJCQk9ICJ7JHhtbC0+ZGJfa2V5fSI7DQpcJF9TRVNTSU9OWydxcyddW1wkX1NFU1NJT05bJ2VudHJ5X2tleSddXVsianF1ZXJ5X2ZpbGVfdXBsb2FkX3RyYW5zZmVyIl1bImRiY29ubmVjdG9yIl0JCQk9ICJ7JGZpZWxkLT5kYmNvbm5lY3Rvcn0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJ0aHVtYiJdCQkJCT0gInskZmllbGQtPnRodW1ifSI7DQpcJF9TRVNTSU9OWydxcyddW1wkX1NFU1NJT05bJ2VudHJ5X2tleSddXVsianF1ZXJ5X2ZpbGVfdXBsb2FkX3RyYW5zZmVyIl1bIm1heHRodW1iIl0JCQk9ICJ7JGZpZWxkLT5tYXh0aHVtYn0iOw0KXCRfU0VTU0lPTlsncXMnXVtcJF9TRVNTSU9OWydlbnRyeV9rZXknXV1bImpxdWVyeV9maWxlX3VwbG9hZF90cmFuc2ZlciJdWyJ0aHVtYmRlc3RpbmF0aW9uIl0JPSAieyR0aHVtYmRlc3RpbmF0aW9ufSI7DQpcJF9TRVNTSU9OWydxcyddW1wkX1NFU1NJT05bJ2VudHJ5X2tleSddXVsianF1ZXJ5X2ZpbGVfdXBsb2FkX3RyYW5zZmVyIl1bImNvbmRpdGlvbmFsX21ldGhvZCJdCT0gInskZmllbGQtPmNvbmRpdGlvbmFsLT5tZXRob2R9IjsNCj8+CQkJCQ0KCQkNCkVPRjsNCg0KDQogICAgICAgICRlbGVtZW50IC49ICRwaHBfdHJhbnNmZXI7DQoNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJGZpZWxkd2lkdGggPSAnODUlJzsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCg0KDQogICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYnRvb2x0aXAteyRpZH0gZmJ0b29sdGlwXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmU7XCI+eyR0b29sdGlwX2VsZW1lbnQtPnRleHR9PC9kaXY+XG4iOw0KICAgICAgICAkZWxlbWVudCAuPSAkdG9vbHRpcF9lbGVtZW50LT5qczsNCg0KICAgICAgICBpZiAoJGhlbHBlciAhPSAnJykgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxici8+PGRpdiBjbGFzcz1cImhlbHBlclwiIHN0eWxlPVwiY29sb3I6eyRoZWxwZXJjb2xvcn07XCI+eyRoZWxwZXJ9PC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgICRlbGVtZW50IC49ICc8YnIgLz4nOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9odG1sNV9maWxlKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGpvYm5hbWUsICRkYl9rZXksICRidWNrZXRfbm9kZSA9ICIiKQ0KICAgIHsNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQogICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7DQogICAgICAgICRyZXEgPSAkZmllbGQtPnZhbGlkYXRpb24tPnJlcTsNCiAgICAgICAgJGNvbG9yID0gJGZpZWxkLT5jb2xvcjsNCiAgICAgICAgJGlucHV0X2NvbG9yID0gJGZpZWxkLT5pbnB1dF9jb2xvcjsNCiAgICAgICAgJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCiAgICAgICAgJGxhYmVscG9zID0gJGZpZWxkLT5sYWJlbHBvczsNCiAgICAgICAgJGluaGVyaXRzdHlsZSA9ICRmaWVsZC0+aW5oZXJpdHN0eWxlOw0KICAgICAgICAkZmllbGR3aWR0aCA9ICRmaWVsZC0+ZmllbGR3aWR0aDsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICR0b29sdGlwID0gJGZpZWxkLT50b29sdGlwOw0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KDQogICAgICAgIA0KICAgICAgICAkdGhpcy0+dW0tPnB1bGxDdXN0b21Db25uZWN0b3JGaWxlKChzdHJpbmcpJGZpZWxkLT5kYmNvbm5lY3Rvcik7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGxhYmVsID09ICIiKSB7DQogICAgICAgICAgICAkbGFiZWwgPSAiJm5ic3A7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRzdHlsZSk7DQoNCiAgICAgICAgDQogICAgICAgICR0b29sdGlwX2VsZW1lbnQgPSAkdGhpcy0+dHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGlkKTsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICR0ZXN0ID0gKGludCkkaW5oZXJpdHN0eWxlOw0KICAgICAgICBpZiAoJHRlc3QgIT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9IDA7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCRpbmhlcml0c3R5bGUgPT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCJmb250LXNpemU6eyRmb250c2l6ZX07IGNvbG9yOnskaW5wdXRfY29sb3J9OyBmb250LWZhbWlseTppbmhlcml0OyB7JGF0dHJpYnV0ZXN0eWxlfSBcIiAiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgc3R5bGU9XCIgY29sb3I6eyRpbnB1dF9jb2xvcn07IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+bGVmdGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyRmaXhlZF93aWR0aH1weDsgbWFyZ2luLXJpZ2h0OjhweDsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259XCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgJHJlcSwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsICRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUsICR0b29sdGlwLCAnJywgJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgc3dpdGNoICgkZmllbGQtPmFsbG93ZWQpIHsNCiAgICAgICAgICAgIGNhc2UgJzAnOiANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkYWxsb3dlZF9maWxlX3R5cGVzX2pzID0gPDw8RU9KDQogICAgYWNjZXB0ZWRUeXBlcyA9IHsgJ2FsbCc6IHRydWUgfSwJDQpFT0o7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxJzogDQogICAgICAgICAgICAgICAgJGFsbG93ZWRfZmlsZV90eXBlc19qcyA9IDw8PEVPSg0KDQoJYWNjZXB0ZWRUeXBlcyA9IHsNCiAgICAgJ2ltYWdlL3BuZyc6IHRydWUsDQogICAgICdpbWFnZS9qcGVnJzogdHJ1ZSwNCiAgICAgJ2ltYWdlL2dpZic6IHRydWUNCiAgIH0sDQogICAgCQkNCkVPSjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOiANCiAgICAgICAgICAgICAgICAkYWxsb3dlZF9maWxlX3R5cGVzX2pzID0gPDw8RU9KDQoNCglhY2NlcHRlZFR5cGVzID0gew0KICAgICAnaW1hZ2UvcG5nJzogZmFsc2UsDQogICAgICdpbWFnZS9qcGVnJzogZmFsc2UsDQogICAgICdpbWFnZS9naWYnOiBmYWxzZSwNCiAgICAgJ3RleHQveG1sJzogdHJ1ZSwNCiAgICAgJ2FwcGxpY2F0aW9uL3htbCc6IHRydWUsDQogICAgICd0ZXh0L3BsYWluJzogdHJ1ZSwNCiAgICAgJ211bHRpcGFydC94LXppcCc6IHRydWUsDQogICAgICdhcHBsaWNhdGlvbi94LWNvbXByZXNzZWQnOiB0cnVlLA0KICAgICAnYXBwbGljYXRpb24vZXhjZWwnOiB0cnVlLA0KICAgICAnYXBwbGljYXRpb24vbXN3b3JkJzogdHJ1ZQ0KICAgfSwNCiAgICAJCQ0KRU9KOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMyc6IA0KDQogICAgICAgICAgICAgICAgJGFsbG93ZWRfZmlsZV90eXBlc19qcyA9IDw8PEVPSg0KDQoJYWNjZXB0ZWRUeXBlcyA9IHsNCiAgICAgJ2FwcGxpY2F0aW9uL3BkZic6IHRydWUsDQogICAgICd4LXBkZic6IHRydWUNCiAgIH0sDQogICAgCQkNCkVPSjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGQtPmZmZGVzdGluYXRpb24gPT0gJycpIHsNCiAgICAgICAgICAgICRkZXN0aW5hdGlvbiA9ICd1cGxvYWQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGRlc3RpbmF0aW9uID0gJGZpZWxkLT5mZmRlc3RpbmF0aW9uOw0KICAgICAgICB9DQogICAgICAgIGlmICgkZmllbGQtPnRodW1iZGVzdGluYXRpb24gPT0gJycpIHsNCiAgICAgICAgICAgICR0aHVtYmRlc3RpbmF0aW9uID0gJ3VwbG9hZCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkdGh1bWJkZXN0aW5hdGlvbiA9ICRmaWVsZC0+dGh1bWJkZXN0aW5hdGlvbjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdHJhbnNmZXIgPSBhcnJheSgpOw0KICAgICAgICBpZiAoJGZpZWxkLT5mbGF0ZmlsZSA9PSAnMScpIHsNCiAgICAgICAgICAgICR0cmFuc2ZlcltdID0gJ2ZsYXRmaWxlJzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoJGZpZWxkLT5kYXRhYmFzZSA9PSAnMScpIHsNCiAgICAgICAgICAgICR0cmFuc2ZlcltdID0gJ2RhdGFiYXNlJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGQtPmVtYWlsID09ICcxJykgew0KICAgICAgICAgICAgJHRyYW5zZmVyW10gPSAnZW1haWwnOw0KICAgICAgICAgICAgJHRyYW5zZmVyW10gPSAncXMnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRmaWVsZC0+ZmxhdGZpbGUgPT0gJzAnICYmICRmaWVsZC0+ZGF0YWJhc2UgPT0gJzAnICYmICRmaWVsZC0+ZW1haWwgPT0gJzAnKSB7DQogICAgICAgICAgICAkdHJhbnNmZXJbXSA9ICdxcyc7DQogICAgICAgIH0NCg0KICAgICAgICAkdHJhbnNmZXJfcmF3ID0gaW1wbG9kZSgnLCcsICR0cmFuc2Zlcik7DQoNCiAgICAgICAgDQogICAgICAgICRhcHBlbmQgPSBpc3NldCgkZmllbGQtPmFwcGVuZCkgPyAkZmllbGQtPmFwcGVuZCA6ICIiOw0KICAgICAgICANCiAgICAgICAgJG1heF9maWxlX3NpemUgPSAkdGhpcy0+Y3JlYXRlX2ZpbGVfdXBsb2FkX3NwZWMoJGZpZWxkLT5tYXhmaWxlc2l6ZSwgJ251bWJlcnNfb25seScpOw0KDQogICAgICAgIA0KICAgICAgICAkcHJlcGVuZCA9IGlzc2V0KCRmaWVsZC0+cHJlcGVuZCkgPyAkZmllbGQtPnByZXBlbmQgOiAiIjsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG48P3BocFxuIjsNCiAgICAgICAgJGVsZW1lbnQgLj0gIlwkX1NFU1NJT05bJ2h0bWw1X2N1cnJlbnRfZmllbGRfbmFtZSddID0gJ3skZmllbGQtPm5hbWV9JztcbiI7IA0KICAgICAgICAkZWxlbWVudCAuPSAiXCRfU0VTU0lPTlsnUkZfSFRNTDVfVVBMT0FEX1NQRUMnXVtcIntcJF9TRVNTSU9OWydodG1sNV9jdXJyZW50X2ZpZWxkX25hbWUnXX1cIl0gPSBhcnJheSgnam9ibmFtZScgPT4gJ3skam9ibmFtZX0nLCANCgkJCQkJCQkJCQkJCQkJCQknZGVzdGluYXRpb24nID0+ICd7JGRlc3RpbmF0aW9ufScsDQoJCQkJCQkJCQkJCQkJCQkJDQoJCQkJCQkJCQkJCQkJCQkJLy8gYXBwZW5kDQoJCQkJCQkJCQkJCQkJCQkJJ2FwcGVuZCcgPT4gJ3skYXBwZW5kfScsDQoJCQkJCQkJCQkJCQkJCQkJJ3ByZXBlbmQnID0+ICd7JHByZXBlbmR9JywNCgkJCQkJCQkJCQkJCQkJCQkNCgkJCQkJCQkJCQkJCQkJCQkvLyBzaXplIGFuZCBoZWlnaHQNCgkJCQkJCQkJCQkJCQkJCQknbWF4d2lkdGgnID0+ICd7JGZpZWxkLT5tYXh3aWR0aH0nLA0KCQkJCQkJCQkJCQkJCQkJCSdtYXhoZWlnaHQnID0+ICd7JGZpZWxkLT5tYXhoZWlnaHR9JywNCgkJCQkJCQkJCQkJCQkJCQkNCgkJCQkJCQkJCQkJCQkJCQkvLyB0aHVtYm5haWxzDQoJCQkJCQkJCQkJCQkJCQkJJ3RodW1iJyA9PiAneyRmaWVsZC0+dGh1bWJ9JywNCgkJCQkJCQkJCQkJCQkJCQknbWF4dGh1bWInID0+ICd7JGZpZWxkLT5tYXh0aHVtYn0nLA0KCQkJCQkJCQkJCQkJCQkJCSd0aHVtYmRlc3RpbmF0aW9uJyA9PiAneyR0aHVtYmRlc3RpbmF0aW9ufScsDQoJCQkJCQkJCQkJCQkJCQkJDQoJCQkJCQkJCQkJCQkJCQkJLy8gZmlsZSBwcm9wZXJ0aWVzDQoJCQkJCQkJCQkJCQkJCQkJJ25hbWUnID0+ICd7JGZpZWxkLT5uYW1lfScsDQoJCQkJCQkJCQkJCQkJCQkJJ2xhYmVsJyA9PiAneyRmaWVsZC0+bGFiZWx9JywNCgkJCQkJCQkJCQkJCQkJCQknbWF4ZmlsZXNpemUnID0+ICd7JG1heF9maWxlX3NpemV9JywNCgkJCQkJCQkJCQkJCQkJCQkNCgkJCQkJCQkJCQkJCQkJCQkvLyBmaWxlIG1vdmVtZW50DQoJCQkJCQkJCQkJCQkJCQkJJ3RyYW5zZmVyJyA9PiAneyR0cmFuc2Zlcl9yYXd9JywNCgkJCQkJCQkJCQkJCQkJCQkNCgkJCQkJCQkJCQkJCQkJCQkvLyBkYXRhYmFzZQ0KCQkJCQkJCQkJCQkJCQkJCSdkYl9rZXknID0+ICd7JGRiX2tleX0nLA0KCQkJCQkJCQkJCQkJCQkJCSdkYmNvbm5lY3RvcicgPT4gJ3skZmllbGQtPmRiY29ubmVjdG9yfScsDQoJCQkJCQkJCQkJCQkJCQkJDQoJCQkJCQkJCQkJCQkJCQkJJ3JlcScgPT4gJ3skZmllbGQtPnZhbGlkYXRpb24tPnJlcX0nLA0KCQkJCQkJCQkJCQkJCQkJCQ0KCQkJCQkJCQkJCQkJCQkJCS8vIGFsbG93ZWQgZmlsZSB0eXBlcw0KCQkJCQkJCQkJCQkJCQkJCSdhbGxvd2VkJyA9PiAneyRmaWVsZC0+YWxsb3dlZH0nKTsiOw0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPz5cbiI7DQoNCg0KICAgICAgICANCiAgICAgICAgJGh0bWw1cHJldmlldyA9ICdmYWxzZSc7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+aHRtbDVwcmV2aWV3KSAmJiAoaW50KSRmaWVsZC0+aHRtbDVwcmV2aWV3ID09IDEpIHsNCiAgICAgICAgICAgICRodG1sNXByZXZpZXcgPSAndHJ1ZSc7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGh0bWw1QXJ0aWNsZUhlaWdodCA9IGludHZhbCgkZmllbGQtPmh0bWw1aGVpZ2h0KSArIDE2IC4gInB4OyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQojaG9sZGVyX3skZmllbGQtPm5hbWV9IHsgYmFja2dyb3VuZC1jb2xvcjogI2ZhZmFmYTsgYm9yZGVyLXJhZGl1czogMTBweDsgYm9yZGVyOiAycHggZG90dGVkICNjY2M7IHdpZHRoOiB7JGZpZWxkLT5odG1sNXdpZHRofTsgbWluLWhlaWdodDogeyRmaWVsZC0+aHRtbDVoZWlnaHR9OyBtYXJnaW46IDdweCAwIDEycHg7IH0gLyogbWFyZ2luOiAyMHB4IGF1dG87ICovDQojaG9sZGVyX3skZmllbGQtPm5hbWV9LmhvdmVyIHsgYm9yZGVyOiAycHggZG90dGVkICMwYzA7IH0NCiNob2xkZXJfeyRmaWVsZC0+bmFtZX0gaW1nIHsgZGlzcGxheTogYmxvY2s7IG1hcmdpbjogMTBweCBhdXRvOyB9DQojaG9sZGVyX3skZmllbGQtPm5hbWV9IHAgeyBtYXJnaW46IDEwcHg7IGZvbnQtc2l6ZTogMTZweDsgfQ0KI3VwbG9hZHByb2dyZXNzX3skZmllbGQtPm5hbWV9IHsgfQ0KI3VwbG9hZHByb2dyZXNzX3skZmllbGQtPm5hbWV9OmFmdGVyIHsgY29udGVudDogJyUnOyB9DQouZmFpbCB7IGJhY2tncm91bmQ6ICNjMDA7IHBhZGRpbmc6IDJweDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6NXB4OyB9DQouaGlkZGVuIHsgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O30NCi52aXNpYmxlIHsgZGlzcGxheTogYmxvY2sgIWltcG9ydGFudDt9DQojaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9IHsgcGFkZGluZzogMTBweDsgfQ0KLmh0bWw1LXVwbG9hZC1lcnJvci1tZXNzYWdlIHsgZm9udC13ZWlnaHQ6IGJvbGQ7IGxpbmUtaGVpZ2h0OiAxNXB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7IH0NCg0KLmh0bWw1SW5zdHJ1Y3Rpb25zIHsgDQoJDQp9DQoNCi5odG1sNVN0YXR1c0Jsb2NrIHsNCglwb3NpdGlvbjogYWJzb2x1dGU7DQoJdG9wOiAzMHB4Ow0KCWxlZnQ6IDE2cHg7DQp9DQoNCi5odG1sNUFydGljbGUgew0KCXBvc2l0aW9uOiByZWxhdGl2ZTsNCn0NCg0KLmh0bWw1UHJldmlld0NvbnRhaW5lciB7DQoJbWFyZ2luLXRvcDoxOHB4Ow0KCXBhZGRpbmc6IDNweDsNCn0NCg0KLmh0bWw1UHJldmlld0l0ZW0gew0KCWZsb2F0OiBsZWZ0Ow0KCXBhZGRpbmc6IDNweDsNCglib3JkZXI6IDFweCBzb2xpZCAjZjNmM2YzOw0KCW1hcmdpbjogMnB4Ow0KfQ0KDQouaHRtbDVGaWxlbmFtZUxpc3Qgew0KCWNvbG9yOiAjNzg3ODc4Ow0KfQ0KDQouaHRtbDVEZWxldGVCdXR0b24gew0KCWJhY2tncm91bmQtY29sb3I6ICM4MTgxODE7DQoJY29sb3I6IHdoaXRlOw0KCWN1cnNvcjogcG9pbnRlcjsNCgl0b3A6IDNweDsNCglsZWZ0OiA0cHg7DQoJaGVpZ2h0OiAzMHB4Ow0KCXdpZHRoOiAzMHB4Ow0KCXRleHQtYWxpZ246IGNlbnRlcjsNCglsaW5lLWhlaWdodDogMzFweDsNCglmb250LXdlaWdodDogYm9sZDsNCn0NCg0KLm91dGVyIHsNCiAgZGlzcGxheTogdGFibGU7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgaGVpZ2h0OiAxMDAlOw0KICB3aWR0aDogMTAwJTsNCn0NCg0KLm1pZGRsZSB7DQogIGRpc3BsYXk6IHRhYmxlLWNlbGw7DQogIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7DQp9DQoNCi5pbm5lciB7DQogIG1hcmdpbi1sZWZ0OiBhdXRvOw0KICBtYXJnaW4tcmlnaHQ6IGF1dG87DQogIHdpZHRoOiA0MDBweDsNCiAgLyp3aGF0ZXZlciB3aWR0aCB5b3Ugd2FudCovDQp9DQoNCjwvc3R5bGU+DQoNCjxhcnRpY2xlIGNsYXNzPSJodG1sNUFydGljbGUiIHN0eWxlPSJoZWlnaHQ6IHskaHRtbDVBcnRpY2xlSGVpZ2h0fTsiPg0KDQoJPGxhYmVsIGFyaWEtbGFiZWw9IlVwbG9hZGVyIiBmb3I9InskaWR9IiBzdHlsZT0iY3Vyc29yOnBvaW50ZXI7Ij4NCgkgIA0KCSAgPGRpdiBjbGFzcz0ib3V0ZXIiIGlkPSJob2xkZXJfeyRmaWVsZC0+bmFtZX0iIHN0eWxlPSJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlOyBoZWlnaHQ6IHskZmllbGQtPmh0bWw1aGVpZ2h0fTsgdGV4dC1hbGlnbjogY2VudGVyOyBjb2xvcjojODk4OTg5OyBmb250LXNpemU6MTNwdDsgIj4NCgkgIA0KCSAgCTxkaXYgY2xhc3M9Im1pZGRsZSI+DQoJICAJDQoJCSAgCTxkaXYgaWQ9Imh0bWw1SW5zdHJ1Y3Rpb25zX3skZmllbGQtPm5hbWV9IiBjbGFzcz0iaW5uZXIgaHRtbDVJbnN0cnVjdGlvbnMiIHN0eWxlPSJkaXNwbGF5OmJsb2NrOyI+DQoJCSAgCQl7JGZpZWxkLT5odG1sNWluc3RydWN0aW9uc30NCgkJICAJPC9kaXY+DQoJCSAgCQ0KCQkgIAk8ZGl2IGlkPSJ1cGxvYWQtcHJvZ3Jlc3MtbWVzc2FnZV97JGZpZWxkLT5uYW1lfSIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPg0KCQkgIAkJeyRmaWVsZC0+aHRtbDVwcm9ncmVzc21lc3NhZ2V9IA0KCSAgCQkJPHByb2dyZXNzIGlkPSJ1cGxvYWRwcm9ncmVzc197JGZpZWxkLT5uYW1lfSIgbWluPSIwIiBtYXg9IjEwMCIgdmFsdWU9IjAiIHN0eWxlPSIiPjA8L3Byb2dyZXNzPg0KCSAgCQk8L2Rpdj4NCgkgIAkNCgkgIAk8L2Rpdj4NCg0KCSAgPC9kaXY+IA0KDQoJICA8cCBpZD0idXBsb2FkX3skZmllbGQtPm5hbWV9IiBjbGFzcz0iaGlkZGVuIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPg0KCSAgCTxsYWJlbD5EcmFnICYgZHJvcCBub3Qgc3VwcG9ydGVkLCBidXQgeW91IGNhbiBzdGlsbCB1cGxvYWQgdmlhIHRoaXMgaW5wdXQgZmllbGQ6PGJyPg0KCQkJPGlucHV0IHNpemU9InskZmllbGR3aWR0aH0iIHR5cGU9ImZpbGUiIG5hbWU9InskbmFtZX0iIGlkPSJ7JGlkfSIgeyR0YWJodG1sfSB7JGluaGVyaXRzdHlsZX0geyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IC8+DQoJCTwvbGFiZWw+DQoJICA8L3A+DQoJICANCgkgIDxkaXYgY2xhc3M9Imh0bWw1U3RhdHVzQmxvY2siPg0KCSAgCQ0KCQkgIDxwIGNsYXNzPSJoaWRkZW4iIGlkPSJmaWxlcmVhZGVyX3skZmllbGQtPm5hbWV9IiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPkZpbGUgQVBJICYgRmlsZVJlYWRlciBBUEkgbm90IHN1cHBvcnRlZDwvcD4NCgkJICA8cCBjbGFzcz0iaGlkZGVuIiBpZD0iZm9ybWRhdGFfeyRmaWVsZC0+bmFtZX0iIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+WEhSMidzIEZvcm1EYXRhIGlzIG5vdCBzdXBwb3J0ZWQ8L3A+DQoJCSAgPHAgY2xhc3M9ImhpZGRlbiIgaWQ9InByb2dyZXNzX3skZmllbGQtPm5hbWV9IiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPlhIUjIncyB1cGxvYWQgcHJvZ3Jlc3MgaXNuJ3Qgc3VwcG9ydGVkPC9wPg0KDQoJCSAgPCEtLSBFcnJvciBNZXNzYWdlcyAtLT4NCgkJICA8cCBpZD0iaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9IiBjbGFzcz0iZmFpbCIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij48L3A+DQoJCSAgDQoJICA8L2Rpdj4NCgkgIA0KCTwvbGFiZWw+DQoJDQo8L2FydGljbGU+DQoNCjxkaXYgY2xhc3M9Imh0bWw1RmlsZW5hbWVMaXN0Ij4NCgk8cCBjbGFzcz0iaGlkZGVuIiBpZD0iZmlsZW5hbWVfeyRmaWVsZC0+bmFtZX0iPjwvcD4NCjwvZGl2Pg0KDQo8IS0tIFByZXZpZXcgQ29udGFpbmVyIC0tPg0KDQo8ZGl2IGlkPSJwcmV2aWV3Q29udGFpbmVyX3skZmllbGQtPm5hbWV9IiBjbGFzcz0iaHRtbDVQcmV2aWV3Q29udGFpbmVyIiBzdHlsZT0iY2xlYXI6IGJvdGg7Ij48L2Rpdj4NCg0KDQoNCjxzY3JpcHQ+DQp2YXIgaG9sZGVyX3skZmllbGQtPm5hbWV9ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2hvbGRlcl97JGZpZWxkLT5uYW1lfScpLA0KICAgIHRlc3RzID0gew0KICAgICAgZmlsZXJlYWRlcjogdHlwZW9mIEZpbGVSZWFkZXIgIT0gJ3VuZGVmaW5lZCcsDQogICAgICBkbmQ6ICdkcmFnZ2FibGUnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSwNCiAgICAgIGZvcm1kYXRhOiAhIXdpbmRvdy5Gb3JtRGF0YSwNCiAgICAgIHByb2dyZXNzOiAidXBsb2FkIiBpbiBuZXcgWE1MSHR0cFJlcXVlc3QNCiAgICB9LCANCiAgICBzdXBwb3J0ID0gew0KICAgICAgZmlsZXJlYWRlcjogZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbGVyZWFkZXJfeyRmaWVsZC0+bmFtZX0nKSwNCiAgICAgIGZvcm1kYXRhOiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZm9ybWRhdGFfeyRmaWVsZC0+bmFtZX0nKSwNCiAgICAgIHByb2dyZXNzOiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0nKQ0KICAgIH0sDQogICAgeyRhbGxvd2VkX2ZpbGVfdHlwZXNfanN9DQogICAgcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0nKSwNCiAgICBmaWxldXBsb2FkX3skZmllbGQtPm5hbWV9ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZF97JGZpZWxkLT5uYW1lfScpOw0KDQoiZmlsZXJlYWRlciBmb3JtZGF0YSBwcm9ncmVzcyIuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uIChhcGkpIHsNCiAgaWYgKHRlc3RzW2FwaV0gPT09IGZhbHNlKSB7DQogICAgc3VwcG9ydFthcGldLmNsYXNzTmFtZSA9ICdmYWlsJzsNCiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaG9sZGVyX3skZmllbGQtPm5hbWV9JykuY2xhc3NOYW1lID0gJ2hpZGRlbic7DQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZHByb2dyZXNzX3skZmllbGQtPm5hbWV9JykuY2xhc3NOYW1lID0gJ2hpZGRlbic7DQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZC1wcm9ncmVzcy1tZXNzYWdlX3skZmllbGQtPm5hbWV9JykuY2xhc3NOYW1lID0gJ2hpZGRlbic7DQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZC1pbnN0cnVjdGlvbnNfeyRmaWVsZC0+bmFtZX0nKS5jbGFzc05hbWUgPSAnaGlkZGVuJzsNCgkNCiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkX3skZmllbGQtPm5hbWV9JykuY2xhc3NOYW1lID0gJ3Zpc2libGUnOw0KICB9IGVsc2Ugew0KICAgIHN1cHBvcnRbYXBpXS5jbGFzc05hbWUgPSAnaGlkZGVuJzsNCiAgfQ0KfSk7DQoNCmZ1bmN0aW9uIHByZXZpZXdmaWxlX3skZmllbGQtPm5hbWV9KGZpbGUpIHsNCg0KICBpZiAodGVzdHMuZmlsZXJlYWRlciA9PT0gdHJ1ZSAmJiAoYWNjZXB0ZWRUeXBlcy5hbGwgPT0gdHJ1ZSA/IHRydWUgOiBhY2NlcHRlZFR5cGVzW2ZpbGUudHlwZV0gPT09IHRydWUpKSB7DQoJDQoJdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7DQoJDQoJcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uIChldmVudCkgew0KDQoJCXZhciBpbWFnZSA9IG5ldyBJbWFnZSgpOw0KCQkgIA0KCQkvLyBJcyBUaGlzIEFuIEltYWdlIFdlIFVwbG9hZGVkPw0KDQoJCXZhciBmaWxlSXNJbWFnZSA9IChmaWxlLnR5cGUuc3BsaXQoJy8nKVswXSA9PSAnaW1hZ2UnKSA/IHRydWUgOiBmYWxzZTsNCg0KCQlpZihmaWxlSXNJbWFnZSl7DQoNCgkJCS8vIFVzZSBHaXZlbiBJbWFnZQ0KDQoJCQlpbWFnZS5zcmMgPSBldmVudC50YXJnZXQucmVzdWx0Ow0KDQoJCQlpbWFnZS53aWR0aCA9IDIwMDsgLy8gYSBmYWtlIHJlc2l6ZQ0KDQoJCX0gZWxzZSB7DQoNCgkJCS8vIE5vdCBBbiBJbWFnZSwgU28gQ3JlYXRlIEJhc2ljIEJhY2tncm91bmQuDQoJCQkNCgkJCXZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTsNCg0KCQkJdmFyIF9zaXplID0gMjAwOw0KDQoJCQljYW52YXMud2lkdGggPSBfc2l6ZTsNCgkJCWNhbnZhcy5oZWlnaHQgPSBfc2l6ZTsNCg0KCQkJdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpOw0KDQoJCQkvLyBCYWNrZ3JvdW5kIENvbG9yDQoJCQljdHguZmlsbFN0eWxlID0gImdyYXkiOw0KCQkJY3R4LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7DQoNCgkJCS8vIEJhc2ljIFRleHQNCgkJCWN0eC5maWxsU3R5bGUgPSAid2hpdGUiOw0KCQkJY3R4LmZvbnQgPSAiMjJweCBBcmlhbCI7DQoJCQljdHguZmlsbFRleHQoIkZpbGUgVXBsb2FkIiwgMzAsIDUwKTsgDQoNCgkJCS8vIEZpbGUgTmFtZSBUZXh0DQoJCQljdHguZmlsbFN0eWxlID0gIndoaXRlIjsNCgkJCWN0eC5mb250ID0gIjE0cHggQXJpYWwiOw0KCQkJY3R4LnRleHRCYXNlbGluZSA9ICdib3R0b20nOyAgLy8gc2V0IHRleHQgcG9zaXRpb24NCgkJCWN0eC5maWxsVGV4dChmaWxlLm5hbWUsIDMwLCAxNTApOyANCg0KCQkJaW1hZ2Uuc3JjID0gY2FudmFzLnRvRGF0YVVSTCgpOw0KDQoJCX0NCg0KICAgICAgDQogICAgICAJLy8gQ3JlYXRlIEltYWdlIEhvbGRlcg0KCQl2YXIgaW1hZ2VXcmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiRElWIik7DQoJCWltYWdlV3JhcHBlci5pZCA9ICJodG1sNVByZXZpZXdfIiArIGZpbGUubmFtZTsNCgkJaW1hZ2VXcmFwcGVyLmNsYXNzTmFtZSA9ICJodG1sNVByZXZpZXdJdGVtIjsNCgkJaW1hZ2VXcmFwcGVyLnN0eWxlLnBvc2l0aW9uID0gInJlbGF0aXZlIjsNCgkJDQoJCS8vIENyZWF0ZSBEZWxldGUgQ29udHJvbC4NCgkJdmFyIGRlbGV0ZUJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkRJViIpOw0KCQlkZWxldGVCdXR0b24uY2xhc3NOYW1lID0gImh0bWw1RGVsZXRlQnV0dG9uIjsNCgkJZGVsZXRlQnV0dG9uLnN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsNCgkJDQoJCS8vIEFkZCBEZWxldGUgQnV0dG9uIFRleHQgKFgpDQoJCWRlbGV0ZUJ1dHRvbi5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnWCcpKTsNCg0KCQlkZWxldGVCdXR0b24uc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2RlbGV0ZUZpbGVfVHJhaW5pbmdfRG9jdW1lbnRhdGlvbigiJyArIGZpbGUubmFtZSArICciKTsnKTsNCg0KCQkvLyBBcHBlbmQgRGVsZXRlIEJ1dHRvbg0KCQlpbWFnZVdyYXBwZXIuYXBwZW5kQ2hpbGQoZGVsZXRlQnV0dG9uKTsNCgkJDQoJCS8vIEFwcGVuZCBJbWFnZQ0KCQlpbWFnZVdyYXBwZXIuYXBwZW5kQ2hpbGQoaW1hZ2UpOw0KDQoNCgkJLy8gQXBwZW5kIEltYWdlIEhvbGRlciBUbyBNYXN0ZXIgQ29udGFpbmVyLg0KCQlwcmV2aWV3Q29udGFpbmVyX1RyYWluaW5nX0RvY3VtZW50YXRpb24uYXBwZW5kQ2hpbGQoaW1hZ2VXcmFwcGVyKTsNCg0KICAgIH07DQoNCiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTsNCiAgICANCiAgfSBlbHNlIHsNCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MID0gJzxwPkNhbm5vdCB1cGxvYWQ6ICcgKyBmaWxlLm5hbWUgKyAnLiBBIGRpc2FsbG93ZWQgZmlsZSB0eXBlIHVzdWFsbHkgY2F1c2VzIHRoaXMgZXJyb3IuPC9wPic7DQogIH0NCn0NCg0KZnVuY3Rpb24gcmVzaXplRmlsZV97JGZpZWxkLT5uYW1lfShmaWxlcywgaWR4LCBkYXRhVVJMLCBmaWxlVHlwZSwgZmlsZU5hbWUsIG1heFdpZHRoLCBtYXhIZWlnaHQpIHsNCgkNCgltYXhXaWR0aCA9IG1heFdpZHRoID09ICIiID8gMjUwMDAgOiBwYXJzZUludChtYXhXaWR0aCk7DQoJbWF4SGVpZ2h0ID0gbWF4SGVpZ2h0ID09ICIiID8gMjUwMDAgOiBwYXJzZUludChtYXhIZWlnaHQpOw0KDQoJdmFyIGltYWdlID0gbmV3IEltYWdlKCk7DQoJaW1hZ2Uuc3JjID0gZGF0YVVSTDsNCg0KCWltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHsNCgkJdmFyIHdpZHRoID0gaW1hZ2Uud2lkdGg7DQoJCXZhciBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7DQoJCXZhciBzaG91bGRSZXNpemUgPSAod2lkdGggPiBtYXhXaWR0aCkgfHwgKGhlaWdodCA+IG1heEhlaWdodCk7DQoNCgkJaWYgKCFzaG91bGRSZXNpemUpIHsNCgkJCQ0KCQkJZm9ybURhdGEuYXBwZW5kKCdmaWVsZCcsICd7JGZpZWxkLT5uYW1lfScpOw0KCQkJZm9ybURhdGEuYXBwZW5kKCdmaWxlJyArIGksIGRhdGFVUkwpOw0KCQkJDQoJCQlyZXR1cm47DQoJCX0NCg0KCQl2YXIgbmV3V2lkdGg7DQoJCXZhciBuZXdIZWlnaHQ7DQoNCgkJaWYgKHdpZHRoID4gaGVpZ2h0KSB7DQoJCQluZXdIZWlnaHQgPSBoZWlnaHQgKiAobWF4V2lkdGggLyB3aWR0aCk7DQoJCQluZXdXaWR0aCA9IG1heFdpZHRoOw0KCQl9IGVsc2Ugew0KCQkJbmV3V2lkdGggPSB3aWR0aCAqIChtYXhIZWlnaHQgLyBoZWlnaHQpOw0KCQkJbmV3SGVpZ2h0ID0gbWF4SGVpZ2h0Ow0KCQl9DQoNCgkJdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpOw0KDQoJCWNhbnZhcy53aWR0aCA9IG5ld1dpZHRoOw0KCQljYW52YXMuaGVpZ2h0ID0gbmV3SGVpZ2h0Ow0KDQoJCXZhciBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7DQoNCgkJY29udGV4dC5kcmF3SW1hZ2UodGhpcywgMCwgMCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7DQoNCgkJZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoZmlsZVR5cGUpOw0KCQkNCgkJLy8gU2VuZCBGb3IgVXBsb2FkLg0KCQkvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRm9ybURhdGENCgkJDQoJCXZhciBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpOw0KCQkNCgkJLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hUTUxDYW52YXNFbGVtZW50L3RvQmxvYg0KCQkNCgkJY2FudmFzLnRvQmxvYihmdW5jdGlvbihibG9iKSB7DQoJCQ0KCQkJdmFyIG5ld0ltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpLCB1cmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpOw0KCQkJICAgICAgDQoJCQkvLyBEZWJ1Zw0KCQkJbmV3SW1nLm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KCQkJCS8vIG5vIGxvbmdlciBuZWVkIHRvIHJlYWQgdGhlIGJsb2Igc28gaXQncyByZXZva2VkDQoJCQkJVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpOw0KCQkJfTsNCgkJCQ0KCQkJLy8gTm90IFN1cHBvcnRlZCBJbiBTYWZhcmkgKEFzIE9mIDMvMTgpDQoJCQkNCgkJCWlmKCFJc1NhZmFyaUJyb3dzZXIoKSkgew0KCQkJDQoJCQkJdmFyIGZpbGUgPSBuZXcgRmlsZShbYmxvYl0sIGZpbGVOYW1lLCB7DQoJCQkJICB0eXBlOiAiaW1hZ2UvanBlZyIsDQoJCQkJfSk7DQoJCQkJDQoJCQkJZm9ybURhdGEuYXBwZW5kKCdmaWxlJyArIGlkeCwgZmlsZSk7DQoJCQkNCgkJCX0gZWxzZSB7DQoJCQkNCgkJCQlmb3JtRGF0YS5hcHBlbmQoJ2ZpbGUnICsgaWR4LCBibG9iKTsNCgkJCQkNCgkJCQlmb3JtRGF0YS5hcHBlbmQoJ3NhZmFyaVJlc2l6ZWQnLCAndHJ1ZScpOw0KCQkJCWZvcm1EYXRhLmFwcGVuZCgnc2FmYXJpUmVzaXplZE5hbWUnLCBmaWxlTmFtZSk7DQoJCQkJDQoJCQl9DQoNCgkJCS8vIENvbW1vbiBJdGVtcy4gDQoJCQkNCgkJCWZvcm1EYXRhLmFwcGVuZCgnZmllbGQnLCAneyRmaWVsZC0+bmFtZX0nKTsNCgkJCQ0KCQkJDQoJCQkvLyBEZWJ1ZyAtIFNob3dzIEltYWdlIEF0IEJvdHRvbSBPZiBXaW5kb3cuDQoJCQkvLyBuZXdJbWcuc3JjID0gdXJsOw0KCQkJLy8gZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChuZXdJbWcpOw0KDQoJCQlwb3N0RmlsZV97JGZpZWxkLT5uYW1lfShmb3JtRGF0YSwgZmlsZXMpOw0KDQoJCX0sICdpbWFnZS9qcGVnJywgMC45NSk7DQoNCgl9Ow0KDQoJaW1hZ2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHsNCgkJYWxlcnQoJ1RoZXJlIHdhcyBhbiBlcnJvciBwcm9jZXNzaW5nIHlvdXIgZmlsZSEnKTsNCgl9Ow0KfQ0KDQpmdW5jdGlvbiBJc1NhZmFyaUJyb3dzZXIoKQ0Kew0KICB2YXIgVmVuZG9yTmFtZT13aW5kb3cubmF2aWdhdG9yLnZlbmRvcjsNCiAgcmV0dXJuICgoVmVuZG9yTmFtZS5pbmRleE9mKCdBcHBsZScpID4gLTEpICYmDQogICAgICAgICAgKHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ1NhZmFyaScpID4gLTEpKTsNCn0NCg0KZnVuY3Rpb24gcmVhZGZpbGVzX3skZmllbGQtPm5hbWV9KGZpbGVzKSB7DQoNCgkvLyBoaWRlIGZpZWxkIGFuZCBjbGVhciBhbnkgZXhpc3RpbmcgbWVzc2FnZXMNCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9Jykuc3R5bGUuZGlzcGxheSA9ICdub25lJzsNCglkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MID0gJyc7DQoJDQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbGVuYW1lX3skZmllbGQtPm5hbWV9JykuY2xhc3NOYW1lID0gJ2hpZGRlbic7DQoJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbGVuYW1lX3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MID0gJyc7DQoJDQogICAgdmFyIGZvcm1EYXRhID0gdGVzdHMuZm9ybWRhdGEgPyBuZXcgRm9ybURhdGEoKSA6IG51bGw7DQogICAgDQogICAgdmFyIGVycm9yX21lc3NhZ2UgPSAiIjsNCiAgICANCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7IA0KICAgICAgICANCiAgICAgICAgLy8gQ2hlY2sgRmlsZSBTaXplLg0KICAgICAgICANCiAgICAgICAgaWYoZmlsZXNbaV0uc2l6ZSA+IHskbWF4X2ZpbGVfc2l6ZX0pew0KICAgICAgICAgICAgDQogICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9ICJGaWxlICgiICsgZmlsZXNbaV0ubmFtZSArICIpIFRvbyBMYXJnZSwgTXVzdCBCZSBVbmRlciAiICsgKHskbWF4X2ZpbGVfc2l6ZX0gLyAxMDI0IC8gMTAyNCkgKyAiIE1CIDxici8+IjsNCg0KICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KICAgIA0KCQkvLyBJZiBSZXNpemluZyBSYXcgSW1hZ2VzLCBEbyBTbyBOb3cuDQoJCQ0KCQl2YXIgZmlsZUlzSW1hZ2UgPSAoZmlsZXNbaV0udHlwZS5zcGxpdCgnLycpWzBdID09ICdpbWFnZScpID8gdHJ1ZSA6IGZhbHNlOw0KCSAgICANCgkgICAgaWYoZmlsZUlzSW1hZ2UgJiYgKCd7JGZpZWxkLT5tYXh3aWR0aH0nICE9ICcnIHx8ICd7JGZpZWxkLT5tYXhoZWlnaHR9JyAhPSAnJykpew0KCSAgICANCgkgICAgCXJlYWRGaWxlX3skZmllbGQtPm5hbWV9KGZpbGVzLCBpLCBmaWxlc1tpXSwgJyRmaWVsZC0+bWF4d2lkdGgnLCAnJGZpZWxkLT5tYXhoZWlnaHQnKTsNCg0KCSAgICB9IGVsc2Ugew0KCSAgICANCgkJICAgIGlmICh0ZXN0cy5mb3JtZGF0YSl7DQoJCQkJZm9ybURhdGEuYXBwZW5kKCdmaWVsZCcsICd7JGZpZWxkLT5uYW1lfScpOw0KCQkJCWZvcm1EYXRhLmFwcGVuZCgnZmlsZScgKyBpLCBmaWxlc1tpXSk7DQoJCQl9DQoJCQkNCgkJCXBvc3RGaWxlX3skZmllbGQtPm5hbWV9KGZvcm1EYXRhLCBmaWxlcyk7DQoJCQ0KCSAgICB9DQoNCgkJaWYoeyRodG1sNXByZXZpZXd9ID09IHRydWUgJiYgZmlsZXNbaV0uc2l6ZSA8IHskdGhpcy0+Y3JlYXRlX2ZpbGVfdXBsb2FkX3NwZWMoJGZpZWxkLT5tYXhmaWxlc2l6ZSwgJ251bWJlcnNfb25seScpfSl7DQoJCQlwcmV2aWV3ZmlsZV97JGZpZWxkLT5uYW1lfShmaWxlc1tpXSk7DQoJCX0NCiAgICAgIA0KICAgIH0NCiAgICANCiAgICBpZihlcnJvcl9tZXNzYWdlICE9ICIiKXsNCiAgICAgICAgDQogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodG1sNS11cGxvYWQtZXJyb3JfeyRmaWVsZC0+bmFtZX0nKS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsNCiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2h0bWw1LXVwbG9hZC1lcnJvcl97JGZpZWxkLT5uYW1lfScpLmlubmVySFRNTCArPSAnPHNwYW4gY2xhc3M9Imh0bWw1LXVwbG9hZC1lcnJvci1tZXNzYWdlIj4nICsgZXJyb3JfbWVzc2FnZSArICc8L3NwYW4+JzsNCiAgICANCiAgICB9DQogICAgDQp9DQoNCmZ1bmN0aW9uIHJlYWRGaWxlX3skZmllbGQtPm5hbWV9KGZpbGVzLCBpZHgsIGZpbGUsIG1heFdpZHRoLCBtYXhIZWlnaHQpIHsNCgl2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsNCgkNCgkJcmVhZGVyLm9ubG9hZGVuZCA9IGZ1bmN0aW9uICgpIHsNCgkJCXJlc2l6ZUZpbGVfeyRmaWVsZC0+bmFtZX0oZmlsZXMsIGlkeCwgcmVhZGVyLnJlc3VsdCwgZmlsZS50eXBlLCBmaWxlLm5hbWUsIG1heFdpZHRoLCBtYXhIZWlnaHQpOw0KCQl9DQoJDQoJCXJlYWRlci5vbmVycm9yID0gZnVuY3Rpb24gKCkgew0KCQkJYWxlcnQoJ1RoZXJlIHdhcyBhbiBlcnJvciByZWFkaW5nIHRoZSBmaWxlIScpOw0KCQl9DQoJDQoJcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7DQp9DQoNCmZ1bmN0aW9uIGRlbGV0ZUZpbGVfeyRmaWVsZC0+bmFtZX0oZmlsZW5hbWUpew0KDQoJLy8gRGVsZXRlIEZyb20gVXBsb2Fkcw0KCQ0KCXZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsNCgkNCgl2YXIgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTsNCgkNCglmb3JtRGF0YS5hcHBlbmQoJ2FjdGlvbicsICJkZWxldGUiKTsNCglmb3JtRGF0YS5hcHBlbmQoJ2ZpbGVuYW1lJywgZmlsZW5hbWUpOw0KCWZvcm1EYXRhLmFwcGVuZCgnZmllbGRuYW1lJywgJ3skZmllbGQtPm5hbWV9Jyk7DQoNCgl4aHIub3BlbignUE9TVCcsICdsaWIvdXBsb2FkL2h0bWw1X3VwbG9hZC5waHAnKTsNCiAgICAgIA0KCXhoci5vbmxvYWQgPSBmdW5jdGlvbih4aHIpIHsgLy8gZmlsZSBkb25lIHVwbG9hZGluZy4uLg0KICAgICAgDQoJCWlmKHhoci50YXJnZXQucmVzcG9uc2UuaW5kZXhPZignWEhSX0VSUk9SJykgIT0gLTEpew0KCQkNCgkJDQoJCX0gZWxzZSB7DQoJCQ0KCQkNCgkJfQ0KICAgICAgDQoJfQ0KCQ0KCXhoci5zZW5kKGZvcm1EYXRhKTsNCgkNCgkvLyBEZWxldGUgRnJvbSBET00NCgkNCgl2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJodG1sNVByZXZpZXdfIiArIGZpbGVuYW1lKTsNCgllbGVtZW50Lm91dGVySFRNTCA9ICIiOw0KCWRlbGV0ZSBlbGVtZW50Ow0KCQ0KfQ0KDQpmdW5jdGlvbiBwb3N0RmlsZV97JGZpZWxkLT5uYW1lfShmb3JtRGF0YSwgZmlsZXMpew0KDQoJLy8gbm93IHBvc3QgYSBuZXcgWEhSIHJlcXVlc3QNCiAgICBpZiAodGVzdHMuZm9ybWRhdGEpIHsNCiAgICANCiAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsNCiAgICAgIA0KICAgICAgeGhyLm9wZW4oJ1BPU1QnLCAnbGliL3VwbG9hZC9odG1sNV91cGxvYWQucGhwJyk7DQogICAgICANCiAgICAgIA0KICAgICAgLy8gSGlkZSBNZXNzYWdlDQogICAgICANCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodG1sNUluc3RydWN0aW9uc197JGZpZWxkLT5uYW1lfScpLnN0eWxlLmRpc3BsYXkgPSAibm9uZSI7DQogICAgICANCiAgICAgIC8vIFNob3cgUHJvZ3Jlc3MgQmFyDQoNCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGxvYWQtcHJvZ3Jlc3MtbWVzc2FnZV97JGZpZWxkLT5uYW1lfScpLnN0eWxlLmRpc3BsYXkgPSAiYmxvY2siOw0KICAgICAgDQogICAgICANCiAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbih4aHIpIHsgLy8gZmlsZSBkb25lIHVwbG9hZGluZy4uLg0KICAgICAgICANCgkJLy8gY2hlY2sgZm9yIGVycm9ycy4uLg0KDQoJCWlmKHhoci50YXJnZXQucmVzcG9uc2UuaW5kZXhPZignWEhSX0VSUk9SJykgIT0gLTEpew0KCQkgICAgDQoJCQltZXNzYWdlID0geGhyLnRhcmdldC5yZXNwb25zZS5yZXBsYWNlKCdYSFJfRVJST1InLCAnJykucmVwbGFjZSgnPGJyLz4nLCAnJyk7DQoJCQkNCgkJICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodG1sNS11cGxvYWQtZXJyb3JfeyRmaWVsZC0+bmFtZX0nKS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsNCgkJIAlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaHRtbDUtdXBsb2FkLWVycm9yX3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MICs9ICc8c3BhbiBjbGFzcz0iaHRtbDUtdXBsb2FkLWVycm9yLW1lc3NhZ2UiPicgKyBtZXNzYWdlICsgJzwvc3Bhbj4nOw0KCQkgCQ0KCQkgCS8vIFNob3cgTWVzc2FnZQ0KICAgICAgCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaHRtbDVJbnN0cnVjdGlvbnNfeyRmaWVsZC0+bmFtZX0nKS5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIjsNCiAgICAgIA0KICAgICAgCQkvLyBIaWRlIFByb2dyZXNzIEJhcg0KICAgICAgCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkLXByb2dyZXNzLW1lc3NhZ2VfeyRmaWVsZC0+bmFtZX0nKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOw0KICAgICAgDQoJCQkvLyBSZXNldCBQcm9ncmVzcyBCYXIuDQoJCSAJdXBsb2FkcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0udmFsdWUgPSAwOw0KCQkgCXVwbG9hZHByb2dyZXNzX3skZmllbGQtPm5hbWV9LmlubmVySFRNTCA9ICIwIjsNCgkJCSAJDQoJCX0gZWxzZSB7DQoJCQkNCgkJCXVwbG9hZHByb2dyZXNzX3skZmllbGQtPm5hbWV9LnZhbHVlID0gdXBsb2FkcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0uaW5uZXJIVE1MID0gMTAwOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbGVuYW1lX3skZmllbGQtPm5hbWV9JykuaW5uZXJIVE1MID0gIiI7DQoJCSAJDQoJCSAJZm9yKGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspew0KCQkgCQ0KCQkJIAlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmlsZW5hbWVfeyRmaWVsZC0+bmFtZX0nKS5jbGFzc05hbWUgPSAndmlzaWJsZSc7DQoJCQkgCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaWxlbmFtZV97JGZpZWxkLT5uYW1lfScpLmlubmVySFRNTCArPSAieyRmaWVsZC0+aHRtbDVjb21wbGV0ZW1lc3NhZ2V9ICIgKyAiPHN0cm9uZz4iICsgZmlsZXNbaV0ubmFtZSArICI8L3N0cm9uZz48YnIvPiI7DQoJCQkgCQ0KCQkJIAkvLyBTaG93IE1lc3NhZ2UNCiAgICAgIAkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdodG1sNUluc3RydWN0aW9uc197JGZpZWxkLT5uYW1lfScpLnN0eWxlLmRpc3BsYXkgPSAiYmxvY2siOw0KICAgICAgDQogICAgICAJCQkvLyBIaWRlIFByb2dyZXNzIEJhcg0KICAgICAgCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZC1wcm9ncmVzcy1tZXNzYWdlX3skZmllbGQtPm5hbWV9Jykuc3R5bGUuZGlzcGxheSA9ICJub25lIjsNCiAgICAgIAkJDQoJCQkgCS8vIFJlc2V0IFByb2dyZXNzIEJhci4NCgkJCSAJdXBsb2FkcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0udmFsdWUgPSAwOw0KCQkJIAl1cGxvYWRwcm9ncmVzc197JGZpZWxkLT5uYW1lfS5pbm5lckhUTUwgPSAiMCI7DQoJCSAJDQoJCSAJfQ0KCQkgCQ0KCQl9DQogICAgICAgICAgDQogICAgICB9Ow0KDQogICAgICBpZiAodGVzdHMucHJvZ3Jlc3MpIHsNCiAgICAgICAgeGhyLnVwbG9hZC5vbnByb2dyZXNzID0gZnVuY3Rpb24gKGV2ZW50KSB7DQogICAgICAgICAgaWYgKGV2ZW50Lmxlbmd0aENvbXB1dGFibGUpIHsNCiAgICAgICAgICAgIHZhciBjb21wbGV0ZSA9IChldmVudC5sb2FkZWQgLyBldmVudC50b3RhbCAqIDEwMCB8IDApOw0KICAgICAgICAgICAgdXBsb2FkcHJvZ3Jlc3NfeyRmaWVsZC0+bmFtZX0udmFsdWUgPSB1cGxvYWRwcm9ncmVzc197JGZpZWxkLT5uYW1lfS5pbm5lckhUTUwgPSBjb21wbGV0ZTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCg0KICAgICAgeGhyLnNlbmQoZm9ybURhdGEpOw0KICAgIH0NCiAgICANCn0NCg0KaWYgKHRlc3RzLmRuZCkgeyANCg0KCS8vIEdldCBFeGlzdGluZyBDbGFzcyBOYW1lKHMpDQoJdmFyIF9leGlzdGluZ0NsYXNzID0gaG9sZGVyX3skZmllbGQtPm5hbWV9LmNsYXNzTmFtZTsNCg0KCWhvbGRlcl97JGZpZWxkLT5uYW1lfS5vbmRyYWdvdmVyID0gZnVuY3Rpb24gKCkgeyB0aGlzLmNsYXNzTmFtZSA9IF9leGlzdGluZ0NsYXNzICsgJyBob3Zlcic7IHJldHVybiBmYWxzZTsgfTsNCglob2xkZXJfeyRmaWVsZC0+bmFtZX0ub25kcmFnbGVhdmUgPSBmdW5jdGlvbiAoKSB7IHRoaXMuY2xhc3NOYW1lID0gX2V4aXN0aW5nQ2xhc3M7IHJldHVybiBmYWxzZTsgfTsNCglob2xkZXJfeyRmaWVsZC0+bmFtZX0ub25kcmFnZW5kID0gZnVuY3Rpb24gKCkgeyB0aGlzLmNsYXNzTmFtZSA9IF9leGlzdGluZ0NsYXNzOyByZXR1cm4gZmFsc2U7IH07DQoJaG9sZGVyX3skZmllbGQtPm5hbWV9Lm9uZHJvcCA9IGZ1bmN0aW9uIChlKSB7DQogICAgCXRoaXMuY2xhc3NOYW1lID0gX2V4aXN0aW5nQ2xhc3M7DQogICAgCWUucHJldmVudERlZmF1bHQoKTsNCiAgICAJcmVhZGZpbGVzX3skZmllbGQtPm5hbWV9KGUuZGF0YVRyYW5zZmVyLmZpbGVzKTsNCiAgCX0NCiAgCQ0KfSANCg0KZmlsZXVwbG9hZF97JGZpZWxkLT5uYW1lfS5jbGFzc05hbWUgPSAnaGlkZGVuJzsNCmZpbGV1cGxvYWRfeyRmaWVsZC0+bmFtZX0ucXVlcnlTZWxlY3RvcignaW5wdXQnKS5vbmNoYW5nZSA9IGZ1bmN0aW9uICgpIHsNCiAgICByZWFkZmlsZXNfeyRmaWVsZC0+bmFtZX0odGhpcy5maWxlcyk7DQp9Ow0KDQo8L3NjcmlwdD4NCgkJDQpFT0Y7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZidG9vbHRpcC17JGlkfSBmYnRvb2x0aXBcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj57JHRvb2x0aXBfZWxlbWVudC0+dGV4dH08L2Rpdj5cbiI7DQogICAgICAgICRlbGVtZW50IC49ICR0b29sdGlwX2VsZW1lbnQtPmpzOw0KDQogICAgICAgIGlmICgkaGVscGVyICE9ICcnKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48YnIvPjxkaXYgY2xhc3M9XCJoZWxwZXJcIiBzdHlsZT1cImNvbG9yOnskaGVscGVyY29sb3J9O1wiPnskaGVscGVyfTwvZGl2PlxuIjsNCiAgICAgICAgfQ0KICAgICAgICAkZWxlbWVudCAuPSAnPGJyIC8+JzsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjwvZGl2PlxuIjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICAgICAgDQogICAgfSANCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9tdWx0aWZpbGUoJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQogICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRoZWxwZXIgPSAkZmllbGQtPmhlbHBlcjsNCiAgICAgICAgJGhlbHBlcmNvbG9yID0gJGZpZWxkLT5oZWxwZXJjb2xvcjsNCiAgICAgICAgJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCiAgICAgICAgJGxhYmVscG9zID0gJGZpZWxkLT5sYWJlbHBvczsNCiAgICAgICAgJGF1dG9tb2RlID0gJGZpZWxkLT5hdXRvbW9kZTsNCiAgICAgICAgJGZpbGVjb3VudCA9ICRmaWVsZC0+ZmlsZWNvdW50Ow0KICAgICAgICAkZGVzdGluYXRpb24gPSAkZmllbGQtPmRlc3RpbmF0aW9uOw0KICAgICAgICAkdXNlY3VzdG9tY29kZSA9ICRmaWVsZC0+dXNlY3VzdG9tY29kZTsNCiAgICAgICAgJGN1c3RvbWNvZGUgPSAkZmllbGQtPmN1c3RvbWNvZGU7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICR0YWJpbmRleCA9ICRmaWVsZC0+dGFiaW5kZXg7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCg0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgICRzdHlsZXMgPSAkdGhpcy0+dHJhbnNsYXRlRmllbGRTdHlsZXMoJHN0eWxlKTsNCg0KICAgICAgICANCiAgICAgICAgJGRlc3RpbmF0aW9uID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGVzdGluYXRpb24sIDYpOw0KDQogICAgICAgICRsYWJlbHBvcyA9ICR0aGlzLT5nZXRfbGFiZWxfcG9zKCRsYWJlbHBvcyk7DQoNCiAgICAgICAgaWYgKChpbnQpJGF1dG9tb2RlID09IDEpIHsNCiAgICAgICAgICAgICRhdXRvID0gJyc7DQogICAgICAgICAgICAkYXV0b21vZGUgPSAndHJ1ZSc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYXV0byA9ICI8c3BhbiBjbGFzcz1cInVwbG9hZGlmeUNvbnRyb2xcIiB7JHRhYmh0bWx9PjxhIGhyZWY9XCJqYXZhc2NyaXB0OmpRdWVyeSgnI3skaWR9JykudXBsb2FkaWZ5VXBsb2FkKCk7XCI+VXBsb2FkIEZpbGVzPC9hPiB8IDxhIGhyZWY9XCJqYXZhc2NyaXB0OmpRdWVyeSgnI3skaWR9JykudXBsb2FkaWZ5Q2xlYXJRdWV1ZSgpO1wiPkNsZWFyIFF1ZXVlPC9hPjwvc3Bhbj4iOw0KICAgICAgICAgICAgJGF1dG9tb2RlID0gJ2ZhbHNlJzsNCiAgICAgICAgfQ0KDQogICAgICAgICRtdWx0aSA9IChpbnQpJGZpbGVjb3VudCA9PSAwID8gJ2ZhbHNlJyA6ICd0cnVlJzsNCg0KICAgICAgICAkc2NyaXB0cyA9IDw8PEVPVA0KDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJsaWIvdXBsb2FkaWZ5L2pxdWVyeS0xLjMuMi5taW4uanMiPjwvc2NyaXB0Pg0KCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImxpYi91cGxvYWRpZnkvc3dmb2JqZWN0LmpzIj48L3NjcmlwdD4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ibGliL3VwbG9hZGlmeS9qcXVlcnkudXBsb2FkaWZ5LnYyLjEuMC5taW4uanMiPjwvc2NyaXB0Pg0KDQo8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBocmVmPSJsaWIvdXBsb2FkaWZ5L3VwbG9hZGlmeS5jc3MiIG1lZGlhPSJzY3JlZW4iIC8+DQoJCQ0KCQkNCkVPVDsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+bGVmdGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRmaXhlZF93aWR0aCA9ICR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aCAtIDg7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyRmaXhlZF93aWR0aH1weDsgbWFyZ2luLXJpZ2h0OjhweDsgcGFkZGluZy10b3A6M3B4OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259XCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJlcSA9IDA7DQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgJHJlcSwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsICRsYWJlbHBvcywgKHN0cmluZykkZmllbGQtPnR5cGUsICcnLCAnJywgJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfdGFibGVfbW9kZV9tb2JpbGVfbGFiZWwoJGZpZWxkLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICAkZWxlbWVudCAuPSA8PDxFT0YNCg0KPGlucHV0IGlkPSJ7JGlkfSIgbmFtZT0ieyRuYW1lfSIgdHlwZT0iZmlsZSIgLz48YnIvPg0KeyRhdXRvfQ0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPi8vIDwhW0NEQVRBWw0KalF1ZXJ5Lm5vQ29uZmxpY3QoKTsNCmpRdWVyeShkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7DQpqUXVlcnkoJyN7JGlkfScpLnVwbG9hZGlmeSh7DQondXBsb2FkZXInICA6ICdsaWIvdXBsb2FkaWZ5L3VwbG9hZGlmeS5zd2YnLA0KJ3NjcmlwdCcgICAgOiAnbGliL3VwbG9hZGlmeS91cGxvYWRpZnkucGhwJywNCidjYW5jZWxJbWcnIDogJ2xpYi91cGxvYWRpZnkvY2FuY2VsLnBuZycsDQonZm9sZGVyJyAgICA6ICd7JGRlc3RpbmF0aW9ufScsDQonYXV0bycJCTogeyRhdXRvbW9kZX0sDQonbXVsdGknCQk6IHskbXVsdGl9DQp9KTsNCn0pOw0KLy8gXV0+PC9zY3JpcHQ+DQpFT0Y7DQoNCiAgICAgICAgaWYgKChpbnQpJHVzZWN1c3RvbWNvZGUgPT0gMSAmJiAkY3VzdG9tY29kZSAhPSAnJykgew0KICAgICAgICAgICAgJGVsZW1lbnQgPSAkY3VzdG9tY29kZTsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgaWYgKCRoZWxwZXIgIT0gJycpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8YnIvPjxkaXYgY2xhc3M9XCJoZWxwZXJcIiBzdHlsZT1cImNvbG9yOnskaGVscGVyY29sb3J9O1wiPnskaGVscGVyfTwvZGl2PiI7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAnPGJyIC8+JzsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkc2NyaXB0cyAuICRlbGVtZW50Ow0KICAgIH0NCg0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2NhbGVuZGFyKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+eydsYWJlbCd9Ow0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+eyduYW1lJ307DQogICAgICAgICRpZCA9ICRmaWVsZC0+eydpZCd9Ow0KICAgICAgICAkcmVxID0gJGZpZWxkLT52YWxpZGF0aW9uLT5yZXE7DQogICAgICAgICRmaWVsZHdpZHRoID0gJGZpZWxkLT5maWVsZHdpZHRoOw0KICAgICAgICAkZmllbGRoZWlnaHQgPSAkZmllbGQtPmZpZWxkaGVpZ2h0Ow0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGZpZWxkLT5kZWZhdWx0dmFsdWU7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KCQkkbWF4bGVuZ3RoID0gJGZpZWxkLT52YWxpZGF0aW9uLT5tYXg7DQoJCSRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9IGlzc2V0KCRmaWVsZC0+ZmllbGRwb3B1bGF0ZWRlZmF1bHQpID8gJGZpZWxkLT5maWVsZHBvcHVsYXRlZGVmYXVsdCA6IDE7IA0KICAgICAgICAkYXR0cmlidXRlID0gJGZpZWxkLT5hdHRyaWJ1dGU7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICRmaWVsZC0+YXR0cmlidXRlc3R5bGU7DQogICAgICAgICRjb25kaXRpb25hbCA9ICRmaWVsZC0+Y29uZGl0aW9uYWw7DQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICR0b29sdGlwID0gJGZpZWxkLT50b29sdGlwOw0KDQogICAgICAgICRjYWxlbmRhcnR5cGUgPSAkZmllbGQtPmNhbGVuZGFydHlwZTsNCiAgICAgICAgJGNhbGVuZGFyYXJndW1lbnRzID0gJGZpZWxkLT5jYWxlbmRhcmFyZ3VtZW50czsNCg0KICAgICAgICAkY2FsbGJhY2sgPSBpc3NldCgkZmllbGQtPmNhbGxiYWNrKSA/ICRmaWVsZC0+Y2FsbGJhY2sgOiAnJzsgDQoNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCg0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQogICAgICAgICRzdHlsZXMgPSAkdGhpcy0+dHJhbnNsYXRlRmllbGRTdHlsZXMoJHN0eWxlKTsNCg0KICAgICAgICANCiAgICAgICAgJGRlZmF1bHR2YWx1ZSA9ICR0aGlzLT5jcmVhdGVfZGVmYXVsdF92YWx1ZV90b2tlbnMoJGRlZmF1bHR2YWx1ZSk7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF9jYWxsID0gJHRoaXMtPl9jcmVhdGVDb25kaXRpb25hbEV2ZW50KCRjb25kaXRpb25hbCwgJG5hbWUsICRpZCk7DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICRjb25kaXRpb25hbF9jYWxsWzBdOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAkY29uZGl0aW9uYWxfY2FsbFsxXTsNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRmaWVsZGhlaWdodCkpIHsNCiAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICIiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkaGVpZ2h0ID09ICIiKSB7DQogICAgICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7IA0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiaGVpZ2h0OnskZmllbGRoZWlnaHR9cHg7IjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdwdCcpOw0KICAgICAgICAkY3QyID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHgnKTsNCg0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJGZvbnRzaXplID0gJGZvbnRzaXplIC4gJ3B4JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkdGVzdCA9IChpbnQpJGluaGVyaXRzdHlsZTsNCiAgICAgICAgaWYgKCR0ZXN0ICE9IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAwOw0KICAgICAgICB9DQogICAgICAgIGlmICgkaW5oZXJpdHN0eWxlID09IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIGZvbnQtc2l6ZTp7JGZvbnRzaXplfTsgY29sb3I6eyRpbnB1dF9jb2xvcn07IHskZmllbGRoZWlnaHR9IGZvbnQtZmFtaWx5OmluaGVyaXQ7IHskYXR0cmlidXRlc3R5bGV9ICI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgY29sb3I6eyRpbnB1dF9jb2xvcn07IHskYXR0cmlidXRlc3R5bGV9IHskZmllbGRoZWlnaHR9ICI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZmllbGR3aWR0aCwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZmllbGR3aWR0aCwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRzaXplX2NzcyA9ICIgd2lkdGg6eyRmaWVsZHdpZHRofXB4OyAiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHNpemVfY3NzID0gIiB3aWR0aDp7JGZpZWxkd2lkdGh9OyAiOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGJ1Y2tldF9ub2RlKSAmJiAkYnVja2V0X25vZGUgIT0gIiIgJiYgKGludCkkYnVja2V0X25vZGUtPnJlcGVhdGVyLT5yZXNwb25zaXZlID09IDEpIHsNCiAgICAgICAgICAgICRzaXplX2NzcyA9ICIgd2lkdGg6NjAlOyAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkY2FsX2FyZ3MgPSBleHBsb2RlKCd8JywgJGNhbGVuZGFyYXJndW1lbnRzKTsNCiAgICAgICAgJGFyZ19saXN0ID0gJyc7DQogICAgICAgIGlmICgkY2FsX2FyZ3NbMF0gIT09ICcnKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkY2FsX2FyZ3MgYXMgJGFyZ3MpIHsNCiAgICAgICAgICAgICAgICAkYXJnX2xpc3QgLj0gImNhbHskbmFtZX0uIiAuICRhcmdzIC4gJzsnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmxlZnRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskZml4ZWRfd2lkdGh9cHg7IG1hcmdpbi1yaWdodDo4cHg7IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufVwiID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRtYXhsZW5ndGggIT0gJycpIHsNCiAgICAgICAgICAgICRtYXggPSAgIm1heGxlbmd0aD1cInskbWF4bGVuZ3RofVwiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRtYXggPSAnJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJG5hbWUsICRyZXEsICRyZXF1aXJlZF90ZXh0LCAkY29sb3IsICRmb250c2l6ZSwgJHN0eWxlcywgJGxhYmVsLCAkbGFiZWxwb3MsIChzdHJpbmcpJGZpZWxkLT50eXBlLCAnJywgJycsICR0YWJsZW1vZGUpOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkY2FsYmFja19jb2RlID0gPDw8RU9GDQoNCnZhciBkYXRlID0gbmV3IERhdGUoRGF0ZS5VVEMoeSxtLTEsZCwwLDAsMCkpOw0KdmFyIHNfdHMgPSBkYXRlLmdldFRpbWUoKS8xMDAwOw0KdmFyIGNfdHMgPSBNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpLzEwMDApDQoJCQ0KeyRjYWxsYmFja30NCg0KRU9GOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGV4dHJhY2xhc3NuYW1lcyA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPmV4dHJhY2xhc3NuYW1lKSAmJiAkZmllbGQtPmV4dHJhY2xhc3NuYW1lICE9ICIiKSB7DQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gJGZpZWxkLT5leHRyYWNsYXNzbmFtZTsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+Y3JlYXRlX3RhYmxlX21vZGVfbW9iaWxlX2xhYmVsKCRmaWVsZCwgJHRhYmxlbW9kZSk7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJHJlYWRvbmx5ID0gaXNzZXQoJHJlYWRvbmx5KSA/ICRyZWFkb25seSA9PSAxID8gIiByZWFkb25seSAiIDogIiIgOiAiIjsNCiAgICAgICAgJGVuYWJsZWQgPSBpc3NldCgkZmllbGRlbmFibGVkKSA/ICRmaWVsZGVuYWJsZWQgPT0gMCA/ICIgZGlzYWJsZWQgIiA6ICIiIDogIiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZihpc3NldCgkZmllbGQtPmJ1Y2tldCkgJiYgJGZpZWxkLT5idWNrZXQgIT0gIiIpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZXh0cmFjbGFzc25hbWVzIC49ICIgYnVja2V0LWNvbnRhaW5lZC1maWVsZCI7DQogICAgICAgICAgICANCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJF92YWx1ZSA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OW1wieyRuYW1lfVwiXSkgPyBwcmludCBcJF9TRVNTSU9OW1wieyRuYW1lfVwiXSA6IHByaW50ICRkZWZhdWx0dmFsdWU7ID8+IjsNCg0KICAgICAgICBpZihpc3NldCgkZmllbGRwb3B1bGF0ZWRlZmF1bHQpICYmICRmaWVsZHBvcHVsYXRlZGVmYXVsdCA9PSAwKXsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJF92YWx1ZSA9ICc8P3BocCBwcmludCAkZGVmYXVsdHZhbHVlOyA/Pic7DQoNCiAgICAgICAgfSANCiAgICAgICAgDQogICAgICAgIHN3aXRjaCAoJGNhbGVuZGFydHlwZSkgew0KICAgICAgICAgICAgY2FzZSAnMCc6IA0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCgkvLyBDYWxlbmRhciBCbG9ja3MgSGludA0KCS8vdmFyIGNhbHskbmFtZX0gPSBuZXcgQ2FsZW5kYXJQb3B1cCgpOyAvLyB1c2UgcG9wdXAgd2luZG93DQoJdmFyIGNhbHskbmFtZX0gPSBuZXcgQ2FsZW5kYXJQb3B1cCgiY2FsLWRpdi17JG5hbWV9Iik7IHskYXJnX2xpc3R9DQoJY2FseyRuYW1lfS5zZXRSZXR1cm5GdW5jdGlvbigic2V0TXVsdGlwbGVWYWx1ZXNfeyRuYW1lfSIpOw0KCWZ1bmN0aW9uIHNldE11bHRpcGxlVmFsdWVzX3skbmFtZX0oeSxtLGQpIHsNCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykudmFsdWU9TFoobSkgKyAnLycgKyBMWihkKSArICcvJyArIHk7DQoJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0xJ10uY2hlY2soKTsNCgkJDQoJCS8vIEJ1aWxkIDkxNSAtIEZvY3VzIGZpZWxkLCBhbGxvd3MgdXMgdG8gYmluZCBldmVudHMgdG8gdGhpcyB2YWx1ZSBjaGFuZ2luZy4NCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykuZm9jdXMoKTsNCgkJDQoJCS8vIEN1c3RvbSBDYWxsYmFjayBDb2RlLg0KCQl7JGNhbGJhY2tfY29kZX0NCgkJDQogICAgIH0NCgk8L3NjcmlwdD4NCgk8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+DQoNCjxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gdHlwZT0idGV4dCIgY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1maWVsZC1mdWxsIiBuYW1lPSJ7JG5hbWV9IiBpZD0iZGF0ZS17JGlkfS0xIiB7JHRhYmh0bWx9IHZhbHVlPSJ7JF92YWx1ZX0iIHskbWF4fSBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IHskc2l6ZV9jc3N9IiB7JGF0dHJpYnV0ZX0geyRjb25kaXRpb25hbF9jYWxsX2lubGluZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCTxhIGlkPSJjYWwtYW5jaG9yLXskbmFtZX0iIGNsYXNzPSJjYWwtYW5jaG9yLWZ1bGwiIG5hbWU9ImNhbC1hbmNob3IteyRuYW1lfSIgaHJlZj0iIyIgb25jbGljaz0iY2FseyRuYW1lfS5zaG93Q2FsZW5kYXIoJ2NhbC1hbmNob3IteyRuYW1lfScpOyByZXR1cm4gZmFsc2U7IiA+PGltZyBjbGFzcz0iY2FsLWFuY2hvciIgc3R5bGU9Im1hcmdpbi1sZWZ0OjVweDsgbWFyZ2luLWJvdHRvbTotN3B4OyIgYWx0PSJEYXRlIFBpY2tlciIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvY2FsLTAucG5nIiBib3JkZXI9IjAiIC8+PC9hPgkNCg0KRU9UOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIGNhc2UgJzEnOiANCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCgk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJICAgIC8vIENhbGVuZGFyIEJsb2NrcyBIaW50DQoJCXZhciBjYWx7JG5hbWV9ID0gbmV3IENhbGVuZGFyUG9wdXAoImNhbC1kaXYteyRuYW1lfSIpOyB7JGFyZ19saXN0fQ0KCQljYWx7JG5hbWV9LnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9Iik7DQoJCWZ1bmN0aW9uIHNldE11bHRpcGxlVmFsdWVzX3skbmFtZX0oeSxtLGQpIHsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLnZhbHVlPUxaKG0pOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0yJykudmFsdWU9TFooZCk7DQoJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTMnKS52YWx1ZT15Ow0KCQkJdmFsaWRhdG9yc1snZGF0ZS17JG5hbWV9LTEnXS5jaGVjaygpOw0KCQkJdmFsaWRhdG9yc1snZGF0ZS17JG5hbWV9LTInXS5jaGVjaygpOw0KCQkJdmFsaWRhdG9yc1snZGF0ZS17JG5hbWV9LTMnXS5jaGVjaygpOw0KCQkJDQoJCQkvLyBCdWlsZCA5MTUgLSBGb2N1cyBmaWVsZCwgYWxsb3dzIHVzIHRvIGJpbmQgZXZlbnRzIHRvIHRoaXMgdmFsdWUgY2hhbmdpbmcuDQoJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTEnKS5mb2N1cygpOw0KCQkJDQoJCQkvLyBDdXN0b20gQ2FsbGJhY2sgQ29kZS4NCgkJCXskY2FsYmFja19jb2RlfQ0KCQkJDQoJICAgICB9DQoJPC9zY3JpcHQ+DQo8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+CQ0KDQoJPD9waHANCglcJGR2ID0geyRkZWZhdWx0dmFsdWV9Ow0KCQ0KCWlmKFwkZHYgPT0gIiIpDQoJCVwkZHYgPSBcJGRhdGV0aW1lOw0KCQ0KCVwkbW9udGggPSAnJzsNCglcJGRheSA9ICcnOw0KCVwkeWVhciA9ICcnOw0KCQ0KCWlmKFwkZHYgIT0gJycpew0KCQkNCgkJLy8gYW1lcmljYW4NCgkJaWYoaXNfb2JqZWN0KFwkZHYpKSB7DQoJCQlcJGRhdGUgPSBcJGR2Ow0KCQl9IGVsc2Ugew0KCQkJXCRkYXRlID0gbmV3IERhdGVUaW1lKHskZGVmYXVsdHZhbHVlfSk7DQoJCX0NCg0KCQlcJG1vbnRoID0gXCRkYXRlLT5mb3JtYXQoJ20nKTsNCgkJXCRkYXkgPSBcJGRhdGUtPmZvcm1hdCgnZCcpOw0KCQlcJHllYXIgPSBcJGRhdGUtPmZvcm1hdCgnWScpOw0KCQkNCgl9DQoJDQoJXCRjYWxfc2VsZWN0X2NvZGUgPSAiJ3tcJG1vbnRofS97XCRkYXl9L3tcJHllYXJ9JyI7DQoJDQoJPz4NCg0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gdHlwZT0idGV4dCIgY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1udW1lcmljLWZpZWxkLTEiIG5hbWU9ImRhdGUteyRuYW1lfS0xIiBpZD0iZGF0ZS17JGlkfS0xIiB7JHRhYmh0bWx9IHZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSA/IHByaW50IFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gOiBwcmludCBcJG1vbnRoOyA/PiIgc2l6ZT0iMiIgbWF4bGVuZ3RoPSIyIiBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gdHlwZT0idGV4dCIgY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1udW1lcmljLWZpZWxkLTIiIG5hbWU9ImRhdGUteyRuYW1lfS0yIiBpZD0iZGF0ZS17JGlkfS0yIiB2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgPyBwcmludCBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddIDogcHJpbnQgXCRkYXk7ID8+IiBzaXplPSIyIiBtYXhsZW5ndGg9IjIiIHN0eWxlPSJ7JGluaGVyaXRzdHlsZX0iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiB0eXBlPSJ0ZXh0IiBjbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLW51bWVyaWMtZmllbGQtMyIgbmFtZT0iZGF0ZS17JG5hbWV9LTMiIGlkPSJkYXRlLXskaWR9LTMiIHZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMyddKSA/IHByaW50IFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0zJ10gOiBwcmludCBcJHllYXI7ID8+IiBzaXplPSI0IiBtYXhsZW5ndGg9IjQiIHN0eWxlPSJ7JGluaGVyaXRzdHlsZX0iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJPGEgaWQ9ImNhbC1hbmNob3IteyRuYW1lfSIgY2xhc3M9ImNhbC1hbmNob3ItbXVsdGkiIG5hbWU9ImNhbC1hbmNob3IteyRuYW1lfSIgaHJlZj0iIyIgb25jbGljaz0iY2FseyRuYW1lfS5zaG93Q2FsZW5kYXIoJ2NhbC1hbmNob3IteyRuYW1lfScsIDw/cGhwIGVjaG8gXCRjYWxfc2VsZWN0X2NvZGU7ID8+KTsgcmV0dXJuIGZhbHNlOyIgPjxpbWcgY2xhc3M9ImNhbC1hbmNob3IiIHN0eWxlPSJtYXJnaW4tbGVmdDo1cHg7IG1hcmdpbi1ib3R0b206LTdweDsiIGFsdD0iRGF0ZSBQaWNrZXIiIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmNhbGVuZGFyL2NhbC0wLnBuZyIgYm9yZGVyPSIwIiAvPjwvYT4JDQoNCkVPVDsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOiANCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCgk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJICAgIC8vIENhbGVuZGFyIEJsb2NrcyBIaW50DQoJCXZhciBjYWx7JG5hbWV9ID0gbmV3IENhbGVuZGFyUG9wdXAoImNhbC1kaXYteyRuYW1lfSIpOyB7JGFyZ19saXN0fQ0KCQljYWx7JG5hbWV9LnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9Iik7DQoJCWZ1bmN0aW9uIHNldE11bHRpcGxlVmFsdWVzX3skbmFtZX0oeSxtLGQpIHsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLnNlbGVjdGVkSW5kZXg9bTsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMicpLnNlbGVjdGVkSW5kZXg9ZDsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMycpLnZhbHVlPXk7DQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMSddLmNoZWNrKCk7DQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMiddLmNoZWNrKCk7DQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMyddLmNoZWNrKCk7DQoJCQkNCgkJCS8vIEJ1aWxkIDkxNSAtIEZvY3VzIGZpZWxkLCBhbGxvd3MgdXMgdG8gYmluZCBldmVudHMgdG8gdGhpcyB2YWx1ZSBjaGFuZ2luZy4NCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLmZvY3VzKCk7DQoJCQkNCgkJCS8vIEN1c3RvbSBDYWxsYmFjayBDb2RlLg0KCQkJeyRjYWxiYWNrX2NvZGV9DQoJCQ0KICAgICAJfQ0KCTwvc2NyaXB0Pg0KPHNwYW4gaWQ9ImNhbC1kaXYteyRuYW1lfSIgc3R5bGU9InBvc2l0aW9uOiBhYnNvbHV0ZTsgdmlzaWJpbGl0eTogaGlkZGVuOyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsgei1pbmRleDoxMDAxOyI+PC9zcGFuPgkNCg0KDQoJPHNlbGVjdCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1zZWxlY3QtZmllbGQtMSIgbmFtZT0iZGF0ZS17JG5hbWV9LTEiIGlkPSJkYXRlLXskaWR9LTEiIHskdGFiaHRtbH0gc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9Pg0KICAJCTxvcHRpb24+PC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iSmFuIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICdKYW4nKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5KYW51YXJ5PC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iRmViIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICdGZWInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5GZWJydWFyeTwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9Ik1hciIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnTWFyJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+TWFyY2g8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJBcHIiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJ0FwcicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkFwcmlsPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTWF5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICdNYXknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5NYXk8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJKdW4iIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJ0p1bicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkp1bmU8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJKdWwiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJ0p1bCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkp1bHk8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJBdWciIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJ0F1ZycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkF1Z3VzdDwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IlNlcCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnU2VwJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+U2VwdGVtYmVyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iT2N0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICdPY3QnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5PY3RvYmVyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTm92IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICdOb3YnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5Ob3ZlbWJlcjwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IkRlYyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnRGVjJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+RGVjZW1iZXI8L29wdGlvbj4NCgk8L3NlbGVjdD4NCgk8c2VsZWN0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiBjbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLXNlbGVjdC1maWVsZC0yIiBuYW1lPSJkYXRlLXskbmFtZX0tMiIgaWQ9ImRhdGUteyRpZH0tMiIgc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9Pg0KCQk8b3B0aW9uPjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICcxJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+MTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICcyJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Mjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICczJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Mzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc0JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+NDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI1IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc1JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+NTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI2IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc2JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Njwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI3IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc3JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Nzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI4IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc4JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+ODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICc5JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+OTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTQnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTUnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTYnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTcnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxOCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTgnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxOSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMTknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xOTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjQnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjUnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjYnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjcnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyOCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjgnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyOSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMjknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yOTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMzAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4zMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnMzEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4zMTwvb3B0aW9uPg0KCTwvc2VsZWN0Pg0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1zZWxlY3QtZmllbGQtMyIgdHlwZT0idGV4dCIgbmFtZT0iZGF0ZS17JG5hbWV9LTMiIGlkPSJkYXRlLXskaWR9LTMiIHZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMyddKSA/IHByaW50IFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0zJ10gOiBwcmludCAnJzsgPz4iIHNpemU9IjQiIG1heGxlbmd0aD0iNCIgc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgk8YSBpZD0iY2FsLWFuY2hvci17JG5hbWV9IiBjbGFzcz0iY2FsLWFuY2hvci1tdWx0aSIgbmFtZT0iY2FsLWFuY2hvci17JG5hbWV9IiBocmVmPSIjIiBvbmNsaWNrPSJjYWx7JG5hbWV9LnNob3dDYWxlbmRhcignY2FsLWFuY2hvci17JG5hbWV9Jyk7IHJldHVybiBmYWxzZTsiID48aW1nIGNsYXNzPSJjYWwtYW5jaG9yIiBzdHlsZT0ibWFyZ2luLWxlZnQ6NXB4OyBtYXJnaW4tYm90dG9tOi03cHg7IiBhbHQ9IkRhdGUgUGlja2VyIiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5jYWxlbmRhci9jYWwtMC5wbmciIGJvcmRlcj0iMCIgLz48L2E+CQ0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICczJzogDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCS8vIENhbGVuZGFyIEJsb2NrcyBIaW50DQoJLy92YXIgY2FseyRuYW1lfSA9IG5ldyBDYWxlbmRhclBvcHVwKCk7IC8vIHVzZSBwb3B1cCB3aW5kb3cNCgl2YXIgY2FseyRuYW1lfSA9IG5ldyBDYWxlbmRhclBvcHVwKCJjYWwtZGl2LXskbmFtZX0iKTsgeyRhcmdfbGlzdH0NCgljYWx7JG5hbWV9LnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9Iik7DQoJZnVuY3Rpb24gc2V0TXVsdGlwbGVWYWx1ZXNfeyRuYW1lfSh5LG0sZCkgew0KCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTEnKS52YWx1ZT1MWihkKSArICcvJyArIExaKG0pICsgJy8nICsgeTsNCgkJdmFsaWRhdG9yc1snZGF0ZS17JG5hbWV9LTEnXS5jaGVjaygpOw0KCQkNCgkJLy8gQnVpbGQgOTE1IC0gRm9jdXMgZmllbGQsIGFsbG93cyB1cyB0byBiaW5kIGV2ZW50cyB0byB0aGlzIHZhbHVlIGNoYW5naW5nLg0KCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTEnKS5mb2N1cygpOw0KCQkNCgkJLy8gQ3VzdG9tIENhbGxiYWNrIENvZGUuDQoJCXskY2FsYmFja19jb2RlfQ0KCQkNCiAgICB9DQoJPC9zY3JpcHQ+DQo8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+CQ0KDQo8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IGNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gY2FsZW5kYXItZmllbGQtZnVsbCIgdHlwZT0idGV4dCIgbmFtZT0ieyRuYW1lfSIgaWQ9ImRhdGUteyRpZH0tMSIgeyR0YWJodG1sfSB2YWx1ZT0ieyRfdmFsdWV9IiB7JG1heH0gc3R5bGU9InskaW5oZXJpdHN0eWxlfSB7JHNpemVfY3NzfSIgeyRhdHRyaWJ1dGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IC8+DQoJPGEgaWQ9ImNhbC1hbmNob3IteyRuYW1lfSIgY2xhc3M9ImNhbC1hbmNob3ItZnVsbCIgbmFtZT0iY2FsLWFuY2hvci17JG5hbWV9IiBocmVmPSIjIiBvbmNsaWNrPSJjYWx7JG5hbWV9LnNob3dDYWxlbmRhcignY2FsLWFuY2hvci17JG5hbWV9Jyk7IHJldHVybiBmYWxzZTsiID48aW1nIGNsYXNzPSJjYWwtYW5jaG9yIiBzdHlsZT0ibWFyZ2luLWxlZnQ6NXB4OyBtYXJnaW4tYm90dG9tOi03cHg7IiBhbHQ9IkRhdGUgUGlja2VyIiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5jYWxlbmRhci9jYWwtMC5wbmciIGJvcmRlcj0iMCIgLz48L2E+CQ0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc0JzogDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCSAgICAvLyBDYWxlbmRhciBCbG9ja3MgSGludA0KCQl2YXIgY2FseyRuYW1lfSA9IG5ldyBDYWxlbmRhclBvcHVwKCJjYWwtZGl2LXskbmFtZX0iKTsgeyRhcmdfbGlzdH0NCgkJY2FseyRuYW1lfS5zZXRSZXR1cm5GdW5jdGlvbigic2V0TXVsdGlwbGVWYWx1ZXNfeyRuYW1lfSIpOw0KCQlmdW5jdGlvbiBzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9KHksbSxkKSB7DQoJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTEnKS52YWx1ZT1MWihkKTsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMicpLnZhbHVlPUxaKG0pOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0zJykudmFsdWU9eTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0xJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0yJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0zJ10uY2hlY2soKTsNCgkJCQ0KCQkJLy8gQnVpbGQgOTE1IC0gRm9jdXMgZmllbGQsIGFsbG93cyB1cyB0byBiaW5kIGV2ZW50cyB0byB0aGlzIHZhbHVlIGNoYW5naW5nLg0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykuZm9jdXMoKTsNCgkJCQ0KCQkJLy8gQ3VzdG9tIENhbGxiYWNrIENvZGUuDQoJCQl7JGNhbGJhY2tfY29kZX0NCgkJDQogICAgIAl9DQoJPC9zY3JpcHQ+DQoNCgk8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+CQ0KDQoJPD9waHANCglcJGR2ID0geyRkZWZhdWx0dmFsdWV9Ow0KCQ0KCWlmKFwkZHYgPT0gIiIpDQoJCVwkZHYgPSBcJGRhdGV0aW1lOw0KCQ0KCVwkbW9udGggPSAnJzsNCglcJGRheSA9ICcnOw0KCVwkeWVhciA9ICcnOw0KCQ0KCWlmKFwkZHYgIT0gJycpew0KCQkNCgkJLy8gZXVyb3BlYW4NCgkJaWYoaXNfb2JqZWN0KFwkZHYpKSB7DQoJCQlcJGRhdGUgPSBcJGR2Ow0KCQl9IGVsc2Ugew0KCQkJXCRkYXRlID0gbmV3IERhdGVUaW1lKHskZGVmYXVsdHZhbHVlfSk7DQoJCX0NCgkJDQoJCVwkbW9udGggPSBcJGRhdGUtPmZvcm1hdCgnbScpOw0KCQlcJGRheSA9IFwkZGF0ZS0+Zm9ybWF0KCdkJyk7DQoJCVwkeWVhciA9IFwkZGF0ZS0+Zm9ybWF0KCdZJyk7DQoJCQ0KCX0NCgkNCglcJGNhbF9zZWxlY3RfY29kZSA9ICIne1wkZGF5fS97XCRtb250aH0ve1wkeWVhcn0nIjsNCgkNCgk/Pg0KDQoJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiBjbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLW51bWVyaWMtZmllbGQtMSIgdHlwZT0idGV4dCIgbmFtZT0iZGF0ZS17JG5hbWV9LTEiIGlkPSJkYXRlLXskaWR9LTEiIHskdGFiaHRtbH0gdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA6IHByaW50IFwkZGF5OyA/PiIgc2l6ZT0iMiIgbWF4bGVuZ3RoPSIyIiBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1udW1lcmljLWZpZWxkLTIiIHR5cGU9InRleHQiIG5hbWU9ImRhdGUteyRuYW1lfS0yIiBpZD0iZGF0ZS17JGlkfS0yIiB2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgPyBwcmludCBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddIDogcHJpbnQgXCRtb250aDsgPz4iIHNpemU9IjIiIG1heGxlbmd0aD0iMiIgc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgk8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IGNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gY2FsZW5kYXItbnVtZXJpYy1maWVsZC0zIiB0eXBlPSJ0ZXh0IiBuYW1lPSJkYXRlLXskbmFtZX0tMyIgaWQ9ImRhdGUteyRpZH0tMyIgdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0zJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTMnXSA6IHByaW50IFwkeWVhcjsgPz4iIHNpemU9IjQiIG1heGxlbmd0aD0iNCIgc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgk8YSBpZD0iY2FsLWFuY2hvci17JG5hbWV9IiBjbGFzcz0iY2FsLWFuY2hvci1tdWx0aSIgbmFtZT0iY2FsLWFuY2hvci17JG5hbWV9IiBocmVmPSIjIiBvbkNsaWNrPSJjYWx7JG5hbWV9LnNob3dDYWxlbmRhcignY2FsLWFuY2hvci17JG5hbWV9JywgPD9waHAgZWNobyBcJGNhbF9zZWxlY3RfY29kZTsgPz4pOyByZXR1cm4gZmFsc2U7IiA+PGltZyBjbGFzcz0iY2FsLWFuY2hvciIgc3R5bGU9Im1hcmdpbi1sZWZ0OjVweDsgbWFyZ2luLWJvdHRvbTotN3B4OyIgYWx0PSJEYXRlIFBpY2tlciIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvY2FsLTAucG5nIiBib3JkZXI9IjAiIC8+PC9hPgkNCg0KRU9UOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNSc6IA0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCgkgICAgLy8gQ2FsZW5kYXIgQmxvY2tzIEhpbnQNCgkJdmFyIGNhbHskbmFtZX0gPSBuZXcgQ2FsZW5kYXJQb3B1cCgiY2FsLWRpdi17JG5hbWV9Iik7IHskYXJnX2xpc3R9DQoJCWNhbHskbmFtZX0uc2V0UmV0dXJuRnVuY3Rpb24oInNldE11bHRpcGxlVmFsdWVzX3skbmFtZX0iKTsNCgkJZnVuY3Rpb24gc2V0TXVsdGlwbGVWYWx1ZXNfeyRuYW1lfSh5LG0sZCkgew0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykuc2VsZWN0ZWRJbmRleD1kOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0yJykuc2VsZWN0ZWRJbmRleD1tOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0zJykudmFsdWU9eTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0xJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0yJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0zJ10uY2hlY2soKTsNCgkJCQ0KCQkJLy8gQnVpbGQgOTE1IC0gRm9jdXMgZmllbGQsIGFsbG93cyB1cyB0byBiaW5kIGV2ZW50cyB0byB0aGlzIHZhbHVlIGNoYW5naW5nLg0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykuZm9jdXMoKTsNCgkJCQ0KCQkJLy8gQ3VzdG9tIENhbGxiYWNrIENvZGUuDQoJCQl7JGNhbGJhY2tfY29kZX0NCgkJDQogICAgIAl9DQoJPC9zY3JpcHQ+DQo8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+CQ0KDQoJPHNlbGVjdCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1zZWxlY3QtZmllbGQtMSIgbmFtZT0iZGF0ZS17JG5hbWV9LTEiIGlkPSJkYXRlLXskaWR9LTEiIHskdGFiaHRtbH0gc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9Pg0KCQk8b3B0aW9uPjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+MTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Mjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICczJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Mzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc0JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+NDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI1IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc1JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+NTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI2IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc2JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Njwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI3IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc3JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+Nzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI4IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc4JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+ODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSI5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICc5JykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+OTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxMyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xMzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTQnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTUnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTYnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxNyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTcnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xNzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxOCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTgnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIxOSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMTknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xOTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyMyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yMzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjQnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjUnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjYnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNjwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyNyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjcnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yNzwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyOCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjgnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yODwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIyOSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMjknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yOTwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzMCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMzAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4zMDwvb3B0aW9uPg0KCQk8b3B0aW9uIHZhbHVlPSIzMSIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTEnXSA9PSAnMzEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4zMTwvb3B0aW9uPg0KCTwvc2VsZWN0Pg0KCTxzZWxlY3QgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IGNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gY2FsZW5kYXItc2VsZWN0LWZpZWxkLTIiIG5hbWU9ImRhdGUteyRuYW1lfS0yIiBpZD0iZGF0ZS17JGlkfS0yIiBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0+DQogIAkJPG9wdGlvbj48L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJKYW4iIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0phbicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkphbnVhcnk8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJGZWIiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0ZlYicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkZlYnJ1YXJ5PC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTWFyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdNYXInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5NYXJjaDwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IkFwciIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnQXByJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+QXByaWw8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJNYXkiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ01heScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPk1heTwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9Ikp1biIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnSnVuJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+SnVuZTwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9Ikp1bCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnSnVsJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+SnVseTwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IkF1ZyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnQXVnJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+QXVndXN0PC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iU2VwIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdTZXAnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5TZXB0ZW1iZXI8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJPY3QiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ09jdCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPk9jdG9iZXI8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJOb3YiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ05vdicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPk5vdmVtYmVyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iRGVjIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdEZWMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5EZWNlbWJlcjwvb3B0aW9uPg0KCTwvc2VsZWN0Pg0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1zZWxlY3QtZmllbGQtMyIgdHlwZT0idGV4dCIgbmFtZT0iZGF0ZS17JG5hbWV9LTMiIGlkPSJkYXRlLXskaWR9LTMiIHZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMyddKSA/IHByaW50IFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0zJ10gOiBwcmludCAnJzsgPz4iIHNpemU9IjQiIG1heGxlbmd0aD0iNCIgc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgk8YSBpZD0iY2FsLWFuY2hvci17JG5hbWV9IiBjbGFzcz0iY2FsLWFuY2hvci1tdWx0aSIgbmFtZT0iY2FsLWFuY2hvci17JG5hbWV9IiBocmVmPSIjIiBvbkNsaWNrPSJjYWx7JG5hbWV9LnNob3dDYWxlbmRhcignY2FsLWFuY2hvci17JG5hbWV9Jyk7IHJldHVybiBmYWxzZTsiID48aW1nIGNsYXNzPSJjYWwtYW5jaG9yIiBzdHlsZT0ibWFyZ2luLWxlZnQ6NXB4OyBtYXJnaW4tYm90dG9tOi03cHg7IiBhbHQ9IkRhdGUgUGlja2VyIiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5jYWxlbmRhci9jYWwtMC5wbmciIGJvcmRlcj0iMCIgLz48L2E+CQ0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIGNhc2UgJzYnOiANCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCgk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJICAgIC8vIENhbGVuZGFyIEJsb2NrcyBIaW50DQoJCXZhciBjYWx7JG5hbWV9ID0gbmV3IENhbGVuZGFyUG9wdXAoImNhbC1kaXYteyRuYW1lfSIpOyB7JGFyZ19saXN0fQ0KCQljYWx7JG5hbWV9LnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9Iik7DQoJCQ0KCQlmdW5jdGlvbiBzZXRNdWx0aXBsZVZhbHVlc197JG5hbWV9KHksbSxkKSB7DQoJCQkNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLnZhbHVlPUxaKGQpOw0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0yJykudmFsdWU9TFoobSk7DQoJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZGF0ZS17JG5hbWV9LTMnKS52YWx1ZT15Ow0KCQkJDQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMSddLmNoZWNrKCk7DQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMiddLmNoZWNrKCk7DQoJCQl2YWxpZGF0b3JzWydkYXRlLXskbmFtZX0tMyddLmNoZWNrKCk7DQoJCQkNCgkJCS8vIEJ1aWxkIDkxNSAtIEZvY3VzIGZpZWxkLCBhbGxvd3MgdXMgdG8gYmluZCBldmVudHMgdG8gdGhpcyB2YWx1ZSBjaGFuZ2luZy4NCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLmZvY3VzKCk7DQoJCQkNCgkJCS8vIEN1c3RvbSBDYWxsYmFjayBDb2RlLg0KCQkJeyRjYWxiYWNrX2NvZGV9DQogICAgIAl9DQogICAgIAkNCiAgICAgCWNhbHskbmFtZX0uc2V0TW9udGhOYW1lcygnSmFudWFyJywnRmVicnVhcicsJ00mYXVtbDtyeicsJ0FwcmlsJywnTWFpJywnSnVuaScsJ0p1bGknLCdBdWd1c3QnLCdTZXB0ZW1iZXInLCdPa3RvYmVyJywnTm92ZW1iZXInLCdEZXplbWJlcicpOw0KCQljYWx7JG5hbWV9LnNldERheUhlYWRlcnMoJ1MnLCdNJywnRCcsJ00nLCdEJywnRicsJ1MnKTsNCgkJY2FseyRuYW1lfS5zZXRXZWVrU3RhcnREYXkoMSk7DQoJCWNhbHskbmFtZX0uc2V0VG9kYXlUZXh0KCJIZXV0ZSIpOw0KICAgICAJDQoJPC9zY3JpcHQ+DQo8c3BhbiBpZD0iY2FsLWRpdi17JG5hbWV9IiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij48L3NwYW4+DQoNCgk8P3BocA0KCVwkZHYgPSB7JGRlZmF1bHR2YWx1ZX07DQoJDQoJaWYoXCRkdiA9PSAiIikNCgkJXCRkdiA9IFwkZGF0ZXRpbWU7DQoJDQoJXCRtb250aCA9ICcnOw0KCVwkZGF5ID0gJyc7DQoJXCR5ZWFyID0gJyc7DQoJDQoJaWYoXCRkdiAhPSAnJyl7DQoJCQ0KCQkvLyBldXJvcGVhbg0KCQlpZihpc19vYmplY3QoXCRkdikpIHsNCgkJCVwkZGF0ZSA9IFwkZHY7DQoJCX0gZWxzZSB7DQoJCQlcJGRhdGUgPSBuZXcgRGF0ZVRpbWUoeyRkZWZhdWx0dmFsdWV9KTsNCgkJfQ0KCQkNCgkJXCRtb250aCA9IFwkZGF0ZS0+Zm9ybWF0KCdtJyk7DQoJCVwkZGF5ID0gXCRkYXRlLT5mb3JtYXQoJ2QnKTsNCgkJXCR5ZWFyID0gXCRkYXRlLT5mb3JtYXQoJ1knKTsNCgkJDQoJfQ0KCQ0KCVwkY2FsX3NlbGVjdF9jb2RlID0gIid7XCRkYXl9L3tcJG1vbnRofS97XCR5ZWFyfSciOw0KCQ0KCT8+DQoNCgk8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IA0KCQljbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLW51bWVyaWMtZmllbGQtMSIgDQoJCXR5cGU9InRleHQiIA0KCQluYW1lPSJkYXRlLXskbmFtZX0tMSIgDQoJCWlkPSJkYXRlLXskaWR9LTEiIHskdGFiaHRtbH0gDQoJCXZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSA/IHByaW50IFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gOiBwcmludCBcJGRheTsgPz4iIA0KCQlzaXplPSIyIiANCgkJbWF4bGVuZ3RoPSIyIiANCgkJc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgkNCgk8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IA0KCQljbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLW51bWVyaWMtZmllbGQtMiIgDQoJCXR5cGU9InRleHQiIA0KCQluYW1lPSJkYXRlLXskbmFtZX0tMiIgDQoJCWlkPSJkYXRlLXskaWR9LTIiIA0KCQl2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgPyBwcmludCBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddIDogcHJpbnQgXCRtb250aDsgPz4iIA0KCQlzaXplPSIyIiANCgkJbWF4bGVuZ3RoPSIyIiANCgkJc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgkNCgk8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IA0KCQljbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLW51bWVyaWMtZmllbGQtMyIgDQoJCXR5cGU9InRleHQiIA0KCQluYW1lPSJkYXRlLXskbmFtZX0tMyIgDQoJCWlkPSJkYXRlLXskaWR9LTMiIA0KCQl2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTMnXSkgPyBwcmludCBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMyddIDogcHJpbnQgXCR5ZWFyOyA/PiIgDQoJCXNpemU9IjQiIA0KCQltYXhsZW5ndGg9IjQiIA0KCQlzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCQ0KCTxhIGlkPSJjYWwtYW5jaG9yLXskbmFtZX0iIA0KCQljbGFzcz0iY2FsLWFuY2hvci1tdWx0aSIgDQoJCW5hbWU9ImNhbC1hbmNob3IteyRuYW1lfSIgDQoJCWhyZWY9IiMiIG9uQ2xpY2s9ImNhbHskbmFtZX0uc2hvd0NhbGVuZGFyKCdjYWwtYW5jaG9yLXskbmFtZX0nLCA8P3BocCBlY2hvIFwkY2FsX3NlbGVjdF9jb2RlOyA/Pik7IHJldHVybiBmYWxzZTsiID4NCgkJCTxpbWcgDQoJCQkJY2xhc3M9ImNhbC1hbmNob3IiDQoJCQkJc3R5bGU9Im1hcmdpbi1sZWZ0OjVweDsgDQoJCQkJbWFyZ2luLWJvdHRvbTotN3B4OyIgDQoJCQkJYWx0PSJEYXRlIFBpY2tlciIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvY2FsLTAucG5nIiANCgkJCQlib3JkZXI9IjAiIA0KCQkJLz4NCgk8L2E+CQ0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCg0KICAgICAgICAgICAgY2FzZSAnNyc6IA0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCgkgICAgLy8gQ2FsZW5kYXIgQmxvY2tzIEhpbnQNCgkJdmFyIGNhbHskbmFtZX0gPSBuZXcgQ2FsZW5kYXJQb3B1cCgiY2FsLWRpdi17JG5hbWV9Iik7IHskYXJnX2xpc3R9DQoJCWNhbHskbmFtZX0uc2V0UmV0dXJuRnVuY3Rpb24oInNldE11bHRpcGxlVmFsdWVzX3skbmFtZX0iKTsNCgkJZnVuY3Rpb24gc2V0TXVsdGlwbGVWYWx1ZXNfeyRuYW1lfSh5LG0sZCkgew0KCQkNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMScpLnNlbGVjdGVkSW5kZXg9ZDsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMicpLnNlbGVjdGVkSW5kZXg9bTsNCgkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskbmFtZX0tMycpLnZhbHVlPXk7DQoJCQkNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0xJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0yJ10uY2hlY2soKTsNCgkJCXZhbGlkYXRvcnNbJ2RhdGUteyRuYW1lfS0zJ10uY2hlY2soKTsNCgkJCQ0KCQkJLy8gQnVpbGQgOTE1IC0gRm9jdXMgZmllbGQsIGFsbG93cyB1cyB0byBiaW5kIGV2ZW50cyB0byB0aGlzIHZhbHVlIGNoYW5naW5nLg0KCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRuYW1lfS0xJykuZm9jdXMoKTsNCgkJCQ0KCQkJLy8gQ3VzdG9tIENhbGxiYWNrIENvZGUuDQoJCQl7JGNhbGJhY2tfY29kZX0NCiAgICAgCX0NCiAgICAgCQ0KICAgICAJY2FseyRuYW1lfS5zZXRNb250aE5hbWVzKCdKYW51YXInLCdGZWJydWFyJywnTSZhdW1sO3J6JywnQXByaWwnLCdNYWknLCdKdW5pJywnSnVsaScsJ0F1Z3VzdCcsJ1NlcHRlbWJlcicsJ09rdG9iZXInLCdOb3ZlbWJlcicsJ0RlemVtYmVyJyk7DQoJCWNhbHskbmFtZX0uc2V0RGF5SGVhZGVycygnUycsJ00nLCdEJywnTScsJ0QnLCdGJywnUycpOw0KCQljYWx7JG5hbWV9LnNldFdlZWtTdGFydERheSgxKTsNCgkJY2FseyRuYW1lfS5zZXRUb2RheVRleHQoIkhldXRlIik7DQoJCQkNCgk8L3NjcmlwdD4NCjxzcGFuIGlkPSJjYWwtZGl2LXskbmFtZX0iIHN0eWxlPSJwb3NpdGlvbjogYWJzb2x1dGU7IHZpc2liaWxpdHk6IGhpZGRlbjsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IHotaW5kZXg6MTAwMTsiPjwvc3Bhbj4JDQoNCgk8c2VsZWN0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/PiBjbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IGNhbGVuZGFyLXNlbGVjdC1maWVsZC0zIiBuYW1lPSJkYXRlLXskbmFtZX0tMSIgaWQ9ImRhdGUteyRpZH0tMSIgeyR0YWJodG1sfSBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0+DQoJCTxvcHRpb24+PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjEiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzEnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4xPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjIiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4yPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjMiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzMnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID4zPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjQiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzQnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID40PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjUiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzUnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID41PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjYiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzYnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID42PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjciIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzcnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID43PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjgiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzgnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID44PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjkiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0xJ10gPT0gJzknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID45PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjEwIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxMCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjEwPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjExIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxMScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjExPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjEyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxMicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjEyPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjEzIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxMycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjEzPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxNCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE0PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE1IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxNScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE1PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE2IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxNicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE2PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE3IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxNycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE3PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE4IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxOCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE4PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjE5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcxOScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjE5PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjIwIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyMCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjIwPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjIxIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyMScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjIxPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjIyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyMicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjIyPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjIzIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyMycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjIzPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyNCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI0PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI1IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyNScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI1PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI2IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyNicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI2PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI3IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyNycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI3PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI4IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyOCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI4PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjI5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICcyOScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjI5PC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjMwIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICczMCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjMwPC9vcHRpb24+DQoJCTxvcHRpb24gdmFsdWU9IjMxIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMSddID09ICczMScpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPjMxPC9vcHRpb24+DQoJPC9zZWxlY3Q+DQoJDQoJPHNlbGVjdCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4gY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBjYWxlbmRhci1zZWxlY3QtZmllbGQtMiIgbmFtZT0iZGF0ZS17JG5hbWV9LTIiIGlkPSJkYXRlLXskaWR9LTIiIHN0eWxlPSJ7JGluaGVyaXRzdHlsZX0iIHskYXR0cmlidXRlfT4NCiAgCQk8b3B0aW9uPjwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IkphbiIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnSmFuJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+SmFudWFyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iRmViIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdGZWInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5GZWJydWFyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTWFyIiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdNYXInKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5NJmF1bWw7cno8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJBcHIiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0FwcicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkFwcmlsPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTWF5IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdNYXknKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5NYWc8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJKdW4iIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0p1bicpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkp1bmk8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJKdWwiIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0p1bCcpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkp1bGk8L29wdGlvbj4NCiAgCQk8b3B0aW9uIHZhbHVlPSJBdWciIDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10pICYmIFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0yJ10gPT0gJ0F1ZycpIHsgZWNobyAnc2VsZWN0ZWQ9InNlbGVjdGVkIic7IH0gPz4gPkF1Z3VzdDwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IlNlcCIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnU2VwJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+U2VwdGVtYmVyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iT2N0IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdPY3QnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5Pa3RvYmVyPC9vcHRpb24+DQogIAkJPG9wdGlvbiB2YWx1ZT0iTm92IiA8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddKSAmJiBcJF9TRVNTSU9OWydkYXRlLXskbmFtZX0tMiddID09ICdOb3YnKSB7IGVjaG8gJ3NlbGVjdGVkPSJzZWxlY3RlZCInOyB9ID8+ID5Ob3ZlbWJlcjwvb3B0aW9uPg0KICAJCTxvcHRpb24gdmFsdWU9IkRlYyIgPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSkgJiYgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTInXSA9PSAnRGVjJykgeyBlY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsgfSA/PiA+RGV6ZW1iZXI8L29wdGlvbj4NCgk8L3NlbGVjdD4NCgkJDQoJPGlucHV0IHR5cGU9InRleHQiIGNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30iXCJ7JGV4dHJhY2xhc3NuYW1lc30gY2FsZW5kYXItc2VsZWN0LWZpZWxkLTFcIiBuYW1lPSJkYXRlLXskbmFtZX0tMyIgaWQ9ImRhdGUteyRpZH0tMyIgdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ2RhdGUteyRuYW1lfS0zJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsnZGF0ZS17JG5hbWV9LTMnXSA6IHByaW50ICcnOyA/PiIgc2l6ZT0iNCIgbWF4bGVuZ3RoPSI0IiBzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCQ0KCQkNCgk8YSBpZD0iY2FsLWFuY2hvci17JG5hbWV9IiBjbGFzcz0iY2FsLWFuY2hvci1tdWx0aSIgbmFtZT0iY2FsLWFuY2hvci17JG5hbWV9IiBocmVmPSIjIiBvbkNsaWNrPSJjYWx7JG5hbWV9LnNob3dDYWxlbmRhcignY2FsLWFuY2hvci17JG5hbWV9Jyk7IHJldHVybiBmYWxzZTsiID48aW1nIGNsYXNzPSJjYWwtYW5jaG9yIiBzdHlsZT0ibWFyZ2luLWxlZnQ6NXB4OyBtYXJnaW4tYm90dG9tOi03cHg7IiBhbHQ9IkRhdGUgUGlja2VyIiBzcmM9Ijw/cGhwIGVjaG8gXCRfU0VTU0lPTlsnTUFYX1BBVEgnXTsgPz5jYWxlbmRhci9jYWwtMC5wbmciIGJvcmRlcj0iMCIgLz48L2E+CQ0KCQkJCQ0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgaWYgKCRoZWxwZXIgIT0gJycpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8YnIvPjxkaXYgY2xhc3M9XCJoZWxwZXJcIiBzdHlsZT1cImNvbG9yOnskaGVscGVyY29sb3J9O1wiPnskaGVscGVyfTwvZGl2PiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPGJyIC8+IjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICAgICAgDQogICAgfSANCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9kYXRldGltZSgkcGFnZSwgJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+eydsYWJlbCd9Ow0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+eyduYW1lJ307DQogICAgICAgICRpZCA9ICRmaWVsZC0+eydpZCd9Ow0KICAgICAgICAkcmVxID0gJGZpZWxkLT52YWxpZGF0aW9uLT5yZXE7DQogICAgICAgICRmaWVsZHdpZHRoID0gJGZpZWxkLT5maWVsZHdpZHRoOw0KICAgICAgICAkZmllbGRoZWlnaHQgPSAkZmllbGQtPmZpZWxkaGVpZ2h0Ow0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJGZpZWxkLT5kZWZhdWx0dmFsdWU7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRsYWJlbHBvcyA9ICRmaWVsZC0+bGFiZWxwb3M7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCiAgICAgICAgJGhlbHBlciA9ICRmaWVsZC0+aGVscGVyOw0KICAgICAgICAkaGVscGVyY29sb3IgPSAkZmllbGQtPmhlbHBlcmNvbG9yOw0KCQkkbWF4bGVuZ3RoID0gJGZpZWxkLT52YWxpZGF0aW9uLT5tYXg7DQoJCSRyZWFkb25seSA9IGlzc2V0KCRmaWVsZC0+cmVhZG9ubHkpID8gJGZpZWxkLT5yZWFkb25seSA6IDA7DQogICAgICAgICRmaWVsZGVuYWJsZWQgPSBpc3NldCgkZmllbGQtPmZpZWxkZW5hYmxlZCkgPyAkZmllbGQtPmZpZWxkZW5hYmxlZCA6IDE7DQogICAgICAgICRhdHRyaWJ1dGUgPSAkZmllbGQtPmF0dHJpYnV0ZTsNCiAgICAgICAgJGF0dHJpYnV0ZXN0eWxlID0gJGZpZWxkLT5hdHRyaWJ1dGVzdHlsZTsNCiAgICAgICAgJGNvbmRpdGlvbmFsID0gJGZpZWxkLT5jb25kaXRpb25hbDsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCiAgICAgICAgJHRvb2x0aXAgPSAkZmllbGQtPnRvb2x0aXA7DQoNCiAgICAgICAgJHR5cGUgPSAkZmllbGQtPmNhbGVuZGFydHlwZTsNCiAgICAgICAgJGNhbGVuZGFyYXJndW1lbnRzID0gJGZpZWxkLT5jYWxlbmRhcmFyZ3VtZW50czsNCg0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KICAgICAgICANCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICAkZGVmYXVsdHZhbHVlID0gJHRoaXMtPmNyZWF0ZV9kZWZhdWx0X3ZhbHVlX3Rva2VucygkZGVmYXVsdHZhbHVlKTsNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGwgPSAkdGhpcy0+X2NyZWF0ZUNvbmRpdGlvbmFsRXZlbnQoJGNvbmRpdGlvbmFsLCAkbmFtZSwgJGlkKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJGNvbmRpdGlvbmFsX2NhbGxbMF07DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICRjb25kaXRpb25hbF9jYWxsWzFdOw0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJGZpZWxkaGVpZ2h0KSkgew0KICAgICAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBpZiAoKHN0cmluZykkZmllbGRoZWlnaHQgPT0gIiIpIHsNCiAgICAgICAgICAgICAgICAkZmllbGRoZWlnaHQgPSAiIjsgDQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRmaWVsZGhlaWdodCA9ICJoZWlnaHQ6eyRmaWVsZGhlaWdodH1weDsiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN0MSA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgIGlmICgkY3QxID09IDAgJiYgJGN0MiA9PSAwKSB7DQogICAgICAgICAgICAkZm9udHNpemUgPSAkZm9udHNpemUgLiAncHgnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICR0ZXN0ID0gKGludCkkaW5oZXJpdHN0eWxlOw0KICAgICAgICBpZiAoJHRlc3QgIT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9IDA7DQogICAgICAgIH0NCiAgICAgICAgaWYgKCRpbmhlcml0c3R5bGUgPT0gMSkgew0KICAgICAgICAgICAgJGluaGVyaXRzdHlsZSA9ICIgZm9udC1zaXplOnskZm9udHNpemV9OyBjb2xvcjp7JGlucHV0X2NvbG9yfTsgeyRmaWVsZGhlaWdodH0gZm9udC1mYW1pbHk6aW5oZXJpdDsgeyRhdHRyaWJ1dGVzdHlsZX0gIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIGNvbG9yOnskaW5wdXRfY29sb3J9OyB7JGF0dHJpYnV0ZXN0eWxlfSB7JGZpZWxkaGVpZ2h0fSAiOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRjdDEgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZmllbGR3aWR0aCwgJ3B0Jyk7DQogICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZmllbGR3aWR0aCwgJ3B4Jyk7DQoNCiAgICAgICAgJHNpemVfY3NzID0gIiI7DQogICAgICAgIA0KICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgJHNpemVfY3NzID0gIiB3aWR0aDp7JGZpZWxkd2lkdGh9cHg7ICI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkc2l6ZV9jc3MgPSAiIHdpZHRoOnskZmllbGR3aWR0aH07ICI7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkYnVja2V0X25vZGUpICYmICRidWNrZXRfbm9kZSAhPSAiIiAmJiAoaW50KSRidWNrZXRfbm9kZS0+cmVwZWF0ZXItPnJlc3BvbnNpdmUgPT0gMSkgew0KICAgICAgICAgICAgJHNpemVfY3NzID0gIiB3aWR0aDo2MCU7ICI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGNhbF9hcmdzID0gZXhwbG9kZSgnfCcsICRjYWxlbmRhcmFyZ3VtZW50cyk7DQogICAgICAgICRhcmdfbGlzdCA9ICcnOw0KICAgICAgICBpZiAoJGNhbF9hcmdzWzBdICE9PSAnJykgew0KICAgICAgICAgICAgZm9yZWFjaCAoJGNhbF9hcmdzIGFzICRhcmdzKSB7DQogICAgICAgICAgICAgICAgJGFyZ19saXN0IC49ICJjYWx7JG5hbWV9LiIgLiAkYXJncyAuICc7JzsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5sZWZ0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JGZpeGVkX3dpZHRofXB4OyBtYXJnaW4tcmlnaHQ6OHB4OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn1cIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkbWF4bGVuZ3RoICE9ICcnKSB7DQogICAgICAgICAgICAkbWF4ID0gICJtYXhsZW5ndGg9XCJ7JG1heGxlbmd0aH1cIiI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkbWF4ID0gJyc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJHJlcXVpcmVkX3RleHQgPSBpc3NldCgkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIpID8gJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyIDogIiYjNDI7IjsNCg0KICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+X2hlbHBlcl9maWVsZF9sYWJlbCgkZmllbGQsICRuYW1lLCAkcmVxLCAkcmVxdWlyZWRfdGV4dCwgJGNvbG9yLCAkZm9udHNpemUsICRzdHlsZXMsICRsYWJlbCwgJGxhYmVscG9zLCAoc3RyaW5nKSRmaWVsZC0+dHlwZSwgJycsICcnLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICAkZWxlbWVudCAuPSAiXG57JGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0fVxuIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtZWxlbWVudFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPnJpZ2h0Y29sdW1ud2lkdGh9OyBmbG9hdDpsZWZ0OyB0ZXh0LWFsaWduOnskYWxpZ259OyBtYXJnaW4tYm90dG9tOnskYm90dG9tX21hcmdpbl92YWx1ZX1weDsgXCIgPiI7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkZXh0cmFjbGFzc25hbWVzID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZXh0cmFjbGFzc25hbWUpICYmICRmaWVsZC0+ZXh0cmFjbGFzc25hbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgPSAkZmllbGQtPmV4dHJhY2xhc3NuYW1lOw0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRmaWVsZC0+YnVja2V0KSAmJiAkZmllbGQtPmJ1Y2tldCAhPSAiIil7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRleHRyYWNsYXNzbmFtZXMgLj0gIiBidWNrZXQtY29udGFpbmVkLWZpZWxkIjsNCiAgICAgICAgICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5jcmVhdGVfdGFibGVfbW9kZV9tb2JpbGVfbGFiZWwoJGZpZWxkLCR0YWJsZW1vZGUpOw0KDQogICAgICAgIA0KICAgICAgICAkcmVhZG9ubHkgPSBpc3NldCgkcmVhZG9ubHkpID8gJHJlYWRvbmx5ID09IDEgPyAiIHJlYWRvbmx5ICIgOiAiIiA6ICIiOw0KICAgICAgICAkZW5hYmxlZCA9IGlzc2V0KCRmaWVsZGVuYWJsZWQpID8gJGZpZWxkZW5hYmxlZCA9PSAwID8gIiBkaXNhYmxlZCAiIDogIiIgOiAiIjsNCg0KCQkNCgkJDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJF9vcHRpb25zRGF0ZSA9IG5ldyBzdGRDbGFzcygpOw0KDQogICAgICAgICRfY3VzdG9tX29wdGlvbnMgPSBpc3NldCgkZmllbGQtPm5vZGUtPmN1c3RvbV9vcHRpb25zKSA/IChzdHJpbmcpJGZpZWxkLT5ub2RlLT5jdXN0b21fb3B0aW9ucyA6ICcnOw0KDQogICAgICAgIGlmKCRfY3VzdG9tX29wdGlvbnMgIT0gJycpew0KICAgICAgICAgICAgaWYoc3Vic3RyKCRfY3VzdG9tX29wdGlvbnMsIC0xKSAhPSAnLCcpew0KICAgICAgICAgICAgICAgICRfY3VzdG9tX29wdGlvbnMgPSAkX2N1c3RvbV9vcHRpb25zIC4gIiwiIC4gUEhQX0VPTDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHN3aXRjaCAoKHN0cmluZykkZmllbGQtPm5vZGUtPnR5cGUpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGNhc2UgJzAnOiANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJG1hc3Rlcl9mb3JtYXQgPSAibS9kL1kgZzppIGEiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bm9kZS0+X2RhdGUtPmZvcm1hdCkgJiYgaXNzZXQoJGZpZWxkLT5ub2RlLT5fdGltZS0+Zm9ybWF0KSkgew0KDQogICAgICAgICAgICAgICAgICAgICRtYXN0ZXJfZm9ybWF0ID0gKHN0cmluZykkZmllbGQtPm5vZGUtPl9kYXRlLT5mb3JtYXQgLiAiICIgLiAoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X3RpbWUtPmZvcm1hdDsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fdGltZS0+Zm9ybWF0ID0gc3RyX3JlcGxhY2UoJzpzJywgJycsIChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fdGltZS0+Zm9ybWF0KTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRkZWZhdWx0dmFsdWUgPSBzdHJfcmVwbGFjZSgnbS9kL1knLCAkbWFzdGVyX2Zvcm1hdCwgJGRlZmF1bHR2YWx1ZSk7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICR0aW1lX2Zvcm1hdCA9ICJnOmkgYSI7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5ub2RlLT5fdGltZS0+Zm9ybWF0KSkgew0KICAgICAgICAgICAgICAgICAgICAkdGltZV9mb3JtYXQgPSAkZmllbGQtPm5vZGUtPl90aW1lLT5mb3JtYXQ7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkZGF0ZV9mb3JtYXQgPSAibS9kL1kiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bm9kZS0+X2RhdGUtPmZvcm1hdCkpIHsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gJGZpZWxkLT5ub2RlLT5fZGF0ZS0+Zm9ybWF0Ow0KICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgJHRoZW1lID0gInRoZW1lOiAnZGVmYXVsdCciOw0KDQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fZGF0ZXRpbWUtPnRoZW1lID09ICJEYXJrIikgew0KICAgICAgICAgICAgICAgICAgICAkdGhlbWUgPSAidGhlbWU6ICdkYXJrJyI7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkbWluX3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X3RpbWUtPm1pbl90aW1lICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRtaW5fdGltZSA9ICJtaW5UaW1lOiAneyRmaWVsZC0+bm9kZS0+X3RpbWUtPm1pbl90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkbWF4X3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X3RpbWUtPm1heF90aW1lICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRtYXhfdGltZSA9ICJtYXhUaW1lOiAneyRmaWVsZC0+bm9kZS0+X3RpbWUtPm1heF90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRtaW5fZGF0ZSA9ICIiOw0KICAgICAgICAgICAgICAgICRtaW5fZGF0ZV9waHAgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X2RhdGUtPm1pbl9kYXRlICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKERhdGVUaW1lOjpjcmVhdGVGcm9tRm9ybWF0KCRmaWVsZC0+bm9kZS0+X2RhdGUtPmZvcm1hdCwgJGZpZWxkLT5ub2RlLT5fZGF0ZS0+bWluX2RhdGUpKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAkbWluX2RhdGUgPSAibWluRGF0ZTogJ3skZmllbGQtPm5vZGUtPl9kYXRlLT5taW5fZGF0ZX0nLCI7DQoNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRvcCA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X2RhdGUtPm1pbl9kYXRlLCAiLSIpICE9IDAgPyAic3ViIiA6ICJhZGQiOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAkcmF3X2RheXMgPSBzdHJfcmVwbGFjZSgiLSIsICIiLCAkZmllbGQtPm5vZGUtPl9kYXRlLT5taW5fZGF0ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAkcmF3X2RheXMgPSBzdHJfcmVwbGFjZSgiKyIsICIiLCAkcmF3X2RheXMpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAkbWluX2RhdGVfcGhwID0gPDw8RU9GDQoNCjw/cGhwDQoNCi8vIENhbGN1bGF0ZSBNaW4gRGF0ZS4NClwkZGF0ZSA9IGRhdGVfY3JlYXRlKGRhdGUoREFURV9SRkMyODIyKSk7IC8vIEN1cnJlbnQgVGltZS4NCmRhdGVfeyRvcH0oXCRkYXRlLCBkYXRlX2ludGVydmFsX2NyZWF0ZV9mcm9tX2RhdGVfc3RyaW5nKCd7JHJhd19kYXlzfSBkYXlzJykpOw0KXCRtaW5fZGF0ZV9waHAgPSBkYXRlX2Zvcm1hdChcJGRhdGUsICd7JGZpZWxkLT5ub2RlLT5fZGF0ZS0+Zm9ybWF0fScpOwkJCQkJCQkJDQoJCQkJCQkJCQ0KPz4NCgkJCQkJCQ0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAkbWluX2RhdGUgPSAibWluRGF0ZTogJzw/cGhwIGVjaG8gXCRtaW5fZGF0ZV9waHA7ID8+JywiOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJG1heF9kYXRlID0gIiI7DQogICAgICAgICAgICAgICAgJG1heF9kYXRlX3BocCA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fZGF0ZS0+bWF4X2RhdGUgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICBpZiAoRGF0ZVRpbWU6OmNyZWF0ZUZyb21Gb3JtYXQoJGZpZWxkLT5ub2RlLT5fZGF0ZS0+Zm9ybWF0LCAkZmllbGQtPm5vZGUtPl9kYXRlLT5tYXhfZGF0ZSkpIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRtYXhfZGF0ZSA9ICJtaW5EYXRlOiAneyRmaWVsZC0+bm9kZS0+X2RhdGUtPm1heF9kYXRlfScsIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgJG9wID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fZGF0ZS0+bWF4X2RhdGUsICItIikgIT0gMCA/ICJzdWIiIDogImFkZCI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRyYXdfZGF5cyA9IHN0cl9yZXBsYWNlKCItIiwgIiIsICRmaWVsZC0+bm9kZS0+X2RhdGUtPm1heF9kYXRlKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICRyYXdfZGF5cyA9IHN0cl9yZXBsYWNlKCIrIiwgIiIsICRyYXdfZGF5cyk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRtYXhfZGF0ZV9waHAgPSA8PDxFT0YNCg0KPD9waHANCg0KLy8gQ2FsY3VsYXRlIE1pbiBEYXRlLg0KXCRkYXRlID0gZGF0ZV9jcmVhdGUoZGF0ZShEQVRFX1JGQzI4MjIpKTsgLy8gQ3VycmVudCBUaW1lLg0KZGF0ZV97JG9wfShcJGRhdGUsIGRhdGVfaW50ZXJ2YWxfY3JlYXRlX2Zyb21fZGF0ZV9zdHJpbmcoJ3skcmF3X2RheXN9IGRheXMnKSk7DQpcJG1heF9kYXRlX3BocCA9IGRhdGVfZm9ybWF0KFwkZGF0ZSwgJ3skZmllbGQtPm5vZGUtPl9kYXRlLT5mb3JtYXR9Jyk7CQkJCQkJCQkNCgkJCQkJCQkJDQo/Pg0KCQkJCQkJDQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRtYXhfZGF0ZSA9ICJtYXhEYXRlOiAnPD9waHAgZWNobyBcJG1heF9kYXRlX3BocDsgPz4nLCI7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkdGltZV9zdGVwID0gIjMwIjsNCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPm5vZGUtPl90aW1lLT5taW51dGVfaW5jcmVtZW50KSkgew0KICAgICAgICAgICAgICAgICAgICAkdGltZV9zdGVwID0gJGZpZWxkLT5ub2RlLT5fdGltZS0+bWludXRlX2luY3JlbWVudDsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkcnVsZXNfdGFyZ2V0X2pzID0gIiI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBmb3JlYWNoKCRwYWdlLT5mb3JtLT5maWVsZCBhcyAkZil7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZighaXNzZXQoJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQpKXsNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkYSA9ICRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkOw0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZGF5c0JlZm9yZSA9ICIwIjsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmKChzdHJpbmcpJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQtPnRhcmdldF9iZWZvcmVfZGVsdGFfdmFsdWUgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZGF5c0JlZm9yZSA9IChzdHJpbmcpJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQtPnRhcmdldF9iZWZvcmVfZGVsdGFfdmFsdWU7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmKChzdHJpbmcpJGYtPnR5cGUgPT0gImRhdGV0aW1lIiAmJiAoc3RyaW5nKSRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkLT50YXJnZXRfYmVmb3JlID09ICRuYW1lKXsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUJlZm9yZSA9IGpRdWVyeSgnIyIgLiAoc3RyaW5nKSRhLT50YXJnZXRfYmVmb3JlIC4gIicpLmRhdGV0aW1lcGlja2VyKCdnZXRWYWx1ZScpO1xyXG4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkcnVsZXNfdGFyZ2V0X2pzIC49ICJ2YXIgX2Jhc2VEYXRlQmVmb3JlRGVsdGEgPSBtb21lbnQoX2Jhc2VEYXRlQmVmb3JlLCAneyRtYXN0ZXJfZm9ybWF0fScpLnN1YnRyYWN0KHskZGF5c0JlZm9yZX0sICdkYXlzJykuX2Q7XHJcbiI7IA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkcnVsZXNfdGFyZ2V0X2pzIC49ICJqUXVlcnkoJyMiIC4gKHN0cmluZykkZi0+bmFtZSAuICInKS5kYXRldGltZXBpY2tlcignc2V0T3B0aW9ucycsIHttYXhEYXRlOiBfYmFzZURhdGVCZWZvcmVEZWx0YX0pO1xyXG4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZGF5c0FmdGVyPSAiMCI7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZigoc3RyaW5nKSRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkLT50YXJnZXRfYWZ0ZXJfZGVsdGFfdmFsdWUgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZGF5c0FmdGVyID0gKHN0cmluZykkZi0+bm9kZS0+X2RhdGUtPnJ1bGVzLT5hZHZhbmNlZC0+dGFyZ2V0X2FmdGVyX2RlbHRhX3ZhbHVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIH07DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZigoc3RyaW5nKSRmLT50eXBlID09ICJkYXRldGltZSIgJiYgKHN0cmluZykkZi0+bm9kZS0+X2RhdGUtPnJ1bGVzLT5hZHZhbmNlZC0+dGFyZ2V0X2FmdGVyID09ICRuYW1lKXsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUFmdGVyID0galF1ZXJ5KCcjIiAuIChzdHJpbmcpJGEtPnRhcmdldF9hZnRlciAuICInKS5kYXRldGltZXBpY2tlcignZ2V0VmFsdWUnKTtcclxuIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUFmdGVyRGVsdGEgPSBtb21lbnQoX2Jhc2VEYXRlQWZ0ZXIsICd7JG1hc3Rlcl9mb3JtYXR9JykuYWRkKHskZGF5c0FmdGVyfSwgJ2RheXMnKS5fZDtcclxuIjsgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRydWxlc190YXJnZXRfanMgLj0gImpRdWVyeSgnIyIgLiAoc3RyaW5nKSRmLT5uYW1lIC4gIicpLmRhdGV0aW1lcGlja2VyKCdzZXRPcHRpb25zJywge21pbkRhdGU6IF9iYXNlRGF0ZUFmdGVyRGVsdGF9KTtcclxuIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRzaG93X3RpbWUgPSBpc3NldCgkZmllbGQtPm5vZGUtPl90aW1lLT5zaG93X3RpbWUpID8gJGZpZWxkLT5ub2RlLT5fdGltZS0+c2hvd190aW1lIDogJ3RydWUnOw0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmKCRzaG93X3RpbWUgIT0gJ3RydWUnKXsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRtYXN0ZXJfZm9ybWF0ID0gJGRhdGVfZm9ybWF0Ow0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJCQkJDQo8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+IA0KCQljbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IiANCgkJdHlwZT0idGV4dCIgDQoJCW5hbWU9InskbmFtZX0iIA0KCQlpZD0ieyRpZH0iIA0KCQl2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRuYW1lfSddKSA/IHByaW50IGh0bWxlbnRpdGllcyhcJF9TRVNTSU9OWyd7JG5hbWV9J10sIEVOVF9DT01QQVQsICdVVEYtOCcpIDogcHJpbnQgeyRkZWZhdWx0dmFsdWV9OyA/PiIgDQoJCXN0eWxlPSJ7JGluaGVyaXRzdHlsZX0geyRzaXplX2Nzc30iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJCQkJDQoJCQ0KeyRtaW5fZGF0ZV9waHB9DQp7JG1heF9kYXRlX3BocH0NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KDQovLyBodHRwczovL3hkc29mdC5uZXQvanFwbHVnaW5zL2RhdGV0aW1lcGlja2VyLw0KDQpqUXVlcnkoJyN7JGlkfScpLmRhdGV0aW1lcGlja2VyKHsNCg0KICAgIC8vIEN1c3RvbSBVc2VyIE9wdGlvbnMuDQogICAgeyRfY3VzdG9tX29wdGlvbnN9DQoNCiAgICB2YWxpZGF0ZU9uQmx1cjogdHJ1ZSwNCiAgICANCiAgICBjbG9zZU9uRGF0ZVNlbGVjdDogMSwNCg0KCWRhdGVwaWNrZXI6IHRydWUsDQoJdGltZXBpY2tlcjogJHtzaG93X3RpbWV9LA0KCQ0KCXskbWluX3RpbWV9DQoJeyRtYXhfdGltZX0NCgkNCgl7JG1pbl9kYXRlfQ0KCXskbWF4X2RhdGV9DQoJDQoJeyR0aGVtZX0sDQoJCQ0KCWZvcm1hdDogJ3skbWFzdGVyX2Zvcm1hdH0nLA0KCWZvcm1hdFRpbWU6ICd7JHRpbWVfZm9ybWF0fScsDQogICAgZm9ybWF0RGF0ZTogJ3skZGF0ZV9mb3JtYXR9JywNCiAgICANCglzdGVwOiB7JHRpbWVfc3RlcH0sDQoJCQ0KCW9uQ2hhbmdlRGF0ZVRpbWU6ZnVuY3Rpb24oZHAsXCRpbnB1dCl7DQoJCS8vIFwkaW5wdXQudmFsKCkNCiAgICB9LA0KICAgIA0KICAgIG9uQ2xvc2U6IGZ1bmN0aW9uKGRhdGVUZXh0KXsNCiAgICAgICAgDQogICAgICAgIGlmIChkYXRlVGV4dCAhPSAiIikgew0KDQogICAgICAgICAgICAvLyBTdGFydCAvIEVuZCBEYXRlIENvbnN0cmFpbnQgTG9naWMuDQogICAgICAgICAgICANCiAgICAgICAgICAgIHskcnVsZXNfdGFyZ2V0X2pzfSANCg0KICAgICAgICB9DQogICAgfQ0KfSk7DQogICAgCQkNCjwvc2NyaXB0Pg0KDQpFT1Q7DQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGNhc2UgJzEnOiANCg0KICAgICAgICAgICAgICAgICRsYW5ndWFnZSA9ICJlbiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5ub2RlLT5fZGF0ZS0+bGFuZ3VhZ2UpKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGxhbmd1YWdlID0gJGZpZWxkLT5ub2RlLT5fZGF0ZS0+bGFuZ3VhZ2U7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gIm1tL2RkL3l5eXkiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bm9kZS0+X2RhdGUtPmZvcm1hdCkpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZGF0ZV9mb3JtYXQgPSAkZmllbGQtPm5vZGUtPl9kYXRlLT5mb3JtYXQ7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHR2YWx1ZSA9IHN0cl9yZXBsYWNlKCdtL2QvWScsICRkYXRlX2Zvcm1hdCwgJGRlZmF1bHR2YWx1ZSk7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRkYXRlX2Zvcm1hdCA9IHN0cl9yZXBsYWNlKCJkIiwgImRkIiwgJGRhdGVfZm9ybWF0KTsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gc3RyX3JlcGxhY2UoImoiLCAiZCIsICRkYXRlX2Zvcm1hdCk7DQogICAgICAgICAgICAgICAgICAgICRkYXRlX2Zvcm1hdCA9IHN0cl9yZXBsYWNlKCJsIiwgIkREIiwgJGRhdGVfZm9ybWF0KTsNCg0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZGF0ZV9mb3JtYXQgPSBzdHJfcmVwbGFjZSgiRiIsICJNTSIsICRkYXRlX2Zvcm1hdCk7DQogICAgICAgICAgICAgICAgICAgICRkYXRlX2Zvcm1hdCA9IHN0cl9yZXBsYWNlKCJtIiwgIm1tIiwgJGRhdGVfZm9ybWF0KTsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gc3RyX3JlcGxhY2UoIm4iLCAibSIsICRkYXRlX2Zvcm1hdCk7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRkYXRlX2Zvcm1hdCA9IHN0cl9yZXBsYWNlKCJ5IiwgInl5IiwgJGRhdGVfZm9ybWF0KTsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gc3RyX3JlcGxhY2UoIlkiLCAieXl5eSIsICRkYXRlX2Zvcm1hdCk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJGRlZmF1bHRfdmlld19kYXRlID0gIiI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGRhdGVfbm9kZSA9ICRmaWVsZC0+bm9kZS0+X2RhdGU7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHN0YXJ0X2RhdGUgPSBpc3NldCgkZGF0ZV9ub2RlLT5taW5fZGF0ZSkgJiYgJGRhdGVfbm9kZS0+bWluX2RhdGUgIT0gIiIgPyAic3RhcnREYXRlOiAneyRkYXRlX25vZGUtPm1pbl9kYXRlfScsIiA6ICcnOw0KICAgICAgICAgICAgICAgICRlbmRfZGF0ZSA9IGlzc2V0KCRkYXRlX25vZGUtPm1heF9kYXRlKSAmJiAkZGF0ZV9ub2RlLT5tYXhfZGF0ZSAhPSAiIiA/ICJlbmREYXRlOiAneyRkYXRlX25vZGUtPm1heF9kYXRlfScsIiA6ICcnOw0KICAgICAgICANCiAgICAgICAgICAgICAgICAkcnVsZXNfdGFyZ2V0X2pzID0gIiI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBmb3JlYWNoKCRwYWdlLT5mb3JtLT5maWVsZCBhcyAkZil7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZighaXNzZXQoJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQpKXsNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkYSA9ICRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkOw0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZGF5c0JlZm9yZSA9ICIwIjsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmKChzdHJpbmcpJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQtPnRhcmdldF9iZWZvcmVfZGVsdGFfdmFsdWUgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZGF5c0JlZm9yZSA9IChzdHJpbmcpJGYtPm5vZGUtPl9kYXRlLT5ydWxlcy0+YWR2YW5jZWQtPnRhcmdldF9iZWZvcmVfZGVsdGFfdmFsdWU7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmKChzdHJpbmcpJGYtPnR5cGUgPT0gImRhdGV0aW1lIiAmJiAoc3RyaW5nKSRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkLT50YXJnZXRfYmVmb3JlID09ICRuYW1lKXsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUJlZm9yZSA9IGpRdWVyeSgnIyIgLiAoc3RyaW5nKSRhLT50YXJnZXRfYmVmb3JlIC4gIicpLmRhdGVwaWNrZXIoJ2dldERhdGUnKTtcclxuIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUJlZm9yZURlbHRhID0gbW9tZW50KF9iYXNlRGF0ZUJlZm9yZSwgJ3skZGF0ZV9mb3JtYXR9Jykuc3VidHJhY3QoeyRkYXlzQmVmb3JlfSwgJ2RheXMnKS5fZDtcclxuIjsgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRydWxlc190YXJnZXRfanMgLj0gImpRdWVyeSgnIyIgLiAoc3RyaW5nKSRmLT5uYW1lIC4gIicpLmRhdGVwaWNrZXIoJ3NldEVuZERhdGUnLCBfYmFzZURhdGVCZWZvcmVEZWx0YSk7XHJcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkZGF5c0FmdGVyPSAiMCI7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZigoc3RyaW5nKSRmLT5ub2RlLT5fZGF0ZS0+cnVsZXMtPmFkdmFuY2VkLT50YXJnZXRfYWZ0ZXJfZGVsdGFfdmFsdWUgIT0gIiIpew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAkZGF5c0FmdGVyID0gKHN0cmluZykkZi0+bm9kZS0+X2RhdGUtPnJ1bGVzLT5hZHZhbmNlZC0+dGFyZ2V0X2FmdGVyX2RlbHRhX3ZhbHVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIH07DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZigoc3RyaW5nKSRmLT50eXBlID09ICJkYXRldGltZSIgJiYgKHN0cmluZykkZi0+bm9kZS0+X2RhdGUtPnJ1bGVzLT5hZHZhbmNlZC0+dGFyZ2V0X2FmdGVyID09ICRuYW1lKXsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAidmFyIF9iYXNlRGF0ZUFmdGVyID0galF1ZXJ5KCcjIiAuIChzdHJpbmcpJGEtPnRhcmdldF9hZnRlciAuICInKS5kYXRlcGlja2VyKCdnZXREYXRlJyk7XHJcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRydWxlc190YXJnZXRfanMgLj0gInZhciBfYmFzZURhdGVBZnRlckRlbHRhID0gbW9tZW50KF9iYXNlRGF0ZUFmdGVyLCAneyRkYXRlX2Zvcm1hdH0nKS5hZGQoeyRkYXlzQWZ0ZXJ9LCAnZGF5cycpLl9kO1xyXG4iOyANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgJHJ1bGVzX3RhcmdldF9qcyAuPSAialF1ZXJ5KCcjIiAuIChzdHJpbmcpJGYtPm5hbWUgLiAiJykuZGF0ZXBpY2tlcignc2V0U3RhcnREYXRlJywgX2Jhc2VEYXRlQWZ0ZXJEZWx0YSk7XHJcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCgkJDQo8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+DQoJCWNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30iDQoJCXR5cGU9InRleHQiDQoJCW5hbWU9InskbmFtZX0iDQoJCWlkPSJ7JGlkfSINCgkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgPyBwcmludCBodG1sZW50aXRpZXMoXCRfU0VTU0lPTlsneyRuYW1lfSddLCBFTlRfQ09NUEFULCAnVVRGLTgnKSA6IHByaW50IHskZGVmYXVsdHZhbHVlfTsgPz4iDQoJCXN0eWxlPSJ7JGluaGVyaXRzdHlsZX0geyRzaXplX2Nzc30iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJDQpqUXVlcnkoZnVuY3Rpb24oKSB7DQoNCiAgICBqUXVlcnkoIiN7JGlkfSIpLmRhdGVwaWNrZXIoew0KICAgIA0KICAgICAgICAvLyBDdXN0b20gVXNlciBPcHRpb25zLg0KICAgICAgICB7JF9jdXN0b21fb3B0aW9uc30NCg0KICAgIAlsYW5ndWFnZTogJ3skbGFuZ3VhZ2V9JywNCiAgICAJJ2Zvcm1hdCc6ICd7JGRhdGVfZm9ybWF0fScsDQogICAgCSdhdXRvY2xvc2UnOiB0cnVlLA0KICAgICAgICB7JGRlZmF1bHRfdmlld19kYXRlfQ0KICAgICAgICB7JHN0YXJ0X2RhdGV9DQogICAgICAgIHskZW5kX2RhdGV9DQogICAgICAgIHRvZGF5QnRuOiB0cnVlLA0KICAgICAgICB0b2RheUhpZ2hsaWdodDogdHJ1ZSwgICAgDQogICAgICB9KQ0KICAgICAgICAvLyBodHRwczovL2Jvb3RzdHJhcC1kYXRlcGlja2VyLnJlYWR0aGVkb2NzLmlvL2VuL2xhdGVzdC9ldmVudHMuaHRtbCMNCiAgICAgICAgDQogICAgICAgIC5vbignaGlkZScsIGZ1bmN0aW9uKGUpIHsgLy8gYGVgIGhlcmUgY29udGFpbnMgdGhlIGV4dHJhIGF0dHJpYnV0ZXMNCiAgICAgICAgICAgIHskcnVsZXNfdGFyZ2V0X2pzfSAvLyBTdGFydCAvIEVuZCBEYXRlIENvbnN0cmFpbnQgTG9naWMuDQogICAgICAgIH0pDQogICAgICAgIA0KICAgICAgICAub24oJ3Nob3cnLCBmdW5jdGlvbihlKSB7IC8vIGBlYCBoZXJlIGNvbnRhaW5zIHRoZSBleHRyYSBhdHRyaWJ1dGVzDQogICAgICAgICAgICANCiAgICAgICAgfSk7DQogIH0pOw0KDQogIGZ1bmN0aW9uIHNldERlZmF1bHREYXRlX3skaWR9KCl7DQoNCiAgICBpZihkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIjeyRpZH0iKS52YWx1ZSA9PSAiQ1VSUkVOVF9EQVRFIil7DQogICAgICAgIHZhciB0b2RheSA9IG5ldyBEYXRlKCk7DQogICAgICAgIHZhciBmcm10ID0gdG9kYXkuZm9ybWF0KCd7JGRhdGVfZm9ybWF0fScpOw0KICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIjeyRpZH0iKS52YWx1ZSA9IGZybXQ7DQogICAgfQ0KICB9DQoNCiAgc2V0RGVmYXVsdERhdGVfeyRpZH0oKTsNCgkNCjwvc2NyaXB0Pg0KCQ0KRU9UOw0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGNhc2UgJzInOiANCg0KICAgICAgICAgICAgICAgICR0aW1lX2Zvcm1hdCA9ICJnOmkgYSI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkbWluX3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X3RpbWUtPm1pbl90aW1lICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRtaW5fdGltZSA9ICJtaW5UaW1lOiAneyRmaWVsZC0+bm9kZS0+X3RpbWUtPm1pbl90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkbWF4X3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X3RpbWUtPm1heF90aW1lICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRtYXhfdGltZSA9ICJtYXhUaW1lOiAneyRmaWVsZC0+bm9kZS0+X3RpbWUtPm1heF90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5ub2RlLT5fdGltZS0+Zm9ybWF0KSkgew0KICAgICAgICAgICAgICAgICAgICAkdGltZV9mb3JtYXQgPSAkZmllbGQtPm5vZGUtPl90aW1lLT5mb3JtYXQ7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkZGVmYXVsdHZhbHVlID0gc3RyX3JlcGxhY2UoJ20vZC9ZJywgJHRpbWVfZm9ybWF0LCAkZGVmYXVsdHZhbHVlKTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICR0aW1lc3RlcF92YWx1ZSA9ICRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT50aW1lX3N0ZXA7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5ub2RlLT5fdGltZS0+bWludXRlX2luY3JlbWVudCAhPSAiQ3VzdG9tIikgew0KICAgICAgICAgICAgICAgICAgICAkdGltZXN0ZXBfdmFsdWUgPSAkZmllbGQtPm5vZGUtPl90aW1lLT5taW51dGVfaW5jcmVtZW50Ow0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICR0aW1lc3RlcCA9IDw8PEVPRg0KJ3N0ZXAnOiBmdW5jdGlvbihpKSB7DQoJCQlyZXR1cm4geyR0aW1lc3RlcF92YWx1ZX07DQoJCX0NCkVPRjsNCg0KICAgICAgICAgICAgICAgICRzY3JvbGxfZGVmYXVsdCA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+bm9kZS0+X3RpbWUtPnVzZV9jdXJyZW50X3RpbWVfYXNfZGVmYXVsdCkgJiYgJGZpZWxkLT5ub2RlLT5fdGltZS0+dXNlX2N1cnJlbnRfdGltZV9hc19kZWZhdWx0ID09ICIxIikgew0KICAgICAgICAgICAgICAgICAgICAkc2Nyb2xsX2RlZmF1bHQgPSAiJ3Njcm9sbERlZmF1bHQnOiAnbm93JywiOw0KICAgICAgICAgICAgICAgIH0NCg0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJCQkJDQo8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+DQoJCWNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30iDQoJCXR5cGU9InRleHQiDQoJCW5hbWU9InskbmFtZX0iDQoJCWlkPSJ7JGlkfSINCgkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX0nXSkgPyBwcmludCBodG1sZW50aXRpZXMoXCRfU0VTU0lPTlsneyRuYW1lfSddLCBFTlRfQ09NUEFULCAnVVRGLTgnKSA6IHByaW50IHskZGVmYXVsdHZhbHVlfTsgPz4iDQoJCXN0eWxlPSJ7JGluaGVyaXRzdHlsZX0geyRzaXplX2Nzc30iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJCQkJDQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoNCi8vJChmdW5jdGlvbigpIHsNCi8vICAgICQoJyN7JGlkfScpLnRpbWVwaWNrZXIoeyAnc3RlcCc6IDE1LCAndGltZUZvcm1hdCc6ICd7JHRpbWVfZm9ybWF0fScgfSk7DQovL30pOw0KDQovLyBodHRwczovL3d3dy5qb250aG9ybnRvbi5jb20vanF1ZXJ5LXRpbWVwaWNrZXIvDQovLyBodHRwczovL2dpdGh1Yi5jb20vam9udGhvcm50b24vanF1ZXJ5LXRpbWVwaWNrZXIjdGltZXBpY2tlci1wbHVnaW4tZm9yLWpxdWVyeQ0KDQpqUXVlcnkoZnVuY3Rpb24oKSB7DQoJalF1ZXJ5KCcjeyRpZH0nKS50aW1lcGlja2VyKHsNCiAgICAgICAgLy8gQ3VzdG9tIFVzZXIgT3B0aW9ucy4NCiAgICAgICAgeyRfY3VzdG9tX29wdGlvbnN9DQogICAgICAgICdzaG93RHVyYXRpb24nOiB0cnVlLA0KICAgICAgICAndGltZUZvcm1hdCc6ICd7JHRpbWVfZm9ybWF0fScsDQogICAgICAgIHskc2Nyb2xsX2RlZmF1bHR9DQogICAgICAgIHskdGltZXN0ZXB9DQogICAgICAgIHskbWluX3RpbWV9DQogICAgICAgIHskbWF4X3RpbWV9DQogICAgfSk7DQp9KTsNCiAgIAkJDQo8L3NjcmlwdD4NCg0KRU9UOw0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCg0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgY2FzZSAnMyc6IA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkdGltZXN0ZXBfdmFsdWUgPSAkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+dGltZV9zdGVwOw0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT50aW1lX3N0ZXAgPT0gIkN1c3RvbSIpIHsNCiAgICAgICAgICAgICAgICAgICAgJHRpbWVzdGVwX3ZhbHVlID0gJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPnRpbWVfc3RlcF9jdXN0b207DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJHRpbWVzdGVwID0gPDw8RU9GDQonc3RlcCc6IGZ1bmN0aW9uKGkpIHsNCgkJCXJldHVybiB7JHRpbWVzdGVwX3ZhbHVlfTsNCgkJfQkJDQpFT0Y7DQoNCg0KICAgICAgICAgICAgICAgICRkYXRlX2Zvcm1hdCA9ICRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5kYXRlX2Zvcm1hdDsNCg0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+ZGF0ZV9mb3JtYXQgPT0gIkN1c3RvbSIpIHsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGVfZm9ybWF0ID0gJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPmRhdGVfZm9ybWF0X2N1c3RvbTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkdGltZV9mb3JtYXQgPSAkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+dGltZV9mb3JtYXQ7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPnRpbWVfZm9ybWF0ID09ICJDdXN0b20iKSB7DQogICAgICAgICAgICAgICAgICAgICR0aW1lX2Zvcm1hdCA9ICRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT50aW1lX2Zvcm1hdF9jdXN0b207DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGRlZmF1bHRfdmlld19kYXRlID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPmRlZmF1bHRfZGF0ZSAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkdiA9IGV4cGxvZGUoIi8iLCAoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5kZWZhdWx0X2RhdGUpOw0KDQogICAgICAgICAgICAgICAgICAgICRkYXRlX29iamVjdCA9ICJ7eWVhcjp7JHZbMl19LCBtb250aDp7JHZbMV19LCBkYXk6eyR2WzBdfX0iOw0KDQogICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZpZXdfZGF0ZSA9ICInZGVmYXVsdFZpZXdEYXRlJzogeyRkYXRlX29iamVjdH0sIjsNCiAgICAgICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRzY3JvbGxfZGVmYXVsdCA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5kZWZhdWx0X3RpbWUgPT0gIm5vdyIpIHsNCiAgICAgICAgICAgICAgICAgICAgJHNjcm9sbF9kZWZhdWx0ID0gIidzY3JvbGxEZWZhdWx0JzogJ25vdycsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPmRlZmF1bHRfdGltZSAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAkdGltZXN0ZXAgPSAiIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkc3RhcnRfZGF0ZSA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5taW5fZGF0ZSAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAkc3RhcnRfZGF0ZSA9ICInc3RhcnREYXRlJzogJ3skZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+bWluX2RhdGV9JywiOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRlbmRfZGF0ZSA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5tYXhfZGF0ZSAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAkZW5kX2RhdGUgPSAiJ2VuZERhdGUnOiAneyRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5tYXhfZGF0ZX0nLCI7DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkbWluX3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+bWluX3RpbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAgICAgJG1pbl90aW1lID0gIm1pblRpbWU6ICd7JGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPm1pbl90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkbWF4X3RpbWUgPSAiIjsNCg0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+bWluX3RpbWUgIT0gIiIpIHsNCiAgICAgICAgICAgICAgICAgICAgJG1heF90aW1lID0gIm1heFRpbWU6ICd7JGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPm1heF90aW1lfScsIjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZGVmYXVsdF9kYXRlX2RlbHRhID0gMTsNCg0KICAgICAgICAgICAgICAgIGlmICgkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+ZGVmYXVsdF9kYXRlX2RlbHRhICE9ICIiKSB7DQogICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X2RhdGVfZGVsdGEgPSAkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+ZGVmYXVsdF9kYXRlX2RlbHRhOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRkZWZhdWx0X3RpbWVfZGVsdGEgPSA3MjAwMDAwOw0KDQogICAgICAgICAgICAgICAgaWYgKCRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5kZWZhdWx0X3RpbWVfZGVsdGEgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3RpbWVfZGVsdGEgPSAkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+ZGVmYXVsdF90aW1lX2RlbHRhICogNjAwMDA7DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGZpZWxkX3NpemUgPSAxMDsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoKHN0cmluZykkZmllbGQtPm5vZGUtPl9kYXRlcGFpci0+bW9kZSA9PSAiRGF0ZStUaW1lIikgew0KDQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KCQkJCQ0KPGRpdiBpZD0ieyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyIj4NCg0KCTxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InskbmFtZX0iIHZhbHVlPSIwMS8wMS8yMDAxIiAvPg0KCQkJCQ0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4NCgkJCWNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gZGF0ZSBzdGFydCINCgkJCXNpemU9InskZmllbGRfc2l6ZX0iDQoJCQl0eXBlPSJ0ZXh0Ig0KCQkJbmFtZT0ieyRuYW1lfV9kYXRlX3N0YXJ0Ig0KCQkJaWQ9InskaWR9X2RhdGVfc3RhcnQiDQoJCQl2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRuYW1lfV9kYXRlX3N0YXJ0J10pID8gcHJpbnQgaHRtbGVudGl0aWVzKFwkX1NFU1NJT05bJ3skbmFtZX1fZGF0ZV9zdGFydCddLCBFTlRfQ09NUEFULCAnVVRGLTgnKSA6IHByaW50IHskZGVmYXVsdHZhbHVlfTsgPz4iDQoJCQlzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCQkNCgk8aW5wdXQgPD9waHAgZWNobyBcJGVuYWJsZWQ7ID8+DQoJCQljbGFzcz0ieyRleHRyYWNsYXNzbmFtZXN9IHRpbWUgc3RhcnQiDQoJCQlzaXplPSJ7JGZpZWxkX3NpemV9Ig0KCQkJdHlwZT0idGV4dCINCgkJCW5hbWU9InskbmFtZX1fdGltZV9zdGFydCINCgkJCWlkPSJ7JGlkfV90aW1lX3N0YXJ0Ig0KCQkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX1fdGltZV9zdGFydCddKSA/IHByaW50IGh0bWxlbnRpdGllcyhcJF9TRVNTSU9OWyd7JG5hbWV9X3RpbWVfc3RhcnQnXSwgRU5UX0NPTVBBVCwgJ1VURi04JykgOiBwcmludCAnJzsgPz4iDQoJCQlzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCQkNCgk8c3Bhbj50bzwvc3Bhbj4NCgkJCQ0KCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4NCgkJCWNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gdGltZSBlbmQiDQoJCQlzaXplPSJ7JGZpZWxkX3NpemV9Ig0KCQkJdHlwZT0idGV4dCINCgkJCW5hbWU9InskbmFtZX1fdGltZV9lbmQiDQoJCQlpZD0ieyRpZH1fdGltZV9lbmQiDQoJCQl2YWx1ZT0iPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRuYW1lfV90aW1lX2VuZCddKSA/IHByaW50IGh0bWxlbnRpdGllcyhcJF9TRVNTSU9OWyd7JG5hbWV9X3RpbWVfZW5kJ10sIEVOVF9DT01QQVQsICdVVEYtOCcpIDogcHJpbnQgJyc7ID8+Ig0KCQkJc3R5bGU9InskaW5oZXJpdHN0eWxlfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgkJDQoJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/Pg0KCQkJY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBkYXRlIGVuZCINCgkJCXNpemU9InskZmllbGRfc2l6ZX0iDQoJCQl0eXBlPSJ0ZXh0Ig0KCQkJbmFtZT0ieyRuYW1lfV9kYXRlX2VuZCINCgkJCWlkPSJ7JGlkfV9kYXRlX2VuZCINCgkJCXZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JG5hbWV9X2RhdGVfZW5kJ10pID8gcHJpbnQgaHRtbGVudGl0aWVzKFwkX1NFU1NJT05bJ3skbmFtZX1fZGF0ZV9lbmQnXSwgRU5UX0NPTVBBVCwgJ1VURi04JykgOiBwcmludCAnJzsgPz4iDQoJCQlzdHlsZT0ieyRpbmhlcml0c3R5bGV9IiB7JGF0dHJpYnV0ZX0geyRlbmFibGVkfSB7JHJlYWRvbmx5fSAvPg0KCQkJDQo8L2Rpdj4NCgkJCQkNCjxzY3JpcHQ+DQogICAgLy8gaW5pdGlhbGl6ZSBpbnB1dCB3aWRnZXRzIGZpcnN0DQogICAgalF1ZXJ5KCcjeyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyIC50aW1lJykudGltZXBpY2tlcih7DQogICAgICAgIC8vIEN1c3RvbSBVc2VyIE9wdGlvbnMuDQogICAgICAgIHskX2N1c3RvbV9vcHRpb25zfQ0KICAgICAgICAnc2hvd0R1cmF0aW9uJzogdHJ1ZSwNCiAgICAgICAgJ3RpbWVGb3JtYXQnOiAneyR0aW1lX2Zvcm1hdH0nLA0KICAgICAgICB7JHNjcm9sbF9kZWZhdWx0fQ0KICAgICAgICB7JHRpbWVzdGVwfQ0KICAgICAgICB7JG1pbl90aW1lfQ0KICAgICAgICB7JG1heF90aW1lfQ0KICAgIH0pOw0KCQkJCQ0KICAgIGpRdWVyeSgnI3skbmFtZX1fZGF0ZXBhaXJfd3JhcHBlciAuZGF0ZScpLmRhdGVwaWNrZXIoew0KICAgICAgICAvLyBDdXN0b20gVXNlciBPcHRpb25zLg0KICAgICAgICB7JF9jdXN0b21fb3B0aW9uc30NCiAgICAgICAgJ2Zvcm1hdCc6ICd7JGRhdGVfZm9ybWF0fScsDQogICAgICAgICdhdXRvY2xvc2UnOiB0cnVlLA0KICAgICAgICB7JGRlZmF1bHRfdmlld19kYXRlfQ0KICAgICAgICB7JHN0YXJ0X2RhdGV9DQogICAgICAgIHskZW5kX2RhdGV9DQogICAgfSkub24oImhpZGUiLCBmdW5jdGlvbihlKSB7DQogICAgICAgIA0KICAgICAgICAvLyBgZWAgaGVyZSBjb250YWlucyB0aGUgZXh0cmEgYXR0cmlidXRlcw0KICAgICAgIA0KICAgICAgICAvLyBGb2N1cy9CbHVyIFRhcmdldCBFbGVtZW50IFRvIEZvcmNlIFZhbGlkYXRpb24uDQogICAgICAgIGUuZGVsZWdhdGVUYXJnZXQuZm9jdXMoKTsNCiAgICAgICAgZS5kZWxlZ2F0ZVRhcmdldC5ibHVyKCk7DQogICAgICAgIA0KICAgIH0pOw0KCQkJCQ0KICAgIC8vIEluaXRpYWxpemUgRGF0ZSBQYWlyDQogICAgdmFyIHskbmFtZX1fZGF0ZXBhaXJfd3JhcHBlckVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skbmFtZX1fZGF0ZXBhaXJfd3JhcHBlcicpOw0KICAgIHZhciBkYXRlcGFpcl97JG5hbWV9ID0gbmV3IERhdGVwYWlyKHskbmFtZX1fZGF0ZXBhaXJfd3JhcHBlckVsLCAgew0KCQknZGVmYXVsdERhdGVEZWx0YSc6IHskZGVmYXVsdF9kYXRlX2RlbHRhfSwgICAgICAvLyBkYXlzDQogICAgCSdkZWZhdWx0VGltZURlbHRhJzogeyRkZWZhdWx0X3RpbWVfZGVsdGF9IC8vIG1pbGxpc2Vjb25kcw0KCX0pOw0KPC9zY3JpcHQ+DQoJCQ0KRU9UOw0KICAgICAgICAgICAgICAgIH0gDQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJGZpZWxkLT5ub2RlLT5fZGF0ZXBhaXItPm1vZGUgPT0gIkRhdGUgT25seSIpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCgkJCQ0KPGRpdiBpZD0ieyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyIj4NCgkJCQ0KCTxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InskbmFtZX0iIHZhbHVlPSIwMS8wMS8yMDAxIiAvPg0KDQoJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/Pg0KCQkJY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBkYXRlIHN0YXJ0Ig0KCQkJdHlwZT0idGV4dCINCgkJCW5hbWU9InskbmFtZX1fZGF0ZV9zdGFydCINCgkJCWlkPSJ7JGlkfV9kYXRlX3N0YXJ0Ig0KCQkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX1fZGF0ZV9zdGFydCddKSA/IHByaW50IGh0bWxlbnRpdGllcyhcJF9TRVNTSU9OWyd7JG5hbWV9X2RhdGVfc3RhcnQnXSwgRU5UX0NPTVBBVCwgJ1VURi04JykgOiBwcmludCB7JGRlZmF1bHR2YWx1ZX07ID8+Ig0KCQkJc3R5bGU9InskaW5oZXJpdHN0eWxlfSB7JHNpemVfY3NzfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCg0KCTxzcGFuPnRvPC9zcGFuPg0KCQkJDQoJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/Pg0KCQkJY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSBkYXRlIGVuZCINCgkJCXR5cGU9InRleHQiDQoJCQluYW1lPSJ7JG5hbWV9X2RhdGVfZW5kIg0KCQkJaWQ9InskaWR9X2RhdGVfZW5kIg0KCQkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX1fZGF0ZV9lbmQnXSkgPyBwcmludCBodG1sZW50aXRpZXMoXCRfU0VTU0lPTlsneyRuYW1lfV9kYXRlX2VuZCddLCBFTlRfQ09NUEFULCAnVVRGLTgnKSA6IHByaW50ICcnOyA/PiINCgkJCXN0eWxlPSJ7JGluaGVyaXRzdHlsZX0geyRzaXplX2Nzc30iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJCQ0KPC9kaXY+DQoJCQkNCjxzY3JpcHQ+DQogICAgalF1ZXJ5KCcjeyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyIC5kYXRlJykuZGF0ZXBpY2tlcih7DQogICAgICAgIC8vIEN1c3RvbSBVc2VyIE9wdGlvbnMuDQogICAgICAgIHskX2N1c3RvbV9vcHRpb25zfQ0KICAgICAgICAnZm9ybWF0JzogJ3skZGF0ZV9mb3JtYXR9JywNCiAgICAgICAgJ2F1dG9jbG9zZSc6IHRydWUsDQogICAgICAgIHskZGVmYXVsdF92aWV3X2RhdGV9DQogICAgICAgIHskc3RhcnRfZGF0ZX0NCiAgICAgICAgeyRlbmRfZGF0ZX0NCiAgICB9KS5vbigiaGlkZSIsIGZ1bmN0aW9uKGUpIHsNCiAgICAgICAgDQogICAgICAgIC8vIGBlYCBoZXJlIGNvbnRhaW5zIHRoZSBleHRyYSBhdHRyaWJ1dGVzDQogICAgICAgDQogICAgICAgIC8vIEZvY3VzL0JsdXIgVGFyZ2V0IEVsZW1lbnQgVG8gRm9yY2UgVmFsaWRhdGlvbi4NCiAgICAgICAgZS5kZWxlZ2F0ZVRhcmdldC5mb2N1cygpOw0KICAgICAgICBlLmRlbGVnYXRlVGFyZ2V0LmJsdXIoKTsNCiAgICAgICAgDQogICAgfSkub24oInNob3ciLCBmdW5jdGlvbihlKXsNCiAgICAJDQogICAgfSk7DQogICAgCQkNCiAgICAvLyBJbml0aWFsaXplIERhdGUgUGFpcg0KICAgIHZhciB7JG5hbWV9X2RhdGVwYWlyX3dyYXBwZXJFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JG5hbWV9X2RhdGVwYWlyX3dyYXBwZXInKTsNCiAgICB2YXIgZGF0ZXBhaXJfeyRuYW1lfSA9IG5ldyBEYXRlcGFpcih7JG5hbWV9X2RhdGVwYWlyX3dyYXBwZXJFbCwgIHsNCgkJJ2RlZmF1bHREYXRlRGVsdGEnOiB7JGRlZmF1bHRfZGF0ZV9kZWx0YX0sICAgICAgLy8gZGF5cw0KICAgIAknZGVmYXVsdFRpbWVEZWx0YSc6IHskZGVmYXVsdF90aW1lX2RlbHRhfSAvLyBtaWxsaXNlY29uZHMNCgl9KTsNCiAgICAJCQkNCjwvc2NyaXB0Pg0KCQkJDQpFT1Q7DQogICAgICAgICAgICAgICAgfSANCg0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICgoc3RyaW5nKSRmaWVsZC0+bm9kZS0+X2RhdGVwYWlyLT5tb2RlID09ICJUaW1lIE9ubHkiKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJCQkJCQkNCjxkaXYgaWQ9InskbmFtZX1fZGF0ZXBhaXJfd3JhcHBlciI+DQoJCQkJDQoJCTxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InskbmFtZX0iIHZhbHVlPSIwMS8wMS8yMDAxIiAvPg0KCQkJDQoJCTxpbnB1dCA8P3BocCBlY2hvIFwkZW5hYmxlZDsgPz4NCgkJCWNsYXNzPSJ7JGV4dHJhY2xhc3NuYW1lc30gdGltZSBzdGFydCINCgkJCXR5cGU9InRleHQiDQoJCQluYW1lPSJ7JG5hbWV9X3RpbWVfc3RhcnQiDQoJCQlpZD0ieyRpZH1fdGltZV9zdGFydCINCgkJCXZhbHVlPSI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JG5hbWV9X3RpbWVfc3RhcnQnXSkgPyBwcmludCBodG1sZW50aXRpZXMoXCRfU0VTU0lPTlsneyRuYW1lfV90aW1lX3N0YXJ0J10sIEVOVF9DT01QQVQsICdVVEYtOCcpIDogcHJpbnQgJyc7ID8+Ig0KCQkJc3R5bGU9InskaW5oZXJpdHN0eWxlfSB7JHNpemVfY3NzfSIgeyRhdHRyaWJ1dGV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCgkJCQ0KCQk8c3Bhbj50bzwvc3Bhbj4NCgkJCQkNCgkJPGlucHV0IDw/cGhwIGVjaG8gXCRlbmFibGVkOyA/Pg0KCQkJY2xhc3M9InskZXh0cmFjbGFzc25hbWVzfSB0aW1lIGVuZCINCgkJCXR5cGU9InRleHQiDQoJCQluYW1lPSJ7JG5hbWV9X3RpbWVfZW5kIg0KCQkJaWQ9InskaWR9X3RpbWVfZW5kIg0KCQkJdmFsdWU9Ijw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skbmFtZX1fdGltZV9lbmQnXSkgPyBwcmludCBodG1sZW50aXRpZXMoXCRfU0VTU0lPTlsneyRuYW1lfV90aW1lX2VuZCddLCBFTlRfQ09NUEFULCAnVVRGLTgnKSA6IHByaW50ICcnOyA/PiINCgkJCXN0eWxlPSJ7JGluaGVyaXRzdHlsZX0geyRzaXplX2Nzc30iIHskYXR0cmlidXRlfSB7JGVuYWJsZWR9IHskcmVhZG9ubHl9IC8+DQoJCQkNCjwvZGl2Pg0KCQkJCQ0KPHNjcmlwdD4NCgkNCgkvLyBpbml0aWFsaXplIGlucHV0IHdpZGdldHMgZmlyc3QNCiAgICBqUXVlcnkoJyN7JG5hbWV9X2RhdGVwYWlyX3dyYXBwZXIgLnRpbWUnKS50aW1lcGlja2VyKHsNCiAgICAgICAgLy8gQ3VzdG9tIFVzZXIgT3B0aW9ucy4NCiAgICAgICAgeyRfY3VzdG9tX29wdGlvbnN9DQogICAgICAgICdzaG93RHVyYXRpb24nOiB0cnVlLA0KICAgICAgICAndGltZUZvcm1hdCc6ICd7JHRpbWVfZm9ybWF0fScsDQogICAgICAgIHskc2Nyb2xsX2RlZmF1bHR9DQogICAgICAgIHskdGltZXN0ZXB9DQogICAgICAgIHskbWluX3RpbWV9DQogICAgICAgIHskbWF4X3RpbWV9DQogICAgfSk7DQoJDQoJLy8gSW5pdGlhbGl6ZSBEYXRlIFBhaXINCgl2YXIgeyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyJyk7DQoJdmFyIGRhdGVwYWlyX3skbmFtZX0gPSBuZXcgRGF0ZXBhaXIoeyRuYW1lfV9kYXRlcGFpcl93cmFwcGVyRWwsICB7DQoJCSdkZWZhdWx0RGF0ZURlbHRhJzogeyRkZWZhdWx0X2RhdGVfZGVsdGF9LCAvLyBkYXlzDQoJCSdkZWZhdWx0VGltZURlbHRhJzogeyRkZWZhdWx0X3RpbWVfZGVsdGF9ICAvLyBtaWxsaXNlY29uZHMNCgl9KTsNCgkJCSANCjwvc2NyaXB0Pg0KCQkJCQ0KRU9UOw0KICAgICAgICAgICAgICAgIH0gDQoNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCg0KDQogICAgICAgIGlmICgkaGVscGVyICE9ICcnKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPGJyLz48ZGl2IGNsYXNzPVwiaGVscGVyXCIgc3R5bGU9XCJjb2xvcjp7JGhlbHBlcmNvbG9yfTtcIj57JGhlbHBlcn08L2Rpdj4iOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjxiciAvPiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmJ0b29sdGlwLXskaWR9IGZidG9vbHRpcFwiIHN0eWxlPVwiZGlzcGxheTpub25lO1wiPjwvZGl2PlxuIjsNCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgICAgIA0KICAgIH0gDQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZGF0YWdyaWQoJGZpZWxkLCAkcGFnZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KDQogICAgICAgICRuYW1lID0gJGZpZWxkLT5uYW1lOw0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+bGFiZWw7DQoNCiAgICAgICAgDQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRpbnB1dF9jb2xvciA9ICRmaWVsZC0+aW5wdXRfY29sb3I7DQogICAgICAgICRmb250c2l6ZSA9ICRmaWVsZC0+Zm9udHNpemU7DQogICAgICAgICRpbmhlcml0c3R5bGUgPSAkZmllbGQtPmluaGVyaXRzdHlsZTsNCg0KICAgICAgICANCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCiAgICAgICAgJHN0eWxlcyA9ICR0aGlzLT50cmFuc2xhdGVGaWVsZFN0eWxlcygkc3R5bGUpOw0KDQogICAgICAgIA0KICAgICAgICAkdGFiaW5kZXggPSAkZmllbGQtPnRhYmluZGV4Ow0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQoNCiAgICAgICAgDQogICAgICAgICRncmlkID0gJGZpZWxkLT5ncmlkX3Byb3BlcnRpZXM7DQoNCg0KDQogICAgICAgIA0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRmb250c2l6ZSA9ICRmb250c2l6ZSAuICdweCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGZpZWxkd2lkdGggPSAiIjsNCiAgICAgICAgJGZpZWxkaGVpZ2h0ID0gIiI7DQogICAgICAgICRhdHRyaWJ1dGVzdHlsZSA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICAkdGVzdCA9IChpbnQpJGluaGVyaXRzdHlsZTsNCiAgICAgICAgaWYgKCR0ZXN0ICE9IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAwOw0KICAgICAgICB9DQogICAgICAgIGlmICgkaW5oZXJpdHN0eWxlID09IDEpIHsNCiAgICAgICAgICAgICRpbmhlcml0c3R5bGUgPSAiIHN0eWxlPVwiZm9udC1zaXplOnskZm9udHNpemV9OyBjb2xvcjp7JGlucHV0X2NvbG9yfTsgZm9udC1mYW1pbHk6aW5oZXJpdDsgd2lkdGg6eyRncmlkLT5maWVsZF93aWR0aH1weDsgaGVpZ2h0OnskZmllbGRoZWlnaHR9cHg7IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkaW5oZXJpdHN0eWxlID0gIiBzdHlsZT1cIiBjb2xvcjp7JGlucHV0X2NvbG9yfTsgd2lkdGg6eyRncmlkLT5maWVsZF93aWR0aH1weDsgaGVpZ2h0OnskZmllbGRoZWlnaHR9cHg7IHskYXR0cmlidXRlc3R5bGV9IFwiICI7DQogICAgICAgIH0NCg0KDQogICAgICAgICR0YWJsZW1vZGUgPSAkcGFnZS0+dGFibGVtb2RlOw0KICAgICAgICANCg0KDQogICAgICAgIA0KICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICBpZiAoIWlzc2V0KCRzdHlsZS0+dGFibGVtb2Rlc3BhbikpIHsNCiAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gZmFsc2U7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBpZiAoKGludCkkc3R5bGUtPnRhYmxlbW9kZXNwYW4gPT0gMCkgew0KICAgICAgICAgICAgICAgICR0YWJsZW1vZGVzcGFuID0gdHJ1ZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5sZWZ0Y29sdW1uYWxpZ24gPT0gMCkgew0KICAgICAgICAgICAgJGFsaWduID0gJ2xlZnQnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGFsaWduID0gJ3JpZ2h0JzsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1sYWJlbCBkZXNrdG9wLWNlbGxcIiBzdHlsZT1cIndpZHRoOnskZml4ZWRfd2lkdGh9cHg7IG1hcmdpbi1yaWdodDo4cHg7IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufVwiID4iOw0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgICRyZXF1aXJlZF90ZXh0ID0gaXNzZXQoJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyKSA/ICRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlciA6ICImIzQyOyI7DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJHRoaXMtPl9oZWxwZXJfZmllbGRfbGFiZWwoJGZpZWxkLCAkbmFtZSwgMCwgJHJlcXVpcmVkX3RleHQsICRjb2xvciwgJGZvbnRzaXplLCAkc3R5bGVzLCAkbGFiZWwsIDAsIChzdHJpbmcpJGZpZWxkLT50eXBlLCAnJywgJycsICR0YWJsZW1vZGUpOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5yaWdodGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkYm90dG9tX21hcmdpbl92YWx1ZSA9IGludHZhbCgkdGFibGVtb2RlLT5tYXJnaW5ib3R0b20pOw0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7IFwiID4iOw0KICAgICAgICB9DQoNCg0KDQogICAgICAgIA0KICAgICAgICAkZXZlbnRfY29kZSA9ICcnOw0KDQogICAgICAgIGlmIChpc3NldCgkZ3JpZC0+anNfZXZlbnRfY29kZSkgJiYgJGdyaWQtPmpzX2V2ZW50X2NvZGUgIT0gJycpIHsNCiAgICAgICAgICAgICRldmVudF9jb2RlID0gJGdyaWQtPmpzX2V2ZW50X2NvZGU7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgICRmaWVsZF90eXBlcyA9IGFycmF5KA0KICAgICAgICAgICAgMCA9PiAiPGlucHV0IHR5cGU9XCJ0ZXh0XCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gdmFsdWU9XCJfX0RFRkFVTFRfVkFMVUVfX1wiIC8+IiwNCiAgICAgICAgICAgIDEgPT4gIjxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBuYW1lPVwieyRmaWVsZC0+bmFtZX1fX0lOREVYX1wiIGlkPVwieyRmaWVsZC0+aWR9X19JTkRFWF9cIiBfVEFCLUlOREVYXyB7JGluaGVyaXRzdHlsZX0geyRldmVudF9jb2RlfSB2YWx1ZT1cIl9fREVGQVVMVF9WQUxVRV9fXCIgLz4iLA0KICAgICAgICAgICAgMiA9PiAiPHRleHRhcmVhIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfXCIgaWQ9XCJ7JGZpZWxkLT5pZH1fX0lOREVYX1wiIF9UQUItSU5ERVhfIHskaW5oZXJpdHN0eWxlfSB7JGV2ZW50X2NvZGV9Pl9fREVGQVVMVF9WQUxVRV9fPC90ZXh0YXJlYT4iLA0KICAgICAgICAgICAgMyA9PiAiPGlucHV0IHR5cGU9XCJkYXRlXCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gdmFsdWU9XCJfX0RFRkFVTFRfVkFMVUVfX1wiIC8+IiwNCiAgICAgICAgICAgIDQgPT4gIjxpbnB1dCB0eXBlPVwiZGF0ZVwiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfXCIgaWQ9XCJ7JGZpZWxkLT5pZH1fX0lOREVYX1wiIF9UQUItSU5ERVhfIHskaW5oZXJpdHN0eWxlfSB7JGV2ZW50X2NvZGV9IHZhbHVlPVwiX19ERUZBVUxUX1ZBTFVFX19cIiAvPiIsDQogICAgICAgICAgICA1ID0+ICI8c2VsZWN0IGNsYXNzPVwiZm9ybS1jb250cm9sXCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0+X19ERUZBVUxUX1ZBTFVFX188L3NlbGVjdD4iLA0KICAgICAgICAgICAgNiA9PiAiPGlucHV0IHR5cGU9XCJyYWRpb1wiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfXCIgaWQ9XCJ7JGZpZWxkLT5pZH1fX0lOREVYX2BgU1VCSU5ERVhgYFwiIF9UQUItSU5ERVhfIHskaW5oZXJpdHN0eWxlfSB7JGV2ZW50X2NvZGV9IHZhbHVlPVwiX19ERUZBVUxUX1ZBTFVFX19cIiBfQ0hFQ0tFRF8gLz48bGFiZWwgc3R5bGU9XCJcIiBmb3I9XCJ7JGZpZWxkLT5pZH1fX0lOREVYX2BgU1VCSU5ERVhgYFwiPl9fREVGQVVMVF9WQUxVRV9fPC9sYWJlbD4iLA0KICAgICAgICAgICAgNyA9PiAiPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIHZhbHVlPVwiX0NIRUNLQk9YX1ZBTFVFX1wiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfW11cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfYGBTVUJJTkRFWGBgXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gX0NIRUNLRURfIC8+PGxhYmVsIHN0eWxlPVwiXCIgZm9yPVwieyRmaWVsZC0+aWR9X19JTkRFWF9gYFNVQklOREVYYGBcIj5fX0RFRkFVTFRfVkFMVUVfXzwvbGFiZWw+IiwNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICA4ID0+ICI8aW5wdXQgdHlwZT1cIm51bWJlclwiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfXCIgaWQ9XCJ7JGZpZWxkLT5pZH1fX0lOREVYX1wiIF9UQUItSU5ERVhfIHskaW5oZXJpdHN0eWxlfSB7JGV2ZW50X2NvZGV9IHZhbHVlPVwiX19ERUZBVUxUX1ZBTFVFX19cIiAvPiIsDQogICAgICAgICAgICA5ID0+ICI8aW5wdXQgdHlwZT1cImNvbG9yXCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gdmFsdWU9XCJfX0RFRkFVTFRfVkFMVUVfX1wiIC8+IiwNCiAgICAgICAgICAgIDEwID0+ICI8aW5wdXQgdHlwZT1cImRhdGVcIiBuYW1lPVwieyRmaWVsZC0+bmFtZX1fX0lOREVYX1wiIGlkPVwieyRmaWVsZC0+aWR9X19JTkRFWF9cIiBfVEFCLUlOREVYXyB7JGluaGVyaXRzdHlsZX0geyRldmVudF9jb2RlfSB2YWx1ZT1cIl9fREVGQVVMVF9WQUxVRV9fXCIgLz4iLA0KICAgICAgICAgICAgMTEgPT4gIjxpbnB1dCB0eXBlPVwiZW1haWxcIiBuYW1lPVwieyRmaWVsZC0+bmFtZX1fX0lOREVYX1wiIGlkPVwieyRmaWVsZC0+aWR9X19JTkRFWF9cIiBfVEFCLUlOREVYXyB7JGluaGVyaXRzdHlsZX0geyRldmVudF9jb2RlfSB2YWx1ZT1cIl9fREVGQVVMVF9WQUxVRV9fXCIgLz4iLA0KICAgICAgICAgICAgMTIgPT4gIjxpbnB1dCB0eXBlPVwidGVsZXBob25lXCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gdmFsdWU9XCJfX0RFRkFVTFRfVkFMVUVfX1wiIC8+IiwNCiAgICAgICAgICAgIDEzID0+ICI8aW5wdXQgdHlwZT1cInRpbWVcIiBuYW1lPVwieyRmaWVsZC0+bmFtZX1fX0lOREVYX1wiIGlkPVwieyRmaWVsZC0+aWR9X19JTkRFWF9cIiBfVEFCLUlOREVYXyB7JGluaGVyaXRzdHlsZX0geyRldmVudF9jb2RlfSB2YWx1ZT1cIl9fREVGQVVMVF9WQUxVRV9fXCIgLz4iLA0KICAgICAgICAgICAgMTQgPT4gIjxpbnB1dCB0eXBlPVwidXJsXCIgbmFtZT1cInskZmllbGQtPm5hbWV9X19JTkRFWF9cIiBpZD1cInskZmllbGQtPmlkfV9fSU5ERVhfXCIgX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gdmFsdWU9XCJfX0RFRkFVTFRfVkFMVUVfX1wiIC8+Ig0KICAgICAgICApOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGZpZWxkX3R5cGVzWzNdID0gPDw8RU9GDQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KCS8vIEFtZXJpY2FuIENhbGVuZGFyIEZpZWxkLg0KCQ0KCXZhciBjYWx7JGZpZWxkLT5uYW1lfV9fSU5ERVhfID0gbmV3IENhbGVuZGFyUG9wdXAoImNhbC1kaXYteyRmaWVsZC0+bmFtZX1fX0lOREVYXyIpOw0KCWNhbHskZmllbGQtPm5hbWV9X19JTkRFWF8uc2V0Q3NzUHJlZml4KCdGQi1DQUwnKTsNCgljYWx7JGZpZWxkLT5uYW1lfV9fSU5ERVhfLnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JGZpZWxkLT5uYW1lfV9fSU5ERVhfIik7DQoJDQoJZnVuY3Rpb24gc2V0TXVsdGlwbGVWYWx1ZXNfeyRmaWVsZC0+bmFtZX1fX0lOREVYXyh5LG0sZCkgew0KCQkNCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRmaWVsZC0+aWR9X19JTkRFWF8tMScpLnZhbHVlPUxaKG0pICsgJy8nICsgTFooZCkgKyAnLycgKyB5OwkNCgkJDQoJCXZhbGlkYXRvcnNbJ2RhdGUteyRmaWVsZC0+aWR9X19JTkRFWF8tMSddLmNoZWNrKCk7DQoJCQ0KCQkvLyBGb2N1cyBmaWVsZCwgYWxsb3dzIHVzIHRvIGJpbmQgZXZlbnRzIHRvIHRoaXMgdmFsdWUgY2hhbmdpbmcuDQoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkYXRlLXskZmllbGQtPmlkfV9fSU5ERVhfLTEnKS5mb2N1cygpOw0KCQkNCgkJLy8gQ3VzdG9tIENhbGxiYWNrIENvZGUuDQoJCQ0KCQl2YXIgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKHksbS0xLGQsMCwwLDApKTsNCgkJdmFyIHNfdHMgPSBkYXRlLmdldFRpbWUoKS8xMDAwOw0KCQl2YXIgY190cyA9IE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkvMTAwMCk7DQoNCgl9DQoNCjwvc2NyaXB0Pg0KDQo8c3BhbiBpZD0iY2FsLWRpdi17JGZpZWxkLT5uYW1lfV9fSU5ERVhfIiANCglzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyB2aXNpYmlsaXR5OiBoaWRkZW47IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OjEwMDE7Ij4NCjwvc3Bhbj4NCg0KPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InskZmllbGQtPm5hbWV9X19JTkRFWF8iIGNsYXNzPSJkYXRhZ3JpZC1jb2x1bW4tY2FsZW5kYXIiDQoJCWlkPSJkYXRlLXskZmllbGQtPmlkfV9fSU5ERVhfLTEiIHskdGFiaHRtbH0gX1RBQi1JTkRFWF8geyRpbmhlcml0c3R5bGV9IHskZXZlbnRfY29kZX0gDQoJCXZhbHVlPSJfX0RFRkFVTFRfVkFMVUVfXyIgLz4NCg0KPGEgaWQ9ImNhbC1hbmNob3IteyRmaWVsZC0+bmFtZX1fX0lOREVYXyIgDQoJCW5hbWU9ImNhbC1hbmNob3IteyRmaWVsZC0+bmFtZX1fX0lOREVYXyIgaHJlZj0iIyIgDQoJCW9uY2xpY2s9ImNhbHskZmllbGQtPm5hbWV9X19JTkRFWF8uc2hvd0NhbGVuZGFyKCdjYWwtYW5jaG9yLXskZmllbGQtPm5hbWV9X19JTkRFWF8nKTsgcmV0dXJuIGZhbHNlOyIgPg0KCTxpbWcgc3R5bGU9Im1hcmdpbi1sZWZ0OjVweDsgbWFyZ2luLWJvdHRvbTotN3B4OyIgDQoJCWFsdD0iRGF0ZSBQaWNrZXIiIHNyYz0iPD9waHAgZWNobyBcJF9TRVNTSU9OWydNQVhfUEFUSCddOyA/PmNhbGVuZGFyL2NhbC0wLnBuZyIgDQoJCWJvcmRlcj0iMCIgLz4NCjwvYT4JDQoNCkVPRjsNCg0KDQogICAgICAgICRmaWVsZF90eXBlc1s0XSA9IDw8PEVPRg0KCQkNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCgkJDQoJLy8gRXVyb3BlYW4gQ2FsZW5kYXIgRmllbGQuDQoJCQ0KCXZhciBjYWx7JGZpZWxkLT5uYW1lfV9fSU5ERVhfID0gbmV3IENhbGVuZGFyUG9wdXAoImNhbC1kaXYteyRmaWVsZC0+bmFtZX1fX0lOREVYXyIpOw0KCWNhbHskZmllbGQtPm5hbWV9X19JTkRFWF8uc2V0Q3NzUHJlZml4KCdGQi1DQUwnKTsNCgljYWx7JGZpZWxkLT5uYW1lfV9fSU5ERVhfLnNldFJldHVybkZ1bmN0aW9uKCJzZXRNdWx0aXBsZVZhbHVlc197JGZpZWxkLT5uYW1lfV9fSU5ERVhfIik7DQoJDQoJZnVuY3Rpb24gc2V0TXVsdGlwbGVWYWx1ZXNfeyRmaWVsZC0+bmFtZX1fX0lOREVYXyh5LG0sZCkgew0KCQkNCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRmaWVsZC0+aWR9X19JTkRFWF8tMScpLnZhbHVlPUxaKGQpICsgJy8nICsgTFoobSkgKyAnLycgKyB5Ow0KCQkNCgkJdmFsaWRhdG9yc1snZGF0ZS17JGZpZWxkLT5pZH1fX0lOREVYXy0xJ10uY2hlY2soKTsNCgkJDQoJCS8vIEZvY3VzIGZpZWxkLCBhbGxvd3MgdXMgdG8gYmluZCBldmVudHMgdG8gdGhpcyB2YWx1ZSBjaGFuZ2luZy4NCgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUteyRmaWVsZC0+aWR9X19JTkRFWF8tMScpLmZvY3VzKCk7DQoJCQ0KCQkvLyBDdXN0b20gQ2FsbGJhY2sgQ29kZS4NCgkJDQoJCXZhciBkYXRlID0gbmV3IERhdGUoRGF0ZS5VVEMoeSxtLTEsZCwwLDAsMCkpOw0KCQl2YXIgc190cyA9IGRhdGUuZ2V0VGltZSgpLzEwMDA7DQoJCXZhciBjX3RzID0gTWF0aC5yb3VuZChuZXcgRGF0ZSgpLmdldFRpbWUoKS8xMDAwKTsNCg0KCX0NCgkJDQo8L3NjcmlwdD4NCgkJDQo8c3BhbiBpZD0iY2FsLWRpdi17JGZpZWxkLT5uYW1lfV9fSU5ERVhfIg0KCXN0eWxlPSJwb3NpdGlvbjogYWJzb2x1dGU7IHZpc2liaWxpdHk6IGhpZGRlbjsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IHotaW5kZXg6MTAwMTsiPg0KPC9zcGFuPg0KCQkNCjxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJ7JGZpZWxkLT5uYW1lfV9fSU5ERVhfIiBjbGFzcz0iZGF0YWdyaWQtY29sdW1uLWNhbGVuZGFyIg0KCQlpZD0iZGF0ZS17JGZpZWxkLT5pZH1fX0lOREVYXy0xIiB7JHRhYmh0bWx9IF9UQUItSU5ERVhfIHskaW5oZXJpdHN0eWxlfSB7JGV2ZW50X2NvZGV9DQoJCXZhbHVlPSJfX0RFRkFVTFRfVkFMVUVfXyIgLz4NCgkJDQo8YSBpZD0iY2FsLWFuY2hvci17JGZpZWxkLT5uYW1lfV9fSU5ERVhfIg0KCQluYW1lPSJjYWwtYW5jaG9yLXskZmllbGQtPm5hbWV9X19JTkRFWF8iIGhyZWY9IiMiDQoJCW9uY2xpY2s9ImNhbHskZmllbGQtPm5hbWV9X19JTkRFWF8uc2hvd0NhbGVuZGFyKCdjYWwtYW5jaG9yLXskZmllbGQtPm5hbWV9X19JTkRFWF8nKTsgcmV0dXJuIGZhbHNlOyIgPg0KCTxpbWcgc3R5bGU9Im1hcmdpbi1sZWZ0OjVweDsgbWFyZ2luLWJvdHRvbTotN3B4OyINCgkJYWx0PSJEYXRlIFBpY2tlciIgc3JjPSI8P3BocCBlY2hvIFwkX1NFU1NJT05bJ01BWF9QQVRIJ107ID8+Y2FsZW5kYXIvY2FsLTAucG5nIg0KCQlib3JkZXI9IjAiIC8+DQo8L2E+DQoJCQ0KRU9GOw0KDQoNCiAgICAgICAgDQogICAgICAgICRmaWVsZF9pdGVtID0gJGZpZWxkX3R5cGVzWyhpbnQpJGZpZWxkLT5ncmlkX3Byb3BlcnRpZXMtPmZpZWxkdHlwZV07DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICI8dGFibGUgY2xhc3M9XCJkYXRhZ3JpZFwiIGlkPVwieyRmaWVsZC0+bmFtZX1cIiB3aWR0aD1cInskZ3JpZC0+d2lkdGh9XCIgYm9yZGVyPVwieyRncmlkLT5ib3JkZXJ9XCIgY2VsbHBhZGRpbmc9XCJ7JGdyaWQtPmNlbGxwYWRkaW5nfVwiIGNlbGxzcGFjaW5nPVwieyRncmlkLT5jZWxsc3BhY2luZ31cIiA+IjsNCg0KICAgICAgICANCiAgICAgICAgJHJvd3MgPSAoaW50KSRncmlkLT5yb3dzOw0KICAgICAgICAkY29sdW1ucyA9IChpbnQpJGdyaWQtPmNvbHVtbnM7DQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICI8dHI+IjsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIjx0aCBzdHlsZT1cIndpZHRoOnskZ3JpZC0+cm93X2NvbHVtbl93aWR0aH1weDsgXCIgYWxpZ249XCJsZWZ0XCIgaWQ9XCJcIj48L3RoPiI7DQoNCiAgICAgICAgDQogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8ICRjb2x1bW5zOyAkaSsrKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjx0aCBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6eyRncmlkLT5jb2x1bW5fYmFja2dyb3VuZF9jb2xvcn07IGNvbG9yOnskZ3JpZC0+ZGF0YWdyaWRfY29sdW1uX2NvbG9yfTsgdmVydGljYWwtYWxpZ246IGJvdHRvbTsgZm9udC13ZWlnaHQ6eyRncmlkLT5jb2x1bW5fZm9udF93ZWlnaHR9O1wiIGFsaWduPVwieyRncmlkLT5jb2x1bW5fYWxpZ25tZW50fVwiID4iIC4gJGdyaWQtPmdyaWRfaGVhZGVycy0+Y29sdW1uc1skaV0gLiAiPC90aD4iOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIjwvdHI+IjsNCg0KICAgICAgICAkX2l0ZW1Db3VudCA9IDA7DQoNCiAgICAgICAgDQogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8ICRyb3dzOyAkaSsrKSB7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8dHI+IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRyb3dfc3R5bGUgPSAiIGZvbnQtd2VpZ2h0OnskZ3JpZC0+cm93X2ZvbnRfd2VpZ2h0fTsgY29sb3I6eyRncmlkLT5kYXRhZ3JpZF9yb3dfY29sb3J9OyAiOw0KDQogICAgICAgICAgICBpZiAoKGludCkkZ3JpZC0+YWx0ZXJuYXRlX2xpbmVzID09IDEgJiYgJGkgJSAyICE9IDApIHsNCiAgICAgICAgICAgICAgICAkcm93X3N0eWxlIC49ICIgYmFja2dyb3VuZC1jb2xvcjoiIC4gJGdyaWQtPmFsdGVybmF0ZV9saW5lX2NvbG9yIC4gIjsgIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkc3ViaGVhZF90ZXh0ID0gJGdyaWQtPmdyaWRfaGVhZGVycy0+cm93c1skaV07DQoNCiAgICAgICAgICAgICRpc19zdWJoZWFkID0gZmFsc2U7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKHByZWdfbWF0Y2goJy9cfFx8LisvJywgJGdyaWQtPmdyaWRfaGVhZGVycy0+cm93c1skaV0pICE9IDApIHsNCiAgICAgICAgICAgICAgICAkaXNfc3ViaGVhZCA9IHRydWU7DQoNCiAgICAgICAgICAgICAgICAkbmV3X3RleHQgPSBzdHJfcmVwbGFjZSgnfHwnLCAnJywgJGdyaWQtPmdyaWRfaGVhZGVycy0+cm93c1skaV0pOw0KICAgICAgICAgICAgICAgICRzdWJoZWFkX3RleHQgPSAkbmV3X3RleHQ7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjx0ZCBzdHlsZT1cInskcm93X3N0eWxlfVwiIGlkPVwieyRmaWVsZC0+bmFtZX0tcm93LWxhYmVsLXskaX1cIiBjbGFzcz1cImRhdGFncmlkLXJvdy1sYWJlbFwiIGFsaWduPVwieyRncmlkLT5yb3dfYWxpZ25tZW50fVwiID4iIC4gJHN1YmhlYWRfdGV4dCAuICI8L3RkPiI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgZm9yICgkaiA9IDA7ICRqIDwgJGNvbHVtbnM7ICRqKyspIHsNCg0KICAgICAgICAgICAgICAgICRoYXNfb3ZlcnJpZGUgPSBmYWxzZTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5jb2x1bW5fdHlwZVskal0pICYmIChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+Y29sdW1uX3R5cGVbJGpdICE9ICcnKSB7IA0KDQogICAgICAgICAgICAgICAgICAgICRoYXNfb3ZlcnJpZGUgPSB0cnVlOw0KDQogICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX292ZXJyaWRlID0gJGZpZWxkX3R5cGVzWyhpbnQpJGdyaWQtPmdyaWRfaGVhZGVycy0+Y29sdW1uX3R5cGVbJGpdXTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoJGhhc19vdmVycmlkZSkgew0KDQogICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSAkZmllbGRfaXRlbV9vdmVycmlkZTsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSAkZmllbGRfaXRlbTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkaGFzX2RlZmF1bHRfdmFsdWVfdmFyID0gZmFsc2U7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdKSAmJiAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXSAhPSAnJyAmJiAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXSAhPSAnTm8gVmFsdWUnKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGhhc19kZWZhdWx0X3ZhbHVlX3ZhciA9IHRydWU7DQoNCiAgICAgICAgICAgICAgICAgICAgJG9wdGlvbnNfaHRtbCA9ICcnOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKChpbnQpJGdyaWQtPmdyaWRfaGVhZGVycy0+Y29sdW1uX3R5cGVbJGpdKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3N0YXRpY192YWx1ZSA9IChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgPyBwcmludCBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10gOiAneyRkZWZhdWx0X3N0YXRpY192YWx1ZX0nOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF9zdGF0aWNfdmFsdWUgPSAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF92YWx1ZSA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddIDogJ3skZGVmYXVsdF9zdGF0aWNfdmFsdWV9JzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfc3RhdGljX3ZhbHVlID0gKHN0cmluZykkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5kZWZhdWx0X3ZhbHVlc1skal07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfdmFsdWUgPSAiPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddKSA/IHByaW50IFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSA6ICd7JGRlZmF1bHRfc3RhdGljX3ZhbHVlfSc7ID8+IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX19ERUZBVUxUX1ZBTFVFX18nLCAkZGVmYXVsdF92YWx1ZSwgJGZpZWxkX2l0ZW1fY29weSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3N0YXRpY192YWx1ZSA9IChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgPyBwcmludCBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10gOiAneyRkZWZhdWx0X3N0YXRpY192YWx1ZX0nOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNDogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF9zdGF0aWNfdmFsdWUgPSAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF92YWx1ZSA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddIDogJ3skZGVmYXVsdF9zdGF0aWNfdmFsdWV9JzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDU6IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvcHRpb25zID0gZXhwbG9kZSgnfCcsIChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JlYWNoICgkb3B0aW9ucyBhcyAkb3B0KSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNlbGVjdGVkX3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgJiYgXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddID09ICd7JG9wdH0nID8gcHJpbnQgJ3NlbGVjdGVkPVwic2VsZWN0ZWRcIicgOiAnJzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvcHRpb25zX2h0bWwgLj0gIjxvcHRpb24gdmFsdWU9XCJ7JG9wdH1cIiB7JHNlbGVjdGVkX3ZhbHVlfT57JG9wdH08L29wdGlvbj4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJG9wdGlvbnNfaHRtbCwgJGZpZWxkX2l0ZW1fY29weSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNjogDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJG9wdGlvbnMgPSBleHBsb2RlKCd8JywgKHN0cmluZykkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5kZWZhdWx0X3ZhbHVlc1skal0pOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuZXdfdmFsdWUgPSAnJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JlYWNoICgkb3B0aW9ucyBhcyAkaWR4ID0+ICRvcHQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gJGZpZWxkX2l0ZW1fY29weTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRjaGVja2VkID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgJiYgXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddID09ICd7JG9wdH0nID8gcHJpbnQgJyBjaGVja2VkPVwiY2hlY2tlZFwiICcgOiAnJzsgPz4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV90bXAgPSBzdHJfcmVwbGFjZSgnX0NIRUNLRURfJywgJGNoZWNrZWQsICRmaWVsZF9pdGVtX3RtcCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gc3RyX3JlcGxhY2UoJ2BgU1VCSU5ERVhgYCcsICdfJyAuICRpZHgsICRmaWVsZF9pdGVtX3RtcCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX3RtcCA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRvcHQsICRmaWVsZF9pdGVtX3RtcCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuZXdfdmFsdWUgLj0gJGZpZWxkX2l0ZW1fdG1wOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gJG5ld192YWx1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA3OiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkb3B0aW9ucyA9IGV4cGxvZGUoJ3wnLCAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJG5ld192YWx1ZSA9ICcnOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJG9wdGlvbnMgYXMgJGlkeCA9PiAkb3B0KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX3RtcCA9ICRmaWVsZF9pdGVtX2NvcHk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkY2hlY2tlZCA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10pICYmIGluX2FycmF5KCd7JG9wdH0nLCBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10pID8gcHJpbnQgJyBjaGVja2VkPVwiY2hlY2tlZFwiICcgOiAnJzsgPz4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV90bXAgPSBzdHJfcmVwbGFjZSgnX0NIRUNLRURfJywgJGNoZWNrZWQsICRmaWVsZF9pdGVtX3RtcCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gc3RyX3JlcGxhY2UoJ2BgU1VCSU5ERVhgYCcsICdfJyAuICRpZHgsICRmaWVsZF9pdGVtX3RtcCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX3RtcCA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRvcHQsICRmaWVsZF9pdGVtX3RtcCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX3RtcCA9IHN0cl9yZXBsYWNlKCdfQ0hFQ0tCT1hfVkFMVUVfJywgJG9wdCwgJGZpZWxkX2l0ZW1fdG1wKTsgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuZXdfdmFsdWUgLj0gJGZpZWxkX2l0ZW1fdG1wOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gJG5ld192YWx1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgKHN0cmluZykkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5kZWZhdWx0X3ZhbHVlc1skal0sICRmaWVsZF9pdGVtX2NvcHkpOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKChpbnQpJGdyaWQtPmdyaWRfaGVhZGVycy0+Y29sdW1uX3R5cGVbJGpdKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNjogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkb3B0aW9ucyA9IGV4cGxvZGUoJ3wnLCAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV90bXAgPSAkZmllbGRfaXRlbV9jb3B5Ow0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50KCRvcHRpb25zKSA9PSAxICYmICRvcHRpb25zWzBdID09ICdObyBWYWx1ZScpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gc3RyX3JlcGxhY2UoJ2BgU1VCSU5ERVhgYCcsICdfJyAuICcwJywgJGZpZWxkX2l0ZW1fdG1wKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJycsICRmaWVsZF9pdGVtX3RtcCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9ICRmaWVsZF9pdGVtX3RtcDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA3OiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvcHRpb25zID0gZXhwbG9kZSgnfCcsIChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdKTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX3RtcCA9ICRmaWVsZF9pdGVtX2NvcHk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY291bnQoJG9wdGlvbnMpID09IDEgJiYgJG9wdGlvbnNbMF0gPT0gJ05vIFZhbHVlJykgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV90bXAgPSBzdHJfcmVwbGFjZSgnYGBTVUJJTkRFWGBgJywgJ18nIC4gJzAnLCAkZmllbGRfaXRlbV90bXApOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV90bXAgPSBzdHJfcmVwbGFjZSgnX19ERUZBVUxUX1ZBTFVFX18nLCAnJywgJGZpZWxkX2l0ZW1fdG1wKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fdG1wID0gc3RyX3JlcGxhY2UoJ19DSEVDS0JPWF9WQUxVRV8nLCAnMScsICRmaWVsZF9pdGVtX3RtcCk7IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSAkZmllbGRfaXRlbV90bXA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIH0gDQoNCg0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGQtPmdyaWRfcHJvcGVydGllcy0+ZGF0YWJhc2VfZGVmYXVsdHMpICYmIGlzX2FycmF5KChhcnJheSkkZmllbGQtPmdyaWRfcHJvcGVydGllcy0+ZGF0YWJhc2VfZGVmYXVsdHMpKSB7DQogICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJF92YWwgPSAkZmllbGQtPmdyaWRfcHJvcGVydGllcy0+ZGF0YWJhc2VfZGVmYXVsdHNbJF9pdGVtQ291bnRdOw0KDQogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoKGludCkkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5jb2x1bW5fdHlwZVskal0pIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkcG9wWzBdWyd7JF92YWx9J10pID8gcHJpbnQgXCRwb3BbMF1bJ3skX3ZhbH0nXSA6ICcnOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF92YWx1ZSA9ICI8P3BocCBpc3NldChcJHBvcFswXVsneyRfdmFsfSddKSA/IHByaW50IFwkcG9wWzBdWyd7JF92YWx9J10gOiAnJzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfdmFsdWUgPSAiPD9waHAgaXNzZXQoXCRwb3BbMF1bJ3skX3ZhbH0nXSkgPyBwcmludCBcJHBvcFswXVsneyRfdmFsfSddIDogJyc7ID8+IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX19ERUZBVUxUX1ZBTFVFX18nLCAkZGVmYXVsdF92YWx1ZSwgJGZpZWxkX2l0ZW1fY29weSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkcG9wWzBdWyd7JF92YWx9J10pID8gcHJpbnQgXCRwb3BbMF1bJ3skX3ZhbH0nXSA6ICcnOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNDogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF92YWx1ZSA9ICI8P3BocCBpc3NldChcJHBvcFswXVsneyRfdmFsfSddKSA/IHByaW50IFwkcG9wWzBdWyd7JF92YWx9J10gOiAnJzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJycsICRmaWVsZF9pdGVtX2NvcHkpOw0KICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICB9IA0KDQoNCg0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmICghJGhhc19kZWZhdWx0X3ZhbHVlX3Zhcikgew0KDQogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoKGludCkkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5jb2x1bW5fdHlwZVskal0pIHsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3N0YXRpY192YWx1ZSA9IChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgPyBwcmludCBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10gOiAnJzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfc3RhdGljX3ZhbHVlID0gKHN0cmluZykkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5kZWZhdWx0X3ZhbHVlc1skal07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfdmFsdWUgPSAiPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddKSA/IHByaW50IFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSA6ICcnOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjogDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF9zdGF0aWNfdmFsdWUgPSAoc3RyaW5nKSRncmlkLT5ncmlkX2hlYWRlcnMtPmRlZmF1bHRfdmFsdWVzWyRqXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGVmYXVsdF92YWx1ZSA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10pID8gcHJpbnQgXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddIDogJyc7ID8+IjsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX19ERUZBVUxUX1ZBTFVFX18nLCAkZGVmYXVsdF92YWx1ZSwgJGZpZWxkX2l0ZW1fY29weSk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOiANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3N0YXRpY192YWx1ZSA9IChzdHJpbmcpJGdyaWQtPmdyaWRfaGVhZGVycy0+ZGVmYXVsdF92YWx1ZXNbJGpdOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkZWZhdWx0X3ZhbHVlID0gIjw/cGhwIGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSkgPyBwcmludCBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fSU5ERVhfJ10gOiAnJzsgPz4iOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfX0RFRkFVTFRfVkFMVUVfXycsICRkZWZhdWx0X3ZhbHVlLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6IA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfc3RhdGljX3ZhbHVlID0gKHN0cmluZykkZ3JpZC0+Z3JpZF9oZWFkZXJzLT5kZWZhdWx0X3ZhbHVlc1skal07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlZmF1bHRfdmFsdWUgPSAiPD9waHAgaXNzZXQoXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1fX0lOREVYXyddKSA/IHByaW50IFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19JTkRFWF8nXSA6ICcnOyA/PiI7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJGRlZmF1bHRfdmFsdWUsICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19fREVGQVVMVF9WQUxVRV9fJywgJycsICRmaWVsZF9pdGVtX2NvcHkpOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19JTkRFWF8nLCAkaSAuICdfJyAuICRqLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGlmICgkdGFiaHRtbCAhPSAnJykgew0KICAgICAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19UQUItSU5ERVhfJywgJHRhYmh0bWwsICRmaWVsZF9pdGVtX2NvcHkpOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX1RBQi1JTkRFWF8nLCAnJywgJGZpZWxkX2l0ZW1fY29weSk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgaWYgKCRpc19zdWJoZWFkKSB7DQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8dGQgc3R5bGU9XCJ7JHJvd19zdHlsZX1cIiBhbGlnbj1cInskZ3JpZC0+Y29sdW1uX2FsaWdubWVudH1cIiA+PC90ZD4iOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8dGQgc3R5bGU9XCJ7JHJvd19zdHlsZX1cIiBhbGlnbj1cInskZ3JpZC0+Y29sdW1uX2FsaWdubWVudH1cIiA+IiAuICRmaWVsZF9pdGVtX2NvcHkgLiAiPC90ZD4iOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICRfaXRlbUNvdW50Kys7DQoNCiAgICAgICAgICAgIH0gDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvdHI+IjsgDQoNCg0KICAgICAgICB9IA0KDQoNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIjwvdGFibGU+IjsNCg0KDQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgJHRhYmxlbW9kZXNwYW4gJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPC9kaXY+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9zdXJ2ZXkoJGZpZWxkLCAkcGFnZSwgJGpvYm5hbWUsICRidWNrZXRfbm9kZSA9ICIiKQ0KICAgIHsNCiAgICAgICAgDQoNCiAgICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5zdXJ2ZXlfcHJvcGVydGllcy0+dXNlX2R5bmFtaWNfZ2VuZXJhdGlvbikgJiYgJGZpZWxkLT5zdXJ2ZXlfcHJvcGVydGllcy0+dXNlX2R5bmFtaWNfZ2VuZXJhdGlvbiA9PSAiMCIpIHsNCg0KICAgICAgICAgICAgJGpzb24gPSBuZXcgc3RkQ2xhc3MoKTsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGpzb24tPmZpZWxkID0gJGZpZWxkLT5hc1hNTCgpOw0KICAgICAgICAgICAgJGpzb24tPnBhZ2UgPSAkcGFnZS0+YXNYTUwoKTsNCiAgICAgICAgICAgICRqc29uLT5qb2JuYW1lID0gJGpvYm5hbWUtPmFzWE1MKCk7DQogICAgICAgICAgICAkanNvbi0+YnVja2V0X25vZGUgPSAkYnVja2V0X25vZGU7DQoNCiAgICAgICAgICAgICRyYXdfZGF0YSA9IGNodW5rX3NwbGl0KGJhc2U2NF9lbmNvZGUoanNvbl9lbmNvZGUoJGpzb24pKSk7DQoNCiAgICAgICAgICAgICRyZXQgPSA8PDxFT0YNCjw/cGhwDQoNCi8vIFJhdyBTdXJ2ZXkgRmllbGQgRGF0YS4NCg0KXCRkZWJ1Z19yYXdfc3VydmV5X2xvZ2ljID0gZmFsc2U7DQpcJGRlYnVnX3Jhd19odG1sID0gZmFsc2U7DQoNClwkZGF0YSA9IGpzb25fZGVjb2RlKGJhc2U2NF9kZWNvZGUoJ3skcmF3X2RhdGF9JyksIGZhbHNlKTsNCg0KaWYoXCRkZWJ1Z19yYXdfc3VydmV5X2xvZ2ljKSB7DQoJZWNobyAnPHByZT5SQVcgU1VSVkVZIENSRUFURSBDT0RFOjxici8+JzsNCgl2YXJfZHVtcChcJGRhdGEpOw0KCWVjaG8gJzxwcmU+JzsNCn0NCg0KLy8gR2VuZXJhdGUgRHluYW1pYyBDb2RlLg0KXCRfZmllbGQgPSBuZXcgU2ltcGxlWE1MRWxlbWVudChcJGRhdGEtPmZpZWxkKTsNClwkX3BhZ2UgPSBuZXcgU2ltcGxlWE1MRWxlbWVudChcJGRhdGEtPnBhZ2UpOw0KXCRfam9ibmFtZSA9IG5ldyBTaW1wbGVYTUxFbGVtZW50KFwkZGF0YS0+am9ibmFtZSk7DQpcJGR5bmFtaWNfaHRtbCA9IGNyZWF0ZV9keW5hbWljX3N1cnZleShcJF9maWVsZCwgXCRfcGFnZSwgXCRfam9ibmFtZSwgXCRkYXRhLT5idWNrZXRfbm9kZSk7DQoNCmlmKFwkZGVidWdfcmF3X2h0bWwpIHsNCgllY2hvICc8cHJlPlJBVyBIVE1MOic7DQoJZWNobyBcJGR5bmFtaWNfaHRtbDsNCgllY2hvICc8L3ByZT4nOw0KfQ0KDQovLyBHZW5lcmF0ZSBUZW1wIEZpbGUgYW5kIEluY2x1ZGUuDQovLyBOZWVkZWQgdG8gUGFyc2UgRHluYW1pYyBQSFAuDQpcJHRtcGZuYW1lID0gdGVtcG5hbSgiL3RtcCIsICJGT08iKTsNClwkaGFuZGxlID0gZm9wZW4oXCR0bXBmbmFtZSwgInciKTsNCmZ3cml0ZShcJGhhbmRsZSwgXCRkeW5hbWljX2h0bWwpOw0KZmNsb3NlKFwkaGFuZGxlKTsNCmluY2x1ZGUgXCR0bXBmbmFtZTsNCnVubGluayhcJHRtcGZuYW1lKTsNCg0KPz4NCgkJCQ0KRU9GOw0KICAgICAgICAgICAgcmV0dXJuICRyZXQ7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQoNCg0KICAgICAgICANCg0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+bmFtZTsNCg0KICAgICAgICAkbGFiZWwgPSAkZmllbGQtPmxhYmVsOw0KDQogICAgICAgIA0KICAgICAgICAkY29sb3IgPSAkZmllbGQtPmNvbG9yOw0KICAgICAgICAkaW5wdXRfY29sb3IgPSAkZmllbGQtPmlucHV0X2NvbG9yOw0KICAgICAgICAkZm9udHNpemUgPSAkZmllbGQtPmZvbnRzaXplOw0KICAgICAgICAkaW5oZXJpdHN0eWxlID0gJGZpZWxkLT5pbmhlcml0c3R5bGU7DQoNCiAgICAgICAgDQogICAgICAgICRzdHlsZSA9ICRmaWVsZC0+c3R5bGU7DQogICAgICAgICRzdHlsZXMgPSAkdGhpcy0+dHJhbnNsYXRlRmllbGRTdHlsZXMoJHN0eWxlKTsNCg0KICAgICAgICANCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCiAgICAgICAgJHRhYmh0bWwgPSAkdGhpcy0+Y3JlYXRlVGFiSW5kZXhDb2RlKChpbnQpJHRhYmluZGV4KTsNCg0KDQogICAgICAgIA0KICAgICAgICAkc3VydmV5ID0gJGZpZWxkLT5zdXJ2ZXlfcHJvcGVydGllczsNCg0KDQogICAgICAgIA0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRmb250c2l6ZSwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRmb250c2l6ZSA9ICRmb250c2l6ZSAuICdweCc7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNzZXQoJHN1cnZleS0+cXVlc3Rpb25fZm9udF9zaXplKSB8fCAkc3VydmV5LT5xdWVzdGlvbl9mb250X3NpemUgPT0gIiIpIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPnF1ZXN0aW9uX2ZvbnRfc2l6ZSA9ICIxMHB0OyI7DQogICAgICAgIH0NCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHN1cnZleS0+cXVlc3Rpb25fZm9udF9zaXplLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRzdXJ2ZXktPnF1ZXN0aW9uX2ZvbnRfc2l6ZSwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPnF1ZXN0aW9uX2ZvbnRfc2l6ZSA9ICRzdXJ2ZXktPnF1ZXN0aW9uX2ZvbnRfc2l6ZSAuICdwdCc7DQogICAgICAgIH0NCg0KDQogICAgICAgIGlmICghaXNzZXQoJHN1cnZleS0+cmVzcG9uc2VfZm9udF9zaXplKSB8fCAkc3VydmV5LT5yZXNwb25zZV9mb250X3NpemUgPT0gIiIpIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPnJlc3BvbnNlX2ZvbnRfc2l6ZSA9ICIxMHB0OyI7DQogICAgICAgIH0NCg0KICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJHN1cnZleS0+cmVzcG9uc2VfZm9udF9zaXplLCAncHQnKTsNCiAgICAgICAgJGN0MiA9IHN1YnN0cl9jb3VudCgoc3RyaW5nKSRzdXJ2ZXktPnJlc3BvbnNlX2ZvbnRfc2l6ZSwgJ3B4Jyk7DQoNCiAgICAgICAgaWYgKCRjdDEgPT0gMCAmJiAkY3QyID09IDApIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPnJlc3BvbnNlX2ZvbnRfc2l6ZSA9ICRzdXJ2ZXktPnJlc3BvbnNlX2ZvbnRfc2l6ZSAuICdwdCc7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNzZXQoJHN1cnZleS0+Y3VzdG9tX2V2ZW50X2NhbGxiYWNrKSB8fCAkc3VydmV5LT5jdXN0b21fZXZlbnRfY2FsbGJhY2sgPT0gIiIpIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPmN1c3RvbV9ldmVudF9jYWxsYmFjayA9ICIiOw0KICAgICAgICB9DQoNCg0KDQoNCiAgICAgICAgJHRhYmxlbW9kZSA9ICRwYWdlLT50YWJsZW1vZGU7DQoNCg0KICAgICAgICANCiAgICAgICAgJHRhYmxlbW9kZXNwYW4gPSBmYWxzZTsNCiAgICAgICAgaWYgKCFpc3NldCgkc3R5bGUtPnRhYmxlbW9kZXNwYW4pKSB7DQogICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IGZhbHNlOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKChpbnQpJHN0eWxlLT50YWJsZW1vZGVzcGFuID09IDApIHsNCiAgICAgICAgICAgICAgICAkdGFibGVtb2Rlc3BhbiA9IHRydWU7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+bGVmdGNvbHVtbmFsaWduID09IDApIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdsZWZ0JzsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRhbGlnbiA9ICdyaWdodCc7DQogICAgICAgIH0NCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAkdGFibGVtb2Rlc3BhbiAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCg0KICAgICAgICAgICAgJGZpeGVkX3dpZHRoID0gJHRhYmxlbW9kZS0+bGVmdGNvbHVtbndpZHRoIC0gODsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcbjxkaXYgY2xhc3M9XCJmYi10YWJsZW1vZGUtbGFiZWwgZGVza3RvcC1jZWxsXCIgc3R5bGU9XCJ3aWR0aDp7JGZpeGVkX3dpZHRofXB4OyBtYXJnaW4tcmlnaHQ6OHB4OyBwYWRkaW5nLXRvcDozcHg7IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn1cIiA+IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQogICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJG5hbWUsIDAsICRyZXF1aXJlZF90ZXh0LCAkY29sb3IsICRmb250c2l6ZSwgJHN0eWxlcywgJGxhYmVsLCAwLCAoc3RyaW5nKSRmaWVsZC0+dHlwZSwgJycsICcnLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICI8L2Rpdj4iOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGJvdHRvbV9tYXJnaW5fdmFsdWUgPSBpbnR2YWwoJHRhYmxlbW9kZS0+bWFyZ2luYm90dG9tKTsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPGRpdiBjbGFzcz1cImZiLXRhYmxlbW9kZS1lbGVtZW50XCIgc3R5bGU9XCJ3aWR0aDp7JHRhYmxlbW9kZS0+cmlnaHRjb2x1bW53aWR0aH07IGZsb2F0OmxlZnQ7IHRleHQtYWxpZ246eyRhbGlnbn07IG1hcmdpbi1ib3R0b206eyRib3R0b21fbWFyZ2luX3ZhbHVlfXB4OyBcIiA+IjsNCiAgICAgICAgfQ0KDQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGN1c3RvbV9ldmVudCA9ICIiOw0KDQogICAgICAgIGlmICgoc3RyaW5nKSRzdXJ2ZXktPmN1c3RvbV9ldmVudF9jYWxsYmFjayAhPSAiIikgew0KICAgICAgICAgICAgJGN1c3RvbV9ldmVudCA9ICRzdXJ2ZXktPmN1c3RvbV9ldmVudF9jYWxsYmFjazsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZXZlbnRfdHJpZ2dlcl9jb2RlID0gIiI7DQogICAgICAgICRldmVudF90cmlnZ2VyX2lubGluZSA9ICIiOw0KDQogICAgICAgIGlmICgoc3RyaW5nKSRzdXJ2ZXktPnRyaWdnZXJjb2RlICE9ICIiKSB7DQoNCiAgICAgICAgICAgICRldmVudF90cmlnZ2VyX2NvZGUgPSA8PDxFT0YNCg0KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQoJCQ0KCQkJLy8gZmllbGQgdmFsdWUsIGNhbGxpbmcgZmllbGQgaWQsIHRyaWdnZXIgZmllbGQgaWQNCgkJCWZ1bmN0aW9uIHByb2Nlc3NUcmlnZ2VyX3skZmllbGQtPmlkfV9fSURfKGV2ZW50LCB2YWx1ZSwgY2FsbGluZ19maWVsZF9pZCwgdHJpZ2dlcl9maWVsZF9pZCl7DQoJCQkJdmFyIGluZGV4ID0gX1RSSUdHRVJfSU5ERVhfOw0KCQkJCXZhciBjb2wyID0gJ19UUklHR0VSX0NPTDJfJzsNCgkJCQlpZih7JHN1cnZleS0+dHJpZ2dlcmNvZGV9KSB7DQoJCQkJCS8vZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZiX2ZsZC0nICsgdHJpZ2dlcl9maWVsZF9pZCkuc3R5bGUuZGlzcGxheSA9ICJ0YWJsZS1yb3ciOw0KCQkJCQlmYmMuc2hvdyh0cmlnZ2VyX2ZpZWxkX2lkLCBldmVudCwgJ2ZhZGUnKTsNCgkJCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skZmllbGQtPmlkfV9fSURfJyArICdfdHJpZ2dlckZpZWxkJykuZGlzYWJsZWQgPSBmYWxzZTsgLy8gZW5hYmxlDQoJCQkJfSBlbHNlIHsNCgkJCQkJLy9kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmJfZmxkLScgKyB0cmlnZ2VyX2ZpZWxkX2lkKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOw0KCQkJCQlmYmMuaGlkZSh0cmlnZ2VyX2ZpZWxkX2lkLCBldmVudCwgJ2ZhZGUnKTsJDQoJCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGZpZWxkLT5pZH1fX0lEXycgKyAnX3RyaWdnZXJGaWVsZCcpLmRpc2FibGVkID0gdHJ1ZTsgLy8gZGlzYWJsZQ0KCQkJCX0NCgkJCX0NCg0KCQkJDQoJCQkvLyBQb3B1bGF0ZSBvbiBwYWdlIGxvYWQuDQoJCQkNCgkJCXZhciB2YWx1ZSA9ICcnOw0KDQoJCQlmb3IodmFyIGkgPSAwOyBpIDwgMjA7IGkrKyl7DQoJCQkJaWYoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skZmllbGQtPmlkfV9fSURfJyArICdfJyArIGkpKSB7DQoJCQkJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGZpZWxkLT5pZH1fX0lEXycgKyAnXycgKyBpKS5jaGVja2VkKXsNCgkJCQkJCXZhbHVlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skZmllbGQtPmlkfV9fSURfJyArICdfJyArIGkpLnZhbHVlOw0KCQkJCQkJYnJlYWs7DQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoNCgkJCXZhciBpbmRleCA9IF9UUklHR0VSX0lOREVYXzsNCgkJCXZhciBjb2wyID0gJ19UUklHR0VSX0NPTDJfJzsNCgkJCQkNCgkJCWlmKHZhbHVlICE9ICcnICYmIHskc3VydmV5LT50cmlnZ2VyY29kZX0pIHsNCgkJCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmJfZmxkLScgKyAneyRmaWVsZC0+aWR9X19JRF8nICsgJ190cmlnZ2VyJykuc3R5bGUuZGlzcGxheSA9ICJ0YWJsZS1yb3ciOyAvLyBzaG93DQoJCQkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skZmllbGQtPmlkfV9fSURfJyArICdfdHJpZ2dlckZpZWxkJykuZGlzYWJsZWQgPSBmYWxzZTsgLy8gZW5hYmxlDQoJCQl9IGVsc2Ugew0KCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmYl9mbGQtJyArICd7JGZpZWxkLT5pZH1fX0lEXycgKyAnX3RyaWdnZXInKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOw0KCQkJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGZpZWxkLT5pZH1fX0lEXycgKyAnX3RyaWdnZXJGaWVsZCcpLmRpc2FibGVkID0gdHJ1ZTsgLy8gZGlzYWJsZQ0KCQkJfQ0KCQkJDQoJCTwvc2NyaXB0PgkJCQ0KDQpFT0Y7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGV2ZW50X3RyaWdnZXJfaW5saW5lID0gInByb2Nlc3NUcmlnZ2VyX3skZmllbGQtPmlkfV9fVFJJR0dFUl9ST1dfKGV2ZW50LCB0aGlzLnZhbHVlLCAneyRmaWVsZC0+aWR9X19JRF8nLCAneyRmaWVsZC0+aWR9X19UUklHR0VSX1JPV19fdHJpZ2dlcicpOyI7DQogICAgICAgIH0NCg0KDQogICAgICAgICRldmVudF9jb2RlID0gIiI7DQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKCRldmVudF90cmlnZ2VyX2lubGluZSAhPSAiIiB8fCAkY3VzdG9tX2V2ZW50ICE9ICIiKSB7DQoNCiAgICAgICAgICAgIHN3aXRjaCAoKGludCkkZmllbGQtPmdyaWRfcHJvcGVydGllcy0+ZmllbGR0eXBlKSB7DQoNCiAgICAgICAgICAgICAgICBjYXNlIDA6DQogICAgICAgICAgICAgICAgICAgICRldmVudF9jb2RlID0gIm9uY2xpY2s9XCJ7JGN1c3RvbV9ldmVudH0geyRldmVudF90cmlnZ2VyX2lubGluZX1cIiI7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+Z3JpZF9wcm9wZXJ0aWVzLT5maWVsZHR5cGUpIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkZmllbGRfaXRlbSA9ICI8aW5wdXQgY2xhc3M9XCJzdXJ2ZXktcmVzcG9uc2UtaW5wdXQtZmllbGRcIiB7JGV2ZW50X2NvZGV9IHR5cGU9XCJyYWRpb1wiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV9fTkFNRV9cIiBpZD1cInskZmllbGQtPmlkfV9fSURfXCIgdmFsdWU9XCJfRFlOQU1JQ19WQUxVRV9cIiBfVEFCLUlOREVYXyAiOw0KICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtIC49ICJcblxuXHRcdFx0XHRcdDw/cGhwIGlmKGlzc2V0KFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9X19OQU1FXyddKSAmJiBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV9fTkFNRV8nXSA9PSBcIl9EWU5BTUlDX1ZBTFVFX1wiKSB7IGVjaG8gXCJjaGVja2VkPSdjaGVja2VkJ1wiOyB9ID8+IjsNCiAgICAgICAgICAgICAgICAkZmllbGRfaXRlbSAuPSAiXG5cblx0XHRcdFx0Lz5cbiI7IA0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgaWYgKGRlZmluZWQoJ01PQklMRV9NT0RFJykpIHsNCiAgICAgICAgICAgICRzdXJ2ZXktPndpZHRoID0gIjEwMCUiOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuXG48dGFibGUgY2xhc3M9XCJzdXJ2ZXlcIiBpZD1cInskZmllbGQtPm5hbWV9XCIgd2lkdGg9XCJ7JHN1cnZleS0+d2lkdGh9XCIgYm9yZGVyPVwieyRzdXJ2ZXktPmJvcmRlcn1cIiBjZWxscGFkZGluZz1cInskc3VydmV5LT5jZWxscGFkZGluZ31cIiBjZWxsc3BhY2luZz1cInskc3VydmV5LT5jZWxsc3BhY2luZ31cIiA+XG4iOw0KDQogICAgICAgIA0KICAgICAgICAkcmVzcG9uc2VzID0gZXhwbG9kZSgiXG4iLCAkc3VydmV5LT5yZXNwb25zZXMpOw0KDQoNCiAgICAgICAgDQogICAgICAgICRsYWJlbF9jbGFzc19jb2RlID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+c3VydmV5X3Byb3BlcnRpZXMtPmxhYmVsY2xhc3Njb2RlKSAmJiAkZmllbGQtPnN1cnZleV9wcm9wZXJ0aWVzLT5sYWJlbGNsYXNzY29kZSAhPSAiIikgew0KDQogICAgICAgICAgICAkbGFiZWxfY2xhc3NfY29kZSA9ICRmaWVsZC0+c3VydmV5X3Byb3BlcnRpZXMtPmxhYmVsY2xhc3Njb2RlOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmIChpc3NldCgkc3VydmV5LT5xdWVzdGlvbnNfcXVlcnkpICYmICRzdXJ2ZXktPnF1ZXN0aW9uc19xdWVyeSAhPSAiIikgew0KDQogICAgICAgICAgICAkcXVlc3Rpb25zID0gYXJyYXkoKTsNCiAgICAgICAgICAgICRjb2wyID0gYXJyYXkoKTsgDQoNCiAgICAgICAgICAgICRkYmRzbiA9ICIiOyANCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5kYmhvc3QpICYmIChzdHJpbmcpJGZpZWxkLT5kYmhvc3QgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGRiX3R5cGUgPSAoc3RyaW5nKSRmaWVsZC0+c291cmNldHlwZTsNCiAgICAgICAgICAgICAgICAkZGJfaG9zdCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPmRiaG9zdCwgOCk7DQogICAgICAgICAgICAgICAgJG15c3FsX3NvY2tldCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPmRic29ja2V0LCA4KTsNCiAgICAgICAgICAgICAgICAkbXlzcWxfcG9ydCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPmRicG9ydCwgOCk7DQogICAgICAgICAgICAgICAgJGRiZHNuID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRmaWVsZC0+ZGJkc24sIDgpOw0KICAgICAgICAgICAgICAgICRkYl91c2VyID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRmaWVsZC0+ZGJ1c2VyLCA4KTsNCiAgICAgICAgICAgICAgICAkZGJfcGFzcyA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPmRicHdkLCA4KTsNCiAgICAgICAgICAgICAgICAkZGJfY2F0YWxvZyA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPmRic2NoZW1hLCA4KTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAkZGJfdHlwZSAgPSBEQl9UWVBFOw0KICAgICAgICAgICAgICAgICRkYl9ob3N0ID0gREJfSE9TVDsNCiAgICAgICAgICAgICAgICAkZGJfY2F0YWxvZyA9IERCX0NBVEFMT0c7DQogICAgICAgICAgICAgICAgJGRiX3VzZXIgPSBEQl9VU0VSOw0KICAgICAgICAgICAgICAgICRkYl9wYXNzID0gREJfUEFTUzsNCiAgICAgICAgICAgICAgICAkbXlzcWxfc29ja2V0ID0gTVlTUUxfU09DS0VUOw0KICAgICAgICAgICAgICAgICRteXNxbF9wb3J0ID0gTVlTUUxfUE9SVDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJHF1ZXN0aW9uc19xdWVyeSA9IGlzc2V0KCRzdXJ2ZXktPnF1ZXN0aW9uc19xdWVyeSkgPyB1cmxkZWNvZGUoKHN0cmluZykkc3VydmV5LT5xdWVzdGlvbnNfcXVlcnkpIDogJyc7DQogICAgICAgICAgICAkZGJjb25uZWN0b3IgPSBpc3NldCgkZmllbGQtPmRiY29ubmVjdG9yKSA/IHVybGRlY29kZSgoc3RyaW5nKSRmaWVsZC0+ZGJjb25uZWN0b3IpIDogJyc7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJHRoaXMtPnVtLT5wdWxsQ3VzdG9tQ29ubmVjdG9yRmlsZSgoc3RyaW5nKSRmaWVsZC0+ZGJjb25uZWN0b3IpOw0KDQogICAgICAgICAgICBpZiAoJGRiY29ubmVjdG9yICE9ICIiKSB7DQogICAgICAgICAgICAgICAgaWYgKGZpbGVfZXhpc3RzKCIuLi8uLi9vdXRwdXQvZm9ybXMveyRqb2JuYW1lfS97JGRiY29ubmVjdG9yfSIpKSB7DQogICAgICAgICAgICAgICAgICAgIGluY2x1ZGUgIi4uLy4uL291dHB1dC9mb3Jtcy97JGpvYm5hbWV9L3skZGJjb25uZWN0b3J9IjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRwYXJhbXMgPSBhcnJheSgpOw0KDQogICAgICAgICAgICAkcmVzdWx0ID0gRGF0YWJhc2U6Om9uZW9mZl9mbGV4aWJsZV9xdWVyeSgNCiAgICAgICAgICAgICAgICAkZGJfdHlwZSwNCiAgICAgICAgICAgICAgICAkZGJfaG9zdCwNCiAgICAgICAgICAgICAgICAkZGJfY2F0YWxvZywNCiAgICAgICAgICAgICAgICAkZGJfdXNlciwNCiAgICAgICAgICAgICAgICAkZGJfcGFzcywNCiAgICAgICAgICAgICAgICAkbXlzcWxfc29ja2V0LA0KICAgICAgICAgICAgICAgICRteXNxbF9wb3J0LA0KICAgICAgICAgICAgICAgICRkYmRzbiwNCiAgICAgICAgICAgICAgICAkcXVlc3Rpb25zX3F1ZXJ5LA0KICAgICAgICAgICAgICAgICRwYXJhbXMsDQogICAgICAgICAgICAgICAgMCwgDQogICAgICAgICAgICAgICAgMCwgDQogICAgICAgICAgICAgICAgMQ0KICAgICAgICAgICAgKTsgDQoNCiAgICAgICAgICAgIGlmICgkcmVzdWx0ICE9IGZhbHNlKSB7DQoNCiAgICAgICAgICAgICAgICBmb3JlYWNoICgkcmVzdWx0WzFdIGFzICRpZHggPT4gJHEpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkcXVlc3Rpb25zW10gPSAkcVsnUXVlc3Rpb25UZXh0J107DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRxWydjb2wyJ10pKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkY29sMltdID0gJHFbJ2NvbDInXTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgJHF1ZXN0aW9ucyA9IGV4cGxvZGUoIlxuIiwgJHN1cnZleS0+cXVlc3Rpb25zKTsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQogICAgICAgICRlbGVtZW50IC49ICJcblx0PHRyIGNsYXNzPVwic3VydmV5LWhlYWRlci1yb3dcIj4iOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCAuPSAiXG5cdFx0PHRoIGNsYXNzPVwic3VydmV5LXF1ZXN0aW9uLW5vLWRhdGFcIiBzdHlsZT1cIndpZHRoOnskc3VydmV5LT5xdWVzdGlvbl9jb2x1bW5fd2lkdGh9cHg7IFwiIGFsaWduPVwibGVmdFwiIGlkPVwiXCI+PC90aD4iOw0KDQogICAgICAgIA0KICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCBjb3VudCgkcmVzcG9uc2VzKTsgJGkrKykgew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cdFx0PHRoIGNsYXNzPVwic3VydmV5LXJlc3BvbnNlLWhlYWRlclwiIHN0eWxlPVwiYmFja2dyb3VuZC1jb2xvcjp7JHN1cnZleS0+aGVhZGVyX2JhY2tncm91bmRfY29sb3J9OyBjb2xvcjp7JHN1cnZleS0+c3VydmV5X3Jlc3BvbnNlX2NvbG9yfTsgdmVydGljYWwtYWxpZ246IGJvdHRvbTsgZm9udC13ZWlnaHQ6eyRzdXJ2ZXktPnJlc3BvbnNlX2ZvbnRfd2VpZ2h0fTsgZm9udC1zaXplOnskc3VydmV5LT5yZXNwb25zZV9mb250X3NpemV9O1wiIGFsaWduPVwieyRzdXJ2ZXktPnJlc3BvbnNlX2FsaWdubWVudH1cIiA+IiAuICRyZXNwb25zZXNbJGldIC4gIjwvdGg+IjsNCiAgICAgICAgfQ0KDQogICAgICAgICRlbGVtZW50IC49ICJcblx0PC90cj5cbiI7DQoNCiAgICAgICAgDQogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8IGNvdW50KCRxdWVzdGlvbnMpOyAkaSsrKSB7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcblx0PHRyIGNsYXNzPVwic3VydmV5LXJlc3BvbnNlLXJvd1wiPlxuIjsNCg0KICAgICAgICAgICAgJHF1ZXN0aW9uX3N0eWxlID0gIiBmb250LXdlaWdodDp7JHN1cnZleS0+cXVlc3Rpb25fZm9udF93ZWlnaHR9OyBmb250LXNpemU6eyRzdXJ2ZXktPnF1ZXN0aW9uX2ZvbnRfc2l6ZX07IGNvbG9yOnskc3VydmV5LT5zdXJ2ZXlfcXVlc3Rpb25fY29sb3J9OyAiOw0KDQogICAgICAgICAgICBpZiAoKGludCkkc3VydmV5LT5hbHRlcm5hdGVfbGluZXMgPT0gMSAmJiAkaSAlIDIgIT0gMCkgew0KICAgICAgICAgICAgICAgICRxdWVzdGlvbl9zdHlsZSAuPSAiIGJhY2tncm91bmQtY29sb3I6IiAuICRzdXJ2ZXktPmFsdGVybmF0ZV9saW5lX2NvbG9yIC4gIjsgIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRxdWVzdGlvbl9udW1iZXIgPSAiIjsNCg0KICAgICAgICAgICAgaWYgKGlzc2V0KCRzdXJ2ZXktPm51bWJlcl9xdWVzdGlvbnMpICYmIChpbnQpJHN1cnZleS0+bnVtYmVyX3F1ZXN0aW9ucyA9PSAxKSB7DQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJHN1cnZleS0+bnVtYmVyX3F1ZXN0aW9uc190ZW1wbGF0ZSAhPSAiIikgew0KICAgICAgICAgICAgICAgICAgICAkcXVlc3Rpb25fbnVtYmVyID0gc3RyX3JlcGxhY2UoJ3tufScsICRpICsgMSwgKHN0cmluZykkc3VydmV5LT5udW1iZXJfcXVlc3Rpb25zX3RlbXBsYXRlKTsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAkcXVlc3Rpb25fbnVtYmVyID0gJGkgLiAnMScgLiAiLiZuYnNwOyI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRlbGVtZW50IC49ICJcblx0XHQ8dGQgY2xhc3M9XCJzdXJ2ZXktcXVlc3Rpb24tdGV4dFwiIHN0eWxlPVwieyRxdWVzdGlvbl9zdHlsZX1cIiBpZD1cInskZmllbGQtPm5hbWV9LXJvdy1sYWJlbC17JGl9XCIgY2xhc3M9XCJzdXJ2ZXktcm93LWxhYmVsXCIgYWxpZ249XCJ7JHN1cnZleS0+cXVlc3Rpb25fYWxpZ25tZW50fVwiPiI7DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49ICRxdWVzdGlvbl9udW1iZXIgLiAiXG5cdFx0XHQ8c3BhbiBjbGFzcz1cInN1cnZleS1xdWVzdGlvblwiPiIgLiAkcXVlc3Rpb25zWyRpXSAuICI8L3NwYW4+XG4iIC4gIlx0XHQ8L3RkPlxuIjsNCg0KICAgICAgICAgICAgZm9yICgkaiA9IDA7ICRqIDwgY291bnQoJHJlc3BvbnNlcyk7ICRqKyspIHsNCg0KICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSAkZmllbGRfaXRlbTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX05BTUVfJywgJGksICRmaWVsZF9pdGVtX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfSURfJywgJGkgLiAnXycgLiAkaiwgJGZpZWxkX2l0ZW1fY29weSk7DQoNCiAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19UUklHR0VSX1JPV18nLCAkaSwgJGZpZWxkX2l0ZW1fY29weSk7DQoNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRldmVudF90cmlnZ2VyX2NvZGVfY29weSA9IHN0cl9yZXBsYWNlKCdfSURfJywgJGksICRldmVudF90cmlnZ2VyX2NvZGUpOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGV2ZW50X3RyaWdnZXJfY29kZV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19UUklHR0VSX0lOREVYXycsICRpLCAkZXZlbnRfdHJpZ2dlcl9jb2RlX2NvcHkpOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRjb2wyKSAmJiBjb3VudCgkY29sMikgIT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAkZXZlbnRfdHJpZ2dlcl9jb2RlX2NvcHkgPSBzdHJfcmVwbGFjZSgnX1RSSUdHRVJfQ09MMl8nLCAkY29sMlskaV0sICRldmVudF90cmlnZ2VyX2NvZGVfY29weSk7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJGV2ZW50X3RyaWdnZXJfY29kZV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19UUklHR0VSX0NPTDJfJywgJycsICRldmVudF90cmlnZ2VyX2NvZGVfY29weSk7DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkZmllbGRfaXRlbV9jb3B5ID0gc3RyX3JlcGxhY2UoJ19EWU5BTUlDX1ZBTFVFXycsICRyZXNwb25zZXNbJGpdLCAkZmllbGRfaXRlbV9jb3B5KTsNCg0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKCR0YWJodG1sICE9ICcnKSB7DQogICAgICAgICAgICAgICAgICAgICRmaWVsZF9pdGVtX2NvcHkgPSBzdHJfcmVwbGFjZSgnX1RBQi1JTkRFWF8nLCAkdGFiaHRtbCwgJGZpZWxkX2l0ZW1fY29weSk7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkX2l0ZW1fY29weSA9IHN0cl9yZXBsYWNlKCdfVEFCLUlOREVYXycsICcnLCAkZmllbGRfaXRlbV9jb3B5KTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkY3VzdG9tX2xhYmVsX3ZhbHVlID0gJyc7DQoNCiAgICAgICAgICAgICAgICAkY3VzdG9tX2xhYmVsID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoJGxhYmVsX2NsYXNzX2NvZGUgIT0gJycpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRjb2wyX3ZhbHVlID0gJyc7DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRjb2wyKSAmJiBjb3VudCgkY29sMikgIT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgJGNvbDJfdmFsdWUgPSBhZGRzbGFzaGVzKCRjb2wyWyRpXSk7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAkcmVzID0gYWRkc2xhc2hlcygkcmVzcG9uc2VzWyRqXSk7DQoNCiAgICAgICAgICAgICAgICAgICAgJGN1c3RvbV9sYWJlbCA9ICI8P3BocCBcJGluZGV4ID0geyRpfTsgXCR2YWx1ZSA9ICd7JHJlc30nOyBcJGNvbDIgPSAneyRjb2wyX3ZhbHVlfSc7ID8+ICIgLiAkbGFiZWxfY2xhc3NfY29kZTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cdFx0PHRkIGNsYXNzPVwic3VydmV5LXF1ZXN0aW9uLXJlc3BvbnNlXCIgc3R5bGU9XCJ7JHF1ZXN0aW9uX3N0eWxlfSB0ZXh0LWFsaWduOnskc3VydmV5LT5yZXNwb25zZV9hbGlnbm1lbnR9XCI+IjsNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cblx0XHRcdDxsYWJlbCBjbGFzcz1cInskY3VzdG9tX2xhYmVsfVwiIHN0eWxlPVwidGV4dC1hbGlnbjp7JHN1cnZleS0+cmVzcG9uc2VfYWxpZ25tZW50fTtcIj4iOw0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICJcblxuXHRcdFx0XHQiIC4gJGZpZWxkX2l0ZW1fY29weTsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICI8c3BhbiBjbGFzcz1cInN1cnZleS1yZXNwb25zaXZlLXF1ZXN0aW9uLXRleHRcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj57JHJlc3BvbnNlc1skal19PC9zcGFuPiI7DQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXHRcdFx0PC9sYWJlbD5cbiI7DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cdFx0PC90ZD5cbiI7DQogICAgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXHQ8L3RyPlxuIjsNCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXHQ8IS0tIFN1cnZleSBSb3cgRW5kIC0tPlxuIjsNCg0KDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoJGV2ZW50X3RyaWdnZXJfaW5saW5lICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cdDx0ciBjbGFzcz1cInN1cnZleS10cmlnZ2VyLXJvd1wiIGlkPVwiZmJfZmxkLXskZmllbGQtPm5hbWV9X3skaX1fdHJpZ2dlclwiIHN0eWxlPVwiZGlzcGxheTpub25lO1wiPlxuIjsNCg0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkdHJpZ2dlcl9maWVsZCA9ICIiOw0KDQogICAgICAgICAgICAgICAgJGNvbHNwYW4gPSAkaiArIDE7DQoNCiAgICAgICAgICAgICAgICAkdHJpZ2dlcl9maWVsZCAuPSAiXG5cdFx0PHRkIGNsYXNzPVwic3VydmV5LXRyaWdnZXItdGRcIiBjb2xzcGFuPVwieyRjb2xzcGFufVwiIGFsaWduPVwicmlnaHRcIj4iOw0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkdHJpZ2dlcl9yZXF1aXJlZCA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRzdXJ2ZXktPnRyaWdnZXJmaWVsZHJlcXVpcmVkKSAmJiAoaW50KSRzdXJ2ZXktPnRyaWdnZXJmaWVsZHJlcXVpcmVkID09IDEpIHsNCiAgICAgICAgICAgICAgICAgICAgJHRyaWdnZXJfcmVxdWlyZWQgPSAiJm5ic3A7PHNwYW4gY2xhc3M9XCJzdXJ2ZXktdHJpZ2dlci1yZXF1aXJlZFwiPio8L3NwYW4+IjsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkdHJpZ2dlcl9maWVsZCAuPSAiXG5cblx0XHRcdDxsYWJlbCBjbGFzcz1cInN1cnZleS10cmlnZ2VyLWxhYmVsXCI+eyRzdXJ2ZXktPnRyaWdnZXJmaWVsZGxhYmVsfXskdHJpZ2dlcl9yZXF1aXJlZH0iOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHZhbHVlX2NvZGUgPSAiPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsneyRmaWVsZC0+bmFtZX1feyRpfV90cmlnZ2VyRmllbGQnXSkpIHsgZWNobyBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfV97JGl9X3RyaWdnZXJGaWVsZCddOyB9ID8+IjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgc3dpdGNoICgoc3RyaW5nKSRzdXJ2ZXktPnRyaWdnZXJmaWVsZHR5cGUpIHsNCg0KICAgICAgICAgICAgICAgICAgICBjYXNlICcwJzogDQogICAgICAgICAgICAgICAgICAgICAgICAkdHJpZ2dlcl9maWVsZCAuPSAiXG5cblx0XHRcdFx0PGlucHV0IGNsYXNzPVwic3VydmV5LXRyaWdnZXItdGV4dC1maWVsZFwiIHR5cGU9XCJ0ZXh0XCIgdmFsdWU9XCJ7JHZhbHVlX2NvZGV9XCIgbmFtZT1cInskZmllbGQtPm5hbWV9X3skaX1fdHJpZ2dlckZpZWxkXCIgaWQ9XCJ7JGZpZWxkLT5uYW1lfV97JGl9X3RyaWdnZXJGaWVsZFwiIGRpc2FibGVkIC8+XG4iOw0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnMSc6IA0KICAgICAgICAgICAgICAgICAgICAgICAgJHRyaWdnZXJfZmllbGQgLj0gIlxuXG5cdFx0XHRcdDx0ZXh0YXJlYSBjbGFzcz1cInN1cnZleS10cmlnZ2VyLXRleHQtYXJlYVwiIG5hbWU9XCJ7JGZpZWxkLT5uYW1lfV97JGl9X3RyaWdnZXJGaWVsZFwiIGlkPVwieyRmaWVsZC0+bmFtZX1feyRpfV90cmlnZ2VyRmllbGRcIiBkaXNhYmxlZD57JHZhbHVlX2NvZGV9PC90ZXh0YXJlYT5cbiI7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkdHJpZ2dlcl9maWVsZCAuPSAiXG5cdFx0XHQ8L2xhYmVsPiI7DQoNCg0KICAgICAgICAgICAgICAgICR0cmlnZ2VyX2ZpZWxkIC49ICJcblxuXHRcdDwvdGQ+XG4iOw0KDQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAkdHJpZ2dlcl9maWVsZDsNCg0KDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRlbGVtZW50IC49ICRldmVudF90cmlnZ2VyX2NvZGVfY29weTsNCg0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG5cdDwvdHI+XG4iOw0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuXHQ8IS0tIFRyaWdnZXIgUm93IEVuZCAtLT5cbiI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgLj0gIlxuPC90YWJsZT5cbiI7DQoNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICR0YWJsZW1vZGVzcGFuICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfSANCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9xdWVyeSgNCiAgICAgICAgJGpvYm5hbWUsDQogICAgICAgICRzb3VyY2V0eXBlLA0KICAgICAgICAkZGJob3N0LA0KICAgICAgICAkZGJzY2hlbWEsDQogICAgICAgICRtb25nb2NvbGxlY3Rpb24sDQogICAgICAgICRkYnVzZXIsDQogICAgICAgICRkYnB3ZCwNCiAgICAgICAgJGRic29ja2V0LA0KICAgICAgICAkZGJwb3J0LA0KICAgICAgICAkZGJkc24sDQogICAgICAgICRkYmNvbm5lY3RvciwNCiAgICAgICAgJHF1ZXJ5X3NxbCwNCiAgICAgICAgJHF1ZXJ5X3ZhcmlhYmxlcywNCiAgICAgICAgJHF1ZXJ5X215c3FsNGNvbXBhdCwNCiAgICAgICAgJHF1ZXJ5X2RlYnVnX2xldmVsLA0KICAgICAgICAkY29uZGl0aW9uLA0KICAgICAgICAkcXVlcnlfaW5zZXJ0aWQsDQoNCiAgICAgICAgJHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyLA0KDQogICAgICAgIA0KICAgICAgICAkcXVlcnlfZnVuY3Rpb25fY2FsbCwNCiAgICAgICAgJHF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0LA0KDQogICAgICAgIA0KICAgICAgICAkcXVlcnlfZnVuY3Rpb25fY3JlYXRlX2pzb24sDQogICAgICAgIA0KICAgICAgICAkcXVlcnlfY29kZSwNCiAgICAgICAgJHF1ZXJ5X2FwcGVuZF9sYWJlbCwNCiAgICAgICAgJHF1ZXJ5X2FwcGVuZF92YWx1ZSwNCiAgICAgICAgJHF1ZXJ5X2FwcGVuZF9wb3NpdGlvbiwNCiAgICAgICAgJHVzZV9waHBfdGFncywNCg0KICAgICAgICANCiAgICAgICAgJGNyZWF0ZV9lbGVtZW50cywNCg0KICAgICAgICANCiAgICAgICAgJGNsb3NlX2Nvbm5lY3Rpb24sDQoNCiAgICAgICAgDQogICAgICAgICRxdWVyeV9leHBvcnQsDQoNCiAgICAgICAgJGZpZWxkDQoNCiAgICApIHsNCg0KICAgICAgICBpZigkcXVlcnlfbXlzcWw0Y29tcGF0ID09IG51bGwpew0KICAgICAgICAgICAgJHF1ZXJ5X215c3FsNGNvbXBhdCA9IDA7DQogICAgICAgIH0NCg0KICAgICAgICBpZigkcXVlcnlfZGVidWdfbGV2ZWwgPT0gbnVsbCl7DQogICAgICAgICAgICAkcXVlcnlfZGVidWdfbGV2ZWwgPSAwOw0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHRoaXMtPnVtLT5wdWxsQ3VzdG9tQ29ubmVjdG9yRmlsZSgoc3RyaW5nKSRmaWVsZC0+ZGJjb25uZWN0b3IpOw0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRqb2JuYW1lID0gc3RyX2lyZXBsYWNlKCctJywgJ18nLCAkam9ibmFtZSk7DQoNCiAgICAgICAgDQogICAgICAgICRwaHBfc3RhcnRfdGFnID0gJyc7DQogICAgICAgICRwaHBfY2xvc2VfdGFnID0gJyc7DQoNCiAgICAgICAgaWYgKCR1c2VfcGhwX3RhZ3MgPT0gMSkgew0KICAgICAgICAgICAgJHBocF9zdGFydF90YWcgPSAnPD9waHAnOw0KICAgICAgICAgICAgJHBocF9jbG9zZV90YWcgPSAnPz4nOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25fY29kZV9zdGFydCA9ICcnOw0KICAgICAgICAkY29uZGl0aW9uX2NvZGVfZW5kID0gJyc7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkY29uZGl0aW9uID0gJHRoaXMtPnJlcGxhY2VfY29uZGl0aW9uX3ZhcnMoJGNvbmRpdGlvbik7DQoNCiAgICAgICAgaWYgKChzdHJpbmcpJGNvbmRpdGlvbiAhPSAnJykgew0KICAgICAgICAgICAgJGNvbmRpdGlvbl9jb2RlX3N0YXJ0ID0gIi8vIGNvbmRpdGlvbiBjb2RlIHN0YXJ0XHJcbiI7DQogICAgICAgICAgICAkY29uZGl0aW9uX2NvZGVfc3RhcnQgLj0gImlmKHskY29uZGl0aW9ufSkgeyAiOw0KICAgICAgICAgICAgJGNvbmRpdGlvbl9jb2RlX2VuZCA9ICd9IC8vIGNvbmRpdGlvbiBjb2RlIGVuZCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGRiX3R5cGUgPSAkdGhpcy0+dW0tPnRyYW5zbGF0ZVNvdXJjZVR5cGUoKGludCkkc291cmNldHlwZSk7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXIgPT0gJycpDQogICAgICAgICRxdWVyeV9yZXR1cm5fcmVzdWx0X3ZhciA9ICckZmJfcXVlcnknOw0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGRiaG9zdCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRiaG9zdCwgOCk7DQogICAgICAgICRkYnNvY2tldCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRic29ja2V0LCA4KTsNCiAgICAgICAgJGRicG9ydCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRicG9ydCwgOCk7DQogICAgICAgICRkYmRzbiA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRiZHNuLCA4KTsNCiAgICAgICAgJGRidXNlciA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRidXNlciwgOCk7DQogICAgICAgICRkYnB3ZCA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGRicHdkLCA4KTsNCiAgICAgICAgJGRic2NoZW1hID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkZGJzY2hlbWEsIDgpOw0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoJGRiX3R5cGUgPT0gJ21vbmdvZGInKSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJG12ID0gbmV3IHN0ZENsYXNzKCk7DQoNCiAgICAgICAgICAgICRtdi0+am9ibmFtZSA9IChzdHJpbmcpJGpvYm5hbWU7DQogICAgICAgICAgICAkbXYtPnNvdXJjZXR5cGUgPSAoc3RyaW5nKSRzb3VyY2V0eXBlOw0KICAgICAgICAgICAgJG12LT5kYmhvc3QgPSAoc3RyaW5nKSRkYmhvc3Q7DQogICAgICAgICAgICAkbXYtPmRic2NoZW1hID0gKHN0cmluZykkZGJzY2hlbWE7DQogICAgICAgICAgICAkbXYtPmNvbGxlY3Rpb24gPSAoc3RyaW5nKSRtb25nb2NvbGxlY3Rpb247DQogICAgICAgICAgICAkbXYtPmRidXNlciA9IChzdHJpbmcpJGRidXNlcjsNCiAgICAgICAgICAgICRtdi0+ZGJwd2QgPSAoc3RyaW5nKSRkYnB3ZDsNCiAgICAgICAgICAgICRtdi0+ZGJzb2NrZXQgPSAoc3RyaW5nKSRkYnNvY2tldDsNCiAgICAgICAgICAgICRtdi0+ZGJwb3J0ID0gKHN0cmluZykkZGJwb3J0Ow0KICAgICAgICAgICAgJG12LT5kYmRzbiA9IChzdHJpbmcpJGRiZHNuOw0KICAgICAgICAgICAgJG12LT5kYmNvbm5lY3RvciA9IChzdHJpbmcpJGRiY29ubmVjdG9yOw0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICRtdi0+bW9uZ29kYl9xdWVyeSA9IChzdHJpbmcpJHF1ZXJ5X3NxbDsgDQogICAgICAgICAgICAkbXYtPnF1ZXJ5X3ZhcmlhYmxlcyA9IChzdHJpbmcpJHF1ZXJ5X3ZhcmlhYmxlczsNCiAgICAgICAgICAgICRtdi0+cXVlcnlfbXlzcWw0Y29tcGF0ID0gKHN0cmluZykkcXVlcnlfc3FsOyANCiAgICAgICAgICAgICRtdi0+cXVlcnlfZGVidWdfbGV2ZWwgPSAoc3RyaW5nKSRxdWVyeV9kZWJ1Z19sZXZlbDsNCg0KICAgICAgICAgICAgaWYgKCFpc3NldCgkZmllbGQtPnF1ZXJ5X21vbmdvX3F1ZXJ5X21vZGUpKSB7DQogICAgICAgICAgICAgICAgJG12LT5xdWVyeV9tb25nb19xdWVyeV9tb2RlID0gIjAiOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkbXYtPnF1ZXJ5X21vbmdvX3F1ZXJ5X21vZGUgPSAkZmllbGQtPnF1ZXJ5X21vbmdvX3F1ZXJ5X21vZGU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRtdi0+Y29uZGl0aW9uID0gKHN0cmluZykkY29uZGl0aW9uOw0KICAgICAgICAgICAgJG12LT5xdWVyeV9pbnNlcnRpZCA9IChpbnQpJHF1ZXJ5X2luc2VydGlkOw0KDQogICAgICAgICAgICAkbXYtPnF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyID0gKHN0cmluZykkcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXI7DQoNCiAgICAgICAgICAgICRtdi0+cXVlcnlfZnVuY3Rpb25fY2FsbCA9IChzdHJpbmcpJHF1ZXJ5X2Z1bmN0aW9uX2NhbGw7DQogICAgICAgICAgICAkbXYtPnF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0ID0gKGludCkkcXVlcnlfZnVuY3Rpb25fcmV0dXJuc19yZXN1bHQ7DQoNCiAgICAgICAgICAgICRtdi0+cXVlcnlfY29kZSA9IChzdHJpbmcpJHF1ZXJ5X2NvZGU7DQogICAgICAgICAgICAkbXYtPnF1ZXJ5X2FwcGVuZF9sYWJlbCA9IChzdHJpbmcpJHF1ZXJ5X2FwcGVuZF9sYWJlbDsNCiAgICAgICAgICAgICRtdi0+cXVlcnlfYXBwZW5kX3ZhbHVlID0gKHN0cmluZykkcXVlcnlfYXBwZW5kX3ZhbHVlOw0KICAgICAgICAgICAgJG12LT5xdWVyeV9hcHBlbmRfcG9zaXRpb24gPSAoc3RyaW5nKSRxdWVyeV9hcHBlbmRfcG9zaXRpb247DQogICAgICAgICAgICAkbXYtPnVzZV9waHBfdGFncyA9IChpbnQpJHVzZV9waHBfdGFnczsNCg0KICAgICAgICAgICAgJG12LT5jcmVhdGVfZWxlbWVudHMgPSAkY3JlYXRlX2VsZW1lbnRzOw0KDQogICAgICAgICAgICByZXR1cm4gJHRoaXMtPmNyZWF0ZV9xdWVyeV9tb25nb2RiKCRtdik7IA0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQoNCiAgICAgICAgDQogICAgICAgICRzdHJzID0gZXhwbG9kZSgnLCcsICRxdWVyeV92YXJpYWJsZXMpOw0KDQogICAgICAgICRhcnJheV92YXJzID0gYXJyYXkoKTsgDQoNCiAgICAgICAgaWYgKCRxdWVyeV9teXNxbDRjb21wYXQgPT0gMSkgew0KICAgICAgICAgICAgJHBhcmFtcyA9ICcnOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHBhcmFtcyA9ICckcGFyYW1zID0gYXJyYXkoJzsNCiAgICAgICAgfQ0KICAgICAgICBmb3JlYWNoICgkc3RycyBhcyAka2V5ID0+ICRzKSB7DQogICAgICAgICAgICBpZiAoJGtleSAhPSAwKSB7DQogICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnLCAnOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAkcyA9IHRyaW0oJHMpOw0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJHMgPT0gJ1NFU1NJT05fSUQnIHx8ICRzID09ICdUSU1FU1RBTVAnIHx8ICRzID09ICdEQVRFVElNRScgfHwgJHMgPT0gJ05PVygpJyB8fCAkcyA9PSAnQ1VSUkVOVF9USU1FU1RBTVAnIHx8ICRzID09ICdSRU1PVEVfQUREUicgfHwgJHMgPT0gJ3Zpc2l0b3JfaXAnKSB7DQogICAgICAgICAgICAgICAgc3dpdGNoICgkcykgew0KICAgICAgICAgICAgICAgICAgICBjYXNlICdTRVNTSU9OX0lEJzoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkcXVlcnlfbXlzcWw0Y29tcGF0KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnJHNlc3Npb25faWQnOw0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFyYW1zIC49ICckc2Vzc2lvbl9pZCc7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnVElNRVNUQU1QJzoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkcXVlcnlfbXlzcWw0Y29tcGF0KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnJHRpbWVzdGFtcCc7DQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJyR0aW1lc3RhbXAnOw0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgJ0RBVEVUSU1FJzoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkcXVlcnlfbXlzcWw0Y29tcGF0KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnJGRhdGV0aW1lJzsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnJGRhdGV0aW1lJzsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBjYXNlICdSRU1PVEVfQUREUic6DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHF1ZXJ5X215c3FsNGNvbXBhdCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJyRyZW1vdGVfaXAnOw0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFyYW1zIC49ICckcmVtb3RlX2lwJzsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICd2aXNpdG9yX2lwJzoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkcXVlcnlfbXlzcWw0Y29tcGF0KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAnJHJlbW90ZV9pcCc7DQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJyRyZW1vdGVfaXAnOw0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHF1ZXJ5X215c3FsNGNvbXBhdCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJyRkYXRldGltZSc7DQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJyRkYXRldGltZSc7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRhcnJheV92YXJzW10gPSAiJyRzJyI7IA0KICAgICAgICAgICAgICAgIGlmICgkcXVlcnlfbXlzcWw0Y29tcGF0ID09IDEpIHsNCiAgICAgICAgICAgICAgICAgICAgaXNfbnVtZXJpYygkcyk7IA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAibXlzcWxfcmVhbF9lc2NhcGVfc3RyaW5nKFwkX1NFU1NJT05bJ3FzJ11bXCJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119XCJdWyd7JHN9J10sIFwkbGluaykiOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIGlmIChwcmVnX21hdGNoKCcvKF58Lnxccnxcbik/KFBIUFx7KC4qPylcfSkvJywgJHMsICRwaHBfdmFyX21hdGNoKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmFtcyAuPSAiaXNzZXQoXCR7JHBocF92YXJfbWF0Y2hbM119KSA/IFwkeyRwaHBfdmFyX21hdGNoWzNdfSA6ICcnIjsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZWdfbWF0Y2goJy8oXnwufFxyfFxuKShcXlx7KC4qPylcfSkvJywgJHMsICRwaHBfc2Vzc2lvbl9tYXRjaCkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gImlzc2V0KFwkX1NFU1NJT05bJ3skcGhwX3Nlc3Npb25fbWF0Y2hbM119J10pID8gXCRfU0VTU0lPTlsneyRwaHBfc2Vzc2lvbl9tYXRjaFszXX0nXSA6ICcnIjsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmVnX21hdGNoKCcvKF58LnxccnxcbikoXCNceyguKj8pXH0pLycsICRzLCAkcGhwX2dldF9tYXRjaCkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gImlzc2V0KFwkX0dFVFsneyRwaHBfZ2V0X21hdGNoWzNdfSddKSA/IFwkX0dFVFsneyRwaHBfZ2V0X21hdGNoWzNdfSddIDogJyciOw0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZWdfbWF0Y2goJy8oXnwufFxyfFxuKShcKlx7KC4qPylcfSkvJywgJHMsICRwaHBfcG9zdF9tYXRjaCkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gImlzc2V0KFwkX1BPU1RbJ3skcGhwX3Bvc3RfbWF0Y2hbM119J10pID8gXCRfUE9TVFsneyRwaHBfcG9zdF9tYXRjaFszXX0nXSA6ICcnIjsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmVnX21hdGNoKCcvKF58LnxccnxcbikoQFx7KC4qPylcfSkvJywgJHMsICRwaHBfZmllbGRfbWF0Y2gpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkcGFyYW1zIC49ICJpc3NldChcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRwaHBfZmllbGRfbWF0Y2hbM119J10pID8gXCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3skcGhwX2ZpZWxkX21hdGNoWzNdfSddIDogJyciOw0KICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICRwYXJhbXMgLj0gJHM7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkcGFyYW1zID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRwYXJhbXMsIDQuMSk7IA0KDQogICAgICAgIA0KICAgICAgICAkcXVlcnlfY29kZSA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkcXVlcnlfY29kZSwgMCk7DQoNCiAgICAgICAgDQogICAgICAgIGZvcmVhY2ggKCRhcnJheV92YXJzIGFzICRpZHggPT4gJGR5bikgew0KICAgICAgICAgICAgaWYgKHByZWdfbWF0Y2goJy8oXnwufFxyfFxuKT8oUEhQXHsoLio/KVx9KS8nLCAkZHluLCAkcGhwX3Zhcl9tYXRjaCkpIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1skaWR4XSA9ICInJHBocF92YXJfbWF0Y2hbM10nIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZHluX3ZhcnMgPSBpbXBsb2RlKCcsJywgJGFycmF5X3ZhcnMpOyANCg0KICAgICAgICBpZiAoJHF1ZXJ5X215c3FsNGNvbXBhdCA9PSAxKSB7DQogICAgICAgICAgICANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRwYXJhbXMgLj0gJyk7JzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRxdWVyeV9pbnNlcnRpZCkpIHsNCiAgICAgICAgICAgICRxdWVyeV9pbnNlcnRpZCA9IDA7DQogICAgICAgIH0gDQogICAgICAgIGlmICgoaW50KSRxdWVyeV9pbnNlcnRpZCAhPSAxKSB7DQogICAgICAgICAgICAkcXVlcnlfaW5zZXJ0aWQgPSAwOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkY2xvc2VfY29ubmVjdGlvbikpIHsNCiAgICAgICAgICAgICRjbG9zZV9jb25uZWN0aW9uID0gJzAnOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRjbG9zZV9jb25uZWN0aW9uID09ICIxIikgew0KICAgICAgICAgICAgJGNsb3NlX2Nvbm5lY3Rpb24gPSAidHJ1ZSI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkY2xvc2VfY29ubmVjdGlvbiA9ICJmYWxzZSI7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIGlmIChjb3VudCgkc3RycykgPT0gMSAmJiAkc3Ryc1swXSA9PSAiIiAmJiAkcXVlcnlfbXlzcWw0Y29tcGF0ID09IDApIHsNCiAgICAgICAgICAgICRwYXJhbXMgPSAiXCRwYXJhbXMgPSBhcnJheSgpOyI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKGNvdW50KCRzdHJzKSA9PSAxICYmICRzdHJzWzBdID09ICIiICYmICRxdWVyeV9teXNxbDRjb21wYXQgPT0gMSkgew0KICAgICAgICAgICAgJHBhcmFtcyA9ICInJyI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkanNvbl9wcm9jZXNzaW5nX2NvZGUgPSAiIjsNCiAgICAgICAgDQogICAgICAgIGlmKGlzc2V0KCRxdWVyeV9mdW5jdGlvbl9jcmVhdGVfanNvbikgJiYgJHF1ZXJ5X2Z1bmN0aW9uX2NyZWF0ZV9qc29uID09IDEpew0KICAgICAgICAgICAgDQogICAgICAgICAgICAkanNvbl9wcm9jZXNzaW5nX2NvZGUgPSA8PDxFT0YNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgLy8gQ29udmVydCBEYXRhYmFzZSBSZXN1bHQgdG8gSmF2YVNjcmlwdCBPYmplY3QuDQoNCiAgICAgICAgICAgIFwkbmwgPSAiXHJcbiI7DQogICAgICAgICAgICANCiAgICAgICAgICAgIGVjaG8gJzxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4nOyBlY2hvIFwkbmw7DQogICAgICAgICAgICANCiAgICAgICAgICAgIGVjaG8gJ3ZhciBfZGF0YSA9IFwnJzsgZWNobyBqc29uX2VuY29kZSh7JHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyfSk7IGVjaG8gJ1wnOyc7IGVjaG8gXCRubDsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgZWNobyAndmFyIHExID0gZXZhbChfZGF0YSk7JzsgZWNobyBcJG5sOw0KICAgICAgICAgICAgDQogICAgICAgICAgICBlY2hvICc8L3NjcmlwdD4nOw0KRU9GOw0KDQogICAgICAgIH0gDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGNhbGxfY29kZSA9IDw8PEVPRg0KDQpcJGFtYmlndW91c19jb2x1bW5fbmFtZV93YXJuaW5nID0gZmFsc2U7DQoNClwkY2xvc2VfY29ubmVjdGlvbiA9IHskY2xvc2VfY29ubmVjdGlvbn07DQoNCi8vIFNldCBPcHRpb25hbCBNeVNRTCBTU0wgUHJvcGVydGllcy4NCg0KXCRkYmgtPnNldE15U1FMU1NMUHJvcGVydGllcyhcJGRiX3NzbF9rZXksIFwkZGJfc3NsX2NlcnRpZmljYXRlLCBcJGRiX3NzbF9jYV9jZXJ0LCBcJGRiX3NzbF92ZXJpZnlfY2VydCwgXCRkYl9zc2xfY2lwaGVyKTsNCgkNCi8vIERlZmF1bHQgU1FMIENhbGwuDQoNCnskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9ID0gXCRkYmgtPnBkb19wcm9jZWR1cmVfcGFyYW1zKFwkZGVidWcsIA0KCQkJCQkJCQkJCQkJCQkgXCRzcWxfeyRqb2JuYW1lfSwNCgkJCQkJCQkJCQkJCQkJIFwkZGJfaG9zdCwNCgkJCQkJCQkJCQkJCQkJIFwkZGJfdHlwZSwNCgkJCQkJCQkJCQkJCQkJIFwkbXlzcWxfc29ja2V0LA0KCQkJCQkJCQkJCQkJCQkgXCRteXNxbF9wb3J0LA0KCQkJCQkJCQkJCQkJCQkgXCRkYmRzbiwNCgkJCQkJCQkJCQkJCQkJIFwkZGJfdXNlciwNCgkJCQkJCQkJCQkJCQkJIFwkZGJfcGFzcywNCgkJCQkJCQkJCQkJCQkJIFwkZGJfY2F0YWxvZywNCgkJCQkJCQkJCQkJCQkJIFwkcGFyYW1zLA0KCQkJCQkJCQkJCQkJCQkgMCwgLy8gcmV0dXJuX3RydWUNCgkJCQkJCQkJCQkJCQkJIHskcXVlcnlfaW5zZXJ0aWR9LCAvLyByZXR1cm5fbGFzdF9pbnNlcnRfaWQsDQoJCQkJCQkJCQkJCQkJCSA0LCAvLyBmZXRjaF9tb2RlLA0KCQkJCQkJCQkJCQkJCQkgMCwgLy8gcGFzc19udWxscywNCgkJCQkJCQkJCQkJCQkJIGZhbHNlLCAvLyBidWlsZGVyX3F1ZXJ5LA0KCQkJCQkJCQkJCQkJCQkgXCRhbWJpZ3VvdXNfY29sdW1uX25hbWVfd2FybmluZywNCgkJCQkJCQkJCQkJCQkJIDAsIC8vIHF1ZXJ5X21vbmdvX3F1ZXJ5X21vZGUsDQoJCQkJCQkJCQkJCQkJCSAnJywgLy8gbW9uZ29fY29sbGVjdGlvbg0KCQkJCQkJCQkJCQkJCQkgXCRjbG9zZV9jb25uZWN0aW9uKTsNCkVPRjsNCg0KICAgICAgICAkZGVidWdfY29kZSA9IDw8PEVPRg0KaWYoXCRkZWJ1ZyA9PSAyKSB7IA0KDQoJaWYoXCRhbWJpZ3VvdXNfY29sdW1uX25hbWVfd2FybmluZyA9PSB0cnVlKXsNCgkJZWNobyAnPHN0cm9uZz5DYXV0aW9uOjwvc3Ryb25nPiBZb3VyIFF1ZXJ5IFJlc3VsdCBDb250YWlucyBBbWJpZ3VvdXMgQ29sdW1ucywgTW9zdCBMaWtlbHkgQ2F1c2VkIEJ5IFVzaW5nIFNFTEVDVCAqIEFuZCBBIEpPSU4uPGJyPic7DQoJCWVjaG8gJ1dlIEhhdmUgVGh1cyBJbmRleGVkIFRoZXNlIENvbHVtbnMgRm9yIFlvdSBUbyBDcmVhdGUgVW5pcXVlIENvbHVtbiBOYW1lcyw8YnI+JzsNCgkJZWNobyAnQnV0IEl0XCdzIE11Y2ggQmV0dGVyIFRvIFNpbXBseSBSZXdyaXRlIFRoZSBRdWVyeSBUbyAqTk9UKiBVc2UgU0VMRUNUICogV2hlbiBVc2luZyBBIEpPSU4uJzsNCgl9DQoJDQoJDQoJaWYoJHF1ZXJ5X2luc2VydGlkID09IDEpIHsNCgkNCgkJZWNobyAnPHByZT57JHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyfSBsYXN0SW5zZXJ0SUQgPSAnOyBlY2hvICRxdWVyeV9yZXR1cm5fcmVzdWx0X3ZhcjsgZWNobyAnPC9wcmU+JzsNCgkNCgl9IGVsc2Ugew0KCQ0KCQllY2hvICc8cHJlPnskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9ID0gJzsgcHJpbnRfcigkcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXIpOyBlY2hvICc8L3ByZT4nOw0KCQkJCQ0KCX0NCg0KfQ0KDQp7JGpzb25fcHJvY2Vzc2luZ19jb2RlfQ0KDQpFT0Y7DQoNCg0KDQoNCiAgICAgICAgDQogICAgICAgICRteXNxbDQgPSA8PDxFT1QNCgkvLyBteXNxbCA0IGNvbXBhdGFiaWxpdHkgbW9kZQ0KCVwkbGluayA9IG15c3FsX2Nvbm5lY3QoXCRkYl9ob3N0LCBcJGRiX3VzZXIsIFwkZGJfcGFzcykNCiAgICAJb3IgZGllKCdDb3VsZCBub3QgY29ubmVjdDogJyAuIG15c3FsX2Vycm9yKCkpOw0KCWlmKFwkZGVidWcpIHsgZWNobyAnQ29ubmVjdGVkIHN1Y2Nlc3NmdWxseSc7IH0NCglteXNxbF9zZWxlY3RfZGIoXCRkYl9jYXRhbG9nKSBvciBkaWUoJ0NvdWxkIG5vdCBzZWxlY3QgZGF0YWJhc2UnKTsNCgkNCgkvLyBQZXJmb3JtaW5nIFNRTCBxdWVyeQ0KCVwkcXVlcnkgPSBzcHJpbnRmKCJ7JHF1ZXJ5X3NxbH0iLCAkcGFyYW1zKTsNCglcJHJlc3VsdCA9IG15c3FsX3F1ZXJ5KFwkcXVlcnkpIG9yIGRpZSgnUXVlcnkgZmFpbGVkOiAnIC4gbXlzcWxfZXJyb3IoKSk7DQoJeyRxdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn0gPSBteXNxbF9mZXRjaF9hcnJheShcJHJlc3VsdCwgTVlTUUxfQk9USCk7DQpFT1Q7DQoNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGV4cG9ydF9sb2NhdGlvbiA9ICIiOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPnF1ZXJ5X2V4cG9ydF9maWxlbmFtZSkgJiYgJGZpZWxkLT5xdWVyeV9leHBvcnRfZmlsZW5hbWUgIT0gIiIpIHsNCg0KICAgICAgICAgICAgJGV4cG9ydF9sb2NhdGlvbiA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoKHN0cmluZykkZmllbGQtPnF1ZXJ5X2V4cG9ydF9maWxlbmFtZSwgMSk7DQogICAgICAgIH0NCg0KDQoNCiAgICAgICAgJGV4cG9ydF9jb2RlID0gIiI7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cXVlcnlfZXhwb3J0KSAmJiAkZmllbGQtPnF1ZXJ5X2V4cG9ydCAhPSAiMCIpIHsNCg0KICAgICAgICAgICAgJGV4cG9ydF9jb2RlID0gPDw8RU9GDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgLy8gUmVtb3ZlIG51bWVyaWMga2V5cyBmcm9tIHJlc3VsdCBhcnJheQ0KICAgICAgICAgICAgZm9yZWFjaCAoeyRxdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn0gYXMgXCRrZXlfaSA9PiBcJHZhbHVlX2kpIHsNCiAgICAgICAgICAgICAgICBmb3JlYWNoIChcJHZhbHVlX2kgYXMgXCRrZXlfaiA9PiBcJHZhbHVlX2kpIHsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgaWYoaXNfaW50KFwka2V5X2opKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICB1bnNldCh7JHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyfVtcJGtleV9pXVtcJGtleV9qXSk7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAvLyBEb3dubG9hZCBQcm9tcHQgTWV0aG9kLg0KICAgICAgICAgICAgaWYoeyRmaWVsZC0+cXVlcnlfZXhwb3J0fSA9PSAxKSB7DQogICAgICAgICAgICANCgkgICAgICAgICAgICBcJGZpbGVuYW1lID0gInskam9ibmFtZX1fIiAuIGRhdGUoJ1ltZCcpIC4gIi5jc3YiOyANCgkgICAgICAgICAgICBoZWFkZXIoIkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiXCRmaWxlbmFtZVwiIik7IA0KCSAgICAgICAgICAgIGhlYWRlcigiQ29udGVudC1UeXBlOiB0ZXh0L2NzdjsiKTsNCgkgICAgICAgICAgICANCgkgICAgICAgICAgICAvLyBCdWlsZCA5MTMgLSBQcm9jZXNzIEFueSBDb2RlIEFmdGVyIFF1ZXJ5IExvZ2ljLg0KCSAgICAgICAgICAgIHskcXVlcnlfY29kZX0NCgkNCgkgICAgICAgICAgICBcJG91dCA9IGZvcGVuKCJwaHA6Ly9vdXRwdXQiLCAndycpOw0KCQ0KCSAgICAgICAgICAgIFwkZmxhZyA9IGZhbHNlOw0KCSAgICAgICAgICAgIA0KCSAgICAgICAgICAgIGZvcmVhY2ggKHskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9IGFzIFwkcm93KSB7DQoJICAgICAgICAgICAgICAgIGlmICghXCRmbGFnKSB7DQoJICAgICAgICAgICAgICAgICAgICAvLyBkaXNwbGF5IGZpZWxkL2NvbHVtbiBuYW1lcyBhcyBmaXJzdCByb3cgDQoJICAgICAgICAgICAgICAgICAgICBmcHV0Y3N2KFwkb3V0LCBhcnJheV9rZXlzKFwkcm93KSwgJywnLCAnIicpOw0KCSAgICAgICAgICAgICAgICAgICAgXCRmbGFnID0gdHJ1ZTsNCgkgICAgICAgICAgICAgICAgfQ0KCSAgICAgICAgICAgIAkJDQoJICAgICAgICAgICAgCS8vIENvbnZlcnQgTVNTUUwgRGF0ZSBvYmplY3RzIGludG8gc3RyaW5ncy4NCgkgICAgICAgICAgICAJZm9yZWFjaChcJHJvdyBhcyBcJGtleSA9PiBcJHZhbCl7DQoJCQkJCQlpZihpc19vYmplY3QoXCR2YWwpKXsNCgkgICAgICAgICAgICAJCQlpZihpc3NldChcJHZhbC0+ZGF0ZSkpew0KCSAgICAgICAgICAgIAkJCQlcJHJvd1sie1wka2V5fSJdID0gXCR2YWwtPmRhdGU7DQoJICAgICAgICAgICAgCQkJfSBlbHNlIHsNCgkgICAgICAgICAgICAJCQkJXCRyb3dbIntcJGtleX0iXSA9ICcnOw0KCSAgICAgICAgICAgIAkJCX0NCgkJCQkJCQkNCgkJCQkJCX0NCgkJCQkJfQ0KCQkJCQkJCQkJDQoJICAgICAgICAgICAgICAgIGZwdXRjc3YoXCRvdXQsIGFycmF5X3ZhbHVlcyhcJHJvdyksICcsJywgJyInKTsNCgkgICAgICAgICAgICB9DQoJDQoJICAgICAgICAgICAgZmNsb3NlKFwkb3V0KTsNCgkgICAgICAgICAgICBleGl0Ow0KICAgICAgICAgICAgDQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIC8vIFNhdmUgRmlsZSBNZXRob2QuDQoJICAgICAgICBpZih7JGZpZWxkLT5xdWVyeV9leHBvcnR9ID09IDIpIHsNCgkgICAgICAgIA0KCSAgICAgICAgCVwkZGVidWdfZmlsZV9zYXZlID0gZmFsc2U7DQoJICAgICAgICAJCQ0KCSAgICAgICAgCS8vIEJ1aWxkIDkxMyAtIFByb2Nlc3MgQW55IENvZGUgQWZ0ZXIgUXVlcnkgTG9naWMuDQoJICAgICAgICAgICAgeyRxdWVyeV9jb2RlfQ0KCSAgICAgICAgICAgIA0KCSAgICAgICAgICAgIFwkZXhwb3J0X2xvY2F0aW9uID0gInskZXhwb3J0X2xvY2F0aW9ufSI7DQoJICAgICAgICAgICAgDQoJICAgICAgICAgICAgaWYoXCRkZWJ1Z19maWxlX3NhdmUpIHsNCgkgICAgICAgICAgICAJZWNobyAiPHByZT5SQVcgRVhQT1JUIExPQ0FUSU9OOiB7XCRleHBvcnRfbG9jYXRpb259PC9wcmU+IjsNCgkgICAgICAgICAgICB9DQoJICAgICAgICAgICAgCQkNCgkgICAgICAgICAgICAvLyBHZXQgSW5mbyBBYm91dCBGaWxlIE5hbWluZy4NCgkgICAgICAgICAgICBcJHBhdGggPSBwYXRoaW5mbyhcJGV4cG9ydF9sb2NhdGlvbik7DQoJICAgICAgICAgICAgDQoJICAgICAgICAgICAgaWYoXCRkZWJ1Z19maWxlX3NhdmUpIHsNCgkgICAgICAgICAgICAJZWNobyAiPHByZT5DU1YgRVhQT1JUIERFQlVHOiBQQVRIIEluZm86PC9wcmU+IjsNCgkgICAgICAgICAgICAJZWNobyAnPHByZT4nOyBwcmludF9yKFwkcGF0aCk7IGVjaG8gJzwvcHJlPic7DQoJICAgICAgICAgICAgfQ0KDQoJICAgICAgICAgICAgLy8gTm8gRGlyZWN0b3J5IEdpdmVuLCBDcmVhdGUgSW4gQ3VycmVudCBEaXJlY3RvcnkuDQoJICAgICAgICAgICAgaWYoIWlzc2V0KFwkcGF0aFsnZGlybmFtZSddKSB8fCB0cmltKFwkcGF0aFsnZGlybmFtZSddKSA9PSAiIiB8fCBcJHBhdGhbJ2Rpcm5hbWUnXSA9PSAiLiIpIHsNCgkgICAgICAgICAgICAJXCRleHBvcnRfbG9jYXRpb24gPSAiLi8iIC4gXCRwYXRoWydiYXNlbmFtZSddOwkNCgkgICAgICAgICAgICB9DQoJICAgICAgICAgICAgCQkNCgkgICAgICAgICAgICAvLyBObyBGaWxlbmFtZSBHaXZlbiwgQ3JlYXRlIERlZmF1bHQgVG1wIEZpbGUuDQoJICAgICAgICAgICAgaWYodHJpbShcJHBhdGhbJ2ZpbGVuYW1lJ10pID09ICIiIHx8IFwkcGF0aFsnZmlsZW5hbWUnXSA9PSAiLiIpIHsNCgkgICAgICAgICAgICAJXCRleHBvcnRfbG9jYXRpb24gPSB0ZW1wbmFtKFwkZXhwb3J0X2xvY2F0aW9uLCAiUXVlcnktIik7CQ0KCSAgICAgICAgICAgIH0NCgkgICAgICAgICAgICANCgkgICAgICAgICAgICBpZihcJGRlYnVnX2ZpbGVfc2F2ZSkgew0KCSAgICAgICAgICAgIAllY2hvICI8cHJlPkNTViBFWFBPUlQgREVCVUc6IEZpbmFsIGV4cG9ydF9sb2NhdGlvbjoge1wkZXhwb3J0X2xvY2F0aW9ufTwvcHJlPiI7DQoJICAgICAgICAgICAgfQ0KCSAgICAgICAgICAgIAkJDQoJICAgICAgICAgICAgLy8gQ3JlYXRlIEZpbGUgSWYgTm90IEFscmVhZHkgQ3JlYXRlZCBWaWEgdGVtcG5hbSgpLg0KCQkJCWlmKCFmaWxlX2V4aXN0cyhcJGV4cG9ydF9sb2NhdGlvbikpIHsNCgkJCQkJZmlsZV9wdXRfY29udGVudHMoXCRleHBvcnRfbG9jYXRpb24sICIiKTsNCgkJCQl9DQoJICAgICAgICAgICAgDQogICAgICAgICAgICAJLy8gQ3JlYXRlIGZpbGUgaWYgbmVlZGVkLg0KICAgICAgICAgICAgCWlmKGZpbGVzaXplKFwkZXhwb3J0X2xvY2F0aW9uKSA9PSAwKSB7DQogICAgICAgICAgICAJDQoJICAgICAgICAgICAgCWlmKFwkZGVidWdfZmlsZV9zYXZlKSB7DQoJCSAgICAgICAgICAgIAllY2hvICI8cHJlPkNTViBFWFBPUlQgREVCVUc6IE5ldyBFeHBvcnQgRGV0ZWN0ZWQuPC9wcmU+IjsNCgkJICAgICAgICAgICAgfQ0KCSAgICAgICAgICAgIAkJDQogICAgICAgICAgICAJCWZpbGVfcHV0X2NvbnRlbnRzKFwkZXhwb3J0X2xvY2F0aW9uLCAiIik7DQoNCgkgICAgICAgICAgICAJXCRoYW5kbGUgPSBmb3BlbihcJGV4cG9ydF9sb2NhdGlvbiwgInIrIik7DQoJICAgICAgICAgICAgCQkNCgkgICAgICAgICAgICAJXCRmbGFnID0gZmFsc2U7DQoJICAgICAgICAgICAgDQoJCSAgICAgICAgICAgIGZvcmVhY2ggKHskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9IGFzIFwkcm93KSB7DQoJCSAgICAgICAgICAgICAgICBpZiAoIVwkZmxhZykgew0KCQkgICAgICAgICAgICAgICAgICAgIC8vIGRpc3BsYXkgZmllbGQvY29sdW1uIG5hbWVzIGFzIGZpcnN0IHJvdyANCgkJICAgICAgICAgICAgICAgICAgICBmcHV0Y3N2KFwkaGFuZGxlLCBhcnJheV9rZXlzKFwkcm93KSwgJywnLCAnIicpOw0KCQkgICAgICAgICAgICAgICAgICAgIFwkZmxhZyA9IHRydWU7DQoJCSAgICAgICAgICAgICAgICB9DQoJCSAgICAgICAgICAgIAkJDQoJCSAgICAgICAgICAgIAkvLyBDb252ZXJ0IE1TU1FMIERhdGUgb2JqZWN0cyBpbnRvIHN0cmluZ3MuDQoJCSAgICAgICAgICAgIAlmb3JlYWNoKFwkcm93IGFzIFwka2V5ID0+IFwkdmFsKXsNCgkJCQkJCQlpZihpc19vYmplY3QoXCR2YWwpKXsNCgkJICAgICAgICAgICAgCQkJaWYoaXNzZXQoXCR2YWwtPmRhdGUpKXsNCgkJICAgICAgICAgICAgCQkJCVwkcm93WyJ7XCRrZXl9Il0gPSBcJHZhbC0+ZGF0ZTsNCgkJICAgICAgICAgICAgCQkJfSBlbHNlIHsNCgkJICAgICAgICAgICAgCQkJCVwkcm93WyJ7XCRrZXl9Il0gPSAnJzsNCgkJICAgICAgICAgICAgCQkJfQ0KCQkJCQkJCQkNCgkJCQkJCQl9DQoJCQkJCQl9DQoJCQkJCQkJCQkJDQoJCSAgICAgICAgICAgICAgICBmcHV0Y3N2KFwkaGFuZGxlLCBhcnJheV92YWx1ZXMoXCRyb3cpLCAnLCcsICciJyk7DQoJCSAgICAgICAgICAgIH0NCgkNCgkJICAgICAgICAgICAgZmNsb3NlKFwkaGFuZGxlKTsNCgkgICAgICAgICAgICAJCQ0KICAgICAgICAgICAgCX0gZWxzZSB7DQoNCgkgICAgICAgICAgICAJLy8gRmlsZSBBbHJlYWR5IEV4aXN0cyAtIEFwcGVuZCBEYXRhLg0KCSAgICAgICAgICAgIAkNCgkgICAgICAgICAgICAJZWNobyAiPHByZT5DU1YgRVhQT1JUIERFQlVHOiBFeGlzdGluZyBFeHBvcnQgRGV0ZWN0ZWQuPC9wcmU+IjsNCgkgICAgICAgICAgICAJCQ0KCSAgICAgICAgICAgIAlcJGhhbmRsZSA9IGZvcGVuKFwkZXhwb3J0X2xvY2F0aW9uLCAiYSsiKTsNCgkJICAgICAgICAgICAgCQkNCgkJICAgICAgICAgICAgZm9yZWFjaCAoeyRxdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn0gYXMgXCRyb3cpIHsNCgkJICAgICAgICAgICAgCQkNCgkJICAgICAgICAgICAgCS8vIENvbnZlcnQgTVNTUUwgRGF0ZSBvYmplY3RzIGludG8gc3RyaW5ncy4NCgkJICAgICAgICAgICAgCWZvcmVhY2goXCRyb3cgYXMgXCRrZXkgPT4gXCR2YWwpew0KCQkJCQkJCWlmKGlzX29iamVjdChcJHZhbCkpew0KCQkgICAgICAgICAgICAJCQlpZihpc3NldChcJHZhbC0+ZGF0ZSkpew0KCQkgICAgICAgICAgICAJCQkJXCRyb3dbIntcJGtleX0iXSA9IFwkdmFsLT5kYXRlOw0KCQkgICAgICAgICAgICAJCQl9IGVsc2Ugew0KCQkgICAgICAgICAgICAJCQkJXCRyb3dbIntcJGtleX0iXSA9ICcnOw0KCQkgICAgICAgICAgICAJCQl9DQoJCQkJCQkJCQ0KCQkJCQkJCX0NCgkJCQkJCX0NCgkJCQkJCQkJCQkNCgkJICAgICAgICAgICAgICAgIGZwdXRjc3YoXCRoYW5kbGUsIGFycmF5X3ZhbHVlcyhcJHJvdyksICcsJywgJyInKTsNCgkJICAgICAgICAgICAgfQ0KCQ0KCQkgICAgICAgICAgICBmY2xvc2UoXCRoYW5kbGUpOw0KCSAgICAgICAgICAgIAkJDQoJICAgICAgICAgICAgfQ0KDQoJDQoJICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgDQpFT0Y7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KICAgICAgICAkYXBwZW5kID0gIiI7DQogICAgICAgIHN3aXRjaCAoKGludCkkcXVlcnlfYXBwZW5kX3Bvc2l0aW9uKSB7DQogICAgICAgICAgICBjYXNlIDE6DQogICAgICAgICAgICAgICAgJGFwcGVuZCA9ICJhcnJheV91bnNoaWZ0KHskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9LCBhcnJheSgwPT4neyRxdWVyeV9hcHBlbmRfbGFiZWx9JywgMT0+J3skcXVlcnlfYXBwZW5kX3ZhbHVlfScpKTsiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyOg0KICAgICAgICAgICAgICAgICRhcHBlbmQgPSAiYXJyYXlfcHVzaCh7JHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyfSwgYXJyYXkoMD0+J3skcXVlcnlfYXBwZW5kX2xhYmVsfScsIDE9Pid7JHF1ZXJ5X2FwcGVuZF92YWx1ZX0nKSk7IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRzdGFuZGFyZF9zcWwgPSA8PDxFT1QNClwkc3FsX3skam9ibmFtZX0gPSA8PDxFT0cNCnskcXVlcnlfc3FsfQ0KRU9HOw0KDQpcdHskcGFyYW1zfQ0KDQpcdHskY2FsbF9jb2RlfQ0KDQpcdC8vIEFueSBhdXRvbWF0ZWQgYXBwZW5kIGNhbGxzLi4uDQpcdHskYXBwZW5kfQ0KDQpcdC8vIERhdGEgRXhwb3J0IChPcHRpb25hbCkNClx0eyRleHBvcnRfY29kZX0NCg0KXHR7JGRlYnVnX2NvZGV9DQoNCkVPVDsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRxdWVyeV9teXNxbDRjb21wYXQgPT0gMSkgew0KICAgICAgICAgICAgJHNxbCA9ICRteXNxbDQ7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkc3FsID0gJHN0YW5kYXJkX3NxbDsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICAkZnVuY3Rpb25fdGFnX3N0YXJ0ID0gIiI7DQogICAgICAgICRmdW5jdGlvbl90YWdfZW5kID0gIiI7DQoNCiAgICAgICAgJHQgPSAoc3RyaW5nKSRxdWVyeV9mdW5jdGlvbl9yZXR1cm5zX3Jlc3VsdDsNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJHF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0KSB8fCAkcXVlcnlfZnVuY3Rpb25fcmV0dXJuc19yZXN1bHQgPT0gIiIpIHsNCiAgICAgICAgICAgICRxdWVyeV9mdW5jdGlvbl9yZXR1cm5zX3Jlc3VsdCA9IDA7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKChzdHJpbmcpJHF1ZXJ5X2Z1bmN0aW9uX2NhbGwgIT09ICIiKSB7DQogICAgICAgICAgICAkZnVuY3Rpb25fdGFnX3N0YXJ0ID0gImZ1bmN0aW9uICIgLiBzdHJfcmVwbGFjZSgnOycsICcnLCAkcXVlcnlfZnVuY3Rpb25fY2FsbCkgLiAieyI7DQoNCiAgICAgICAgICAgIGlmICgoaW50KSRxdWVyeV9mdW5jdGlvbl9yZXR1cm5zX3Jlc3VsdCA9PSAxKSB7DQogICAgICAgICAgICAgICAgJGZ1bmN0aW9uX3RhZ19lbmQgPSAiXG4vL1JldHVybiBSZXN1bHRcbnJldHVybiB7JHF1ZXJ5X3JldHVybl9yZXN1bHRfdmFyfTtcbn0gLy8gZW5kIHskcXVlcnlfZnVuY3Rpb25fY2FsbH0iOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAkZnVuY3Rpb25fdGFnX2VuZCA9ICJ9IC8vIGVuZCB7JHF1ZXJ5X2Z1bmN0aW9uX2NhbGx9IjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgICRmb3JtX3BvcHVsYXRlX2NvZGUgPSAiIjsNCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkLT5xdWVyeV9kZWJ1Z19sZXZlbCkgJiYgJGZpZWxkLT5xdWVyeV9kZWJ1Z19sZXZlbCA9PSAnMycpIHsNCg0KICAgICAgICAgICAgJGZvcm1fcG9wdWxhdGVfY29kZSA9IDw8PEVPRg0KPCEtLSBGb3JtIFByZS1Qb3B1bGF0ZSBDb2RlLiAtLT4NCiAgICANCjxzY3JpcHQgc3JjPSIvL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMi4xLjEubWluLmpzIj48L3NjcmlwdD4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KDQpcJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24odCl7DQogICAgPD9waHAgDQoNCiAgICBlY2hvICJ2YXIgdCA9IDA7XG4iOw0KICAgIA0KICAgIGZvcmVhY2goeyRxdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn1bMF0gYXMgXCRrZXkgPT4gXCR2YWx1ZSl7DQogICAgDQogICAgICAgIGlmKGlzX251bWVyaWMoXCRrZXkpKQ0KICAgICAgICAgICAgY29udGludWU7DQogICAgDQogICAgICAgIFwkdmFsID0gc3RyX3JlcGxhY2UoIiciLCAiXCciLCBcJHZhbHVlKTsNCiAgICAgICAgDQogICAgICAgIC8vIHN0YW5kYXJkIHRleHQNCiAgICAgICAgZWNobyAiJCgnI3tcJGtleX0nKS52YWwoJ3tcJHZhbH0nKTtcbiI7DQogICAgICAgIA0KICAgICAgICAvLyBjYWxlbmRhcg0KICAgICAgICBlY2hvICIkKCcjZGF0ZS17XCRrZXl9LTEnKS52YWwoJ3tcJHZhbH0nKTtcbiI7DQogICAgICAgIA0KICAgICAgICAvLyBjaGVja2JveGVzDQogICAgICAgIGVjaG8gInQgPSAxMDA7XG4iOw0KICAgICAgICANClwkY2JfbG9vcCA9IDw8PEVPRw0KZm9yKGkgPSAwOyBpIDwgdDsgaSsrKXsNCiAgICBpZigkKCcje1wka2V5fScgKyBpKSl7DQogICAgICAgIA0KICAgICAgICB2YXIgX3ZhbHVlID0gJ3tcJHZhbH0nOw0KICAgICAgICANCiAgICAgICAgdmFyIF92YWxzID0gX3ZhbHVlLnNwbGl0KCd8Jyk7DQogICAgICAgIA0KICAgICAgICBpZihfdmFscy5pbmRleE9mKCQoJyN7XCRrZXl9JyArIGkpLnZhbCgpKSAhPSAtMSkNCiAgICAgICAgICAgICQoJyN7XCRrZXl9JyArIGkpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTsNCiAgICAgICAgICAgIA0KICAgIH0NCn1cblxuDQpFT0c7DQoNCiAgICAgICAgZWNobyBcJGNiX2xvb3A7DQogICAgICAgIA0KICAgIH0NCg0KICAgID8+DQp9KTsgICAgICAgIA0KICAgICAgICANCjwvc2NyaXB0Pg0KICAgICAgICANCiAgICAgICAgDQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGZvcm1fcG9wdWxhdGVfY29kZSA9ICIiOw0KDQoNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmICghaXNzZXQoJGRiZHNuKSkgew0KICAgICAgICAgICAgJGRiZHNuID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICAkZWx0ID0gPDw8RU9UDQp7JHBocF9zdGFydF90YWd9DQovKioNCiAqIFJhY2tGb3JtcyBEYXRhYmFzZSBRdWVyeSBNb2R1bGUgUHJvY2Vzcw0KICogVXNlcyBjdXN0b20gU1FMIHRvIHF1ZXJ5IGEgZGF0YWJhc2Ugb2YgeW91ciBjaG9vc2luZy4NCiAqKi8NCg0KeyRmdW5jdGlvbl90YWdfc3RhcnR9DQoNCgkvLyBTdGFydCBvdXIgbWFpbiBzZXNzaW9uIGlmIG5vdCBhbHJlYWR5DQoJaWYoIXNlc3Npb25faWQoKSkgeyBzZXNzaW9uX3N0YXJ0KCk7IH0NCgkNCgl7JGNvbmRpdGlvbl9jb2RlX3N0YXJ0fQ0KCVwkZGJfdHlwZSA9ICJ7JGRiX3R5cGV9IjsNCglcJGRiX2hvc3QgPSAieyRkYmhvc3R9IjsNCglcJG15c3FsX3NvY2tldCA9ICJ7JGRic29ja2V0fSI7DQoJXCRteXNxbF9wb3J0ID0gInskZGJwb3J0fSI7DQoJXCRkYmRzbiA9ICJ7JGRiZHNufSI7DQoJXCRkYl91c2VyID0gInskZGJ1c2VyfSI7DQoJXCRkYl9wYXNzID0gInskZGJwd2R9IjsNCglcJGRiX2NhdGFsb2cgPSAieyRkYnNjaGVtYX0iOw0KCQ0KCVwkZGJfc3NsX2tleSA9ICd7JGZpZWxkLT5kYnNzbGtleX0nOw0KCVwkZGJfc3NsX2NlcnRpZmljYXRlID0gJ3skZmllbGQtPmRic3NsY2VydGlmaWNhdGV9JzsNCglcJGRiX3NzbF9jYV9jZXJ0ID0gJ3skZmllbGQtPmRic3NsY2FjZXJ0fSc7DQoJXCRkYl9zc2xfdmVyaWZ5X2NlcnQgPSAneyRmaWVsZC0+ZGJzc2x2ZXJpZnljZXJ0fSc7DQoJXCRkYl9zc2xfY2lwaGVyID0gJ3skZmllbGQtPmRic3NsY2lwaGVyfSc7DQoJDQoJaW5jbHVkZSAnRGF0YWJhc2UucGhwJzsNCgkNCglcJGRlYnVnID0geyRxdWVyeV9kZWJ1Z19sZXZlbH07IC8vIFVJIG92ZXJyaWRlDQoJLy8gT3B0aW9uYWwgREIgQ29ubmVjdG9yIEZpbGUgLSBpZiBub3Qgc3BlY2lmaWVkIHdlIHdpbGwgdXNlIGNvbmZpZy5waHAgdmlhIERhdGFiYXNlLnBocCBpbmNsdWRlDQoJaWYoZmlsZV9leGlzdHMoJ3skZGJjb25uZWN0b3J9Jykpew0KCQlpbmNsdWRlICd7JGRiY29ubmVjdG9yfSc7DQoJfQ0KCQ0KCS8vIFF1ZXJ5IEl0ZW0gUXF1ZXJ5DQoJXCRzcWxfeyRqb2JuYW1lfSA9ICJ7JGpvYm5hbWV9IjsNCglcJGRiaCA9IG5ldyBEYXRhYmFzZSgpOw0KCQ0KCVwkam9ibmFtZSA9ICd7JGpvYm5hbWV9JzsNCglcJHNlc3Npb25faWQgPSBzZXNzaW9uX2lkKCk7DQoJXCR0aW1lc3RhbXAgPSB0aW1lKCk7DQoJXCRkYXRldGltZSA9IGRhdGUoJ1ktbS1kICBIOmk6cycsIHRpbWUoKSk7DQoJDQoJLy8gVXNlZCBGb3IgU2VjdXJpdHkgUHJvY2Vzc2luZw0KCVwkcmVtb3RlX2lwID0gXCRfU0VSVkVSWydSRU1PVEVfQUREUiddOw0KCQ0KCSRzcWwNCgkNCgl7JHF1ZXJ5X2NvZGV9DQoJDQoJeyRjb25kaXRpb25fY29kZV9lbmR9DQoNCnskZnVuY3Rpb25fdGFnX2VuZH0NCg0KeyRwaHBfY2xvc2VfdGFnfQ0KeyRmb3JtX3BvcHVsYXRlX2NvZGV9DQpFT1Q7DQoNCg0KICAgICAgICANCiAgICAgICAgJHNpbXBsZV9saXN0ID0gImZhbHNlIjsNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+cXVlcnlfY3JlYXRlX21vZGUpKSB7DQogICAgICAgICAgICBzd2l0Y2ggKCRmaWVsZC0+cXVlcnlfY3JlYXRlX21vZGUpIHsNCiAgICAgICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAgICAgJHNpbXBsZV9saXN0ID0gImZhbHNlIjsgDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICAgICAkc2ltcGxlX2xpc3QgPSAiZmFsc2UiOyANCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAnMic6DQogICAgICAgICAgICAgICAgICAgICRzaW1wbGVfbGlzdCA9ICJ0cnVlIjsgDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgDQoNCiAgICAgICAgJGR5bmFtaWNfZmllbGRzID0gJyc7DQoNCg0KICAgICAgICAkZHluYW1pY19maWVsZHMgLj0gPDw8RU9GDQpcblxuPD9waHANCg0KLy8gT3B0aW9ucw0KXCRzaW1wbGVfbGlzdCA9IHskc2ltcGxlX2xpc3R9Ow0KDQovLyBDcmVhdGUgRHluYW1pYyBGb3JtIEZpZWxkIEVsZW1lbnRzIEZyb20gVGhpcyBRdWVyeS4NCmlmKHN1YnN0cl9jb3VudChcJHNxbF97JGpvYm5hbWV9LCAnd2hlcmUnKSA9PSAxKXsNCglcJG5vX3doZXJlID0gZXhwbG9kZSgnd2hlcmUnLCBcJHNxbF97JGpvYm5hbWV9KTsNCn0gZWxzZSB7DQoJXCRub193aGVyZSA9IGV4cGxvZGUoJ1dIRVJFJywgXCRzcWxfeyRqb2JuYW1lfSk7DQp9DQoNClwkc3FsX2VsZW1lbnRzX3skam9ibmFtZX0gPSBcJG5vX3doZXJlWzBdOw0KDQovLyBEZWZhdWx0IFNRTCBDYWxsLgkJDQpcJHJlc3VsdF9lbGVtZW50c197JGpvYm5hbWV9ID0gXCRkYmgtPm15c3FsX21ldGFfcXVlcnkoXCRkZWJ1ZywgDQoJCQkJCQkJCQkJCQkJCSBcJHNxbF9lbGVtZW50c197JGpvYm5hbWV9LA0KCQkJCQkJCQkJCQkJCQkgXCRkYl9ob3N0LA0KCQkJCQkJCQkJCQkJCQkgXCRkYl90eXBlLA0KCQkJCQkJCQkJCQkJCQkgXCRteXNxbF9zb2NrZXQsDQoJCQkJCQkJCQkJCQkJCSBcJG15c3FsX3BvcnQsDQoJCQkJCQkJCQkJCQkJCSBcJGRiZHNuLA0KCQkJCQkJCQkJCQkJCQkgXCRkYl91c2VyLA0KCQkJCQkJCQkJCQkJCQkgXCRkYl9wYXNzLA0KCQkJCQkJCQkJCQkJCQkgXCRkYl9jYXRhbG9nKTsNCg0KaWYoXCRyZXN1bHRfZWxlbWVudHNfeyRqb2JuYW1lfVswXSA9PSAxKXsJDQoJXCRyZXN1bHRfZWxlbWVudHNfZW5jb2RlZCA9IHBocF9qc29uX2VuY29kZShcJHJlc3VsdF9lbGVtZW50c197JGpvYm5hbWV9WzFdKTsNCn0gZWxzZSB7DQoJZWNobyAnVGhlcmUgd2FzIGEgcHJvYmxlbSBjcmVhdGluZyB5b3VyIFF1ZXJ5IEZvcm0gRWxlbWVudHMuJzsNCn0NCg0KLy8gY3JlYXRlIGEgc2Vzc2lvbiBlbGVtZW50IHRoYXQgc3RvcmVzIHZhbGlkIGZpZWxkIG5hbWVzLCB0aGVzZSBhcmUgcHJvY2Vzc2VkIGluIHRoZSBfcHJvY2Vzcy5waHAgZmlsZS4NClwkX1NFU1NJT05bJ2ZiX2R5bmFtaWNfZWxlbWVudHMnXSA9ICcnOw0KDQovLyBhbGxvdyBmb3IgbXVsdGlwbGUgcXVlcmllcyBvbiB0aGUgc2FtZSBwYWdlLg0KaWYoIWlzc2V0KFwkZWxlbWVudHNfdG9fc2F2ZSkpew0KCVwkZWxlbWVudHNfdG9fc2F2ZSA9IGFycmF5KCk7DQp9DQoNCi8vIG5vdyB0aGF0IHdlIGtub3cgdGhpZXIgZmllbGRzIG1ldGEgY29udGVudCwgY3JlYXRlIHRoZSBlbGVtZW50cy4NCg0KLy8gY3JlYXRlIG91ciBlbGVtZW50cyBiYXNlZCBvbiBkYXRhIHR5cGUNCg0KXCRmb3JtX2VsZW1lbnRzID0gJzx1bCBjbGFzcz0iZHluYW1pYy1mb3JtLWVsZW1lbnRzLXVsIj4nOw0KDQpmb3JlYWNoKHskcXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9IGFzIFwkaWR4ID0+IFwkcSl7DQoJDQoJZm9yZWFjaChcJHEgYXMgXCRpZGogPT4gXCRmKXsNCgkJDQoJCWlmKCFpc19udW1lcmljKFwkaWRqKSkNCgkJCWNvbnRpbnVlOyAvLyB3ZSBvbmx5IHdhbnQgaW5kZXhlZCBpdGVtcw0KCQkJDQoJCQkNCgkJLy8gU2ltcGxlIExpc3QgTW9kZQ0KCQkvLyBDcmVhdGUgZm9ybSBlbGVtZW50cyB1c2luZyBhIHNpbXBsZSByYWRpbyBpbnRlcmZhY2UsIHVzZWZ1bCBmb3IgZHluYW1pYyBwcm9kdWN0IHNlbGVjdGlvbiBmb3Jtcy4gDQoJCQ0KCQkvLyBXZSBtYWtlIGEgZmV3IGFzc3VtcHRpb25zIGhlcmU6DQoJCS8vIGEpIFRoZSBxdWVyeSBkcml2aW5nIHRoaXMgb25seSBncmFicyB0d28gZmllbGRzLCBvbmUgb2Ygd2hpY2ggaXMgdGhlIFBLLg0KCQkvLyBiKSBUaGUgZmllbGQgdmFsdWUgYmVjb21lcyB0aGUgbGFiZWwuDQoJCS8vIGMpIFRoZSBmaWVsZCBjb2x1bW4gbmFtZSBiZWNvbWVzIHRoZSBpbmRleGVkIG5hbWUgcHJvcGVydHkuDQoJCQ0KCQlpZihcJHNpbXBsZV9saXN0ID09IHRydWUpew0KDQoJCQlcJHQgPSBleHBsb2RlKCcsJywgXCRyZXN1bHRfZWxlbWVudHNfeyRqb2JuYW1lfVsxXVtcJGlkal0pOyAvLyBmaWVsZCBuYW1lLCBmaWVsZCB0eXBlLCBQSw0KCQkJDQoJCQkvLyBEbyBub3QgY3JlYXRlIGZpZWxkIG9yIHJlY29yZCBmb3IgUEsgZmllbGQuDQoJCQlpZihcJHRbMl0gPT0gInRydWUiKQ0KCQkJCWNvbnRpbnVlOw0KCQkJDQoJCQkvLyBDcmVhdGUgbmFtZSBmb3IgdGhpcyBmaWVsZCBiYXNlZCBvbiB0aGUgY29sdW1uIG5hbWUgKyBpbmRleA0KCQkJXCRfZmllbGRfbmFtZSA9IFwkdFswXSAuIFwkaWR4Ow0KCQkJDQoJCQkvLyBwdXNoIHRoaXMgZWxlbWVudCB0byBvdXIgZHluYW1pYyBwcm9jZXNzaW5nIGFycmF5Lg0KCQkJXCRlbGVtZW50c190b19zYXZlW10gPSBcJF9maWVsZF9uYW1lOw0KCQkJDQoJCQlcJGZvcm1fZWxlbWVudHMgLj0gIjxsaT4iOw0KCQkJDQoJCQkNCgkJCS8vIFRoZSBQSyBGaWVsZCBGb3IgVGhpcyBJdGVtIEJlY29tZXMgVGhlIFZhbHVlLCBPdGhlcndpc2UgV2UgVXNlIFRoZSBCYXNlIEZpZWxkIFZhbHVlLg0KCQkJXCR0ZW1wX3ZhbHVlID0gXCRxWyJ7XCR0WzBdfSJdOw0KCQkJDQoJCQkvLyBMb29wIG92ZXIgYWxsIGl0ZW1zIGFuZCBncmFiIGEgUEsgaWYgcG9zc2libGUNCgkJCWZvcmVhY2goXCRyZXN1bHRfZWxlbWVudHNfeyRqb2JuYW1lfVsxXSBhcyBcJHJlc19sb29wKXsNCgkJCQlcJF90ID0gZXhwbG9kZSgnLCcsIFwkcmVzX2xvb3ApOyAvLyBmaWVsZCBuYW1lLCBmaWVsZCB0eXBlLCBQSw0KCQkJCWlmKFwkX3RbMl0gPT0gInRydWUiKXsNCgkJCQkJXCR0ZW1wX3ZhbHVlID0gXCRxWyJ7XCRfdFswXX0iXTsNCgkJCQkJYnJlYWs7DQoJCQkJfQ0KCQkJfQ0KCQkJDQoJCQkNCgkJCVwkZGF0YV90eXBlID0gJ0lOVCc7DQoJCQlcJGZpZWxkX3R5cGUgPSAidGV4dGJveCI7DQoJCQkNCgkJCVwkc2VsID0gJyc7DQoJCQlpZihcJGYgPT0gJzEnKSB7IFwkc2VsID0gJyBjaGVja2VkPSJjaGVja2VkIiAnOyB9DQoJCQkNCgkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPHNwYW4gY2xhc3M9XCJcIj57XCRxWyJ7XCR0WzBdfSJdfTwvc3Bhbj48YnIgLz4iOyAvLyBGaWVsZCBWYWx1ZSBCZWNvbWVzIExhYmVsDQoJCQkvL1wkZm9ybV9lbGVtZW50cyAuPSAiPGxhYmVsIGZvcj1cIntcJF9maWVsZF9uYW1lfS1mYWxzZVwiPjxpbnB1dCB0eXBlPVwicmFkaW9cIiBuYW1lPVwie1wkX2ZpZWxkX25hbWV9XCIgaWQ9XCJ7XCRfZmllbGRfbmFtZX0tZmFsc2VcIiB2YWx1ZT1cIlwiIC8+Tm90IFNlbGVjdGVkPC9sYWJlbD4iOw0KCQkJXCRmb3JtX2VsZW1lbnRzIC49ICI8bGFiZWwgZm9yPVwie1wkX2ZpZWxkX25hbWV9LXRydWVcIj48aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgbmFtZT1cIntcJF9maWVsZF9uYW1lfVwiIGlkPVwie1wkX2ZpZWxkX25hbWV9LXRydWVcIiB2YWx1ZT1cIntcJHRlbXBfdmFsdWV9XCIge1wkc2VsfSAvPjwvbGFiZWw+IjsNCgkJCQ0KCQkJXCRmb3JtX2VsZW1lbnRzIC49ICI8L2xpPiI7DQoJCQkNCgkJCS8vIERvIE5vdCBQcm9jZXNzIEZ1cnRoZXIuDQoJCQljb250aW51ZTsNCg0KCQl9IC8vIFNpbXBsZSBMaXN0IE1vZGUNCgkJDQoJDQoJCVwkdCA9IGV4cGxvZGUoJywnLCBcJHJlc3VsdF9lbGVtZW50c197JGpvYm5hbWV9WzFdW1wkaWRqXSk7IC8vIGZpZWxkIG5hbWUsIGZpZWxkIHR5cGUsIFBLDQoJCQ0KCQkvLyBwdXNoIHRoaXMgZWxlbWVudCB0byBvdXIgZHluYW1pYyBwcm9jZXNzaW5nIGFycmF5Lg0KCQlcJGVsZW1lbnRzX3RvX3NhdmVbXSA9IFwkdFswXTsNCgkJDQoJCQ0KCQlcJGxhYmVsX3ZhbHVlX3VwcGVyID0gdWN3b3JkcyhcJHRbMF0pOw0KCQkNCgkJDQoJCVwkZGVmYXVsdF90ZXh0X2ZpZWxkID0gIjxkaXYgY2xhc3M9XCJkeW5hbWljLWZvcm0tZWxlbWVudHMtZmllbGQtd3JhcHBlclwiPiI7DQoJCVwkZGVmYXVsdF90ZXh0X2ZpZWxkIC49ICI8bGFiZWwgY2xhc3M9XCJkeW5hbWljLWZvcm0tZWxlbWVudHMtbGFiZWxcIiBmb3I9XCJ7XCR0WzBdfVwiPntcJGxhYmVsX3ZhbHVlX3VwcGVyfTwvbGFiZWw+IjsNCgkJXCRkZWZhdWx0X3RleHRfZmllbGQgLj0gIjwvZGl2PiI7DQoJCQkJDQoJCS8vIEJ1aWxkIDgyOSAtIE9wdGlvbiB0byBwcmUtcG9wdWxhdGUgZmllbGQuIA0KCQkJCQ0KCQlpZih7JGZpZWxkLT5xdWVyeV9jcmVhdGVfbW9kZX0gPT0gIjAiKXsNCgkJCVwkZGVmYXVsdF90ZXh0X2ZpZWxkIC49ICI8aW5wdXQgY2xhc3M9XCJkeW5hbWljLWZvcm0tZWxlbWVudHMtdGV4dFwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cIntcJHRbMF19XCIgdmFsdWU9XCJ7XCRmfVwiIC8+IjsJDQoJCX0NCgkJCQkNCgkJaWYoeyRmaWVsZC0+cXVlcnlfY3JlYXRlX21vZGV9ID09ICIxIil7DQoJCQlcJGRlZmF1bHRfdGV4dF9maWVsZCAuPSAiPGlucHV0IGNsYXNzPVwiZHluYW1pYy1mb3JtLWVsZW1lbnRzLXRleHRcIiB0eXBlPVwidGV4dFwiIG5hbWU9XCJ7XCR0WzBdfVwiIHZhbHVlPVwiXCIgLz4iOwkNCgkJfQ0KCQkJCQ0KCQkvLyBCdWlsZCA4MjkgLSBDcmVhdGUgUEsgSXRlbXMgYXMgSGlkZGVuIEZpZWxkcy4NCgkJCQkNCgkJaWYoXCR0WzJdID09ICJ0cnVlIil7DQoJCQkNCgkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwie1wkdFswXX1cIiB2YWx1ZT1cIntcJGZ9XCIgLz4iOw0KCQkNCgkJfSBlbHNlIHsNCgkJCQkNCgkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPGxpPiI7DQoJCQkJDQoJCQlzd2l0Y2goXCR0WzFdKXsNCgkJCQljYXNlICdMT05HJyA6DQoJCQkJCVwkZGF0YV90eXBlID0gJ0lOVCc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJ0ZXh0Ym94IjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICdGTE9BVCcgOg0KCQkJCQlcJGRhdGFfdHlwZSA9ICdJTlQnOw0KCQkJCQlcJGZpZWxkX3R5cGUgPSAidGV4dGJveCI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnVkFSX1NUUklORycgOg0KCQkJCQlcJGRhdGFfdHlwZSA9ICdTVFJJTkcnOw0KCQkJCQlcJGZpZWxkX3R5cGUgPSAidGV4dGJveCI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnQkxPQicgOg0KCQkJCQlcJGRhdGFfdHlwZSA9ICdCTE9CJzsNCgkJCQkJXCRmaWVsZF90eXBlID0gImZpbGUtZGIiOw0KCQkJCQlcJHVwZGF0ZV9kZWZhdWx0X3ZhbHVlID0gIjEwNDg1NzYiOw0KCQkJCQlicmVhazsNCgkJCQkJDQoJCQkJLy8gbXlzcWxpIC0NCgkJCQkvLyBodHRwOi8vd3d3LnBocC5uZXQvbWFudWFsL2VuL215c3FsaS5jb25zdGFudHMucGhwDQoJCQkJCQ0KCQkJCWNhc2UgJzEnIDogLy8gTVlTUUxJX1RZUEVfVElOWSAvIEJPT0wNCgkJCQkJXCRkYXRhX3R5cGUgPSAnSU5UJzsNCgkJCQkJXCRmaWVsZF90eXBlID0gInRleHRib3giOw0KCQkJCQlcJHNlbCA9ICcnOw0KCQkJCQlpZihcJGYgPT0gJzEnKSB7IFwkc2VsID0gJyBjaGVja2VkPSJjaGVja2VkIiAnOyB9DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPHNwYW4gY2xhc3M9XCJcIj57XCR0WzBdfTwvc3Bhbj48YnIgLz4iOw0KCQkJCQlcJGZvcm1fZWxlbWVudHMgLj0gIjxsYWJlbCBmb3I9XCJ7XCR0WzBdfS1mYWxzZVwiPjxpbnB1dCB0eXBlPVwicmFkaW9cIiBuYW1lPVwie1wkdFswXX1cIiBpZD1cIntcJHRbMF19LWZhbHNlXCIgdmFsdWU9XCIwXCIgLz5Ob3QgU2VsZWN0ZWQ8L2xhYmVsPiI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPGxhYmVsIGZvcj1cIntcJHRbMF19LXRydWVcIj48aW5wdXQgdHlwZT1cInJhZGlvXCIgbmFtZT1cIntcJHRbMF19XCIgaWQ9XCJ7XCR0WzBdfS10cnVlXCIgdmFsdWU9XCIxXCIge1wkc2VsfSAvPlNlbGVjdGVkPC9sYWJlbD4iOw0KCQkJCQlicmVhazsNCgkJCQkJDQoJCQkJY2FzZSAnMycgOiAvLyBNWVNRTElfVFlQRV9MT05HDQoJCQkJCVwkZGF0YV90eXBlID0gJ0lOVCc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJ0ZXh0Ym94IjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICc0JyA6IC8vIE1ZU1FMSV9UWVBFX0ZMT0FUDQoJCQkJCVwkZGF0YV90eXBlID0gJ0lOVCc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJ0ZXh0Ym94IjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICc3JyA6IC8vIE1ZU1FMSV9UWVBFX1RJTUVTVEFNUA0KCQkJCQlcJGRhdGFfdHlwZSA9ICdUSU1FU1RBTVBfQSc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJjYWxlbmRhciI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnMTInIDogLy8gTVlTUUxJX1RZUEVfREFURVRJTUUNCgkJCQkJXCRkYXRhX3R5cGUgPSAnREFURVRJTUVfQSc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJjYWxlbmRhciI7IC8vIHdhcyB0ZXh0Ym94DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnMjUyJyA6IC8vIE1ZU1FMSV9UWVBFX0JJTkFSWQ0KCQkJCQkvLyBUcmlja3kgYXMgdGhpcyBjYW4gYWxzbyBiZSBwYXNzd29yZCBmaWVsZHMgYW5kIEJJR1RFWFQuIEZvciBub3csIG5vdCBzdXBwb3J0ZWQuDQoJCQkJCVwkZmllbGRfdHlwZSA9ICJmaWxlLWRiIjsNCgkJCQkJXCR1cGRhdGVfZGVmYXVsdF92YWx1ZSA9ICIxMDQ4NTc2IjsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnMjUzJyA6DQoJCQkJCVwkZGF0YV90eXBlID0gJ1NUUklORyc7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJ0ZXh0Ym94IjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQkJDQoJCQkJLy8gTVNTUUwgU1FMU1JWIFN1cHBvcnQNCgkJCQkJDQoJCQkJLy8gU2Nyb2xsIGRvd24gYSBiaXQgdG8gc2VlIGFsbCBuYXRpdmUgdHlwZXM6DQoJCQkJLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi1VUy9saWJyYXJ5L2NjMjk2MTk3JTI4dj1TUUwuOTAlMjkuYXNweA0KCQkJCQkNCgkJCQljYXNlICctMicgOiAvLyBTUUxfQklOQVJZDQoJCQkJCVwkZGF0YV90eXBlID0gJ1RJTUVTVEFNUF9BJzsNCgkJCQkJXCRmaWVsZF90eXBlID0gImNhbGVuZGFyIjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICctNCcgOg0KCQkJCQlcJGZpZWxkX3R5cGUgPSAiZmlsZS1kYiI7DQoJCQkJCVwkdXBkYXRlX2RlZmF1bHRfdmFsdWUgPSAiMTA0ODU3NiI7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgJy05JyA6IC8vIEJ1aWxkIDcxMCAtIE5WQVJDSEFSDQoJCQkJCVwkZmllbGRfdHlwZSA9ICJ0ZXh0Ym94IjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICcyJyA6IC8vIEJ1aWxkIDcxMCAtIE51bWVyaWMNCgkJCQkJXCRmaWVsZF90eXBlID0gInRleHRib3giOw0KCQkJCQlcJGZvcm1fZWxlbWVudHMgLj0gXCRkZWZhdWx0X3RleHRfZmllbGQ7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgJzkzJyA6DQoJCQkJCVwkZGF0YV90eXBlID0gIkRBVEVUSU1FX0EiOyAvL1NRTF9UWVBFX1RJTUVTVEFNUCAoZGF0ZXRpbWUpDQoJCQkJCVwkZmllbGRfdHlwZSA9ICJjYWxlbmRhciI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJCQ0KCQkJCS8vIFBvc3RncmVTUUwgU3VwcG9ydA0KCQkJCWNhc2UgJ2J5dGVhJyA6DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJmaWxlLWRiIjsNCgkJCQkJXCR1cGRhdGVfZGVmYXVsdF92YWx1ZSA9ICIxMDQ4NTc2IjsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnZGF0ZScgOg0KCQkJCQlcJGRhdGFfdHlwZSA9ICJEQVRFVElNRV9BIjsNCgkJCQkJXCRmaWVsZF90eXBlID0gImNhbGVuZGFyIjsNCgkJCQkJXCRmb3JtX2VsZW1lbnRzIC49IFwkZGVmYXVsdF90ZXh0X2ZpZWxkOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICd0aW1lc3RhbXAnIDoNCgkJCQkJXCRkYXRhX3R5cGUgPSAiREFURVRJTUVfQSI7DQoJCQkJCVwkZmllbGRfdHlwZSA9ICJjYWxlbmRhciI7DQoJCQkJCVwkZm9ybV9lbGVtZW50cyAuPSBcJGRlZmF1bHRfdGV4dF9maWVsZDsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAnbW9uZXknIDoNCgkJCQkJXCRmaWVsZF90eXBlID0gInRleHRib3giOw0KCQkJCQlcJGZvcm1fZWxlbWVudHMgLj0gXCRkZWZhdWx0X3RleHRfZmllbGQ7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgJ2ludDQnIDoNCgkJCQkJXCRmaWVsZF90eXBlID0gInRleHRib3giOw0KCQkJCQlcJGZvcm1fZWxlbWVudHMgLj0gXCRkZWZhdWx0X3RleHRfZmllbGQ7DQoJCQkJCWJyZWFrOw0KCQkJCQkNCgkJCX0NCgkJCQkNCgkJCVwkZm9ybV9lbGVtZW50cyAuPSAiPC9saT4iOw0KCQkJCQ0KCQl9IC8vIGlzIHBrIG9yIG5vdC4NCgkJDQoJCQ0KCQkNCgl9DQp9DQoNClwkZm9ybV9lbGVtZW50cyAuPSAnPC91bD4nOw0KDQovLyBzYXZlIGFsbCBkeW5hbWljIGVsZW1lbnQgZmllbGQgbmFtZXMgdG8gb3VyIHByb2Nlc3MgY2hlY2sgYXJyYXkuDQpcJF9TRVNTSU9OWydmYl9keW5hbWljX2VsZW1lbnRzJ10gPSBcJGVsZW1lbnRzX3RvX3NhdmU7DQoNCmVjaG8gXCRmb3JtX2VsZW1lbnRzOw0KPz4NCkVPRjsNCg0KDQoNCg0KICAgICAgICANCg0KDQoNCiAgICAgICAgaWYgKGlzc2V0KCRjcmVhdGVfZWxlbWVudHMpICYmIChpbnQpJGNyZWF0ZV9lbGVtZW50cyA9PSAxKSB7DQogICAgICAgICAgICAkZWx0ID0gJGVsdCAuICRkeW5hbWljX2ZpZWxkczsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0gDQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9xdWVyeV9tb25nb2RiKCRtKQ0KICAgIHsNCg0KICAgICAgICANCiAgICAgICAgJGpvYm5hbWUgPSBzdHJfaXJlcGxhY2UoJy0nLCAnXycsICRtLT5qb2JuYW1lKTsNCg0KICAgICAgICANCiAgICAgICAgJHBocF9zdGFydF90YWcgPSAnJzsNCiAgICAgICAgJHBocF9jbG9zZV90YWcgPSAnJzsNCg0KICAgICAgICBpZiAoJG0tPnVzZV9waHBfdGFncyA9PSAxKSB7DQogICAgICAgICAgICAkcGhwX3N0YXJ0X3RhZyA9ICc8P3BocCc7DQogICAgICAgICAgICAkcGhwX2Nsb3NlX3RhZyA9ICc/Pic7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbl9jb2RlX3N0YXJ0ID0gJyc7DQogICAgICAgICRjb25kaXRpb25fY29kZV9lbmQgPSAnJzsNCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbiA9ICR0aGlzLT5yZXBsYWNlX2NvbmRpdGlvbl92YXJzKCRtLT5jb25kaXRpb24pOw0KDQogICAgICAgIGlmICgoc3RyaW5nKSRjb25kaXRpb24gIT0gJycpIHsNCiAgICAgICAgICAgICRjb25kaXRpb25fY29kZV9zdGFydCA9ICJpZih7JGNvbmRpdGlvbn0pIHsgLy8gY29uZGl0aW9uIGNvZGUgc3RhcnQiOw0KICAgICAgICAgICAgJGNvbmRpdGlvbl9jb2RlX2VuZCA9ICd9IC8vIGNvbmRpdGlvbiBjb2RlIGVuZCc7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGRiX3R5cGUgPSAkdGhpcy0+dW0tPnRyYW5zbGF0ZVNvdXJjZVR5cGUoKGludCkkbS0+c291cmNldHlwZSk7DQoNCiAgICAgICAgDQogICAgICAgICRwYXJhbXMgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJG0tPnF1ZXJ5X3ZhcmlhYmxlcywgNC4xKTsgDQoNCiAgICAgICAgDQogICAgICAgICRxdWVyeV9jb2RlID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgoc3RyaW5nKSRtLT5xdWVyeV9jb2RlLCAwKTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKHN1YnN0cl9jb3VudCgkcGFyYW1zLCAiOyIpID09IDAgJiYgJHBhcmFtcyAhPSAnJykgew0KICAgICAgICAgICAgJHBhcmFtcyA9ICJcJHBhcmFtcyA9IHskcGFyYW1zfTsiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHBhcmFtcyA9ICJcJHBhcmFtcyA9IFwiXCI7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJG0tPm1vbmdvZGJfcXVlcnkgPT0gIiIpDQogICAgICAgICRtLT5tb25nb2RiX3F1ZXJ5ID0gIicnIjsNCg0KICAgICAgICBpZiAoIWlzc2V0KCRtLT5xdWVyeV9tb25nb19xdWVyeV9tb2RlKSB8fCAkbS0+cXVlcnlfbW9uZ29fcXVlcnlfbW9kZSA9PSAnJykNCiAgICAgICAgJG0tPnF1ZXJ5X21vbmdvX3F1ZXJ5X21vZGUgPSAiMCI7DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJG0tPnF1ZXJ5X2luc2VydGlkKSkNCiAgICAgICAgJG0tPnF1ZXJ5X2luc2VydGlkID0gMDsNCg0KICAgICAgICAkY2FsbF9jb2RlID0gPDw8RU9GDQoNClwkYW1iaWd1b3VzX2NvbHVtbl9uYW1lX3dhcm5pbmcgPSBmYWxzZTsNCg0KLy8gRGVmYXVsdCBTUUwgQ2FsbC4JCQ0KeyRtLT5xdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn0gPSBcJGRiaC0+cGRvX3Byb2NlZHVyZV9wYXJhbXMoXCRkZWJ1ZywgDQoJCQkJCQkJCQkJIFwkbW9uZ29kYl97JGpvYm5hbWV9LA0KCQkJCQkJCQkJCSBcJGRiX2hvc3QsDQoJCQkJCQkJCQkJIFwkZGJfdHlwZSwNCgkJCQkJCQkJCQkgXCRteXNxbF9zb2NrZXQsDQoJCQkJCQkJCQkJIFwkbXlzcWxfcG9ydCwNCgkJCQkJCQkJCQkgXCRkYmRzbiwNCgkJCQkJCQkJCQkgXCRkYl91c2VyLA0KCQkJCQkJCQkJCSBcJGRiX3Bhc3MsDQoJCQkJCQkJCQkJIFwkZGJfY2F0YWxvZywNCgkJCQkJCQkJCQkgXCRwYXJhbXMsDQoJCQkJCQkJCQkJIDAsIC8vIHJldHVybl90cnVlDQoJCQkJCQkJCQkJIHskbS0+cXVlcnlfaW5zZXJ0aWR9LCAvLyByZXR1cm5fbGFzdF9pbnNlcnRfaWQsDQoJCQkJCQkJCQkJIDQsIC8vIGZldGNoX21vZGUsDQoJCQkJCQkJCQkJIDAsIC8vIHBhc3NfbnVsbHMsDQoJCQkJCQkJCQkJIGZhbHNlLCAvLyBidWlsZGVyX3F1ZXJ5LA0KCQkJCQkJCQkJCSBcJGFtYmlndW91c19jb2x1bW5fbmFtZV93YXJuaW5nLA0KCQkJCQkJCQkJCSAkbS0+cXVlcnlfbW9uZ29fcXVlcnlfbW9kZSwNCgkJCQkJCQkJCQkgJ3skbS0+Y29sbGVjdGlvbn0nKTsNCkVPRjsNCg0KICAgICAgICAkZGVidWdfY29kZSA9IDw8PEVPRg0KaWYoXCRkZWJ1ZyA9PSAyKSB7IAkNCgllY2hvICc8cHJlPnskbS0+cXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9ID0gJzsgcHJpbnRfcigkbS0+cXVlcnlfcmV0dXJuX3Jlc3VsdF92YXIpOyBlY2hvICc8L3ByZT4nOw0KfQ0KRU9GOw0KDQoNCiAgICAgICAgDQogICAgICAgICRhcHBlbmQgPSAiIjsNCiAgICAgICAgc3dpdGNoICgoaW50KSRtLT5xdWVyeV9hcHBlbmRfcG9zaXRpb24pIHsNCiAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAkYXBwZW5kID0gImFycmF5X3Vuc2hpZnQoeyRtLT5xdWVyeV9yZXR1cm5fcmVzdWx0X3Zhcn0sIGFycmF5KDA9Pid7JG0tPnF1ZXJ5X2FwcGVuZF9sYWJlbH0nLCAxPT4neyRtLT5xdWVyeV9hcHBlbmRfdmFsdWV9JykpOyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDI6DQogICAgICAgICAgICAgICAgJGFwcGVuZCA9ICJhcnJheV9wdXNoKHskbS0+cXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9LCBhcnJheSgwPT4neyRtLT5xdWVyeV9hcHBlbmRfbGFiZWx9JywgMT0+J3skbS0+cXVlcnlfYXBwZW5kX3ZhbHVlfScpKTsiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJG0tPm1vbmdvZGJfcXVlcnkgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJG0tPm1vbmdvZGJfcXVlcnksIDQuMSk7IA0KDQogICAgICAgIA0KICAgICAgICAkcXVlcnkgPSA8PDxFT1QNClwkbW9uZ29kYl97JGpvYm5hbWV9ID0geyRtLT5tb25nb2RiX3F1ZXJ5fTsNCg0KXHR7JHBhcmFtc30NCg0KXHR7JGNhbGxfY29kZX0NCg0KXHQvLyBBbnkgYXV0b21hdGVkIGFwcGVuZCBjYWxscy4uLg0KXHR7JGFwcGVuZH0NCg0KXHR7JGRlYnVnX2NvZGV9DQoNCkVPVDsNCg0KDQogICAgICAgIA0KDQogICAgICAgICRmdW5jdGlvbl90YWdfc3RhcnQgPSAiIjsNCiAgICAgICAgJGZ1bmN0aW9uX3RhZ19lbmQgPSAiIjsNCg0KICAgICAgICAkdCA9IChzdHJpbmcpJG0tPnF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0Ow0KDQogICAgICAgIA0KICAgICAgICBpZiAoIWlzc2V0KCRtLT5xdWVyeV9mdW5jdGlvbl9yZXR1cm5zX3Jlc3VsdCkgfHwgJG0tPnF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0ID09ICIiKSB7DQogICAgICAgICAgICAkcXVlcnlfZnVuY3Rpb25fcmV0dXJuc19yZXN1bHQgPSAwOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKChzdHJpbmcpJG0tPnF1ZXJ5X2Z1bmN0aW9uX2NhbGwgIT09ICIiKSB7DQogICAgICAgICAgICAkZnVuY3Rpb25fdGFnX3N0YXJ0ID0gImZ1bmN0aW9uICIgLiAkbS0+cXVlcnlfZnVuY3Rpb25fY2FsbCAuICJ7IjsNCg0KICAgICAgICAgICAgaWYgKChpbnQpJHF1ZXJ5X2Z1bmN0aW9uX3JldHVybnNfcmVzdWx0ID09IDEpIHsNCiAgICAgICAgICAgICAgICAkZnVuY3Rpb25fdGFnX2VuZCA9ICJcbi8vUmV0dXJuIFJlc3VsdFxucmV0dXJuIHskbS0+cXVlcnlfcmV0dXJuX3Jlc3VsdF92YXJ9O1xufSAvLyBlbmQgeyRtLT5xdWVyeV9mdW5jdGlvbl9jYWxsfSI7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRmdW5jdGlvbl90YWdfZW5kID0gIn0gLy8gZW5kIHskbS0+cXVlcnlfZnVuY3Rpb25fY2FsbH0iOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCFpc3NldCgkbS0+ZGJkc24pKSB7DQogICAgICAgICAgICAkZGJkc24gPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgICRlbHQgPSA8PDxFT1QNCnskcGhwX3N0YXJ0X3RhZ30NCi8qKg0KICogRGF0YWJhc2UgUXVlcnkgTW9kdWxlIFByb2Nlc3MNCiAqIFVzZXMgY3VzdG9tIFNRTCB0byBxdWVyeSBhIGRhdGFiYXNlIG9mIHlvdXIgY2hvb3NpbmcuDQogKiovDQoNCnskZnVuY3Rpb25fdGFnX3N0YXJ0fQ0KDQoJLy8gU3RhcnQgb3VyIG1haW4gc2Vzc2lvbiBpZiBub3QgYWxyZWFkeQ0KCWlmKCFzZXNzaW9uX2lkKCkpIHsgc2Vzc2lvbl9zdGFydCgpOyB9DQoJDQoJeyRjb25kaXRpb25fY29kZV9zdGFydH0NCglcJGRiX3R5cGUgPSAneyRkYl90eXBlfSc7DQoJXCRkYl9ob3N0ID0gJ3skbS0+ZGJob3N0fSc7DQoJXCRteXNxbF9zb2NrZXQgPSAneyRtLT5kYnNvY2tldH0nOw0KCVwkbXlzcWxfcG9ydCA9ICd7JG0tPmRicG9ydH0nOw0KCVwkZGJkc24gPSAneyRkYmRzbn0nOw0KCVwkZGJfdXNlciA9ICd7JG0tPmRidXNlcn0nOw0KCVwkZGJfcGFzcyA9ICd7JG0tPmRicHdkfSc7DQoJXCRkYl9jYXRhbG9nID0gJ3skbS0+ZGJzY2hlbWF9JzsNCgkNCglpbmNsdWRlICdEYXRhYmFzZS5waHAnOw0KCVwkZGVidWcgPSB7JG0tPnF1ZXJ5X2RlYnVnX2xldmVsfTsgLy8gVUkgb3ZlcnJpZGUNCgkvLyBPcHRpb25hbCBEQiBDb25uZWN0b3IgRmlsZSAtIGlmIG5vdCBzcGVjaWZpZWQgd2Ugd2lsbCB1c2UgY29uZmlnLnBocCB2aWEgRGF0YWJhc2UucGhwIGluY2x1ZGUNCglpZihmaWxlX2V4aXN0cygneyRtLT5kYmNvbm5lY3Rvcn0nKSl7DQoJCWluY2x1ZGUgJ3skbS0+ZGJjb25uZWN0b3J9JzsNCgl9DQoJLy8gTW9uZ28gUXVlcnkNCglcJHNxbF97JGpvYm5hbWV9ID0gInskam9ibmFtZX0iOw0KCVwkZGJoID0gbmV3IERhdGFiYXNlKCk7DQoJDQoJXCRqb2JuYW1lID0gJ3skam9ibmFtZX0nOw0KCVwkc2Vzc2lvbl9pZCA9IHNlc3Npb25faWQoKTsNCglcJHRpbWVzdGFtcCA9IHRpbWUoKTsNCglcJGRhdGV0aW1lID0gZGF0ZSgnWS1tLWQgIEg6aTpzJywgdGltZSgpKTsNCgkNCgkvLyBVc2VkIEZvciBTZWN1cml0eSBQcm9jZXNzaW5nDQoJXCRyZW1vdGVfaXAgPSBcJF9TRVJWRVJbJ1JFTU9URV9BRERSJ107DQoJDQoJJHF1ZXJ5DQoJDQoJeyRxdWVyeV9jb2RlfQ0KCQ0KCXskY29uZGl0aW9uX2NvZGVfZW5kfQ0KDQp7JGZ1bmN0aW9uX3RhZ19lbmR9DQoNCnskcGhwX2Nsb3NlX3RhZ30NCkVPVDsNCg0KDQogICAgICAgIA0KICAgICAgICAkZHluYW1pY19maWVsZHMgPSAnJzsNCg0KICAgICAgICBpZiAoaXNzZXQoJG0tPmNyZWF0ZV9lbGVtZW50cykgJiYgKGludCkkbS0+Y3JlYXRlX2VsZW1lbnRzID09IDEpIHsNCiAgICAgICAgICAgICRlbHQgPSAkZWx0IC4gJGR5bmFtaWNfZmllbGRzOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbHQ7DQogICAgfSANCg0KDQoNCiAgICANCiAgICANCiAgICANCg0KICAgIA0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3ByZWZhYl9zdXJ2ZXlfc2NhbGUoJGZpZWxkLCAkdGFibGVtb2RlLCAkYnVja2V0X25vZGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgJGxhYmVsID0gJGZpZWxkLT5sYWJlbDsNCiAgICAgICAgJG5hbWUgPSAkZmllbGQtPm5hbWU7DQogICAgICAgICRpZCA9ICRmaWVsZC0+aWQ7DQogICAgICAgICRjb2xvciA9ICRmaWVsZC0+Y29sb3I7DQogICAgICAgICRoZWxwZXIgPSAkZmllbGQtPmhlbHBlcjsNCiAgICAgICAgJGhlbHBlcmNvbG9yID0gJGZpZWxkLT5oZWxwZXJjb2xvcjsNCiAgICAgICAgJGZvbnRzaXplID0gJGZpZWxkLT5mb250c2l6ZTsNCiAgICAgICAgJGxhYmVscG9zID0gJGZpZWxkLT5sYWJlbHBvczsNCiAgICAgICAgJHN0eWxlID0gJGZpZWxkLT5zdHlsZTsNCg0KICAgICAgICAkcHJlZmFiID0gJGZpZWxkLT5wcmVmYWI7DQoNCiAgICAgICAgJHRhYmluZGV4ID0gJGZpZWxkLT50YWJpbmRleDsNCg0KICAgICAgICAkdGFiaHRtbCA9ICR0aGlzLT5jcmVhdGVUYWJJbmRleENvZGUoKGludCkkdGFiaW5kZXgpOw0KDQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRzdHlsZSk7DQoNCg0KDQogICAgICAgIA0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICAkcmVxdWlyZWQgPSAoaW50KSRmaWVsZC0+dmFsaWRhdGlvbi0+cmVxID09IDEgPyAiPHNwYW4gY2xhc3M9XCJyZXEtc3RhclwiPiZuYnNwO3skcmVxdWlyZWRfdGV4dH08L3NwYW4+IiA6ICcnOw0KDQogICAgICAgICRxdWVzdGlvbkNvbHVtbnMgPSAiIjsNCg0KICAgICAgICAkc2NhbGVCb3R0b20gPSAoaW50KSRwcmVmYWItPnNjYWxlX2JvdHRvbTsNCiAgICAgICAgJHNjYWxlVG9wID0gKGludCkkcHJlZmFiLT5zY2FsZV90b3A7DQoNCiAgICAgICAgJGRlbHRhID0gJHNjYWxlVG9wIC0gJHNjYWxlQm90dG9tOw0KDQogICAgICAgIGlmICgkZGVsdGEgPj0gMikgew0KDQogICAgICAgICAgICBmb3IgKCRpID0gJHNjYWxlQm90dG9tOyAkaSA8PSAkc2NhbGVUb3A7ICRpKyspIHsNCg0KICAgICAgICAgICAgICAgICRzZWxlY3RlZCA9ICI8P3BocCBpc3NldChcJF9TRVNTSU9OW1wieyRmaWVsZC0+bmFtZX1cIl0pICYmIFwkX1NFU1NJT05bXCJ7JGZpZWxkLT5uYW1lfVwiXSA9PSB7JGl9ID8gcHJpbnQgJ2NoZWNrZWQ9XCJjaGVja2VkXCInIDogcHJpbnQgJyc7ID8+IjsNCg0KICAgICAgICAgICAgICAgICRxdWVzdGlvbkNvbHVtbnMgLj0gPDw8RU9GDQoJDQoJPGxhYmVsIGNsYXNzPSJzdXJ2ZXktc2NhbGUtY29sdW1uIj4JDQoJCTxkaXYgY2xhc3M9InN1cnZleS1zY2FsZS1sYWJlbCI+eyRpfTwvZGl2Pg0KCQk8ZGl2IGNsYXNzPSJzdXJ2ZXktc2NhbGUtaW5wdXQiPg0KCQkJPGlucHV0IHR5cGU9InJhZGlvIiBuYW1lPSJ7JGZpZWxkLT5uYW1lfSIgaWQ9InskZmllbGQtPmlkfV97JGl9IiB2YWx1ZT0ieyRpfSIgeyRzZWxlY3RlZH0gLz4NCgkJPC9kaXY+DQoJPC9sYWJlbD5cbg0KRU9GOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9GDQoNCjxkaXYgY2xhc3M9InN1cnZleS1zY2FsZS1xdWVzdGlvbi10ZXh0Ij48c3Bhbj57JHByZWZhYi0+cXVlc3Rpb25fdGV4dH17JHJlcXVpcmVkfTwvc3Bhbj48L2Rpdj4NCg0KPGRpdiBjbGFzcz0ic3VydmV5LXNjYWxlLWNvbnRlbnQtY29udGFpbmVyIj4NCg0KCTxkaXYgY2xhc3M9InN1cnZleS1zY2FsZS1sYWJlbC1jb2x1bW4iPg0KCQk8ZGl2IGNsYXNzPSJzdXJ2ZXktc2NhbGUtcGxhY2Vob2xkZXIiPjwvZGl2Pg0KCQk8ZGl2IGNsYXNzPSJzdXJ2ZXktc2NhbGUtdGV4dCBzdXJ2ZXktc2NhbGUtdGV4dC1ib3R0b20iPnskcHJlZmFiLT50ZXh0X2JvdHRvbX08L2Rpdj4NCgk8L2Rpdj4JDQoJDQoJPGRpdiBjbGFzcz0ic3VydmV5LXNjYWxlLXF1ZXN0aW9ucyI+DQoJCXskcXVlc3Rpb25Db2x1bW5zfQ0KCTwvZGl2Pg0KCQ0KCTxkaXYgY2xhc3M9InN1cnZleS1zY2FsZS1sYWJlbC1jb2x1bW4iPg0KCQk8ZGl2IGNsYXNzPSJzdXJ2ZXktc2NhbGUtcGxhY2Vob2xkZXIiPjwvZGl2Pg0KCQk8ZGl2IGNsYXNzPSJzdXJ2ZXktc2NhbGUtdGV4dCBzdXJ2ZXktc2NhbGUtdGV4dC10b3AiPnskcHJlZmFiLT50ZXh0X3RvcH08L2Rpdj4NCgk8L2Rpdj4NCgkNCjwvZGl2PiA8IS0tIENsb3NlIENvbnRlbnQgQ29udGFpbmVyIC0tPg0KDQpFT0Y7DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGVsZW1lbnQgLj0gJzxkaXYgc3R5bGU9ImhlaWdodDogMjBweDsgd2lkdGg6IDEwMCU7IGNsZWFyOmJvdGg7Ij48L2Rpdj4nOw0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9IA0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2Vjb21tKCRmaWVsZCwgJHRhYmxlbW9kZSwgJGJ1Y2tldF9ub2RlID0gIiIpDQogICAgew0KCQkkcmVhZG9ubHkgPSBpc3NldCgkZmllbGQtPnJlYWRvbmx5KSA/ICRmaWVsZC0+cmVhZG9ubHkgOiAwOw0KICAgICAgICAkZmllbGRlbmFibGVkID0gaXNzZXQoJGZpZWxkLT5maWVsZGVuYWJsZWQpID8gJGZpZWxkLT5maWVsZGVuYWJsZWQgOiAxOw0KDQogICAgICAgIA0KICAgICAgICAkZWxlbWVudCA9ICIiOw0KDQogICAgICAgICRlbHQgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+dHJhbnNhY3Rpb250eXBlKSB7DQogICAgICAgICAgICBjYXNlICcwJzoNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQoNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOiANCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMyc6IA0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoaW50KSRmaWVsZC0+Y3VycmVuY3kpIHsNCiAgICAgICAgICAgIGNhc2UgJzAnOg0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICckJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICcmZXVybzsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMic6IA0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICcmcG91bmQ7JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzMnOiANCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJnllbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgY2FzZSA0Og0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICckJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgNToNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJmN1cnJlbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSA2Og0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICckJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgNzoNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJmN1cnJlbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSA4Og0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICcmY3VycmVuOyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDk6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZldXJvOyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDEwOg0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICckJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTE6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTI6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTM6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZ5ZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTQ6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTU6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTY6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTc6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxODoNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJmN1cnJlbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAxOToNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJmN1cnJlbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyMDoNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJnBvdW5kOyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDIxOg0KICAgICAgICAgICAgICAgICRjdXJyZW5jeSA9ICckJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjI6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjM6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyZjdXJyZW47JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjQ6DQogICAgICAgICAgICAgICAgJGN1cnJlbmN5ID0gJyQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyNToNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJmN1cnJlbjsnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAyNjoNCiAgICAgICAgICAgICAgICAkY3VycmVuY3kgPSAnJCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgkZmllbGQtPmZpZWxkdHlwZSkgew0KICAgICAgICAgICAgY2FzZSAnMCc6DQogICAgICAgICAgICAgICAgJGZpZWxkdHlwZSA9ICdjaGVja2JveCc7DQogICAgICAgICAgICAgICAgJGZpZWxkYXJyYXkgPSAnW10nOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJGZpZWxkdHlwZSA9ICdyYWRpbyc7DQogICAgICAgICAgICAgICAgJGZpZWxkYXJyYXkgPSAnJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRmaWVsZHR5cGUgPSAnc2VsZWN0JzsNCiAgICAgICAgICAgICAgICAkZmllbGRhcnJheSA9ICcnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICAkZmllbGR0eXBlID0gJ2NoZWNrYm94JzsNCiAgICAgICAgICAgICAgICAkZmllbGRhcnJheSA9ICdbXSc7DQogICAgICAgIH0NCg0KDQogICAgICAgICRzdHlsZXMgPSAkdGhpcy0+dHJhbnNsYXRlRmllbGRTdHlsZXMoJGZpZWxkLT5zdHlsZSk7DQoNCiAgICAgICAgDQogICAgICAgICR0YWJpbmRleCA9ICRmaWVsZC0+dGFiaW5kZXg7DQogICAgICAgICR0YWJodG1sID0gJHRoaXMtPmNyZWF0ZVRhYkluZGV4Q29kZSgoaW50KSR0YWJpbmRleCk7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF9jYWxsID0gJHRoaXMtPl9jcmVhdGVDb25kaXRpb25hbEV2ZW50KCRmaWVsZC0+Y29uZGl0aW9uYWwsICRmaWVsZC0+bmFtZSwgJGZpZWxkLT5pZCk7DQogICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICRjb25kaXRpb25hbF9jYWxsWzBdOw0KICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAkY29uZGl0aW9uYWxfY2FsbFsxXTsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+cmlnaHRjb2x1bW5hbGlnbiA9PSAwKSB7DQogICAgICAgICAgICAkYWxpZ24gPSAnbGVmdCc7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkYWxpZ24gPSAncmlnaHQnOw0KICAgICAgICB9DQogICAgICAgIGlmICgoaW50KSR0YWJsZW1vZGUtPmVuYWJsZXRhYmxlbGF5b3V0ID09IDEgJiYgKCFpc3NldCgkZmllbGQtPmJ1Y2tldCkgfHwgJGZpZWxkLT5idWNrZXQgPT0gIiIpKSB7DQogICAgICAgICAgICAkZml4ZWRfd2lkdGggPSAkdGFibGVtb2RlLT5sZWZ0Y29sdW1ud2lkdGggLSA4Ow0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRib3R0b21fbWFyZ2luX3ZhbHVlID0gaW50dmFsKCR0YWJsZW1vZGUtPm1hcmdpbmJvdHRvbSk7DQoNCg0KICAgICAgICAgICAgJGVsdCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWxhYmVsIGRlc2t0b3AtY2VsbFwiIHN0eWxlPVwid2lkdGg6eyR0YWJsZW1vZGUtPmxlZnRjb2x1bW53aWR0aH07IHBhZGRpbmctdG9wOjNweDsgZmxvYXQ6bGVmdDtcIj4mbmJzcDs8L2Rpdj4iOw0KICAgICAgICAgICAgJGVsdCAuPSAiXG48ZGl2IGNsYXNzPVwiZmItdGFibGVtb2RlLWVsZW1lbnRcIiBzdHlsZT1cIndpZHRoOnskdGFibGVtb2RlLT5yaWdodGNvbHVtbndpZHRofTsgZmxvYXQ6bGVmdDsgdGV4dC1hbGlnbjp7JGFsaWdufTsgbWFyZ2luLWJvdHRvbTp7JGJvdHRvbV9tYXJnaW5fdmFsdWV9cHg7XCIgPlxuIjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgDQoJCSRmaWVsZC0+bGFiZWwgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKChzdHJpbmcpJGZpZWxkLT5sYWJlbCwgNik7DQoNCiAgICAgICAgDQogICAgICAgICRyZWFkb25seSA9IGlzc2V0KCRyZWFkb25seSkgPyAkcmVhZG9ubHkgPT0gMSA/ICIgcmVhZG9ubHkgIiA6ICIiIDogIiI7DQogICAgICAgICRlbmFibGVkID0gaXNzZXQoJGZpZWxkZW5hYmxlZCkgPyAkZmllbGRlbmFibGVkID09IDAgPyAiIGRpc2FibGVkICIgOiAiIiA6ICIiOw0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJHJlcXVpcmVkX3RleHQgPSBpc3NldCgkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIpID8gJGZpZWxkLT5yZXF1aXJlZGZpZWxkY2hhcmFjdGVyIDogIiYjNDI7IjsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRmaWVsZHR5cGUgPT0gInNlbGVjdCIpIHsNCiAgICAgICAgICAgICRlbGVtZW50IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJGZpZWxkLT5uYW1lLCAkZmllbGQtPnZhbGlkYXRpb24tPnJlcSwgJHJlcXVpcmVkX3RleHQsICRmaWVsZC0+Y29sb3IsICRmaWVsZC0+Zm9udHNpemUsICRzdHlsZXMsICRmaWVsZC0+bGFiZWwsICRmaWVsZC0+bGFiZWxwb3MsIChzdHJpbmcpJGZpZWxkLT50eXBlLCAnJywgJycsICR0YWJsZW1vZGUpOw0KICAgICAgICB9DQoNCiAgICAgICAgJGlubGluZV9sYWJlbF9wb3MgPSAkdGhpcy0+Z2V0X2lubGluZV9sYWJlbF9wb3MoJGZpZWxkLT5sYWJlbHBvcyk7DQoNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICR0ZXh0YWxpZ25tZW50ID0gImxlZnQiOw0KICAgICAgICANCiAgICAgICAgaWYgKGlzc2V0KCRmaWVsZC0+ZWxlbWVudHBvcykgJiYgJGZpZWxkLT5lbGVtZW50cG9zICE9ICIwIikgew0KDQogICAgICAgICAgICBzd2l0Y2ggKChpbnQpJGZpZWxkLT5lbGVtZW50cG9zKSB7DQogICAgICAgICAgICAgICAgY2FzZSAwOg0KICAgICAgICAgICAgICAgICAgICAkdGV4dGFsaWdubWVudCA9ICdsZWZ0JzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAkdGV4dGFsaWdubWVudCA9ICdyaWdodCc7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIGNhc2UgMjoNCiAgICAgICAgICAgICAgICAgICAgJHRleHRhbGlnbm1lbnQgPSAnY2VudGVyJzsgDQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJGVsdCAuPSA8PDxFT1QNCg0KPD9waHANClwkX1NFU1NJT04gWyd7JGZpZWxkLT5uYW1lfSddID0gaXNzZXQgKCBcJF9TRVNTSU9OIFsneyRmaWVsZC0+bmFtZX0nXSApID8gXCRfU0VTU0lPTiBbJ3skZmllbGQtPm5hbWV9J10gOiAiIjsNCg0KaWYgKCEgaXNzZXQgKCBcJF9TRVNTSU9OIFsneyRmaWVsZC0+bmFtZX1faXMnXSApKSB7DQoJXCRfU0VTU0lPTiBbJ3skZmllbGQtPm5hbWV9X2lzJ10gPSAxOw0KfQ0KPz4NCnskY29uZGl0aW9uYWxfY2FsbF9zY3JpcHR9DQp7JGVsZW1lbnR9DQo8c3BhbiBzdHlsZT0iY2xlYXI6Ym90aDsgZmxvYXQ6eyR0ZXh0YWxpZ25tZW50fTsiPg0KRU9UOw0KDQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRmaWVsZHR5cGUgPT0gInNlbGVjdCIpIHsNCiAgICAgICAgICAgICRlbHQgLj0gIjxzZWxlY3QgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBuYW1lPVwieyRmaWVsZC0+bmFtZX1cIiBpZD1cInskZmllbGQtPmlkfVwiIHskdGFiaHRtbH0geyRmaWVsZC0+YXR0cmlidXRlc3R5bGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9ID4iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkZmllbGR0eXBlICE9ICJzZWxlY3QiKSB7DQoNCiAgICAgICAgICAgICRlbHQgLj0gIlxuPGZpZWxkc2V0IGRhdGEtcm9sZT1cImNvbnRyb2xncm91cFwiIHN0eWxlPVwiYm9yZGVyOjA7IHBhZGRpbmc6MHB4OyBtYXJnaW46MHB4O1wiPlxuIjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWx0IC49ICR0aGlzLT5faGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJGZpZWxkLT5uYW1lLCAkZmllbGQtPnZhbGlkYXRpb24tPnJlcSwgJHJlcXVpcmVkX3RleHQsICRmaWVsZC0+Y29sb3IsICRmaWVsZC0+Zm9udHNpemUsICRzdHlsZXMsICRmaWVsZC0+bGFiZWwsICRmaWVsZC0+bGFiZWxwb3MsIChzdHJpbmcpJGZpZWxkdHlwZSwgJycsICcnLCAkdGFibGVtb2RlKTsNCg0KICAgICAgICAgICAgJGVsdCAuPSAiXG48c3BhbiBjbGFzcz1cImZiLW11bHRpc2VsZWN0LWNvbHVtbiByYWRpby1jb2x1bW5cIj5cbiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgZm9yZWFjaCAoJGZpZWxkLT5zZWxlY3RpdGVtcyBhcyAka2V5ID0+ICR2YWwpIHsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkbGFiZWwgPSAieyR2YWwtPm5hbWV9IC0geyRjdXJyZW5jeX08P3BocCBlY2hvIHJlcGxhY2VFY29tbVByaWNlVG9rZW5zKCd7JHZhbC0+cHJpY2V9Jyk7ID8+IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoJHZhbC0+c2VsZWN0ZWQgPT0gMSkgew0KICAgICAgICAgICAgICAgICRleHRyYSA9ICIgfHwgXCRfU0VTU0lPTiBbJ3skZmllbGQtPm5hbWV9X2lzJ10gPT0gMSI7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRleHRyYSA9ICIiOw0KICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICAkZm9udHNpemUgPSAkZmllbGQtPmZvbnRzaXplOw0KDQogICAgICAgICAgICAkY3QxID0gc3Vic3RyX2NvdW50KChzdHJpbmcpJGZvbnRzaXplLCAncHQnKTsNCiAgICAgICAgICAgICRjdDIgPSBzdWJzdHJfY291bnQoKHN0cmluZykkZm9udHNpemUsICdweCcpOw0KDQogICAgICAgICAgICBpZiAoJGN0MSA9PSAwICYmICRjdDIgPT0gMCkgew0KICAgICAgICAgICAgICAgICRmb250c2l6ZSA9ICRmb250c2l6ZSAuICdweCc7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgaWYgKCRmaWVsZHR5cGUgPT0gInNlbGVjdCIpIHsNCg0KICAgICAgICAgICAgICAgICRlbHQgLj0gPDw8RE9DDQoNCjxvcHRpb24gdmFsdWU9InskdmFsLT5uYW1lfSINCgk8P3BocA0KCWlmKFwkX1NFU1NJT05bJ3skZmllbGQtPm5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlKCJ7JHZhbC0+bmFtZX0iLCBFTlRfUVVPVEVTKSB7JGV4dHJhfSkgew0KCQllY2hvICdzZWxlY3RlZD0ic2VsZWN0ZWQiJzsNCgl9DQoJPz4gPnskbGFiZWx9PC9vcHRpb24+DQpET0M7DQogICAgICAgICAgICB9IGVsc2UgeyANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNCjxkaXYgY2xhc3M9Im11bHRpc2VsZWN0LWl0ZW0gZmllbGQiIHN0eWxlPSJtYXJnaW46MXB4OyBjbGVhcjpib3RoOyBhbGlnbjpsZWZ0OyI+DQo8aW5wdXQgdHlwZT0ieyRmaWVsZHR5cGV9IiBuYW1lPSJ7JGZpZWxkLT5uYW1lfXskZmllbGRhcnJheX0iIGlkPSJ7JGZpZWxkLT5uYW1lfXskdmFsLT5pZH0iIHskdGFiaHRtbH0gdmFsdWU9InskdmFsLT5uYW1lfSINCjw/cGhwDQppZiAoXCRfU0VTU0lPTiBbJ3skZmllbGQtPm5hbWV9J10gPT0gaHRtbF9lbnRpdHlfZGVjb2RlICggInskdmFsLT5uYW1lfSIsIEVOVF9RVU9URVMgKSB7JGV4dHJhfSkgew0KCQkJZWNobyAnY2hlY2tlZD0iY2hlY2tlZCInOw0KfQ0KPz4NCnskZmllbGQtPmF0dHJpYnV0ZX0geyRmaWVsZC0+YXR0cmlidXRlc3R5bGV9IHskY29uZGl0aW9uYWxfY2FsbF9pbmxpbmV9IHskZW5hYmxlZH0geyRyZWFkb25seX0gLz4NCjxsYWJlbCBjbGFzcz0icmYtbXVsdGlzZWxlY3QtaXRlbS1sYWJlbCIgZm9yPSJ7JGZpZWxkLT5uYW1lfXskdmFsLT5pZH0iIHN0eWxlPSJjb2xvcjp7JGZpZWxkLT5jb2xvcn07IGZvbnQtc2l6ZTp7JGZvbnRzaXplfTsiPnskbGFiZWx9PC9sYWJlbD4geyRpbmxpbmVfbGFiZWxfcG9zfQ0KPC9kaXY+DQoNCkVPRjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJGZpZWxkdHlwZSAhPSAic2VsZWN0Iikgew0KICAgICAgICAgICAgJGVsdCAuPSA8PDxFT0YNCg0KCQk8L3NwYW4+DQoJPHNwYW4gY2xhc3M9ImZiLWNoZWNrYm94LWNsZWFyIiBzdHlsZT0iY2xlYXI6Ym90aDsiPjwvc3Bhbj4NCjwvZmllbGRzZXQ+DQoJDQpFT0Y7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCRmaWVsZHR5cGUgPT0gInNlbGVjdCIpIHsNCiAgICAgICAgICAgICRlbHQgLj0gIjwvc2VsZWN0PiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGVsdCAuPSAnPC9zcGFuPic7DQoNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgJG1heF9xdWFudGl0eSA9IDMxOw0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPnF1YW50aXR5X21heCkpIHsNCiAgICAgICAgICAgICRtYXhfcXVhbnRpdHkgPSBpbnR2YWwoJGZpZWxkLT5xdWFudGl0eV9tYXgpICsgMTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGQtPnF1YW50aXR5KSAmJiAkZmllbGQtPnF1YW50aXR5ICE9ICIwIikgew0KDQogICAgICAgICAgICAkX2UgPSA8PDxFT0YNCgkJCQ0KPGRpdiBzdHlsZT0id2lkdGg6MTAwJTsgY2xlYXI6Ym90aDsgaGVpZ2h0OjEwcHgiPjwvZGl2Pg0KDQo8bGFiZWwgZm9yPSJ7JGZpZWxkLT5uYW1lfS1xdWFudGl0eSI+eyRmaWVsZC0+cXVhbnRpdHlfbGFiZWx9DQo8c2VsZWN0IGNsYXNzPSJmb3JtLWNvbnRyb2wiIG5hbWU9InskZmllbGQtPm5hbWV9LXF1YW50aXR5IiBpZD0ieyRmaWVsZC0+bmFtZX0tcXVhbnRpdHkiIHN0eWxlPSIiPg0KCTw/cGhwIA0KCQlmb3IoXCRxID0gMTsgXCRxIDwgeyRtYXhfcXVhbnRpdHl9OyBcJHErKyl7DQoJCQlcJF9ja2QgPSAiIjsNCgkJCWlmIChpc3NldChcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfS1xdWFudGl0eSddKSAmJiBcJF9TRVNTSU9OWyd7JGZpZWxkLT5uYW1lfS1xdWFudGl0eSddID09IFwkcSkgew0KCQkJCVwkX2NrZCA9ICcgc2VsZWN0ZWQ9InNlbGVjdGVkIiAnOw0KCQkJfQ0KCQkJZWNobyAnPG9wdGlvbiB2YWx1ZT0iJyAuIFwkcSAuICciJyAuIFwkX2NrZCAuJz4nIC4gXCRxIC4gJzwvb3B0aW9uPic7DQoJCX0NCgk/Pg0KPC9zZWxlY3Q+PC9sYWJlbD4NCgkJDQpFT0Y7DQoNCiAgICAgICAgICAgICRlbHQgLj0gJF9lOw0KICAgICAgICB9IA0KDQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSAmJiAoIWlzc2V0KCRmaWVsZC0+YnVja2V0KSB8fCAkZmllbGQtPmJ1Y2tldCA9PSAiIikpIHsNCiAgICAgICAgICAgICRlbHQgLj0gIjwvZGl2PiI7DQogICAgICAgIH0NCg0KDQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0NCg0KDQogICAgDQogICAgcHJpdmF0ZSBmdW5jdGlvbiBfaGVscGVyX2ZpZWxkX2xhYmVsKCRmaWVsZCwgJG5hbWUsICRyZXEsICRyZXF1aXJlZF90ZXh0LCAkY29sb3IsICRmb250c2l6ZSwgJHN0eWxlcywgJGxhYmVsLCAkbGFiZWxwb3MsICRmaWVsZF90eXBlLCAkdG9vbHRpcCwgJGxpbmVoZWlnaHQsICR0YWJsZW1vZGUpDQogICAgew0KDQogICAgICAgIGlmKCRmaWVsZF90eXBlID09IG51bGwpew0KICAgICAgICAgICAgJGZpZWxkX3R5cGUgPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmKCR0b29sdGlwID09IG51bGwpew0KICAgICAgICAgICAgJHRvb2x0aXAgPSAiIjsNCiAgICAgICAgIH0NCg0KICAgICAgICAgaWYoJGxpbmVoZWlnaHQgPT0gbnVsbCl7DQogICAgICAgICAgICAkbGluZWhlaWdodCA9ICIiOw0KICAgICAgICAgfQ0KDQogICAgICAgICRsYWJlbHBvcyA9ICR0aGlzLT5nZXRfbGFiZWxfcG9zKCRsYWJlbHBvcywgJGZpZWxkX3R5cGUpOw0KDQogICAgICAgICRlbGVtZW50ID0gIiI7DQoNCiAgICAgICAgaWYgKCRyZXEgPT0gJzEnKSB7DQoNCiAgICAgICAgICAgICRzcGFjZSA9ICIiOw0KDQogICAgICAgICAgICBpZiAoJGZpZWxkLT50eXBlICE9ICJ0ZXh0YXJlYSIpIHsNCiAgICAgICAgICAgICAgICAkc3BhY2UgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgaWYgKChzdHJpbmcpJGxhYmVsID09ICImbmJzcDsiKSB7DQogICAgICAgICAgICAgICAgJGxhYmVsID0gIiI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgIT0gInJhZGlvIiB8fCAkZmllbGQtPnR5cGUgIT0gImNoZWNrYm94Iikgew0KDQogICAgICAgICAgICAgICAgJHJlcSA9ICI8c3BhbiBjbGFzcz1cInJlcS1zdGFyXCI+eyRyZXF1aXJlZF90ZXh0fXskc3BhY2V9PC9zcGFuPiI7IA0KICAgICAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgICAgICRyZXEgPSAiPHNwYW4gY2xhc3M9XCJyZXEtc3RhclwiPnskcmVxdWlyZWRfdGV4dH17JHNwYWNlfTwvc3Bhbj4iOyANCiAgICAgICAgICAgIH0NCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICRyZXEgPSAnJzsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRsYWJlbF9iZWZvcmUgPSAkbGFiZWw7DQoNCiAgICAgICAgJGxhYmVsID0gJHRoaXMtPnV2LT5yZXBsYWNlX2FsbCgkbGFiZWwsIDYpOw0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkbGFiZWxfYmVmb3JlICE9ICRsYWJlbCkgew0KDQogICAgICAgICAgICAkZWxlbWVudCAuPSAiPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwieyRuYW1lfV9keW5fbGFiZWxcIiB2YWx1ZT1cInskbGFiZWx9XCIgLz5cbiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkdG9vbHRpcF9odG1sID0gIiI7DQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKGlzX29iamVjdCgkdG9vbHRpcCkgJiYgKHN0cmluZykkdG9vbHRpcC0+dGV4dCAhPSAiIikgew0KDQogICAgICAgICAgICBpZiAoKGludCkkdG9vbHRpcC0+ZXZlbnRzID09IDIgfHwgKGludCkkdG9vbHRpcC0+ZXZlbnRzID09IDMpIHsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfdGV4dCA9IChzdHJpbmcpJHRvb2x0aXAtPnRleHQ7DQoNCiAgICAgICAgICAgICAgICAkdG9vbHRpcF90ZXh0ID0gIiI7IA0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCA9ICImbmJzcDsiOyANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZF90eXBlKSAmJiAkZmllbGRfdHlwZSAhPSAiIiAmJiAoJGZpZWxkX3R5cGUgPT0gInJhZGlvIiB8fCAkZmllbGRfdHlwZSA9PSAiY2hlY2tib3giKSkgew0KICAgICAgICAgICAgICAgICAgICBpZiAoJGxhYmVsID09ICIiIHx8ICRsYWJlbCA9PSAiJm5ic3A7Iikgew0KICAgICAgICAgICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCA9ICIiOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICR0b29sdGlwX2h0bWwgLj0gIjxpbWcgaWQ9XCJ7JG5hbWV9LXRvb2x0aXAtYnV0dG9uXCIgY2xhc3M9XCJ7JG5hbWV9LXRvb2x0aXAtYnV0dG9uXCIgc3JjPVwiaWNvbnMvdG9vbHRpcC1idXR0b24taWNvbi5wbmdcIiB0aXRsZT1cInskdG9vbHRpcF90ZXh0fVwiIG9uY2xpY2s9XCJyZXR1cm4gZmFsc2VcIiAvPiI7DQoNCg0KICAgICAgICAgICAgICAgICR0b29sdGlwX2h0bWwgLj0gIiZuYnNwOyI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICBpZiAoJGZpZWxkLT50eXBlID09ICJ0ZXh0IiAmJiAkbGFiZWxwb3MgPT0gImZsb2F0OmxlZnQ7Iikgew0KDQogICAgICAgICAgICAkdG9vbHRpcF9odG1sID0gIiI7DQoNCiAgICAgICAgfQ0KDQoNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICAkbGluZWhlaWdodF9jc3MgPSAiIjsNCg0KICAgICAgICANCg0KICAgICAgICBpZiAoJGxhYmVscG9zID09ICJmbG9hdDpsZWZ0OyIpIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmIChpc3NldCgkbGluZWhlaWdodCkgJiYgJGxpbmVoZWlnaHQgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZF90eXBlKSAmJiAkZmllbGRfdHlwZSAhPSAiIiAmJiAoJGZpZWxkX3R5cGUgPT0gInRleHQiIHx8ICRmaWVsZF90eXBlID09ICJwYXNzd29yZCIpKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGxpbmVoZWlnaHRfY3NzID0gImxpbmUtaGVpZ2h0OiIgLiAoaW50dmFsKCRsaW5laGVpZ2h0KSArIDUpIC4gInB4OyI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkX3R5cGUpICYmICRmaWVsZF90eXBlICE9ICIiICYmICgkZmllbGRfdHlwZSA9PSAic2VsZWN0IikpIHsNCg0KICAgICAgICAgICAgICAgICAgICAkbGluZWhlaWdodF9jc3MgPSAibGluZS1oZWlnaHQ6IiAuIChpbnR2YWwoJGxpbmVoZWlnaHQpICsgMTgpIC4gInB4OyI7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmIChpc3NldCgkdGFibGVtb2RlKSAmJiBpc3NldCgkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCkgJiYgKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxKQ0KICAgICAgICAkbGFiZWxwb3MgPSAiIjsNCg0KDQogICAgICAgICR3aWR0aF9jc3MgPSAiIjsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICBpZiAoJGxhYmVsID09ICIiIHx8ICRsYWJlbCA9PSAiJm5ic3A7Iikgew0KICAgICAgICAgICAgJHdpZHRoX2NzcyA9ICJ3aWR0aDowcHg7IjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KDQogICAgICAgICRoZWlnaHRfY3NzID0gIiI7DQoNCiAgICAgICAgaWYgKCRsYWJlbCA9PSAiIiB8fCAkbGFiZWwgPT0gIiZuYnNwOyIpIHsNCiAgICAgICAgICAgICRoZWlnaHRfY3NzID0gImhlaWdodDowcHg7IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICB9DQoNCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIGlmIChpc3NldCgkZmllbGRfdHlwZSkgJiYgJGZpZWxkX3R5cGUgIT0gIiIgJiYgKCRmaWVsZF90eXBlID09ICJyYWRpbyIgfHwgJGZpZWxkX3R5cGUgPT0gImNoZWNrYm94IikpIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIGlmICgoaW50KSRmaWVsZC0+dmFsaWRhdGlvbi0+cmVxID09IDEgJiYgKCRsYWJlbCA9PSAiIiB8fCAkbGFiZWwgPT0gIiZuYnNwOyIpKSB7DQoNCiAgICAgICAgICAgICAgICAkaGVpZ2h0X2NzcyA9ICIiOw0KICAgICAgICAgICAgICAgICR3aWR0aF9jc3MgPSAiZmxvYXQ6bGVmdDsgd2lkdGg6OXB4OyI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoKCRsYWJlbCA9PSAiIiB8fCAkbGFiZWwgPT0gIiZuYnNwOyIpICYmICR0b29sdGlwX2h0bWwgIT0gIiIpIHsNCg0KICAgICAgICAgICAgICAgICRoZWlnaHRfY3NzID0gIiI7DQogICAgICAgICAgICAgICAgJHdpZHRoX2NzcyA9ICJmbG9hdDpsZWZ0OyB3aWR0aDoxNXB4OyI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJGZvbnR3ZWlnaHQgPSBpc3NldCgkc3R5bGVzWydmb250d2VpZ2h0J10pICYmICRzdHlsZXNbJ2ZvbnR3ZWlnaHQnXSAhPSAiIiA/ICRzdHlsZXNbJ2ZvbnR3ZWlnaHQnXSA6ICJub3JtYWwiOw0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgICRtZDUgPSBtZDUocmFuZCgxMDAwMCwgMTAwMDAwMDApKTsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQoJCQkNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJI2xlZ2VuZC17JG5hbWV9LXskbWQ1fSB7DQoJCXskbGFiZWxwb3N9DQoJCWNvbG9yOnskY29sb3J9OyANCgkJZm9udC1zaXplOnskZm9udHNpemV9OyANCgkJeyRsaW5laGVpZ2h0X2Nzc30gDQoJCXskd2lkdGhfY3NzfQ0KCQl7JGhlaWdodF9jc3N9DQoJCWZvbnQtd2VpZ2h0OnskZm9udHdlaWdodH07DQoJCXBhZGRpbmc6MDsgDQoJfQ0KPC9zdHlsZT4NCg0KPGxlZ2VuZCBjbGFzcz0iaGVhZGluZy1tYWluIiBpZD0ibGVnZW5kLXskbmFtZX0teyRtZDV9Ij57JGxhYmVsfXskdG9vbHRpcF9odG1sfXskcmVxfTwvbGVnZW5kPg0KPGRpdiBzdHlsZT0icG9zaXRpb246cmVsYXRpdmUiPg0KCTxkaXYgaWQ9InskbmFtZX0tdmFsaWRhdGlvbi1zdHlsZS0zLWxpbmUiIGNsYXNzPSJ2YWxpZGF0aW9uLXN0eWxlLTMtbGluZSIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPiZuYnNwOzwvZGl2Pg0KCTxkaXYgaWQ9InskbmFtZX0tdmFsaWRhdGlvbi1zdHlsZS0zLWljb24iIGNsYXNzPSJ2YWxpZGF0aW9uLXN0eWxlLTMtaWNvbiIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPiZuYnNwOzwvZGl2Pg0KCTxkaXYgaWQ9InskbmFtZX0tdmFsaWRhdGlvbi1zdHlsZS0zLW1lc3NhZ2UiIGNsYXNzPSJ2YWxpZGF0aW9uLXN0eWxlLTMtbWVzc2FnZSBlcnJvcm1zZyIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPiZuYnNwOzwvZGl2Pg0KPC9kaXY+DQoNCkVPVDsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgICRmaW5hbF9uYnNwID0gIiZuYnNwOyI7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCgkZmllbGRfdHlwZSA9PSAnc2VsZWN0JyB8fCAkZmllbGRfdHlwZSA9PSAndGV4dCcgfHwgJGZpZWxkX3R5cGUgPT0gJ3Bhc3N3b3JkJyB8fCAkZmllbGRfdHlwZSA9PSAndGV4dGFyZWEnKSAmJiAkbGFiZWwgPT0gIiZuYnNwOyIpIHsNCiAgICAgICAgICAgICAgICAkbGFiZWwgPSAiIjsNCiAgICAgICAgICAgICAgICAkZmluYWxfbmJzcCA9ICIiOw0KDQogICAgICAgICAgICAgICAgaWYgKCR0b29sdGlwID09ICIiKQ0KICAgICAgICAgICAgICAgICR0b29sdGlwX2h0bWwgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoaXNzZXQoJGZpZWxkX3R5cGUpICYmICRmaWVsZF90eXBlICE9ICIiICYmICRmaWVsZF90eXBlID09ICJjYWxlbmRhciIpIHsNCg0KICAgICAgICAgICAgICAgICRuYW1lID0gImRhdGUteyRmaWVsZC0+aWR9LTEiOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgJGVsZW1lbnQgLj0gPDw8RU9UDQo8ZGl2IHN0eWxlPSJ7JGxhYmVscG9zfSB7JGxpbmVoZWlnaHRfY3NzfSIgY2xhc3M9ImhlYWRpbmctbWFpbiI+DQoJPGxhYmVsIGFyaWEtbGFiZWw9IkZvcm0gRmllbGQgLSB7JG5hbWV9IiBmb3I9InskbmFtZX0iIHN0eWxlPSJjb2xvcjp7JGNvbG9yfTsgZm9udC1zaXplOnskZm9udHNpemV9OyB7JGxpbmVoZWlnaHRfY3NzfSB7JHdpZHRoX2Nzc30gZm9udC13ZWlnaHQ6eyRzdHlsZXNbJ2ZvbnR3ZWlnaHQnXX07ICI+eyRsYWJlbH17JHJlcX17JHRvb2x0aXBfaHRtbH17JGZpbmFsX25ic3B9PC9sYWJlbD4NCgk8ZGl2IHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZSI+DQoJCTxkaXYgaWQ9InskbmFtZX0tdmFsaWRhdGlvbi1zdHlsZS0zLWxpbmUiIGNsYXNzPSJ2YWxpZGF0aW9uLXN0eWxlLTMtbGluZSIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPiZuYnNwOzwvZGl2Pg0KCQk8ZGl2IGlkPSJ7JG5hbWV9LXZhbGlkYXRpb24tc3R5bGUtMy1pY29uIiBjbGFzcz0idmFsaWRhdGlvbi1zdHlsZS0zLWljb24iIHN0eWxlPSJkaXNwbGF5Om5vbmU7Ij4mbmJzcDs8L2Rpdj4NCgkJPGRpdiBpZD0ieyRuYW1lfS12YWxpZGF0aW9uLXN0eWxlLTMtbWVzc2FnZSIgY2xhc3M9InZhbGlkYXRpb24tc3R5bGUtMy1tZXNzYWdlIGVycm9ybXNnIiBzdHlsZT0iZGlzcGxheTpub25lOyI+Jm5ic3A7PC9kaXY+DQoJPC9kaXY+DQo8L2Rpdj4NCkVPVDsNCiAgICAgICAgfSANCg0KICAgICAgICANCg0KICAgICAgICByZXR1cm4gJGVsZW1lbnQ7DQogICAgfQ0KDQogICAgDQogICAgZnVuY3Rpb24gX2hlbHBlcl9maWVsZF9sYWJlbF9odG1sX29ubHkoJGZpZWxkLCAkdGFibGVtb2RlKQ0KICAgIHsNCg0KICAgICAgICAkbmFtZSA9ICRmaWVsZC0+bmFtZTsNCiAgICAgICAgJHJlcSA9ICRmaWVsZC0+cmVxOw0KICAgICAgICAkcmVxdWlyZWRfdGV4dCA9ICRmaWVsZC0+dmFsaWRhdGlvbi0+cmVxOw0KICAgICAgICAkY29sb3IgPSAkZmllbGQtPmNvbG9yOw0KICAgICAgICAkZm9udHNpemUgPSAkZmllbGQtPmZvbnRzaXplOw0KICAgICAgICAkc3R5bGVzID0gJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRmaWVsZC0+c3R5bGUpOw0KICAgICAgICAkbGFiZWwgPSAkZmllbGQtPmxhYmVsOw0KICAgICAgICAkbGFiZWxwb3MgPSAkZmllbGQtPmxhYmVscG9zOw0KICAgICAgICAkZmllbGRfdHlwZSA9IChzdHJpbmcpJGZpZWxkLT50eXBlOw0KICAgICAgICAkdG9vbHRpcCA9ICRmaWVsZC0+dG9vbHRpcDsNCiAgICAgICAgJGxpbmVoZWlnaHQgPSAkZmllbGQtPmZpZWxkaGVpZ2h0Ow0KDQoNCiAgICAgICAgJGxhYmVscG9zID0gJHRoaXMtPmdldF9sYWJlbF9wb3MoJGxhYmVscG9zLCAkZmllbGRfdHlwZSk7DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICBpZiAoJHJlcSA9PSAnMScpIHsNCg0KICAgICAgICAgICAgJHNwYWNlID0gIiI7DQoNCiAgICAgICAgICAgIGlmICgkZmllbGQtPnR5cGUgIT0gInRleHRhcmVhIikgew0KICAgICAgICAgICAgICAgICRzcGFjZSA9ICIiOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoKHN0cmluZykkbGFiZWwgPT0gIiZuYnNwOyIpIHsNCiAgICAgICAgICAgICAgICAkbGFiZWwgPSAiIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgaWYgKCRmaWVsZC0+dHlwZSAhPSAicmFkaW8iIHx8ICRmaWVsZC0+dHlwZSAhPSAiY2hlY2tib3giKSB7DQoNCiAgICAgICAgICAgICAgICAkcmVxID0gIjxzcGFuIGNsYXNzPVwicmVxLXN0YXJcIj57JHJlcXVpcmVkX3RleHR9eyRzcGFjZX08L3NwYW4+IjsgDQogICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgJHJlcSA9ICI8c3BhbiBjbGFzcz1cInJlcS1zdGFyXCI+eyRyZXF1aXJlZF90ZXh0fXskc3BhY2V9PC9zcGFuPiI7IA0KICAgICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHJlcSA9ICcnOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGxhYmVsX2JlZm9yZSA9ICRsYWJlbDsNCg0KICAgICAgICAkbGFiZWwgPSAkdGhpcy0+dXYtPnJlcGxhY2VfYWxsKCRsYWJlbCwgNik7DQoNCiAgICAgICAgJGxpbmVoZWlnaHRfY3NzID0gIiI7DQoNCiAgICAgICAgDQoNCiAgICAgICAgaWYgKCRsYWJlbHBvcyA9PSAiZmxvYXQ6bGVmdDsiKSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoaXNzZXQoJGxpbmVoZWlnaHQpICYmICRsaW5laGVpZ2h0ICE9ICIiKSB7DQoNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGRfdHlwZSkgJiYgJGZpZWxkX3R5cGUgIT0gIiIgJiYgKCRmaWVsZF90eXBlID09ICJ0ZXh0IiB8fCAkZmllbGRfdHlwZSA9PSAicGFzc3dvcmQiKSkgew0KDQogICAgICAgICAgICAgICAgICAgICRsaW5laGVpZ2h0X2NzcyA9ICJsaW5lLWhlaWdodDoiIC4gKGludHZhbCgkbGluZWhlaWdodCkgKyA1KSAuICJweDsiOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7IA0KDQogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRmaWVsZF90eXBlKSAmJiAkZmllbGRfdHlwZSAhPSAiIiAmJiAoJGZpZWxkX3R5cGUgPT0gInNlbGVjdCIpKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJGxpbmVoZWlnaHRfY3NzID0gImxpbmUtaGVpZ2h0OiIgLiAoaW50dmFsKCRsaW5laGVpZ2h0KSArIDE4KSAuICJweDsiOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJHRhYmxlbW9kZSkgJiYgaXNzZXQoJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQpICYmIChpbnQpJHRhYmxlbW9kZS0+ZW5hYmxldGFibGVsYXlvdXQgPT0gMSkNCiAgICAgICAgJGxhYmVscG9zID0gIiI7DQoNCg0KICAgICAgICAkd2lkdGhfY3NzID0gIiI7DQoNCiAgICAgICAgaWYgKCRsYWJlbCA9PSAiIiB8fCAkbGFiZWwgPT0gIiZuYnNwOyIpIHsNCiAgICAgICAgICAgICR3aWR0aF9jc3MgPSAid2lkdGg6MHB4OyI7DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICAkaGVpZ2h0X2NzcyA9ICIiOw0KDQogICAgICAgIGlmICgkbGFiZWwgPT0gIiIgfHwgJGxhYmVsID09ICImbmJzcDsiKSB7DQogICAgICAgICAgICAkaGVpZ2h0X2NzcyA9ICJoZWlnaHQ6MHB4OyI7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJGZpZWxkX3R5cGUpICYmICRmaWVsZF90eXBlICE9ICIiICYmICgkZmllbGRfdHlwZSA9PSAicmFkaW8iIHx8ICRmaWVsZF90eXBlID09ICJjaGVja2JveCIpKSB7DQoNCiAgICAgICAgICAgIGlmICgoJGxhYmVsID09ICIiIHx8ICRsYWJlbCA9PSAiJm5ic3A7IikgJiYgJHRvb2x0aXBfaHRtbCAhPSAiIikgew0KDQogICAgICAgICAgICAgICAgJGhlaWdodF9jc3MgPSAiIjsNCiAgICAgICAgICAgICAgICAkd2lkdGhfY3NzID0gImZsb2F0OmxlZnQ7IHdpZHRoOjE1cHg7IjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJGZpbmFsX25ic3AgPSAiJm5ic3A7IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICAkZWxlbWVudCAuPSA8PDxFT1QNCjxkaXYgc3R5bGU9InskbGFiZWxwb3N9IHskbGluZWhlaWdodF9jc3N9IiBjbGFzcz0iaGVhZGluZy1tYWluIj4NCgk8bGFiZWwgYXJpYS1sYWJlbD0iRm9ybSBGaWVsZCBGb3IgJHtuYW1lfSIgZm9yPSJ7JG5hbWV9IiBzdHlsZT0iY29sb3I6eyRjb2xvcn07IGZvbnQtc2l6ZTp7JGZvbnRzaXplfTsgeyRsaW5laGVpZ2h0X2Nzc30geyR3aWR0aF9jc3N9IGZvbnQtd2VpZ2h0Onskc3R5bGVzWydmb250d2VpZ2h0J119OyAiPnskbGFiZWx9eyRmaW5hbF9uYnNwfTwvbGFiZWw+DQo8L2Rpdj4NCkVPVDsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgJGZpbmFsX25ic3AgPSAiJm5ic3A7IjsNCg0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZiAoKCRmaWVsZF90eXBlID09ICdzZWxlY3QnIHx8ICRmaWVsZF90eXBlID09ICd0ZXh0JyB8fCAkZmllbGRfdHlwZSA9PSAncGFzc3dvcmQnIHx8ICRmaWVsZF90eXBlID09ICd0ZXh0YXJlYScpICYmICRsYWJlbCA9PSAiJm5ic3A7Iikgew0KICAgICAgICAgICAgICAgICRsYWJlbCA9ICIiOw0KICAgICAgICAgICAgICAgICRmaW5hbF9uYnNwID0gIiI7DQoNCiAgICAgICAgICAgICAgICBpZiAoJHRvb2x0aXAgPT0gIiIpDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCA9ICIiOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIGlmIChpc3NldCgkZmllbGRfdHlwZSkgJiYgJGZpZWxkX3R5cGUgIT0gIiIgJiYgJGZpZWxkX3R5cGUgPT0gImNhbGVuZGFyIikgew0KDQogICAgICAgICAgICAgICAgJG5hbWUgPSAiZGF0ZS17JGZpZWxkLT5pZH0tMSI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICRlbGVtZW50IC49IDw8PEVPVA0KPGRpdiBzdHlsZT0ieyRsYWJlbHBvc30geyRsaW5laGVpZ2h0X2Nzc30iIGNsYXNzPSJoZWFkaW5nLW1haW4iPg0KCTxsYWJlbCBhcmlhLWxhYmVsPSJGb3JtIEZpZWxkIC0geyRuYW1lfSIgZm9yPSJ7JG5hbWV9IiBzdHlsZT0iY29sb3I6eyRjb2xvcn07IGZvbnQtc2l6ZTp7JGZvbnRzaXplfTsgeyRsaW5laGVpZ2h0X2Nzc30geyR3aWR0aF9jc3N9IGZvbnQtd2VpZ2h0Onskc3R5bGVzWydmb250d2VpZ2h0J119OyAiPnskbGFiZWx9eyRmaW5hbF9uYnNwfTwvbGFiZWw+DQo8L2Rpdj4NCkVPVDsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkZWxlbWVudDsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfdG9vbHRpcF9odG1sKCR0b29sdGlwLCAkbmFtZSkNCiAgICB7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHRvb2x0aXBfaHRtbCA9ICIiOw0KDQogICAgICAgIGlmICgkdG9vbHRpcCAhPSAiIikgew0KDQogICAgICAgICAgICBpZiAoKGludCkkdG9vbHRpcC0+ZXZlbnRzID09IDIgfHwgKGludCkkdG9vbHRpcC0+ZXZlbnRzID09IDMpIHsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfdGV4dCA9ICR0b29sdGlwLT50ZXh0Ow0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfdGV4dCA9ICIiOyANCg0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCA9ICImbmJzcDsiOw0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCAuPSAiPGltZyBpZD1cInskbmFtZX0tdG9vbHRpcC1idXR0b25cIiBjbGFzcz1cInskbmFtZX0tdG9vbHRpcC1idXR0b24gdG9vbHRpcC1idXR0b25cIiBzcmM9XCJpY29ucy90b29sdGlwLWJ1dHRvbi1pY29uLnBuZ1wiIHRpdGxlPVwieyR0b29sdGlwX3RleHR9XCIgb25jbGljaz1cInJldHVybiBmYWxzZVwiIC8+IjsNCg0KDQogICAgICAgICAgICAgICAgJHRvb2x0aXBfaHRtbCAuPSAiJm5ic3A7IjsNCg0KICAgICAgICAgICAgICAgIHJldHVybiAkdG9vbHRpcF9odG1sOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV90YWJsZV9tb2RlX21vYmlsZV9sYWJlbCgkZmllbGQsICR0YWJsZW1vZGUpDQogICAgew0KDQogICAgICAgIA0KDQogICAgICAgICRsYWJlbCA9ICRmaWVsZC0+eydsYWJlbCd9Ow0KICAgICAgICAkbGFiZWxwb3MgPSAkZmllbGQtPmxhYmVscG9zOw0KDQogICAgICAgIA0KDQogICAgICAgIGlmICgkbGFiZWwgPT0gIiIpIHsNCiAgICAgICAgICAgICRsYWJlbCA9ICImbmJzcDsiOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVsZW1lbnQgPSAiIjsNCg0KICAgICAgICANCg0KICAgICAgICBpZiAoKGludCkkdGFibGVtb2RlLT5lbmFibGV0YWJsZWxheW91dCA9PSAxICYmICghaXNzZXQoJGZpZWxkLT5idWNrZXQpIHx8ICRmaWVsZC0+YnVja2V0ID09ICIiKSkgew0KDQogICAgICAgICAgICAkcmVxdWlyZWRfdGV4dCA9IGlzc2V0KCRmaWVsZC0+cmVxdWlyZWRmaWVsZGNoYXJhY3RlcikgPyAkZmllbGQtPnJlcXVpcmVkZmllbGRjaGFyYWN0ZXIgOiAiJiM0MjsiOw0KDQogICAgICAgICAgICBpZiAoKHN0cmluZykkbGFiZWwgIT0gIiZuYnNwOyIgfHwgJHRoaXMtPmdldF9sYWJlbF9wb3MoJGxhYmVscG9zLCAoc3RyaW5nKSRmaWVsZC0+dHlwZSkgIT0gImZsb2F0OmxlZnQ7Iikgew0KDQogICAgICAgICAgICAgICAgJGVsZW1lbnQgLj0gIlxuPHNwYW4gY2xhc3M9XCJtb2JpbGUtYmxvY2tcIj5cbiI7DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAkdGhpcy0+X2hlbHBlcl9maWVsZF9sYWJlbCgNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkLA0KICAgICAgICAgICAgICAgICAgICAkZmllbGQtPm5hbWUsDQogICAgICAgICAgICAgICAgICAgICRmaWVsZC0+dmFsaWRhdGlvbi0+cmVxLA0KICAgICAgICAgICAgICAgICAgICAkcmVxdWlyZWRfdGV4dCwNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkLT5jb2xvciwNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkLT5mb250c2l6ZSwNCiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPnRyYW5zbGF0ZUZpZWxkU3R5bGVzKCRmaWVsZC0+c3R5bGUpLA0KICAgICAgICAgICAgICAgICAgICAkbGFiZWwsDQogICAgICAgICAgICAgICAgICAgICRsYWJlbHBvcywNCiAgICAgICAgICAgICAgICAgICAgKHN0cmluZykkZmllbGQtPnR5cGUsDQogICAgICAgICAgICAgICAgICAgICRmaWVsZC0+dG9vbHRpcCwNCiAgICAgICAgICAgICAgICAgICAgJGZpZWxkLT5maWVsZGhlaWdodCwNCiAgICAgICAgICAgICAgICAgICAgJHRhYmxlbW9kZQ0KICAgICAgICAgICAgICAgICk7DQoNCiAgICAgICAgICAgICAgICAkZWxlbWVudCAuPSAiXG48L3NwYW4+XG4iOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRlbGVtZW50Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRfbGFiZWxfcG9zKCRsYWJlbHBvcywgJGZpZWxkX3R5cGUgPSAiIikNCiAgICB7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBpZiAoJGZpZWxkX3R5cGUgPT0gImNoZWNrYm94IiB8fCAkZmllbGRfdHlwZSA9PSAicmFkaW8iKSB7DQogICAgICAgICAgICAkbGFiZWxwb3MgPSAiIjsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHN3aXRjaCAoJGxhYmVscG9zKSB7DQogICAgICAgICAgICAgICAgY2FzZSAnMCc6IA0KICAgICAgICAgICAgICAgICAgICAkbGFiZWxwb3MgPSAnJzsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgY2FzZSAnMSc6IA0KICAgICAgICAgICAgICAgICAgICAkbGFiZWxwb3MgPSAnZmxvYXQ6bGVmdDsnOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkbGFiZWxwb3M7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGdldF9pbmxpbmVfbGFiZWxfcG9zKCRsYWJlbHBvcykNCiAgICB7DQogICAgICAgIHN3aXRjaCAoJGxhYmVscG9zKSB7DQogICAgICAgICAgICBjYXNlICcwJzogDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgaWYgKCFkZWZpbmVkKCdNT0JJTEVfTU9ERScpKSB7DQogICAgICAgICAgICAgICAgICAgICRsYWJlbHBvcyA9ICc8YnIvPic7DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgJGxhYmVscG9zID0gJyc7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6IA0KICAgICAgICAgICAgICAgICRsYWJlbHBvcyA9ICcnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkbGFiZWxwb3M7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gcmVwbGFjZV9jb25kaXRpb25fdmFycygkY29uZGl0aW9uKQ0KICAgIHsNCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgJGNvbmRpdGlvbiA9IChzdHJpbmcpJGNvbmRpdGlvbjsNCg0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pKCNceyguKj8pXH0pLycsICRjb25kaXRpb24sICRtYXRjaGVzKTsNCg0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRjb25kaXRpb24gPSBzdHJfcmVwbGFjZSgnI3snIC4gJG0gLiAnfScsICJpc3NldChcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRtfSddKSAmJiBcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRtfSddIiwgJGNvbmRpdGlvbik7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbiA9ICR0aGlzLT51di0+cmVwbGFjZV9hbGwoJGNvbmRpdGlvbiwgNC4xKTsNCg0KICAgICAgICByZXR1cm4gJGNvbmRpdGlvbjsNCiAgICB9DQoNCg0KDQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiByZXR1cm5fYnl0ZXMoJHZhbCkNCiAgICB7DQogICAgICAgICR2YWwgPSB0cmltKCR2YWwpOw0KICAgICAgICANCiAgICAgICAgJGxhc3QgPSBzdHJ0b2xvd2VyKCR2YWxbc3RybGVuKCR2YWwpIC0gMV0pOw0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgkbGFzdCkgew0KICAgICAgICAgICAgY2FzZSAoJGxhc3QgPT0gJ2cnIHx8ICRsYXN0ID09ICdHJykgOg0KICAgICAgICAgICAgICAgICR2YWwgPSAkdmFsICogKDEwMjQgKiAxMDI0ICogMTAyNCk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICgkbGFzdCA9PSAnbScgfHwgJGxhc3QgPT0gJ00nKSA6DQogICAgICAgICAgICAgICAgJHZhbCA9ICR2YWwgKiAoMTAyNCAqIDEwMjQpOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAoJGxhc3QgPT0gJ2snIHx8ICRsYXN0ID09ICdLJyk6DQogICAgICAgICAgICAgICAgJHZhbCA9ICR2YWwgKiAxMDI0Ow0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdCA6IA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICR2YWwgPSAkdmFsOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICR2YWw7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIHJldHVybl9mb250KCR2YWx1ZSkNCiAgICB7DQogICAgICAgICRmYW1pbHkgPSAnJzsNCiAgICAgICAgc3dpdGNoICgkdmFsdWUpIHsNCiAgICAgICAgICAgIGNhc2UgJzAnOg0KICAgICAgICAgICAgICAgICRmYW1pbHkgPSAnRGVqYVZ1IFNhbnMsIEdlbmV2YSwgQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZic7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxJzoNCiAgICAgICAgICAgICAgICAkZmFtaWx5ID0gJ0RlamFWdSBTYW5zLCBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRmYW1pbHkgPSAiRGVqYVZ1IFNhbnMsICdUaW1lcyBOZXcgUm9tYW4nLCBUaW1lcywgc2VyaWYiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMyc6DQogICAgICAgICAgICAgICAgJGZhbWlseSA9ICJEZWphVnUgU2FucywgJ0NvdXJpZXIgTmV3JywgQ291cmllciwgbW9ub3NwYWNlIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzQnOg0KICAgICAgICAgICAgICAgICRmYW1pbHkgPSAnRGVqYVZ1IFNhbnMsIFZlcmRhbmEsIEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWYnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNSc6DQogICAgICAgICAgICAgICAgJGZhbWlseSA9ICdEZWphVnUgU2FucywgQ29taWMgU2FucyBNUyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc2JzoNCiAgICAgICAgICAgICAgICAkZmFtaWx5ID0gJ0RlamFWdSBTYW5zLCBUYWhvbWEnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNyc6DQogICAgICAgICAgICAgICAgJGZhbWlseSA9ICdEZWphVnUgU2FucywgVHJlYnVjaGV0IE1TLEhlbHZldGljYSxzYW5zLXNlcmlmJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzgnOg0KICAgICAgICAgICAgICAgICRmYW1pbHkgPSAnRGVqYVZ1IFNhbnMsIEx1Y2lkYSBHcmFuZGUsSGVsdmV0aWNhLHNhbnMtc2VyaWYnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnOSc6DQogICAgICAgICAgICAgICAgJGZhbWlseSA9ICJEZWphVnUgU2FucywgJ015cmlhZCcsJ015cmlhZCBQcm8nLCdMdWNpZGEgR3JhbmRlJywnTHVjaWRhIFNhbnMgVW5pY29kZScsVmVyZGFuYSI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBkZWZhdWx0OiANCiAgICAgICAgICAgICAgICAkZmFtaWx5ID0gJHZhbHVlOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkZmFtaWx5Ow0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiB0cmFuc2xhdGVDb25kaXRpb25hbEV2ZW50KCRldmVudCkNCiAgICB7DQogICAgICAgICRlbHQgPSAiJyciOw0KICAgICAgICBzd2l0Y2ggKCRldmVudCkgew0KICAgICAgICAgICAgY2FzZSAnMCc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICcnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICdvbmNsaWNrJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnb25ibHVyJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzMnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnb25jaGFuZ2UnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICdvbmtleXVwJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzUnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnb25tb3VzZW92ZXInOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNic6DQogICAgICAgICAgICAgICAgJGVsdCA9ICdvbm1vdXNlb3V0JzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJGVsdDsNCiAgICB9DQoNCiAgICANCiAgICANCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gdHJhbnNsYXRlQ29uZGl0aW9uYWxBamF4RXZlbnQoJGV2ZW50KQ0KICAgIHsNCiAgICAgICAgJGVsdCA9ICInJyI7DQogICAgICAgIHN3aXRjaCAoJGV2ZW50KSB7DQogICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gJyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gJ2NsaWNrJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnYmx1cic7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICczJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gJ2NoYW5nZSc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc0JzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gJ2tleXVwJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzUnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnbW91c2VvdmVyJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzYnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAnbW91c2VvdXQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiB0cmFuc2xhdGVDb25kaXRpb25hbEFuaW1hdGlvbigkYW5pbWF0aW9uKQ0KICAgIHsNCiAgICAgICAgJGVsdCA9ICInJyI7DQogICAgICAgIHN3aXRjaCAoJGFuaW1hdGlvbikgew0KICAgICAgICAgICAgY2FzZSAnMCc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInJyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gIidmYWRlJyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcyJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gIidibGluZCciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiB0cmFuc2xhdGVDb25kaXRpb25hbENvbmRpdGlvbigkY29uZGl0aW9uKQ0KICAgIHsNCiAgICAgICAgJGVsdCA9ICInJyI7DQogICAgICAgIHN3aXRjaCAoJGNvbmRpdGlvbikgew0KICAgICAgICAgICAgY2FzZSAnMSc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInIT0nIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJz09JyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICczJzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gIic8JyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc0JzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gIic+JyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICc1JzoNCiAgICAgICAgICAgICAgICAkZWx0ID0gIic8PSciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNic6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInPj0nIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzcnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ2NoZWNrZWQnIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzgnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ3VuY2hlY2tlZCciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnOSc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInY2xpY2tlZCciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnMTAnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ25vdGJsYW5rJyI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICcxMSc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInYmxhbmsnIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJGVsdDsNCiAgICB9DQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gdHJhbnNsYXRlQ29uZGl0aW9uYWxBY3Rpb24oJGFjdGlvbikNCiAgICB7DQogICAgICAgICRlbHQgPSAiJyciOw0KICAgICAgICBzd2l0Y2ggKCRhY3Rpb24pIHsNCiAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ2hpZGUnIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzInOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ3Nob3cnIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzMnOg0KICAgICAgICAgICAgICAgICRlbHQgPSAiJ2VuYWJsZSciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNCc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInZGlzYWJsZSciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnNSc6DQogICAgICAgICAgICAgICAgJGVsdCA9ICInbWFrZSByZXF1aXJlZCciOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkZWx0Ow0KICAgIH0NCg0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gdHJhbnNsYXRlRmllbGRTdHlsZXMoJHN0eWxlKQ0KICAgIHsNCiAgICAgICAgJHN0eWxlcyA9IGFycmF5KCk7DQoNCiAgICAgICAgDQogICAgICAgIHN3aXRjaCAoJHN0eWxlLT5mb250d2VpZ2h0KSB7DQogICAgICAgICAgICBjYXNlICcwJzoNCiAgICAgICAgICAgICAgICAkc3R5bGVzWydmb250d2VpZ2h0J10gPSAnJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJzEnOg0KICAgICAgICAgICAgICAgICRzdHlsZXNbJ2ZvbnR3ZWlnaHQnXSA9ICdib2xkJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAkc3R5bGVzOw0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9jdXN0b21fY3NzX2Jsb2NrKCRpZCwgJGN1c3RvbV9jc3MpDQogICAgew0KDQogICAgICAgIA0KICAgICAgICBpZiAoaXNzZXQoJGN1c3RvbV9jc3MtPmFsbCkgJiYgJGN1c3RvbV9jc3MtPmFsbCAhPSAiIikgew0KDQogICAgICAgICAgICAkaHRtbCA9ICJcblxuIiAuICRjdXN0b21fY3NzLT5hbGwgLiAiXG5cbiI7DQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgaWYgKCFpc3NldCgkY3VzdG9tX2Nzcy0+bm9ybWFsKSkNCiAgICAgICAgICAgIHJldHVybiAnJzsNCg0KICAgICAgICAgICAgJGh0bWwgPSA8PDxFT0YNClxyXG48c3R5bGUgdHlwZT0idGV4dC9jc3MiIHNjb3BlZD4NCg0KI3skaWR9ew0KeyRjdXN0b21fY3NzLT5ub3JtYWx9DQp9DQoNCiN7JGlkfTpob3ZlcnsNCnskY3VzdG9tX2Nzcy0+b3Zlcn0NCn0NCg0KI3skaWR9OmZvY3Vzew0KeyRjdXN0b21fY3NzLT5mb2N1c30NCn0NCg0KPC9zdHlsZT4NCgkJDQpFT0Y7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQogICAgICAgICRodG1sID0gc3RyX3JlcGxhY2UoJy8qIFRoaXMgYnV0dG9uIHdhcyBnZW5lcmF0ZWQgdXNpbmcgQ1NTQnV0dG9uR2VuZXJhdG9yLmNvbSAqLycsICcnLCAkaHRtbCk7DQoNCg0KICAgICAgICByZXR1cm4gJGh0bWw7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gdHJhbnNsYXRlVG9vbHRpcCgkdG9vbHRpcCwgJGlkKQ0KICAgIHsNCg0KICAgICAgICBpZiAoJHRvb2x0aXAtPnRleHQgPT0gIiIpIHsNCiAgICAgICAgICAgICR0b29sdGlwX29iaiA9IG5ldyBzdGRDbGFzcygpOw0KICAgICAgICAgICAgJHRvb2x0aXBfb2JqLT50ZXh0ID0gIiI7DQogICAgICAgICAgICAkdG9vbHRpcF9vYmotPmpzID0gIiI7DQogICAgICAgICAgICByZXR1cm4gJHRvb2x0aXBfb2JqOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRvb2x0aXBfb2JqID0gbmV3IHN0ZENsYXNzKCk7DQoNCiAgICAgICAgDQogICAgICAgICR0b29sdGlwX29iai0+dGV4dCA9IChzdHJpbmcpJHRvb2x0aXAtPnRleHQ7DQoNCiAgICAgICAgJHBvc2l0aW9uID0gImNlbnRlciByaWdodCI7IA0KDQogICAgICAgIHN3aXRjaCAoJHRvb2x0aXAtPnBvc2l0aW9uKSB7DQogICAgICAgICAgICBjYXNlICIwIjoNCiAgICAgICAgICAgICAgICAkcG9zaXRpb24gPSAidG9wIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjEiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJ0b3AtY2VudGVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjIiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJyaWdodCI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIzIjoNCiAgICAgICAgICAgICAgICAkcG9zaXRpb24gPSAicmlnaHQtY2VudGVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjQiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJib3R0b20iOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiNSI6DQogICAgICAgICAgICAgICAgJHBvc2l0aW9uID0gImJvdHRvbS1jZW50ZXIiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiNiI6DQogICAgICAgICAgICAgICAgJHBvc2l0aW9uID0gImxlZnQiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiNyI6DQogICAgICAgICAgICAgICAgJHBvc2l0aW9uID0gImxlZnQtY2VudGVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgICRyZWxhdGl2ZXBvc2l0aW9uID0gImZhbHNlIjsNCg0KICAgICAgICBzd2l0Y2ggKCR0b29sdGlwLT5jc3Nwb3NpdGlvbikgew0KICAgICAgICAgICAgY2FzZSAiMCI6DQogICAgICAgICAgICAgICAgJHJlbGF0aXZlcG9zaXRpb24gPSAiZmFsc2UiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiMSI6DQogICAgICAgICAgICAgICAgJHJlbGF0aXZlcG9zaXRpb24gPSAidHJ1ZSI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCR0b29sdGlwLT5ldmVudHMgPT0gMCB8fCAkdG9vbHRpcC0+ZXZlbnRzID09IDEpIHsNCiAgICAgICAgICAgICRyZWxhdGl2ZXBvc2l0aW9uID0gInJlbGF0aXZlOiBcInskcmVsYXRpdmVwb3NpdGlvbn1cIiwiOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHJlbGF0aXZlcG9zaXRpb24gPSAiIjsNCiAgICAgICAgfQ0KDQogICAgICAgICRlZmZlY3QgPSAidG9nZ2xlIjsgDQoNCiAgICAgICAgc3dpdGNoICgkdG9vbHRpcC0+ZWZmZWN0KSB7DQogICAgICAgICAgICBjYXNlICIwIjoNCiAgICAgICAgICAgICAgICAkZWZmZWN0ID0gIiI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIxIjoNCiAgICAgICAgICAgICAgICAkZWZmZWN0ID0gImZhZGUiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiMiI6IA0KICAgICAgICAgICAgICAgICRlZmZlY3QgPSAic2xpZGUiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgc3dpdGNoICgkdG9vbHRpcC0+ZXZlbnRzKSB7DQogICAgICAgICAgICBjYXNlICIwIjoNCiAgICAgICAgICAgICAgICAkYWN0aXZhdGlvbiA9ICJjbGljayI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIxIjoNCiAgICAgICAgICAgICAgICAkYWN0aXZhdGlvbiA9ICJvdmVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjIiOiANCiAgICAgICAgICAgICAgICAkYWN0aXZhdGlvbiA9ICJjbGljayI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIzIjogDQogICAgICAgICAgICAgICAgJGFjdGl2YXRpb24gPSAib3ZlciI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgaWYgKCFpc3NldCgkdG9vbHRpcC0+Ymdjb2xvcikpIHsNCiAgICAgICAgICAgICR0b29sdGlwLT5iZ2NvbG9yID0gIiMwMDAwMDA7IjsNCiAgICAgICAgICAgICR0b29sdGlwLT5jb2xvciA9ICIjRkZGRkZGIjsNCiAgICAgICAgICAgICR0b29sdGlwLT5ib3JkZXJjb2xvciA9ICIjRkZGRkZGIjsNCiAgICAgICAgICAgICR0b29sdGlwLT5zaGFkb3djb2xvciA9ICIjMDAwMDAwIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICAkYnV0dG9uX2FwcGVuZF9jb2RlID0gIiI7DQoNCiAgICAgICAgaWYgKCR0b29sdGlwLT5ldmVudHMgPT0gMiB8fCAkdG9vbHRpcC0+ZXZlbnRzID09IDMpIHsNCiAgICAgICAgICAgICRidXR0b25fYXBwZW5kX2NvZGUgPSAiLXRvb2x0aXAtYnV0dG9uIjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgJGpzY29kZSA9IDw8PEVPVA0KXG5cbjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KLy8gaW5pdCBvcHRpb25zDQp2YXIgb3B0aW9ucyA9IG5ldyBBcnJheSgpOw0Kb3B0aW9ucy5wdXNoKCJ7JGlkfXskYnV0dG9uX2FwcGVuZF9jb2RlfSIpOyAvLyBlbGVtZW50IHRvIHdhdGNoDQpvcHRpb25zLnB1c2goImZidG9vbHRpcC17JGlkfSIpOyAvLyB0b29sdGlwIGVsZW1lbnQNCm9wdGlvbnMucHVzaCgieyRwb3NpdGlvbn0iKTsgLy8gcG9zaXRpb24NCm9wdGlvbnMucHVzaCh7JHRvb2x0aXAtPmRlbGF5fSk7IC8vIGRlbGF5DQpvcHRpb25zLnB1c2gobmV3IEFycmF5KHskdG9vbHRpcC0+b2Zmc2V0eH0sIHskdG9vbHRpcC0+b2Zmc2V0eX0pKTsgLy8gb2Zmc2V0DQpvcHRpb25zLnB1c2goInskYWN0aXZhdGlvbn0iKTsgLy8gYWN0aXZhdGlvbg0Kb3B0aW9ucy5wdXNoKCJ7JGVmZmVjdH0iKTsgLy8gZWZmZWN0DQpvcHRpb25zLnB1c2goMjApOyAvLyBhbmltYXRpb24gdGltZQ0Kb3B0aW9ucy5wdXNoKHskdG9vbHRpcC0+dHJhbnNwYXJlbmN5fSk7IC8vIG9wYWN0aXR5DQoNCi8vIGluaXQgdG9vbHRpcAkJDQp2YXIgdG9vbHRpcF97JGlkfSA9IG5ldyBSYWNrRm9ybXNfVG9vbFRpcCgpOw0KdG9vbHRpcF97JGlkfS5pbml0KG9wdGlvbnMpOw0KDQo8L3NjcmlwdD4NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCi5mYnRvb2x0aXAteyRpZH0gew0KCWJhY2tncm91bmQtY29sb3I6eyR0b29sdGlwLT5iZ2NvbG9yfTsNCglib3JkZXI6MXB4IHNvbGlkIHskdG9vbHRpcC0+Ym9yZGVyY29sb3J9Ow0KCXBhZGRpbmc6MTBweCAxNXB4Ow0KCXdpZHRoOjIwMHB4Ow0KCWRpc3BsYXk6bm9uZTsNCglmb250LWZhbWlseTogQXJpYWw7DQoJY29sb3I6eyR0b29sdGlwLT5jb2xvcn07DQoJdGV4dC1hbGlnbjpsZWZ0Ow0KCWZvbnQtc2l6ZToxMnB4Ow0KCXotaW5kZXg6OTk5OTk7DQoJDQoJLyogZWZmZWN0cyAqLw0KCWJveC1zaGFkb3c6MnB4IDFweCAycHggeyR0b29sdGlwLT5zaGFkb3djb2xvcn07DQoJYm9yZGVyLXJhZGl1czo0cHg7DQoJDQoJLyogZm9yIG9sZGVyIHZlcnNpb25zIG9mIEZpcmVmb3ggKi8NCgktbW96LWJveC1zaGFkb3c6MnB4IDFweCAycHggeyR0b29sdGlwLT5zaGFkb3djb2xvcn07DQoJLXdlYmtpdC1ib3gtc2hhZG93OjJweCAxcHggMnB4IHskdG9vbHRpcC0+c2hhZG93Y29sb3J9Ow0KCQkJDQoJcG9zaXRpb246IGFic29sdXRlOw0KfQ0KPC9zdHlsZT4NCkVPVDsNCg0KICAgICAgICAkdG9vbHRpcF9vYmotPmpzID0gJGpzY29kZTsNCg0KICAgICAgICByZXR1cm4gJHRvb2x0aXBfb2JqOw0KICAgIH0NCg0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gdHJhbnNsYXRlVG9vbHRpcF9PTEQoJHRvb2x0aXAsICRpZCkNCiAgICB7DQoNCiAgICAgICAgaWYgKCR0b29sdGlwLT50ZXh0ID09ICIiKSB7DQogICAgICAgICAgICAkdG9vbHRpcF9vYmogPSBuZXcgc3RkQ2xhc3MoKTsNCiAgICAgICAgICAgICR0b29sdGlwX29iai0+dGV4dCA9ICIiOw0KICAgICAgICAgICAgJHRvb2x0aXBfb2JqLT5qcyA9ICIiOw0KICAgICAgICAgICAgcmV0dXJuICR0b29sdGlwX29iajsNCiAgICAgICAgfQ0KDQogICAgICAgICR0b29sdGlwX29iaiA9IG5ldyBzdGRDbGFzcygpOw0KDQogICAgICAgIA0KICAgICAgICAkdG9vbHRpcF9vYmotPnRleHQgPSAoc3RyaW5nKSR0b29sdGlwLT50ZXh0Ow0KDQogICAgICAgICRwb3NpdGlvbiA9ICJjZW50ZXIgcmlnaHQiOyANCg0KICAgICAgICBzd2l0Y2ggKCR0b29sdGlwLT5wb3NpdGlvbikgew0KICAgICAgICAgICAgY2FzZSAiMCI6DQogICAgICAgICAgICAgICAgJHBvc2l0aW9uID0gInRvcCBsZWZ0IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjEiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJ0b3AgY2VudGVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjIiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJ0b3AgcmlnaHQiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiMyI6DQogICAgICAgICAgICAgICAgJHBvc2l0aW9uID0gImNlbnRlciByaWdodCI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICI0IjoNCiAgICAgICAgICAgICAgICAkcG9zaXRpb24gPSAiYm90dG9tIHJpZ2h0IjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjUiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJib3R0b20gY2VudGVyIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjYiOg0KICAgICAgICAgICAgICAgICRwb3NpdGlvbiA9ICJib3R0b20gbGVmdCI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICI3IjoNCiAgICAgICAgICAgICAgICAkcG9zaXRpb24gPSAiY2VudGVyIGxlZnQiOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgJHJlbGF0aXZlcG9zaXRpb24gPSAiZmFsc2UiOw0KDQogICAgICAgIHN3aXRjaCAoJHRvb2x0aXAtPmNzc3Bvc2l0aW9uKSB7DQogICAgICAgICAgICBjYXNlICIwIjoNCiAgICAgICAgICAgICAgICAkcmVsYXRpdmVwb3NpdGlvbiA9ICJmYWxzZSI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIxIjoNCiAgICAgICAgICAgICAgICAkcmVsYXRpdmVwb3NpdGlvbiA9ICJ0cnVlIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoJHRvb2x0aXAtPmV2ZW50cyA9PSAwIHx8ICR0b29sdGlwLT5ldmVudHMgPT0gMSkgew0KICAgICAgICAgICAgJHJlbGF0aXZlcG9zaXRpb24gPSAicmVsYXRpdmU6IFwieyRyZWxhdGl2ZXBvc2l0aW9ufVwiLCI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkcmVsYXRpdmVwb3NpdGlvbiA9ICIiOw0KICAgICAgICB9DQoNCiAgICAgICAgJGVmZmVjdCA9ICJ0b2dnbGUiOyANCg0KICAgICAgICBzd2l0Y2ggKCR0b29sdGlwLT5lZmZlY3QpIHsNCiAgICAgICAgICAgIGNhc2UgIjAiOg0KICAgICAgICAgICAgICAgICRlZmZlY3QgPSAidG9nZ2xlIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjEiOg0KICAgICAgICAgICAgICAgICRlZmZlY3QgPSAiZmFkZSI7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIyIjoNCiAgICAgICAgICAgICAgICAkZWZmZWN0ID0gInNsaWRlIjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIHN3aXRjaCAoJHRvb2x0aXAtPmV2ZW50cykgew0KICAgICAgICAgICAgY2FzZSAiMCI6DQogICAgICAgICAgICAgICAgJGV2ZW50cyA9IDw8PCBFT1INCmV2ZW50czogew0KCSAgZGVmOiAgICAgIm1vdXNlb3Zlcixtb3VzZW91dCIsDQoJICBpbnB1dDogICAiZm9jdXMsYmx1ciIsDQoJICB3aWRnZXQ6ICAiZm9jdXMgbW91c2VvdmVyLGJsdXIgbW91c2VvdXQiLA0KCSAgdG9vbHRpcDogIm1vdXNlb3Zlcixtb3VzZW91dCINCgl9DQpFT1I7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICIxIjoNCiAgICAgICAgICAgICAgICAkZXZlbnRzID0gPDw8IEVPUg0KZXZlbnRzOiB7DQoJICBkZWY6ICAgICAibW91c2VvdmVyLG1vdXNlb3V0IiwNCgkgIGlucHV0OiAgICJtb3VzZW92ZXIsbW91c2VvdXQiLA0KCSAgd2lkZ2V0OiAgImZvY3VzIG1vdXNlb3ZlcixibHVyIG1vdXNlb3V0IiwNCgkgIHRvb2x0aXA6ICJtb3VzZW92ZXIsbW91c2VvdXQiDQoJfQ0KRU9SOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAiMiI6IA0KICAgICAgICAgICAgICAgICRldmVudHMgPSA8PDwgRU9SDQpldmVudHM6IHsNCgkgIGRlZjogICAgICJtb3VzZW92ZXIsbW91c2VvdXQiLA0KCSAgaW5wdXQ6ICAgImNsaWNrLG1vdXNlb3V0IiwNCgkgIHdpZGdldDogICJmb2N1cyBtb3VzZW92ZXIsYmx1ciBtb3VzZW91dCIsDQoJICB0b29sdGlwOiAibW91c2VvdmVyLG1vdXNlb3V0Ig0KCX0NCkVPUjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgIjMiOiANCiAgICAgICAgICAgICAgICAkZXZlbnRzID0gPDw8IEVPUg0KZXZlbnRzOiB7DQoJICBkZWY6ICAgICAibW91c2VvdmVyLG1vdXNlb3V0IiwNCgkgIGlucHV0OiAgICJtb3VzZW92ZXIsbW91c2VvdXQiLA0KCSAgd2lkZ2V0OiAgImZvY3VzIG1vdXNlb3ZlcixibHVyIG1vdXNlb3V0IiwNCgkgIHRvb2x0aXA6ICJtb3VzZW92ZXIsbW91c2VvdXQiDQoJfQ0KRU9SOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICghaXNzZXQoJHRvb2x0aXAtPmJnY29sb3IpKSB7DQogICAgICAgICAgICAkdG9vbHRpcC0+Ymdjb2xvciA9ICIjMDAwMDAwOyI7DQogICAgICAgICAgICAkdG9vbHRpcC0+Y29sb3IgPSAiI0ZGRkZGRiI7DQogICAgICAgICAgICAkdG9vbHRpcC0+Ym9yZGVyY29sb3IgPSAiI0ZGRkZGRiI7DQogICAgICAgICAgICAkdG9vbHRpcC0+c2hhZG93Y29sb3IgPSAiIzAwMDAwMCI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRidXR0b25fYXBwZW5kX2NvZGUgPSAiIjsNCg0KICAgICAgICBpZiAoJHRvb2x0aXAtPmV2ZW50cyA9PSAyIHx8ICR0b29sdGlwLT5ldmVudHMgPT0gMykgew0KICAgICAgICAgICAgJGJ1dHRvbl9hcHBlbmRfY29kZSA9ICItdG9vbHRpcC1idXR0b24iOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KDQogICAgICAgICRqc2NvZGUgPSA8PDxFT1QNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCi8vIHNlbGVjdCBhbGwgZGVzaXJlZCBpbnB1dCBmaWVsZHMgYW5kIGF0dGFjaCB0b29sdGlwcyB0byB0aGVtDQovLyBodHRwOi8vZmxvd3BsYXllci5vcmcvdG9vbHMvdG9vbHRpcC9pbmRleC5odG1sDQpqUXVlcnkoIiN7JGlkfXskYnV0dG9uX2FwcGVuZF9jb2RlfSIpLnRvb2x0aXAoew0KCQ0KCS8vIHBsYWNlIHRvb2x0aXAgaW4gdGhlIGNvcnJlY3QgbG9jYXRpb24NCglwb3NpdGlvbjogInskcG9zaXRpb259IiwNCgkvLyBhIGxpdHRsZSB0d2Vha2luZyBvZiB0aGUgcG9zaXRpb24NCglvZmZzZXQ6IFt7JHRvb2x0aXAtPm9mZnNldHl9LCB7JHRvb2x0aXAtPm9mZnNldHh9XSwNCgkvLyB1c2UgdGhlIGJ1aWx0LWluIGZhZGVJbi9mYWRlT3V0IGVmZmVjdA0KCWVmZmVjdDogInskZWZmZWN0fSIsDQoJLy8gY3VzdG9tIG9wYWNpdHkgc2V0dGluZw0KCW9wYWNpdHk6IHskdG9vbHRpcC0+dHJhbnNwYXJlbmN5fSwNCgkvLyBkZWxheQ0KCWRlbGF5OiB7JHRvb2x0aXAtPmRlbGF5fSwNCgkvLyBQb3NpdGlvbg0KCXskcmVsYXRpdmVwb3NpdGlvbn0NCgkvLyBjbGFzcw0KCXRpcENsYXNzOiAiZmJ0b29sdGlwLXskaWR9IiwNCgkvLyBldmVudCBsaXN0DQoJeyRldmVudHN9DQoJDQp9KTsNCjwvc2NyaXB0PjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQouZmJ0b29sdGlwLXskaWR9IHsNCgliYWNrZ3JvdW5kLWNvbG9yOnskdG9vbHRpcC0+Ymdjb2xvcn07DQoJYm9yZGVyOjFweCBzb2xpZCB7JHRvb2x0aXAtPmJvcmRlcmNvbG9yfTsNCglwYWRkaW5nOjEwcHggMTVweDsNCgl3aWR0aDoyMDBweDsNCglkaXNwbGF5Om5vbmU7DQoJZm9udC1mYW1pbHk6IEFyaWFsOw0KCWNvbG9yOnskdG9vbHRpcC0+Y29sb3J9Ow0KCXRleHQtYWxpZ246bGVmdDsNCglmb250LXNpemU6MTJweDsNCgl6LWluZGV4Ojk5OTk5Ow0KCQ0KCS8qIGVmZmVjdHMgKi8NCglib3gtc2hhZG93OjJweCAxcHggMnB4IHskdG9vbHRpcC0+c2hhZG93Y29sb3J9Ow0KCQ0KCS8qIGZvciBvbGRlciB2ZXJzaW9ucyBvZiBGaXJlZm94ICovDQoJLW1vei1ib3gtc2hhZG93OjJweCAxcHggMnB4IHskdG9vbHRpcC0+c2hhZG93Y29sb3J9Ow0KCS13ZWJraXQtYm94LXNoYWRvdzoycHggMXB4IDJweCB7JHRvb2x0aXAtPnNoYWRvd2NvbG9yfTsNCn0NCjwvc3R5bGU+DQpFT1Q7DQoNCiAgICAgICAgJHRvb2x0aXBfb2JqLT5qcyA9ICRqc2NvZGU7DQoNCiAgICAgICAgcmV0dXJuICR0b29sdGlwX29iajsNCiAgICB9DQoNCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiB0cmFuc2xhdGVHcmFkaWVudCgkc2VsZWN0b3IsICR0b3AsICRib3R0b20pDQogICAgew0KDQogICAgICAgICRjc3MgPSA8PDxFT0YNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQovKiBCYWNrZ3JvdW5kIEdyYWRpZW50ICovDQoueyRzZWxlY3Rvcn17DQoJYmFja2dyb3VuZDogeyR0b3B9OyAvKiBPbGQgYnJvd3NlcnMgKi8NCgliYWNrZ3JvdW5kOiAtbW96LWxpbmVhci1ncmFkaWVudCh0b3AsICB7JHRvcH0gMCUsIHskYm90dG9tfSAxMDAlKTsgLyogRkYzLjYrICovDQoJYmFja2dyb3VuZDogLXdlYmtpdC1ncmFkaWVudChsaW5lYXIsIGxlZnQgdG9wLCBsZWZ0IGJvdHRvbSwgY29sb3Itc3RvcCgwJSx7JHRvcH0pLCBjb2xvci1zdG9wKDEwMCUseyRib3R0b219KSk7IC8qIENocm9tZSxTYWZhcmk0KyAqLw0KCWJhY2tncm91bmQ6IC13ZWJraXQtbGluZWFyLWdyYWRpZW50KHRvcCwgIHskdG9wfSAwJSx7JGJvdHRvbX0gMTAwJSk7IC8qIENocm9tZTEwKyxTYWZhcmk1LjErICovDQoJYmFja2dyb3VuZDogLW8tbGluZWFyLWdyYWRpZW50KHRvcCwgIHskdG9wfSAwJSx7JGJvdHRvbX0gMTAwJSk7IC8qIE9wZXJhIDExLjEwKyAqLw0KCWJhY2tncm91bmQ6IC1tcy1saW5lYXItZ3JhZGllbnQodG9wLCAgeyR0b3B9IDAlLHskYm90dG9tfSAxMDAlKTsgLyogSUUxMCsgKi8NCgliYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCAgeyR0b3B9IDAlLHskYm90dG9tfSAxMDAlKTsgLyogVzNDICovDQoJZmlsdGVyOiBwcm9naWQ6RFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuZ3JhZGllbnQoIHN0YXJ0Q29sb3JzdHI9J3skdG9wfScsIGVuZENvbG9yc3RyPSd7JGJvdHRvbX0nLEdyYWRpZW50VHlwZT0wICk7IC8qIElFNi05ICovDQp9DQo8L3N0eWxlPg0KRU9GOw0KDQogICAgICAgIHJldHVybiAkY3NzOw0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiB0cmFuc2xhdGVCb3JkZXJTdHlsZSgkc3R5bGUpDQogICAgew0KDQogICAgICAgICRib3JkZXJfc3R5bGUgPSAnJzsNCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJHN0eWxlKSB7DQoNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkYm9yZGVyX3N0eWxlID0gJ3NvbGlkJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAkYm9yZGVyX3N0eWxlID0gJ2RvdHRlZCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDI6DQogICAgICAgICAgICAgICAgJGJvcmRlcl9zdHlsZSA9ICdkYXNoZWQnOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuICRib3JkZXJfc3R5bGU7DQogICAgfQ0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIHRyYW5zbGF0ZUNvbG9ycGlja2VyKCRjb2xvcnBpY2tlciwgJGlkKQ0KICAgIHsNCg0KICAgICAgICANCiAgICAgICAgaWYgKChpbnQpJGNvbG9ycGlja2VyLT5lbmFibGUgPT0gMCkgew0KDQogICAgICAgICAgICAkY29sb3JwaWNrZXJfb2JqID0gbmV3IHN0ZENsYXNzKCk7DQogICAgICAgICAgICAkY29sb3JwaWNrZXJfb2JqLT5qc2NvZGUgPSAiIjsNCiAgICAgICAgICAgIHJldHVybiAkY29sb3JwaWNrZXJfb2JqOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGNvbG9ycGlja2VyX29iaiA9IG5ldyBzdGRDbGFzcygpOw0KDQogICAgICAgICRjb2xvcnBpY2tlcl9vYmotPmpzY29kZSA9ICIiOw0KDQogICAgICAgIA0KICAgICAgICBpZiAoKGludCkkY29sb3JwaWNrZXItPmNvbG9yYmFja2dyb3VuZCA9PSAxKSB7DQogICAgICAgICAgICAkY29sb3JiYWNrZ3JvdW5kID0gImpRdWVyeSgnI3skaWR9JykuY3NzKCdiYWNrZ3JvdW5kQ29sb3InLCAnIycgKyBoZXgpOyI7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAkY29sb3JiYWNrZ3JvdW5kID0gIiI7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgc3dpdGNoICgoaW50KSRjb2xvcnBpY2tlci0+bW9kZSkgew0KDQogICAgICAgICAgICBjYXNlIDA6IA0KICAgICAgICAgICAgICAgICRqc19tb2RlID0gPDw8RU9GDQpqUXVlcnkoJyNmYl9mbGQteyRpZH0nKS5Db2xvclBpY2tlcih7DQogICAJZmxhdDogdHJ1ZSwNCiAgIAljb2xvcjogJ3skY29sb3JwaWNrZXItPmluaXRpYWx2YWx1ZX0nLA0KICAgCW9uQ2hhbmdlOiBmdW5jdGlvbiAoaHNiLCBoZXgsIHJnYikgew0KCQl7JGNvbG9yYmFja2dyb3VuZH0NCgkJalF1ZXJ5KCcjeyRpZH0nKS52YWwoJyMnICsgaGV4KTsNCgl9DQp9KTsJCQkNCkVPRjsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMTogDQogICAgICAgICAgICAgICAgJGpzX21vZGUgPSA8PDxFT0YNCmpRdWVyeSgnI3skaWR9JykuQ29sb3JQaWNrZXIoew0KCWNvbG9yOiAneyRjb2xvcnBpY2tlci0+aW5pdGlhbHZhbHVlfScsDQoJb25TaG93OiBmdW5jdGlvbiAoY29scGtyKSB7DQoJICAgICAgCWpRdWVyeShjb2xwa3IpLmZhZGVJbig1MDApOw0KCSAgICAgIAlyZXR1cm4gZmFsc2U7DQoJfSwNCglvbkhpZGU6IGZ1bmN0aW9uIChjb2xwa3IpIHsNCgkJalF1ZXJ5KGNvbHBrcikuZmFkZU91dCg1MDApOw0KCQlyZXR1cm4gZmFsc2U7DQoJfSwNCglvbkNoYW5nZTogZnVuY3Rpb24gKGhzYiwgaGV4LCByZ2IpIHsNCgkJeyRjb2xvcmJhY2tncm91bmR9DQoJCWpRdWVyeSgnI3skaWR9JykudmFsKCcjJyArIGhleCk7DQoJfQkNCn0pOwkJCQkNCkVPRjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICBpZiAoKHN0cmluZykkY29sb3JwaWNrZXItPmN1c3RvbWNvZGUgIT0gIiIpIHsNCiAgICAgICAgICAgICRqc19tb2RlID0gKHN0cmluZykkY29sb3JwaWNrZXItPmN1c3RvbWNvZGU7DQogICAgICAgIH0NCg0KICAgICAgICANCiAgICAgICAgJGpzX2JvZHkgPSA8PDxFT0YNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCi8vIHN0YXJ0IG5vQ29uZmxpY3QoKQ0KalF1ZXJ5Lm5vQ29uZmxpY3QoKTsNCg0KalF1ZXJ5KGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsgLy8gaHR0cDovL2FwaS5qcXVlcnkuY29tL3JlYWR5Lw0KICAgIHskanNfbW9kZX0NCn0pOw0KPC9zY3JpcHQ+DQoNCkVPRjsNCg0KICAgICAgICAkY29sb3JwaWNrZXJfb2JqLT5qc2NvZGUgPSAkanNfYm9keTsNCg0KICAgICAgICByZXR1cm4gJGNvbG9ycGlja2VyX29iajsNCiAgICB9DQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIHRyYW5zbGF0ZUpzbGlkZXIoJGpzbGlkZXIsICRpZCkNCiAgICB7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoaW50KSRqc2xpZGVyLT5lbmFibGUgPT0gMCkgew0KDQogICAgICAgICAgICAkanNsaWRlcl9vYmogPSBuZXcgc3RkQ2xhc3MoKTsNCiAgICAgICAgICAgICRqc2xpZGVyX29iai0+anNjb2RlID0gIiI7DQogICAgICAgICAgICByZXR1cm4gJGpzbGlkZXJfb2JqOw0KICAgICAgICB9DQoNCiAgICAgICAgDQoNCiAgICAgICAgJGpzbGlkZXJfb2JqID0gbmV3IHN0ZENsYXNzKCk7DQoNCiAgICAgICAgJGpzbGlkZXJfb2JqLT5qc2NvZGUgPSAiIjsNCg0KICAgICAgICBzd2l0Y2ggKChpbnQpJGpzbGlkZXItPnNraW4pIHsNCiAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAkc2tpbiA9ICdjbGFzc2ljJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMToNCiAgICAgICAgICAgICAgICAkc2tpbiA9ICdwbGFzdGljJzsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgMjoNCiAgICAgICAgICAgICAgICAkc2tpbiA9ICdyb3VuZCc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlIDM6DQogICAgICAgICAgICAgICAgJHNraW4gPSAncm91bmRfcGxhc3RpYyc7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KDQogICAgICAgIA0KDQoNCiAgICAgICAgDQogICAgICAgICRmb3JtYXQgPSAiIjsNCg0KICAgICAgICBpZiAoJGpzbGlkZXItPmZvcm1hdCAhPSAnJykgew0KICAgICAgICAgICAgJGZvcm1hdCA9ICJmb3JtYXQ6IHsgeyRqc2xpZGVyLT5mb3JtYXR9IH0sIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkaGV0ZXJvZ2VuZWl0eSA9ICIiOw0KDQogICAgICAgIGlmICgkanNsaWRlci0+aGV0ZXJvZ2VuZWl0eSAhPSAnJykgew0KICAgICAgICAgICAgJGhldGVyb2dlbmVpdHkgPSAiaGV0ZXJvZ2VuZWl0eTogWyB7JGpzbGlkZXItPmhldGVyb2dlbmVpdHl9IF0sIjsNCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkc2NhbGUgPSAiIjsNCg0KICAgICAgICBpZiAoJGpzbGlkZXItPnNjYWxlICE9ICcnKSB7DQogICAgICAgICAgICAkc2NhbGUgPSAic2NhbGU6IFsgeyRqc2xpZGVyLT5zY2FsZX0gXSwiOw0KICAgICAgICB9DQoNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgJGNhbGN1bGF0ZSA9ICcnOw0KDQogICAgICAgIGlmICgkanNsaWRlci0+Y2FsdWxhdGUgIT0gJycpIHsNCiAgICAgICAgICAgICRjYWxjdWxhdGUgPSA8PDxFT0YNCgljYWxjdWxhdGU6IGZ1bmN0aW9uKHZhbHVlKSB7DQoJCXskanNsaWRlci0+Y2FsY3VsYXRlfQ0KCX0sCQkNCkVPRjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgJG9uc3RhdGVjaGFuZ2UgPSAnJzsNCg0KICAgICAgICBpZiAoJGpzbGlkZXItPm9uc3RhdGVjaGFuZ2UgIT0gJycpIHsNCiAgICAgICAgICAgICRvbnN0YXRlY2hhbmdlID0gPDw8RU9GDQoJb25zdGF0ZWNoYW5nZTogZnVuY3Rpb24odmFsdWUpIHsgDQoJCXskanNsaWRlci0+b25zdGF0ZWNoYW5nZX0NCgl9LAkJDQpFT0Y7DQogICAgICAgIH0NCg0KDQogICAgICAgICRjYWxsYmFjayA9ICcnOw0KDQogICAgICAgIGlmICgkanNsaWRlci0+Y2FsbGJhY2sgICE9ICcnKSB7DQogICAgICAgICAgICAkY2FsbGJhY2sgID0gPDw8RU9GDQoJY2FsbGJhY2s6IGZ1bmN0aW9uKHZhbHVlKSB7IA0KCQl7JGpzbGlkZXItPmNhbGxiYWNrfQ0KCX0sCQkNCkVPRjsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgJGpzX21vZGUgPSA8PDxFT0YNCnNsaWRlcl97JGlkfSA9ICQoIiN7JGlkfSIpLnNsaWRlcih7IA0KCWZyb206IHskanNsaWRlci0+ZnJvbX0sIA0KCXRvOiB7JGpzbGlkZXItPnRvfSwgDQoJc3RlcDogeyRqc2xpZGVyLT5zdGVwfSwgDQoJcm91bmQ6IHskanNsaWRlci0+cm91bmR9LCANCgl7JGZvcm1hdH0gDQoJeyRoZXRlcm9nZW5laXR5fQ0KCWRpbWVuc2lvbjogInskanNsaWRlci0+ZGltZW5zaW9ufSIsIA0KCQ0KCWxpbWl0czogInskanNsaWRlci0+bGltaXRzfSIsIA0KCXskc2NhbGV9DQoJc2tpbjogInskc2tpbn0iLA0KCQ0KCXskY2FsY3VsYXRlfQ0KCQ0KCXskb25zdGF0ZWNoYW5nZX0NCgkNCgl7JGNhbGxiYWNrfQ0KCQ0KCXNtb290aDogdHJ1ZQ0KfSk7CQkNCkVPRjsNCg0KDQogICAgICAgIA0KICAgICAgICBpZiAoKHN0cmluZykkanNsaWRlci0+Y3VzdG9tY29kZSAhPSAiIikgew0KICAgICAgICAgICAgJGpzX21vZGUgPSAoc3RyaW5nKSRqc2xpZGVyLT5jdXN0b21jb2RlOw0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkanNfYm9keSA9IDw8PEVPRg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KdmFyIHNsaWRlcl97JGlkfTsNCiQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgeyAvLyBodHRwOi8vYXBpLmpxdWVyeS5jb20vcmVhZHkvDQogICAgeyRqc19tb2RlfQ0KfSk7DQo8L3NjcmlwdD4NCg0KRU9GOw0KDQogICAgICAgICRqc2xpZGVyX29iai0+anNjb2RlID0gJGpzX2JvZHk7DQoNCiAgICAgICAgcmV0dXJuICRqc2xpZGVyX29iajsNCiAgICB9DQoNCg0KDQogICAgDQogICAgcHJpdmF0ZSBmdW5jdGlvbiBfY3JlYXRlQ29uZGl0aW9uYWxFdmVudCgkY29uZGl0aW9uYWwsICRuYW1lLCAkaWQpDQogICAgew0KDQogICAgICAgIA0KICAgICAgICAkY29uZGl0aW9uYWxFdmVudCA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEV2ZW50KChzdHJpbmcpJGNvbmRpdGlvbmFsLT5ldmVudCk7DQogICAgICAgICRjb25kaXRpb25hbEFuaW1hdGlvbiA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFuaW1hdGlvbigoc3RyaW5nKSRjb25kaXRpb25hbC0+YW5pbWF0aW9uKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsQ29uZGl0aW9uID0gJHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsQ29uZGl0aW9uKChzdHJpbmcpJGNvbmRpdGlvbmFsLT5jb25kaXRpb24pOw0KICAgICAgICAkY29uZGl0aW9uYWxWYWx1ZSA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT52YWx1ZSA9PSAnJyA/ICInJyIgOiAiJyIgLiAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmFsdWUgLiAiJyI7DQogICAgICAgICRjb25kaXRpb25hbEFjdGlvbiA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFjdGlvbigoc3RyaW5nKSRjb25kaXRpb25hbC0+YWN0aW9uKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsRmllbGQgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+ZmllbGQgPT0gJycgPyAiJyciIDogIiciIC4gKHN0cmluZykkY29uZGl0aW9uYWwtPmZpZWxkIC4gIiciOw0KICAgICAgICAkY29uZGl0aW9uYWxXcmFwcGVyID0gKHN0cmluZykkY29uZGl0aW9uYWwtPndyYXBwZXIgPT0gJycgPyAiJyciIDogIiciIC4gKHN0cmluZykkY29uZGl0aW9uYWwtPndyYXBwZXIgLiAiJyI7DQogICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT5jdXN0b207DQogICAgICAgICRjb25kaXRpb25hbFRvZ2dsZSA9IChpbnQpJGNvbmRpdGlvbmFsLT50b2dnbGUgPT0gJzEnID8gJ3RydWUnIDogJ2ZhbHNlJzsNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRjb25kaXRpb25hbEV2ZW50ICE9ICcnKSB7DQogICAgICAgICAgICBpZiAoJGNvbmRpdGlvbmFsQ3VzdG9tID09ICIiKSB7IA0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICIgeyRjb25kaXRpb25hbEV2ZW50fT1cImZiYy5oYW5kbGVFdmVudChldmVudCwgdGhpcy52YWx1ZSwgJGNvbmRpdGlvbmFsQ29uZGl0aW9uLCAkY29uZGl0aW9uYWxWYWx1ZSwgJGNvbmRpdGlvbmFsQWN0aW9uLCAkY29uZGl0aW9uYWxGaWVsZCwgJGNvbmRpdGlvbmFsV3JhcHBlciwgJGNvbmRpdGlvbmFsVG9nZ2xlLCAkY29uZGl0aW9uYWxBbmltYXRpb24pO1wiICI7DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0ID0gIiI7IA0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCA9ICI8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj4iOw0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgJGpzX2lkZW50aWZpZXIgPSAoc3RyaW5nKSRuYW1lOw0KDQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJG5hbWUgIT0gKHN0cmluZykkaWQpIHsNCiAgICAgICAgICAgICAgICAgICAgJGpzX2lkZW50aWZpZXIgPSAoc3RyaW5nKSRpZDsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgLj0gIlxuZnVuY3Rpb24gZmJfZHluX3skanNfaWRlbnRpZmllcn0oZXZlbnQsIGluX3ZhbHVlLCBlbHQsIGNoZWNrZWQpe1xuIjsNCg0KDQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfc2NyaXB0IC49ICRjb25kaXRpb25hbEN1c3RvbTsNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgLj0gIn0iOw0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCAuPSAiPC9zY3JpcHQ+IjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9ICIgeyRjb25kaXRpb25hbEV2ZW50fT1cImZiX2R5bl97JGpzX2lkZW50aWZpZXJ9KGV2ZW50LCB0aGlzLnZhbHVlLCB0aGlzLCB0aGlzLmNoZWNrZWQpXCIiOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gJyc7DQogICAgICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9zY3JpcHQgPSAnJzsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiBhcnJheSgkY29uZGl0aW9uYWxfY2FsbF9pbmxpbmUsICRjb25kaXRpb25hbF9jYWxsX3NjcmlwdCk7DQogICAgfQ0KDQoNCiAgICANCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0Q29uZGl0aW9uYWxFdmVudENvZGUoKQ0KICAgIHsNCiAgICAgICAgcmV0dXJuICR0aGlzLT5fY29uZGl0aW9uYWxQYWdlTG9hZENvZGU7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIHJlc2V0Q29uZGl0aW9uYWxFdmVudENvZGUoKQ0KICAgIHsNCiAgICAgICAgJHRoaXMtPl9jb25kaXRpb25hbFBhZ2VMb2FkQ29kZSA9ICIiOw0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBhcHBlbmRDb25kaXRpb25hbEV2ZW50Q29kZSgkY29kZSkNCiAgICB7DQogICAgICAgICR0aGlzLT5fY29uZGl0aW9uYWxQYWdlTG9hZENvZGUgLj0gIlx0IjsNCiAgICAgICAgJHRoaXMtPl9jb25kaXRpb25hbFBhZ2VMb2FkQ29kZSAuPSAkY29kZTsNCiAgICAgICAgJHRoaXMtPl9jb25kaXRpb25hbFBhZ2VMb2FkQ29kZSAuPSAiXG4iOw0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBwcmVwQ29uZGl0aW9uYWxFdmVudENvZGUoKQ0KICAgIHsNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgICR0bXAgPSA8PDxFT1QNCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KCQkJDQpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIiwgZnVuY3Rpb24oKSB7DQoNCgl7JHRoaXMtPmdldENvbmRpdGlvbmFsRXZlbnRDb2RlKCl9DQoNCn0pOw0KDQo8L3NjcmlwdD4NCg0KRU9UOw0KDQogICAgICAgICR0aGlzLT5fY29uZGl0aW9uYWxQYWdlTG9hZENvZGUgPSAkdG1wOw0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGFkZENvbmR0aW9uYWxMb2FkRXZlbnQoJHR5cGUsICRpZCwgJGNvbmRpdGlvbmFsLCAkc2FtZXBhZ2UpDQogICAgew0KDQogICAgICAgIA0KDQogICAgICAgICRjb25kaXRpb25hbEV2ZW50ID0gJHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsRXZlbnQoKHN0cmluZykkY29uZGl0aW9uYWwtPmV2ZW50KTsNCiAgICAgICAgJGNvbmRpdGlvbmFsQW5pbWF0aW9uID0gJHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsQW5pbWF0aW9uKChzdHJpbmcpJGNvbmRpdGlvbmFsLT5hbmltYXRpb24pOw0KICAgICAgICAkY29uZGl0aW9uYWxDb25kaXRpb24gPSAkdGhpcy0+dHJhbnNsYXRlQ29uZGl0aW9uYWxDb25kaXRpb24oKHN0cmluZykkY29uZGl0aW9uYWwtPmNvbmRpdGlvbik7DQoNCiAgICAgICAgDQogICAgICAgICRjb25kaXRpb25hbF92YWx1ZSA9IHN0cl9yZXBsYWNlKCInIiwgIidcJyIsIChzdHJpbmcpJGNvbmRpdGlvbmFsLT52YWx1ZSk7DQoNCiAgICAgICAgJGNvbmRpdGlvbmFsVmFsdWUgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmFsdWUgPT0gJycgPyAiJyciIDogIiciIC4gJGNvbmRpdGlvbmFsX3ZhbHVlIC4gIiciOw0KDQogICAgICAgICRjb25kaXRpb25hbEFjdGlvbiA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFjdGlvbigoc3RyaW5nKSRjb25kaXRpb25hbC0+YWN0aW9uKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsRmllbGQgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+ZmllbGQgPT0gJycgPyAiJyciIDogIiciIC4gKHN0cmluZykkY29uZGl0aW9uYWwtPmZpZWxkIC4gIiciOw0KICAgICAgICAkY29uZGl0aW9uYWxXcmFwcGVyID0gKHN0cmluZykkY29uZGl0aW9uYWwtPndyYXBwZXIgPT0gJycgPyAiJyciIDogIiciIC4gKHN0cmluZykkY29uZGl0aW9uYWwtPndyYXBwZXIgLiAiJyI7DQogICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT5jdXN0b207DQogICAgICAgICRjb25kaXRpb25hbFRvZ2dsZSA9IChpbnQpJGNvbmRpdGlvbmFsLT50b2dnbGUgPT0gJzEnID8gJ3RydWUnIDogJ2ZhbHNlJzsNCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCg0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgIA0KICAgICAgICBpZiAoKHN0cmluZykkdHlwZSAhPSAnY2hlY2tib3gnICYmIChzdHJpbmcpJHR5cGUgIT0gJ3JhZGlvJyAmJiAoc3RyaW5nKSR0eXBlICE9ICdlY29tbScpIHsNCiAgICAgICAgICAgICR1c2Vfd2hpbGUgPSAwOyANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICR1c2Vfd2hpbGUgPSAxOyANCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHNhbWVwYWdlX2NvZGUgPSAnJzsgDQoNCg0KICAgICAgICANCiAgICAgICAgaWYgKCRjb25kaXRpb25hbEN1c3RvbSA9PSAiIikgeyANCg0KICAgICAgICAgICAgaWYgKCEkdXNlX3doaWxlKSB7DQoNCiAgICAgICAgICAgICAgICBpZiAoJHNhbWVwYWdlID09IHRydWUpIHsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gImZiYy5oYW5kbGVFdmVudExvYWQoJ3skaWR9JywgJGNvbmRpdGlvbmFsQ29uZGl0aW9uLCAkY29uZGl0aW9uYWxWYWx1ZSwgJGNvbmRpdGlvbmFsQWN0aW9uLCAkY29uZGl0aW9uYWxGaWVsZCwgJGNvbmRpdGlvbmFsV3JhcHBlciwgJGNvbmRpdGlvbmFsVG9nZ2xlLCAkY29uZGl0aW9uYWxBbmltYXRpb24sIGZhbHNlLCAnJyk7IjsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9IDw8PEVPRg0KPD9waHANCi8vIGNvbmRpdGlvbmFsIGNhbGwgbG9hZCBjb2RlIGZvcjogeyRpZH0NCmlmKGlzc2V0KFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsneyRpZH0nXSkpIHsNCglcJGZiX3NhbWVwYWdlX3ZhbCA9IFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsneyRpZH0nXTsNCn0gZWxzZSB7IA0KCVwkZmJfc2FtZXBhZ2VfdmFsID0gJyc7DQp9DQoNClwkZmJfc2FtZXBhZ2VfdmFsID0gc3RyX3JlcGxhY2UoIiciLCAiXFwnIiwgXCRmYl9zYW1lcGFnZV92YWwpOw0KDQo/Pg0KDQpmYmMuaGFuZGxlRXZlbnRMb2FkKCd7JGlkfScsIHskY29uZGl0aW9uYWxDb25kaXRpb259LCB7JGNvbmRpdGlvbmFsVmFsdWV9LCB7JGNvbmRpdGlvbmFsQWN0aW9ufSwgeyRjb25kaXRpb25hbEZpZWxkfSwgeyRjb25kaXRpb25hbFdyYXBwZXJ9LCB7JGNvbmRpdGlvbmFsVG9nZ2xlfSwgeyRjb25kaXRpb25hbEFuaW1hdGlvbn0sIGZhbHNlLCAnPD9waHAgZWNobyBcJGZiX3NhbWVwYWdlX3ZhbDsgPz4nKTsNCg0KRU9GOw0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSBlbHNlIHsgDQoNCiAgICAgICAgICAgICAgICBpZiAoJHNhbWVwYWdlID09IHRydWUpIHsNCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lID0gPDw8RU9GDQoJDQoJLy8gY3JlYXRlIGxpc3Qgb2YgdmFsaWQgaW5kZXhlcyBmb3I6IHskaWR9DQoJaiA9IG5ldyBBcnJheSgpOw0KCQ0KCWZvcihrID0gMDsgayA8IDEwMDA7IGsrKyl7DQoJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGlkfScgKyBrKSAhPT0gbnVsbCl7DQoJCQlqLnB1c2goJ3skaWR9JyArIGspOw0KCQl9DQoJfQ0KDQoJZm9yKHQgPSAwOyB0IDwgai5sZW5ndGg7IHQrKyl7DQoJCWlmKGZiYy5oYW5kbGVFdmVudExvYWQoalt0XSwgJGNvbmRpdGlvbmFsQ29uZGl0aW9uLCAkY29uZGl0aW9uYWxWYWx1ZSwgJGNvbmRpdGlvbmFsQWN0aW9uLCAkY29uZGl0aW9uYWxGaWVsZCwgJGNvbmRpdGlvbmFsV3JhcHBlciwgJGNvbmRpdGlvbmFsVG9nZ2xlLCAkY29uZGl0aW9uYWxBbmltYXRpb24sIHRydWUpKXsNCgkJCWJyZWFrOw0KCQl9DQoJfQ0KRU9GOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9IDw8PEVPRg0KDQo8P3BocA0KLy8gY29uZGl0aW9uYWwgY2FsbCBsb2FkIGNvZGUgZm9yOiB7JGlkfQ0KaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdWyd7JGlkfSddKSkgeyANCglcJGZiX3NhbWVwYWdlX3ZhbCA9IFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVsneyRpZH0nXTsgDQp9IGVsc2UgeyANCglcJGZiX3NhbWVwYWdlX3ZhbCA9ICcnOyANCn0NCg0KLy8gaXRlcmF0ZSBvdmVyIGNvbGxlY3Rpb24NCmlmKGlzX2FycmF5KFwkZmJfc2FtZXBhZ2VfdmFsKSl7IC8vIGNoZWNrYm94DQoJZm9yZWFjaChcJGZiX3NhbWVwYWdlX3ZhbCBhcyBcJGZiX3RtcF9zcF92YWwpew0KCQllY2hvICJmYmMuaGFuZGxlRXZlbnRMb2FkKCd7JGlkfScsICRjb25kaXRpb25hbENvbmRpdGlvbiwgJGNvbmRpdGlvbmFsVmFsdWUsICRjb25kaXRpb25hbEFjdGlvbiwgJGNvbmRpdGlvbmFsRmllbGQsICRjb25kaXRpb25hbFdyYXBwZXIsICRjb25kaXRpb25hbFRvZ2dsZSwgJGNvbmRpdGlvbmFsQW5pbWF0aW9uLCBmYWxzZSwgJ3tcJGZiX3RtcF9zcF92YWx9Jyk7IjsNCgl9DQp9IGVsc2UgeyAvLyByYWRpbw0KCWVjaG8gImZiYy5oYW5kbGVFdmVudExvYWQoJ3skaWR9JywgJGNvbmRpdGlvbmFsQ29uZGl0aW9uLCAkY29uZGl0aW9uYWxWYWx1ZSwgJGNvbmRpdGlvbmFsQWN0aW9uLCAkY29uZGl0aW9uYWxGaWVsZCwgJGNvbmRpdGlvbmFsV3JhcHBlciwgJGNvbmRpdGlvbmFsVG9nZ2xlLCAkY29uZGl0aW9uYWxBbmltYXRpb24sIGZhbHNlLCAne1wkZmJfc2FtZXBhZ2VfdmFsfScpOyI7DQp9DQo/Pg0KDQpFT0Y7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkdGhpcy0+YXBwZW5kQ29uZGl0aW9uYWxFdmVudENvZGUoJGNvbmRpdGlvbmFsX2NhbGxfaW5saW5lKTsNCiAgICAgICAgfSBlbHNlIHsNCg0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQoNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgDQogICAgICAgICAgICANCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoISR1c2Vfd2hpbGUpIHsgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSAiXG4vLyBjdXN0b20gY2FsbCBmb3IgeyRpZH0gLS1cbnskY29uZGl0aW9uYWxDdXN0b219XG4vLyBlbmQgY2FsbCBmb3IgeyRpZH1cbiI7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnaGlkZUZpZWxkJywgJ2hpZGVGaWVsZExvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdzaG93RmllbGQnLCAnc2hvd0ZpZWxkTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ2hpZGVXcmFwcGVyJywgJ2hpZGVXcmFwcGVyTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ3Nob3dXcmFwcGVyJywgJ3Nob3dXcmFwcGVyTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnRmllbGQoZXZlbnQnLCAiRmllbGQoJ3skaWR9JyIsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ1dyYXBwZXIoZXZlbnQnLCAiV3JhcHBlcigneyRpZH0nIiwgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnTG9hZChldmVudCcsICJMb2FkKCd7JGlkfSciLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnaW5fdmFsdWUnLCAiZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWR9JykudmFsdWUiLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJHRoaXMtPmFwcGVuZENvbmRpdGlvbmFsRXZlbnRDb2RlKCRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICB9IGVsc2UgeyANCg0KDQogICAgICAgICAgICAgICAgaWYgKChzdHJpbmcpJHR5cGUgPT0gJ2NoZWNrYm94JykgeyANCg0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b21Db2RlID0gJGNvbmRpdGlvbmFsQ3VzdG9tOyANCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tQ29kZSA9IHN0cl9yZXBsYWNlKCdoaWRlRmllbGQnLCAnaGlkZUZpZWxkTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbUNvZGUpOw0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b21Db2RlID0gc3RyX3JlcGxhY2UoJ3Nob3dGaWVsZCcsICdzaG93RmllbGRMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tQ29kZSk7DQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbUNvZGUgPSBzdHJfcmVwbGFjZSgnaGlkZVdyYXBwZXInLCAnaGlkZVdyYXBwZXJMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tQ29kZSk7DQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbUNvZGUgPSBzdHJfcmVwbGFjZSgnc2hvd1dyYXBwZXInLCAnc2hvd1dyYXBwZXJMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tQ29kZSk7DQoNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gIlxuXG4vLyBDdXN0b20gQ2FsbCBDaGVja2JveCBvbkxvYWQgUmV3cml0ZSBGb3I6IHskaWR9IC0tXG5cbiI7DQoNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tIC49IDw8PEVPRg0KCQkJCQkNCi8vIGNyZWF0ZSBsaXN0IG9mIHZhbGlkIGluZGV4ZXMgZm9yOiB7JGlkfQ0KaiA9IG5ldyBBcnJheSgpOw0KDQpmb3IoayA9IDA7IGsgPCAxMDAwOyBrKyspew0KCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGlkfScgKyBrKSAhPT0gbnVsbCl7DQoJCWoucHVzaCgneyRpZH0nICsgayk7DQoJfQ0KfQ0KDQpmb3IodCA9IDA7IHQgPCBqLmxlbmd0aDsgdCsrKXsNCg0KCXZhciBpbl92YWx1ZSA9ICcnOw0KCXZhciBjaGVja2VkID0gZmFsc2U7DQoNCglpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZChqW3RdKSAhPT0gbnVsbCl7DQoJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGpbdF0pLmNoZWNrZWQpIHsgY2hlY2tlZCA9IHRydWU7IH0NCgkJaW5fdmFsdWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChqW3RdKS52YWx1ZTsNCgl9DQoNCgkvL2NvbnNvbGUubG9nKGluX3ZhbHVlLCBjaGVja2VkLCBqW3RdKTsNCg0KCS8vIE9yaWdpbmFsIENvZGUgU3RhcnQNCgkNCgl7JGNvbmRpdGlvbmFsQ3VzdG9tQ29kZX0NCgkNCgkvLyBPcmlnaW5hbCBDb2RlIEVuZA0KCQkJDQp9DQoJDQpFT0Y7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnRmllbGQoZXZlbnQnLCAiRmllbGQoJ3skaWR9JyArIGsiLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnV3JhcHBlcihldmVudCcsICJXcmFwcGVyKCd7JGlkfScgKyBrIiwgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ0xvYWQoZXZlbnQnLCAiTG9hZCgneyRpZH0nICsgayIsICRjb25kaXRpb25hbEN1c3RvbSk7DQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5hcHBlbmRDb25kaXRpb25hbEV2ZW50Q29kZSgkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9ICJcblxuLy8gY3VzdG9tIGNhbGwgb25Mb2FkIHJld3JpdGUgZm9yIHskaWR9IC0tXG5cbnskY29uZGl0aW9uYWxDdXN0b219XG5cbi8vIGVuZCBjYWxsIGZvciB7JGlkfVxuIjsNCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ2hpZGVGaWVsZCcsICdoaWRlRmllbGRMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ3Nob3dGaWVsZCcsICdzaG93RmllbGRMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ2hpZGVXcmFwcGVyJywgJ2hpZGVXcmFwcGVyTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdzaG93V3JhcHBlcicsICdzaG93V3JhcHBlckxvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b21Mb29wID0gPDw8RU9GDQoJCQkJCQ0KCQkvLyBnZXQgdmFsdWUgb2YgdmFsaWQsIGFjdGl2ZSByYWRpbyBpdGVtIGZvciB7JGlkfQ0KCQkJCQkNCgkJaW5fdmFsdWUgPSAnJzsgLy8gc2V0IGRlZmF1bHQNCgkJCQkJDQoJCWZvcihrID0gMDsgayA8IDEwMDA7IGsrKyl7DQoJCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRpZH0nICsgaykgIT09IG51bGwpew0KCQkJCWlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd7JGlkfScgKyBrKS5jaGVja2VkKXsNCgkJCQkJaW5fdmFsdWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRpZH0nICsgaykudmFsdWU7DQoJCQkJCWJyZWFrOw0KCQkJCX0NCgkJCX0NCgkJfQ0KRU9GOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSAkY29uZGl0aW9uYWxDdXN0b21Mb29wIC4gJGNvbmRpdGlvbmFsQ3VzdG9tOw0KDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ0ZpZWxkKGV2ZW50JywgIkZpZWxkKCd7JGlkfScgKyBrIiwgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ1dyYXBwZXIoZXZlbnQnLCAiV3JhcHBlcigneyRpZH0nICsgayIsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdMb2FkKGV2ZW50JywgIkxvYWQoJ3skaWR9JyArIGsiLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQoNCiAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5hcHBlbmRDb25kaXRpb25hbEV2ZW50Q29kZSgkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGFkZENvbmR0aW9uYWxMb2FkRXZlbnRGb3JCdWNrZXRSZXBlYXRlcnMoJHR5cGUsICRpZCwgJGNvbmRpdGlvbmFsKQ0KICAgIHsNCg0KICAgICAgICANCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgICRyZXRfc3RhcnQgPSAiXG48c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj5cbiI7DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJHJldF9lbmQgPSAiXG48L3NjcmlwdD5cbiI7DQoNCiAgICAgICAgDQogICAgICAgIA0KDQogICAgICAgICRjb25kaXRpb25hbEFuaW1hdGlvbiA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFuaW1hdGlvbigoc3RyaW5nKSRjb25kaXRpb25hbC0+YW5pbWF0aW9uKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsQ29uZGl0aW9uID0gJHRoaXMtPnRyYW5zbGF0ZUNvbmRpdGlvbmFsQ29uZGl0aW9uKChzdHJpbmcpJGNvbmRpdGlvbmFsLT5jb25kaXRpb24pOw0KICAgICAgICAkY29uZGl0aW9uYWxWYWx1ZSA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT52YWx1ZSA9PSAnJyA/ICInJyIgOiAiJyIgLiAoc3RyaW5nKSRjb25kaXRpb25hbC0+dmFsdWUgLiAiJyI7DQogICAgICAgICRjb25kaXRpb25hbEFjdGlvbiA9ICR0aGlzLT50cmFuc2xhdGVDb25kaXRpb25hbEFjdGlvbigoc3RyaW5nKSRjb25kaXRpb25hbC0+YWN0aW9uKTsNCiAgICAgICAgJGNvbmRpdGlvbmFsRmllbGQgPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+ZmllbGQgPT0gJycgPyAiJyciIDogIiciIC4gKHN0cmluZykkY29uZGl0aW9uYWwtPmZpZWxkIC4gIiciOw0KICAgICAgICANCiAgICAgICAgJGNvbmRpdGlvbmFsV3JhcHBlciA9IChzdHJpbmcpJGNvbmRpdGlvbmFsLT53cmFwcGVyID09ICcnID8gIicnIiA6ICInIiAuIChzdHJpbmcpJGNvbmRpdGlvbmFsLT53cmFwcGVyIC4gIiciOw0KICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSAoc3RyaW5nKSRjb25kaXRpb25hbC0+Y3VzdG9tOw0KICAgICAgICAkY29uZGl0aW9uYWxUb2dnbGUgPSAoaW50KSRjb25kaXRpb25hbC0+dG9nZ2xlID09ICcxJyA/ICd0cnVlJyA6ICdmYWxzZSc7DQoNCiAgICAgICAgDQogICAgICAgIGlmICgoc3RyaW5nKSR0eXBlICE9ICdjaGVja2JveCcgJiYgKHN0cmluZykkdHlwZSAhPSAncmFkaW8nICYmIChzdHJpbmcpJHR5cGUgIT0gJ2Vjb21tJykgew0KICAgICAgICAgICAgJHVzZV93aGlsZSA9IDA7IA0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHVzZV93aGlsZSA9IDE7IA0KICAgICAgICB9DQoNCiAgICAgICAgDQogICAgICAgIGlmICgkY29uZGl0aW9uYWxDdXN0b20gPT0gIiIpIHsgDQogICAgICAgICAgICBpZiAoISR1c2Vfd2hpbGUpIHsNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxfY2FsbF9pbmxpbmUgPSAiZmJjLmhhbmRsZUV2ZW50TG9hZCgneyRpZH0nLCAkY29uZGl0aW9uYWxDb25kaXRpb24sICRjb25kaXRpb25hbFZhbHVlLCAkY29uZGl0aW9uYWxBY3Rpb24sICRjb25kaXRpb25hbEZpZWxkLCAkY29uZGl0aW9uYWxXcmFwcGVyLCAkY29uZGl0aW9uYWxUb2dnbGUsICRjb25kaXRpb25hbEFuaW1hdGlvbiwgZmFsc2UpOyI7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbF9jYWxsX2lubGluZSA9IDw8PEVPRg0KCQ0KCS8vIGNyZWF0ZSBsaXN0IG9mIHZhbGlkIGluZGV4ZXMgZm9yOiB7JGlkfQ0KCWogPSBuZXcgQXJyYXkoKTsNCgkNCglmb3IoayA9IDA7IGsgPCAxMDAwOyBrKyspew0KCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRpZH0nICsgaykgIT09IG51bGwpew0KCQkJai5wdXNoKCd7JGlkfScgKyBrKTsNCgkJfQ0KCX0NCg0KCWZvcih0ID0gMDsgdCA8IGoubGVuZ3RoOyB0Kyspew0KCQlpZihmYmMuaGFuZGxlRXZlbnRMb2FkKGpbdF0sICRjb25kaXRpb25hbENvbmRpdGlvbiwgJGNvbmRpdGlvbmFsVmFsdWUsICRjb25kaXRpb25hbEFjdGlvbiwgJGNvbmRpdGlvbmFsRmllbGQsICRjb25kaXRpb25hbFdyYXBwZXIsICRjb25kaXRpb25hbFRvZ2dsZSwgJGNvbmRpdGlvbmFsQW5pbWF0aW9uLCB0cnVlKSl7DQoJCQlicmVhazsNCgkJfQ0KCX0NCkVPRjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgJHJldCA9ICRyZXRfc3RhcnQ7DQogICAgICAgICAgICAkcmV0IC49ICRjb25kaXRpb25hbF9jYWxsX2lubGluZTsNCiAgICAgICAgICAgICRyZXQgLj0gJHJldF9lbmQ7DQoNCiAgICAgICAgICAgIHJldHVybiAkcmV0Ow0KICAgICAgICAgICAgDQogICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgIA0KDQogICAgICAgICAgICBpZiAoISR1c2Vfd2hpbGUpIHsgDQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSAiXG4vLyBjdXN0b20gY2FsbCBmb3IgeyRpZH0gLS1cbnskY29uZGl0aW9uYWxDdXN0b219XG4vLyBlbmQgY2FsbCBmb3IgeyRpZH1cbiI7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnaGlkZUZpZWxkJywgJ2hpZGVGaWVsZExvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdzaG93RmllbGQnLCAnc2hvd0ZpZWxkTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ2hpZGVXcmFwcGVyJywgJ2hpZGVXcmFwcGVyTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ3Nob3dXcmFwcGVyJywgJ3Nob3dXcmFwcGVyTG9hZCcsICRjb25kaXRpb25hbEN1c3RvbSk7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnZXZlbnQnLCAiJ3skaWR9JyIsICRjb25kaXRpb25hbEN1c3RvbSk7DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnaW5fdmFsdWUnLCAiZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWR9JykudmFsdWUiLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQoNCiAgICAgICAgICAgICAgICAkcmV0ID0gJHJldF9zdGFydDsNCiAgICAgICAgICAgICAgICAkcmV0IC49ICRjb25kaXRpb25hbEN1c3RvbTsNCiAgICAgICAgICAgICAgICAkcmV0IC49ICRyZXRfZW5kOw0KDQogICAgICAgICAgICAgICAgcmV0dXJuICRyZXQ7DQogICAgICAgICAgICB9IGVsc2UgeyANCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9ICJcclxuLy8gY3VzdG9tIGNhbGwgb25Mb2FkIHJld3JpdGUgZm9yIHskaWR9IC0tXHJcbnskY29uZGl0aW9uYWxDdXN0b219XHJcbi8vIGVuZCBjYWxsIGZvciB7JGlkfVxyXG4iOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tID0gc3RyX3JlcGxhY2UoJ2hpZGVGaWVsZCcsICdoaWRlRmllbGRMb2FkJywgJGNvbmRpdGlvbmFsQ3VzdG9tKTsNCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnc2hvd0ZpZWxkJywgJ3Nob3dGaWVsZExvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdoaWRlV3JhcHBlcicsICdoaWRlV3JhcHBlckxvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9IHN0cl9yZXBsYWNlKCdzaG93V3JhcHBlcicsICdzaG93V3JhcHBlckxvYWQnLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgJGNvbmRpdGlvbmFsQ3VzdG9tTG9vcCA9IDw8PEVPRg0KCQkJCQ0KCQkvLyBnZXQgdmFsdWUgb2YgdmFsaWQsIGFjdGl2ZSByYWRpbyBpdGVtIGZvciB7JGlkfQ0KCQkJCQ0KCQlpbl92YWx1ZSA9ICcnOyAvLyBzZXQgZGVmYXVsdA0KCQ0KCQlmb3IoayA9IDA7IGsgPCAxMDAwOyBrKyspew0KCQkJaWYoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWR9JyArIGspICE9PSBudWxsKXsNCgkJCQlpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneyRpZH0nICsgaykuY2hlY2tlZCl7DQoJCQkJCWluX3ZhbHVlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3skaWR9JyArIGspLnZhbHVlOw0KCQkJCQlicmVhazsNCgkJCQl9DQoJCQl9DQoJCX0NCkVPRjsNCg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICRjb25kaXRpb25hbEN1c3RvbSA9ICRjb25kaXRpb25hbEN1c3RvbUxvb3AgLiAkY29uZGl0aW9uYWxDdXN0b207DQoNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAkY29uZGl0aW9uYWxDdXN0b20gPSBzdHJfcmVwbGFjZSgnZXZlbnQnLCAiJ3skaWR9JyArIGsiLCAkY29uZGl0aW9uYWxDdXN0b20pOw0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAkcmV0ID0gJHJldF9zdGFydDsNCiAgICAgICAgICAgICAgICAkcmV0IC49ICRjb25kaXRpb25hbEN1c3RvbTsNCiAgICAgICAgICAgICAgICAkcmV0IC49ICRyZXRfZW5kOw0KDQogICAgICAgICAgICAgICAgcmV0dXJuICRyZXQ7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQoNCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9pbmxpbmVfZmllbGRfdmFycygkdGV4dCwgJHNlcGFyYXRvciA9ICcsICcpDQogICAgew0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgJHRleHQgPSAoc3RyaW5nKSR0ZXh0Ow0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oQFx7KC4qPylcfSkvJywgJHRleHQsICRtYXRjaGVzKTsNCg0KICAgICAgICAkYXJyYXlfdmFycyA9IGFycmF5KCk7IA0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRhcnJheV92YXJzW10gPSAiJyRtJyI7IA0KDQogICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICBpZiAoJG0gPT0gJ1RPREFZU19EQVRFJykgew0KDQogICAgICAgICAgICAgICAgICAgICR0ZXh0ID0gc3RyX3JlcGxhY2UoJ0B7JyAuICRtIC4gJ30nLCAiPD9waHAgZWNobyBkYXRlKCdtL2QvWScsIHRpbWUoKSk7ID8+IiwgJHRleHQpOw0KICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJG0gPT0gJ1RPREFZU19EQVRFX0VVJykgew0KDQogICAgICAgICAgICAgICAgICAgICR0ZXh0ID0gc3RyX3JlcGxhY2UoJ0B7JyAuICRtIC4gJ30nLCAiPD9waHAgZWNobyBkYXRlKCdkL20vWScsIHRpbWUoKSk7ID8+IiwgJHRleHQpOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJHRleHQgPSBzdHJfcmVwbGFjZSgnQHsnIC4gJG0gLiAnfScsICI8P3BocCBpZihpc3NldChcJF9TRVNTSU9OWydxcyddW1wie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfVwiXVsneyRtfSddKSkgeyBlY2hvIFwie1wkX1NFU1NJT05bJ3FzJ11bXCJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119XCJdWyd7JG19J119XCI7IH0/PiIsICR0ZXh0KTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICANCg0KICAgICAgICANCg0KICAgICAgICAkZHluX3ZhcnMgPSBpbXBsb2RlKCcsJywgJGFycmF5X3ZhcnMpOyANCg0KICAgICAgICAkZWxlbWVudCA9IDw8PEVPVA0KXG48P3BocA0KLy8gUHJvY2VzcyBBcnJheSBWYXJpYWJsZXMuDQppZighaXNzZXQoXCRhcnJheV92YXJzX3Byb2Nlc3NlZCkpeyANCgkvLyBjaGVjayBmb3IgYW5kIHJlcGxhY2UgYXJyYXkgYmFzZWQgdmFyaWFibGVzIGlmIG5vdCBhbHJlYWR5IGRvbmUNCglcJHZhcnMgPSBhcnJheSh7JGR5bl92YXJzfSk7DQoJZm9yZWFjaChcJHZhcnMgYXMgXCR2YXIpew0KCQlpZihpc3NldChcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bXCR2YXJdKSl7DQoJCQlpZihpc19hcnJheShcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bXCR2YXJdKSl7DQoJCQkJXCRmaWVsZF9pdGVtcyA9ICcnOw0KCQkJCWZvcmVhY2goXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdW1wkdmFyXSBhcyBcJGtleT0+XCR2KXsNCgkJCQkJaWYoXCRrZXkgIT0gMCl7IFwkZmllbGRfaXRlbXMgLj0gJ3skc2VwYXJhdG9yfSc7IH0NCgkJCQkJXCRmaWVsZF9pdGVtcyAuPSBcJHY7DQoJCQkJfQ0KCQkJCVwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVtcJHZhcl0gPSBcJGZpZWxkX2l0ZW1zOw0KCQkJfQ0KCQl9DQoJfQ0KCVwkYXJyYXlfdmFyc19wcm9jZXNzZWQgPSB0cnVlOw0KfQ0KPz4NCg0KRU9UOw0KDQogICAgICAgIA0KICAgICAgICANCg0KICAgICAgICAkZWxlbWVudCA9IDw8PEVPVA0KXG48P3BocA0KLy8gUHJvY2VzcyBBcnJheSBWYXJpYWJsZXMuDQppZighaXNzZXQoXCRhcnJheV92YXJzX3Byb2Nlc3NlZCkpeyBcJHZhcnMgPSBhcnJheSh7JGR5bl92YXJzfSk7IHByb2Nlc3NfYXJyYXlfdmFyaWFibGVzKFwkdmFycywgJ3skc2VwYXJhdG9yfScpOyBcJGFycmF5X3ZhcnNfcHJvY2Vzc2VkID0gdHJ1ZTsgfQ0KPz4NCgkJDQpFT1Q7DQoNCiAgICAgICAgDQogICAgICAgIHJldHVybiBhcnJheSgkdGV4dCwgJGVsZW1lbnQpOw0KICAgIH0NCg0KICAgIA0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVUYWJJbmRleENvZGUoJHRhYmluZGV4KQ0KICAgIHsNCg0KICAgICAgICAkdGFiaHRtbCA9ICcnOyANCg0KICAgICAgICBpZiAoaXNzZXQoJHRhYmluZGV4KSAmJiAkdGFiaW5kZXggIT0gJycgJiYgaXNfaW50KCR0YWJpbmRleCkpIHsNCiAgICAgICAgICAgICR0YWJodG1sID0gInRhYmluZGV4PVwieyR0YWJpbmRleH1cIiI7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gJHRhYmh0bWw7DQogICAgfQ0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2lubGluZV9nZXRfdmFycygkdGV4dCkNCiAgICB7DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkdGV4dCA9IChzdHJpbmcpJHRleHQ7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIHByZWdfbWF0Y2hfYWxsKCcvKF58Lnxccnxcbik/KCNceyguKj8pXH0pLycsICR0ZXh0LCAkbWF0Y2hlcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOyANCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1tdID0gIickbSciOyANCiAgICAgICAgICAgICAgICAkdGV4dCA9IHN0cl9yZXBsYWNlKCcjeycgLiAkbSAuICd9JywgIjw/cGhwIGlmKGlzc2V0KFwkX0dFVFsneyRtfSddKSkgeyBlY2hvIFwie1wkX0dFVFsneyRtfSddfVwiOyB9Pz4iLCAkdGV4dCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuICR0ZXh0Ow0KICAgIH0NCg0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9pbmxpbmVfcG9zdF92YXJzKCR0ZXh0KQ0KICAgIHsNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICR0ZXh0ID0gKHN0cmluZykkdGV4dDsNCg0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oXCpceyguKj8pXH0pLycsICR0ZXh0LCAkbWF0Y2hlcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOyANCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1tdID0gIickbSciOyANCiAgICAgICAgICAgICAgICAkdGV4dCA9IHN0cl9yZXBsYWNlKCcqeycgLiAkbSAuICd9JywgIjw/cGhwIGlmKGlzc2V0KFwkX1BPU1RbJ3skbX0nXSkpIHsgZWNobyBcIntcJF9QT1NUWyd7JG19J119XCI7IH0/PiIsICR0ZXh0KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHRleHQ7DQogICAgfQ0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2lubGluZV9zZXNzaW9uX3ZhcnMoJHRleHQpDQogICAgew0KICAgICAgICANCiAgICAgICAgDQogICAgICAgICRtYXRjaGVzID0gYXJyYXkoKTsNCiAgICAgICAgJHRleHQgPSAoc3RyaW5nKSR0ZXh0Ow0KDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pPyhcXlx7KC4qPylcfSkvJywgJHRleHQsICRtYXRjaGVzKTsNCg0KICAgICAgICAkYXJyYXlfdmFycyA9IGFycmF5KCk7IA0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRhcnJheV92YXJzW10gPSAiJyRtJyI7IA0KICAgICAgICAgICAgICAgICR0ZXh0ID0gc3RyX3JlcGxhY2UoJ157JyAuICRtIC4gJ30nLCAiPD9waHAgaWYoaXNzZXQoXCRfU0VTU0lPTlsneyRtfSddKSkgeyBlY2hvIFwie1wkX1NFU1NJT05bJ3skbX0nXX1cIjsgfT8+IiwgJHRleHQpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkdGV4dDsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2lubGluZV9waHBfdmFycygkdGV4dCkNCiAgICB7DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkdGV4dCA9IChzdHJpbmcpJHRleHQ7DQoNCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgDQogICAgICAgIA0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pPyhQSFBceyguKj8pXH0pLycsICR0ZXh0LCAkbWF0Y2hlcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOyANCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1tdID0gIickbSciOyANCiAgICAgICAgICAgICAgICAkdGV4dCA9IHN0cl9yZXBsYWNlKCckeycgLiAkbSAuICd9JywgIjw/cGhwIGlmKGlzc2V0KFwkeyRtfSkpIHsgZWNobyBcJHskbX07IH0gPz4iLCAkdGV4dCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuICR0ZXh0Ow0KICAgIH0NCg0KDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9lbWJlZGRlZF9maWVsZF92YXJzKCR0ZXh0LCAkc2VwYXJhdG9yID0gJywgJykNCiAgICB7DQogICAgICAgIA0KICAgICAgICANCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkdGV4dCA9IChzdHJpbmcpJHRleHQ7DQoNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oQFx7KC4qPylcfSkvJywgJHRleHQsICRtYXRjaGVzKTsNCg0KICAgICAgICAkYXJyYXlfdmFycyA9IGFycmF5KCk7IA0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRhcnJheV92YXJzW10gPSAiJyRtJyI7IA0KICAgICAgICAgICAgICAgICR0ZXh0ID0gc3RyX3JlcGxhY2UoJ0B7JyAuICRtIC4gJ30nLCAiXCRfU0VTU0lPTlsncXMnXVtcIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX1cIl1bJ3skbX0nXSIsICR0ZXh0KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIA0KICAgICAgICAkZHluX3ZhcnMgPSBpbXBsb2RlKCcsJywgJGFycmF5X3ZhcnMpOyANCg0KICAgICAgICAkZWxlbWVudCA9IDw8PEVPVA0KXG48P3BocA0KaWYoIWlzc2V0KFwkYXJyYXlfdmFyc19wcm9jZXNzZWQpKXsgDQoJLy8gY2hlY2sgZm9yIGFuZCByZXBsYWNlIGFycmF5IGJhc2VkIHZhcmlhYmxlcyBpZiBub3QgYWxyZWFkeSBkb25lDQoJXCR2YXJzID0gYXJyYXkoeyRkeW5fdmFyc30pOw0KCWZvcmVhY2goXCR2YXJzIGFzIFwkdmFyKXsNCgkJaWYoaXNzZXQoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdW1wkdmFyXSkpew0KCQkJaWYoaXNfYXJyYXkoXCRfU0VTU0lPTlsncXMnXVsie1wkX1NFU1NJT05bJ2VudHJ5X2tleSddfSJdW1wkdmFyXSkpew0KCQkJCVwkZmllbGRfaXRlbXMgPSAnJzsNCgkJCQlmb3JlYWNoKFwkX1NFU1NJT05bJ3FzJ11bIntcJF9TRVNTSU9OWydlbnRyeV9rZXknXX0iXVtcJHZhcl0gYXMgXCRrZXk9Plwkdil7DQoJCQkJCWlmKFwka2V5ICE9IDApeyBcJGZpZWxkX2l0ZW1zIC49ICd7JHNlcGFyYXRvcn0nOyB9DQoJCQkJCVwkZmllbGRfaXRlbXMgLj0gXCR2Ow0KCQkJCX0NCgkJCQlcJF9TRVNTSU9OWydxcyddWyJ7XCRfU0VTU0lPTlsnZW50cnlfa2V5J119Il1bXCR2YXJdID0gXCRmaWVsZF9pdGVtczsNCgkJCX0NCgkJfQ0KCX0NCglcJGFycmF5X3ZhcnNfcHJvY2Vzc2VkID0gdHJ1ZTsNCn0NCj8+DQoNCkVPVDsNCg0KICAgICAgICANCiAgICAgICAgJGVsZW1lbnQgPSA8PDxFT1QNClxuPD9waHANCi8vIFByb2Nlc3MgQXJyYXkgVmFyaWFibGVzLg0KaWYoIWlzc2V0KFwkYXJyYXlfdmFyc19wcm9jZXNzZWQpKXsgXCR2YXJzID0gYXJyYXkoeyRkeW5fdmFyc30pOyBwcm9jZXNzX2FycmF5X3ZhcmlhYmxlcyhcJHZhcnMsICd7JHNlcGFyYXRvcn0nKTsgXCRhcnJheV92YXJzX3Byb2Nlc3NlZCA9IHRydWU7IH0NCj8+DQoJCQ0KRU9UOw0KDQogICAgICAgIA0KICAgICAgICByZXR1cm4gYXJyYXkoJHRleHQsICRlbGVtZW50KTsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2VtYmVkZGVkX2dldF92YXJzKCR0ZXh0KQ0KICAgIHsNCg0KICAgICAgICAkbWF0Y2hlcyA9IGFycmF5KCk7DQogICAgICAgICR0ZXh0ID0gKHN0cmluZykkdGV4dDsNCg0KICAgICAgICBwcmVnX21hdGNoX2FsbCgnLyhefC58XHJ8XG4pPygjXHsoLio/KVx9KS8nLCAkdGV4dCwgJG1hdGNoZXMpOw0KDQogICAgICAgICRhcnJheV92YXJzID0gYXJyYXkoKTsgDQogICAgICAgIGlmIChpc3NldCgkbWF0Y2hlc1szXSkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRtYXRjaGVzWzNdIGFzICRtKSB7DQogICAgICAgICAgICAgICAgJGFycmF5X3ZhcnNbXSA9ICInJG0nIjsgDQogICAgICAgICAgICAgICAgJHRleHQgPSBzdHJfcmVwbGFjZSgnI3snIC4gJG0gLiAnfScsICJcJF9HRVRbJ3skbX0nXSIsICR0ZXh0KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHRleHQ7DQogICAgfQ0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2VtYmVkZGVkX3Bvc3RfdmFycygkdGV4dCkNCiAgICB7DQoNCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkdGV4dCA9IChzdHJpbmcpJHRleHQ7DQoNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oXCpceyguKj8pXH0pLycsICR0ZXh0LCAkbWF0Y2hlcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOyANCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1tdID0gIickbSciOyANCiAgICAgICAgICAgICAgICAkdGV4dCA9IHN0cl9yZXBsYWNlKCcqeycgLiAkbSAuICd9JywgIlwkX1BPU1RbJ3skbX0nXSIsICR0ZXh0KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHRleHQ7DQogICAgfQ0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX2VtYmVkZGVkX3Nlc3Npb25fdmFycygkdGV4dCkNCiAgICB7DQoNCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOw0KICAgICAgICAkdGV4dCA9IChzdHJpbmcpJHRleHQ7DQoNCiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJy8oXnwufFxyfFxuKT8oXF5ceyguKj8pXH0pLycsICR0ZXh0LCAkbWF0Y2hlcyk7DQoNCiAgICAgICAgJGFycmF5X3ZhcnMgPSBhcnJheSgpOyANCiAgICAgICAgaWYgKGlzc2V0KCRtYXRjaGVzWzNdKSkgew0KICAgICAgICAgICAgZm9yZWFjaCAoJG1hdGNoZXNbM10gYXMgJG0pIHsNCiAgICAgICAgICAgICAgICAkYXJyYXlfdmFyc1tdID0gIickbSciOyANCiAgICAgICAgICAgICAgICAkdGV4dCA9IHN0cl9yZXBsYWNlKCdeeycgLiAkbSAuICd9JywgIlwkX1NFU1NJT05bJ3skbX0nXSIsICR0ZXh0KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHRleHQ7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZV9lbWJlZGRlZF9waHBfdmFycygkdGV4dCkNCiAgICB7DQoNCiAgICAgICAgJG1hdGNoZXMgPSBhcnJheSgpOyANCiAgICAgICAgJHRleHQgPSAoc3RyaW5nKSR0ZXh0Ow0KDQogICAgICAgIHByZWdfbWF0Y2hfYWxsKCcvKF58Lnxccnxcbik/KFBIUFx7KC4qPylcfSkvJywgJHRleHQsICRtYXRjaGVzKTsNCg0KICAgICAgICAkYXJyYXlfdmFycyA9IGFycmF5KCk7IA0KICAgICAgICBpZiAoaXNzZXQoJG1hdGNoZXNbM10pKSB7DQogICAgICAgICAgICBmb3JlYWNoICgkbWF0Y2hlc1szXSBhcyAkbSkgew0KICAgICAgICAgICAgICAgICRhcnJheV92YXJzW10gPSAiJyRtJyI7IA0KICAgICAgICAgICAgICAgICR0ZXh0ID0gc3RyX3JlcGxhY2UoJ1BIUHsnIC4gJG0gLiAnfScsICJcJHskbX0iLCAkdGV4dCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuICR0ZXh0Ow0KICAgIH0NCn0NCj8+')); ?>
Function Calls
base64_decode | 1 |
Stats
MD5 | cf517fd745e0590d6f9a39b8e522bda8 |
Eval Count | 1 |
Decode Time | 1925 ms |