<?php
/**
* Hangang System inc.
*
* Customer Doc Class
* 고객 증빙 서류 upload 클래스 정보
* 2019.11.04
*
*/
class Customer_Doc
{
public static $instance ;
private $c_db = NULL ;
private $results = NULL ;
private $agent_id = NULL ;
private $contract_kind = NULL ;
private $current_password = NULL ;
private $work_kind = NULL;
private $ContractInfo = NULL;
private $DocumentInfo = NULL;
public function __construct()
{
$this->c_db = DBController::getInstance() ;
}
public static function getInstance()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function check_login($market_code, $agent_id)
{
$results = $this->c_db->SQLGetRow("GET_GROUP_LOGIN_USER", array($market_code, $agent_id));
if( $results == false )
{
return false;
}
else
{
$this->makeSession($results);
}
$this->c_db->disconn();
return true ;
}
public function getResult()
{
return $this->results;
}
public function makeSession($results)
{
@logHandler
(PEAR_LOG_INFO
, "Make Session : ". print_r($results, true), $PHP_SELF, __FILE__, __LINE__ ) ;
$this->results = $results;
}
public function setContractInfo($con_info)
{
// Hangang_auto_start (autopay - upload)
/* 작업 정보 */
if ($con_info['contract_kind'] =="P")
{
if ($con_info['activity_code'] == "C84"){
$this->ContractInfo = $this->c_db->SQLGetRow('GET_REC_PAYMENT_METHOD_HISTORY', array($con_info['market_code'], $con_info['work_group'])) ; }
else{
$this->ContractInfo = $this->c_db->SQLGetRow('GET_REC_CCM_WORK_GROUP', array($con_info['market_code'], $con_info['work_group'], CCM_WORK_STATUS_COMPLETE
)) ; }
{
throw new Exception (ERROR_CODE_NO_WORK_GROUP);
}
}
// Hangang_auto_end
// 2018.10.17 ==> for encryption password
{
$customerInfo = $this->c_db->SQLGetRow('GET_CUSTOMER_PASSWORD_INFO', array($con_info['market_code'], $con_info['cid'] )) ;
{
@logHandler(PEAR_LOG_ERR, "GET_CUSTOMER_PASSWORD_INFO FAILURE", $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_NO_WORK_GROUP);
}
if( strlen($customerInfo['BIRTHDAY']) == 6) {
$this->ContractInfo['CUSTYYMMDD'] = $customerInfo['BIRTHDAY'];
}
elseif( strlen($customerInfo['BIRTHDAY']) == 10 ) {
$this->ContractInfo['CUSTYYMMDD'] = substr($customerInfo['BIRTHDAY'],0,6); }
else
{
$this->ContractInfo['CUSTYYMMDD'] = substr($customerInfo['REP_ID'],0,6); }
}
// 2018.10.17 ==> for encryption password
$this->ContractInfo['INFO'] = $con_info;
//폴더명과 파일명 세팅처리
if (!$this->ContractInfo['INFO']['seq'])
{
$folder_name = $this->getPDFServerFolderName();
$file_name = $this->getPDFServerFileName();
$this->ContractInfo['INFO']['seq'] = $this->c_db->SQLGetOne('GET_GROUP_CONTRACT_INFO_SEQ',array($this->ContractInfo['INFO']['market_code'], $this->ContractInfo['INFO']['cid']));
$file_name .= "_".$this->ContractInfo['INFO']['seq'].".pdf";
$this->ContractInfo['INFO']['folder_name'] =$folder_name;
$this->ContractInfo['INFO']['file_name'] =$file_name;
}
@logHandler
(PEAR_LOG_INFO
, print_r($this->ContractInfo, true), $PHP_SELF, __FILE__, __LINE__ ) ; }
public function getContractInfo()
{
return $this->ContractInfo;
}
//------------------------------------------------------------
// insert Document -- 이 부분 다시 수정해야 한다.
public function insertDocumentInfo($doc_info) {
$seq_cnt = $this->c_db->SQLGetOne('GET_CUSTOMER_DOCUMENT_SEQ', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'] ));
if($seq_cnt = 2) {
if( false == $this->c_db->SQLExecute('UPD_CUSTOMER_DOCUMENT', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'], $seq_cnt - 1)) ) throw new Exception(ERROR_CODE_DB_FAILURE);
} else if($seq_cnt > 2) {
if( false == $this->c_db->SQLExecute('INS_CUSTOMER_DOCUMENT', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'], $seq_cnt)) ) throw new Exception(ERROR_CODE_DB_FAILURE);
}
}
// set Document
public function setDocumentInfo($doc_info, $ext) {
// Hangang_auto_end
// 2018.10.17 ==> for encryption password
/*
{
$customerInfo = $this->c_db->SQLGetRow('GET_CUSTOMER_PASSWORD_INFO', array($con_info['market_code'], $con_info['cid'] )) ;
if(! is_array($customerInfo))
{
@logHandler(PEAR_LOG_ERR, "GET_CUSTOMER_PASSWORD_INFO FAILURE", $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_NO_WORK_GROUP);
}
if( strlen($customerInfo['BIRTHDAY']) == 6)
{
$this->DocumentInfo['CUSTYYMMDD'] = $customerInfo['BIRTHDAY'];
}
elseif( strlen($customerInfo['BIRTHDAY']) == 10 )
{
$this->DocumentInfo['CUSTYYMMDD'] = substr($customerInfo['BIRTHDAY'],0,6);
}
else
{
$this->DocumentInfo['CUSTYYMMDD'] = substr($customerInfo['REP_ID'],0,6);
}
}
*/
$seq_cnt = $this->c_db->SQLGetOne('GET_CUSTOMER_DOCUMENT_SEQ', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'] )); $seq_cnt = $seq_cnt - 1;
$this->DocumentInfo = $this->c_db->SQLGetRow('GET_CUSTOMER_DOCUMENT_INFO', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'], $seq_cnt));
throw new Exception (ERROR_CODE_NO_WORK_GROUP);
}
$this->DocumentInfo['INFO'] = $doc_info;
//폴더명과 파일명 세팅처리
if (!$this->DocumentInfo['INFO']['seq']) {
$folder_name = $this->getDocumentFolderName();
$file_name = $this->getDocumentFileName();
$this->DocumentInfo['INFO']['seq'] = $seq_cnt;
$file_name .= "_" . $this->DocumentInfo['INFO']['seq'] . "." . $ext;
$this->DocumentInfo['INFO']['folder_name'] = $folder_name;
$this->DocumentInfo['INFO']['file_name'] = $file_name;
}
@logHandler
(PEAR_LOG_INFO
, print_r($this->DocumentInfo, true), $PHP_SELF, __FILE__, __LINE__ ) ;
}
public function getDocumentInfo() {
return $this->DocumentInfo;
}
//ftp 서버 접속
public function _connect_ftpServer()
{
$msg = "";
$c_imgServer = ImageServer::getInstance() ;
$imgServerInfo = $c_imgServer->getImageServerInfo();
if($imgServerInfo['SERVER_IP'] == "" || $imgServerInfo['SERVER_PORT'] == "" || $imgServerInfo['USER_ID'] == "")
{
@logHandler(PEAR_LOG_ERR, "No ImageServer FTP Server Connection Info", $PHP_SELF, __FILE__, __LINE__ ) ;
@logHandler
(PEAR_LOG_ERR
, print_r($imgServerInfo, true), $PHP_SELF, __FILE__, __LINE__ ) ; throw new Exception (ERROR_CODE_NO_INF_INFO);
}
$this->ftp_conn = @ftp_connect ($imgServerInfo['SERVER_IP'], $imgServerInfo['SERVER_PORT'] );
if(false == $this->ftp_conn)
{
@logHandler(PEAR_LOG_ERR, "FTP Server Connection Failure [{$imgServerInfo['SERVER_IP']}[{$imgServerInfo['SERVER_PORT']}]", $PHP_SELF, __FILE__, __LINE__ ) ;
// throw new Exception (ERROR_CODE_ERR_INF_SERVER);
}
if(false == @ftp_login($this->ftp_conn, $imgServerInfo['USER_ID'], $imgServerInfo['USER_PW'])) {
@logHandler(PEAR_LOG_ERR, "FTP Server Login Failure [{$imgServerInfo['USER_ID']}[{$imgServerInfo['USER_PW']}]", $PHP_SELF, __FILE__, __LINE__ ) ;
//throw new Exception (ERROR_CODE_ERR_INF_SERVER);
}else{
@logHandler(PEAR_LOG_INFO, "set ftp to passive mode.".FTP_MODE, $PHP_SELF, __FILE__, __LINE__ );
ftp_pasv($this->ftp_conn, FTP_MODE
=="PASSIVE" ); }
if( $imgServerInfo['FOLDER'] )
{
@ftp_chdir($this->ftp_conn, $imgServerInfo['FOLDER']); }
}
//계약서 upload
// 2018.10.17 ==> for encryption password
//public function _uploadImageServerPDF($contract_kind, $att_file_info = array())
public function _uploadImageServerPDF
($contract_kind, $att_file_info = array(), $enc_password) // 2018.10.17 ==> for encryption password
{
$this->_connect_ftpServer();
if( !is_file( $att_file_info['tmp_name'] ) ) {
@logHandler(PEAR_LOG_ERR, "NO FILE To FTP Put Attach : " . $att_file_info['tmp_name'], $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
try
{
// 2018.10.17 ==> for encryption password
//$this->_saveImageServerPDF($att_file_info, $contract_kind);
$this->_saveImageServerPDF($att_file_info, $contract_kind, $enc_password);
// 2018.10.17 ==> for encryption password
}
catch (Exception $e)
{
throw $e;
}
}
// 고객 증빙 서류 업로드
public function _uploadDocumentServer
($att_file_info = array()) {
$this->_connect_ftpServer();
if( !is_file( $att_file_info['tmp_name'] ) ) {
@logHandler(PEAR_LOG_ERR, "NO FILE To FTP Put Attach : " . $att_file_info['tmp_name'], $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
try
{
// 2018.10.17 ==> for encryption password
//$this->_saveImageServerPDF($att_file_info, $contract_kind);
//$this->_saveImageServerPDF($att_file_info, $contract_kind, $enc_password);
$this->_saveDocumentServer($att_file_info);
}
catch (Exception $e)
{
throw $e;
}
}
public function _saveDocumentServer($att_file_info) {
if( !is_file( $att_file_info['tmp_name'] ) ) {
@logHandler(PEAR_LOG_ERR, "NO FILE To FTP Put Attach : " . $att_file_info['tmp_name'], $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
$folder = $this->DocumentInfo['INFO']['folder_name'];
$file = $this->DocumentInfo['INFO']['file_name'];
$parts = explode('/',$folder); // SOID/YYYY/MMDD foreach($parts as $part)
{
{
}
}
// $tmpfile = TMP_DIR . "/" . uniqid();
$tmpfile = TMP_DIR . "/" . $file;
/* DRM 해지 처리 : 2018.08.28 */
if(isDRMEncryptedFile($tmpfile))
{
$encfile = TMP_DIR . "/enc_" . $file;
if(doDRMExtract($tmpfile, $encfile))
{
$tmpfile = $encfile;
}
}
/*
// 2018.10.17 ==> for encryption password
$exec_command = PDFSECURE_PROGRAM . " --encrypt '{$enc_password}' '' 128 --use-aes=y -- " . $tmpfile . " " . $tmpfile . "__enc_pass";
@logHandler(PEAR_LOG_INFO, $exec_command , $PHP_SELF, __FILE__, __LINE__ ) ;
exec( $exec_command );
if( !is_file( $tmpfile . "__enc_pass" ) )
{
@logHandler(PEAR_LOG_ERR, "NO FILE Found (Secured Applied) : " . $tmpfile . "__enc_pass", $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_PDF_PROCESS);
}
$tmpfile = $tmpfile . "__enc_pass";
// 2018.10.17 ==> for encryption password
*/
if(!@ftp_put($this->ftp_conn, $file, $tmpfile, FTP_BINARY
)) {
@logHandler(PEAR_LOG_ERR, "FTP upload Failure : " . $tmpfile . " ===> $file ", $PHP_SELF, __FILE__, __LINE__ ) ;
// throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
// Hangang_auto_start (autopay - upload)
//개인 계약서 일 경우 cid_install_barcode 에 저장한다.
/*
if (($this->ContractInfo['INFO']['contract_kind']=="P") && ($this->ContractInfo['INFO']['activity_code']!="C84"))
// if ($this->ContractInfo['INFO']['contract_kind']=="P")
{
@logHandler(PEAR_LOG_INFO, "Insert into cid_install_barcode", $PHP_SELF, __FILE__, __LINE__ );
$this->insertBarcode();
}
*/
// Hangang_auto_end
//신규테이블에 계약서 upload 정보를 저장한다.
//@logHandler(PEAR_LOG_INFO, "Insert into customer_document", $PHP_SELF, __FILE__, __LINE__ );
/*
$this->insertGroupContract();
//insert ccm_memo
@logHandler(PEAR_LOG_INFO, "Insert into ccm_memo", $PHP_SELF, __FILE__, __LINE__ );
$sys_memo_text = $this->ContractInfo['INFO']['contract_kind'] =="P"? "작업내역:[개인 계약서 업로드]":"작업상태:[단체 계약서 업로드]";
$usr_memo_text = "1.파일명: [".$this->ContractInfo['INFO']['file_name']."], 2.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
$this->insertCCM_MEMO($sys_memo_text, $usr_memo_text);
// Hangang_auto_start : insertPaymentMethodHistory (autopay - upload)
//insert payment_method_history
@logHandler(PEAR_LOG_INFO, "Insert into payment_method_history", $PHP_SELF, __FILE__, __LINE__ );
$this->insertPaymentMethodHistory();
// Hangang_auto_end
$this->commit();
*/
// 파일 경로 업데이트 - check status = Y 로 바꾸어야 함 .
// $this->updateDocumentFile();
}
/*
public function updateDocumentFile() {
if( false == $this->c_db->SQLExecute('UPD_CUSTOMER_DOCUMENT', array($doc_info['market_code'], $doc_info['cid'], $doc_info['reg_date'], $seq_cnt)) )
throw new Exception(ERROR_CODE_DB_FAILURE);
}
*/
//계약서 서버 저장
// 2018.10.17 ==> for encryption password
//public function _saveImageServerPDF($att_file_info, $contract_kind)
public function _saveImageServerPDF($att_file_info, $contract_kind, $enc_password)
// 2018.10.17 ==> for encryption password
{
if( !is_file( $att_file_info['tmp_name'] ) ) {
@logHandler(PEAR_LOG_ERR, "NO FILE To FTP Put Attach : " . $att_file_info['tmp_name'], $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
$folder = $this->ContractInfo['INFO']['folder_name'];
$file = $this->ContractInfo['INFO']['file_name'];
$parts = explode('/',$folder); // SOID/YYYY/MMDD foreach($parts as $part)
{
{
}
}
$tmpfile = TMP_DIR
. "/" . uniqid();
/* DRM 해지 처리 : 2018.08.28 */
if(isDRMEncryptedFile($tmpfile))
{
$encfile = TMP_DIR
. "/enc_" . uniqid(); if(doDRMExtract($tmpfile, $encfile))
{
$tmpfile = $encfile;
}
}
// 2018.10.17 ==> for encryption password
$exec_command = PDFSECURE_PROGRAM . " --encrypt '{$enc_password}' '' 128 --use-aes=y -- " . $tmpfile . " " . $tmpfile . "__enc_pass";
@logHandler(PEAR_LOG_INFO, $exec_command , $PHP_SELF, __FILE__, __LINE__ ) ;
if( !is_file( $tmpfile . "__enc_pass" ) ) {
@logHandler(PEAR_LOG_ERR, "NO FILE Found (Secured Applied) : " . $tmpfile . "__enc_pass", $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_PDF_PROCESS);
}
$tmpfile = $tmpfile . "__enc_pass";
// 2018.10.17 ==> for encryption password
if(!@ftp_put($this->ftp_conn, $file, $tmpfile, FTP_BINARY
)) {
@logHandler(PEAR_LOG_ERR, "FTP upload Failure : " . $tmpfile . " ===> $file ", $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_ATT_PROCESS);
}
// Hangang_auto_start (autopay - upload)
//개인 계약서 일 경우 cid_install_barcode 에 저장한다.
if (($this->ContractInfo['INFO']['contract_kind']=="P") && ($this->ContractInfo['INFO']['activity_code']!="C84"))
// if ($this->ContractInfo['INFO']['contract_kind']=="P")
{
@logHandler(PEAR_LOG_INFO, "Insert into cid_install_barcode", $PHP_SELF, __FILE__, __LINE__ );
$this->insertBarcode();
}
// Hangang_auto_end
//신규테이블에 계약서 upload 정보를 저장한다.
@logHandler(PEAR_LOG_INFO, "Insert into group_contract_info", $PHP_SELF, __FILE__, __LINE__ );
$this->insertGroupContract();
//insert ccm_memo
@logHandler(PEAR_LOG_INFO, "Insert into ccm_memo", $PHP_SELF, __FILE__, __LINE__ );
$sys_memo_text = $this->ContractInfo['INFO']['contract_kind'] =="P"? "작업내역:[개인 계약서 업로드]":"작업상태:[단체 계약서 업로드]";
$usr_memo_text = "1.파일명: [".$this->ContractInfo['INFO']['file_name']."], 2.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
$this->insertCCM_MEMO($sys_memo_text, $usr_memo_text);
// Hangang_auto_start : insertPaymentMethodHistory (autopay - upload)
//insert payment_method_history
@logHandler(PEAR_LOG_INFO, "Insert into payment_method_history", $PHP_SELF, __FILE__, __LINE__ );
$this->insertPaymentMethodHistory();
// Hangang_auto_end
$this->commit();
}
//파일 다운로드
public function _downImageServerPDF($file_name)
{
$this->_connect_ftpServer();
$sys_memo_text = $this->ContractInfo['INFO']['contract_kind'] =="P"? "작업내역:[개인 계약서 다운로드]":"작업상태:[단체 계약서 다운로드]";
$usr_memo_text = "1.파일명: [".$file_name."], 2.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
$this->insertCCM_MEMO($sys_memo_text, $usr_memo_text);
if(0 < ftp_size($this->ftp_conn, $file_name)) {
if(!ftp_get($this->ftp_conn, TMP_DIR
. "/" . $this->file, $file_name, FTP_BINARY
)) {
@logHandler(PEAR_LOG_ERR, "FTP DownLoad Failure : " . $file_name, $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_PDF_PROCESS);
}
}
else
{
@logHandler(PEAR_LOG_ERR, "FTP FILE NOT EXISTS : " . $file_name, $PHP_SELF, __FILE__, __LINE__ ) ;
prtErr("이미지 서버에 파일({$file_name})이 없습니다.");
return "이미지 서버에 파일({$file_name})이 없습니다.";
}
return TMP_DIR
. "/" . $this->file ; }
// 파일 삭제
public function _deleteImageServerPDF($file_name)
{
$this->_connect_ftpServer();
if(0 < ftp_size($this->ftp_conn, $file_name)) {
{
@logHandler(PEAR_LOG_ERR, "FTP delete Failure : " . $file_name, $PHP_SELF, __FILE__, __LINE__ ) ;
throw new Exception (ERROR_CODE_ERR_PDF_PROCESS);
}
}
}
//insert cid_install_barcode
public function insertBarcode()
{
@logHandler(PEAR_LOG_INFO, "Insert into cid_install_barcode start", $PHP_SELF, __FILE__, __LINE__ ) ;
$exist = $this->c_db->SQLGetOne('GET_CID_INSTALL_BARCODE_COUNT',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['work_group']
));
if($exist){
if(false == $this->c_db->SQLExecute('UPD_CID_INSTALL_BARCODE',
"Y" // --scan_yn
,$this->ContractInfo['INFO']['agree_yn'] // -- agree_yn
,$this->ContractInfo['INFO']['agree_yn2'] // -- agree_yn2
,$this->ContractInfo['INFO']['agree_yn3'] // -- agree_yn3
,$this->ContractInfo['INFO']['agree_yn4'] // -- agree_yn4
,$this->ContractInfo['INFO']['agent_id'] // -- scan_agent
,""
,"" // -- post_gubun
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['work_group']
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}else{
if(false == $this->c_db->SQLExecute('INS_CID_INSTALL_BARCODE',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['work_group']
,$this->ContractInfo['WORK_REG_DATE']
,$this->ContractInfo['ACTIVITY_CODE']
,"1"
,$this->ContractInfo['INFO']['agent_id']
,"FTP" // -- sys_application_id
,"INS" // -- dl_service_code
,"0" // -- dl_update_stamp
,$this->ContractInfo['FULL_NAME'] // -- full_name
,$this->ContractInfo['CID_STATUS'] // -- cid_status
,"W" // -- keep_status
,substr($this->ContractInfo['WORK_DATETIME'], 0, 8) // -- actv_date ,$this->ContractInfo['INFO']['agent_id'] // -- actv_agent
,"Y" // -- scan_yn
,$this->ContractInfo['INFO']['agree_yn'] // -- agree_yn
,$this->ContractInfo['INFO']['agree_yn2'] // -- agree_yn2
,$this->ContractInfo['INFO']['agree_yn3'] // -- agree_yn3
,$this->ContractInfo['INFO']['agree_yn4'] // -- agree_yn4
,"" // -- doc_type
,$this->ContractInfo['INFO']['agent_id'] // -- scan_agent
,"" // -- post_gubun
,""
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
@logHandler(PEAR_LOG_INFO, "Insert into cid_install_barcode end", $PHP_SELF, __FILE__, __LINE__ ) ;
}
//install group_contract_info
public function insertGroupContract()
{
@logHandler(PEAR_LOG_INFO, "Insert into group_contract_info start", $PHP_SELF, __FILE__, __LINE__ ) ;
$exist = $this->c_db->SQLGetOne('GET_GROUP_CONTRACT_INFO_COUNT',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
));
if($exist){
//기존 이력 저장
$this->insertGroupHistory();
if(false == $this->c_db->SQLExecute('UPD_GROUP_CONTRACT_INFO',
$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['agent_id'] // --reg_agent_id
,$this->ContractInfo['INFO']['remark'] // --remark
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
else
{ //신규저장
if(false == $this->c_db->SQLExecute('INS_GROUP_CONTRACT_INFO',
$this->ContractInfo['INFO']['market_code'] // --market_code
,$this->ContractInfo['INFO']['cid'] // --cid
,$this->ContractInfo['INFO']['seq'] // --seq
,date('Ymd') // --reg_date ,$this->ContractInfo['INFO']['agent_id'] // --reg_agent_id
,$this->ContractInfo['INFO']['contract_kind'] // --contract_kind
,$this->ContractInfo['INFO']['contract_type'] // --contract_type
,$this->ContractInfo['INFO']['work_group'] // --work_group
,$this->ContractInfo['ACTIVITY_CODE'] // --activity_code
,$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['folder_name'] // --folder_name
,$this->ContractInfo['INFO']['file_name'] // --file_name
,"Y" // --flag
,$this->ContractInfo['INFO']['remark'] // --remark
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
//$this->commit();
@logHandler(PEAR_LOG_INFO, "Insert into group_contract_info end", $PHP_SELF, __FILE__, __LINE__ ) ;
}
//install customer_document
public function insertCustomerDocument()
{
@logHandler(PEAR_LOG_INFO, "Insert into customer_document start", $PHP_SELF, __FILE__, __LINE__ ) ;
$exist = $this->c_db->SQLGetOne('GET_GROUP_CONTRACT_INFO_COUNT',
$this->DocumentInfo['INFO']['market_code']
,$this->DocumentInfo['INFO']['cid']
,$this->DocumentInfo['INFO']['seq']
));
if($exist){
//기존 이력 저장
$this->insertDocumentHistory();
if(false == $this->c_db->SQLExecute('UPD_GROUP_CONTRACT_INFO',
$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['agent_id'] // --reg_agent_id
,$this->ContractInfo['INFO']['remark'] // --remark
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
else
{ //신규저장
if(false == $this->c_db->SQLExecute('INS_GROUP_CONTRACT_INFO',
$this->ContractInfo['INFO']['market_code'] // --market_code
,$this->ContractInfo['INFO']['cid'] // --cid
,$this->ContractInfo['INFO']['seq'] // --seq
,date('Ymd') // --reg_date ,$this->ContractInfo['INFO']['agent_id'] // --reg_agent_id
,$this->ContractInfo['INFO']['contract_kind'] // --contract_kind
,$this->ContractInfo['INFO']['contract_type'] // --contract_type
,$this->ContractInfo['INFO']['work_group'] // --work_group
,$this->ContractInfo['ACTIVITY_CODE'] // --activity_code
,$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['folder_name'] // --folder_name
,$this->ContractInfo['INFO']['file_name'] // --file_name
,"Y" // --flag
,$this->ContractInfo['INFO']['remark'] // --remark
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
//$this->commit();
@logHandler(PEAR_LOG_INFO, "Insert into group_contract_info end", $PHP_SELF, __FILE__, __LINE__ ) ;
}
//insert group_contract_info_his
public function insertGroupHistory()
{
if(false == $this->c_db->SQLExecute('INS_GROUP_CONTRACT_INFO_HIS',
$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['market_code'] // --market_code
,$this->ContractInfo['INFO']['cid'] // --cid
,$this->ContractInfo['INFO']['seq'] // --seq
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
//insert customer_document_his
public function insertDocumentHistory()
{
if(false == $this->c_db->SQLExecute('INS_GROUP_CONTRACT_INFO_HIS',
$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['market_code'] // --market_code
,$this->ContractInfo['INFO']['cid'] // --cid
,$this->ContractInfo['INFO']['seq'] // --seq
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
}
//비고항목및 동의항목 수정
public function editContract()
{
//기존 이력 저장
$this->insertGroupHistory();
if(false == $this->c_db->SQLExecute('UPD_GROUP_CONTRACT_INFO_DATA',
$this->ContractInfo['INFO']['agent_id'] // --sys_operator_id
,$this->ContractInfo['INFO']['contract_type']
,$this->ContractInfo['INFO']['reg_agent_id']
,$this->ContractInfo['INFO']['remark']
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
if ($this->ContractInfo['INFO']['contract_kind'] == "P")
{
$sys_memo_text = "작업내역:[개인 계약서 정보 수정]";
$usr_memo_text = "1.변경사항:[비고 - ".$this->ContractInfo['INFO']['remark']."],3.작업그룹:[".$this->ContractInfo['INFO']['work_group']."] 3.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
}
else
{
$sys_memo_text = "작업내역:[단체 계약서 정보 수정]";
$usr_memo_text = "1.변경사항:[비고 - ".$this->ContractInfo['INFO']['remark']."],2.SEQ_NO:[".$this->ContractInfo['INFO']['seq']."] 3.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
}
$this->insertCCM_MEMO($sys_memo_text, $usr_memo_text);
$this->commit();
}
// Hangang_auto_start : insertPaymentMethodHistory (autopay - upload)
//insert payment_method_history
public function insertPaymentMethodHistory()
{
@logHandler(PEAR_LOG_INFO, "Insert into payment_method_history start", $PHP_SELF, __FILE__, __LINE__ ) ;
$agree_name = $this->ContractInfo['INFO']['folder_name']."/".$this->ContractInfo['INFO']['file_name'];
if(false == $this->c_db->SQLExecute('UPD_PAYMENT_METHOD_HISTORY',
$agree_name // agree_name
,'SCAN' // agree_type
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['work_group']
)))
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
//$this->commit();
@logHandler(PEAR_LOG_INFO, "Insert into payment_method_history end", $PHP_SELF, __FILE__, __LINE__ ) ;
}
// Hangang_auto_end
//단체계약서 저장이력 삭제
public function deleteContract($file_name)
{
$this->_deleteImageServerPDF($file_name);
//이력삭제
if(false == $this->c_db->SQLExecute('DELETE_GROUP_CONTRACT_INFO_HIS',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
)))
{
throw new Exception(ERROR_CODE_DB_FAILURE);
}
//정보삭제
if(false == $this->c_db->SQLExecute('DELETE_GROUP_CONTRACT_INFO',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['seq']
)))
{
throw new Exception(ERROR_CODE_DB_FAILURE);
}
$sys_memo_text = "작업냐역:[단체 계약서 삭제처리]";
$usr_memo_text = "1.삭제파일명:[".$file_name."],2.작업자:[".$this->ContractInfo['INFO']['agent_name']."]";
$this->insertCCM_MEMO($sys_memo_text, $usr_memo_text);
$this->commit();
}
public function insertCCM_MEMO($sys_memo_text, $usr_memo_text)
{
if(false == $this->c_db->SQLExecute('INS_CCM_MEMO',
$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid']
,$this->ContractInfo['INFO']['agent_id']
,"0038"
,$sys_memo_text
,$usr_memo_text
,$this->ContractInfo['INFO']['market_code']
,$this->ContractInfo['INFO']['cid'])) )
{
throw new Exception (ERROR_CODE_DB_FAILURE);
}
// $this->commit();
}
//PDF 저장 폴더
public function getPDFServerFolderName()
{
$yyyymmdd = substr($yyyymmdd, 0, 8);
$folder = $this->ContractInfo['INFO']['market_code'] . "/" . substr($yyyymmdd, 0, 4) . "/" . substr($yyyymmdd, -4) ;
return $folder;
}
// 서류 저장 폴더
public function getDocumentFolderName()
{
$yyyymmdd = substr($yyyymmdd, 0, 8);
$folder = $this->DocumentInfo['INFO']['market_code'] . "/" . substr($yyyymmdd, 0, 4) . "/" . substr($yyyymmdd, -4) ;
return $folder;
}
//PDF 파일명
public function getPDFServerFileName()
{
$yyyymmdd = substr($yyyymmdd, 0, 8); $file_name = $this->ContractInfo['INFO']['market_code'] ."_". $this->ContractInfo['INFO']['cid'];
$file_name = ($this->ContractInfo['INFO']['contract_kind'] =="P") ? $file_name ."_". $this->ContractInfo['INFO']['work_group'] ."_". $yyyymmdd : $file_name."_".$yyyymmdd ;
return $file_name ;
}
// 서류 파일명
public function getDocumentFileName()
{
$yyyymmdd = substr($yyyymmdd, 0, 8);
$file_name = $this->DocumentInfo['INFO']['market_code'] ."_". $this->DocumentInfo['INFO']['cid'] ."_". $yyyymmdd ;
//$file_name = ($this->DocumentInfo['INFO']['contract_kind'] =="P") ? $file_name ."_". $this->DocumentInfo['INFO']['work_group'] ."_". $yyyymmdd : $file_name."_".$yyyymmdd ;
return $file_name ;
}
//계약서 종류 가져오기
public function get_contract_type($market_code)
{
$this->c_db = DBController::getInstance();
$_list = $this->c_db->SQLQuery("GET_CONTRACT_TYPE_LIST", array($market_code));
for($i=0; $i < count($_list); $i++) {
$arr[$_list[$i]['CODE_VAL'] ] = $_list[$i]['CODE_STR'];
}
return $arr;
}
public function commit()
{
$this->c_db->commit();
}
public function rollback()
{
$this->c_db->rollback();
}
public function disconn($flag=FALSE)
{
$this->c_db->disconn($flag);
}
//파일정보 재배열 처리
public function multiple
(array $_files, $top = TRUE) {
foreach($_files as $name=>$file){
if($top) $sub_name = $file['name'];
else $sub_name = $name;
$files[$name][$key] = array( 'name' => $file['name'][$key],
'type' => $file['type'][$key],
'tmp_name' => $file['tmp_name'][$key],
'error' => $file['error'][$key],
'size' => $file['size'][$key],
);
$files[$name] = $this->multiple($files[$name], FALSE);
}
}else{
$files[$name] = $file;
}
}
return $files;
}
public function login_chk()
{
if (!$_SESSION['fromSMS'])
{
header("Location: /group_contract/index.php"); }
}
public function prt_return
($str, $url, array $data) {
echo "<script type=\"text/javascript\">alert(\"$str\");</script>";
_user_reaction($url, $data);
}
}
PD9waHAKICAgIC8qKgogICAgICogIEhhbmdhbmcgU3lzdGVtIGluYy4KICAgICAqCiAgICAgKiAgQ3VzdG9tZXIgRG9jIENsYXNzCiAgICAgKiAg6rOg6rCdIOymneu5mSDshJzrpZggdXBsb2FkIO2BtOuemOyKpCDsoJXrs7QKICAgICAqICAyMDE5LjExLjA0CiAgICAgKgogICAgICovCiAgICBjbGFzcyBDdXN0b21lcl9Eb2MKICAgIHsKICAgICAgICBwdWJsaWMgc3RhdGljICRpbnN0YW5jZSAgIDsKCiAgICAgICAgcHJpdmF0ZSAkY19kYiAgICAgICAgICAgICA9IE5VTEwgIDsKICAgICAgICBwcml2YXRlICRyZXN1bHRzICAgICAgICAgID0gTlVMTCAgOwogICAgICAgIHByaXZhdGUgJGFnZW50X2lkICAgICAgICAgPSBOVUxMICA7CiAgICAgICAgcHJpdmF0ZSAkY29udHJhY3Rfa2luZCAgICA9IE5VTEwgOwogICAgICAgIHByaXZhdGUgJGN1cnJlbnRfcGFzc3dvcmQgPSBOVUxMIDsKICAgICAgICBwcml2YXRlICR3b3JrX2tpbmQgICAgICAgID0gTlVMTDsKCiAgICAgICAgcHJpdmF0ZSAkQ29udHJhY3RJbmZvID0gTlVMTDsKICAgICAgICAKICAgICAgICBwcml2YXRlICREb2N1bWVudEluZm8gPSBOVUxMOwoKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoKQogICAgICAgIHsKICAgICAgICAgICAgJHRoaXMtPmNfZGIgPSBEQkNvbnRyb2xsZXI6OmdldEluc3RhbmNlKCkgOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRJbnN0YW5jZSgpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWlzc2V0KHNlbGY6OiRpbnN0YW5jZSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICRjID0gX19DTEFTU19fOwogICAgICAgICAgICAgICAgc2VsZjo6JGluc3RhbmNlID0gbmV3ICRjOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gc2VsZjo6JGluc3RhbmNlOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGNoZWNrX2xvZ2luKCRtYXJrZXRfY29kZSwgJGFnZW50X2lkKQogICAgICAgIHsKICAgICAgICAgICAgJHJlc3VsdHMgPSAkdGhpcy0+Y19kYi0+U1FMR2V0Um93KCJHRVRfR1JPVVBfTE9HSU5fVVNFUiIsIGFycmF5KCRtYXJrZXRfY29kZSwgJGFnZW50X2lkKSk7CgogICAgICAgICAgICBpZiggJHJlc3VsdHMgPT0gZmFsc2UgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAkdGhpcy0+bWFrZVNlc3Npb24oJHJlc3VsdHMpOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkdGhpcy0+Y19kYi0+ZGlzY29ubigpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZSA7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0UmVzdWx0KCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAkdGhpcy0+cmVzdWx0czsKICAgICAgICB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIG1ha2VTZXNzaW9uKCRyZXN1bHRzKQogICAgICAgIHsKICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIk1ha2UgU2Vzc2lvbiA6ICIuIHByaW50X3IoJHJlc3VsdHMsIHRydWUpLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKCiAgICAgICAgICAgICR0aGlzLT5yZXN1bHRzID0gJHJlc3VsdHM7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0Q29udHJhY3RJbmZvKCRjb25faW5mbykKICAgICAgICB7Ci8vIEhhbmdhbmdfYXV0b19zdGFydCAoYXV0b3BheSAtIHVwbG9hZCkKICAgICAgICAgICAgLyog7J6R7JeFIOygleuztCAqLwogICAgICAgICAgICBpZiAoJGNvbl9pbmZvWydjb250cmFjdF9raW5kJ10gPT0iUCIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmICgkY29uX2luZm9bJ2FjdGl2aXR5X2NvZGUnXSA9PSAiQzg0Iil7CiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mbyA9ICR0aGlzLT5jX2RiLT5TUUxHZXRSb3coJ0dFVF9SRUNfUEFZTUVOVF9NRVRIT0RfSElTVE9SWScsIGFycmF5KCRjb25faW5mb1snbWFya2V0X2NvZGUnXSwgJGNvbl9pbmZvWyd3b3JrX2dyb3VwJ10pKSA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlewogICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm8gPSAkdGhpcy0+Y19kYi0+U1FMR2V0Um93KCdHRVRfUkVDX0NDTV9XT1JLX0dST1VQJywgYXJyYXkoJGNvbl9pbmZvWydtYXJrZXRfY29kZSddLCAkY29uX2luZm9bJ3dvcmtfZ3JvdXAnXSwgQ0NNX1dPUktfU1RBVFVTX0NPTVBMRVRFICkpIDsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZighIGlzX2FycmF5KCR0aGlzLT5Db250cmFjdEluZm8pKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfTk9fV09SS19HUk9VUCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCi8vIEhhbmdhbmdfYXV0b19lbmQKCiAgICAgICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICRjdXN0b21lckluZm8gPSAkdGhpcy0+Y19kYi0+U1FMR2V0Um93KCdHRVRfQ1VTVE9NRVJfUEFTU1dPUkRfSU5GTycsIGFycmF5KCRjb25faW5mb1snbWFya2V0X2NvZGUnXSwgJGNvbl9pbmZvWydjaWQnXSApKSA7CgogICAgICAgICAgICAgICAgaWYoISBpc19hcnJheSgkY3VzdG9tZXJJbmZvKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19FUlIsICJHRVRfQ1VTVE9NRVJfUEFTU1dPUkRfSU5GTyBGQUlMVVJFIiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9OT19XT1JLX0dST1VQKTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiggc3RybGVuKCRjdXN0b21lckluZm9bJ0JJUlRIREFZJ10pID09IDYpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snQ1VTVFlZTU1ERCddID0gJGN1c3RvbWVySW5mb1snQklSVEhEQVknXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2VpZiggc3RybGVuKCRjdXN0b21lckluZm9bJ0JJUlRIREFZJ10pID09IDEwICkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydDVVNUWVlNTUREJ10gPSBzdWJzdHIoJGN1c3RvbWVySW5mb1snQklSVEhEQVknXSwwLDYpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0NVU1RZWU1NREQnXSA9IHN1YnN0cigkY3VzdG9tZXJJbmZvWydSRVBfSUQnXSwwLDYpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCgogICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ10gPSAkY29uX2luZm87CgogICAgICAgICAgICAvL+2PtOuNlOuqheqzvCDtjIzsnbzrqoUg7IS47YyF7LKY66asCiAgICAgICAgICAgIGlmICghJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydzZXEnXSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgJGZvbGRlcl9uYW1lICAgPSAkdGhpcy0+Z2V0UERGU2VydmVyRm9sZGVyTmFtZSgpOwogICAgICAgICAgICAgICAgJGZpbGVfbmFtZSAgICAgPSAkdGhpcy0+Z2V0UERGU2VydmVyRmlsZU5hbWUoKTsKCiAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddID0gJHRoaXMtPmNfZGItPlNRTEdldE9uZSgnR0VUX0dST1VQX0NPTlRSQUNUX0lORk9fU0VRJyxhcnJheSgkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10sICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10pKTsKCiAgICAgICAgICAgICAgICAkZmlsZV9uYW1lICAgIC49ICJfIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddLiIucGRmIjsKICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXSA9JGZvbGRlcl9uYW1lOwogICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmaWxlX25hbWUnXSAgID0kZmlsZV9uYW1lOwogICAgICAgICAgICB9CgogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCBwcmludF9yKCR0aGlzLT5Db250cmFjdEluZm8sIHRydWUpLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRDb250cmFjdEluZm8oKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuICR0aGlzLT5Db250cmFjdEluZm87CiAgICAgICAgfQogICAgICAgICAgICAgICAKICAgICAgICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCQkJCS8vIGluc2VydCBEb2N1bWVudCAtLSDsnbQg67aA67aEIOuLpOyLnCDsiJjsoJXtlbTslbwg7ZWc64ukLiAgICAgIAogCQkJCXB1YmxpYyBmdW5jdGlvbiBpbnNlcnREb2N1bWVudEluZm8oJGRvY19pbmZvKSB7CiAJCQkJCSAgJHNlcV9jbnQgPSAkdGhpcy0+Y19kYi0+U1FMR2V0T25lKCdHRVRfQ1VTVE9NRVJfRE9DVU1FTlRfU0VRJywgYXJyYXkoJGRvY19pbmZvWydtYXJrZXRfY29kZSddLCAkZG9jX2luZm9bJ2NpZCddLCAkZG9jX2luZm9bJ3JlZ19kYXRlJ10gKSk7CgkJCQkJCQkJCgkJCQkJCWlmKCRzZXFfY250ID0gMikgewoJCQkJCQkJICBpZiggZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ1VQRF9DVVNUT01FUl9ET0NVTUVOVCcsIGFycmF5KCRkb2NfaW5mb1snbWFya2V0X2NvZGUnXSwgJGRvY19pbmZvWydjaWQnXSwgJGRvY19pbmZvWydyZWdfZGF0ZSddLCAkc2VxX2NudCAtIDEpKSApCgkgCQkJCQkgCQkJCXRocm93IG5ldyBFeGNlcHRpb24oRVJST1JfQ09ERV9EQl9GQUlMVVJFKTsKCQkJCQkgIH0gZWxzZSBpZigkc2VxX2NudCA+IDIpIHsKCSAJCQkJCSAJCWlmKCBmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnSU5TX0NVU1RPTUVSX0RPQ1VNRU5UJywgYXJyYXkoJGRvY19pbmZvWydtYXJrZXRfY29kZSddLCAkZG9jX2luZm9bJ2NpZCddLCAkZG9jX2luZm9bJ3JlZ19kYXRlJ10sICRzZXFfY250KSkgKQoJIAkJCQkJIAkJCQl0aHJvdyBuZXcgRXhjZXB0aW9uKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAJCQkJCQl9CiAJCQkJfSAgICAgIAogICAgICAgCiAgICAgICAgLy8gc2V0IERvY3VtZW50CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldERvY3VtZW50SW5mbygkZG9jX2luZm8sICRleHQpIHsKICAgICAgICAgIAovLyBIYW5nYW5nX2F1dG9fZW5kCgogICAgICAgICAgICAvLyAyMDE4LjEwLjE3ID09PiBmb3IgZW5jcnlwdGlvbiBwYXNzd29yZAogICAgICAgICAgICAvKgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAkY3VzdG9tZXJJbmZvID0gJHRoaXMtPmNfZGItPlNRTEdldFJvdygnR0VUX0NVU1RPTUVSX1BBU1NXT1JEX0lORk8nLCBhcnJheSgkY29uX2luZm9bJ21hcmtldF9jb2RlJ10sICRjb25faW5mb1snY2lkJ10gKSkgOwoKICAgICAgICAgICAgICAgIGlmKCEgaXNfYXJyYXkoJGN1c3RvbWVySW5mbykpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfRVJSLCAiR0VUX0NVU1RPTUVSX1BBU1NXT1JEX0lORk8gRkFJTFVSRSIsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfTk9fV09SS19HUk9VUCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgaWYoIHN0cmxlbigkY3VzdG9tZXJJbmZvWydCSVJUSERBWSddKSA9PSA2KQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICR0aGlzLT5Eb2N1bWVudEluZm9bJ0NVU1RZWU1NREQnXSA9ICRjdXN0b21lckluZm9bJ0JJUlRIREFZJ107CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlaWYoIHN0cmxlbigkY3VzdG9tZXJJbmZvWydCSVJUSERBWSddKSA9PSAxMCApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkRvY3VtZW50SW5mb1snQ1VTVFlZTU1ERCddID0gc3Vic3RyKCRjdXN0b21lckluZm9bJ0JJUlRIREFZJ10sMCw2KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAkdGhpcy0+RG9jdW1lbnRJbmZvWydDVVNUWVlNTUREJ10gPSBzdWJzdHIoJGN1c3RvbWVySW5mb1snUkVQX0lEJ10sMCw2KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAqLyAgICAgICAgIAkgICAgICAgIAogICAgICAgICAgICAKCQkJCQkJJHNlcV9jbnQgPSAkdGhpcy0+Y19kYi0+U1FMR2V0T25lKCdHRVRfQ1VTVE9NRVJfRE9DVU1FTlRfU0VRJywgYXJyYXkoJGRvY19pbmZvWydtYXJrZXRfY29kZSddLCAkZG9jX2luZm9bJ2NpZCddLCAkZG9jX2luZm9bJ3JlZ19kYXRlJ10gKSk7CiAgCQkJCQkkc2VxX2NudCA9ICRzZXFfY250IC0gMTsKICAgICAgICAgICAgCiAgICAgICAgICAgICR0aGlzLT5Eb2N1bWVudEluZm8gPSAkdGhpcy0+Y19kYi0+U1FMR2V0Um93KCdHRVRfQ1VTVE9NRVJfRE9DVU1FTlRfSU5GTycsIGFycmF5KCRkb2NfaW5mb1snbWFya2V0X2NvZGUnXSwgJGRvY19pbmZvWydjaWQnXSwgJGRvY19pbmZvWydyZWdfZGF0ZSddLCAkc2VxX2NudCkpOwogICAgICAgICAgICAKICAgICAgICAgICAgaWYoISBpc19hcnJheSgkdGhpcy0+RG9jdW1lbnRJbmZvKSkgewogICAgICAgICAgICAJdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9OT19XT1JLX0dST1VQKTsJICAgCiAgICAgICAgICAgIH0gCiAgICAgICAgICAgIAogICAgICAgICAgCiAgICAgICAgICAgICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXSA9ICRkb2NfaW5mbzsKCiAgICAgICAgICAgIC8v7Y+0642U66qF6rO8IO2MjOydvOuqhSDshLjtjIXsspjrpqwKICAgICAgICAgICAgaWYgKCEkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ3NlcSddKSB7CiAgICAgICAgICAgICAgICAkZm9sZGVyX25hbWUgICA9ICR0aGlzLT5nZXREb2N1bWVudEZvbGRlck5hbWUoKTsKICAgICAgICAgICAgICAgICRmaWxlX25hbWUgICAgID0gJHRoaXMtPmdldERvY3VtZW50RmlsZU5hbWUoKTsKCiAgICAgICAgICAgICAgICAkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ3NlcSddID0gJHNlcV9jbnQ7CgkJCQkJCQkJCiAgICAgICAgICAgICAgICAkZmlsZV9uYW1lICAgICAuPSAiXyIgLiAkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ3NlcSddIC4gIi4iIC4gJGV4dDsKICAgICAgICAgICAgICAgICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXSA9ICRmb2xkZXJfbmFtZTsKICAgICAgICAgICAgICAgICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXVsnZmlsZV9uYW1lJ10gICA9ICRmaWxlX25hbWU7CiAgICAgICAgICAgIH0gCgogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCBwcmludF9yKCR0aGlzLT5Eb2N1bWVudEluZm8sIHRydWUpLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgCiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0RG9jdW1lbnRJbmZvKCkgewogICAgICAgICAgICAJcmV0dXJuICR0aGlzLT5Eb2N1bWVudEluZm87CiAgICAgICAgfQoKICAgICAgICAvL2Z0cCDshJzrsoQg7KCR7IaNCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIF9jb25uZWN0X2Z0cFNlcnZlcigpCiAgICAgICAgewogICAgICAgICAgICAkbXNnID0gIiI7CgogICAgICAgICAgICAkY19pbWdTZXJ2ZXIgICA9IEltYWdlU2VydmVyOjpnZXRJbnN0YW5jZSgpIDsKICAgICAgICAgICAgJGltZ1NlcnZlckluZm8gPSAkY19pbWdTZXJ2ZXItPmdldEltYWdlU2VydmVySW5mbygpOwoKICAgICAgICAgICAgaWYoJGltZ1NlcnZlckluZm9bJ1NFUlZFUl9JUCddID09ICIiIHx8ICRpbWdTZXJ2ZXJJbmZvWydTRVJWRVJfUE9SVCddID09ICIiIHx8ICRpbWdTZXJ2ZXJJbmZvWydVU0VSX0lEJ10gPT0gIiIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIk5vIEltYWdlU2VydmVyIEZUUCBTZXJ2ZXIgQ29ubmVjdGlvbiBJbmZvIiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19FUlIsIHByaW50X3IoJGltZ1NlcnZlckluZm8sIHRydWUpLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfTk9fSU5GX0lORk8pOwogICAgICAgICAgICB9CgkJCQkJCQogICAgICAgICAgICAkdGhpcy0+ZnRwX2Nvbm4gPSBAZnRwX2Nvbm5lY3QgKCRpbWdTZXJ2ZXJJbmZvWydTRVJWRVJfSVAnXSwgJGltZ1NlcnZlckluZm9bJ1NFUlZFUl9QT1JUJ10gKTsgICAgCiAgICAgICAgICAgIAogICAgICAgICAgICBpZihmYWxzZSA9PSAkdGhpcy0+ZnRwX2Nvbm4pCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIkZUUCBTZXJ2ZXIgQ29ubmVjdGlvbiBGYWlsdXJlIFt7JGltZ1NlcnZlckluZm9bJ1NFUlZFUl9JUCddfVt7JGltZ1NlcnZlckluZm9bJ1NFUlZFUl9QT1JUJ119XSIsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAgICAgLy8gdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9FUlJfSU5GX1NFUlZFUik7CiAgICAgICAgICAgIH0KCQkJCQkJCiAgICAgICAgICAgIGlmKGZhbHNlID09IEBmdHBfbG9naW4oJHRoaXMtPmZ0cF9jb25uLCAkaW1nU2VydmVySW5mb1snVVNFUl9JRCddLCAkaW1nU2VydmVySW5mb1snVVNFUl9QVyddKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfRVJSLCAiRlRQIFNlcnZlciBMb2dpbiBGYWlsdXJlIFt7JGltZ1NlcnZlckluZm9bJ1VTRVJfSUQnXX1beyRpbWdTZXJ2ZXJJbmZvWydVU0VSX1BXJ119XSIsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAgICAgZnRwX2Nsb3NlKCR0aGlzLT5mdHBfY29ubik7CiAgICAgICAgICAgICAgICAvL3Rocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfRVJSX0lORl9TRVJWRVIpOwogICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0lORk8sICJzZXQgZnRwIHRvIHBhc3NpdmUgbW9kZS4iLkZUUF9NT0RFLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwogICAgICAgICAgICAgICAgZnRwX3Bhc3YoJHRoaXMtPmZ0cF9jb25uLCBGVFBfTU9ERT09IlBBU1NJVkUiICk7CiAgICAgICAgICAgIH0KCQkJCQkJCiAgICAgICAgICAgIGlmKCAkaW1nU2VydmVySW5mb1snRk9MREVSJ10gKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBAZnRwX2NoZGlyKCR0aGlzLT5mdHBfY29ubiwgJGltZ1NlcnZlckluZm9bJ0ZPTERFUiddKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy/qs4Tslb3shJwgdXBsb2FkCiAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKICAgICAgICAvL3B1YmxpYyBmdW5jdGlvbiBfdXBsb2FkSW1hZ2VTZXJ2ZXJQREYoJGNvbnRyYWN0X2tpbmQsICRhdHRfZmlsZV9pbmZvID0gYXJyYXkoKSkKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gX3VwbG9hZEltYWdlU2VydmVyUERGKCRjb250cmFjdF9raW5kLCAkYXR0X2ZpbGVfaW5mbyA9IGFycmF5KCksICRlbmNfcGFzc3dvcmQpCiAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKICAgICAgICB7CiAgICAgICAgICAgICR0aGlzLT5fY29ubmVjdF9mdHBTZXJ2ZXIoKTsKCiAgICAgICAgICAgIGlmKCAhaXNfZmlsZSggJGF0dF9maWxlX2luZm9bJ3RtcF9uYW1lJ10gKSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIk5PIEZJTEUgVG8gRlRQIFB1dCBBdHRhY2ggOiAgIiAuICRhdHRfZmlsZV9pbmZvWyd0bXBfbmFtZSddLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfRVJSX0FUVF9QUk9DRVNTKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdHJ5CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCiAgICAgICAgICAgICAgICAvLyR0aGlzLT5fc2F2ZUltYWdlU2VydmVyUERGKCRhdHRfZmlsZV9pbmZvLCAkY29udHJhY3Rfa2luZCk7CiAgICAgICAgICAgICAgICAkdGhpcy0+X3NhdmVJbWFnZVNlcnZlclBERigkYXR0X2ZpbGVfaW5mbywgJGNvbnRyYWN0X2tpbmQsICRlbmNfcGFzc3dvcmQpOwogICAgICAgICAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoRXhjZXB0aW9uICRlKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBmdHBfY2xvc2UoJHRoaXMtPmZ0cF9jb25uKTsKICAgICAgICAgICAgICAgIHRocm93ICRlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBmdHBfY2xvc2UoJHRoaXMtPmZ0cF9jb25uKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy8g6rOg6rCdIOymneu5mSDshJzrpZgg7JeF66Gc65OcCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIF91cGxvYWREb2N1bWVudFNlcnZlcigkYXR0X2ZpbGVfaW5mbyA9IGFycmF5KCkpIHsKICAgICAgICAJCiAgICAgICAgICAkdGhpcy0+X2Nvbm5lY3RfZnRwU2VydmVyKCk7CiAgICAgICAgCQogICAgICAgIAlpZiggIWlzX2ZpbGUoICRhdHRfZmlsZV9pbmZvWyd0bXBfbmFtZSddICkgKQogICAgICAgICAgewogICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIk5PIEZJTEUgVG8gRlRQIFB1dCBBdHRhY2ggOiAgIiAuICRhdHRfZmlsZV9pbmZvWyd0bXBfbmFtZSddLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0VSUl9BVFRfUFJPQ0VTUyk7CiAgICAgICAgICB9CiAgICAgICAgICAKICAgICAgICAJdHJ5CiAgICAgICAgICB7CiAgICAgICAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKICAgICAgICAgICAgICAvLyR0aGlzLT5fc2F2ZUltYWdlU2VydmVyUERGKCRhdHRfZmlsZV9pbmZvLCAkY29udHJhY3Rfa2luZCk7ICAKICAgICAgICAgICAgICAvLyR0aGlzLT5fc2F2ZUltYWdlU2VydmVyUERGKCRhdHRfZmlsZV9pbmZvLCAkY29udHJhY3Rfa2luZCwgJGVuY19wYXNzd29yZCk7CiAgICAgICAgICAgICAgJHRoaXMtPl9zYXZlRG9jdW1lbnRTZXJ2ZXIoJGF0dF9maWxlX2luZm8pOwoKICAgICAgICAgIH0KICAgICAgICAgIGNhdGNoIChFeGNlcHRpb24gJGUpCiAgICAgICAgICB7CiAgICAgICAgICAgICAgZnRwX2Nsb3NlKCR0aGlzLT5mdHBfY29ubik7CiAgICAgICAgICAgICAgdGhyb3cgJGU7CiAgICAgICAgICB9CgkJCQogICAgICAgICAgZnRwX2Nsb3NlKCR0aGlzLT5mdHBfY29ubik7CiAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIF9zYXZlRG9jdW1lbnRTZXJ2ZXIoJGF0dF9maWxlX2luZm8pIHsKICAgICAgICAJaWYoICFpc19maWxlKCAkYXR0X2ZpbGVfaW5mb1sndG1wX25hbWUnXSApICkKICAgICAgICAgIHsKICAgICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19FUlIsICJOTyBGSUxFIFRvIEZUUCBQdXQgQXR0YWNoIDogICIgLiAkYXR0X2ZpbGVfaW5mb1sndG1wX25hbWUnXSwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9FUlJfQVRUX1BST0NFU1MpOwogICAgICAgICAgfQoKICAgICAgICAgICRmb2xkZXIgICA9ICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXTsKICAgICAgICAgICRmaWxlICAgICA9ICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXVsnZmlsZV9uYW1lJ107CgogICAgICAgICAgJHBhcnRzID0gZXhwbG9kZSgnLycsJGZvbGRlcik7IC8vIFNPSUQvWVlZWS9NTURECiAgICAgICAgICBmb3JlYWNoKCRwYXJ0cyBhcyAkcGFydCkKICAgICAgICAgIHsKICAgICAgICAgICAgICBAZnRwX3B3ZCgkdGhpcy0+ZnRwX2Nvbm4pOwogICAgICAgICAgICAgIGlmKCFAZnRwX2NoZGlyKCR0aGlzLT5mdHBfY29ubiwgJHBhcnQpKQogICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgQGZ0cF9wd2QoJHRoaXMtPmZ0cF9jb25uKTsKICAgICAgICAgICAgICAgICAgQGZ0cF9ta2RpcigkdGhpcy0+ZnRwX2Nvbm4sICRwYXJ0KTsKICAgICAgICAgICAgICAgICAgQGZ0cF9jaGRpcigkdGhpcy0+ZnRwX2Nvbm4sICRwYXJ0KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgLy8gJHRtcGZpbGUgPSBUTVBfRElSIC4gIi8iIC4gdW5pcWlkKCk7ICAgICAKIAkJCQkJJHRtcGZpbGUgPSBUTVBfRElSIC4gIi8iIC4gJGZpbGU7ICAgICAKICAgICAgICAgIG1vdmVfdXBsb2FkZWRfZmlsZSgkYXR0X2ZpbGVfaW5mb1sndG1wX25hbWUnXSwgJHRtcGZpbGUpOwoKCiAgICAgICAgICAvKiBEUk0g7ZW07KeAIOyymOumrCA6IDIwMTguMDguMjggKi8gICAgICAgICAKICAgICAgICAgIGlmKGlzRFJNRW5jcnlwdGVkRmlsZSgkdG1wZmlsZSkpCiAgICAgICAgICB7CiAgICAgICAgICAgICAgJGVuY2ZpbGUgPSBUTVBfRElSIC4gIi9lbmNfIiAuICRmaWxlOwogICAgICAgICAgICAgIGlmKGRvRFJNRXh0cmFjdCgkdG1wZmlsZSwgJGVuY2ZpbGUpKQogICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgJHRtcGZpbGUgPSAkZW5jZmlsZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9CgovKgogICAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKICAgICAgICAgICRleGVjX2NvbW1hbmQgPSBQREZTRUNVUkVfUFJPR1JBTSAuICIgLS1lbmNyeXB0ICd7JGVuY19wYXNzd29yZH0nICcnIDEyOCAtLXVzZS1hZXM9eSAtLSAiIC4gJHRtcGZpbGUgLiAiICIgLiAkdG1wZmlsZSAuICJfX2VuY19wYXNzIjsKICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0lORk8sICRleGVjX2NvbW1hbmQgLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgIGV4ZWMoICRleGVjX2NvbW1hbmQgKTsKCiAgICAgICAgICBpZiggIWlzX2ZpbGUoICR0bXBmaWxlIC4gIl9fZW5jX3Bhc3MiICkgKQogICAgICAgICAgewogICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIk5PIEZJTEUgRm91bmQgKFNlY3VyZWQgQXBwbGllZCkgOiAgIiAuICR0bXBmaWxlIC4gIl9fZW5jX3Bhc3MiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0VSUl9QREZfUFJPQ0VTUyk7CiAgICAgICAgICB9CiAgICAgICAgICAkdG1wZmlsZSA9ICR0bXBmaWxlIC4gIl9fZW5jX3Bhc3MiOwogICAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKKi8KCiAgICAgICAgICBpZighQGZ0cF9wdXQoJHRoaXMtPmZ0cF9jb25uLCAkZmlsZSwgJHRtcGZpbGUsIEZUUF9CSU5BUlkpKQogICAgICAgICAgewogICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIkZUUCB1cGxvYWQgRmFpbHVyZSA6ICAiIC4gJHRtcGZpbGUgLiAiID09PT4gJGZpbGUgIiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgLy8gdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9FUlJfQVRUX1BST0NFU1MpOwogICAgICAgICAgfQoKCi8vIEhhbmdhbmdfYXV0b19zdGFydCAoYXV0b3BheSAtIHVwbG9hZCkKICAgICAgICAgIC8v6rCc7J24IOqzhOyVveyEnCDsnbwg6rK97JqwIGNpZF9pbnN0YWxsX2JhcmNvZGUg7JeQIOyggOyepe2VnOuLpC4KICAgICAgICAgLyoKICAgICAgICAgIGlmICgoJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF9raW5kJ109PSJQIikgJiYgKCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWN0aXZpdHlfY29kZSddIT0iQzg0IikpCi8vICAgICAgICAgICAgaWYgKCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY29udHJhY3Rfa2luZCddPT0iUCIpCiAgICAgICAgICB7CiAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGNpZF9pbnN0YWxsX2JhcmNvZGUiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwogICAgICAgICAgICAgICAkdGhpcy0+aW5zZXJ0QmFyY29kZSgpOwogICAgICAgICAgfQogICAgICAgICAgKi8KICAgICAgIAovLyBIYW5nYW5nX2F1dG9fZW5kCgoKICAgICAgICAgIC8v7Iug6rec7YWM7J2067iU7JeQIOqzhOyVveyEnCB1cGxvYWQg7KCV67O066W8IOyggOyepe2VnOuLpC4KICAgICAgICAgIC8vQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGN1c3RvbWVyX2RvY3VtZW50IiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKTsKLyogICAgICAgICAgCiAgICAgICAgICAkdGhpcy0+aW5zZXJ0R3JvdXBDb250cmFjdCgpOwoKICAgICAgICAgIC8vaW5zZXJ0IGNjbV9tZW1vCiAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gY2NtX21lbW8iLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwoKICAgICAgICAgICRzeXNfbWVtb190ZXh0ID0gJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF9raW5kJ10gPT0iUCI/ICLsnpHsl4XrgrTsl606W+qwnOyduCDqs4Tslb3shJwg7JeF66Gc65OcXSI6IuyekeyXheyDge2DnDpb64uo7LK0IOqzhOyVveyEnCDsl4XroZzrk5xdIjsKICAgICAgICAgICR1c3JfbWVtb190ZXh0ID0gIjEu7YyM7J2866qFOiBbIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2ZpbGVfbmFtZSddLiJdLCAyLuyekeyXheyekDpbIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X25hbWUnXS4iXSI7CiAgICAgICAgICAkdGhpcy0+aW5zZXJ0Q0NNX01FTU8oJHN5c19tZW1vX3RleHQsICR1c3JfbWVtb190ZXh0KTsKCi8vIEhhbmdhbmdfYXV0b19zdGFydCA6IGluc2VydFBheW1lbnRNZXRob2RIaXN0b3J5IChhdXRvcGF5IC0gdXBsb2FkKQogICAgICAgICAgLy9pbnNlcnQgcGF5bWVudF9tZXRob2RfaGlzdG9yeQogICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIHBheW1lbnRfbWV0aG9kX2hpc3RvcnkiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwogICAgICAgICAgJHRoaXMtPmluc2VydFBheW1lbnRNZXRob2RIaXN0b3J5KCk7Ci8vIEhhbmdhbmdfYXV0b19lbmQKCiAgICAgICAgICAkdGhpcy0+Y29tbWl0KCk7CiAgICAgICAgICAKICAgICAgICAgICovCiAgICAgICAgICAKICAgICAgICAgIC8vIO2MjOydvCDqsr3roZwg7JeF642w7J207Yq4IC0gY2hlY2sgc3RhdHVzID0gWSDroZwg67CU6r647Ja07JW8IO2VqCAuIAogICAgICAgICAgLy8gJHRoaXMtPnVwZGF0ZURvY3VtZW50RmlsZSgpOwogICAgICAgICAgCiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8qCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHVwZGF0ZURvY3VtZW50RmlsZSgpIHsKICAgICAgICAJCWlmKCBmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnVVBEX0NVU1RPTUVSX0RPQ1VNRU5UJywgYXJyYXkoJGRvY19pbmZvWydtYXJrZXRfY29kZSddLCAkZG9jX2luZm9bJ2NpZCddLCAkZG9jX2luZm9bJ3JlZ19kYXRlJ10sICRzZXFfY250KSkgKQoJIAkJCQkJIAkJCQl0aHJvdyBuZXcgRXhjZXB0aW9uKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CgkJCQkJICAKICAgICAgICB9CiAgICAgICAgKi8KCiAgICAgICAgLy/qs4Tslb3shJwg7ISc67KEIOyggOyepQogICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCiAgICAgICAgLy9wdWJsaWMgZnVuY3Rpb24gX3NhdmVJbWFnZVNlcnZlclBERigkYXR0X2ZpbGVfaW5mbywgJGNvbnRyYWN0X2tpbmQpCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIF9zYXZlSW1hZ2VTZXJ2ZXJQREYoJGF0dF9maWxlX2luZm8sICRjb250cmFjdF9raW5kLCAkZW5jX3Bhc3N3b3JkKQogICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCiAgICAgICAgewogICAgICAgICAgICBpZiggIWlzX2ZpbGUoICRhdHRfZmlsZV9pbmZvWyd0bXBfbmFtZSddICkgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19FUlIsICJOTyBGSUxFIFRvIEZUUCBQdXQgQXR0YWNoIDogICIgLiAkYXR0X2ZpbGVfaW5mb1sndG1wX25hbWUnXSwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0VSUl9BVFRfUFJPQ0VTUyk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRmb2xkZXIgICA9ICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXTsKICAgICAgICAgICAgJGZpbGUgICAgID0gJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmaWxlX25hbWUnXTsKCiAgICAgICAgICAgICRwYXJ0cyA9IGV4cGxvZGUoJy8nLCRmb2xkZXIpOyAvLyBTT0lEL1lZWVkvTU1ERAogICAgICAgICAgICBmb3JlYWNoKCRwYXJ0cyBhcyAkcGFydCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgQGZ0cF9wd2QoJHRoaXMtPmZ0cF9jb25uKTsKICAgICAgICAgICAgICAgIGlmKCFAZnRwX2NoZGlyKCR0aGlzLT5mdHBfY29ubiwgJHBhcnQpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIEBmdHBfcHdkKCR0aGlzLT5mdHBfY29ubik7CiAgICAgICAgICAgICAgICAgICAgQGZ0cF9ta2RpcigkdGhpcy0+ZnRwX2Nvbm4sICRwYXJ0KTsKICAgICAgICAgICAgICAgICAgICBAZnRwX2NoZGlyKCR0aGlzLT5mdHBfY29ubiwgJHBhcnQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICAkdG1wZmlsZSA9IFRNUF9ESVIgLiAiLyIgLiB1bmlxaWQoKTsKICAgICAgICAgICAgbW92ZV91cGxvYWRlZF9maWxlKCRhdHRfZmlsZV9pbmZvWyd0bXBfbmFtZSddLCAkdG1wZmlsZSk7CgogICAgICAgICAgICAvKiBEUk0g7ZW07KeAIOyymOumrCA6IDIwMTguMDguMjggKi8KICAgICAgICAgICAgaWYoaXNEUk1FbmNyeXB0ZWRGaWxlKCR0bXBmaWxlKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgJGVuY2ZpbGUgPSBUTVBfRElSIC4gIi9lbmNfIiAuIHVuaXFpZCgpOwogICAgICAgICAgICAgICAgaWYoZG9EUk1FeHRyYWN0KCR0bXBmaWxlLCAkZW5jZmlsZSkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgJHRtcGZpbGUgPSAkZW5jZmlsZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKCiAgICAgICAgICAgIC8vIDIwMTguMTAuMTcgPT0+IGZvciBlbmNyeXB0aW9uIHBhc3N3b3JkCiAgICAgICAgICAgICRleGVjX2NvbW1hbmQgPSBQREZTRUNVUkVfUFJPR1JBTSAuICIgLS1lbmNyeXB0ICd7JGVuY19wYXNzd29yZH0nICcnIDEyOCAtLXVzZS1hZXM9eSAtLSAiIC4gJHRtcGZpbGUgLiAiICIgLiAkdG1wZmlsZSAuICJfX2VuY19wYXNzIjsKICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgJGV4ZWNfY29tbWFuZCAsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICBleGVjKCAkZXhlY19jb21tYW5kICk7CgogICAgICAgICAgICBpZiggIWlzX2ZpbGUoICR0bXBmaWxlIC4gIl9fZW5jX3Bhc3MiICkgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19FUlIsICJOTyBGSUxFIEZvdW5kIChTZWN1cmVkIEFwcGxpZWQpIDogICIgLiAkdG1wZmlsZSAuICJfX2VuY19wYXNzIiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0VSUl9QREZfUFJPQ0VTUyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgJHRtcGZpbGUgPSAkdG1wZmlsZSAuICJfX2VuY19wYXNzIjsKICAgICAgICAgICAgLy8gMjAxOC4xMC4xNyA9PT4gZm9yIGVuY3J5cHRpb24gcGFzc3dvcmQKCgoKICAgICAgICAgICAgaWYoIUBmdHBfcHV0KCR0aGlzLT5mdHBfY29ubiwgJGZpbGUsICR0bXBmaWxlLCBGVFBfQklOQVJZKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfRVJSLCAiRlRQIHVwbG9hZCBGYWlsdXJlIDogICIgLiAkdG1wZmlsZSAuICIgPT09PiAkZmlsZSAiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfRVJSX0FUVF9QUk9DRVNTKTsKICAgICAgICAgICAgfQovLyBIYW5nYW5nX2F1dG9fc3RhcnQgKGF1dG9wYXkgLSB1cGxvYWQpCiAgICAgICAgICAgIC8v6rCc7J24IOqzhOyVveyEnCDsnbwg6rK97JqwIGNpZF9pbnN0YWxsX2JhcmNvZGUg7JeQIOyggOyepe2VnOuLpC4KICAgICAgICAgICAgaWYgKCgkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X2tpbmQnXT09IlAiKSAmJiAoJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhY3Rpdml0eV9jb2RlJ10hPSJDODQiKSkKLy8gICAgICAgICAgICBpZiAoJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF9raW5kJ109PSJQIikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGNpZF9pbnN0YWxsX2JhcmNvZGUiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwogICAgICAgICAgICAgICAgICR0aGlzLT5pbnNlcnRCYXJjb2RlKCk7CiAgICAgICAgICAgIH0KLy8gSGFuZ2FuZ19hdXRvX2VuZAoKICAgICAgICAgICAgLy/si6Dqt5zthYzsnbTruJTsl5Ag6rOE7JW97IScIHVwbG9hZCDsoJXrs7Trpbwg7KCA7J6l7ZWc64ukLgogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gZ3JvdXBfY29udHJhY3RfaW5mbyIsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICk7CiAgICAgICAgICAgICR0aGlzLT5pbnNlcnRHcm91cENvbnRyYWN0KCk7CgogICAgICAgICAgICAvL2luc2VydCBjY21fbWVtbwogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gY2NtX21lbW8iLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApOwoKICAgICAgICAgICAgJHN5c19tZW1vX3RleHQgPSAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X2tpbmQnXSA9PSJQIj8gIuyekeyXheuCtOyXrTpb6rCc7J24IOqzhOyVveyEnCDsl4XroZzrk5xdIjoi7J6R7JeF7IOB7YOcOlvri6jssrQg6rOE7JW97IScIOyXheuhnOuTnF0iOwogICAgICAgICAgICAkdXNyX21lbW9fdGV4dCA9ICIxLu2MjOydvOuqhTogWyIuJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmaWxlX25hbWUnXS4iXSwgMi7snpHsl4XsnpA6WyIuJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9uYW1lJ10uIl0iOwogICAgICAgICAgICAkdGhpcy0+aW5zZXJ0Q0NNX01FTU8oJHN5c19tZW1vX3RleHQsICR1c3JfbWVtb190ZXh0KTsKCi8vIEhhbmdhbmdfYXV0b19zdGFydCA6IGluc2VydFBheW1lbnRNZXRob2RIaXN0b3J5IChhdXRvcGF5IC0gdXBsb2FkKQogICAgICAgICAgICAvL2luc2VydCBwYXltZW50X21ldGhvZF9oaXN0b3J5CiAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0lORk8sICJJbnNlcnQgaW50byBwYXltZW50X21ldGhvZF9oaXN0b3J5IiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKTsKICAgICAgICAgICAgJHRoaXMtPmluc2VydFBheW1lbnRNZXRob2RIaXN0b3J5KCk7Ci8vIEhhbmdhbmdfYXV0b19lbmQKCiAgICAgICAgICAgICR0aGlzLT5jb21taXQoKTsKICAgICAgICB9CgogICAgICAgIC8v7YyM7J28IOuLpOyatOuhnOuTnAogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBfZG93bkltYWdlU2VydmVyUERGKCRmaWxlX25hbWUpCiAgICAgICAgewogICAgICAgICAgICAkdGhpcy0+X2Nvbm5lY3RfZnRwU2VydmVyKCk7CgogICAgICAgICAgICAkc3lzX21lbW9fdGV4dCA9ICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY29udHJhY3Rfa2luZCddID09IlAiPyAi7J6R7JeF64K07JetOlvqsJzsnbgg6rOE7JW97IScIOuLpOyatOuhnOuTnF0iOiLsnpHsl4Xsg4Htg5w6W+uLqOyytCDqs4Tslb3shJwg64uk7Jq066Gc65OcXSI7CiAgICAgICAgICAgICR1c3JfbWVtb190ZXh0ID0gIjEu7YyM7J2866qFOiBbIi4kZmlsZV9uYW1lLiJdLCAyLuyekeyXheyekDpbIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X25hbWUnXS4iXSI7CiAgICAgICAgICAgICR0aGlzLT5pbnNlcnRDQ01fTUVNTygkc3lzX21lbW9fdGV4dCwgJHVzcl9tZW1vX3RleHQpOwoKICAgICAgICAgICAgJHRoaXMtPmZpbGUgPSB1bmlxaWQoKSAuICIucGRmIjsKCiAgICAgICAgICAgIGlmKDAgPCBmdHBfc2l6ZSgkdGhpcy0+ZnRwX2Nvbm4sICRmaWxlX25hbWUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZighZnRwX2dldCgkdGhpcy0+ZnRwX2Nvbm4sIFRNUF9ESVIgLiAiLyIgLiAkdGhpcy0+ZmlsZSwgJGZpbGVfbmFtZSwgRlRQX0JJTkFSWSkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfRVJSLCAiRlRQIERvd25Mb2FkIEZhaWx1cmUgOiAgIiAuICRmaWxlX25hbWUsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfRVJSX1BERl9QUk9DRVNTKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIkZUUCBGSUxFIE5PVCBFWElTVFMgOiAgIiAuICRmaWxlX25hbWUsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAgICAgZnRwX2Nsb3NlKCR0aGlzLT5mdHBfY29ubik7CiAgICAgICAgICAgICAgICBwcnRFcnIoIuydtOuvuOyngCDshJzrsoTsl5Ag7YyM7J28KHskZmlsZV9uYW1lfSnsnbQg7JeG7Iq164uI64ukLiIpOwogICAgICAgICAgICAgICAgcmV0dXJuICLsnbTrr7jsp4Ag7ISc67KE7JeQIO2MjOydvCh7JGZpbGVfbmFtZX0p7J20IOyXhuyKteuLiOuLpC4iOwogICAgICAgICAgICB9CgogICAgICAgICAgICBmdHBfY2xvc2UoJHRoaXMtPmZ0cF9jb25uKTsKCiAgICAgICAgICAgIHJldHVybiBUTVBfRElSIC4gIi8iIC4gJHRoaXMtPmZpbGUgOwogICAgICAgIH0KCiAgICAgICAgLy8g7YyM7J28IOyCreygnAogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBfZGVsZXRlSW1hZ2VTZXJ2ZXJQREYoJGZpbGVfbmFtZSkKICAgICAgICB7CiAgICAgICAgICAgICR0aGlzLT5fY29ubmVjdF9mdHBTZXJ2ZXIoKTsKCiAgICAgICAgICAgIGlmKDAgPCBmdHBfc2l6ZSgkdGhpcy0+ZnRwX2Nvbm4sICRmaWxlX25hbWUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZighZnRwX2RlbGV0ZSgkdGhpcy0+ZnRwX2Nvbm4sICRmaWxlX25hbWUpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0VSUiwgIkZUUCBkZWxldGUgRmFpbHVyZSA6ICAiIC4gJGZpbGVfbmFtZSwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9FUlJfUERGX1BST0NFU1MpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBmdHBfY2xvc2UoJHRoaXMtPmZ0cF9jb25uKTsKICAgICAgICB9CgogICAgICAgIC8vaW5zZXJ0IGNpZF9pbnN0YWxsX2JhcmNvZGUKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gaW5zZXJ0QmFyY29kZSgpCiAgICAgICAgewogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gY2lkX2luc3RhbGxfYmFyY29kZSBzdGFydCIsICRQSFBfU0VMRiwgX19GSUxFX18sIF9fTElORV9fICkgOwogICAgICAgICAgICAkZXhpc3QgPSAkdGhpcy0+Y19kYi0+U1FMR2V0T25lKCdHRVRfQ0lEX0lOU1RBTExfQkFSQ09ERV9DT1VOVCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnd29ya19ncm91cCddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKTsKCiAgICAgICAgICAgIGlmKCRleGlzdCl7CiAgICAgICAgICAgICAgICBpZihmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnVVBEX0NJRF9JTlNUQUxMX0JBUkNPREUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJZIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tc2Nhbl95bgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdyZWVfeW4nXSAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGFncmVlX3luCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ3JlZV95bjInXSAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gYWdyZWVfeW4yCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ3JlZV95bjMnXSAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gYWdyZWVfeW4zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ3JlZV95bjQnXSAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gYWdyZWVfeW40CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gc2Nhbl9hZ2VudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIiIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gcG9zdF9ndWJ1bgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3dvcmtfZ3JvdXAnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH1lbHNlewogICAgICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ0lOU19DSURfSU5TVEFMTF9CQVJDT0RFJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3dvcmtfZ3JvdXAnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ1dPUktfUkVHX0RBVEUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0FDVElWSVRZX0NPREUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCIxIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfaWQnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCJGVFAiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIHN5c19hcHBsaWNhdGlvbl9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCJJTlMiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGRsX3NlcnZpY2VfY29kZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCIwIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGRsX3VwZGF0ZV9zdGFtcAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0ZVTExfTkFNRSddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGZ1bGxfbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0NJRF9TVEFUVVMnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGNpZF9zdGF0dXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwiVyIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBrZWVwX3N0YXR1cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHN1YnN0cigkdGhpcy0+Q29udHJhY3RJbmZvWydXT1JLX0RBVEVUSU1FJ10sIDAsIDgpICAgICAgICAgICAgIC8vIC0tIGFjdHZfZGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfaWQnXSAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIGFjdHZfYWdlbnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwiWSIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBzY2FuX3luCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ3JlZV95biddICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS0gYWdyZWVfeW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FncmVlX3luMiddICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBhZ3JlZV95bjIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FncmVlX3luMyddICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBhZ3JlZV95bjMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FncmVlX3luNCddICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBhZ3JlZV95bjQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwiIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBkb2NfdHlwZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfaWQnXSAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tIHNjYW5fYWdlbnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwiIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLSBwb3N0X2d1YnVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0RCX0ZBSUxVUkUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gY2lkX2luc3RhbGxfYmFyY29kZSBlbmQiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICB9CgogICAgICAgIC8vaW5zdGFsbCBncm91cF9jb250cmFjdF9pbmZvCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGluc2VydEdyb3VwQ29udHJhY3QoKQogICAgICAgIHsKICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGdyb3VwX2NvbnRyYWN0X2luZm8gc3RhcnQiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICAgICAgJGV4aXN0ID0gJHRoaXMtPmNfZGItPlNRTEdldE9uZSgnR0VUX0dST1VQX0NPTlRSQUNUX0lORk9fQ09VTlQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSk7CiAgICAgICAgICAgIGlmKCRleGlzdCl7CiAgICAgICAgICAgICAgICAvL+q4sOyhtCDsnbTroKUg7KCA7J6lCiAgICAgICAgICAgICAgICAkdGhpcy0+aW5zZXJ0R3JvdXBIaXN0b3J5KCk7CgogICAgICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ1VQRF9HUk9VUF9DT05UUkFDVF9JTkZPJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfaWQnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXN5c19vcGVyYXRvcl9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tcmVnX2FnZW50X2lkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3JlbWFyayddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1yZW1hcmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydzZXEnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7ICAgICAgICAgICAgICAgIC8v7Iug6rec7KCA7J6lCiAgICAgICAgICAgICAgICBpZihmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnSU5TX0dST1VQX0NPTlRSQUNUX0lORk8nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddICAgICAgICAgICAgICAgICAgICAvLyAtLW1hcmtldF9jb2RlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLWNpZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnc2VxJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1zZXEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxkYXRlKCdZbWQnKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tcmVnX2RhdGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X2lkJ10gICAgICAgICAgICAgICAgICAgICAgIC8vIC0tcmVnX2FnZW50X2lkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF9raW5kJ10gICAgICAgICAgICAgICAgICAvLyAtLWNvbnRyYWN0X2tpbmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X3R5cGUnXSAgICAgICAgICAgICAgICAgIC8vIC0tY29udHJhY3RfdHlwZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnd29ya19ncm91cCddICAgICAgICAgICAgICAgICAgICAgLy8gLS13b3JrX2dyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snQUNUSVZJVFlfQ09ERSddICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLWFjdGl2aXR5X2NvZGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X2lkJ10gICAgICAgICAgICAgICAgICAgICAgIC8vIC0tc3lzX29wZXJhdG9yX2lkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmb2xkZXJfbmFtZSddICAgICAgICAgICAgICAgICAgICAvLyAtLWZvbGRlcl9uYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmaWxlX25hbWUnXSAgICAgICAgICAgICAgICAgICAgICAvLyAtLWZpbGVfbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCJZIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1mbGFnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydyZW1hcmsnXSAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXJlbWFyawogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vJHRoaXMtPmNvbW1pdCgpOwogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gZ3JvdXBfY29udHJhY3RfaW5mbyBlbmQiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy9pbnN0YWxsIGN1c3RvbWVyX2RvY3VtZW50CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGluc2VydEN1c3RvbWVyRG9jdW1lbnQoKQogICAgICAgIHsKICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGN1c3RvbWVyX2RvY3VtZW50IHN0YXJ0IiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgICAgICRleGlzdCA9ICR0aGlzLT5jX2RiLT5TUUxHZXRPbmUoJ0dFVF9HUk9VUF9DT05UUkFDVF9JTkZPX0NPVU5UJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ2NpZCddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkRvY3VtZW50SW5mb1snSU5GTyddWydzZXEnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpOwogICAgICAgICAgICBpZigkZXhpc3QpewogICAgICAgICAgICAgICAgLy/quLDsobQg7J2066ClIOyggOyepQogICAgICAgICAgICAgICAgJHRoaXMtPmluc2VydERvY3VtZW50SGlzdG9yeSgpOwoKICAgICAgICAgICAgICAgIGlmKGZhbHNlID09ICR0aGlzLT5jX2RiLT5TUUxFeGVjdXRlKCdVUERfR1JPVVBfQ09OVFJBQ1RfSU5GTycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X2lkJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1zeXNfb3BlcmF0b3JfaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfaWQnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXJlZ19hZ2VudF9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydyZW1hcmsnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tcmVtYXJrCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnc2VxJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0RCX0ZBSUxVUkUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgeyAgICAgICAgICAgICAgICAvL+yLoOq3nOyggOyepQogICAgICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ0lOU19HUk9VUF9DT05UUkFDVF9JTkZPJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXSAgICAgICAgICAgICAgICAgICAgLy8gLS1tYXJrZXRfY29kZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1jaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tc2VxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZGF0ZSgnWW1kJykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXJlZ19kYXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXJlZ19hZ2VudF9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY29udHJhY3Rfa2luZCddICAgICAgICAgICAgICAgICAgLy8gLS1jb250cmFjdF9raW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF90eXBlJ10gICAgICAgICAgICAgICAgICAvLyAtLWNvbnRyYWN0X3R5cGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3dvcmtfZ3JvdXAnXSAgICAgICAgICAgICAgICAgICAgIC8vIC0td29ya19ncm91cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0FDVElWSVRZX0NPREUnXSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1hY3Rpdml0eV9jb2RlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXN5c19vcGVyYXRvcl9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXSAgICAgICAgICAgICAgICAgICAgLy8gLS1mb2xkZXJfbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnZmlsZV9uYW1lJ10gICAgICAgICAgICAgICAgICAgICAgLy8gLS1maWxlX25hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwiWSIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tZmxhZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsncmVtYXJrJ10gICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1yZW1hcmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uIChFUlJPUl9DT0RFX0RCX0ZBSUxVUkUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyR0aGlzLT5jb21taXQoKTsKICAgICAgICAgICAgQGxvZ0hhbmRsZXIoUEVBUl9MT0dfSU5GTywgIkluc2VydCBpbnRvIGdyb3VwX2NvbnRyYWN0X2luZm8gZW5kIiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CiAgICAgICAgfQoKICAgICAgICAvL2luc2VydCBncm91cF9jb250cmFjdF9pbmZvX2hpcwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBpbnNlcnRHcm91cEhpc3RvcnkoKQogICAgICAgIHsKICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ0lOU19HUk9VUF9DT05UUkFDVF9JTkZPX0hJUycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1zeXNfb3BlcmF0b3JfaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tbWFya2V0X2NvZGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tY2lkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXNlcQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy9pbnNlcnQgY3VzdG9tZXJfZG9jdW1lbnRfaGlzCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGluc2VydERvY3VtZW50SGlzdG9yeSgpCiAgICAgICAgewogICAgICAgICAgICBpZihmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnSU5TX0dST1VQX0NPTlRSQUNUX0lORk9fSElTJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2FnZW50X2lkJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXN5c19vcGVyYXRvcl9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1tYXJrZXRfY29kZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLS1jaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnc2VxJ10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0tc2VxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbiAoRVJST1JfQ09ERV9EQl9GQUlMVVJFKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy/ruYTqs6Dtla3rqqnrsI8g64+Z7J2Y7ZWt66qpIOyImOyglQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBlZGl0Q29udHJhY3QoKQogICAgICAgIHsKICAgICAgICAgICAgLy/quLDsobQg7J2066ClIOyggOyepQogICAgICAgICAgICAkdGhpcy0+aW5zZXJ0R3JvdXBIaXN0b3J5KCk7CgogICAgICAgICAgICBpZihmYWxzZSA9PSAkdGhpcy0+Y19kYi0+U1FMRXhlY3V0ZSgnVVBEX0dST1VQX0NPTlRSQUNUX0lORk9fREFUQScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAtLXN5c19vcGVyYXRvcl9pZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X3R5cGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3JlZ19hZ2VudF9pZCddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsncmVtYXJrJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydzZXEnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmICgkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X2tpbmQnXSA9PSAiUCIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICRzeXNfbWVtb190ZXh0ID0gIuyekeyXheuCtOyXrTpb6rCc7J24IOqzhOyVveyEnCDsoJXrs7Qg7IiY7KCVXSI7CiAgICAgICAgICAgICAgICAkdXNyX21lbW9fdGV4dCA9ICIxLuuzgOqyveyCrO2VrTpb67mE6rOgIC0gIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3JlbWFyayddLiJdLDMu7J6R7JeF6re466O5OlsiLiR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnd29ya19ncm91cCddLiJdIDMu7J6R7JeF7J6QOlsiLiR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnYWdlbnRfbmFtZSddLiJdIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICRzeXNfbWVtb190ZXh0ID0gIuyekeyXheuCtOyXrTpb64uo7LK0IOqzhOyVveyEnCDsoJXrs7Qg7IiY7KCVXSI7CiAgICAgICAgICAgICAgICAkdXNyX21lbW9fdGV4dCA9ICIxLuuzgOqyveyCrO2VrTpb67mE6rOgIC0gIi4kdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3JlbWFyayddLiJdLDIuU0VRX05POlsiLiR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnc2VxJ10uIl0gMy7snpHsl4XsnpA6WyIuJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9uYW1lJ10uIl0iOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkdGhpcy0+aW5zZXJ0Q0NNX01FTU8oJHN5c19tZW1vX3RleHQsICR1c3JfbWVtb190ZXh0KTsKCiAgICAgICAgICAgICR0aGlzLT5jb21taXQoKTsKICAgICAgICB9CgovLyBIYW5nYW5nX2F1dG9fc3RhcnQgOiBpbnNlcnRQYXltZW50TWV0aG9kSGlzdG9yeSAoYXV0b3BheSAtIHVwbG9hZCkKICAgICAgICAvL2luc2VydCBwYXltZW50X21ldGhvZF9oaXN0b3J5CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGluc2VydFBheW1lbnRNZXRob2RIaXN0b3J5KCkKICAgICAgICB7CiAgICAgICAgICAgIEBsb2dIYW5kbGVyKFBFQVJfTE9HX0lORk8sICJJbnNlcnQgaW50byBwYXltZW50X21ldGhvZF9oaXN0b3J5IHN0YXJ0IiwgJFBIUF9TRUxGLCBfX0ZJTEVfXywgX19MSU5FX18gKSA7CgogICAgICAgICAgICAkYWdyZWVfbmFtZSA9ICR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnZm9sZGVyX25hbWUnXS4iLyIuJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydmaWxlX25hbWUnXTsKCiAgICAgICAgICAgIGlmKGZhbHNlID09ICR0aGlzLT5jX2RiLT5TUUxFeGVjdXRlKCdVUERfUEFZTUVOVF9NRVRIT0RfSElTVE9SWScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgJGFncmVlX25hbWUgICAgICAgICAgICAgICAgICAgICAvLyBhZ3JlZV9uYW1lCiAgICAgICAgICAgICAgICAgICAgLCdTQ0FOJyAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWdyZWVfdHlwZQogICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10KICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXQogICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3dvcmtfZ3JvdXAnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vJHRoaXMtPmNvbW1pdCgpOwogICAgICAgICAgICBAbG9nSGFuZGxlcihQRUFSX0xPR19JTkZPLCAiSW5zZXJ0IGludG8gcGF5bWVudF9tZXRob2RfaGlzdG9yeSBlbmQiLCAkUEhQX1NFTEYsIF9fRklMRV9fLCBfX0xJTkVfXyApIDsKICAgICAgICB9Ci8vIEhhbmdhbmdfYXV0b19lbmQKCiAgICAgICAgLy/ri6jssrTqs4Tslb3shJwg7KCA7J6l7J2066ClIOyCreygnAogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBkZWxldGVDb250cmFjdCgkZmlsZV9uYW1lKQogICAgICAgIHsKICAgICAgICAgICAgJHRoaXMtPl9kZWxldGVJbWFnZVNlcnZlclBERigkZmlsZV9uYW1lKTsKCiAgICAgICAgICAgIC8v7J2066Cl7IKt7KCcCiAgICAgICAgICAgIGlmKGZhbHNlID09ICR0aGlzLT5jX2RiLT5TUUxFeGVjdXRlKCdERUxFVEVfR1JPVVBfQ09OVFJBQ1RfSU5GT19ISVMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnc2VxJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oRVJST1JfQ09ERV9EQl9GQUlMVVJFKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy/soJXrs7Tsgq3soJwKICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ0RFTEVURV9HUk9VUF9DT05UUkFDVF9JTkZPJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3NlcSddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbihFUlJPUl9DT0RFX0RCX0ZBSUxVUkUpOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkc3lzX21lbW9fdGV4dCA9ICLsnpHsl4Xrg5Dsl606W+uLqOyytCDqs4Tslb3shJwg7IKt7KCc7LKY66asXSI7CiAgICAgICAgICAgICR1c3JfbWVtb190ZXh0ID0gIjEu7IKt7KCc7YyM7J2866qFOlsiLiRmaWxlX25hbWUuIl0sMi7snpHsl4XsnpA6WyIuJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9uYW1lJ10uIl0iOwoKICAgICAgICAgICAgJHRoaXMtPmluc2VydENDTV9NRU1PKCRzeXNfbWVtb190ZXh0LCAkdXNyX21lbW9fdGV4dCk7CgogICAgICAgICAgICAkdGhpcy0+Y29tbWl0KCk7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gaW5zZXJ0Q0NNX01FTU8oJHN5c19tZW1vX3RleHQsICR1c3JfbWVtb190ZXh0KQogICAgICAgIHsKICAgICAgICAgICAgaWYoZmFsc2UgPT0gJHRoaXMtPmNfZGItPlNRTEV4ZWN1dGUoJ0lOU19DQ01fTUVNTycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ2NpZCddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydhZ2VudF9pZCddCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIjAwMzgiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJHN5c19tZW1vX3RleHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwkdXNyX21lbW9fdGV4dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnbWFya2V0X2NvZGUnXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCR0aGlzLT5Db250cmFjdEluZm9bJ0lORk8nXVsnY2lkJ10pKSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24gKEVSUk9SX0NPREVfREJfRkFJTFVSRSk7CiAgICAgICAgICAgIH0KLy8gICAgICAgICAgICAkdGhpcy0+Y29tbWl0KCk7CiAgICAgICAgfQoKICAgICAgICAvL1BERiDsoIDsnqUg7Y+0642UCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldFBERlNlcnZlckZvbGRlck5hbWUoKQogICAgICAgIHsKICAgICAgICAgICAgJHl5eXltbWRkID0gc3RyX3JlcGxhY2UoIi4iLCIiLCBkYXRlKCdZLm0uZCcpKTsKICAgICAgICAgICAgJHl5eXltbWRkID0gc3Vic3RyKCR5eXl5bW1kZCwgMCwgOCk7CgogICAgICAgICAgICAkZm9sZGVyICAgPSAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10gLiAiLyIgLiBzdWJzdHIoJHl5eXltbWRkLCAwLCA0KSAuICIvIiAuIHN1YnN0cigkeXl5eW1tZGQsIC00KSA7CgogICAgICAgICAgICByZXR1cm4gJGZvbGRlcjsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy8g7ISc66WYIOyggOyepSDtj7TrjZQKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0RG9jdW1lbnRGb2xkZXJOYW1lKCkKICAgICAgICB7CiAgICAgICAgICAgICR5eXl5bW1kZCA9IHN0cl9yZXBsYWNlKCIuIiwiIiwgZGF0ZSgnWS5tLmQnKSk7CiAgICAgICAgICAgICR5eXl5bW1kZCA9IHN1YnN0cigkeXl5eW1tZGQsIDAsIDgpOwoKICAgICAgICAgICAgJGZvbGRlciAgID0gJHRoaXMtPkRvY3VtZW50SW5mb1snSU5GTyddWydtYXJrZXRfY29kZSddIC4gIi8iIC4gc3Vic3RyKCR5eXl5bW1kZCwgMCwgNCkgLiAiLyIgLiBzdWJzdHIoJHl5eXltbWRkLCAtNCkgOwoJCQkJCQkKICAgICAgICAgICAgcmV0dXJuICRmb2xkZXI7CiAgICAgICAgfQoKICAgICAgICAvL1BERiDtjIzsnbzrqoUKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0UERGU2VydmVyRmlsZU5hbWUoKQogICAgICAgIHsKICAgICAgICAgICAgJHl5eXltbWRkID0gc3RyX3JlcGxhY2UoIi4iLCIiLCBkYXRlKCdZLm0uZCcpKTsKICAgICAgICAgICAgJHl5eXltbWRkID0gc3Vic3RyKCR5eXl5bW1kZCwgMCwgOCk7CiAgICAgICAgICAgICRmaWxlX25hbWUgPSAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10gLiJfIi4gJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjaWQnXTsKCiAgICAgICAgICAgICRmaWxlX25hbWUgPSAoJHRoaXMtPkNvbnRyYWN0SW5mb1snSU5GTyddWydjb250cmFjdF9raW5kJ10gPT0iUCIpID8gJGZpbGVfbmFtZSAuIl8iLiAkdGhpcy0+Q29udHJhY3RJbmZvWydJTkZPJ11bJ3dvcmtfZ3JvdXAnXSAuIl8iLiAkeXl5eW1tZGQgOiAkZmlsZV9uYW1lLiJfIi4keXl5eW1tZGQgOwoKICAgICAgICAgICAgcmV0dXJuICRmaWxlX25hbWUgOwogICAgICAgIH0KICAgICAgICAKICAgICAgICAvLyDshJzrpZgg7YyM7J2866qFIAogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXREb2N1bWVudEZpbGVOYW1lKCkKICAgICAgICB7CiAgICAgICAgICAgICR5eXl5bW1kZCA9IHN0cl9yZXBsYWNlKCIuIiwiIiwgZGF0ZSgnWS5tLmQnKSk7CiAgICAgICAgICAgICR5eXl5bW1kZCA9IHN1YnN0cigkeXl5eW1tZGQsIDAsIDgpOwogICAgICAgICAgICAgCiAgICAgICAgICAgICRmaWxlX25hbWUgPSAkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ21hcmtldF9jb2RlJ10gLiJfIi4gJHRoaXMtPkRvY3VtZW50SW5mb1snSU5GTyddWydjaWQnXSAuIl8iLiAkeXl5eW1tZGQgOwoJCQkJCiAgICAgICAgICAgIC8vJGZpbGVfbmFtZSA9ICgkdGhpcy0+RG9jdW1lbnRJbmZvWydJTkZPJ11bJ2NvbnRyYWN0X2tpbmQnXSA9PSJQIikgPyAkZmlsZV9uYW1lIC4iXyIuICR0aGlzLT5Eb2N1bWVudEluZm9bJ0lORk8nXVsnd29ya19ncm91cCddIC4iXyIuICR5eXl5bW1kZCA6ICRmaWxlX25hbWUuIl8iLiR5eXl5bW1kZCA7CgogICAgICAgICAgICByZXR1cm4gJGZpbGVfbmFtZSA7CiAgICAgICAgfQogICAgICAgIAoKICAgICAgICAvL+qzhOyVveyEnCDsooXrpZgg6rCA7KC47Jik6riwCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldF9jb250cmFjdF90eXBlKCRtYXJrZXRfY29kZSkKICAgICAgICB7CiAgICAgICAgICAgICR0aGlzLT5jX2RiID0gREJDb250cm9sbGVyOjpnZXRJbnN0YW5jZSgpOwogICAgICAgICAgICAkX2xpc3QgPSAkdGhpcy0+Y19kYi0+U1FMUXVlcnkoIkdFVF9DT05UUkFDVF9UWVBFX0xJU1QiLCBhcnJheSgkbWFya2V0X2NvZGUpKTsKCiAgICAgICAgICAgICRhcnIgPSBhcnJheSgpOwoKICAgICAgICAgICAgZm9yKCRpPTA7ICRpIDwgY291bnQoJF9saXN0KTsgJGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgJGFyclskX2xpc3RbJGldWydDT0RFX1ZBTCddIF0gPSAkX2xpc3RbJGldWydDT0RFX1NUUiddOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gJGFycjsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBjb21taXQoKQogICAgICAgIHsKICAgICAgICAgICAgJHRoaXMtPmNfZGItPmNvbW1pdCgpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHJvbGxiYWNrKCkKICAgICAgICB7CiAgICAgICAgICAgICR0aGlzLT5jX2RiLT5yb2xsYmFjaygpOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGRpc2Nvbm4oJGZsYWc9RkFMU0UpCiAgICAgICAgewogICAgICAgICAgICAkdGhpcy0+Y19kYi0+ZGlzY29ubigkZmxhZyk7CiAgICAgICAgfQoKICAgICAgICAvL+2MjOydvOygleuztCDsnqzrsLDsl7Qg7LKY66asCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIG11bHRpcGxlKGFycmF5ICRfZmlsZXMsICR0b3AgPSBUUlVFKQogICAgICAgIHsKICAgICAgICAgICAgJGZpbGVzID0gYXJyYXkoKTsKICAgICAgICAgICAgZm9yZWFjaCgkX2ZpbGVzIGFzICRuYW1lPT4kZmlsZSl7CiAgICAgICAgICAgICAgICBpZigkdG9wKSAkc3ViX25hbWUgPSAkZmlsZVsnbmFtZSddOwogICAgICAgICAgICAgICAgZWxzZSAgICAgJHN1Yl9uYW1lID0gJG5hbWU7CgogICAgICAgICAgICAgICAgaWYoaXNfYXJyYXkoJHN1Yl9uYW1lKSl7CiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaChhcnJheV9rZXlzKCRzdWJfbmFtZSkgYXMgJGtleSl7CiAgICAgICAgICAgICAgICAgICAgICAgICRmaWxlc1skbmFtZV1bJGtleV0gPSBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICduYW1lJyAgICAgPT4gJGZpbGVbJ25hbWUnXVska2V5XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJyAgICAgPT4gJGZpbGVbJ3R5cGUnXVska2V5XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0bXBfbmFtZScgPT4gJGZpbGVbJ3RtcF9uYW1lJ11bJGtleV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXJyb3InICAgID0+ICRmaWxlWydlcnJvciddWyRrZXldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemUnICAgICA9PiAkZmlsZVsnc2l6ZSddWyRrZXldLAogICAgICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgICAgICAgICAkZmlsZXNbJG5hbWVdID0gJHRoaXMtPm11bHRpcGxlKCRmaWxlc1skbmFtZV0sIEZBTFNFKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgICAgICAkZmlsZXNbJG5hbWVdID0gJGZpbGU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuICRmaWxlczsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBsb2dpbl9jaGsoKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCEkX1NFU1NJT05bJ2Zyb21TTVMnXSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2Vzc2lvbl9kZXN0cm95KCk7CiAgICAgICAgICAgICAgICBoZWFkZXIoIkxvY2F0aW9uOiAvZ3JvdXBfY29udHJhY3QvaW5kZXgucGhwIik7CiAgICAgICAgICAgICAgICBkaWUoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHBydF9yZXR1cm4oJHN0ciwgJHVybCwgYXJyYXkgJGRhdGEpCiAgICAgICAgewogICAgICAgICAgICBlY2hvICI8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj5hbGVydChcIiRzdHJcIik7PC9zY3JpcHQ+IjsKICAgICAgICAgICAgX3VzZXJfcmVhY3Rpb24oJHVybCwgJGRhdGEpOwogICAgICAgIH0KCiAgICB9