LyogSVdpbmVEM0RDbGlwcGVyIGltcGxlbWVudGF0aW9uCiAqCiAqIENvcHlyaWdodCAyMDAwIChjKSBNYXJjdXMgTWVpc3NuZXIKICogQ29weXJpZ2h0IDIwMDAgKGMpIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcyBJbmMuCiAqIENvcHlyaWdodCAyMDA2IChjKSBTdGVmYW4gRPZzaW5nZXIKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwoKI2luY2x1ZGUgImNvbmZpZy5oIgojaW5jbHVkZSA8c3RkaW8uaD4KI2lmZGVmIEhBVkVfRkxPQVRfSAojIGluY2x1ZGUgPGZsb2F0Lmg+CiNlbmRpZgojaW5jbHVkZSAid2luZWQzZF9wcml2YXRlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChkM2QpOwoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfUXVlcnlJbnRlcmZhY2UoSVdpbmVEM0RDbGlwcGVyICppZmFjZSwgUkVGSUlEIHJpaWQsIHZvaWQgKipPYmopCnsKICAgIElXaW5lRDNEQ2xpcHBlckltcGwgKlRoaXMgPSAoSVdpbmVEM0RDbGlwcGVySW1wbCAqKWlmYWNlOwoKICAgIFRSQUNFKCIoJXApLT4oJXAsJXApXG4iLCBUaGlzLCByaWlkLCBPYmopOwogICAgaWYgKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24sIHJpaWQpCiAgICAgICAgfHwgSXNFcXVhbEdVSUQoJklJRF9JV2luZUQzRENsaXBwZXIsIHJpaWQpKQogICAgewogICAgICAgICpPYmogPSBpZmFjZTsKICAgICAgICBJV2luZUQzRENsaXBwZXJfQWRkUmVmKGlmYWNlKTsKICAgICAgICByZXR1cm4gU19PSzsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKICAgIH0KfQoKc3RhdGljIFVMT05HIFdJTkFQSSBJV2luZUQzRENsaXBwZXJJbXBsX0FkZFJlZihJV2luZUQzRENsaXBwZXIgKmlmYWNlICkKewogICAgSVdpbmVEM0RDbGlwcGVySW1wbCAqVGhpcyA9IChJV2luZUQzRENsaXBwZXJJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgaW5jcmVtZW50aW5nIGZyb20gJXUuXG4iLCBUaGlzLCByZWYgLSAxKTsKCiAgICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfUmVsZWFzZShJV2luZUQzRENsaXBwZXIgKmlmYWNlKQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKICAgIFVMT05HIHJlZiA9IEludGVybG9ja2VkRGVjcmVtZW50KCZUaGlzLT5yZWYpOwoKICAgIFRSQUNFKCIoJXApLT4oKSBkZWNyZW1lbnRpbmcgZnJvbSAldS5cbiIsIFRoaXMsIHJlZiArIDEpOwoKICAgIGlmIChyZWYgPT0gMCkKICAgIHsKICAgICAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzKTsKICAgICAgICByZXR1cm4gMDsKICAgIH0KICAgIGVsc2UgcmV0dXJuIHJlZjsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfR2V0UGFyZW50KElXaW5lRDNEQ2xpcHBlciAqaWZhY2UsIElVbmtub3duICoqUGFyZW50KQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBQYXJlbnQpOwoKICAgICpQYXJlbnQgPSBUaGlzLT5QYXJlbnQ7CiAgICBJVW5rbm93bl9BZGRSZWYoKlBhcmVudCk7CiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfU2V0SHduZChJV2luZUQzRENsaXBwZXIgKmlmYWNlLCBEV09SRCBGbGFncywgSFdORCBoV25kKQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKCiAgICBUUkFDRSgiKCVwKS0+KDB4JTA4eCwlcClcbiIsIFRoaXMsIEZsYWdzLCBoV25kKTsKICAgIGlmKCBGbGFncyApCiAgICB7CiAgICAgICAgRklYTUUoIkZsYWdzID0gMHglMDh4LCBub3Qgc3VwcG9ydGVkLlxuIixGbGFncyk7CiAgICAgICAgcmV0dXJuIFdJTkVEM0RFUlJfSU5WQUxJRENBTEw7CiAgICB9CgogICAgVGhpcy0+aFduZCA9IGhXbmQ7CiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfR2V0Q2xpcExpc3QoSVdpbmVEM0RDbGlwcGVyICppZmFjZSwgUkVDVCAqUmVjdCwgUkdOREFUQSAqQ2xpcExpc3QsIERXT1JEICpTaXplKQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXAsJXAsJXAsJXApXG4iLCBUaGlzLCBSZWN0LCBDbGlwTGlzdCwgU2l6ZSk7CgogICAgaWYgKFRoaXMtPmhXbmQpCiAgICB7CiAgICAgICAgSERDIGhEQyA9IEdldERDRXgoVGhpcy0+aFduZCwgTlVMTCwgRENYX1dJTkRPVyk7CiAgICAgICAgaWYgKGhEQykKICAgICAgICB7CiAgICAgICAgICAgIEhSR04gaFJnbiA9IENyZWF0ZVJlY3RSZ24oMCwwLDAsMCk7CiAgICAgICAgICAgIGlmIChHZXRSYW5kb21SZ24oaERDLCBoUmduLCBTWVNSR04pKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoR2V0VmVyc2lvbigpICYgMHg4MDAwMDAwMCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvKiBtYXAgcmVnaW9uIHRvIHNjcmVlbiBjb29yZGluYXRlcyAqLwogICAgICAgICAgICAgICAgICAgIFBPSU5UIG9yZzsKICAgICAgICAgICAgICAgICAgICBHZXREQ09yZ0V4KCBoREMsICZvcmcgKTsKICAgICAgICAgICAgICAgICAgICBPZmZzZXRSZ24oIGhSZ24sIG9yZy54LCBvcmcueSApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKFJlY3QpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgSFJHTiBoUmduQ2xpcCA9IENyZWF0ZVJlY3RSZ24oUmVjdC0+bGVmdCwgUmVjdC0+dG9wLAogICAgICAgICAgICAgICAgICAgICAgICBSZWN0LT5yaWdodCwgUmVjdC0+Ym90dG9tKTsKICAgICAgICAgICAgICAgICAgICBDb21iaW5lUmduKGhSZ24sIGhSZ24sIGhSZ25DbGlwLCBSR05fQU5EKTsKICAgICAgICAgICAgICAgICAgICBEZWxldGVPYmplY3QoaFJnbkNsaXApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKlNpemUgPSBHZXRSZWdpb25EYXRhKGhSZ24sICpTaXplLCBDbGlwTGlzdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgRGVsZXRlT2JqZWN0KGhSZ24pOwogICAgICAgICAgICBSZWxlYXNlREMoVGhpcy0+aFduZCwgaERDKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIFdJTkVEM0RfT0s7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc3RhdGljIGludCB3YXJuZWQgPSAwOwogICAgICAgIGlmICh3YXJuZWQrKyA8IDEwKQogICAgICAgICAgICBGSVhNRSgiKCVwLCVwLCVwLCVwKSxzdHViIVxuIixUaGlzLFJlY3QsQ2xpcExpc3QsU2l6ZSk7CiAgICAgICAgaWYgKFNpemUpICpTaXplPTA7CiAgICAgICAgcmV0dXJuIFdJTkVEREVSUl9OT0NMSVBMSVNUOwogICAgfQp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RDbGlwcGVySW1wbF9TZXRDbGlwTGlzdChJV2luZUQzRENsaXBwZXIgKmlmYWNlLCBSR05EQVRBICpyZ24sIERXT1JEIEZsYWdzKQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKICAgIHN0YXRpYyBpbnQgd2FybmVkID0gMDsKCiAgICBpZiAod2FybmVkKysgPCAxMCB8fCByZ24gPT0gTlVMTCkKICAgICAgICBGSVhNRSgiKCVwLCVwLCVkKSxzdHViIVxuIixUaGlzLHJnbixGbGFncyk7CiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfR2V0SHduZChJV2luZUQzRENsaXBwZXIgKmlmYWNlLCBIV05EICpod25kKQp7CiAgICBJV2luZUQzRENsaXBwZXJJbXBsICpUaGlzID0gKElXaW5lRDNEQ2xpcHBlckltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBod25kKTsKCiAgICAqaHduZCA9IFRoaXMtPmhXbmQ7CiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEQ2xpcHBlckltcGxfSXNDbGlwTGlzdENoYW5nZWQoSVdpbmVEM0RDbGlwcGVyICppZmFjZSwgQk9PTCAqY2hhbmdlZCkKewogICAgSVdpbmVEM0RDbGlwcGVySW1wbCAqVGhpcyA9IChJV2luZUQzRENsaXBwZXJJbXBsICopaWZhY2U7CiAgICBGSVhNRSgiKCVwKS0+KCVwKSxzdHViIVxuIixUaGlzLGNoYW5nZWQpOwoKICAgIC8qIFhYWCBXaGF0IGlzIHNhZmVzdD8gKi8KICAgICpjaGFuZ2VkID0gRkFMU0U7CgogICAgcmV0dXJuIFdJTkVEM0RfT0s7Cn0KCnN0YXRpYyBjb25zdCBJV2luZUQzRENsaXBwZXJWdGJsIElXaW5lRDNEQ2xpcHBlcl9WdGJsID0KewogICAgSVdpbmVEM0RDbGlwcGVySW1wbF9RdWVyeUludGVyZmFjZSwKICAgIElXaW5lRDNEQ2xpcHBlckltcGxfQWRkUmVmLAogICAgSVdpbmVEM0RDbGlwcGVySW1wbF9SZWxlYXNlLAogICAgSVdpbmVEM0RDbGlwcGVySW1wbF9HZXRQYXJlbnQsCiAgICBJV2luZUQzRENsaXBwZXJJbXBsX0dldENsaXBMaXN0LAogICAgSVdpbmVEM0RDbGlwcGVySW1wbF9HZXRId25kLAogICAgSVdpbmVEM0RDbGlwcGVySW1wbF9Jc0NsaXBMaXN0Q2hhbmdlZCwKICAgIElXaW5lRDNEQ2xpcHBlckltcGxfU2V0Q2xpcExpc3QsCiAgICBJV2luZUQzRENsaXBwZXJJbXBsX1NldEh3bmQKfTsKCklXaW5lRDNEQ2xpcHBlciogV0lOQVBJIFdpbmVEaXJlY3QzRENyZWF0ZUNsaXBwZXIoSVVua25vd24gKlBhcmVudCkKewogICAgSVdpbmVEM0RDbGlwcGVySW1wbCAqb2JqOwoKICAgIFRSQUNFKCJDcmVhdGluZyBjbGlwcGVyLCBwYXJlbnQgJXBcbiIsIFBhcmVudCk7CiAgICBvYmogPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgc2l6ZW9mKCpvYmopKTsKICAgIGlmKCFvYmopCiAgICB7CiAgICAgICAgRVJSKCJPdXQgb2YgbWVtb3J5IHdoZW4gdHJ5aW5nIHRvIGFsbG9jYXRlIGEgV2luZUQzRCBDbGlwcGVyXG4iKTsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICBvYmotPmxwVnRibCA9ICZJV2luZUQzRENsaXBwZXJfVnRibDsKICAgIG9iai0+UGFyZW50ID0gUGFyZW50OwoKICAgIElXaW5lRDNEQ2xpcHBlcl9BZGRSZWYoKElXaW5lRDNEQ2xpcHBlciAqKW9iaik7CiAgICByZXR1cm4gKElXaW5lRDNEQ2xpcHBlciAqKSBvYmo7Cn0K