Ly8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBUb25lIG1hcHBpbmcgb3BlcmF0b3IgKEZhdHRhbCwgMjAwMikKLy8KLy8gRGVzaWduIGFuZCBpbXBsZW1lbnRhdGlvbiBieQovLyAtIEhlcnbpIERyb2xvbiAoZHJvbG9uQGluZm9uaWUuZnIpCi8vCi8vIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEZyZWVJbWFnZSAzCi8vCi8vIENPVkVSRUQgQ09ERSBJUyBQUk9WSURFRCBVTkRFUiBUSElTIExJQ0VOU0UgT04gQU4gIkFTIElTIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5UWQovLyBPRiBBTlkgS0lORCwgRUlUSEVSIEVYUFJFU1NFRCBPUiBJTVBMSUVELCBJTkNMVURJTkcsIFdJVEhPVVQgTElNSVRBVElPTiwgV0FSUkFOVElFUwovLyBUSEFUIFRIRSBDT1ZFUkVEIENPREUgSVMgRlJFRSBPRiBERUZFQ1RTLCBNRVJDSEFOVEFCTEUsIEZJVCBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UKLy8gT1IgTk9OLUlORlJJTkdJTkcuIFRIRSBFTlRJUkUgUklTSyBBUyBUTyBUSEUgUVVBTElUWSBBTkQgUEVSRk9STUFOQ0UgT0YgVEhFIENPVkVSRUQKLy8gQ09ERSBJUyBXSVRIIFlPVS4gU0hPVUxEIEFOWSBDT1ZFUkVEIENPREUgUFJPVkUgREVGRUNUSVZFIElOIEFOWSBSRVNQRUNULCBZT1UgKE5PVAovLyBUSEUgSU5JVElBTCBERVZFTE9QRVIgT1IgQU5ZIE9USEVSIENPTlRSSUJVVE9SKSBBU1NVTUUgVEhFIENPU1QgT0YgQU5ZIE5FQ0VTU0FSWQovLyBTRVJWSUNJTkcsIFJFUEFJUiBPUiBDT1JSRUNUSU9OLiBUSElTIERJU0NMQUlNRVIgT0YgV0FSUkFOVFkgQ09OU1RJVFVURVMgQU4gRVNTRU5USUFMCi8vIFBBUlQgT0YgVEhJUyBMSUNFTlNFLiBOTyBVU0UgT0YgQU5ZIENPVkVSRUQgQ09ERSBJUyBBVVRIT1JJWkVEIEhFUkVVTkRFUiBFWENFUFQgVU5ERVIKLy8gVEhJUyBESVNDTEFJTUVSLgovLwovLyBVc2UgYXQgeW91ciBvd24gcmlzayEKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKI2luY2x1ZGUgPGNtYXRoPgoKI2luY2x1ZGUgIkZyZWVJbWFnZS5oIgojaW5jbHVkZSAiVXRpbGl0aWVzLmgiCiNpbmNsdWRlICJUb25lTWFwcGluZy5oIgoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBHcmFkaWVudCBkb21haW4gSERSIGNvbXByZXNzaW9uCi8vIFJlZmVyZW5jZToKLy8gWzFdIFIuIEZhdHRhbCwgRC4gTGlzY2hpbnNraSwgYW5kIE0uV2VybWFuLCAKLy8gR3JhZGllbnQgZG9tYWluIGhpZ2ggZHluYW1pYyByYW5nZSBjb21wcmVzc2lvbiwKLy8gQUNNIFRyYW5zYWN0aW9ucyBvbiBHcmFwaGljcywgc3BlY2lhbCBpc3N1ZSBvbiBQcm9jLiBvZiBBQ00gU0lHR1JBUEggMjAwMiwgCi8vIFNhbiBBbnRvbmlvLCBUZXhhcywgdm9sLiAyMSgzKSwgcHAuIDI1Ny0yNjYsIDIwMDIuCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnN0YXRpYyBjb25zdCBmbG9hdCBFUFNJTE9OID0gMWUtNEY7CgovKioKUGVyZm9ybXMgYSA1IGJ5IDUgZ2F1c3NpYW4gZmlsdGVyaW5nIHVzaW5nIHR3byAxRCBjb252b2x1dGlvbnMsIApmb2xsb3dlZCBieSBhIHN1YnNhbXBsaW5nIGJ5IDIuIApAcGFyYW0gZGliIElucHV0IGltYWdlCkByZXR1cm4gUmV0dXJucyBhIGJsdXJyZWQgaW1hZ2Ugb2Ygc2l6ZSBTSVpFKGRpYikvMgpAc2VlIEdhdXNzaWFuUHlyYW1pZAoqLwpzdGF0aWMgRklCSVRNQVAqIEdhdXNzaWFuTGV2ZWw1eDUoRklCSVRNQVAgKmRpYikgewoJRklCSVRNQVAgKmhfZGliID0gTlVMTCwgKnZfZGliID0gTlVMTCwgKmRzdCA9IE5VTEw7CglmbG9hdCAqc3JjX3BpeGVsLCAqZHN0X3BpeGVsOwoKCXRyeSB7CgkJY29uc3QgRlJFRV9JTUFHRV9UWVBFIGltYWdlX3R5cGUgPSBGcmVlSW1hZ2VfR2V0SW1hZ2VUeXBlKGRpYik7CgkJaWYoaW1hZ2VfdHlwZSAhPSBGSVRfRkxPQVQpIHRocm93KDEpOwoKCQljb25zdCB1bnNpZ25lZCB3aWR0aCA9IEZyZWVJbWFnZV9HZXRXaWR0aChkaWIpOwoJCWNvbnN0IHVuc2lnbmVkIGhlaWdodCA9IEZyZWVJbWFnZV9HZXRIZWlnaHQoZGliKTsKCgkJaF9kaWIgPSBGcmVlSW1hZ2VfQWxsb2NhdGVUKGltYWdlX3R5cGUsIHdpZHRoLCBoZWlnaHQpOwoJCXZfZGliID0gRnJlZUltYWdlX0FsbG9jYXRlVChpbWFnZV90eXBlLCB3aWR0aCwgaGVpZ2h0KTsKCQlpZighaF9kaWIgfHwgIXZfZGliKSB0aHJvdygxKTsKCgkJY29uc3QgdW5zaWduZWQgcGl0Y2ggPSBGcmVlSW1hZ2VfR2V0UGl0Y2goZGliKSAvIHNpemVvZihmbG9hdCk7CgoJCS8vIGhvcml6b250YWwgY29udm9sdXRpb24gZGliIC0+IGhfZGliCgoJCXNyY19waXhlbCA9IChmbG9hdCopRnJlZUltYWdlX0dldEJpdHMoZGliKTsKCQlkc3RfcGl4ZWwgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKGhfZGliKTsKCgkJZm9yKHVuc2lnbmVkIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQkJLy8gd29yayBvbiBsaW5lIHkKCQkJZm9yKHVuc2lnbmVkIHggPSAyOyB4IDwgd2lkdGggLSAyOyB4KyspIHsKCQkJCWRzdF9waXhlbFt4XSA9IHNyY19waXhlbFt4LTJdICsgc3JjX3BpeGVsW3grMl0gKyA0ICogKHNyY19waXhlbFt4LTFdICsgc3JjX3BpeGVsW3grMV0pICsgNiAqIHNyY19waXhlbFt4XTsKCQkJCWRzdF9waXhlbFt4XSAvPSAxNjsKCQkJfQoJCQkvLyBib3VuZGFyeSBtaXJyb3JpbmcKCQkJZHN0X3BpeGVsWzBdID0gKDIgKiBzcmNfcGl4ZWxbMl0gKyA4ICogc3JjX3BpeGVsWzFdICsgNiAqIHNyY19waXhlbFswXSkgLyAxNjsKCQkJZHN0X3BpeGVsWzFdID0gKHNyY19waXhlbFszXSArIDQgKiAoc3JjX3BpeGVsWzBdICsgc3JjX3BpeGVsWzJdKSArIDcgKiBzcmNfcGl4ZWxbMV0pIC8gMTY7CgkJCWRzdF9waXhlbFt3aWR0aC0yXSA9IChzcmNfcGl4ZWxbd2lkdGgtNF0gKyA1ICogc3JjX3BpeGVsW3dpZHRoLTFdICsgNCAqIHNyY19waXhlbFt3aWR0aC0zXSArIDYgKiBzcmNfcGl4ZWxbd2lkdGgtMl0pIC8gMTY7CgkJCWRzdF9waXhlbFt3aWR0aC0xXSA9IChzcmNfcGl4ZWxbd2lkdGgtM10gKyA1ICogc3JjX3BpeGVsW3dpZHRoLTJdICsgMTAgKiBzcmNfcGl4ZWxbd2lkdGgtMV0pIC8gMTY7CgoJCQkvLyBuZXh0IGxpbmUKCQkJc3JjX3BpeGVsICs9IHBpdGNoOwoJCQlkc3RfcGl4ZWwgKz0gcGl0Y2g7CgkJfQoKCQkvLyB2ZXJ0aWNhbCBjb252b2x1dGlvbiBoX2RpYiAtPiB2X2RpYgoKCQlzcmNfcGl4ZWwgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKGhfZGliKTsKCQlkc3RfcGl4ZWwgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKHZfZGliKTsKCgkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewkJCgkJCS8vIHdvcmsgb24gY29sdW1uIHgKCQkJZm9yKHVuc2lnbmVkIHkgPSAyOyB5IDwgaGVpZ2h0IC0gMjsgeSsrKSB7CgkJCQljb25zdCB1bnNpZ25lZCBpbmRleCA9IHkqcGl0Y2ggKyB4OwoJCQkJZHN0X3BpeGVsW2luZGV4XSA9IHNyY19waXhlbFtpbmRleC0yKnBpdGNoXSArIHNyY19waXhlbFtpbmRleCsyKnBpdGNoXSArIDQgKiAoc3JjX3BpeGVsW2luZGV4LXBpdGNoXSArIHNyY19waXhlbFtpbmRleCtwaXRjaF0pICsgNiAqIHNyY19waXhlbFtpbmRleF07CgkJCQlkc3RfcGl4ZWxbaW5kZXhdIC89IDE2OwoJCQl9CgkJCS8vIGJvdW5kYXJ5IG1pcnJvcmluZwoJCQlkc3RfcGl4ZWxbeF0gPSAoMiAqIHNyY19waXhlbFt4KzIqcGl0Y2hdICsgOCAqIHNyY19waXhlbFt4K3BpdGNoXSArIDYgKiBzcmNfcGl4ZWxbeF0pIC8gMTY7CgkJCWRzdF9waXhlbFt4K3BpdGNoXSA9IChzcmNfcGl4ZWxbeCszKnBpdGNoXSArIDQgKiAoc3JjX3BpeGVsW3hdICsgc3JjX3BpeGVsW3grMipwaXRjaF0pICsgNyAqIHNyY19waXhlbFt4K3BpdGNoXSkgLyAxNjsKCQkJZHN0X3BpeGVsWyhoZWlnaHQtMikqcGl0Y2greF0gPSAoc3JjX3BpeGVsWyhoZWlnaHQtNCkqcGl0Y2greF0gKyA1ICogc3JjX3BpeGVsWyhoZWlnaHQtMSkqcGl0Y2greF0gKyA0ICogc3JjX3BpeGVsWyhoZWlnaHQtMykqcGl0Y2greF0gKyA2ICogc3JjX3BpeGVsWyhoZWlnaHQtMikqcGl0Y2greF0pIC8gMTY7CgkJCWRzdF9waXhlbFsoaGVpZ2h0LTEpKnBpdGNoK3hdID0gKHNyY19waXhlbFsoaGVpZ2h0LTMpKnBpdGNoK3hdICsgNSAqIHNyY19waXhlbFsoaGVpZ2h0LTIpKnBpdGNoK3hdICsgMTAgKiBzcmNfcGl4ZWxbKGhlaWdodC0xKSpwaXRjaCt4XSkgLyAxNjsKCQl9CgoJCUZyZWVJbWFnZV9VbmxvYWQoaF9kaWIpOyBoX2RpYiA9IE5VTEw7CgoJCS8vIHBlcmZvcm0gZG93bnNhbXBsaW5nCgoJCWRzdCA9IEZyZWVJbWFnZV9SZXNjYWxlKHZfZGliLCB3aWR0aC8yLCBoZWlnaHQvMiwgRklMVEVSX0JJTElORUFSKTsKCgkJRnJlZUltYWdlX1VubG9hZCh2X2RpYik7CgoJCXJldHVybiBkc3Q7CgoJfSBjYXRjaChpbnQpIHsKCQlpZihoX2RpYikgRnJlZUltYWdlX1VubG9hZChoX2RpYik7CgkJaWYodl9kaWIpIEZyZWVJbWFnZV9VbmxvYWQodl9kaWIpOwoJCWlmKGRzdCkgRnJlZUltYWdlX1VubG9hZChkc3QpOwoJCXJldHVybiBOVUxMOwoJfQp9CgovKioKQ29tcHV0ZSBhIEdhdXNzaWFuIHB5cmFtaWQgdXNpbmcgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgbGV2ZWxzLiAKQHBhcmFtIEggT3JpZ2luYWwgYml0bWFwCkBwYXJhbSBweXJhbWlkIFJlc3VsdGluZyBweXJhbWlkIGFycmF5IApAcGFyYW0gbmxldmVscyBOdW1iZXIgb2YgcmVzb2x1dGlvbiBsZXZlbHMKQHJldHVybiBSZXR1cm5zIFRSVUUgaWYgc3VjY2Vzc2Z1bCwgcmV0dXJucyBGQUxTRSBvdGhlcndpc2UKKi8Kc3RhdGljIEJPT0wgR2F1c3NpYW5QeXJhbWlkKEZJQklUTUFQICpILCBGSUJJVE1BUCAqKnB5cmFtaWQsIGludCBubGV2ZWxzKSB7Cgl0cnkgewoJCS8vIGZpcnN0IGxldmVsIGlzIHRoZSBvcmlnaW5hbCBpbWFnZQoJCXB5cmFtaWRbMF0gPSBGcmVlSW1hZ2VfQ2xvbmUoSCk7CgkJaWYocHlyYW1pZFswXSA9PSBOVUxMKSB0aHJvdygxKTsKCQkvLyBjb21wdXRlIG5leHQgbGV2ZWxzCgkJZm9yKGludCBrID0gMTsgayA8IG5sZXZlbHM7IGsrKykgewoJCQlweXJhbWlkW2tdID0gR2F1c3NpYW5MZXZlbDV4NShweXJhbWlkW2stMV0pOwoJCQlpZihweXJhbWlkW2tdID09IE5VTEwpIHRocm93KDEpOwoJCX0KCQlyZXR1cm4gVFJVRTsKCX0gY2F0Y2goaW50KSB7CgkJZm9yKGludCBrID0gMDsgayA8IG5sZXZlbHM7IGsrKykgewoJCQlpZihweXJhbWlkW2tdICE9IE5VTEwpIHsKCQkJCUZyZWVJbWFnZV9VbmxvYWQocHlyYW1pZFtrXSk7CgkJCQlweXJhbWlkW2tdID0gTlVMTDsKCQkJfQoJCX0KCQlyZXR1cm4gRkFMU0U7Cgl9Cn0KCi8qKgpDb21wdXRlIHRoZSBncmFkaWVudCBtYWduaXR1ZGUgb2YgYW4gaW5wdXQgaW1hZ2UgSCB1c2luZyBjZW50cmFsIGRpZmZlcmVuY2VzLCAKYW5kIHJldHVybnMgdGhlIGF2ZXJhZ2UgZ3JhZGllbnQuIApAcGFyYW0gSCBJbnB1dCBpbWFnZQpAcGFyYW0gYXZnR3JhZCBbb3V0XSBBdmVyYWdlIGdyYWRpZW50CkBwYXJhbSBrIExldmVsIG51bWJlcgpAcmV0dXJuIFJldHVybnMgdGhlIGdyYWRpZW50IG1hZ25pdHVkZSBpZiBzdWNjZXNzZnVsLCByZXR1cm5zIE5VTEwgb3RoZXJ3aXNlCkBzZWUgR3JhZGllbnRQeXJhbWlkCiovCnN0YXRpYyBGSUJJVE1BUCogR3JhZGllbnRMZXZlbChGSUJJVE1BUCAqSCwgZmxvYXQgKmF2Z0dyYWQsIGludCBrKSB7CglGSUJJVE1BUCAqRyA9IE5VTEw7CgoJdHJ5IHsKCQljb25zdCBGUkVFX0lNQUdFX1RZUEUgaW1hZ2VfdHlwZSA9IEZyZWVJbWFnZV9HZXRJbWFnZVR5cGUoSCk7CgkJaWYoaW1hZ2VfdHlwZSAhPSBGSVRfRkxPQVQpIHRocm93KDEpOwoKCQljb25zdCB1bnNpZ25lZCB3aWR0aCA9IEZyZWVJbWFnZV9HZXRXaWR0aChIKTsKCQljb25zdCB1bnNpZ25lZCBoZWlnaHQgPSBGcmVlSW1hZ2VfR2V0SGVpZ2h0KEgpOwoKCQlHID0gRnJlZUltYWdlX0FsbG9jYXRlVChpbWFnZV90eXBlLCB3aWR0aCwgaGVpZ2h0KTsKCQlpZighRykgdGhyb3coMSk7CgkJCgkJY29uc3QgdW5zaWduZWQgcGl0Y2ggPSBGcmVlSW1hZ2VfR2V0UGl0Y2goSCkgLyBzaXplb2YoZmxvYXQpOwoJCQoJCWNvbnN0IGZsb2F0IGRpdmlkZXIgPSAoZmxvYXQpKDEgPDwgKGsgKyAxKSk7CgkJZmxvYXQgYXZlcmFnZSA9IDA7CgkJCgkJZmxvYXQgKnNyY19waXhlbCA9IChmbG9hdCopRnJlZUltYWdlX0dldEJpdHMoSCk7CgkJZmxvYXQgKmRzdF9waXhlbCA9IChmbG9hdCopRnJlZUltYWdlX0dldEJpdHMoRyk7CgoJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCWNvbnN0IHVuc2lnbmVkIG4gPSAoeSA9PSAwID8gMCA6IHktMSk7CgkJCWNvbnN0IHVuc2lnbmVkIHMgPSAoeSsxID09IGhlaWdodCA/IHkgOiB5KzEpOwoJCQlmb3IodW5zaWduZWQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CgkJCQljb25zdCB1bnNpZ25lZCB3ID0gKHggPT0gMCA/IDAgOiB4LTEpOwoJCQkJY29uc3QgdW5zaWduZWQgZSA9ICh4KzEgPT0gd2lkdGggPyB4IDogeCsxKTsJCQoJCQkJLy8gY2VudHJhbCBkaWZmZXJlbmNlCgkJCQljb25zdCBmbG9hdCBneCA9IChzcmNfcGl4ZWxbeSpwaXRjaCtlXSAtIHNyY19waXhlbFt5KnBpdGNoK3ddKSAvIGRpdmlkZXI7IC8vIFtIayh4KzEsIHkpIC0gSGsoeC0xLCB5KV0gLyAyKiooaysxKQoJCQkJY29uc3QgZmxvYXQgZ3kgPSAoc3JjX3BpeGVsW3MqcGl0Y2greF0gLSBzcmNfcGl4ZWxbbipwaXRjaCt4XSkgLyBkaXZpZGVyOyAvLyBbSGsoeCwgeSsxKSAtIEhrKHgsIHktMSldIC8gMioqKGsrMSkKCQkJCS8vIGdyYWRpZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHN0X3BpeGVsW3hdID0gc3RkOjpzcXJ0KGd4ICogZ3ggKyBneSAqIGd5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhdmVyYWdlIGdyYWRpZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZlcmFnZSArPSBkc3RfcGl4ZWxbeF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KCQkJLy8gbmV4dCBsaW5lCgkJCWRzdF9waXhlbCArPSBwaXRjaDsKCQl9CgkJCgkJKmF2Z0dyYWQgPSBhdmVyYWdlIC8gKHdpZHRoICogaGVpZ2h0KTsKCgkJcmV0dXJuIEc7CgoJfSBjYXRjaChpbnQpIHsKCQlpZihHKSBGcmVlSW1hZ2VfVW5sb2FkKEcpOwoJCXJldHVybiBOVUxMOwoJfQp9CgovKioKQ2FsY3VsYXRlIGdyYWRpZW50IG1hZ25pdHVkZSBhbmQgaXRzIGF2ZXJhZ2UgdmFsdWUgb24gZWFjaCBweXJhbWlkIGxldmVsCkBwYXJhbSBweXJhbWlkIEdhdXNzaWFuIHB5cmFtaWQgKG5sZXZlbHMgbGV2ZWxzKQpAcGFyYW0gbmxldmVscyBOdW1iZXIgb2YgbGV2ZWxzCkBwYXJhbSBncmFkaWVudHMgW291dF0gR3JhZGllbnQgcHlyYW1pZCAobmxldmVscyBsZXZlbHMpCkBwYXJhbSBhdmdHcmFkIFtvdXRdIEF2ZXJhZ2UgZ3JhZGllbnQgb24gZWFjaCBsZXZlbCAoYXJyYXkgb2Ygc2l6ZSBubGV2ZWxzKQpAcmV0dXJuIFJldHVybnMgVFJVRSBpZiBzdWNjZXNzZnVsLCByZXR1cm5zIEZBTFNFIG90aGVyd2lzZQoqLwpzdGF0aWMgQk9PTCBHcmFkaWVudFB5cmFtaWQoRklCSVRNQVAgKipweXJhbWlkLCBpbnQgbmxldmVscywgRklCSVRNQVAgKipncmFkaWVudHMsIGZsb2F0ICphdmdHcmFkKSB7Cgl0cnkgewoJCWZvcihpbnQgayA9IDA7IGsgPCBubGV2ZWxzOyBrKyspIHsKCQkJRklCSVRNQVAgKkhrID0gcHlyYW1pZFtrXTsKCQkJZ3JhZGllbnRzW2tdID0gR3JhZGllbnRMZXZlbChIaywgJmF2Z0dyYWRba10sIGspOwoJCQlpZihncmFkaWVudHNba10gPT0gTlVMTCkgdGhyb3coMSk7CgkJfQoJCXJldHVybiBUUlVFOwoJfSBjYXRjaChpbnQpIHsKCQlmb3IoaW50IGsgPSAwOyBrIDwgbmxldmVsczsgaysrKSB7CgkJCWlmKGdyYWRpZW50c1trXSAhPSBOVUxMKSB7CgkJCQlGcmVlSW1hZ2VfVW5sb2FkKGdyYWRpZW50c1trXSk7CgkJCQlncmFkaWVudHNba10gPSBOVUxMOwoJCQl9CgkJfQoJCXJldHVybiBGQUxTRTsKCX0KfQoKLyoqCkNvbXB1dGUgdGhlIGdyYWRpZW50IGF0dGVudWF0aW9uIGZ1bmN0aW9uIFBISSh4LCB5KQpAcGFyYW0gZ3JhZGllbnRzIEdyYWRpZW50IHB5cmFtaWQgKG5sZXZlbHMgbGV2ZWxzKQpAcGFyYW0gYXZnR3JhZCBBdmVyYWdlIGdyYWRpZW50IG9uIGVhY2ggbGV2ZWwgKGFycmF5IG9mIHNpemUgbmxldmVscykKQHBhcmFtIG5sZXZlbHMgTnVtYmVyIG9mIGxldmVscwpAcGFyYW0gYWxwaGEgUGFyYW1ldGVyIGFscGhhIGluIHRoZSBwYXBlcgpAcGFyYW0gYmV0YSBQYXJhbWV0ZXIgYmV0YSBpbiB0aGUgcGFwZXIKQHJldHVybiBSZXR1cm5zIHRoZSBhdHRlbnVhdGlvbiBtYXRyaXggUGhpIGlmIHN1Y2Nlc3NmdWwsIHJldHVybnMgTlVMTCBvdGhlcndpc2UKKi8Kc3RhdGljIEZJQklUTUFQKiBQaGlNYXRyaXgoRklCSVRNQVAgKipncmFkaWVudHMsIGZsb2F0ICphdmdHcmFkLCBpbnQgbmxldmVscywgZmxvYXQgYWxwaGEsIGZsb2F0IGJldGEpIHsKCWZsb2F0ICpzcmNfcGl4ZWwsICpkc3RfcGl4ZWw7CglGSUJJVE1BUCAqKnBoaSA9IE5VTEw7CgoJdHJ5IHsKCQlwaGkgPSAoRklCSVRNQVAqKiltYWxsb2MobmxldmVscyAqIHNpemVvZihGSUJJVE1BUCopKTsKCQlpZighcGhpKSB0aHJvdygxKTsKCQltZW1zZXQocGhpLCAwLCBubGV2ZWxzICogc2l6ZW9mKEZJQklUTUFQKikpOwoKCQlmb3IoaW50IGsgPSBubGV2ZWxzLTE7IGsgPj0gMDsgay0tKSB7CgkJCS8vIGNvbXB1dGUgcGhpKGspCgoJCQlGSUJJVE1BUCAqR2sgPSBncmFkaWVudHNba107CgoJCQljb25zdCB1bnNpZ25lZCB3aWR0aCA9IEZyZWVJbWFnZV9HZXRXaWR0aChHayk7CgkJCWNvbnN0IHVuc2lnbmVkIGhlaWdodCA9IEZyZWVJbWFnZV9HZXRIZWlnaHQoR2spOwoJCQljb25zdCB1bnNpZ25lZCBwaXRjaCA9IEZyZWVJbWFnZV9HZXRQaXRjaChHaykgLyBzaXplb2YoZmxvYXQpOwoKCQkJLy8gcGFyYW1ldGVyIGFscGhhIGlzIDAuMSB0aW1lcyB0aGUgYXZlcmFnZSBncmFkaWVudCBtYWduaXR1ZGUKCQkJLy8gYWxzbywgbm90ZSB0aGUgZmFjdG9yIG9mIDIqKmsgaW4gdGhlIGRlbm9taW5hdG9yOyAKCQkJLy8gdGhhdCBpcyB0aGVyZSB0byBjb3JyZWN0IGZvciB0aGUgZmFjdCB0aGF0IGFuIGF2ZXJhZ2UgZ3JhZGllbnQgYXZnR3JhZChIKSBvdmVyIDIqKmsgcGl4ZWxzIAoJCQkvLyBpbiB0aGUgb3JpZ2luYWwgaW1hZ2Ugd2lsbCBhcHBlYXIgYXMgYSBncmFkaWVudCBncmFkKEhrKSA9IDIqKmsqYXZnR3JhZChIKSBvdmVyIGEgc2luZ2xlIHBpeGVsIGluIEhrLiAKCQkJZmxvYXQgQUxQSEEgPSAgYWxwaGEgKiBhdmdHcmFkW2tdICogKGZsb2F0KSgoaW50KTEgPDwgayk7CgkJCWlmKEFMUEhBID09IDApIEFMUEhBID0gRVBTSUxPTjsKCgkJCXBoaVtrXSA9IEZyZWVJbWFnZV9BbGxvY2F0ZVQoRklUX0ZMT0FULCB3aWR0aCwgaGVpZ2h0KTsKCQkJaWYoIXBoaVtrXSkgdGhyb3coMSk7CgkJCQoJCQlzcmNfcGl4ZWwgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKEdrKTsKCQkJZHN0X3BpeGVsID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhwaGlba10pOwoJCQlmb3IodW5zaWduZWQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewoJCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJCS8vIGNvbXB1dGUgKGFscGhhIC8gZ3JhZCkgKiAoZ3JhZCAvIGFscGhhKSAqKiBiZXRhCgkJCQkJY29uc3QgZmxvYXQgdiA9IHNyY19waXhlbFt4XSAvIEFMUEhBOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmxvYXQgdmFsdWUgPSAoZmxvYXQpc3RkOjpwb3coCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZsb2F0KXYsIChmbG9hdCkoYmV0YSAtIDEpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRzdF9waXhlbFt4XSA9ICh2YWx1ZSA+IDEpID8gMSA6IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KCQkJCS8vIG5leHQgbGluZQoJCQkJc3JjX3BpeGVsICs9IHBpdGNoOwoJCQkJZHN0X3BpeGVsICs9IHBpdGNoOwoJCQl9CgoJCQlpZihrIDwgbmxldmVscy0xKSB7CgkJCQkvLyBjb21wdXRlIFBISShrKSA9IEwoIFBISShrKzEpICkgKiBwaGkoaykKCQkJCUZJQklUTUFQICpMID0gRnJlZUltYWdlX1Jlc2NhbGUocGhpW2srMV0sIHdpZHRoLCBoZWlnaHQsIEZJTFRFUl9CSUxJTkVBUik7CgkJCQlpZighTCkgdGhyb3coMSk7CgoJCQkJc3JjX3BpeGVsID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhMKTsKCQkJCWRzdF9waXhlbCA9IChmbG9hdCopRnJlZUltYWdlX0dldEJpdHMocGhpW2tdKTsKCQkJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJCQlkc3RfcGl4ZWxbeF0gKj0gc3JjX3BpeGVsW3hdOwoJCQkJCX0KCQkJCQkvLyBuZXh0IGxpbmUKCQkJCQlzcmNfcGl4ZWwgKz0gcGl0Y2g7CgkJCQkJZHN0X3BpeGVsICs9IHBpdGNoOwoJCQkJfQoKCQkJCUZyZWVJbWFnZV9VbmxvYWQoTCk7CgoJCQkJLy8gUEhJKGsrMSkgaXMgbm8gbG9uZ2VyIG5lZWRlZAoJCQkJRnJlZUltYWdlX1VubG9hZChwaGlbaysxXSk7CgkJCQlwaGlbaysxXSA9IE5VTEw7CgkJCX0KCgkJCS8vIG5leHQgbGV2ZWwKCQl9CgoJCS8vIGdldCB0aGUgZmluYWwgcmVzdWx0IGFuZCByZXR1cm4KCQlGSUJJVE1BUCAqZHN0ID0gcGhpWzBdOwoKCQlmcmVlKHBoaSk7CgoJCXJldHVybiBkc3Q7CgoJfSBjYXRjaChpbnQpIHsKCQlpZihwaGkpIHsKCQkJZm9yKGludCBrID0gbmxldmVscy0xOyBrID49IDA7IGstLSkgewoJCQkJaWYocGhpW2tdKSBGcmVlSW1hZ2VfVW5sb2FkKHBoaVtrXSk7CgkJCX0KCQkJZnJlZShwaGkpOwoJCX0KCQlyZXR1cm4gTlVMTDsKCX0KfQoKLyoqCkNvbXB1dGUgZ3JhZGllbnRzIGluIHggYW5kIHkgZGlyZWN0aW9ucywgYXR0ZW51YXRlIHRoZW0gd2l0aCB0aGUgYXR0ZW51YXRpb24gbWF0cml4LCAKdGhlbiBjb21wdXRlIHRoZSBkaXZlcmdlbmNlIGRpdiBHIGZyb20gdGhlIGF0dGVudWF0ZWQgZ3JhZGllbnQuIApAcGFyYW0gSCBOb3JtYWxpemVkIGx1bWluYW5jZQpAcGFyYW0gUEhJIEF0dGVudWF0aW9uIG1hdHJpeApAcmV0dXJuIFJldHVybnMgdGhlIGRpdmVyZ2VuY2UgbWF0cml4IGlmIHN1Y2Nlc3NmdWwsIHJldHVybnMgTlVMTCBvdGhlcndpc2UKKi8Kc3RhdGljIEZJQklUTUFQKiBEaXZlcmdlbmNlKEZJQklUTUFQICpILCBGSUJJVE1BUCAqUEhJKSB7CglGSUJJVE1BUCAqR3ggPSBOVUxMLCAqR3kgPSBOVUxMLCAqZGl2RyA9IE5VTEw7CglmbG9hdCAqcGhpLCAqaCwgKmd4LCAqZ3ksICpkaXZnOwoKCXRyeSB7CgkJY29uc3QgRlJFRV9JTUFHRV9UWVBFIGltYWdlX3R5cGUgPSBGcmVlSW1hZ2VfR2V0SW1hZ2VUeXBlKEgpOwoJCWlmKGltYWdlX3R5cGUgIT0gRklUX0ZMT0FUKSB0aHJvdygxKTsKCgkJY29uc3QgdW5zaWduZWQgd2lkdGggPSBGcmVlSW1hZ2VfR2V0V2lkdGgoSCk7CgkJY29uc3QgdW5zaWduZWQgaGVpZ2h0ID0gRnJlZUltYWdlX0dldEhlaWdodChIKTsKCgkJR3ggPSBGcmVlSW1hZ2VfQWxsb2NhdGVUKGltYWdlX3R5cGUsIHdpZHRoLCBoZWlnaHQpOwoJCWlmKCFHeCkgdGhyb3coMSk7CgkJR3kgPSBGcmVlSW1hZ2VfQWxsb2NhdGVUKGltYWdlX3R5cGUsIHdpZHRoLCBoZWlnaHQpOwoJCWlmKCFHeSkgdGhyb3coMSk7CgkJCgkJY29uc3QgdW5zaWduZWQgcGl0Y2ggPSBGcmVlSW1hZ2VfR2V0UGl0Y2goSCkgLyBzaXplb2YoZmxvYXQpOwoJCQoJCS8vIHBlcmZvcm0gZ3JhZGllbnQgYXR0ZW51YXRpb24KCgkJcGhpID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhQSEkpOwoJCWggICA9IChmbG9hdCopRnJlZUltYWdlX0dldEJpdHMoSCk7CgkJZ3ggID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhHeCk7CgkJZ3kgID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhHeSk7CgoJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCWNvbnN0IHVuc2lnbmVkIHMgPSAoeSsxID09IGhlaWdodCA/IHkgOiB5KzEpOwoJCQlmb3IodW5zaWduZWQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CQkJCQoJCQkJY29uc3QgdW5zaWduZWQgZSA9ICh4KzEgPT0gd2lkdGggPyB4IDogeCsxKTsKCQkJCS8vIGZvcndhcmQgZGlmZmVyZW5jZQoJCQkJY29uc3QgdW5zaWduZWQgaW5kZXggPSB5KnBpdGNoICsgeDsKCQkJCWNvbnN0IGZsb2F0IHBoaV94eSA9IHBoaVtpbmRleF07CgkJCQljb25zdCBmbG9hdCBoX3h5ICAgPSBoW2luZGV4XTsKCQkJCWd4W3hdID0gKGhbeSpwaXRjaCtlXSAtIGhfeHkpICogcGhpX3h5OyAvLyBbSCh4KzEsIHkpIC0gSCh4LCB5KV0gKiBQSEkoeCwgeSkKCQkJCWd5W3hdID0gKGhbcypwaXRjaCt4XSAtIGhfeHkpICogcGhpX3h5OyAvLyBbSCh4LCB5KzEpIC0gSCh4LCB5KV0gKiBQSEkoeCwgeSkKCQkJfQoJCQkvLyBuZXh0IGxpbmUKCQkJZ3ggKz0gcGl0Y2g7CgkJCWd5ICs9IHBpdGNoOwoJCX0KCgkJLy8gY2FsY3VsYXRlIHRoZSBkaXZlcmdlbmNlCgoJCWRpdkcgPSBGcmVlSW1hZ2VfQWxsb2NhdGVUKGltYWdlX3R5cGUsIHdpZHRoLCBoZWlnaHQpOwoJCWlmKCFkaXZHKSB0aHJvdygxKTsKCQkKCQlneCAgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKEd4KTsKCQlneSAgPSAoZmxvYXQqKUZyZWVJbWFnZV9HZXRCaXRzKEd5KTsKCQlkaXZnID0gKGZsb2F0KilGcmVlSW1hZ2VfR2V0Qml0cyhkaXZHKTsKCgkJZm9yKHVuc2lnbmVkIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewkJCQkKCQkJCS8vIGJhY2t3YXJkIGRpZmZlcmVuY2UgYXBwcm94aW1hdGlvbgoJCQkJLy8gZGl2RyA9IEd4KHgsIHkpIC0gR3goeC0xLCB5KSArIEd5KHgsIHkpIC0gR3koeCwgeS0xKQoJCQkJY29uc3QgdW5zaWduZWQgaW5kZXggPSB5KnBpdGNoICsgeDsKCQkJCWRpdmdbaW5kZXhdID0gZ3hbaW5kZXhdICsgZ3lbaW5kZXhdOwoJCQkJaWYoeCA+IDApIGRpdmdbaW5kZXhdIC09IGd4W2luZGV4LTFdOwoJCQkJaWYoeSA+IDApIGRpdmdbaW5kZXhdIC09IGd5W2luZGV4LXBpdGNoXTsKCQkJfQoJCX0KCgkJLy8gbm8gbG9uZ2VyIG5lZWRlZCAuLi4gCgkJRnJlZUltYWdlX1VubG9hZChHeCk7CgkJRnJlZUltYWdlX1VubG9hZChHeSk7CgoJCS8vIHJldHVybiB0aGUgZGl2ZXJnZW5jZQoJCXJldHVybiBkaXZHOwoKCX0gY2F0Y2goaW50KSB7CgkJaWYoR3gpIEZyZWVJbWFnZV9VbmxvYWQoR3gpOwoJCWlmKEd5KSBGcmVlSW1hZ2VfVW5sb2FkKEd5KTsKCQlpZihkaXZHKSBGcmVlSW1hZ2VfVW5sb2FkKGRpdkcpOwoJCXJldHVybiBOVUxMOwoJfQp9CgovKioKR2l2ZW4gdGhlIGx1bWluYW5jZSBjaGFubmVsLCBmaW5kIG1heCAmIG1pbiBsdW1pbmFuY2UgdmFsdWVzLCAKbm9ybWFsaXplIHRvIHJhbmdlIDAuLjEwMCBhbmQgdGFrZSB0aGUgbG9nYXJpdGhtLiAKQHBhcmFtIFkgSW1hZ2UgbHVtaW5hbmNlCkByZXR1cm4gUmV0dXJucyB0aGUgbm9ybWFsaXplZCBsdW1pbmFuY2UgSCBpZiBzdWNjZXNzZnVsLCByZXR1cm5zIE5VTEwgb3RoZXJ3aXNlCiovCnN0YXRpYyBGSUJJVE1BUCogTG9nTHVtaW5hbmNlKEZJQklUTUFQICpZKSB7CglGSUJJVE1BUCAqSCA9IE5VTEw7CgoJdHJ5IHsKCQkvLyBnZXQgdGhlIGx1bWluYW5jZSBjaGFubmVsCgkJRklCSVRNQVAgKkggPSBGcmVlSW1hZ2VfQ2xvbmUoWSk7CgkJaWYoIUgpIHRocm93KDEpOwoKCQljb25zdCB1bnNpZ25lZCB3aWR0aCAgPSBGcmVlSW1hZ2VfR2V0V2lkdGgoSCk7CgkJY29uc3QgdW5zaWduZWQgaGVpZ2h0ID0gRnJlZUltYWdlX0dldEhlaWdodChIKTsKCQljb25zdCB1bnNpZ25lZCBwaXRjaCAgPSBGcmVlSW1hZ2VfR2V0UGl0Y2goSCk7CgoJCS8vIGZpbmQgbWF4ICYgbWluIGx1bWluYW5jZSB2YWx1ZXMKCQlmbG9hdCBtYXhMdW0gPSAtMWUyMEYsIG1pbkx1bSA9IDFlMjBGOwoKCQlCWVRFICpiaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKEgpOwoJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCWNvbnN0IGZsb2F0ICpwaXhlbCA9IChmbG9hdCopYml0czsKCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJY29uc3QgZmxvYXQgdmFsdWUgPSBwaXhlbFt4XTsKCQkJCW1heEx1bSA9IChtYXhMdW0gPCB2YWx1ZSkgPyB2YWx1ZSA6IG1heEx1bTsJLy8gbWF4IEx1bWluYW5jZSBpbiB0aGUgc2NlbmUKCQkJCW1pbkx1bSA9IChtaW5MdW0gPCB2YWx1ZSkgPyBtaW5MdW0gOiB2YWx1ZTsJLy8gbWluIEx1bWluYW5jZSBpbiB0aGUgc2NlbmUKCQkJfQoJCQkvLyBuZXh0IGxpbmUKCQkJYml0cyArPSBwaXRjaDsKCQl9CgkJaWYobWF4THVtID09IG1pbkx1bSkgdGhyb3coMSk7CgoJCS8vIG5vcm1hbGl6ZSB0byByYW5nZSAwLi4xMDAgYW5kIHRha2UgdGhlIGxvZ2FyaXRobQoJCWNvbnN0IGZsb2F0IHNjYWxlID0gMTAwLkYgLyAobWF4THVtIC0gbWluTHVtKTsKCQliaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKEgpOwoJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCWZsb2F0ICpwaXhlbCA9IChmbG9hdCopYml0czsKCQkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewoJCQkJY29uc3QgZmxvYXQgdmFsdWUgPSAocGl4ZWxbeF0gLSBtaW5MdW0pICogc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGl4ZWxbeF0gPSBzdGQ6OmxvZyh2YWx1ZSArIEVQU0lMT04pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5leHQgbGluZQogICAgICAgICAgICAgICAgICAgICAgICBiaXRzICs9IHBpdGNoOwoJCX0KCgkJcmV0dXJuIEg7CgoJfSBjYXRjaChpbnQpIHsKCQlpZihIKSBGcmVlSW1hZ2VfVW5sb2FkKEgpOwoJCXJldHVybiBOVUxMOwoJfQp9CgovKioKR2l2ZW4gYSBub3JtYWxpemVkIGx1bWluYW5jZSwgcGVyZm9ybSBleHBvbmVudGlhdGlvbiBhbmQgcmVjb3ZlciB0aGUgbG9nIGNvbXByZXNzZWQgaW1hZ2UgCkBwYXJhbSBZIElucHV0L091dHB1dCBsdW1pbmFuY2UgaW1hZ2UKKi8Kc3RhdGljIHZvaWQgRXhwTHVtaW5hbmNlKEZJQklUTUFQICpZKSB7Cgljb25zdCB1bnNpZ25lZCB3aWR0aCA9IEZyZWVJbWFnZV9HZXRXaWR0aChZKTsKCWNvbnN0IHVuc2lnbmVkIGhlaWdodCA9IEZyZWVJbWFnZV9HZXRIZWlnaHQoWSk7Cgljb25zdCB1bnNpZ25lZCBwaXRjaCA9IEZyZWVJbWFnZV9HZXRQaXRjaChZKTsKCglCWVRFICpiaXRzID0gKEJZVEUqKUZyZWVJbWFnZV9HZXRCaXRzKFkpOwoJZm9yKHVuc2lnbmVkIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKCQlmbG9hdCAqcGl4ZWwgPSAoZmxvYXQqKWJpdHM7CgkJZm9yKHVuc2lnbmVkIHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICAgICAgICAgICAgICBwaXhlbFt4XSA9IHN0ZDo6ZXhwKHBpeGVsW3hdKSAtIEVQU0lMT047CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBiaXRzICs9IHBpdGNoOwogICAgICAgIH0KfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCi8qKgpHcmFkaWVudCBEb21haW4gSERSIHRvbmUgbWFwcGluZyBvcGVyYXRvcgpAcGFyYW0gWSBJbWFnZSBsdW1pbmFuY2UgdmFsdWVzCkBwYXJhbSBhbHBoYSBQYXJhbWV0ZXIgYWxwaGEgb2YgdGhlIHBhcGVyIChzdWdnZXN0ZWQgdmFsdWUgaXMgMC4xKQpAcGFyYW0gYmV0YSBQYXJhbWV0ZXIgYmV0YSBvZiB0aGUgcGFwZXIgKHN1Z2dlc3RlZCB2YWx1ZSBpcyBiZXR3ZWVuIDAuOCBhbmQgMC45KQpAcmV0dXJuIHJldHVybnMgdGhlIHRvbmUgbWFwcGVkIGx1bWluYW5jZQoqLwpzdGF0aWMgRklCSVRNQVAqIHRtb0ZhdHRhbDAyKEZJQklUTUFQICpZLCBmbG9hdCBhbHBoYSwgZmxvYXQgYmV0YSkgewoJY29uc3QgdW5zaWduZWQgTUlOX1BZUkFNSURfU0laRSA9IDMyOwkvLyBtaW5pbXVuIHNpemUgKHdpZHRoIG9yIGhlaWdodCkgb2YgdGhlIGNvYXJzZXN0IGxldmVsIG9mIHRoZSBweXJhbWlkCgoJRklCSVRNQVAgKkggPSBOVUxMOwoJRklCSVRNQVAgKipweXJhbWlkID0gTlVMTDsKCUZJQklUTUFQICoqZ3JhZGllbnRzID0gTlVMTDsKCUZJQklUTUFQICpwaHkgPSBOVUxMOwoJRklCSVRNQVAgKmRpdkcgPSBOVUxMOwoJRklCSVRNQVAgKlUgPSBOVUxMOwoJZmxvYXQgKmF2Z0dyYWQgPSBOVUxMOwoKCWludCBrOwoJaW50IG5sZXZlbHMgPSAwOwoKCXRyeSB7CgkJLy8gZ2V0IHRoZSBub3JtYWxpemVkIGx1bWluYW5jZQoJCUZJQklUTUFQICpIID0gTG9nTHVtaW5hbmNlKFkpOwoJCWlmKCFIKSB0aHJvdygxKTsKCQkKCQkvLyBnZXQgdGhlIG51bWJlciBvZiBsZXZlbHMgZm9yIHRoZSBweXJhbWlkCgkJY29uc3QgdW5zaWduZWQgd2lkdGggPSBGcmVlSW1hZ2VfR2V0V2lkdGgoSCk7CgkJY29uc3QgdW5zaWduZWQgaGVpZ2h0ID0gRnJlZUltYWdlX0dldEhlaWdodChIKTsKCQl1bnNpZ25lZCBtaW5zaXplID0gTUlOKHdpZHRoLCBoZWlnaHQpOwoJCXdoaWxlKG1pbnNpemUgPj0gTUlOX1BZUkFNSURfU0laRSkgewoJCQlubGV2ZWxzKys7CgkJCW1pbnNpemUgLz0gMjsKCQl9CgoJCS8vIGNyZWF0ZSB0aGUgR2F1c3NpYW4gcHlyYW1pZAoJCXB5cmFtaWQgPSAoRklCSVRNQVAqKiltYWxsb2MobmxldmVscyAqIHNpemVvZihGSUJJVE1BUCopKTsKCQlpZighcHlyYW1pZCkgdGhyb3coMSk7CgkJbWVtc2V0KHB5cmFtaWQsIDAsIG5sZXZlbHMgKiBzaXplb2YoRklCSVRNQVAqKSk7CgoJCWlmKCFHYXVzc2lhblB5cmFtaWQoSCwgcHlyYW1pZCwgbmxldmVscykpIHRocm93KDEpOwoKCQkvLyBjYWxjdWxhdGUgZ3JhZGllbnQgbWFnbml0dWRlIGFuZCBpdHMgYXZlcmFnZSB2YWx1ZSBvbiBlYWNoIHB5cmFtaWQgbGV2ZWwKCQlncmFkaWVudHMgPSAoRklCSVRNQVAqKiltYWxsb2MobmxldmVscyAqIHNpemVvZihGSUJJVE1BUCopKTsKCQlpZighZ3JhZGllbnRzKSB0aHJvdygxKTsKCQltZW1zZXQoZ3JhZGllbnRzLCAwLCBubGV2ZWxzICogc2l6ZW9mKEZJQklUTUFQKikpOwoJCWF2Z0dyYWQgPSAoZmxvYXQqKW1hbGxvYyhubGV2ZWxzICogc2l6ZW9mKGZsb2F0KSk7CgkJaWYoIWF2Z0dyYWQpIHRocm93KDEpOwoKCQlpZighR3JhZGllbnRQeXJhbWlkKHB5cmFtaWQsIG5sZXZlbHMsIGdyYWRpZW50cywgYXZnR3JhZCkpIHRocm93KDEpOwoKCQkvLyBmcmVlIHRoZSBHYXVzc2lhbiBweXJhbWlkCgkJZm9yKGsgPSAwOyBrIDwgbmxldmVsczsgaysrKSB7CgkJCWlmKHB5cmFtaWRba10pIEZyZWVJbWFnZV9VbmxvYWQocHlyYW1pZFtrXSk7CgkJfQoJCWZyZWUocHlyYW1pZCk7IHB5cmFtaWQgPSBOVUxMOwoKCQkvLyBjb21wdXRlIHRoZSBncmFkaWVudCBhdHRlbnVhdGlvbiBmdW5jdGlvbiBQSEkoeCwgeSkKCQlwaHkgPSBQaGlNYXRyaXgoZ3JhZGllbnRzLCBhdmdHcmFkLCBubGV2ZWxzLCBhbHBoYSwgYmV0YSk7CgkJaWYoIXBoeSkgdGhyb3coMSk7CgoJCS8vIGZyZWUgdGhlIGdyYWRpZW50IHB5cmFtaWQKCQlmb3IoayA9IDA7IGsgPCBubGV2ZWxzOyBrKyspIHsKCQkJaWYoZ3JhZGllbnRzW2tdKSBGcmVlSW1hZ2VfVW5sb2FkKGdyYWRpZW50c1trXSk7CgkJfQoJCWZyZWUoZ3JhZGllbnRzKTsgZ3JhZGllbnRzID0gTlVMTDsKCQlmcmVlKGF2Z0dyYWQpOyBhdmdHcmFkID0gTlVMTDsKCgkJLy8gY29tcHV0ZSBncmFkaWVudHMgaW4geCBhbmQgeSBkaXJlY3Rpb25zLCBhdHRlbnVhdGUgdGhlbSB3aXRoIHRoZSBhdHRlbnVhdGlvbiBtYXRyaXgsIAoJCS8vIHRoZW4gY29tcHV0ZSB0aGUgZGl2ZXJnZW5jZSBkaXYgRyBmcm9tIHRoZSBhdHRlbnVhdGVkIGdyYWRpZW50LiAKCQlkaXZHID0gRGl2ZXJnZW5jZShILCBwaHkpOwoJCWlmKCFkaXZHKSB0aHJvdygxKTsKCgkJLy8gSCAmIHBoeSBubyBsb25nZXIgbmVlZGVkCgkJRnJlZUltYWdlX1VubG9hZChIKTsgSCA9IE5VTEw7CgkJRnJlZUltYWdlX1VubG9hZChwaHkpOyBwaHkgPSBOVUxMOwoKCQkvLyBzb2x2ZSB0aGUgUERFIChQb2lzc29uIGVxdWF0aW9uKSB1c2luZyBhIG11bHRpZ3JpZCBzb2x2ZXIgYW5kIDMgY3ljbGVzCgkJRklCSVRNQVAgKlUgPSBGcmVlSW1hZ2VfTXVsdGlncmlkUG9pc3NvblNvbHZlcihkaXZHLCAzKTsKCQlpZighVSkgdGhyb3coMSk7CgoJCUZyZWVJbWFnZV9VbmxvYWQoZGl2Ryk7CgoJCS8vIHBlcmZvcm0gZXhwb25lbnRpYXRpb24gYW5kIHJlY292ZXIgdGhlIGxvZyBjb21wcmVzc2VkIGltYWdlCgkJRXhwTHVtaW5hbmNlKFUpOwoKCQlyZXR1cm4gVTsKCgl9IGNhdGNoKGludCkgewoJCWlmKEgpIEZyZWVJbWFnZV9VbmxvYWQoSCk7CgkJaWYocHlyYW1pZCkgewoJCQlmb3IoaW50IGkgPSAwOyBpIDwgbmxldmVsczsgaSsrKSB7CgkJCQlpZihweXJhbWlkW2ldKSBGcmVlSW1hZ2VfVW5sb2FkKHB5cmFtaWRbaV0pOwoJCQl9CgkJCWZyZWUocHlyYW1pZCk7CgkJfQoJCWlmKGdyYWRpZW50cykgewoJCQlmb3IoaW50IGkgPSAwOyBpIDwgbmxldmVsczsgaSsrKSB7CgkJCQlpZihncmFkaWVudHNbaV0pIEZyZWVJbWFnZV9VbmxvYWQoZ3JhZGllbnRzW2ldKTsKCQkJfQoJCQlmcmVlKGdyYWRpZW50cyk7CgkJfQoJCWlmKGF2Z0dyYWQpIGZyZWUoYXZnR3JhZCk7CgkJaWYocGh5KSBGcmVlSW1hZ2VfVW5sb2FkKHBoeSk7CgkJaWYoZGl2RykgRnJlZUltYWdlX1VubG9hZChkaXZHKTsKCQlpZihVKSBGcmVlSW1hZ2VfVW5sb2FkKFUpOwoKCQlyZXR1cm4gTlVMTDsKCX0KfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyAgTWFpbiBhbGdvcml0aG0KLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKLyoqCkFwcGx5IHRoZSBHcmFkaWVudCBEb21haW4gSGlnaCBEeW5hbWljIFJhbmdlIENvbXByZXNzaW9uIHRvIGEgUkdCRiBpbWFnZSBhbmQgY29udmVydCB0byAyNC1iaXQgUkdCCkBwYXJhbSBkaWIgSW5wdXQgUkdCRiAvIFJHQjE2IGltYWdlCkBwYXJhbSBjb2xvcl9zYXR1cmF0aW9uIENvbG9yIHNhdHVyYXRpb24gKHMgcGFyYW1ldGVyIGluIHRoZSBwYXBlcikgaW4gWzAuNC4uMC42XQpAcGFyYW0gYXR0ZW51YXRpb24gQXRlbnVhdGlvbiBmYWN0b3IgKGJldGEgcGFyYW1ldGVyIGluIHRoZSBwYXBlcikgaW4gWzAuOC4uMC45XQpAcmV0dXJuIFJldHVybnMgYSAyNC1iaXQgUkdCIGltYWdlIGlmIHN1Y2Nlc3NmdWwsIHJldHVybnMgTlVMTCBvdGhlcndpc2UKKi8KRklCSVRNQVAqIERMTF9DQUxMQ09OViAKRnJlZUltYWdlX1Rtb0ZhdHRhbDAyKEZJQklUTUFQICpkaWIsIGRvdWJsZSBjb2xvcl9zYXR1cmF0aW9uLCBkb3VibGUgYXR0ZW51YXRpb24pIHsJCgljb25zdCBmbG9hdCBhbHBoYSA9IDAuMUY7CQkJCQkJCQkJLy8gcGFyYW1ldGVyIGFscGhhID0gMC4xCgljb25zdCBmbG9hdCBiZXRhID0gKGZsb2F0KU1BWCgwLjgsIE1JTigwLjksIGF0dGVudWF0aW9uKSk7CS8vIHBhcmFtZXRlciBiZXRhID0gWzAuOC4uMC45XQoJY29uc3QgZmxvYXQgcyA9IChmbG9hdClNQVgoMC40LCBNSU4oMC42LCBjb2xvcl9zYXR1cmF0aW9uKSk7Ly8gZXhwb25lbnQgcyBjb250cm9scyBjb2xvciBzYXR1cmF0aW9uID0gWzAuNC4uMC42XQoKCUZJQklUTUFQICpzcmMgPSBOVUxMOwoJRklCSVRNQVAgKllpbiA9IE5VTEw7CglGSUJJVE1BUCAqWW91dCA9IE5VTEw7CglGSUJJVE1BUCAqZHN0ID0gTlVMTDsKCglpZighRnJlZUltYWdlX0hhc1BpeGVscyhkaWIpKSByZXR1cm4gTlVMTDsKCgl0cnkgewoKCQkvLyBjb252ZXJ0IHRvIFJHQkYKCQlzcmMgPSBGcmVlSW1hZ2VfQ29udmVydFRvUkdCRihkaWIpOwoJCWlmKCFzcmMpIHRocm93KDEpOwoKCQkvLyBnZXQgdGhlIGx1bWluYW5jZSBjaGFubmVsCgkJWWluID0gQ29udmVydFJHQkZUb1koc3JjKTsKCQlpZighWWluKSB0aHJvdygxKTsKCgkJLy8gcGVyZm9ybSB0aGUgdG9uZSBtYXBwaW5nCgkJWW91dCA9IHRtb0ZhdHRhbDAyKFlpbiwgYWxwaGEsIGJldGEpOwoJCWlmKCFZb3V0KSB0aHJvdygxKTsKCgkJLy8gY2xpcCBsb3cgYW5kIGhpZ2ggdmFsdWVzIGFuZCBub3JtYWxpemUgdG8gWzAuLjFdCgkJLy9Ob3JtYWxpemVZKFlvdXQsIDAuMDAxRiwgMC45OTVGKTsKCQlOb3JtYWxpemVZKFlvdXQsIDAsIDEpOwoKCQkvLyBjb21wcmVzcyB0aGUgZHluYW1pYyByYW5nZQoKCQljb25zdCB1bnNpZ25lZCB3aWR0aCA9IEZyZWVJbWFnZV9HZXRXaWR0aChzcmMpOwoJCWNvbnN0IHVuc2lnbmVkIGhlaWdodCA9IEZyZWVJbWFnZV9HZXRIZWlnaHQoc3JjKTsKCgkJY29uc3QgdW5zaWduZWQgcmdiX3BpdGNoID0gRnJlZUltYWdlX0dldFBpdGNoKHNyYyk7CgkJY29uc3QgdW5zaWduZWQgeV9waXRjaCA9IEZyZWVJbWFnZV9HZXRQaXRjaChZaW4pOwoKCQlCWVRFICpiaXRzICAgICAgPSAoQllURSopRnJlZUltYWdlX0dldEJpdHMoc3JjKTsKCQlCWVRFICpiaXRzX3lpbiAgPSAoQllURSopRnJlZUltYWdlX0dldEJpdHMoWWluKTsKCQlCWVRFICpiaXRzX3lvdXQgPSAoQllURSopRnJlZUltYWdlX0dldEJpdHMoWW91dCk7CgoJCWZvcih1bnNpZ25lZCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CgkJCWZsb2F0ICpMaW4gPSAoZmxvYXQqKWJpdHNfeWluOwoJCQlmbG9hdCAqTG91dCA9IChmbG9hdCopYml0c195b3V0OwoJCQlmbG9hdCAqY29sb3IgPSAoZmxvYXQqKWJpdHM7CgkJCWZvcih1bnNpZ25lZCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKCQkJCWZvcih1bnNpZ25lZCBjID0gMDsgYyA8IDM7IGMrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKmNvbG9yID0gKExpblt4XSA+IDApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBzdGQ6OnBvdygqY29sb3IgLyBMaW5beF0sIHMpICoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb3V0W3hdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CgkJCX0KCQkJYml0cyArPSByZ2JfcGl0Y2g7CgkJCWJpdHNfeWluICs9IHlfcGl0Y2g7CgkJCWJpdHNfeW91dCArPSB5X3BpdGNoOwoJCX0KCgkJLy8gbm90IG5lZWRlZCBhbnltb3JlCgkJRnJlZUltYWdlX1VubG9hZChZaW4pOyAgWWluICA9IE5VTEw7CgkJRnJlZUltYWdlX1VubG9hZChZb3V0KTsgWW91dCA9IE5VTEw7CgoJCS8vIGNsYW1wIGltYWdlIGhpZ2hlc3QgdmFsdWVzIHRvIGRpc3BsYXkgd2hpdGUsIHRoZW4gY29udmVydCB0byAyNC1iaXQgUkdCCgkJZHN0ID0gQ2xhbXBDb252ZXJ0UkdCRlRvMjQoc3JjKTsKCgkJLy8gY2xlYW4tdXAgYW5kIHJldHVybgoJCUZyZWVJbWFnZV9VbmxvYWQoc3JjKTsgc3JjID0gTlVMTDsKCgkJLy8gY29weSBtZXRhZGF0YSBmcm9tIHNyYyB0byBkc3QKCQlGcmVlSW1hZ2VfQ2xvbmVNZXRhZGF0YShkc3QsIGRpYik7CgkJCgkJcmV0dXJuIGRzdDsKCgl9IGNhdGNoKGludCkgewoJCWlmKHNyYykgRnJlZUltYWdlX1VubG9hZChzcmMpOwoJCWlmKFlpbikgRnJlZUltYWdlX1VubG9hZChZaW4pOwoJCWlmKFlvdXQpIEZyZWVJbWFnZV9VbmxvYWQoWW91dCk7CgkJcmV0dXJuIE5VTEw7Cgl9Cn0K