LyoKICogRE9TIGludGVycnVwdCAwOWggaGFuZGxlciAoSVJRMSAtIEtFWUJPQVJEKQogKgogKiBDb3B5cmlnaHQgMTk5OSBPdmUgS+V2ZW4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqLwoKI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgIm1pc2NlbXUuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKI2luY2x1ZGUgImRvc2V4ZS5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwoaW50KTsKCiNkZWZpbmUgUVVFVUVMRU4gMzEKCnN0YXRpYyBzdHJ1Y3QKewogIEJZVEUgcXVldWVsZW4scXVldWVbUVVFVUVMRU5dLGFzY2lpW1FVRVVFTEVOXTsKfSBrYmRpbmZvOwoKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCSAgICBET1NWTV9JbnQwOUhhbmRsZXIKICoKICogSGFuZGxlciBmb3IgaW50IDA5aC4KICovCnZvaWQgV0lOQVBJIERPU1ZNX0ludDA5SGFuZGxlciggQ09OVEVYVDg2ICpjb250ZXh0ICkKewogIEJZVEUgYXNjaWksIHNjYW4gPSBET1NWTV9JbnQwOVJlYWRTY2FuKCZhc2NpaSk7CiAgQllURSBjaFsyXTsKICBpbnQgY250LCBjMjsKCiAgVFJBQ0UoInNjYW49JTAyeFxuIixzY2FuKTsKICBpZiAoIShzY2FuICYgMHg4MCkpIHsKICAgIGlmIChhc2NpaSkgewogICAgICAvKiB3ZSBhbHJlYWR5IGhhdmUgYW4gQVNDSUkgY29kZSwgbm8gdHJhbnNsYXRpb24gbmVjZXNzYXJ5ICovCiAgICAgIGNoWzBdID0gYXNjaWk7CiAgICAgIGNudCA9IDE7CiAgICB9IGVsc2UgewogICAgICBVSU5UIHZrZXkgPSBNYXBWaXJ0dWFsS2V5QShzY2FuJjB4N2YsIDEpOwogICAgICBCWVRFIGtleXN0YXRlWzI1Nl07CiAgICAgIEdldEtleWJvYXJkU3RhdGUoa2V5c3RhdGUpOwogICAgICBjbnQgPSBUb0FzY2lpKHZrZXksIHNjYW4sIGtleXN0YXRlLCAoTFBXT1JEKWNoLCAwKTsKICAgIH0KICAgIGlmIChjbnQ+MCkgewogICAgICBmb3IgKGMyPTA7IGMyPGNudDsgYzIrKykKICAgICAgICBET1NWTV9JbnQxNkFkZENoYXIoY2hbYzJdLCBzY2FuKTsKICAgIH0gZWxzZQogICAgaWYgKGNudD09MCkgewogICAgICAvKiBGSVhNRTogbmVlZCB0byBoYW5kbGUgdGhpbmdzIGxpa2Ugc2hpZnQtRi1rZXlzLAogICAgICAgKiAweEUwIGV4dGVuZGVkIGtleXMsIGV0YyAqLwogICAgICBET1NWTV9JbnQxNkFkZENoYXIoMCwgc2Nhbik7CiAgICB9CiAgfQogIERPU1ZNX1BJQ19pb3BvcnRfb3V0KCAweDIwLCAweDIwICk7IC8qIHNlbmQgRU9JICovCn0KCnN0YXRpYyB2b2lkIEtiZFJlbGF5KCBDT05URVhUODYgKmNvbnRleHQsIHZvaWQgKmRhdGEgKQp7CiAgaWYgKGtiZGluZm8ucXVldWVsZW4pIHsKICAgIC8qIGNsZWFudXAgb3BlcmF0aW9uLCBjYWxsZWQgZnJvbSBET1NWTV9QSUNfaW9wb3J0X291dDoKICAgICAqIHdlJ2xsIHJlbW92ZSBjdXJyZW50IHNjYW5jb2RlIGZyb20ga2V5Ym9hcmQgYnVmZmVyIGhlcmUsCiAgICAgKiByYXRoZXIgdGhhbiBpbiBSZWFkU2NhbiwgYmVjYXVzZSBzb21lIERPUyBhcHBzIGRlcGVuZCBvbgogICAgICogdGhlIHNjYW5jb2RlIGJlaW5nIGF2YWlsYWJsZSBmb3IgcmVhZGluZyBtdWx0aXBsZSB0aW1lcy4uLiAqLwogICAgaWYgKC0ta2JkaW5mby5xdWV1ZWxlbikgewogICAgICBtZW1tb3ZlKGtiZGluZm8ucXVldWUsa2JkaW5mby5xdWV1ZSsxLGtiZGluZm8ucXVldWVsZW4pOwogICAgICBtZW1tb3ZlKGtiZGluZm8uYXNjaWksa2JkaW5mby5hc2NpaSsxLGtiZGluZm8ucXVldWVsZW4pOwogICAgfQogIH0KfQoKdm9pZCBXSU5BUEkgRE9TVk1fSW50MDlTZW5kU2NhbiggQllURSBzY2FuLCBCWVRFIGFzY2lpICkKewogIGlmIChrYmRpbmZvLnF1ZXVlbGVuID09IFFVRVVFTEVOKSB7CiAgICBFUlIoImtleWJvYXJkIHF1ZXVlIG92ZXJmbG93XG4iKTsKICAgIHJldHVybjsKICB9CiAgLyogYWRkIHNjYW5jb2RlIHRvIHF1ZXVlICovCiAga2JkaW5mby5xdWV1ZVtrYmRpbmZvLnF1ZXVlbGVuXSA9IHNjYW47CiAga2JkaW5mby5hc2NpaVtrYmRpbmZvLnF1ZXVlbGVuKytdID0gYXNjaWk7CiAgLyogdGVsbCBhcHAgdG8gcmVhZCBpdCBieSB0cmlnZ2VyaW5nIElSUSAxIChpbnQgMDkpICovCiAgRE9TVk1fUXVldWVFdmVudCgxLERPU19QUklPUklUWV9LRVlCT0FSRCxLYmRSZWxheSxOVUxMKTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoJICAgIEtiZFJlYWRTY2FuIChXSU5FRE9TLkApCiAqLwpCWVRFIFdJTkFQSSBET1NWTV9JbnQwOVJlYWRTY2FuKCBCWVRFKmFzY2lpICkKewogICAgaWYgKGFzY2lpKSAqYXNjaWkgPSBrYmRpbmZvLmFzY2lpWzBdOwogICAgcmV0dXJuIGtiZGluZm8ucXVldWVbMF07Cn0K