LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIAogKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lCiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZQogKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbgogKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUKICogIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQogKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLAogKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbgogKiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlCiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMKICogdW5kZXIgdGhlIExpY2Vuc2UuCiAqIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgoKLy8gTUFSS0VSKHVwZGF0ZV9wcmVjb21wLnB5KTogYXV0b2dlbiBpbmNsdWRlIHN0YXRlbWVudCwgZG8gbm90IHJlbW92ZQojaW5jbHVkZSAicHJlY29tcGlsZWRfYmFzaWMuaHh4IgojaW5jbHVkZSA8YmFzaWMvc2J4Lmh4eD4KI2luY2x1ZGUgInNiY29tcC5oeHgiCgpTYnhPYmplY3QqIGNsb25lVHlwZU9iamVjdEltcGwoIGNvbnN0IFNieE9iamVjdCYgclR5cGVPYmogKTsKCi8vIERla2xhcmF0aW9uIGVpbmVyIFZhcmlhYmxlbgovLyBCZWkgRmVobGVybiB3aXJkIGJpcyB6dW0gS29tbWEgb2RlciBOZXdsaW5lIGdlcGFyc3QuCi8vIFJldHVybndlcnQ6IGVpbmUgbmV1ZSBJbnN0YW56LCBkaWUgZWluZ2VmdWVndCB1bmQgZGFubiBnZWxvZXNjaHQgd2lyZC4KLy8gQXJyYXktSW5kZXhlIHdlcmRlbiBhbHMgU2JpRGltTGlzdCB6dXJ1ZWNrZ2VnZWJlbgoKU2JpU3ltRGVmKiBTYmlQYXJzZXI6OlZhckRlY2woIFNiaURpbUxpc3QqKiBwcERpbSwgc2FsX0Jvb2wgYlN0YXRpYywgc2FsX0Jvb2wgYkNvbnN0ICkKewoJYm9vbCBiV2l0aEV2ZW50cyA9IGZhbHNlOwoJaWYoIFBlZWsoKSA9PSBXSVRIRVZFTlRTICkKCXsKCQlOZXh0KCk7CgkJYldpdGhFdmVudHMgPSB0cnVlOwoJfQoJaWYoICFUZXN0U3ltYm9sKCkgKSByZXR1cm4gTlVMTDsKCVNieERhdGFUeXBlIHQgPSBlU2NhblR5cGU7CglTYmlTeW1EZWYqIHBEZWYgPSBiQ29uc3QgPyBuZXcgU2JpQ29uc3REZWYoIGFTeW0gKSA6IG5ldyBTYmlTeW1EZWYoIGFTeW0gKTsKCVNiaURpbUxpc3QqIHBEaW0gPSBOVUxMOwoJLy8gS2xhbW1lcm4/CglpZiggUGVlaygpID09IExQQVJFTiApCgl7CgkJcERpbSA9IG5ldyBTYmlEaW1MaXN0KCB0aGlzICk7CgkJaWYoICFwRGltLT5HZXREaW1zKCkgKQoJCQlwRGVmLT5TZXRXaXRoQnJhY2tldHMoKTsKCX0KCXBEZWYtPlNldFR5cGUoIHQgKTsKCWlmKCBiU3RhdGljICkKCQlwRGVmLT5TZXRTdGF0aWMoKTsKCWlmKCBiV2l0aEV2ZW50cyApCgkJcERlZi0+U2V0V2l0aEV2ZW50cygpOwoJVHlwZURlY2woICpwRGVmICk7CglpZiggIXBwRGltICYmIHBEaW0gKQoJewoJCWlmKHBEaW0tPkdldERpbXMoKSApCgkJCUVycm9yKCBTYkVSUl9FWFBFQ1RFRCwgIigpIiApOwoJCWRlbGV0ZSBwRGltOwoJfQoJZWxzZSBpZiggcHBEaW0gKQoJCSpwcERpbSA9IHBEaW07CglyZXR1cm4gcERlZjsKfQoKLy8gQXVmbG9lc2VuIGVpbmVyIEFTLVR5cGRla2xhcmF0aW9uCi8vIERlciBEYXRlbnR5cCB3aXJkIGluIGRpZSB1ZWJlcmdlYmVuZSBWYXJpYWJsZSBlaW5nZXRyYWdlbgoKdm9pZCBTYmlQYXJzZXI6OlR5cGVEZWNsKCBTYmlTeW1EZWYmIHJEZWYsIHNhbF9Cb29sIGJBc05ld0FscmVhZHlQYXJzZWQgKQp7CglTYnhEYXRhVHlwZSBlVHlwZSA9IHJEZWYuR2V0VHlwZSgpOwoJc2hvcnQgblNpemUgPSAwOwoJaWYoIGJBc05ld0FscmVhZHlQYXJzZWQgfHwgUGVlaygpID09IEFTICkKCXsKCQlpZiggIWJBc05ld0FscmVhZHlQYXJzZWQgKQoJCQlOZXh0KCk7CgkJckRlZi5TZXREZWZpbmVkQXMoKTsKCQlTdHJpbmcgYVR5cGU7CgkJU2JpVG9rZW4gZVRvayA9IE5leHQoKTsKCQlpZiggIWJBc05ld0FscmVhZHlQYXJzZWQgJiYgZVRvayA9PSBORVcgKQoJCXsKCQkJckRlZi5TZXROZXcoKTsKCQkJZVRvayA9IE5leHQoKTsKCQl9CgkJc3dpdGNoKCBlVG9rICkKCQl7CgkJCWNhc2UgQU5ZOgoJCQkJaWYoIHJEZWYuSXNOZXcoKSApCgkJCQkJRXJyb3IoIFNiRVJSX1NZTlRBWCApOwoJCQkJZVR5cGUgPSBTYnhWQVJJQU5UOyBicmVhazsKCQkJY2FzZSBUSU5URUdFUjoKCQkJY2FzZSBUTE9ORzoKCQkJY2FzZSBUU0lOR0xFOgoJCQljYXNlIFRET1VCTEU6CgkJCWNhc2UgVENVUlJFTkNZOgoJCQljYXNlIFREQVRFOgoJCQljYXNlIFRTVFJJTkc6CgkJCWNhc2UgVE9CSkVDVDoKCQkJY2FzZSBfRVJST1JfOgoJCQljYXNlIFRCT09MRUFOOgoJCQljYXNlIFRWQVJJQU5UOgoJCQljYXNlIFRCWVRFOgoJCQkJaWYoIHJEZWYuSXNOZXcoKSApCgkJCQkJRXJyb3IoIFNiRVJSX1NZTlRBWCApOwoJCQkJZVR5cGUgPSAoZVRvaz09VEJZVEUpID8gU2J4QllURSA6IFNieERhdGFUeXBlKCBlVG9rIC0gVElOVEVHRVIgKyBTYnhJTlRFR0VSICk7CgkJCQlpZiggZVR5cGUgPT0gU2J4U1RSSU5HICkKCQkJCXsKCQkJCQkvLyBTVFJJTkcqbiA/CgkJCQkJaWYoIFBlZWsoKSA9PSBNVUwgKQoJCQkJCXsJCS8vIGZpeGVkIHNpemUhCgkJCQkJCU5leHQoKTsKCQkJCQkJU2JpQ29uc3RFeHByZXNzaW9uIGFTaXplKCB0aGlzICk7CgkJCQkJCW5TaXplID0gYVNpemUuR2V0U2hvcnRWYWx1ZSgpOwoJCQkJCQlpZiggblNpemUgPCAwIHx8IChiVkJBU3VwcG9ydE9uICYmIG5TaXplIDw9IDApICkKCQkJCQkJCUVycm9yKCBTYkVSUl9PVVRfT0ZfUkFOR0UgKTsKCQkJCQkJZWxzZQoJCQkJCQkJckRlZi5TZXRGaXhlZFN0cmluZ0xlbmd0aCggblNpemUgKTsKCQkJCQl9CgkJCQl9CgkJCQlicmVhazsKCQkJY2FzZSBTWU1CT0w6IC8vIGthbm4gbnVyIGVpbiBUWVBFIG9kZXIgZWluZSBPYmpla3RrbGFzc2Ugc2VpbiEKCQkJCWlmKCBlU2NhblR5cGUgIT0gU2J4VkFSSUFOVCApCgkJCQkJRXJyb3IoIFNiRVJSX1NZTlRBWCApOwoJCQkJZWxzZQoJCQkJewoJCQkJCVN0cmluZyBhQ29tcGxldGVOYW1lID0gYVN5bTsKCgkJCQkJLy8gIzUyNzA5IERJTSBBUyBORVcgZnVlciBVbm8gbWl0IHZvbGwtcXVhbGlmaXppZXJ0ZW4gTmFtZW4KCQkJCQlpZiggUGVlaygpID09IERPVCApCgkJCQkJewoJCQkJCQlTdHJpbmcgYURvdFN0ciggJy4nICk7CgkJCQkJCXdoaWxlKCBQZWVrKCkgPT0gRE9UICkKCQkJCQkJewoJCQkJCQkJYUNvbXBsZXRlTmFtZSArPSBhRG90U3RyOwoJCQkJCQkJTmV4dCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgU2JpVG9rZW4gZVBlZWtUb2sgPSBQZWVrKCk7CgkJCQkJCQlpZiggZVBlZWtUb2sgPT0gU1lNQk9MIHx8IElzS3dkKCBlUGVla1RvayApICkKCQkJCQkJCXsKCQkJCQkJCQlOZXh0KCk7CgkJCQkJCQkJYUNvbXBsZXRlTmFtZSArPSBhU3ltOwoJCQkJCQkJfQoJCQkJCQkJZWxzZQoJCQkJCQkJewoJCQkJCQkJCU5leHQoKTsKCQkJCQkJCQlFcnJvciggU2JFUlJfVU5FWFBFQ1RFRCwgU1lNQk9MICk7CgkJCQkJCQkJYnJlYWs7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQkJZWxzZSBpZiggckVudW1BcnJheS0+RmluZCggYUNvbXBsZXRlTmFtZSwgU2J4Q0xBU1NfT0JKRUNUICkgKQoJCQkJCXsKCQkJCQkJZVR5cGUgPSBTYnhMT05HOwoJCQkJCQlicmVhazsKCQkJCQl9CgoJCQkJCS8vIEluIGRlbiBTdHJpbmctUG9vbCB1ZWJlcm5laG1lbgoJCQkJCXJEZWYuU2V0VHlwZUlkKCBhR2JsU3RyaW5ncy5BZGQoIGFDb21wbGV0ZU5hbWUgKSApOwoKCQkJCQlpZiggckRlZi5Jc05ldygpICYmIHBQcm9jID09IE5VTEwgKQoJCQkJCQlhUmVxdWlyZWRUeXBlcy5wdXNoX2JhY2soIGFDb21wbGV0ZU5hbWUgKTsKCQkJCX0KCQkJCWVUeXBlID0gU2J4T0JKRUNUOwoJCQkJYnJlYWs7CgkJCWNhc2UgRklYU1RSSU5HOiAvLyBuZXcgc3ludGF4IGZvciBjb21wbGV4IFVOTyB0eXBlcwoJCQkJckRlZi5TZXRUeXBlSWQoIGFHYmxTdHJpbmdzLkFkZCggYVN5bSApICk7CgkJCQllVHlwZSA9IFNieE9CSkVDVDsKCQkJCWJyZWFrOwoJCQlkZWZhdWx0OgoJCQkJRXJyb3IoIFNiRVJSX1VORVhQRUNURUQsIGVUb2sgKTsKCQkJCU5leHQoKTsKCQl9CgkJLy8gRGllIFZhcmlhYmxlIGtvZW5udGUgbWl0IFN1ZmZpeCBkZWtsYXJpZXJ0IHNlaW4KCQlpZiggckRlZi5HZXRUeXBlKCkgIT0gU2J4VkFSSUFOVCApCgkJewoJCQlpZiggckRlZi5HZXRUeXBlKCkgIT0gZVR5cGUgKQoJCQkJRXJyb3IoIFNiRVJSX1ZBUl9ERUZJTkVELCByRGVmLkdldE5hbWUoKSApOwoJCQllbHNlIGlmKCBlVHlwZSA9PSBTYnhTVFJJTkcgJiYgckRlZi5HZXRMZW4oKSAhPSBuU2l6ZSApCgkJCQlFcnJvciggU2JFUlJfVkFSX0RFRklORUQsIHJEZWYuR2V0TmFtZSgpICk7CgkJfQoJCXJEZWYuU2V0VHlwZSggZVR5cGUgKTsKCQlyRGVmLlNldExlbiggblNpemUgKTsKCX0KfQoKLy8gSGllciB3ZXJkZW4gVmFyaWFibGUsIEFycmF5cyB1bmQgU3RydWt0dXJlbiBkZWZpbmllcnQuCi8vIERJTS9QUklWQVRFL1BVQkxJQy9HTE9CQUwKCnZvaWQgU2JpUGFyc2VyOjpEaW0oKQp7CglEZWZWYXIoIF9ESU0sICggcFByb2MgJiYgYlZCQVN1cHBvcnRPbiApID8gcFByb2MtPklzU3RhdGljKCkgOiBzYWxfRmFsc2UgKTsKfQoKdm9pZCBTYmlQYXJzZXI6OkRlZlZhciggU2JpT3Bjb2RlIGVPcCwgc2FsX0Jvb2wgYlN0YXRpYyApCnsKCVNiaVN5bVBvb2wqIHBPbGRQb29sID0gcFBvb2w7CglzYWxfQm9vbCBiU3dpdGNoUG9vbCA9IHNhbF9GYWxzZTsKCXNhbF9Cb29sIGJQZXJzaXN0YW50R2xvYmFsID0gc2FsX0ZhbHNlOwoJU2JpVG9rZW4gZUZpcnN0VG9rID0gZUN1clRvazsKCWlmKCBwUHJvYyAmJiAoIGVDdXJUb2sgPT0gR0xPQkFMIHx8IGVDdXJUb2sgPT0gUFVCTElDIHx8IGVDdXJUb2sgPT0gUFJJVkFURSApICkKCQlFcnJvciggU2JFUlJfTk9UX0lOX1NVQlIsIGVDdXJUb2sgKTsKCWlmKCBlQ3VyVG9rID09IFBVQkxJQyB8fCBlQ3VyVG9rID09IEdMT0JBTCApCiAgICB7CgkJYlN3aXRjaFBvb2wgPSBzYWxfVHJ1ZTsJCS8vIGltIHJpY2h0aWdlbiBNb21lbnQgYXVmIGdsb2JhbGVuIFBvb2wgc2NoYWx0ZW4KICAgIAlpZiggZUN1clRvayA9PSBHTE9CQUwgKQogICAgICAgICAgICBiUGVyc2lzdGFudEdsb2JhbCA9IHNhbF9UcnVlOwogICAgfQoJLy8gYmVoYXZpb3IgaW4gVkJBIGlzIHRoYXQgYSBtb2R1bGUgc2NvcGUgdmFyaWFibGUncyBsaWZldGltZSBpcyAKCS8vIHRpZWQgdG8gdGhlIGRvY3VtZW50LiBlLmcuIGEgbW9kdWxlIHNjb3BlIHZhcmlhYmxlIGlzIGdsb2JhbAogICAJaWYoICBHZXRCYXNpYygpLT5Jc0RvY0Jhc2ljKCkgJiYgYlZCQVN1cHBvcnRPbiAmJiAhcFByb2MgKSAKCQliUGVyc2lzdGFudEdsb2JhbCA9IHNhbF9UcnVlOwoJLy8gUFJJVkFURSBpc3QgU3lub255bSBmdWVyIERJTQoJLy8gX0NPTlNUXz8KCXNhbF9Cb29sIGJDb25zdCA9IHNhbF9GYWxzZTsKCWlmKCBlQ3VyVG9rID09IF9DT05TVF8gKQoJCWJDb25zdCA9IHNhbF9UcnVlOwoJZWxzZSBpZiggUGVlaygpID09IF9DT05TVF8gKQoJCU5leHQoKSwgYkNvbnN0ID0gc2FsX1RydWU7CgoJLy8gIzExMDAwNCBJdCBjYW4gYWxzbyBiZSBhIHN1Yi9mdW5jdGlvbgoJaWYoICFiQ29uc3QgJiYgKGVDdXJUb2sgPT0gU1VCIHx8IGVDdXJUb2sgPT0gRlVOQ1RJT04gfHwgZUN1clRvayA9PSBQUk9QRVJUWSB8fAoJCQkJCWVDdXJUb2sgPT0gU1RBVElDIHx8IGVDdXJUb2sgPT0gRU5VTSB8fCBlQ3VyVG9rID09IERFQ0xBUkUgfHwgZUN1clRvayA9PSBUWVBFKSApCgl7CgkJLy8gTmV4dCB0b2tlbiBpcyByZWFkIGhlcmUsIGJlY2F1c2UgIWJDb25zdAoJCWJvb2wgYlByaXZhdGUgPSAoIGVGaXJzdFRvayA9PSBQUklWQVRFICk7CgoJCWlmKCBlQ3VyVG9rID09IFNUQVRJQyApCgkJewoJCQlOZXh0KCk7CgkJCURlZlN0YXRpYyggYlByaXZhdGUgKTsKCQl9CgkJZWxzZSBpZiggZUN1clRvayA9PSBTVUIgfHwgZUN1clRvayA9PSBGVU5DVElPTiB8fCBlQ3VyVG9rID09IFBST1BFUlRZICkKCQl7CgkJCS8vIEVuZCBnbG9iYWwgY2hhaW4gaWYgbmVjZXNzYXJ5IChub3QgZG9uZSBpbiAKCQkJLy8gU2JpUGFyc2VyOjpQYXJzZSgpIHVuZGVyIHRoZXNlIGNvbmRpdGlvbnMKCQkJaWYoIGJOZXdHYmxEZWZzICYmIG5HYmxDaGFpbiA9PSAwICkKCQkJewoJCQkJbkdibENoYWluID0gYUdlbi5HZW4oIF9KVU1QLCAwICk7CgkJCQliTmV3R2JsRGVmcyA9IHNhbF9GYWxzZTsKCQkJfQoJCQlOZXh0KCk7CgkJCURlZlByb2MoIHNhbF9GYWxzZSwgYlByaXZhdGUgKTsKCQkJcmV0dXJuOwoJCX0KCQllbHNlIGlmKCBlQ3VyVG9rID09IEVOVU0gKQoJCXsKCQkJTmV4dCgpOwoJCQlEZWZFbnVtKCBiUHJpdmF0ZSApOwoJCQlyZXR1cm47CgkJfQoJCWVsc2UgaWYoIGVDdXJUb2sgPT0gREVDTEFSRSApCgkJewoJCQlOZXh0KCk7CgkJCURlZkRlY2xhcmUoIGJQcml2YXRlICk7IAoJCQlyZXR1cm47CgkJfQoJCS8vICNpMTA5MDQ5CgkJZWxzZSBpZiggZUN1clRvayA9PSBUWVBFICkKCQl7CgkJCU5leHQoKTsKCQkJRGVmVHlwZSggYlByaXZhdGUgKTsKCQkJcmV0dXJuOwoJCX0KCX0KCiNpZmRlZiBTSEFSRUQKI2RlZmluZSB0bXBTSEFSRUQKI3VuZGVmIFNIQVJFRAojZW5kaWYKCS8vIFNIQVJFRCB3aXJkIGlnbm9yaWVydAoJaWYoIFBlZWsoKSA9PSBTSEFSRUQgKSBOZXh0KCk7CiNpZmRlZiB0bXBTSEFSRUQKI2RlZmluZSBTSEFSRUQKI3VuZGVmIHRtcFNIQVJFRAojZW5kaWYKCS8vIFBSRVNFUlZFIG51ciBiZWkgUkVESU0KCWlmKCBQZWVrKCkgPT0gUFJFU0VSVkUgKQoJewoJCU5leHQoKTsKCQlpZiggZU9wID09IF9SRURJTSApCgkJCWVPcCA9IF9SRURJTVA7CgkJZWxzZQoJCQlFcnJvciggU2JFUlJfVU5FWFBFQ1RFRCwgZUN1clRvayApOwoJfQoJU2JpU3ltRGVmKiBwRGVmOwoJU2JpRGltTGlzdCogcERpbTsKCgkvLyBBQiA5LjcuOTcsICM0MDY4OSwgU3RhdGljcyAtPiBNb2R1bC1Jbml0aWFsaXNpZXJ1bmcsIGluIFN1YiB1ZWJlcnNwcmluZ2VuCglzYWxfdUludDMyIG5FbmRPZlN0YXRpY0xibCA9IDA7CglpZiggIWJWQkFTdXBwb3J0T24gJiYgYlN0YXRpYyApCgl7CgkJbkVuZE9mU3RhdGljTGJsID0gYUdlbi5HZW4oIF9KVU1QLCAwICk7CgkJYUdlbi5TdGF0ZW1lbnQoKTsJLy8gYmVpIHN0YXRpYyBoaWVyIG5hY2hob2xlbgoJfQoKCXNhbF9Cb29sIGJEZWZpbmVkID0gc2FsX0ZhbHNlOwoJd2hpbGUoICggcERlZiA9IFZhckRlY2woICZwRGltLCBiU3RhdGljLCBiQ29uc3QgKSApICE9IE5VTEwgKQoJewoJCUVuYWJsZUVycm9ycygpOwoJCS8vIFZhcmlhYmxlIHN1Y2hlbjoKCQlpZiggYlN3aXRjaFBvb2wgKQoJCQlwUG9vbCA9ICZhR2xvYmFsczsKCQlTYmlTeW1EZWYqIHBPbGQgPSBwUG9vbC0+RmluZCggcERlZi0+R2V0TmFtZSgpICk7CgkJLy8gQUIgMzEuMy4xOTk2LCAjMjU2NTEjLCBhdWNoIGluIFJ1bnRpbWUtTGlicmFyeSBzdWNoZW4KCQlzYWxfQm9vbCBiUnRsU3ltID0gc2FsX0ZhbHNlOwoJCWlmKCAhcE9sZCApCgkJewoJCQlwT2xkID0gQ2hlY2tSVExGb3JTeW0oIHBEZWYtPkdldE5hbWUoKSwgU2J4VkFSSUFOVCApOwoJCQlpZiggcE9sZCApCgkJCQliUnRsU3ltID0gc2FsX1RydWU7CgkJfQoJCWlmKCBwT2xkICYmICEoZU9wID09IF9SRURJTSB8fCBlT3AgPT0gX1JFRElNUCkgKQoJCXsKCQkJaWYoIHBEZWYtPkdldFNjb3BlKCkgPT0gU2JMT0NBTCAmJiBwT2xkLT5HZXRTY29wZSgpICE9IFNiTE9DQUwgKQoJCQkJcE9sZCA9IE5VTEw7CgkJfQoJCWlmKCBwT2xkICkKCQl7CgkJCWJEZWZpbmVkID0gc2FsX1RydWU7CgkJCS8vIEJlaSBSVEwtU3ltYm9sIGltbWVyIEZlaGxlcgoJCQlpZiggIWJSdGxTeW0gJiYgKGVPcCA9PSBfUkVESU0gfHwgZU9wID09IF9SRURJTVApICkKCQkJewoJCQkJLy8gQmVpIFJFRElNIGRpZSBBdHRyaWJ1dGUgdmVyZ2xlaWNoZW4KCQkJCVNieERhdGFUeXBlIGVEZWZUeXBlOwoJCQkJYm9vbCBiRXJyb3JfID0gZmFsc2U7CgkJCQlpZiggcE9sZC0+SXNTdGF0aWMoKSApCgkJCQl7CgkJCQkJYkVycm9yXyA9IHRydWU7CgkJCQl9CgkJCQllbHNlIGlmKCBwT2xkLT5HZXRUeXBlKCkgIT0gKCBlRGVmVHlwZSA9IHBEZWYtPkdldFR5cGUoKSApICkKCQkJCXsKCQkJCQlpZiggISggZURlZlR5cGUgPT0gU2J4VkFSSUFOVCAmJiAhcERlZi0+SXNEZWZpbmVkQXMoKSApICkKCQkJCQkJYkVycm9yXyA9IHRydWU7CgkJCQl9CgkJCQlpZiggYkVycm9yXyApCgkJCQkJRXJyb3IoIFNiRVJSX1ZBUl9ERUZJTkVELCBwRGVmLT5HZXROYW1lKCkgKTsKCQkJfQoJCQllbHNlCgkJCQlFcnJvciggU2JFUlJfVkFSX0RFRklORUQsIHBEZWYtPkdldE5hbWUoKSApOwoJCQlkZWxldGUgcERlZjsgcERlZiA9IHBPbGQ7CgkJfQoJCWVsc2UKCQkJcFBvb2wtPkFkZCggcERlZiApOwoKCQkvLyAjMzYzNzQ6IFZhcmlhYmxlIHZvciBVbnRlcnNjaGVpZHVuZyBJc05ldygpIGFubGVnZW4KCQkvLyBTb25zdCBFcnJvciBiZWkgRGltIElkZW50aWZpZXIgQXMgTmV3IFR5cGUgdW5kIG9wdGlvbiBleHBsaWNpdAoJCWlmKCAhYkRlZmluZWQgJiYgIShlT3AgPT0gX1JFRElNIHx8IGVPcCA9PSBfUkVESU1QKQogICAgICAgICAgICAgICAgICAgICAgJiYgKCAhYkNvbnN0IHx8IHBEZWYtPkdldFNjb3BlKCkgPT0gU2JHTE9CQUwgKSApCgkJewoJCQkvLyBWYXJpYWJsZSBvZGVyIGdsb2JhbGUgS29uc3RhbnRlIGRla2xhcmllcmVuCgkJCVNiaU9wY29kZSBlT3AyOwoJCQlzd2l0Y2ggKCBwRGVmLT5HZXRTY29wZSgpICkKCQkJewoJCQkJY2FzZSBTYkdMT0JBTDoJZU9wMiA9IGJQZXJzaXN0YW50R2xvYmFsID8gX0dMT0JBTF9QIDogX0dMT0JBTDsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBnbG9iYWw7CgkJCQljYXNlIFNiUFVCTElDOgllT3AyID0gYlBlcnNpc3RhbnRHbG9iYWwgPyBfUFVCTElDX1AgOiBfUFVCTElDOwoJCQkJCQkJCS8vIEFCIDkuNy45NywgIzQwNjg5LCBrZWluIGVpZ2VuZXIgT3Bjb2RlIG1laHIKCQkJCQkJCQlpZiggYlZCQVN1cHBvcnRPbiAmJiBiU3RhdGljICkKCQkJCQkJCQl7CgkJCQkJCQkJCWVPcDIgPSBfU1RBVElDOwoJCQkJCQkJCQlicmVhazsKCQkJCQkJCQl9CgkJCQlnbG9iYWw6CQkJYUdlbi5CYWNrQ2hhaW4oIG5HYmxDaGFpbiApOwoJCQkJCQkJCW5HYmxDaGFpbiA9IDA7CgkJCQkJCQkJYkdibERlZnMgPSBiTmV3R2JsRGVmcyA9IHNhbF9UcnVlOwoJCQkJCQkJCWJyZWFrOwoJCQkJZGVmYXVsdDoJCWVPcDIgPSBfTE9DQUw7CgkJCX0KCQkJc2FsX3VJbnQzMiBuT3BuZDIgPSBzYWw6OnN0YXRpY19pbnRfY2FzdDwgc2FsX3VJbnQxNiA+KCBwRGVmLT5HZXRUeXBlKCkgKTsKCQkJaWYoIHBEZWYtPklzV2l0aEV2ZW50cygpICkKCQkJCW5PcG5kMiB8PSBTQlhfVFlQRV9XSVRIX0VWRU5UU19GTEFHOwoKCQkJaWYoIGJDb21wYXRpYmxlICYmIHBEZWYtPklzTmV3KCkgKQoJCQkJbk9wbmQyIHw9IFNCWF9UWVBFX0RJTV9BU19ORVdfRkxBRzsKCgkJCXNob3J0IG5GaXhlZFN0cmluZ0xlbmd0aCA9IHBEZWYtPkdldEZpeGVkU3RyaW5nTGVuZ3RoKCk7CgkJCWlmKCBuRml4ZWRTdHJpbmdMZW5ndGggPj0gMCApCgkJCQluT3BuZDIgfD0gKFNCWF9GSVhFRF9MRU5fU1RSSU5HX0ZMQUcgKyAoc2FsX3VJbnQzMihuRml4ZWRTdHJpbmdMZW5ndGgpIDw8IDE3KSk7CQkvLyBsZW4gPSBhbGwgYml0cyBhYm92ZSAweDEwMDAwCgoJCQlpZiggcERpbSAhPSBOVUxMICYmIHBEaW0tPkdldERpbXMoKSA+IDAgKQoJCQkJbk9wbmQyIHw9IFNCWF9UWVBFX1ZBUl9UT19ESU1fRkxBRzsKCgkJCWFHZW4uR2VuKCBlT3AyLCBwRGVmLT5HZXRJZCgpLCBuT3BuZDIgKTsKCQl9CgoJCS8vIEluaXRpYWxpc2llcnVuZyBmdWVyIHNlbGJzdGRlZmluaWVydGUgRGF0ZW50eXBlbgoJCS8vIHVuZCBwZXIgTkVXIGFuZ2VsZWd0ZSBWYXJpYWJsZQoJCWlmKCBwRGVmLT5HZXRUeXBlKCkgPT0gU2J4T0JKRUNUCgkJICYmIHBEZWYtPkdldFR5cGVJZCgpICkKCQl7CgkJCWlmKCAhYkNvbXBhdGlibGUgJiYgIXBEZWYtPklzTmV3KCkgKQoJCQl7CgkJCQlTdHJpbmcgYVR5cGVOYW1lKCBhR2JsU3RyaW5ncy5GaW5kKCBwRGVmLT5HZXRUeXBlSWQoKSApICk7CgkJCQlpZiggclR5cGVBcnJheS0+RmluZCggYVR5cGVOYW1lLCBTYnhDTEFTU19PQkpFQ1QgKSA9PSBOVUxMICkKCQkJCQlFcnJvciggU2JFUlJfVU5ERUZfVFlQRSwgYVR5cGVOYW1lICk7CgkJCX0KCgkJCWlmKCBiQ29uc3QgKQoJCQl7CgkJCQlFcnJvciggU2JFUlJfU1lOVEFYICk7CgkJCX0KCgkJCWlmKCBwRGltICkKCQkJewogICAgICAgICAgICAgICAgaWYoIGVPcCA9PSBfUkVESU1QICkKICAgICAgICAgICAgICAgIHsKCQkJCQlTYmlFeHByZXNzaW9uIGFFeHByKCB0aGlzLCAqcERlZiwgTlVMTCApOwoJCQkJCWFFeHByLkdlbigpOwoJCQkJCWFHZW4uR2VuKCBfUkVESU1QX0VSQVNFICk7CgoJCQkJICAgIHBEZWYtPlNldERpbXMoIHBEaW0tPkdldERpbXMoKSApOwoJCQkJICAgIFNiaUV4cHJlc3Npb24gYUV4cHIyKCB0aGlzLCAqcERlZiwgcERpbSApOwoJCQkJICAgIGFFeHByMi5HZW4oKTsKICAgIAkJCQlhR2VuLkdlbiggX0RDUkVBVEVfUkVESU1QLCBwRGVmLT5HZXRJZCgpLCBwRGVmLT5HZXRUeXBlSWQoKSApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewoJCQkJICAgIHBEZWYtPlNldERpbXMoIHBEaW0tPkdldERpbXMoKSApOwoJCQkJICAgIFNiaUV4cHJlc3Npb24gYUV4cHIoIHRoaXMsICpwRGVmLCBwRGltICk7CgkJCQkgICAgYUV4cHIuR2VuKCk7CgkgICAgCQkJYUdlbi5HZW4oIF9EQ1JFQVRFLCBwRGVmLT5HZXRJZCgpLCBwRGVmLT5HZXRUeXBlSWQoKSApOwogICAgICAgICAgICAgICAgfQoJCQl9CgkJCWVsc2UKCQkJewoJCQkJU2JpRXhwcmVzc2lvbiBhRXhwciggdGhpcywgKnBEZWYgKTsKCQkJCWFFeHByLkdlbigpOwoJCQkJU2JpT3Bjb2RlIGVPcF8gPSBwRGVmLT5Jc05ldygpID8gX0NSRUFURSA6IF9UQ1JFQVRFOwoJCQkJYUdlbi5HZW4oIGVPcF8sIHBEZWYtPkdldElkKCksIHBEZWYtPkdldFR5cGVJZCgpICk7CgkJCQlhR2VuLkdlbiggX1NFVCApOwoJCQl9CgkJfQoJCWVsc2UKCQl7CgkJCWlmKCBiQ29uc3QgKQoJCQl7CgkJCQkvLyBLb25zdGFudGVuLURlZmluaXRpb24KCQkJCWlmKCBwRGltICkKCQkJCXsKCQkJCQlFcnJvciggU2JFUlJfU1lOVEFYICk7CgkJCQkJZGVsZXRlIHBEaW07CgkJCQl9CgkJCQlTYmlFeHByZXNzaW9uIGFWYXIoIHRoaXMsICpwRGVmICk7CgkJCQlpZiggIVRlc3RUb2tlbiggRVEgKSApCgkJCQkJZ290byBNeUJyZWFrOwkvLyBBQiAyNC42LjE5OTYgKHMudS4pCgkJCQlTYmlDb25zdEV4cHJlc3Npb24gYUV4cHIoIHRoaXMgKTsKCQkJCWlmKCAhYkRlZmluZWQgJiYgYUV4cHIuSXNWYWxpZCgpICkKCQkJCXsKCQkJCQlpZiggcERlZi0+R2V0U2NvcGUoKSA9PSBTYkdMT0JBTCApCgkJCQkJewoJCQkJCQkvLyBOdXIgQ29kZSBmdWVyIGdsb2JhbGUgS29uc3RhbnRlIGVyemV1Z2VuIQoJCQkJCQlhVmFyLkdlbigpOwoJCQkJCQlhRXhwci5HZW4oKTsKCQkJCQkJYUdlbi5HZW4oIF9QVVRDICk7CgkJCQkJfQoJCQkJCVNiaUNvbnN0RGVmKiBwQ29uc3QgPSBwRGVmLT5HZXRDb25zdERlZigpOwoJCQkJCWlmKCBhRXhwci5HZXRUeXBlKCkgPT0gU2J4U1RSSU5HICkKCQkJCQkJcENvbnN0LT5TZXQoIGFFeHByLkdldFN0cmluZygpICk7CgkJCQkJZWxzZQoJCQkJCQlwQ29uc3QtPlNldCggYUV4cHIuR2V0VmFsdWUoKSwgYUV4cHIuR2V0VHlwZSgpICk7CgkJCQl9CgkJCX0KCQkJZWxzZSBpZiggcERpbSApCgkJCXsKCQkJCS8vIERpZSBWYXJpYWJsZSBkaW1lbnNpb25pZXJlbgoJCQkJLy8gQmVpIFJFRElNIGRpZSBWYXIgdm9yaGVyIGxvZXNjaGVuCgkJCQlpZiggZU9wID09IF9SRURJTSApCgkJCQl7CgkJCQkJU2JpRXhwcmVzc2lvbiBhRXhwciggdGhpcywgKnBEZWYsIE5VTEwgKTsKCQkJCQlhRXhwci5HZW4oKTsKCQkJCQlpZiAoIGJWQkFTdXBwb3J0T24gKQoJCQkJCQkvLyBkZWxldGUgdGhlIGFycmF5IGJ1dAoJCQkJCQkvLyBjbGVhciB0aGUgdmFyaWFibGUgKCB0aGlzCgkJCQkJCS8vIGFsbG93cyB0aGUgcHJvY2Vzc2luZyBvZgoJCQkJCQkvLyB0aGUgcGFyYW0gdG8gaGFwcGVuIGFzIG5vcm1hbCB3aXRob3V0IGVycm9ycyAoIG9yZGluYXJ5IEVSQVNFIGp1c3QgY2xlYXJzIHRoZSBhcnJheSApCgkJCQkJCWFHZW4uR2VuKCBfRVJBU0VfQ0xFQVIgKTsKCQkJCQllbHNlCgkJCQkJCWFHZW4uR2VuKCBfRVJBU0UgKTsKCQkJCX0KCQkJCWVsc2UgaWYoIGVPcCA9PSBfUkVESU1QICkKCQkJCXsKCQkJCQlTYmlFeHByZXNzaW9uIGFFeHByKCB0aGlzLCAqcERlZiwgTlVMTCApOwoJCQkJCWFFeHByLkdlbigpOwoJCQkJCWFHZW4uR2VuKCBfUkVESU1QX0VSQVNFICk7CgkJCQl9CgkJCQlwRGVmLT5TZXREaW1zKCBwRGltLT5HZXREaW1zKCkgKTsKICAgICAgICAgICAgICAgIGlmKCBiUGVyc2lzdGFudEdsb2JhbCApCiAgICAgICAgICAgICAgICAgICAgcERlZi0+U2V0R2xvYmFsKCBzYWxfVHJ1ZSApOwoJCQkJU2JpRXhwcmVzc2lvbiBhRXhwciggdGhpcywgKnBEZWYsIHBEaW0gKTsKCQkJCWFFeHByLkdlbigpOwogICAgICAgICAgICAgICAgcERlZi0+U2V0R2xvYmFsKCBzYWxfRmFsc2UgKTsKCQkJCWFHZW4uR2VuKCAoZU9wID09IF9TVEFUSUMpID8gX0RJTSA6IGVPcCApOwoJCQl9CgkJfQoJCWlmKCAhVGVzdENvbW1hKCkgKQoJCQlnb3RvIE15QnJlYWs7CS8vIEFCIDI0LjYuMTk5NiAocy51LikKCgkJLy8gIzI3OTYzIyBBQiwgMjQuNi4xOTk2CgkJLy8gRWluZnVlaHJ1bmcgYlN3aXRjaFBvb2wgKHMuby4pOiBwUG9vbCBkYXJmIGJlaW0gVmFyRGVjbC1BdWZydWYKCQkvLyBub2NoIG5pY2h0IGF1ZiAmYUdsb2JhbHMgZ2VzZXR6dCBzZWluLgoJCS8vIEFuc29uc3RlbiBzb2xsIGRhcyBWZXJoYWx0ZW4gYWJlciBhYnNvbHV0IGlkZW50aXNjaCBibGVpYmVuLAoJCS8vIGQuaC4gcFBvb2wgbXVzcyBpbW1lciBhbSBTY2hsZWlmZW4tRW5kZSB6dXJ1ZWNrZ2VzZXR6dCB3ZXJkZW4uCgkJLy8gYXVjaCBiZWkgYnJlYWsKCQlwUG9vbCA9IHBPbGRQb29sOwoJCWNvbnRpbnVlOwkJLy8gTXlCcmVhayD8YmVyc3BpbmdlbgoJTXlCcmVhazoKCQlwUG9vbCA9IHBPbGRQb29sOwoJCWJyZWFrOwoJfQoKCS8vIEFCIDkuNy45NywgIzQwNjg5LCBTcHJ1bmcgdWViZXIgU3RhdGljcy1EZWtsYXJhdGlvbiBhYnNjaGxpZXNzZW4KCWlmKCAhYlZCQVN1cHBvcnRPbiAmJiBiU3RhdGljICkKCXsKCQkvLyBnbG9iYWxlbiBDaGFpbiBwZmxlZ2VuCgkJbkdibENoYWluID0gYUdlbi5HZW4oIF9KVU1QLCAwICk7CgkJYkdibERlZnMgPSBiTmV3R2JsRGVmcyA9IHNhbF9UcnVlOwoKCQkvLyBmdWVyIFN1YiBTcHJ1bmcgYXVmIEVuZGUgZGVyIHN0YXRpY3MgZWludHJhZ2VuCgkJYUdlbi5CYWNrQ2hhaW4oIG5FbmRPZlN0YXRpY0xibCApOwoJfQoKCS8vcFBvb2wgPSBwT2xkUG9vbDsKfQoKLy8gSGllciB3ZXJkZW4gQXJyYXlzIHJlZGltZW5zaW9uaWVydC4KCnZvaWQgU2JpUGFyc2VyOjpSZURpbSgpCnsKCURlZlZhciggX1JFRElNLCAoICBwUHJvYyAmJiBiVkJBU3VwcG9ydE9uICkgPyBwUHJvYy0+SXNTdGF0aWMoKSA6IHNhbF9GYWxzZSApOwp9CgovLyBFUkFTRSBhcnJheSwgLi4uCgp2b2lkIFNiaVBhcnNlcjo6RXJhc2UoKQp7Cgl3aGlsZSggIWJBYm9ydCApCgl7CgkJU2JpRXhwcmVzc2lvbiBhRXhwciggdGhpcywgU2JMVkFMVUUgKTsKCQlhRXhwci5HZW4oKTsKCQlhR2VuLkdlbiggX0VSQVNFICk7CgkJaWYoICFUZXN0Q29tbWEoKSApIGJyZWFrOwoJfQp9CgovLyBEZWtsYXJhdGlvbiBlaW5lcyBEYXRlbnR5cHMKCnZvaWQgU2JpUGFyc2VyOjpUeXBlKCkKewoJRGVmVHlwZSggc2FsX0ZhbHNlICk7Cn0KCnZvaWQgU2JpUGFyc2VyOjpEZWZUeXBlKCBzYWxfQm9vbCBiUHJpdmF0ZSApCnsKCS8vIFRPRE86IFVzZSBiUHJpdmF0ZQogICAgKHZvaWQpYlByaXZhdGU7CgoJLy8gTmV1ZXMgVG9rZW4gbGVzZW4sIGVzIG11c3MgZWluIFN5bWJvbCBzZWluCglpZiAoIVRlc3RTeW1ib2woKSkKCQlyZXR1cm47CgoJaWYgKHJUeXBlQXJyYXktPkZpbmQoYVN5bSxTYnhDTEFTU19PQkpFQ1QpKQoJewoJCUVycm9yKCBTYkVSUl9WQVJfREVGSU5FRCwgYVN5bSApOwoJCXJldHVybjsKCX0KCglTYnhPYmplY3QgKnBUeXBlID0gbmV3IFNieE9iamVjdChhU3ltKTsKCglTYmlTeW1EZWYqIHBFbGVtOwoJU2JpRGltTGlzdCogcERpbSA9IE5VTEw7CglzYWxfQm9vbCBiRG9uZSA9IHNhbF9GYWxzZTsKCgl3aGlsZSggIWJEb25lICYmICFJc0VvZigpICkKCXsKCQlzd2l0Y2goIFBlZWsoKSApCgkJewoJCQljYXNlIEVORFRZUEUgOgoJCQkJcEVsZW0gPSBOVUxMOwoJCQkJYkRvbmUgPSBzYWxfVHJ1ZTsKCQkJCU5leHQoKTsKCQkJYnJlYWs7CgoJCQljYXNlIEVPTE4gOgoJCQljYXNlIFJFTSA6CgkJCQlwRWxlbSA9IE5VTEw7CgkJCQlOZXh0KCk7CgkJCWJyZWFrOwoKCQkJZGVmYXVsdDoKCQkJCXBEaW0gPSBOVUxMOwoJCQkJcEVsZW0gPSBWYXJEZWNsKCZwRGltLHNhbF9GYWxzZSxzYWxfRmFsc2UpOwoJCQkJaWYoICFwRWxlbSApCgkJCQkJYkRvbmUgPSBzYWxfVHJ1ZTsJLy8gRXJyb3Igb2NjdXJyZWQKCQl9CgkJaWYoIHBFbGVtICkKCQl7CgkJCVNieEFycmF5ICpwVHlwZU1lbWJlcnMgPSBwVHlwZS0+R2V0UHJvcGVydGllcygpOwoJCQlTdHJpbmcgYUVsZW1OYW1lID0gcEVsZW0tPkdldE5hbWUoKTsKCQkJaWYoIHBUeXBlTWVtYmVycy0+RmluZCggYUVsZW1OYW1lLCBTYnhDTEFTU19ET05UQ0FSRSkgKQoJCQkJRXJyb3IgKFNiRVJSX1ZBUl9ERUZJTkVEKTsKCQkJZWxzZQoJCQl7CgkJCQlTYnhEYXRhVHlwZSBlRWxlbVR5cGUgPSBwRWxlbS0+R2V0VHlwZSgpOwoJCQkJU2J4UHJvcGVydHkgKnBUeXBlRWxlbSA9IG5ldyBTYnhQcm9wZXJ0eSggYUVsZW1OYW1lLCBlRWxlbVR5cGUgKTsKCQkJCWlmKCBwRGltICkKCQkJCXsKCQkJCQlTYnhEaW1BcnJheSogcEFycmF5ID0gbmV3IFNieERpbUFycmF5KCBwRWxlbS0+R2V0VHlwZSgpICk7CQoJCQkJCWlmICggcERpbS0+R2V0U2l6ZSgpICkKCQkJCQl7CgkJCQkJCS8vIERpbWVuc2lvbiB0aGUgdGFyZ2V0IGFycmF5CgoJCQkJCQlmb3IgKCBzaG9ydCBpPTA7IGk8cERpbS0+R2V0U2l6ZSgpOysraSApCgkJCQkJCXsKCQkJCQkJCXNhbF9JbnQzMiB1YiA9IC0xOwoJCQkJCQkJc2FsX0ludDMyIGxiID0gbkJhc2U7CgkJCQkJCQlTYmlFeHByTm9kZSogcE5vZGUgPSAgcERpbS0+R2V0KGkpLT5HZXRFeHByTm9kZSgpOwoJCQkJCQkJdWIgPSBwTm9kZS0+R2V0TnVtYmVyKCk7CgkJCQkJCQlpZiAoICFwRGltLT5HZXQoIGkgKS0+SXNCYXNlZCgpICkgLy8gZWFjaCBkaW0gaXMgbG93L3VwCgkJCQkJCQl7CgkJCQkJCQkJaWYgKCAgKytpID49IHBEaW0tPkdldFNpemUoKSApIC8vIHRyb3VibGUKCQkJCQkJCQkJU3RhckJBU0lDOjpGYXRhbEVycm9yKCBTYkVSUl9JTlRFUk5BTF9FUlJPUiApOwoJCQkJCQkJCXBOb2RlID0gIHBEaW0tPkdldChpKS0+R2V0RXhwck5vZGUoKTsKCQkJCQkJCQlsYiA9IHViOwoJCQkJCQkJCXViID0gcE5vZGUtPkdldE51bWJlcigpOwoJCQkJCQkJfQoJCQkJCQkJZWxzZSBpZiAoICFiQ29tcGF0aWJsZSApCgkJCQkJCQkJdWIgKz0gbkJhc2U7CgkJCQkJCQlwQXJyYXktPkFkZERpbTMyKCBsYiwgdWIgKTsgICAgICAKCQkJCQkJfQoJCQkJCQlwQXJyYXktPnNldEhhc0ZpeGVkU2l6ZSggdHJ1ZSApOwoJCQkJCX0KCQkJCQllbHNlCgkJCQkJCXBBcnJheS0+dW5vQWRkRGltKCAwLCAtMSApOyAvLyB2YXJpYW50IGFycmF5CgkJCQkJc2FsX3VJbnQxNiBuU2F2RmxhZ3MgPSBwVHlwZUVsZW0tPkdldEZsYWdzKCk7CgkJCQkJLy8gbmVlZCB0byByZXNldCB0aGUgRklYRUQgZmxhZyAKCQkJCQkvLyB3aGVuIGNhbGxpbmcgUHV0T2JqZWN0ICggYmVjYXVzZSB0aGUgdHlwZSB3aWxsIG5vdCBtYXRjaCBPYmplY3QgKSAJCgkJCQkJcFR5cGVFbGVtLT5SZXNldEZsYWcoIFNCWF9GSVhFRCApOwoJCQkJCXBUeXBlRWxlbS0+UHV0T2JqZWN0KCBwQXJyYXkgKTsKCQkJCQlwVHlwZUVsZW0tPlNldEZsYWdzKCBuU2F2RmxhZ3MgKTsKCQkJCX0KCQkJCS8vIE5lc3RlZCB1c2VyIHR5cGU/CgkJCQlpZiggZUVsZW1UeXBlID09IFNieE9CSkVDVCApCgkJCQl7CgkJCQkJc2FsX3VJbnQxNiBuRWxlbVR5cGVJZCA9IHBFbGVtLT5HZXRUeXBlSWQoKTsKCQkJCQlpZiggbkVsZW1UeXBlSWQgIT0gMCApCgkJCQkJewoJCQkJCQlTdHJpbmcgYVR5cGVOYW1lKCBhR2JsU3RyaW5ncy5GaW5kKCBuRWxlbVR5cGVJZCApICk7CgkJCQkJCVNieE9iamVjdCogcFR5cGVPYmogPSBzdGF0aWNfY2FzdDwgU2J4T2JqZWN0KiA+KCByVHlwZUFycmF5LT5GaW5kKCBhVHlwZU5hbWUsIFNieENMQVNTX09CSkVDVCApICk7CgkJCQkJCWlmKCBwVHlwZU9iaiAhPSBOVUxMICkKCQkJCQkJewoJCQkJCQkJU2J4T2JqZWN0KiBwQ2xvbmVPYmogPSBjbG9uZVR5cGVPYmplY3RJbXBsKCAqcFR5cGVPYmogKTsKCQkJCQkJCXBUeXBlRWxlbS0+UHV0T2JqZWN0KCBwQ2xvbmVPYmogKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCWRlbGV0ZSBwRGltOwoJCQkJcFR5cGVNZW1iZXJzLT5JbnNlcnQoIHBUeXBlRWxlbSwgcFR5cGVNZW1iZXJzLT5Db3VudCgpICk7CgkJCX0KCQkJZGVsZXRlIHBFbGVtOwoJCX0KCX0KCglwVHlwZS0+UmVtb3ZlKCBYdWJTdHJpbmcoIFJUTF9DT05TVEFTQ0lJX1VTVFJJTkdQQVJBTSgiTmFtZSIpICksIFNieENMQVNTX0RPTlRDQVJFICk7CglwVHlwZS0+UmVtb3ZlKCBYdWJTdHJpbmcoIFJUTF9DT05TVEFTQ0lJX1VTVFJJTkdQQVJBTSgiUGFyZW50IikgKSwgU2J4Q0xBU1NfRE9OVENBUkUgKTsKCglyVHlwZUFycmF5LT5JbnNlcnQgKHBUeXBlLHJUeXBlQXJyYXktPkNvdW50KCkpOwp9CgoKLy8gRGVjbGFyYXRpb24gb2YgRW51bSB0eXBlCgp2b2lkIFNiaVBhcnNlcjo6RW51bSgpCnsKCURlZkVudW0oIHNhbF9GYWxzZSApOwp9Cgp2b2lkIFNiaVBhcnNlcjo6RGVmRW51bSggc2FsX0Jvb2wgYlByaXZhdGUgKQp7CgkvLyBOZXVlcyBUb2tlbiBsZXNlbiwgZXMgbXVzcyBlaW4gU3ltYm9sIHNlaW4KCWlmICghVGVzdFN5bWJvbCgpKQoJCXJldHVybjsKCglTdHJpbmcgYUVudW1OYW1lID0gYVN5bTsKCWlmKCByRW51bUFycmF5LT5GaW5kKGFFbnVtTmFtZSxTYnhDTEFTU19PQkpFQ1QpICkKCXsKCQlFcnJvciggU2JFUlJfVkFSX0RFRklORUQsIGFTeW0gKTsKCQlyZXR1cm47Cgl9CgoJU2J4T2JqZWN0ICpwRW51bSA9IG5ldyBTYnhPYmplY3QoIGFFbnVtTmFtZSApOwoJaWYoIGJQcml2YXRlICkKCQlwRW51bS0+U2V0RmxhZyggU0JYX1BSSVZBVEUgKTsKCglTYmlTeW1EZWYqIHBFbGVtOwoJU2JpRGltTGlzdCogcERpbTsKCXNhbF9Cb29sIGJEb25lID0gc2FsX0ZhbHNlOwoKCS8vIFN0YXJ0aW5nIHdpdGggLTEgdG8gbWFrZSBmaXJzdCBkZWZhdWx0IHZhbHVlIDAgYWZ0ZXIgKysKCXNhbF9JbnQzMiBuQ3VycmVudEVudW1WYWx1ZSA9IC0xOwoJd2hpbGUoICFiRG9uZSAmJiAhSXNFb2YoKSApCgl7CgkJc3dpdGNoKCBQZWVrKCkgKQoJCXsKCQkJY2FzZSBFTkRFTlVNIDoKCQkJCXBFbGVtID0gTlVMTDsKCQkJCWJEb25lID0gc2FsX1RydWU7CgkJCQlOZXh0KCk7CgkJCWJyZWFrOwoKCQkJY2FzZSBFT0xOIDoKCQkJY2FzZSBSRU0gOgoJCQkJcEVsZW0gPSBOVUxMOwoJCQkJTmV4dCgpOwoJCQlicmVhazsKCgkJCWRlZmF1bHQ6CgkJCXsKCQkJCS8vIFRPRE86IENoZWNrIGV4aXN0aW5nIQoJCQkJc2FsX0Jvb2wgYkRlZmluZWQgPSBzYWxfRmFsc2U7CgoJCQkJcERpbSA9IE5VTEw7CgkJCQlwRWxlbSA9IFZhckRlY2woICZwRGltLCBzYWxfRmFsc2UsIHNhbF9UcnVlICk7CgkJCQlpZiggIXBFbGVtICkKCQkJCXsKCQkJCQliRG9uZSA9IHNhbF9UcnVlOwkvLyBFcnJvciBvY2N1cnJlZAoJCQkJCWJyZWFrOwoJCQkJfQoJCQkJZWxzZSBpZiggcERpbSApCgkJCQl7CgkJCQkJZGVsZXRlIHBEaW07CgkJCQkJRXJyb3IoIFNiRVJSX1NZTlRBWCApOwoJCQkJCWJEb25lID0gc2FsX1RydWU7CS8vIEVycm9yIG9jY3VycmVkCgkJCQkJYnJlYWs7CgkJCQl9CgoJCQkJU2JpRXhwcmVzc2lvbiBhVmFyKCB0aGlzLCAqcEVsZW0gKTsKCQkJCWlmKCBQZWVrKCkgPT0gRVEgKQoJCQkJewoJCQkJCU5leHQoKTsKCgkJCQkJU2JpQ29uc3RFeHByZXNzaW9uIGFFeHByKCB0aGlzICk7CgkJCQkJaWYoICFiRGVmaW5lZCAmJiBhRXhwci5Jc1ZhbGlkKCkgKQoJCQkJCXsKCQkJCQkJU2J4VmFyaWFibGVSZWYgeENvbnZlcnRWYXIgPSBuZXcgU2J4VmFyaWFibGUoKTsKCQkJCQkJaWYoIGFFeHByLkdldFR5cGUoKSA9PSBTYnhTVFJJTkcgKQoJCQkJCQkJeENvbnZlcnRWYXItPlB1dFN0cmluZyggYUV4cHIuR2V0U3RyaW5nKCkgKTsKCQkJCQkJZWxzZQoJCQkJCQkJeENvbnZlcnRWYXItPlB1dERvdWJsZSggYUV4cHIuR2V0VmFsdWUoKSApOwoKCQkJCQkJbkN1cnJlbnRFbnVtVmFsdWUgPSB4Q29udmVydFZhci0+R2V0TG9uZygpOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UKCQkJCQluQ3VycmVudEVudW1WYWx1ZSsrOwoKCQkJCVNiaVN5bVBvb2wqIHBQb29sVG9Vc2UgPSBiUHJpdmF0ZSA/IHBQb29sIDogJmFHbG9iYWxzOwoKCQkJCVNiaVN5bURlZiogcE9sZCA9IHBQb29sVG9Vc2UtPkZpbmQoIHBFbGVtLT5HZXROYW1lKCkgKTsKCQkJCWlmKCBwT2xkICkKCQkJCXsKCQkJCQlFcnJvciggU2JFUlJfVkFSX0RFRklORUQsIHBFbGVtLT5HZXROYW1lKCkgKTsKCQkJCQliRG9uZSA9IHNhbF9UcnVlOwkvLyBFcnJvciBvY2N1cnJlZAoJCQkJCWJyZWFrOwoJCQkJfQoKCQkJCXBQb29sLT5BZGQoIHBFbGVtICk7CgoJCQkJaWYoICFiUHJpdmF0ZSApCgkJCQl7CgkJCQkJU2JpT3Bjb2RlIGVPcCA9IF9HTE9CQUw7IAoJCQkJCWFHZW4uQmFja0NoYWluKCBuR2JsQ2hhaW4gKTsKCQkJCQluR2JsQ2hhaW4gPSAwOwoJCQkJCWJHYmxEZWZzID0gYk5ld0dibERlZnMgPSBzYWxfVHJ1ZTsKCQkJCQlhR2VuLkdlbigKICAgICAgICAgICAgICAgICAgICAgICAgZU9wLCBwRWxlbS0+R2V0SWQoKSwKICAgICAgICAgICAgICAgICAgICAgICAgc2FsOjpzdGF0aWNfaW50X2Nhc3Q8IHNhbF91SW50MTYgPiggcEVsZW0tPkdldFR5cGUoKSApICk7CgoJCQkJCWFWYXIuR2VuKCk7CgkJCQkJc2FsX3VJbnQxNiBuU3RyaW5nSWQgPSBhR2VuLkdldFBhcnNlcigpLT5hR2JsU3RyaW5ncy5BZGQoIG5DdXJyZW50RW51bVZhbHVlLCBTYnhMT05HICk7CgkJCQkJYUdlbi5HZW4oIF9OVU1CRVIsIG5TdHJpbmdJZCApOwoJCQkJCWFHZW4uR2VuKCBfUFVUQyApOwoJCQkJfQoKCQkJCVNiaUNvbnN0RGVmKiBwQ29uc3QgPSBwRWxlbS0+R2V0Q29uc3REZWYoKTsKCQkJCXBDb25zdC0+U2V0KCBuQ3VycmVudEVudW1WYWx1ZSwgU2J4TE9ORyApOwoJCQl9CgkJfQoJCWlmKCBwRWxlbSApCgkJewoJCQlTYnhBcnJheSAqcEVudW1NZW1iZXJzID0gcEVudW0tPkdldFByb3BlcnRpZXMoKTsKCQkJU2J4UHJvcGVydHkgKnBFbnVtRWxlbSA9IG5ldyBTYnhQcm9wZXJ0eSggcEVsZW0tPkdldE5hbWUoKSwgU2J4TE9ORyApOwoJCQlwRW51bUVsZW0tPlB1dExvbmcoIG5DdXJyZW50RW51bVZhbHVlICk7CgkJCXBFbnVtRWxlbS0+UmVzZXRGbGFnKCBTQlhfV1JJVEUgKTsKCQkJcEVudW1FbGVtLT5TZXRGbGFnKCBTQlhfQ09OU1QgKTsKCQkJcEVudW1NZW1iZXJzLT5JbnNlcnQoIHBFbnVtRWxlbSwgcEVudW1NZW1iZXJzLT5Db3VudCgpICk7CgkJfQoJfQoKCXBFbnVtLT5SZW1vdmUoIFh1YlN0cmluZyggUlRMX0NPTlNUQVNDSUlfVVNUUklOR1BBUkFNKCJOYW1lIikgKSwgU2J4Q0xBU1NfRE9OVENBUkUgKTsKCXBFbnVtLT5SZW1vdmUoIFh1YlN0cmluZyggUlRMX0NPTlNUQVNDSUlfVVNUUklOR1BBUkFNKCJQYXJlbnQiKSApLCBTYnhDTEFTU19ET05UQ0FSRSApOwoKCXJFbnVtQXJyYXktPkluc2VydCggcEVudW0sIHJFbnVtQXJyYXktPkNvdW50KCkgKTsKfQoKCi8vIFByb3plZHVyLURla2xhcmF0aW9uCi8vIGRhcyBlcnN0ZSBUb2tlbiBpc3QgYmVyZWl0cyBlaW5nZWxlc2VuIChTVUIvRlVOQ1RJT04pCi8vIHh4eCBOYW1lIFtMSUIgIm5hbWUiW0FMSUFTICJuYW1lIl1dWyhQYXJhbWV0ZXIpXVtBUyBUWVBFXQoKU2JpUHJvY0RlZiogU2JpUGFyc2VyOjpQcm9jRGVjbCggc2FsX0Jvb2wgYkRlY2wgKQp7CglzYWxfQm9vbCBiRnVuYyA9IHNhbF9Cb29sKCBlQ3VyVG9rID09IEZVTkNUSU9OICk7CglzYWxfQm9vbCBiUHJvcCA9IHNhbF9Cb29sKCBlQ3VyVG9rID09IEdFVCB8fCBlQ3VyVG9rID09IFNFVCB8fCBlQ3VyVG9rID09IExFVCApOwoJaWYoICFUZXN0U3ltYm9sKCkgKSByZXR1cm4gTlVMTDsKCVN0cmluZyBhTmFtZSggYVN5bSApOwoJU2J4RGF0YVR5cGUgZVR5cGUgPSBlU2NhblR5cGU7CglTYmlQcm9jRGVmKiBwRGVmID0gbmV3IFNiaVByb2NEZWYoIHRoaXMsIGFOYW1lLCB0cnVlICk7CglwRGVmLT5TZXRUeXBlKCBlVHlwZSApOwoJaWYoIFBlZWsoKSA9PSBfQ0RFQ0xfICkKCXsKCQlOZXh0KCk7IHBEZWYtPlNldENkZWNsKCk7Cgl9CglpZiggUGVlaygpID09IExJQiApCgl7CgkJTmV4dCgpOwoJCWlmKCBOZXh0KCkgPT0gRklYU1RSSU5HICkKCQkJcERlZi0+R2V0TGliKCkgPSBhU3ltOwoJCWVsc2UKCQkJRXJyb3IoIFNiRVJSX1NZTlRBWCApOwoJfQoJaWYoIFBlZWsoKSA9PSBBTElBUyApCgl7CgkJTmV4dCgpOwoJCWlmKCBOZXh0KCkgPT0gRklYU1RSSU5HICkKCQkJcERlZi0+R2V0QWxpYXMoKSA9IGFTeW07CgkJZWxzZQoJCQlFcnJvciggU2JFUlJfU1lOVEFYICk7Cgl9CglpZiggIWJEZWNsICkKCXsKCQkvLyBDREVDTCwgTElCIHVuZCBBTElBUyBzaW5kIHVuenVsYWVzc2lnCgkJaWYoIHBEZWYtPkdldExpYigpLkxlbigpICkKCQkJRXJyb3IoIFNiRVJSX1VORVhQRUNURUQsIExJQiApOwoJCWlmKCBwRGVmLT5HZXRBbGlhcygpLkxlbigpICkKCQkJRXJyb3IoIFNiRVJSX1VORVhQRUNURUQsIEFMSUFTICk7CgkJaWYoIHBEZWYtPklzQ2RlY2woKSApCgkJCUVycm9yKCBTYkVSUl9VTkVYUEVDVEVELCBfQ0RFQ0xfICk7CgkJcERlZi0+U2V0Q2RlY2woIHNhbF9GYWxzZSApOwoJCXBEZWYtPkdldExpYigpLkVyYXNlKCk7CgkJcERlZi0+R2V0QWxpYXMoKS5FcmFzZSgpOwoJfQoJZWxzZSBpZiggIXBEZWYtPkdldExpYigpLkxlbigpICkKCXsKCQkvLyBBTElBUyB1bmQgQ0RFQ0wgbnVyIHp1c2FtbWVuIG1pdCBMSUIKCQlpZiggcERlZi0+R2V0QWxpYXMoKS5MZW4oKSApCgkJCUVycm9yKCBTYkVSUl9VTkVYUEVDVEVELCBBTElBUyApOwoJCWlmKCBwRGVmLT5Jc0NkZWNsKCkgKQoJCQlFcnJvciggU2JFUlJfVU5FWFBFQ1RFRCwgX0NERUNMXyApOwoJCXBEZWYtPlNldENkZWNsKCBzYWxfRmFsc2UgKTsKCQlwRGVmLT5HZXRBbGlhcygpLkVyYXNlKCk7Cgl9CgkvLyBLbGFtbWVybj8KCWlmKCBQZWVrKCkgPT0gTFBBUkVOICkKCXsKCQlOZXh0KCk7CgkJaWYoIFBlZWsoKSA9PSBSUEFSRU4gKQoJCQlOZXh0KCk7CgkJZWxzZQoJCSAgZm9yKDs7KSB7CgkJCXNhbF9Cb29sIGJCeVZhbCA9IHNhbF9GYWxzZTsKCQkJc2FsX0Jvb2wgYk9wdGlvbmFsID0gc2FsX0ZhbHNlOwoJCQlzYWxfQm9vbCBiUGFyYW1BcnJheSA9IHNhbF9GYWxzZTsKCQkJd2hpbGUoIFBlZWsoKSA9PSBCWVZBTCB8fCBQZWVrKCkgPT0gQllSRUYgfHwgUGVlaygpID09IF9PUFRJT05BTF8gKQoJCQl7CgkJCQlpZgkJKCBQZWVrKCkgPT0gQllWQUwgKQkJTmV4dCgpLCBiQnlWYWwgPSBzYWxfVHJ1ZTsKCQkJCWVsc2UgaWYJKCBQZWVrKCkgPT0gQllSRUYgKQkJTmV4dCgpLCBiQnlWYWwgPSBzYWxfRmFsc2U7CgkJCQllbHNlIGlmCSggUGVlaygpID09IF9PUFRJT05BTF8gKQlOZXh0KCksIGJPcHRpb25hbCA9IHNhbF9UcnVlOwoJCQl9CgkJCWlmKCBiQ29tcGF0aWJsZSAmJiBQZWVrKCkgPT0gUEFSQU1BUlJBWSApCgkJCXsKCQkJCWlmKCBiQnlWYWwgfHwgYk9wdGlvbmFsICkKCQkJCQlFcnJvciggU2JFUlJfVU5FWFBFQ1RFRCwgUEFSQU1BUlJBWSApOwoJCQkJTmV4dCgpOwoJCQkJYlBhcmFtQXJyYXkgPSBzYWxfVHJ1ZTsKCQkJfQoJCQlTYmlTeW1EZWYqIHBQYXIgPSBWYXJEZWNsKCBOVUxMLCBzYWxfRmFsc2UsIHNhbF9GYWxzZSApOwoJCQlpZiggIXBQYXIgKQoJCQkJYnJlYWs7CgkJCWlmKCBiQnlWYWwgKQoJCQkJcFBhci0+U2V0QnlWYWwoKTsKCQkJaWYoIGJPcHRpb25hbCApCgkJCQlwUGFyLT5TZXRPcHRpb25hbCgpOwoJCQlpZiggYlBhcmFtQXJyYXkgKQoJCQkJcFBhci0+U2V0UGFyYW1BcnJheSgpOwoJCQlwRGVmLT5HZXRQYXJhbXMoKS5BZGQoIHBQYXIgKTsKCQkJU2JpVG9rZW4gZVRvayA9IE5leHQoKTsKCQkJaWYoIGVUb2sgIT0gQ09NTUEgJiYgZVRvayAhPSBSUEFSRU4gKQoJCQl7CgkJCQlzYWxfQm9vbCBiRXJyb3IyID0gc2FsX1RydWU7CgkJCQlpZiggYk9wdGlvbmFsICYmIGJDb21wYXRpYmxlICYmIGVUb2sgPT0gRVEgKQoJCQkJewoJCQkJCVNiaUNvbnN0RXhwcmVzc2lvbiogcERlZmF1bHRFeHByID0gbmV3IFNiaUNvbnN0RXhwcmVzc2lvbiggdGhpcyApOwoJCQkJCVNieERhdGFUeXBlIGVUeXBlMiA9IHBEZWZhdWx0RXhwci0+R2V0VHlwZSgpOwoKCQkJCQlzYWxfdUludDE2IG5TdHJpbmdJZDsKCQkJCQlpZiggZVR5cGUyID09IFNieFNUUklORyApCgkJCQkJCW5TdHJpbmdJZCA9IGFHYmxTdHJpbmdzLkFkZCggcERlZmF1bHRFeHByLT5HZXRTdHJpbmcoKSApOwoJCQkJCWVsc2UKCQkJCQkJblN0cmluZ0lkID0gYUdibFN0cmluZ3MuQWRkKCBwRGVmYXVsdEV4cHItPkdldFZhbHVlKCksIGVUeXBlMiApOwoKCQkJCQlwUGFyLT5TZXREZWZhdWx0SWQoIG5TdHJpbmdJZCApOwoJCQkJCWRlbGV0ZSBwRGVmYXVsdEV4cHI7CgoJCQkJCWVUb2sgPSBOZXh0KCk7CgkJCQkJaWYoIGVUb2sgPT0gQ09NTUEgfHwgZVRvayA9PSBSUEFSRU4gKQoJCQkJCQliRXJyb3IyID0gc2FsX0ZhbHNlOwoJCQkJfQoJCQkJaWYoIGJFcnJvcjIgKQoJCQkJewoJCQkJCUVycm9yKCBTYkVSUl9FWFBFQ1RFRCwgUlBBUkVOICk7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCX0KCQkJaWYoIGVUb2sgPT0gUlBBUkVOICkKCQkJCWJyZWFrOwoJCX0KCX0KCVR5cGVEZWNsKCAqcERlZiApOwoJaWYoIGVUeXBlICE9IFNieFZBUklBTlQgJiYgcERlZi0+R2V0VHlwZSgpICE9IGVUeXBlICkKCQlFcnJvciggU2JFUlJfQkFEX0RFQ0xBUkFUSU9OLCBhTmFtZSApOwovLwlpZiggcERlZi0+R2V0VHlwZSgpID09IFNieE9CSkVDVCApCi8vCQlwRGVmLT5TZXRUeXBlKCBTYnhWQVJJQU5UICksCi8vCQlFcnJvciggU2JFUlJfU1lOVEFYICk7CglpZiggcERlZi0+R2V0VHlwZSgpID09IFNieFZBUklBTlQgJiYgISggYkZ1bmMgfHwgYlByb3AgKSApCgkJcERlZi0+U2V0VHlwZSggU2J4RU1QVFkgKTsKCXJldHVybiBwRGVmOwp9CgovLyBERUNMQVJFCgp2b2lkIFNiaVBhcnNlcjo6RGVjbGFyZSgpCnsKCURlZkRlY2xhcmUoIHNhbF9GYWxzZSApOwp9Cgp2b2lkIFNiaVBhcnNlcjo6RGVmRGVjbGFyZSggc2FsX0Jvb2wgYlByaXZhdGUgKQp7CglOZXh0KCk7CglpZiggZUN1clRvayAhPSBTVUIgJiYgZUN1clRvayAhPSBGVU5DVElPTiApCgkgIEVycm9yKCBTYkVSUl9VTkVYUEVDVEVELCBlQ3VyVG9rICk7CgllbHNlCgl7CgkJYm9vbCBiRnVuY3Rpb24gPSAoZUN1clRvayA9PSBGVU5DVElPTik7CgoJCVNiaVByb2NEZWYqIHBEZWYgPSBQcm9jRGVjbCggc2FsX1RydWUgKTsKCQlpZiggcERlZiApCgkJewoJCQlpZiggIXBEZWYtPkdldExpYigpLkxlbigpICkKCQkJCUVycm9yKCBTYkVSUl9FWFBFQ1RFRCwgTElCICk7CgkJCS8vIGdpYnRzIGRlbiBzY2hvbj8KCQkJU2JpU3ltRGVmKiBwT2xkID0gYVB1YmxpY3MuRmluZCggcERlZi0+R2V0TmFtZSgpICk7CgkJCWlmKCBwT2xkICkKCQkJewoJCQkJU2JpUHJvY0RlZiogcCA9IHBPbGQtPkdldFByb2NEZWYoKTsKCQkJCWlmKCAhcCApCgkJCQl7CgkJCQkJLy8gQWxzIFZhcmlhYmxlIGRla2xhcmllcnQKCQkJCQlFcnJvciggU2JFUlJfQkFEX0RFQ0xBUkFUSU9OLCBwRGVmLT5HZXROYW1lKCkgKTsKCQkJCQlkZWxldGUgcERlZjsKCQkJCQlwRGVmID0gTlVMTDsKCQkJCX0KCQkJCWVsc2UKCQkJCQlwRGVmLT5NYXRjaCggcCApOwoJCQl9CgkJCWVsc2UKCQkJCWFQdWJsaWNzLkFkZCggcERlZiApOwoKCQkJaWYgKCBwRGVmICkKCQkJewoJCQkJcERlZi0+U2V0UHVibGljKCAhYlByaXZhdGUgKTsKCgkJCQkvLyBOZXcgZGVjbGFyZSBoYW5kbGluZwoJCQkJaWYoIHBEZWYtPkdldExpYigpLkxlbigpID4gMCApCgkJCQl7CgkJCQkJaWYoIGJOZXdHYmxEZWZzICYmIG5HYmxDaGFpbiA9PSAwICkKCQkJCQl7CgkJCQkJCW5HYmxDaGFpbiA9IGFHZW4uR2VuKCBfSlVNUCwgMCApOwoJCQkJCQliTmV3R2JsRGVmcyA9IHNhbF9GYWxzZTsKCQkJCQl9CgoJCQkJCXNhbF91SW50MTYgblNhdkxpbmUgPSBuTGluZTsKCQkJCQlhR2VuLlN0YXRlbWVudCgpOwoJCQkJCXBEZWYtPkRlZmluZSgpOwoJCQkJCXBEZWYtPlNldExpbmUxKCBuU2F2TGluZSApOwoJCQkJCXBEZWYtPlNldExpbmUyKCBuU2F2TGluZSApOwoKCQkJCQlTYmlTeW1Qb29sJiByUG9vbCA9IHBEZWYtPkdldFBhcmFtcygpOwoJCQkJCXNhbF91SW50MTYgblBhckNvdW50ID0gclBvb2wuR2V0U2l6ZSgpOwoKCQkJCQlTYnhEYXRhVHlwZSBlVHlwZSA9IHBEZWYtPkdldFR5cGUoKTsKCQkJCQlpZiggYkZ1bmN0aW9uICkKCQkJCQkJYUdlbi5HZW4oIF9QQVJBTSwgMCwgc2FsOjpzdGF0aWNfaW50X2Nhc3Q8IHNhbF91SW50MTYgPiggZVR5cGUgKSApOwoKCQkJCQlpZiggblBhckNvdW50ID4gMSApCgkJCQkJewoJCQkJCQlhR2VuLkdlbiggX0FSR0MgKTsKCgkJCQkJCWZvciggc2FsX3VJbnQxNiBpID0gMSA7IGkgPCBuUGFyQ291bnQgOyArK2kgKQoJCQkJCQl7CgkJCQkJCQlTYmlTeW1EZWYqIHBQYXJEZWYgPSByUG9vbC5HZXQoIGkgKTsKCQkJCQkJCVNieERhdGFUeXBlIGVQYXJUeXBlID0gcFBhckRlZi0+R2V0VHlwZSgpOwoKCQkJCQkJCWFHZW4uR2VuKCBfUEFSQU0sIGksIHNhbDo6c3RhdGljX2ludF9jYXN0PCBzYWxfdUludDE2ID4oIGVQYXJUeXBlICkgKTsKCQkJCQkJCWFHZW4uR2VuKCBfQVJHViApOwoKCQkJCQkJCXNhbF91SW50MTYgblR5cCA9IHNhbDo6c3RhdGljX2ludF9jYXN0PCBzYWxfdUludDE2ID4oIHBQYXJEZWYtPkdldFR5cGUoKSApOwoJCQkJCQkJaWYoIHBQYXJEZWYtPklzQnlWYWwoKSApCgkJCQkJCQl7CgkJCQkJCQkJLy8gUmVzZXQgdG8gYXZvaWQgYWRkaXRpb25hbCBieXZhbCBpbiBjYWxsIHRvIHdyYXBwZXIgZnVuY3Rpb24KCQkJCQkJCQlwUGFyRGVmLT5TZXRCeVZhbCggc2FsX0ZhbHNlICk7CgkJCQkJCQkJblR5cCB8PSAweDgwMDA7CgkJCQkJCQl9CgkJCQkJCQlhR2VuLkdlbiggX0FSR1RZUCwgblR5cCApOwoJCQkJCQl9CgkJCQkJfQoKCQkJCQlhR2VuLkdlbiggX0xJQiwgYUdibFN0cmluZ3MuQWRkKCBwRGVmLT5HZXRMaWIoKSApICk7CgoJCQkJCVNiaU9wY29kZSBlT3AgPSBwRGVmLT5Jc0NkZWNsKCkgPyBfQ0FMTEMgOiBfQ0FMTDsKCQkJCQlzYWxfdUludDE2IG5JZCA9IHBEZWYtPkdldElkKCk7CgkJCQkJaWYoIHBEZWYtPkdldEFsaWFzKCkuTGVuKCkgKQoJCQkJCQluSWQgPSAoIG5JZCAmIDB4ODAwMCApIHwgYUdibFN0cmluZ3MuQWRkKCBwRGVmLT5HZXRBbGlhcygpICk7CgkJCQkJaWYoIG5QYXJDb3VudCA+IDEgKQoJCQkJCQluSWQgfD0gMHg4MDAwOwoJCQkJCWFHZW4uR2VuKCBlT3AsIG5JZCwgc2FsOjpzdGF0aWNfaW50X2Nhc3Q8IHNhbF91SW50MTYgPiggZVR5cGUgKSApOwoKCQkJCQlpZiggYkZ1bmN0aW9uICkKCQkJCQkJYUdlbi5HZW4oIF9QVVQgKTsKCgkJCQkJYUdlbi5HZW4oIF9MRUFWRSApOwoJCQkJfQoJCQl9CgkJfQoJfQp9CgovLyBBdWZydWYgZWluZXIgU1VCIG9kZXIgRlVOQ1RJT04KCnZvaWQgU2JpUGFyc2VyOjpDYWxsKCkKewoJU3RyaW5nIGFOYW1lKCBhU3ltICk7CglTYmlFeHByZXNzaW9uIGFWYXIoIHRoaXMsIFNiU1lNQk9MICk7CglhVmFyLkdlbiggRk9SQ0VfQ0FMTCApOwoJYUdlbi5HZW4oIF9HRVQgKTsKfQoKLy8gU1VCL0ZVTkNUSU9OCgp2b2lkIFNiaVBhcnNlcjo6U3ViRnVuYygpCnsKCURlZlByb2MoIHNhbF9GYWxzZSwgc2FsX0ZhbHNlICk7Cn0KCi8vIEVpbmxlc2VuIGVpbmVyIFByb3plZHVyCgpzYWxfQm9vbCBydW5zSW5TZXR1cCggdm9pZCApOwoKdm9pZCBTYmlQYXJzZXI6OkRlZlByb2MoIHNhbF9Cb29sIGJTdGF0aWMsIHNhbF9Cb29sIGJQcml2YXRlICkKewoJc2FsX3VJbnQxNiBsMSA9IG5MaW5lLCBsMiA9IG5MaW5lOwoJc2FsX0Jvb2wgYlN1YiA9IHNhbF9Cb29sKCBlQ3VyVG9rID09IFNVQiApOwoJc2FsX0Jvb2wgYlByb3BlcnR5ID0gc2FsX0Jvb2woIGVDdXJUb2sgPT0gUFJPUEVSVFkgKTsKCVByb3BlcnR5TW9kZSBlUHJvcGVydHlNb2RlID0gUFJPUEVSVFlfTU9ERV9OT05FOwoJaWYoIGJQcm9wZXJ0eSApCgl7CgkJTmV4dCgpOwoJCWlmKCBlQ3VyVG9rID09IEdFVCApCgkJCWVQcm9wZXJ0eU1vZGUgPSBQUk9QRVJUWV9NT0RFX0dFVDsKCQllbHNlIGlmKCBlQ3VyVG9rID09IExFVCApCgkJCWVQcm9wZXJ0eU1vZGUgPSBQUk9QRVJUWV9NT0RFX0xFVDsKCQllbHNlIGlmKCBlQ3VyVG9rID09IFNFVCApCgkJCWVQcm9wZXJ0eU1vZGUgPSBQUk9QRVJUWV9NT0RFX1NFVDsKCQllbHNlCgkJCUVycm9yKCBTYkVSUl9FWFBFQ1RFRCwgIkdldCBvciBMZXQgb3IgU2V0IiApOwoJfQoKCVNiaVRva2VuIGVFeGl0ID0gZUN1clRvazsKCVNiaVByb2NEZWYqIHBEZWYgPSBQcm9jRGVjbCggc2FsX0ZhbHNlICk7CglpZiggIXBEZWYgKQoJCXJldHVybjsKCXBEZWYtPnNldFByb3BlcnR5TW9kZSggZVByb3BlcnR5TW9kZSApOwoKCS8vIElzdCBkaWUgUHJvYyBiZXJlaXRzIGRla2xhcmllcnQ/CglTYmlTeW1EZWYqIHBPbGQgPSBhUHVibGljcy5GaW5kKCBwRGVmLT5HZXROYW1lKCkgKTsKCWlmKCBwT2xkICkKCXsKCQlib29sIGJFcnJvcl8gPSBmYWxzZTsKCgkJcFByb2MgPSBwT2xkLT5HZXRQcm9jRGVmKCk7CgkJaWYoICFwUHJvYyApCgkJewoJCQkvLyBBbHMgVmFyaWFibGUgZGVrbGFyaWVydAoJCQlFcnJvciggU2JFUlJfQkFEX0RFQ0xBUkFUSU9OLCBwRGVmLT5HZXROYW1lKCkgKTsKCQkJZGVsZXRlIHBEZWY7CgkJCXBQcm9jID0gTlVMTDsKCQkJYkVycm9yXyA9IHRydWU7CgkJfQoJCS8vICMxMDAwMjc6IE11bHRpcGxlIGRlY2xhcmF0aW9uIC0+IEVycm9yCgkJLy8gIzExMjc4NzogTm90IGZvciBzZXR1cCwgUkVNT1ZFIGZvciA4CgkJZWxzZSBpZiggIXJ1bnNJblNldHVwKCkgJiYgcFByb2MtPklzVXNlZEZvclByb2NEZWNsKCkgKQoJCXsKCQkJUHJvcGVydHlNb2RlIGVQcm9wTW9kZSA9IHBEZWYtPmdldFByb3BlcnR5TW9kZSgpOwoJCQlpZiggZVByb3BNb2RlID09IFBST1BFUlRZX01PREVfTk9ORSB8fCBlUHJvcE1vZGUgPT0gcFByb2MtPmdldFByb3BlcnR5TW9kZSgpICkKCQkJewoJCQkJRXJyb3IoIFNiRVJSX1BST0NfREVGSU5FRCwgcERlZi0+R2V0TmFtZSgpICk7CgkJCQlkZWxldGUgcERlZjsKCQkJCXBQcm9jID0gTlVMTDsKCQkJCWJFcnJvcl8gPSB0cnVlOwoJCQl9CgkJfQoKCQlpZiggIWJFcnJvcl8gKQoJCXsKCQkJcERlZi0+TWF0Y2goIHBQcm9jICk7CgkJCXBQcm9jID0gcERlZjsKCQl9Cgl9CgllbHNlCgkJYVB1YmxpY3MuQWRkKCBwRGVmICksIHBQcm9jID0gcERlZjsKCglpZiggIXBQcm9jICkKCQlyZXR1cm47CglwUHJvYy0+U2V0UHVibGljKCAhYlByaXZhdGUgKTsKCgkvLyBOdW4gc2V0emVuIHdpciBkaWUgU3VjaGhpZXJhcmNoaWUgZnVlciBTeW1ib2xlIHNvd2llIGRpZSBha3R1ZWxsZQoJLy8gUHJvemVkdXIuCglhUHVibGljcy5TZXRQcm9jSWQoIHBQcm9jLT5HZXRJZCgpICk7CglwUHJvYy0+R2V0UGFyYW1zKCkuU2V0UGFyZW50KCAmYVB1YmxpY3MgKTsKCWlmKCBiU3RhdGljICkKICAgICAgICB7CgkJaWYgKCBiVkJBU3VwcG9ydE9uICkKCQkJcFByb2MtPlNldFN0YXRpYyggc2FsX1RydWUgKTsKCQllbHNlCgkJCUVycm9yKCBTYkVSUl9OT1RfSU1QTEVNRU5URUQgKTsgLy8gU1RBVElDIFNVQiAuLi4KICAgICAgICB9CiAJZWxzZQoJewoJCXBQcm9jLT5TZXRTdGF0aWMoIHNhbF9GYWxzZSApOwogICAgICAgIH0KCS8vIE5vcm1hbGZhbGw6IExva2FsZSBWYXJpYWJsZS0+UGFyYW1ldGVyLT5HbG9iYWxlIFZhcmlhYmxlCglwUHJvYy0+R2V0TG9jYWxzKCkuU2V0UGFyZW50KCAmcFByb2MtPkdldFBhcmFtcygpICk7CglwUG9vbCA9ICZwUHJvYy0+R2V0TG9jYWxzKCk7CgoJcFByb2MtPkRlZmluZSgpOwoJT3BlbkJsb2NrKCBlRXhpdCApOwoJU3RtbnRCbG9jayggYlN1YiA/IEVORFNVQiA6IChiUHJvcGVydHkgPyBFTkRQUk9QRVJUWSA6IEVOREZVTkMpICk7CglsMiA9IG5MaW5lOwoJcFByb2MtPlNldExpbmUxKCBsMSApOwoJcFByb2MtPlNldExpbmUyKCBsMiApOwoJcFBvb2wgPSAmYVB1YmxpY3M7CglhUHVibGljcy5TZXRQcm9jSWQoIDAgKTsKCS8vIE9mZmVuZSBMYWJlbHM/CglwUHJvYy0+R2V0TGFiZWxzKCkuQ2hlY2tSZWZzKCk7CglDbG9zZUJsb2NrKCk7CglhR2VuLkdlbiggX0xFQVZFICk7CglwUHJvYyA9IE5VTEw7Cn0KCi8vIFNUQVRJQyB2YXJpYWJsZXxwcm9jZWR1cmUKCnZvaWQgU2JpUGFyc2VyOjpTdGF0aWMoKQp7CglEZWZTdGF0aWMoIHNhbF9GYWxzZSApOwp9Cgp2b2lkIFNiaVBhcnNlcjo6RGVmU3RhdGljKCBzYWxfQm9vbCBiUHJpdmF0ZSApCnsKCXN3aXRjaCggUGVlaygpICkKCXsKCQljYXNlIFNVQjoKCQljYXNlIEZVTkNUSU9OOgoJCWNhc2UgUFJPUEVSVFk6CgkJCS8vIEVuZCBnbG9iYWwgY2hhaW4gaWYgbmVjZXNzYXJ5IChub3QgZG9uZSBpbiAKCQkJLy8gU2JpUGFyc2VyOjpQYXJzZSgpIHVuZGVyIHRoZXNlIGNvbmRpdGlvbnMKCQkJaWYoIGJOZXdHYmxEZWZzICYmIG5HYmxDaGFpbiA9PSAwICkKCQkJewoJCQkJbkdibENoYWluID0gYUdlbi5HZW4oIF9KVU1QLCAwICk7CgkJCQliTmV3R2JsRGVmcyA9IHNhbF9GYWxzZTsKCQkJfQoJCQlOZXh0KCk7CgkJCURlZlByb2MoIHNhbF9UcnVlLCBiUHJpdmF0ZSApOwoJCQlicmVhazsKCQlkZWZhdWx0OiB7CgkJCWlmKCAhcFByb2MgKQoJCQkJRXJyb3IoIFNiRVJSX05PVF9JTl9TVUJSICk7CgkJCS8vIFBvb2wgdW1zZXR6ZW4sIGRhbWl0IFNUQVRJQy1EZWtsYXJhdGlvbmVuIGltIGdsb2JhbGVuCgkJCS8vIFBvb2wgbGFuZGVuCgkJCVNiaVN5bVBvb2wqIHAgPSBwUG9vbDsgcFBvb2wgPSAmYVB1YmxpY3M7CgkJCURlZlZhciggX1NUQVRJQywgc2FsX1RydWUgKTsKCQkJcFBvb2wgPSBwOwoJCQl9IGJyZWFrOwoJfQp9Cgo=