LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgojaW5jbHVkZSAiZXh0cmFjaHVuay5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2luZ2RpLmgiCiNpbmNsdWRlICJ3aW51c2VyLmgiCiNpbmNsdWRlICJ2ZncuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChhdmlmaWxlKTsKCi8qIHJlYWRzIGEgY2h1bmsgb3V0b2YgdGhlIGV4dHJhY2h1bmstc3RydWN0dXJlICovCkhSRVNVTFQgUmVhZEV4dHJhQ2h1bmsoY29uc3QgRVhUUkFDSFVOS1MgKmV4dHJhLEZPVVJDQyBja2lkLExQVk9JRCBscERhdGEsTFBMT05HIHNpemUpCnsKICBMUEJZVEUgbHA7CiAgRFdPUkQgIGNiOwoKICAvKiBwcmUtY29uZGl0aW9ucyAqLwogIGFzc2VydChleHRyYSAhPSBOVUxMKTsKICBhc3NlcnQoc2l6ZSAhPSBOVUxMKTsKCiAgbHAgPSBleHRyYS0+bHA7CiAgY2IgPSBleHRyYS0+Y2I7CgogIGlmIChscCAhPSBOVUxMKSB7CiAgICB3aGlsZSAoY2IgPiAwKSB7CiAgICAgIGlmICgoKEZPVVJDQyopbHApWzBdID09IGNraWQpIHsKCS8qIGZvdW5kIGNvcnJlY3QgY2h1bmsgKi8KCWlmIChscERhdGEgIT0gTlVMTCAmJiAqc2l6ZSA+IDApCgkgIG1lbWNweShscERhdGEsIGxwICsgMiAqIHNpemVvZihEV09SRCksCgkJIG1pbigoKExQRFdPUkQpbHApWzFdLCAqKExQRFdPUkQpc2l6ZSkpOwoKCSooTFBEV09SRClzaXplID0gKChMUERXT1JEKWxwKVsxXTsKCglyZXR1cm4gQVZJRVJSX09LOwogICAgICB9IGVsc2UgewoJLyogc2tpcCB0byBuZXh0IGNodW5rICovCgljYiAtPSAoKExQRFdPUkQpbHApWzFdICsgMiAqIHNpemVvZihEV09SRCk7CglscCArPSAoKExQRFdPUkQpbHApWzFdICsgMiAqIHNpemVvZihEV09SRCk7CiAgICAgIH0KICAgIH0KICB9CgogIC8qIHdhbnRlZCBjaHVuayBkb2Vzbid0IGV4aXN0ICovCiAgKnNpemUgPSAwOwoKICByZXR1cm4gQVZJRVJSX05PREFUQTsKfQoKLyogd3JpdGVzIGEgY2h1bmsgaW50byB0aGUgZXh0cmFjaHVuay1zdHJ1Y3R1cmUgKi8KSFJFU1VMVCBXcml0ZUV4dHJhQ2h1bmsoTFBFWFRSQUNIVU5LUyBleHRyYSxGT1VSQ0MgY2tpZCxMUENWT0lEIGxwRGF0YSwgTE9ORyBzaXplKQp7CiAgTFBEV09SRCBscDsKCiAgLyogcHJlLWNvbmRpdGlvbnMgKi8KICBhc3NlcnQoZXh0cmEgIT0gTlVMTCk7CiAgYXNzZXJ0KGxwRGF0YSAhPSBOVUxMKTsKICBhc3NlcnQoc2l6ZSA+IDApOwoKICBpZiAoZXh0cmEtPmxwKQogICAgbHAgPSBIZWFwUmVBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBleHRyYS0+bHAsIGV4dHJhLT5jYiArIHNpemUgKyAyICogc2l6ZW9mKERXT1JEKSk7CiAgZWxzZQogICAgbHAgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgc2l6ZSArIDIgKiBzaXplb2YoRFdPUkQpKTsKCiAgaWYgKGxwID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKCiAgZXh0cmEtPmxwICA9IGxwOwogIGxwID0gKExQRFdPUkQpICgoTFBCWVRFKWxwICsgZXh0cmEtPmNiKTsKICBleHRyYS0+Y2IgKz0gc2l6ZSArIDIgKiBzaXplb2YoRFdPUkQpOwoKICAvKiBpbnNlcnQgY2h1bmstaGVhZGVyIGluIGJsb2NrICovCiAgbHBbMF0gPSBja2lkOwogIGxwWzFdID0gc2l6ZTsKCiAgaWYgKGxwRGF0YSAhPSBOVUxMICYmIHNpemUgPiAwKQogICAgbWVtY3B5KGxwICsgMiwgbHBEYXRhLCBzaXplKTsKCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKLyogcmVhZHMgYSBjaHVuayBmb21yIHRoZSBITU1JTyBpbnRvIHRoZSBleHRyYWNodW5rLXN0cnVjdHVyZSAqLwpIUkVTVUxUIFJlYWRDaHVua0ludG9FeHRyYShMUEVYVFJBQ0hVTktTIGV4dHJhLEhNTUlPIGhtbWlvLGNvbnN0IE1NQ0tJTkZPICpscGNrKQp7CiAgTFBEV09SRCBscDsKICBEV09SRCAgIGNiOwoKICAvKiBwcmUtY29uZGl0aW9ucyAqLwogIGFzc2VydChleHRyYSAhPSBOVUxMKTsKICBhc3NlcnQoaG1taW8gIT0gTlVMTCk7CiAgYXNzZXJ0KGxwY2sgICE9IE5VTEwpOwoKICBjYiAgPSBscGNrLT5ja3NpemUgKyAyICogc2l6ZW9mKERXT1JEKTsKICBjYiArPSAoY2IgJiAxKTsKCiAgaWYgKGV4dHJhLT5scCAhPSBOVUxMKQogICAgbHAgPSBIZWFwUmVBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBleHRyYS0+bHAsIGV4dHJhLT5jYiArIGNiKTsKICBlbHNlCiAgICBscCA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBjYik7CgogIGlmIChscCA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogIGV4dHJhLT5scCAgPSBscDsKICBscCA9IChMUERXT1JEKSAoKExQQllURSlscCArIGV4dHJhLT5jYik7CiAgZXh0cmEtPmNiICs9IGNiOwoKICAvKiBpbnNlcnQgY2h1bmstaGVhZGVyIGluIGJsb2NrICovCiAgbHBbMF0gPSBscGNrLT5ja2lkOwogIGxwWzFdID0gbHBjay0+Y2tzaXplOwoKICBpZiAobHBjay0+Y2tzaXplID4gMCkgewogICAgaWYgKG1taW9TZWVrKGhtbWlvLCBscGNrLT5kd0RhdGFPZmZzZXQsIFNFRUtfU0VUKSA9PSAtMSkKICAgICAgcmV0dXJuIEFWSUVSUl9GSUxFUkVBRDsKICAgIGlmIChtbWlvUmVhZChobW1pbywgKEhQU1RSKSZscFsyXSwgbHBjay0+Y2tzaXplKSAhPSAoTE9ORylscGNrLT5ja3NpemUpCiAgICAgIHJldHVybiBBVklFUlJfRklMRVJFQUQ7CiAgfQoKICByZXR1cm4gQVZJRVJSX09LOwp9CgovKiByZWFkcyBhbGwgbm9uLWp1bmsgY2h1bmtzIGludG8gdGhlIGV4dHJhY2h1bmstc3RydWN0dXJlIHVudGlsIGl0IGZpbmRzCiAqIHRoZSBnaXZlbiBjaHVuayBvciB0aGUgb3B0aW9uYWwgcGFyZW50LWNodW5rIGlzIGF0IHRoZSBlbmQgKi8KSFJFU1VMVCBGaW5kQ2h1bmtBbmRLZWVwRXh0cmFzKExQRVhUUkFDSFVOS1MgZXh0cmEsSE1NSU8gaG1taW8sTU1DS0lORk8gKmxwY2ssCgkJCSAgICAgICBNTUNLSU5GTyAqbHBja1BhcmVudCxVSU5UIGZsYWdzKQp7CiAgRk9VUkNDICBja2lkOwogIEZPVVJDQyAgZmNjVHlwZTsKICBIUkVTVUxUIGhyOwoKICAvKiBwcmUtY29uZGl0aW9ucyAqLwogIGFzc2VydChleHRyYSAhPSBOVUxMKTsKICBhc3NlcnQoaG1taW8gIT0gTlVMTCk7CiAgYXNzZXJ0KGxwY2sgICE9IE5VTEwpOwoKICBUUkFDRSgiKHslcCwldX0sJXAsJXAsJXAsMHglWClcbiIsIGV4dHJhLT5scCwgZXh0cmEtPmNiLCBobW1pbywgbHBjaywKCWxwY2tQYXJlbnQsIGZsYWdzKTsKCiAgLyogd2hhdCBjaHVuayBpZCBhbmQgZm9ybS9saXN0IHR5cGUgc2hvdWxkIHdlIHNlYXJjaD8gKi8KICBpZiAoZmxhZ3MgJiBNTUlPX0ZJTkRDSFVOSykgewogICAgY2tpZCAgICA9IGxwY2stPmNraWQ7CiAgICBmY2NUeXBlID0gMDsKICB9IGVsc2UgaWYgKGZsYWdzICYgTU1JT19GSU5ETElTVCkgewogICAgY2tpZCAgICA9IEZPVVJDQ19MSVNUOwogICAgZmNjVHlwZSA9IGxwY2stPmZjY1R5cGU7CiAgfSBlbHNlIGlmIChmbGFncyAmIE1NSU9fRklORFJJRkYpIHsKICAgIGNraWQgICAgPSBGT1VSQ0NfUklGRjsKICAgIGZjY1R5cGUgPSBscGNrLT5mY2NUeXBlOwogIH0gZWxzZQogICAgY2tpZCA9IGZjY1R5cGUgPSAoRk9VUkNDKS0xOyAvKiBjb2xsZWN0IGV2ZXJ5dGhpbmcgaW50byBleHRyYSEgKi8KCiAgVFJBQ0UoIjogZmluZCBja2lkPTB4JTA4WCBmY2NUeXBlPTB4JTA4WFxuIiwgY2tpZCwgZmNjVHlwZSk7CgogIGZvciAoOzspIHsKICAgIGhyID0gbW1pb0Rlc2NlbmQoaG1taW8sIGxwY2ssIGxwY2tQYXJlbnQsIDApOwogICAgaWYgKGhyICE9IFNfT0spIHsKICAgICAgLyogTm8gZXh0cmEgY2h1bmtzIGluIGZyb250IG9mIGRlc2lyZWQgY2h1bms/ICovCiAgICAgIGlmIChmbGFncyA9PSAwICYmIGhyID09IE1NSU9FUlJfQ0hVTktOT1RGT1VORCkKCWhyID0gQVZJRVJSX09LOwogICAgICByZXR1cm4gaHI7CiAgICB9CgogICAgLyogSGF2ZSB3ZSBmb3VuZCB3aGF0IHdlIHNlYXJjaCBmb3I/ICovCiAgICBpZiAoKGxwY2stPmNraWQgPT0gY2tpZCkgJiYKCShmY2NUeXBlID09IChGT1VSQ0MpMCB8fCBscGNrLT5mY2NUeXBlID09IGZjY1R5cGUpKQogICAgICByZXR1cm4gQVZJRVJSX09LOwoKICAgIC8qIFNraXAgcGFkZGluZyBjaHVua3MsIHRoZSBvdGhlcnMgcHV0IGludG8gdGhlIGV4dHJhY2h1bmstc3RydWN0dXJlICovCiAgICBpZiAobHBjay0+Y2tpZCA9PSBja2lkQVZJUEFERElORyB8fAoJbHBjay0+Y2tpZCA9PSBtbWlvRk9VUkNDKCdwJywnYScsJ2QnLCdkJykpCiAgICAgIGhyID0gbW1pb0FzY2VuZChobW1pbywgbHBjaywgMCk7CiAgICBlbHNlCiAgICAgIGhyID0gUmVhZENodW5rSW50b0V4dHJhKGV4dHJhLCBobW1pbywgbHBjayk7CiAgICBpZiAoRkFJTEVEKGhyKSkKICAgICAgcmV0dXJuIGhyOwogIH0KfQo=