DIR : /home/kozerus/public_html/ko/ko_tmvi.html
/home/kozerus/public_html/ko
<!-- /ko/ko_tm.html 20230107_2100 3d args ->
<!-- <link rel="stylesheet" media="all" href="./terminal.css"> -->
<!--
<link rel="stylesheet" media="all" href="data:/text/plain;base64,QGZvbnQtZmFjZSB7CiAgZm9udC1mYW1pbHk6ICdJbmNvbnNvbGF0YSc7CiAgZm9udC1zdHlsZTogbm9ybWFsOwogIGZvbnQtd2VpZ2h0OiBub3JtYWw7CiAgc3JjOiBsb2NhbCgnSW5jb25zb2xhdGEnKSwgdXJsKCdJbmNvbnNvbGF0YS53b2ZmJykgZm9ybWF0KCd3b2ZmJyk7Cn0KCi8qQC13ZWJraXQta2V5ZnJhbWVzIHB1bHNlIHsKIDAlIHsKICBvcGFjaXR5OiAwOwogfQogMjUlIHsKICBvcGFjaXR5OiAwLjI7CiB9CiA1MCUgewogIG9wYWNpdHk6IDA7CiB9CiA3NSUgewogIG9wYWNpdHk6IDA7CiB9CiAxMDAlIHsKICAgb3BhY2l0eTogMC4yOwogfQp9CiovCi8qCkAtd2Via2l0LWtleWZyYW1lcyBmbGlja2VyIHsKICAwJSB7IG9wYWNpdHk6IDAuOTU7IH0KICAxMCUgeyBvcGFjaXR5OiAwLjk7IH0KICAyMCUgeyBvcGFjaXR5OiAwLjg1OyB9CiAgMzAlIHsgb3BhY2l0eTogMC45OyB9CiAgNDAlIHsgb3BhY2l0eTogMC45NTsgfQogIDUwJSB7IG9wYWNpdHk6IDAuOTsgfQogIDYwJSB7IG9wYWNpdHk6IDAuOTU7IH0KICA3MCUgeyBvcGFjaXR5OiAwLjkyOyB9CiAgODAlIHsgb3BhY2l0eTogMC44NTsgfQogIDkwJSB7IG9wYWNpdHk6IDAuOTI7IH0KICAxMDAlIHsgb3BhY2l0eTogMC45OyB9Cn0KKi8KQC13ZWJraXQta2V5ZnJhbWVzIGZsaWNrZXIgewogIDAlIHsgb3BhY2l0eTogMC43NTsgfQogIDEwJSB7IG9wYWNpdHk6IDAuNzsgfQogIDIwJSB7IG9wYWNpdHk6IDAuNjU7IH0KICAzMCUgeyBvcGFjaXR5OiAwLjc7IH0KICA0MCUgeyBvcGFjaXR5OiAwLjc1OyB9CiAgNTAlIHsgb3BhY2l0eTogMC42NTsgfQogIDYwJSB7IG9wYWNpdHk6IDAuNzU7IH0KICA3MCUgeyBvcGFjaXR5OiAwLjcyOyB9CiAgODAlIHsgb3BhY2l0eTogMC42NTsgfQogIDkwJSB7IG9wYWNpdHk6IDAuNzI7IH0KICAxMDAlIHsgb3BhY2l0eTogMC43OyB9Cn0KCjo6c2VsZWN0aW9uIHsKICBiYWNrZ3JvdW5kOiAjMDA4MEZGOwogIHRleHQtc2hhZG93OiBub25lICFpbXBvcnRhbnQ7Cn0KaHRtbCwgYm9keSB7CiAgbWFyZ2luOiAwOwogIGhlaWdodDogMTAwJTsKfQpib2R5IHsKICBmb250LWZhbWlseTogSW5jb25zb2xhdGEsIG1vbm9zcGFjZTsKICBjb2xvcjogd2hpdGU7CiAgYmFja2dyb3VuZDogLXdlYmtpdC1yYWRpYWwtZ3JhZGllbnQoY2VudGVyIGNlbnRlciwgY29udGFpbiwgcmdiYSgwLDE1MCwwLDEpLCBibGFjaykgY2VudGVyIGNlbnRlciBuby1yZXBlYXQsIGJsYWNrOyAvKmNlbnRlciBjZW50ZXIgZm9yIHRoZSBncmFkaWVudCBzY3JvbGxzIHdpdGggdGhlIHBhZ2UgOigqLwogIC8qYmFja2dyb3VuZDogLXdlYmtpdC1yYWRpYWwtZ3JhZGllbnQoY2VudGVyIDc1JSwgY29udGFpbiwgcmdiYSgwLDc1LDAsMC44KSwgYmxhY2spIGNlbnRlciBjZW50ZXIgbm8tcmVwZWF0LCBibGFjazsqLwogIC13ZWJraXQtYmFja2dyb3VuZC1zaXplOiAxMTAlIDEwMCU7Cn0KLm9mZnNjcmVlbiB7CiAgYmFja2dyb3VuZDogLXdlYmtpdC1saW5lYXItZ3JhZGllbnQodG9wLCAjMDAwLCAjMzMzKTsKfQoub2Zmc2NyZWVuICNjb250YWluZXIgewogIGJhY2tncm91bmQ6IHJnYmEoMCwwLDAsMC43KTsKICBoZWlnaHQ6IDEwMCU7CiAgcG9zaXRpb246IGZpeGVkOwogIHRleHQtc2hhZG93OiBub25lOwogIGJveC1zaGFkb3c6IDAgMCAxNXB4IGJsYWNrOwp9Ci5vZmZzY3JlZW4gI2NvbnRhaW5lciBvdXRwdXQgewogIG92ZXJmbG93LXg6IGhpZGRlbjsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgaGVpZ2h0OiAxMDBweDsKfQoub2Zmc2NyZWVuIC5pbnRlcmxhY2UgewogIGRpc3BsYXk6IG5vbmU7Cn0KI2NvbnRhaW5lciB7CiAgLXdlYmtpdC10cmFuc2l0aW9uOiAtd2Via2l0LXRyYW5zZm9ybSAxLjVzIGVhc2UtaW4tb3V0OwogIHdpZHRoOiAxMDAlOwogIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDsKICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgouZHJvcHBpbmcgewogIC8qYmFja2dyb3VuZDogLXdlYmtpdC1saW5lYXItZ3JhZGllbnQoCiAgICBib3R0b20sCiAgICByZ2IoMjA5LDE0NCwyMykgMTMlLAogICAgcmdiKDI1MSwxNzMsNTEpIDU3JSwKICAgIHJnYigyNTUsMjA4LDc3KSA3OSUKICApOyovCiAgYmFja2dyb3VuZDogLXdlYmtpdC1yYWRpYWwtZ3JhZGllbnQoY2VudGVyIGNlbnRlciwgY29udGFpbiwgcmdiYSgwLDE3NSwwLDEpLCBibGFjaykgY2VudGVyIGNlbnRlciBuby1yZXBlYXQ7CiAgLXdlYmtpdC1iYWNrZ3JvdW5kLXNpemU6IDEyNSUgMTI1JTsKfQovKgouY3J0IHsKICB6LWluZGV4OiA1MDsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDUwcHg7CiAgcG9zaXRpb246IGZpeGVkOwogIC8qbWFyZ2luOiAxNXB4IDMxcHggMHB4IDMycHg7CiAgYm9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czogMTBweDsKICBib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czogMTBweDsKICBiYWNrZ3JvdW5kOiAtd2Via2l0LWdyYWRpZW50KHJhZGlhbCwgNTAlIDEwMDU3JSwgNDk5OSwgNTAlIDEwMDU1JSwgNTAwMCwgZnJvbSh0cmFuc3BhcmVudCksIHRvKGJsYWNrKSApIHRyYW5zcGFyZW50IG5vLXJlcGVhdCAxMCUgMTAwJTsKfQouY3J0LnRvcCB7CiAgdG9wOiAtMjBweDsKfQouY3J0LmJvdHRvbSB7CiAgLXdlYmtpdC10cmFuc2Zvcm06IHJvdGF0ZSgxODBkZWcpOwogIGJvdHRvbTogLTIwcHg7Cn0qLwouY3J0IHsKICB6LWluZGV4OiA1MDsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDUwcHg7CiAgcG9zaXRpb246IGZpeGVkOwogIGJhY2tncm91bmQ6IGJsYWNrOwp9Ci5jcnQudG9wIHsKICB0b3A6IDA7Cn0KLmNydC5ib3R0b20gewogIGJvdHRvbTogMDsKICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDE4MGRlZyk7Cn0KLmh6IHsKICAtd2Via2l0LWFuaW1hdGlvbi1uYW1lOiBoejsKICAtd2Via2l0LWFuaW1hdGlvbi1kdXJhdGlvbjogMzBzOwogIC13ZWJraXQtYW5pbWF0aW9uLWl0ZXJhdGlvbi1jb3VudDogaW5maW5pdGU7Cn0KCi5mbGlja2VyIHsKICAtd2Via2l0LWFuaW1hdGlvbi1uYW1lOiBmbGlja2VyOwogIC13ZWJraXQtYW5pbWF0aW9uLWR1cmF0aW9uOiAxczsKICAtd2Via2l0LWFuaW1hdGlvbi1pdGVyYXRpb24tY291bnQ6IGluZmluaXRlOwogIC13ZWJraXQtYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogZWFzZS1pbi1vdXQ7Cn0KLmludGVybGFjZSB7CiAgcG9zaXRpb246IGFic29sdXRlOwogIGxlZnQ6IDA7CiAgdG9wOiAwOwogIGJhY2tncm91bmQ6IHVybChpbnRlcmxhY2UucG5nKSB0b3AgbGVmdCByZXBlYXQsIHJnYmEoMjU1LDI1NSwyNTUsMC41KTsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDEwMCU7CiAgb3BhY2l0eTogMC4yOwogIHotaW5kZXg6IDEwOwogIHBvaW50ZXItZXZlbnRzOiBub25lOwogIC8qYm9yZGVyLXRvcC1sZWZ0LXJhZGl1czogMTUwcHggNTBweDsKICBib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogMTUwcHggNTBweDsKICBib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOiAxNTBweCA1MHB4OwogIGJvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOiAxNTBweCA1MHB4OyovCn0KLmhpZGRlbiB7CiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50Owp9Ci5kaW0gPiAqIHsKICBvcGFjaXR5OiAwLjQ7Cn0KLmRpbSAuaGVscCB7CiAgb3BhY2l0eTogMTsKfQppZnJhbWUjZnNuIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgaGVpZ2h0OiAxMDAlOwogIHdpZHRoOiAxMDAlOwogIGJvcmRlcjogbm9uZTsKfQojY29udGFpbmVyIHsKICBwYWRkaW5nOiAxZW0gMS41ZW0gMWVtIDFlbTsKICB0ZXh0LXNoYWRvdzogMCAwIDVweCAjQzhDOEM4OwogIC8qb3ZlcmZsb3c6IGhpZGRlbjsKICB3aGl0ZS1zcGFjZTogbm93cmFwOyovCgogIC8qYm94LXNoYWRvdzogMTBweCA1cHggMjBweCByZ2JhKDI1NSwyNTUsMjU1LDAuMikgaW5zZXQsCiAgICAgICAgICAgICAgLTEwcHggLTVweCAyMHB4IHJnYmEoMjU1LDI1NSwyNTUsMC4yKSBpbnNldDsKICBib3JkZXItcmFkaXVzOiA1MHB4OwogIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4xKTsqLwp9CiNjb250YWluZXIgb3V0cHV0IHsKICBjbGVhcjogYm90aDsKICB3aWR0aDogMTAwJTsKfQojY29udGFpbmVyIG91dHB1dCBoMyB7CiAgbWFyZ2luOiAwOwp9CiNjb250YWluZXIgb3V0cHV0IHByZSB7CiAgbWFyZ2luOiAwOwp9CiNjb250YWluZXIgb3V0cHV0IHRleHRhcmVhIHsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDIwMHB4OwogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsMC4xKTsKICBib3JkZXI6IG5vbmU7CiAgY29sb3I6IGluaGVyaXQ7CiAgZm9udDogaW5oZXJpdDsKICBvdXRsaW5lOiAwOwogIGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgcGFkZGluZzogNXB4Owp9CiNjb250YWluZXIgb3V0cHV0IHRleHRhcmVhOjpzZWxlY3Rpb24gewogIGJhY2tncm91bmQ6IHJlZDsKfQojY29udGFpbmVyIG91dHB1dCB0ZXh0YXJlYTo6LXdlYmtpdC1zY3JvbGxiYXIgewogIHdpZHRoOiAxZXg7Cn0KI2NvbnRhaW5lciBvdXRwdXQgdGV4dGFyZWE6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHsKICBib3JkZXItdG9wOiAxcHggc29saWQgI2ZmZjsKICBiYWNrZ3JvdW5kOiAjY2NjIC13ZWJraXQtbGluZWFyLWdyYWRpZW50KHJnYigyNDAsIDI0MCwgMjQwKSwgcmdiKDIxMCwgMjEwLCAyMTApKTsKICBib3JkZXItcmFkaXVzOiAxZXg7CiAgYm94LXNoYWRvdzogMCAxcHggM3B4IHJnYmEoMCwgMCwgMCwgMC40KTsKfQouaW5wdXQtbGluZSB7CiAgZGlzcGxheTogLXdlYmtpdC1ib3g7CiAgLXdlYmtpdC1ib3gtb3JpZW50OiBob3Jpem9udGFsOwogIC13ZWJraXQtYm94LWFsaWduOiBzdHJldGNoOwogIGRpc3BsYXk6IGJveDsKICBib3gtb3JpZW50OiBob3Jpem9udGFsOwogIGJveC1hbGlnbjogc3RyZXRjaDsKICBjbGVhcjogYm90aDsKfQouaW5wdXQtbGluZSA+IGRpdjpudGgtY2hpbGQoMikgewogIC13ZWJraXQtYm94LWZsZXg6IDE7CiAgYm94LWZsZXg6IDE7Cn0KLnByb21wdCB7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKICBjb2xvcjogI2ZmY2MwMDsgLypncmVlbjsqLwogIG1hcmdpbi1yaWdodDogN3B4OwogIGRpc3BsYXk6IC13ZWJraXQtYm94OwogIC13ZWJraXQtYm94LXBhY2s6IGNlbnRlcjsKICAtd2Via2l0LWJveC1vcmllbnQ6IHZlcnRpY2FsOwogIGRpc3BsYXk6IGJveDsKICBib3gtcGFjazogY2VudGVyOwogIGJveC1vcmllbnQ6IHZlcnRpY2FsOwogIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7CiAgdXNlci1zZWxlY3Q6IG5vbmU7Cn0KLmNtZGxpbmUgewogIG91dGxpbmU6IG5vbmU7CiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7CiAgbWFyZ2luOiAwOwogIHdpZHRoOiAxMDAlOwogIGZvbnQ6IGluaGVyaXQ7CiAgYm9yZGVyOiBub25lOwogIGNvbG9yOiBpbmhlcml0Owp9Ci5mb2xkZXIgewogIGNvbG9yOiAjZmZjYzAwOwp9Ci5scy1maWxlcyB7CiAgLypoZWlnaHQ6IDQ1cHg7Ki8KICAvKiBEZWZhdWx0LCBidXQgY2hhbmdlZCBieSBqcyBkZXBlbmRpbmcgb24gbGVuZ3RoIG9mIGZpbGVuYW1lICovCiAgLXdlYmtpdC1jb2x1bW4td2lkdGg6IDEwMHB4OwogIGNvbHVtbi13aWR0aDogMTAwcHg7Cn0KLmxzLWZpbGVzIHNwYW4gewogIGN1cnNvcjogcG9pbnRlcjsKfQoubHMtZmlsZXMgc3Bhbjpob3ZlciB7CiAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7Cn0KYnV0dG9uIHsKICBiYWNrZ3JvdW5kOiAtd2Via2l0LWdyYWRpZW50KGxpbmVhciwgMCUgNDAlLCAwJSA3MCUsIGZyb20oI0Y5RjlGOSksIHRvKCNFM0UzRTMpKTsKICBib3JkZXI6IDFweCBzb2xpZCAjY2NjOwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBjb2xvcjogYmxhY2s7CiAgcGFkZGluZzogNXB4IDhweDsKICBvdXRsaW5lOiBub25lOwogIHdoaXRlLXNwYWNlOiBub3dyYXA7CiAgdmVydGljYWwtYWxpZ246IG1pZGRsZTsKICAtd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7CiAgdXNlci1zZWxlY3Q6IG5vbmU7CiAgY3Vyc29yOiBwb2ludGVyOwp9CmJ1dHRvbjpub3QoW2Rpc2FibGVkXSk6aG92ZXIgewogIGJvcmRlci1jb2xvcjogI2ZmY2MwMDsKfQpidXR0b246bm90KFtkaXNhYmxlZF0pOmFjdGl2ZSB7CiAgYmFja2dyb3VuZDogLXdlYmtpdC1ncmFkaWVudChsaW5lYXIsIDAlIDQwJSwgMCUgNzAlLCBmcm9tKCNFM0UzRTMpLCB0bygjRjlGOUY5KSk7Cn0KYnV0dG9uW2Rpc2FibGVkXSB7CiAgY29sb3I6ICNjY2M7Cn0KLmhlbHAgewogIGZvbnQtZmFtaWx5OiAnRHJvaWQgU2FucycsIEFyaWFsLCBzYW5zLXNlcmlmOwogIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlhc2VkOwogIHBvc2l0aW9uOiBmaXhlZDsKICB0b3A6IDA7CiAgbGVmdDogMDsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDEwMCU7CiAgei1pbmRleDogMTAwOwogIGRpc3BsYXk6IC13ZWJraXQtYm94OwogIC13ZWJraXQtYm94LWFsaWduOiBjZW50ZXI7CiAgLXdlYmtpdC1ib3gtcGFjazogY2VudGVyOwogIC13ZWJraXQtYm94LW9yaWVudDogdmVydGljYWw7CiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTsKICB1c2VyLXNlbGVjdDogbm9uZTsKICBmb250LXNpemU6IDEwcHQ7Cn0KLmhlbHAsCi5oZWxwID4gc2VjdGlvbiB7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKfQouaGVscCA+IHNlY3Rpb24gewogIHBhZGRpbmc6IDEwcHg7CiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjMpOwogIC13ZWJraXQtYm94LXNoYWRvdzogM3B4IDNweCA1cHggcmdiYSgwLDAsMCwwLjYpOwogIGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgY29sb3I6IHdoaXRlOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB3aWR0aDogNjEwcHg7Cn0KLmhlbHAgc2VjdGlvbiA+IGRpdjpmaXJzdC1jaGlsZCB7CiAgYm9yZGVyLXRvcC1sZWZ0LXJhZGl1czogMTBweDsKICBib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogMTBweDsKfQouaGVscCBzZWN0aW9uID4gZGl2Omxhc3QtY2hpbGQgewogIHBhZGRpbmctdG9wOiAwOwogIGJvcmRlci1ib3R0b20tbGVmdC1yYWRpdXM6IDEwcHg7CiAgYm9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6IDEwcHg7Cn0KLmhlbHAgPiBzZWN0aW9uID4gZGl2IHsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDAsIDAsIDEpOwogIHBhZGRpbmc6IDIwcHg7Cn0KLmhlbHAgaDIgewogIHBhZGRpbmctYm90dG9tOiA4cHg7CiAgbWFyZ2luLXRvcDogMDsKICBtYXJnaW4tYm90dG9tOiAyNXB4OwogIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZmZmOwogIGNvbG9yOiAjZmZjYzAwOwp9Ci5oZWxwIHAgc3Ryb25nIHsKICB3aWR0aDogNjBweDsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7Cn0KLmhlbHAgI2Nsb3NlIHsKICBib3JkZXItcmFkaXVzOiAyMHB4OwogIHBhZGRpbmc6IDJweCA2cHggMnB4IDdweDsKICBib3JkZXI6IDJweCBzb2xpZCAjZmZmOwogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICByaWdodDogMjBweDsKICB0b3A6IDIwcHg7CiAgY3Vyc29yOiBwb2ludGVyOwogIGZvbnQtc2l6ZTogOTAlOwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGxpbmUtaGVpZ2h0OiAxN3B4Owp9Ci5oZWxwICNjbG9zZTphY3RpdmUgewogIHJpZ2h0OiAxOXB4OwogIHRvcDogMjFweDsKfQouaGVscCAuc2hvcnRjdXRzIHsKICAtd2Via2l0LWNvbHVtbnM6IDI7CiAgY29sdW1uczogMjsKfQoKCi8qIFRoZW1lcyAqLwouY3JlYW0gewogIGNvbG9yOiBibGFjazsKICBiYWNrZ3JvdW5kOiAjZmZmZmYzOwp9Ci5jcmVhbSAuaW50ZXJsYWNlIHsKICBvcGFjaXR5OiAwLjE7Cn0KLmNyZWFtIC5wcm9tcHQgewogIGNvbG9yOiBwdXJwbGU7Cn0KLmNyZWFtIC5jbWRsaW5lIHsKICBjb2xvcjogYmxhY2s7Cn0K">
-->
<style id="style_terminal_css">
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: normal;
src: local('Inconsolata'), url('Inconsolata.woff') format('woff');
}
/*@-webkit-keyframes pulse {
0% {
opacity: 0;
}
25% {
opacity: 0.2;
}
50% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 0.2;
}
}
*/
/*
@-webkit-keyframes flicker {
0% { opacity: 0.95; }
10% { opacity: 0.9; }
20% { opacity: 0.85; }
30% { opacity: 0.9; }
40% { opacity: 0.95; }
50% { opacity: 0.9; }
60% { opacity: 0.95; }
70% { opacity: 0.92; }
80% { opacity: 0.85; }
90% { opacity: 0.92; }
100% { opacity: 0.9; }
}
*/
@-webkit-keyframes flicker {
0% { opacity: 0.75; }
10% { opacity: 0.7; }
20% { opacity: 0.65; }
30% { opacity: 0.7; }
40% { opacity: 0.75; }
50% { opacity: 0.65; }
60% { opacity: 0.75; }
70% { opacity: 0.72; }
80% { opacity: 0.65; }
90% { opacity: 0.72; }
100% { opacity: 0.7; }
}
::selection {
background: #0080FF;
text-shadow: none !important;
}
html, body {
margin: 0;
height: 100%;
}
body {
font-family: Inconsolata, monospace;
color: white;
// background: -webkit-radial-gradient(center center, contain, rgba(0,150,0,1), black) center center no-repeat, black; /*center center for the gradient scrolls with the page :(*/
background: slategrey;
/*background: -webkit-radial-gradient(center 75%, contain, rgba(0,75,0,0.8), black) center center no-repeat, black;*/
-webkit-background-size: 110% 100%;
}
.offscreen {
// background: -webkit-linear-gradient(top, #000, #333);
background: ivory;
}
.offscreen #container {
background: rgba(0,0,0,0.7);
height: 100%;
position: fixed;
text-shadow: none;
box-shadow: 0 0 15px slategrey;
}
.offscreen #container output {
overflow-x: hidden;
display: inline-block;
height: 100px;
}
.offscreen .interlace {
display: none;
}
#container {
-webkit-transition: -webkit-transform 1.5s ease-in-out;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.dropping {
/*background: -webkit-linear-gradient(
bottom,
rgb(209,144,23) 13%,
rgb(251,173,51) 57%,
rgb(255,208,77) 79%
);*/
background: -webkit-radial-gradient(center center, contain, rgba(0,175,0,1), black) center center no-repeat;
-webkit-background-size: 125% 125%;
}
/*
.crt {
z-index: 50;
width: 100%;
height: 50px;
position: fixed;
/*margin: 15px 31px 0px 32px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
background: -webkit-gradient(radial, 50% 10057%, 4999, 50% 10055%, 5000, from(transparent), to(black) ) transparent no-repeat 10% 100%;
}
.crt.top {
top: -20px;
}
.crt.bottom {
-webkit-transform: rotate(180deg);
bottom: -20px;
}*/
.crt {
z-index: 50;
width: 100%;
height: 50px;
position: fixed;
background: black;
}
.crt.top {
top: 0;
}
.crt.bottom {
bottom: 0;
-webkit-transform: rotate(180deg);
}
.hz {
-webkit-animation-name: hz;
-webkit-animation-duration: 30s;
-webkit-animation-iteration-count: infinite;
}
.flicker {
-webkit-animation-name: flicker;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: ease-in-out;
}
.interlace {
position: absolute;
left: 0;
top: 0;
background: url(interlace.png) top left repeat, rgba(255,255,255,0.5);
width: 100%;
height: 100%;
opacity: 0.2;
z-index: 10;
pointer-events: none;
/*border-top-left-radius: 150px 50px;
border-top-right-radius: 150px 50px;
border-bottom-left-radius: 150px 50px;
border-bottom-right-radius: 150px 50px;*/
}
.hidden {
display: none !important;
}
.dim > * {
opacity: 0.4;
}
.dim .help {
opacity: 1;
}
iframe#fsn {
position: absolute;
height: 100%;
width: 100%;
border: none;
}
#container {
padding: 1em 1.5em 1em 1em;
text-shadow: 0 0 5px #C8C8C8;
/*overflow: hidden;
white-space: nowrap;*/
/*box-shadow: 10px 5px 20px rgba(255,255,255,0.2) inset,
-10px -5px 20px rgba(255,255,255,0.2) inset;
border-radius: 50px;
background: rgba(255, 255, 255, 0.1);*/
}
#container output {
clear: both;
width: 100%;
}
#container output h3 {
margin: 0;
}
#container output pre {
margin: 0;
}
#container output textarea {
width: 100%;
height: 200px;
background-color: rgba(255,255,255,0.1);
border: none;
color: inherit;
font: inherit;
outline: 0;
border-radius: 10px;
padding: 5px;
}
#container output textarea::selection {
background: red;
}
#container output textarea::-webkit-scrollbar {
width: 1ex;
}
#container output textarea::-webkit-scrollbar-thumb {
border-top: 1px solid #fff;
background: #ccc -webkit-linear-gradient(rgb(240, 240, 240), rgb(210, 210, 210));
border-radius: 1ex;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.input-line {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
clear: both;
}
.input-line > div:nth-child(2) {
-webkit-box-flex: 1;
box-flex: 1;
}
.prompt {
white-space: nowrap;
color: #ffcc00; /*green;*/
margin-right: 7px;
display: -webkit-box;
-webkit-box-pack: center;
-webkit-box-orient: vertical;
display: box;
box-pack: center;
box-orient: vertical;
-webkit-user-select: none;
user-select: none;
}
.cmdline {
outline: none;
background-color: transparent;
margin: 0;
width: 100%;
font: inherit;
border: none;
color: inherit;
}
.folder {
color: #ffcc00;
}
.ls-files {
/*height: 45px;*/
/* Default, but changed by js depending on length of filename */
-webkit-column-width: 100px;
column-width: 100px;
}
.ls-files span {
cursor: pointer;
}
.ls-files span:hover {
text-decoration: underline;
}
button {
background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#F9F9F9), to(#E3E3E3));
border: 1px solid #ccc;
border-radius: 3px;
color: black;
padding: 5px 8px;
outline: none;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select:none;
user-select: none;
cursor: pointer;
}
button:not([disabled]):hover {
border-color: #ffcc00;
}
button:not([disabled]):active {
background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#E3E3E3), to(#F9F9F9));
}
button[disabled] {
color: #ccc;
}
.help {
font-family: 'Droid Sans', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
display: -webkit-box;
-webkit-box-align: center;
-webkit-box-pack: center;
-webkit-box-orient: vertical;
-webkit-user-select: none;
user-select: none;
font-size: 10pt;
}
.help,
.help > section {
border-radius: 10px;
}
.help > section {
padding: 10px;
background: rgba(255, 255, 255, 0.3);
-webkit-box-shadow: 3px 3px 5px rgba(0,0,0,0.6);
border-radius: 10px;
color: white;
position: relative;
width: 610px;
}
.help section > div:first-child {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.help section > div:last-child {
padding-top: 0;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.help > section > div {
background: rgba(0, 0, 0, 1);
padding: 20px;
}
.help h2 {
padding-bottom: 8px;
margin-top: 0;
margin-bottom: 25px;
border-bottom: 1px solid #fff;
color: #ffcc00;
}
.help p strong {
width: 60px;
display: inline-block;
}
.help #close {
border-radius: 20px;
padding: 2px 6px 2px 7px;
border: 2px solid #fff;
position: absolute;
right: 20px;
top: 20px;
cursor: pointer;
font-size: 90%;
font-weight: bold;
line-height: 17px;
}
.help #close:active {
right: 19px;
top: 21px;
}
.help .shortcuts {
-webkit-columns: 2;
columns: 2;
}
/* Themes */
.cream {
color: black;
background: #fffff3;
}
.cream .interlace {
opacity: 0.1;
}
.cream .prompt {
color: purple;
}
.cream .cmdline {
color: black;
}
</style>
<!-- <link rel="chrome-application-definition" href="./manifest.json"> -->
<!--
<link rel="chrome-application-definition" href="data:/text/plain;base64,ewogICJuYW1lIjogIkhUTUw1IFRlcm1pbmFsIiwKICAiZGVzY3JpcHRpb24iOiAiQ29tbWFuZC1saW5lIHRlcm1pbmFsIHNoZWxsIHJ1bm5pbmcgb24gdG9wIG9mIEhUTUw1IEFQSXMiLAogICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAiaWNvbnMiOiB7CiAgICAiMTYiOiAidGVybWluYWwtaWNvbi5wbmciLAogICAgIjEyOCI6ICJ0ZXJtaW5hbC1pY29uLnBuZyIKICB9LAogICJtaW5pbXVtX2Nocm9tZV92ZXJzaW9uIjogIjExIiwKICAvKiJ1cmxzIjogWwogICAgIio6Ly9sb2NhbGhvc3QvIgogIF0sKi8KICAibGF1bmNoX3VybCI6ICJ0ZXJtaW5hbC5odG1sIiwKICAicGVybWlzc2lvbnMiOiBbCiAgICAidW5saW1pdGVkU3RvcmFnZSIKICBdCn0K">
-->
<style id="style_manifest_json">
{
"name": "HTML5 Terminal",
"description": "Command-line terminal shell running on top of HTML5 APIs",
"version": "1.0.0",
"icons": {
"16": "terminal-icon.png",
"128": "terminal-icon.png"
},
"minimum_chrome_version": "11",
/*"urls": [
"*://localhost/"
],*/
"launch_url": "terminal.html",
"permissions": [
"unlimitedStorage"
]
}
</style>
<aside class="help hidden">
<section>
<div>
<span onclick="toggleHelp()" id="close">x</span>
<h2>Keyboard shortcuts</h2>
<div class="shortcuts">
<p><strong><ctrl> + s</strong> : Toggle CRT monitor flicker effect</p>
<p><strong><esc></strong> : toggle this help menu</p>
</div>
</div>
<!--
<div>
<h2>What is this?</h2>
<p>A Command-line terminal/shell running on top of HTML5 APIs.</p>
<p>By: Eric Bidelman <ericbidelman@chromium.org></p>
</div>
-->
</section>
</aside>
<!--<div class="crt top"></div>-->
<div class="interlace"></div>
<div id="container"></div>
<!--<div class="crt bottom"></div>-->
<!-- <script src="./terminal.js"></script> -->
<!--
<script src="data:/text/plain;base64,LyoKQ29weXJpZ2h0IDIwMTEgR29vZ2xlIEluYy4KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKClVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuClNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgpBdXRob3I6IEVyaWMgQmlkZWxtYW4gKGVyaWNiaWRlbG1hbkBjaHJvbWl1bS5vcmcpCiovCgp2YXIgdXRpbCA9IHV0aWwgfHwge307CnV0aWwudG9BcnJheSA9IGZ1bmN0aW9uKGxpc3QpIHsKICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobGlzdCB8fCBbXSwgMCk7Cn07CgovLyBDcm9zcy1icm93c2VyIGltcGwgdG8gZ2V0IGRvY3VtZW50J3MgaGVpZ2h0Lgp1dGlsLmdldERvY0hlaWdodCA9IGZ1bmN0aW9uKCkgewogIHZhciBkID0gZG9jdW1lbnQ7CiAgcmV0dXJuIE1hdGgubWF4KAogICAgICBNYXRoLm1heChkLmJvZHkuc2Nyb2xsSGVpZ2h0LCBkLmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQpLAogICAgICBNYXRoLm1heChkLmJvZHkub2Zmc2V0SGVpZ2h0LCBkLmRvY3VtZW50RWxlbWVudC5vZmZzZXRIZWlnaHQpLAogICAgICBNYXRoLm1heChkLmJvZHkuY2xpZW50SGVpZ2h0LCBkLmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpCiAgKTsKfTsKCgovLyBUT0RPKGVyaWNiaWRlbG1hbik6IGFkZCBmYWxsYmFjayB0byBodG1sNSBhdWRpby4KZnVuY3Rpb24gU291bmQob3B0X2xvb3ApIHsKICB2YXIgc2VsZl8gPSB0aGlzOwogIHZhciBjb250ZXh0XyA9IG51bGw7CiAgdmFyIHNvdXJjZV8gPSBudWxsOwogIHZhciBsb29wXyA9IG9wdF9sb29wIHx8IGZhbHNlOwoKICB3aW5kb3cuQXVkaW9Db250ZXh0ID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fCB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0OwogIGlmICh3aW5kb3cuQXVkaW9Db250ZXh0KSB7CiAgICBjb250ZXh0XyA9IG5ldyB3aW5kb3cuQXVkaW9Db250ZXh0KCk7CiAgfQoKICB0aGlzLmxvYWQgPSBmdW5jdGlvbih1cmwsIG1peFRvTW9ubywgb3B0X2NhbGxiYWNrKSB7CiAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTsKICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInOwogICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkgewogICAgICBpZiAoY29udGV4dF8pIHsKICAgICAgICAvKnNlbGZfLnNhbXBsZSA9IGNvbnRleHRfLmNyZWF0ZUJ1ZmZlcih0aGlzLnJlc3BvbnNlLCBtaXhUb01vbm8pOwogICAgICAgIGlmIChvcHRfY2FsbGJhY2spIHsKICAgICAgICAgIG9wdF9jYWxsYmFjaygpOwogICAgICAgIH0KICAgICAgICAqLwogICAgICAgIGNvbnRleHRfLmRlY29kZUF1ZGlvRGF0YSh0aGlzLnJlc3BvbnNlLCBmdW5jdGlvbihhdWRpb0J1ZmZlcikgewogICAgICAgICAgc2VsZl8uc2FtcGxlID0gYXVkaW9CdWZmZXI7CiAgICAgICAgICBvcHRfY2FsbGJhY2sgJiYgb3B0X2NhbGxiYWNrKCk7CiAgICAgICAgfSwgZnVuY3Rpb24oZSkgewogICAgICAgICAgY29uc29sZS5sb2coZSk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH07CiAgICB4aHIuc2VuZCgpOwogIH07CgogIHRoaXMucGxheSA9IGZ1bmN0aW9uKCkgewogICAgaWYgKGNvbnRleHRfKSB7CiAgICAgIHNvdXJjZV8gPSBjb250ZXh0Xy5jcmVhdGVCdWZmZXJTb3VyY2UoKTsKICAgICAgc291cmNlXy5idWZmZXIgPSBzZWxmXy5zYW1wbGU7CiAgICAgIHNvdXJjZV8ubG9vcGluZyA9IGxvb3BfOwogICAgICBzb3VyY2VfLmNvbm5lY3QoY29udGV4dF8uZGVzdGluYXRpb24pOwogICAgICBzb3VyY2VfLm5vdGVPbigwKTsKICAgIH0KICB9OwoKICB0aGlzLnN0b3AgPSBmdW5jdGlvbigpIHsKICAgIGlmIChzb3VyY2VfKSB7CiAgICAgIHNvdXJjZV8ubm90ZU9mZigwKTsKICAgICAgc291cmNlXy5kaXNjb25uZWN0KDApOwogICAgfQogIH07Cn0KCnZhciBUZXJtaW5hbCA9IFRlcm1pbmFsIHx8IGZ1bmN0aW9uKGNvbnRhaW5lcklkKSB7CiAgd2luZG93LlVSTCA9IHdpbmRvdy5VUkwgfHwgd2luZG93LndlYmtpdFVSTDsKICB3aW5kb3cucmVxdWVzdEZpbGVTeXN0ZW0gPSB3aW5kb3cucmVxdWVzdEZpbGVTeXN0ZW0gfHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cud2Via2l0UmVxdWVzdEZpbGVTeXN0ZW07CgogIGNvbnN0IFZFUlNJT05fID0gJzEuMC4wJzsKICBjb25zdCBDTURTXyA9IFsKICAgICczZCcsICdjYXQnLCAnY2QnLCAnY3AnLCAnY2xlYXInLCAnZGF0ZScsICdoZWxwJywgJ2luc3RhbGwnLCAnbHMnLCAnbWtkaXInLAogICAgJ212JywgJ29wZW4nLCAncHdkJywgJ3JtJywgJ3JtZGlyJywgJ3RoZW1lJywgJ3ZlcnNpb24nLCAnd2hvJywgJ3dnZXQnCiAgXTsKICBjb25zdCBUSEVNRVNfID0gWydkZWZhdWx0JywgJ2NyZWFtJ107CgogIHZhciBmc18gPSBudWxsOwogIHZhciBjd2RfID0gbnVsbDsKICB2YXIgaGlzdG9yeV8gPSBbXTsKICB2YXIgaGlzdHBvc18gPSAwOwogIHZhciBoaXN0dGVtcF8gPSAwOwoKICB2YXIgdGltZXJfID0gbnVsbDsKICB2YXIgbWFnaWNXb3JkXyA9IG51bGw7CgogIHZhciBmc25fID0gbnVsbDsKICB2YXIgaXMzRF8gPSBmYWxzZTsKCiAgLy8gRmlyZSB3b3JrZXIgdG8gcmV0dXJuIHJlY3Vyc2l2ZSBzbmFwc2hvdCBvZiBjdXJyZW50IEZTIHRyZWUuCiAgdmFyIHdvcmtlcl8gPSBuZXcgV29ya2VyKCd3b3JrZXIuanMnKTsKICB3b3JrZXJfLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHsKICAgIHZhciBkYXRhID0gZS5kYXRhOwogICAgaWYgKGRhdGEuZW50cmllcykgewogICAgICBmc25fLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe2NtZDogJ2J1aWxkJywgZGF0YTogZGF0YS5lbnRyaWVzfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pOwogICAgfQogICAgaWYgKGRhdGEubXNnKSB7CiAgICAgIG91dHB1dCgnPGRpdj4nICsgZGF0YS5tc2cgKyAnPC9kaXY+Jyk7CiAgICB9CiAgfTsKICB3b3JrZXJfLm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7IGNvbnNvbGUubG9nKGUpIH07CgogIC8vIENyZWF0ZSB0ZXJtaW5hbCBhbmQgY2FjaGUgRE9NIG5vZGVzOwogIHZhciBjb250YWluZXJfID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY29udGFpbmVySWQpOwogIGNvbnRhaW5lcl8uaW5zZXJ0QWRqYWNlbnRIVE1MKCdiZWZvcmVFbmQnLAogICAgICBbJzxvdXRwdXQ+PC9vdXRwdXQ+JywKICAgICAgICc8ZGl2IGlkPSJpbnB1dC1saW5lIiBjbGFzcz0iaW5wdXQtbGluZSI+JywKICAgICAgICc8ZGl2IGNsYXNzPSJwcm9tcHQiPiQmZ3Q7PC9kaXY+PGRpdj48aW5wdXQgY2xhc3M9ImNtZGxpbmUiIGF1dG9mb2N1cyAvPjwvZGl2PicsCiAgICAgICAnPC9kaXY+J10uam9pbignJykpOwogIHZhciBjbWRMaW5lXyA9IGNvbnRhaW5lcl8ucXVlcnlTZWxlY3RvcignI2lucHV0LWxpbmUgLmNtZGxpbmUnKTsKICB2YXIgb3V0cHV0XyA9IGNvbnRhaW5lcl8ucXVlcnlTZWxlY3Rvcignb3V0cHV0Jyk7CiAgdmFyIGludGVybGFjZV8gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaW50ZXJsYWNlJyk7CiAgdmFyIGJlbGxfID0gbmV3IFNvdW5kKGZhbHNlKTsKICBiZWxsXy5sb2FkKCdiZWVwLm1wMycsIGZhbHNlKTsKCiAgLy8gSGFja2VyeSB0byByZXNpemUgdGhlIGludGVybGFjZSBiYWNrZ3JvdW5kIGltYWdlIGFzIHRoZSBjb250YWluZXIgZ3Jvd3MuCiAgb3V0cHV0Xy5hZGRFdmVudExpc3RlbmVyKCdET01TdWJ0cmVlTW9kaWZpZWQnLCBmdW5jdGlvbihlKSB7CiAgICB2YXIgZG9jSGVpZ2h0ID0gdXRpbC5nZXREb2NIZWlnaHQoKTsKICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5oZWlnaHQgPSBkb2NIZWlnaHQgKyAncHgnOwogICAgLy9kb2N1bWVudC5ib2R5LnN0eWxlLmJhY2tncm91bmQgPSAnLXdlYmtpdC1yYWRpYWwtZ3JhZGllbnQoY2VudGVyICcgKyAoTWF0aC5yb3VuZChkb2NIZWlnaHQgLyAyKSkgKyAncHgsIGNvbnRhaW4sIHJnYmEoMCw3NSwwLDAuOCksIGJsYWNrKSBjZW50ZXIgY2VudGVyIG5vLXJlcGVhdCwgYmxhY2snOwogICAgaW50ZXJsYWNlXy5zdHlsZS5oZWlnaHQgPSBkb2NIZWlnaHQgKyAncHgnOwogICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgLy8gTmVlZCB0aGlzIHdyYXBwZWQgaW4gYSBzZXRUaW1lb3V0LiBDaHJvbWUgaXMganVwbWluZyB0byB0b3AgOigKICAgICAgLy93aW5kb3cuc2Nyb2xsVG8oMCwgZG9jSGVpZ2h0KTsKICAgICAgY21kTGluZV8uc2Nyb2xsSW50b1ZpZXcoKTsKICAgIH0sIDApOwogICAgLy93aW5kb3cuc2Nyb2xsVG8oMCwgZG9jSGVpZ2h0KTsKICB9LCBmYWxzZSk7CgogIG91dHB1dF8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbihlKSB7CiAgICB2YXIgZWwgPSBlLnRhcmdldDsKICAgIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZpbGUnKSB8fCBlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZvbGRlcicpKSB7CiAgICAgIGNtZExpbmVfLnZhbHVlICs9ICcgJyArIGVsLnRleHRDb250ZW50OwogICAgfQogIH0sIGZhbHNlKTsKCiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZSkgewogICAgLy9pZiAoIWRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmNvbnRhaW5zKCdvZmZzY3JlZW4nKSkgewogICAgICBjbWRMaW5lXy5mb2N1cygpOwogICAgLy99CiAgfSwgZmFsc2UpOwoKICAvLyBBbHdheXMgZm9yY2UgdGV4dCBjdXJzb3IgdG8gZW5kIG9mIGlucHV0IGxpbmUuCiAgY21kTGluZV8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBpbnB1dFRleHRDbGlja18sIGZhbHNlKTsKCiAgLy8gSGFuZGxlIHVwL2Rvd24ga2V5IHByZXNzZXMgZm9yIHNoZWxsIGhpc3RvcnkgYW5kIGVudGVyIGZvciBuZXcgY29tbWFuZC4KICBjbWRMaW5lXy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywga2V5Ym9hcmRTaG9ydGN1dEhhbmRsZXJfLCBmYWxzZSk7CiAgY21kTGluZV8uYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCBoaXN0b3J5SGFuZGxlcl8sIGZhbHNlKTsgLy8ga2V5dXAgbmVlZGVkIGZvciBpbnB1dCBibGlua2VyIHRvIGFwcGVhciBhdCBlbmQgb2YgaW5wdXQuCiAgY21kTGluZV8uYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHByb2Nlc3NOZXdDb21tYW5kXywgZmFsc2UpOwoKICAvKndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdiZWZvcmV1bmxvYWQnLCBmdW5jdGlvbihlKSB7CiAgICByZXR1cm4gIkRvbid0IGxlYXZlIG1lISI7CiAgfSwgZmFsc2UpOyovCgogIGZ1bmN0aW9uIGlucHV0VGV4dENsaWNrXyhlKSB7CiAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZTsKICB9CgogIGZ1bmN0aW9uIGtleWJvYXJkU2hvcnRjdXRIYW5kbGVyXyhlKSB7CiAgICAvLyBUb2dnbGUgQ1JUIHNjcmVlbiBmbGlja2VyLgogICAgaWYgKChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSAmJiBlLmtleUNvZGUgPT0gODMpIHsgLy8gY3J0bCtzCiAgICAgIGNvbnRhaW5lcl8uY2xhc3NMaXN0LnRvZ2dsZSgnZmxpY2tlcicpOwogICAgICBvdXRwdXQoJzxkaXY+U2NyZWVuIGZsaWNrZXI6ICcgKwogICAgICAgICAgICAgKGNvbnRhaW5lcl8uY2xhc3NMaXN0LmNvbnRhaW5zKCdmbGlja2VyJykgPyAnb24nIDogJ29mZicpICsKICAgICAgICAgICAgICc8L2Rpdj4nKTsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBlLnN0b3BQcm9wYWdhdGlvbigpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gc2VsZWN0RmlsZV8oZWwpIHsKICAgIGFsZXJ0KGVsKQogIH0KCiAgZnVuY3Rpb24gaGlzdG9yeUhhbmRsZXJfKGUpIHsgLy8gVGFiIG5lZWRzIHRvIGJlIGtleWRvd24uCgogICAgaWYgKGhpc3RvcnlfLmxlbmd0aCkgewogICAgICBpZiAoZS5rZXlDb2RlID09IDM4IHx8IGUua2V5Q29kZSA9PSA0MCkgewogICAgICAgIGlmIChoaXN0b3J5X1toaXN0cG9zX10pIHsKICAgICAgICAgIGhpc3RvcnlfW2hpc3Rwb3NfXSA9IHRoaXMudmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGhpc3R0ZW1wXyA9IHRoaXMudmFsdWU7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoZS5rZXlDb2RlID09IDM4KSB7IC8vIHVwCiAgICAgICAgaGlzdHBvc18tLTsKICAgICAgICBpZiAoaGlzdHBvc18gPCAwKSB7CiAgICAgICAgICBoaXN0cG9zXyA9IDA7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSA0MCkgeyAvLyBkb3duCiAgICAgICAgaGlzdHBvc18rKzsKICAgICAgICBpZiAoaGlzdHBvc18gPiBoaXN0b3J5Xy5sZW5ndGgpIHsKICAgICAgICAgIGhpc3Rwb3NfID0gaGlzdG9yeV8ubGVuZ3RoOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGUua2V5Q29kZSA9PSAzOCB8fCBlLmtleUNvZGUgPT0gNDApIHsKICAgICAgICB0aGlzLnZhbHVlID0gaGlzdG9yeV9baGlzdHBvc19dID8gaGlzdG9yeV9baGlzdHBvc19dIDogaGlzdHRlbXBfOwogICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlOyAvLyBTZXRzIGN1cnNvciB0byBlbmQgb2YgaW5wdXQuCiAgICAgIH0KICAgIH0KICB9CgogIGZ1bmN0aW9uIHByb2Nlc3NOZXdDb21tYW5kXyhlKSB7CgogICAgLy8gQmVlcCBvbiBiYWNrc3BhY2UgYW5kIG5vIHZhbHVlIG9uIGNvbW1hbmQgbGluZS4KICAgIGlmICghdGhpcy52YWx1ZSAmJiBlLmtleUNvZGUgPT0gOCkgewogICAgICBiZWxsXy5zdG9wKCk7CiAgICAgIGJlbGxfLnBsYXkoKTsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChlLmtleUNvZGUgPT0gOSkgeyAvLyBUYWIKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAvLyBUT0RPKGVyaWNiaWRlbG1hbik6IEltcGxlbWVudCB0YWIgc3VnZ2VzdC4KICAgIH0gZWxzZSBpZiAoZS5rZXlDb2RlID09IDEzKSB7IC8vIGVudGVyCgogICAgICAvLyBTYXZlIHNoZWxsIGhpc3RvcnkuCiAgICAgIGlmICh0aGlzLnZhbHVlKSB7CiAgICAgICAgaGlzdG9yeV9baGlzdG9yeV8ubGVuZ3RoXSA9IHRoaXMudmFsdWU7CiAgICAgICAgaGlzdHBvc18gPSBoaXN0b3J5Xy5sZW5ndGg7CiAgICAgIH0KCiAgICAgIC8vIER1cGxpY2F0ZSBjdXJyZW50IGlucHV0IGFuZCBhcHBlbmQgdG8gb3V0cHV0IHNlY3Rpb24uCiAgICAgIHZhciBsaW5lID0gdGhpcy5wYXJlbnROb2RlLnBhcmVudE5vZGUuY2xvbmVOb2RlKHRydWUpOwogICAgICBsaW5lLnJlbW92ZUF0dHJpYnV0ZSgnaWQnKQogICAgICBsaW5lLmNsYXNzTGlzdC5hZGQoJ2xpbmUnKTsKICAgICAgdmFyIGlucHV0ID0gbGluZS5xdWVyeVNlbGVjdG9yKCdpbnB1dC5jbWRsaW5lJyk7CiAgICAgIGlucHV0LmF1dG9mb2N1cyA9IGZhbHNlOwogICAgICBpbnB1dC5yZWFkT25seSA9IHRydWU7CiAgICAgIG91dHB1dF8uYXBwZW5kQ2hpbGQobGluZSk7CgogICAgICAvLyBQYXJzZSBvdXQgY29tbWFuZCwgYXJncywgYW5kIHRyaW0gb2ZmIHdoaXRlc3BhY2UuCiAgICAgIC8vIFRPRE8oZXJpY2JpZGVsbWFuKTogU3VwcG9ydCBtdWx0aXBsZSBjb21tYSBzZXBhcmF0ZWQgY29tbWFuZHMuCiAgICAgIGlmICh0aGlzLnZhbHVlICYmIHRoaXMudmFsdWUudHJpbSgpKSB7CiAgICAgICAgdmFyIGFyZ3MgPSB0aGlzLnZhbHVlLnNwbGl0KCcgJykuZmlsdGVyKGZ1bmN0aW9uKHZhbCwgaSkgewogICAgICAgICAgcmV0dXJuIHZhbDsKICAgICAgICB9KTsKICAgICAgICB2YXIgY21kID0gYXJnc1swXS50b0xvd2VyQ2FzZSgpOwogICAgICAgIGFyZ3MgPSBhcmdzLnNwbGljZSgxKTsgLy8gUmVtb3ZlIGNtZCBmcm9tIGFyZyBsaXN0LgogICAgICB9CgogICAgICBzd2l0Y2ggKGNtZCkgewogICAgICAgIGNhc2UgJzNkJzoKICAgICAgICAgIGNsZWFyXyh0aGlzKTsKICAgICAgICAgIG91dHB1dCgnSG9sZCBvbiB0byB5b3VyIGJ1dHRzIScpOwogICAgICAgICAgdG9nZ2xlM0RWaWV3XygpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnY2F0JzoKICAgICAgICAgIHZhciBmaWxlTmFtZSA9IGFyZ3Muam9pbignICcpOwoKICAgICAgICAgIGlmICghZmlsZU5hbWUpIHsKICAgICAgICAgICAgb3V0cHV0KCd1c2FnZTogJyArIGNtZCArICcgZmlsZW5hbWUnKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CgogICAgICAgICAgcmVhZF8oY21kLCBmaWxlTmFtZSwgZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgICAgIG91dHB1dCgnPHByZT4nICsgcmVzdWx0ICsgJzwvcHJlPicpOwogICAgICAgICAgfSk7CgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnY2xlYXInOgogICAgICAgICAgY2xlYXJfKHRoaXMpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIGNhc2UgJ2RhdGUnOgogICAgICAgICAgb3V0cHV0KChuZXcgRGF0ZSgpKS50b0xvY2FsZVN0cmluZygpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2V4aXQnOgogICAgICAgICAgaWYgKGlzM0RfKSB7CiAgICAgICAgICAgIHRvZ2dsZTNEVmlld18oKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0aW1lcl8gIT0gbnVsbCkgewogICAgICAgICAgICBtYWdpY1dvcmRfLnN0b3AoKTsKICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lcl8pOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnaGVscCc6CiAgICAgICAgICBvdXRwdXQoJzxkaXYgY2xhc3M9ImxzLWZpbGVzIj4nICsgQ01EU18uam9pbignPGJyPicpICsgJzwvZGl2PicpOwogICAgICAgICAgb3V0cHV0KCc8cD5BZGQgZmlsZXMgYnkgZHJhZ2dpbmcgdGhlbSBmcm9tIHlvdXIgZGVza3RvcC48L3A+Jyk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdpbnN0YWxsJzoKICAgICAgICAgIC8vIENoZWNrIGlzIGluc3RhbGxlZC4KICAgICAgICAgIGlmICh3aW5kb3cuY2hyb21lICYmIHdpbmRvdy5jaHJvbWUuYXBwKSB7CiAgICAgICAgICAgIGlmICghd2luZG93LmNocm9tZS5hcHAuaXNJbnN0YWxsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgY2hyb21lLmFwcC5pbnN0YWxsKCk7CiAgICAgICAgICAgICAgfSBjYXRjaChlKSB7CiAgICAgICAgICAgICAgICBhbGVydChlICsgJ1xuRW5hYmxlIGlzIGFib3V0OmZsYWdzJyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIG91dHB1dCgnVGhpcyBhcHAgaXMgYWxyZWFkeSBpbnN0YWxsZWQuJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2xzJzoKICAgICAgICAgIGxzXyhmdW5jdGlvbihlbnRyaWVzKSB7CiAgICAgICAgICAgIGlmIChlbnRyaWVzLmxlbmd0aCkgewogICAgICAgICAgICAgIHZhciBodG1sID0gZm9ybWF0Q29sdW1uc18oZW50cmllcyk7CiAgICAgICAgICAgICAgdXRpbC50b0FycmF5KGVudHJpZXMpLmZvckVhY2goZnVuY3Rpb24oZW50cnksIGkpIHsKICAgICAgICAgICAgICAgIGh0bWwucHVzaCgKICAgICAgICAgICAgICAgICAgICAnPHNwYW4gY2xhc3M9IicsIGVudHJ5LmlzRGlyZWN0b3J5ID8gJ2ZvbGRlcicgOiAnZmlsZScsCiAgICAgICAgICAgICAgICAgICAgJyI+JywgZW50cnkubmFtZSwgJzwvc3Bhbj48YnI+Jyk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgaHRtbC5wdXNoKCc8L2Rpdj4nKTsKICAgICAgICAgICAgICBvdXRwdXQoaHRtbC5qb2luKCcnKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAncHdkJzoKICAgICAgICAgIG91dHB1dChjd2RfLmZ1bGxQYXRoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2NkJzoKICAgICAgICAgIHZhciBkZXN0ID0gYXJncy5qb2luKCcgJykgfHwgJy8nOwoKICAgICAgICAgIGN3ZF8uZ2V0RGlyZWN0b3J5KGRlc3QsIHt9LCBmdW5jdGlvbihkaXJFbnRyeSkgewogICAgICAgICAgICBjd2RfID0gZGlyRW50cnk7CiAgICAgICAgICAgIG91dHB1dCgnPGRpdj4nICsgZGlyRW50cnkuZnVsbFBhdGggKyAnPC9kaXY+Jyk7CgogICAgICAgICAgICAvLyBUZWxsIEZTTiB2aXN1YWxpemVyIHRoYXQgd2UncmUgY2QnaW5nLgogICAgICAgICAgICBpZiAoZnNuXykgewogICAgICAgICAgICAgIGZzbl8uY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7Y21kOiAnY2QnLCBkYXRhOiBkZXN0fSwgbG9jYXRpb24ub3JpZ2luKTsKICAgICAgICAgICAgfQoKICAgICAgICAgIH0sIGZ1bmN0aW9uKGUpIHsgaW52YWxpZE9wRm9yRW50cnlUeXBlXyhlLCBjbWQsIGRlc3QpOyB9KTsKCiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdta2Rpcic6CiAgICAgICAgICB2YXIgZGFzaFAgPSBmYWxzZTsKICAgICAgICAgIHZhciBpbmRleCA9IGFyZ3MuaW5kZXhPZignLXAnKTsKICAgICAgICAgIGlmIChpbmRleCAhPSAtMSkgewogICAgICAgICAgICBhcmdzLnNwbGljZShpbmRleCwgMSk7CiAgICAgICAgICAgIGRhc2hQID0gdHJ1ZTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoIWFyZ3MubGVuZ3RoKSB7CiAgICAgICAgICAgIG91dHB1dCgndXNhZ2U6ICcgKyBjbWQgKyAnIFstcF0gZGlyZWN0b3J5PGJyPicpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KCiAgICAgICAgICAvLyBDcmVhdGUgZWFjaCBkaXJlY3RvcnkgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LgogICAgICAgICAgYXJncy5mb3JFYWNoKGZ1bmN0aW9uKGRpck5hbWUsIGkpIHsKICAgICAgICAgICAgaWYgKGRhc2hQKSB7CiAgICAgICAgICAgICAgdmFyIGZvbGRlcnMgPSBkaXJOYW1lLnNwbGl0KCcvJyk7CgogICAgICAgICAgICAgIC8vIFRocm93IG91dCAnLi8nIG9yICcvJyBpZiBwcmVzZW50IG9uIHRoZSBiZWdpbm5pbmcgb2Ygb3VyIHBhdGguCiAgICAgICAgICAgICAgaWYgKGZvbGRlcnNbMF0gPT0gJy4nIHx8IGZvbGRlcnNbMF0gPT0gJycpIHsKICAgICAgICAgICAgICAgIGZvbGRlcnMgPSBmb2xkZXJzLnNsaWNlKDEpOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgY3JlYXRlRGlyXyhjd2RfLCBmb2xkZXJzKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBjd2RfLmdldERpcmVjdG9yeShkaXJOYW1lLCB7Y3JlYXRlOiB0cnVlLCBleGNsdXNpdmU6IHRydWV9LCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgIC8vIFRlbGwgRlNOIHZpc3VhbGl6ZXIgdGhhdCB3ZSdyZSBta2RpcidpbmcuCiAgICAgICAgICAgICAgICBpZiAoZnNuXykgewogICAgICAgICAgICAgICAgICBmc25fLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe2NtZDogJ21rZGlyJywgZGF0YTogZGlyTmFtZX0sIGxvY2F0aW9uLm9yaWdpbik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSwgZnVuY3Rpb24oZSkgeyBpbnZhbGlkT3BGb3JFbnRyeVR5cGVfKGUsIGNtZCwgZGlyTmFtZSk7IH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2NwJzoKICAgICAgICBjYXNlICdtdic6CiAgICAgICAgICB2YXIgc3JjID0gYXJnc1swXTsKICAgICAgICAgIHZhciBkZXN0ID0gYXJnc1sxXTsKCiAgICAgICAgICBpZiAoIXNyYyB8fCAhZGVzdCkgewogICAgICAgICAgICBvdXRwdXQoWyd1c2FnZTogJywgY21kLCAnIHNvdXJjZSB0YXJnZXQ8YnI+JywKICAgICAgICAgICAgICAgICAgICcmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsnLCBjbWQsCiAgICAgICAgICAgICAgICAgICAnIHNvdXJjZSBkaXJlY3RvcnkvJ10uam9pbignJykpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KCiAgICAgICAgICB2YXIgcnVuQWN0aW9uID0gZnVuY3Rpb24oY21kLCBzcmNEaXJFbnRyeSwgZGVzdERpckVudHJ5LCBvcHRfbmV3TmFtZSkgewogICAgICAgICAgICB2YXIgbmV3TmFtZSA9IG9wdF9uZXdOYW1lIHx8IG51bGw7CiAgICAgICAgICAgIGlmIChjbWQgPT0gJ212JykgewogICAgICAgICAgICAgICAgc3JjRGlyRW50cnkubW92ZVRvKGRlc3REaXJFbnRyeSwgbmV3TmFtZSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHNyY0RpckVudHJ5LmNvcHlUbyhkZXN0RGlyRW50cnksIG5ld05hbWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgIH07CgogICAgICAgICAgLy8gTW92aW5nIHRvIGEgZm9sZGVyPyAoZS5nLiBzZWNvbmQgYXJnIGVuZHMgaW4gJy8nKS4KICAgICAgICAgIGlmIChkZXN0W2Rlc3QubGVuZ3RoIC0gMV0gPT0gJy8nKSB7CiAgICAgICAgICAgIGN3ZF8uZ2V0RGlyZWN0b3J5KHNyYywge30sIGZ1bmN0aW9uKHNyY0RpckVudHJ5KSB7CiAgICAgICAgICAgICAgLy8gQ3JlYXRlIGJsYWNrbGlzdCBmb3IgZGlycyB3ZSBjYW4ndCByZS1jcmVhdGUuCiAgICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IFsKICAgICAgICAgICAgICAgICcuJywgJy4vJywgJy4uJywgJy4uLycsICcvJ10uaW5kZXhPZihkZXN0KSAhPSAtMSA/IGZhbHNlIDogdHJ1ZTsKCiAgICAgICAgICAgICAgY3dkXy5nZXREaXJlY3RvcnkoZGVzdCwge2NyZWF0ZTogY3JlYXRlfSwgZnVuY3Rpb24oZGVzdERpckVudHJ5KSB7CiAgICAgICAgICAgICAgICBydW5BY3Rpb24oY21kLCBzcmNEaXJFbnRyeSwgZGVzdERpckVudHJ5KTsKICAgICAgICAgICAgICB9LCBlcnJvckhhbmRsZXJfKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgIC8vIFRyeSB0aGUgc3JjIGVudHJ5IGFzIGEgZmlsZSBpbnN0ZWFkLgogICAgICAgICAgICAgIGN3ZF8uZ2V0RmlsZShzcmMsIHt9LCBmdW5jdGlvbihzcmNEaXJFbnRyeSkgewogICAgICAgICAgICAgICAgY3dkXy5nZXREaXJlY3RvcnkoZGVzdCwge30sIGZ1bmN0aW9uKGRlc3REaXJFbnRyeSkgewogICAgICAgICAgICAgICAgICBydW5BY3Rpb24oY21kLCBzcmNEaXJFbnRyeSwgZGVzdERpckVudHJ5KTsKICAgICAgICAgICAgICAgIH0sIGVycm9ySGFuZGxlcl8pOwogICAgICAgICAgICAgIH0sIGVycm9ySGFuZGxlcl8pOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7IC8vIFRyZWF0IHNyYy9kZXN0aW5hdGlvbiBhcyBmaWxlcy4KICAgICAgICAgICAgY3dkXy5nZXRGaWxlKHNyYywge30sIGZ1bmN0aW9uKHNyY0ZpbGVFbnRyeSkgewogICAgICAgICAgICAgIHNyY0ZpbGVFbnRyeS5nZXRQYXJlbnQoZnVuY3Rpb24ocGFyZW50RGlyRW50cnkpIHsKICAgICAgICAgICAgICAgIHJ1bkFjdGlvbihjbWQsIHNyY0ZpbGVFbnRyeSwgcGFyZW50RGlyRW50cnksIGRlc3QpOwogICAgICAgICAgICAgIH0sIGVycm9ySGFuZGxlcl8pOwogICAgICAgICAgICB9LCBlcnJvckhhbmRsZXJfKTsKICAgICAgICAgIH0KCiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdvcGVuJzoKICAgICAgICAgIHZhciBmaWxlTmFtZSA9IGFyZ3Muam9pbignICcpOwoKICAgICAgICAgIGlmICghZmlsZU5hbWUpIHsKICAgICAgICAgICAgb3V0cHV0KCd1c2FnZTogJyArIGNtZCArICcgZmlsZW5hbWUnKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CgogICAgICAgICAgb3Blbl8oY21kLCBmaWxlTmFtZSwgZnVuY3Rpb24oZmlsZUVudHJ5KSB7CiAgICAgICAgICAgIHZhciBteVdpbiA9IHdpbmRvdy5vcGVuKGZpbGVFbnRyeS50b1VSTCgpLCAnbXl3aW4nKTsKICAgICAgICAgIH0pOwoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2luaXQnOgogICAgICAgICAgaWYgKHdvcmtlcl8pIHsKICAgICAgICAgICAgd29ya2VyXy5wb3N0TWVzc2FnZSh7Y21kOiAnaW5pdCcsIHR5cGU6IHR5cGVfLCBzaXplOiBzaXplX30pOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAncm0nOgogICAgICAgICAgLy8gUmVtb3ZlIHJlY3Vyc2l2ZWx5PyBJZiBzbywgcmVtb3ZlIHRoZSBmbGFnKHMpIGZyb20gdGhlIGFyZyBsaXN0LgogICAgICAgICAgdmFyIHJlY3Vyc2l2ZSA9IGZhbHNlOwogICAgICAgICAgWyctcicsICctZicsICctcmYnLCAnLWZyJ10uZm9yRWFjaChmdW5jdGlvbihhcmcsIGkpIHsKICAgICAgICAgICAgdmFyIGluZGV4ID0gYXJncy5pbmRleE9mKGFyZyk7CiAgICAgICAgICAgIGlmIChpbmRleCAhPSAtMSkgewogICAgICAgICAgICAgIGFyZ3Muc3BsaWNlKGluZGV4LCAxKTsKICAgICAgICAgICAgICByZWN1cnNpdmUgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKCiAgICAgICAgICAvLyBSZW1vdmUgZWFjaCBmaWxlIHBhc3NlZCBhcyBhbiBhcmd1bWVudC4KICAgICAgICAgIGFyZ3MuZm9yRWFjaChmdW5jdGlvbihmaWxlTmFtZSwgaSkgewogICAgICAgICAgICBjd2RfLmdldEZpbGUoZmlsZU5hbWUsIHt9LCBmdW5jdGlvbihmaWxlRW50cnkpIHsKICAgICAgICAgICAgICBmaWxlRW50cnkucmVtb3ZlKGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgLy8gVGVsbCBGU04gdmlzdWFsaXplciB0aGF0IHdlJ3JlIHJtJ2luZy4KICAgICAgICAgICAgICAgIGlmIChmc25fKSB7CiAgICAgICAgICAgICAgICAgIGZzbl8uY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7Y21kOiAncm0nLCBkYXRhOiBmaWxlTmFtZX0sIGxvY2F0aW9uLm9yaWdpbik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSwgZXJyb3JIYW5kbGVyXyk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICBpZiAocmVjdXJzaXZlICYmIGUuY29kZSA9PSBGaWxlRXJyb3IuVFlQRV9NSVNNQVRDSF9FUlIpIHsKICAgICAgICAgICAgICAgIGN3ZF8uZ2V0RGlyZWN0b3J5KGZpbGVOYW1lLCB7fSwgZnVuY3Rpb24oZGlyRW50cnkpIHsKICAgICAgICAgICAgICAgICAgZGlyRW50cnkucmVtb3ZlUmVjdXJzaXZlbHkobnVsbCwgZXJyb3JIYW5kbGVyXyk7CiAgICAgICAgICAgICAgICB9LCBlcnJvckhhbmRsZXJfKTsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuY29kZSA9PSBGaWxlRXJyb3IuSU5WQUxJRF9TVEFURV9FUlIpIHsKICAgICAgICAgICAgICAgIG91dHB1dChjbWQgKyAnOiAnICsgZmlsZU5hbWUgKyAnOiBpcyBhIGRpcmVjdG9yeTxicj4nKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyXyhlKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdybWRpcic6CiAgICAgICAgICAvLyBSZW1vdmUgZWFjaCBkaXJlY3RvcnkgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LgogICAgICAgICAgYXJncy5mb3JFYWNoKGZ1bmN0aW9uKGRpck5hbWUsIGkpIHsKICAgICAgICAgICAgY3dkXy5nZXREaXJlY3RvcnkoZGlyTmFtZSwge30sIGZ1bmN0aW9uKGRpckVudHJ5KSB7CiAgICAgICAgICAgICAgZGlyRW50cnkucmVtb3ZlKGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgLy8gVGVsbCBGU04gdmlzdWFsaXplciB0aGF0IHdlJ3JlIHJtZGlyJ2luZy4KICAgICAgICAgICAgICAgIGlmIChmc25fKSB7CiAgICAgICAgICAgICAgICAgIGZzbl8uY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7Y21kOiAncm0nLCBkYXRhOiBkaXJOYW1lfSwgbG9jYXRpb24ub3JpZ2luKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9LCBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICBpZiAoZS5jb2RlID09IEZpbGVFcnJvci5JTlZBTElEX01PRElGSUNBVElPTl9FUlIpIHsKICAgICAgICAgICAgICAgICAgb3V0cHV0KGNtZCArICc6ICcgKyBkaXJOYW1lICsgJzogRGlyZWN0b3J5IG5vdCBlbXB0eTxicj4nKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlcl8oZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGUpIHsgaW52YWxpZE9wRm9yRW50cnlUeXBlXyhlLCBjbWQsIGRpck5hbWUpOyB9KTsKICAgICAgICAgIH0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnc3Vkbyc6CiAgICAgICAgICBpZiAodGltZXJfICE9IG51bGwpIHsKICAgICAgICAgICAgbWFnaWNXb3JkXy5zdG9wKCk7CiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGltZXJfKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghbWFnaWNXb3JkXykgewogICAgICAgICAgICBtYWdpY1dvcmRfID0gbmV3IFNvdW5kKHRydWUpOwogICAgICAgICAgICBtYWdpY1dvcmRfLmxvYWQoJ21hZ2ljX3dvcmQubXAzJywgZmFsc2UsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIG1hZ2ljV29yZF8ucGxheSgpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG1hZ2ljV29yZF8ucGxheSgpOwogICAgICAgICAgfQogICAgICAgICAgdGltZXJfID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIG91dHB1dCgiPGRpdj5ZT1UgRElETidUIFNBWSBUSEUgTUFHSUMgV09SRCE8L2Rpdj4iKTsKICAgICAgICAgIH0sIDEwMCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICd0aGVtZSc6CiAgICAgICAgICB2YXIgdGhlbWUgPSBhcmdzLmpvaW4oJyAnKTsKICAgICAgICAgIGlmICghdGhlbWUpIHsKICAgICAgICAgICAgb3V0cHV0KFsndXNhZ2U6ICcsIGNtZCwgJyAnICsgVEhFTUVTXy5qb2luKCcsJyldLmpvaW4oJycpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmIChUSEVNRVNfLmluZGV4T2YodGhlbWUpICE9IC0xKSB7CiAgICAgICAgICAgICAgc2V0VGhlbWVfKHRoZW1lKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBvdXRwdXQoJ0Vycm9yIC0gVW5yZWNvZ25pemVkIHRoZW1lIHVzZWQnKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAndmVyc2lvbic6CiAgICAgICAgY2FzZSAndmVyJzoKICAgICAgICAgIG91dHB1dChWRVJTSU9OXyk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICd3Z2V0JzoKICAgICAgICAgIHZhciB1cmwgPSBhcmdzWzBdOwogICAgICAgICAgaWYgKCF1cmwpIHsKICAgICAgICAgICAgb3V0cHV0KFsndXNhZ2U6ICcsIGNtZCwgJyBtaXNzaW5nIFVSTCddLmpvaW4oJycpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9IGVsc2UgaWYgKHVybC5zZWFyY2goJ15odHRwOi8vJykgPT0gLTEpIHsKICAgICAgICAgICAgdXJsID0gJ2h0dHA6Ly8nICsgdXJsOwogICAgICAgICAgfQogICAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgaWYgKHRoaXMuc3RhdHVzID09IDIwMCAmJiB0aGlzLnJlYWR5U3RhdGUgPT0gNCkgewogICAgICAgICAgICAgIG91dHB1dCgnPHRleHRhcmVhPicgKyB0aGlzLnJlc3BvbnNlICsgJzwvdGV4dGFyZWE+Jyk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgb3V0cHV0KCdFUlJPUjogJyArIHRoaXMuc3RhdHVzICsgJyAnICsgdGhpcy5zdGF0dXNUZXh0KTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKICAgICAgICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgICBvdXRwdXQoJ0VSUk9SOiAnICsgdGhpcy5zdGF0dXMgKyAnICcgKyB0aGlzLnN0YXR1c1RleHQpOwogICAgICAgICAgICBvdXRwdXQoJ0NvdWxkIG5vdCBmZXRjaCAnICsgdXJsKTsKICAgICAgICAgIH07CiAgICAgICAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTsKICAgICAgICAgIHhoci5zZW5kKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICd3aG8nOgogICAgICAgICAgb3V0cHV0KGRvY3VtZW50LnRpdGxlICsKICAgICAgICAgICAgICAgICAnIC0gQnk6IEVyaWMgQmlkZWxtYW4gJmx0O2VyaWNiaWRlbG1hbkBjaHJvbWl1bS5vcmcmZ3Q7Jyk7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaWYgKGNtZCkgewogICAgICAgICAgICBvdXRwdXQoY21kICsgJzogY29tbWFuZCBub3QgZm91bmQnKTsKICAgICAgICAgIH0KICAgICAgfTsKCiAgICAgIHRoaXMudmFsdWUgPSAnJzsgLy8gQ2xlYXIvc2V0dXAgbGluZSBmb3IgbmV4dCBpbnB1dC4KICAgIH0KICB9CgogIGZ1bmN0aW9uIGZvcm1hdENvbHVtbnNfKGVudHJpZXMpIHsKICAgIHZhciBtYXhOYW1lID0gZW50cmllc1swXS5uYW1lOwogICAgdXRpbC50b0FycmF5KGVudHJpZXMpLmZvckVhY2goZnVuY3Rpb24oZW50cnksIGkpIHsKICAgICAgaWYgKGVudHJ5Lm5hbWUubGVuZ3RoID4gbWF4TmFtZS5sZW5ndGgpIHsKICAgICAgICBtYXhOYW1lID0gZW50cnkubmFtZTsKICAgICAgfQogICAgfSk7CgogICAgLy8gSWYgd2UgaGF2ZSAzIG9yIGxlc3MgZW50cmllcywgc2hvcnRlbiB0aGUgb3V0cHV0IGNvbnRhaW5lcidzIGhlaWdodC4KICAgIC8vIDE1cHggaGVpZ2h0IHdpdGggYSBtb25vc3BhY2UgZm9udC1zaXplIG9mIH4xMnB4OwogICAgdmFyIGhlaWdodCA9IGVudHJpZXMubGVuZ3RoID09IDEgPyAnaGVpZ2h0OiAnICsgKGVudHJpZXMubGVuZ3RoICogMzApICsgJ3B4OycgOgogICAgICAgICAgICAgICAgIGVudHJpZXMubGVuZ3RoIDw9IDMgPyAnaGVpZ2h0OiAnICsgKGVudHJpZXMubGVuZ3RoICogMTgpICsgJ3B4OycgOiAnJzsKCiAgICAvLyB+MTJweCBtb25vc3BhY2UgZm9udCB5aWVsZHMgfjhweCBzY3JlZW4gd2lkdGguCiAgICB2YXIgY29sV2lkdGggPSBtYXhOYW1lLmxlbmd0aCAqIDE2Oy8vOzg7CgogICAgcmV0dXJuIFsnPGRpdiBjbGFzcz0ibHMtZmlsZXMiIHN0eWxlPSItd2Via2l0LWNvbHVtbi13aWR0aDonLAogICAgICAgICAgICBjb2xXaWR0aCwgJ3B4OycsIGhlaWdodCwgJyI+J107CiAgfQoKICBmdW5jdGlvbiBpbnZhbGlkT3BGb3JFbnRyeVR5cGVfKGUsIGNtZCwgZGVzdCkgewogICAgaWYgKGUuY29kZSA9PSBGaWxlRXJyb3IuTk9UX0ZPVU5EX0VSUikgewogICAgICBvdXRwdXQoY21kICsgJzogJyArIGRlc3QgKyAnOiBObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5PGJyPicpOwogICAgfSBlbHNlIGlmIChlLmNvZGUgPT0gRmlsZUVycm9yLklOVkFMSURfU1RBVEVfRVJSKSB7CiAgICAgIG91dHB1dChjbWQgKyAnOiAnICsgZGVzdCArICc6IE5vdCBhIGRpcmVjdG9yeTxicj4nKTsKICAgIH0gZWxzZSBpZiAoZS5jb2RlID09IEZpbGVFcnJvci5JTlZBTElEX01PRElGSUNBVElPTl9FUlIpIHsKICAgICAgb3V0cHV0KGNtZCArICc6ICcgKyBkZXN0ICsgJzogRmlsZSBhbHJlYWR5IGV4aXN0czxicj4nKTsKICAgIH0gZWxzZSB7CiAgICAgIGVycm9ySGFuZGxlcl8oZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBlcnJvckhhbmRsZXJfKGUpIHsKICAgIHZhciBtc2cgPSAnJzsKICAgIHN3aXRjaCAoZS5jb2RlKSB7CiAgICAgIGNhc2UgRmlsZUVycm9yLlFVT1RBX0VYQ0VFREVEX0VSUjoKICAgICAgICBtc2cgPSAnUVVPVEFfRVhDRUVERURfRVJSJzsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBGaWxlRXJyb3IuTk9UX0ZPVU5EX0VSUjoKICAgICAgICBtc2cgPSAnTk9UX0ZPVU5EX0VSUic7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgRmlsZUVycm9yLlNFQ1VSSVRZX0VSUjoKICAgICAgICBtc2cgPSAnU0VDVVJJVFlfRVJSJzsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBGaWxlRXJyb3IuSU5WQUxJRF9NT0RJRklDQVRJT05fRVJSOgogICAgICAgIG1zZyA9ICdJTlZBTElEX01PRElGSUNBVElPTl9FUlInOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIEZpbGVFcnJvci5JTlZBTElEX1NUQVRFX0VSUjoKICAgICAgICBtc2cgPSAnSU5WQUxJRF9TVEFURV9FUlInOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIG1zZyA9ICdVbmtub3duIEVycm9yJzsKICAgICAgICBicmVhazsKICAgIH07CiAgICBvdXRwdXQoJzxkaXY+RXJyb3I6ICcgKyBtc2cgKyAnPC9kaXY+Jyk7CiAgfQoKICBmdW5jdGlvbiBjcmVhdGVEaXJfKHJvb3REaXJFbnRyeSwgZm9sZGVycywgb3B0X2Vycm9yQ2FsbGJhY2spIHsKICAgIHZhciBlcnJvckNhbGxiYWNrID0gb3B0X2Vycm9yQ2FsbGJhY2sgfHwgZXJyb3JIYW5kbGVyXzsKCiAgICByb290RGlyRW50cnkuZ2V0RGlyZWN0b3J5KGZvbGRlcnNbMF0sIHtjcmVhdGU6IHRydWV9LCBmdW5jdGlvbihkaXJFbnRyeSkgewoKICAgICAgLy8gUmVjdXJzaXZlbHkgYWRkIHRoZSBuZXcgc3ViZm9sZGVyIGlmIHdlIHN0aWxsIGhhdmUgYSBzdWJmb2xkZXIgdG8gY3JlYXRlLgogICAgICBpZiAoZm9sZGVycy5sZW5ndGgpIHsKICAgICAgICBjcmVhdGVEaXJfKGRpckVudHJ5LCBmb2xkZXJzLnNsaWNlKDEpKTsKICAgICAgfQogICAgfSwgZXJyb3JDYWxsYmFjayk7CiAgfQoKICBmdW5jdGlvbiBvcGVuXyhjbWQsIHBhdGgsIHN1Y2Nlc3NDYWxsYmFjaykgewogICAgaWYgKCFmc18pIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGN3ZF8uZ2V0RmlsZShwYXRoLCB7fSwgc3VjY2Vzc0NhbGxiYWNrLCBmdW5jdGlvbihlKSB7CiAgICAgIGlmIChlLmNvZGUgPT0gRmlsZUVycm9yLk5PVF9GT1VORF9FUlIpIHsKICAgICAgICBvdXRwdXQoY21kICsgJzogJyArIHBhdGggKyAnOiBObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5PGJyPicpOwogICAgICB9CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHJlYWRfKGNtZCwgcGF0aCwgc3VjY2Vzc0NhbGxiYWNrKSB7CiAgICBpZiAoIWZzXykgewogICAgICByZXR1cm47CiAgICB9CgogICAgY3dkXy5nZXRGaWxlKHBhdGgsIHt9LCBmdW5jdGlvbihmaWxlRW50cnkpIHsKICAgICAgZmlsZUVudHJ5LmZpbGUoZnVuY3Rpb24oZmlsZSkgewogICAgICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpOwoKICAgICAgICByZWFkZXIub25sb2FkZW5kID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKHRoaXMucmVzdWx0KTsKICAgICAgICB9OwoKICAgICAgICByZWFkZXIucmVhZEFzVGV4dChmaWxlKTsKICAgICAgfSwgZXJyb3JIYW5kbGVyXyk7CiAgICB9LCBmdW5jdGlvbihlKSB7CiAgICAgIGlmIChlLmNvZGUgPT0gRmlsZUVycm9yLklOVkFMSURfU1RBVEVfRVJSKSB7CiAgICAgICAgb3V0cHV0KGNtZCArICc6ICcgKyBwYXRoICsgJzogaXMgYSBkaXJlY3Rvcnk8YnI+Jyk7CiAgICAgIH0gZWxzZSBpZiAoZS5jb2RlID09IEZpbGVFcnJvci5OT1RfRk9VTkRfRVJSKSB7CiAgICAgICAgb3V0cHV0KGNtZCArICc6ICcgKyBwYXRoICsgJzogTm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeTxicj4nKTsKICAgICAgfQogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBsc18oc3VjY2Vzc0NhbGxiYWNrKSB7CiAgICBpZiAoIWZzXykgewogICAgICByZXR1cm47CiAgICB9CgogICAgLy8gUmVhZCBjb250ZW50cyBvZiBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LiBBY2NvcmRpbmcgdG8gc3BlYywgbmVlZCB0bwogICAgLy8ga2VlcCBjYWxsaW5nIHJlYWRFbnRyaWVzKCkgdW50aWwgbGVuZ3RoIG9mIHJlc3VsdCBhcnJheSBpcyAwLiBXZSdyZQogICAgLy8gZ3VhcmVudGVlZCB0aGUgc2FtZSBlbnRyeSB3b24ndCBiZSByZXR1cm5lZCBhZ2Fpbi4KICAgIHZhciBlbnRyaWVzID0gW107CiAgICB2YXIgcmVhZGVyID0gY3dkXy5jcmVhdGVSZWFkZXIoKTsKCiAgICB2YXIgcmVhZEVudHJpZXMgPSBmdW5jdGlvbigpIHsKICAgICAgcmVhZGVyLnJlYWRFbnRyaWVzKGZ1bmN0aW9uKHJlc3VsdHMpIHsKICAgICAgICBpZiAoIXJlc3VsdHMubGVuZ3RoKSB7CiAgICAgICAgICBlbnRyaWVzID0gZW50cmllcy5zb3J0KCk7CiAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soZW50cmllcyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGVudHJpZXMgPSBlbnRyaWVzLmNvbmNhdCh1dGlsLnRvQXJyYXkocmVzdWx0cykpOwogICAgICAgICAgcmVhZEVudHJpZXMoKTsKICAgICAgICB9CiAgICAgIH0sIGVycm9ySGFuZGxlcl8pOwogICAgfTsKCiAgICByZWFkRW50cmllcygpOwogIH0KCiAgZnVuY3Rpb24gY2xlYXJfKGlucHV0KSB7CiAgICBvdXRwdXRfLmlubmVySFRNTCA9ICcnOwogICAgaW5wdXQudmFsdWUgPSAnJzsKICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7CiAgICBpbnRlcmxhY2VfLnN0eWxlLmhlaWdodCA9ICcxMDAlJzsKICB9CgogIGZ1bmN0aW9uIHNldFRoZW1lXyh0aGVtZSkgewogICAgdmFyIGN1cnJlbnRVcmwgPSBkb2N1bWVudC5sb2NhdGlvbi5wYXRobmFtZTsKCiAgICBpZiAoIXRoZW1lIHx8IHRoZW1lID09ICdkZWZhdWx0JykgewogICAgICAvL2hpc3RvcnkucmVwbGFjZVN0YXRlKHt9LCAnJywgY3VycmVudFVybCk7CiAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCd0aGVtZScpOwogICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTmFtZSA9ICcnOwogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHRoZW1lKSB7CiAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCh0aGVtZSk7CiAgICAgIGxvY2FsU3RvcmFnZS50aGVtZSA9IHRoZW1lOwogICAgICAvL2hpc3RvcnkucmVwbGFjZVN0YXRlKHt9LCAnJywgY3VycmVudFVybCArICcjdGhlbWU9JyArIHRoZW1lKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHRvZ2dsZTNEVmlld18oKSB7CiAgICB2YXIgYm9keSA9IGRvY3VtZW50LmJvZHk7CiAgICBib2R5LmNsYXNzTGlzdC50b2dnbGUoJ29mZnNjcmVlbicpOwoKICAgIGlzM0RfID0gIWlzM0RfOwoKICAgIGlmIChib2R5LmNsYXNzTGlzdC5jb250YWlucygnb2Zmc2NyZWVuJykpIHsKCiAgICAgIGNvbnRhaW5lcl8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0KICAgICAgICAgICd0cmFuc2xhdGVZKCcgKyAodXRpbC5nZXREb2NIZWlnaHQoKSAtIDE3NSkgKyAncHgpJzsKCiAgICAgIHZhciB0cmFuc0VuZF8gPSBmdW5jdGlvbihlKSB7CiAgICAgICAgdmFyIGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpOwogICAgICAgIGlmcmFtZS5pZCA9ICdmc24nOwogICAgICAgIGlmcmFtZS5zcmMgPSAnLi4vZnNuL2Zzbl9wcm90by5odG1sJzsKCiAgICAgICAgZnNuXyA9IGJvZHkuaW5zZXJ0QmVmb3JlKGlmcmFtZSwgYm9keS5maXJzdEVsZW1lbnRDaGlsZCk7CgogICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93Lm9ubG9hZCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgd29ya2VyXy5wb3N0TWVzc2FnZSh7Y21kOiAncmVhZCcsIHR5cGU6IHR5cGVfLCBzaXplOiBzaXplX30pOwogICAgICAgIH0KICAgICAgICBjb250YWluZXJfLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3dlYmtpdFRyYW5zaXRpb25FbmQnLCB0cmFuc0VuZF8sIGZhbHNlKTsKICAgICAgfTsKICAgICAgY29udGFpbmVyXy5hZGRFdmVudExpc3RlbmVyKCd3ZWJraXRUcmFuc2l0aW9uRW5kJywgdHJhbnNFbmRfLCBmYWxzZSk7CiAgICB9IGVsc2UgewogICAgICBjb250YWluZXJfLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICd0cmFuc2xhdGVZKDApJzsKICAgICAgYm9keS5yZW1vdmVDaGlsZChmc25fKTsKICAgICAgZnNuXyA9IG51bGw7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBvdXRwdXQoaHRtbCkgewogICAgb3V0cHV0Xy5pbnNlcnRBZGphY2VudEhUTUwoJ2JlZm9yZUVuZCcsIGh0bWwpOwogICAgLy9vdXRwdXRfLnNjcm9sbEludG9WaWV3KCk7CiAgICBjbWRMaW5lXy5zY3JvbGxJbnRvVmlldygpOwogIH0KCiAgcmV0dXJuIHsKICAgIGluaXRGUzogZnVuY3Rpb24ocGVyc2lzdGVudCwgc2l6ZSkgewogICAgICBvdXRwdXQoJzxkaXY+V2VsY29tZSB0byAnICsgZG9jdW1lbnQudGl0bGUgKwogICAgICAgICAgICAgJyEgKHYnICsgVkVSU0lPTl8gKyAnKTwvZGl2PicpOwogICAgICBvdXRwdXQoKG5ldyBEYXRlKCkpLnRvTG9jYWxlU3RyaW5nKCkpOwogICAgICBvdXRwdXQoJzxwPkRvY3VtZW50YXRpb246IHR5cGUgImhlbHAiPC9wPicpOwoKICAgICAgaWYgKCEhIXdpbmRvdy5yZXF1ZXN0RmlsZVN5c3RlbSkgewogICAgICAgIG91dHB1dCgnPGRpdj5Tb3JyeSEgVGhlIEZpbGVTeXN0ZW0gQVBJcyBhcmUgbm90IGF2YWlsYWJsZSBpbiB5b3VyIGJyb3dzZXIuPC9kaXY+Jyk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgdHlwZSA9IHBlcnNpc3RlbnQgPyB3aW5kb3cuUEVSU0lTVEVOVCA6IHdpbmRvdy5URU1QT1JBUlk7CiAgICAgIHdpbmRvdy5yZXF1ZXN0RmlsZVN5c3RlbSh0eXBlLCBzaXplLCBmdW5jdGlvbihmaWxlc3lzdGVtKSB7CiAgICAgICAgZnNfID0gZmlsZXN5c3RlbTsKICAgICAgICBjd2RfID0gZnNfLnJvb3Q7CiAgICAgICAgdHlwZV8gPSB0eXBlOwogICAgICAgIHNpemVfID0gc2l6ZTsKCiAgICAgICAgLy8gSWYgd2UgZ2V0IHRoaXMgZmFyLCBhdHRlbXB0IHRvIGNyZWF0ZSBhIGZvbGRlciB0byB0ZXN0IGlmIHRoZQogICAgICAgIC8vIC0tdW5saW1pdGVkLXF1b3RhLWZvci1maWxlcyBmYWcgaXMgc2V0LgogICAgICAgIGN3ZF8uZ2V0RGlyZWN0b3J5KCd0ZXN0cXVvdGFmb3Jmc2ZvbGRlcicsIHtjcmVhdGU6IHRydWV9LCBmdW5jdGlvbihkaXJFbnRyeSkgewogICAgICAgICAgZGlyRW50cnkucmVtb3ZlKGZ1bmN0aW9uKCkgeyAvLyBJZiBzdWNjZXNzZnVsbHkgY3JlYXRlZCwganVzdCBkZWxldGUgaXQuCiAgICAgICAgICAgIC8vIG5vb3AuCiAgICAgICAgICB9KTsKICAgICAgICB9LCBmdW5jdGlvbihlKSB7CiAgICAgICAgICBpZiAoZS5jb2RlID09IEZpbGVFcnJvci5RVU9UQV9FWENFRURFRF9FUlIpIHsKICAgICAgICAgICAgb3V0cHV0KCdFUlJPUjogV3JpdGUgYWNjZXNzIHRvIHRoZSBGaWxlU3lzdGVtIGlzIHVuYXZhaWxhYmxlLjxicj4nKTsKICAgICAgICAgICAgb3V0cHV0KCdUeXBlICJpbnN0YWxsIiBvciBydW4gQ2hyb21lIHdpdGggdGhlIC0tdW5saW1pdGVkLXF1b3RhLWZvci1maWxlcyBmbGFnLicpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZXJyb3JIYW5kbGVyXyhlKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKCiAgICAgIH0sIGVycm9ySGFuZGxlcl8pOwogICAgfSwKICAgIG91dHB1dDogb3V0cHV0LAogICAgc2V0VGhlbWU6IHNldFRoZW1lXywKICAgIGdldENtZExpbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY21kTGluZV87IH0sCiAgICBhZGREcm9wcGVkRmlsZXM6IGZ1bmN0aW9uKGZpbGVzKSB7CiAgICAgIHV0aWwudG9BcnJheShmaWxlcykuZm9yRWFjaChmdW5jdGlvbihmaWxlLCBpKSB7CiAgICAgICAgY3dkXy5nZXRGaWxlKGZpbGUubmFtZSwge2NyZWF0ZTogdHJ1ZSwgZXhjbHVzaXZlOiB0cnVlfSwgZnVuY3Rpb24oZmlsZUVudHJ5KSB7CgogICAgICAgICAgLy8gVGVsbCBGU04gdmlzdWFsaXplciB3ZSd2ZSBhZGRlZCBhIGZpbGUuCiAgICAgICAgICBpZiAoZnNuXykgewogICAgICAgICAgICBmc25fLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe2NtZDogJ3RvdWNoJywgZGF0YTogZmlsZS5uYW1lfSwgbG9jYXRpb24ub3JpZ2luKTsKICAgICAgICAgIH0KICAgICAgICAgIAogICAgICAgICAgZmlsZUVudHJ5LmNyZWF0ZVdyaXRlcihmdW5jdGlvbihmaWxlV3JpdGVyKSB7CiAgICAgICAgICAgIGZpbGVXcml0ZXIud3JpdGUoZmlsZSk7CiAgICAgICAgICB9LCBlcnJvckhhbmRsZXJfKTsKICAgICAgICB9LCBlcnJvckhhbmRsZXJfKTsKICAgICAgfSk7CiAgICB9LAogICAgdG9nZ2xlM0RWaWV3OiB0b2dnbGUzRFZpZXdfLAogICAgc2VsZWN0RmlsZTogc2VsZWN0RmlsZV8KICB9Cn07Cgo="></script>
-->
<script id="script_terminal_js" >
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Author: Eric Bidelman (ericbidelman@chromium.org)
*/
var util = util || {};
util.toArray = function(list) {
return Array.prototype.slice.call(list || [], 0);
};
// Cross-browser impl to get document's height.
util.getDocHeight = function() {
var d = document;
return Math.max(
Math.max(d.body.scrollHeight, d.documentElement.scrollHeight),
Math.max(d.body.offsetHeight, d.documentElement.offsetHeight),
Math.max(d.body.clientHeight, d.documentElement.clientHeight)
);
};
// TODO(ericbidelman): add fallback to html5 audio.
function Sound(opt_loop) {
var self_ = this;
var context_ = null;
var source_ = null;
var loop_ = opt_loop || false;
window.AudioContext = window.AudioContext || window.webkitAudioContext;
if (window.AudioContext) {
context_ = new window.AudioContext();
}
this.load = function(url, mixToMono, opt_callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
if (context_) {
/*self_.sample = context_.createBuffer(this.response, mixToMono);
if (opt_callback) {
opt_callback();
}
*/
context_.decodeAudioData(this.response, function(audioBuffer) {
self_.sample = audioBuffer;
opt_callback && opt_callback();
}, function(e) {
console.log(e);
});
}
};
xhr.send();
};
this.play = function() {
if (context_) {
source_ = context_.createBufferSource();
source_.buffer = self_.sample;
source_.looping = loop_;
source_.connect(context_.destination);
source_.noteOn(0);
}
};
this.stop = function() {
if (source_) {
source_.noteOff(0);
source_.disconnect(0);
}
};
}
var Terminal = Terminal || function(containerId) {
window.URL = window.URL || window.webkitURL;
window.requestFileSystem = window.requestFileSystem ||
window.webkitRequestFileSystem;
const VERSION_ = '1.0.0';
const CMDS_ = [
'vi', ':', '/', '?', '3d', 'cat', 'cd', 'cp', 'clear', 'date', 'help', 'install', 'ls', 'mkdir',
'mv', 'open', 'pwd', 'rm', 'rmdir', 'theme', 'version', 'who', 'wget', 'ajax', 'sql3'
];
const THEMES_ = ['default', 'cream'];
var fs_ = null;
var cwd_ = null;
var history_ = [];
var histpos_ = 0;
var histtemp_ = 0;
var timer_ = null;
var magicWord_ = null;
var fsn_ = null;
var is3D_ = false;
// Fire worker to return recursive snapshot of current FS tree.
var worker_ = new Worker('worker.js');
worker_.onmessage = function(e) {
var data = e.data;
if (data.entries) {
fsn_.contentWindow.postMessage({cmd: 'build', data: data.entries},
window.location.origin);
}
if (data.msg) {
output('<div>' + data.msg + '</div>');
}
};
worker_.onerror = function(e) { console.log(e) };
// Create terminal and cache DOM nodes;
var container_ = document.getElementById(containerId);
container_.insertAdjacentHTML('beforeEnd',
['<output></output>',
'<div id="input-line" class="input-line">',
'<div class="prompt">$></div><div><input class="cmdline" autofocus /></div>',
'</div>'].join(''));
var cmdLine_ = container_.querySelector('#input-line .cmdline');
var output_ = container_.querySelector('output');
var interlace_ = document.querySelector('.interlace');
var bell_ = new Sound(false);
bell_.load('beep.mp3', false);
// Hackery to resize the interlace background image as the container grows.
output_.addEventListener('DOMSubtreeModified', function(e) {
var docHeight = util.getDocHeight();
document.documentElement.style.height = docHeight + 'px';
//document.body.style.background = '-webkit-radial-gradient(center ' + (Math.round(docHeight / 2)) + 'px, contain, rgba(0,75,0,0.8), black) center center no-repeat, black';
interlace_.style.height = docHeight + 'px';
setTimeout(function() { // Need this wrapped in a setTimeout. Chrome is jupming to top :(
//window.scrollTo(0, docHeight);
cmdLine_.scrollIntoView();
}, 0);
//window.scrollTo(0, docHeight);
}, false);
output_.addEventListener('click', function(e) {
var el = e.target;
if (el.classList.contains('file') || el.classList.contains('folder')) {
cmdLine_.value += ' ' + el.textContent;
}
}, false);
window.addEventListener('click', function(e) {
//if (!document.body.classList.contains('offscreen')) {
cmdLine_.focus();
//}
}, false);
// Always force text cursor to end of input line.
cmdLine_.addEventListener('click', inputTextClick_, false);
// Handle up/down key presses for shell history and enter for new command.
cmdLine_.addEventListener('keydown', keyboardShortcutHandler_, false);
cmdLine_.addEventListener('keyup', historyHandler_, false); // keyup needed for input blinker to appear at end of input.
cmdLine_.addEventListener('keydown', processNewCommand_, false);
/*window.addEventListener('beforeunload', function(e) {
return "Don't leave me!";
}, false);*/
function inputTextClick_(e) {
this.value = this.value;
}
function keyboardShortcutHandler_(e) {
// Toggle CRT screen flicker.
if ((e.ctrlKey || e.metaKey) && e.keyCode == 83) { // crtl+s
container_.classList.toggle('flicker');
output('<div>Screen flicker: ' +
(container_.classList.contains('flicker') ? 'on' : 'off') +
'</div>');
e.preventDefault();
e.stopPropagation();
}
}
function selectFile_(el) {
alert(el)
}
function historyHandler_(e) { // Tab needs to be keydown.
if (history_.length) {
if (e.keyCode == 38 || e.keyCode == 40) {
if (history_[histpos_]) {
history_[histpos_] = this.value;
} else {
histtemp_ = this.value;
}
}
if (e.keyCode == 38) { // up
histpos_--;
if (histpos_ < 0) {
histpos_ = 0;
}
} else if (e.keyCode == 40) { // down
histpos_++;
if (histpos_ > history_.length) {
histpos_ = history_.length;
}
}
if (e.keyCode == 38 || e.keyCode == 40) {
this.value = history_[histpos_] ? history_[histpos_] : histtemp_;
this.value = this.value; // Sets cursor to end of input.
}
}
}
function processNewCommand_(e) {
// Beep on backspace and no value on command line.
if (!this.value && e.keyCode == 8) {
bell_.stop();
bell_.play();
return;
}
if (e.keyCode == 9) { // Tab
e.preventDefault();
// TODO(ericbidelman): Implement tab suggest.
} else if (e.keyCode == 13) { // enter
// Save shell history.
if (this.value) {
history_[history_.length] = this.value;
histpos_ = history_.length;
}
// Duplicate current input and append to output section.
var line = this.parentNode.parentNode.cloneNode(true);
line.removeAttribute('id')
line.classList.add('line');
var input = line.querySelector('input.cmdline');
input.autofocus = false;
input.readOnly = true;
output_.appendChild(line);
// Parse out command, args, and trim off whitespace.
// TODO(ericbidelman): Support multiple comma separated commands.
if (this.value && this.value.trim()) {
var args = this.value.split(' ').filter(function(val, i) {
return val;
});
var cmd = args[0].toLowerCase();
args = args.splice(1); // Remove cmd from arg list.
}
switch (cmd) {
case '3d':
// var src = args.join(' ');
src=""; a2=""; a3="";
var argc=args.length;
var src=args[0];
a1=args[0];
if( argc>0 ) { a2=args[1]; }
if( argc>1 ) { a3=args[2]; }
src=a1;
if( !src ) { src="/notice.html"; }
clear_(this);
alert( "BUGS_730 3d cmd="+cmd+" src="+src+" argc="+argc+"\n a1="+a1+" a2="+a2+" a3="+a3 );
// output('Hold on to your butts!');
output('kopower! ');
toggle3DView_(src);
break;
case 'cat':
var fileName = args.join(' ');
if (!fileName) {
output('usage: ' + cmd + ' filename');
break;
}
read_(cmd, fileName, function(result) {
output('<pre>' + result + '</pre>');
});
break;
case 'clear':
clear_(this);
return;
case 'date':
output((new Date()).toLocaleString());
break;
case 'exit':
if (is3D_) {
toggle3DView_('');
}
if (timer_ != null) {
magicWord_.stop();
clearInterval(timer_);
}
break;
case 'help':
output('<div class="ls-files">' + CMDS_.join('<br>') + '</div>');
output('<p>Add files by dragging them from your desktop.</p>');
break;
case 'install':
// Check is installed.
if (window.chrome && window.chrome.app) {
if (!window.chrome.app.isInstalled) {
try {
chrome.app.install();
} catch(e) {
alert(e + '\nEnable is about:flags');
}
} else {
output('This app is already installed.');
}
}
break;
case 'ls':
ls_(function(entries) {
if (entries.length) {
var html = formatColumns_(entries);
util.toArray(entries).forEach(function(entry, i) {
html.push(
'<span class="', entry.isDirectory ? 'folder' : 'file',
'">', entry.name, '</span><br>');
});
html.push('</div>');
output(html.join(''));
}
});
break;
case 'pwd':
output(cwd_.fullPath);
break;
case 'cd':
var dest = args.join(' ') || '/';
cwd_.getDirectory(dest, {}, function(dirEntry) {
cwd_ = dirEntry;
output('<div>' + dirEntry.fullPath + '</div>');
// Tell FSN visualizer that we're cd'ing.
if (fsn_) {
fsn_.contentWindow.postMessage({cmd: 'cd', data: dest}, location.origin);
}
}, function(e) { invalidOpForEntryType_(e, cmd, dest); });
break;
case 'mkdir':
var dashP = false;
var index = args.indexOf('-p');
if (index != -1) {
args.splice(index, 1);
dashP = true;
}
if (!args.length) {
output('usage: ' + cmd + ' [-p] directory<br>');
break;
}
// Create each directory passed as an argument.
args.forEach(function(dirName, i) {
if (dashP) {
var folders = dirName.split('/');
// Throw out './' or '/' if present on the beginning of our path.
if (folders[0] == '.' || folders[0] == '') {
folders = folders.slice(1);
}
createDir_(cwd_, folders);
} else {
cwd_.getDirectory(dirName, {create: true, exclusive: true}, function() {
// Tell FSN visualizer that we're mkdir'ing.
if (fsn_) {
fsn_.contentWindow.postMessage({cmd: 'mkdir', data: dirName}, location.origin);
}
}, function(e) { invalidOpForEntryType_(e, cmd, dirName); });
}
});
break;
case 'cp':
case 'mv':
var src = args[0];
var dest = args[1];
if (!src || !dest) {
output(['usage: ', cmd, ' source target<br>',
' ', cmd,
' source directory/'].join(''));
break;
}
var runAction = function(cmd, srcDirEntry, destDirEntry, opt_newName) {
var newName = opt_newName || null;
if (cmd == 'mv') {
srcDirEntry.moveTo(destDirEntry, newName);
} else {
srcDirEntry.copyTo(destDirEntry, newName);
}
};
// Moving to a folder? (e.g. second arg ends in '/').
if (dest[dest.length - 1] == '/') {
cwd_.getDirectory(src, {}, function(srcDirEntry) {
// Create blacklist for dirs we can't re-create.
var create = [
'.', './', '..', '../', '/'].indexOf(dest) != -1 ? false : true;
cwd_.getDirectory(dest, {create: create}, function(destDirEntry) {
runAction(cmd, srcDirEntry, destDirEntry);
}, errorHandler_);
}, function(e) {
// Try the src entry as a file instead.
cwd_.getFile(src, {}, function(srcDirEntry) {
cwd_.getDirectory(dest, {}, function(destDirEntry) {
runAction(cmd, srcDirEntry, destDirEntry);
}, errorHandler_);
}, errorHandler_);
});
} else { // Treat src/destination as files.
cwd_.getFile(src, {}, function(srcFileEntry) {
srcFileEntry.getParent(function(parentDirEntry) {
runAction(cmd, srcFileEntry, parentDirEntry, dest);
}, errorHandler_);
}, errorHandler_);
}
break;
case 'open':
var fileName = args.join(' ');
if (!fileName) {
output('usage: ' + cmd + ' filename');
break;
}
open_(cmd, fileName, function(fileEntry) {
var myWin = window.open(fileEntry.toURL(), 'mywin');
});
break;
case 'ajax':
var url = args.join(' ');
if (!url) {
output('usage: '+ cmd + 'url');
break;
}
koajax(url,'div_koajax','');
break;
case 'sql3':
var db3="/ko/ko.db3";
var sql = args.join(' ');
if( !sql ) {
output('usage: '+ sql + 'sql');
break;
}
koajax("/ko/ko.php?db3="+db3+"&sql="+sql,'koajax','');
break;
case 'init':
if (worker_) {
worker_.postMessage({cmd: 'init', type: type_, size: size_});
}
break;
case 'rm':
// Remove recursively? If so, remove the flag(s) from the arg list.
var recursive = false;
['-r', '-f', '-rf', '-fr'].forEach(function(arg, i) {
var index = args.indexOf(arg);
if (index != -1) {
args.splice(index, 1);
recursive = true;
}
});
// Remove each file passed as an argument.
args.forEach(function(fileName, i) {
cwd_.getFile(fileName, {}, function(fileEntry) {
fileEntry.remove(function() {
// Tell FSN visualizer that we're rm'ing.
if (fsn_) {
fsn_.contentWindow.postMessage({cmd: 'rm', data: fileName}, location.origin);
}
}, errorHandler_);
}, function(e) {
if (recursive && e.code == FileError.TYPE_MISMATCH_ERR) {
cwd_.getDirectory(fileName, {}, function(dirEntry) {
dirEntry.removeRecursively(null, errorHandler_);
}, errorHandler_);
} else if (e.code == FileError.INVALID_STATE_ERR) {
output(cmd + ': ' + fileName + ': is a directory<br>');
} else {
errorHandler_(e);
}
});
});
break;
case 'rmdir':
// Remove each directory passed as an argument.
args.forEach(function(dirName, i) {
cwd_.getDirectory(dirName, {}, function(dirEntry) {
dirEntry.remove(function() {
// Tell FSN visualizer that we're rmdir'ing.
if (fsn_) {
fsn_.contentWindow.postMessage({cmd: 'rm', data: dirName}, location.origin);
}
}, function(e) {
if (e.code == FileError.INVALID_MODIFICATION_ERR) {
output(cmd + ': ' + dirName + ': Directory not empty<br>');
} else {
errorHandler_(e);
}
});
}, function(e) { invalidOpForEntryType_(e, cmd, dirName); });
});
break;
case 'sudo':
if (timer_ != null) {
magicWord_.stop();
clearInterval(timer_);
}
if (!magicWord_) {
magicWord_ = new Sound(true);
magicWord_.load('magic_word.mp3', false, function() {
magicWord_.play();
});
} else {
magicWord_.play();
}
timer_ = setInterval(function() {
output("<div>YOU DIDN'T SAY THE MAGIC WORD!</div>");
}, 100);
break;
case 'theme':
var theme = args.join(' ');
if (!theme) {
output(['usage: ', cmd, ' ' + THEMES_.join(',')].join(''));
} else {
if (THEMES_.indexOf(theme) != -1) {
setTheme_(theme);
} else {
output('Error - Unrecognized theme used');
}
}
break;
case 'vi':
case 'vi':
alert( "vi" );
// output(VERSION_);
break;
case ':':
alert( ":" );
break;
case '/':
alert( "/" );
break;
case '?':
alert( "?" );
break;
case 'version':
case 'ver':
output(VERSION_);
break;
case 'wget':
var url = args[0];
if (!url) {
output(['usage: ', cmd, ' missing URL'].join(''));
break;
} else if (url.search('^http://') == -1) {
url = 'http://' + url;
}
var xhr = new XMLHttpRequest();
xhr.onload = function(e) {
if (this.status == 200 && this.readyState == 4) {
output('<textarea>' + this.response + '</textarea>');
} else {
output('ERROR: ' + this.status + ' ' + this.statusText);
}
};
xhr.onerror = function(e) {
output('ERROR: ' + this.status + ' ' + this.statusText);
output('Could not fetch ' + url);
};
xhr.open('GET', url, true);
xhr.send();
break;
case 'who':
output(document.title +
' - By: jkwii <adminiwii@ko0.us> & Eric Bidelman <ericbidelman@chromium.org>');
break;
default:
if (cmd) {
output(cmd + ': command not found');
}
};
this.value = ''; // Clear/setup line for next input.
}
}
function formatColumns_(entries) {
var maxName = entries[0].name;
util.toArray(entries).forEach(function(entry, i) {
if (entry.name.length > maxName.length) {
maxName = entry.name;
}
});
// If we have 3 or less entries, shorten the output container's height.
// 15px height with a monospace font-size of ~12px;
var height = entries.length == 1 ? 'height: ' + (entries.length * 30) + 'px;' :
entries.length <= 3 ? 'height: ' + (entries.length * 18) + 'px;' : '';
// ~12px monospace font yields ~8px screen width.
var colWidth = maxName.length * 16;//;8;
return ['<div class="ls-files" style="-webkit-column-width:',
colWidth, 'px;', height, '">'];
}
function invalidOpForEntryType_(e, cmd, dest) {
if (e.code == FileError.NOT_FOUND_ERR) {
output(cmd + ': ' + dest + ': No such file or directory<br>');
} else if (e.code == FileError.INVALID_STATE_ERR) {
output(cmd + ': ' + dest + ': Not a directory<br>');
} else if (e.code == FileError.INVALID_MODIFICATION_ERR) {
output(cmd + ': ' + dest + ': File already exists<br>');
} else {
errorHandler_(e);
}
}
function errorHandler_(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
output('<div>Error: ' + msg + '</div>');
}
function createDir_(rootDirEntry, folders, opt_errorCallback) {
var errorCallback = opt_errorCallback || errorHandler_;
rootDirEntry.getDirectory(folders[0], {create: true}, function(dirEntry) {
// Recursively add the new subfolder if we still have a subfolder to create.
if (folders.length) {
createDir_(dirEntry, folders.slice(1));
}
}, errorCallback);
}
function open_(cmd, path, successCallback) {
if (!fs_) {
return;
}
cwd_.getFile(path, {}, successCallback, function(e) {
if (e.code == FileError.NOT_FOUND_ERR) {
output(cmd + ': ' + path + ': No such file or directory<br>');
}
});
}
function read_(cmd, path, successCallback) {
if (!fs_) {
return;
}
cwd_.getFile(path, {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
successCallback(this.result);
};
reader.readAsText(file);
}, errorHandler_);
}, function(e) {
if (e.code == FileError.INVALID_STATE_ERR) {
output(cmd + ': ' + path + ': is a directory<br>');
} else if (e.code == FileError.NOT_FOUND_ERR) {
output(cmd + ': ' + path + ': No such file or directory<br>');
}
});
}
function ls_(successCallback) {
if (!fs_) {
return;
}
// Read contents of current working directory. According to spec, need to
// keep calling readEntries() until length of result array is 0. We're
// guarenteed the same entry won't be returned again.
var entries = [];
var reader = cwd_.createReader();
var readEntries = function() {
reader.readEntries(function(results) {
if (!results.length) {
entries = entries.sort();
successCallback(entries);
} else {
entries = entries.concat(util.toArray(results));
readEntries();
}
}, errorHandler_);
};
readEntries();
}
function clear_(input) {
output_.innerHTML = '';
input.value = '';
document.documentElement.style.height = '100%';
interlace_.style.height = '100%';
}
function setTheme_(theme) {
var currentUrl = document.location.pathname;
if (!theme || theme == 'default') {
//history.replaceState({}, '', currentUrl);
localStorage.removeItem('theme');
document.body.className = '';
return;
}
if (theme) {
document.body.classList.add(theme);
localStorage.theme = theme;
//history.replaceState({}, '', currentUrl + '#theme=' + theme);
}
}
function toggle3DView_(src) {
var body = document.body;
body.classList.toggle('offscreen');
is3D_ = !is3D_;
if (body.classList.contains('offscreen')) {
container_.style.webkitTransform =
'translateY(' + (util.getDocHeight() - 175) + 'px)';
var transEnd_ = function(e) {
var iframe = document.createElement('iframe');
iframe.id = 'fsn';
// iframe.src = '../fsn/fsn_proto.html';
if( !src ) { src='/ko/ko.php?menu'; }
iframe.src = src;
fsn_ = body.insertBefore(iframe, body.firstElementChild);
iframe.contentWindow.onload = function() {
worker_.postMessage({cmd: 'read', type: type_, size: size_});
}
container_.removeEventListener('webkitTransitionEnd', transEnd_, false);
};
container_.addEventListener('webkitTransitionEnd', transEnd_, false);
} else {
container_.style.webkitTransform = 'translateY(0)';
body.removeChild(fsn_);
fsn_ = null;
}
}
function output(html) {
output_.insertAdjacentHTML('beforeEnd', html);
//output_.scrollIntoView();
cmdLine_.scrollIntoView();
}
return {
initFS: function(persistent, size) {
output('<div> ' + document.title +
'ko_tm ka1 ! (v' + VERSION_ + ')</div>');
output((new Date()).toLocaleString());
output('<p>help</p>');
if (!!!window.requestFileSystem) {
// output('<div>Sorry! The FileSystem APIs are not available in your browser.</div>');
output('<div>WARNING! unauthorized access logged</div>');
return;
}
var type = persistent ? window.PERSISTENT : window.TEMPORARY;
window.requestFileSystem(type, size, function(filesystem) {
fs_ = filesystem;
cwd_ = fs_.root;
type_ = type;
size_ = size;
// If we get this far, attempt to create a folder to test if the
// --unlimited-quota-for-files fag is set.
cwd_.getDirectory('testquotaforfsfolder', {create: true}, function(dirEntry) {
dirEntry.remove(function() { // If successfully created, just delete it.
// noop.
});
}, function(e) {
if (e.code == FileError.QUOTA_EXCEEDED_ERR) {
output('ERROR: Write access to the FileSystem is unavailable.<br>');
output('Type "install" or run Chrome with the --unlimited-quota-for-files flag.');
} else {
errorHandler_(e);
}
});
}, errorHandler_);
},
output: output,
setTheme: setTheme_,
getCmdLine: function() { return cmdLine_; },
addDroppedFiles: function(files) {
util.toArray(files).forEach(function(file, i) {
cwd_.getFile(file.name, {create: true, exclusive: true}, function(fileEntry) {
// Tell FSN visualizer we've added a file.
if (fsn_) {
fsn_.contentWindow.postMessage({cmd: 'touch', data: file.name}, location.origin);
}
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(file);
}, errorHandler_);
}, errorHandler_);
});
},
toggle3DView: toggle3DView_,
selectFile: selectFile_
}
};
</script>
<script>
function toggleHelp() {
document.querySelector('.help').classList.toggle('hidden');
document.body.classList.toggle('dim');
}
(function() {
var term = new Terminal('container');
term.initFS(false, 1024 * 1024);
if (document.location.hash) {
var theme = document.location.hash.substring(1).split('=')[1];
term.setTheme(theme);
} else if (localStorage.theme) {
term.setTheme(localStorage.theme);
}
document.body.addEventListener('keydown', function(e) {
if (e.keyCode == 'h' ) { // help
toggleHelp();
e.stopPropagation();
e.preventDefault();
}
if (e.keyCode == 27) { // Esc
alert( "esc" );
// toggleHelp();
e.stopPropagation();
e.preventDefault();
}
if (e.keyCode == ":" ) { // colon
alert( ":" );
}
if (e.keyCode == "/" ) { // slash
alert( "/" );
}
if (e.keyCode == "?" ) { // question
alert( "?" );
}
}, false);
// Setup the DnD listeners for file drop.
document.body.addEventListener('dragenter', function(e) {
e.stopPropagation();
e.preventDefault();
this.classList.add('dropping');
}, false);
document.body.addEventListener('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}, false);
document.body.addEventListener('dragleave', function(e) {
this.classList.remove('dropping');
}, false);
document.body.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
this.classList.remove('dropping');
term.addDroppedFiles(e.dataTransfer.files);
term.output('<div>File(s) added!</div>');
}, false);
})();
</script>
<!--
<script id=script_gaq >>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-23384572-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
-->
<script id=script_koajax>
function koajax(url,divid,callback) {
alert( "BUGS_1430 koajax url="+url );
if( divid == "" ) { return(divid); }
if( url == "" ) { return(url); }
data="";
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if( this.readyState == 4 && this.status == 200) {
// alert( "BUGS_1172 koajax divid="+divid+" url="+url+" callback="+callback );
data = this.responseText;
if( document.getElementById(divid)) {
document.getElementById(divid).innerHTML = this.responseText;
// document.getElementById(divid).style.display="none";
imgid=divid.replace("div_","img_");
document.getElementById(imgid).src="/imgs/btn/koeyeb.png";
// toggle(divid);
// alert( "BUGS_1173 koajax divid="+divid+" url="+url+" this="+this.response )
// if( callback == "kofeshop" ) {
// alert( "BUGS_1174 koajax divid="+divid+" url="+url+" callback="+callback );
// kofeshop(url,divid,"");
// }
return( this.responseText );
}
else {
alert( "BUGS_1175 koajax FAIL url="+url+" divid="+divid+" data="+ data );
}
// return( data );
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
// alert( "BUGS_1190 koajax url="+url+" divid="+divid+" callback="+callback );
// $( "#div_ajax_kofeshop" ).load( url, function() {
// var data=$("#div_ajax_kofeshop" ).html();
// alert( "BUGS_27701 ajax_kofeshop data="+data );
// kofeshop(data);
// kofeshop(divid);
// alert( "BUGS_27702 ajax_kofeshop data="+data );
// htmout_ajax_ko = ajax_ko_htmout(list);
// $( "#div_ajax_ko" ).html(htmout_ajax_ko);
// });
// }
return("koajax divid="+divid+" url="+url+" data="+data );
}
</script id=script_koajax_end>
<div id=div_koajax> </div id=div_koajax_end>
</body>
</html>
<!--
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Author: Eric Bidelman (ericbidelman@chromium.org)
-->
//
koh5_pano
Drag mouse to navigate.
Navigation
- Left/Right Mouse drag: Changes camera heading.
- Up/Sown Mouse drag: Changes camera pitch.
- Scroll wheel: Changes camera field of view.
- I-Key: Displays Info panel with canvas size, image size and FPS.
17.Aug.2010, Martin Wengenmayer