# smd_lib 0.23 # Shared function library used by smd_ plugins and others. # Stef Dawson # http://stefdawson.com/ # ..................................................................... # This is a plugin for Textpattern - http://textpattern.com/ # To install: textpattern > admin > plugins # Paste the following text into the 'Install plugin' box: # ..................................................................... YTo5OntzOjQ6Im5hbWUiO3M6Nzoic21kX2xpYiI7czo2OiJhdXRob3IiO3M6MTE6IlN0ZWYgRGF3c29uIjtzOjEwOiJhdXRob3JfdXJpIjtzOjIyOiJodHRwOi8vc3RlZmRhd3Nvbi5jb20vIjtzOjc6InZlcnNpb24iO3M6NDoiMC4yMyI7czoxMToiZGVzY3JpcHRpb24iO3M6NTY6IlNoYXJlZCBmdW5jdGlvbiBsaWJyYXJ5IHVzZWQgYnkgc21kXyBwbHVnaW5zIGFuZCBvdGhlcnMuIjtzOjQ6ImhlbHAiO3M6Njk1MDoiCTxoMT5zbWRfIHBsdWdpbiBsaWJyYXJ5PC9oMT4NCg0KCTxwPk9mZmVycyBubyBwdWJsaWMgdGV4dHBhdHRlcm4gdGFncy4gSXQgaXMgc2ltcGx5IGEgc2hhcmVkIGxpYnJhcnkgb2YgY29tbW9uIGZ1bmN0aW9ucyB1c2VkIGJ5IHNtZF8gcGx1Z2lucy48L3A+DQoNCjxoMT5zbWRfIHBsdWdpbiBsaWJyYXJ5PC9oMT4NCg0KPHA+T2ZmZXJzIG5vIHB1YmxpYyB0ZXh0cGF0dGVybiB0YWdzLiBJdCBpcyBzaW1wbHkgYSBzaGFyZWQgbGlicmFyeSBvZiBjb21tb24gZnVuY3Rpb25zIHVzZWQgYnkgc21kXyBwbHVnaW5zLjwvcD4NCjxoMj5DaGFuZ2Vsb2c8L2gyPg0KDQo8dWw+DQo8bGk+djAuMSAgIDA3LTAyLTI1IEluaXRpYWwgcHVibGljIHJlbGVhc2U8L2xpPg0KPGxpPnYwLjIgICAwNy0wMy0wMyBBZGRlZCA8c3BhbiBjbGFzcz0iY2FwcyI+TUxQPC9zcGFuPiAoTXVsdGktTGluZ3VhbCBQYWNrKSBsaWJyYXJ5IHN1cHBvcnQ8L2xpPg0KPGxpPnYwLjIxICAwNy0wMy0wNiBBZGRlZCBpbnRlZ2VyIHJhbmdlIGZ1bmN0aW9uYWxpdHkuIGdldEF0dHMgbm93IHRha2VzIGEgcmVnZXhwIGFyZy48L2xpPg0KPGxpPnYwLjIxYSAwNy0wMy0yMSBGaXhlZDogQ2hhcmFjdGVyIHJhbmdlcyBpZ25vcmVkICh0aGFua3MgbXJkYWxlKTwvbGk+DQo8bGk+djAuMjFiIDA3LTA0LTAyIEZpeGVkOiBTdGlja3kgYXJ0aWNsZSBzdXBwb3J0IGluIGdldEF0dHMgKHRoYW5rcyBwaWVtYW4pPC9saT4NCjxsaT52MC4yMWMgMDctMDctMjkgRml4ZWQ6IE51bWVyaWMgcmFuZ2VzIGluIGNhdGVnb3JpZXMgKHRoYW5rcyB3b2xsZSk8L2xpPg0KPGxpPnYwLjIxZCAwNy0wOC0wMyBGaXhlZDogTmVnYXRpb24gd2l0aCBtdWx0aXBsZSBlbGVtZW50czwvbGk+DQo8bGk+djAuMjIgIDA3LTAzLTIxIEFkZGVkIGdlbmVyaWMgPHNwYW4gY2xhc3M9ImNhcHMiPk1MUDwvc3Bhbj4gY2xhc3MuPC9saT4NCjxsaT52MC4yMyAgMDctMDMtMjUgQWRkZWQgdGhlIEZ1enp5RmluZCBjbGFzcyBhbmQgZ2V0V29yZCBmdW5jdGlvbi4gZ2V0QXR0cygpIG5vdyBhbGxvd3MgJiM4MjE2Oz9xJiM4MjE3OzwvbGk+DQo8L3VsPg0KDQoJPHA+PGgyPkZ1bmN0aW9uIFJlZmVyZW5jZTwvaDI+PGJyIC8+DQo8Yj5zbWRfYWRkUVNWYXI8L2I+PGJyIC8+DQoNCjxiPnNtZF9yZW1vdmVRU1ZhcjwvYj48YnIgLz4NCjxwPkFkZCBvciByZW1vdmUgYSBxdWVyeSBzdHJpbmcgdmFyaWFibGUgdG8gdGhlIGdpdmVuIDxzcGFuIGNsYXNzPSJjYXBzIj5VUkw8L3NwYW4+LCB0YWtpbmcgaW50byBhY2NvdW50IGFueSBleGlzdGluZyB2YXJpYWJsZXMgdGhhdCBtYXkgYmUgaW4gdGhlIDxzcGFuIGNsYXNzPSJjYXBzIj5VUkw8L3NwYW4+IGFscmVhZHkuICYjODIxNjtBZGQmIzgyMTc7IHRha2VzIHRocmVlIGFyZ3VtZW50cywgJiM4MjE2O1JlbW92ZSYjODIxNzsganVzdCB0YWtlcyB0aGUgZmlyc3QgdHdvOjwvcD48YnIgLz4NCjxvbD48YnIgLz4NCjxsaT5UaGUgPHNwYW4gY2xhc3M9ImNhcHMiPlVSTDwvc3Bhbj4gc3RyaW5nIHRvIGFkZCB0by9yZW1vdmUgZnJvbTwvbGk+PGJyIC8+DQo8bGk+VGhlIGlkIG9mIHRoZSBxdWVyeXN0cmluZyAodGhlIGJpdCBiZWZvcmUgdGhlID0gc2lnbik8L2xpPjxiciAvPg0KPGxpPlRoZSB2YWx1ZSBvZiB0aGUgbmV3IHF1ZXJ5c3RyaW5nICh0aGUgYml0IGFmdGVyIHRoZSA9IHNpZ24pPC9saT48YnIgLz4NCjwvb2w+PGJyIC8+DQo8cD5lLmcuIDxjb2RlPnNtZF9hZGRRU1ZhcigkdGhpc2FydGljbGVbJiMzOTt1cmxfdGl0bGUmIzM5O10sICYjMzk7dHBnJiMzOTssIDE1KTs8L2NvZGU+IHdvdWxkIGFkZCA8Y29kZT50cGc9MTU8L2NvZGU+IHRvIHRoZSBjdXJyZW50IGFydGljbGUmIzgyMTc7cyA8c3BhbiBjbGFzcz0iY2FwcyI+VVJMPC9zcGFuPi4gSWYgdGhlcmUgYXJlIG5vIG90aGVyIHZhcmlhYmxlcyBjdXJyZW50bHkgaW4gdGhlIDxzcGFuIGNsYXNzPSJjYXBzIj5VUkw8L3NwYW4+LCBpdCBpcyBhZGRlZCB3aXRoIGEgcXVlc3Rpb24tbWFyaywgb3RoZXJ3aXNlIGl0IGlzIGFwcGVuZGVkIHdpdGggYW4gYW1wZXJzYW5kLjwvcD48L3A+DQoNCgk8cD48Yj5zbWRfZ2V0QXR0czwvYj48YnIgLz4NCjxwPlNlYXJjaGVzIHRoZSBwYXNzZWQgc3RyaW5nIGZvciBwcmVkZXRlcm1pbmVkIHNlcXVlbmNlcyBvZiBjaGFyYWN0ZXJzIGFuZCwgaWYgdGhhdCBzZXF1ZW5jZSBpcyBpbiB0aGUgZ2l2ZW4gJGFsbG93ZWQgYXJyYXksIHJlcGxhY2VzIGl0IGFzIGZvbGxvd3M6PC9wPjxiciAvPg0KPHVsPjxiciAvPg0KPGxpPj9jID0gY3VycmVudCBnbG9iYWwgY2F0ZWdvcnkgKCFjID0gbm90IGN1cnJlbnQgY2F0ZWdvcnkpPC9saT48YnIgLz4NCjxsaT4/cyA9IGN1cnJlbnQgc2VjdGlvbiAoIXMgPSBub3QgY3VycmVudCBzZWN0aW9uKTwvbGk+PGJyIC8+DQo8bGk+P3QgPSBjdXJyZW50IGFydGljbGUgdGl0bGUgKCF0ID0gbm90IGN1cnJlbnQgdGl0bGUpPC9saT48YnIgLz4NCjxsaT4/aWQgPSBjdXJyZW50IGFydGljbGUgSUQsIHByZXBlbmRlZCB3aXRoICRpZHByZWZpeCAoIWlkID0gbm90IGN1cnJlbnQgSUQpPC9saT48YnIgLz4NCjxsaT4/cSA9IGN1cnJlbnQgcXVlcnkgdGVybSAoIXEgPSBub3QgY3VycmVudCBxdWVyeSB0ZXJtKTwvbGk+PGJyIC8+DQo8bGk+P2ZpZWxkID0gY29udGVudHMgb2YgdGhlIGN1cnJlbnQgYXJ0aWNsZSYjODIxNztzIGZpZWxkIChjb3VsZCBiZSBhIGNvbW1hLXNlcGFyYXRlZCBsaXN0KTwvbGk+PGJyIC8+DQo8bGk+IWZpZWxkID0gbm90IHRoZSBjb250ZW50cyBvZiB0aGUgY3VycmVudCBhcnRpY2xlJiM4MjE3O3MgZmllbGQgKGNvdWxkIGJlIGEgY29tbWEtc2VwYXJhdGVkIGxpc3QpPC9saT48YnIgLz4NCjwvdWw+PGJyIC8+DQo8cD5JbnRlZ2VyIHJhbmdlcyAoZS5nLiAxLTUpIHdpbGwgYmUgZXhwYW5kZWQgaW50byB0aGVpciBpbmRpdmlkdWFsIHZhbHVlczsgYW55dGhpbmcgZWxzZSBpcyByZXR1cm5lZCB2ZXJiYXRpbS4gSXQgb3V0cHV0cyB0d28gYXJyYXlzOyB0aGUgMXN0IGNvbnRhaW5pbmcgaXRlbXMgZm9yIGluY2x1c2lvbiwgdGhlIDJuZCBjb250YWlucyBpdGVtcyBmb3IgZXhjbHVzaW9uLjwvcD48L3A+DQoNCgk8cD48Yj5zbWRfc3BsaXRSYW5nZTwvYj48YnIgLz4NCjxwPlJldHVybiBhbiBhcnJheSBvZiBpdGVtcyBmcm9tIGEgc3RyaW5nIG9mICh1c3VhbGx5KSBjb21tYS1zZXBhcmF0ZWQgdmFsdWVzLiBJZiBhbnkgdmFsdWVzIGNvbnRhaW4gcmFuZ2VzIG9mIG51bWJlcnMgbGlrZSAxLTUgdGhhdCBuZWVkICYjODIxNjtleHBhbmRpbmcmIzgyMTc7IGZpcnN0LCB0aGV5IGFyZSBkZWFsdCB3aXRoLiBUYWtlcyBvbmUgbWFuZGF0b3J5IGFuZCBvbmUgb3B0aW9uYWwgYXJndW1lbnQ6PC9wPjxiciAvPg0KPG9sPjxiciAvPg0KPGxpPlRoZSBzdHJpbmcgdG8gc3BsaXQgdXA8L2xpPjxiciAvPg0KPGxpPlRoZSByZWd1bGFyIGV4cHJlc3Npb24gY2hhcmFjdGVyIGNsYXNzZXMgdG8gbWF0Y2guIEVhY2ggaXRlbSBpbiB0aGlzIHN0cmluZyBpcyB0cmVhdGVkIGFzIGFuIGVudGl0eSBhbmQgaXMgZmFpciBnYW1lIGZvciBzcGxpdHRpbmcgdGhlIHN0cmluZyBhdC4gRGVmYXVsdHMgdG8gJiM4MjIwO1xzLCYjODIyMTsgd2hpY2ggaXMgYSAmIzgyMTY7c3BhY2UmIzgyMTc7IGNoYXJhY3RlciBvciBjb21tYS48L2xpPjxiciAvPg0KPC9vbD48L3A+DQoNCgk8cD48Yj5zbWRfTUxQPC9iPjxiciAvPg0KPHA+SW5zdGFudGlhdGUgb25lIG9mIHRoZXNlIHRvIGhhbmRsZSA8c3BhbiBjbGFzcz0iY2FwcyI+TUxQPC9zcGFuPiBpbiB5b3VyIHBsdWdpbiBsaWtlIHRoaXM6PGJyIC8+DQo8b2w+PGJyIC8+DQo8bGk+RGVjbGFyZSBhIHVuaXF1ZSBnbG9iYWwgdmFyaWFibGUsIGUuZy4gZ2xvYmFsICRteVBsdWc8L2xpPjxiciAvPg0KPGxpPkRlZmluZSB5b3VyIGRlZmF1bHQgc3RyaW5nIHJlcGxhY2VtZW50IGFycmF5IChkb2VzbiYjODIxNzt0IG5lZWQgdG8gYmUgZ2xvYmFsKSwgZS5nOjxiciAvPg0KDQogICAgJG15U3RyaW5ncyA9IGFycmF5ICgmIzgyMTY7bXNnMSYjODIxNzsgPT4gJiM4MjE2O1RoaXMgaXMgbWVzc2FnZSAxJiM4MjE3OywgJiM4MjE2O21zZzImIzgyMTc7ID0+ICYjODIxNjtUaGlzIGlzIG1lc3NhZ2UgMiYjODIxNzspOzwvbGk+PGJyIC8+DQo8bGk+Q3JlYXRlIGFuIDxzcGFuIGNsYXNzPSJjYXBzIj5NTFA8L3NwYW4+IGhhbmRsZXI6PC9iciAvPg0KICAgICRteVBsdWcgPSBuZXcgc21kX01MUCgmIzgyMTY7cGx1Z2luX25hbWUmIzgyMTc7LCAmIzgyMTY7cGx1Z2luX3ByZWZpeCYjODIxNzssICRteVN0cmluZ3MpOzwvbGk+PGJyIC8+DQo8bGk+VGhhdCYjODIxNztzIGl0ISBUaGVyZSBhcmUgdHdvIG9wdGlvbmFsIGFyZ3MgdG8gc21kX01MUDo8YnIgLz4NCg0KICAgICBhKSB0aGUgZGVmYXVsdCAoZnVsbCkgbGFuZ3VhZ2UgdG8gdXNlLCBlLmcgJiM4MjE2O2RhLWRrJiM4MjE3Oy4gRGVmYXVsdHMgdG8gJiM4MjE2O2VuLWdiJiM4MjE3Oy48YnIgLz4NCg0KICAgICBiKSB0aGUgaW50ZXJmYWNlIHRoZSBzdHJpbmdzIGFyZSBmb3IuIENob29zZSBmcm9tICYjODIxNjtwdWJsaWMmIzgyMTc7ICh0aGUgZGVmYXVsdCksICYjODIxNjthZG1pbiYjODIxNzsgb3IgJiM4MjE2O2NvbW1vbiYjODIxNzs8L2xpPjxiciAvPg0KPGxpPlRvIHVzZSBhIHJlcGxhY2VtZW50IHN0cmluZyBpbiB5b3VyIGNvZGU6PGJyIC8+DQoNCiAgICAgYSkgTWFrZSBzdXJlIHRvIGltcG9ydCB0aGUgdW5pcXVlIGdsb2JhbCB2YXJpYWJsZTogZS5nLiBnbG9iYWwgJG15UGx1Zzs8YnIgLz4NCg0KICAgICBiKSBDYWxsICRteVBsdWctPmdUeHQoJiM4MjE2O21lc3NhZ2VJRCYjODIxNzspOyBbIGUuZy4gJG15UGx1Zy0+Z1R4dCgmIzgyMTY7bXNnMSYjODIxNzspIF08YnIgLz4NCg0KICAgICBjKSBJZiB5b3Ugd2FudCB0byByZXBsYWNlIGFueSBhcmdzIGluIHlvdXIgbWVzc2FnZSBzdHJpbmcsIHBhc3MgYW4gYXNzb2NpYXRpdmUNCiAgICAgICAgIGFycmF5IGFzIHRoZSAybmQgYXJnIHRvIGdUeHQoKTwvbGk+PGJyIC8+DQo8L29sPjxiciAvPg0KPC9wPjwvcD4NCg0KCTxwPjxiPnNtZF9GdXp6eUZpbmQ8L2I+PGJyIC8+DQo8cD5BIDxzcGFuIGNsYXNzPSJjYXBzIj5QSFA8L3NwYW4+IGNsYXNzIGZvciBhcHByb3hpbWF0ZSBzdHJpbmcgc2VhcmNoaW5nIG9mIGxhcmdlIHRleHQgbWFzc2VzLCBhZGFwdGVkICgqY291Z2gqIGJvcnJvd2VkKSBmcm9tIGh0dHA6Ly9lbG9uZW4uaWtpLmZpL2NvZGUvbWlzYy1ub3Rlcy9hcHByLXNlYXJjaC1waHAvLiBJbnN0YW50aWF0ZSBvbmUgb2YgdGhlc2UgYW5kIHBhc3MgaXQgdGhlIHN0cmluZyBwYXR0ZXJuL3dvcmQgeW91IGFyZSBsb29raW5nIGZvciBhbmQgYSBudW1iZXIgaW5kaWF0aW5nIGhvdyBjbG9zZSB0aGF0IG1hdGNoIGhhcyB0byBiZSAodGhlIGFtb3VudCBvZiBlcnJvciB0b2xlcmFibGUpLiAwPWV4YWN0IG1hdGNoOyAxMD1wcmV0dHkgbXVjaCBldmVyeSBzdHJpbmcgaW4gdGhlIHdvcmxkLiBQcmFjdGljYWwgdmFsdWVzIGFyZSB1c3VhbGx5IDEgb3IgMiwgc29tZXRpbWVzIDMuPC9wPjxiciAvPg0KPHA+VXNhZ2UgZXhhbXBsZTo8L3A+PGJyIC8+DQo8cHJlPg0KICAkZmluZGVyID0gbmV3IHNtZF9GdXp6eUZpbmQoJHBhdHQsICRtYXhfZXJyKTsNCiAgaWYgKCRmaW5kZXItPnRvb19zaG9ydF9lcnIpDQogICAgJGVycm9yID0gJiM4MjIwO1VuYWJsZSB0byBzZWFyY2ggJiM4MjExOyB1c2UgbG9uZ2VyIHBhdHRlcm4gb3IgcmVkdWNlIGVycm9yIHRvbGVyYW5jZS4mIzgyMjE7OzwvcD4NCg0KICB3aGlsZSgkdGV4dCA9IGdldF9uZXh0X3BhZ2Vfb2ZfdGV4dCgpKSB7DQogICAgJG1hdGNoZXMgPSAkZmluZGVyLT5zZWFyY2goJHRleHQpOw0KICAgIHdoaWxlKGxpc3QoJGlkeCwkcm5nKSA9IGVhY2goJG1hdGNoZXMpKQ0KICAgICAgcHJpbnQgJiM4MjIwO01hdGNoIGZvdW5kIGVuZGluZyBhdCBwb3NpdGlvbiAkaWR4IHdpdGggYSBjbG9zZW5lc3Mgb2YgJHZhbFxuJiM4MjIxOzsNCiAgfQ0KPC9wcmU+DQo8cD5UaGUgY29kZSB1c2VzIGluaXRpYWwgZmlsdGVyaW5nIHRvIHNvcnQgb3V0IHBvc3NpYmxlIG1hdGNoIGNhbmRpZGF0ZXMgYW5kIHRoZW4gYXBwbGllcyBhIHNsb3dlciBjaGFyYWN0ZXItYnktY2hhcmFjdGVyIHNlYXJjaCAoc2VhcmNoX3Nob3J0KCkpIGFnYWluc3QgdGhlbS48L3A+DQoNCgk8cD48Yj5zbWRfZ2V0V29yZDwvYj48YnIgLz4NCjxwPlVzZWZ1bCB3aXRoIHNtZF9GdXp6eUZpbmQ6IGl0IHRha2VzIGEgc3RyaW5nIGFuZCBhbiBvZmZzZXQgaW50byB0aGF0IHN0cmluZyBhbmQgcmV0dXJucyB0aGUgbmVhcmVzdCAmIzgyMjA7d29yZCYjODIyMTsgYmVmb3JlIHRoYXQgb2Zmc2V0IHBvc2l0aW9uLjwvcD4gSWYgdGhlIG9mZnNldCBpcyBub3Qgc3VwcGxpZWQgaXQgc3RhcnRzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc3RyaW5nLCB0aHVzIHJldHVybmluZyB0aGUgZmlyc3Qgd29yZC48L3A+PC9wPg0KDQo8cD5UaGUgb3B0aW9uYWwgdGhpcmQgYXJndW1lbnQgaXMgYSBmdWxsIHJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJuIChpbmNsdWRpbmcgc3RhcnQgYW5kIGVuZCBzbGFzaGVzIGFuZCBzd2l0Y2hlcykgdGhhdCBkZXRlcm1pbmUgd2hhdCBhICYjODIxNjtjaGFyYWN0ZXImIzgyMTc7IGlzLiBBbnl0aGluZyB0aGF0IDxzdHJvbmc+ZG9lc24mIzgyMTc7dDwvc3Ryb25nPiBtYXRjaCBpcyB0cmVhdGVkIGFzIGEgd29yZCBkZWxpbWl0ZXIuIERlZmF1bHRzIHRvIGFueSAodW5pY29kZSkgbGV0dGVyIG9yIG51bWJlciBjaGFyYWN0ZXIuIE5vdGUgdGhhdCBhbHRob3VnaCBpdCB1c2VzIGEgdW5pY29kZSBwYXR0ZXJuIGJ5IGRlZmF1bHQsIGl0IHRyZWF0cyBjaGFycyBpbiB0aGUgc3RyaW5nIGFzIHNpbmdsZS1ieXRlIGVudGl0aWVzJiM4MjMwOyB0aGlzIHdpbGwgYmUgcmV2aXNpdGVkIHdoZW4gUEhQNiBiZWNvbWVzIGF2YWlsYWJsZSBvbiB3ZWJob3N0cy4gU28sIG1heWJlIGFyb3VuZCAyMDQyLjwvcD4iO3M6NDoiY29kZSI7czoxNzk5NDoiLy8gc21kTUxQIERFUFJFQ0FURUQ6IHVzZSBzbWRfTUxQIGNsYXNzIGluc3RlYWQNCmdsb2JhbCAkc21kTUxQOw0KJHNtZE1MUCA9IGFycmF5KA0KCQknc21kX3NsaW1ib3gnID0+ICdzbWRfc2JveCcsDQoJCSdzbWRfc2xpbWJveF9pbmMnID0+ICdzbWRfc2JveCcsDQoJCSdzbWRfcmFuZG9tX2Jhbm5lcicgPT4gJ3NtZF9yYmFuJywNCik7DQpjbGFzcyBzbWRfRnV6enlGaW5kIHsNCgkvLyBUaGUgbGFzdCAzIHBhcmFtZXRlcnMgYXJlIGZvciBvcHRpbWl6YXRpb24gb25seSwgdG8gYXZvaWQgdGhlDQoJLy8gc3VycHJpc2luZ2x5IHNsb3cgc3RybGVuKCkgYW5kIHN1YnN0cigpIGNhbGxzOg0KCS8vICAtICRzdGFydF9pbmRleCA9IGZyb20gd2hpY2ggY2hhcmFjdGVyIG9mICR0ZXh0IHRvIHN0YXJ0IHRoZSBzZWFyY2gNCgkvLyAgLSAkbWF4X2xlbiA9IG1heGltdW0gY2hhcmFjdGVyIHRvIHNlYXJjaCAoc3RhcnRpbmcgZnJvbSAkc3RhcnRfaW5kZXgpDQoJLy8gIC0gJHRleHRfc3RybGVuID0NCgkvLyBUaGUgcmV0dXJuIHZhbHVlIGlzIGFuIGFycmF5IG9mIG1hdGNoZXM6DQoJLy8gICBBcnJheSggWzxtYXRjaC1lbmQtaW5kZXg+XSA9PiA8ZXJyb3I+LCAuLi4gKQ0KCS8vIE5vdGU6IDxlcnJvcj4gaXMgZ2VuZXJhbGx5IE5PVCBhbiBleGFjdCBlZGl0IGRpc3RhbmNlIGJ1dCByYXRoZXIgYQ0KCS8vIGxvd2VyIGJvdW5kLiBUaGlzIGlzIHVuZm9ydHVuYXRlIGJ1dCB0aGUgcm91dGluZSB3b3VsZCBiZSBzbG93ZXIgaWYNCgkvLyB0aGUgZXhhY3QgZXJyb3Igd2FzIGNhbGN1bGF0ZSBhbG9uZyB3aXRoIHRoZSBtYXRjaGVzLg0KCS8vIFRoZSBmdW5jdGlvbiBpcyBiYXNlZCBvbiB0aGUgbm9uLWRldGVybWluaXN0aWMgYXV0b21hdG9uIHNpbXVsYXRpb24NCgkvLyBhbGdvcml0aG0gKHdpdGhvdXQgYml0IHBhcmFsbGVsaXNtIG9wdGltaXphdGlvbnMpLg0KCWZ1bmN0aW9uIHNlYXJjaF9zaG9ydCgkcGF0dCwgJGssICR0ZXh0LCAkc3RhcnRfaW5kZXg9MCwgJG1heF9sZW49LTEsICR0ZXh0X3N0cmxlbj0tMSkgew0KCQlpZiAoICR0ZXh0X3N0cmxlbiA8IDAgKQ0KCQkJJHRleHRfc3RybGVuID0gc3RybGVuKCAkdGV4dCApOw0KDQoJCWlmICggJG1heF9sZW4gPCAwICkNCgkJCSRtYXhfbGVuID0gJHRleHRfc3RybGVuOw0KDQoJCSRzdGFydF9pbmRleCA9IG1heCggMCwgJHN0YXJ0X2luZGV4ICk7DQoJCSRuID0gbWluKCAkbWF4X2xlbiwgJHRleHRfc3RybGVuLSRzdGFydF9pbmRleCApOw0KCQkkbSA9IHN0cmxlbiggJHBhdHQgKTsNCgkJJGVuZF9pbmRleCA9ICRzdGFydF9pbmRleCArICRuOw0KDQoJCS8vIElmICR0ZXh0IGlzIHNob3J0ZXIgdGhhbiAkcGF0dCwgdXNlIHRoZSBidWlsdC1pbg0KCQkvLyBsZXZlbnNodGVpbigpIGluc3RlYWQ6DQoJCWlmICgkbiA8ICRtKQ0KCQl7DQoJCQkkbGV2ID0gbGV2ZW5zaHRlaW4oc3Vic3RyKCR0ZXh0LCAkc3RhcnRfaW5kZXgsICRuKSwgJHBhdHQpOw0KCQkJaWYgKCAkbGV2IDw9ICRrICkNCgkJCQlyZXR1cm4gQXJyYXkoICRzdGFydF9pbmRleCskbi0xID0+ICRsZXYgKTsNCgkJCWVsc2UNCgkJCQlyZXR1cm4gQXJyYXkoKTsNCgkJfQ0KDQoJCSRzID0gQXJyYXkoKTsNCgkJZm9yICgkaT0wOyAkaTwkbTsgJGkrKykNCgkJew0KCQkJJGMgPSAkcGF0dHskaX07DQoJCQlpZiAoIGlzc2V0KCRzWyRjXSkpDQoJCQkJJHNbJGNdID0gbWluKCRpLCAkc1skY10pOw0KCQkJZWxzZQ0KCQkJCSRzWyRjXSA9ICRpOw0KCQl9DQoNCgkJaWYgKCAkZW5kX2luZGV4IDwgJHN0YXJ0X2luZGV4ICkNCgkJCXJldHVybiBBcnJheSgpOw0KDQoJCSRtYXRjaGVzID0gQXJyYXkoKTsNCgkJJGRhID0gJGRiID0gcmFuZ2UoMCwgJG0tJGsrMSk7DQoNCgkJJG1rID0gJG0tJGs7DQoNCgkJZm9yICgkdD0kc3RhcnRfaW5kZXg7ICR0PCRlbmRfaW5kZXg7ICR0KyspDQoJCXsNCgkJCSRjID0gJHRleHR7JHR9Ow0KCQkJJGluX3BhdHQgPSBpc3NldCgkc1skY10pOw0KDQoJCQlpZiAoJHQmMSkgeyAkZD0mJGRhOyAkZT0mJGRiOyB9DQoJCQllbHNlIHsgJGQ9JiRkYjsgJGU9JiRkYTsgfQ0KDQoJCQlmb3IgKCRpPTE7ICRpPD0kbWs7ICRpKyspDQoJCQl7DQoJCQkJJGcgPSBtaW4oICRrKzEsICRlWyRpXSsxLCAkZVskaSsxXSsxICk7DQoNCgkJCQkvLyBUT0RPOiBvcHRpbWl6ZSB0aGlzIHdpdGggYSBsb29rLXVwLXRhYmxlPw0KCQkJCWlmICggJGluX3BhdHQgKQ0KCQkJCQlmb3IgKCRqPSRlWyRpLTFdOyAoJGo8JGcgJiYgJGo8PSRtayk7ICRqKyspDQoJCQkJCQlpZiAoICRwYXR0eyRpKyRqLTF9ID09ICRjICkNCgkJCQkJCQkkZyA9ICRqOw0KDQoJCQkJJGRbJGldID0gJGc7DQoJCQl9DQoNCgkJCWlmICggJGRbJG1rXSA8PSAkayApDQoJCQl7DQoJCQkJJGVyciA9ICRkWyRta107DQoJCQkJJGkgPSBtaW4oICR0LSRlcnIrJGsrMSwgJHN0YXJ0X2luZGV4KyRuLTEpOw0KCQkJCWlmICggIWlzc2V0KCRtYXRjaGVzWyRpXSkgfHwgJGVyciA8ICRtYXRjaGVzWyRpXSkNCgkJCQkJJG1hdGNoZXNbJGldID0gJGVycjsNCgkJCX0NCgkJfQ0KDQoJCXVuc2V0KCAkZGEsICRkYiApOw0KCQlyZXR1cm4gJG1hdGNoZXM7DQoJfQ0KCWZ1bmN0aW9uIHRlc3Rfc2hvcnRfc2VhcmNoKCkgew0KCQkkdGVzdF90ZXh0ID0gIk9saXBhIGtlcnJhbiBqdXNzaSBiaiZ4bGluZyBqYSBrb2xtZVxuIGlsb2lzdGEgIi4NCgkJCSJqdXNzaSBiZm9ybGluZzppYSBtdXR0YSBlaSB5aHRhYW4ganVzc2kgYmpvcmxpbmctbmltaXN0YSBsYXVsYWphYS4iOw0KCQkkdGVzdF9wYXR0ID0gImp1c3NpIGJqb3JsaW5nIjsNCgkJYXNzZXJ0KCAkdGhpcy0+c2VhcmNoX3Nob3J0KCR0ZXN0X3BhdHQsIDQsICR0ZXN0X3RleHQpID09IEFycmF5KDI3PT4yLCA2MD0+MSwgOTQ9PjApKTsNCgkJYXNzZXJ0KCAkdGhpcy0+c2VhcmNoX3Nob3J0KCR0ZXN0X3BhdHQsIDIsICR0ZXN0X3RleHQpID09IEFycmF5KDI3PT4yLCA2MD0+MSwgOTQ9PjApKTsNCgkJYXNzZXJ0KCAkdGhpcy0+c2VhcmNoX3Nob3J0KCR0ZXN0X3BhdHQsIDEsICR0ZXN0X3RleHQpID09IEFycmF5KDYwPT4xLCA5ND0+MCkpOw0KCQlhc3NlcnQoICR0aGlzLT5zZWFyY2hfc2hvcnQoJHRlc3RfcGF0dCwgMCwgJHRlc3RfdGV4dCkgPT0gQXJyYXkoOTQ9PjApKTsNCgkJYXNzZXJ0KCAkdGhpcy0+c2VhcmNoX3Nob3J0KCJiam9ybGluZyIsIDIsICR0ZXN0X3RleHQsIDE5LCA3KSA9PSBBcnJheSgpKTsNCgkJYXNzZXJ0KCAkdGhpcy0+c2VhcmNoX3Nob3J0KCJiam9ybGluZyIsIDIsICR0ZXN0X3RleHQsIDE5LCA4KSA9PSBBcnJheSgyNj0+MikpOw0KCQlhc3NlcnQoICR0aGlzLT5zZWFyY2hfc2hvcnQoImJqb3JsaW5nIiwgMiwgJHRlc3RfdGV4dCwgMjAsIDgpID09IEFycmF5KCkpOw0KCX0NCg0KCXZhciAkcGF0dCwgJHBhdHRfbGVuLCAkbWF4X2VycjsNCgl2YXIgJHBhcnRzLCAkbl9wYXJ0cywgJHVuaXF1ZV9wYXJ0cywgJG1heF9wYXJ0X2xlbjsNCgl2YXIgJHRyYW5zZl9wYXR0Ow0KCXZhciAkdG9vX3Nob3J0X2VycjsNCglmdW5jdGlvbiBzbWRfRnV6enlGaW5kKCAkcGF0dGVybiwgJG1heF9lcnJvciApIHsNCgkJJHRoaXMtPnBhdHQgPSAkcGF0dGVybjsNCgkJJHRoaXMtPnBhdHRfbGVuID0gc3RybGVuKCR0aGlzLT5wYXR0KTsNCgkJJHRoaXMtPm1heF9lcnIgPSAkbWF4X2Vycm9yOw0KDQoJCS8vIENhbGN1bGF0ZSBwYXR0ZXJuIHBhcnRpdGlvbiBzaXplDQoJCSRpbnRwYXJ0bGVuID0gZmxvb3IoJHRoaXMtPnBhdHRfbGVuLygkdGhpcy0+bWF4X2VycisyKSk7DQoJCWlmICgkaW50cGFydGxlbiA8IDEpDQoJCXsNCgkJCSR0aGlzLT50b29fc2hvcnRfZXJyID0gVHJ1ZTsNCgkJCXJldHVybjsNCgkJfQ0KCQllbHNlICR0aGlzLT50b29fc2hvcnRfZXJyID0gRmFsc2U7DQoNCgkJLy8gUGFydGl0aW9uIHRoZSBwYXR0ZXJuIGZvciBwcnVuaW5nDQoJCSR0aGlzLT5wYXJ0cyA9IEFycmF5KCk7DQoJCWZvciAoJGk9MDsgJGk8JHRoaXMtPnBhdHRfbGVuOyAkaSs9JGludHBhcnRsZW4pDQoJCXsNCgkJCWlmICggJGkgKyAkaW50cGFydGxlbioyID4gJHRoaXMtPnBhdHRfbGVuICkNCgkJCXsNCgkJCQkkdGhpcy0+cGFydHNbXSA9IHN1YnN0ciggJHRoaXMtPnBhdHQsICRpICk7DQoJCQkJYnJlYWs7DQoJCQl9DQoJCQllbHNlDQoJCQkJJHRoaXMtPnBhcnRzW10gPSBzdWJzdHIoICR0aGlzLT5wYXR0LCAkaSwgJGludHBhcnRsZW4gKTsNCgkJfQ0KCQkkdGhpcy0+bl9wYXJ0cyA9IGNvdW50KCR0aGlzLT5wYXJ0cyk7DQoNCgkJLy8gVGhlIGludHBhcnRsZW4gdGVzdCBhYm92ZSBzaG91bGQgaGF2ZSBjb3ZlcmVkIHRoaXM6DQoJCWFzc2VydCggJHRoaXMtPm5fcGFydHMgPj0gJHRoaXMtPm1heF9lcnIrMSApOw0KDQoJCS8vIEZpbmQgbWF4aW11bSBwYXJ0IGxlbmd0aA0KCQlmb3JlYWNoKCAkdGhpcy0+cGFydHMgYXMgJHAgKQ0KCQkJJHRoaXMtPm1heF9wYXJ0X2xlbiA9IG1heCggJHRoaXMtPm1heF9wYXJ0X2xlbiwgc3RybGVuKCRwKSk7DQoNCgkJLy8gTWFrZSBhIG5ldyBwYXJ0IGFycmF5IHdpdGggZHVwbGljYXRlIHN0cmluZ3MgcmVtb3ZlZA0KCQkkdGhpcy0+dW5pcXVlX3BhcnRzID0gYXJyYXlfdW5pcXVlKCR0aGlzLT5wYXJ0cyk7DQoNCgkJLy8gVHJhbnNmb3JtIHRoZSBwYXR0ZXJuIGludG8gYSBsb3cgcmVzb2x1dGlvbiBwcnVuaW5nIHN0cmluZw0KCQkvLyBieSByZXBsYWNpbmcgcGFydHMgd2l0aCBzaW5nbGUgY2hhcmFjdGVycw0KCQkkdGhpcy0+dHJhbnNmX3BhdHQgPSAiIjsNCgkJcmVzZXQoICR0aGlzLT5wYXJ0cyApOw0KCQl3aGlsZSAobGlzdCgsJHApID0gZWFjaCgkdGhpcy0+cGFydHMpKQ0KCQkgICAkdGhpcy0+dHJhbnNmX3BhdHQgLj0gY2hyKGFycmF5X3NlYXJjaCgkcCwgJHRoaXMtPnVuaXF1ZV9wYXJ0cykrb3JkKCJBIikpOw0KDQoJCS8vIFNlbGYgZGlhZ25vc3RpY3MNCgkJJHRoaXMtPnRlc3Rfc2hvcnRfc2VhcmNoKCk7DQoJfQ0KCWZ1bmN0aW9uIHNlYXJjaCggJHRleHQgKSB7DQoJCS8vIEZpbmQgYWxsIG9jY3VyZW5jZXMgb2YgdW5pcXVlIHBhcnRzIGluIHRoZQ0KCQkvLyBmdWxsIHRleHQuIFRoZSByZXN1bHQgaXMgYW4gYXJyYXk6DQoJCS8vICAgQXJyYXkoIDxpbmRleD4gPT4gPHBhcnQjPiwgLi4gKQ0KCQkkcGFydF9tYXAgPSBBcnJheSgpOw0KCQlyZXNldCggJHRoaXMtPnVuaXF1ZV9wYXJ0cyApOw0KCQl3aGlsZSAobGlzdCgkcGksICRwYXJ0X3N0cikgPSBlYWNoKCR0aGlzLT51bmlxdWVfcGFydHMpKQ0KCQl7DQoJCQkkcG9zID0gc3RycG9zKCR0ZXh0LCAkcGFydF9zdHIpOw0KCQkJd2hpbGUgKCAkcG9zICE9PSBGYWxzZSApDQoJCQl7DQoJCQkJJHBhcnRfbWFwWyRwb3NdID0gJHBpOw0KCQkJCSRwb3MgPSBzdHJwb3MoJHRleHQsICRwYXJ0X3N0ciwgJHBvcysxKTsNCgkJCX0NCgkJfQ0KCQlrc29ydCggJHBhcnRfbWFwICk7IC8vIFNvcnQgYnkgc3RyaW5nIGluZGV4DQoNCgkJLy8gVGhlIGZvbGxvd2luZyBjb2RlIGRvZXMgc2V2ZXJhbCB0aGluZ3Mgc2ltdWx0YW5lb3VzbHk6DQoJCS8vICAxKSBEaXZpZGUgdGhlIGluZGljZXMgaW50byBncm91cHMgdXNpbmcgZ2Fwcw0KCQkvLwkgIGxhcmdlciB0aGFuICR0aGlzLT5tYXhfZXJyIGFzIGJvdW5kYXJpZXMuDQoJCS8vICAyKSBUcmFuc2xhdGUgdGhlIGdyb3VwcyBpbnRvIHN0cmluZ3Mgc28gdGhhdA0KCQkvLwkgIHBhcnQjIDAgPSAnQScsIHBhcnQjIDEgPSAnQicgZXRjLiB0byBtYWtlDQoJCS8vCSAgYSBsb3cgcmVzb2x1dGlvbiBhcHByb3hpbWF0ZSBzZWFyY2ggcG9zc2libGUgbGF0ZXINCgkJLy8gIDMpIFNhdmUgdGhlIHN0cmluZyBpbmRpY2VzIGluIHRoZSBmdWxsIHN0cmluZw0KCQkvLwkgIHRoYXQgY29ycmVzcG9uZCB0byBjaGFyYWN0ZXJzIGluIHRoZSB0cmFuc2xhdGVkIHN0cmluZy4NCgkJLy8gIDQpIERpc2NhcmQgZ3JvdXBzICg9cGFydCBzZXF1ZW5jZXMpIHRoYXQgYXJlIHRvbw0KCQkvLwkgIHNob3J0IHRvIGNvbnRhaW4gdGhlIGFwcHJveGltYXRlIHBhdHRlcm4uDQoJCS8vIFRoZSBmb3JtYXQgb2YgcmVzdWx0aW5nIGFycmF5Og0KCQkvLyAgIEFycmF5KA0KCQkvLwkgIEFycmF5KCAiPHRyYW5zbGF0ZS1zdHJpbmc+IiwNCgkJLy8JCQkgQXJyYXkoIDx0cmFuc2xhdGVkLWlkeD4gPT4gPGZ1bGwtaW5kZXg+LCAuLi4gKSApLA0KCQkvLwkgIC4uLiApDQoJCSR0cmFuc2YgPSBBcnJheSgpOw0KCQkkdHJhbnNmX3RleHQgPSAiIjsNCgkJJHRyYW5zZl9wb3MgPSBBcnJheSgpOw0KCQkkbGFzdF9lbmQgPSAwOw0KCQkkZ3JvdXBfbGVuID0gMDsNCgkJcmVzZXQoICRwYXJ0X21hcCApOw0KCQl3aGlsZSAobGlzdCgkaSwkcCkgPSBlYWNoKCRwYXJ0X21hcCkpDQoJCXsNCgkJCWlmICggJGktJGxhc3RfZW5kID4gJHRoaXMtPm1heF9wYXJ0X2xlbiskdGhpcy0+bWF4X2VyciApDQoJCQl7DQoJCQkJaWYgKCAkZ3JvdXBfbGVuID49ICgkdGhpcy0+bl9wYXJ0cy0kdGhpcy0+bWF4X2VycikpDQoJCQkJCSR0cmFuc2ZbXSA9IEFycmF5KCAkdHJhbnNmX3RleHQsICR0cmFuc2ZfcG9zICk7DQoNCgkJCQkkdHJhbnNmX3RleHQgPSAiIjsNCgkJCQkkdHJhbnNmX3BvcyA9IEFycmF5KCk7DQoJCQkJJGdyb3VwX2xlbiA9IDA7DQoJCQl9DQoNCgkJCSR0cmFuc2ZfdGV4dCAuPSBjaHIoJHAgKyBvcmQoIkEiKSk7DQoJCQkkdHJhbnNmX3Bvc1tdID0gJGk7DQoJCQkkZ3JvdXBfbGVuKys7DQoJCQkkbGFzdF9lbmQgPSAkaSArIHN0cmxlbigkdGhpcy0+cGFydHNbJHBdKTsNCgkJfQ0KCQlpZiAoIHN0cmxlbiggJHRyYW5zZl90ZXh0ICkgPj0gKCR0aGlzLT5uX3BhcnRzLSR0aGlzLT5tYXhfZXJyKSkNCgkJCSR0cmFuc2ZbXSA9IEFycmF5KCAkdHJhbnNmX3RleHQsICR0cmFuc2ZfcG9zICk7DQoNCgkJdW5zZXQoICR0cmFuc2ZfdGV4dCwgJHRyYW5zZl9wb3MgKTsNCg0KCQlpZiAoIGN1cnJlbnQoJHRyYW5zZikgPT09IEZhbHNlICkNCgkJCXJldHVybiBBcnJheSgpOw0KDQoJCS8vIEZpbHRlciB0aGUgcmVtYWluaW5nIGdyb3VwcyAoImFwcHJveGltYXRlIGFuYWdyYW1zIg0KCQkvLyBvZiB0aGUgcGF0dGVybikgYW5kIGxlYXZlIG9ubHkgdGhlIG9uZXMgdGhhdCBoYXZlIGVub3VnaA0KCQkvLyBwYXJ0cyBpbiBjb3JyZWN0IG9yZGVyLiBZb3UgY2FuIHRoaW5rIG9mIHRoaXMgbGFzdCBzdGVwIG9mIHRoZQ0KCQkvLyBhbGdvcml0aG0gYXMgYSAqbG93IHJlc29sdXRpb24qIGFwcHJveGltYXRlIHN0cmluZyBzZWFyY2guDQoJCS8vIFRoZSByZXN1bHQgaXMgYW4gYXJyYXkgb2YgY2FuZGlkYXRlIHRleHQgc3BhbnMgdG8gYmUgc2Nhbm5lZDoNCgkJLy8gICBBcnJheSggQXJyYXkoPGZ1bGwtc3RhcnQtaWR4PiwgPGZ1bGwtZW5kLWlkeD4pLCAuLi4gKQ0KCQkkcGFydF9wb3NpdGlvbnMgPSBBcnJheSgpOw0KCQl3aGlsZSAobGlzdCgsbGlzdCgkc3RyLCAkcG9zX21hcCkpID0gZWFjaCgkdHJhbnNmKSkNCgkJew0KLy8JCQlwcmludCAifCR0cmFuc2ZfcGF0dHwgLSB8JHN0cnxcbiI7DQoJCQkkbG9yZXNfbWF0Y2hlcyA9ICR0aGlzLT5zZWFyY2hfc2hvcnQoICR0aGlzLT50cmFuc2ZfcGF0dCwgJHRoaXMtPm1heF9lcnIsICRzdHIgKTsNCgkJCXdoaWxlIChsaXN0KCR0cl9lbmQsICkgPSBlYWNoKCRsb3Jlc19tYXRjaGVzKSkNCgkJCXsNCgkJCQkkdHJfc3RhcnQgPSBtYXgoMCwgJHRyX2VuZCAtICR0aGlzLT5uX3BhcnRzKTsNCgkJCQlpZiAoICR0cl9lbmQgPj0gJHRyX3N0YXJ0ICkNCgkJCQl7DQoJCQkJCSRtZWRpYW5fcG9zID0gJHBvc19tYXBbIChpbnQpKCgkdHJfc3RhcnQrJHRyX2VuZCkvMikgXTsNCgkJCQkJJHN0YXJ0ID0gJG1lZGlhbl9wb3MgLSAoJHRoaXMtPnBhdHRfbGVuLzIrMSkgLSAkdGhpcy0+bWF4X2VyciAtICR0aGlzLT5tYXhfcGFydF9sZW47DQoJCQkJCSRlbmQgPSAkbWVkaWFuX3BvcyArICgkdGhpcy0+cGF0dF9sZW4vMisxKSArICR0aGlzLT5tYXhfZXJyICsgJHRoaXMtPm1heF9wYXJ0X2xlbjsNCg0KLy8JCQkJCXByaW50ICIjIiAuIHN0cnRyKHN1YnN0ciggJHRleHQsICRzdGFydCwgJGVuZC0kc3RhcnQgKSwgIlxuXHIiLCAiJCQiKSAuICIjXG4iOw0KLy8JCQkJCXByaW50X3IoICR0aGlzLT5zZWFyY2hfc2hvcnQoICYkdGhpcy0+cGF0dCwgJHRoaXMtPm1heF9lcnIsICYkdGV4dCwgJHN0YXJ0LCAkZW5kLSRzdGFydCApKTsNCg0KCQkJCQkkcGFydF9wb3NpdGlvbnNbXSA9IEFycmF5KCRzdGFydCwgJGVuZCk7DQoJCQkJfQ0KCQkJfQ0KCQkJdW5zZXQoICRsb3Jlc19tYXRjaGVzICk7DQoJCX0NCgkJdW5zZXQoICR0cmFuc2YgKTsNCg0KCQlpZiAoIGN1cnJlbnQoJHBhcnRfcG9zaXRpb25zKSA9PT0gRmFsc2UgKQ0KCQkJcmV0dXJuIEFycmF5KCk7DQoNCgkJLy8gU2NhbiB0aGUgZmluYWwgY2FuZGlkYXRlcyBhbmQgcHV0IHRoZSBtYXRjaGVzIGluIGEgbmV3IGFycmF5Og0KCQkkbWF0Y2hlcyA9IEFycmF5KCk7DQoJCSR0ZXh0X2xlbiA9IHN0cmxlbigkdGV4dCk7DQoJCXdoaWxlIChsaXN0KCwgbGlzdCgkc3RhcnQsICRlbmQpKSA9IGVhY2goJHBhcnRfcG9zaXRpb25zKSkNCgkJew0KCQkJJG0gPSAkdGhpcy0+c2VhcmNoX3Nob3J0KCAkdGhpcy0+cGF0dCwgJHRoaXMtPm1heF9lcnIsICR0ZXh0LCAkc3RhcnQsICRlbmQtJHN0YXJ0LCAkdGV4dF9sZW4gKTsNCgkJCXdoaWxlIChsaXN0KCRpLCAkY29zdCkgPSBlYWNoKCRtKSkNCgkJCQkkbWF0Y2hlc1skaV0gPSAkY29zdDsNCgkJfQ0KCQl1bnNldCgkcGFydF9wb3NpdGlvbnMpOw0KDQoJCXJldHVybiAkbWF0Y2hlczsNCgl9DQp9DQoNCmNsYXNzIHNtZF9NTFAgew0KCXZhciAkc21kX3N0cmluZ3M7DQoJdmFyICRzbWRfb3duZXI7DQoJdmFyICRzbWRfcHJlZml4Ow0KCXZhciAkc21kX2xhbmc7DQoJdmFyICRzbWRfZXZlbnQ7DQoJZnVuY3Rpb24gc21kX01MUCgkcGx1ZywgJHByZWZ4LCAkc3RyYXJyYXksICRsbmc9J2VuLWdiJywgJGV2PSdwdWJsaWMnKSB7DQoJCSR0aGlzLT5zbWRfb3duZXIgPSAkcGx1ZzsNCgkJJHRoaXMtPnNtZF9wcmVmaXggPSAkcHJlZng7DQoJCSR0aGlzLT5zbWRfc3RyaW5ncyA9ICRzdHJhcnJheTsNCgkJJHRoaXMtPnNtZF9sYW5nID0gJGxuZzsNCgkJJHRoaXMtPnNtZF9ldmVudCA9ICRldjsNCgkJcmVnaXN0ZXJfY2FsbGJhY2soYXJyYXkoJiR0aGlzLCAnc21kX0NhbGxiYWNrJyksICdsMTBuLmVudW1lcmF0ZV9zdHJpbmdzJyk7DQoJfQ0KCWZ1bmN0aW9uIHNtZF9DYWxsYmFjaygkZXZlbnQ9J2wxMG4uZW51bWVyYXRlX3N0cmluZ3MnLCAkc3RlcD0nJywgJHByZT0wKSB7DQoJCSRyID0gYXJyYXkoDQoJCQknb3duZXInID0+ICR0aGlzLT5zbWRfb3duZXIsDQoJCQkncHJlZml4JyA9PiAkdGhpcy0+c21kX3ByZWZpeCwNCgkJCSdsYW5nJyA9PiAkdGhpcy0+c21kX2xhbmcsDQoJCQknZXZlbnQnID0+ICR0aGlzLT5zbWRfZXZlbnQsDQoJCQknc3RyaW5ncycgPT4gJHRoaXMtPnNtZF9zdHJpbmdzLA0KCQkpOw0KCQlyZXR1cm4gJHI7DQoJfQ0KCS8vIEdlbmVyaWMgbG9va3VwDQoJLy8gICR3aGF0ID0ga2V5IHRvIGxvb2sgdXANCgkvLyAgJGFyZ3MgPSBhbnkgYXJndW1lbnRzIHRoZSBrZXkgaXMgZXhwZWN0aW5nIGZvciByZXBsYWNlbWVudA0KCWZ1bmN0aW9uIGdUeHQoJHdoYXQsICRhcmdzID0gYXJyYXkoKSkgew0KCQlnbG9iYWwgJHRleHRhcnJheTsNCg0KCQkvLyBQcmVwYXJlIHRoZSBwcmVmaXhlZCBrZXkgZm9yIHVzZQ0KCQkka2V5ID0gJHRoaXMtPnNtZF9wcmVmaXggLiAnLScgLiAkd2hhdDsNCgkJJGtleSA9IHN0cnRvbG93ZXIoJGtleSk7DQoNCgkJLy8gR3JhYiBmcm9tIHRoZSBnbG9iYWwgdGV4dGFycmF5IChwb3NzaWJseSBlZGl0ZWQgYnkgTUxQKSBpZiB3ZSBjYW4NCgkJaWYoaXNzZXQoJHRleHRhcnJheVska2V5XSkpIHsNCgkJCSRzdHIgPSAkdGV4dGFycmF5WyRrZXldOw0KCQl9IGVsc2Ugew0KCQkJLy8gVGhlIHN0cmluZyBpc24ndCBpbiB0aGUgbG9jYWxpc2VkIHRleHRhcnJheSBzbyBmYWxsYmFjayB0byB1c2luZw0KCQkJLy8gdGhlIChub24gcHJlZml4ZWQpIHN0cmluZyBhcnJheSBpbiB0aGUgcGx1Z2luDQoJCQkka2V5ID0gc3RydG9sb3dlcigkd2hhdCk7DQoJCQkkc3RyID0gKGlzc2V0KCR0aGlzLT5zbWRfc3RyaW5nc1ska2V5XSkpID8gJHRoaXMtPnNtZF9zdHJpbmdzWyRrZXldIDogJHdoYXQ7DQoJCX0NCgkJLy8gUGVyZm9ybSBzdWJzdGl0dXRpb25zDQoJCWlmKCFlbXB0eSgkYXJncykpIHsNCgkJCSRzdHIgPSBzdHJ0cigkc3RyLCAkYXJncyk7DQoJCX0NCg0KCQlyZXR1cm4gJHN0cjsNCgl9DQp9DQpmdW5jdGlvbiBzbWRfYWRkUVNWYXIoJHVybCwgJGtleSwgJHZhbHVlKSB7DQoJJHVybCA9IHNtZF9yZW1vdmVRU1ZhcigkdXJsLCAka2V5KTsNCglpZiAoc3RycG9zKCR1cmwsICc/JykgPT09IGZhbHNlKSB7DQoJCXJldHVybiAoJHVybCAuICc/JyAuICRrZXkgLiAnPScgLiAkdmFsdWUpOw0KCX0gZWxzZSB7DQoJCXJldHVybiAoJHVybCAuICcmJyAuICRrZXkgLiAnPScgLiAkdmFsdWUpOw0KCX0NCn0NCmZ1bmN0aW9uIHNtZF9yZW1vdmVRU1ZhcigkdXJsLCAka2V5KSB7DQoJJHVybCA9IHByZWdfcmVwbGFjZSgnLyguKikoXD98JiknIC4gJGtleSAuICc9W14mXSs/KCYpKC4qKS9pJywgJyQxJDIkNCcsICR1cmwgLiAnJicpOw0KCSR1cmwgPSBzdWJzdHIoJHVybCwgMCwgLTEpOw0KCXJldHVybiAoJHVybCk7DQp9DQovLyByZXR1cm4gYSBsaXN0IG9mIGNhdGVnb3JpZXMgdW5kZXIgKGFuZCBpbmNsdWRpbmcpIHRoZSBnaXZlbiBwYXJlbnQgY2F0ZWdvcnkNCmZ1bmN0aW9uIHNtZF9nZXRTdWJDYXRzKCRwYXJlbnQsJGNhdHR5cGUpIHsNCgkkcGFyZW50ID0gZG9TbGFzaCgkcGFyZW50KTsNCgkkbGV4dHJlbSA9IDE7ICRyZXh0cmVtID0gMTsNCglleHRyYWN0KHNhZmVfcm93KCJsZnQgYXMgbGV4dHJlbSwgcmd0IGFzIHJleHRyZW0iLCAidHhwX2NhdGVnb3J5IiwgIm5hbWU9JyRwYXJlbnQnIGFuZCB0eXBlID0gJyRjYXR0eXBlJyIpKTsNCgkkcnMgPSBzYWZlX3Jvd3Nfc3RhcnQoImlkLG5hbWUsdGl0bGUiLCJ0eHBfY2F0ZWdvcnkiLCAibGZ0IGJldHdlZW4gJGxleHRyZW0gYW5kICRyZXh0cmVtIGFuZCB0eXBlID0gJyRjYXR0eXBlJyBvcmRlciBieSBsZnQgYXNjIik7DQoJJGNhdHMgPSBhcnJheSgpOw0KDQoJd2hpbGUgKCRyb3cgPSBuZXh0Um93KCRycykpIHsNCgkJJGNhdHNbXSA9IGFycmF5KA0KCQkJJ2lkJyA9PiAkcm93WydpZCddLA0KCQkJJ25hbWUnID0+ICRyb3dbJ25hbWUnXSwNCgkJCSd0aXRsZScgPT4gJHJvd1sndGl0bGUnXQ0KCQkpOw0KCX0NCglyZXR1cm4gJGNhdHM7DQp9DQpmdW5jdGlvbiBzbWRfZ2V0QXR0cygkc3RyLCAkYWxsb3dlZCwgJGlkcHJlZml4PSIiLCAkc3BsaXRhdD0iLFxzIikgew0KCWdsb2JhbCAkcHJldGV4dCwgJHRoaXNhcnRpY2xlOw0KDQoJJG91dCA9IGFycmF5KCk7DQoJJHN1Ym91dCA9IGFycmF5KCk7DQoJJG5vdG91dCA9IGFycmF5KCk7DQoJJG1hdGNoZXMgPSBzbWRfc3BsaXRSYW5nZSgkc3RyLCAkc3BsaXRhdCk7DQoNCglmb3IgKCRpZHggPSAwOyAkaWR4IDwgY291bnQoJG1hdGNoZXMpOyAkaWR4KyspIHsNCgkJJHRoaXNtYXRjaCA9ICRtYXRjaGVzWyRpZHhdOw0KCQlpZiAoKCR0aGlzbWF0Y2ggPT09ICI/YyIpICYmIGluX2FycmF5KCI/YyIsJGFsbG93ZWQpKSB7DQoJCQkvLyBVc2UgZ2xvYmFsIGFydGljbGUgY2F0ZWdvcnksIGlmIGl0IGV4aXN0cw0KCQkJaWYgKCRwcmV0ZXh0WydjJ10gIT0gIiIpIHsNCgkJCQlpZiAoIWluX2FycmF5KCRwcmV0ZXh0WydjJ10sICRvdXQpKSB7DQoJCQkJCSRvdXRbXSA9ICRwcmV0ZXh0WydjJ107DQoJCQkJfQ0KCQkJfQ0KCQl9IGVsc2UgaWYgKCgkdGhpc21hdGNoID09PSAiIWMiKSAmJiBpbl9hcnJheSgiIWMiLCRhbGxvd2VkKSkgew0KCQkJLy8gRG9uJ3QgdXNlIGdsb2JhbCBhcnRpY2xlIGNhdGVnb3J5DQoJCQlpZiAoJHByZXRleHRbJ2MnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHByZXRleHRbJ2MnXSwgJG5vdG91dCkpIHsNCgkJCQkJJG5vdG91dFtdID0gJHByZXRleHRbJ2MnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICI/cyIpICYmIGluX2FycmF5KCI/cyIsJGFsbG93ZWQpKSB7DQoJCQkvLyBVc2UgYXJ0aWNsZSBzZWN0aW9uDQoJCQlpZiAoJHByZXRleHRbJ3MnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHByZXRleHRbJ3MnXSwgJG91dCkpIHsNCgkJCQkJJG91dFtdID0gJHByZXRleHRbJ3MnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICIhcyIpICYmIGluX2FycmF5KCIhcyIsJGFsbG93ZWQpKSB7DQoJCQkvLyBEb24ndCB1c2UgYXJ0aWNsZSBzZWN0aW9uDQoJCQlpZiAoJHByZXRleHRbJ3MnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHByZXRleHRbJ3MnXSwgJG5vdG91dCkpIHsNCgkJCQkJJG5vdG91dFtdID0gJHByZXRleHRbJ3MnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICI/cSIpICYmIGluX2FycmF5KCI/cSIsJGFsbG93ZWQpKSB7DQoJCQkvLyBVc2UgcXVlcnkgc3RyaW5nDQoJCQlpZiAoJHByZXRleHRbJ3EnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHByZXRleHRbJ3EnXSwgJG91dCkpIHsNCgkJCQkJJG91dFtdID0gJHByZXRleHRbJ3EnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICIhcSIpICYmIGluX2FycmF5KCIhcSIsJGFsbG93ZWQpKSB7DQoJCQkvLyBEb24ndCB1c2UgcXVlcnkgc3RyaW5nDQoJCQlpZiAoJHByZXRleHRbJ3EnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHByZXRleHRbJ3EnXSwgJG5vdG91dCkpIHsNCgkJCQkJJG5vdG91dFtdID0gJHByZXRleHRbJ3EnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICI/dCIpICYmIGluX2FycmF5KCI/dCIsJGFsbG93ZWQpKSB7DQoJCQkvLyBVc2UgYXJ0aWNsZSBVUkwgdGl0bGUgaWYgdGhpcyBpcyBhbiBhcnRpY2xlLg0KCQkJaWYgKCR0aGlzYXJ0aWNsZSAhPSBOVUxMICYmICR0aGlzYXJ0aWNsZVsndXJsX3RpdGxlJ10gIT0gIiIpIHsNCgkJCQlpZiAoIWluX2FycmF5KCR0aGlzYXJ0aWNsZVsndXJsX3RpdGxlJ10sICRvdXQpKSB7DQoJCQkJCSRvdXRbXSA9ICR0aGlzYXJ0aWNsZVsndXJsX3RpdGxlJ107DQoJCQkJfQ0KCQkJfQ0KCQl9IGVsc2UgaWYgKCgkdGhpc21hdGNoID09PSAiIXQiKSAmJiBpbl9hcnJheSgiIXQiLCRhbGxvd2VkKSkgew0KCQkJLy8gRG9uJ3QgdXNlIGFydGljbGUgVVJMIHRpdGxlDQoJCQlpZiAoJHRoaXNhcnRpY2xlICE9IE5VTEwgJiYgJHRoaXNhcnRpY2xlWyd1cmxfdGl0bGUnXSAhPSAiIikgew0KCQkJCWlmICghaW5fYXJyYXkoJHRoaXNhcnRpY2xlWyd1cmxfdGl0bGUnXSwgJG5vdG91dCkpIHsNCgkJCQkJJG5vdG91dFtdID0gJHRoaXNhcnRpY2xlWyd1cmxfdGl0bGUnXTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2ggPT09ICI/aWQiKSAmJiBpbl9hcnJheSgiP2lkIiwkYWxsb3dlZCkpIHsNCgkJCS8vIFVzZSBhcnRpY2xlIElELCBwcmVwZW5kZWQgd2l0aCAkaWRwcmVmaXgNCgkJCWlmICgkdGhpc2FydGljbGUgIT0gTlVMTCkgew0KCQkJCWlmICghaW5fYXJyYXkoJGlkcHJlZml4IC4gJHByZXRleHRbJ2lkJ10sICRvdXQpKSB7DQoJCQkJCSRvdXRbXSA9ICRpZHByZWZpeCAuICRwcmV0ZXh0WydpZCddOw0KCQkJCX0NCgkJCX0NCgkJfSBlbHNlIGlmICgoJHRoaXNtYXRjaCA9PT0gIiFpZCIpICYmIGluX2FycmF5KCIhaWQiLCRhbGxvd2VkKSkgew0KCQkJLy8gRG9uJ3QgdXNlIGFydGljbGUgSUQNCgkJCWlmICgkdGhpc2FydGljbGUgIT0gTlVMTCkgew0KCQkJCWlmICghaW5fYXJyYXkoJGlkcHJlZml4IC4gJHByZXRleHRbJ2lkJ10sICRub3RvdXQpKSB7DQoJCQkJCSRub3RvdXRbXSA9ICRpZHByZWZpeCAuICRwcmV0ZXh0WydpZCddOw0KCQkJCX0NCgkJCX0NCgkJfSBlbHNlIGlmICgoJHRoaXNtYXRjaFswXSA9PT0gIj8iKSAmJiBpbl9hcnJheSgiP2ZpZWxkIiwkYWxsb3dlZCkpIHsNCgkJCS8vIFVzZSB0aGUgZ2l2ZW4gZmllbGQgbmFtZTsgd2hpY2ggbWF5IGJlIGEgY29tbWEtc2VwYXJhdGVkIHN1Ymxpc3QuDQoJCQkvLyBTcGxpdCBvZmYgdGhlIGZpZWxkIG5hbWUgZnJvbSB0aGUgcXVlc3Rpb24gbWFyaw0KCQkJJGZpZWxkbmFtZSA9IHN1YnN0cigkdGhpc21hdGNoLDEpOw0KCQkJaWYgKCgkdGhpc2FydGljbGUgIT0gTlVMTCkgJiYgKGlzc2V0KCR0aGlzYXJ0aWNsZVskZmllbGRuYW1lXSkpKSB7DQoJCQkJJGZpZWxkQ29udGVudHMgPSAkdGhpc2FydGljbGVbJGZpZWxkbmFtZV07DQoJCQl9IGVsc2Ugew0KCQkJCSRmaWVsZENvbnRlbnRzID0gJGZpZWxkbmFtZTsNCgkJCX0NCgkJCWlmICghZW1wdHkoJGZpZWxkQ29udGVudHMpKSB7DQoJCQkJJHN1Ym91dCA9IHNtZF9zcGxpdFJhbmdlKHN0cmlwX3RhZ3MoJGZpZWxkQ29udGVudHMpLCAkc3BsaXRhdCk7DQoJCQkJZm9yZWFjaCAoJHN1Ym91dCBhcyAkc3VibmFtZSkgew0KCQkJCQlpZiAoIWluX2FycmF5KCRzdWJuYW1lLCAkb3V0KSkgew0KCQkJCQkJJG91dFtdID0gJHN1Ym5hbWU7DQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSBpZiAoKCR0aGlzbWF0Y2hbMF0gPT09ICIhIikgJiYgaW5fYXJyYXkoIiFmaWVsZCIsJGFsbG93ZWQpKSB7DQoJCQkvLyBOZWdhdGlvbi4gTWF5IGVpdGhlciBiZSBhIGZpZWxkIG5hbWUgKGFuZCBtYXliZSBhbm90aGVyIENTTCkgb3IgYSBmaXhlZCB0ZXJtLg0KCQkJLy8gU3BsaXQgb2ZmIHRoZSBuYW1lIGZyb20gdGhlIGV4Y2xhbWF0aW9uIG1hcmsNCgkJCSRmaWVsZG5hbWUgPSBzdWJzdHIoJHRoaXNtYXRjaCwxKTsNCgkJCWlmICgoJHRoaXNhcnRpY2xlICE9IE5VTEwpICYmIChpc3NldCgkdGhpc2FydGljbGVbJGZpZWxkbmFtZV0pKSkgew0KCQkJCSRmaWVsZENvbnRlbnRzID0gJHRoaXNhcnRpY2xlWyRmaWVsZG5hbWVdOw0KCQkJfSBlbHNlIHsNCgkJCQkkZmllbGRDb250ZW50cyA9ICRmaWVsZG5hbWU7DQoJCQl9DQoJCQlpZiAoIWVtcHR5KCRmaWVsZENvbnRlbnRzKSkgew0KCQkJCSRzdWJvdXQgPSBzbWRfc3BsaXRSYW5nZShzdHJpcF90YWdzKCRmaWVsZENvbnRlbnRzKSwgJHNwbGl0YXQpOw0KCQkJCWZvcmVhY2ggKCRzdWJvdXQgYXMgJHN1Ym5hbWUpIHsNCgkJCQkJaWYgKCFpbl9hcnJheSgkc3VibmFtZSwgJG5vdG91dCkpIHsNCgkJCQkJCSRub3RvdXRbXSA9ICRzdWJuYW1lOw0KCQkJCQl9DQoJCQkJfQ0KCQkJfQ0KCQl9IGVsc2Ugew0KCQkJaWYgKCFpbl9hcnJheSgkdGhpc21hdGNoLCAkb3V0KSkgew0KCQkJCSRvdXRbXSA9ICR0aGlzbWF0Y2g7DQoJCQl9DQoJCX0NCgl9DQoJcmV0dXJuIGFycmF5KCRvdXQsJG5vdG91dCk7DQp9DQpmdW5jdGlvbiBzbWRfc3BsaXRSYW5nZSgkc3RyLCAkc3BsaXRhdD0iLFxzIikgew0KCSRyZXRhcnIgPSBhcnJheSgpOw0KCSRlbGVtcyA9IHByZWdfc3BsaXQoJy9bJy4kc3BsaXRhdC4nXSsvJywgJHN0ciwgLTEsIFBSRUdfU1BMSVRfTk9fRU1QVFkpOw0KCWZvcmVhY2ggKCRlbGVtcyBhcyAkaXRlbSkgew0KCQkkbmVnYXRlID0gZmFsc2U7DQoJCS8vIERvZXMgdGhlIGl0ZW0gc3RhcnQgd2l0aCBhIG5lZ2F0aW9uIGNoYXJhY3Rlcg0KCQlpZiAoJGl0ZW1bMF0gPT09ICIhIikgew0KCQkJJG5lZ2F0ZSA9IHRydWU7DQoJCQkkaXRlbSA9IHN1YnN0cigkaXRlbSwxKTsNCgkJfQ0KCQkvLyBJcyB0aGUgaXRlbSBhbiBpbnRlZ2VyIGxpc3QgcmFuZ2UNCgkJaWYgKHByZWdfbWF0Y2goJy9eKFxkKylcLShcZCspJC8nLCAkaXRlbSkpIHsNCgkJCWxpc3QoJGxvLCAkaGkpID0gZXhwbG9kZSgiLSIsICRpdGVtLCAyKTsNCgkJCSRybmcgPSByYW5nZSgkbG8sICRoaSk7DQoJCQkvLyBSZWFwcGx5IHRoZSBuZWdhdGlvbiBpZiBuZWNlc3NhcnkNCgkJCWZvcigkaWR4ID0gMDsgJGlkeCA8IGNvdW50KCRybmcpOyAkaWR4KyspIHsNCgkJCQkkcm5nWyRpZHhdID0gKCgkbmVnYXRlKSA/ICIhIiA6ICIiKSAuICRybmdbJGlkeF07DQoJCQl9DQoJCQkkcmV0YXJyID0gYXJyYXlfbWVyZ2UoJHJldGFyciwgJHJuZyk7DQoJCX0gZWxzZSB7DQoJCQkkcmV0YXJyW10gPSAoKCRuZWdhdGUpID8gIiEiIDogIiIpIC4gJGl0ZW07DQoJCX0NCgl9DQoJcmV0dXJuICRyZXRhcnI7DQp9DQpmdW5jdGlvbiBzbWRfZ2V0V29yZCgkaGF5c3RhY2ssJHNlYXJjaHRlcm0sJG9mZnNldD0wKSB7DQoJJG51bXdvcmRzID0gc3RyX3dvcmRfY291bnQoJHNlYXJjaHRlcm0pOw0KCSRoYXlzdGFjayA9IHN0cnJldihzdWJzdHIoJGhheXN0YWNrLDAsJG9mZnNldCsxKSk7DQoJJHNwYWNlUG9zID0gMTsNCgkvLyBJZiB0aGUgYWxnb3JpdGhtIGhhcyBmb3VuZCB0aGUgc3RhcnQgb2YgdGhlIG5leHQgd29yZCBpbnN0ZWFkIG9mIHRoZSBlbmQgb2YgdGhlIGxhc3Qgd29yZCwgc2tpcCBpdA0KCWlmIChjdHlwZV9zcGFjZSgkaGF5c3RhY2tbMV0pICYmIGN0eXBlX2FsbnVtKCRoYXlzdGFja1swXSkpIHsNCgkJJHN0YXJ0cG9zID0gMjsNCgkJJHNwYWNlUG9zID0gMjsNCgl9DQoJZm9yICgkaWR4ID0gMDsgJGlkeCA8ICRudW13b3JkczsgJGlkeCsrKSB7DQoJCSRzcGFjZVBvcyA9IChzdHJwb3MoJGhheXN0YWNrLCAiICIsICRzcGFjZVBvcykpKzE7DQoJfQ0KCXJldHVybiB0cmltKHN0cnJldihzdWJzdHIoJGhheXN0YWNrLCAkc3RhcnRwb3MsICRzcGFjZVBvcy0kc3RhcnRwb3MpKSk7DQp9DQovL0RFUFJFQ0FURUQ6IHVzZSBzbWRfTUxQLT5nVHh0KCkgaW5zdGVhZA0KLy8gR2VuZXJpYyBsb29rdXAgZnVuY3Rpb24gZm9yIGludGVyZmFjaW5nIHdpdGggTUxQIHRvIGxvY2FsaXNlIHN0cmluZ3MuDQovLyAgJHN0cmF5ID0gYXJyYXkgb2YgZGVmYXVsdCBzdHJpbmdzDQovLyAgJHdoYXQgPSBrZXkgdG8gbG9vayB1cA0KLy8gICRhcmdzID0gYW55IGFyZ3VtZW50cyB0aGUga2V5IGlzIGV4cGVjdGluZyBmb3IgcmVwbGFjZW1lbnQNCmZ1bmN0aW9uIHNtZF9nVHh0KCRzdHJheSwgJHdoYXQsICRhcmdzID0gYXJyYXkoKSkgew0KCWdsb2JhbCAkdGV4dGFycmF5LCAkc21kTUxQOw0KCSRmbiA9IHNtZF9nZXRDYWxsZXIoKTsNCg0KCS8vIERyb3Agb3V0IGlmIHRoZSBpZCBpc24ndCBkZWZpbmVkLg0KCS8vIFdvdWxkIGJlIG5pY2UgdG8gdXNlIHJlZmxlY3Rpb24gdG8gZmluZCB0aGUgbmFtZSBvZiB0aGUgZnVuY3Rpb24gYW5kIHBhc3MgdGhhdCwNCgkvLyBidXQgdGhhdCdzIFBIUDUgdGVycml0b3J5IG9ubHkNCglpZiAoZW1wdHkoJGZuKSkgew0KCQkkc3RyID0gJHdoYXQ7DQoJfSBlbHNlIHsNCgkJLy8gUHJlcGFyZSB0aGUgcHJlZml4ZWQga2V5IGZvciB1c2UNCgkJJGtleSA9ICRzbWRNTFBbJGZuXSAuICctJyAuICR3aGF0Ow0KCQkka2V5ID0gc3RydG9sb3dlcigka2V5KTsNCg0KCQkvLyBHcmFiIGZyb20gdGhlIGdsb2JhbCB0ZXh0YXJyYXkgKHBvc3NpYmx5IGVkaXRlZCBieSBNTFApIGlmIHdlIGNhbg0KCQlpZihpc3NldCgkdGV4dGFycmF5WyRrZXldKSkgew0KCQkJJHN0ciA9ICR0ZXh0YXJyYXlbJGtleV07DQoJCX0gZWxzZSB7DQoJCQkvLyBUaGUgc3RyaW5nIGlzbid0IGluIHRoZSBsb2NhbGlzZWQgJHRleHRhcnJheSBzbyBmYWxsYmFjayB0byB1c2luZw0KCQkJLy8gdGhlIChub24gcHJlZml4ZWQpIHN0cmluZyBhcnJheSBpbiB0aGUgcGx1Z2luDQoJCQkka2V5ID0gc3RydG9sb3dlcigkd2hhdCk7DQoJCQkkc3RyID0gKGlzc2V0KCRzdHJheVska2V5XSkpID8gJHN0cmF5WyRrZXldIDogJHdoYXQ7DQoJCX0NCgl9DQoJLy8gUGVyZm9ybSBzdWJzdGl0dXRpb25zDQoJaWYoIWVtcHR5KCRhcmdzKSkgew0KCQkkc3RyID0gc3RydHIoJHN0ciwgJGFyZ3MpOw0KCX0NCglyZXR1cm4gJHN0cjsNCn0NCi8vREVQUkVDQVRFRDogV2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IHJlbGVhc2UNCi8vIENoZWF0aW5nIHdheSBvZiBmaW5kaW5nIGEgZnVuY3Rpb24ncyBjYWxsZXINCmZ1bmN0aW9uIHNtZF9nZXRDYWxsZXIoKSB7DQoJJGJhY2t0cmFjZSA9IGRlYnVnX2JhY2t0cmFjZSgpOw0KCXJldHVybiAkYmFja3RyYWNlWzJdWydmdW5jdGlvbiddOw0KfQ0KIjtzOjQ6InR5cGUiO3M6MToiMCI7czozOiJtZDUiO3M6MzI6IjdkMTZhNGYzYmM1NDU2Mjk4YjI1MGU1MGNkYTg1YzBiIjt9