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("aWYoaW50dmFsKHN1YnN0cihwaHB2ZXJzaW9uKCksMCwxKSk8IDUpe2VjaG8gJ1BIUGZvck..

Decoded Output download

if(intval(substr(phpversion(),0,1))< 5){echo 'PHPforFb needs PHP version 5.0 or higher.';exit;}if(!function_exists('json_decode')){echo "PHPforFb needs the JSON PHP extension.
Please visit http://www.php.net/manual/en/book.json.php for more information and installation instructions.";exit;}if(!function_exists('curl_init')){echo "PHPforFb needs the CURL PHP extension.
Please visit http://www.php.net/manual/en/book.curl.php for more information and installation instructions.";exit;}define('GRAPH_URL','https://graph.facebook.com');define('FQL_URL','https://api.facebook.com/method/fql.query');define('REST_URL','https://api.facebook.com/restserver.php');define('NOT_IN_THIS_MODE','Only available in PHPforFB app/page mode');class PHPforFB{public $appID;public $appName;public $appFBURL;public $appServerURL;public $appAccessToken;public $ssl_proxy_url = '';public $logDir;public $logLevel = 1;public $logging = 0;public $caching = TRUE;public $cacheExpires = 600;public $callFromFacebook;public $userLoggedIn = FALSE;public $userAuthenticated = FALSE;public $userUsedLanguage;public $userActualCountry;public $userIsAdult = FALSE;public $callFrom = '';public $okURL;public $cancelURL;public $accessToken;public $accessToken_url_param;public $accessToken_expire_date;public $accessToken_expires_in_seconds;public $userID;public $userData;public $userFriendsData;public $userLikes;public $userAlbums;public $lastErrorCode;public $lastError;public $runOutofIframe = FALSE;public $callAsPage = FALSE;public $pageID = 0;public $isPageAdmin;public $userLikesPage;public $pageData;public $isMobileDevice = FALSE;public $mobileDevice = '';public $runMode = 'app';public $protocol = 'http://';private $scopes = 'basic';private $scopes_ok = '';private $scopes_request_date;private $gotoPage = FALSE;private $gotoURL;private $object_id;private $session_id;private $last_update;private $log_filename;private $AppSecKey;private $addPage_redirect_url = '';private $app_call_params = '';private $classVersion = '1.96';private $classBuild = '30617';public $PERMISSONS_AVAILABLE = array( 'basic','user_about_me','friends_about_me','user_activities','friends_activities','user_birthday','friends_birthday','user_checkins','friends_checkins','user_education_history','friends_education_history','user_events','friends_events','user_groups','friends_groups','user_hometown','friends_hometown','user_interests','friends_interests','user_likes','friends_likes','user_location','friends_location','user_notes','friends_notes','user_photos','friends_photos','user_questions','friends_questions','user_relationships','friends_relationships','user_relationship_details','friends_relationship_details','user_religion_politics','friends_religion_politics','user_status','friends_status','user_subscriptions','friends_subscriptions','user_videos','friends_videos','user_website','friends_website','user_work_history','friends_work_history','email','publish_actions','user_games_activity','friends_games_activity','~','read_friendlists','read_insights','read_mailbox','read_requests','read_stream','xmpp_login','ads_management','create_event','manage_friendlists','manage_notifications','user_online_presence','friends_online_presence','publish_checkins','publish_stream','rsvp_event','offline_access',);public function __construct($structInitData){if(strstr($_SERVER['HTTP_USER_AGENT'],'IE')){if(!headers_sent()){header('P3P: CP=CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE');}}if(empty($structInitData['mode'])|| !isset($structInitData['mode'])){$mode = 'app';}else{$modes = array('app','page','callback','direct_use');$mode = $structInitData['mode'];if(!in_array(strtolower($mode),$modes)){$this->lastError = 'Unknown mode parameter'."
Please use: ".var_export($modes,TRUE);$this->lastErrorCode = 1029;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if($mode == 'page')$mode = 'app';$this->runMode = $mode;if(isset($structInitData['logDir']))$log_directory = $structInitData['logDir'];else $log_directory = '';$arr = array('logLevel','logging','caching','cacheExpires','runOutofIframe');foreach($arr as $val)if(isset($structInitData[$val])&& $structInitData[$val]<>'' )$this->$val = $structInitData[$val];$this->log_filename = 'PHPforFB_'.DATE('Ymd').'.log';if($log_directory <> ''){$this->logging = 1;if(strtoupper($log_directory)== 'TEMP_DIR'){$this->logDir = $this->getTempDir();$this->WriteLog(2,'set tempdir to '.$this->logDir);}else{if($log_directory=='./')$log_directory = dirname($_SERVER['SCRIPT_FILENAME']).'/';if(substr($log_directory,-1)<>'/')$log_directory.='/';if(!is_dir($log_directory)){if(!mkdir($log_directory,0700,true)){$this->lastError = 'Can not create Log directory';$this->lastErrorCode = 1005;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}$this->logDir = $log_directory;$this->WriteLog(2,'set tempdir to '.$this->logDir);}}else{$this->logging = 0;}if(!empty($structInitData['app_id'])){$app_id = $structInitData['app_id'];if(strlen($app_id)< 12){if($app_id==''){$this->lastError = 'appID not available';$this->lastErrorCode = 1001;}else{$this->lastError = 'Invalid appID';$this->lastErrorCode = 1002;}$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if($this->runMode == 'app'){$app_name = $structInitData['app_name'];$sec_key = $structInitData['sec_key'];if(session_id()== ''){$res = session_start();if($res <> FALSE){$this->WriteLog(2,'Session started with Session-Id: '.session_id());}else{$this->lastError = 'Session start failed';$this->lastErrorCode = 1000;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}else{$this->WriteLog(2,'Session-Id: '.session_id());}if(strlen($sec_key)< 28){if($sec_key==''){$this->lastError = 'SecurityKey not available';$this->lastErrorCode = 1003;}else{$this->lastError = 'Invalid SecurityKey';$this->lastErrorCode = 1004;}$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(strlen($app_name)< 3){if($app_name==''){$this->lastError = 'AppName(Namespace / Canvas Name)not available';$this->lastErrorCode = 1008;}else{$this->lastError = 'AppName(Namespace / Canvas Name)too short';$this->lastErrorCode = 1009;}$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if(isset($_REQUEST['signed_request'])){$signed_request = $this->GetSignedRequest($_REQUEST['signed_request']);}$mobile_web = FALSE;if(isset($_GET['_rdr'])){$mobile_web = TRUE;if(!isset($_REQUEST['fbs_'.$app_id])){}else{if(!isset($_REQUEST['signed_request'])&& !empty($app_id)&& isset($_REQUEST['fbs_'.$app_id])&& !empty($_REQUEST['fbs_'.$app_id])){$fbs_token = $this->GetFbsToken($_REQUEST['fbs_'.$app_id]);$this->WriteLog(2,'FBS_TOKEN detected');if($fbs_token === FALSE){$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$signed_request['user_id'] = $fbs_token['uid'];$signed_request['oauth_token'] = $fbs_token['access_token'];$signed_request['expires'] = $fbs_token['expires'];}}}}if(isset($signed_request)){if(isset($signed_request['user_id']))$user_id = $signed_request['user_id'];else $user_id = '';}else{$user_id = '';}$this->isMobileDevice = FALSE;$useragent=$_SERVER['HTTP_USER_AGENT'];if(strlen($useragent)> 10){$tabletDevices = array( 'BlackBerryTablet'  => 'PlayBook|RIM Tablet','iPad'              => 'iPad|iPad.*Mobile', 'NexusTablet'       => '^.*Android.*Nexus(?:(?!Mobile).)*$','Kindle'            => 'Kindle|Silk.*Accelerated','SamsungTablet'     => 'SAMSUNG.*Tablet|Galaxy.*Tab|GT-P1000|GT-P1010|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P1000|GT-P3100|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7300|GT-P7320|GT-P7500|GT-P7510|GT-P7511','HTCtablet'         => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200','MotorolaTablet'    => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617','AsusTablet'        => 'Transformer|TF101','NookTablet'        => 'Android.*Nook|NookColor|nook browser|BNTV250A|LogicPD Zoom2','AcerTablet'        => 'Android.*(A100|A101|A200|A500|A501|A510|W500|W500P|W501|W501P)','YarvikTablet'      => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)','MedionTablet'      => 'Android.*OYO|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB','ArnovaTablet'      => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT','ArchosTablet'      => 'Android.*ARCHOS|101G9|80G9','AinolTablet'       => 'NOVO7|Novo7Aurora|Novo7Basic|NOVO7PALADIN','SonyTablet'        => 'Sony Tablet|Sony Tablet S','GenericTablet'     => 'Tablet(?!.*PC)|ViewPad7|LG-V909|MID7015|BNTV250A|LogicPD Zoom2|A7EB|CatNova8|A1_07|CT704|CT1002|M721|hp-tablet',);$regex = '';foreach($tabletDevices as $val => $regex){$regex = str_replace('/','\/',$regex);if(preg_match('/'.$regex.'/is',$useragent)){$this->isMobileDevice = TRUE;$this->mobileDevice = 'tablet';break;}}if($this->isMobileDevice === FALSE){if(preg_match('/ipad/i',$useragent)||preg_match('/ipod/i',$useragent)||preg_match('/iphone/i',$useragent)|| preg_match('/android/i',$useragent)|| preg_match('/opera mini/i',$useragent)|| preg_match('/blackberry/i',$useragent)|| preg_match('/(pre\/|palm os|palm|hiptop|avantgo|plucker|xiino|blazer|elaine)/i',$useragent)|| preg_match('/(iris|3g_t|windows ce|opera mobi|windows ce;smartphone;|windows ce;iemobile)/i',$useragent)){$this->isMobileDevice = TRUE;$this->mobileDevice = 'touch';}}if($this->isMobileDevice === FALSE){if(preg_match('/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows(ce|phone)|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))){$this->isMobileDevice = TRUE;$this->mobileDevice = 'wap';}}}if($this->isMobileDevice === FALSE && $mobile_web === TRUE)$this->isMobileDevice = TRUE; if((isset($_GET[$app_name])&& $_GET[$app_name]==$app_name)||(isset($_GET['$'.'ap'.'d'])&& $_GET['$'.'apd']=='47912070')){echo 'Code use PHPforFB class v. '.$this->classVersion.'(Build '.$this->classBuild.')';exit;}if(isset($_SERVER['https'])&&($_SERVER['https'] == 'on' || $_SERVER['https'] == 1)){$this->protocol = 'https://';}elseif($_SERVER['SERVER_PORT'] == 443){$this->protocol = 'https://';}if($this->protocol <> 'https://' && isset($structInitData['ssl_proxy_available'])&& $structInitData['ssl_proxy_available']===TRUE){if(!isset($_SERVER['HTTP_X_FORWARDED_HOST'])&& !isset($_SERVER['HTTP_X_FORWARDED_SERVER'])){$this->ssl_proxy_url = '';}else{if(!isset($structInitData['ssl_app_url'])|| empty($structInitData['ssl_app_url'])|| strlen($structInitData['ssl_app_url'])<5){$this->lastError = 'ssl_app_url is empty or invalid';$this->lastErrorCode = 1033;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$okk = 0;if(isset($_SERVER['HTTP_X_FORWARDED_HOST'])&& strpos(strtolower($structInitData['ssl_app_url']),strtolower($_SERVER['HTTP_X_FORWARDED_HOST']))!== FALSE){$okk = 1;}if(isset($_SERVER['HTTP_X_FORWARDED_SERVER'])&& strpos(strtolower($structInitData['ssl_app_url']),strtolower($_SERVER['HTTP_X_FORWARDED_SERVER']))!== FALSE){$okk = 1;}if($okk==1){if(strtolower(substr($structInitData['ssl_app_url'],0,8))=='https://')$structInitData['ssl_app_url'] = substr($structInitData['ssl_app_url'],8,1000);if(substr($structInitData['ssl_app_url'],-1)<>'/')$structInitData['ssl_app_url'].='/';$this->protocol = 'https://';$this->ssl_proxy_url = $this->protocol.str_replace(substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'?')),'',$structInitData['ssl_app_url']);if(substr($this->ssl_proxy_url,-1)=='/')$this->ssl_proxy_url=substr($this->ssl_proxy_url,0,-1);}else{$this->ssl_proxy_url = '';}}}}if($mode == 'callback'){if(empty($signed_request)){$this->lastError = 'callback-Mode: no signed_request send by facebook';$this->lastErrorCode = 1030;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$this->userID = $signed_request['user_id'];if(isset($signed_request['user']['locale']))$this->userUsedLanguage = $signed_request['user']['locale'];if(isset($signed_request['user']['country']))$this->userActualCountry = $signed_request['user']['country'];$this->WriteLog(2,'Callback mode call width userID '.$this->userID);}}else{$this->appID = $app_id;if($mode == 'direct_use'){$this->WriteLog(2,'Start direct_user mode');}else{$CreateNewClass = 0;if(!isset($_SESSION['PHP4Fb_'.$app_id])|| !isset($_SESSION['PHP4Fb_'.$app_id]['app_id'])|| !isset($_SESSION['PHP4Fb_'.$app_id]['sec_key'])){$CreateNewClass = 1;}else{if( $_SESSION['PHP4Fb_'.$app_id]['app_id'] <> $app_id || $_SESSION['PHP4Fb_'.$app_id]['sec_key'] <> $sec_key ){$this->lastError = 'Internal Error(Init AppID or Sec_Key)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!isset($_REQUEST['signed_request'])|| $_REQUEST['signed_request'] == ''){$CreateNewClass = 2;}else{if(isset($_REQUEST['state'])&& $_REQUEST['state'] <> ''){$CreateNewClass = 2;}else{if($user_id == ''){if(!isset($_SESSION['PHP4Fb_'.$app_id]['object'])){$CreateNewClass = 1;}else{$allclassvars = $_SESSION['PHP4Fb_'.$app_id]['object'];$allclassvars = base64_decode($allclassvars);$allclassvars = unserialize($allclassvars);if($allclassvars['appID'] <> $app_id)$CreateNewClass = 1;else{if($allclassvars['gotoPage'] === TRUE){$CreateNewClass = 2;}else{$CreateNewClass = 1;}}}}else{if(!empty($_SESSION['PHP4Fb_'.$app_id]['user_id'])&& $_SESSION['PHP4Fb_'.$app_id]['user_id'] <> $user_id){$CreateNewClass = 1;}else{if(isset($signed_request['user_id'])&& isset($signed_request['oauth_token'])){if(!empty($_SESSION['PHP4Fb_'.$app_id]['object'])){$tmp_arr = unserialize(base64_decode($_SESSION['PHP4Fb_'.$app_id]['object']));}if(isset($tmp_arr['gotoPage'])&&  $tmp_arr['gotoPage'] === TRUE){$CreateNewClass = 2;}else{$CreateNewClass = 1;}}else{$CreateNewClass = 2;}}}}}}}$this->AppSecKey = $sec_key;$this->appName = $app_name;$this->appFBURL = $this->protocol.'apps.facebook.com/'.$this->appName.'/';if(!isset($_SESSION['PHP4Fb_'.$app_id])){$checkName = FALSE;$L_filename = 'PHP4Fb'.$this->appID.'.dat';$checkName = $this->CheckTempFile($L_filename,24);if($checkName === TRUE){$this->WriteLog(2,'Checking appFBURL '.$this->appFBURL);$c = curl_init();$ok = 1;if(curl_setopt( $c,CURLOPT_URL,'https://apps.facebook.com/'.$this->appName.'/')===FALSE)$ok = 0; if(curl_setopt( $c,CURLOPT_SSL_VERIFYPEER,false)=== FALSE )$ok = 0;if(curl_setopt( $c,CURLOPT_RETURNTRANSFER,true )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_CUSTOMREQUEST,'HEAD' )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_HEADER,1 )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_NOBODY,true )=== FALSE )$ok = 0;if(curl_setopt( $c,CURLOPT_USERAGENT,'Mozilla/5.0(X11;Linux)Gecko Firefox/5.0')===FALSE)$ok = 0;if($ok<>1){trigger_error(curl_error($c));$this->lastError = 'CURL setting failed(checking appFBURL)';$this->lastErrorCode = 1013;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$res = strtolower(curl_exec( $c ));if($res === FALSE){trigger_error(curl_error($c));$this->lastError = 'CURL exec failed(checking appFBURL)';$this->lastErrorCode = 1006 ;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$info = curl_getinfo($c);if($info['http_code']<>200 || strpos($res,'content-length: 0')>0 || strpos($res,'location: http://www.facebook.com/4oh4.php')>0 || strpos($res,'location: https://www.facebook.com/4oh4.php')>0){ $this->lastError = 'appName(Namespace / Canvas Name)incorrect: '.$this->appFBURL.'(Sand box mode active?)';$this->lastErrorCode = 1028;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}}}}if($CreateNewClass == 1){if(isset($_SERVER['QUERY_STRING']))$this->app_call_params = strtolower($_SERVER['QUERY_STRING']);if(isset($_SESSION['PHP4Fb_'.$app_id]))unset($_SESSION['PHP4Fb_'.$app_id]);$_SESSION['PHP4Fb_'.$app_id]['app_id'] = $app_id;$_SESSION['PHP4Fb_'.$app_id]['sec_key'] = $sec_key;$this->object_id = substr(md5(time()),0,16);$this->session_id = session_id();if(!isset($structInitData['ssl_proxy_available'])|| $structInitData['ssl_proxy_available']===FALSE || $this->ssl_proxy_url==''){$this->appServerURL = $this->protocol.$_SERVER['HTTP_HOST'];if(strpos($_SERVER['REQUEST_URI'],'?')>0)$this->appServerURL .= substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'?'));else $this->appServerURL .= $_SERVER['REQUEST_URI'];}else{$this->appServerURL = $this->ssl_proxy_url;if(strpos($_SERVER['REQUEST_URI'],'?')>0)$this->appServerURL .= substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'?'));else $this->appServerURL .= $_SERVER['REQUEST_URI'];if(!isset($_SESSION['PHP4Fb_'.$app_id])){$c = curl_init();$ok = 1;if(curl_setopt( $c,CURLOPT_URL,$this->appServerURL )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_RETURNTRANSFER,true )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_CUSTOMREQUEST,'HEAD' )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_HEADER,1 )===FALSE)$ok = 0;if(curl_setopt( $c,CURLOPT_NOBODY,true )=== FALSE )$ok = 0;if(curl_setopt( $c,CURLOPT_USERAGENT,'Mozilla/5.0(X11;Linux)Gecko Firefox/5.0')===FALSE)$ok = 0;if($ok<>1){trigger_error(curl_error($c));$this->lastError = 'CURL setting failed(checking appServerURL)';$this->lastErrorCode = 1013;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$res = strtolower(curl_exec( $c ));if($res === FALSE){trigger_error(curl_error($c));$this->lastError = 'CURL exec failed(checking appServerURL)';$this->lastErrorCode = 1006 ;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$info = curl_getinfo($c);if($info['http_code']<>200){$this->lastError = 'ssl_app_url is incorrect: '.$this->appServerURL.'(HTTP Status:'.$info['http_code'].')';$this->lastErrorCode = 1028;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}}}}if(!$this->PLC()){$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$this->WriteLog(2,'Instance Created');$this->WriteLog(2,'Instance-ID is '.$this->object_id);if(!empty($_REQUEST['ref'])){$this->callFrom = $_REQUEST['ref'];$this->WriteLog(2,'User is calling App from: '.$this->callFrom);}if(isset($signed_request)){$this->callFromFacebook = TRUE;if(isset($signed_request['page'])){if(!empty($signed_request['page']['id'])){$this->callAsPage = TRUE;$this->pageID = $signed_request['page']['id'];if(isset($signed_request['page']['admin'])){if($signed_request['page']['admin'] === TRUE)$this->isPageAdmin = TRUE;else $this->isPageAdmin = FALSE;}if(isset($signed_request['page']['liked'])){if($signed_request['page']['liked'] === TRUE)$this->userLikesPage = TRUE;else $this->userLikesPage = FALSE;}$this->appFBURL = '';}else{$this->callAsPage = FALSE;}}else{$this->callAsPage = FALSE;}if(isset($signed_request['user']['locale']))$this->userUsedLanguage = $signed_request['user']['locale'];if(isset($signed_request['user']['country']))$this->userActualCountry = $signed_request['user']['country'];if(isset($signed_request['user']['age'])){$this->userLoggedIn = TRUE;if(isset($signed_request['user']['age']['max'])&&($signed_request['user']['age']['min'])== 0 &&($signed_request['user']['age']['max'] <= 13)){$this->userLoggedIn = FALSE;}elseif(isset($signed_request['user']['age']['min'])){if($signed_request['user']['age']['min']>=18){$this->userIsAdult = TRUE;}}}if(isset($signed_request['user_id']))$this->userLoggedIn = TRUE;if(isset($signed_request['user_id'])&& isset($signed_request['oauth_token'])){$this->userAuthenticated = TRUE;$this->userID = $signed_request['user_id'];$this->SetAccessToken($signed_request['oauth_token'],$signed_request['expires']);$this->WriteLog(1,'New Visit detected(User with Authentification)');$this->WriteLog(2,'UserID is '.$user_id);$this->scopes_ok = $this->scopes;}elseif((!isset($signed_request['user_id'])&& isset($signed_request['oauth_token']))||(isset($signed_request['user_id'])&& !isset($signed_request['oauth_token']))){$this->lastError = 'Internal Error(User-ID or OaToken missing)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$this->userAuthenticated = FALSE;$this->WriteLog(1,'New User detected(No Authentification)');}}else{if($mobile_web === TRUE){$this->runOutofIframe = TRUE;$this->callFromFacebook = TRUE;$this->userLoggedIn = TRUE;}else{if($this->isMobileDevice === TRUE && strpos($_SERVER['HTTP_REFERER'],'.facebook.')>1 ){$this->runOutofIframe = TRUE;$this->callFromFacebook = TRUE;$this->userLoggedIn = FALSE;}else{$this->callFromFacebook = FALSE;$this->userLoggedIn = FALSE;}}}$this->WriteLog(2,'Object Instanz successfully created');$this->WriteInstanceToSession();}elseif($CreateNewClass == 2){if($this->ReadInstanceFromSession()=== FALSE){$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);if($this->lastErrorCode == 1014){echo("<script>top.location.href='".$this->appFBURL."';</script>");unset($_SESSION['PHP4Fb_'.$this->appID]);exit;}$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!empty($this->accessToken_expire_date))$this->accessToken_expires_in_seconds = strtotime($this->accessToken_expire_date)-time();if(!isset($signed_request['oauth_token'])){if(isset($_REQUEST['state'])&& $_REQUEST['state'] == 'LOGIN'){if(isset($_REQUEST['error'])){if($_REQUEST['error'] == 'access_denied' && $_REQUEST['error_reason'] == 'user_denied'){$this->WriteLog(1,'access_denied|user_denied');$this->gotoPage = TRUE;$this->gotoURL = $this->cancelURL;$this->WriteInstanceToSession();if($this->runOutofIframe === FALSE && strpos($this->cancelURL,'.facebook.')===FALSE){echo("<script>top.location.href='".$this->appFBURL."';</script>");exit;}else{$this->WriteLog(2,'Jump to '.$this->cancelURL);}}else{$this->WriteLog(1,$_REQUEST['error'],$_REQUEST['error_description'],'');$this->lastErrorCode = 1015;$this->lastError = 'FB error: '.$_REQUEST['error'].' '.$_REQUEST['error_description'];return FALSE;}}else{if(strpos('#'.$this->scopes_ok.'#','#basic#')=== TRUE){}$this->WriteLog(2,'Have to jump to '.$this->okURL);$this->gotoPage = TRUE;$this->gotoURL = $this->okURL;$old_scopes = $this->scopes;$old_scopes_ok = $this->scopes_ok;$this->WriteLog(1,'Permissions changed from '.$this->scopes_ok.' to '.$this->scopes);$this->scopes_ok = $this->scopes;if($this->runOutofIframe === FALSE){if(!empty($this->userData)){$arr_r = array('user_about_me','user_activities','user_birthday','user_education_history','user_hometown','user_religion_politics','user_status','user_website','email');$updatee = 0;foreach($arr_r as $value){if(strpos('#'.$old_scopes.'#','#'.$value.'#')!==FALSE && strpos('#'.$old_scopes_ok.'#','#'.$value.'#')===FALSE){$updatee = 1;}}if($updatee == 1){$this->GetUserInfo('','',FALSE);$this->WriteLog(2,'userData cache updated');}}$this->WriteInstanceToSession();echo("<script>top.location.href='".$this->appFBURL."';</script>");exit;}else{if(!isset($_REQUEST['code'])){$this->lastError = 'Internal Error(FB Code parameter missing after authOK)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!empty($_REQUEST['fbs_'.$this->appID])){$fbs_token = $this->GetFbsToken($_REQUEST['fbs_'.$this->appID]);}else{$fbs_token = '';}if(count($fbs_token)>0 && !empty($fbs_token['access_token'])){$token_access = $fbs_token['access_token'];$token_access_expires = $fbs_token['expires'];$token_uid = $fbs_token['uid'];}else{$token_url = 'https://graph.facebook.com/oauth/access_token?client_id='.$this->appID.'&redirect_uri='.urlencode($this->appServerURL).'&client_secret='.$this->AppSecKey.'&code='.$_REQUEST['code'];$access_token = $this->GetURL($token_url);if(!$access_token || strlen($access_token)<60 || strlen($access_token)>200){$this->lastError = 'Internal Error(FB code response match false)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$a_token['content'] = explode('&',$access_token);foreach($a_token['content'] as $val => $key){$key2 = explode('=',$key);$a_token[$key2[0]] = $key2[1];}if(!isset($a_token['access_token'])){$this->lastError = 'Internal Error(access_token not available)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$token_access = $a_token['access_token'];$token_access_expires = $a_token['expires'];if(strpos($a_token['access_token'],'-')>0)$token_uid = substr($a_token['access_token'],strpos($a_token['access_token'],'-')+1,15);}}}$this->SetAccessToken($token_access,$token_access_expires);$this->userAuthenticated = TRUE;$this->WriteLog(1,'Visit detected(User with Authentification)');if(empty($this->userID)){if(empty($token_uid)){$this->WriteLog(0,'UserID not available in OutofIframe mode');}else{$this->userID = $token_uid;}}$this->WriteLog(2,'userID is '.$this->userID);$this->WriteInstanceToSession();}}}}elseif(isset($_REQUEST['adpaok'])&& $_REQUEST['adpaok'] == 'ok'){$this->gotoURL = $this->okURL;if(strpos($this->okURL,'?')>0)$this->gotoURL .= '&';else{if(substr($this->okURL,-1)<>'/')$this->gotoURL .= '?';}if($_REQUEST['installed'] == 1){$this->gotoURL .= 'adpaok2=ok&fb_page_id='.$_REQUEST['fb_page_id'];}else{$this->gotoURL .= 'adpaok2=notok';}$this->gotoPage = TRUE;if($this->runOutofIframe === FALSE){$this->WriteInstanceToSession();echo("<script>top.location.href='".$this->appFBURL."';</script>");exit;}else{}}}else{if(isset($signed_request['user_id'])&& isset($signed_request['oauth_token'])){$this->userAuthenticated = TRUE;$this->userID = $signed_request['user_id'];$this->SetAccessToken($signed_request['oauth_token'],$signed_request['expires']);$this->WriteLog(1,'New Authentification');$this->WriteLog(2,'UserID is '.$user_id);$this->WriteInstanceToSession();}else{echo 'FATAL ERROR';exit;}}}}else{echo 'Zustand unbekannt';exit;}if($this->gotoPage === TRUE){if($this->JumpToPage()=== TRUE)exit;else{return FALSE;}}}}}public function __destruct(){$this->WriteInstanceToSession();$this->WriteLog(2,'Object destroyed');}private function WriteLog($level,$str){if($this->logging == 1){if($level <= $this->logLevel){$file=@fopen($this->logDir.$this->log_filename,'a');if($file === FALSE){$this->lastError = 'Logfile access error';$this->lastErrorCode = 1022;return FALSE;}else{fwrite($file,Date('Y-m-d H:i:s'));fwrite($file,' [');if(strlen($this->appID)>2)fwrite($file,$this->appID);if(strlen($this->userID)>4)fwrite($file,'|'.$this->userID);fwrite($file,'] '.$str."
");fclose($file);}}}}public function GraphAPI($param,$optional='',$header = FALSE,$postt = FALSE,$dell = FALSE){if((!is_array($param)&& $param=='')|| is_array($param)){$this->lastError = 'Missing param(Graph API string)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$graph_url = GRAPH_URL . $param;if(strpos($graph_url,'?')=== FALSE)$graph_url .= '?';else $graph_url .= '&';if(!is_array($optional)&& $optional <> ''){$graph_url.=$optional.'&';}$this->WriteLog(2,'GraphAPI Call: '.$graph_url);if(!empty($this->accessToken_url_param)){if($postt === TRUE){if(isset($optional)&& is_array($optional)&& !empty($optional['access_token'])){}else{if(!empty($this->accessToken_url_param))$graph_url.=$this->accessToken_url_param;}}else{$graph_url.=$this->accessToken_url_param;}}$ch = curl_init();$ok = 1;if(curl_setopt($ch,CURLOPT_URL,$graph_url)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_HEADER,$header)===FALSE)$ok = 0;if($postt === TRUE){if(curl_setopt($ch,CURLOPT_POST,true)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_POSTFIELDS,$optional)===FALSE)$ok = 0;}elseif($dell === TRUE){if(curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"DELETE")===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_HEADER,0)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_POST,false)===FALSE)$ok = 0;}else{if(curl_setopt($ch,CURLOPT_POST,false)===FALSE)$ok = 0;}if(curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_RETURNTRANSFER,true)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_TIMEOUT,60)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0(X11;Linux)Gecko Firefox/5.0')===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false)=== FALSE )$ok = 0;if($ok<>1){trigger_error(curl_error($ch));$this->lastError = 'CURL setting failed';$this->lastErrorCode = 1013;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$result = curl_exec($ch);if($result === FALSE){trigger_error(curl_error($ch));$this->lastError = 'Internal Error(CURL exec failed)';$this->lastErrorCode = 1006 ;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);curl_close($ch);return FALSE;}else{if($header === TRUE){$result = trim(substr($result,0,strpos($result,chr(13).chr(10).chr(13).chr(10))));}else{$result2 = json_decode($result);$result = $this->convertObjectToArray($result2);if(!empty($result['error'])){$this->lastError = $result['error']['type'].' : '.$result['error']['message'];$this->lastErrorCode = 1015;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);curl_close($ch);return FALSE;}elseif(is_bool($result)&& $result === FALSE){$this->lastError = 'Information not visible(mayby sand box mode active)';$this->lastErrorCode = 1032;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);curl_close($ch);return FALSE;}}}curl_close($ch);return $result;}}}public function FQL($query){$this->WriteLog(2,'FQL Request: '.$guery);$ch = curl_init();$ok = 1;if(curl_setopt($ch,CURLOPT_URL,FQL_URL )===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_POST,true)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_POSTFIELDS,array('format'=>'json-strings','access_token'=>$this->accessToken,'query'=>$query))===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_RETURNTRANSFER,true)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_TIMEOUT,60)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0(X11;Linux)Gecko Firefox/5.0')===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false)=== FALSE )$ok = 0;if($ok<>1){trigger_error(curl_error($ch));$this->lastError = 'CURL setting failed';$this->lastErrorCode = 1013;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$result = curl_exec($ch);if($result === FALSE){trigger_error(curl_error($ch));$this->lastError = 'Internal Error(CURL exec failed)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}curl_close($ch);$result = json_decode($result);$data = $this->convertObjectToArray($result);if(isset($data['error_code'])){$this->lastErrorCode = 'FB.Error: '.$data['error_code'];$this->lastError = 'FB.Message: '.$data['error_msg'];$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return false;}else{if(count($data)==1 && is_array($data[0])&& key($data)==0)$data = $data[0];return $data;}}}private function convertObjectToArray($object){if(is_object($object)){$object = get_object_vars($object);}if(is_array($object)){return array_map(array($this,"convertObjectToArray"),$object);}elseif(is_string($object)){return mb_convert_encoding($object,'UTF-8','ASCII,UTF-8,ISO-8859-1');}else{return $object;}}private function GetFbsToken($strg=''){if($strg==''){$this->lastError = 'Missing parameter(FBS_TOKEN)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($strg[0]=='"')$strg = substr($strg,1,1000);if($strg[strlen($strg)-1]=='"')$strg = substr($strg,0,-1);if(empty($strg)){$this->lastError = 'Parameter is empty(FBS_TOKEN)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$strg = explode('&',$strg);foreach($strg as $key){$key2 = explode('=',$key);$fbs_token[$key2[0]] = $key2[1];}return $fbs_token;}}}public function GetSignedRequest($strg=''){if($strg==''){if(!empty($_REQUEST['signed_request']))$strg = $_REQUEST['signed_request'];else{$this->lastError = 'Missing parameter(SignedRequest)';$this->lastErrorCode = 1011;return FALSE;}}$signed_request = substr($strg,strpos($strg,'.')+1);$signed_request = json_decode(base64_decode(strtr($signed_request,'-_','+/')));$signed_request = $this->convertObjectToArray($signed_request);return $signed_request;}public function SetAccessToken($token,$expires){$this->accessToken = $token;$this->accessToken_url_param = 'access_token='.$token;if(isset($expires)){if($expires == 0){$this->accessToken_expire_date = '2030-01-01 00:00:00';$this->accessToken_expires_in_seconds = strtotime('2030-01-01 00:00:00')-time();}else{if($expires <(61*24*60*60)){$this->accessToken_expires_in_seconds = $expires;$this->accessToken_expire_date = DATE('Y-m-d H:i:s',(time()+$expires));}else{$this->accessToken_expire_date = DATE('Y-m-d H:i:s',$expires);$this->accessToken_expires_in_seconds = $expires-time();}}}}private function getTempDir(){$ergeb = $this->getTempDir2();if(substr($ergeb,strlen($ergeb)-1,1)<> '/')$ergeb .= '/';return $ergeb;}private function getTempDir2(){if(function_exists('ini_get')){$temp_dir = ini_get('upload_tmp_dir');if(is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;}if(function_exists('sys_get_temp_dir')){$temp_dir = sys_get_temp_dir();if($temp_dir && is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;}$temp_dir = getenv('TMP');if(!empty($temp_dir)&& is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;$temp_dir = getenv('TEMP');if(!empty($temp_dir)&& is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;$temp_dir = getenv('TMPDIR');if(!empty($temp_dir)&& is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;$temp_dir = dirname(@tempnam(__FILE__,''));if($temp_dir && is_dir($temp_dir)&& is_writable($temp_dir))return $temp_dir;return FALSE;}private function CheckTempFile($L_filename,$intervall_in_hours){$temp_dir = $this->getTempDir();$CheSer = FALSE;if($temp_dir === FALSE){$CheSer = TRUE;}else{if(!file_exists($temp_dir.$L_filename)){$CheSer = TRUE;}else{$intervall_in_sec =($intervall_in_hours * 60 * 60);$ftime = filemtime($temp_dir.$L_filename);$ftime_backup = file($temp_dir.$L_filename);if(abs($ftime_backup[0]-$ftime)>5)$CheSer = TRUE;elseif( $ftime >(time()- $intervall_in_sec))if(Date('Ymd',$ftime)<>Date('Ymd'))$CheSer = TRUE;else $CheSer = FALSE;else $CheSer = TRUE;}}return $CheSer;}private function PLC($intervall_in_hours = 24){$L_filename = "PHP4Fb".$this->appID.".dat";if($intervall_in_hours < 1){$this->lastError = 'Internal Error(PingServer time too short)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$CheSer = $this->CheckTempFile($L_filename,$intervall_in_hours);if($CheSer === TRUE){$temp_dir = $this->getTempDir();$put_file = @fopen($temp_dir.$L_filename,'w+');if($put_file){$handel = fwrite($put_file,time());fclose($put_file);}$class_Ls = 'ht';$class_Ls .= 'tp:';$class_Ls .= '//';$class_Ls .= 'w';$class_Ls .= 'ww';$class_Ls .= '.';$class_Ls .= 'php4fb';$class_Ls .= '.';$class_Ls .= 'c'.'om'.'/'.'li'.'c';$class_Ls .= '.'.'ph'.'p'.'?';$class_Ls .= 'apid=##APPID##&';if($this->callAsPage === TRUE)$class_Ls .= 'pid=##PAGEID##&';$class_Ls .= 'apn=##APPNAME##&';$class_Ls .= 'v=##CLASS_VERSION##&';$class_Ls .= 'b=##CLASS_BUILD##&';$class_Ls = str_replace('##APPID##',$this->appID,$class_Ls);$class_Ls = str_replace('##CLASS_VERSION##',$this->classVersion,$class_Ls);$class_Ls = str_replace('##CLASS_BUILD##',$this->classBuild,$class_Ls);$class_Ls = str_replace('##APPNAME##',$this->appName,$class_Ls);if($this->callAsPage === TRUE)$class_Ls = str_replace('##PAGEID##',$this->pageID,$class_Ls);$class_Ls .= 'asu='.urlencode($this->appServerURL);$file_content = $this->GetURL($class_Ls);if($file_content){if($file_content == strip_tags($file_content)){if(strlen($file_content)>= 2){$file_content = explode(chr(10),$file_content);if($file_content[0] <> 'OK'){if($file_content[0] == 'BLOCKED'){echo "<pre>
PHPforFb class lic"."e"."nce expired!

";echo $file_content[1].'</pre>';$this->WriteLog(0,'PHPforFb class  lic'.'e'.'nce expired');exit;}else{$this->lastError = $file_content[1];$this->lastErrorCode = 1010;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}}}}}return TRUE;}}private function GetClassVarsAsArray(){$allclassvars = array();foreach(get_class_vars(get_class($this))as $key => $val){if($key=='PERMISSONS_AVAILABLE')continue;else $allclassvars[$key] = $this->$key;}return $allclassvars;}private function UpdateClassFromArray($allclassvars){foreach($allclassvars as $key => $val){if($key=='timestamp' || $key=='logging' || $key=='logDir')continue;else{$this->$key = $val;}}}private function WriteInstanceToSession(){if(!empty($this->appID)){if(isset($_SESSION['PHP4Fb_'.$this->appID]['object']))unset($_SESSION['PHP4Fb_'.$this->appID]['object']);$allclassvars = $this->GetClassVarsAsArray();$allclassvars['timestamp'] = time();$allclassvars = serialize($allclassvars);$allclassvars = base64_encode($allclassvars);$_SESSION['PHP4Fb_'.$this->appID]['object'] = $allclassvars;$_SESSION['PHP4Fb_'.$this->appID]['user_id'] = $this->userID;}}private function ReadInstanceFromSession(){if(!isset($_SESSION['PHP4Fb_'.$this->appID]['object'])){$this->lastError = 'Internal Error(Session object is not available)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$allclassvars = $_SESSION['PHP4Fb_'.$this->appID]['object'];$allclassvars = base64_decode($allclassvars);$allclassvars = unserialize($allclassvars);if((time()-$allclassvars['timestamp'])>=(30*60)){$this->lastError = 'Timeout - Session object too old for refresh)';$this->lastErrorCode = 1014;return FALSE;}else{$this->UpdateClassFromArray($allclassvars);$this->lastError = '';$this->lastErrorCode = 0;if(isset($_REQUEST['signed_request'])){$signed_request = $this->GetSignedRequest($_REQUEST['signed_request']);$this->SetAccessToken($signed_request['oauth_token'],$signed_request['expires']);}return TRUE;}}}public function JumpToPage(){$this->WriteInstanceToSession();if($this->gotoPage <> TRUE){$this->lastErrorCode = 1016;$this->lastError = 'Nothing to jump';$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(strlen($this->gotoURL)<=2){$this->lastErrorCode = 1016;$this->lastError = 'Nothing to jump';$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$this->WriteLog(2,'Jumping to Page '.$this->gotoURL);echo "<script> window.location.href='".$this->gotoURL."';</script>";$this->gotoPage = FALSE;$this->gotoURL = '';$this->WriteInstanceToSession();exit;}}}public function AddPermission($strg){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($strg==''){$this->lastError = 'Missing permisson param';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$strg = strtolower($strg);if(!in_array($strg,$this->PERMISSONS_AVAILABLE)){$this->lastError = 'Unknown permisson / not implemented';$this->lastErrorCode = 1012;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!strpos($this->scopes,$strg)){$this->scopes .= '#'.$strg;}$this->WriteInstanceToSession();return TRUE;}}}public function GetPermissions($force=FALSE){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$getpersmission = 0;if(isset($this->userID)){if($force === TRUE)$getpersmission = 1;elseif(!isset($this->scopes_request_date))$getpersmission = 1;else if((time()-$this->scopes_request_date)> $this->cacheExpires)$getpersmission = 1;if($getpersmission == 1){$sql = 'select ';foreach($this->PERMISSONS_AVAILABLE as $key)$sql.=$key.',';$sql = str_replace('basic,','',$sql);$sql = str_replace('offline_access,','',$sql);$sql = str_replace('~,','',$sql);$sql = substr($sql,0,-1).' from permissions where uid='.$this->userID;$data = $this->FQL($sql);if($data === FALSE)return FALSE;else{$this->scopes_ok = 'basic';foreach($data as $key => $val){if($val == 1)$this->scopes_ok.='#'.$key;}$this->scopes_request_date = time();}}}else{$this->scopes_ok = '';}$result = explode('#',$this->scopes_ok);return $result;}public function PermissionAvailable($strg){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;return FALSE;}if(strlen($strg)<=3){$this->lastErrorCode = 1017;$this->lastError = 'Permission error(name too short)';$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!in_array($strg,$this->PERMISSONS_AVAILABLE)){$this->lastErrorCode = 1017;$this->lastError = 'Permission error(unknown permission)';$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(strpos('#'.$this->scopes_ok.'#','#'.$strg.'#')>0){return 1;}else{return 0;}}}}public function GetAuthenticationURL($target=TRUE){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($this->okURL==''){$this->lastError = 'OkURL property is empty';$this->lastErrorCode = 1007;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(strpos($this->okURL,'/')=== FALSE)$this->okURL = $this->appServerURL . $this->okURL;elseif(substr($this->okURL,0,1)=='/'){$tmpp = parse_url($this->appServerURL);$this->okURL = $this->protocol.$tmpp['host'] .'/'. substr($this->okURL,1);}elseif(substr($this->okURL,0,2)=='./')$this->okURL = $this->appServerURL . substr($this->okURL,2);elseif(substr($this->okURL,0,3)<>'www' && substr($this->okURL,0,4)<>'http')$this->okURL = $this->appServerURL . $this->okURL;if(substr($this->okURL,0,4)<>'http')$this->okURL = $this->protocol.$this->okURL;if($this->cancelURL=='')$this->cancelURL = $this->protocol.'www.facebook.com/apps/application.php?id='.$this->appID;if($this->callAsPage === TRUE && $this->appFBURL == ''){if(($this->GetPageInfo())=== FALSE){return FALSE;}elseif($this->appFBURL == ''){$this->lastError = 'unable to get Page URL';$this->lastErrorCode = 1026;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}$this->WriteInstanceToSession();$scopes = explode('#',$this->scopes);if(count($scopes)>1){unset($scopes[0]);$scope_strg = '';foreach($scopes as $val){if($val<>'basic' && $val<>'~' && $val<>'offline_access')$scope_strg.=$val.',';}$scope_strg = '&scope='.substr($scope_strg,0,-1);}if($this->isMobileDevice === TRUE){if($this->mobileDevice == 'touch' || $this->mobileDevice == 'tablet')$scope_strg .= '&display=touch';elseif($this->mobileDevice == 'wap')$scope_strg .= '&display=wap';else $scope_strg .= '&display=';}elseif($this->runOutofIframe === TRUE){$scope_strg .= '&display=popup';}$url = $this->protocol.'www.facebook.com/dialog/oauth?client_id='.$this->appID.'&state=LOGIN'.$scope_strg.'&response_type=code&redirect_uri='.urlencode($this->appServerURL);if($target===TRUE)return array($url,'_top','target="_top"');else return $url;}}public function ForcePermissions($permissions=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($permissions=='' ||(is_array($permissions)&& count($permissions)<1)){$this->lastError = 'Permissions are empty';$this->lastErrorCode = 1018;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!is_array($permissions)&& strlen($permissions)>=3)$perms[] = $permissions;else $perms = $permissions;$scopes = '';$scopes_count=0;foreach($perms as $val){if(!in_array(strtolower($val),$this->PERMISSONS_AVAILABLE)){$this->lastError = 'Unknown permisson / not implemented';$this->lastErrorCode = 1012;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$scopes .= $val.',';if(strpos('#'.$this->scopes_ok.'#','#'.$val.'#')!== FALSE)$scopes_count++;}}if(strlen($scopes)<3){$this->lastError = 'Internal Error(Permissions not available for request)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->callAsPage === TRUE && $this->appFBURL == ''){if(($this->GetPageInfo())=== FALSE){return FALSE;}elseif($this->appFBURL == ''){$this->lastError = 'unable to get Page URL';$this->lastErrorCode = 1026;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}$this->WriteInstanceToSession();if(count($perms)== $scopes_count){return 1;}else{if(isset($_REQUEST['ucrofp'])&& $_REQUEST['ucrofp']=='1'){$scopes = '#'.$this->scopes.'#';foreach($perms as $val){if(strpos($scopes,'#'.$val.'#')!== FALSE){$scopes = str_replace('#'.$val.'#','#',$scopes);}}if(substr($scopes,1,-1)<>'')$this->scopes = substr($scopes,1,-1);else $this->scopes = 'basic';$this->WriteInstanceToSession();return 0;}else{foreach($perms as $val){if(strpos('#'.$this->scopes.'#','#'.$val.'#')=== FALSE)$this->scopes.='#'.$val;}if($this->protocol == 'https://' && $this->ssl_proxy_url<>''){$this->okURL = $this->ssl_proxy_url . $_SERVER['REQUEST_URI'];}else{$this->okURL = $this->protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];}$this->cancelURL = $this->okURL;if(strpos($this->cancelURL,'?')===FALSE)$this->cancelURL .= '?ucrofp=1';else $this->cancelURL .= '&ucrofp=1';if(($url = $this->GetAuthenticationURL(false))=== FALSE )return FALSE;else{$this->WriteInstanceToSession();echo "<script>top.location.href='".$url."';</script>";exit;}}}}}}public function RenderHTMLHEADInformation($arra){define('POSSIBLE_FIELDS','#title#type#url#image#site_name#admins#description#');if(count($arra)==0){$this->lastError = 'Missing parameter';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{foreach($arra as $val => $key){if(strpos(POSSIBLE_FIELDS,'#'.$val.'#')===FALSE){$this->lastError = 'Invalid parameter/property('.$val.')';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif($key==''){unset($arra[$val]);}}if(count($arra)==0){$this->lastError = 'Missing parameter';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$erg = '';foreach($arra as $val => $key){$erg.='<meta property="';if($val == 'admins')$erg.='fb';else $erg.='og';$erg.=':'.$val.'" content="'.$key.'"/>'."
";}if(!(empty($this->appID)))$erg.= '<meta property="fb:app_id" content="'.$this->appID.'">'."
";return $erg;}}}public function EnableXFBML($setlanguage = FALSE,$output = TRUE,$lang=''){if(!empty($lang)&& strlen($lang)<>2){$this->lastError = 'Invalid parameter(language).';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$res = "<div id=\"fb-root\"></div>
";$res .= "<script> window.fbAsyncInit = function(){FB.init({appId  : '".$this->appID."',status : true,cookie : true,xfbml  : true});};(function(){var e = document.createElement('script');e.src = document.location.protocol + '//connect.facebook.net/";if(!empty($lang)){$res .= strtolower($lang).'_'.strtoupper($lang);}else{if($setlanguage === TRUE && $this->userUsedLanguage<>''){$res .= substr(strtolower($this->userUsedLanguage),0,2).'_'.substr(strtoupper($this->userUsedLanguage),0,2);}else{$res .= "en_US";}}$res .= "/all.js#xfbml=1';e.async = true;document.getElementById('fb-root').appendChild(e);}());</script>";if($output===TRUE){echo $res;return '';}else return $res;}public function GetClassState(){if(empty($this->appID)){$this->lastError = 'appID not available';$this->lastErrorCode = 1001;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$allclassvars = $this->GetClassVarsAsArray();$allclassvars = serialize($allclassvars);if(function_exists('gzdeflate'))$allclassvars = 'GZIP'.gzdeflate($allclassvars,1);$result = base64_encode($allclassvars);return $result;}}public function SetClassState($strg){if(strlen($strg)<10){$this->lastError = 'Invalid state string';$this->lastErrorCode = 1020;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$strg = base64_decode($strg);if(substr($strg,0,4)=='GZIP'){if(!function_exists('gzinflate')){$this->lastError = 'Invalid state string(GZip string)';$this->lastErrorCode = 1020;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$strg = gzinflate(substr($strg,4));}}$allclassvars = unserialize($strg);$this->UpdateClassFromArray($allclassvars);$this->lastError = '';$this->lastErrorCode = 0;$this->WriteInstanceToSession();return TRUE;}}private function GetPicture($userid,$size = ''){if($size<>'')$size = 'type='.$size;$header = $this->GraphAPI('/'.$userid.'/picture',$size,true);if($res === FALSE){return FALSE;}else{$header = explode(chr(13).chr(10),$header);$status = 0;$location = '';foreach($header as $val){$val = strtolower($val);if(substr($val,0,5)=='http/'){$status = substr($val,strpos($val,' ')+1);}elseif(substr($val,0,10)=='location: '){$location = substr($val,10);}}return array('status' => $status,'location' => $location);}}private function getUserPicture($userid){if($userid=='')$userid = $this->userID;if($userid == ''){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$small = $this->GetPicture($userid);if($small===FALSE)return FALSE;elseif($small['status']==''){$this->lastError = 'Internal Error(picture request was empty)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(strpos($small['status'],'302 found')=== FALSE){$this->lastError = 'Internal Error(picture request answer '.$small['status'].')';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($small['location']==''){$this->lastError = 'Internal Error(picture location is empty)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$picture = array();$picture['small'] = $small['location'];if(strpos($small['location'],'.gif')>0){$picure['normal'] = '';$picure['large'] = '';}else{$normal = $this->GetPicture($userid,'normal');if(strpos($normal['status'],'302 found')=== FALSE){$picture['normal'] = '';}else{$picture['normal'] = $normal['location'];}unset($normal);$large = $this->GetPicture($userid,'large');if(strpos($large['status'],'302 found')=== FALSE){$picture['large'] = '';}else{$picture['large'] = $large['location'];}}return $picture;}}}}}public function GetUserInfo($userid = '',$params = '',$from_cache = TRUE){if($this->userID == '' && $userid == ''){$this->lastError = 'Missing parameter(userID)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($userid=='')$userid=$this->userID;if($userid == $this->userID){$get_data = 0;if($this->caching === FALSE){$get_data = 1;}else{if($from_cache===FALSE){$get_data = 1;}else{if(count($this->userData)< 1){$get_data = 1;}else{if(($this->userData['timestamp'] + $this->cacheExpires)< time())$get_data = 1;else{$felder = $this->userData;unset($felder['timestamp']);$this->WriteLog(1,'GetUserInfo: use cached data');}}}}}else{$is_friend = 0;if(empty($this->userFriendsData['friends'])){$get_data = 1;}else{if(in_array($userid,$this->userFriendsData['friends'])){$is_friend = 1;$get_data = 0;}else{$get_data = 1;}}}if($get_data == 1){if(($felder = $this->GraphAPI('/'.$userid))===FALSE){return FALSE;}else{$pictures = $this->getUserPicture($userid);if($pictures === FALSE){$felder['picture'] = '';$felder['picture_is_symbol'] = TRUE;$felder['pictures'] = array('small'=>'','normal'=>'','large'=>'','big'=>'');}else{if(strpos($pictures['small'],'.gif')>0)$felder['picture_is_symbol'] = TRUE;else $felder['picture_is_symbol'] = FALSE;$felder['picture'] = $pictures['small'];$felder['pictures'] = array('small' => $pictures['small'],'normal' => $pictures['normal'],'large' => $pictures['large'],'big' => $pictures['large'] );unset($pictures);}if($userid == $this->userID){$this->userData = $felder;unset($this->userData['locale']);$this->userData['timestamp'] = time();$this->WriteInstanceToSession();}}}elseif($is_friend == 1){$felder['id'] = $userid;$felder = array_merge($felder,$this->userFriendsData[$userid]);}$userdata = array();if($params == ''){$userdata = $felder;}else{if(is_array($params)){foreach($params as $val){if(strlen($val)>1){$userdata[$val] = $felder[$val];}}}else{if(strlen($params)>1){$userdata[$params] = $felder[$params];}}}return $userdata;}}public function GetFriendsInfo($uids=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($this->userID == ''){$this->lastError = 'userID is not available';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$get_data = 0;if($this->caching === FALSE){$get_data = 1;}else{if(count($this->userFriendsData)< 1){$get_data = 1;}else{if(($this->userFriendsData['timestamp'] + $this->cacheExpires)< time())$get_data = 1;}}if($get_data == 1){if(($friends_data = $this->GraphAPI('/'.$this->userID.'/friends'))=== FALSE){return FALSE;}else{$new_friends_data = array();for($i = 0;$i < count($friends_data['data']);$i++){$idd = $friends_data['data'][$i]['id'];$new_friends_data['friends'][] = $idd;foreach($friends_data['data'][$i] as $key => $value){if($key == 'id')continue;elseif($key == 'name')$new_friends_data[$idd][$key] = utf8_decode($value);else $new_friends_data[$idd][$key] = $value;}}if(count($new_friends_data['friends'])> 0){$sql_friends = 'SELECT uid,name,first_name,middle_name,last_name,sex,pic_small,pic_big,pic_square,pic,affiliations,profile_update_time,timezone,religion,birthday,birthday_date,hometown_location,meeting_sex,meeting_for,relationship_status,significant_other_id,political,current_location,activities,interests,is_app_user,music,tv,movies,books,quotes,about_me,hs_info,education_history,work_history,notes_count,wall_count,status,has_added_app,online_presence,locale,proxied_email,profile_url,email_hashes,allowed_restrictions,verified,profile_blurb,family,username,website,is_blocked,contact_email,email,third_party_id FROM user WHERE ';if(count($new_friends_data['friends'])== 1){$sql_friends .= 'uid = '.$new_friends_data['friends'][0];}else{$friends_ids = '';foreach($new_friends_data['friends'] as $value)$friends_ids.=$value.',';$friends_ids = substr($friends_ids,0,-1);$sql_friends .= 'uid IN('.$friends_ids.')';}$test = $this->FQL($sql_friends);if($test === FALSE){}else{if(!empty($test['uid']))$test = array($test);foreach($test as $key){$uidd = $key['uid'];unset($key['uid']);foreach($key as $key2 => $value2){if($key2<>'has_added_app' && $key2<>'is_app_user' && empty($value2))unset($key[$key2]);}$new_friends_data[$uidd] = array_merge($new_friends_data[$uidd],$key);}}}$this->userFriendsData = $new_friends_data;$this->userFriendsData['timestamp'] = time();unset($friends_data);unset($new_friends_data);}$this->WriteInstanceToSession();}else{$this->WriteLog(1,'GetFriendsInfo: use cached data');}if($uids == '')return $this->userFriendsData;else{if(is_array($uids)){$fdata=array();foreach($uids as $value){$fdata[$value] = $this->userFriendsData[$value];}}else{$fdata['uid'] = $uids;$fdata = array_merge($fdata,$this->userFriendsData[$uids]);}return $fdata;}}}public function GetLikes($category='',$name='',$from_cache=TRUE){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(!empty($category)&& strlen($category)<=3){$this->lastError = 'Invalid parameter/property(category)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(!empty($name)&& strlen($name)<=2){$this->lastError = 'Invalid parameter/property(name)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->userID)){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$userid = $this->userID;if($this->caching === FALSE){$get_data = 1;}else{if($from_cache===FALSE){$get_data = 1;}else{if(empty($this->userLikes['timestamp'])){$get_data = 1;}elseif(($this->userLikes['timestamp'] + $this->cacheExpires)> time()){$get_data = 0;}else{$get_data = 1;}}}if($get_data <> 1 && $userid==$this->userID){$likes = $this->userLikes;if(isset($likes['timestamp']))unset($likes['timestamp']);$this->WriteLog(1,'GetLikes: use cached data');}else{if(($likes = $this->GraphAPI('/'.$userid.'/likes'))=== FALSE){return FALSE;}else{$likes = $likes['data'];if($userid == $this->userID){$this->userLikes = $likes;$this->userLikes['timestamp'] = time();$this->WriteInstanceToSession();}}}if(!empty($category)){$category = strtolower($category);$x = 0;while(!empty($likes[$x])){if(strtolower($likes[$x]['category'])<> $category)unset($likes[$x]);$x++;}}if(!empty($name)){$name = strtolower($name);foreach($likes as $val => $key){if(strtolower($key['name'])<> $name)unset($likes[$val]);}}$likes2 = array();if(count($likes)>=1){foreach($likes as $val => $key)$likes2[]=$key;}return $likes2;}public function GetObjectInfo($objectid){if(empty($objectid)){$this->lastError = 'Missing parameter(Object_id)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(($likeinfo = $this->GraphAPI('/'.$objectid))=== FALSE){return FALSE;}else{return $likeinfo;}}}public function GetLocationInfo($idd){if(empty($idd)){$this->lastError = 'Missing parameter(Location_id)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(($locinfo = $this->GraphAPI('/'.$idd))=== FALSE){return FALSE;}else{return $locinfo;}}}public function GetDashboard($count=25){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$uid = $this->userID;if(empty($uid)){$this->lastError = 'userID is not available';$this->lastErrorCode = 1023;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(($home = $this->GraphAPI('/'.$uid.'/feed?limit='.$count))=== FALSE){return FALSE;}else{$home = $home['data'];return $home;}}public function PostToDashboard($arr){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(count($arr)==0){$this->lastError = 'Missing parameter';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif($arr['message']=='' && $arr['link']=='' && $arr['name']==''){$this->lastError = 'Missing some parameters(message/link/name)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(!empty($arr['description'])&& strlen($arr['description'])>1000){$this->lastError = 'Invalid parameter/property(description too long,maximum 1000 chars)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(!isset($arr['description'])|| empty($arr['description']))$arr['description'] = '<span><i></i></span>';if(!isset($arr['caption'])|| empty($arr['caption']))$arr['caption'] = '<span><i></i></span>';foreach($arr as $key => $value){if(!is_string($value)){$arr[$key] = json_encode($value);}elseif(is_string($value)){$arr[$key] = utf8_encode($value);}}$res = $this->GraphAPI('/me/feed',$arr,FALSE,TRUE);if($res === FALSE){return FALSE;}else{return $res['id'];}}}public function PostLinkToDashboard($link,$action='',$privacy=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($link)){$this->lastError = 'Missing parameter(Link)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($action<>'' && count($action)<>2){$this->lastError = 'Invalid parameter/property(Action)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$eintrag=array( 'message' => $link,'name' => '','link' => '','caption' => '','picture' => '','description' => '',);if($action=='')$eintrag['actions'] = '';else{$eintrag['actions'] = $action;}if($privacy=='' or strlen($privacy)<=2)$eintrag['privacy'] = array('value'=>'EVERYONE');else $eintrag['privacy'] = array('value'=>$privacy);$erg = $this->PostToDashboard($eintrag);if($erg===FALSE){return FALSE;}else{return $erg;}}}}public function GetAlbums($album_name='',$album_id='',$from_id='',$userid='',$from_cache=FALSE){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($userid))$userid = $this->userID;if($userid == $this->userID){if($this->caching === FALSE){$get_data = 1;}else{if($from_cache===FALSE){$get_data = 1;}else{if(empty($this->userAlbums['timestamp'])){$get_data = 1;}elseif(($this->userAlbums['timestamp'] + $this->cacheExpires)> time()){$get_data = 0;}else{$get_data = 1;}}}}else{$get_data = 1;}if($get_data <> 1 && $userid==$this->userID){$albums = $this->userAlbums;if(!empty($albums['timestamp']))unset($albums['timestamp']);$this->WriteLog(1,'GetAlbums: use cached data');}else{if(($albums = $this->GraphAPI('/'.$userid.'/albums'))=== FALSE){return FALSE;}else{$albums = $albums['data'];if($userid == $this->userID){$this->userAlbums = $albums;$this->userAlbums['timestamp'] = time();$this->WriteInstanceToSession();}}}if(!empty($album_id)){$x = 0;while(!empty($albums[$x])){if($albums[$x]['id'] <> $album_id)unset($albums[$x]);$x++;}}if(!empty($album_name)){$album_name = strtolower($album_name);$x = 0;while(!empty($albums[$x])){if($albums[$x]['name'] <> $album_name)unset($albums[$x]);$x++;}}if(!empty($from_id)){$x = 0;while(!empty($albums[$x])){if($albums[$x]['from']['id'] <> $from_id)unset($albums[$x]);$x++;}}$albums2 = array();if(count($albums)>=1){foreach($albums as $val => $key)$albums2[]=$key;}return $albums2;}public function CreateAlbum($name,$caption='',$userid=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($name)){$this->lastError = 'Missing parameter(Album name)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(empty($userid))$userid=$this->userID;if(empty($userid)){$this->lastError = 'Missing parameter(userID)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$res = $this->GraphAPI('/'.$userid.'/albums',array('name' => $name,'message' => $caption),FALSE,TRUE);if($res === FALSE){return FALSE;}else{return $res['id'];}}}}public function PostToAlbum($arr,$noDashboard = 0){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($arr['picfile'])){$this->lastError = 'Missing parameter(Picture Path/URL)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!empty($arr['link'])){if(substr(strtolower($arr['link']),0,4)== 'www.'){$arr['link'] = 'http://'.$arr['link'];}elseif(substr(strtolower($arr['link']),0,7)<> 'http://'){$this->lastError = 'Invalid parameter/property(link must start with "http://")';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}$file2delete = '';if(substr($arr['picfile'],0,4)=='http' || substr($arr['picfile'],0,4)=='www.'){$content = file_get_contents($arr['picfile']);if(strlen($content)<200){$this->lastError = 'Invalid parameter/property(Picture not found)'."
".'[Picture URL send:(Length='.strlen($content).')"'.$content.'"]';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$temp_dir = $this->getTempDir();if($temp_dir === FALSE){$this->lastError = 'Invalid parameter/property(Picture_URL ist not supported on this server)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$temp_dir.=md5(time());$put_file = @fopen($temp_dir,'w+');if($put_file){$handel = fwrite($put_file,$content);fclose($put_file);}$arr['picfile'] = $temp_dir;$file2delete = $temp_dir;}}}if(!file_exists($arr['picfile'])){$this->lastError = 'Invalid parameter/property(Picture not found)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$arr['picfile'] = '@'.$arr['picfile'];}if(empty($arr['album_id'])){$arr['album_id'] = $this->userID;}if(!empty($arr['link']))$arr['caption'] .= ' '.$arr['link'];$res = $this->GraphAPI('/'.$arr['album_id'].'/photos',array('source' => $arr['picfile'],'message' => $arr['caption']),FALSE,TRUE);if(!empty($file2delete))unlink($file2delete);if($res === FALSE){return FALSE;}else{return $res['id'];}}}public function GetPageInfo($page = 0){if(empty($page)){if($this->callAsPage === FALSE){$this->lastError = 'PageID/Name not available';$this->lastErrorCode = 1025;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->pageID > 0){$page = $this->pageID;}else{$this->lastError = 'Invalid PageID/Name';$this->lastErrorCode = 1025;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}}if(($felder = $this->GraphAPI('/'.$page))===FALSE){return FALSE;}else{if($this->callAsPage === TRUE && $felder['id'] == $this->pageID){$this->pageData = $felder;unset($this->pageData['id']);if($this->appFBURL == ''){if(strpos($felder['link'],'?')>0)$this->appFBURL = $felder['link'].'&sk=app_'.$this->appID;else $this->appFBURL = $felder['link'].'?sk=app_'.$this->appID;}}return $felder;}}public function KillIframeBorder($target=''){return $this->KillFacebookBorder($target);}public function KillFacebookBorder($target=''){if($this->runOutofIframe === TRUE){$this->lastError = 'running without Facebook border';$this->lastErrorCode = 1027;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($target==''){if($this->protocol == 'https://' && $this->ssl_proxy_url<>''){$target = $this->ssl_proxy_url.$_SERVER['REQUEST_URI'];}else{$target = $this->protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];}}$this->runOutofIframe = TRUE;$this->WriteInstanceToSession();$this->WriteLog(2,'Facebook border killed');echo("<script>top.location.href='".$target."';</script>");exit;}}private function GetURL($urll=''){if(strlen($urll)<= 5){$this->lastError = 'Missing parameter(URL)';$this->lastErrorCode = 1011;return FALSE;}else{$ch = curl_init();$ok = 1;if(curl_setopt($ch,CURLOPT_URL,$urll)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_POST,false)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_RETURNTRANSFER,true)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_TIMEOUT,60)===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0(X11;Linux)Gecko Firefox/5.0')===FALSE)$ok = 0;if(curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false)=== FALSE )$ok = 0;if($ok<>1){trigger_error(curl_error($ch));$this->lastError = 'CURL setting failed';$this->lastErrorCode = 1013;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$result = curl_exec($ch);if($result === FALSE){trigger_error(curl_error($ch));curl_close($ch);$this->lastError = 'Internal Error(CURL exec failed)';$this->lastErrorCode = 1006 ;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{curl_close($ch);return $result;}}}}private function GetAppAccessToken(){$token_url = 'https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id='.$this->appID.'&client_secret='.$this->AppSecKey;$access_token = $this->GetURL($token_url);if(!$access_token || strlen($access_token)<20 || strlen($access_token)>200){$this->lastError = 'Internal Error(getting access_token for app)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$access_token = substr($access_token,strpos($access_token,'=')+1);$this->appAccessToken = $access_token;$this->WriteLog(2,'app_access_token requested');return $access_token;}}public function SetAppProperty($property,$value){if(empty($property)|| strlen($property)<=3 || empty($value)|| strlen($value)<=3){$this->lastError = 'Missing parameter';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->appAccessToken == ''){if($this->GetAppAccessToken()=== FALSE)return FALSE;}if($this->appAccessToken == ''){$this->lastError = 'Internal Error(access_token for app is empty)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$urll = REST_URL . '?method=admin.setAppProperties&properties='.urlencode(json_encode(array( $property => $value ))).'&access_token='.$this->appAccessToken;$result = $this->GetURL($urll);if($result === FALSE){return FALSE;}else{$result = strip_tags($result);if($result <> 1){$this->lastError = 'FB error: '.substr($result,0,strpos($result,'method'));$this->lastErrorCode = 1015;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{return TRUE;}}}}}public function AddAppAsPage($api_key=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($api_key)|| strlen($api_key)<8){if(!empty($this->appID)&& strlen($this->appID)> 5)$api_key = $this->appID;else{$this->lastError = 'appID not available';$this->lastErrorCode = 1001;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if($_REQUEST['adpaok2'] == 'ok'){return $_REQUEST['fb_page_id'];}elseif($_REQUEST['adpaok2'] == 'notok'){return -1;}else{if($this->addPage_redirect_url == ''){$res = $this->SetAppProperty('post_authorize_redirect_url',$this->appServerURL.'?adpaok=ok');if($res === FALSE){return FALSE;}else{$this->addPage_redirect_url = $this->appServerURL.'?adpaok=ok';$this->WriteLog(2,'AddAppTarget set successfully');}}$urll = $this->protocol.'www.facebook.com/add.php?api_key='.$api_key.'&pages=1';if($this->protocol == 'https://' && $this->ssl_proxy_url<>''){$this->okURL = $this->ssl_proxy_url.$_SERVER['REQUEST_URI'];}else{$this->okURL = $this->protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];}$this->WriteInstanceToSession();echo "<script>top.location.href='".$urll."';</script>";exit;}}public function AddAppToPage(){$ret = $this->AddAppAsPage($this->appID);return $ret;}public function SearchSite($keyword,$type,$count=0,$mode=0){$type = trim($type);$keyword = trim($keyword);if(!is_numeric($mode)OR $mode< 0 OR $mode > 1){$this->lastError = 'Invalid parameter/property(mode)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(trim($type)== 'place'){$this->lastError = 'Unsupported type for search("place")';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(empty($type)){$type = 'post';}if($mode == 1 || $type == 'user' || $type == 'checkin'){if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if(empty($count)|| $count<1)$count=25;if(strlen($keyword)<2){$this->lastError = 'Missing parameter / too short(keyword)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$keyword = str_replace(' ','+',$keyword);if($mode == 0){$data = $this->GraphAPI('/search?q='.$keyword.'&type='.$type.'&limit='.$count);}elseif($mode == 1){$data = $this->GraphAPI('/me/home?q='.$keyword.'&limit='.$count);}if($data === FALSE){return FALSE;}else{unset($data['paging']['previous']);unset($data['paging']['next']);unset($data['paging']);$data = $data['data'];return $data;}}}public function SearchUserFeed($keyword,$count){return $this->SearchSite($keyword,'post',$count,1);}public function GetHome($count=25){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(!is_numeric($count)){$this->lastError = 'Invalid parameter/property(count)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($count < 1)$count = 25;$data = $this->GraphAPI('/me/home?limit='.$count);if($data === FALSE){return FALSE;}else{unset($data['paging']['previous']);unset($data['paging']['next']);unset($data['paging']);$data = $data['data'];return $data;}}}}public function GetAccessTokenInfo($access_token=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($access_token)){if(!empty($this->accessToken)){$access_token = $this->accessToken;}else{$this->lastError = 'Missing param(accessToken)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}if(!$access_token || strlen($access_token)<60 || strlen($access_token)>200){$this->lastError = 'access_token not available or invalid';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->appAccessToken == ''){if($this->GetAppAccessToken()=== FALSE)return FALSE;}if($this->appAccessToken == ''){$this->lastError = 'Internal Error(access_token for app is empty)';$this->lastErrorCode = 1006;return FALSE;}else{$token_url = 'https://graph.facebook.com/debug_token?input_token='.$access_token.'&access_token='.$this->appAccessToken;$res = $this->GetURL($token_url);$result2 = json_decode($res);$res = $this->convertObjectToArray($result2);if(isset($res['data']['error'])&& is_array($res['data']['error'])){if($res['data']['error']['code'] == 190){$res2['is_valid'] = FALSE;$res2['error'] = $res['data']['error'];return $res2;}else{$this->lastError = $res['data']['error']['code'].' : '.$res['data']['error']['message'];$this->lastErrorCode = 1015;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}}else{$res = $res['data'];$res['scopes'][] = 'basic';if(isset($res['expires_at'])){$res['expires'] = Date('Y-m-d H:i:s',$res['expires_at']);$res['expires_in'] = $res['expires_at']-time();}if($res['is_valid'] == 1)$res['is_valid'] = TRUE;elseif($res['is_valid'] == 0)$res['is_valid'] = FALSE;if($res['expires_in']<=(2*60*60))$res['type'] = 'short_lived';else $res['type'] = 'long_lived';return $res;}}}}public function GetObjectConnections($objectid){if(empty($objectid)){$this->lastError = 'Missing parameter(Object_id)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(strpos(substr($objectid,1,-1),'/')!== FALSE){$this->lastError = 'Invalid parameter(Object_id)- only single ObjectID accepted';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(substr($objectid,0,1)<>'/')$objectid='/'.$objectid;if(($res = $this->GraphAPI($objectid,'metadata=1'))=== FALSE){return FALSE;}else{$res2 = array();if(isset($res['metadata'])){if(isset($res['metadata']['type']))$res2['type'] = $res['metadata']['type'];if(isset($res['metadata']['connections'])){foreach($res['metadata']['connections'] as $val => $key)$res2['connections'][] = $val;}}unset($res);return $res2;}}}}public function GetLinkStatistic($link=''){$link = strtolower($link);if(empty($link)){$this->lastError = 'Missing param(link string)';$this->lastErrorCode = 1011;return FALSE;}elseif(substr($link,0,8)=='https://'){$this->lastError = 'Invalid parameter/property(https not supported)';$this->lastErrorCode = 1019;return FALSE;}else{if(substr($link,0,7)=='http://')$link=substr($link,7,1000);$xml_result = $this->GetURL('http://api.facebook.com/restserver.php?method=links.getStats&urls='.urlencode($link));if($xml_result === FALSE){return FALSE;}else{$arr_daten = array();$pos = substr($xml_result,strpos($xml_result,"<link_stat>")+11);$xml_result = substr($pos,0,strpos($pos,"</link_stat>"));$split_xml = explode("
",$xml_result);for($i=1;$i< count($split_xml)-1;$i++){$pos1=substr($split_xml[$i],strpos($split_xml[$i],"<")+1);$pos2=substr($pos1,strpos($pos1,">")+1);$pos3=substr($pos2,0,strpos($pos2,"</"));$index = substr($pos1,0,strpos($pos1,">"));$arr_daten[$index] = $pos3;}unset($arr_daten['total_count']);if(strpos($link,"http://")=== FALSE)$link="http://".$link;$result_link = $this->GraphAPI("/".$link);if($result_link === FALSE){return FALSE;}else{$arr_daten = array_merge($arr_daten,$result_link);if(isset($arr_daten['comments_fbid'])&& $arr_daten['comments_fbid'] <> ''){$result_id = $this->GetObjectInfo($arr_daten['comments_fbid']);if($result_id === FALSE){return FALSE;}else{unset($arr_daten['comments_fbid']);$arr_daten['fb_object']['id'] = $result_id['id'];if(isset($result_id['description']))$tmp = $result_id['description'];unset($result_id['description']);unset($result_id['id']);foreach($result_id as $key => $value){$arr_daten['fb_object'][$key] = $value;if($key == 'title' && isset($tmp)&& !empty($tmp))$arr_daten['fb_object']['description'] = $tmp;}}}return $arr_daten;}}}}public function SendNotification($textt='',$link=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$userid=='';if($this->userID == ''){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else $userid = $this->userID;if(empty($textt)){$this->lastError = 'Missing parameter(text is empty)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(strlen($textt)>180){$this->lastError = 'Invalid parameter(text)maxsize 180 chars';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(empty($link)){$this->lastError = 'Missing parameter(link)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(substr($link,0,2)=='./' || strtolower(substr($link,0,4))=='http' || strtolower(substr($link,0,4))=='www.'){$this->lastError = 'Invalid parameter(link)only relativ URL to FBAppUrl or filename or only parameters';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if(substr($link,0,1)=='/')$link = substr($link,1);if($this->appAccessToken == ''){if($this->GetAppAccessToken()=== FALSE)return FALSE;}if($this->appAccessToken == ''){$this->lastError = 'Internal Error(access_token for app is empty)';$this->lastErrorCode = 1006;return FALSE;}else{$params = array();$params['href'] = $link;$params['template'] = $textt;$params['access_token'] = $this->appAccessToken;$res = $this->GraphAPI('/'.$userid.'/notifications',$params,FALSE,TRUE);if($res === FALSE)return FALSE;else{if(isset($res['success'])&& $res['success']==1)return TRUE;else return $res;}}}}public function SendAppRequest($description='',$customstring=''){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($this->userID == ''){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else $userid = $this->userID;if(empty($description)){$this->lastError = 'Missing parameter(description is empty)';$this->lastErrorCode = 1011;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(strlen($description)>120){$this->lastError = 'Invalid parameter(description)maxsize 120 chars';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(strlen($customstring)>255){$this->lastError = 'Invalid parameter(customstring)maxsize 255 chars';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->appAccessToken == ''){if($this->GetAppAccessToken()=== FALSE)return FALSE;}if($this->appAccessToken == ''){$this->lastError = 'Internal Error(access_token for app is empty)';$this->lastErrorCode = 1006;return FALSE;}else{$params = array();$params['message'] = utf8_encode($description);$params['data'] = $customstring;$params['access_token'] = $this->appAccessToken;$res = $this->GraphAPI('/'.$userid.'/apprequests',$params,FALSE,TRUE);if($res === FALSE)return FALSE;else{unset($res2);if(isset($res['request']))$res2 = $res['request'];else $res2 = $res;return $res2;}}}}public function GetAppRequest($max_numb=1){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($this->userID == ''){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else $userid = $this->userID;if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif($max_numb < 1 || $max_numb > 20){$this->lastError = 'Invalid parameter(max_numb)max. 20';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$res = $this->GraphAPI('/'.$userid.'/apprequests','limit='.$max_numb);if($res === FALSE)return FALSE;else{if(isset($res['paging']))unset($res['paging']);unset($res2);if(isset($res['data'])&& count($res['data'])>0){if(count($res['data'])== 1){$res2 = $res['data'][0];if(strpos($res2['id'],'_')!== FALSE)$res2['id'] = substr($res2['id'],0,strpos($res2['id'],'_'));if(isset($res2['created_time']))$res2['created_localtime'] = Date('Y-m-d H:i:s',strtotime($res2['created_time']));if(isset($res2['message']))$res2['description'] = $res2['message'];if(isset($res2['data']))$res2['customstring'] = $res2['data'];}else{$res2 = $res['data'];for($x=0;$x < count($res2);$x++){if(strpos($res2[$x]['id'],'_')!== FALSE)$res2[$x]['id'] = substr($res2[$x]['id'],0,strpos($res2[$x]['id'],'_'));if(isset($res2[$x]['created_time']))$res2[$x]['created_localtime'] = Date('Y-m-d H:i:s',strtotime($res2[$x]['created_time']));if(isset($res2[$x]['message']))$res2[$x]['description'] = $res2[$x]['message'];if(isset($res2[$x]['data']))$res2[$x]['customstring'] = $res2[$x]['data'];}}}return $res2;}}}public function DelAppRequest($request_id){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($this->userID == ''){$this->lastError = 'userID is empty';$this->lastErrorCode = 1021;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else $userid = $this->userID;if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(empty($request_id)){$this->lastError = 'Invalid parameter/empty(request_id)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}elseif(!is_string($request_id)){$this->lastError = 'Invalid parameter(request_id)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{if($this->appAccessToken == ''){if($this->GetAppAccessToken()=== FALSE)return FALSE;}if($this->appAccessToken == ''){$this->lastError = 'Internal Error(access_token for app is empty)';$this->lastErrorCode = 1006;return FALSE;}else{if(strpos($request_id,'_')=== FALSE)$request_id.='_'.$this->userID;$params = array();$res = $this->GraphAPI('/'.$request_id,'',FALSE,FALSE,TRUE);if($res === FALSE)return FALSE;else{return $res;}}}}public function CheckAppRequestClick($extended=0){if(empty($this->app_call_params)|| strpos($this->app_call_params,'fb_source=bookmark')===FALSE){return FALSE;}else{$params = explode('&',$this->app_call_params);foreach($params as $val){$val2 = explode('=',$val);$params2[$val2[0]] = strtolower($val2[1]);}if((isset($params2['fb_source'])|| isset($params2['ref']))&&($params2['ref']=='bookmarks' || strpos($params2['fb_source'],'bookmark')<>FALSE)){if(isset($params2['count'])&& $params2['count']>0)if($extended == 1){$res = $this->GetAppRequest(1);if($res === FALSE)return FALSE;else{$res2 = array();$res2['click'] = TRUE;if(isset($res['id']))$res2['id'] = $res['id'];if(isset($res['to']['id']))$res2['to_id'] = $res['to']['id'];if(isset($res['description']))$res2['description'] = $res['description'];if(isset($res['customstring']))$res2['customstring'] = $res['customstring'];if(isset($res['created_localtime']))$res2['created_localtime'] = $res['created_localtime'];unset($res);return $res2;}}else return TRUE;else return FALSE;}else return FALSE;}}public function ActivateOfflineAccess(){if($this->runMode<>'app'){$this->lastError = NOT_IN_THIS_MODE;$this->lastErrorCode = 1031;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if(empty($this->accessToken)){$this->lastError = 'access_token not available - please Auth first';$this->lastErrorCode = 1024;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}$token_url = 'https://graph.facebook.com/oauth/access_token?client_id='.$this->appID.'&client_secret='.$this->AppSecKey.'&grant_type=fb_exchange_token&fb_exchange_token='.$this->accessToken;$access_token = $this->GetURL($token_url);if(!$access_token || strlen($access_token)<60 || strlen($access_token)>200){$this->lastError = 'Internal Error(FB doesnt send access_token)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$a_token = explode('&',$access_token);foreach($a_token as $val => $key){$key2 = explode('=',$key);$a_token[$key2[0]] = $key2[1];}if(!isset($a_token['access_token'])){$this->lastError = 'Internal Error(access_token not available)';$this->lastErrorCode = 1006;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}else{$this->SetAccessToken($a_token['access_token'],$a_token['expires']);return TRUE;}}}public function CheckOfflineAccess($extended=0){$res = $this->GetAccessTokenInfo();if($res === FALSE)return FALSE;else{if(!isset($res['is_valid'])){return FALSE;}else{if($res['is_valid']===FALSE)return 0;else{if(isset($res['typ'])&& $res['typ']=='short_lived'){return 0;}else{if($extended==0)return 1;else return $res;}}}}}public function SocialCommentBox($href,$width=300,$num_posts=1,$language=''){if(empty($href)|| strlen($href)<5){$this->lastError = 'Invalid parameter/empty(url)';$this->lastErrorCode = 1019;$this->WriteLog(0,$this->lastErrorCode.' '.$this->lastError);return FALSE;}if($language <> ''){$content = $this->EnableXFBML(FALSE,FALSE,$language);}else{$content = $this->EnableXFBML(TRUE,FALSE);}$width=(int)$width;$num_posts=(int)$num_posts;$colorscheme='light';$mobile='auto-detect';$content.='<div class="fb-comments" data-href="'.$href.'" data-width="'.$width.'" data-num-posts="'.$num_posts.'" data-colorscheme="'.$colorscheme.'" data-mobile="'.$mobile.'"></div>';return $content;}}

Did this file decode correctly?

Original Code

eval(base64_decode("aWYoaW50dmFsKHN1YnN0cihwaHB2ZXJzaW9uKCksMCwxKSk8IDUpe2VjaG8gJ1BIUGZvckZiIG5lZWRzIFBIUCB2ZXJzaW9uIDUuMCBvciBoaWdoZXIuJztleGl0O31pZighZnVuY3Rpb25fZXhpc3RzKCdqc29uX2RlY29kZScpKXtlY2hvICJQSFBmb3JGYiBuZWVkcyB0aGUgSlNPTiBQSFAgZXh0ZW5zaW9uLlxuUGxlYXNlIHZpc2l0IGh0dHA6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vYm9vay5qc29uLnBocCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhbmQgaW5zdGFsbGF0aW9uIGluc3RydWN0aW9ucy4iO2V4aXQ7fWlmKCFmdW5jdGlvbl9leGlzdHMoJ2N1cmxfaW5pdCcpKXtlY2hvICJQSFBmb3JGYiBuZWVkcyB0aGUgQ1VSTCBQSFAgZXh0ZW5zaW9uLlxuUGxlYXNlIHZpc2l0IGh0dHA6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vYm9vay5jdXJsLnBocCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhbmQgaW5zdGFsbGF0aW9uIGluc3RydWN0aW9ucy4iO2V4aXQ7fWRlZmluZSgnR1JBUEhfVVJMJywnaHR0cHM6Ly9ncmFwaC5mYWNlYm9vay5jb20nKTtkZWZpbmUoJ0ZRTF9VUkwnLCdodHRwczovL2FwaS5mYWNlYm9vay5jb20vbWV0aG9kL2ZxbC5xdWVyeScpO2RlZmluZSgnUkVTVF9VUkwnLCdodHRwczovL2FwaS5mYWNlYm9vay5jb20vcmVzdHNlcnZlci5waHAnKTtkZWZpbmUoJ05PVF9JTl9USElTX01PREUnLCdPbmx5IGF2YWlsYWJsZSBpbiBQSFBmb3JGQiBhcHAvcGFnZSBtb2RlJyk7Y2xhc3MgUEhQZm9yRkJ7cHVibGljICRhcHBJRDtwdWJsaWMgJGFwcE5hbWU7cHVibGljICRhcHBGQlVSTDtwdWJsaWMgJGFwcFNlcnZlclVSTDtwdWJsaWMgJGFwcEFjY2Vzc1Rva2VuO3B1YmxpYyAkc3NsX3Byb3h5X3VybCA9ICcnO3B1YmxpYyAkbG9nRGlyO3B1YmxpYyAkbG9nTGV2ZWwgPSAxO3B1YmxpYyAkbG9nZ2luZyA9IDA7cHVibGljICRjYWNoaW5nID0gVFJVRTtwdWJsaWMgJGNhY2hlRXhwaXJlcyA9IDYwMDtwdWJsaWMgJGNhbGxGcm9tRmFjZWJvb2s7cHVibGljICR1c2VyTG9nZ2VkSW4gPSBGQUxTRTtwdWJsaWMgJHVzZXJBdXRoZW50aWNhdGVkID0gRkFMU0U7cHVibGljICR1c2VyVXNlZExhbmd1YWdlO3B1YmxpYyAkdXNlckFjdHVhbENvdW50cnk7cHVibGljICR1c2VySXNBZHVsdCA9IEZBTFNFO3B1YmxpYyAkY2FsbEZyb20gPSAnJztwdWJsaWMgJG9rVVJMO3B1YmxpYyAkY2FuY2VsVVJMO3B1YmxpYyAkYWNjZXNzVG9rZW47cHVibGljICRhY2Nlc3NUb2tlbl91cmxfcGFyYW07cHVibGljICRhY2Nlc3NUb2tlbl9leHBpcmVfZGF0ZTtwdWJsaWMgJGFjY2Vzc1Rva2VuX2V4cGlyZXNfaW5fc2Vjb25kcztwdWJsaWMgJHVzZXJJRDtwdWJsaWMgJHVzZXJEYXRhO3B1YmxpYyAkdXNlckZyaWVuZHNEYXRhO3B1YmxpYyAkdXNlckxpa2VzO3B1YmxpYyAkdXNlckFsYnVtcztwdWJsaWMgJGxhc3RFcnJvckNvZGU7cHVibGljICRsYXN0RXJyb3I7cHVibGljICRydW5PdXRvZklmcmFtZSA9IEZBTFNFO3B1YmxpYyAkY2FsbEFzUGFnZSA9IEZBTFNFO3B1YmxpYyAkcGFnZUlEID0gMDtwdWJsaWMgJGlzUGFnZUFkbWluO3B1YmxpYyAkdXNlckxpa2VzUGFnZTtwdWJsaWMgJHBhZ2VEYXRhO3B1YmxpYyAkaXNNb2JpbGVEZXZpY2UgPSBGQUxTRTtwdWJsaWMgJG1vYmlsZURldmljZSA9ICcnO3B1YmxpYyAkcnVuTW9kZSA9ICdhcHAnO3B1YmxpYyAkcHJvdG9jb2wgPSAnaHR0cDovLyc7cHJpdmF0ZSAkc2NvcGVzID0gJ2Jhc2ljJztwcml2YXRlICRzY29wZXNfb2sgPSAnJztwcml2YXRlICRzY29wZXNfcmVxdWVzdF9kYXRlO3ByaXZhdGUgJGdvdG9QYWdlID0gRkFMU0U7cHJpdmF0ZSAkZ290b1VSTDtwcml2YXRlICRvYmplY3RfaWQ7cHJpdmF0ZSAkc2Vzc2lvbl9pZDtwcml2YXRlICRsYXN0X3VwZGF0ZTtwcml2YXRlICRsb2dfZmlsZW5hbWU7cHJpdmF0ZSAkQXBwU2VjS2V5O3ByaXZhdGUgJGFkZFBhZ2VfcmVkaXJlY3RfdXJsID0gJyc7cHJpdmF0ZSAkYXBwX2NhbGxfcGFyYW1zID0gJyc7cHJpdmF0ZSAkY2xhc3NWZXJzaW9uID0gJzEuOTYnO3ByaXZhdGUgJGNsYXNzQnVpbGQgPSAnMzA2MTcnO3B1YmxpYyAkUEVSTUlTU09OU19BVkFJTEFCTEUgPSBhcnJheSggJ2Jhc2ljJywndXNlcl9hYm91dF9tZScsJ2ZyaWVuZHNfYWJvdXRfbWUnLCd1c2VyX2FjdGl2aXRpZXMnLCdmcmllbmRzX2FjdGl2aXRpZXMnLCd1c2VyX2JpcnRoZGF5JywnZnJpZW5kc19iaXJ0aGRheScsJ3VzZXJfY2hlY2tpbnMnLCdmcmllbmRzX2NoZWNraW5zJywndXNlcl9lZHVjYXRpb25faGlzdG9yeScsJ2ZyaWVuZHNfZWR1Y2F0aW9uX2hpc3RvcnknLCd1c2VyX2V2ZW50cycsJ2ZyaWVuZHNfZXZlbnRzJywndXNlcl9ncm91cHMnLCdmcmllbmRzX2dyb3VwcycsJ3VzZXJfaG9tZXRvd24nLCdmcmllbmRzX2hvbWV0b3duJywndXNlcl9pbnRlcmVzdHMnLCdmcmllbmRzX2ludGVyZXN0cycsJ3VzZXJfbGlrZXMnLCdmcmllbmRzX2xpa2VzJywndXNlcl9sb2NhdGlvbicsJ2ZyaWVuZHNfbG9jYXRpb24nLCd1c2VyX25vdGVzJywnZnJpZW5kc19ub3RlcycsJ3VzZXJfcGhvdG9zJywnZnJpZW5kc19waG90b3MnLCd1c2VyX3F1ZXN0aW9ucycsJ2ZyaWVuZHNfcXVlc3Rpb25zJywndXNlcl9yZWxhdGlvbnNoaXBzJywnZnJpZW5kc19yZWxhdGlvbnNoaXBzJywndXNlcl9yZWxhdGlvbnNoaXBfZGV0YWlscycsJ2ZyaWVuZHNfcmVsYXRpb25zaGlwX2RldGFpbHMnLCd1c2VyX3JlbGlnaW9uX3BvbGl0aWNzJywnZnJpZW5kc19yZWxpZ2lvbl9wb2xpdGljcycsJ3VzZXJfc3RhdHVzJywnZnJpZW5kc19zdGF0dXMnLCd1c2VyX3N1YnNjcmlwdGlvbnMnLCdmcmllbmRzX3N1YnNjcmlwdGlvbnMnLCd1c2VyX3ZpZGVvcycsJ2ZyaWVuZHNfdmlkZW9zJywndXNlcl93ZWJzaXRlJywnZnJpZW5kc193ZWJzaXRlJywndXNlcl93b3JrX2hpc3RvcnknLCdmcmllbmRzX3dvcmtfaGlzdG9yeScsJ2VtYWlsJywncHVibGlzaF9hY3Rpb25zJywndXNlcl9nYW1lc19hY3Rpdml0eScsJ2ZyaWVuZHNfZ2FtZXNfYWN0aXZpdHknLCd+JywncmVhZF9mcmllbmRsaXN0cycsJ3JlYWRfaW5zaWdodHMnLCdyZWFkX21haWxib3gnLCdyZWFkX3JlcXVlc3RzJywncmVhZF9zdHJlYW0nLCd4bXBwX2xvZ2luJywnYWRzX21hbmFnZW1lbnQnLCdjcmVhdGVfZXZlbnQnLCdtYW5hZ2VfZnJpZW5kbGlzdHMnLCdtYW5hZ2Vfbm90aWZpY2F0aW9ucycsJ3VzZXJfb25saW5lX3ByZXNlbmNlJywnZnJpZW5kc19vbmxpbmVfcHJlc2VuY2UnLCdwdWJsaXNoX2NoZWNraW5zJywncHVibGlzaF9zdHJlYW0nLCdyc3ZwX2V2ZW50Jywnb2ZmbGluZV9hY2Nlc3MnLCk7cHVibGljIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRzdHJ1Y3RJbml0RGF0YSl7aWYoc3Ryc3RyKCRfU0VSVkVSWydIVFRQX1VTRVJfQUdFTlQnXSwnSUUnKSl7aWYoIWhlYWRlcnNfc2VudCgpKXtoZWFkZXIoJ1AzUDogQ1A9Q0FPIERTUCBDT1IgQ1VSYSBBRE1hIERFVmEgT1VSIElORCBQSFkgT05MIFVOSSBDT00gTkFWIElOVCBERU0gUFJFJyk7fX1pZihlbXB0eSgkc3RydWN0SW5pdERhdGFbJ21vZGUnXSl8fCAhaXNzZXQoJHN0cnVjdEluaXREYXRhWydtb2RlJ10pKXskbW9kZSA9ICdhcHAnO31lbHNleyRtb2RlcyA9IGFycmF5KCdhcHAnLCdwYWdlJywnY2FsbGJhY2snLCdkaXJlY3RfdXNlJyk7JG1vZGUgPSAkc3RydWN0SW5pdERhdGFbJ21vZGUnXTtpZighaW5fYXJyYXkoc3RydG9sb3dlcigkbW9kZSksJG1vZGVzKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdVbmtub3duIG1vZGUgcGFyYW1ldGVyJy4iXG5QbGVhc2UgdXNlOiAiLnZhcl9leHBvcnQoJG1vZGVzLFRSVUUpOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO319aWYoJG1vZGUgPT0gJ3BhZ2UnKSRtb2RlID0gJ2FwcCc7JHRoaXMtPnJ1bk1vZGUgPSAkbW9kZTtpZihpc3NldCgkc3RydWN0SW5pdERhdGFbJ2xvZ0RpciddKSkkbG9nX2RpcmVjdG9yeSA9ICRzdHJ1Y3RJbml0RGF0YVsnbG9nRGlyJ107ZWxzZSAkbG9nX2RpcmVjdG9yeSA9ICcnOyRhcnIgPSBhcnJheSgnbG9nTGV2ZWwnLCdsb2dnaW5nJywnY2FjaGluZycsJ2NhY2hlRXhwaXJlcycsJ3J1bk91dG9mSWZyYW1lJyk7Zm9yZWFjaCgkYXJyIGFzICR2YWwpaWYoaXNzZXQoJHN0cnVjdEluaXREYXRhWyR2YWxdKSYmICRzdHJ1Y3RJbml0RGF0YVskdmFsXTw+JycgKSR0aGlzLT4kdmFsID0gJHN0cnVjdEluaXREYXRhWyR2YWxdOyR0aGlzLT5sb2dfZmlsZW5hbWUgPSAnUEhQZm9yRkJfJy5EQVRFKCdZbWQnKS4nLmxvZyc7aWYoJGxvZ19kaXJlY3RvcnkgPD4gJycpeyR0aGlzLT5sb2dnaW5nID0gMTtpZihzdHJ0b3VwcGVyKCRsb2dfZGlyZWN0b3J5KT09ICdURU1QX0RJUicpeyR0aGlzLT5sb2dEaXIgPSAkdGhpcy0+Z2V0VGVtcERpcigpOyR0aGlzLT5Xcml0ZUxvZygyLCdzZXQgdGVtcGRpciB0byAnLiR0aGlzLT5sb2dEaXIpO31lbHNle2lmKCRsb2dfZGlyZWN0b3J5PT0nLi8nKSRsb2dfZGlyZWN0b3J5ID0gZGlybmFtZSgkX1NFUlZFUlsnU0NSSVBUX0ZJTEVOQU1FJ10pLicvJztpZihzdWJzdHIoJGxvZ19kaXJlY3RvcnksLTEpPD4nLycpJGxvZ19kaXJlY3RvcnkuPScvJztpZighaXNfZGlyKCRsb2dfZGlyZWN0b3J5KSl7aWYoIW1rZGlyKCRsb2dfZGlyZWN0b3J5LDA3MDAsdHJ1ZSkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnQ2FuIG5vdCBjcmVhdGUgTG9nIGRpcmVjdG9yeSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA1OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX0kdGhpcy0+bG9nRGlyID0gJGxvZ19kaXJlY3Rvcnk7JHRoaXMtPldyaXRlTG9nKDIsJ3NldCB0ZW1wZGlyIHRvICcuJHRoaXMtPmxvZ0Rpcik7fX1lbHNleyR0aGlzLT5sb2dnaW5nID0gMDt9aWYoIWVtcHR5KCRzdHJ1Y3RJbml0RGF0YVsnYXBwX2lkJ10pKXskYXBwX2lkID0gJHN0cnVjdEluaXREYXRhWydhcHBfaWQnXTtpZihzdHJsZW4oJGFwcF9pZCk8IDEyKXtpZigkYXBwX2lkPT0nJyl7JHRoaXMtPmxhc3RFcnJvciA9ICdhcHBJRCBub3QgYXZhaWxhYmxlJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDE7fWVsc2V7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIGFwcElEJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDI7fSR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX1pZigkdGhpcy0+cnVuTW9kZSA9PSAnYXBwJyl7JGFwcF9uYW1lID0gJHN0cnVjdEluaXREYXRhWydhcHBfbmFtZSddOyRzZWNfa2V5ID0gJHN0cnVjdEluaXREYXRhWydzZWNfa2V5J107aWYoc2Vzc2lvbl9pZCgpPT0gJycpeyRyZXMgPSBzZXNzaW9uX3N0YXJ0KCk7aWYoJHJlcyA8PiBGQUxTRSl7JHRoaXMtPldyaXRlTG9nKDIsJ1Nlc3Npb24gc3RhcnRlZCB3aXRoIFNlc3Npb24tSWQ6ICcuc2Vzc2lvbl9pZCgpKTt9ZWxzZXskdGhpcy0+bGFzdEVycm9yID0gJ1Nlc3Npb24gc3RhcnQgZmFpbGVkJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDA7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9fWVsc2V7JHRoaXMtPldyaXRlTG9nKDIsJ1Nlc3Npb24tSWQ6ICcuc2Vzc2lvbl9pZCgpKTt9aWYoc3RybGVuKCRzZWNfa2V5KTwgMjgpe2lmKCRzZWNfa2V5PT0nJyl7JHRoaXMtPmxhc3RFcnJvciA9ICdTZWN1cml0eUtleSBub3QgYXZhaWxhYmxlJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDM7fWVsc2V7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIFNlY3VyaXR5S2V5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDQ7fSR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKHN0cmxlbigkYXBwX25hbWUpPCAzKXtpZigkYXBwX25hbWU9PScnKXskdGhpcy0+bGFzdEVycm9yID0gJ0FwcE5hbWUoTmFtZXNwYWNlIC8gQ2FudmFzIE5hbWUpbm90IGF2YWlsYWJsZSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA4O31lbHNleyR0aGlzLT5sYXN0RXJyb3IgPSAnQXBwTmFtZShOYW1lc3BhY2UgLyBDYW52YXMgTmFtZSl0b28gc2hvcnQnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwOTt9JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9fWlmKGlzc2V0KCRfUkVRVUVTVFsnc2lnbmVkX3JlcXVlc3QnXSkpeyRzaWduZWRfcmVxdWVzdCA9ICR0aGlzLT5HZXRTaWduZWRSZXF1ZXN0KCRfUkVRVUVTVFsnc2lnbmVkX3JlcXVlc3QnXSk7fSRtb2JpbGVfd2ViID0gRkFMU0U7aWYoaXNzZXQoJF9HRVRbJ19yZHInXSkpeyRtb2JpbGVfd2ViID0gVFJVRTtpZighaXNzZXQoJF9SRVFVRVNUWydmYnNfJy4kYXBwX2lkXSkpe31lbHNle2lmKCFpc3NldCgkX1JFUVVFU1RbJ3NpZ25lZF9yZXF1ZXN0J10pJiYgIWVtcHR5KCRhcHBfaWQpJiYgaXNzZXQoJF9SRVFVRVNUWydmYnNfJy4kYXBwX2lkXSkmJiAhZW1wdHkoJF9SRVFVRVNUWydmYnNfJy4kYXBwX2lkXSkpeyRmYnNfdG9rZW4gPSAkdGhpcy0+R2V0RmJzVG9rZW4oJF9SRVFVRVNUWydmYnNfJy4kYXBwX2lkXSk7JHRoaXMtPldyaXRlTG9nKDIsJ0ZCU19UT0tFTiBkZXRlY3RlZCcpO2lmKCRmYnNfdG9rZW4gPT09IEZBTFNFKXskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddID0gJGZic190b2tlblsndWlkJ107JHNpZ25lZF9yZXF1ZXN0WydvYXV0aF90b2tlbiddID0gJGZic190b2tlblsnYWNjZXNzX3Rva2VuJ107JHNpZ25lZF9yZXF1ZXN0WydleHBpcmVzJ10gPSAkZmJzX3Rva2VuWydleHBpcmVzJ107fX19fWlmKGlzc2V0KCRzaWduZWRfcmVxdWVzdCkpe2lmKGlzc2V0KCRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddKSkkdXNlcl9pZCA9ICRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddO2Vsc2UgJHVzZXJfaWQgPSAnJzt9ZWxzZXskdXNlcl9pZCA9ICcnO30kdGhpcy0+aXNNb2JpbGVEZXZpY2UgPSBGQUxTRTskdXNlcmFnZW50PSRfU0VSVkVSWydIVFRQX1VTRVJfQUdFTlQnXTtpZihzdHJsZW4oJHVzZXJhZ2VudCk+IDEwKXskdGFibGV0RGV2aWNlcyA9IGFycmF5KCAnQmxhY2tCZXJyeVRhYmxldCcgID0+ICdQbGF5Qm9va3xSSU0gVGFibGV0JywnaVBhZCcgICAgICAgICAgICAgID0+ICdpUGFkfGlQYWQuKk1vYmlsZScsICdOZXh1c1RhYmxldCcgICAgICAgPT4gJ14uKkFuZHJvaWQuKk5leHVzKD86KD8hTW9iaWxlKS4pKiQnLCdLaW5kbGUnICAgICAgICAgICAgPT4gJ0tpbmRsZXxTaWxrLipBY2NlbGVyYXRlZCcsJ1NhbXN1bmdUYWJsZXQnICAgICA9PiAnU0FNU1VORy4qVGFibGV0fEdhbGF4eS4qVGFifEdULVAxMDAwfEdULVAxMDEwfEdULVA2MjEwfEdULVA2ODAwfEdULVA2ODEwfEdULVA3MTAwfEdULVA3MzAwfEdULVA3MzEwfEdULVA3NTAwfEdULVA3NTEwfFNDSC1JODAwfFNDSC1JODE1fFNDSC1JOTA1fFNHSC1JOTU3fFNHSC1JOTg3fFNHSC1UODQ5fFNHSC1UODU5fFNHSC1UODY5fFNQSC1QMTAwfEdULVAxMDAwfEdULVAzMTAwfEdULVAzMTEwfEdULVA1MTAwfEdULVA1MTEwfEdULVA2MjAwfEdULVA3MzAwfEdULVA3MzIwfEdULVA3NTAwfEdULVA3NTEwfEdULVA3NTExJywnSFRDdGFibGV0JyAgICAgICAgID0+ICdIVEMgRmx5ZXJ8SFRDIEpldHN0cmVhbXxIVEMtUDcxNWF8SFRDIEVWTyBWaWV3IDRHfFBHNDEyMDAnLCdNb3Rvcm9sYVRhYmxldCcgICAgPT4gJ3hvb218c2hvbGVzdHxNWjYxNXxNWjYwNXxNWjUwNXxNWjYwMXxNWjYwMnxNWjYwM3xNWjYwNHxNWjYwNnxNWjYwN3xNWjYwOHxNWjYwOXxNWjYxNXxNWjYxNnxNWjYxNycsJ0FzdXNUYWJsZXQnICAgICAgICA9PiAnVHJhbnNmb3JtZXJ8VEYxMDEnLCdOb29rVGFibGV0JyAgICAgICAgPT4gJ0FuZHJvaWQuKk5vb2t8Tm9va0NvbG9yfG5vb2sgYnJvd3NlcnxCTlRWMjUwQXxMb2dpY1BEIFpvb20yJywnQWNlclRhYmxldCcgICAgICAgID0+ICdBbmRyb2lkLipcYihBMTAwfEExMDF8QTIwMHxBNTAwfEE1MDF8QTUxMHxXNTAwfFc1MDBQfFc1MDF8VzUwMVApXGInLCdZYXJ2aWtUYWJsZXQnICAgICAgPT4gJ0FuZHJvaWQuKihUQUIyMTB8VEFCMjExfFRBQjIyNHxUQUIyNTB8VEFCMjYwfFRBQjI2NHxUQUIzMTB8VEFCMzYwfFRBQjM2NHxUQUI0MTB8VEFCNDExfFRBQjQyMHxUQUI0MjR8VEFCNDUwfFRBQjQ2MHxUQUI0NjF8VEFCNDY0fFRBQjQ2NXxUQUI0Njd8VEFCNDY4KScsJ01lZGlvblRhYmxldCcgICAgICA9PiAnQW5kcm9pZC4qXGJPWU9cYnxMSUZFLiooUDkyMTJ8UDk1MTR8UDk1MTZ8Uzk1MTIpfExJRkVUQUInLCdBcm5vdmFUYWJsZXQnICAgICAgPT4gJ0FOMTBHMnxBTjdiRzN8QU43ZkczfEFOOEczfEFOOGNHM3xBTjdHM3xBTjlHM3xBTjdkRzN8QU43ZEczU1R8QU43ZEczQ2hpbGRQYWR8QU4xMGJHM3xBTjEwYkczRFQnLCdBcmNob3NUYWJsZXQnICAgICAgPT4gJ0FuZHJvaWQuKkFSQ0hPU3wxMDFHOXw4MEc5JywnQWlub2xUYWJsZXQnICAgICAgID0+ICdOT1ZPN3xOb3ZvN0F1cm9yYXxOb3ZvN0Jhc2ljfE5PVk83UEFMQURJTicsJ1NvbnlUYWJsZXQnICAgICAgICA9PiAnU29ueSBUYWJsZXR8U29ueSBUYWJsZXQgUycsJ0dlbmVyaWNUYWJsZXQnICAgICA9PiAnVGFibGV0KD8hLipQQyl8Vmlld1BhZDd8TEctVjkwOXxNSUQ3MDE1fEJOVFYyNTBBfExvZ2ljUEQgWm9vbTJ8XGJBN0VCXGJ8Q2F0Tm92YTh8QTFfMDd8Q1Q3MDR8Q1QxMDAyfFxiTTcyMVxifGhwLXRhYmxldCcsKTskcmVnZXggPSAnJztmb3JlYWNoKCR0YWJsZXREZXZpY2VzIGFzICR2YWwgPT4gJHJlZ2V4KXskcmVnZXggPSBzdHJfcmVwbGFjZSgnLycsJ1wvJywkcmVnZXgpO2lmKHByZWdfbWF0Y2goJy8nLiRyZWdleC4nL2lzJywkdXNlcmFnZW50KSl7JHRoaXMtPmlzTW9iaWxlRGV2aWNlID0gVFJVRTskdGhpcy0+bW9iaWxlRGV2aWNlID0gJ3RhYmxldCc7YnJlYWs7fX1pZigkdGhpcy0+aXNNb2JpbGVEZXZpY2UgPT09IEZBTFNFKXtpZihwcmVnX21hdGNoKCcvaXBhZC9pJywkdXNlcmFnZW50KXx8cHJlZ19tYXRjaCgnL2lwb2QvaScsJHVzZXJhZ2VudCl8fHByZWdfbWF0Y2goJy9pcGhvbmUvaScsJHVzZXJhZ2VudCl8fCBwcmVnX21hdGNoKCcvYW5kcm9pZC9pJywkdXNlcmFnZW50KXx8IHByZWdfbWF0Y2goJy9vcGVyYSBtaW5pL2knLCR1c2VyYWdlbnQpfHwgcHJlZ19tYXRjaCgnL2JsYWNrYmVycnkvaScsJHVzZXJhZ2VudCl8fCBwcmVnX21hdGNoKCcvKHByZVwvfHBhbG0gb3N8cGFsbXxoaXB0b3B8YXZhbnRnb3xwbHVja2VyfHhpaW5vfGJsYXplcnxlbGFpbmUpL2knLCR1c2VyYWdlbnQpfHwgcHJlZ19tYXRjaCgnLyhpcmlzfDNnX3R8d2luZG93cyBjZXxvcGVyYSBtb2JpfHdpbmRvd3MgY2U7c21hcnRwaG9uZTt8d2luZG93cyBjZTtpZW1vYmlsZSkvaScsJHVzZXJhZ2VudCkpeyR0aGlzLT5pc01vYmlsZURldmljZSA9IFRSVUU7JHRoaXMtPm1vYmlsZURldmljZSA9ICd0b3VjaCc7fX1pZigkdGhpcy0+aXNNb2JpbGVEZXZpY2UgPT09IEZBTFNFKXtpZihwcmVnX21hdGNoKCcvYW5kcm9pZC4rbW9iaWxlfGF2YW50Z298YmFkYVwvfGJsYWNrYmVycnl8YmxhemVyfGNvbXBhbHxlbGFpbmV8ZmVubmVjfGhpcHRvcHxpZW1vYmlsZXxpcChob25lfG9kKXxpcmlzfGtpbmRsZXxsZ2UgfG1hZW1vfG1lZWdvLittb2JpbGV8bWlkcHxtbXB8bmV0ZnJvbnR8b3BlcmEgbShvYnxpbilpfHBhbG0oIG9zKT98cGhvbmV8cChpeGl8cmUpXC98cGx1Y2tlcnxwb2NrZXR8cHNwfHNlcmllcyg0fDYpMHxzeW1iaWFufHRyZW98dXBcLihicm93c2VyfGxpbmspfHZvZGFmb25lfHdhcHx3aW5kb3dzKGNlfHBob25lKXx4ZGF8eGlpbm8vaScsJHVzZXJhZ2VudCl8fHByZWdfbWF0Y2goJy8xMjA3fDYzMTB8NjU5MHwzZ3NvfDR0aHB8NTBbMS02XWl8Nzcwc3w4MDJzfGEgd2F8YWJhY3xhYyhlcnxvb3xzXC0pfGFpKGtvfHJuKXxhbChhdnxjYXxjbyl8YW1vaXxhbihleHxueXx5dyl8YXB0dXxhcihjaHxnbyl8YXModGV8dXMpfGF0dHd8YXUoZGl8XC1tfHIgfHMgKXxhdmFufGJlKGNrfGxsfG5xKXxiaShsYnxyZCl8YmwoYWN8YXopfGJyKGV8dil3fGJ1bWJ8YndcLShufHUpfGM1NVwvfGNhcGl8Y2N3YXxjZG1cLXxjZWxsfGNodG18Y2xkY3xjbWRcLXxjbyhtcHxuZCl8Y3Jhd3xkYShpdHxsbHxuZyl8ZGJ0ZXxkY1wtc3xkZXZpfGRpY2F8ZG1vYnxkbyhjfHApb3xkcygxMnxcLWQpfGVsKDQ5fGFpKXxlbShsMnx1bCl8ZXIoaWN8azApfGVzbDh8ZXooWzQtN10wfG9zfHdhfHplKXxmZXRjfGZseShcLXxfKXxnMSB1fGc1NjB8Z2VuZXxnZlwtNXxnXC1tb3xnbyhcLnd8b2QpfGdyKGFkfHVuKXxoYWllfGhjaXR8aGRcLShtfHB8dCl8aGVpXC18aGkocHR8dGEpfGhwKCBpfGlwKXxoc1wtY3xodChjKFwtfCB8X3xhfGd8cHxzfHQpfHRwKXxodShhd3x0Yyl8aVwtKDIwfGdvfG1hKXxpMjMwfGlhYyggfFwtfFwvKXxpYnJvfGlkZWF8aWcwMXxpa29tfGltMWt8aW5ub3xpcGFxfGlyaXN8amEodHx2KWF8amJyb3xqZW11fGppZ3N8a2RkaXxrZWppfGtndCggfFwvKXxrbG9ufGtwdCB8a3djXC18a3lvKGN8ayl8bGUobm98eGkpfGxnKCBnfFwvKGt8bHx1KXw1MHw1NHxcLVthLXddKXxsaWJ3fGx5bnh8bTFcLXd8bTNnYXxtNTBcL3xtYSh0ZXx1aXx4byl8bWMoMDF8MjF8Y2EpfG1cLWNyfG1lKGRpfHJjfHJpKXxtaShvOHxvYXx0cyl8bW1lZnxtbygwMXwwMnxiaXxkZXxkb3x0KFwtfCB8b3x2KXx6eil8bXQoNTB8cDF8diApfG13YnB8bXl3YXxuMTBbMC0yXXxuMjBbMi0zXXxuMzAoMHwyKXxuNTAoMHwyfDUpfG43KDAoMHwxKXwxMCl8bmUoKGN8bSlcLXxvbnx0Znx3Znx3Z3x3dCl8bm9rKDZ8aSl8bnpwaHxvMmltfG9wKHRpfHd2KXxvcmFufG93ZzF8cDgwMHxwYW4oYXxkfHQpfHBkeGd8cGcoMTN8XC0oWzEtOF18YykpfHBoaWx8cGlyZXxwbChheXx1Yyl8cG5cLTJ8cG8oY2t8cnR8c2UpfHByb3h8cHNpb3xwdFwtZ3xxYVwtYXxxYygwN3wxMnwyMXwzMnw2MHxcLVsyLTddfGlcLSl8cXRla3xyMzgwfHI2MDB8cmFrc3xyaW05fHJvKHZlfHpvKXxzNTVcL3xzYShnZXxtYXxtbXxtc3xueXx2YSl8c2MoMDF8aFwtfG9vfHBcLSl8c2RrXC98c2UoYyhcLXwwfDEpfDQ3fG1jfG5kfHJpKXxzZ2hcLXxzaGFyfHNpZShcLXxtKXxza1wtMHxzbCg0NXxpZCl8c20oYWx8YXJ8YjN8aXR8dDUpfHNvKGZ0fG55KXxzcCgwMXxoXC18dlwtfHYgKXxzeSgwMXxtYil8dDIoMTh8NTApfHQ2KDAwfDEwfDE4KXx0YShndHxsayl8dGNsXC18dGRnXC18dGVsKGl8bSl8dGltXC18dFwtbW98dG8ocGx8c2gpfHRzKDcwfG1cLXxtM3xtNSl8dHhcLTl8dXAoXC5ifGcxfHNpKXx1dHN0fHY0MDB8djc1MHx2ZXJpfHZpKHJnfHRlKXx2ayg0MHw1WzAtM118XC12KXx2bTQwfHZvZGF8dnVsY3x2eCg1Mnw1M3w2MHw2MXw3MHw4MHw4MXw4M3w4NXw5OCl8dzNjKFwtfCApfHdlYmN8d2hpdHx3aShnIHxuY3xudyl8d21sYnx3b251fHg3MDB8eWFzXC18eW91cnx6ZXRvfHp0ZVwtL2knLHN1YnN0cigkdXNlcmFnZW50LDAsNCkpKXskdGhpcy0+aXNNb2JpbGVEZXZpY2UgPSBUUlVFOyR0aGlzLT5tb2JpbGVEZXZpY2UgPSAnd2FwJzt9fX1pZigkdGhpcy0+aXNNb2JpbGVEZXZpY2UgPT09IEZBTFNFICYmICRtb2JpbGVfd2ViID09PSBUUlVFKSR0aGlzLT5pc01vYmlsZURldmljZSA9IFRSVUU7IGlmKChpc3NldCgkX0dFVFskYXBwX25hbWVdKSYmICRfR0VUWyRhcHBfbmFtZV09PSRhcHBfbmFtZSl8fChpc3NldCgkX0dFVFsnJCcuJ2FwJy4nZCddKSYmICRfR0VUWyckJy4nYXBkJ109PSc0NzkxMjA3MCcpKXtlY2hvICdDb2RlIHVzZSBQSFBmb3JGQiBjbGFzcyB2LiAnLiR0aGlzLT5jbGFzc1ZlcnNpb24uJyhCdWlsZCAnLiR0aGlzLT5jbGFzc0J1aWxkLicpJztleGl0O31pZihpc3NldCgkX1NFUlZFUlsnaHR0cHMnXSkmJigkX1NFUlZFUlsnaHR0cHMnXSA9PSAnb24nIHx8ICRfU0VSVkVSWydodHRwcyddID09IDEpKXskdGhpcy0+cHJvdG9jb2wgPSAnaHR0cHM6Ly8nO31lbHNlaWYoJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10gPT0gNDQzKXskdGhpcy0+cHJvdG9jb2wgPSAnaHR0cHM6Ly8nO31pZigkdGhpcy0+cHJvdG9jb2wgPD4gJ2h0dHBzOi8vJyAmJiBpc3NldCgkc3RydWN0SW5pdERhdGFbJ3NzbF9wcm94eV9hdmFpbGFibGUnXSkmJiAkc3RydWN0SW5pdERhdGFbJ3NzbF9wcm94eV9hdmFpbGFibGUnXT09PVRSVUUpe2lmKCFpc3NldCgkX1NFUlZFUlsnSFRUUF9YX0ZPUldBUkRFRF9IT1NUJ10pJiYgIWlzc2V0KCRfU0VSVkVSWydIVFRQX1hfRk9SV0FSREVEX1NFUlZFUiddKSl7JHRoaXMtPnNzbF9wcm94eV91cmwgPSAnJzt9ZWxzZXtpZighaXNzZXQoJHN0cnVjdEluaXREYXRhWydzc2xfYXBwX3VybCddKXx8IGVtcHR5KCRzdHJ1Y3RJbml0RGF0YVsnc3NsX2FwcF91cmwnXSl8fCBzdHJsZW4oJHN0cnVjdEluaXREYXRhWydzc2xfYXBwX3VybCddKTw1KXskdGhpcy0+bGFzdEVycm9yID0gJ3NzbF9hcHBfdXJsIGlzIGVtcHR5IG9yIGludmFsaWQnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRva2sgPSAwO2lmKGlzc2V0KCRfU0VSVkVSWydIVFRQX1hfRk9SV0FSREVEX0hPU1QnXSkmJiBzdHJwb3Moc3RydG9sb3dlcigkc3RydWN0SW5pdERhdGFbJ3NzbF9hcHBfdXJsJ10pLHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfSE9TVCddKSkhPT0gRkFMU0UpeyRva2sgPSAxO31pZihpc3NldCgkX1NFUlZFUlsnSFRUUF9YX0ZPUldBUkRFRF9TRVJWRVInXSkmJiBzdHJwb3Moc3RydG9sb3dlcigkc3RydWN0SW5pdERhdGFbJ3NzbF9hcHBfdXJsJ10pLHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfU0VSVkVSJ10pKSE9PSBGQUxTRSl7JG9rayA9IDE7fWlmKCRva2s9PTEpe2lmKHN0cnRvbG93ZXIoc3Vic3RyKCRzdHJ1Y3RJbml0RGF0YVsnc3NsX2FwcF91cmwnXSwwLDgpKT09J2h0dHBzOi8vJykkc3RydWN0SW5pdERhdGFbJ3NzbF9hcHBfdXJsJ10gPSBzdWJzdHIoJHN0cnVjdEluaXREYXRhWydzc2xfYXBwX3VybCddLDgsMTAwMCk7aWYoc3Vic3RyKCRzdHJ1Y3RJbml0RGF0YVsnc3NsX2FwcF91cmwnXSwtMSk8PicvJykkc3RydWN0SW5pdERhdGFbJ3NzbF9hcHBfdXJsJ10uPScvJzskdGhpcy0+cHJvdG9jb2wgPSAnaHR0cHM6Ly8nOyR0aGlzLT5zc2xfcHJveHlfdXJsID0gJHRoaXMtPnByb3RvY29sLnN0cl9yZXBsYWNlKHN1YnN0cigkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSwwLHN0cnBvcygkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSwnPycpKSwnJywkc3RydWN0SW5pdERhdGFbJ3NzbF9hcHBfdXJsJ10pO2lmKHN1YnN0cigkdGhpcy0+c3NsX3Byb3h5X3VybCwtMSk9PScvJykkdGhpcy0+c3NsX3Byb3h5X3VybD1zdWJzdHIoJHRoaXMtPnNzbF9wcm94eV91cmwsMCwtMSk7fWVsc2V7JHRoaXMtPnNzbF9wcm94eV91cmwgPSAnJzt9fX19aWYoJG1vZGUgPT0gJ2NhbGxiYWNrJyl7aWYoZW1wdHkoJHNpZ25lZF9yZXF1ZXN0KSl7JHRoaXMtPmxhc3RFcnJvciA9ICdjYWxsYmFjay1Nb2RlOiBubyBzaWduZWRfcmVxdWVzdCBzZW5kIGJ5IGZhY2Vib29rJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMzA7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskdGhpcy0+dXNlcklEID0gJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyX2lkJ107aWYoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyJ11bJ2xvY2FsZSddKSkkdGhpcy0+dXNlclVzZWRMYW5ndWFnZSA9ICRzaWduZWRfcmVxdWVzdFsndXNlciddWydsb2NhbGUnXTtpZihpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnY291bnRyeSddKSkkdGhpcy0+dXNlckFjdHVhbENvdW50cnkgPSAkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnY291bnRyeSddOyR0aGlzLT5Xcml0ZUxvZygyLCdDYWxsYmFjayBtb2RlIGNhbGwgd2lkdGggdXNlcklEICcuJHRoaXMtPnVzZXJJRCk7fX1lbHNleyR0aGlzLT5hcHBJRCA9ICRhcHBfaWQ7aWYoJG1vZGUgPT0gJ2RpcmVjdF91c2UnKXskdGhpcy0+V3JpdGVMb2coMiwnU3RhcnQgZGlyZWN0X3VzZXIgbW9kZScpO31lbHNleyRDcmVhdGVOZXdDbGFzcyA9IDA7aWYoIWlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF0pfHwgIWlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF1bJ2FwcF9pZCddKXx8ICFpc3NldCgkX1NFU1NJT05bJ1BIUDRGYl8nLiRhcHBfaWRdWydzZWNfa2V5J10pKXskQ3JlYXRlTmV3Q2xhc3MgPSAxO31lbHNle2lmKCAkX1NFU1NJT05bJ1BIUDRGYl8nLiRhcHBfaWRdWydhcHBfaWQnXSA8PiAkYXBwX2lkIHx8ICRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF1bJ3NlY19rZXknXSA8PiAkc2VjX2tleSApeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IoSW5pdCBBcHBJRCBvciBTZWNfS2V5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoIWlzc2V0KCRfUkVRVUVTVFsnc2lnbmVkX3JlcXVlc3QnXSl8fCAkX1JFUVVFU1RbJ3NpZ25lZF9yZXF1ZXN0J10gPT0gJycpeyRDcmVhdGVOZXdDbGFzcyA9IDI7fWVsc2V7aWYoaXNzZXQoJF9SRVFVRVNUWydzdGF0ZSddKSYmICRfUkVRVUVTVFsnc3RhdGUnXSA8PiAnJyl7JENyZWF0ZU5ld0NsYXNzID0gMjt9ZWxzZXtpZigkdXNlcl9pZCA9PSAnJyl7aWYoIWlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF1bJ29iamVjdCddKSl7JENyZWF0ZU5ld0NsYXNzID0gMTt9ZWxzZXskYWxsY2xhc3N2YXJzID0gJF9TRVNTSU9OWydQSFA0RmJfJy4kYXBwX2lkXVsnb2JqZWN0J107JGFsbGNsYXNzdmFycyA9IGJhc2U2NF9kZWNvZGUoJGFsbGNsYXNzdmFycyk7JGFsbGNsYXNzdmFycyA9IHVuc2VyaWFsaXplKCRhbGxjbGFzc3ZhcnMpO2lmKCRhbGxjbGFzc3ZhcnNbJ2FwcElEJ10gPD4gJGFwcF9pZCkkQ3JlYXRlTmV3Q2xhc3MgPSAxO2Vsc2V7aWYoJGFsbGNsYXNzdmFyc1snZ290b1BhZ2UnXSA9PT0gVFJVRSl7JENyZWF0ZU5ld0NsYXNzID0gMjt9ZWxzZXskQ3JlYXRlTmV3Q2xhc3MgPSAxO319fX1lbHNle2lmKCFlbXB0eSgkX1NFU1NJT05bJ1BIUDRGYl8nLiRhcHBfaWRdWyd1c2VyX2lkJ10pJiYgJF9TRVNTSU9OWydQSFA0RmJfJy4kYXBwX2lkXVsndXNlcl9pZCddIDw+ICR1c2VyX2lkKXskQ3JlYXRlTmV3Q2xhc3MgPSAxO31lbHNle2lmKGlzc2V0KCRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddKSYmIGlzc2V0KCRzaWduZWRfcmVxdWVzdFsnb2F1dGhfdG9rZW4nXSkpe2lmKCFlbXB0eSgkX1NFU1NJT05bJ1BIUDRGYl8nLiRhcHBfaWRdWydvYmplY3QnXSkpeyR0bXBfYXJyID0gdW5zZXJpYWxpemUoYmFzZTY0X2RlY29kZSgkX1NFU1NJT05bJ1BIUDRGYl8nLiRhcHBfaWRdWydvYmplY3QnXSkpO31pZihpc3NldCgkdG1wX2FyclsnZ290b1BhZ2UnXSkmJiAgJHRtcF9hcnJbJ2dvdG9QYWdlJ10gPT09IFRSVUUpeyRDcmVhdGVOZXdDbGFzcyA9IDI7fWVsc2V7JENyZWF0ZU5ld0NsYXNzID0gMTt9fWVsc2V7JENyZWF0ZU5ld0NsYXNzID0gMjt9fX19fX19JHRoaXMtPkFwcFNlY0tleSA9ICRzZWNfa2V5OyR0aGlzLT5hcHBOYW1lID0gJGFwcF9uYW1lOyR0aGlzLT5hcHBGQlVSTCA9ICR0aGlzLT5wcm90b2NvbC4nYXBwcy5mYWNlYm9vay5jb20vJy4kdGhpcy0+YXBwTmFtZS4nLyc7aWYoIWlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF0pKXskY2hlY2tOYW1lID0gRkFMU0U7JExfZmlsZW5hbWUgPSAnUEhQNEZiJy4kdGhpcy0+YXBwSUQuJy5kYXQnOyRjaGVja05hbWUgPSAkdGhpcy0+Q2hlY2tUZW1wRmlsZSgkTF9maWxlbmFtZSwyNCk7aWYoJGNoZWNrTmFtZSA9PT0gVFJVRSl7JHRoaXMtPldyaXRlTG9nKDIsJ0NoZWNraW5nIGFwcEZCVVJMICcuJHRoaXMtPmFwcEZCVVJMKTskYyA9IGN1cmxfaW5pdCgpOyRvayA9IDE7aWYoY3VybF9zZXRvcHQoICRjLENVUkxPUFRfVVJMLCdodHRwczovL2FwcHMuZmFjZWJvb2suY29tLycuJHRoaXMtPmFwcE5hbWUuJy8nKT09PUZBTFNFKSRvayA9IDA7IGlmKGN1cmxfc2V0b3B0KCAkYyxDVVJMT1BUX1NTTF9WRVJJRllQRUVSLGZhbHNlKT09PSBGQUxTRSApJG9rID0gMDtpZihjdXJsX3NldG9wdCggJGMsQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUix0cnVlICk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCAkYyxDVVJMT1BUX0NVU1RPTVJFUVVFU1QsJ0hFQUQnICk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCAkYyxDVVJMT1BUX0hFQURFUiwxICk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCAkYyxDVVJMT1BUX05PQk9EWSx0cnVlICk9PT0gRkFMU0UgKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoICRjLENVUkxPUFRfVVNFUkFHRU5ULCdNb3ppbGxhLzUuMChYMTE7TGludXgpR2Vja28gRmlyZWZveC81LjAnKT09PUZBTFNFKSRvayA9IDA7aWYoJG9rPD4xKXt0cmlnZ2VyX2Vycm9yKGN1cmxfZXJyb3IoJGMpKTskdGhpcy0+bGFzdEVycm9yID0gJ0NVUkwgc2V0dGluZyBmYWlsZWQoY2hlY2tpbmcgYXBwRkJVUkwpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTM7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskcmVzID0gc3RydG9sb3dlcihjdXJsX2V4ZWMoICRjICkpO2lmKCRyZXMgPT09IEZBTFNFKXt0cmlnZ2VyX2Vycm9yKGN1cmxfZXJyb3IoJGMpKTskdGhpcy0+bGFzdEVycm9yID0gJ0NVUkwgZXhlYyBmYWlsZWQoY2hlY2tpbmcgYXBwRkJVUkwpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDYgOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGluZm8gPSBjdXJsX2dldGluZm8oJGMpO2lmKCRpbmZvWydodHRwX2NvZGUnXTw+MjAwIHx8IHN0cnBvcygkcmVzLCdjb250ZW50LWxlbmd0aDogMCcpPjAgfHwgc3RycG9zKCRyZXMsJ2xvY2F0aW9uOiBodHRwOi8vd3d3LmZhY2Vib29rLmNvbS80b2g0LnBocCcpPjAgfHwgc3RycG9zKCRyZXMsJ2xvY2F0aW9uOiBodHRwczovL3d3dy5mYWNlYm9vay5jb20vNG9oNC5waHAnKT4wKXsgJHRoaXMtPmxhc3RFcnJvciA9ICdhcHBOYW1lKE5hbWVzcGFjZSAvIENhbnZhcyBOYW1lKWluY29ycmVjdDogJy4kdGhpcy0+YXBwRkJVUkwuJyhTYW5kIGJveCBtb2RlIGFjdGl2ZT8pJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjg7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9fX19fWlmKCRDcmVhdGVOZXdDbGFzcyA9PSAxKXtpZihpc3NldCgkX1NFUlZFUlsnUVVFUllfU1RSSU5HJ10pKSR0aGlzLT5hcHBfY2FsbF9wYXJhbXMgPSBzdHJ0b2xvd2VyKCRfU0VSVkVSWydRVUVSWV9TVFJJTkcnXSk7aWYoaXNzZXQoJF9TRVNTSU9OWydQSFA0RmJfJy4kYXBwX2lkXSkpdW5zZXQoJF9TRVNTSU9OWydQSFA0RmJfJy4kYXBwX2lkXSk7JF9TRVNTSU9OWydQSFA0RmJfJy4kYXBwX2lkXVsnYXBwX2lkJ10gPSAkYXBwX2lkOyRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF1bJ3NlY19rZXknXSA9ICRzZWNfa2V5OyR0aGlzLT5vYmplY3RfaWQgPSBzdWJzdHIobWQ1KHRpbWUoKSksMCwxNik7JHRoaXMtPnNlc3Npb25faWQgPSBzZXNzaW9uX2lkKCk7aWYoIWlzc2V0KCRzdHJ1Y3RJbml0RGF0YVsnc3NsX3Byb3h5X2F2YWlsYWJsZSddKXx8ICRzdHJ1Y3RJbml0RGF0YVsnc3NsX3Byb3h5X2F2YWlsYWJsZSddPT09RkFMU0UgfHwgJHRoaXMtPnNzbF9wcm94eV91cmw9PScnKXskdGhpcy0+YXBwU2VydmVyVVJMID0gJHRoaXMtPnByb3RvY29sLiRfU0VSVkVSWydIVFRQX0hPU1QnXTtpZihzdHJwb3MoJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10sJz8nKT4wKSR0aGlzLT5hcHBTZXJ2ZXJVUkwgLj0gc3Vic3RyKCRfU0VSVkVSWydSRVFVRVNUX1VSSSddLDAsc3RycG9zKCRfU0VSVkVSWydSRVFVRVNUX1VSSSddLCc/JykpO2Vsc2UgJHRoaXMtPmFwcFNlcnZlclVSTCAuPSAkX1NFUlZFUlsnUkVRVUVTVF9VUkknXTt9ZWxzZXskdGhpcy0+YXBwU2VydmVyVVJMID0gJHRoaXMtPnNzbF9wcm94eV91cmw7aWYoc3RycG9zKCRfU0VSVkVSWydSRVFVRVNUX1VSSSddLCc/Jyk+MCkkdGhpcy0+YXBwU2VydmVyVVJMIC49IHN1YnN0cigkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSwwLHN0cnBvcygkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSwnPycpKTtlbHNlICR0aGlzLT5hcHBTZXJ2ZXJVUkwgLj0gJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ107aWYoIWlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJGFwcF9pZF0pKXskYyA9IGN1cmxfaW5pdCgpOyRvayA9IDE7aWYoY3VybF9zZXRvcHQoICRjLENVUkxPUFRfVVJMLCR0aGlzLT5hcHBTZXJ2ZXJVUkwgKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoICRjLENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsdHJ1ZSApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCggJGMsQ1VSTE9QVF9DVVNUT01SRVFVRVNULCdIRUFEJyApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCggJGMsQ1VSTE9QVF9IRUFERVIsMSApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCggJGMsQ1VSTE9QVF9OT0JPRFksdHJ1ZSApPT09IEZBTFNFICkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCAkYyxDVVJMT1BUX1VTRVJBR0VOVCwnTW96aWxsYS81LjAoWDExO0xpbnV4KUdlY2tvIEZpcmVmb3gvNS4wJyk9PT1GQUxTRSkkb2sgPSAwO2lmKCRvazw+MSl7dHJpZ2dlcl9lcnJvcihjdXJsX2Vycm9yKCRjKSk7JHRoaXMtPmxhc3RFcnJvciA9ICdDVVJMIHNldHRpbmcgZmFpbGVkKGNoZWNraW5nIGFwcFNlcnZlclVSTCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRyZXMgPSBzdHJ0b2xvd2VyKGN1cmxfZXhlYyggJGMgKSk7aWYoJHJlcyA9PT0gRkFMU0Upe3RyaWdnZXJfZXJyb3IoY3VybF9lcnJvcigkYykpOyR0aGlzLT5sYXN0RXJyb3IgPSAnQ1VSTCBleGVjIGZhaWxlZChjaGVja2luZyBhcHBTZXJ2ZXJVUkwpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDYgOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGluZm8gPSBjdXJsX2dldGluZm8oJGMpO2lmKCRpbmZvWydodHRwX2NvZGUnXTw+MjAwKXskdGhpcy0+bGFzdEVycm9yID0gJ3NzbF9hcHBfdXJsIGlzIGluY29ycmVjdDogJy4kdGhpcy0+YXBwU2VydmVyVVJMLicoSFRUUCBTdGF0dXM6Jy4kaW5mb1snaHR0cF9jb2RlJ10uJyknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyODskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO319fX19aWYoISR0aGlzLT5QTEMoKSl7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9JHRoaXMtPldyaXRlTG9nKDIsJ0luc3RhbmNlIENyZWF0ZWQnKTskdGhpcy0+V3JpdGVMb2coMiwnSW5zdGFuY2UtSUQgaXMgJy4kdGhpcy0+b2JqZWN0X2lkKTtpZighZW1wdHkoJF9SRVFVRVNUWydyZWYnXSkpeyR0aGlzLT5jYWxsRnJvbSA9ICRfUkVRVUVTVFsncmVmJ107JHRoaXMtPldyaXRlTG9nKDIsJ1VzZXIgaXMgY2FsbGluZyBBcHAgZnJvbTogJy4kdGhpcy0+Y2FsbEZyb20pO31pZihpc3NldCgkc2lnbmVkX3JlcXVlc3QpKXskdGhpcy0+Y2FsbEZyb21GYWNlYm9vayA9IFRSVUU7aWYoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0WydwYWdlJ10pKXtpZighZW1wdHkoJHNpZ25lZF9yZXF1ZXN0WydwYWdlJ11bJ2lkJ10pKXskdGhpcy0+Y2FsbEFzUGFnZSA9IFRSVUU7JHRoaXMtPnBhZ2VJRCA9ICRzaWduZWRfcmVxdWVzdFsncGFnZSddWydpZCddO2lmKGlzc2V0KCRzaWduZWRfcmVxdWVzdFsncGFnZSddWydhZG1pbiddKSl7aWYoJHNpZ25lZF9yZXF1ZXN0WydwYWdlJ11bJ2FkbWluJ10gPT09IFRSVUUpJHRoaXMtPmlzUGFnZUFkbWluID0gVFJVRTtlbHNlICR0aGlzLT5pc1BhZ2VBZG1pbiA9IEZBTFNFO31pZihpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ3BhZ2UnXVsnbGlrZWQnXSkpe2lmKCRzaWduZWRfcmVxdWVzdFsncGFnZSddWydsaWtlZCddID09PSBUUlVFKSR0aGlzLT51c2VyTGlrZXNQYWdlID0gVFJVRTtlbHNlICR0aGlzLT51c2VyTGlrZXNQYWdlID0gRkFMU0U7fSR0aGlzLT5hcHBGQlVSTCA9ICcnO31lbHNleyR0aGlzLT5jYWxsQXNQYWdlID0gRkFMU0U7fX1lbHNleyR0aGlzLT5jYWxsQXNQYWdlID0gRkFMU0U7fWlmKGlzc2V0KCRzaWduZWRfcmVxdWVzdFsndXNlciddWydsb2NhbGUnXSkpJHRoaXMtPnVzZXJVc2VkTGFuZ3VhZ2UgPSAkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnbG9jYWxlJ107aWYoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyJ11bJ2NvdW50cnknXSkpJHRoaXMtPnVzZXJBY3R1YWxDb3VudHJ5ID0gJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyJ11bJ2NvdW50cnknXTtpZihpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnYWdlJ10pKXskdGhpcy0+dXNlckxvZ2dlZEluID0gVFJVRTtpZihpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnYWdlJ11bJ21heCddKSYmKCRzaWduZWRfcmVxdWVzdFsndXNlciddWydhZ2UnXVsnbWluJ10pPT0gMCAmJigkc2lnbmVkX3JlcXVlc3RbJ3VzZXInXVsnYWdlJ11bJ21heCddIDw9IDEzKSl7JHRoaXMtPnVzZXJMb2dnZWRJbiA9IEZBTFNFO31lbHNlaWYoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyJ11bJ2FnZSddWydtaW4nXSkpe2lmKCRzaWduZWRfcmVxdWVzdFsndXNlciddWydhZ2UnXVsnbWluJ10+PTE4KXskdGhpcy0+dXNlcklzQWR1bHQgPSBUUlVFO319fWlmKGlzc2V0KCRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddKSkkdGhpcy0+dXNlckxvZ2dlZEluID0gVFJVRTtpZihpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ3VzZXJfaWQnXSkmJiBpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ29hdXRoX3Rva2VuJ10pKXskdGhpcy0+dXNlckF1dGhlbnRpY2F0ZWQgPSBUUlVFOyR0aGlzLT51c2VySUQgPSAkc2lnbmVkX3JlcXVlc3RbJ3VzZXJfaWQnXTskdGhpcy0+U2V0QWNjZXNzVG9rZW4oJHNpZ25lZF9yZXF1ZXN0WydvYXV0aF90b2tlbiddLCRzaWduZWRfcmVxdWVzdFsnZXhwaXJlcyddKTskdGhpcy0+V3JpdGVMb2coMSwnTmV3IFZpc2l0IGRldGVjdGVkKFVzZXIgd2l0aCBBdXRoZW50aWZpY2F0aW9uKScpOyR0aGlzLT5Xcml0ZUxvZygyLCdVc2VySUQgaXMgJy4kdXNlcl9pZCk7JHRoaXMtPnNjb3Blc19vayA9ICR0aGlzLT5zY29wZXM7fWVsc2VpZigoIWlzc2V0KCRzaWduZWRfcmVxdWVzdFsndXNlcl9pZCddKSYmIGlzc2V0KCRzaWduZWRfcmVxdWVzdFsnb2F1dGhfdG9rZW4nXSkpfHwoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyX2lkJ10pJiYgIWlzc2V0KCRzaWduZWRfcmVxdWVzdFsnb2F1dGhfdG9rZW4nXSkpKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKFVzZXItSUQgb3IgT2FUb2tlbiBtaXNzaW5nKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHRoaXMtPnVzZXJBdXRoZW50aWNhdGVkID0gRkFMU0U7JHRoaXMtPldyaXRlTG9nKDEsJ05ldyBVc2VyIGRldGVjdGVkKE5vIEF1dGhlbnRpZmljYXRpb24pJyk7fX1lbHNle2lmKCRtb2JpbGVfd2ViID09PSBUUlVFKXskdGhpcy0+cnVuT3V0b2ZJZnJhbWUgPSBUUlVFOyR0aGlzLT5jYWxsRnJvbUZhY2Vib29rID0gVFJVRTskdGhpcy0+dXNlckxvZ2dlZEluID0gVFJVRTt9ZWxzZXtpZigkdGhpcy0+aXNNb2JpbGVEZXZpY2UgPT09IFRSVUUgJiYgc3RycG9zKCRfU0VSVkVSWydIVFRQX1JFRkVSRVInXSwnLmZhY2Vib29rLicpPjEgKXskdGhpcy0+cnVuT3V0b2ZJZnJhbWUgPSBUUlVFOyR0aGlzLT5jYWxsRnJvbUZhY2Vib29rID0gVFJVRTskdGhpcy0+dXNlckxvZ2dlZEluID0gRkFMU0U7fWVsc2V7JHRoaXMtPmNhbGxGcm9tRmFjZWJvb2sgPSBGQUxTRTskdGhpcy0+dXNlckxvZ2dlZEluID0gRkFMU0U7fX19JHRoaXMtPldyaXRlTG9nKDIsJ09iamVjdCBJbnN0YW56IHN1Y2Nlc3NmdWxseSBjcmVhdGVkJyk7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTt9ZWxzZWlmKCRDcmVhdGVOZXdDbGFzcyA9PSAyKXtpZigkdGhpcy0+UmVhZEluc3RhbmNlRnJvbVNlc3Npb24oKT09PSBGQUxTRSl7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO2lmKCR0aGlzLT5sYXN0RXJyb3JDb2RlID09IDEwMTQpe2VjaG8oIjxzY3JpcHQ+dG9wLmxvY2F0aW9uLmhyZWY9JyIuJHRoaXMtPmFwcEZCVVJMLiInOzwvc2NyaXB0PiIpO3Vuc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJHRoaXMtPmFwcElEXSk7ZXhpdDt9JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZighZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuX2V4cGlyZV9kYXRlKSkkdGhpcy0+YWNjZXNzVG9rZW5fZXhwaXJlc19pbl9zZWNvbmRzID0gc3RydG90aW1lKCR0aGlzLT5hY2Nlc3NUb2tlbl9leHBpcmVfZGF0ZSktdGltZSgpO2lmKCFpc3NldCgkc2lnbmVkX3JlcXVlc3RbJ29hdXRoX3Rva2VuJ10pKXtpZihpc3NldCgkX1JFUVVFU1RbJ3N0YXRlJ10pJiYgJF9SRVFVRVNUWydzdGF0ZSddID09ICdMT0dJTicpe2lmKGlzc2V0KCRfUkVRVUVTVFsnZXJyb3InXSkpe2lmKCRfUkVRVUVTVFsnZXJyb3InXSA9PSAnYWNjZXNzX2RlbmllZCcgJiYgJF9SRVFVRVNUWydlcnJvcl9yZWFzb24nXSA9PSAndXNlcl9kZW5pZWQnKXskdGhpcy0+V3JpdGVMb2coMSwnYWNjZXNzX2RlbmllZHx1c2VyX2RlbmllZCcpOyR0aGlzLT5nb3RvUGFnZSA9IFRSVUU7JHRoaXMtPmdvdG9VUkwgPSAkdGhpcy0+Y2FuY2VsVVJMOyR0aGlzLT5Xcml0ZUluc3RhbmNlVG9TZXNzaW9uKCk7aWYoJHRoaXMtPnJ1bk91dG9mSWZyYW1lID09PSBGQUxTRSAmJiBzdHJwb3MoJHRoaXMtPmNhbmNlbFVSTCwnLmZhY2Vib29rLicpPT09RkFMU0Upe2VjaG8oIjxzY3JpcHQ+dG9wLmxvY2F0aW9uLmhyZWY9JyIuJHRoaXMtPmFwcEZCVVJMLiInOzwvc2NyaXB0PiIpO2V4aXQ7fWVsc2V7JHRoaXMtPldyaXRlTG9nKDIsJ0p1bXAgdG8gJy4kdGhpcy0+Y2FuY2VsVVJMKTt9fWVsc2V7JHRoaXMtPldyaXRlTG9nKDEsJF9SRVFVRVNUWydlcnJvciddLCRfUkVRVUVTVFsnZXJyb3JfZGVzY3JpcHRpb24nXSwnJyk7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE1OyR0aGlzLT5sYXN0RXJyb3IgPSAnRkIgZXJyb3I6ICcuJF9SRVFVRVNUWydlcnJvciddLicgJy4kX1JFUVVFU1RbJ2Vycm9yX2Rlc2NyaXB0aW9uJ107cmV0dXJuIEZBTFNFO319ZWxzZXtpZihzdHJwb3MoJyMnLiR0aGlzLT5zY29wZXNfb2suJyMnLCcjYmFzaWMjJyk9PT0gVFJVRSl7fSR0aGlzLT5Xcml0ZUxvZygyLCdIYXZlIHRvIGp1bXAgdG8gJy4kdGhpcy0+b2tVUkwpOyR0aGlzLT5nb3RvUGFnZSA9IFRSVUU7JHRoaXMtPmdvdG9VUkwgPSAkdGhpcy0+b2tVUkw7JG9sZF9zY29wZXMgPSAkdGhpcy0+c2NvcGVzOyRvbGRfc2NvcGVzX29rID0gJHRoaXMtPnNjb3Blc19vazskdGhpcy0+V3JpdGVMb2coMSwnUGVybWlzc2lvbnMgY2hhbmdlZCBmcm9tICcuJHRoaXMtPnNjb3Blc19vay4nIHRvICcuJHRoaXMtPnNjb3Blcyk7JHRoaXMtPnNjb3Blc19vayA9ICR0aGlzLT5zY29wZXM7aWYoJHRoaXMtPnJ1bk91dG9mSWZyYW1lID09PSBGQUxTRSl7aWYoIWVtcHR5KCR0aGlzLT51c2VyRGF0YSkpeyRhcnJfciA9IGFycmF5KCd1c2VyX2Fib3V0X21lJywndXNlcl9hY3Rpdml0aWVzJywndXNlcl9iaXJ0aGRheScsJ3VzZXJfZWR1Y2F0aW9uX2hpc3RvcnknLCd1c2VyX2hvbWV0b3duJywndXNlcl9yZWxpZ2lvbl9wb2xpdGljcycsJ3VzZXJfc3RhdHVzJywndXNlcl93ZWJzaXRlJywnZW1haWwnKTskdXBkYXRlZSA9IDA7Zm9yZWFjaCgkYXJyX3IgYXMgJHZhbHVlKXtpZihzdHJwb3MoJyMnLiRvbGRfc2NvcGVzLicjJywnIycuJHZhbHVlLicjJykhPT1GQUxTRSAmJiBzdHJwb3MoJyMnLiRvbGRfc2NvcGVzX29rLicjJywnIycuJHZhbHVlLicjJyk9PT1GQUxTRSl7JHVwZGF0ZWUgPSAxO319aWYoJHVwZGF0ZWUgPT0gMSl7JHRoaXMtPkdldFVzZXJJbmZvKCcnLCcnLEZBTFNFKTskdGhpcy0+V3JpdGVMb2coMiwndXNlckRhdGEgY2FjaGUgdXBkYXRlZCcpO319JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTtlY2hvKCI8c2NyaXB0PnRvcC5sb2NhdGlvbi5ocmVmPSciLiR0aGlzLT5hcHBGQlVSTC4iJzs8L3NjcmlwdD4iKTtleGl0O31lbHNle2lmKCFpc3NldCgkX1JFUVVFU1RbJ2NvZGUnXSkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IoRkIgQ29kZSBwYXJhbWV0ZXIgbWlzc2luZyBhZnRlciBhdXRoT0spJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDY7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZighZW1wdHkoJF9SRVFVRVNUWydmYnNfJy4kdGhpcy0+YXBwSURdKSl7JGZic190b2tlbiA9ICR0aGlzLT5HZXRGYnNUb2tlbigkX1JFUVVFU1RbJ2Zic18nLiR0aGlzLT5hcHBJRF0pO31lbHNleyRmYnNfdG9rZW4gPSAnJzt9aWYoY291bnQoJGZic190b2tlbik+MCAmJiAhZW1wdHkoJGZic190b2tlblsnYWNjZXNzX3Rva2VuJ10pKXskdG9rZW5fYWNjZXNzID0gJGZic190b2tlblsnYWNjZXNzX3Rva2VuJ107JHRva2VuX2FjY2Vzc19leHBpcmVzID0gJGZic190b2tlblsnZXhwaXJlcyddOyR0b2tlbl91aWQgPSAkZmJzX3Rva2VuWyd1aWQnXTt9ZWxzZXskdG9rZW5fdXJsID0gJ2h0dHBzOi8vZ3JhcGguZmFjZWJvb2suY29tL29hdXRoL2FjY2Vzc190b2tlbj9jbGllbnRfaWQ9Jy4kdGhpcy0+YXBwSUQuJyZyZWRpcmVjdF91cmk9Jy51cmxlbmNvZGUoJHRoaXMtPmFwcFNlcnZlclVSTCkuJyZjbGllbnRfc2VjcmV0PScuJHRoaXMtPkFwcFNlY0tleS4nJmNvZGU9Jy4kX1JFUVVFU1RbJ2NvZGUnXTskYWNjZXNzX3Rva2VuID0gJHRoaXMtPkdldFVSTCgkdG9rZW5fdXJsKTtpZighJGFjY2Vzc190b2tlbiB8fCBzdHJsZW4oJGFjY2Vzc190b2tlbik8NjAgfHwgc3RybGVuKCRhY2Nlc3NfdG9rZW4pPjIwMCl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihGQiBjb2RlIHJlc3BvbnNlIG1hdGNoIGZhbHNlKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGFfdG9rZW5bJ2NvbnRlbnQnXSA9IGV4cGxvZGUoJyYnLCRhY2Nlc3NfdG9rZW4pO2ZvcmVhY2goJGFfdG9rZW5bJ2NvbnRlbnQnXSBhcyAkdmFsID0+ICRrZXkpeyRrZXkyID0gZXhwbG9kZSgnPScsJGtleSk7JGFfdG9rZW5bJGtleTJbMF1dID0gJGtleTJbMV07fWlmKCFpc3NldCgkYV90b2tlblsnYWNjZXNzX3Rva2VuJ10pKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKGFjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHRva2VuX2FjY2VzcyA9ICRhX3Rva2VuWydhY2Nlc3NfdG9rZW4nXTskdG9rZW5fYWNjZXNzX2V4cGlyZXMgPSAkYV90b2tlblsnZXhwaXJlcyddO2lmKHN0cnBvcygkYV90b2tlblsnYWNjZXNzX3Rva2VuJ10sJy0nKT4wKSR0b2tlbl91aWQgPSBzdWJzdHIoJGFfdG9rZW5bJ2FjY2Vzc190b2tlbiddLHN0cnBvcygkYV90b2tlblsnYWNjZXNzX3Rva2VuJ10sJy0nKSsxLDE1KTt9fX0kdGhpcy0+U2V0QWNjZXNzVG9rZW4oJHRva2VuX2FjY2VzcywkdG9rZW5fYWNjZXNzX2V4cGlyZXMpOyR0aGlzLT51c2VyQXV0aGVudGljYXRlZCA9IFRSVUU7JHRoaXMtPldyaXRlTG9nKDEsJ1Zpc2l0IGRldGVjdGVkKFVzZXIgd2l0aCBBdXRoZW50aWZpY2F0aW9uKScpO2lmKGVtcHR5KCR0aGlzLT51c2VySUQpKXtpZihlbXB0eSgkdG9rZW5fdWlkKSl7JHRoaXMtPldyaXRlTG9nKDAsJ1VzZXJJRCBub3QgYXZhaWxhYmxlIGluIE91dG9mSWZyYW1lIG1vZGUnKTt9ZWxzZXskdGhpcy0+dXNlcklEID0gJHRva2VuX3VpZDt9fSR0aGlzLT5Xcml0ZUxvZygyLCd1c2VySUQgaXMgJy4kdGhpcy0+dXNlcklEKTskdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO319fX1lbHNlaWYoaXNzZXQoJF9SRVFVRVNUWydhZHBhb2snXSkmJiAkX1JFUVVFU1RbJ2FkcGFvayddID09ICdvaycpeyR0aGlzLT5nb3RvVVJMID0gJHRoaXMtPm9rVVJMO2lmKHN0cnBvcygkdGhpcy0+b2tVUkwsJz8nKT4wKSR0aGlzLT5nb3RvVVJMIC49ICcmJztlbHNle2lmKHN1YnN0cigkdGhpcy0+b2tVUkwsLTEpPD4nLycpJHRoaXMtPmdvdG9VUkwgLj0gJz8nO31pZigkX1JFUVVFU1RbJ2luc3RhbGxlZCddID09IDEpeyR0aGlzLT5nb3RvVVJMIC49ICdhZHBhb2syPW9rJmZiX3BhZ2VfaWQ9Jy4kX1JFUVVFU1RbJ2ZiX3BhZ2VfaWQnXTt9ZWxzZXskdGhpcy0+Z290b1VSTCAuPSAnYWRwYW9rMj1ub3Rvayc7fSR0aGlzLT5nb3RvUGFnZSA9IFRSVUU7aWYoJHRoaXMtPnJ1bk91dG9mSWZyYW1lID09PSBGQUxTRSl7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTtlY2hvKCI8c2NyaXB0PnRvcC5sb2NhdGlvbi5ocmVmPSciLiR0aGlzLT5hcHBGQlVSTC4iJzs8L3NjcmlwdD4iKTtleGl0O31lbHNle319fWVsc2V7aWYoaXNzZXQoJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyX2lkJ10pJiYgaXNzZXQoJHNpZ25lZF9yZXF1ZXN0WydvYXV0aF90b2tlbiddKSl7JHRoaXMtPnVzZXJBdXRoZW50aWNhdGVkID0gVFJVRTskdGhpcy0+dXNlcklEID0gJHNpZ25lZF9yZXF1ZXN0Wyd1c2VyX2lkJ107JHRoaXMtPlNldEFjY2Vzc1Rva2VuKCRzaWduZWRfcmVxdWVzdFsnb2F1dGhfdG9rZW4nXSwkc2lnbmVkX3JlcXVlc3RbJ2V4cGlyZXMnXSk7JHRoaXMtPldyaXRlTG9nKDEsJ05ldyBBdXRoZW50aWZpY2F0aW9uJyk7JHRoaXMtPldyaXRlTG9nKDIsJ1VzZXJJRCBpcyAnLiR1c2VyX2lkKTskdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO31lbHNle2VjaG8gJ0ZBVEFMIEVSUk9SJztleGl0O319fX1lbHNle2VjaG8gJ1p1c3RhbmQgdW5iZWthbm50JztleGl0O31pZigkdGhpcy0+Z290b1BhZ2UgPT09IFRSVUUpe2lmKCR0aGlzLT5KdW1wVG9QYWdlKCk9PT0gVFJVRSlleGl0O2Vsc2V7cmV0dXJuIEZBTFNFO319fX19cHVibGljIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXskdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpOyR0aGlzLT5Xcml0ZUxvZygyLCdPYmplY3QgZGVzdHJveWVkJyk7fXByaXZhdGUgZnVuY3Rpb24gV3JpdGVMb2coJGxldmVsLCRzdHIpe2lmKCR0aGlzLT5sb2dnaW5nID09IDEpe2lmKCRsZXZlbCA8PSAkdGhpcy0+bG9nTGV2ZWwpeyRmaWxlPUBmb3BlbigkdGhpcy0+bG9nRGlyLiR0aGlzLT5sb2dfZmlsZW5hbWUsJ2EnKTtpZigkZmlsZSA9PT0gRkFMU0UpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTG9nZmlsZSBhY2Nlc3MgZXJyb3InOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyMjtyZXR1cm4gRkFMU0U7fWVsc2V7ZndyaXRlKCRmaWxlLERhdGUoJ1ktbS1kIEg6aTpzJykpO2Z3cml0ZSgkZmlsZSwnIFsnKTtpZihzdHJsZW4oJHRoaXMtPmFwcElEKT4yKWZ3cml0ZSgkZmlsZSwkdGhpcy0+YXBwSUQpO2lmKHN0cmxlbigkdGhpcy0+dXNlcklEKT40KWZ3cml0ZSgkZmlsZSwnfCcuJHRoaXMtPnVzZXJJRCk7ZndyaXRlKCRmaWxlLCddICcuJHN0ci4iXG4iKTtmY2xvc2UoJGZpbGUpO319fX1wdWJsaWMgZnVuY3Rpb24gR3JhcGhBUEkoJHBhcmFtLCRvcHRpb25hbD0nJywkaGVhZGVyID0gRkFMU0UsJHBvc3R0ID0gRkFMU0UsJGRlbGwgPSBGQUxTRSl7aWYoKCFpc19hcnJheSgkcGFyYW0pJiYgJHBhcmFtPT0nJyl8fCBpc19hcnJheSgkcGFyYW0pKXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW0oR3JhcGggQVBJIHN0cmluZyknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRncmFwaF91cmwgPSBHUkFQSF9VUkwgLiAkcGFyYW07aWYoc3RycG9zKCRncmFwaF91cmwsJz8nKT09PSBGQUxTRSkkZ3JhcGhfdXJsIC49ICc/JztlbHNlICRncmFwaF91cmwgLj0gJyYnO2lmKCFpc19hcnJheSgkb3B0aW9uYWwpJiYgJG9wdGlvbmFsIDw+ICcnKXskZ3JhcGhfdXJsLj0kb3B0aW9uYWwuJyYnO30kdGhpcy0+V3JpdGVMb2coMiwnR3JhcGhBUEkgQ2FsbDogJy4kZ3JhcGhfdXJsKTtpZighZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuX3VybF9wYXJhbSkpe2lmKCRwb3N0dCA9PT0gVFJVRSl7aWYoaXNzZXQoJG9wdGlvbmFsKSYmIGlzX2FycmF5KCRvcHRpb25hbCkmJiAhZW1wdHkoJG9wdGlvbmFsWydhY2Nlc3NfdG9rZW4nXSkpe31lbHNle2lmKCFlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW5fdXJsX3BhcmFtKSkkZ3JhcGhfdXJsLj0kdGhpcy0+YWNjZXNzVG9rZW5fdXJsX3BhcmFtO319ZWxzZXskZ3JhcGhfdXJsLj0kdGhpcy0+YWNjZXNzVG9rZW5fdXJsX3BhcmFtO319JGNoID0gY3VybF9pbml0KCk7JG9rID0gMTtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9VUkwsJGdyYXBoX3VybCk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX0hFQURFUiwkaGVhZGVyKT09PUZBTFNFKSRvayA9IDA7aWYoJHBvc3R0ID09PSBUUlVFKXtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NULHRydWUpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NURklFTERTLCRvcHRpb25hbCk9PT1GQUxTRSkkb2sgPSAwO31lbHNlaWYoJGRlbGwgPT09IFRSVUUpe2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX0NVU1RPTVJFUVVFU1QsIkRFTEVURSIpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9IRUFERVIsMCk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1BPU1QsZmFsc2UpPT09RkFMU0UpJG9rID0gMDt9ZWxzZXtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NULGZhbHNlKT09PUZBTFNFKSRvayA9IDA7fWlmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX0NPTk5FQ1RUSU1FT1VULDEwKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoJGNoLENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsdHJ1ZSk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1RJTUVPVVQsNjApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9VU0VSQUdFTlQsJ01vemlsbGEvNS4wKFgxMTtMaW51eClHZWNrbyBGaXJlZm94LzUuMCcpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9TU0xfVkVSSUZZUEVFUixmYWxzZSk9PT0gRkFMU0UgKSRvayA9IDA7aWYoJG9rPD4xKXt0cmlnZ2VyX2Vycm9yKGN1cmxfZXJyb3IoJGNoKSk7JHRoaXMtPmxhc3RFcnJvciA9ICdDVVJMIHNldHRpbmcgZmFpbGVkJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTM7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskcmVzdWx0ID0gY3VybF9leGVjKCRjaCk7aWYoJHJlc3VsdCA9PT0gRkFMU0Upe3RyaWdnZXJfZXJyb3IoY3VybF9lcnJvcigkY2gpKTskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKENVUkwgZXhlYyBmYWlsZWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDYgOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtjdXJsX2Nsb3NlKCRjaCk7cmV0dXJuIEZBTFNFO31lbHNle2lmKCRoZWFkZXIgPT09IFRSVUUpeyRyZXN1bHQgPSB0cmltKHN1YnN0cigkcmVzdWx0LDAsc3RycG9zKCRyZXN1bHQsY2hyKDEzKS5jaHIoMTApLmNocigxMykuY2hyKDEwKSkpKTt9ZWxzZXskcmVzdWx0MiA9IGpzb25fZGVjb2RlKCRyZXN1bHQpOyRyZXN1bHQgPSAkdGhpcy0+Y29udmVydE9iamVjdFRvQXJyYXkoJHJlc3VsdDIpO2lmKCFlbXB0eSgkcmVzdWx0WydlcnJvciddKSl7JHRoaXMtPmxhc3RFcnJvciA9ICRyZXN1bHRbJ2Vycm9yJ11bJ3R5cGUnXS4nIDogJy4kcmVzdWx0WydlcnJvciddWydtZXNzYWdlJ107JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE1OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtjdXJsX2Nsb3NlKCRjaCk7cmV0dXJuIEZBTFNFO31lbHNlaWYoaXNfYm9vbCgkcmVzdWx0KSYmICRyZXN1bHQgPT09IEZBTFNFKXskdGhpcy0+bGFzdEVycm9yID0gJ0luZm9ybWF0aW9uIG5vdCB2aXNpYmxlKG1heWJ5IHNhbmQgYm94IG1vZGUgYWN0aXZlKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMyOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtjdXJsX2Nsb3NlKCRjaCk7cmV0dXJuIEZBTFNFO319fWN1cmxfY2xvc2UoJGNoKTtyZXR1cm4gJHJlc3VsdDt9fX1wdWJsaWMgZnVuY3Rpb24gRlFMKCRxdWVyeSl7JHRoaXMtPldyaXRlTG9nKDIsJ0ZRTCBSZXF1ZXN0OiAnLiRndWVyeSk7JGNoID0gY3VybF9pbml0KCk7JG9rID0gMTtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9VUkwsRlFMX1VSTCApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NULHRydWUpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NURklFTERTLGFycmF5KCdmb3JtYXQnPT4nanNvbi1zdHJpbmdzJywnYWNjZXNzX3Rva2VuJz0+JHRoaXMtPmFjY2Vzc1Rva2VuLCdxdWVyeSc9PiRxdWVyeSkpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9DT05ORUNUVElNRU9VVCwxMCk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1JFVFVSTlRSQU5TRkVSLHRydWUpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9USU1FT1VULDYwKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoJGNoLENVUkxPUFRfVVNFUkFHRU5ULCdNb3ppbGxhLzUuMChYMTE7TGludXgpR2Vja28gRmlyZWZveC81LjAnKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoJGNoLENVUkxPUFRfU1NMX1ZFUklGWVBFRVIsZmFsc2UpPT09IEZBTFNFICkkb2sgPSAwO2lmKCRvazw+MSl7dHJpZ2dlcl9lcnJvcihjdXJsX2Vycm9yKCRjaCkpOyR0aGlzLT5sYXN0RXJyb3IgPSAnQ1VSTCBzZXR0aW5nIGZhaWxlZCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDEzOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHJlc3VsdCA9IGN1cmxfZXhlYygkY2gpO2lmKCRyZXN1bHQgPT09IEZBTFNFKXt0cmlnZ2VyX2Vycm9yKGN1cmxfZXJyb3IoJGNoKSk7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihDVVJMIGV4ZWMgZmFpbGVkKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWN1cmxfY2xvc2UoJGNoKTskcmVzdWx0ID0ganNvbl9kZWNvZGUoJHJlc3VsdCk7JGRhdGEgPSAkdGhpcy0+Y29udmVydE9iamVjdFRvQXJyYXkoJHJlc3VsdCk7aWYoaXNzZXQoJGRhdGFbJ2Vycm9yX2NvZGUnXSkpeyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gJ0ZCLkVycm9yOiAnLiRkYXRhWydlcnJvcl9jb2RlJ107JHRoaXMtPmxhc3RFcnJvciA9ICdGQi5NZXNzYWdlOiAnLiRkYXRhWydlcnJvcl9tc2cnXTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIGZhbHNlO31lbHNle2lmKGNvdW50KCRkYXRhKT09MSAmJiBpc19hcnJheSgkZGF0YVswXSkmJiBrZXkoJGRhdGEpPT0wKSRkYXRhID0gJGRhdGFbMF07cmV0dXJuICRkYXRhO319fXByaXZhdGUgZnVuY3Rpb24gY29udmVydE9iamVjdFRvQXJyYXkoJG9iamVjdCl7aWYoaXNfb2JqZWN0KCRvYmplY3QpKXskb2JqZWN0ID0gZ2V0X29iamVjdF92YXJzKCRvYmplY3QpO31pZihpc19hcnJheSgkb2JqZWN0KSl7cmV0dXJuIGFycmF5X21hcChhcnJheSgkdGhpcywiY29udmVydE9iamVjdFRvQXJyYXkiKSwkb2JqZWN0KTt9ZWxzZWlmKGlzX3N0cmluZygkb2JqZWN0KSl7cmV0dXJuIG1iX2NvbnZlcnRfZW5jb2RpbmcoJG9iamVjdCwnVVRGLTgnLCdBU0NJSSxVVEYtOCxJU08tODg1OS0xJyk7fWVsc2V7cmV0dXJuICRvYmplY3Q7fX1wcml2YXRlIGZ1bmN0aW9uIEdldEZic1Rva2VuKCRzdHJnPScnKXtpZigkc3RyZz09JycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoRkJTX1RPS0VOKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoJHN0cmdbMF09PSciJykkc3RyZyA9IHN1YnN0cigkc3RyZywxLDEwMDApO2lmKCRzdHJnW3N0cmxlbigkc3RyZyktMV09PSciJykkc3RyZyA9IHN1YnN0cigkc3RyZywwLC0xKTtpZihlbXB0eSgkc3RyZykpeyR0aGlzLT5sYXN0RXJyb3IgPSAnUGFyYW1ldGVyIGlzIGVtcHR5KEZCU19UT0tFTiknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRzdHJnID0gZXhwbG9kZSgnJicsJHN0cmcpO2ZvcmVhY2goJHN0cmcgYXMgJGtleSl7JGtleTIgPSBleHBsb2RlKCc9Jywka2V5KTskZmJzX3Rva2VuWyRrZXkyWzBdXSA9ICRrZXkyWzFdO31yZXR1cm4gJGZic190b2tlbjt9fX1wdWJsaWMgZnVuY3Rpb24gR2V0U2lnbmVkUmVxdWVzdCgkc3RyZz0nJyl7aWYoJHN0cmc9PScnKXtpZighZW1wdHkoJF9SRVFVRVNUWydzaWduZWRfcmVxdWVzdCddKSkkc3RyZyA9ICRfUkVRVUVTVFsnc2lnbmVkX3JlcXVlc3QnXTtlbHNleyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoU2lnbmVkUmVxdWVzdCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTtyZXR1cm4gRkFMU0U7fX0kc2lnbmVkX3JlcXVlc3QgPSBzdWJzdHIoJHN0cmcsc3RycG9zKCRzdHJnLCcuJykrMSk7JHNpZ25lZF9yZXF1ZXN0ID0ganNvbl9kZWNvZGUoYmFzZTY0X2RlY29kZShzdHJ0cigkc2lnbmVkX3JlcXVlc3QsJy1fJywnKy8nKSkpOyRzaWduZWRfcmVxdWVzdCA9ICR0aGlzLT5jb252ZXJ0T2JqZWN0VG9BcnJheSgkc2lnbmVkX3JlcXVlc3QpO3JldHVybiAkc2lnbmVkX3JlcXVlc3Q7fXB1YmxpYyBmdW5jdGlvbiBTZXRBY2Nlc3NUb2tlbigkdG9rZW4sJGV4cGlyZXMpeyR0aGlzLT5hY2Nlc3NUb2tlbiA9ICR0b2tlbjskdGhpcy0+YWNjZXNzVG9rZW5fdXJsX3BhcmFtID0gJ2FjY2Vzc190b2tlbj0nLiR0b2tlbjtpZihpc3NldCgkZXhwaXJlcykpe2lmKCRleHBpcmVzID09IDApeyR0aGlzLT5hY2Nlc3NUb2tlbl9leHBpcmVfZGF0ZSA9ICcyMDMwLTAxLTAxIDAwOjAwOjAwJzskdGhpcy0+YWNjZXNzVG9rZW5fZXhwaXJlc19pbl9zZWNvbmRzID0gc3RydG90aW1lKCcyMDMwLTAxLTAxIDAwOjAwOjAwJyktdGltZSgpO31lbHNle2lmKCRleHBpcmVzIDwoNjEqMjQqNjAqNjApKXskdGhpcy0+YWNjZXNzVG9rZW5fZXhwaXJlc19pbl9zZWNvbmRzID0gJGV4cGlyZXM7JHRoaXMtPmFjY2Vzc1Rva2VuX2V4cGlyZV9kYXRlID0gREFURSgnWS1tLWQgSDppOnMnLCh0aW1lKCkrJGV4cGlyZXMpKTt9ZWxzZXskdGhpcy0+YWNjZXNzVG9rZW5fZXhwaXJlX2RhdGUgPSBEQVRFKCdZLW0tZCBIOmk6cycsJGV4cGlyZXMpOyR0aGlzLT5hY2Nlc3NUb2tlbl9leHBpcmVzX2luX3NlY29uZHMgPSAkZXhwaXJlcy10aW1lKCk7fX19fXByaXZhdGUgZnVuY3Rpb24gZ2V0VGVtcERpcigpeyRlcmdlYiA9ICR0aGlzLT5nZXRUZW1wRGlyMigpO2lmKHN1YnN0cigkZXJnZWIsc3RybGVuKCRlcmdlYiktMSwxKTw+ICcvJykkZXJnZWIgLj0gJy8nO3JldHVybiAkZXJnZWI7fXByaXZhdGUgZnVuY3Rpb24gZ2V0VGVtcERpcjIoKXtpZihmdW5jdGlvbl9leGlzdHMoJ2luaV9nZXQnKSl7JHRlbXBfZGlyID0gaW5pX2dldCgndXBsb2FkX3RtcF9kaXInKTtpZihpc19kaXIoJHRlbXBfZGlyKSYmIGlzX3dyaXRhYmxlKCR0ZW1wX2RpcikpcmV0dXJuICR0ZW1wX2Rpcjt9aWYoZnVuY3Rpb25fZXhpc3RzKCdzeXNfZ2V0X3RlbXBfZGlyJykpeyR0ZW1wX2RpciA9IHN5c19nZXRfdGVtcF9kaXIoKTtpZigkdGVtcF9kaXIgJiYgaXNfZGlyKCR0ZW1wX2RpcikmJiBpc193cml0YWJsZSgkdGVtcF9kaXIpKXJldHVybiAkdGVtcF9kaXI7fSR0ZW1wX2RpciA9IGdldGVudignVE1QJyk7aWYoIWVtcHR5KCR0ZW1wX2RpcikmJiBpc19kaXIoJHRlbXBfZGlyKSYmIGlzX3dyaXRhYmxlKCR0ZW1wX2RpcikpcmV0dXJuICR0ZW1wX2RpcjskdGVtcF9kaXIgPSBnZXRlbnYoJ1RFTVAnKTtpZighZW1wdHkoJHRlbXBfZGlyKSYmIGlzX2RpcigkdGVtcF9kaXIpJiYgaXNfd3JpdGFibGUoJHRlbXBfZGlyKSlyZXR1cm4gJHRlbXBfZGlyOyR0ZW1wX2RpciA9IGdldGVudignVE1QRElSJyk7aWYoIWVtcHR5KCR0ZW1wX2RpcikmJiBpc19kaXIoJHRlbXBfZGlyKSYmIGlzX3dyaXRhYmxlKCR0ZW1wX2RpcikpcmV0dXJuICR0ZW1wX2RpcjskdGVtcF9kaXIgPSBkaXJuYW1lKEB0ZW1wbmFtKF9fRklMRV9fLCcnKSk7aWYoJHRlbXBfZGlyICYmIGlzX2RpcigkdGVtcF9kaXIpJiYgaXNfd3JpdGFibGUoJHRlbXBfZGlyKSlyZXR1cm4gJHRlbXBfZGlyO3JldHVybiBGQUxTRTt9cHJpdmF0ZSBmdW5jdGlvbiBDaGVja1RlbXBGaWxlKCRMX2ZpbGVuYW1lLCRpbnRlcnZhbGxfaW5faG91cnMpeyR0ZW1wX2RpciA9ICR0aGlzLT5nZXRUZW1wRGlyKCk7JENoZVNlciA9IEZBTFNFO2lmKCR0ZW1wX2RpciA9PT0gRkFMU0UpeyRDaGVTZXIgPSBUUlVFO31lbHNle2lmKCFmaWxlX2V4aXN0cygkdGVtcF9kaXIuJExfZmlsZW5hbWUpKXskQ2hlU2VyID0gVFJVRTt9ZWxzZXskaW50ZXJ2YWxsX2luX3NlYyA9KCRpbnRlcnZhbGxfaW5faG91cnMgKiA2MCAqIDYwKTskZnRpbWUgPSBmaWxlbXRpbWUoJHRlbXBfZGlyLiRMX2ZpbGVuYW1lKTskZnRpbWVfYmFja3VwID0gZmlsZSgkdGVtcF9kaXIuJExfZmlsZW5hbWUpO2lmKGFicygkZnRpbWVfYmFja3VwWzBdLSRmdGltZSk+NSkkQ2hlU2VyID0gVFJVRTtlbHNlaWYoICRmdGltZSA+KHRpbWUoKS0gJGludGVydmFsbF9pbl9zZWMpKWlmKERhdGUoJ1ltZCcsJGZ0aW1lKTw+RGF0ZSgnWW1kJykpJENoZVNlciA9IFRSVUU7ZWxzZSAkQ2hlU2VyID0gRkFMU0U7ZWxzZSAkQ2hlU2VyID0gVFJVRTt9fXJldHVybiAkQ2hlU2VyO31wcml2YXRlIGZ1bmN0aW9uIFBMQygkaW50ZXJ2YWxsX2luX2hvdXJzID0gMjQpeyRMX2ZpbGVuYW1lID0gIlBIUDRGYiIuJHRoaXMtPmFwcElELiIuZGF0IjtpZigkaW50ZXJ2YWxsX2luX2hvdXJzIDwgMSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihQaW5nU2VydmVyIHRpbWUgdG9vIHNob3J0KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JENoZVNlciA9ICR0aGlzLT5DaGVja1RlbXBGaWxlKCRMX2ZpbGVuYW1lLCRpbnRlcnZhbGxfaW5faG91cnMpO2lmKCRDaGVTZXIgPT09IFRSVUUpeyR0ZW1wX2RpciA9ICR0aGlzLT5nZXRUZW1wRGlyKCk7JHB1dF9maWxlID0gQGZvcGVuKCR0ZW1wX2Rpci4kTF9maWxlbmFtZSwndysnKTtpZigkcHV0X2ZpbGUpeyRoYW5kZWwgPSBmd3JpdGUoJHB1dF9maWxlLHRpbWUoKSk7ZmNsb3NlKCRwdXRfZmlsZSk7fSRjbGFzc19McyA9ICdodCc7JGNsYXNzX0xzIC49ICd0cDonOyRjbGFzc19McyAuPSAnLy8nOyRjbGFzc19McyAuPSAndyc7JGNsYXNzX0xzIC49ICd3dyc7JGNsYXNzX0xzIC49ICcuJzskY2xhc3NfTHMgLj0gJ3BocDRmYic7JGNsYXNzX0xzIC49ICcuJzskY2xhc3NfTHMgLj0gJ2MnLidvbScuJy8nLidsaScuJ2MnOyRjbGFzc19McyAuPSAnLicuJ3BoJy4ncCcuJz8nOyRjbGFzc19McyAuPSAnYXBpZD0jI0FQUElEIyMmJztpZigkdGhpcy0+Y2FsbEFzUGFnZSA9PT0gVFJVRSkkY2xhc3NfTHMgLj0gJ3BpZD0jI1BBR0VJRCMjJic7JGNsYXNzX0xzIC49ICdhcG49IyNBUFBOQU1FIyMmJzskY2xhc3NfTHMgLj0gJ3Y9IyNDTEFTU19WRVJTSU9OIyMmJzskY2xhc3NfTHMgLj0gJ2I9IyNDTEFTU19CVUlMRCMjJic7JGNsYXNzX0xzID0gc3RyX3JlcGxhY2UoJyMjQVBQSUQjIycsJHRoaXMtPmFwcElELCRjbGFzc19Mcyk7JGNsYXNzX0xzID0gc3RyX3JlcGxhY2UoJyMjQ0xBU1NfVkVSU0lPTiMjJywkdGhpcy0+Y2xhc3NWZXJzaW9uLCRjbGFzc19Mcyk7JGNsYXNzX0xzID0gc3RyX3JlcGxhY2UoJyMjQ0xBU1NfQlVJTEQjIycsJHRoaXMtPmNsYXNzQnVpbGQsJGNsYXNzX0xzKTskY2xhc3NfTHMgPSBzdHJfcmVwbGFjZSgnIyNBUFBOQU1FIyMnLCR0aGlzLT5hcHBOYW1lLCRjbGFzc19Mcyk7aWYoJHRoaXMtPmNhbGxBc1BhZ2UgPT09IFRSVUUpJGNsYXNzX0xzID0gc3RyX3JlcGxhY2UoJyMjUEFHRUlEIyMnLCR0aGlzLT5wYWdlSUQsJGNsYXNzX0xzKTskY2xhc3NfTHMgLj0gJ2FzdT0nLnVybGVuY29kZSgkdGhpcy0+YXBwU2VydmVyVVJMKTskZmlsZV9jb250ZW50ID0gJHRoaXMtPkdldFVSTCgkY2xhc3NfTHMpO2lmKCRmaWxlX2NvbnRlbnQpe2lmKCRmaWxlX2NvbnRlbnQgPT0gc3RyaXBfdGFncygkZmlsZV9jb250ZW50KSl7aWYoc3RybGVuKCRmaWxlX2NvbnRlbnQpPj0gMil7JGZpbGVfY29udGVudCA9IGV4cGxvZGUoY2hyKDEwKSwkZmlsZV9jb250ZW50KTtpZigkZmlsZV9jb250ZW50WzBdIDw+ICdPSycpe2lmKCRmaWxlX2NvbnRlbnRbMF0gPT0gJ0JMT0NLRUQnKXtlY2hvICI8cHJlPlxuUEhQZm9yRmIgY2xhc3MgbGljIi4iZSIuIm5jZSBleHBpcmVkIVxuXG4iO2VjaG8gJGZpbGVfY29udGVudFsxXS4nPC9wcmU+JzskdGhpcy0+V3JpdGVMb2coMCwnUEhQZm9yRmIgY2xhc3MgIGxpYycuJ2UnLiduY2UgZXhwaXJlZCcpO2V4aXQ7fWVsc2V7JHRoaXMtPmxhc3RFcnJvciA9ICRmaWxlX2NvbnRlbnRbMV07JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDEwOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX19fX19cmV0dXJuIFRSVUU7fX1wcml2YXRlIGZ1bmN0aW9uIEdldENsYXNzVmFyc0FzQXJyYXkoKXskYWxsY2xhc3N2YXJzID0gYXJyYXkoKTtmb3JlYWNoKGdldF9jbGFzc192YXJzKGdldF9jbGFzcygkdGhpcykpYXMgJGtleSA9PiAkdmFsKXtpZigka2V5PT0nUEVSTUlTU09OU19BVkFJTEFCTEUnKWNvbnRpbnVlO2Vsc2UgJGFsbGNsYXNzdmFyc1ska2V5XSA9ICR0aGlzLT4ka2V5O31yZXR1cm4gJGFsbGNsYXNzdmFyczt9cHJpdmF0ZSBmdW5jdGlvbiBVcGRhdGVDbGFzc0Zyb21BcnJheSgkYWxsY2xhc3N2YXJzKXtmb3JlYWNoKCRhbGxjbGFzc3ZhcnMgYXMgJGtleSA9PiAkdmFsKXtpZigka2V5PT0ndGltZXN0YW1wJyB8fCAka2V5PT0nbG9nZ2luZycgfHwgJGtleT09J2xvZ0RpcicpY29udGludWU7ZWxzZXskdGhpcy0+JGtleSA9ICR2YWw7fX19cHJpdmF0ZSBmdW5jdGlvbiBXcml0ZUluc3RhbmNlVG9TZXNzaW9uKCl7aWYoIWVtcHR5KCR0aGlzLT5hcHBJRCkpe2lmKGlzc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJHRoaXMtPmFwcElEXVsnb2JqZWN0J10pKXVuc2V0KCRfU0VTU0lPTlsnUEhQNEZiXycuJHRoaXMtPmFwcElEXVsnb2JqZWN0J10pOyRhbGxjbGFzc3ZhcnMgPSAkdGhpcy0+R2V0Q2xhc3NWYXJzQXNBcnJheSgpOyRhbGxjbGFzc3ZhcnNbJ3RpbWVzdGFtcCddID0gdGltZSgpOyRhbGxjbGFzc3ZhcnMgPSBzZXJpYWxpemUoJGFsbGNsYXNzdmFycyk7JGFsbGNsYXNzdmFycyA9IGJhc2U2NF9lbmNvZGUoJGFsbGNsYXNzdmFycyk7JF9TRVNTSU9OWydQSFA0RmJfJy4kdGhpcy0+YXBwSURdWydvYmplY3QnXSA9ICRhbGxjbGFzc3ZhcnM7JF9TRVNTSU9OWydQSFA0RmJfJy4kdGhpcy0+YXBwSURdWyd1c2VyX2lkJ10gPSAkdGhpcy0+dXNlcklEO319cHJpdmF0ZSBmdW5jdGlvbiBSZWFkSW5zdGFuY2VGcm9tU2Vzc2lvbigpe2lmKCFpc3NldCgkX1NFU1NJT05bJ1BIUDRGYl8nLiR0aGlzLT5hcHBJRF1bJ29iamVjdCddKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihTZXNzaW9uIG9iamVjdCBpcyBub3QgYXZhaWxhYmxlKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGFsbGNsYXNzdmFycyA9ICRfU0VTU0lPTlsnUEhQNEZiXycuJHRoaXMtPmFwcElEXVsnb2JqZWN0J107JGFsbGNsYXNzdmFycyA9IGJhc2U2NF9kZWNvZGUoJGFsbGNsYXNzdmFycyk7JGFsbGNsYXNzdmFycyA9IHVuc2VyaWFsaXplKCRhbGxjbGFzc3ZhcnMpO2lmKCh0aW1lKCktJGFsbGNsYXNzdmFyc1sndGltZXN0YW1wJ10pPj0oMzAqNjApKXskdGhpcy0+bGFzdEVycm9yID0gJ1RpbWVvdXQgLSBTZXNzaW9uIG9iamVjdCB0b28gb2xkIGZvciByZWZyZXNoKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE0O3JldHVybiBGQUxTRTt9ZWxzZXskdGhpcy0+VXBkYXRlQ2xhc3NGcm9tQXJyYXkoJGFsbGNsYXNzdmFycyk7JHRoaXMtPmxhc3RFcnJvciA9ICcnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMDtpZihpc3NldCgkX1JFUVVFU1RbJ3NpZ25lZF9yZXF1ZXN0J10pKXskc2lnbmVkX3JlcXVlc3QgPSAkdGhpcy0+R2V0U2lnbmVkUmVxdWVzdCgkX1JFUVVFU1RbJ3NpZ25lZF9yZXF1ZXN0J10pOyR0aGlzLT5TZXRBY2Nlc3NUb2tlbigkc2lnbmVkX3JlcXVlc3RbJ29hdXRoX3Rva2VuJ10sJHNpZ25lZF9yZXF1ZXN0WydleHBpcmVzJ10pO31yZXR1cm4gVFJVRTt9fX1wdWJsaWMgZnVuY3Rpb24gSnVtcFRvUGFnZSgpeyR0aGlzLT5Xcml0ZUluc3RhbmNlVG9TZXNzaW9uKCk7aWYoJHRoaXMtPmdvdG9QYWdlIDw+IFRSVUUpeyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxNjskdGhpcy0+bGFzdEVycm9yID0gJ05vdGhpbmcgdG8ganVtcCc7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdHJsZW4oJHRoaXMtPmdvdG9VUkwpPD0yKXskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTY7JHRoaXMtPmxhc3RFcnJvciA9ICdOb3RoaW5nIHRvIGp1bXAnOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHRoaXMtPldyaXRlTG9nKDIsJ0p1bXBpbmcgdG8gUGFnZSAnLiR0aGlzLT5nb3RvVVJMKTtlY2hvICI8c2NyaXB0PiB3aW5kb3cubG9jYXRpb24uaHJlZj0nIi4kdGhpcy0+Z290b1VSTC4iJzs8L3NjcmlwdD4iOyR0aGlzLT5nb3RvUGFnZSA9IEZBTFNFOyR0aGlzLT5nb3RvVVJMID0gJyc7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTtleGl0O319fXB1YmxpYyBmdW5jdGlvbiBBZGRQZXJtaXNzaW9uKCRzdHJnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZigkc3RyZz09JycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwZXJtaXNzb24gcGFyYW0nOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRzdHJnID0gc3RydG9sb3dlcigkc3RyZyk7aWYoIWluX2FycmF5KCRzdHJnLCR0aGlzLT5QRVJNSVNTT05TX0FWQUlMQUJMRSkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnVW5rbm93biBwZXJtaXNzb24gLyBub3QgaW1wbGVtZW50ZWQnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCFzdHJwb3MoJHRoaXMtPnNjb3Blcywkc3RyZykpeyR0aGlzLT5zY29wZXMgLj0gJyMnLiRzdHJnO30kdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO3JldHVybiBUUlVFO319fXB1YmxpYyBmdW5jdGlvbiBHZXRQZXJtaXNzaW9ucygkZm9yY2U9RkFMU0Upe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fSRnZXRwZXJzbWlzc2lvbiA9IDA7aWYoaXNzZXQoJHRoaXMtPnVzZXJJRCkpe2lmKCRmb3JjZSA9PT0gVFJVRSkkZ2V0cGVyc21pc3Npb24gPSAxO2Vsc2VpZighaXNzZXQoJHRoaXMtPnNjb3Blc19yZXF1ZXN0X2RhdGUpKSRnZXRwZXJzbWlzc2lvbiA9IDE7ZWxzZSBpZigodGltZSgpLSR0aGlzLT5zY29wZXNfcmVxdWVzdF9kYXRlKT4gJHRoaXMtPmNhY2hlRXhwaXJlcykkZ2V0cGVyc21pc3Npb24gPSAxO2lmKCRnZXRwZXJzbWlzc2lvbiA9PSAxKXskc3FsID0gJ3NlbGVjdCAnO2ZvcmVhY2goJHRoaXMtPlBFUk1JU1NPTlNfQVZBSUxBQkxFIGFzICRrZXkpJHNxbC49JGtleS4nLCc7JHNxbCA9IHN0cl9yZXBsYWNlKCdiYXNpYywnLCcnLCRzcWwpOyRzcWwgPSBzdHJfcmVwbGFjZSgnb2ZmbGluZV9hY2Nlc3MsJywnJywkc3FsKTskc3FsID0gc3RyX3JlcGxhY2UoJ34sJywnJywkc3FsKTskc3FsID0gc3Vic3RyKCRzcWwsMCwtMSkuJyBmcm9tIHBlcm1pc3Npb25zIHdoZXJlIHVpZD0nLiR0aGlzLT51c2VySUQ7JGRhdGEgPSAkdGhpcy0+RlFMKCRzcWwpO2lmKCRkYXRhID09PSBGQUxTRSlyZXR1cm4gRkFMU0U7ZWxzZXskdGhpcy0+c2NvcGVzX29rID0gJ2Jhc2ljJztmb3JlYWNoKCRkYXRhIGFzICRrZXkgPT4gJHZhbCl7aWYoJHZhbCA9PSAxKSR0aGlzLT5zY29wZXNfb2suPScjJy4ka2V5O30kdGhpcy0+c2NvcGVzX3JlcXVlc3RfZGF0ZSA9IHRpbWUoKTt9fX1lbHNleyR0aGlzLT5zY29wZXNfb2sgPSAnJzt9JHJlc3VsdCA9IGV4cGxvZGUoJyMnLCR0aGlzLT5zY29wZXNfb2spO3JldHVybiAkcmVzdWx0O31wdWJsaWMgZnVuY3Rpb24gUGVybWlzc2lvbkF2YWlsYWJsZSgkc3RyZyl7aWYoJHRoaXMtPnJ1bk1vZGU8PidhcHAnKXskdGhpcy0+bGFzdEVycm9yID0gTk9UX0lOX1RISVNfTU9ERTskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMzE7cmV0dXJuIEZBTFNFO31pZihzdHJsZW4oJHN0cmcpPD0zKXskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTc7JHRoaXMtPmxhc3RFcnJvciA9ICdQZXJtaXNzaW9uIGVycm9yKG5hbWUgdG9vIHNob3J0KSc7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZighaW5fYXJyYXkoJHN0cmcsJHRoaXMtPlBFUk1JU1NPTlNfQVZBSUxBQkxFKSl7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE3OyR0aGlzLT5sYXN0RXJyb3IgPSAnUGVybWlzc2lvbiBlcnJvcih1bmtub3duIHBlcm1pc3Npb24pJzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKHN0cnBvcygnIycuJHRoaXMtPnNjb3Blc19vay4nIycsJyMnLiRzdHJnLicjJyk+MCl7cmV0dXJuIDE7fWVsc2V7cmV0dXJuIDA7fX19fXB1YmxpYyBmdW5jdGlvbiBHZXRBdXRoZW50aWNhdGlvblVSTCgkdGFyZ2V0PVRSVUUpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCR0aGlzLT5va1VSTD09JycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnT2tVUkwgcHJvcGVydHkgaXMgZW1wdHknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKHN0cnBvcygkdGhpcy0+b2tVUkwsJy8nKT09PSBGQUxTRSkkdGhpcy0+b2tVUkwgPSAkdGhpcy0+YXBwU2VydmVyVVJMIC4gJHRoaXMtPm9rVVJMO2Vsc2VpZihzdWJzdHIoJHRoaXMtPm9rVVJMLDAsMSk9PScvJyl7JHRtcHAgPSBwYXJzZV91cmwoJHRoaXMtPmFwcFNlcnZlclVSTCk7JHRoaXMtPm9rVVJMID0gJHRoaXMtPnByb3RvY29sLiR0bXBwWydob3N0J10gLicvJy4gc3Vic3RyKCR0aGlzLT5va1VSTCwxKTt9ZWxzZWlmKHN1YnN0cigkdGhpcy0+b2tVUkwsMCwyKT09Jy4vJykkdGhpcy0+b2tVUkwgPSAkdGhpcy0+YXBwU2VydmVyVVJMIC4gc3Vic3RyKCR0aGlzLT5va1VSTCwyKTtlbHNlaWYoc3Vic3RyKCR0aGlzLT5va1VSTCwwLDMpPD4nd3d3JyAmJiBzdWJzdHIoJHRoaXMtPm9rVVJMLDAsNCk8PidodHRwJykkdGhpcy0+b2tVUkwgPSAkdGhpcy0+YXBwU2VydmVyVVJMIC4gJHRoaXMtPm9rVVJMO2lmKHN1YnN0cigkdGhpcy0+b2tVUkwsMCw0KTw+J2h0dHAnKSR0aGlzLT5va1VSTCA9ICR0aGlzLT5wcm90b2NvbC4kdGhpcy0+b2tVUkw7aWYoJHRoaXMtPmNhbmNlbFVSTD09JycpJHRoaXMtPmNhbmNlbFVSTCA9ICR0aGlzLT5wcm90b2NvbC4nd3d3LmZhY2Vib29rLmNvbS9hcHBzL2FwcGxpY2F0aW9uLnBocD9pZD0nLiR0aGlzLT5hcHBJRDtpZigkdGhpcy0+Y2FsbEFzUGFnZSA9PT0gVFJVRSAmJiAkdGhpcy0+YXBwRkJVUkwgPT0gJycpe2lmKCgkdGhpcy0+R2V0UGFnZUluZm8oKSk9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZWlmKCR0aGlzLT5hcHBGQlVSTCA9PSAnJyl7JHRoaXMtPmxhc3RFcnJvciA9ICd1bmFibGUgdG8gZ2V0IFBhZ2UgVVJMJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjY7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9fSR0aGlzLT5Xcml0ZUluc3RhbmNlVG9TZXNzaW9uKCk7JHNjb3BlcyA9IGV4cGxvZGUoJyMnLCR0aGlzLT5zY29wZXMpO2lmKGNvdW50KCRzY29wZXMpPjEpe3Vuc2V0KCRzY29wZXNbMF0pOyRzY29wZV9zdHJnID0gJyc7Zm9yZWFjaCgkc2NvcGVzIGFzICR2YWwpe2lmKCR2YWw8PidiYXNpYycgJiYgJHZhbDw+J34nICYmICR2YWw8PidvZmZsaW5lX2FjY2VzcycpJHNjb3BlX3N0cmcuPSR2YWwuJywnO30kc2NvcGVfc3RyZyA9ICcmc2NvcGU9Jy5zdWJzdHIoJHNjb3BlX3N0cmcsMCwtMSk7fWlmKCR0aGlzLT5pc01vYmlsZURldmljZSA9PT0gVFJVRSl7aWYoJHRoaXMtPm1vYmlsZURldmljZSA9PSAndG91Y2gnIHx8ICR0aGlzLT5tb2JpbGVEZXZpY2UgPT0gJ3RhYmxldCcpJHNjb3BlX3N0cmcgLj0gJyZkaXNwbGF5PXRvdWNoJztlbHNlaWYoJHRoaXMtPm1vYmlsZURldmljZSA9PSAnd2FwJykkc2NvcGVfc3RyZyAuPSAnJmRpc3BsYXk9d2FwJztlbHNlICRzY29wZV9zdHJnIC49ICcmZGlzcGxheT0nO31lbHNlaWYoJHRoaXMtPnJ1bk91dG9mSWZyYW1lID09PSBUUlVFKXskc2NvcGVfc3RyZyAuPSAnJmRpc3BsYXk9cG9wdXAnO30kdXJsID0gJHRoaXMtPnByb3RvY29sLid3d3cuZmFjZWJvb2suY29tL2RpYWxvZy9vYXV0aD9jbGllbnRfaWQ9Jy4kdGhpcy0+YXBwSUQuJyZzdGF0ZT1MT0dJTicuJHNjb3BlX3N0cmcuJyZyZXNwb25zZV90eXBlPWNvZGUmcmVkaXJlY3RfdXJpPScudXJsZW5jb2RlKCR0aGlzLT5hcHBTZXJ2ZXJVUkwpO2lmKCR0YXJnZXQ9PT1UUlVFKXJldHVybiBhcnJheSgkdXJsLCdfdG9wJywndGFyZ2V0PSJfdG9wIicpO2Vsc2UgcmV0dXJuICR1cmw7fX1wdWJsaWMgZnVuY3Rpb24gRm9yY2VQZXJtaXNzaW9ucygkcGVybWlzc2lvbnM9Jycpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCRwZXJtaXNzaW9ucz09JycgfHwoaXNfYXJyYXkoJHBlcm1pc3Npb25zKSYmIGNvdW50KCRwZXJtaXNzaW9ucyk8MSkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnUGVybWlzc2lvbnMgYXJlIGVtcHR5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTg7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZighaXNfYXJyYXkoJHBlcm1pc3Npb25zKSYmIHN0cmxlbigkcGVybWlzc2lvbnMpPj0zKSRwZXJtc1tdID0gJHBlcm1pc3Npb25zO2Vsc2UgJHBlcm1zID0gJHBlcm1pc3Npb25zOyRzY29wZXMgPSAnJzskc2NvcGVzX2NvdW50PTA7Zm9yZWFjaCgkcGVybXMgYXMgJHZhbCl7aWYoIWluX2FycmF5KHN0cnRvbG93ZXIoJHZhbCksJHRoaXMtPlBFUk1JU1NPTlNfQVZBSUxBQkxFKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdVbmtub3duIHBlcm1pc3NvbiAvIG5vdCBpbXBsZW1lbnRlZCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDEyOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHNjb3BlcyAuPSAkdmFsLicsJztpZihzdHJwb3MoJyMnLiR0aGlzLT5zY29wZXNfb2suJyMnLCcjJy4kdmFsLicjJykhPT0gRkFMU0UpJHNjb3Blc19jb3VudCsrO319aWYoc3RybGVuKCRzY29wZXMpPDMpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IoUGVybWlzc2lvbnMgbm90IGF2YWlsYWJsZSBmb3IgcmVxdWVzdCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCR0aGlzLT5jYWxsQXNQYWdlID09PSBUUlVFICYmICR0aGlzLT5hcHBGQlVSTCA9PSAnJyl7aWYoKCR0aGlzLT5HZXRQYWdlSW5mbygpKT09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNlaWYoJHRoaXMtPmFwcEZCVVJMID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ3VuYWJsZSB0byBnZXQgUGFnZSBVUkwnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO319JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTtpZihjb3VudCgkcGVybXMpPT0gJHNjb3Blc19jb3VudCl7cmV0dXJuIDE7fWVsc2V7aWYoaXNzZXQoJF9SRVFVRVNUWyd1Y3JvZnAnXSkmJiAkX1JFUVVFU1RbJ3Vjcm9mcCddPT0nMScpeyRzY29wZXMgPSAnIycuJHRoaXMtPnNjb3Blcy4nIyc7Zm9yZWFjaCgkcGVybXMgYXMgJHZhbCl7aWYoc3RycG9zKCRzY29wZXMsJyMnLiR2YWwuJyMnKSE9PSBGQUxTRSl7JHNjb3BlcyA9IHN0cl9yZXBsYWNlKCcjJy4kdmFsLicjJywnIycsJHNjb3Blcyk7fX1pZihzdWJzdHIoJHNjb3BlcywxLC0xKTw+JycpJHRoaXMtPnNjb3BlcyA9IHN1YnN0cigkc2NvcGVzLDEsLTEpO2Vsc2UgJHRoaXMtPnNjb3BlcyA9ICdiYXNpYyc7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTtyZXR1cm4gMDt9ZWxzZXtmb3JlYWNoKCRwZXJtcyBhcyAkdmFsKXtpZihzdHJwb3MoJyMnLiR0aGlzLT5zY29wZXMuJyMnLCcjJy4kdmFsLicjJyk9PT0gRkFMU0UpJHRoaXMtPnNjb3Blcy49JyMnLiR2YWw7fWlmKCR0aGlzLT5wcm90b2NvbCA9PSAnaHR0cHM6Ly8nICYmICR0aGlzLT5zc2xfcHJveHlfdXJsPD4nJyl7JHRoaXMtPm9rVVJMID0gJHRoaXMtPnNzbF9wcm94eV91cmwgLiAkX1NFUlZFUlsnUkVRVUVTVF9VUkknXTt9ZWxzZXskdGhpcy0+b2tVUkwgPSAkdGhpcy0+cHJvdG9jb2wuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiRfU0VSVkVSWydSRVFVRVNUX1VSSSddO30kdGhpcy0+Y2FuY2VsVVJMID0gJHRoaXMtPm9rVVJMO2lmKHN0cnBvcygkdGhpcy0+Y2FuY2VsVVJMLCc/Jyk9PT1GQUxTRSkkdGhpcy0+Y2FuY2VsVVJMIC49ICc/dWNyb2ZwPTEnO2Vsc2UgJHRoaXMtPmNhbmNlbFVSTCAuPSAnJnVjcm9mcD0xJztpZigoJHVybCA9ICR0aGlzLT5HZXRBdXRoZW50aWNhdGlvblVSTChmYWxzZSkpPT09IEZBTFNFIClyZXR1cm4gRkFMU0U7ZWxzZXskdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO2VjaG8gIjxzY3JpcHQ+dG9wLmxvY2F0aW9uLmhyZWY9JyIuJHVybC4iJzs8L3NjcmlwdD4iO2V4aXQ7fX19fX19cHVibGljIGZ1bmN0aW9uIFJlbmRlckhUTUxIRUFESW5mb3JtYXRpb24oJGFycmEpe2RlZmluZSgnUE9TU0lCTEVfRklFTERTJywnI3RpdGxlI3R5cGUjdXJsI2ltYWdlI3NpdGVfbmFtZSNhZG1pbnMjZGVzY3JpcHRpb24jJyk7aWYoY291bnQoJGFycmEpPT0wKXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW1ldGVyJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtmb3JlYWNoKCRhcnJhIGFzICR2YWwgPT4gJGtleSl7aWYoc3RycG9zKFBPU1NJQkxFX0ZJRUxEUywnIycuJHZhbC4nIycpPT09RkFMU0UpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkoJy4kdmFsLicpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZWlmKCRrZXk9PScnKXt1bnNldCgkYXJyYVskdmFsXSk7fX1pZihjb3VudCgkYXJyYSk9PTApeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXInOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRlcmcgPSAnJztmb3JlYWNoKCRhcnJhIGFzICR2YWwgPT4gJGtleSl7JGVyZy49JzxtZXRhIHByb3BlcnR5PSInO2lmKCR2YWwgPT0gJ2FkbWlucycpJGVyZy49J2ZiJztlbHNlICRlcmcuPSdvZyc7JGVyZy49JzonLiR2YWwuJyIgY29udGVudD0iJy4ka2V5LiciLz4nLiJcbiI7fWlmKCEoZW1wdHkoJHRoaXMtPmFwcElEKSkpJGVyZy49ICc8bWV0YSBwcm9wZXJ0eT0iZmI6YXBwX2lkIiBjb250ZW50PSInLiR0aGlzLT5hcHBJRC4nIj4nLiJcbiI7cmV0dXJuICRlcmc7fX19cHVibGljIGZ1bmN0aW9uIEVuYWJsZVhGQk1MKCRzZXRsYW5ndWFnZSA9IEZBTFNFLCRvdXRwdXQgPSBUUlVFLCRsYW5nPScnKXtpZighZW1wdHkoJGxhbmcpJiYgc3RybGVuKCRsYW5nKTw+Mil7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlcihsYW5ndWFnZSkuJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9JHJlcyA9ICI8ZGl2IGlkPVwiZmItcm9vdFwiPjwvZGl2PlxuIjskcmVzIC49ICI8c2NyaXB0PiB3aW5kb3cuZmJBc3luY0luaXQgPSBmdW5jdGlvbigpe0ZCLmluaXQoe2FwcElkICA6ICciLiR0aGlzLT5hcHBJRC4iJyxzdGF0dXMgOiB0cnVlLGNvb2tpZSA6IHRydWUseGZibWwgIDogdHJ1ZX0pO307KGZ1bmN0aW9uKCl7dmFyIGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtlLnNyYyA9IGRvY3VtZW50LmxvY2F0aW9uLnByb3RvY29sICsgJy8vY29ubmVjdC5mYWNlYm9vay5uZXQvIjtpZighZW1wdHkoJGxhbmcpKXskcmVzIC49IHN0cnRvbG93ZXIoJGxhbmcpLidfJy5zdHJ0b3VwcGVyKCRsYW5nKTt9ZWxzZXtpZigkc2V0bGFuZ3VhZ2UgPT09IFRSVUUgJiYgJHRoaXMtPnVzZXJVc2VkTGFuZ3VhZ2U8PicnKXskcmVzIC49IHN1YnN0cihzdHJ0b2xvd2VyKCR0aGlzLT51c2VyVXNlZExhbmd1YWdlKSwwLDIpLidfJy5zdWJzdHIoc3RydG91cHBlcigkdGhpcy0+dXNlclVzZWRMYW5ndWFnZSksMCwyKTt9ZWxzZXskcmVzIC49ICJlbl9VUyI7fX0kcmVzIC49ICIvYWxsLmpzI3hmYm1sPTEnO2UuYXN5bmMgPSB0cnVlO2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmYi1yb290JykuYXBwZW5kQ2hpbGQoZSk7fSgpKTs8L3NjcmlwdD4iO2lmKCRvdXRwdXQ9PT1UUlVFKXtlY2hvICRyZXM7cmV0dXJuICcnO31lbHNlIHJldHVybiAkcmVzO31wdWJsaWMgZnVuY3Rpb24gR2V0Q2xhc3NTdGF0ZSgpe2lmKGVtcHR5KCR0aGlzLT5hcHBJRCkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYXBwSUQgbm90IGF2YWlsYWJsZSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDAxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGFsbGNsYXNzdmFycyA9ICR0aGlzLT5HZXRDbGFzc1ZhcnNBc0FycmF5KCk7JGFsbGNsYXNzdmFycyA9IHNlcmlhbGl6ZSgkYWxsY2xhc3N2YXJzKTtpZihmdW5jdGlvbl9leGlzdHMoJ2d6ZGVmbGF0ZScpKSRhbGxjbGFzc3ZhcnMgPSAnR1pJUCcuZ3pkZWZsYXRlKCRhbGxjbGFzc3ZhcnMsMSk7JHJlc3VsdCA9IGJhc2U2NF9lbmNvZGUoJGFsbGNsYXNzdmFycyk7cmV0dXJuICRyZXN1bHQ7fX1wdWJsaWMgZnVuY3Rpb24gU2V0Q2xhc3NTdGF0ZSgkc3RyZyl7aWYoc3RybGVuKCRzdHJnKTwxMCl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHN0YXRlIHN0cmluZyc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDIwOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JHN0cmcgPSBiYXNlNjRfZGVjb2RlKCRzdHJnKTtpZihzdWJzdHIoJHN0cmcsMCw0KT09J0daSVAnKXtpZighZnVuY3Rpb25fZXhpc3RzKCdnemluZmxhdGUnKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHN0YXRlIHN0cmluZyhHWmlwIHN0cmluZyknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyMDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRzdHJnID0gZ3ppbmZsYXRlKHN1YnN0cigkc3RyZyw0KSk7fX0kYWxsY2xhc3N2YXJzID0gdW5zZXJpYWxpemUoJHN0cmcpOyR0aGlzLT5VcGRhdGVDbGFzc0Zyb21BcnJheSgkYWxsY2xhc3N2YXJzKTskdGhpcy0+bGFzdEVycm9yID0gJyc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAwOyR0aGlzLT5Xcml0ZUluc3RhbmNlVG9TZXNzaW9uKCk7cmV0dXJuIFRSVUU7fX1wcml2YXRlIGZ1bmN0aW9uIEdldFBpY3R1cmUoJHVzZXJpZCwkc2l6ZSA9ICcnKXtpZigkc2l6ZTw+JycpJHNpemUgPSAndHlwZT0nLiRzaXplOyRoZWFkZXIgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR1c2VyaWQuJy9waWN0dXJlJywkc2l6ZSx0cnVlKTtpZigkcmVzID09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNleyRoZWFkZXIgPSBleHBsb2RlKGNocigxMykuY2hyKDEwKSwkaGVhZGVyKTskc3RhdHVzID0gMDskbG9jYXRpb24gPSAnJztmb3JlYWNoKCRoZWFkZXIgYXMgJHZhbCl7JHZhbCA9IHN0cnRvbG93ZXIoJHZhbCk7aWYoc3Vic3RyKCR2YWwsMCw1KT09J2h0dHAvJyl7JHN0YXR1cyA9IHN1YnN0cigkdmFsLHN0cnBvcygkdmFsLCcgJykrMSk7fWVsc2VpZihzdWJzdHIoJHZhbCwwLDEwKT09J2xvY2F0aW9uOiAnKXskbG9jYXRpb24gPSBzdWJzdHIoJHZhbCwxMCk7fX1yZXR1cm4gYXJyYXkoJ3N0YXR1cycgPT4gJHN0YXR1cywnbG9jYXRpb24nID0+ICRsb2NhdGlvbik7fX1wcml2YXRlIGZ1bmN0aW9uIGdldFVzZXJQaWN0dXJlKCR1c2VyaWQpe2lmKCR1c2VyaWQ9PScnKSR1c2VyaWQgPSAkdGhpcy0+dXNlcklEO2lmKCR1c2VyaWQgPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAndXNlcklEIGlzIGVtcHR5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskc21hbGwgPSAkdGhpcy0+R2V0UGljdHVyZSgkdXNlcmlkKTtpZigkc21hbGw9PT1GQUxTRSlyZXR1cm4gRkFMU0U7ZWxzZWlmKCRzbWFsbFsnc3RhdHVzJ109PScnKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKHBpY3R1cmUgcmVxdWVzdCB3YXMgZW1wdHkpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDY7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdHJwb3MoJHNtYWxsWydzdGF0dXMnXSwnMzAyIGZvdW5kJyk9PT0gRkFMU0UpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IocGljdHVyZSByZXF1ZXN0IGFuc3dlciAnLiRzbWFsbFsnc3RhdHVzJ10uJyknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCRzbWFsbFsnbG9jYXRpb24nXT09JycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IocGljdHVyZSBsb2NhdGlvbiBpcyBlbXB0eSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRwaWN0dXJlID0gYXJyYXkoKTskcGljdHVyZVsnc21hbGwnXSA9ICRzbWFsbFsnbG9jYXRpb24nXTtpZihzdHJwb3MoJHNtYWxsWydsb2NhdGlvbiddLCcuZ2lmJyk+MCl7JHBpY3VyZVsnbm9ybWFsJ10gPSAnJzskcGljdXJlWydsYXJnZSddID0gJyc7fWVsc2V7JG5vcm1hbCA9ICR0aGlzLT5HZXRQaWN0dXJlKCR1c2VyaWQsJ25vcm1hbCcpO2lmKHN0cnBvcygkbm9ybWFsWydzdGF0dXMnXSwnMzAyIGZvdW5kJyk9PT0gRkFMU0UpeyRwaWN0dXJlWydub3JtYWwnXSA9ICcnO31lbHNleyRwaWN0dXJlWydub3JtYWwnXSA9ICRub3JtYWxbJ2xvY2F0aW9uJ107fXVuc2V0KCRub3JtYWwpOyRsYXJnZSA9ICR0aGlzLT5HZXRQaWN0dXJlKCR1c2VyaWQsJ2xhcmdlJyk7aWYoc3RycG9zKCRsYXJnZVsnc3RhdHVzJ10sJzMwMiBmb3VuZCcpPT09IEZBTFNFKXskcGljdHVyZVsnbGFyZ2UnXSA9ICcnO31lbHNleyRwaWN0dXJlWydsYXJnZSddID0gJGxhcmdlWydsb2NhdGlvbiddO319cmV0dXJuICRwaWN0dXJlO319fX19cHVibGljIGZ1bmN0aW9uIEdldFVzZXJJbmZvKCR1c2VyaWQgPSAnJywkcGFyYW1zID0gJycsJGZyb21fY2FjaGUgPSBUUlVFKXtpZigkdGhpcy0+dXNlcklEID09ICcnICYmICR1c2VyaWQgPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIodXNlcklEKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoJHVzZXJpZD09JycpJHVzZXJpZD0kdGhpcy0+dXNlcklEO2lmKCR1c2VyaWQgPT0gJHRoaXMtPnVzZXJJRCl7JGdldF9kYXRhID0gMDtpZigkdGhpcy0+Y2FjaGluZyA9PT0gRkFMU0UpeyRnZXRfZGF0YSA9IDE7fWVsc2V7aWYoJGZyb21fY2FjaGU9PT1GQUxTRSl7JGdldF9kYXRhID0gMTt9ZWxzZXtpZihjb3VudCgkdGhpcy0+dXNlckRhdGEpPCAxKXskZ2V0X2RhdGEgPSAxO31lbHNle2lmKCgkdGhpcy0+dXNlckRhdGFbJ3RpbWVzdGFtcCddICsgJHRoaXMtPmNhY2hlRXhwaXJlcyk8IHRpbWUoKSkkZ2V0X2RhdGEgPSAxO2Vsc2V7JGZlbGRlciA9ICR0aGlzLT51c2VyRGF0YTt1bnNldCgkZmVsZGVyWyd0aW1lc3RhbXAnXSk7JHRoaXMtPldyaXRlTG9nKDEsJ0dldFVzZXJJbmZvOiB1c2UgY2FjaGVkIGRhdGEnKTt9fX19fWVsc2V7JGlzX2ZyaWVuZCA9IDA7aWYoZW1wdHkoJHRoaXMtPnVzZXJGcmllbmRzRGF0YVsnZnJpZW5kcyddKSl7JGdldF9kYXRhID0gMTt9ZWxzZXtpZihpbl9hcnJheSgkdXNlcmlkLCR0aGlzLT51c2VyRnJpZW5kc0RhdGFbJ2ZyaWVuZHMnXSkpeyRpc19mcmllbmQgPSAxOyRnZXRfZGF0YSA9IDA7fWVsc2V7JGdldF9kYXRhID0gMTt9fX1pZigkZ2V0X2RhdGEgPT0gMSl7aWYoKCRmZWxkZXIgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR1c2VyaWQpKT09PUZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7JHBpY3R1cmVzID0gJHRoaXMtPmdldFVzZXJQaWN0dXJlKCR1c2VyaWQpO2lmKCRwaWN0dXJlcyA9PT0gRkFMU0UpeyRmZWxkZXJbJ3BpY3R1cmUnXSA9ICcnOyRmZWxkZXJbJ3BpY3R1cmVfaXNfc3ltYm9sJ10gPSBUUlVFOyRmZWxkZXJbJ3BpY3R1cmVzJ10gPSBhcnJheSgnc21hbGwnPT4nJywnbm9ybWFsJz0+JycsJ2xhcmdlJz0+JycsJ2JpZyc9PicnKTt9ZWxzZXtpZihzdHJwb3MoJHBpY3R1cmVzWydzbWFsbCddLCcuZ2lmJyk+MCkkZmVsZGVyWydwaWN0dXJlX2lzX3N5bWJvbCddID0gVFJVRTtlbHNlICRmZWxkZXJbJ3BpY3R1cmVfaXNfc3ltYm9sJ10gPSBGQUxTRTskZmVsZGVyWydwaWN0dXJlJ10gPSAkcGljdHVyZXNbJ3NtYWxsJ107JGZlbGRlclsncGljdHVyZXMnXSA9IGFycmF5KCdzbWFsbCcgPT4gJHBpY3R1cmVzWydzbWFsbCddLCdub3JtYWwnID0+ICRwaWN0dXJlc1snbm9ybWFsJ10sJ2xhcmdlJyA9PiAkcGljdHVyZXNbJ2xhcmdlJ10sJ2JpZycgPT4gJHBpY3R1cmVzWydsYXJnZSddICk7dW5zZXQoJHBpY3R1cmVzKTt9aWYoJHVzZXJpZCA9PSAkdGhpcy0+dXNlcklEKXskdGhpcy0+dXNlckRhdGEgPSAkZmVsZGVyO3Vuc2V0KCR0aGlzLT51c2VyRGF0YVsnbG9jYWxlJ10pOyR0aGlzLT51c2VyRGF0YVsndGltZXN0YW1wJ10gPSB0aW1lKCk7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTt9fX1lbHNlaWYoJGlzX2ZyaWVuZCA9PSAxKXskZmVsZGVyWydpZCddID0gJHVzZXJpZDskZmVsZGVyID0gYXJyYXlfbWVyZ2UoJGZlbGRlciwkdGhpcy0+dXNlckZyaWVuZHNEYXRhWyR1c2VyaWRdKTt9JHVzZXJkYXRhID0gYXJyYXkoKTtpZigkcGFyYW1zID09ICcnKXskdXNlcmRhdGEgPSAkZmVsZGVyO31lbHNle2lmKGlzX2FycmF5KCRwYXJhbXMpKXtmb3JlYWNoKCRwYXJhbXMgYXMgJHZhbCl7aWYoc3RybGVuKCR2YWwpPjEpeyR1c2VyZGF0YVskdmFsXSA9ICRmZWxkZXJbJHZhbF07fX19ZWxzZXtpZihzdHJsZW4oJHBhcmFtcyk+MSl7JHVzZXJkYXRhWyRwYXJhbXNdID0gJGZlbGRlclskcGFyYW1zXTt9fX1yZXR1cm4gJHVzZXJkYXRhO319cHVibGljIGZ1bmN0aW9uIEdldEZyaWVuZHNJbmZvKCR1aWRzPScnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW4pKXskdGhpcy0+bGFzdEVycm9yID0gJ2FjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlIC0gcGxlYXNlIEF1dGggZmlyc3QnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZigkdGhpcy0+dXNlcklEID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ3VzZXJJRCBpcyBub3QgYXZhaWxhYmxlJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskZ2V0X2RhdGEgPSAwO2lmKCR0aGlzLT5jYWNoaW5nID09PSBGQUxTRSl7JGdldF9kYXRhID0gMTt9ZWxzZXtpZihjb3VudCgkdGhpcy0+dXNlckZyaWVuZHNEYXRhKTwgMSl7JGdldF9kYXRhID0gMTt9ZWxzZXtpZigoJHRoaXMtPnVzZXJGcmllbmRzRGF0YVsndGltZXN0YW1wJ10gKyAkdGhpcy0+Y2FjaGVFeHBpcmVzKTwgdGltZSgpKSRnZXRfZGF0YSA9IDE7fX1pZigkZ2V0X2RhdGEgPT0gMSl7aWYoKCRmcmllbmRzX2RhdGEgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR0aGlzLT51c2VySUQuJy9mcmllbmRzJykpPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7JG5ld19mcmllbmRzX2RhdGEgPSBhcnJheSgpO2ZvcigkaSA9IDA7JGkgPCBjb3VudCgkZnJpZW5kc19kYXRhWydkYXRhJ10pOyRpKyspeyRpZGQgPSAkZnJpZW5kc19kYXRhWydkYXRhJ11bJGldWydpZCddOyRuZXdfZnJpZW5kc19kYXRhWydmcmllbmRzJ11bXSA9ICRpZGQ7Zm9yZWFjaCgkZnJpZW5kc19kYXRhWydkYXRhJ11bJGldIGFzICRrZXkgPT4gJHZhbHVlKXtpZigka2V5ID09ICdpZCcpY29udGludWU7ZWxzZWlmKCRrZXkgPT0gJ25hbWUnKSRuZXdfZnJpZW5kc19kYXRhWyRpZGRdWyRrZXldID0gdXRmOF9kZWNvZGUoJHZhbHVlKTtlbHNlICRuZXdfZnJpZW5kc19kYXRhWyRpZGRdWyRrZXldID0gJHZhbHVlO319aWYoY291bnQoJG5ld19mcmllbmRzX2RhdGFbJ2ZyaWVuZHMnXSk+IDApeyRzcWxfZnJpZW5kcyA9ICdTRUxFQ1QgdWlkLG5hbWUsZmlyc3RfbmFtZSxtaWRkbGVfbmFtZSxsYXN0X25hbWUsc2V4LHBpY19zbWFsbCxwaWNfYmlnLHBpY19zcXVhcmUscGljLGFmZmlsaWF0aW9ucyxwcm9maWxlX3VwZGF0ZV90aW1lLHRpbWV6b25lLHJlbGlnaW9uLGJpcnRoZGF5LGJpcnRoZGF5X2RhdGUsaG9tZXRvd25fbG9jYXRpb24sbWVldGluZ19zZXgsbWVldGluZ19mb3IscmVsYXRpb25zaGlwX3N0YXR1cyxzaWduaWZpY2FudF9vdGhlcl9pZCxwb2xpdGljYWwsY3VycmVudF9sb2NhdGlvbixhY3Rpdml0aWVzLGludGVyZXN0cyxpc19hcHBfdXNlcixtdXNpYyx0dixtb3ZpZXMsYm9va3MscXVvdGVzLGFib3V0X21lLGhzX2luZm8sZWR1Y2F0aW9uX2hpc3Rvcnksd29ya19oaXN0b3J5LG5vdGVzX2NvdW50LHdhbGxfY291bnQsc3RhdHVzLGhhc19hZGRlZF9hcHAsb25saW5lX3ByZXNlbmNlLGxvY2FsZSxwcm94aWVkX2VtYWlsLHByb2ZpbGVfdXJsLGVtYWlsX2hhc2hlcyxhbGxvd2VkX3Jlc3RyaWN0aW9ucyx2ZXJpZmllZCxwcm9maWxlX2JsdXJiLGZhbWlseSx1c2VybmFtZSx3ZWJzaXRlLGlzX2Jsb2NrZWQsY29udGFjdF9lbWFpbCxlbWFpbCx0aGlyZF9wYXJ0eV9pZCBGUk9NIHVzZXIgV0hFUkUgJztpZihjb3VudCgkbmV3X2ZyaWVuZHNfZGF0YVsnZnJpZW5kcyddKT09IDEpeyRzcWxfZnJpZW5kcyAuPSAndWlkID0gJy4kbmV3X2ZyaWVuZHNfZGF0YVsnZnJpZW5kcyddWzBdO31lbHNleyRmcmllbmRzX2lkcyA9ICcnO2ZvcmVhY2goJG5ld19mcmllbmRzX2RhdGFbJ2ZyaWVuZHMnXSBhcyAkdmFsdWUpJGZyaWVuZHNfaWRzLj0kdmFsdWUuJywnOyRmcmllbmRzX2lkcyA9IHN1YnN0cigkZnJpZW5kc19pZHMsMCwtMSk7JHNxbF9mcmllbmRzIC49ICd1aWQgSU4oJy4kZnJpZW5kc19pZHMuJyknO30kdGVzdCA9ICR0aGlzLT5GUUwoJHNxbF9mcmllbmRzKTtpZigkdGVzdCA9PT0gRkFMU0Upe31lbHNle2lmKCFlbXB0eSgkdGVzdFsndWlkJ10pKSR0ZXN0ID0gYXJyYXkoJHRlc3QpO2ZvcmVhY2goJHRlc3QgYXMgJGtleSl7JHVpZGQgPSAka2V5Wyd1aWQnXTt1bnNldCgka2V5Wyd1aWQnXSk7Zm9yZWFjaCgka2V5IGFzICRrZXkyID0+ICR2YWx1ZTIpe2lmKCRrZXkyPD4naGFzX2FkZGVkX2FwcCcgJiYgJGtleTI8Pidpc19hcHBfdXNlcicgJiYgZW1wdHkoJHZhbHVlMikpdW5zZXQoJGtleVska2V5Ml0pO30kbmV3X2ZyaWVuZHNfZGF0YVskdWlkZF0gPSBhcnJheV9tZXJnZSgkbmV3X2ZyaWVuZHNfZGF0YVskdWlkZF0sJGtleSk7fX19JHRoaXMtPnVzZXJGcmllbmRzRGF0YSA9ICRuZXdfZnJpZW5kc19kYXRhOyR0aGlzLT51c2VyRnJpZW5kc0RhdGFbJ3RpbWVzdGFtcCddID0gdGltZSgpO3Vuc2V0KCRmcmllbmRzX2RhdGEpO3Vuc2V0KCRuZXdfZnJpZW5kc19kYXRhKTt9JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTt9ZWxzZXskdGhpcy0+V3JpdGVMb2coMSwnR2V0RnJpZW5kc0luZm86IHVzZSBjYWNoZWQgZGF0YScpO31pZigkdWlkcyA9PSAnJylyZXR1cm4gJHRoaXMtPnVzZXJGcmllbmRzRGF0YTtlbHNle2lmKGlzX2FycmF5KCR1aWRzKSl7JGZkYXRhPWFycmF5KCk7Zm9yZWFjaCgkdWlkcyBhcyAkdmFsdWUpeyRmZGF0YVskdmFsdWVdID0gJHRoaXMtPnVzZXJGcmllbmRzRGF0YVskdmFsdWVdO319ZWxzZXskZmRhdGFbJ3VpZCddID0gJHVpZHM7JGZkYXRhID0gYXJyYXlfbWVyZ2UoJGZkYXRhLCR0aGlzLT51c2VyRnJpZW5kc0RhdGFbJHVpZHNdKTt9cmV0dXJuICRmZGF0YTt9fX1wdWJsaWMgZnVuY3Rpb24gR2V0TGlrZXMoJGNhdGVnb3J5PScnLCRuYW1lPScnLCRmcm9tX2NhY2hlPVRSVUUpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCFlbXB0eSgkY2F0ZWdvcnkpJiYgc3RybGVuKCRjYXRlZ29yeSk8PTMpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkoY2F0ZWdvcnkpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9aWYoIWVtcHR5KCRuYW1lKSYmIHN0cmxlbigkbmFtZSk8PTIpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkobmFtZSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkdGhpcy0+dXNlcklEKSl7JHRoaXMtPmxhc3RFcnJvciA9ICd1c2VySUQgaXMgZW1wdHknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO30kdXNlcmlkID0gJHRoaXMtPnVzZXJJRDtpZigkdGhpcy0+Y2FjaGluZyA9PT0gRkFMU0UpeyRnZXRfZGF0YSA9IDE7fWVsc2V7aWYoJGZyb21fY2FjaGU9PT1GQUxTRSl7JGdldF9kYXRhID0gMTt9ZWxzZXtpZihlbXB0eSgkdGhpcy0+dXNlckxpa2VzWyd0aW1lc3RhbXAnXSkpeyRnZXRfZGF0YSA9IDE7fWVsc2VpZigoJHRoaXMtPnVzZXJMaWtlc1sndGltZXN0YW1wJ10gKyAkdGhpcy0+Y2FjaGVFeHBpcmVzKT4gdGltZSgpKXskZ2V0X2RhdGEgPSAwO31lbHNleyRnZXRfZGF0YSA9IDE7fX19aWYoJGdldF9kYXRhIDw+IDEgJiYgJHVzZXJpZD09JHRoaXMtPnVzZXJJRCl7JGxpa2VzID0gJHRoaXMtPnVzZXJMaWtlcztpZihpc3NldCgkbGlrZXNbJ3RpbWVzdGFtcCddKSl1bnNldCgkbGlrZXNbJ3RpbWVzdGFtcCddKTskdGhpcy0+V3JpdGVMb2coMSwnR2V0TGlrZXM6IHVzZSBjYWNoZWQgZGF0YScpO31lbHNle2lmKCgkbGlrZXMgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR1c2VyaWQuJy9saWtlcycpKT09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNleyRsaWtlcyA9ICRsaWtlc1snZGF0YSddO2lmKCR1c2VyaWQgPT0gJHRoaXMtPnVzZXJJRCl7JHRoaXMtPnVzZXJMaWtlcyA9ICRsaWtlczskdGhpcy0+dXNlckxpa2VzWyd0aW1lc3RhbXAnXSA9IHRpbWUoKTskdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO319fWlmKCFlbXB0eSgkY2F0ZWdvcnkpKXskY2F0ZWdvcnkgPSBzdHJ0b2xvd2VyKCRjYXRlZ29yeSk7JHggPSAwO3doaWxlKCFlbXB0eSgkbGlrZXNbJHhdKSl7aWYoc3RydG9sb3dlcigkbGlrZXNbJHhdWydjYXRlZ29yeSddKTw+ICRjYXRlZ29yeSl1bnNldCgkbGlrZXNbJHhdKTskeCsrO319aWYoIWVtcHR5KCRuYW1lKSl7JG5hbWUgPSBzdHJ0b2xvd2VyKCRuYW1lKTtmb3JlYWNoKCRsaWtlcyBhcyAkdmFsID0+ICRrZXkpe2lmKHN0cnRvbG93ZXIoJGtleVsnbmFtZSddKTw+ICRuYW1lKXVuc2V0KCRsaWtlc1skdmFsXSk7fX0kbGlrZXMyID0gYXJyYXkoKTtpZihjb3VudCgkbGlrZXMpPj0xKXtmb3JlYWNoKCRsaWtlcyBhcyAkdmFsID0+ICRrZXkpJGxpa2VzMltdPSRrZXk7fXJldHVybiAkbGlrZXMyO31wdWJsaWMgZnVuY3Rpb24gR2V0T2JqZWN0SW5mbygkb2JqZWN0aWQpe2lmKGVtcHR5KCRvYmplY3RpZCkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoT2JqZWN0X2lkKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoKCRsaWtlaW5mbyA9ICR0aGlzLT5HcmFwaEFQSSgnLycuJG9iamVjdGlkKSk9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXtyZXR1cm4gJGxpa2VpbmZvO319fXB1YmxpYyBmdW5jdGlvbiBHZXRMb2NhdGlvbkluZm8oJGlkZCl7aWYoZW1wdHkoJGlkZCkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoTG9jYXRpb25faWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZigoJGxvY2luZm8gPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiRpZGQpKT09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNle3JldHVybiAkbG9jaW5mbzt9fX1wdWJsaWMgZnVuY3Rpb24gR2V0RGFzaGJvYXJkKCRjb3VudD0yNSl7aWYoJHRoaXMtPnJ1bk1vZGU8PidhcHAnKXskdGhpcy0+bGFzdEVycm9yID0gTk9UX0lOX1RISVNfTU9ERTskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMzE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9aWYoZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSAtIHBsZWFzZSBBdXRoIGZpcnN0JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9JHVpZCA9ICR0aGlzLT51c2VySUQ7aWYoZW1wdHkoJHVpZCkpeyR0aGlzLT5sYXN0RXJyb3IgPSAndXNlcklEIGlzIG5vdCBhdmFpbGFibGUnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyMzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZigoJGhvbWUgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR1aWQuJy9mZWVkP2xpbWl0PScuJGNvdW50KSk9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXskaG9tZSA9ICRob21lWydkYXRhJ107cmV0dXJuICRob21lO319cHVibGljIGZ1bmN0aW9uIFBvc3RUb0Rhc2hib2FyZCgkYXJyKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW4pKXskdGhpcy0+bGFzdEVycm9yID0gJ2FjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlIC0gcGxlYXNlIEF1dGggZmlyc3QnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihjb3VudCgkYXJyKT09MCl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlcic7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2VpZigkYXJyWydtZXNzYWdlJ109PScnICYmICRhcnJbJ2xpbmsnXT09JycgJiYgJGFyclsnbmFtZSddPT0nJyl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHNvbWUgcGFyYW1ldGVycyhtZXNzYWdlL2xpbmsvbmFtZSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoIWVtcHR5KCRhcnJbJ2Rlc2NyaXB0aW9uJ10pJiYgc3RybGVuKCRhcnJbJ2Rlc2NyaXB0aW9uJ10pPjEwMDApeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkoZGVzY3JpcHRpb24gdG9vIGxvbmcsbWF4aW11bSAxMDAwIGNoYXJzKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE5OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSAtIHBsZWFzZSBBdXRoIGZpcnN0JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9aWYoIWlzc2V0KCRhcnJbJ2Rlc2NyaXB0aW9uJ10pfHwgZW1wdHkoJGFyclsnZGVzY3JpcHRpb24nXSkpJGFyclsnZGVzY3JpcHRpb24nXSA9ICc8c3Bhbj48aT48L2k+PC9zcGFuPic7aWYoIWlzc2V0KCRhcnJbJ2NhcHRpb24nXSl8fCBlbXB0eSgkYXJyWydjYXB0aW9uJ10pKSRhcnJbJ2NhcHRpb24nXSA9ICc8c3Bhbj48aT48L2k+PC9zcGFuPic7Zm9yZWFjaCgkYXJyIGFzICRrZXkgPT4gJHZhbHVlKXtpZighaXNfc3RyaW5nKCR2YWx1ZSkpeyRhcnJbJGtleV0gPSBqc29uX2VuY29kZSgkdmFsdWUpO31lbHNlaWYoaXNfc3RyaW5nKCR2YWx1ZSkpeyRhcnJbJGtleV0gPSB1dGY4X2VuY29kZSgkdmFsdWUpO319JHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgnL21lL2ZlZWQnLCRhcnIsRkFMU0UsVFJVRSk7aWYoJHJlcyA9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXtyZXR1cm4gJHJlc1snaWQnXTt9fX1wdWJsaWMgZnVuY3Rpb24gUG9zdExpbmtUb0Rhc2hib2FyZCgkbGluaywkYWN0aW9uPScnLCRwcml2YWN5PScnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW4pKXskdGhpcy0+bGFzdEVycm9yID0gJ2FjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlIC0gcGxlYXNlIEF1dGggZmlyc3QnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkbGluaykpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoTGluayknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCRhY3Rpb248PicnICYmIGNvdW50KCRhY3Rpb24pPD4yKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyL3Byb3BlcnR5KEFjdGlvbiknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRlaW50cmFnPWFycmF5KCAnbWVzc2FnZScgPT4gJGxpbmssJ25hbWUnID0+ICcnLCdsaW5rJyA9PiAnJywnY2FwdGlvbicgPT4gJycsJ3BpY3R1cmUnID0+ICcnLCdkZXNjcmlwdGlvbicgPT4gJycsKTtpZigkYWN0aW9uPT0nJykkZWludHJhZ1snYWN0aW9ucyddID0gJyc7ZWxzZXskZWludHJhZ1snYWN0aW9ucyddID0gJGFjdGlvbjt9aWYoJHByaXZhY3k9PScnIG9yIHN0cmxlbigkcHJpdmFjeSk8PTIpJGVpbnRyYWdbJ3ByaXZhY3knXSA9IGFycmF5KCd2YWx1ZSc9PidFVkVSWU9ORScpO2Vsc2UgJGVpbnRyYWdbJ3ByaXZhY3knXSA9IGFycmF5KCd2YWx1ZSc9PiRwcml2YWN5KTskZXJnID0gJHRoaXMtPlBvc3RUb0Rhc2hib2FyZCgkZWludHJhZyk7aWYoJGVyZz09PUZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7cmV0dXJuICRlcmc7fX19fXB1YmxpYyBmdW5jdGlvbiBHZXRBbGJ1bXMoJGFsYnVtX25hbWU9JycsJGFsYnVtX2lkPScnLCRmcm9tX2lkPScnLCR1c2VyaWQ9JycsJGZyb21fY2FjaGU9RkFMU0Upe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR1c2VyaWQpKSR1c2VyaWQgPSAkdGhpcy0+dXNlcklEO2lmKCR1c2VyaWQgPT0gJHRoaXMtPnVzZXJJRCl7aWYoJHRoaXMtPmNhY2hpbmcgPT09IEZBTFNFKXskZ2V0X2RhdGEgPSAxO31lbHNle2lmKCRmcm9tX2NhY2hlPT09RkFMU0UpeyRnZXRfZGF0YSA9IDE7fWVsc2V7aWYoZW1wdHkoJHRoaXMtPnVzZXJBbGJ1bXNbJ3RpbWVzdGFtcCddKSl7JGdldF9kYXRhID0gMTt9ZWxzZWlmKCgkdGhpcy0+dXNlckFsYnVtc1sndGltZXN0YW1wJ10gKyAkdGhpcy0+Y2FjaGVFeHBpcmVzKT4gdGltZSgpKXskZ2V0X2RhdGEgPSAwO31lbHNleyRnZXRfZGF0YSA9IDE7fX19fWVsc2V7JGdldF9kYXRhID0gMTt9aWYoJGdldF9kYXRhIDw+IDEgJiYgJHVzZXJpZD09JHRoaXMtPnVzZXJJRCl7JGFsYnVtcyA9ICR0aGlzLT51c2VyQWxidW1zO2lmKCFlbXB0eSgkYWxidW1zWyd0aW1lc3RhbXAnXSkpdW5zZXQoJGFsYnVtc1sndGltZXN0YW1wJ10pOyR0aGlzLT5Xcml0ZUxvZygxLCdHZXRBbGJ1bXM6IHVzZSBjYWNoZWQgZGF0YScpO31lbHNle2lmKCgkYWxidW1zID0gJHRoaXMtPkdyYXBoQVBJKCcvJy4kdXNlcmlkLicvYWxidW1zJykpPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7JGFsYnVtcyA9ICRhbGJ1bXNbJ2RhdGEnXTtpZigkdXNlcmlkID09ICR0aGlzLT51c2VySUQpeyR0aGlzLT51c2VyQWxidW1zID0gJGFsYnVtczskdGhpcy0+dXNlckFsYnVtc1sndGltZXN0YW1wJ10gPSB0aW1lKCk7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTt9fX1pZighZW1wdHkoJGFsYnVtX2lkKSl7JHggPSAwO3doaWxlKCFlbXB0eSgkYWxidW1zWyR4XSkpe2lmKCRhbGJ1bXNbJHhdWydpZCddIDw+ICRhbGJ1bV9pZCl1bnNldCgkYWxidW1zWyR4XSk7JHgrKzt9fWlmKCFlbXB0eSgkYWxidW1fbmFtZSkpeyRhbGJ1bV9uYW1lID0gc3RydG9sb3dlcigkYWxidW1fbmFtZSk7JHggPSAwO3doaWxlKCFlbXB0eSgkYWxidW1zWyR4XSkpe2lmKCRhbGJ1bXNbJHhdWyduYW1lJ10gPD4gJGFsYnVtX25hbWUpdW5zZXQoJGFsYnVtc1skeF0pOyR4Kys7fX1pZighZW1wdHkoJGZyb21faWQpKXskeCA9IDA7d2hpbGUoIWVtcHR5KCRhbGJ1bXNbJHhdKSl7aWYoJGFsYnVtc1skeF1bJ2Zyb20nXVsnaWQnXSA8PiAkZnJvbV9pZCl1bnNldCgkYWxidW1zWyR4XSk7JHgrKzt9fSRhbGJ1bXMyID0gYXJyYXkoKTtpZihjb3VudCgkYWxidW1zKT49MSl7Zm9yZWFjaCgkYWxidW1zIGFzICR2YWwgPT4gJGtleSkkYWxidW1zMltdPSRrZXk7fXJldHVybiAkYWxidW1zMjt9cHVibGljIGZ1bmN0aW9uIENyZWF0ZUFsYnVtKCRuYW1lLCRjYXB0aW9uPScnLCR1c2VyaWQ9Jycpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCRuYW1lKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlcihBbGJ1bSBuYW1lKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoZW1wdHkoJHVzZXJpZCkpJHVzZXJpZD0kdGhpcy0+dXNlcklEO2lmKGVtcHR5KCR1c2VyaWQpKXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW1ldGVyKHVzZXJJRCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRyZXMgPSAkdGhpcy0+R3JhcGhBUEkoJy8nLiR1c2VyaWQuJy9hbGJ1bXMnLGFycmF5KCduYW1lJyA9PiAkbmFtZSwnbWVzc2FnZScgPT4gJGNhcHRpb24pLEZBTFNFLFRSVUUpO2lmKCRyZXMgPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7cmV0dXJuICRyZXNbJ2lkJ107fX19fXB1YmxpYyBmdW5jdGlvbiBQb3N0VG9BbGJ1bSgkYXJyLCRub0Rhc2hib2FyZCA9IDApe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCRhcnJbJ3BpY2ZpbGUnXSkpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIoUGljdHVyZSBQYXRoL1VSTCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCFlbXB0eSgkYXJyWydsaW5rJ10pKXtpZihzdWJzdHIoc3RydG9sb3dlcigkYXJyWydsaW5rJ10pLDAsNCk9PSAnd3d3LicpeyRhcnJbJ2xpbmsnXSA9ICdodHRwOi8vJy4kYXJyWydsaW5rJ107fWVsc2VpZihzdWJzdHIoc3RydG9sb3dlcigkYXJyWydsaW5rJ10pLDAsNyk8PiAnaHR0cDovLycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkobGluayBtdXN0IHN0YXJ0IHdpdGggImh0dHA6Ly8iKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE5OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX0kZmlsZTJkZWxldGUgPSAnJztpZihzdWJzdHIoJGFyclsncGljZmlsZSddLDAsNCk9PSdodHRwJyB8fCBzdWJzdHIoJGFyclsncGljZmlsZSddLDAsNCk9PSd3d3cuJyl7JGNvbnRlbnQgPSBmaWxlX2dldF9jb250ZW50cygkYXJyWydwaWNmaWxlJ10pO2lmKHN0cmxlbigkY29udGVudCk8MjAwKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyL3Byb3BlcnR5KFBpY3R1cmUgbm90IGZvdW5kKScuIlxuIi4nW1BpY3R1cmUgVVJMIHNlbmQ6KExlbmd0aD0nLnN0cmxlbigkY29udGVudCkuJykiJy4kY29udGVudC4nIl0nOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyR0ZW1wX2RpciA9ICR0aGlzLT5nZXRUZW1wRGlyKCk7aWYoJHRlbXBfZGlyID09PSBGQUxTRSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlci9wcm9wZXJ0eShQaWN0dXJlX1VSTCBpc3Qgbm90IHN1cHBvcnRlZCBvbiB0aGlzIHNlcnZlciknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyR0ZW1wX2Rpci49bWQ1KHRpbWUoKSk7JHB1dF9maWxlID0gQGZvcGVuKCR0ZW1wX2RpciwndysnKTtpZigkcHV0X2ZpbGUpeyRoYW5kZWwgPSBmd3JpdGUoJHB1dF9maWxlLCRjb250ZW50KTtmY2xvc2UoJHB1dF9maWxlKTt9JGFyclsncGljZmlsZSddID0gJHRlbXBfZGlyOyRmaWxlMmRlbGV0ZSA9ICR0ZW1wX2Rpcjt9fX1pZighZmlsZV9leGlzdHMoJGFyclsncGljZmlsZSddKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlci9wcm9wZXJ0eShQaWN0dXJlIG5vdCBmb3VuZCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRhcnJbJ3BpY2ZpbGUnXSA9ICdAJy4kYXJyWydwaWNmaWxlJ107fWlmKGVtcHR5KCRhcnJbJ2FsYnVtX2lkJ10pKXskYXJyWydhbGJ1bV9pZCddID0gJHRoaXMtPnVzZXJJRDt9aWYoIWVtcHR5KCRhcnJbJ2xpbmsnXSkpJGFyclsnY2FwdGlvbiddIC49ICcgJy4kYXJyWydsaW5rJ107JHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgnLycuJGFyclsnYWxidW1faWQnXS4nL3Bob3RvcycsYXJyYXkoJ3NvdXJjZScgPT4gJGFyclsncGljZmlsZSddLCdtZXNzYWdlJyA9PiAkYXJyWydjYXB0aW9uJ10pLEZBTFNFLFRSVUUpO2lmKCFlbXB0eSgkZmlsZTJkZWxldGUpKXVubGluaygkZmlsZTJkZWxldGUpO2lmKCRyZXMgPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7cmV0dXJuICRyZXNbJ2lkJ107fX19cHVibGljIGZ1bmN0aW9uIEdldFBhZ2VJbmZvKCRwYWdlID0gMCl7aWYoZW1wdHkoJHBhZ2UpKXtpZigkdGhpcy0+Y2FsbEFzUGFnZSA9PT0gRkFMU0UpeyR0aGlzLT5sYXN0RXJyb3IgPSAnUGFnZUlEL05hbWUgbm90IGF2YWlsYWJsZSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI1OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoJHRoaXMtPnBhZ2VJRCA+IDApeyRwYWdlID0gJHRoaXMtPnBhZ2VJRDt9ZWxzZXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgUGFnZUlEL05hbWUnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO319fWlmKCgkZmVsZGVyID0gJHRoaXMtPkdyYXBoQVBJKCcvJy4kcGFnZSkpPT09RkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXtpZigkdGhpcy0+Y2FsbEFzUGFnZSA9PT0gVFJVRSAmJiAkZmVsZGVyWydpZCddID09ICR0aGlzLT5wYWdlSUQpeyR0aGlzLT5wYWdlRGF0YSA9ICRmZWxkZXI7dW5zZXQoJHRoaXMtPnBhZ2VEYXRhWydpZCddKTtpZigkdGhpcy0+YXBwRkJVUkwgPT0gJycpe2lmKHN0cnBvcygkZmVsZGVyWydsaW5rJ10sJz8nKT4wKSR0aGlzLT5hcHBGQlVSTCA9ICRmZWxkZXJbJ2xpbmsnXS4nJnNrPWFwcF8nLiR0aGlzLT5hcHBJRDtlbHNlICR0aGlzLT5hcHBGQlVSTCA9ICRmZWxkZXJbJ2xpbmsnXS4nP3NrPWFwcF8nLiR0aGlzLT5hcHBJRDt9fXJldHVybiAkZmVsZGVyO319cHVibGljIGZ1bmN0aW9uIEtpbGxJZnJhbWVCb3JkZXIoJHRhcmdldD0nJyl7cmV0dXJuICR0aGlzLT5LaWxsRmFjZWJvb2tCb3JkZXIoJHRhcmdldCk7fXB1YmxpYyBmdW5jdGlvbiBLaWxsRmFjZWJvb2tCb3JkZXIoJHRhcmdldD0nJyl7aWYoJHRoaXMtPnJ1bk91dG9mSWZyYW1lID09PSBUUlVFKXskdGhpcy0+bGFzdEVycm9yID0gJ3J1bm5pbmcgd2l0aG91dCBGYWNlYm9vayBib3JkZXInOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNle2lmKCR0YXJnZXQ9PScnKXtpZigkdGhpcy0+cHJvdG9jb2wgPT0gJ2h0dHBzOi8vJyAmJiAkdGhpcy0+c3NsX3Byb3h5X3VybDw+JycpeyR0YXJnZXQgPSAkdGhpcy0+c3NsX3Byb3h5X3VybC4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXTt9ZWxzZXskdGFyZ2V0ID0gJHRoaXMtPnByb3RvY29sLiRfU0VSVkVSWydIVFRQX0hPU1QnXS4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXTt9fSR0aGlzLT5ydW5PdXRvZklmcmFtZSA9IFRSVUU7JHRoaXMtPldyaXRlSW5zdGFuY2VUb1Nlc3Npb24oKTskdGhpcy0+V3JpdGVMb2coMiwnRmFjZWJvb2sgYm9yZGVyIGtpbGxlZCcpO2VjaG8oIjxzY3JpcHQ+dG9wLmxvY2F0aW9uLmhyZWY9JyIuJHRhcmdldC4iJzs8L3NjcmlwdD4iKTtleGl0O319cHJpdmF0ZSBmdW5jdGlvbiBHZXRVUkwoJHVybGw9Jycpe2lmKHN0cmxlbigkdXJsbCk8PSA1KXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW1ldGVyKFVSTCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTtyZXR1cm4gRkFMU0U7fWVsc2V7JGNoID0gY3VybF9pbml0KCk7JG9rID0gMTtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9VUkwsJHVybGwpPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NULGZhbHNlKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoJGNoLENVUkxPUFRfQ09OTkVDVFRJTUVPVVQsMTApPT09RkFMU0UpJG9rID0gMDtpZihjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUix0cnVlKT09PUZBTFNFKSRvayA9IDA7aWYoY3VybF9zZXRvcHQoJGNoLENVUkxPUFRfVElNRU9VVCw2MCk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1VTRVJBR0VOVCwnTW96aWxsYS81LjAoWDExO0xpbnV4KUdlY2tvIEZpcmVmb3gvNS4wJyk9PT1GQUxTRSkkb2sgPSAwO2lmKGN1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1NTTF9WRVJJRllQRUVSLGZhbHNlKT09PSBGQUxTRSApJG9rID0gMDtpZigkb2s8PjEpe3RyaWdnZXJfZXJyb3IoY3VybF9lcnJvcigkY2gpKTskdGhpcy0+bGFzdEVycm9yID0gJ0NVUkwgc2V0dGluZyBmYWlsZWQnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMzskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRyZXN1bHQgPSBjdXJsX2V4ZWMoJGNoKTtpZigkcmVzdWx0ID09PSBGQUxTRSl7dHJpZ2dlcl9lcnJvcihjdXJsX2Vycm9yKCRjaCkpO2N1cmxfY2xvc2UoJGNoKTskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKENVUkwgZXhlYyBmYWlsZWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDYgOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7Y3VybF9jbG9zZSgkY2gpO3JldHVybiAkcmVzdWx0O319fX1wcml2YXRlIGZ1bmN0aW9uIEdldEFwcEFjY2Vzc1Rva2VuKCl7JHRva2VuX3VybCA9ICdodHRwczovL2dyYXBoLmZhY2Vib29rLmNvbS9vYXV0aC9hY2Nlc3NfdG9rZW4/Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmY2xpZW50X2lkPScuJHRoaXMtPmFwcElELicmY2xpZW50X3NlY3JldD0nLiR0aGlzLT5BcHBTZWNLZXk7JGFjY2Vzc190b2tlbiA9ICR0aGlzLT5HZXRVUkwoJHRva2VuX3VybCk7aWYoISRhY2Nlc3NfdG9rZW4gfHwgc3RybGVuKCRhY2Nlc3NfdG9rZW4pPDIwIHx8IHN0cmxlbigkYWNjZXNzX3Rva2VuKT4yMDApeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IoZ2V0dGluZyBhY2Nlc3NfdG9rZW4gZm9yIGFwcCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyRhY2Nlc3NfdG9rZW4gPSBzdWJzdHIoJGFjY2Vzc190b2tlbixzdHJwb3MoJGFjY2Vzc190b2tlbiwnPScpKzEpOyR0aGlzLT5hcHBBY2Nlc3NUb2tlbiA9ICRhY2Nlc3NfdG9rZW47JHRoaXMtPldyaXRlTG9nKDIsJ2FwcF9hY2Nlc3NfdG9rZW4gcmVxdWVzdGVkJyk7cmV0dXJuICRhY2Nlc3NfdG9rZW47fX1wdWJsaWMgZnVuY3Rpb24gU2V0QXBwUHJvcGVydHkoJHByb3BlcnR5LCR2YWx1ZSl7aWYoZW1wdHkoJHByb3BlcnR5KXx8IHN0cmxlbigkcHJvcGVydHkpPD0zIHx8IGVtcHR5KCR2YWx1ZSl8fCBzdHJsZW4oJHZhbHVlKTw9Myl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlcic7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoJHRoaXMtPmFwcEFjY2Vzc1Rva2VuID09ICcnKXtpZigkdGhpcy0+R2V0QXBwQWNjZXNzVG9rZW4oKT09PSBGQUxTRSlyZXR1cm4gRkFMU0U7fWlmKCR0aGlzLT5hcHBBY2Nlc3NUb2tlbiA9PSAnJyl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihhY2Nlc3NfdG9rZW4gZm9yIGFwcCBpcyBlbXB0eSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyR1cmxsID0gUkVTVF9VUkwgLiAnP21ldGhvZD1hZG1pbi5zZXRBcHBQcm9wZXJ0aWVzJnByb3BlcnRpZXM9Jy51cmxlbmNvZGUoanNvbl9lbmNvZGUoYXJyYXkoICRwcm9wZXJ0eSA9PiAkdmFsdWUgKSkpLicmYWNjZXNzX3Rva2VuPScuJHRoaXMtPmFwcEFjY2Vzc1Rva2VuOyRyZXN1bHQgPSAkdGhpcy0+R2V0VVJMKCR1cmxsKTtpZigkcmVzdWx0ID09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNleyRyZXN1bHQgPSBzdHJpcF90YWdzKCRyZXN1bHQpO2lmKCRyZXN1bHQgPD4gMSl7JHRoaXMtPmxhc3RFcnJvciA9ICdGQiBlcnJvcjogJy5zdWJzdHIoJHJlc3VsdCwwLHN0cnBvcygkcmVzdWx0LCdtZXRob2QnKSk7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE1OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7cmV0dXJuIFRSVUU7fX19fX1wdWJsaWMgZnVuY3Rpb24gQWRkQXBwQXNQYWdlKCRhcGlfa2V5PScnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkYXBpX2tleSl8fCBzdHJsZW4oJGFwaV9rZXkpPDgpe2lmKCFlbXB0eSgkdGhpcy0+YXBwSUQpJiYgc3RybGVuKCR0aGlzLT5hcHBJRCk+IDUpJGFwaV9rZXkgPSAkdGhpcy0+YXBwSUQ7ZWxzZXskdGhpcy0+bGFzdEVycm9yID0gJ2FwcElEIG5vdCBhdmFpbGFibGUnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO319aWYoJF9SRVFVRVNUWydhZHBhb2syJ10gPT0gJ29rJyl7cmV0dXJuICRfUkVRVUVTVFsnZmJfcGFnZV9pZCddO31lbHNlaWYoJF9SRVFVRVNUWydhZHBhb2syJ10gPT0gJ25vdG9rJyl7cmV0dXJuIC0xO31lbHNle2lmKCR0aGlzLT5hZGRQYWdlX3JlZGlyZWN0X3VybCA9PSAnJyl7JHJlcyA9ICR0aGlzLT5TZXRBcHBQcm9wZXJ0eSgncG9zdF9hdXRob3JpemVfcmVkaXJlY3RfdXJsJywkdGhpcy0+YXBwU2VydmVyVVJMLic/YWRwYW9rPW9rJyk7aWYoJHJlcyA9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXskdGhpcy0+YWRkUGFnZV9yZWRpcmVjdF91cmwgPSAkdGhpcy0+YXBwU2VydmVyVVJMLic/YWRwYW9rPW9rJzskdGhpcy0+V3JpdGVMb2coMiwnQWRkQXBwVGFyZ2V0IHNldCBzdWNjZXNzZnVsbHknKTt9fSR1cmxsID0gJHRoaXMtPnByb3RvY29sLid3d3cuZmFjZWJvb2suY29tL2FkZC5waHA/YXBpX2tleT0nLiRhcGlfa2V5LicmcGFnZXM9MSc7aWYoJHRoaXMtPnByb3RvY29sID09ICdodHRwczovLycgJiYgJHRoaXMtPnNzbF9wcm94eV91cmw8PicnKXskdGhpcy0+b2tVUkwgPSAkdGhpcy0+c3NsX3Byb3h5X3VybC4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXTt9ZWxzZXskdGhpcy0+b2tVUkwgPSAkdGhpcy0+cHJvdG9jb2wuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiRfU0VSVkVSWydSRVFVRVNUX1VSSSddO30kdGhpcy0+V3JpdGVJbnN0YW5jZVRvU2Vzc2lvbigpO2VjaG8gIjxzY3JpcHQ+dG9wLmxvY2F0aW9uLmhyZWY9JyIuJHVybGwuIic7PC9zY3JpcHQ+IjtleGl0O319cHVibGljIGZ1bmN0aW9uIEFkZEFwcFRvUGFnZSgpeyRyZXQgPSAkdGhpcy0+QWRkQXBwQXNQYWdlKCR0aGlzLT5hcHBJRCk7cmV0dXJuICRyZXQ7fXB1YmxpYyBmdW5jdGlvbiBTZWFyY2hTaXRlKCRrZXl3b3JkLCR0eXBlLCRjb3VudD0wLCRtb2RlPTApeyR0eXBlID0gdHJpbSgkdHlwZSk7JGtleXdvcmQgPSB0cmltKCRrZXl3b3JkKTtpZighaXNfbnVtZXJpYygkbW9kZSlPUiAkbW9kZTwgMCBPUiAkbW9kZSA+IDEpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkobW9kZSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYodHJpbSgkdHlwZSk9PSAncGxhY2UnKXskdGhpcy0+bGFzdEVycm9yID0gJ1Vuc3VwcG9ydGVkIHR5cGUgZm9yIHNlYXJjaCgicGxhY2UiKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE5OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2VpZihlbXB0eSgkdHlwZSkpeyR0eXBlID0gJ3Bvc3QnO31pZigkbW9kZSA9PSAxIHx8ICR0eXBlID09ICd1c2VyJyB8fCAkdHlwZSA9PSAnY2hlY2tpbicpe2lmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX1pZihlbXB0eSgkY291bnQpfHwgJGNvdW50PDEpJGNvdW50PTI1O2lmKHN0cmxlbigka2V5d29yZCk8Mil7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlciAvIHRvbyBzaG9ydChrZXl3b3JkKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7JGtleXdvcmQgPSBzdHJfcmVwbGFjZSgnICcsJysnLCRrZXl3b3JkKTtpZigkbW9kZSA9PSAwKXskZGF0YSA9ICR0aGlzLT5HcmFwaEFQSSgnL3NlYXJjaD9xPScuJGtleXdvcmQuJyZ0eXBlPScuJHR5cGUuJyZsaW1pdD0nLiRjb3VudCk7fWVsc2VpZigkbW9kZSA9PSAxKXskZGF0YSA9ICR0aGlzLT5HcmFwaEFQSSgnL21lL2hvbWU/cT0nLiRrZXl3b3JkLicmbGltaXQ9Jy4kY291bnQpO31pZigkZGF0YSA9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXt1bnNldCgkZGF0YVsncGFnaW5nJ11bJ3ByZXZpb3VzJ10pO3Vuc2V0KCRkYXRhWydwYWdpbmcnXVsnbmV4dCddKTt1bnNldCgkZGF0YVsncGFnaW5nJ10pOyRkYXRhID0gJGRhdGFbJ2RhdGEnXTtyZXR1cm4gJGRhdGE7fX19cHVibGljIGZ1bmN0aW9uIFNlYXJjaFVzZXJGZWVkKCRrZXl3b3JkLCRjb3VudCl7cmV0dXJuICR0aGlzLT5TZWFyY2hTaXRlKCRrZXl3b3JkLCdwb3N0JywkY291bnQsMSk7fXB1YmxpYyBmdW5jdGlvbiBHZXRIb21lKCRjb3VudD0yNSl7aWYoJHRoaXMtPnJ1bk1vZGU8PidhcHAnKXskdGhpcy0+bGFzdEVycm9yID0gTk9UX0lOX1RISVNfTU9ERTskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMzE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9aWYoZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSAtIHBsZWFzZSBBdXRoIGZpcnN0JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZighaXNfbnVtZXJpYygkY291bnQpKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyL3Byb3BlcnR5KGNvdW50KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE5OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoJGNvdW50IDwgMSkkY291bnQgPSAyNTskZGF0YSA9ICR0aGlzLT5HcmFwaEFQSSgnL21lL2hvbWU/bGltaXQ9Jy4kY291bnQpO2lmKCRkYXRhID09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNle3Vuc2V0KCRkYXRhWydwYWdpbmcnXVsncHJldmlvdXMnXSk7dW5zZXQoJGRhdGFbJ3BhZ2luZyddWyduZXh0J10pO3Vuc2V0KCRkYXRhWydwYWdpbmcnXSk7JGRhdGEgPSAkZGF0YVsnZGF0YSddO3JldHVybiAkZGF0YTt9fX19cHVibGljIGZ1bmN0aW9uIEdldEFjY2Vzc1Rva2VuSW5mbygkYWNjZXNzX3Rva2VuPScnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31pZihlbXB0eSgkYWNjZXNzX3Rva2VuKSl7aWYoIWVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyRhY2Nlc3NfdG9rZW4gPSAkdGhpcy0+YWNjZXNzVG9rZW47fWVsc2V7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtKGFjY2Vzc1Rva2VuKSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fX1pZighJGFjY2Vzc190b2tlbiB8fCBzdHJsZW4oJGFjY2Vzc190b2tlbik8NjAgfHwgc3RybGVuKCRhY2Nlc3NfdG9rZW4pPjIwMCl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSBvciBpbnZhbGlkJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZigkdGhpcy0+YXBwQWNjZXNzVG9rZW4gPT0gJycpe2lmKCR0aGlzLT5HZXRBcHBBY2Nlc3NUb2tlbigpPT09IEZBTFNFKXJldHVybiBGQUxTRTt9aWYoJHRoaXMtPmFwcEFjY2Vzc1Rva2VuID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKGFjY2Vzc190b2tlbiBmb3IgYXBwIGlzIGVtcHR5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2O3JldHVybiBGQUxTRTt9ZWxzZXskdG9rZW5fdXJsID0gJ2h0dHBzOi8vZ3JhcGguZmFjZWJvb2suY29tL2RlYnVnX3Rva2VuP2lucHV0X3Rva2VuPScuJGFjY2Vzc190b2tlbi4nJmFjY2Vzc190b2tlbj0nLiR0aGlzLT5hcHBBY2Nlc3NUb2tlbjskcmVzID0gJHRoaXMtPkdldFVSTCgkdG9rZW5fdXJsKTskcmVzdWx0MiA9IGpzb25fZGVjb2RlKCRyZXMpOyRyZXMgPSAkdGhpcy0+Y29udmVydE9iamVjdFRvQXJyYXkoJHJlc3VsdDIpO2lmKGlzc2V0KCRyZXNbJ2RhdGEnXVsnZXJyb3InXSkmJiBpc19hcnJheSgkcmVzWydkYXRhJ11bJ2Vycm9yJ10pKXtpZigkcmVzWydkYXRhJ11bJ2Vycm9yJ11bJ2NvZGUnXSA9PSAxOTApeyRyZXMyWydpc192YWxpZCddID0gRkFMU0U7JHJlczJbJ2Vycm9yJ10gPSAkcmVzWydkYXRhJ11bJ2Vycm9yJ107cmV0dXJuICRyZXMyO31lbHNleyR0aGlzLT5sYXN0RXJyb3IgPSAkcmVzWydkYXRhJ11bJ2Vycm9yJ11bJ2NvZGUnXS4nIDogJy4kcmVzWydkYXRhJ11bJ2Vycm9yJ11bJ21lc3NhZ2UnXTskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTU7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9fWVsc2V7JHJlcyA9ICRyZXNbJ2RhdGEnXTskcmVzWydzY29wZXMnXVtdID0gJ2Jhc2ljJztpZihpc3NldCgkcmVzWydleHBpcmVzX2F0J10pKXskcmVzWydleHBpcmVzJ10gPSBEYXRlKCdZLW0tZCBIOmk6cycsJHJlc1snZXhwaXJlc19hdCddKTskcmVzWydleHBpcmVzX2luJ10gPSAkcmVzWydleHBpcmVzX2F0J10tdGltZSgpO31pZigkcmVzWydpc192YWxpZCddID09IDEpJHJlc1snaXNfdmFsaWQnXSA9IFRSVUU7ZWxzZWlmKCRyZXNbJ2lzX3ZhbGlkJ10gPT0gMCkkcmVzWydpc192YWxpZCddID0gRkFMU0U7aWYoJHJlc1snZXhwaXJlc19pbiddPD0oMio2MCo2MCkpJHJlc1sndHlwZSddID0gJ3Nob3J0X2xpdmVkJztlbHNlICRyZXNbJ3R5cGUnXSA9ICdsb25nX2xpdmVkJztyZXR1cm4gJHJlczt9fX19cHVibGljIGZ1bmN0aW9uIEdldE9iamVjdENvbm5lY3Rpb25zKCRvYmplY3RpZCl7aWYoZW1wdHkoJG9iamVjdGlkKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlcihPYmplY3RfaWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdHJwb3Moc3Vic3RyKCRvYmplY3RpZCwxLC0xKSwnLycpIT09IEZBTFNFKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyKE9iamVjdF9pZCktIG9ubHkgc2luZ2xlIE9iamVjdElEIGFjY2VwdGVkJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdWJzdHIoJG9iamVjdGlkLDAsMSk8PicvJykkb2JqZWN0aWQ9Jy8nLiRvYmplY3RpZDtpZigoJHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgkb2JqZWN0aWQsJ21ldGFkYXRhPTEnKSk9PT0gRkFMU0Upe3JldHVybiBGQUxTRTt9ZWxzZXskcmVzMiA9IGFycmF5KCk7aWYoaXNzZXQoJHJlc1snbWV0YWRhdGEnXSkpe2lmKGlzc2V0KCRyZXNbJ21ldGFkYXRhJ11bJ3R5cGUnXSkpJHJlczJbJ3R5cGUnXSA9ICRyZXNbJ21ldGFkYXRhJ11bJ3R5cGUnXTtpZihpc3NldCgkcmVzWydtZXRhZGF0YSddWydjb25uZWN0aW9ucyddKSl7Zm9yZWFjaCgkcmVzWydtZXRhZGF0YSddWydjb25uZWN0aW9ucyddIGFzICR2YWwgPT4gJGtleSkkcmVzMlsnY29ubmVjdGlvbnMnXVtdID0gJHZhbDt9fXVuc2V0KCRyZXMpO3JldHVybiAkcmVzMjt9fX19cHVibGljIGZ1bmN0aW9uIEdldExpbmtTdGF0aXN0aWMoJGxpbms9JycpeyRsaW5rID0gc3RydG9sb3dlcigkbGluayk7aWYoZW1wdHkoJGxpbmspKXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW0obGluayBzdHJpbmcpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTE7cmV0dXJuIEZBTFNFO31lbHNlaWYoc3Vic3RyKCRsaW5rLDAsOCk9PSdodHRwczovLycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIvcHJvcGVydHkoaHR0cHMgbm90IHN1cHBvcnRlZCknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTtyZXR1cm4gRkFMU0U7fWVsc2V7aWYoc3Vic3RyKCRsaW5rLDAsNyk9PSdodHRwOi8vJykkbGluaz1zdWJzdHIoJGxpbmssNywxMDAwKTskeG1sX3Jlc3VsdCA9ICR0aGlzLT5HZXRVUkwoJ2h0dHA6Ly9hcGkuZmFjZWJvb2suY29tL3Jlc3RzZXJ2ZXIucGhwP21ldGhvZD1saW5rcy5nZXRTdGF0cyZ1cmxzPScudXJsZW5jb2RlKCRsaW5rKSk7aWYoJHhtbF9yZXN1bHQgPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7JGFycl9kYXRlbiA9IGFycmF5KCk7JHBvcyA9IHN1YnN0cigkeG1sX3Jlc3VsdCxzdHJwb3MoJHhtbF9yZXN1bHQsIjxsaW5rX3N0YXQ+IikrMTEpOyR4bWxfcmVzdWx0ID0gc3Vic3RyKCRwb3MsMCxzdHJwb3MoJHBvcywiPC9saW5rX3N0YXQ+IikpOyRzcGxpdF94bWwgPSBleHBsb2RlKCJcbiIsJHhtbF9yZXN1bHQpO2ZvcigkaT0xOyRpPCBjb3VudCgkc3BsaXRfeG1sKS0xOyRpKyspeyRwb3MxPXN1YnN0cigkc3BsaXRfeG1sWyRpXSxzdHJwb3MoJHNwbGl0X3htbFskaV0sIjwiKSsxKTskcG9zMj1zdWJzdHIoJHBvczEsc3RycG9zKCRwb3MxLCI+IikrMSk7JHBvczM9c3Vic3RyKCRwb3MyLDAsc3RycG9zKCRwb3MyLCI8LyIpKTskaW5kZXggPSBzdWJzdHIoJHBvczEsMCxzdHJwb3MoJHBvczEsIj4iKSk7JGFycl9kYXRlblskaW5kZXhdID0gJHBvczM7fXVuc2V0KCRhcnJfZGF0ZW5bJ3RvdGFsX2NvdW50J10pO2lmKHN0cnBvcygkbGluaywiaHR0cDovLyIpPT09IEZBTFNFKSRsaW5rPSJodHRwOi8vIi4kbGluazskcmVzdWx0X2xpbmsgPSAkdGhpcy0+R3JhcGhBUEkoIi8iLiRsaW5rKTtpZigkcmVzdWx0X2xpbmsgPT09IEZBTFNFKXtyZXR1cm4gRkFMU0U7fWVsc2V7JGFycl9kYXRlbiA9IGFycmF5X21lcmdlKCRhcnJfZGF0ZW4sJHJlc3VsdF9saW5rKTtpZihpc3NldCgkYXJyX2RhdGVuWydjb21tZW50c19mYmlkJ10pJiYgJGFycl9kYXRlblsnY29tbWVudHNfZmJpZCddIDw+ICcnKXskcmVzdWx0X2lkID0gJHRoaXMtPkdldE9iamVjdEluZm8oJGFycl9kYXRlblsnY29tbWVudHNfZmJpZCddKTtpZigkcmVzdWx0X2lkID09PSBGQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNle3Vuc2V0KCRhcnJfZGF0ZW5bJ2NvbW1lbnRzX2ZiaWQnXSk7JGFycl9kYXRlblsnZmJfb2JqZWN0J11bJ2lkJ10gPSAkcmVzdWx0X2lkWydpZCddO2lmKGlzc2V0KCRyZXN1bHRfaWRbJ2Rlc2NyaXB0aW9uJ10pKSR0bXAgPSAkcmVzdWx0X2lkWydkZXNjcmlwdGlvbiddO3Vuc2V0KCRyZXN1bHRfaWRbJ2Rlc2NyaXB0aW9uJ10pO3Vuc2V0KCRyZXN1bHRfaWRbJ2lkJ10pO2ZvcmVhY2goJHJlc3VsdF9pZCBhcyAka2V5ID0+ICR2YWx1ZSl7JGFycl9kYXRlblsnZmJfb2JqZWN0J11bJGtleV0gPSAkdmFsdWU7aWYoJGtleSA9PSAndGl0bGUnICYmIGlzc2V0KCR0bXApJiYgIWVtcHR5KCR0bXApKSRhcnJfZGF0ZW5bJ2ZiX29iamVjdCddWydkZXNjcmlwdGlvbiddID0gJHRtcDt9fX1yZXR1cm4gJGFycl9kYXRlbjt9fX19cHVibGljIGZ1bmN0aW9uIFNlbmROb3RpZmljYXRpb24oJHRleHR0PScnLCRsaW5rPScnKXtpZigkdGhpcy0+cnVuTW9kZTw+J2FwcCcpeyR0aGlzLT5sYXN0RXJyb3IgPSBOT1RfSU5fVEhJU19NT0RFOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAzMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO30kdXNlcmlkPT0nJztpZigkdGhpcy0+dXNlcklEID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ3VzZXJJRCBpcyBlbXB0eSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDIxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2UgJHVzZXJpZCA9ICR0aGlzLT51c2VySUQ7aWYoZW1wdHkoJHRleHR0KSl7JHRoaXMtPmxhc3RFcnJvciA9ICdNaXNzaW5nIHBhcmFtZXRlcih0ZXh0IGlzIGVtcHR5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2VpZihzdHJsZW4oJHRleHR0KT4xODApeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIodGV4dCltYXhzaXplIDE4MCBjaGFycyc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDE5OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2VpZihlbXB0eSgkbGluaykpeyR0aGlzLT5sYXN0RXJyb3IgPSAnTWlzc2luZyBwYXJhbWV0ZXIobGluayknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxMTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoc3Vic3RyKCRsaW5rLDAsMik9PScuLycgfHwgc3RydG9sb3dlcihzdWJzdHIoJGxpbmssMCw0KSk9PSdodHRwJyB8fCBzdHJ0b2xvd2VyKHN1YnN0cigkbGluaywwLDQpKT09J3d3dy4nKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyKGxpbmspb25seSByZWxhdGl2IFVSTCB0byBGQkFwcFVybCBvciBmaWxlbmFtZSBvciBvbmx5IHBhcmFtZXRlcnMnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSAtIHBsZWFzZSBBdXRoIGZpcnN0JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdWJzdHIoJGxpbmssMCwxKT09Jy8nKSRsaW5rID0gc3Vic3RyKCRsaW5rLDEpO2lmKCR0aGlzLT5hcHBBY2Nlc3NUb2tlbiA9PSAnJyl7aWYoJHRoaXMtPkdldEFwcEFjY2Vzc1Rva2VuKCk9PT0gRkFMU0UpcmV0dXJuIEZBTFNFO31pZigkdGhpcy0+YXBwQWNjZXNzVG9rZW4gPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW50ZXJuYWwgRXJyb3IoYWNjZXNzX3Rva2VuIGZvciBhcHAgaXMgZW1wdHkpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDY7cmV0dXJuIEZBTFNFO31lbHNleyRwYXJhbXMgPSBhcnJheSgpOyRwYXJhbXNbJ2hyZWYnXSA9ICRsaW5rOyRwYXJhbXNbJ3RlbXBsYXRlJ10gPSAkdGV4dHQ7JHBhcmFtc1snYWNjZXNzX3Rva2VuJ10gPSAkdGhpcy0+YXBwQWNjZXNzVG9rZW47JHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgnLycuJHVzZXJpZC4nL25vdGlmaWNhdGlvbnMnLCRwYXJhbXMsRkFMU0UsVFJVRSk7aWYoJHJlcyA9PT0gRkFMU0UpcmV0dXJuIEZBTFNFO2Vsc2V7aWYoaXNzZXQoJHJlc1snc3VjY2VzcyddKSYmICRyZXNbJ3N1Y2Nlc3MnXT09MSlyZXR1cm4gVFJVRTtlbHNlIHJldHVybiAkcmVzO319fX1wdWJsaWMgZnVuY3Rpb24gU2VuZEFwcFJlcXVlc3QoJGRlc2NyaXB0aW9uPScnLCRjdXN0b21zdHJpbmc9Jycpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCR0aGlzLT51c2VySUQgPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAndXNlcklEIGlzIGVtcHR5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZSAkdXNlcmlkID0gJHRoaXMtPnVzZXJJRDtpZihlbXB0eSgkZGVzY3JpcHRpb24pKXskdGhpcy0+bGFzdEVycm9yID0gJ01pc3NpbmcgcGFyYW1ldGVyKGRlc2NyaXB0aW9uIGlzIGVtcHR5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDExOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWVsc2VpZihzdHJsZW4oJGRlc2NyaXB0aW9uKT4xMjApeyR0aGlzLT5sYXN0RXJyb3IgPSAnSW52YWxpZCBwYXJhbWV0ZXIoZGVzY3JpcHRpb24pbWF4c2l6ZSAxMjAgY2hhcnMnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoc3RybGVuKCRjdXN0b21zdHJpbmcpPjI1NSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlcihjdXN0b21zdHJpbmcpbWF4c2l6ZSAyNTUgY2hhcnMnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAxOTskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoZW1wdHkoJHRoaXMtPmFjY2Vzc1Rva2VuKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSAtIHBsZWFzZSBBdXRoIGZpcnN0JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjQ7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZigkdGhpcy0+YXBwQWNjZXNzVG9rZW4gPT0gJycpe2lmKCR0aGlzLT5HZXRBcHBBY2Nlc3NUb2tlbigpPT09IEZBTFNFKXJldHVybiBGQUxTRTt9aWYoJHRoaXMtPmFwcEFjY2Vzc1Rva2VuID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKGFjY2Vzc190b2tlbiBmb3IgYXBwIGlzIGVtcHR5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2O3JldHVybiBGQUxTRTt9ZWxzZXskcGFyYW1zID0gYXJyYXkoKTskcGFyYW1zWydtZXNzYWdlJ10gPSB1dGY4X2VuY29kZSgkZGVzY3JpcHRpb24pOyRwYXJhbXNbJ2RhdGEnXSA9ICRjdXN0b21zdHJpbmc7JHBhcmFtc1snYWNjZXNzX3Rva2VuJ10gPSAkdGhpcy0+YXBwQWNjZXNzVG9rZW47JHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgnLycuJHVzZXJpZC4nL2FwcHJlcXVlc3RzJywkcGFyYW1zLEZBTFNFLFRSVUUpO2lmKCRyZXMgPT09IEZBTFNFKXJldHVybiBGQUxTRTtlbHNle3Vuc2V0KCRyZXMyKTtpZihpc3NldCgkcmVzWydyZXF1ZXN0J10pKSRyZXMyID0gJHJlc1sncmVxdWVzdCddO2Vsc2UgJHJlczIgPSAkcmVzO3JldHVybiAkcmVzMjt9fX19cHVibGljIGZ1bmN0aW9uIEdldEFwcFJlcXVlc3QoJG1heF9udW1iPTEpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCR0aGlzLT51c2VySUQgPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAndXNlcklEIGlzIGVtcHR5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZSAkdXNlcmlkID0gJHRoaXMtPnVzZXJJRDtpZihlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW4pKXskdGhpcy0+bGFzdEVycm9yID0gJ2FjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlIC0gcGxlYXNlIEF1dGggZmlyc3QnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoJG1heF9udW1iIDwgMSB8fCAkbWF4X251bWIgPiAyMCl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlcihtYXhfbnVtYiltYXguIDIwJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskcmVzID0gJHRoaXMtPkdyYXBoQVBJKCcvJy4kdXNlcmlkLicvYXBwcmVxdWVzdHMnLCdsaW1pdD0nLiRtYXhfbnVtYik7aWYoJHJlcyA9PT0gRkFMU0UpcmV0dXJuIEZBTFNFO2Vsc2V7aWYoaXNzZXQoJHJlc1sncGFnaW5nJ10pKXVuc2V0KCRyZXNbJ3BhZ2luZyddKTt1bnNldCgkcmVzMik7aWYoaXNzZXQoJHJlc1snZGF0YSddKSYmIGNvdW50KCRyZXNbJ2RhdGEnXSk+MCl7aWYoY291bnQoJHJlc1snZGF0YSddKT09IDEpeyRyZXMyID0gJHJlc1snZGF0YSddWzBdO2lmKHN0cnBvcygkcmVzMlsnaWQnXSwnXycpIT09IEZBTFNFKSRyZXMyWydpZCddID0gc3Vic3RyKCRyZXMyWydpZCddLDAsc3RycG9zKCRyZXMyWydpZCddLCdfJykpO2lmKGlzc2V0KCRyZXMyWydjcmVhdGVkX3RpbWUnXSkpJHJlczJbJ2NyZWF0ZWRfbG9jYWx0aW1lJ10gPSBEYXRlKCdZLW0tZCBIOmk6cycsc3RydG90aW1lKCRyZXMyWydjcmVhdGVkX3RpbWUnXSkpO2lmKGlzc2V0KCRyZXMyWydtZXNzYWdlJ10pKSRyZXMyWydkZXNjcmlwdGlvbiddID0gJHJlczJbJ21lc3NhZ2UnXTtpZihpc3NldCgkcmVzMlsnZGF0YSddKSkkcmVzMlsnY3VzdG9tc3RyaW5nJ10gPSAkcmVzMlsnZGF0YSddO31lbHNleyRyZXMyID0gJHJlc1snZGF0YSddO2ZvcigkeD0wOyR4IDwgY291bnQoJHJlczIpOyR4Kyspe2lmKHN0cnBvcygkcmVzMlskeF1bJ2lkJ10sJ18nKSE9PSBGQUxTRSkkcmVzMlskeF1bJ2lkJ10gPSBzdWJzdHIoJHJlczJbJHhdWydpZCddLDAsc3RycG9zKCRyZXMyWyR4XVsnaWQnXSwnXycpKTtpZihpc3NldCgkcmVzMlskeF1bJ2NyZWF0ZWRfdGltZSddKSkkcmVzMlskeF1bJ2NyZWF0ZWRfbG9jYWx0aW1lJ10gPSBEYXRlKCdZLW0tZCBIOmk6cycsc3RydG90aW1lKCRyZXMyWyR4XVsnY3JlYXRlZF90aW1lJ10pKTtpZihpc3NldCgkcmVzMlskeF1bJ21lc3NhZ2UnXSkpJHJlczJbJHhdWydkZXNjcmlwdGlvbiddID0gJHJlczJbJHhdWydtZXNzYWdlJ107aWYoaXNzZXQoJHJlczJbJHhdWydkYXRhJ10pKSRyZXMyWyR4XVsnY3VzdG9tc3RyaW5nJ10gPSAkcmVzMlskeF1bJ2RhdGEnXTt9fX1yZXR1cm4gJHJlczI7fX19cHVibGljIGZ1bmN0aW9uIERlbEFwcFJlcXVlc3QoJHJlcXVlc3RfaWQpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKCR0aGlzLT51c2VySUQgPT0gJycpeyR0aGlzLT5sYXN0RXJyb3IgPSAndXNlcklEIGlzIGVtcHR5JzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMjE7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZSAkdXNlcmlkID0gJHRoaXMtPnVzZXJJRDtpZihlbXB0eSgkdGhpcy0+YWNjZXNzVG9rZW4pKXskdGhpcy0+bGFzdEVycm9yID0gJ2FjY2Vzc190b2tlbiBub3QgYXZhaWxhYmxlIC0gcGxlYXNlIEF1dGggZmlyc3QnOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAyNDskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNlaWYoZW1wdHkoJHJlcXVlc3RfaWQpKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyL2VtcHR5KHJlcXVlc3RfaWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZWlmKCFpc19zdHJpbmcoJHJlcXVlc3RfaWQpKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludmFsaWQgcGFyYW1ldGVyKHJlcXVlc3RfaWQpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXtpZigkdGhpcy0+YXBwQWNjZXNzVG9rZW4gPT0gJycpe2lmKCR0aGlzLT5HZXRBcHBBY2Nlc3NUb2tlbigpPT09IEZBTFNFKXJldHVybiBGQUxTRTt9aWYoJHRoaXMtPmFwcEFjY2Vzc1Rva2VuID09ICcnKXskdGhpcy0+bGFzdEVycm9yID0gJ0ludGVybmFsIEVycm9yKGFjY2Vzc190b2tlbiBmb3IgYXBwIGlzIGVtcHR5KSc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDA2O3JldHVybiBGQUxTRTt9ZWxzZXtpZihzdHJwb3MoJHJlcXVlc3RfaWQsJ18nKT09PSBGQUxTRSkkcmVxdWVzdF9pZC49J18nLiR0aGlzLT51c2VySUQ7JHBhcmFtcyA9IGFycmF5KCk7JHJlcyA9ICR0aGlzLT5HcmFwaEFQSSgnLycuJHJlcXVlc3RfaWQsJycsRkFMU0UsRkFMU0UsVFJVRSk7aWYoJHJlcyA9PT0gRkFMU0UpcmV0dXJuIEZBTFNFO2Vsc2V7cmV0dXJuICRyZXM7fX19fXB1YmxpYyBmdW5jdGlvbiBDaGVja0FwcFJlcXVlc3RDbGljaygkZXh0ZW5kZWQ9MCl7aWYoZW1wdHkoJHRoaXMtPmFwcF9jYWxsX3BhcmFtcyl8fCBzdHJwb3MoJHRoaXMtPmFwcF9jYWxsX3BhcmFtcywnZmJfc291cmNlPWJvb2ttYXJrJyk9PT1GQUxTRSl7cmV0dXJuIEZBTFNFO31lbHNleyRwYXJhbXMgPSBleHBsb2RlKCcmJywkdGhpcy0+YXBwX2NhbGxfcGFyYW1zKTtmb3JlYWNoKCRwYXJhbXMgYXMgJHZhbCl7JHZhbDIgPSBleHBsb2RlKCc9JywkdmFsKTskcGFyYW1zMlskdmFsMlswXV0gPSBzdHJ0b2xvd2VyKCR2YWwyWzFdKTt9aWYoKGlzc2V0KCRwYXJhbXMyWydmYl9zb3VyY2UnXSl8fCBpc3NldCgkcGFyYW1zMlsncmVmJ10pKSYmKCRwYXJhbXMyWydyZWYnXT09J2Jvb2ttYXJrcycgfHwgc3RycG9zKCRwYXJhbXMyWydmYl9zb3VyY2UnXSwnYm9va21hcmsnKTw+RkFMU0UpKXtpZihpc3NldCgkcGFyYW1zMlsnY291bnQnXSkmJiAkcGFyYW1zMlsnY291bnQnXT4wKWlmKCRleHRlbmRlZCA9PSAxKXskcmVzID0gJHRoaXMtPkdldEFwcFJlcXVlc3QoMSk7aWYoJHJlcyA9PT0gRkFMU0UpcmV0dXJuIEZBTFNFO2Vsc2V7JHJlczIgPSBhcnJheSgpOyRyZXMyWydjbGljayddID0gVFJVRTtpZihpc3NldCgkcmVzWydpZCddKSkkcmVzMlsnaWQnXSA9ICRyZXNbJ2lkJ107aWYoaXNzZXQoJHJlc1sndG8nXVsnaWQnXSkpJHJlczJbJ3RvX2lkJ10gPSAkcmVzWyd0byddWydpZCddO2lmKGlzc2V0KCRyZXNbJ2Rlc2NyaXB0aW9uJ10pKSRyZXMyWydkZXNjcmlwdGlvbiddID0gJHJlc1snZGVzY3JpcHRpb24nXTtpZihpc3NldCgkcmVzWydjdXN0b21zdHJpbmcnXSkpJHJlczJbJ2N1c3RvbXN0cmluZyddID0gJHJlc1snY3VzdG9tc3RyaW5nJ107aWYoaXNzZXQoJHJlc1snY3JlYXRlZF9sb2NhbHRpbWUnXSkpJHJlczJbJ2NyZWF0ZWRfbG9jYWx0aW1lJ10gPSAkcmVzWydjcmVhdGVkX2xvY2FsdGltZSddO3Vuc2V0KCRyZXMpO3JldHVybiAkcmVzMjt9fWVsc2UgcmV0dXJuIFRSVUU7ZWxzZSByZXR1cm4gRkFMU0U7fWVsc2UgcmV0dXJuIEZBTFNFO319cHVibGljIGZ1bmN0aW9uIEFjdGl2YXRlT2ZmbGluZUFjY2Vzcygpe2lmKCR0aGlzLT5ydW5Nb2RlPD4nYXBwJyl7JHRoaXMtPmxhc3RFcnJvciA9IE5PVF9JTl9USElTX01PREU7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDMxOyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fWlmKGVtcHR5KCR0aGlzLT5hY2Nlc3NUb2tlbikpeyR0aGlzLT5sYXN0RXJyb3IgPSAnYWNjZXNzX3Rva2VuIG5vdCBhdmFpbGFibGUgLSBwbGVhc2UgQXV0aCBmaXJzdCc7JHRoaXMtPmxhc3RFcnJvckNvZGUgPSAxMDI0OyR0aGlzLT5Xcml0ZUxvZygwLCR0aGlzLT5sYXN0RXJyb3JDb2RlLicgJy4kdGhpcy0+bGFzdEVycm9yKTtyZXR1cm4gRkFMU0U7fSR0b2tlbl91cmwgPSAnaHR0cHM6Ly9ncmFwaC5mYWNlYm9vay5jb20vb2F1dGgvYWNjZXNzX3Rva2VuP2NsaWVudF9pZD0nLiR0aGlzLT5hcHBJRC4nJmNsaWVudF9zZWNyZXQ9Jy4kdGhpcy0+QXBwU2VjS2V5LicmZ3JhbnRfdHlwZT1mYl9leGNoYW5nZV90b2tlbiZmYl9leGNoYW5nZV90b2tlbj0nLiR0aGlzLT5hY2Nlc3NUb2tlbjskYWNjZXNzX3Rva2VuID0gJHRoaXMtPkdldFVSTCgkdG9rZW5fdXJsKTtpZighJGFjY2Vzc190b2tlbiB8fCBzdHJsZW4oJGFjY2Vzc190b2tlbik8NjAgfHwgc3RybGVuKCRhY2Nlc3NfdG9rZW4pPjIwMCl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihGQiBkb2VzbnQgc2VuZCBhY2Nlc3NfdG9rZW4pJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMDY7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9ZWxzZXskYV90b2tlbiA9IGV4cGxvZGUoJyYnLCRhY2Nlc3NfdG9rZW4pO2ZvcmVhY2goJGFfdG9rZW4gYXMgJHZhbCA9PiAka2V5KXska2V5MiA9IGV4cGxvZGUoJz0nLCRrZXkpOyRhX3Rva2VuWyRrZXkyWzBdXSA9ICRrZXkyWzFdO31pZighaXNzZXQoJGFfdG9rZW5bJ2FjY2Vzc190b2tlbiddKSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnRlcm5hbCBFcnJvcihhY2Nlc3NfdG9rZW4gbm90IGF2YWlsYWJsZSknOyR0aGlzLT5sYXN0RXJyb3JDb2RlID0gMTAwNjskdGhpcy0+V3JpdGVMb2coMCwkdGhpcy0+bGFzdEVycm9yQ29kZS4nICcuJHRoaXMtPmxhc3RFcnJvcik7cmV0dXJuIEZBTFNFO31lbHNleyR0aGlzLT5TZXRBY2Nlc3NUb2tlbigkYV90b2tlblsnYWNjZXNzX3Rva2VuJ10sJGFfdG9rZW5bJ2V4cGlyZXMnXSk7cmV0dXJuIFRSVUU7fX19cHVibGljIGZ1bmN0aW9uIENoZWNrT2ZmbGluZUFjY2VzcygkZXh0ZW5kZWQ9MCl7JHJlcyA9ICR0aGlzLT5HZXRBY2Nlc3NUb2tlbkluZm8oKTtpZigkcmVzID09PSBGQUxTRSlyZXR1cm4gRkFMU0U7ZWxzZXtpZighaXNzZXQoJHJlc1snaXNfdmFsaWQnXSkpe3JldHVybiBGQUxTRTt9ZWxzZXtpZigkcmVzWydpc192YWxpZCddPT09RkFMU0UpcmV0dXJuIDA7ZWxzZXtpZihpc3NldCgkcmVzWyd0eXAnXSkmJiAkcmVzWyd0eXAnXT09J3Nob3J0X2xpdmVkJyl7cmV0dXJuIDA7fWVsc2V7aWYoJGV4dGVuZGVkPT0wKXJldHVybiAxO2Vsc2UgcmV0dXJuICRyZXM7fX19fX1wdWJsaWMgZnVuY3Rpb24gU29jaWFsQ29tbWVudEJveCgkaHJlZiwkd2lkdGg9MzAwLCRudW1fcG9zdHM9MSwkbGFuZ3VhZ2U9Jycpe2lmKGVtcHR5KCRocmVmKXx8IHN0cmxlbigkaHJlZik8NSl7JHRoaXMtPmxhc3RFcnJvciA9ICdJbnZhbGlkIHBhcmFtZXRlci9lbXB0eSh1cmwpJzskdGhpcy0+bGFzdEVycm9yQ29kZSA9IDEwMTk7JHRoaXMtPldyaXRlTG9nKDAsJHRoaXMtPmxhc3RFcnJvckNvZGUuJyAnLiR0aGlzLT5sYXN0RXJyb3IpO3JldHVybiBGQUxTRTt9aWYoJGxhbmd1YWdlIDw+ICcnKXskY29udGVudCA9ICR0aGlzLT5FbmFibGVYRkJNTChGQUxTRSxGQUxTRSwkbGFuZ3VhZ2UpO31lbHNleyRjb250ZW50ID0gJHRoaXMtPkVuYWJsZVhGQk1MKFRSVUUsRkFMU0UpO30kd2lkdGg9KGludCkkd2lkdGg7JG51bV9wb3N0cz0oaW50KSRudW1fcG9zdHM7JGNvbG9yc2NoZW1lPSdsaWdodCc7JG1vYmlsZT0nYXV0by1kZXRlY3QnOyRjb250ZW50Lj0nPGRpdiBjbGFzcz0iZmItY29tbWVudHMiIGRhdGEtaHJlZj0iJy4kaHJlZi4nIiBkYXRhLXdpZHRoPSInLiR3aWR0aC4nIiBkYXRhLW51bS1wb3N0cz0iJy4kbnVtX3Bvc3RzLiciIGRhdGEtY29sb3JzY2hlbWU9IicuJGNvbG9yc2NoZW1lLiciIGRhdGEtbW9iaWxlPSInLiRtb2JpbGUuJyI+PC9kaXY+JztyZXR1cm4gJGNvbnRlbnQ7fX0="));

Function Calls

base64_decode 1

Variables

None

Stats

MD5 19baf798ce56c4fd79ea04e0cbdc305a
Eval Count 1
Decode Time 204 ms