Lyogdmk6IHNldCBzdz00IHRzPTQ6ICovCi8qCiAqICByZWFkcHJvZmlsZS5jIC0gdXNlZCB0byByZWFkIC9wcm9jL3Byb2ZpbGUKICoKICogIENvcHlyaWdodCAoQykgMTk5NCwxOTk2IEFsZXNzYW5kcm8gUnViaW5pIChydWJpbmlAaXB2dmlzLnVuaXB2Lml0KQogKgogKiBMaWNlbnNlZCB1bmRlciBHUEx2MiBvciBsYXRlciwgc2VlIGZpbGUgTElDRU5TRSBpbiB0aGlzIHRhcmJhbGwgZm9yIGRldGFpbHMuCiAqLwoKLyoKICogMTk5OS0wMi0yMiBBcmthZGl1c3ogTWm2a2lld2ljeiA8bWlzaWVrQHBsZC5PUkcuUEw+CiAqIC0gYWRkZWQgTmF0aXZlIExhbmd1YWdlIFN1cHBvcnQKICogMTk5OS0wOS0wMSBTdGVwaGFuZSBFcmFuaWFuIDxlcmFuaWFuQGNlbGxvLmhwbC5ocC5jb20+CiAqIC0gNjRiaXQgY2xlYW4gcGF0Y2gKICogM0ZlYjIwMDEgQW5kcmV3IE1vcnRvbiA8YW5kcmV3bUB1b3cuZWR1LmF1PgogKiAtIC1NIG9wdGlvbiB0byB3cml0ZSBwcm9maWxlIG11bHRpcGxpZXIuCiAqIDIwMDEtMTEtMDcgV2VybmVyIEFsbWVzYmVyZ2VyIDx3YUBhbG1lc2Jlcmdlci5uZXQ+CiAqIC0gYnl0ZSBvcmRlciBhdXRvLWRldGVjdGlvbiBhbmQgLW4gb3B0aW9uCiAqIDIwMDEtMTEtMDkgV2VybmVyIEFsbWVzYmVyZ2VyIDx3YUBhbG1lc2Jlcmdlci5uZXQ+CiAqIC0gc2tpcCBzdGVwIHNpemUgKGluZGV4IDApCiAqIDIwMDItMDMtMDkgSm9obiBMZXZvbiA8bW96QGNvbXBzb2MubWFuLmFjLnVrPgogKiAtIG1ha2UgbWFwbGluZW5vIGRvIHNvbWV0aGluZwogKiAyMDAyLTExLTI4IE1hZHMgTWFydGluIEpvZXJnZW5zZW4gKwogKiAtIGFsc28gdHJ5IC9ib290L1N5c3RlbS5tYXAtYHVuYW1lIC1yYAogKiAyMDAzLTA0LTA5IFdlcm5lciBBbG1lc2JlcmdlciA8d2FAYWxtZXNiZXJnZXIubmV0PgogKiAtIGZpeGVkIG9mZi1ieSBlaWdodCBlcnJvciBhbmQgaW1wcm92ZWQgaGV1cmlzdGljcyBpbiBieXRlIG9yZGVyIGRldGVjdGlvbgogKiAyMDAzLTA4LTEyIE5pa2l0YSBEYW5pbG92IDxOaWtpdGFATmFtZXN5cy5DT00+CiAqIC0gYWRkZWQgLXMgb3B0aW9uOyBleGFtcGxlIG9mIHVzZToKICogInJlYWRwcm9maWxlIC1zIC1tIC9ib290L1N5c3RlbS5tYXAtdGVzdCB8IGdyZXAgX19kX2xvb2t1cCB8IHNvcnQgLW4gLWszIgogKgogKiBUYWtlbiBmcm9tIHV0aWwtbGludXggYW5kIGFkYXB0ZWQgZm9yIGJ1c3lib3ggYnkKICogUGF1bCBNdW5kdCA8bGV0aGFsQGxpbnV4LXNoLm9yZz4uCiAqLwoKI2luY2x1ZGUgImxpYmJiLmgiCiNpbmNsdWRlIDxzeXMvdXRzbmFtZS5oPgoKI2RlZmluZSBTX0xFTiAxMjgKCi8qIFRoZXNlIGFyZSB0aGUgZGVmYXVsdHMgKi8Kc3RhdGljIGNvbnN0IGNoYXIgZGVmYXVsdG1hcFtdID0gIi9ib290L1N5c3RlbS5tYXAiOwpzdGF0aWMgY29uc3QgY2hhciBkZWZhdWx0cHJvW10gPSAiL3Byb2MvcHJvZmlsZSI7CgppbnQgcmVhZHByb2ZpbGVfbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpOwppbnQgcmVhZHByb2ZpbGVfbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpCnsKCUZJTEUgKm1hcDsKCWNvbnN0IGNoYXIgKm1hcEZpbGUsICpwcm9GaWxlLCAqbXVsdCA9IDA7Cgl1bnNpZ25lZCBsb25nIGluZHggPSAxOwoJc2l6ZV90IGxlbjsKCXVpbnQ2NF90IGFkZDAgPSAwOwoJdW5zaWduZWQgaW50IHN0ZXA7Cgl1bnNpZ25lZCBpbnQgKmJ1ZiwgdG90YWwsIGZuX2xlbjsKCXVuc2lnbmVkIGxvbmcgbG9uZyBmbl9hZGQsIG5leHRfYWRkOyAgICAgLyogY3VycmVudCBhbmQgbmV4dCBhZGRyZXNzICovCgljaGFyIGZuX25hbWVbU19MRU5dLCBuZXh0X25hbWVbU19MRU5dOyAgIC8qIGN1cnJlbnQgYW5kIG5leHQgbmFtZSAqLwoJY2hhciBtYXBsaW5lW1NfTEVOXTsKCWNoYXIgbW9kZVs4XTsKCWludCBvcHRBbGwgPSAwLCBvcHRJbmZvID0gMCwgb3B0UmVzZXQgPSAwOwoJaW50IG9wdFZlcmJvc2UgPSAwLCBvcHROYXRpdmUgPSAwOwoJaW50IG9wdEJpbnMgPSAwLCBvcHRTdWIgPSAwOwoJaW50IG1hcGxpbmVubyA9IDE7CglpbnQgaGVhZGVyX3ByaW50ZWQ7CgojZGVmaW5lIG5leHQgKGN1cnJlbnReMSkKCglwcm9GaWxlID0gZGVmYXVsdHBybzsKCW1hcEZpbGUgPSBkZWZhdWx0bWFwOwoKCW9wdF9jb21wbGVtZW50YXJ5ID0gIm5uOmFhOmJiOnNzOmlpOnJyOnZ2IjsKCWdldG9wdDMyKGFyZ2MsIGFyZ3YsICJNOm06cDpuYWJzaXJ2IiwKCQkJJm11bHQsICZtYXBGaWxlLCAmcHJvRmlsZSwKCQkJJm9wdE5hdGl2ZSwgJm9wdEFsbCwgJm9wdEJpbnMsICZvcHRTdWIsCgkJCSZvcHRJbmZvLCAmb3B0UmVzZXQsICZvcHRWZXJib3NlKTsKCglpZiAob3B0UmVzZXQgfHwgbXVsdCkgewoJCWludCBtdWx0aXBsaWVyLCBmZCwgdG9fd3JpdGU7CgoJCS8qCgkJICogV2hlbiB3cml0aW5nIHRoZSBtdWx0aXBsaWVyLCBpZiB0aGUgbGVuZ3RoIG9mIHRoZSB3cml0ZSBpcwoJCSAqIG5vdCBzaXplb2YoaW50KSwgdGhlIG11bHRpcGxpZXIgaXMgbm90IGNoYW5nZWQKCQkgKi8KCQlpZiAobXVsdCkgewoJCQltdWx0aXBsaWVyID0geGF0b2lfdShtdWx0KTsKCQkJdG9fd3JpdGUgPSBzaXplb2YoaW50KTsKCQl9IGVsc2UgewoJCQltdWx0aXBsaWVyID0gMDsKCQkJdG9fd3JpdGUgPSAxOwkvKiBzdGggZGlmZmVyZW50IGZyb20gc2l6ZW9mKGludCkgKi8KCQl9CgoJCWZkID0geG9wZW4oZGVmYXVsdHBybywgT19XUk9OTFkpOwoKCQlpZiAoZnVsbF93cml0ZShmZCwgJm11bHRpcGxpZXIsIHRvX3dyaXRlKSAhPSB0b193cml0ZSkKCQkJYmJfcGVycm9yX21zZ19hbmRfZGllKCJlcnJvciB3cml0aW5nICVzIiwgZGVmYXVsdHBybyk7CgoJCWNsb3NlKGZkKTsKCQlyZXR1cm4gRVhJVF9TVUNDRVNTOwoJfQoKCS8qCgkgKiBVc2UgYW4gZmQgZm9yIHRoZSBwcm9maWxpbmcgYnVmZmVyLCB0byBza2lwIHN0ZGlvIG92ZXJoZWFkCgkgKi8KCWxlbiA9IE1BWElOVChzc2l6ZV90KTsKCWJ1ZiA9IHhtYWxsb2Nfb3Blbl9yZWFkX2Nsb3NlKHByb0ZpbGUsICZsZW4pOwoJaWYgKCFvcHROYXRpdmUpIHsKCQlpbnQgZW50cmllcyA9IGxlbi9zaXplb2YoKmJ1Zik7CgkJaW50IGJpZyA9IDAsIHNtYWxsID0gMCwgaTsKCQl1bnNpZ25lZCAqcDsKCgkJZm9yIChwID0gYnVmKzE7IHAgPCBidWYrZW50cmllczsgcCsrKSB7CgkJCWlmICgqcCAmIH4wVSA8PCAoc2l6ZW9mKCpidWYpKjQpKQoJCQkJYmlnKys7CgkJCWlmICgqcCAmICgoMSA8PCAoc2l6ZW9mKCpidWYpKjQpKS0xKSkKCQkJCXNtYWxsKys7CgkJfQoJCWlmIChiaWcgPiBzbWFsbCkgewoJCQliYl9lcnJvcl9tc2coImFzc3VtaW5nIHJldmVyc2VkIGJ5dGUgb3JkZXIsICIKCQkJCSJ1c2UgLW4gdG8gZm9yY2UgbmF0aXZlIGJ5dGUgb3JkZXIiKTsKCQkJZm9yIChwID0gYnVmOyBwIDwgYnVmK2VudHJpZXM7IHArKykKCQkJCWZvciAoaSA9IDA7IGkgPCBzaXplb2YoKmJ1ZikvMjsgaSsrKSB7CgkJCQkJdW5zaWduZWQgY2hhciAqYiA9ICh1bnNpZ25lZCBjaGFyICopIHA7CgkJCQkJdW5zaWduZWQgY2hhciB0bXA7CgoJCQkJCXRtcCA9IGJbaV07CgkJCQkJYltpXSA9IGJbc2l6ZW9mKCpidWYpLWktMV07CgkJCQkJYltzaXplb2YoKmJ1ZiktaS0xXSA9IHRtcDsKCQkJCX0KCQl9Cgl9CgoJc3RlcCA9IGJ1ZlswXTsKCWlmIChvcHRJbmZvKSB7CgkJcHJpbnRmKCJTYW1wbGluZ19zdGVwOiAlaVxuIiwgc3RlcCk7CgkJcmV0dXJuIEVYSVRfU1VDQ0VTUzsKCX0KCgl0b3RhbCA9IDA7CgoJbWFwID0geGZvcGVuKG1hcEZpbGUsICJyIik7CgoJd2hpbGUgKGZnZXRzKG1hcGxpbmUsIFNfTEVOLCBtYXApKSB7CgkJaWYgKHNzY2FuZihtYXBsaW5lLCAiJWxseCAlcyAlcyIsICZmbl9hZGQsIG1vZGUsIGZuX25hbWUpICE9IDMpCgkJCWJiX2Vycm9yX21zZ19hbmRfZGllKCIlcyglaSk6IHdyb25nIG1hcCBsaW5lIiwKCQkJCQkgICAgIG1hcEZpbGUsIG1hcGxpbmVubyk7CgoJCWlmICghc3RyY21wKGZuX25hbWUsICJfc3RleHQiKSkgLyogb25seSBlbGYgd29ya3MgbGlrZSB0aGlzICovIHsKCQkJYWRkMCA9IGZuX2FkZDsKCQkJYnJlYWs7CgkJfQoJCW1hcGxpbmVubysrOwoJfQoKCWlmICghYWRkMCkKCQliYl9lcnJvcl9tc2dfYW5kX2RpZSgiY2FuJ3QgZmluZCBcIl9zdGV4dFwiIGluICVzIiwgbWFwRmlsZSk7CgoJLyoKCSAqIE1haW4gbG9vcC4KCSAqLwoJd2hpbGUgKGZnZXRzKG1hcGxpbmUsIFNfTEVOLCBtYXApKSB7CgkJdW5zaWduZWQgaW50IHRoaXMgPSAwOwoKCQlpZiAoc3NjYW5mKG1hcGxpbmUsICIlbGx4ICVzICVzIiwgJm5leHRfYWRkLCBtb2RlLCBuZXh0X25hbWUpICE9IDMpCgkJCWJiX2Vycm9yX21zZ19hbmRfZGllKCIlcyglaSk6IHdyb25nIG1hcCBsaW5lIiwKCQkJCQltYXBGaWxlLCBtYXBsaW5lbm8pOwoKCQloZWFkZXJfcHJpbnRlZCA9IDA7CgoJCS8qIGlnbm9yZSBhbnkgTEVBRElORyAoYmVmb3JlIGEgJ1t0VF0nIHN5bWJvbCBpcyBmb3VuZCkKCQkgICBBYnNvbHV0ZSBzeW1ib2xzICovCgkJaWYgKCgqbW9kZSA9PSAnQScgfHwgKm1vZGUgPT0gJz8nKSAmJiB0b3RhbCA9PSAwKSBjb250aW51ZTsKCQlpZiAoKm1vZGUgIT0gJ1QnICYmICptb2RlICE9ICd0JyAmJgoJCSAgICAqbW9kZSAhPSAnVycgJiYgKm1vZGUgIT0gJ3cnKQoJCQlicmVhazsJLyogb25seSB0ZXh0IGlzIHByb2ZpbGVkICovCgoJCWlmIChpbmR4ID49IGxlbiAvIHNpemVvZigqYnVmKSkKCQkJYmJfZXJyb3JfbXNnX2FuZF9kaWUoInByb2ZpbGUgYWRkcmVzcyBvdXQgb2YgcmFuZ2UuICIKCQkJCQkgICAgICJXcm9uZyBtYXAgZmlsZT8iKTsKCgkJd2hpbGUgKGluZHggPCAobmV4dF9hZGQtYWRkMCkvc3RlcCkgewoJCQlpZiAob3B0QmlucyAmJiAoYnVmW2luZHhdIHx8IG9wdEFsbCkpIHsKCQkJCWlmICghaGVhZGVyX3ByaW50ZWQpIHsKCQkJCQlwcmludGYoIiVzOlxuIiwgZm5fbmFtZSk7CgkJCQkJaGVhZGVyX3ByaW50ZWQgPSAxOwoJCQkJfQoJCQkJcHJpbnRmKCJcdCUiUFJJeDY0Ilx0JXVcbiIsIChpbmR4IC0gMSkqc3RlcCArIGFkZDAsIGJ1ZltpbmR4XSk7CgkJCX0KCQkJdGhpcyArPSBidWZbaW5keCsrXTsKCQl9CgkJdG90YWwgKz0gdGhpczsKCgkJaWYgKG9wdEJpbnMpIHsKCQkJaWYgKG9wdFZlcmJvc2UgfHwgdGhpcyA+IDApCgkJCQlwcmludGYoIiAgdG90YWxcdFx0XHRcdCV1XG4iLCB0aGlzKTsKCQl9IGVsc2UgaWYgKCh0aGlzIHx8IG9wdEFsbCkgJiYKCQkJICAgKGZuX2xlbiA9IG5leHRfYWRkLWZuX2FkZCkgIT0gMCkgewoJCQlpZiAob3B0VmVyYm9zZSkKCQkJCXByaW50ZigiJTAxNmxseCAlLTQwcyAlNmkgJTguNGZcbiIsIGZuX2FkZCwKCQkJCSAgICAgICBmbl9uYW1lLCB0aGlzLCB0aGlzLyhkb3VibGUpZm5fbGVuKTsKCQkJZWxzZQoJCQkJcHJpbnRmKCIlNmkgJS00MHMgJTguNGZcbiIsCgkJCQkgICAgICAgdGhpcywgZm5fbmFtZSwgdGhpcy8oZG91YmxlKWZuX2xlbik7CgkJCWlmIChvcHRTdWIpIHsKCQkJCXVuc2lnbmVkIGxvbmcgbG9uZyBzY2FuOwoKCQkJCWZvciAoc2NhbiA9IChmbl9hZGQtYWRkMCkvc3RlcCArIDE7CgkJCQkgICAgIHNjYW4gPCAobmV4dF9hZGQtYWRkMCkvc3RlcDsgc2NhbisrKSB7CgkJCQkJdW5zaWduZWQgbG9uZyBsb25nIGFkZHI7CgoJCQkJCWFkZHIgPSAoc2NhbiAtIDEpKnN0ZXAgKyBhZGQwOwoJCQkJCXByaW50ZigiXHQlI2xseFx0JXMrJSNsbHhcdCV1XG4iLAoJCQkJCSAgICAgICBhZGRyLCBmbl9uYW1lLCBhZGRyIC0gZm5fYWRkLAoJCQkJCSAgICAgICBidWZbc2Nhbl0pOwoJCQkJfQoJCQl9CgkJfQoKCQlmbl9hZGQgPSBuZXh0X2FkZDsKCQlzdHJjcHkoZm5fbmFtZSwgbmV4dF9uYW1lKTsKCgkJbWFwbGluZW5vKys7Cgl9CgoJLyogY2xvY2sgdGlja3MsIG91dCBvZiBrZXJuZWwgdGV4dCAtIHByb2JhYmx5IG1vZHVsZXMgKi8KCXByaW50ZigiJTZpICVzXG4iLCBidWZbbGVuL3NpemVvZigqYnVmKS0xXSwgIip1bmtub3duKiIpOwoKCS8qIHRyYWlsZXIgKi8KCWlmIChvcHRWZXJib3NlKQoJCXByaW50ZigiJTAxNnggJS00MHMgJTZpICU4LjRmXG4iLAoJCSAgICAgICAwLCAidG90YWwiLCB0b3RhbCwgdG90YWwvKGRvdWJsZSkoZm5fYWRkLWFkZDApKTsKCWVsc2UKCQlwcmludGYoIiU2aSAlLTQwcyAlOC40ZlxuIiwKCQkgICAgICAgdG90YWwsICJ0b3RhbCIsIHRvdGFsLyhkb3VibGUpKGZuX2FkZC1hZGQwKSk7CgoJZmNsb3NlKG1hcCk7CglmcmVlKGJ1Zik7CgoJcmV0dXJuIEVYSVRfU1VDQ0VTUzsKfQo=