LyoKICogQ29weXJpZ2h0IChjKSAxOTk3LCAyMDA3LCBPcmFjbGUgYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLgogKiBETyBOT1QgQUxURVIgT1IgUkVNT1ZFIENPUFlSSUdIVCBOT1RJQ0VTIE9SIFRISVMgRklMRSBIRUFERVIuCiAqCiAqIFRoaXMgY29kZSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CiAqIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIG9ubHksIGFzCiAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgogKgogKiBUaGlzIGNvZGUgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQKICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yCiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiB2ZXJzaW9uIDIgZm9yIG1vcmUgZGV0YWlscyAoYSBjb3B5IGlzIGluY2x1ZGVkIGluIHRoZSBMSUNFTlNFIGZpbGUgdGhhdAogKiBhY2NvbXBhbmllZCB0aGlzIGNvZGUpLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uCiAqIDIgYWxvbmcgd2l0aCB0aGlzIHdvcms7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwKICogSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEgVVNBLgogKgogKiBQbGVhc2UgY29udGFjdCBPcmFjbGUsIDUwMCBPcmFjbGUgUGFya3dheSwgUmVkd29vZCBTaG9yZXMsIENBIDk0MDY1IFVTQQogKiBvciB2aXNpdCB3d3cub3JhY2xlLmNvbSBpZiB5b3UgbmVlZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9yIGhhdmUgYW55CiAqIHF1ZXN0aW9ucy4KICovCgovKgogKiBAdGVzdAogKiBAYnVnIDAwMDAwMDAKICogQGlnbm9yZSBydW4gbWFpbi90aW1lb3V0PTkwMCBQZXJmb3JtYW5jZVRlc3QKICogQHN1bW1hcnkgUGVyZm9ybWFuY2VUZXN0CiAqIEBhdXRob3IgSmFuIEx1ZWhlCiAqCiAqIGlnbm9yZSBzaW5jZSB0aGlzIHRlc3QgZXhpc3RzIGZvciBwZXJmb3JtYW5jZQogKiBwdXJwb3NlIGFuZCBjYW4gYmUgcnVuIHNlcGFyYXRlbHkgaWYgbmVlZGVkLgogKi8KaW1wb3J0IGphdmEuc2VjdXJpdHkuKjsKaW1wb3J0IGphdmEuc2VjdXJpdHkuc3BlYy4qOwppbXBvcnQgamF2YS5pby4qOwppbXBvcnQgamF2YXguY3J5cHRvLio7CmltcG9ydCBqYXZheC5jcnlwdG8uc3BlYy4qOwppbXBvcnQgY29tLnN1bi5jcnlwdG8ucHJvdmlkZXIuKjsKCnB1YmxpYyBjbGFzcyBQZXJmb3JtYW5jZVRlc3QgewoKICAgIENpcGhlciBjaXBoZXI7CiAgICBJdlBhcmFtZXRlclNwZWMgcGFyYW1zID0gbnVsbDsKICAgIFNlY3JldEtleSBjaXBoZXJLZXkgPSBudWxsOwogICAgU3RyaW5nQnVmZmVyIGNvbDsKCiAgICBwdWJsaWMgc3RhdGljIGJ5dGVbXSBrZXkgPSB7CiAgICAgICAgKGJ5dGUpMHgwMSwoYnl0ZSkweDIzLChieXRlKTB4NDUsKGJ5dGUpMHg2NywKICAgICAgICAoYnl0ZSkweDg5LChieXRlKTB4YWIsKGJ5dGUpMHhjZCwoYnl0ZSkweGVmCiAgICB9OwoKICAgIHB1YmxpYyBzdGF0aWMgYnl0ZVtdIGtleTMgPSB7CiAgICAgICAgKGJ5dGUpMHgwMSwoYnl0ZSkweDIzLChieXRlKTB4NDUsKGJ5dGUpMHg2NywKICAgICAgICAoYnl0ZSkweDg5LChieXRlKTB4YWIsKGJ5dGUpMHhjZCwoYnl0ZSkweGVmLAogICAgICAgIChieXRlKTB4ZjAsKGJ5dGUpMHhlMSwoYnl0ZSkweGQyLChieXRlKTB4YzMsCiAgICAgICAgKGJ5dGUpMHhiNCwoYnl0ZSkweGE1LChieXRlKTB4OTYsKGJ5dGUpMHg4NywKICAgICAgICAoYnl0ZSkweGZlLChieXRlKTB4ZGMsKGJ5dGUpMHhiYSwoYnl0ZSkweDk4LAogICAgICAgIChieXRlKTB4NzYsKGJ5dGUpMHg1NCwoYnl0ZSkweDMyLChieXRlKTB4MTB9OwoKICAgIHB1YmxpYyBzdGF0aWMgYnl0ZVtdIGl2ICA9IHsKICAgICAgICAoYnl0ZSkweGZlLChieXRlKTB4ZGMsKGJ5dGUpMHhiYSwoYnl0ZSkweDk4LAogICAgICAgIChieXRlKTB4NzYsKGJ5dGUpMHg1NCwoYnl0ZSkweDMyLChieXRlKTB4MTB9OwoKICAgIHB1YmxpYyBzdGF0aWMgYnl0ZVtdIHBsYWluX2RhdGEgPSAiSXNhaWFoLCBhIGxpdHRsZSBib3kgaXMgZGVhZC4gSGUgZmVsbCBmcm9tIHRoZSByb29mIG9mIGFuIGFwYXJ0bWVudCBob3VzZSwganVzdCBhIGZldyBkYXlzIGJlZm9yZSBDaHJpc3RtYXMuIFRoZSBvbmx5IHBlcnNvbiB3aG8gdHJ1bHkgZ3JpZXZlcyBmb3IgdGhlIGJveSBpcyBTbWlsbGEgSmFzcGVyc29uLCBhIHBvbGFyIHJlc2VhcmNoZXIuIFNtaWxsYSB3YXMgSXNhaWFoJ3Mgb25seSBmcmllbmQuIElzYWlhaCBjYW1lIHdpdGggaGlzIGFsY29ob2xpYyBtb3RoZXIgZnJvbSBHcmVlbmxhbmQgYnV0IG5ldmVyIHJlYWxseSBnb3QgdXNlZCB0byBsaWZlIGluIENvcGVuaGFnZW4uIFNtaWxsYSdzIG1vdGhlciB3YXMgYWxzbyBmcm9tIEdyZWVubGFuZC4gU21pbGxhIGZlZWxzIGEgcGFydGljdWxhciBhZmZpbml0eSB0byB0aGUgYXJjdGljIGxhbmRzY2FwZS4gU2hlIGtub3dzIGEgbG90IGFib3V0IHRoZSBzbm93IGFuZCBob3cgdG8gcmVhZCBpdHMgbW92ZW1lbnRzIGFuZCBpcyBjb252aW5jZWQgdGhhdCB0aGUgYm95J3MgZGVhdGggd2FzIG5vdCBhY2NpZGVudGFsLiIuZ2V0Qnl0ZXMoKTsKCiAgICAvLyBUaGUgY29kZW1ncnRvb2wgd29uJ3QgbGV0IG1lIGNoZWNraW4gdGhpcyBsaW5lLCBzbyBJIGhhZCB0byBicmVhayBpdCB1cC4KCiAgICAvKiBTbWlsbGEgZGVjaWRlcyB0byBlbWJhcmsgdXBvbiBoZXIgb3duIGludmVzdGlnYXRpb25zIGJ1dCBzb29uIGZpbmRzICBoZXJzZWxmIHJ1bm5pbmcgdXAgYWdhaW5zdCBhIGJyaWNrIHdhbGwuIElzYWlhaCdzIG1vdGhlciwgSnVsaWFuZSwgbWlzdHJ1c3RzIGhlciBhbmQgdGhlIGF1dGhvcml0aWVzIGFsc28gbWFrZSBsaWZlIGRpZmZpY3VsdCBmb3IgU21pbGxhLiBCdXQgc2hlIHdvbid0IGxldCBnby4gVGhlbiB0aGVyZSdzIHRoaXMgbWVjaGFuaWMgrSBhIHJldGljZW50LCBpbnNjcnV0YWJsZSBzb3J0IG9mIGd1eSCtIHdobyBsaXZlcyBpbiB0aGUgc2FtZSBhcGFydG1lbnQgYnVpbGRpbmcuIEhlIGFsc28ga25ldyB0aGUgYm95IGFuZCBldmVuIGNvbnN0cnVjdGVkIGEgd29ya2JlbmNoIGZvciBoaW0gaW4gaGlzIGNlbGxhciB3b3Jrc2hvcC4gVGhlIG1lY2hhbmljIHRlbGxzIFNtaWxsYSB0aGF0IGhlJ2QgbGlrZSB0byBoZWxwIGhlciwgYnV0IHRoZW4gYWdhaW4sIGhlIG1heSBqdXN0IGJlIG9uZSBvZiB0aG9zZSB3aG8gc2VlbSB0byB3YW50IHRvIGRvZyBoZXIgaGVlbHMuIEVuZCAiLmdldEJ5dGVzKCk7Ki8KCiAgICBzdGF0aWMgaW50W10gZGF0YVNpemVzID0gezEwMjQsIDgxOTJ9OwogICAgc3RhdGljIFN0cmluZ1tdIGNyeXB0cyA9IHsiREVTIiwgIkRFU2VkZSJ9OwogICAgc3RhdGljIFN0cmluZ1tdIG1vZGVzID0geyJFQ0IiLCAiQ0JDIiwgIkNGQjY0IiwgIk9GQjY0IiwgIlBDQkMifTsKICAgIHN0YXRpYyBTdHJpbmdbXSBwYWRkaW5ncyA9IHsiUEtDUzVQYWRkaW5nIiwgIk5vUGFkZGluZyJ9OwogICAgc3RhdGljIGludFtdIHJvdW5kcyA9IHsxMDAsIDEwMDB9OwogICAgaW50IHN1bSA9MDsKCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBQZXJmb3JtYW5jZVRlc3QgdGVzdCA9IG5ldyBQZXJmb3JtYW5jZVRlc3QoKTsKICAgICAgICB0ZXN0LnJ1bigpOwogICAgfQoKICAgIHB1YmxpYyB2b2lkIHJ1bigpIHRocm93cyBFeGNlcHRpb24gewoKICAgICAgICBieXRlW10gaW47CgogICAgICAgIFN1bkpDRSBqY2UgPSBuZXcgU3VuSkNFKCk7CiAgICAgICAgU2VjdXJpdHkuYWRkUHJvdmlkZXIoamNlKTsKICAgICAgICBjb2wgPSBuZXcgU3RyaW5nQnVmZmVyKCk7CgogICAgICAgIHByaW50SGVhZGluZ3MoKTsKCiAgICAgICAgZm9yIChpbnQgaT0wOyBpPGNyeXB0cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBmb3IgKGludCBqPTA7IGo8bW9kZXMubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgIGZvciAoaW50IGs9MDsgazxwYWRkaW5ncy5sZW5ndGg7IGsrKykgewoKICAgICAgICAgICAgICAgICAgICBjb2wuYXBwZW5kKGNyeXB0c1tpXSsiLyIrbW9kZXNbal0rIi8iK3BhZGRpbmdzW2tdKTsKICAgICAgICAgICAgICAgICAgICBpbnQgbGVuID0gMzIgLSBjb2wubGVuZ3RoKCk7CiAgICAgICAgICAgICAgICAgICAgZm9yKDsgbGVuPjA7IGxlbi0tKQogICAgICAgICAgICAgICAgICAgICAgICBjb2wuYXBwZW5kKCIgIik7IHsKCiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGw9MDsgbDxkYXRhU2l6ZXMubGVuZ3RoOyBsKyspIHsKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbiA9IG5ldyBieXRlW2RhdGFTaXplc1tsXV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgZyA9IE1hdGgubWluKGRhdGFTaXplc1tsXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhaW5fZGF0YS5sZW5ndGgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGxlbj0wOyBsZW4gPCBkYXRhU2l6ZXNbbF0gLSBnOyBsZW4gKz0gZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHBsYWluX2RhdGEsIDAsIGluLCBsZW4sIGcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoZGF0YVNpemVzW2xdIC0gbGVuKSA+IDApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShwbGFpbl9kYXRhLCAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW4sIGxlbiwgZGF0YVNpemVzW2xdLSBsZW4pOwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5hcHBlbmQoZGF0YVNpemVzW2xdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbiA9IDQwIC0gY29sLmxlbmd0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICg7IGxlbj4wOyBsZW4tLSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2wuYXBwZW5kKCIgIik7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpbnQgbT0wOyBtPHJvdW5kcy5sZW5ndGg7IG0rKykgewoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2wuYXBwZW5kKHJvdW5kc1ttXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuID0gNTAgLSBjb2wubGVuZ3RoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICg7IGxlbj4wOyBsZW4tLSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLmFwcGVuZCgiICIpOwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0KGNyeXB0c1tpXSwgbW9kZXNbal0sIHBhZGRpbmdzW2tdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5UZXN0KGluLCByb3VuZHNbbV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihjb2wudG9TdHJpbmcoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLnNldExlbmd0aCg0MCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2wuc2V0TGVuZ3RoKDMyKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb2wuc2V0TGVuZ3RoKDApOwogICAgICAgICAgICAgICAgICAgICAgICBjb2wuYXBwZW5kKCJBdmVyYWdlOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiArIChzdW0vKGRhdGFTaXplcy5sZW5ndGgqcm91bmRzLmxlbmd0aCkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VtID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKGNvbC50b1N0cmluZygpICsgIlxuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5zZXRMZW5ndGgoMCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyB2b2lkIGluaXQoU3RyaW5nIGNyeXB0LCBTdHJpbmcgbW9kZSwgU3RyaW5nIHBhZGRpbmcpCiAgICAgICAgdGhyb3dzIEV4Y2VwdGlvbiB7CgogICAgICAgIEtleVNwZWMgZGVzS2V5U3BlYyA9IG51bGw7CiAgICAgICAgU2VjcmV0S2V5RmFjdG9yeSBmYWN0b3J5ID0gbnVsbDsKCiAgICAgICAgU3RyaW5nQnVmZmVyIGNpcGhlck5hbWUgPSBuZXcgU3RyaW5nQnVmZmVyKGNyeXB0KTsKICAgICAgICBpZiAobW9kZS5sZW5ndGgoKSAhPSAwKQogICAgICAgICAgICBjaXBoZXJOYW1lLmFwcGVuZCgiLyIgKyBtb2RlKTsKICAgICAgICBpZiAocGFkZGluZy5sZW5ndGgoKSAhPSAwKQogICAgICAgICAgICBjaXBoZXJOYW1lLmFwcGVuZCgiLyIgKyBwYWRkaW5nKTsKCiAgICAgICAgY2lwaGVyID0gQ2lwaGVyLmdldEluc3RhbmNlKGNpcGhlck5hbWUudG9TdHJpbmcoKSk7CiAgICAgICAgaWYgKGNyeXB0LmVuZHNXaXRoKCJlZGUiKSkgewogICAgICAgICAgICBkZXNLZXlTcGVjID0gbmV3IERFU2VkZUtleVNwZWMoa2V5Myk7CiAgICAgICAgICAgIGZhY3RvcnkgPSBTZWNyZXRLZXlGYWN0b3J5LmdldEluc3RhbmNlKCJERVNlZGUiLCAiU3VuSkNFIik7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBkZXNLZXlTcGVjID0gbmV3IERFU0tleVNwZWMoa2V5KTsKICAgICAgICAgICAgZmFjdG9yeSA9IFNlY3JldEtleUZhY3RvcnkuZ2V0SW5zdGFuY2UoIkRFUyIsICJTdW5KQ0UiKTsKICAgICAgICB9CgogICAgICAgIC8vIHJldHJpZXZlIHRoZSBjaXBoZXIga2V5CiAgICAgICAgY2lwaGVyS2V5ID0gZmFjdG9yeS5nZW5lcmF0ZVNlY3JldChkZXNLZXlTcGVjKTsKCiAgICAgICAgLy8gcmV0cmlldmUgaXYKICAgICAgICBpZiAoICFtb2RlLmVxdWFscygiRUNCIikpCiAgICAgICAgICAgIHBhcmFtcyA9IG5ldyBJdlBhcmFtZXRlclNwZWMoaXYpOwogICAgICAgIGVsc2UKICAgICAgICAgICAgcGFyYW1zID0gbnVsbDsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCBydW5UZXN0KGJ5dGVbXSBkYXRhLCBpbnQgY291bnQpIHRocm93cyBFeGNlcHRpb24gewoKICAgICAgICBsb25nIHN0YXJ0LCBlbmQ7CiAgICAgICAgY2lwaGVyLmluaXQoQ2lwaGVyLkVOQ1JZUFRfTU9ERSwgY2lwaGVyS2V5LCBwYXJhbXMpOwoKICAgICAgICBzdGFydCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwogICAgICAgIGZvciAoaW50IGk9MDsgaTxjb3VudC0xOyBpKyspIHsKICAgICAgICAgICAgY2lwaGVyLnVwZGF0ZShkYXRhLCAwLCBkYXRhLmxlbmd0aCk7CiAgICAgICAgfQogICAgICAgIGNpcGhlci5kb0ZpbmFsKGRhdGEsIDAsIGRhdGEubGVuZ3RoKTsKICAgICAgICBlbmQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCiAgICAgICAgaW50IHNwZWVkID0gKGludCkoKGRhdGEubGVuZ3RoICogY291bnQpLyhlbmQgLSBzdGFydCkpOwogICAgICAgIHN1bSArPSBzcGVlZDsKICAgICAgICBjb2wuYXBwZW5kKHNwZWVkKTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCBwcmludEhlYWRpbmdzKCkgewogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbgogICAgICAgICAgICAoIlRoZSBmb2xsb3dpbmcgdGVzdHMgbnVtYmVycyBhcmUgZ2VuZXJhdGVkIHVzaW5nIik7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuCiAgICAgICAgICAgICgib3VyIEpDQSBjYWxsaW5nIHRocm91Z2ggQ2lwaGVyIHRvIGEgcGFydGljdWxhciBwcm92aWRlciIpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbgogICAgICAgICAgICAoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSIpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbgogICAgICAgICAgICAoIkFsZ29yaXRobSAgICAgICAgICAgICAgICAgICAgICBEYXRhU2l6ZSBSb3VuZHMgS2J5dGVzL3NlYyIpOwoKICAgIH0KCn0K