1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | <?php /** * Core Function of Villa Portal */ Class VillaPortal { /** * URL to back to the last page, usefull for redirect header * @var string */ public $linkBack; /** * Url Admin, usefull to set redirect * <br />eg. /wp-admin/admin.php?page=vp-property * @var string */ public $urlAdmin; /** * Property ID * @var array|bool Property ID */ public $propertyIdentifier; /** * Array of Configuration * @var array */ public $config; /** * Array of Plugin PATH * @var array */ public $path; /** * array of link page * @var string */ public $linkpage; // Construct function VillaPortal($path, $linkpage) { // Configuration $query = 'SELECT * FROM `vm_sys_config`'; $result = mysql_query($query); while ( $row = mysql_fetch_assoc($result) ) { $this->config = array( $row['config_name'] => $row['config_value'] ); } // Path $this->path = $path; $this->path['dir_tpl'] = $this->path['dir'].'templates/'.$this->config['tpl_dir'].'/'; $this->path['dir_inc'] = $this->path['dir'].'includes/'; $this->path['url_tpl'] = $this->path['url'].'templates/'.$this->config['tpl_dir'].'/'; $this->path['url_ico'] = $this->path['url'].'icon/'; // linkpage $this->linkpage = $linkpage; // Load Extention $this->loadExtention('DBAPI'); } function loadExtention($extName, $arrConstruct=null){ $construct = ($arrConstruct)? implode(', ', $arrConstruct) : $arrConstruct; // Database API switch ($extName){ case 'DBAPI' : if(!require $this->path['dir_inc'].'inc.db.php') return false; $this->db = new DBAPI; return true; break; case 'Property': if(!require $this->path['dir_inc'].'inc.property.php') return false; $this->property = new Property($construct); $this->propertyIdentifier =& $this->property->identifier; return true; break; case 'Room': if(!require_once $this->path['dir_inc'].'inc.room.php') return false; $this->room = new Room($construct); $this->propertyIdentifier =& $this->property->identifier; return true; break; default: return false; break; } } function listLocation() { $resultCountry = mysql_query(" SELECT * FROM `vm_sys_location` WHERE `loc_parent` = '0' "); if (mysql_num_rows($resultCountry) != 0 ) { echo '<ul class="list-location">'; while ( $row = mysql_fetch_assoc($resultCountry) ) { echo '<li>'; echo '<span>'.$row['loc_name'].' <a href="?page=vp-config-country&mode=addlocation&do=add&parent='.$row['loc_id'].'"> <img src="'.$this->path['url_ico'].'action_add.png" title="Add Child" /> </a> <a href="?page=vp-config-country&mode=addlocation&do=edit&id='.$row['loc_id'].'"> <img src="'.$this->path['url_ico'].'file.png" title="Edit" /> </a> <a href="?page=vp-config-country&mode=deletelocation&id='.$row['loc_id'].'"> <img src="'.$this->path['url_ico'].'action_delete.png" title="Delete" /> </a> </span>'; $resultArea = mysql_query(' SELECT * FROM `vm_sys_location` WHERE `loc_parent` = \''.$row['loc_id'].'\' '); if ( mysql_num_rows($resultArea) != 0) { echo '<ul>'; while ( $rowArea = mysql_fetch_assoc($resultArea) ) { echo '<li>'; echo '<span>'.$rowArea['loc_name'].' <a href="?page=vp-config-country&mode=addlocation&do=add&parent='.$rowArea['loc_id'].'"> <img src="'.$this->path['url_ico'].'action_add.png" title="Add Child" /> </a> <a href="?page=vp-config-country&mode=addlocation&do=edit&id='.$rowArea['loc_id'].'"> <img src="'.$this->path['url_ico'].'file.png" title="Edit" /> </a> <a href="?page=vp-config-country&mode=deletelocation&id='.$rowArea['loc_id'].'"> <img src="'.$this->path['url_ico'].'action_delete.png" title="Delete" /> </a> </span>'; $resultCity = mysql_query(' SELECT * FROM `vm_sys_location` WHERE `loc_parent` = \''.$rowArea['loc_id'].'\' '); if ( mysql_num_rows($resultCity) != 0 ) { echo '<ul>'; while ( $rowCity = mysql_fetch_assoc($resultCity) ) { echo '<li>'.$rowCity['loc_name'].' <a href="?page=vp-config-country&mode=addlocation&do=edit&id='.$rowCity['loc_id'].'"> <img src="'.$this->path['url_ico'].'file.png" title="Edit" /> </a> <a href="?page=vp-config-country&mode=deletelocation&id='.$rowCity['loc_id'].'"> <img src="'.$this->path['url_ico'].'action_delete.png" title="Delete" /> </a> </li>'; } echo '</ul>'; } echo '</li>'; } echo '</ul>'; } echo '</li>'; } echo '</ul>'; } } function saveLocation($callback){ $data['loc_id'] = $_POST['thisId']; $data['loc_parent'] = $_POST['parentId']; $data['loctype_id'] = $_POST['thisTypeId']; $data['loc_name'] = $_POST['thisName']; if ($data['loc_id'] == '') { // mode Add $data['loc_id'] = 'null'; $this->db->insert('vm_sys_location', $data); } else { // mode edit $this->db->update('vm_sys_location', $data, 'loc_id='.$data['loc_id']); } header('Location: '.$callback); } function deleteLocation($id, $callback) { $data['loc_id'] = $_GET['id']; $this->db->delete('vm_sys_location', "loc_id=$id"); header('Location: '.$callback); } function formAddLocation($target) { if ($_GET['do'] == 'add') { $parent = ( isset($_GET['parent']) )? $_GET['parent'] : 0; $parentId = $parent; $thisId = ''; $thisName = ''; if ($parent==0){ $thisTypeId = 1; } else { $thisTypeId = $this->getLocType($parent)+1; } } else if ($_GET['do'] == 'edit') { $id = $_GET['id']; $parentId = $this->getLocation($id, 'loc_parent'); $thisTypeId = $this->getLocation($id, 'loctype_id'); $thisId = $this->getLocation($id, 'loc_id'); $thisName = $this->getLocation($id, 'loc_name'); } $search = array( 'target' => $target, 'thisId' => $thisId, 'parentId' => $parentId, 'thisTypeId' => $thisTypeId, 'thisName' => $thisName ); $return = $this->parseChunk('form-addlocation.php', $search, '[+', '+]'); // print $return; } function getLocation ($loc_id, $field) { $result = $this->dbResult('vm_sys_location', $field, "loc_id=$loc_id"); while ($row = mysql_fetch_assoc($result)) { $return = $row[$field]; } return $return; mysql_free_result($result); } function getLocType ($loc_id) { $result = $this->dbResult('vm_sys_location', '*', "loc_id=$loc_id"); while ($row = mysql_fetch_assoc($result)) { $return = $row['loctype_id']; } return (int)$return; } function getListLocation($tpl, $parent=0) { $result = $this->dbResult('vm_sys_location', '*', "loc_parent=$parent"); if ( mysql_num_rows($result) != 0 ) { while ( $row = mysql_fetch_assoc($result) ) { $return .= $this->parseChunk($tpl, array('id' => $row['loc_id'], 'name' => $row['loc_name']) ); } } return $return; mysql_free_result($result); } function dbResult ($table, $select, $condition='', $limit='', $orderBy='') { $table = "FROM $table "; $select = "SELECT $select "; $condition = ($condition != '')? "WHERE $condition " : $condition; $limit = ($limit != '')? "LIMIT $limit " : $limit; $orderBy = ($orderBy != '')? "ORDER BY $orderBy " : $orderBy; $query = $select.$table.$condition.$orderBy.$limit; return mysql_query($query); } /** * Show List Property * @param string $tpl Template * @param string $tplWrap Template Wrap * @param int $limit Limit Show, DEFAULT: NULL * @return string */ function propertyList($tpl, $tplWrap, $limit=null) { $fetch = $this->db->fetch('vm_property'); foreach ($fetch as $key=>$value) { $fetch[$key] = $this->addPropertyKey($value); } foreach ($fetch as $value) { $data .= $this->parseChunk($tpl, $value); } $property['list'] = $data; $property['urlAdd'] = $this->linkpage['property'].'&show=propertyedit'; $template = $this->parseChunk($tplWrap, $property); return $template; } function propertyEdit($tpl) { if($this->propertyIdentifier){ $fetch = $this->property->data; }else{ $fieldName = $this->db->getTableFields('vm_property'); while ($row = mysql_fetch_assoc($fieldName) ){ $fetch[ $row['Field'] ] = ''; } } // Aditional Data $fetch['listCountry'] = $this->getFormLocation(1, 'country', 'country'); $fetch['listProvince'] = $this->getFormLocation(3, 'province', 'province'); $fetch['listCity'] = $this->getFormLocation(4, 'city', 'city'); $fetch['formAction'] = '?page=vp-property&show=action&action=update&id='.$this->propertyIdentifier; $return = $this->parseChunk($tpl, $fetch); return $return; } function getFormLocation($typeLocation, $className, $selectName){ $fetch = $this->db->fetch('vm_sys_location', '*', 'loctype_id='.$typeLocation); if ( count($fetch) ){ $return = '<select class="'.$className.'" name="'.$selectName.'">'; $return .= '<option value="">------</option>'; foreach($fetch as $value){ if ( $value['loc_id'] == $this->property->getLocationIdByType($typeLocation) ){ $return .= '<option value="'.$value['loc_id'].'" selected="selected">'.$value['loc_name'].'</option>'; }else{ $return .= '<option value="'.$value['loc_id'].'">'.$value['loc_name'].'</option>'; } } $return .= '</select>'; } return $return; } function addPropertyKey($data) { $id = $data['id']; $data['link'] = $this->linkpage['property'].'&show=property'."&id=$id"; $data['actionEdit'] = $this->linkpage['property'].'&show=propertyedit'."&id=$id"; $data['actionDelete'] = $this->linkpage['property'].'&show=action'.'&action=delete'."&id=$id"; $data['actionViewRoom'] = $this->linkpage['property'].'&show=property'."&id=$id"; $data['action'] = $this->getIcon( 'icon.php', array('viewroom','edit','delete'), array($data['actionViewRoom'],$data['actionEdit'], $data['actionDelete']) ); return $data; } function getIcon($tpl, $arrIcon, $arrLinkAction) { $path = $this->path['url_ico']; $listIcon = array( 'delete' => $path.'action_delete.png', 'edit' => $path.'file.png', 'viewroom' => $path.'application.png', 'setPrice' => $path.'reply.png' ); foreach ($arrIcon as $key=>$value) { $data['name'] = $value; $data['image'] = $listIcon[$value]; $data['link'] = $arrLinkAction[$key]; $return .= $this->parseChunk($tpl, $data); } return $return; } /*------- Chunk Template System ----------*/ function parseChunk($chunkName, $chunkArr, $prefix= "[+", $suffix= "+]") { if ( !is_array($chunkArr) ) { return false; } $chunk = $this->getChunk($chunkName); foreach ($chunkArr as $key=>$value) { $chunk = str_replace($prefix.$key.$suffix, $value, $chunk); } return $chunk; } function getChunk($chunkName) { $read = $this->path['dir_tpl'].$chunkName; if ( file_exists($read) ) { $content = file_get_contents($read); } else { return false; } return $content; } /** * Print Document Parser * @param string $tpl Template Name * @param array $arrData Data to be sent */ function parser($tpl, $arrData) { print $this->parseChunk($tpl, $arrData); } function registerCSS(){ // Register CSS wp_register_style('villa-portal-style', $this->path['url_tpl'].'style.css', null, '0.1' ); wp_enqueue_style('villa-portal-style'); } function registerScript(){ // Tyny MCE wp_register_script('tinymce', $this->path['url'].'extention/tiny_mce/jquery.tinymce.js', null, '0.1' ); wp_enqueue_script('tinymce'); wp_register_script('villa-portal-script', $this->path['url'].'site.js', null, '0.1' ); wp_enqueue_script('villa-portal-script'); } function getProperty($tpl, $propertyId=null) { $propertyId = ($propertyId)? $propertyId : $this->propertyIdentifier; $return = $this->parseChunk($tpl, $this->property->data); return $return; } function propertyUpdate($data) { if( $this->db->update('vm_property', $data, 'id='.$this->propertyIdentifier) ){ return true; }else{ return false; } } function propertyInsert($data) { $this->db->insert('vm_property', $data); } /** * Delete Property * @return bool Return true on success */ function propertyDelete() { if ($this->propertyIdentifier) { $this->db->delete('vm_property', 'id='.$this->propertyIdentifier); return true; } } function showRoom($tpl, $tplWrap, $limit=null) { if ($this->propertyIdentifier) { $return = '<h2>List Room</h2>'; $return .= '<a href="'.$this->urlAdmin.'&show=roomaction&roomaction=create&id='.$this->propertyIdentifier.'" class="button">Create Room</a>'; $data['listRoom'] = ''; $result = $this->db->select('vm_room', '*', 'property_id='.$this->propertyIdentifier); if ( mysql_num_rows($result) ) { while ( $row = mysql_fetch_assoc($result) ){ $row['url'] = $this->urlAdmin.'&show=roomaction&roomaction=create&id='.$this->propertyIdentifier.'&roomid='.$row['id']; $row['price'] = $this->getRoomPrice($row['id']); $row['action'] = $this->getRoomAction( $row['id'], "<td>%s</td>", $row['url'] ); $data['listRoom'] .= $this->parseChunk($tpl, $row); } $return .= $this->parseChunk($tplWrap, $data); } print($return); } } function getRoomAction($id, $wrap, $linkBase){ $data['actionEdit'] = $linkBase; // $data['actionDelete'] = str_replace('&roomaction=create', '&roomaction=dodelete', $linkBase); $data['actionSetPrice'] = str_replace( array('&show=roomaction', '&roomaction=create'), array('&show=roomprice', ''), $linkBase ); $action = $this->getIcon( 'icon.php', array('edit','delete','setPrice'), array($data['actionEdit'],$data['actionDelete'], $data['actionSetPrice']) ); return $action; } function getRoomPrice($roomId){ } function room_delete($roomId) { $this->db->delete('vm_room', 'id='.$roomId); } function listRate($roomId=null, $yearMonth=null ) { $roomId = ($roomId)? $roomId : $this->room->identifier; $yearMonth = ($yearMonth)? $yearMonth : $_SESSION['rateDate']; $yearMonth = ($yearMonth)? $yearMonth : date('Y-m'); $rate = $this->room->generateRate($yearMonth); foreach ($rate as $value) { $data['listRate'] .= $this->parseChunk('roomrate.php', $value); } $data['link-property'] = $this->urlAdmin.'&show=property&id='.$this->propertyIdentifier; $data['link-formaction'] = $this->urlAdmin.'&show=roomprice&roomprice=update&id='.$this->propertyIdentifier.'&roomid='.$this->room->identifier; $data['listSelectMonth'] = $this->genSelectMonth(); $data['listSelectYear'] = $this->genSelectYear(); $return = $this->parseChunk('roomrate-wrap.php', $data); return $return; } function genSelectMonth() { $monthArry = array( '01' => 'January', '02' => 'February', '03' => 'March', '04' => 'April', '05' => 'May', '06' => 'June', '07' => 'July', '08' => 'August', '09' => 'September', '10' => 'October', '11' => 'November', '12' => 'December' ); $monthNow = Date('m'); foreach ($monthArry as $key=>$value) { $selected = ($key == $monthNow)? 'selected="selected"' : ''; $return .= '<option value="'.$key.'" '.$selected.'>'.$value.'</option>'; } return $return; } function genSelectYear() { $year = (int)Date('Y'); for ($i=0; $i < 4; $i++) { $yearIncrement = $year + $i; $return .= '<option value="'.$yearIncrement.'">'.$yearIncrement.'</option>'; } return $return; } function configListFacility() { $i = 1; $result = $this->db->select('vm_facility'); if( mysql_num_rows($result) ) { $data = $this->db->fetch('vm_facility'); foreach($data as $key=>$value) { $data[$key]['actionDelete'] = '<a href="/wp-admin/admin.php?page=vp-config-facility&action=delete&id='.$data[$key]['id'].'"> <img src="'.$this->path['url_ico'].'action_delete.png" /></a>'; } $i++; } foreach ($data as $key=>$value) { $parser['listFacility'] .= $this->parseChunk('config-facility.php', $value); } $return = $this->parseChunk('config-facility-wrap.php', $parser); print($return); } function showFacility(){ if ( $_POST['action'] == 'facility' ) { unset($_POST['action']); $this->propertyFacilityUpdate($_POST); } $data['title'] = 'Facility'; $data['propertyId'] = $this->propertyIdentifier; $data['listFacility'] = $this->genListFacility(); $return = $this->parseChunk('facility-wrap.php', $data); print $return; } function genListFacility() { $arrFacility = $this->db->fetch('vm_facility'); $arrPropertyFacility = explode(',', $this->db->result('vm_property', 'facility', 'id='.$this->propertyIdentifier)); foreach ($arrFacility as $facility) { foreach ($arrPropertyFacility as $propertyFacility) { // Check if the Facility ID is included in this property facility if ($facility['id'] == $propertyFacility) { $facility['checked'] = 'checked="checked"'; break; }else{ $facility['checked'] = ''; } } $return .= $this->parseChunk('facility.php', $facility); } return $return; } function propertyFacilityUpdate($data) { $data = implode(',', $data['facility']); $update['facility'] = $data; $this->db->update('vm_property', $update, 'id='.$this->propertyIdentifier, $debug=false); } } ?> |
PD9waHAKLyoqCiAqIENvcmUgRnVuY3Rpb24gb2YgVmlsbGEgUG9ydGFsCiAqLwpDbGFzcyBWaWxsYVBvcnRhbCB7CgogICAgLyoqCiAgICAgKiBVUkwgdG8gYmFjayB0byB0aGUgbGFzdCBwYWdlLCB1c2VmdWxsIGZvciByZWRpcmVjdCBoZWFkZXIKICAgICAqIEB2YXIgc3RyaW5nCiAgICAgKi8KICAgIHB1YmxpYyAkbGlua0JhY2s7CgogICAgLyoqCiAgICAgKiBVcmwgQWRtaW4sIHVzZWZ1bGwgdG8gc2V0IHJlZGlyZWN0CiAgICAgKiA8YnIgLz5lZy4gL3dwLWFkbWluL2FkbWluLnBocD9wYWdlPXZwLXByb3BlcnR5CiAgICAgKiBAdmFyIHN0cmluZyAKICAgICAqLwogICAgcHVibGljICR1cmxBZG1pbjsKCiAgICAvKioKICAgICAqIFByb3BlcnR5IElECiAgICAgKiBAdmFyIGFycmF5fGJvb2wgUHJvcGVydHkgSUQKICAgICAqLwogICAgcHVibGljICRwcm9wZXJ0eUlkZW50aWZpZXI7CgogICAgLyoqCiAgICAgKiBBcnJheSBvZiBDb25maWd1cmF0aW9uCiAgICAgKiBAdmFyIGFycmF5CiAgICAgKi8KICAgIHB1YmxpYyAkY29uZmlnOwoKICAgIC8qKgogICAgICogQXJyYXkgb2YgUGx1Z2luIFBBVEgKICAgICAqIEB2YXIgYXJyYXkKICAgICAqLwogICAgcHVibGljICRwYXRoOwoKICAgIC8qKgogICAgICogYXJyYXkgb2YgbGluayBwYWdlCiAgICAgKiBAdmFyIHN0cmluZwogICAgICovCiAgICBwdWJsaWMgJGxpbmtwYWdlOwoKICAgIC8vIENvbnN0cnVjdAogICAgZnVuY3Rpb24gVmlsbGFQb3J0YWwoJHBhdGgsICRsaW5rcGFnZSkgewoJCS8vIENvbmZpZ3VyYXRpb24KCQkkcXVlcnkgPSAnU0VMRUNUICogRlJPTSBgdm1fc3lzX2NvbmZpZ2AnOwoJCSRyZXN1bHQgPSBteXNxbF9xdWVyeSgkcXVlcnkpOwoJCQoJCXdoaWxlICggJHJvdyA9IG15c3FsX2ZldGNoX2Fzc29jKCRyZXN1bHQpICkgewoJCQkkdGhpcy0+Y29uZmlnID0gYXJyYXkoICRyb3dbJ2NvbmZpZ19uYW1lJ10gPT4gJHJvd1snY29uZmlnX3ZhbHVlJ10gKTsKCQl9CgoJCS8vIFBhdGgKCQkkdGhpcy0+cGF0aCA9ICRwYXRoOwoJCSR0aGlzLT5wYXRoWydkaXJfdHBsJ10gPSAkdGhpcy0+cGF0aFsnZGlyJ10uJ3RlbXBsYXRlcy8nLiR0aGlzLT5jb25maWdbJ3RwbF9kaXInXS4nLyc7CgkJJHRoaXMtPnBhdGhbJ2Rpcl9pbmMnXSA9ICR0aGlzLT5wYXRoWydkaXInXS4naW5jbHVkZXMvJzsKCQkkdGhpcy0+cGF0aFsndXJsX3RwbCddID0gJHRoaXMtPnBhdGhbJ3VybCddLid0ZW1wbGF0ZXMvJy4kdGhpcy0+Y29uZmlnWyd0cGxfZGlyJ10uJy8nOwoJCSR0aGlzLT5wYXRoWyd1cmxfaWNvJ10gPSAkdGhpcy0+cGF0aFsndXJsJ10uJ2ljb24vJzsKCgkJLy8gbGlua3BhZ2UKCQkkdGhpcy0+bGlua3BhZ2UgPSAkbGlua3BhZ2U7CgoJCS8vIExvYWQgRXh0ZW50aW9uCgkJJHRoaXMtPmxvYWRFeHRlbnRpb24oJ0RCQVBJJyk7CiAgICB9CgogICAgIGZ1bmN0aW9uIGxvYWRFeHRlbnRpb24oJGV4dE5hbWUsICRhcnJDb25zdHJ1Y3Q9bnVsbCl7CgkkY29uc3RydWN0ID0gKCRhcnJDb25zdHJ1Y3QpPyBpbXBsb2RlKCcsICcsICRhcnJDb25zdHJ1Y3QpIDogJGFyckNvbnN0cnVjdDsKCgkvLyBEYXRhYmFzZSBBUEkKCXN3aXRjaCAoJGV4dE5hbWUpewoJICAgIGNhc2UgJ0RCQVBJJyA6CgkJaWYoIXJlcXVpcmUgJHRoaXMtPnBhdGhbJ2Rpcl9pbmMnXS4naW5jLmRiLnBocCcpCgkJCXJldHVybiBmYWxzZTsKCQkkdGhpcy0+ZGIgPSBuZXcgREJBUEk7CgkJcmV0dXJuIHRydWU7CgkJYnJlYWs7CgkgICAgY2FzZSAnUHJvcGVydHknOgoJCWlmKCFyZXF1aXJlICR0aGlzLT5wYXRoWydkaXJfaW5jJ10uJ2luYy5wcm9wZXJ0eS5waHAnKQoJCQlyZXR1cm4gZmFsc2U7CgkJJHRoaXMtPnByb3BlcnR5ID0gbmV3IFByb3BlcnR5KCRjb25zdHJ1Y3QpOwoJCSR0aGlzLT5wcm9wZXJ0eUlkZW50aWZpZXIgPSYgJHRoaXMtPnByb3BlcnR5LT5pZGVudGlmaWVyOwoJCXJldHVybiB0cnVlOwoJCWJyZWFrOwoJICAgIGNhc2UgJ1Jvb20nOgoJCWlmKCFyZXF1aXJlX29uY2UgJHRoaXMtPnBhdGhbJ2Rpcl9pbmMnXS4naW5jLnJvb20ucGhwJykKCQkJcmV0dXJuIGZhbHNlOwoJCSR0aGlzLT5yb29tID0gbmV3IFJvb20oJGNvbnN0cnVjdCk7CgkJJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllciA9JiAkdGhpcy0+cHJvcGVydHktPmlkZW50aWZpZXI7CgkJcmV0dXJuIHRydWU7CgkJYnJlYWs7CgkgICAgZGVmYXVsdDoKCQlyZXR1cm4gZmFsc2U7CgkJYnJlYWs7Cgl9CiAgICB9CgogICAgZnVuY3Rpb24gbGlzdExvY2F0aW9uKCkgewoJJHJlc3VsdENvdW50cnkgPSBteXNxbF9xdWVyeSgiCgkgICAgU0VMRUNUICoKCSAgICBGUk9NIGB2bV9zeXNfbG9jYXRpb25gCgkgICAgV0hFUkUgYGxvY19wYXJlbnRgID0gJzAnCgkgICAgIik7CgoJaWYgKG15c3FsX251bV9yb3dzKCRyZXN1bHRDb3VudHJ5KSAhPSAwICkgewoJICAgIGVjaG8gJzx1bCBjbGFzcz0ibGlzdC1sb2NhdGlvbiI+JzsKCSAgICB3aGlsZSAoICRyb3cgPSBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0Q291bnRyeSkgKSB7CgkJZWNobyAnPGxpPic7CgkJZWNobyAnPHNwYW4+Jy4kcm93Wydsb2NfbmFtZSddLicKCQkJPGEgaHJlZj0iP3BhZ2U9dnAtY29uZmlnLWNvdW50cnkmbW9kZT1hZGRsb2NhdGlvbiZkbz1hZGQmcGFyZW50PScuJHJvd1snbG9jX2lkJ10uJyI+CgkJCSAgICA8aW1nIHNyYz0iJy4kdGhpcy0+cGF0aFsndXJsX2ljbyddLidhY3Rpb25fYWRkLnBuZyIgdGl0bGU9IkFkZCBDaGlsZCIgLz4KCQkJPC9hPgoJCQk8YSBocmVmPSI/cGFnZT12cC1jb25maWctY291bnRyeSZtb2RlPWFkZGxvY2F0aW9uJmRvPWVkaXQmaWQ9Jy4kcm93Wydsb2NfaWQnXS4nIj4KCQkJICAgIDxpbWcgc3JjPSInLiR0aGlzLT5wYXRoWyd1cmxfaWNvJ10uJ2ZpbGUucG5nIiB0aXRsZT0iRWRpdCIgLz4KCQkJPC9hPgoJCQk8YSBocmVmPSI/cGFnZT12cC1jb25maWctY291bnRyeSZtb2RlPWRlbGV0ZWxvY2F0aW9uJmlkPScuJHJvd1snbG9jX2lkJ10uJyI+CgkJCSAgICA8aW1nIHNyYz0iJy4kdGhpcy0+cGF0aFsndXJsX2ljbyddLidhY3Rpb25fZGVsZXRlLnBuZyIgdGl0bGU9IkRlbGV0ZSIgLz4KCQkJPC9hPgoJCQk8L3NwYW4+JzsKCgkJJHJlc3VsdEFyZWEgPSBteXNxbF9xdWVyeSgnCgkJICAgIFNFTEVDVCAqCgkJICAgIEZST00gYHZtX3N5c19sb2NhdGlvbmAKCQkgICAgV0hFUkUgYGxvY19wYXJlbnRgID0gXCcnLiRyb3dbJ2xvY19pZCddLidcJwoJCSAgICAnKTsKCQlpZiAoIG15c3FsX251bV9yb3dzKCRyZXN1bHRBcmVhKSAhPSAwKSB7CgkJICAgIGVjaG8gJzx1bD4nOwoJCSAgICB3aGlsZSAoICRyb3dBcmVhID0gbXlzcWxfZmV0Y2hfYXNzb2MoJHJlc3VsdEFyZWEpICkgewoJCQllY2hvICc8bGk+JzsKCQkJZWNobyAnPHNwYW4+Jy4kcm93QXJlYVsnbG9jX25hbWUnXS4nCgkJCQk8YSBocmVmPSI/cGFnZT12cC1jb25maWctY291bnRyeSZtb2RlPWFkZGxvY2F0aW9uJmRvPWFkZCZwYXJlbnQ9Jy4kcm93QXJlYVsnbG9jX2lkJ10uJyI+CgkJCQkgICAgPGltZyBzcmM9IicuJHRoaXMtPnBhdGhbJ3VybF9pY28nXS4nYWN0aW9uX2FkZC5wbmciIHRpdGxlPSJBZGQgQ2hpbGQiIC8+CgkJCQk8L2E+CgkJCQk8YSBocmVmPSI/cGFnZT12cC1jb25maWctY291bnRyeSZtb2RlPWFkZGxvY2F0aW9uJmRvPWVkaXQmaWQ9Jy4kcm93QXJlYVsnbG9jX2lkJ10uJyI+CgkJCQkgICAgPGltZyBzcmM9IicuJHRoaXMtPnBhdGhbJ3VybF9pY28nXS4nZmlsZS5wbmciIHRpdGxlPSJFZGl0IiAvPgoJCQkJPC9hPgoJCQkJPGEgaHJlZj0iP3BhZ2U9dnAtY29uZmlnLWNvdW50cnkmbW9kZT1kZWxldGVsb2NhdGlvbiZpZD0nLiRyb3dBcmVhWydsb2NfaWQnXS4nIj4KCQkJCSAgICA8aW1nIHNyYz0iJy4kdGhpcy0+cGF0aFsndXJsX2ljbyddLidhY3Rpb25fZGVsZXRlLnBuZyIgdGl0bGU9IkRlbGV0ZSIgLz4KCQkJCTwvYT4KCQkJPC9zcGFuPic7CgoJCQkkcmVzdWx0Q2l0eSA9IG15c3FsX3F1ZXJ5KCcKCQkJICAgIFNFTEVDVCAqCgkJCSAgICBGUk9NIGB2bV9zeXNfbG9jYXRpb25gCgkJCSAgICBXSEVSRSBgbG9jX3BhcmVudGAgPSBcJycuJHJvd0FyZWFbJ2xvY19pZCddLidcJwoJCQkgICAgJyk7CgkJCWlmICggbXlzcWxfbnVtX3Jvd3MoJHJlc3VsdENpdHkpICE9IDAgKSB7CgkJCSAgICBlY2hvICc8dWw+JzsKCQkJICAgIHdoaWxlICggJHJvd0NpdHkgPSBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0Q2l0eSkgKSB7CgkJCQllY2hvICc8bGk+Jy4kcm93Q2l0eVsnbG9jX25hbWUnXS4nCgkJCQkgICAgPGEgaHJlZj0iP3BhZ2U9dnAtY29uZmlnLWNvdW50cnkmbW9kZT1hZGRsb2NhdGlvbiZkbz1lZGl0JmlkPScuJHJvd0NpdHlbJ2xvY19pZCddLiciPgoJCQkJCTxpbWcgc3JjPSInLiR0aGlzLT5wYXRoWyd1cmxfaWNvJ10uJ2ZpbGUucG5nIiB0aXRsZT0iRWRpdCIgLz4KCQkJCSAgICA8L2E+CgkJCQkgICAgPGEgaHJlZj0iP3BhZ2U9dnAtY29uZmlnLWNvdW50cnkmbW9kZT1kZWxldGVsb2NhdGlvbiZpZD0nLiRyb3dDaXR5Wydsb2NfaWQnXS4nIj4KCQkJCQk8aW1nIHNyYz0iJy4kdGhpcy0+cGF0aFsndXJsX2ljbyddLidhY3Rpb25fZGVsZXRlLnBuZyIgdGl0bGU9IkRlbGV0ZSIgLz4KCQkJCSAgICA8L2E+CgkJCQkgICAgPC9saT4nOwoJCQkgICAgfQoJCQkgICAgZWNobyAnPC91bD4nOwoJCQl9CgoJCQllY2hvICc8L2xpPic7CgkJICAgIH0KCgkJICAgIGVjaG8gJzwvdWw+JzsKCQl9CgkJZWNobyAnPC9saT4nOwoJICAgIH0KCSAgICBlY2hvICc8L3VsPic7Cgl9CQogICAgfSAgICAKCiAgICBmdW5jdGlvbiBzYXZlTG9jYXRpb24oJGNhbGxiYWNrKXsKCQkkZGF0YVsnbG9jX2lkJ10JICAgID0gJF9QT1NUWyd0aGlzSWQnXTsKCQkkZGF0YVsnbG9jX3BhcmVudCddID0gJF9QT1NUWydwYXJlbnRJZCddOwoJCSRkYXRhWydsb2N0eXBlX2lkJ10gPSAkX1BPU1RbJ3RoaXNUeXBlSWQnXTsKCQkkZGF0YVsnbG9jX25hbWUnXSAgID0gJF9QT1NUWyd0aGlzTmFtZSddOwoKCQlpZiAoJGRhdGFbJ2xvY19pZCddID09ICcnKSB7IC8vIG1vZGUgQWRkCgkJCSRkYXRhWydsb2NfaWQnXSA9ICdudWxsJzsKCQkJJHRoaXMtPmRiLT5pbnNlcnQoJ3ZtX3N5c19sb2NhdGlvbicsICRkYXRhKTsKCQl9IGVsc2UgeyAvLyBtb2RlIGVkaXQJICAgIAoJCQkkdGhpcy0+ZGItPnVwZGF0ZSgndm1fc3lzX2xvY2F0aW9uJywgJGRhdGEsICdsb2NfaWQ9Jy4kZGF0YVsnbG9jX2lkJ10pOwoJCX0KCgkJaGVhZGVyKCdMb2NhdGlvbjogJy4kY2FsbGJhY2spOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlbGV0ZUxvY2F0aW9uKCRpZCwgJGNhbGxiYWNrKSB7CgkJJGRhdGFbJ2xvY19pZCddCT0gJF9HRVRbJ2lkJ107CgkJJHRoaXMtPmRiLT5kZWxldGUoJ3ZtX3N5c19sb2NhdGlvbicsICJsb2NfaWQ9JGlkIik7CgoJCWhlYWRlcignTG9jYXRpb246ICcuJGNhbGxiYWNrKTsKICAgIH0KCiAgICBmdW5jdGlvbiBmb3JtQWRkTG9jYXRpb24oJHRhcmdldCkgewoJaWYgKCRfR0VUWydkbyddID09ICdhZGQnKSB7CgkgICAgJHBhcmVudCA9ICggaXNzZXQoJF9HRVRbJ3BhcmVudCddKSApPyAkX0dFVFsncGFyZW50J10gOiAwOwoJICAgICRwYXJlbnRJZCA9ICRwYXJlbnQ7CgkgICAgJHRoaXNJZCA9ICcnOwoJICAgICR0aGlzTmFtZSA9ICcnOwoJICAgIGlmICgkcGFyZW50PT0wKXsKCQkkdGhpc1R5cGVJZCA9IDE7CgkgICAgfSBlbHNlIHsJCQoJCSR0aGlzVHlwZUlkID0gJHRoaXMtPmdldExvY1R5cGUoJHBhcmVudCkrMTsJCQoJICAgIH0KCX0gZWxzZSBpZiAoJF9HRVRbJ2RvJ10gPT0gJ2VkaXQnKSB7CgkgICAgJGlkID0gJF9HRVRbJ2lkJ107CgkgICAgJHBhcmVudElkID0gJHRoaXMtPmdldExvY2F0aW9uKCRpZCwgJ2xvY19wYXJlbnQnKTsKCSAgICAkdGhpc1R5cGVJZCA9ICR0aGlzLT5nZXRMb2NhdGlvbigkaWQsICdsb2N0eXBlX2lkJyk7CgkgICAgJHRoaXNJZCA9ICR0aGlzLT5nZXRMb2NhdGlvbigkaWQsICdsb2NfaWQnKTsKCSAgICAkdGhpc05hbWUgPSAkdGhpcy0+Z2V0TG9jYXRpb24oJGlkLCAnbG9jX25hbWUnKTsKCX0KCQoJJHNlYXJjaCA9IGFycmF5KAoJICAgICd0YXJnZXQnID0+ICR0YXJnZXQsCgkgICAgJ3RoaXNJZCcgPT4gJHRoaXNJZCwKCSAgICAncGFyZW50SWQnID0+ICRwYXJlbnRJZCwKCSAgICAndGhpc1R5cGVJZCcgPT4gJHRoaXNUeXBlSWQsCgkgICAgJ3RoaXNOYW1lJyA9PiAkdGhpc05hbWUKCSAgICApOwoJCgkkcmV0dXJuID0gJHRoaXMtPnBhcnNlQ2h1bmsoJ2Zvcm0tYWRkbG9jYXRpb24ucGhwJywgJHNlYXJjaCwgJ1srJywgJytdJyk7IC8vCglwcmludCAkcmV0dXJuOwoJCiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TG9jYXRpb24gKCRsb2NfaWQsICRmaWVsZCkgewoJJHJlc3VsdCA9ICR0aGlzLT5kYlJlc3VsdCgndm1fc3lzX2xvY2F0aW9uJywgJGZpZWxkLCAibG9jX2lkPSRsb2NfaWQiKTsKCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXNzb2MoJHJlc3VsdCkpIHsKCSAgICAkcmV0dXJuID0gJHJvd1skZmllbGRdOwoJfQoKCXJldHVybiAkcmV0dXJuOwoJbXlzcWxfZnJlZV9yZXN1bHQoJHJlc3VsdCk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TG9jVHlwZSAoJGxvY19pZCkgewoJJHJlc3VsdCA9ICR0aGlzLT5kYlJlc3VsdCgndm1fc3lzX2xvY2F0aW9uJywgJyonLCAibG9jX2lkPSRsb2NfaWQiKTsKCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXNzb2MoJHJlc3VsdCkpIHsKCSAgICAkcmV0dXJuID0gJHJvd1snbG9jdHlwZV9pZCddOwoJfQoKCXJldHVybiAoaW50KSRyZXR1cm47CiAgICB9CiAgICAKICAgIGZ1bmN0aW9uIGdldExpc3RMb2NhdGlvbigkdHBsLCAkcGFyZW50PTApIHsKCSRyZXN1bHQgPSAkdGhpcy0+ZGJSZXN1bHQoJ3ZtX3N5c19sb2NhdGlvbicsICcqJywgImxvY19wYXJlbnQ9JHBhcmVudCIpOwoJCglpZiAoIG15c3FsX251bV9yb3dzKCRyZXN1bHQpICE9IDAgKSB7CSAgICAKCSAgICB3aGlsZSAoICRyb3cgPSBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0KSApIHsKCQkkcmV0dXJuIC49ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsIGFycmF5KCdpZCcgPT4gJHJvd1snbG9jX2lkJ10sCgkJCQkJCQknbmFtZScgPT4gJHJvd1snbG9jX25hbWUnXSkgKTsJCQoJICAgIH0KCX0KCglyZXR1cm4gJHJldHVybjsKCW15c3FsX2ZyZWVfcmVzdWx0KCRyZXN1bHQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGRiUmVzdWx0ICgkdGFibGUsICRzZWxlY3QsICRjb25kaXRpb249JycsICRsaW1pdD0nJywgJG9yZGVyQnk9JycpIHsKCSR0YWJsZSA9ICJGUk9NICR0YWJsZSAiOwoJJHNlbGVjdCA9ICJTRUxFQ1QgJHNlbGVjdCAiOwoJJGNvbmRpdGlvbiA9ICgkY29uZGl0aW9uICE9ICcnKT8gIldIRVJFICRjb25kaXRpb24gIiA6ICRjb25kaXRpb247CgkkbGltaXQgPSAoJGxpbWl0ICE9ICcnKT8gIkxJTUlUICRsaW1pdCAiIDogJGxpbWl0OwoJJG9yZGVyQnkgPSAoJG9yZGVyQnkgIT0gJycpPyAiT1JERVIgQlkgJG9yZGVyQnkgIiA6ICRvcmRlckJ5OwoKCSRxdWVyeSA9ICRzZWxlY3QuJHRhYmxlLiRjb25kaXRpb24uJG9yZGVyQnkuJGxpbWl0OwoJcmV0dXJuIG15c3FsX3F1ZXJ5KCRxdWVyeSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBTaG93IExpc3QgUHJvcGVydHkKICAgICAqIEBwYXJhbSBzdHJpbmcgJHRwbCBUZW1wbGF0ZQogICAgICogQHBhcmFtIHN0cmluZyAkdHBsV3JhcCBUZW1wbGF0ZSBXcmFwCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBMaW1pdCBTaG93LCBERUZBVUxUOiBOVUxMCiAgICAgKiBAcmV0dXJuIHN0cmluZwogICAgICovCiAgICBmdW5jdGlvbiBwcm9wZXJ0eUxpc3QoJHRwbCwgJHRwbFdyYXAsICRsaW1pdD1udWxsKSB7CgkkZmV0Y2ggPSAkdGhpcy0+ZGItPmZldGNoKCd2bV9wcm9wZXJ0eScpOwoJCglmb3JlYWNoICgkZmV0Y2ggYXMgJGtleT0+JHZhbHVlKSB7CgkgICAgJGZldGNoWyRrZXldID0gJHRoaXMtPmFkZFByb3BlcnR5S2V5KCR2YWx1ZSk7Cgl9CgoJZm9yZWFjaCAoJGZldGNoIGFzICR2YWx1ZSkgewoJICAgICRkYXRhIC49ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsICR2YWx1ZSk7Cgl9CgkkcHJvcGVydHlbJ2xpc3QnXSA9ICRkYXRhOwoJJHByb3BlcnR5Wyd1cmxBZGQnXSA9ICR0aGlzLT5saW5rcGFnZVsncHJvcGVydHknXS4nJnNob3c9cHJvcGVydHllZGl0JzsKCSR0ZW1wbGF0ZSA9ICR0aGlzLT5wYXJzZUNodW5rKCR0cGxXcmFwLCAkcHJvcGVydHkpOwoJcmV0dXJuICR0ZW1wbGF0ZTsKICAgIH0KICAgIAogICAgZnVuY3Rpb24gcHJvcGVydHlFZGl0KCR0cGwpIHsKCWlmKCR0aGlzLT5wcm9wZXJ0eUlkZW50aWZpZXIpewoJICAgICRmZXRjaCA9ICR0aGlzLT5wcm9wZXJ0eS0+ZGF0YTsKCX1lbHNlewoJICAgICRmaWVsZE5hbWUgPSAkdGhpcy0+ZGItPmdldFRhYmxlRmllbGRzKCd2bV9wcm9wZXJ0eScpOwoJICAgIHdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXNzb2MoJGZpZWxkTmFtZSkgKXsKCQkkZmV0Y2hbICRyb3dbJ0ZpZWxkJ10gXSA9ICcnOwoJICAgIH0JICAgIAoJfQoKCS8vIEFkaXRpb25hbCBEYXRhCgkkZmV0Y2hbJ2xpc3RDb3VudHJ5J10JPSAkdGhpcy0+Z2V0Rm9ybUxvY2F0aW9uKDEsICdjb3VudHJ5JywgJ2NvdW50cnknKTsKCSRmZXRjaFsnbGlzdFByb3ZpbmNlJ10JPSAkdGhpcy0+Z2V0Rm9ybUxvY2F0aW9uKDMsICdwcm92aW5jZScsICdwcm92aW5jZScpOwoJJGZldGNoWydsaXN0Q2l0eSddCT0gJHRoaXMtPmdldEZvcm1Mb2NhdGlvbig0LCAnY2l0eScsICdjaXR5Jyk7CgkkZmV0Y2hbJ2Zvcm1BY3Rpb24nXQk9ICc/cGFnZT12cC1wcm9wZXJ0eSZzaG93PWFjdGlvbiZhY3Rpb249dXBkYXRlJmlkPScuJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcjsKCQoJJHJldHVybiA9ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsICRmZXRjaCk7CglyZXR1cm4gJHJldHVybjsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRGb3JtTG9jYXRpb24oJHR5cGVMb2NhdGlvbiwgJGNsYXNzTmFtZSwgJHNlbGVjdE5hbWUpewoJJGZldGNoID0gJHRoaXMtPmRiLT5mZXRjaCgndm1fc3lzX2xvY2F0aW9uJywgJyonLCAnbG9jdHlwZV9pZD0nLiR0eXBlTG9jYXRpb24pOwoJaWYgKCBjb3VudCgkZmV0Y2gpICl7CgkgICAgJHJldHVybiA9ICc8c2VsZWN0IGNsYXNzPSInLiRjbGFzc05hbWUuJyIgbmFtZT0iJy4kc2VsZWN0TmFtZS4nIj4nOwoJICAgICRyZXR1cm4gLj0gJzxvcHRpb24gdmFsdWU9IiI+LS0tLS0tPC9vcHRpb24+JzsKCSAgICBmb3JlYWNoKCRmZXRjaCBhcyAkdmFsdWUpewoJCWlmICggJHZhbHVlWydsb2NfaWQnXSA9PSAkdGhpcy0+cHJvcGVydHktPmdldExvY2F0aW9uSWRCeVR5cGUoJHR5cGVMb2NhdGlvbikgKXsKCQkgICAgJHJldHVybiAuPSAnPG9wdGlvbiB2YWx1ZT0iJy4kdmFsdWVbJ2xvY19pZCddLiciIHNlbGVjdGVkPSJzZWxlY3RlZCI+Jy4kdmFsdWVbJ2xvY19uYW1lJ10uJzwvb3B0aW9uPic7CgkJfWVsc2V7CgkJICAgICRyZXR1cm4gLj0gJzxvcHRpb24gdmFsdWU9IicuJHZhbHVlWydsb2NfaWQnXS4nIj4nLiR2YWx1ZVsnbG9jX25hbWUnXS4nPC9vcHRpb24+JzsKCQl9CgkgICAgfQoJICAgICRyZXR1cm4gLj0gJzwvc2VsZWN0Pic7Cgl9CglyZXR1cm4gJHJldHVybjsKICAgIH0KCiAgICBmdW5jdGlvbiBhZGRQcm9wZXJ0eUtleSgkZGF0YSkgewoJJGlkID0gJGRhdGFbJ2lkJ107CgkkZGF0YVsnbGluayddID0gJHRoaXMtPmxpbmtwYWdlWydwcm9wZXJ0eSddLicmc2hvdz1wcm9wZXJ0eScuIiZpZD0kaWQiOwoJJGRhdGFbJ2FjdGlvbkVkaXQnXSA9ICR0aGlzLT5saW5rcGFnZVsncHJvcGVydHknXS4nJnNob3c9cHJvcGVydHllZGl0Jy4iJmlkPSRpZCI7CgkkZGF0YVsnYWN0aW9uRGVsZXRlJ10gPSAkdGhpcy0+bGlua3BhZ2VbJ3Byb3BlcnR5J10uJyZzaG93PWFjdGlvbicuJyZhY3Rpb249ZGVsZXRlJy4iJmlkPSRpZCI7CgkkZGF0YVsnYWN0aW9uVmlld1Jvb20nXSA9ICR0aGlzLT5saW5rcGFnZVsncHJvcGVydHknXS4nJnNob3c9cHJvcGVydHknLiImaWQ9JGlkIjsKCSRkYXRhWydhY3Rpb24nXSA9ICR0aGlzLT5nZXRJY29uKAoJCQkgICAgJ2ljb24ucGhwJywKCQkJICAgIGFycmF5KCd2aWV3cm9vbScsJ2VkaXQnLCdkZWxldGUnKSwKCQkJICAgIGFycmF5KCRkYXRhWydhY3Rpb25WaWV3Um9vbSddLCRkYXRhWydhY3Rpb25FZGl0J10sICRkYXRhWydhY3Rpb25EZWxldGUnXSkKCQkJKTsKCXJldHVybiAkZGF0YTsKICAgIH0KCiAgICAKCiAgICBmdW5jdGlvbiBnZXRJY29uKCR0cGwsICRhcnJJY29uLCAkYXJyTGlua0FjdGlvbikgewoJJHBhdGggPSAkdGhpcy0+cGF0aFsndXJsX2ljbyddOwoJJGxpc3RJY29uICAgPSBhcnJheSgKCQkJJ2RlbGV0ZScgICAgPT4gJHBhdGguJ2FjdGlvbl9kZWxldGUucG5nJywKCQkJJ2VkaXQnCSAgICA9PiAkcGF0aC4nZmlsZS5wbmcnLAoJCQkndmlld3Jvb20nICA9PiAkcGF0aC4nYXBwbGljYXRpb24ucG5nJywKCQkJJ3NldFByaWNlJyAgPT4gJHBhdGguJ3JlcGx5LnBuZycKCQkJKTsKCWZvcmVhY2ggKCRhcnJJY29uIGFzICRrZXk9PiR2YWx1ZSkgewoJICAgICRkYXRhWyduYW1lJ10gICA9ICR2YWx1ZTsKCSAgICAkZGF0YVsnaW1hZ2UnXSAgPSAkbGlzdEljb25bJHZhbHVlXTsKCSAgICAkZGF0YVsnbGluayddICAgPSAkYXJyTGlua0FjdGlvblska2V5XTsKCSAgICAkcmV0dXJuIC49ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsICRkYXRhKTsKCX0KCglyZXR1cm4gJHJldHVybjsKICAgIH0KCiAgICAvKi0tLS0tLS0gQ2h1bmsgVGVtcGxhdGUgU3lzdGVtIC0tLS0tLS0tLS0qLyAgICAKICAgIGZ1bmN0aW9uIHBhcnNlQ2h1bmsoJGNodW5rTmFtZSwgJGNodW5rQXJyLCAkcHJlZml4PSAiWysiLCAkc3VmZml4PSAiK10iKSB7CiAgICAgICAgaWYgKCAhaXNfYXJyYXkoJGNodW5rQXJyKSApIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0JCiAgICAgICAgJGNodW5rID0gJHRoaXMtPmdldENodW5rKCRjaHVua05hbWUpOwogICAgICAgIGZvcmVhY2ggKCRjaHVua0FyciBhcyAka2V5PT4kdmFsdWUpIHsKICAgICAgICAgICAgJGNodW5rID0gc3RyX3JlcGxhY2UoJHByZWZpeC4ka2V5LiRzdWZmaXgsICR2YWx1ZSwgJGNodW5rKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuICRjaHVuazsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRDaHVuaygkY2h1bmtOYW1lKSB7CgkkcmVhZCA9ICR0aGlzLT5wYXRoWydkaXJfdHBsJ10uJGNodW5rTmFtZTsKCQoJaWYgKCBmaWxlX2V4aXN0cygkcmVhZCkgKSB7CgkgICAgJGNvbnRlbnQgPSBmaWxlX2dldF9jb250ZW50cygkcmVhZCk7Cgl9IGVsc2UgewoJICAgIHJldHVybiBmYWxzZTsKCX0KCQoJcmV0dXJuICRjb250ZW50OwogICAgfQoKICAgIC8qKgogICAgICoJUHJpbnQgRG9jdW1lbnQgUGFyc2VyCiAgICAgKiBAcGFyYW0gc3RyaW5nICR0cGwgVGVtcGxhdGUgTmFtZQogICAgICogQHBhcmFtIGFycmF5ICRhcnJEYXRhIERhdGEgdG8gYmUgc2VudAogICAgICovCiAgICBmdW5jdGlvbiBwYXJzZXIoJHRwbCwgJGFyckRhdGEpIHsKCXByaW50ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsICRhcnJEYXRhKTsKICAgIH0KCiAgICBmdW5jdGlvbiByZWdpc3RlckNTUygpewoJLy8gUmVnaXN0ZXIgQ1NTCgl3cF9yZWdpc3Rlcl9zdHlsZSgndmlsbGEtcG9ydGFsLXN0eWxlJywgJHRoaXMtPnBhdGhbJ3VybF90cGwnXS4nc3R5bGUuY3NzJywgbnVsbCwgJzAuMScgKTsKCXdwX2VucXVldWVfc3R5bGUoJ3ZpbGxhLXBvcnRhbC1zdHlsZScpOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlZ2lzdGVyU2NyaXB0KCl7CgkvLyBUeW55IE1DRQoJd3BfcmVnaXN0ZXJfc2NyaXB0KCd0aW55bWNlJywgJHRoaXMtPnBhdGhbJ3VybCddLidleHRlbnRpb24vdGlueV9tY2UvanF1ZXJ5LnRpbnltY2UuanMnLCBudWxsLCAnMC4xJyApOwoJd3BfZW5xdWV1ZV9zY3JpcHQoJ3RpbnltY2UnKTsKCQoJd3BfcmVnaXN0ZXJfc2NyaXB0KCd2aWxsYS1wb3J0YWwtc2NyaXB0JywgJHRoaXMtPnBhdGhbJ3VybCddLidzaXRlLmpzJywgbnVsbCwgJzAuMScgKTsKCXdwX2VucXVldWVfc2NyaXB0KCd2aWxsYS1wb3J0YWwtc2NyaXB0Jyk7CQogICAgfQogICAgCiAgICBmdW5jdGlvbiBnZXRQcm9wZXJ0eSgkdHBsLCAkcHJvcGVydHlJZD1udWxsKSB7CgkkcHJvcGVydHlJZCA9ICgkcHJvcGVydHlJZCk/ICRwcm9wZXJ0eUlkIDogJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcjsKCgkkcmV0dXJuID0gJHRoaXMtPnBhcnNlQ2h1bmsoJHRwbCwgJHRoaXMtPnByb3BlcnR5LT5kYXRhKTsKCXJldHVybiAkcmV0dXJuOwogICAgfQoKICAgIGZ1bmN0aW9uIHByb3BlcnR5VXBkYXRlKCRkYXRhKSB7CQoJaWYoICR0aGlzLT5kYi0+dXBkYXRlKCd2bV9wcm9wZXJ0eScsICRkYXRhLCAnaWQ9Jy4kdGhpcy0+cHJvcGVydHlJZGVudGlmaWVyKSApewoJICAgIHJldHVybiB0cnVlOwoJfWVsc2V7CgkgICAgcmV0dXJuIGZhbHNlOwoJfQkKICAgIH0KCiAgICBmdW5jdGlvbiBwcm9wZXJ0eUluc2VydCgkZGF0YSkgewoJJHRoaXMtPmRiLT5pbnNlcnQoJ3ZtX3Byb3BlcnR5JywgJGRhdGEpOwogICAgfQoKICAgIC8qKgogICAgICogRGVsZXRlIFByb3BlcnR5CiAgICAgKiBAcmV0dXJuIGJvb2wgUmV0dXJuIHRydWUgb24gc3VjY2VzcwogICAgICovCiAgICBmdW5jdGlvbiBwcm9wZXJ0eURlbGV0ZSgpIHsKCWlmICgkdGhpcy0+cHJvcGVydHlJZGVudGlmaWVyKSB7CgkgICAgJHRoaXMtPmRiLT5kZWxldGUoJ3ZtX3Byb3BlcnR5JywgJ2lkPScuJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcik7CgkgICAgcmV0dXJuIHRydWU7Cgl9CiAgICB9CgogICAgZnVuY3Rpb24gc2hvd1Jvb20oJHRwbCwgJHRwbFdyYXAsICRsaW1pdD1udWxsKSB7CglpZiAoJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcikgewoJICAgICRyZXR1cm4gPSAnPGgyPkxpc3QgUm9vbTwvaDI+JzsKCSAgICAkcmV0dXJuIC49ICc8YSBocmVmPSInLiR0aGlzLT51cmxBZG1pbi4nJnNob3c9cm9vbWFjdGlvbiZyb29tYWN0aW9uPWNyZWF0ZSZpZD0nLiR0aGlzLT5wcm9wZXJ0eUlkZW50aWZpZXIuJyIgY2xhc3M9ImJ1dHRvbiI+Q3JlYXRlIFJvb208L2E+JzsKCSAgICAkZGF0YVsnbGlzdFJvb20nXSA9ICcnOwkgICAgCgoJICAgICRyZXN1bHQgPSAkdGhpcy0+ZGItPnNlbGVjdCgndm1fcm9vbScsICcqJywgJ3Byb3BlcnR5X2lkPScuJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcik7CgkgICAgaWYgKCBteXNxbF9udW1fcm93cygkcmVzdWx0KSApIHsKCQl3aGlsZSAoICRyb3cgPSAgbXlzcWxfZmV0Y2hfYXNzb2MoJHJlc3VsdCkgKXsKCQkgICAgJHJvd1sndXJsJ10gPSAkdGhpcy0+dXJsQWRtaW4uJyZzaG93PXJvb21hY3Rpb24mcm9vbWFjdGlvbj1jcmVhdGUmaWQ9Jy4kdGhpcy0+cHJvcGVydHlJZGVudGlmaWVyLicmcm9vbWlkPScuJHJvd1snaWQnXTsKCQkgICAgJHJvd1sncHJpY2UnXSA9ICR0aGlzLT5nZXRSb29tUHJpY2UoJHJvd1snaWQnXSk7CgkJICAgICRyb3dbJ2FjdGlvbiddID0gJHRoaXMtPmdldFJvb21BY3Rpb24oICRyb3dbJ2lkJ10sICI8dGQ+JXM8L3RkPiIsICRyb3dbJ3VybCddICk7CgkJICAgICRkYXRhWydsaXN0Um9vbSddIC49ICR0aGlzLT5wYXJzZUNodW5rKCR0cGwsICRyb3cpOwkJICAgIAoJCX0KCQkkcmV0dXJuIC49ICR0aGlzLT5wYXJzZUNodW5rKCR0cGxXcmFwLCAkZGF0YSk7CgkgICAgfQoJICAgIAoJICAgIHByaW50KCRyZXR1cm4pOwoJfQkKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRSb29tQWN0aW9uKCRpZCwgJHdyYXAsICRsaW5rQmFzZSl7CgkkZGF0YVsnYWN0aW9uRWRpdCddID0gJGxpbmtCYXNlOyAvLwoJJGRhdGFbJ2FjdGlvbkRlbGV0ZSddID0gc3RyX3JlcGxhY2UoJyZyb29tYWN0aW9uPWNyZWF0ZScsICcmcm9vbWFjdGlvbj1kb2RlbGV0ZScsICRsaW5rQmFzZSk7CgkkZGF0YVsnYWN0aW9uU2V0UHJpY2UnXSA9IHN0cl9yZXBsYWNlKAoJCQkJICAgIGFycmF5KCcmc2hvdz1yb29tYWN0aW9uJywgJyZyb29tYWN0aW9uPWNyZWF0ZScpLAoJCQkJICAgIGFycmF5KCcmc2hvdz1yb29tcHJpY2UnLCAnJyksCgkJCQkgICAgJGxpbmtCYXNlCgkJCQkgICAgKTsKCSRhY3Rpb24gPSAkdGhpcy0+Z2V0SWNvbigKCQkJICAgICdpY29uLnBocCcsCgkJCSAgICBhcnJheSgnZWRpdCcsJ2RlbGV0ZScsJ3NldFByaWNlJyksCgkJCSAgICBhcnJheSgkZGF0YVsnYWN0aW9uRWRpdCddLCRkYXRhWydhY3Rpb25EZWxldGUnXSwgJGRhdGFbJ2FjdGlvblNldFByaWNlJ10pCgkJCSk7CglyZXR1cm4gJGFjdGlvbjsJCiAgICB9CgogICAgZnVuY3Rpb24gZ2V0Um9vbVByaWNlKCRyb29tSWQpewoJCiAgICB9CgogICAgZnVuY3Rpb24gcm9vbV9kZWxldGUoJHJvb21JZCkgewoJJHRoaXMtPmRiLT5kZWxldGUoJ3ZtX3Jvb20nLCAnaWQ9Jy4kcm9vbUlkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBsaXN0UmF0ZSgkcm9vbUlkPW51bGwsICR5ZWFyTW9udGg9bnVsbCApIHsKCSRyb29tSWQgPSAoJHJvb21JZCk/ICRyb29tSWQgOiAkdGhpcy0+cm9vbS0+aWRlbnRpZmllcjsKCSR5ZWFyTW9udGggPSAoJHllYXJNb250aCk/ICR5ZWFyTW9udGggOiAkX1NFU1NJT05bJ3JhdGVEYXRlJ107CgkkeWVhck1vbnRoID0gKCR5ZWFyTW9udGgpPyAkeWVhck1vbnRoIDogZGF0ZSgnWS1tJyk7CgoJJHJhdGUgPSAkdGhpcy0+cm9vbS0+Z2VuZXJhdGVSYXRlKCR5ZWFyTW9udGgpOwoJZm9yZWFjaCAoJHJhdGUgYXMgJHZhbHVlKSB7CgkgICAgJGRhdGFbJ2xpc3RSYXRlJ10gLj0gJHRoaXMtPnBhcnNlQ2h1bmsoJ3Jvb21yYXRlLnBocCcsICR2YWx1ZSk7Cgl9CgkKCSRkYXRhWydsaW5rLXByb3BlcnR5J10gPSAkdGhpcy0+dXJsQWRtaW4uJyZzaG93PXByb3BlcnR5JmlkPScuJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcjsKCSRkYXRhWydsaW5rLWZvcm1hY3Rpb24nXSA9ICR0aGlzLT51cmxBZG1pbi4nJnNob3c9cm9vbXByaWNlJnJvb21wcmljZT11cGRhdGUmaWQ9Jy4kdGhpcy0+cHJvcGVydHlJZGVudGlmaWVyLicmcm9vbWlkPScuJHRoaXMtPnJvb20tPmlkZW50aWZpZXI7CgkkZGF0YVsnbGlzdFNlbGVjdE1vbnRoJ10gPSAkdGhpcy0+Z2VuU2VsZWN0TW9udGgoKTsKCSRkYXRhWydsaXN0U2VsZWN0WWVhciddID0gJHRoaXMtPmdlblNlbGVjdFllYXIoKTsKCQoJJHJldHVybiA9ICR0aGlzLT5wYXJzZUNodW5rKCdyb29tcmF0ZS13cmFwLnBocCcsICRkYXRhKTsKCXJldHVybiAkcmV0dXJuOwogICAgfQogICAgCiAgICBmdW5jdGlvbiBnZW5TZWxlY3RNb250aCgpIHsKCSRtb250aEFycnkgPSBhcnJheSgKCSAgICAnMDEnID0+ICdKYW51YXJ5JywKCSAgICAnMDInID0+ICdGZWJydWFyeScsCgkgICAgJzAzJyA9PiAnTWFyY2gnLAoJICAgICcwNCcgPT4gJ0FwcmlsJywKCSAgICAnMDUnID0+ICdNYXknLAoJICAgICcwNicgPT4gJ0p1bmUnLAoJICAgICcwNycgPT4gJ0p1bHknLAoJICAgICcwOCcgPT4gJ0F1Z3VzdCcsCgkgICAgJzA5JyA9PiAnU2VwdGVtYmVyJywKCSAgICAnMTAnID0+ICdPY3RvYmVyJywKCSAgICAnMTEnID0+ICdOb3ZlbWJlcicsCgkgICAgJzEyJyA9PiAnRGVjZW1iZXInCgkpOwkKCSRtb250aE5vdyA9IERhdGUoJ20nKTsJCglmb3JlYWNoICgkbW9udGhBcnJ5IGFzICRrZXk9PiR2YWx1ZSkgewoJICAgICRzZWxlY3RlZCA9ICgka2V5ID09ICRtb250aE5vdyk/ICdzZWxlY3RlZD0ic2VsZWN0ZWQiJyA6ICcnOwoJICAgICRyZXR1cm4gLj0gJzxvcHRpb24gdmFsdWU9IicuJGtleS4nIiAnLiRzZWxlY3RlZC4nPicuJHZhbHVlLic8L29wdGlvbj4nOwoJfQoJcmV0dXJuICRyZXR1cm47CiAgICB9CiAgICAKICAgIGZ1bmN0aW9uIGdlblNlbGVjdFllYXIoKSB7CgkkeWVhciA9IChpbnQpRGF0ZSgnWScpOwkKCWZvciAoJGk9MDsgJGkgPCA0OyAkaSsrKSB7CgkgICAgJHllYXJJbmNyZW1lbnQgPSAkeWVhciArICRpOwoJICAgICRyZXR1cm4gLj0gJzxvcHRpb24gdmFsdWU9IicuJHllYXJJbmNyZW1lbnQuJyI+Jy4keWVhckluY3JlbWVudC4nPC9vcHRpb24+JzsKCX0JCglyZXR1cm4gJHJldHVybjsKICAgIH0KICAgIAogICAgZnVuY3Rpb24gY29uZmlnTGlzdEZhY2lsaXR5KCkgewoJJGkgPSAxOwoJJHJlc3VsdCA9ICR0aGlzLT5kYi0+c2VsZWN0KCd2bV9mYWNpbGl0eScpOwoJaWYoIG15c3FsX251bV9yb3dzKCRyZXN1bHQpICkgewoJICAgICRkYXRhID0gJHRoaXMtPmRiLT5mZXRjaCgndm1fZmFjaWxpdHknKTsKCSAgICBmb3JlYWNoKCRkYXRhIGFzICRrZXk9PiR2YWx1ZSkgewoJCSRkYXRhWyRrZXldWydhY3Rpb25EZWxldGUnXSA9ICc8YSBocmVmPSIvd3AtYWRtaW4vYWRtaW4ucGhwP3BhZ2U9dnAtY29uZmlnLWZhY2lsaXR5JmFjdGlvbj1kZWxldGUmaWQ9Jy4kZGF0YVska2V5XVsnaWQnXS4nIj4KCQkJCQkgICAgPGltZyBzcmM9IicuJHRoaXMtPnBhdGhbJ3VybF9pY28nXS4nYWN0aW9uX2RlbGV0ZS5wbmciIC8+PC9hPic7CgkgICAgfQoJICAgICRpKys7Cgl9Cglmb3JlYWNoICgkZGF0YSBhcyAka2V5PT4kdmFsdWUpIHsKCSAgICAkcGFyc2VyWydsaXN0RmFjaWxpdHknXSAuPSAkdGhpcy0+cGFyc2VDaHVuaygnY29uZmlnLWZhY2lsaXR5LnBocCcsICR2YWx1ZSk7Cgl9CgkKCSRyZXR1cm4gPSAkdGhpcy0+cGFyc2VDaHVuaygnY29uZmlnLWZhY2lsaXR5LXdyYXAucGhwJywgJHBhcnNlcik7CglwcmludCgkcmV0dXJuKTsKICAgIH0KICAgIAogICAgZnVuY3Rpb24gc2hvd0ZhY2lsaXR5KCl7CglpZiAoICRfUE9TVFsnYWN0aW9uJ10gPT0gJ2ZhY2lsaXR5JyApIHsKCSAgICB1bnNldCgkX1BPU1RbJ2FjdGlvbiddKTsKCSAgICAkdGhpcy0+cHJvcGVydHlGYWNpbGl0eVVwZGF0ZSgkX1BPU1QpOwoJfQoJCgkkZGF0YVsndGl0bGUnXSA9ICdGYWNpbGl0eSc7CgkkZGF0YVsncHJvcGVydHlJZCddID0gJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcjsKCSRkYXRhWydsaXN0RmFjaWxpdHknXSA9ICR0aGlzLT5nZW5MaXN0RmFjaWxpdHkoKTsKCSRyZXR1cm4gPSAkdGhpcy0+cGFyc2VDaHVuaygnZmFjaWxpdHktd3JhcC5waHAnLCAkZGF0YSk7CglwcmludCAkcmV0dXJuOwogICAgfQogICAgCiAgICBmdW5jdGlvbiBnZW5MaXN0RmFjaWxpdHkoKSB7CgkkYXJyRmFjaWxpdHkgPSAkdGhpcy0+ZGItPmZldGNoKCd2bV9mYWNpbGl0eScpOwoJJGFyclByb3BlcnR5RmFjaWxpdHkgPSBleHBsb2RlKCcsJywgJHRoaXMtPmRiLT5yZXN1bHQoJ3ZtX3Byb3BlcnR5JywgJ2ZhY2lsaXR5JywgJ2lkPScuJHRoaXMtPnByb3BlcnR5SWRlbnRpZmllcikpOwoJZm9yZWFjaCAoJGFyckZhY2lsaXR5IGFzICRmYWNpbGl0eSkgewoJICAgIGZvcmVhY2ggKCRhcnJQcm9wZXJ0eUZhY2lsaXR5IGFzICRwcm9wZXJ0eUZhY2lsaXR5KSB7IC8vIENoZWNrIGlmIHRoZSBGYWNpbGl0eSBJRCBpcyBpbmNsdWRlZCBpbiB0aGlzIHByb3BlcnR5IGZhY2lsaXR5CgkJaWYgKCRmYWNpbGl0eVsnaWQnXSA9PSAkcHJvcGVydHlGYWNpbGl0eSkgewoJCSAgICAkZmFjaWxpdHlbJ2NoZWNrZWQnXSA9ICdjaGVja2VkPSJjaGVja2VkIic7CgkJICAgIGJyZWFrOwoJCX1lbHNlewoJCSAgICAkZmFjaWxpdHlbJ2NoZWNrZWQnXSA9ICcnOwoJCX0JCQoJICAgIH0KCSAgICAkcmV0dXJuIC49ICR0aGlzLT5wYXJzZUNodW5rKCdmYWNpbGl0eS5waHAnLCAkZmFjaWxpdHkpOwoJfQoJcmV0dXJuICRyZXR1cm47CiAgICB9CiAgICAKICAgIGZ1bmN0aW9uIHByb3BlcnR5RmFjaWxpdHlVcGRhdGUoJGRhdGEpIHsKCQkkZGF0YSA9IGltcGxvZGUoJywnLCAkZGF0YVsnZmFjaWxpdHknXSk7CgkJJHVwZGF0ZVsnZmFjaWxpdHknXSA9ICRkYXRhOwoJCSR0aGlzLT5kYi0+dXBkYXRlKCd2bV9wcm9wZXJ0eScsICR1cGRhdGUsICdpZD0nLiR0aGlzLT5wcm9wZXJ0eUlkZW50aWZpZXIsICRkZWJ1Zz1mYWxzZSk7CQogICAgfQp9Cj8+IA==
includes/inc.villaportal.php


