From 0643ae70f59b28cb0661454981c0620da2bb93a5 Mon Sep 17 00:00:00 2001 From: tickerguy Date: Wed, 19 Oct 2022 12:39:32 -0400 Subject: [PATCH 01/63] Update BridgeUnix.c On FreeBSD the stock code will attempt to expand the interface MTU any time a packet is to be sent that exceeds the current MTU. This results in a down/up on the interface that is wildly disruptive to existing services on that adapter and, eventually, is likely to run into MTU limits and start logging failures, even with jumbo-frame capable adapters. Thus if compiling on a FreeBSD machine disable this capability. Tested against 12.3-STABLE and 13.1-STABLE on v4.38-9760 from the FreeBSD ports tree but likely applies here as well; see bug report https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=267178 --- src/Cedar/BridgeUnix.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Cedar/BridgeUnix.c b/src/Cedar/BridgeUnix.c index d5890cba..ce2b1ffc 100644 --- a/src/Cedar/BridgeUnix.c +++ b/src/Cedar/BridgeUnix.c @@ -805,7 +805,12 @@ bool EthIsChangeMtuSupported(ETH *e) return false; } +// FreeBSD seriously dislikes MTU changes; disable if compiled on that platform +#ifndef __FreeBSD__ return true; +#else + return false; +#endif #else // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS) return false; #endif // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS) From 36505e3896d9ac1beef0e591017d742463a61ad6 Mon Sep 17 00:00:00 2001 From: Roel van de Wiel Date: Wed, 10 May 2023 15:09:57 +0200 Subject: [PATCH 02/63] Changed 'settng' to 'setting' and regenerated the RPC docs --- .../vpnserver-jsonrpc-clients/README.html | 198 ++++++++-------- .../vpnserver-jsonrpc-clients/README.md | 214 +++++++++--------- .../rpc-stubs/JsonRpc.cs | 4 +- .../rpc-stubs/VPNServerRpc.cs | 12 +- .../rpc-stubs/VPNServerRpcTypes.cs | 4 +- .../sample/Main.cs | 4 +- .../sample/VpnServerRpcTest.cs | 28 +-- .../dist/sample.js | 24 +- .../dist/vpnrpc.d.ts | 4 +- .../dist/vpnrpc.js | 8 +- .../src/sample.ts | 28 +-- .../src/vpnrpc.ts | 12 +- .../sample.ts | 28 +-- .../vpnrpc.ts | 12 +- .../VpnServerRpc/VPNServerRpc.cs | 8 +- .../VpnServerRpcTest/VpnServerRpcTest.cs | 24 +- src/Cedar/Admin.c | 8 +- src/bin/hamcore/vpnserver_api_doc.html | 196 ++++++++-------- .../admin/default/out_webpack/bundle.js | 2 +- 19 files changed, 409 insertions(+), 409 deletions(-) diff --git a/developer_tools/vpnserver-jsonrpc-clients/README.html b/developer_tools/vpnserver-jsonrpc-clients/README.html index 637f0c6b..2d41f959 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/README.html +++ b/developer_tools/vpnserver-jsonrpc-clients/README.html @@ -216,8 +216,8 @@ All APIs are based on the JSON-R
  • GetSpecialListener - Get Current Setting of the VPN over ICMP / VPN over DNS Function
  • GetAzureStatus - Show the current status of VPN Azure function
  • SetAzureStatus - Enable / Disable VPN Azure Function
  • -
  • GetDDnsInternetSettng - Get the Proxy Settings for Connecting to the DDNS server
  • -
  • SetDDnsInternetSettng - Set the Proxy Settings for Connecting to the DDNS server
  • +
  • GetDDnsInternetSetting - Get the Proxy Settings for Connecting to the DDNS server
  • +
  • SetDDnsInternetSetting - Set the Proxy Settings for Connecting to the DDNS server
  • SetVgsConfig - Set the VPN Gate Server Configuration
  • GetVgsConfig - Get the VPN Gate Server Configuration
  • @@ -305,7 +305,7 @@ All APIs are based on the JSON-R "ServerBuildInt_u32": 0, "ServerHostName_str": "serverhostname", "ServerType_u32": 0, - "ServerBuildDate_dt": "2020-08-01T12:24:36.123", + "ServerBuildDate_dt": "2024-08-01T12:24:36.123", "ServerFamilyName_str": "serverfamilyname", "OsType_u32": 0, "OsServicePack_u32": 0, @@ -460,9 +460,9 @@ All APIs are based on the JSON-R "Send.BroadcastCount_u64": 0, "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, - "CurrentTime_dt": "2020-08-01T12:24:36.123", + "CurrentTime_dt": "2024-08-01T12:24:36.123", "CurrentTick_u64": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", "TotalMemory_u64": 0, "UsedMemory_u64": 0, "FreeMemory_u64": 0, @@ -1136,7 +1136,7 @@ All APIs are based on the JSON-R "result": { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1283,7 +1283,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1296,7 +1296,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1309,7 +1309,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1422,9 +1422,9 @@ All APIs are based on the JSON-R "Port_u32": 0, "Online_bool": false, "LastError_u32": 0, - "StartedTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectedTime_dt": "2020-08-01T12:24:36.123", + "StartedTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectedTime_dt": "2024-08-01T12:24:36.123", "NumTry_u32": 0, "NumConnected_u32": 0, "NumFailed_u32": 0 @@ -1918,9 +1918,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1941,9 +1941,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1964,9 +1964,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -2309,7 +2309,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -2317,7 +2317,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -2325,7 +2325,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 } ] @@ -2450,7 +2450,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "ServerStr_str": "serverstr", "ServerVer_u32": 0, "ServerBuild_u32": 0, @@ -2620,9 +2620,9 @@ All APIs are based on the JSON-R "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, "SecureNATEnabled_bool": false, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0 } } @@ -2992,19 +2992,19 @@ All APIs are based on the JSON-R "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" } ] } @@ -4348,7 +4348,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -4357,7 +4357,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -4366,7 +4366,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" } @@ -4668,9 +4668,9 @@ All APIs are based on the JSON-R "ServerProductBuild_u32": 0, "ServerX_bin": "SGVsbG8gV29ybGQ=", "ClientX_bin": "SGVsbG8gV29ybGQ=", - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -5996,7 +5996,7 @@ All APIs are based on the JSON-R "Name_str": "name", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6057,9 +6057,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6247,7 +6247,7 @@ All APIs are based on the JSON-R Send.UnicastCount_u64 number (uint64) -Unicast count (Send) +Unicast bytes (Send) UsePolicy_bool @@ -6467,7 +6467,7 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6528,9 +6528,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6948,9 +6948,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -7419,11 +7419,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -7440,11 +7440,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -7461,11 +7461,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -8907,8 +8907,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -8929,8 +8929,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -8951,8 +8951,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -9117,9 +9117,9 @@ All APIs are based on the JSON-R "ServerProductName_str": "serverproductname", "ServerProductVer_u32": 0, "ServerProductBuild_u32": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -9496,8 +9496,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9506,8 +9506,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9516,8 +9516,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9663,8 +9663,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -9673,8 +9673,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -9683,8 +9683,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" } @@ -10376,8 +10376,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10391,8 +10391,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10406,8 +10406,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10527,8 +10527,8 @@ All APIs are based on the JSON-R "DhcpTable": [ { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -10536,8 +10536,8 @@ All APIs are based on the JSON-R }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -10545,8 +10545,8 @@ All APIs are based on the JSON-R }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -13090,19 +13090,19 @@ All APIs are based on the JSON-R "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -14508,15 +14508,15 @@ All APIs are based on the JSON-R
    -

    -

    "GetDDnsInternetSettng" RPC API - Get the Proxy Settings for Connecting to the DDNS server

    +

    +

    "GetDDnsInternetSetting" RPC API - Get the Proxy Settings for Connecting to the DDNS server

    Description

    Get the Proxy Settings for Connecting to the DDNS server.

    Input JSON-RPC Format

    {
       "jsonrpc": "2.0",
       "id": "rpc_call_id",
    -  "method": "GetDDnsInternetSettng",
    +  "method": "GetDDnsInternetSetting",
       "params": {}
     }
     
    @@ -14571,15 +14571,15 @@ All APIs are based on the JSON-R
    -

    -

    "SetDDnsInternetSettng" RPC API - Set the Proxy Settings for Connecting to the DDNS server

    +

    +

    "SetDDnsInternetSetting" RPC API - Set the Proxy Settings for Connecting to the DDNS server

    Description

    Set the Proxy Settings for Connecting to the DDNS server.

    Input JSON-RPC Format

    {
       "jsonrpc": "2.0",
       "id": "rpc_call_id",
    -  "method": "SetDDnsInternetSettng",
    +  "method": "SetDDnsInternetSetting",
       "params": {
         "ProxyType_u32": 0,
         "ProxyHostName_str": "proxyhostname",
    @@ -14640,8 +14640,8 @@ All APIs are based on the JSON-R
     
     
     
    -

    Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen.
    -Copyright (c) 2014-2019
    SoftEther VPN Project under the Apache License 2.0.

    +

    Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen.
    +Copyright (c) 2014-2023 SoftEther VPN Project under the Apache License 2.0.

    diff --git a/developer_tools/vpnserver-jsonrpc-clients/README.md b/developer_tools/vpnserver-jsonrpc-clients/README.md index 22866867..1ea33f9f 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/README.md +++ b/developer_tools/vpnserver-jsonrpc-clients/README.md @@ -208,8 +208,8 @@ Value | Description - [GetSpecialListener - Get Current Setting of the VPN over ICMP / VPN over DNS Function](#getspeciallistener) - [GetAzureStatus - Show the current status of VPN Azure function](#getazurestatus) - [SetAzureStatus - Enable / Disable VPN Azure Function](#setazurestatus) -- [GetDDnsInternetSettng - Get the Proxy Settings for Connecting to the DDNS server](#getddnsinternetsettng) -- [SetDDnsInternetSettng - Set the Proxy Settings for Connecting to the DDNS server](#setddnsinternetsettng) +- [GetDDnsInternetSetting - Get the Proxy Settings for Connecting to the DDNS server](#getddnsinternetsetting) +- [SetDDnsInternetSetting - Set the Proxy Settings for Connecting to the DDNS server](#setddnsinternetsetting) - [SetVgsConfig - Set the VPN Gate Server Configuration](#setvgsconfig) - [GetVgsConfig - Get the VPN Gate Server Configuration](#getvgsconfig) @@ -283,7 +283,7 @@ Get server information. This allows you to obtain the server information of the "ServerBuildInt_u32": 0, "ServerHostName_str": "serverhostname", "ServerType_u32": 0, - "ServerBuildDate_dt": "2020-08-01T12:24:36.123", + "ServerBuildDate_dt": "2024-08-01T12:24:36.123", "ServerFamilyName_str": "serverfamilyname", "OsType_u32": 0, "OsServicePack_u32": 0, @@ -368,9 +368,9 @@ Get Current Server Status. This allows you to obtain in real-time the current st "Send.BroadcastCount_u64": 0, "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, - "CurrentTime_dt": "2020-08-01T12:24:36.123", + "CurrentTime_dt": "2024-08-01T12:24:36.123", "CurrentTick_u64": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", "TotalMemory_u64": 0, "UsedMemory_u64": 0, "FreeMemory_u64": 0, @@ -768,7 +768,7 @@ Get Cluster Member Information. When the VPN Server is operating as a cluster co "result": { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -849,7 +849,7 @@ Get List of Cluster Members. Use this API when the VPN Server is operating as a { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -862,7 +862,7 @@ Get List of Cluster Members. Use this API when the VPN Server is operating as a { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -875,7 +875,7 @@ Get List of Cluster Members. Use this API when the VPN Server is operating as a { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -934,9 +934,9 @@ Get Connection Status to Cluster Controller. Use this API when the VPN Server is "Port_u32": 0, "Online_bool": false, "LastError_u32": 0, - "StartedTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectedTime_dt": "2020-08-01T12:24:36.123", + "StartedTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectedTime_dt": "2024-08-01T12:24:36.123", "NumTry_u32": 0, "NumConnected_u32": 0, "NumFailed_u32": 0 @@ -1278,9 +1278,9 @@ Get List of Virtual Hubs. Use this to get a list of existing Virtual Hubs on the "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1301,9 +1301,9 @@ Get List of Virtual Hubs. Use this to get a list of existing Virtual Hubs on the "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1324,9 +1324,9 @@ Get List of Virtual Hubs. Use this to get a list of existing Virtual Hubs on the "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1525,7 +1525,7 @@ Get List of TCP Connections Connecting to the VPN Server. Use this to get a list "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -1533,7 +1533,7 @@ Get List of TCP Connections Connecting to the VPN Server. Use this to get a list "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -1541,7 +1541,7 @@ Get List of TCP Connections Connecting to the VPN Server. Use this to get a list "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 } ] @@ -1626,7 +1626,7 @@ Get Information of TCP Connections Connecting to the VPN Server. Use this to get "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "ServerStr_str": "serverstr", "ServerVer_u32": 0, "ServerBuild_u32": 0, @@ -1736,9 +1736,9 @@ Get Current Status of Virtual Hub. Use this to get the current status of the Vir "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, "SecureNATEnabled_bool": false, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0 } } @@ -1948,19 +1948,19 @@ Get List of Trusted CA Certificates. Here you can manage the certificate authori "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" } ] } @@ -2210,7 +2210,7 @@ Name | Type | Description `NoUdpAcceleration_bool` | `boolean` | Client Option Parameters: Do not use UDP acceleration mode if the value is true `AuthType_u32` | `number` (enum) | Authentication type
    Values:
    `0`: Anonymous authentication
    `1`: SHA-0 hashed password authentication
    `2`: Plain password authentication
    `3`: Certificate authentication `Username_str` | `string` (ASCII) | User name -`HashedPassword_bin` | `string` (Base64 binary) | SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(password_ascii_string + UpperCase(username_ascii_string)). +`HashedPassword_bin` | `string` (Base64 binary) | SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(UpperCase(username_ascii_string) + password_ascii_string). `PlainPassword_str` | `string` (ASCII) | Plaintext Password. Valid only if ClientAuth_AuthType_u32 == PlainPassword (2). `ClientX_bin` | `string` (Base64 binary) | Client certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). `ClientK_bin` | `string` (Base64 binary) | Client private key of the certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). @@ -2537,7 +2537,7 @@ Name | Type | Description `NoUdpAcceleration_bool` | `boolean` | Client Option Parameters: Do not use UDP acceleration mode if the value is true `AuthType_u32` | `number` (enum) | Authentication type
    Values:
    `0`: Anonymous authentication
    `1`: SHA-0 hashed password authentication
    `2`: Plain password authentication
    `3`: Certificate authentication `Username_str` | `string` (ASCII) | User name -`HashedPassword_bin` | `string` (Base64 binary) | SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(password_ascii_string + UpperCase(username_ascii_string)). +`HashedPassword_bin` | `string` (Base64 binary) | SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(UpperCase(username_ascii_string) + password_ascii_string). `PlainPassword_str` | `string` (ASCII) | Plaintext Password. Valid only if ClientAuth_AuthType_u32 == PlainPassword (2). `ClientX_bin` | `string` (Base64 binary) | Client certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). `ClientK_bin` | `string` (Base64 binary) | Client private key of the certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). @@ -2600,7 +2600,7 @@ Get List of Cascade Connections. Use this to get a list of Cascade Connections t "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -2609,7 +2609,7 @@ Get List of Cascade Connections. Use this to get a list of Cascade Connections t "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -2618,7 +2618,7 @@ Get List of Cascade Connections. Use this to get a list of Cascade Connections t "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" } @@ -2834,9 +2834,9 @@ Get Current Cascade Connection Status. When a Cascade Connection registered on t "ServerProductBuild_u32": 0, "ServerX_bin": "SGVsbG8gV29ybGQ=", "ClientX_bin": "SGVsbG8gV29ybGQ=", - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -3566,7 +3566,7 @@ Create a user. Use this to create a new user in the security account database of "Name_str": "name", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -3629,9 +3629,9 @@ Create a user. Use this to create a new user in the security account database of "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -3779,7 +3779,7 @@ Change User Settings. Use this to change user settings that is registered on the "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -3842,9 +3842,9 @@ Change User Settings. Use this to change user settings that is registered on the "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -4004,9 +4004,9 @@ Get User Settings. Use this to get user settings information that is registered "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -4207,11 +4207,11 @@ Get List of Users. Use this to get a list of users that are registered on the se "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -4228,11 +4228,11 @@ Get List of Users. Use this to get a list of users that are registered on the se "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -4249,11 +4249,11 @@ Get List of Users. Use this to get a list of users that are registered on the se "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -4605,14 +4605,14 @@ Name | Type | Description `Name_str` | `string` (ASCII) | The group name `Realname_utf` | `string` (UTF8) | Optional real name (full name) of the group, allow using any Unicode characters `Note_utf` | `string` (UTF8) | Optional, specify a description of the group -`Recv.BroadcastBytes_u64` | `number` (uint64) | Broadcast bytes (Recv) -`Recv.BroadcastCount_u64` | `number` (uint64) | Number of broadcast packets (Recv) -`Recv.UnicastBytes_u64` | `number` (uint64) | Unicast bytes (Recv) -`Recv.UnicastCount_u64` | `number` (uint64) | Unicast count (Recv) -`Send.BroadcastBytes_u64` | `number` (uint64) | Broadcast bytes (Send) -`Send.BroadcastCount_u64` | `number` (uint64) | Number of broadcast packets (Send) +`Recv.BroadcastBytes_u64` | `number` (uint64) | Number of broadcast packets (Recv) +`Recv.BroadcastCount_u64` | `number` (uint64) | Broadcast bytes (Recv) +`Recv.UnicastBytes_u64` | `number` (uint64) | Unicast count (Recv) +`Recv.UnicastCount_u64` | `number` (uint64) | Unicast bytes (Recv) +`Send.BroadcastBytes_u64` | `number` (uint64) | Number of broadcast packets (Send) +`Send.BroadcastCount_u64` | `number` (uint64) | Broadcast bytes (Send) `Send.UnicastBytes_u64` | `number` (uint64) | Unicast bytes (Send) -`Send.UnicastCount_u64` | `number` (uint64) | Unicast count (Send) +`Send.UnicastCount_u64` | `number` (uint64) | Unicast bytes (Send) `UsePolicy_bool` | `boolean` | The flag whether to use security policy `policy:Access_bool` | `boolean` | Security policy: Allow Access. The users, which this policy value is true, have permission to make VPN connection to VPN Server. `policy:DHCPFilter_bool` | `boolean` | Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. @@ -4939,8 +4939,8 @@ Get List of Connected VPN Sessions. Use this to get a list of the sessions conne "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -4961,8 +4961,8 @@ Get List of Connected VPN Sessions. Use this to get a list of the sessions conne "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -4983,8 +4983,8 @@ Get List of Connected VPN Sessions. Use this to get a list of the sessions conne "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -5059,9 +5059,9 @@ Get Session Status. Use this to specify a session currently connected to the cur "ServerProductName_str": "serverproductname", "ServerProductVer_u32": 0, "ServerProductBuild_u32": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -5222,8 +5222,8 @@ Get the MAC Address Table Database. Use this to get the MAC address table databa "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -5232,8 +5232,8 @@ Get the MAC Address Table Database. Use this to get the MAC address table databa "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -5242,8 +5242,8 @@ Get the MAC Address Table Database. Use this to get the MAC address table databa "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -5337,8 +5337,8 @@ Get the IP Address Table Database. Use this to get the IP address table database "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -5347,8 +5347,8 @@ Get the IP Address Table Database. Use this to get the IP address table database "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -5357,8 +5357,8 @@ Get the IP Address Table Database. Use this to get the IP address table database "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" } @@ -5778,8 +5778,8 @@ Get Virtual NAT Function Session Table of SecureNAT Function. Use this to get th "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -5793,8 +5793,8 @@ Get Virtual NAT Function Session Table of SecureNAT Function. Use this to get th "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -5808,8 +5808,8 @@ Get Virtual NAT Function Session Table of SecureNAT Function. Use this to get th "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -5867,8 +5867,8 @@ Get Virtual DHCP Server Function Lease Table of SecureNAT Function. Use this to "DhcpTable": [ { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -5876,8 +5876,8 @@ Get Virtual DHCP Server Function Lease Table of SecureNAT Function. Use this to }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -5885,8 +5885,8 @@ Get Virtual DHCP Server Function Lease Table of SecureNAT Function. Use this to }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -7642,19 +7642,19 @@ Get List of Log Files. Use this to display a list of log files outputted by the "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -8642,8 +8642,8 @@ Name | Type | Description `IsConnected_bool` | `boolean` | Whether connection to VPN Azure Cloud Server is established *** - -## "GetDDnsInternetSettng" RPC API - Get the Proxy Settings for Connecting to the DDNS server + +## "GetDDnsInternetSetting" RPC API - Get the Proxy Settings for Connecting to the DDNS server ### Description Get the Proxy Settings for Connecting to the DDNS server. @@ -8652,7 +8652,7 @@ Get the Proxy Settings for Connecting to the DDNS server. { "jsonrpc": "2.0", "id": "rpc_call_id", - "method": "GetDDnsInternetSettng", + "method": "GetDDnsInternetSetting", "params": {} } ``` @@ -8683,8 +8683,8 @@ Name | Type | Description `ProxyPassword_str` | `string` (ASCII) | Proxy server password *** - -## "SetDDnsInternetSettng" RPC API - Set the Proxy Settings for Connecting to the DDNS server + +## "SetDDnsInternetSetting" RPC API - Set the Proxy Settings for Connecting to the DDNS server ### Description Set the Proxy Settings for Connecting to the DDNS server. @@ -8693,7 +8693,7 @@ Set the Proxy Settings for Connecting to the DDNS server. { "jsonrpc": "2.0", "id": "rpc_call_id", - "method": "SetDDnsInternetSettng", + "method": "SetDDnsInternetSetting", "params": { "ProxyType_u32": 0, "ProxyHostName_str": "proxyhostname", @@ -8730,6 +8730,6 @@ Name | Type | Description `ProxyPassword_str` | `string` (ASCII) | Proxy server password *** -Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen. -Copyright (c) 2014-2019 [SoftEther VPN Project](https://www.softether.org/) under the Apache License 2.0. +Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen. +Copyright (c) 2014-2023 [SoftEther VPN Project](https://www.softether.org/) under the Apache License 2.0. diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/JsonRpc.cs b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/JsonRpc.cs index 8263a325..e8764013 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/JsonRpc.cs +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/JsonRpc.cs @@ -2,10 +2,10 @@ // // JsonRpc.cs - JSON-RPC Client Utility Functions // -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project using System; using System.IO; diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpc.cs b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpc.cs index e4a0b895..d3d56c44 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpc.cs +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpc.cs @@ -2,10 +2,10 @@ // // VPNServerRpc.cs - SoftEther VPN Server's JSON-RPC Stubs // -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project using System.Threading.Tasks; using SoftEther.JsonRpc; @@ -1357,22 +1357,22 @@ namespace SoftEther.VPNServerRpc /// /// Get the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public async Task GetDDnsInternetSettngAsync() => await CallAsync("GetDDnsInternetSettng", new VpnInternetSetting()); + public async Task GetDDnsInternetSettingAsync() => await CallAsync("GetDDnsInternetSetting", new VpnInternetSetting()); /// /// Get the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public VpnInternetSetting GetDDnsInternetSettng() => GetDDnsInternetSettngAsync().Result; + public VpnInternetSetting GetDDnsInternetSetting() => GetDDnsInternetSettingAsync().Result; /// /// Set the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public async Task SetDDnsInternetSettngAsync(VpnInternetSetting input_param) => await CallAsync("SetDDnsInternetSettng", input_param); + public async Task SetDDnsInternetSettingAsync(VpnInternetSetting input_param) => await CallAsync("SetDDnsInternetSetting", input_param); /// /// Set the Proxy Settings for Connecting to the DDNS server (Sync mode). /// - public VpnInternetSetting SetDDnsInternetSettng(VpnInternetSetting input_param) => SetDDnsInternetSettngAsync(input_param).Result; + public VpnInternetSetting SetDDnsInternetSetting(VpnInternetSetting input_param) => SetDDnsInternetSettingAsync(input_param).Result; /// /// Set the VPN Gate Server Configuration (Async mode). This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpcTypes.cs b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpcTypes.cs index 27f224cf..995228b9 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpcTypes.cs +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/rpc-stubs/VPNServerRpcTypes.cs @@ -2,10 +2,10 @@ // // VPNServerRpcTypes.cs - Data Type Definition for SoftEther VPN Server JSON-RPC Stubs // -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project using System; using Newtonsoft.Json; diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/Main.cs b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/Main.cs index 1021e12b..14d01937 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/Main.cs +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/Main.cs @@ -2,10 +2,10 @@ // // Program.cs - The Main() entry point // -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project class Program { diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/VpnServerRpcTest.cs b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/VpnServerRpcTest.cs index d9ab15f3..8bb9c52a 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/VpnServerRpcTest.cs +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-csharp/sample/VpnServerRpcTest.cs @@ -5,10 +5,10 @@ // This sample code shows how to call all available RPC functions. // You can copy and paste test code to write your own C# codes. // -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project using System; using SoftEther.VPNServerRpc; @@ -255,8 +255,8 @@ class VPNRPCTest Test_GetOpenVpnSstpConfig(); Test_GetDDnsClientStatus(); - Test_SetDDnsInternetSettng(); - Test_GetDDnsInternetSettng(); + Test_SetDDnsInternetSetting(); + Test_GetDDnsInternetSetting(); Test_ChangeDDnsClientHostname(); Test_RegenerateServerCert(); @@ -3641,27 +3641,27 @@ class VPNRPCTest } /// - /// API test for 'GetDDnsInternetSettng', Get DDNS proxy configuration + /// API test for 'GetDDnsInternetSetting', Get DDNS proxy configuration /// - public void Test_GetDDnsInternetSettng() + public void Test_GetDDnsInternetSetting() { - Console.WriteLine("Begin: Test_GetDDnsInternetSettng"); + Console.WriteLine("Begin: Test_GetDDnsInternetSetting"); - VpnInternetSetting out_internet_setting = api.GetDDnsInternetSettng(); + VpnInternetSetting out_internet_setting = api.GetDDnsInternetSetting(); print_object(out_internet_setting); - Console.WriteLine("End: Test_GetDDnsInternetSettng"); + Console.WriteLine("End: Test_GetDDnsInternetSetting"); Console.WriteLine("-----"); Console.WriteLine(); } /// - /// API test for 'SetDDnsInternetSettng', Set DDNS proxy configuration + /// API test for 'SetDDnsInternetSetting', Set DDNS proxy configuration /// - public void Test_SetDDnsInternetSettng() + public void Test_SetDDnsInternetSetting() { - Console.WriteLine("Begin: Test_SetDDnsInternetSettng"); + Console.WriteLine("Begin: Test_SetDDnsInternetSetting"); VpnInternetSetting in_internet_setting = new VpnInternetSetting() { @@ -3671,11 +3671,11 @@ class VPNRPCTest ProxyUsername_str = "neko", ProxyPassword_str = "dog", }; - VpnInternetSetting out_internet_setting = api.SetDDnsInternetSettng(in_internet_setting); + VpnInternetSetting out_internet_setting = api.SetDDnsInternetSetting(in_internet_setting); print_object(out_internet_setting); - Console.WriteLine("End: Test_SetDDnsInternetSettng"); + Console.WriteLine("End: Test_SetDDnsInternetSetting"); Console.WriteLine("-----"); Console.WriteLine(); } diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/sample.js b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/sample.js index dd3db357..4cf85de6 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/sample.js +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/sample.js @@ -560,10 +560,10 @@ function Test_All() { return [4 /*yield*/, Test_GetDDnsClientStatus()]; case 157: _x.sent(); - return [4 /*yield*/, Test_SetDDnsInternetSettng()]; + return [4 /*yield*/, Test_SetDDnsInternetSetting()]; case 158: _x.sent(); - return [4 /*yield*/, Test_GetDDnsInternetSettng()]; + return [4 /*yield*/, Test_GetDDnsInternetSetting()]; case 159: _x.sent(); return [4 /*yield*/, Test_ChangeDDnsClientHostname()]; @@ -4047,19 +4047,19 @@ function Test_SetAzureStatus() { }); }); } -/** API test for 'GetDDnsInternetSettng', Get DDNS proxy configuration */ -function Test_GetDDnsInternetSettng() { +/** API test for 'GetDDnsInternetSetting', Get DDNS proxy configuration */ +function Test_GetDDnsInternetSetting() { return __awaiter(this, void 0, void 0, function () { var out_internet_setting; return __generator(this, function (_a) { switch (_a.label) { case 0: - console.log("Begin: Test_GetDDnsInternetSettng"); - return [4 /*yield*/, api.GetDDnsInternetSettng()]; + console.log("Begin: Test_GetDDnsInternetSetting"); + return [4 /*yield*/, api.GetDDnsInternetSetting()]; case 1: out_internet_setting = _a.sent(); console.log(out_internet_setting); - console.log("End: Test_GetDDnsInternetSettng"); + console.log("End: Test_GetDDnsInternetSetting"); console.log("-----"); console.log(); return [2 /*return*/]; @@ -4067,14 +4067,14 @@ function Test_GetDDnsInternetSettng() { }); }); } -/** API test for 'SetDDnsInternetSettng', Set DDNS proxy configuration */ -function Test_SetDDnsInternetSettng() { +/** API test for 'SetDDnsInternetSetting', Set DDNS proxy configuration */ +function Test_SetDDnsInternetSetting() { return __awaiter(this, void 0, void 0, function () { var in_internet_setting, out_internet_setting; return __generator(this, function (_a) { switch (_a.label) { case 0: - console.log("Begin: Test_SetDDnsInternetSettng"); + console.log("Begin: Test_SetDDnsInternetSetting"); in_internet_setting = new VPN.VpnInternetSetting({ ProxyType_u32: VPN.VpnRpcProxyType.Direct, ProxyHostName_str: "1.2.3.4", @@ -4082,11 +4082,11 @@ function Test_SetDDnsInternetSettng() { ProxyUsername_str: "neko", ProxyPassword_str: "dog" }); - return [4 /*yield*/, api.SetDDnsInternetSettng(in_internet_setting)]; + return [4 /*yield*/, api.SetDDnsInternetSetting(in_internet_setting)]; case 1: out_internet_setting = _a.sent(); console.log(out_internet_setting); - console.log("End: Test_SetDDnsInternetSettng"); + console.log("End: Test_SetDDnsInternetSetting"); console.log("-----"); console.log(); return [2 /*return*/]; diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.d.ts b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.d.ts index 6b839ce9..9ccc0ae9 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.d.ts +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.d.ts @@ -278,9 +278,9 @@ export declare class VpnServerRpc { /** Enable / Disable VPN Azure Function. Enable or disable the VPN Azure function. VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company. You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC. VPN Azure is a cloud VPN service operated by SoftEther Corporation. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions. The VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the ChangeDDnsClientHostname API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */ SetAzureStatus: (in_param: VpnRpcAzureStatus) => Promise; /** Get the Proxy Settings for Connecting to the DDNS server. */ - GetDDnsInternetSettng: () => Promise; + GetDDnsInternetSetting: () => Promise; /** Set the Proxy Settings for Connecting to the DDNS server. */ - SetDDnsInternetSettng: (in_param: VpnInternetSetting) => Promise; + SetDDnsInternetSetting: (in_param: VpnInternetSetting) => Promise; /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */ SetVgsConfig: (in_param: VpnVgsConfig) => Promise; /** Get the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */ diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.js b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.js index eac8ab09..8dc8ea70 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.js +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/dist/vpnrpc.js @@ -599,12 +599,12 @@ var VpnServerRpc = /** @class */ (function () { return _this.CallAsync("SetAzureStatus", in_param); }; /** Get the Proxy Settings for Connecting to the DDNS server. */ - this.GetDDnsInternetSettng = function () { - return _this.CallAsync("GetDDnsInternetSettng", new VpnInternetSetting()); + this.GetDDnsInternetSetting = function () { + return _this.CallAsync("GetDDnsInternetSetting", new VpnInternetSetting()); }; /** Set the Proxy Settings for Connecting to the DDNS server. */ - this.SetDDnsInternetSettng = function (in_param) { - return _this.CallAsync("SetDDnsInternetSettng", in_param); + this.SetDDnsInternetSetting = function (in_param) { + return _this.CallAsync("SetDDnsInternetSetting", in_param); }; /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */ this.SetVgsConfig = function (in_param) { diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/sample.ts b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/sample.ts index ddb69314..ec8e8568 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/sample.ts +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/sample.ts @@ -2,13 +2,13 @@ // Runs on both web browsers and Node.js // // sample.ts -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // This sample code shows how to call all available RPC functions. // You can copy and paste test code to write your own web browser TypeScript / JavaScript codes. // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project // On the web browser uncomment below imports as necessary to support old browsers. // import "core-js/es6/promise"; @@ -216,8 +216,8 @@ async function Test_All(): Promise await Test_SetOpenVpnSstpConfig(); await Test_GetOpenVpnSstpConfig(); await Test_GetDDnsClientStatus(); - await Test_SetDDnsInternetSettng(); - await Test_GetDDnsInternetSettng(); + await Test_SetDDnsInternetSetting(); + await Test_GetDDnsInternetSetting(); await Test_ChangeDDnsClientHostname(); await Test_RegenerateServerCert(); await Test_MakeOpenVpnConfigFile(); @@ -2624,21 +2624,21 @@ async function Test_SetAzureStatus(): Promise console.log(); } -/** API test for 'GetDDnsInternetSettng', Get DDNS proxy configuration */ -async function Test_GetDDnsInternetSettng(): Promise +/** API test for 'GetDDnsInternetSetting', Get DDNS proxy configuration */ +async function Test_GetDDnsInternetSetting(): Promise { - console.log("Begin: Test_GetDDnsInternetSettng"); - let out_internet_setting: VPN.VpnInternetSetting = await api.GetDDnsInternetSettng(); + console.log("Begin: Test_GetDDnsInternetSetting"); + let out_internet_setting: VPN.VpnInternetSetting = await api.GetDDnsInternetSetting(); console.log(out_internet_setting); - console.log("End: Test_GetDDnsInternetSettng"); + console.log("End: Test_GetDDnsInternetSetting"); console.log("-----"); console.log(); } -/** API test for 'SetDDnsInternetSettng', Set DDNS proxy configuration */ -async function Test_SetDDnsInternetSettng(): Promise +/** API test for 'SetDDnsInternetSetting', Set DDNS proxy configuration */ +async function Test_SetDDnsInternetSetting(): Promise { - console.log("Begin: Test_SetDDnsInternetSettng"); + console.log("Begin: Test_SetDDnsInternetSetting"); let in_internet_setting: VPN.VpnInternetSetting = new VPN.VpnInternetSetting( { ProxyType_u32: VPN.VpnRpcProxyType.Direct, @@ -2647,9 +2647,9 @@ async function Test_SetDDnsInternetSettng(): Promise ProxyUsername_str: "neko", ProxyPassword_str: "dog", }); - let out_internet_setting: VPN.VpnInternetSetting = await api.SetDDnsInternetSettng(in_internet_setting); + let out_internet_setting: VPN.VpnInternetSetting = await api.SetDDnsInternetSetting(in_internet_setting); console.log(out_internet_setting); - console.log("End: Test_SetDDnsInternetSettng"); + console.log("End: Test_SetDDnsInternetSetting"); console.log("-----"); console.log(); } diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/vpnrpc.ts b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/vpnrpc.ts index 1774bbd6..552f62bf 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/vpnrpc.ts +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-nodejs-package/src/vpnrpc.ts @@ -1,10 +1,10 @@ // SoftEther VPN Server JSON-RPC Stub code for TypeScript // // vpnrpc.ts -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project // Trivial utility codes @@ -856,15 +856,15 @@ export class VpnServerRpc } /** Get the Proxy Settings for Connecting to the DDNS server. */ - public GetDDnsInternetSettng = (): Promise => + public GetDDnsInternetSetting = (): Promise => { - return this.CallAsync("GetDDnsInternetSettng", new VpnInternetSetting()); + return this.CallAsync("GetDDnsInternetSetting", new VpnInternetSetting()); } /** Set the Proxy Settings for Connecting to the DDNS server. */ - public SetDDnsInternetSettng = (in_param: VpnInternetSetting): Promise => + public SetDDnsInternetSetting = (in_param: VpnInternetSetting): Promise => { - return this.CallAsync("SetDDnsInternetSettng", in_param); + return this.CallAsync("SetDDnsInternetSetting", in_param); } /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */ diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/sample.ts b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/sample.ts index ddb69314..ec8e8568 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/sample.ts +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/sample.ts @@ -2,13 +2,13 @@ // Runs on both web browsers and Node.js // // sample.ts -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // This sample code shows how to call all available RPC functions. // You can copy and paste test code to write your own web browser TypeScript / JavaScript codes. // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project // On the web browser uncomment below imports as necessary to support old browsers. // import "core-js/es6/promise"; @@ -216,8 +216,8 @@ async function Test_All(): Promise await Test_SetOpenVpnSstpConfig(); await Test_GetOpenVpnSstpConfig(); await Test_GetDDnsClientStatus(); - await Test_SetDDnsInternetSettng(); - await Test_GetDDnsInternetSettng(); + await Test_SetDDnsInternetSetting(); + await Test_GetDDnsInternetSetting(); await Test_ChangeDDnsClientHostname(); await Test_RegenerateServerCert(); await Test_MakeOpenVpnConfigFile(); @@ -2624,21 +2624,21 @@ async function Test_SetAzureStatus(): Promise console.log(); } -/** API test for 'GetDDnsInternetSettng', Get DDNS proxy configuration */ -async function Test_GetDDnsInternetSettng(): Promise +/** API test for 'GetDDnsInternetSetting', Get DDNS proxy configuration */ +async function Test_GetDDnsInternetSetting(): Promise { - console.log("Begin: Test_GetDDnsInternetSettng"); - let out_internet_setting: VPN.VpnInternetSetting = await api.GetDDnsInternetSettng(); + console.log("Begin: Test_GetDDnsInternetSetting"); + let out_internet_setting: VPN.VpnInternetSetting = await api.GetDDnsInternetSetting(); console.log(out_internet_setting); - console.log("End: Test_GetDDnsInternetSettng"); + console.log("End: Test_GetDDnsInternetSetting"); console.log("-----"); console.log(); } -/** API test for 'SetDDnsInternetSettng', Set DDNS proxy configuration */ -async function Test_SetDDnsInternetSettng(): Promise +/** API test for 'SetDDnsInternetSetting', Set DDNS proxy configuration */ +async function Test_SetDDnsInternetSetting(): Promise { - console.log("Begin: Test_SetDDnsInternetSettng"); + console.log("Begin: Test_SetDDnsInternetSetting"); let in_internet_setting: VPN.VpnInternetSetting = new VPN.VpnInternetSetting( { ProxyType_u32: VPN.VpnRpcProxyType.Direct, @@ -2647,9 +2647,9 @@ async function Test_SetDDnsInternetSettng(): Promise ProxyUsername_str: "neko", ProxyPassword_str: "dog", }); - let out_internet_setting: VPN.VpnInternetSetting = await api.SetDDnsInternetSettng(in_internet_setting); + let out_internet_setting: VPN.VpnInternetSetting = await api.SetDDnsInternetSetting(in_internet_setting); console.log(out_internet_setting); - console.log("End: Test_SetDDnsInternetSettng"); + console.log("End: Test_SetDDnsInternetSetting"); console.log("-----"); console.log(); } diff --git a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/vpnrpc.ts b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/vpnrpc.ts index 1774bbd6..552f62bf 100644 --- a/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/vpnrpc.ts +++ b/developer_tools/vpnserver-jsonrpc-clients/vpnserver-jsonrpc-client-typescript/vpnrpc.ts @@ -1,10 +1,10 @@ // SoftEther VPN Server JSON-RPC Stub code for TypeScript // // vpnrpc.ts -// Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen +// Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen // // Licensed under the Apache License 2.0 -// Copyright (c) 2014-2019 SoftEther VPN Project +// Copyright (c) 2014-2023 SoftEther VPN Project // Trivial utility codes @@ -856,15 +856,15 @@ export class VpnServerRpc } /** Get the Proxy Settings for Connecting to the DDNS server. */ - public GetDDnsInternetSettng = (): Promise => + public GetDDnsInternetSetting = (): Promise => { - return this.CallAsync("GetDDnsInternetSettng", new VpnInternetSetting()); + return this.CallAsync("GetDDnsInternetSetting", new VpnInternetSetting()); } /** Set the Proxy Settings for Connecting to the DDNS server. */ - public SetDDnsInternetSettng = (in_param: VpnInternetSetting): Promise => + public SetDDnsInternetSetting = (in_param: VpnInternetSetting): Promise => { - return this.CallAsync("SetDDnsInternetSettng", in_param); + return this.CallAsync("SetDDnsInternetSetting", in_param); } /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */ diff --git a/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpc/VPNServerRpc.cs b/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpc/VPNServerRpc.cs index 63da0e6d..06e06658 100644 --- a/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpc/VPNServerRpc.cs +++ b/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpc/VPNServerRpc.cs @@ -1357,22 +1357,22 @@ namespace SoftEther.VPNServerRpc /// /// Get the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public async Task GetDDnsInternetSettngAsync() => await CallAsync("GetDDnsInternetSettng", new VpnInternetSetting()); + public async Task GetDDnsInternetSettingAsync() => await CallAsync("GetDDnsInternetSetting", new VpnInternetSetting()); /// /// Get the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public VpnInternetSetting GetDDnsInternetSettng() => GetDDnsInternetSettngAsync().Result; + public VpnInternetSetting GetDDnsInternetSetting() => GetDDnsInternetSettingAsync().Result; /// /// Set the Proxy Settings for Connecting to the DDNS server (Async mode). /// - public async Task SetDDnsInternetSettngAsync(VpnInternetSetting input_param) => await CallAsync("SetDDnsInternetSettng", input_param); + public async Task SetDDnsInternetSettingAsync(VpnInternetSetting input_param) => await CallAsync("SetDDnsInternetSetting", input_param); /// /// Set the Proxy Settings for Connecting to the DDNS server (Sync mode). /// - public VpnInternetSetting SetDDnsInternetSettng(VpnInternetSetting input_param) => SetDDnsInternetSettngAsync(input_param).Result; + public VpnInternetSetting SetDDnsInternetSetting(VpnInternetSetting input_param) => SetDDnsInternetSettingAsync(input_param).Result; /// /// Set the VPN Gate Server Configuration (Async mode). This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. diff --git a/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpcTest/VpnServerRpcTest.cs b/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpcTest/VpnServerRpcTest.cs index b407750f..a3fe751b 100644 --- a/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpcTest/VpnServerRpcTest.cs +++ b/developer_tools/vpnserver-jsonrpc-codegen/VpnServerRpcTest/VpnServerRpcTest.cs @@ -255,8 +255,8 @@ class VPNRPCTest Test_GetOpenVpnSstpConfig(); Test_GetDDnsClientStatus(); - Test_SetDDnsInternetSettng(); - Test_GetDDnsInternetSettng(); + Test_SetDDnsInternetSetting(); + Test_GetDDnsInternetSetting(); Test_ChangeDDnsClientHostname(); Test_RegenerateServerCert(); @@ -3641,27 +3641,27 @@ class VPNRPCTest } /// - /// API test for 'GetDDnsInternetSettng', Get DDNS proxy configuration + /// API test for 'GetDDnsInternetSetting', Get DDNS proxy configuration /// - public void Test_GetDDnsInternetSettng() + public void Test_GetDDnsInternetSetting() { - Console.WriteLine("Begin: Test_GetDDnsInternetSettng"); + Console.WriteLine("Begin: Test_GetDDnsInternetSetting"); - VpnInternetSetting out_internet_setting = api.GetDDnsInternetSettng(); + VpnInternetSetting out_internet_setting = api.GetDDnsInternetSetting(); print_object(out_internet_setting); - Console.WriteLine("End: Test_GetDDnsInternetSettng"); + Console.WriteLine("End: Test_GetDDnsInternetSetting"); Console.WriteLine("-----"); Console.WriteLine(); } /// - /// API test for 'SetDDnsInternetSettng', Set DDNS proxy configuration + /// API test for 'SetDDnsInternetSetting', Set DDNS proxy configuration /// - public void Test_SetDDnsInternetSettng() + public void Test_SetDDnsInternetSetting() { - Console.WriteLine("Begin: Test_SetDDnsInternetSettng"); + Console.WriteLine("Begin: Test_SetDDnsInternetSetting"); VpnInternetSetting in_internet_setting = new VpnInternetSetting() { @@ -3671,11 +3671,11 @@ class VPNRPCTest ProxyUsername_str = "neko", ProxyPassword_str = "dog", }; - VpnInternetSetting out_internet_setting = api.SetDDnsInternetSettng(in_internet_setting); + VpnInternetSetting out_internet_setting = api.SetDDnsInternetSetting(in_internet_setting); print_object(out_internet_setting); - Console.WriteLine("End: Test_SetDDnsInternetSettng"); + Console.WriteLine("End: Test_SetDDnsInternetSetting"); Console.WriteLine("-----"); Console.WriteLine(); } diff --git a/src/Cedar/Admin.c b/src/Cedar/Admin.c index 85f9bd9b..db14932e 100644 --- a/src/Cedar/Admin.c +++ b/src/Cedar/Admin.c @@ -1644,8 +1644,8 @@ PACK *AdminDispatch(RPC *rpc, char *name, PACK *p) DECLARE_RPC("GetSpecialListener", RPC_SPECIAL_LISTENER, StGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener) DECLARE_RPC("GetAzureStatus", RPC_AZURE_STATUS, StGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus) DECLARE_RPC("SetAzureStatus", RPC_AZURE_STATUS, StSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus) - DECLARE_RPC("GetDDnsInternetSettng", INTERNET_SETTING, StGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) - DECLARE_RPC("SetDDnsInternetSettng", INTERNET_SETTING, StSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) + DECLARE_RPC("GetDDnsInternetSetting", INTERNET_SETTING, StGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) + DECLARE_RPC("SetDDnsInternetSetting", INTERNET_SETTING, StSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) // RPC function declaration: till here @@ -1831,8 +1831,8 @@ DECLARE_SC("SetSpecialListener", RPC_SPECIAL_LISTENER, ScSetSpecialListener, InR DECLARE_SC("GetSpecialListener", RPC_SPECIAL_LISTENER, ScGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener) DECLARE_SC("GetAzureStatus", RPC_AZURE_STATUS, ScGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus) DECLARE_SC("SetAzureStatus", RPC_AZURE_STATUS, ScSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus) -DECLARE_SC("GetDDnsInternetSettng", INTERNET_SETTING, ScGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) -DECLARE_SC("SetDDnsInternetSettng", INTERNET_SETTING, ScSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) +DECLARE_SC("GetDDnsInternetSetting", INTERNET_SETTING, ScGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) +DECLARE_SC("SetDDnsInternetSetting", INTERNET_SETTING, ScSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting) // RPC call function declaration: till here // Setting VPN Gate Server Configuration diff --git a/src/bin/hamcore/vpnserver_api_doc.html b/src/bin/hamcore/vpnserver_api_doc.html index 1735667e..cfd3926d 100644 --- a/src/bin/hamcore/vpnserver_api_doc.html +++ b/src/bin/hamcore/vpnserver_api_doc.html @@ -216,8 +216,8 @@ All APIs are based on the JSON-R
  • GetSpecialListener - Get Current Setting of the VPN over ICMP / VPN over DNS Function
  • GetAzureStatus - Show the current status of VPN Azure function
  • SetAzureStatus - Enable / Disable VPN Azure Function
  • -
  • GetDDnsInternetSettng - Get the Proxy Settings for Connecting to the DDNS server
  • -
  • SetDDnsInternetSettng - Set the Proxy Settings for Connecting to the DDNS server
  • +
  • GetDDnsInternetSetting - Get the Proxy Settings for Connecting to the DDNS server
  • +
  • SetDDnsInternetSetting - Set the Proxy Settings for Connecting to the DDNS server
  • SetVgsConfig - Set the VPN Gate Server Configuration
  • GetVgsConfig - Get the VPN Gate Server Configuration
  • @@ -305,7 +305,7 @@ All APIs are based on the JSON-R "ServerBuildInt_u32": 0, "ServerHostName_str": "serverhostname", "ServerType_u32": 0, - "ServerBuildDate_dt": "2020-08-01T12:24:36.123", + "ServerBuildDate_dt": "2024-08-01T12:24:36.123", "ServerFamilyName_str": "serverfamilyname", "OsType_u32": 0, "OsServicePack_u32": 0, @@ -460,9 +460,9 @@ All APIs are based on the JSON-R "Send.BroadcastCount_u64": 0, "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, - "CurrentTime_dt": "2020-08-01T12:24:36.123", + "CurrentTime_dt": "2024-08-01T12:24:36.123", "CurrentTick_u64": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", "TotalMemory_u64": 0, "UsedMemory_u64": 0, "FreeMemory_u64": 0, @@ -1136,7 +1136,7 @@ All APIs are based on the JSON-R "result": { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1283,7 +1283,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1296,7 +1296,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1309,7 +1309,7 @@ All APIs are based on the JSON-R { "Id_u32": 0, "Controller_bool": false, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Ip_ip": "192.168.0.1", "Hostname_str": "hostname", "Point_u32": 0, @@ -1422,9 +1422,9 @@ All APIs are based on the JSON-R "Port_u32": 0, "Online_bool": false, "LastError_u32": 0, - "StartedTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectedTime_dt": "2020-08-01T12:24:36.123", + "StartedTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectedTime_dt": "2024-08-01T12:24:36.123", "NumTry_u32": 0, "NumConnected_u32": 0, "NumFailed_u32": 0 @@ -1918,9 +1918,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1941,9 +1941,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -1964,9 +1964,9 @@ All APIs are based on the JSON-R "NumSessions_u32": 0, "NumMacTables_u32": 0, "NumIpTables_u32": 0, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0, "IsTrafficFilled_bool": false, "Ex.Recv.BroadcastBytes_u64": 0, @@ -2309,7 +2309,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -2317,7 +2317,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 }, { @@ -2325,7 +2325,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Type_u32": 0 } ] @@ -2450,7 +2450,7 @@ All APIs are based on the JSON-R "Hostname_str": "hostname", "Ip_ip": "192.168.0.1", "Port_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "ServerStr_str": "serverstr", "ServerVer_u32": 0, "ServerBuild_u32": 0, @@ -2620,9 +2620,9 @@ All APIs are based on the JSON-R "Send.UnicastBytes_u64": 0, "Send.UnicastCount_u64": 0, "SecureNATEnabled_bool": false, - "LastCommTime_dt": "2020-08-01T12:24:36.123", - "LastLoginTime_dt": "2020-08-01T12:24:36.123", - "CreatedTime_dt": "2020-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", "NumLogin_u32": 0 } } @@ -2992,19 +2992,19 @@ All APIs are based on the JSON-R "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" }, { "Key_u32": 0, "SubjectName_utf": "subjectname", "IssuerName_utf": "issuername", - "Expires_dt": "2020-08-01T12:24:36.123" + "Expires_dt": "2024-08-01T12:24:36.123" } ] } @@ -4348,7 +4348,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -4357,7 +4357,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" }, @@ -4366,7 +4366,7 @@ All APIs are based on the JSON-R "Online_bool": false, "Connected_bool": false, "LastError_u32": 0, - "ConnectedTime_dt": "2020-08-01T12:24:36.123", + "ConnectedTime_dt": "2024-08-01T12:24:36.123", "Hostname_str": "hostname", "TargetHubName_str": "targethubname" } @@ -4668,9 +4668,9 @@ All APIs are based on the JSON-R "ServerProductBuild_u32": 0, "ServerX_bin": "SGVsbG8gV29ybGQ=", "ClientX_bin": "SGVsbG8gV29ybGQ=", - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -5996,7 +5996,7 @@ All APIs are based on the JSON-R "Name_str": "name", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6057,9 +6057,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6467,7 +6467,7 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6528,9 +6528,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -6948,9 +6948,9 @@ All APIs are based on the JSON-R "GroupName_str": "groupname", "Realname_utf": "realname", "Note_utf": "note", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "AuthType_u32": 0, "Auth_Password_str": "auth_password", "UserX_bin": "SGVsbG8gV29ybGQ=", @@ -7419,11 +7419,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -7440,11 +7440,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -7461,11 +7461,11 @@ All APIs are based on the JSON-R "Note_utf": "note", "AuthType_u32": 0, "NumLogin_u32": 0, - "LastLoginTime_dt": "2020-08-01T12:24:36.123", + "LastLoginTime_dt": "2024-08-01T12:24:36.123", "DenyAccess_bool": false, "IsTrafficFilled_bool": false, "IsExpiresFilled_bool": false, - "Expires_dt": "2020-08-01T12:24:36.123", + "Expires_dt": "2024-08-01T12:24:36.123", "Ex.Recv.BroadcastBytes_u64": 0, "Ex.Recv.BroadcastCount_u64": 0, "Ex.Recv.UnicastBytes_u64": 0, @@ -8907,8 +8907,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -8929,8 +8929,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" }, { "Name_str": "name", @@ -8951,8 +8951,8 @@ All APIs are based on the JSON-R "Client_MonitorMode_bool": false, "VLanId_u32": 0, "UniqueId_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123" + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -9117,9 +9117,9 @@ All APIs are based on the JSON-R "ServerProductName_str": "serverproductname", "ServerProductVer_u32": 0, "ServerProductBuild_u32": 0, - "StartTime_dt": "2020-08-01T12:24:36.123", - "FirstConnectionEstablisiedTime_dt": "2020-08-01T12:24:36.123", - "CurrentConnectionEstablishTime_dt": "2020-08-01T12:24:36.123", + "StartTime_dt": "2024-08-01T12:24:36.123", + "FirstConnectionEstablisiedTime_dt": "2024-08-01T12:24:36.123", + "CurrentConnectionEstablishTime_dt": "2024-08-01T12:24:36.123", "NumConnectionsEatablished_u32": 0, "HalfConnection_bool": false, "QoS_bool": false, @@ -9496,8 +9496,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9506,8 +9506,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9516,8 +9516,8 @@ All APIs are based on the JSON-R "Key_u32": 0, "SessionName_str": "sessionname", "MacAddress_bin": "SGVsbG8gV29ybGQ=", - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname", "VlanId_u32": 0 @@ -9663,8 +9663,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -9673,8 +9673,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" }, @@ -9683,8 +9683,8 @@ All APIs are based on the JSON-R "SessionName_str": "sessionname", "IpAddress_ip": "192.168.0.1", "DhcpAllocated_bool": false, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "UpdatedTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "UpdatedTime_dt": "2024-08-01T12:24:36.123", "RemoteItem_bool": false, "RemoteHostname_str": "remotehostname" } @@ -10376,8 +10376,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10391,8 +10391,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10406,8 +10406,8 @@ All APIs are based on the JSON-R "DestIp_ip": "192.168.0.1", "DestHost_str": "desthost", "DestPort_u32": 0, - "CreatedTime_dt": "2020-08-01T12:24:36.123", - "LastCommTime_dt": "2020-08-01T12:24:36.123", + "CreatedTime_dt": "2024-08-01T12:24:36.123", + "LastCommTime_dt": "2024-08-01T12:24:36.123", "SendSize_u64": 0, "RecvSize_u64": 0, "TcpStatus_u32": 0 @@ -10527,8 +10527,8 @@ All APIs are based on the JSON-R "DhcpTable": [ { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -10536,8 +10536,8 @@ All APIs are based on the JSON-R }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -10545,8 +10545,8 @@ All APIs are based on the JSON-R }, { "Id_u32": 0, - "LeasedTime_dt": "2020-08-01T12:24:36.123", - "ExpireTime_dt": "2020-08-01T12:24:36.123", + "LeasedTime_dt": "2024-08-01T12:24:36.123", + "ExpireTime_dt": "2024-08-01T12:24:36.123", "MacAddress_bin": "SGVsbG8gV29ybGQ=", "IpAddress_ip": "192.168.0.1", "Mask_u32": 0, @@ -13090,19 +13090,19 @@ All APIs are based on the JSON-R "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" }, { "ServerName_str": "servername", "FilePath_str": "filepath", "FileSize_u32": 0, - "UpdatedTime_dt": "2020-08-01T12:24:36.123" + "UpdatedTime_dt": "2024-08-01T12:24:36.123" } ] } @@ -14508,15 +14508,15 @@ All APIs are based on the JSON-R
    -

    -

    "GetDDnsInternetSettng" RPC API - Get the Proxy Settings for Connecting to the DDNS server

    +

    +

    "GetDDnsInternetSetting" RPC API - Get the Proxy Settings for Connecting to the DDNS server

    Description

    Get the Proxy Settings for Connecting to the DDNS server.

    Input JSON-RPC Format

    {
       "jsonrpc": "2.0",
       "id": "rpc_call_id",
    -  "method": "GetDDnsInternetSettng",
    +  "method": "GetDDnsInternetSetting",
       "params": {}
     }
     
    @@ -14571,15 +14571,15 @@ All APIs are based on the JSON-R
    -

    -

    "SetDDnsInternetSettng" RPC API - Set the Proxy Settings for Connecting to the DDNS server

    +

    +

    "SetDDnsInternetSetting" RPC API - Set the Proxy Settings for Connecting to the DDNS server

    Description

    Set the Proxy Settings for Connecting to the DDNS server.

    Input JSON-RPC Format

    {
       "jsonrpc": "2.0",
       "id": "rpc_call_id",
    -  "method": "SetDDnsInternetSettng",
    +  "method": "SetDDnsInternetSetting",
       "params": {
         "ProxyType_u32": 0,
         "ProxyHostName_str": "proxyhostname",
    @@ -14640,8 +14640,8 @@ All APIs are based on the JSON-R
     
     
     
    -

    Automatically generated at 2019-07-10 14:36:11 by vpnserver-jsonrpc-codegen.
    -Copyright (c) 2014-2019
    SoftEther VPN Project under the Apache License 2.0.

    +

    Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen.
    +Copyright (c) 2014-2023 SoftEther VPN Project under the Apache License 2.0.

    diff --git a/src/bin/hamcore/wwwroot/admin/default/out_webpack/bundle.js b/src/bin/hamcore/wwwroot/admin/default/out_webpack/bundle.js index a2a06fdf..2fc795a2 100644 --- a/src/bin/hamcore/wwwroot/admin/default/out_webpack/bundle.js +++ b/src/bin/hamcore/wwwroot/admin/default/out_webpack/bundle.js @@ -2058,7 +2058,7 @@ eval("/* WEBPACK VAR INJECTION */(function(global) {\n/**\n * Module exports.\n /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("/* WEBPACK VAR INJECTION */(function(Buffer) {\r\n// SoftEther VPN Server JSON-RPC Stub code for TypeScript\r\n// \r\n// vpnrpc.ts\r\n// Automatically generated at 2019-05-29 18:21:39 by vpnserver-jsonrpc-codegen\r\n//\r\n// Licensed under the Apache License 2.0\r\n// Copyright (c) 2014-2019 SoftEther VPN Project\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = function (d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nexports.__esModule = true;\r\n// Trivial utility codes\r\nvar is_node_js = (typeof navigator === \"undefined\") || navigator.userAgent.indexOf(\"Node.js\") !== -1 || navigator.userAgent.indexOf(\"jsdom\") !== -1;\r\nfunction is_null(obj) {\r\n return (typeof obj === \"undefined\") || (obj === null);\r\n}\r\nvar debug_mode = false;\r\n/** VPN Server RPC Stubs */\r\nvar VpnServerRpc = /** @class */ (function () {\r\n /**\r\n * Constructor of the VpnServerRpc class\r\n * @param vpnserver_hostname The hostname or IP address of the destination VPN Server. In the web browser you can specify null if you want to connect to the server itself.\r\n * @param vpnserver_port The port number of the destination VPN Server. In the web browser you can specify null if you want to connect to the server itself.\r\n * @param hubname The name of the Virtual Hub if you want to connect to the VPN Server as a Virtual Hub Admin Mode. Specify null if you want to connect to the VPN Server as the Entire VPN Server Admin Mode.\r\n * @param password Specify the administration password. This value is valid only if vpnserver_hostname is sepcified.\r\n * @param nodejs_https_client_reject_untrusted_server_cert In Node.js set this true to check the SSL server certificate on the destination VPN Server. Set this false to ignore the SSL server certification.\r\n */\r\n function VpnServerRpc(vpnserver_hostname, vpnserver_port, hubname, password, nodejs_https_client_reject_untrusted_server_cert) {\r\n var _this = this;\r\n // --- Stubs ---\r\n /** Test RPC function. Input any integer value to the IntValue_u32 field. Then the server will convert the integer to the string, and return the string in the StrValue_str field. */\r\n this.Test = function (in_param) {\r\n return _this.CallAsync(\"Test\", in_param);\r\n };\r\n /** Get server information. This allows you to obtain the server information of the currently connected VPN Server or VPN Bridge. Included in the server information are the version number, build number and build information. You can also obtain information on the current server operation mode and the information of operating system that the server is operating on. */\r\n this.GetServerInfo = function () {\r\n return _this.CallAsync(\"GetServerInfo\", new VpnRpcServerInfo());\r\n };\r\n /** Get Current Server Status. This allows you to obtain in real-time the current status of the currently connected VPN Server or VPN Bridge. You can get statistical information on data communication and the number of different kinds of objects that exist on the server. You can get information on how much memory is being used on the current computer by the OS. */\r\n this.GetServerStatus = function () {\r\n return _this.CallAsync(\"GetServerStatus\", new VpnRpcServerStatus());\r\n };\r\n /** Create New TCP Listener. This allows you to create a new TCP Listener on the server. By creating the TCP Listener the server starts listening for a connection from clients at the specified TCP/IP port number. A TCP Listener that has been created can be deleted by the DeleteListener API. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To execute this API, you must have VPN Server administrator privileges. */\r\n this.CreateListener = function (in_param) {\r\n return _this.CallAsync(\"CreateListener\", in_param);\r\n };\r\n /** Get List of TCP Listeners. This allows you to get a list of TCP listeners registered on the current server. You can obtain information on whether the various TCP listeners have a status of operating or error. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumListener = function () {\r\n return _this.CallAsync(\"EnumListener\", new VpnRpcListenerList());\r\n };\r\n /** Delete TCP Listener. This allows you to delete a TCP Listener that's registered on the server. When the TCP Listener is in a state of operation, the listener will automatically be deleted when its operation stops. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To call this API, you must have VPN Server administrator privileges. */\r\n this.DeleteListener = function (in_param) {\r\n return _this.CallAsync(\"DeleteListener\", in_param);\r\n };\r\n /** Enable / Disable TCP Listener. This starts or stops the operation of TCP Listeners registered on the current server. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnableListener = function (in_param) {\r\n return _this.CallAsync(\"EnableListener\", in_param);\r\n };\r\n /** Set VPN Server Administrator Password. This sets the VPN Server administrator password. You can specify the password as a parameter. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerPassword = function (in_param) {\r\n return _this.CallAsync(\"SetServerPassword\", in_param);\r\n };\r\n /** Set the VPN Server clustering configuration. Use this to set the VPN Server type as Standalone Server, Cluster Controller Server or Cluster Member Server. Standalone server means a VPN Server that does not belong to any cluster in its current state. When VPN Server is installed, by default it will be in standalone server mode. Unless you have particular plans to configure a cluster, we recommend the VPN Server be operated in standalone mode. A cluster controller is the central computer of all member servers of a cluster in the case where a clustering environment is made up of multiple VPN Servers. Multiple cluster members can be added to the cluster as required. A cluster requires one computer to serve this role. The other cluster member servers that are configured in the same cluster begin operation as a cluster member by connecting to the cluster controller. To call this API, you must have VPN Server administrator privileges. Also, when this API is executed, VPN Server will automatically restart. This API cannot be called on VPN Bridge. */\r\n this.SetFarmSetting = function (in_param) {\r\n return _this.CallAsync(\"SetFarmSetting\", in_param);\r\n };\r\n /** Get Clustering Configuration of Current VPN Server. You can use this to acquire the clustering configuration of the current VPN Server. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetFarmSetting = function () {\r\n return _this.CallAsync(\"GetFarmSetting\", new VpnRpcFarm());\r\n };\r\n /** Get Cluster Member Information. When the VPN Server is operating as a cluster controller, you can get information on cluster member servers on that cluster by specifying the IDs of the member servers. You can get the following information about the specified cluster member server: Server Type, Time Connection has been Established, IP Address, Host Name, Points, Public Port List, Number of Operating Virtual Hubs, First Virtual Hub, Number of Sessions and Number of TCP Connections. This API cannot be invoked on VPN Bridge. */\r\n this.GetFarmInfo = function (in_param) {\r\n return _this.CallAsync(\"GetFarmInfo\", in_param);\r\n };\r\n /** Get List of Cluster Members. Use this API when the VPN Server is operating as a cluster controller to get a list of the cluster member servers on the same cluster, including the cluster controller itself. For each member, the following information is also listed: Type, Connection Start, Host Name, Points, Number of Session, Number of TCP Connections, Number of Operating Virtual Hubs, Using Client Connection License and Using Bridge Connection License. This API cannot be invoked on VPN Bridge. */\r\n this.EnumFarmMember = function () {\r\n return _this.CallAsync(\"EnumFarmMember\", new VpnRpcEnumFarm());\r\n };\r\n /** Get Connection Status to Cluster Controller. Use this API when the VPN Server is operating as a cluster controller to get the status of connection to the cluster controller. You can get the following information: Controller IP Address, Port Number, Connection Status, Connection Start Time, First Connection Established Time, Current Connection Established Time, Number of Connection Attempts, Number of Successful Connections, Number of Failed Connections. This API cannot be invoked on VPN Bridge. */\r\n this.GetFarmConnectionStatus = function () {\r\n return _this.CallAsync(\"GetFarmConnectionStatus\", new VpnRpcFarmConnectionStatus());\r\n };\r\n /** Set SSL Certificate and Private Key of VPN Server. You can set the SSL certificate that the VPN Server provides to the connected client and the private key for that certificate. The certificate must be in X.509 format and the private key must be Base 64 encoded format. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerCert = function (in_param) {\r\n return _this.CallAsync(\"SetServerCert\", in_param);\r\n };\r\n /** Get SSL Certificate and Private Key of VPN Server. Use this to get the SSL certificate private key that the VPN Server provides to the connected client. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetServerCert = function () {\r\n return _this.CallAsync(\"GetServerCert\", new VpnRpcKeyPair());\r\n };\r\n /** Get the Encrypted Algorithm Used for VPN Communication. Use this API to get the current setting of the algorithm used for the electronic signature and encrypted for SSL connection to be used for communication between the VPN Server and the connected client and the list of algorithms that can be used on the VPN Server. */\r\n this.GetServerCipher = function () {\r\n return _this.CallAsync(\"GetServerCipher\", new VpnRpcStr());\r\n };\r\n /** Set the Encrypted Algorithm Used for VPN Communication. Use this API to set the algorithm used for the electronic signature and encrypted for SSL connections to be used for communication between the VPN Server and the connected client. By specifying the algorithm name, the specified algorithm will be used later between the VPN Client and VPN Bridge connected to this server and the data will be encrypted. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerCipher = function (in_param) {\r\n return _this.CallAsync(\"SetServerCipher\", in_param);\r\n };\r\n /** Create New Virtual Hub. Use this to create a new Virtual Hub on the VPN Server. The created Virtual Hub will begin operation immediately. When the VPN Server is operating on a cluster, this API is only valid for the cluster controller. Also, the new Virtual Hub will operate as a dynamic Virtual Hub. You can change it to a static Virtual Hub by using the SetHub API. To get a list of Virtual Hubs that are already on the VPN Server, use the EnumHub API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Servers that are operating as a VPN Bridge or cluster member. */\r\n this.CreateHub = function (in_param) {\r\n return _this.CallAsync(\"CreateHub\", in_param);\r\n };\r\n /** Set the Virtual Hub configuration. You can call this API to change the configuration of the specified Virtual Hub. You can set the Virtual Hub online or offline. You can set the maximum number of sessions that can be concurrently connected to the Virtual Hub that is currently being managed. You can set the Virtual Hub administrator password. You can set other parameters for the Virtual Hub. Before call this API, you need to obtain the latest state of the Virtual Hub by using the GetHub API. */\r\n this.SetHub = function (in_param) {\r\n return _this.CallAsync(\"SetHub\", in_param);\r\n };\r\n /** Get the Virtual Hub configuration. You can call this API to get the current configuration of the specified Virtual Hub. To change the configuration of the Virtual Hub, call the SetHub API. */\r\n this.GetHub = function (in_param) {\r\n return _this.CallAsync(\"GetHub\", in_param);\r\n };\r\n /** Get List of Virtual Hubs. Use this to get a list of existing Virtual Hubs on the VPN Server. For each Virtual Hub, you can get the following information: Virtual Hub Name, Status, Type, Number of Users, Number of Groups, Number of Sessions, Number of MAC Tables, Number of IP Tables, Number of Logins, Last Login, and Last Communication. Note that when connecting in Virtual Hub Admin Mode, if in the options of a Virtual Hub that you do not have administrator privileges for, the option Don't Enumerate this Virtual Hub for Anonymous Users is enabled then that Virtual Hub will not be enumerated. If you are connected in Server Admin Mode, then the list of all Virtual Hubs will be displayed. When connecting to and managing a non-cluster-controller cluster member of a clustering environment, only the Virtual Hub currently being hosted by that VPN Server will be displayed. When connecting to a cluster controller for administration purposes, all the Virtual Hubs will be displayed. */\r\n this.EnumHub = function () {\r\n return _this.CallAsync(\"EnumHub\", new VpnRpcEnumHub());\r\n };\r\n /** Delete Virtual Hub. Use this to delete an existing Virtual Hub on the VPN Server. If you delete the Virtual Hub, all sessions that are currently connected to the Virtual Hub will be disconnected and new sessions will be unable to connect to the Virtual Hub. Also, this will also delete all the Hub settings, user objects, group objects, certificates and Cascade Connections. Once you delete the Virtual Hub, it cannot be recovered. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Servers that are operating as a VPN Bridge or cluster member. */\r\n this.DeleteHub = function (in_param) {\r\n return _this.CallAsync(\"DeleteHub\", in_param);\r\n };\r\n /** Get Setting of RADIUS Server Used for User Authentication. Use this to get the current settings for the RADIUS server used when a user connects to the currently managed Virtual Hub using RADIUS Server Authentication Mode. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetHubRadius = function (in_param) {\r\n return _this.CallAsync(\"GetHubRadius\", in_param);\r\n };\r\n /** Set RADIUS Server to use for User Authentication. To accept users to the currently managed Virtual Hub in RADIUS server authentication mode, you can specify an external RADIUS server that confirms the user name and password. (You can specify multiple hostname by splitting with comma or semicolon.) The RADIUS server must be set to receive requests from IP addresses of this VPN Server. Also, authentication by Password Authentication Protocol (PAP) must be enabled. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetHubRadius = function (in_param) {\r\n return _this.CallAsync(\"SetHubRadius\", in_param);\r\n };\r\n /** Get List of TCP Connections Connecting to the VPN Server. Use this to get a list of TCP/IP connections that are currently connecting to the VPN Server. It does not display the TCP connections that have been established as VPN sessions. To get the list of TCP/IP connections that have been established as VPN sessions, you can use the EnumSession API. You can get the following: Connection Name, Connection Source, Connection Start and Type. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumConnection = function () {\r\n return _this.CallAsync(\"EnumConnection\", new VpnRpcEnumConnection());\r\n };\r\n /** Disconnect TCP Connections Connecting to the VPN Server. Use this to forcefully disconnect specific TCP/IP connections that are connecting to the VPN Server. To call this API, you must have VPN Server administrator privileges. */\r\n this.DisconnectConnection = function (in_param) {\r\n return _this.CallAsync(\"DisconnectConnection\", in_param);\r\n };\r\n /** Get Information of TCP Connections Connecting to the VPN Server. Use this to get detailed information of a specific TCP/IP connection that is connecting to the VPN Server. You can get the following information: Connection Name, Connection Type, Source Hostname, Source IP Address, Source Port Number (TCP), Connection Start, Server Product Name, Server Version, Server Build Number, Client Product Name, Client Version, and Client Build Number. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetConnectionInfo = function (in_param) {\r\n return _this.CallAsync(\"GetConnectionInfo\", in_param);\r\n };\r\n /** Switch Virtual Hub to Online or Offline. Use this to set the Virtual Hub to online or offline. A Virtual Hub with an offline status cannot receive VPN connections from clients. When you set the Virtual Hub offline, all sessions will be disconnected. A Virtual Hub with an offline status cannot receive VPN connections from clients. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetHubOnline = function (in_param) {\r\n return _this.CallAsync(\"SetHubOnline\", in_param);\r\n };\r\n /** Get Current Status of Virtual Hub. Use this to get the current status of the Virtual Hub currently being managed. You can get the following information: Virtual Hub Type, Number of Sessions, Number of Each Type of Object, Number of Logins, Last Login, Last Communication, and Communication Statistical Data. */\r\n this.GetHubStatus = function (in_param) {\r\n return _this.CallAsync(\"GetHubStatus\", in_param);\r\n };\r\n /** Set the logging configuration of the Virtual Hub. Use this to enable or disable a security log or packet logs of the Virtual Hub currently being managed, set the save contents of the packet log for each type of packet to be saved, and set the log file switch cycle for the security log or packet log that the currently managed Virtual Hub saves. There are the following packet types: TCP Connection Log, TCP Packet Log, DHCP Packet Log, UDP Packet Log, ICMP Packet Log, IP Packet Log, ARP Packet Log, and Ethernet Packet Log. To get the current setting, you can use the LogGet API. The log file switch cycle can be changed to switch in every second, every minute, every hour, every day, every month or not switch. To get the current setting, you can use the GetHubLog API. */\r\n this.SetHubLog = function (in_param) {\r\n return _this.CallAsync(\"SetHubLog\", in_param);\r\n };\r\n /** Get the logging configuration of the Virtual Hub. Use this to get the configuration for a security log or packet logs of the Virtual Hub currently being managed, get the setting for save contents of the packet log for each type of packet to be saved, and get the log file switch cycle for the security log or packet log that the currently managed Virtual Hub saves. To set the current setting, you can use the SetHubLog API. */\r\n this.GetHubLog = function (in_param) {\r\n return _this.CallAsync(\"GetHubLog\", in_param);\r\n };\r\n /** Add Trusted CA Certificate. Use this to add a new certificate to a list of CA certificates trusted by the currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. To get a list of the current certificates you can use the EnumCa API. The certificate you add must be saved in the X.509 file format. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.AddCa = function (in_param) {\r\n return _this.CallAsync(\"AddCa\", in_param);\r\n };\r\n /** Get List of Trusted CA Certificates. Here you can manage the certificate authority certificates that are trusted by this currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumCa = function (in_param) {\r\n return _this.CallAsync(\"EnumCa\", in_param);\r\n };\r\n /** Get Trusted CA Certificate. Use this to get an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub and save it as a file in X.509 format. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetCa = function (in_param) {\r\n return _this.CallAsync(\"GetCa\", in_param);\r\n };\r\n /** Delete Trusted CA Certificate. Use this to delete an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub. To get a list of the current certificates you can use the EnumCa API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteCa = function (in_param) {\r\n return _this.CallAsync(\"DeleteCa\", in_param);\r\n };\r\n /** Create New Cascade Connection. Use this to create a new Cascade Connection on the currently managed Virtual Hub. By using a Cascade Connection, you can connect this Virtual Hub by Cascade Connection to another Virtual Hub that is operating on the same or a different computer. To create a Cascade Connection, you must specify the name of the Cascade Connection, destination server and destination Virtual Hub and user name. When a new Cascade Connection is created, the type of user authentication is initially set as Anonymous Authentication and the proxy server setting and the verification options of the server certificate is not set. To change these settings and other advanced settings after a Cascade Connection has been created, use the other APIs that include the name \"Link\". [Warning About Cascade Connections] By connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.CreateLink = function (in_param) {\r\n return _this.CallAsync(\"CreateLink\", in_param);\r\n };\r\n /** Get the Cascade Connection Setting. Use this to get the Connection Setting of a Cascade Connection that is registered on the currently managed Virtual Hub. To change the Connection Setting contents of the Cascade Connection, use the APIs that include the name \"Link\" after creating the Cascade Connection. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetLink = function (in_param) {\r\n return _this.CallAsync(\"GetLink\", in_param);\r\n };\r\n /** Change Existing Cascade Connection. Use this to alter the setting of an existing Cascade Connection on the currently managed Virtual Hub. */\r\n this.SetLink = function (in_param) {\r\n return _this.CallAsync(\"SetLink\", in_param);\r\n };\r\n /** Get List of Cascade Connections. Use this to get a list of Cascade Connections that are registered on the currently managed Virtual Hub. By using a Cascade Connection, you can connect this Virtual Hub by Layer 2 Cascade Connection to another Virtual Hub that is operating on the same or a different computer. [Warning About Cascade Connections] By connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumLink = function (in_param) {\r\n return _this.CallAsync(\"EnumLink\", in_param);\r\n };\r\n /** Switch Cascade Connection to Online Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to online status. The Cascade Connection that is switched to online status begins the process of connecting to the destination VPN Server in accordance with the Connection Setting. The Cascade Connection that is switched to online status will establish normal connection to the VPN Server or continue to attempt connection until it is switched to offline status. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetLinkOnline = function (in_param) {\r\n return _this.CallAsync(\"SetLinkOnline\", in_param);\r\n };\r\n /** Switch Cascade Connection to Offline Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to offline status. The Cascade Connection that is switched to offline will not connect to the VPN Server until next time it is switched to the online status using the SetLinkOnline API You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetLinkOffline = function (in_param) {\r\n return _this.CallAsync(\"SetLinkOffline\", in_param);\r\n };\r\n /** Delete Cascade Connection Setting. Use this to delete a Cascade Connection that is registered on the currently managed Virtual Hub. If the specified Cascade Connection has a status of online, the connections will be automatically disconnected and then the Cascade Connection will be deleted. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DeleteLink = function (in_param) {\r\n return _this.CallAsync(\"DeleteLink\", in_param);\r\n };\r\n /** Change Name of Cascade Connection. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to change the name of that Cascade Connection. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.RenameLink = function (in_param) {\r\n return _this.CallAsync(\"RenameLink\", in_param);\r\n };\r\n /** Get Current Cascade Connection Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is currently online, use this to get its connection status and other information. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetLinkStatus = function (in_param) {\r\n return _this.CallAsync(\"GetLinkStatus\", in_param);\r\n };\r\n /** Add Access List Rule. Use this to add a new rule to the access list of the currently managed Virtual Hub. The access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define an priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the access list to generate delays, jitters and packet losses. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.AddAccess = function (in_param) {\r\n return _this.CallAsync(\"AddAccess\", in_param);\r\n };\r\n /** Delete Rule from Access List. Use this to specify a packet filter rule registered on the access list of the currently managed Virtual Hub and delete it. To delete a rule, you must specify that rule's ID. You can display the ID by using the EnumAccess API. If you wish not to delete the rule but to only temporarily disable it, use the SetAccessList API to set the rule status to disable. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteAccess = function (in_param) {\r\n return _this.CallAsync(\"DeleteAccess\", in_param);\r\n };\r\n /** Get Access List Rule List. Use this to get a list of packet filter rules that are registered on access list of the currently managed Virtual Hub. The access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define a priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumAccess = function (in_param) {\r\n return _this.CallAsync(\"EnumAccess\", in_param);\r\n };\r\n /** Replace all access lists on a single bulk API call. This API removes all existing access list rules on the Virtual Hub, and replace them by new access list rules specified by the parameter. */\r\n this.SetAccessList = function (in_param) {\r\n return _this.CallAsync(\"SetAccessList\", in_param);\r\n };\r\n /** Create a user. Use this to create a new user in the security account database of the currently managed Virtual Hub. By creating a user, the VPN Client can connect to the Virtual Hub by using the authentication information of that user. Note that a user whose user name has been created as \"*\" (a single asterisk character) will automatically be registered as a RADIUS authentication user. For cases where there are users with \"*\" as the name, when a user, whose user name that has been provided when a client connected to a VPN Server does not match existing user names, is able to be authenticated by a RADIUS server or NT domain controller by inputting a user name and password, the authentication settings and security policy settings will follow the setting for the user \"*\". To change the user information of a user that has been created, use the SetUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.CreateUser = function (in_param) {\r\n return _this.CallAsync(\"CreateUser\", in_param);\r\n };\r\n /** Change User Settings. Use this to change user settings that is registered on the security account database of the currently managed Virtual Hub. The user settings that can be changed using this API are the three items that are specified when a new user is created using the CreateUser API: Group Name, Full Name, and Description. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.SetUser = function (in_param) {\r\n return _this.CallAsync(\"SetUser\", in_param);\r\n };\r\n /** Get User Settings. Use this to get user settings information that is registered on the security account database of the currently managed Virtual Hub. The information that you can get using this API are User Name, Full Name, Group Name, Expiration Date, Security Policy, and Auth Type, as well as parameters that are specified as auth type attributes and the statistical data of that user. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetUser = function (in_param) {\r\n return _this.CallAsync(\"GetUser\", in_param);\r\n };\r\n /** Delete a user. Use this to delete a user that is registered on the security account database of the currently managed Virtual Hub. By deleting the user, that user will no long be able to connect to the Virtual Hub. You can use the SetUser API to set the user's security policy to deny access instead of deleting a user, set the user to be temporarily denied from logging in. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteUser = function (in_param) {\r\n return _this.CallAsync(\"DeleteUser\", in_param);\r\n };\r\n /** Get List of Users. Use this to get a list of users that are registered on the security account database of the currently managed Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumUser = function (in_param) {\r\n return _this.CallAsync(\"EnumUser\", in_param);\r\n };\r\n /** Create Group. Use this to create a new group in the security account database of the currently managed Virtual Hub. You can register multiple users in a group. To register users in a group use the SetUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.CreateGroup = function (in_param) {\r\n return _this.CallAsync(\"CreateGroup\", in_param);\r\n };\r\n /** Set group settings. Use this to set group settings that is registered on the security account database of the currently managed Virtual Hub. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.SetGroup = function (in_param) {\r\n return _this.CallAsync(\"SetGroup\", in_param);\r\n };\r\n /** Get Group Setting (Sync mode). Use this to get the setting of a group that is registered on the security account database of the currently managed Virtual Hub. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetGroup = function (in_param) {\r\n return _this.CallAsync(\"GetGroup\", in_param);\r\n };\r\n /** Delete User from Group. Use this to delete a specified user from the group that is registered on the security account database of the currently managed Virtual Hub. By deleting a user from the group, that user becomes unassigned. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteGroup = function (in_param) {\r\n return _this.CallAsync(\"DeleteGroup\", in_param);\r\n };\r\n /** Get List of Groups. Use this to get a list of groups that are registered on the security account database of the currently managed Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumGroup = function (in_param) {\r\n return _this.CallAsync(\"EnumGroup\", in_param);\r\n };\r\n /** Get List of Connected VPN Sessions. Use this to get a list of the sessions connected to the Virtual Hub currently being managed. In the list of sessions, the following information will be obtained for each connection: Session Name, Session Site, User Name, Source Host Name, TCP Connection, Transfer Bytes and Transfer Packets. If the currently connected VPN Server is a cluster controller and the currently managed Virtual Hub is a static Virtual Hub, you can get an all-linked-together list of all sessions connected to that Virtual Hub on all cluster members. In all other cases, only the list of sessions that are actually connected to the currently managed VPN Server will be obtained. */\r\n this.EnumSession = function (in_param) {\r\n return _this.CallAsync(\"EnumSession\", in_param);\r\n };\r\n /** Get Session Status. Use this to specify a session currently connected to the currently managed Virtual Hub and get the session information. The session status includes the following: source host name and user name, version information, time information, number of TCP connections, communication parameters, session key, statistical information on data transferred, and other client and server information. To get the list of currently connected sessions, use the EnumSession API. */\r\n this.GetSessionStatus = function (in_param) {\r\n return _this.CallAsync(\"GetSessionStatus\", in_param);\r\n };\r\n /** Disconnect Session. Use this to specify a session currently connected to the currently managed Virtual Hub and forcefully disconnect that session using manager privileges. Note that when communication is disconnected by settings on the source client side and the automatically reconnect option is enabled, it is possible that the client will reconnect. To get the list of currently connected sessions, use the EnumSession API. */\r\n this.DeleteSession = function (in_param) {\r\n return _this.CallAsync(\"DeleteSession\", in_param);\r\n };\r\n /** Get the MAC Address Table Database. Use this to get the MAC address table database that is held by the currently managed Virtual Hub. The MAC address table database is a table that the Virtual Hub requires to perform the action of switching Ethernet frames and the Virtual Hub decides the sorting destination session of each Ethernet frame based on the MAC address table database. The MAC address database is built by the Virtual Hub automatically analyzing the contents of the communication. */\r\n this.EnumMacTable = function (in_param) {\r\n return _this.CallAsync(\"EnumMacTable\", in_param);\r\n };\r\n /** Delete MAC Address Table Entry. Use this API to operate the MAC address table database held by the currently managed Virtual Hub and delete a specified MAC address table entry from the database. To get the contents of the current MAC address table database use the EnumMacTable API. */\r\n this.DeleteMacTable = function (in_param) {\r\n return _this.CallAsync(\"DeleteMacTable\", in_param);\r\n };\r\n /** Get the IP Address Table Database. Use this to get the IP address table database that is held by the currently managed Virtual Hub. The IP address table database is a table that is automatically generated by analyzing the contents of communication so that the Virtual Hub can always know which session is using which IP address and it is frequently used by the engine that applies the Virtual Hub security policy. By specifying the session name you can get the IP address table entry that has been associated with that session. */\r\n this.EnumIpTable = function (in_param) {\r\n return _this.CallAsync(\"EnumIpTable\", in_param);\r\n };\r\n /** Delete IP Address Table Entry. Use this API to operate the IP address table database held by the currently managed Virtual Hub and delete a specified IP address table entry from the database. To get the contents of the current IP address table database use the EnumIpTable API. */\r\n this.DeleteIpTable = function (in_param) {\r\n return _this.CallAsync(\"DeleteIpTable\", in_param);\r\n };\r\n /** Set the Keep Alive Internet Connection Function. Use this to set the destination host name etc. of the Keep Alive Internet Connection Function. For network connection environments where connections will automatically be disconnected where there are periods of no communication that are longer than a set period, by using the Keep Alive Internet Connection Function, it is possible to keep alive the Internet connection by sending packets to a nominated server on the Internet at set intervals. When using this API, you can specify the following: Host Name, Port Number, Packet Send Interval, and Protocol. Packets sent to keep alive the Internet connection will have random content and personal information that could identify a computer or user is not sent. You can use the SetKeep API to enable/disable the Keep Alive Internet Connection Function. To execute this API on a VPN Server or VPN Bridge, you must have administrator privileges. */\r\n this.SetKeep = function (in_param) {\r\n return _this.CallAsync(\"SetKeep\", in_param);\r\n };\r\n /** Get the Keep Alive Internet Connection Function. Use this to get the current setting contents of the Keep Alive Internet Connection Function. In addition to the destination's Host Name, Port Number, Packet Send Interval and Protocol, you can obtain the current enabled/disabled status of the Keep Alive Internet Connection Function. */\r\n this.GetKeep = function (in_param) {\r\n return _this.CallAsync(\"GetKeep\", in_param);\r\n };\r\n /** Enable the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to enable the Virtual NAT and DHCP Server function (SecureNAT Function) on the currently managed Virtual Hub and begin its operation. Before executing this API, you must first check the setting contents of the current Virtual NAT function and DHCP Server function using the SetSecureNATOption API and GetSecureNATOption API. By enabling the SecureNAT function, you can virtually operate a NAT router (IP masquerade) and the DHCP Server function on a virtual network on the Virtual Hub. [Warning about SecureNAT Function] The SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. If you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrator's permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnableSecureNAT = function (in_param) {\r\n return _this.CallAsync(\"EnableSecureNAT\", in_param);\r\n };\r\n /** Disable the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to disable the Virtual NAT and DHCP Server function (SecureNAT Function) on the currently managed Virtual Hub. By executing this API the Virtual NAT function immediately stops operating and the Virtual DHCP Server function deletes the DHCP lease database and stops the service. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DisableSecureNAT = function (in_param) {\r\n return _this.CallAsync(\"DisableSecureNAT\", in_param);\r\n };\r\n /** Change Settings of SecureNAT Function. Use this to change and save the virtual host network interface settings, virtual NAT function settings and virtual DHCP server settings of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. The SecureNAT function holds one virtual network adapter on the L2 segment inside the Virtual Hub and it has been assigned a MAC address and an IP address. By doing this, another host connected to the same L2 segment is able to communicate with the SecureNAT virtual host as if it is an actual IP host existing on the network. [Warning about SecureNAT Function] The SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. If you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrators permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetSecureNATOption = function (in_param) {\r\n return _this.CallAsync(\"SetSecureNATOption\", in_param);\r\n };\r\n /** Get Settings of SecureNAT Function. This API get the registered settings for the SecureNAT function which is set by the SetSecureNATOption API. */\r\n this.GetSecureNATOption = function (in_param) {\r\n return _this.CallAsync(\"GetSecureNATOption\", in_param);\r\n };\r\n /** Get Virtual NAT Function Session Table of SecureNAT Function. Use this to get the table of TCP and UDP sessions currently communicating via the Virtual NAT (NAT table) in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumNAT = function (in_param) {\r\n return _this.CallAsync(\"EnumNAT\", in_param);\r\n };\r\n /** Get Virtual DHCP Server Function Lease Table of SecureNAT Function. Use this to get the lease table of IP addresses, held by the Virtual DHCP Server, that are assigned to clients in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumDHCP = function (in_param) {\r\n return _this.CallAsync(\"EnumDHCP\", in_param);\r\n };\r\n /** Get the Operating Status of the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to get the operating status of the Virtual NAT and DHCP Server function (SecureNAT Function) when it is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetSecureNATStatus = function (in_param) {\r\n return _this.CallAsync(\"GetSecureNATStatus\", in_param);\r\n };\r\n /** Get List of Network Adapters Usable as Local Bridge. Use this to get a list of Ethernet devices (network adapters) that can be used as a bridge destination device as part of a Local Bridge connection. If possible, network connection name is displayed. You can use a device displayed here by using the AddLocalBridge API. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumEthernet = function () {\r\n return _this.CallAsync(\"EnumEthernet\", new VpnRpcEnumEth());\r\n };\r\n /** Create Local Bridge Connection. Use this to create a new Local Bridge connection on the VPN Server. By using a Local Bridge, you can configure a Layer 2 bridge connection between a Virtual Hub operating on this VPN server and a physical Ethernet Device (Network Adapter). You can create a tap device (virtual network interface) on the system and connect a bridge between Virtual Hubs (the tap device is only supported by Linux versions). It is possible to establish a bridge to an operating network adapter of your choice for the bridge destination Ethernet device (network adapter), but in high load environments, we recommend you prepare a network adapter dedicated to serve as a bridge. To call this API, you must have VPN Server administrator privileges. */\r\n this.AddLocalBridge = function (in_param) {\r\n return _this.CallAsync(\"AddLocalBridge\", in_param);\r\n };\r\n /** Delete Local Bridge Connection. Use this to delete an existing Local Bridge connection. To get a list of current Local Bridge connections use the EnumLocalBridge API. To call this API, you must have VPN Server administrator privileges. */\r\n this.DeleteLocalBridge = function (in_param) {\r\n return _this.CallAsync(\"DeleteLocalBridge\", in_param);\r\n };\r\n /** Get List of Local Bridge Connection. Use this to get a list of the currently defined Local Bridge connections. You can get the Local Bridge connection Virtual Hub name and the bridge destination Ethernet device (network adapter) name or tap device name, as well as the operating status. */\r\n this.EnumLocalBridge = function () {\r\n return _this.CallAsync(\"EnumLocalBridge\", new VpnRpcEnumLocalBridge());\r\n };\r\n /** Get whether the localbridge function is supported on the current system. */\r\n this.GetBridgeSupport = function () {\r\n return _this.CallAsync(\"GetBridgeSupport\", new VpnRpcBridgeSupport());\r\n };\r\n /** Reboot VPN Server Service. Use this to restart the VPN Server service. When you restart the VPN Server, all currently connected sessions and TCP connections will be disconnected and no new connections will be accepted until the restart process has completed. By using this API, only the VPN Server service program will be restarted and the physical computer that VPN Server is operating on does not restart. This management session will also be disconnected, so you will need to reconnect to continue management. Also, by specifying the \"IntValue\" parameter to \"1\", the contents of the configuration file (.config) held by the current VPN Server will be initialized. To call this API, you must have VPN Server administrator privileges. */\r\n this.RebootServer = function (in_param) {\r\n return _this.CallAsync(\"RebootServer\", in_param);\r\n };\r\n /** Get List of Server Functions / Capability. Use this get a list of functions and capability of the VPN Server currently connected and being managed. The function and capability of VPN Servers are different depending on the operating VPN server's edition and version. Using this API, you can find out the capability of the target VPN Server and report it. */\r\n this.GetCaps = function () {\r\n return _this.CallAsync(\"GetCaps\", new VpnCapslist());\r\n };\r\n /** Get the current configuration of the VPN Server. Use this to get a text file (.config file) that contains the current configuration contents of the VPN server. You can get the status on the VPN Server at the instant this API is executed. You can edit the configuration file by using a regular text editor. To write an edited configuration to the VPN Server, use the SetConfig API. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetConfig = function () {\r\n return _this.CallAsync(\"GetConfig\", new VpnRpcConfig());\r\n };\r\n /** Write Configuration File to VPN Server. Use this to write the configuration file to the VPN Server. By executing this API, the contents of the specified configuration file will be applied to the VPN Server and the VPN Server program will automatically restart and upon restart, operate according to the new configuration contents. Because it is difficult for an administrator to write all the contents of a configuration file, we recommend you use the GetConfig API to get the current contents of the VPN Server configuration and save it to file. You can then edit these contents in a regular text editor and then use the SetConfig API to rewrite the contents to the VPN Server. This API is for people with a detailed knowledge of the VPN Server and if an incorrectly configured configuration file is written to the VPN Server, it not only could cause errors, it could also result in the lost of the current setting data. Take special care when carrying out this action. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetConfig = function (in_param) {\r\n return _this.CallAsync(\"SetConfig\", in_param);\r\n };\r\n /** Get Virtual Hub Administration Option default values. */\r\n this.GetDefaultHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"GetDefaultHubAdminOptions\", in_param);\r\n };\r\n /** Get List of Virtual Hub Administration Options. Use this to get a list of Virtual Hub administration options that are set on the currently managed Virtual Hub. The purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. Only an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. There is an exception however. If allow_hub_admin_change_option is set to \"1\", even Virtual Hub administrators are able to edit the administration options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.GetHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"GetHubAdminOptions\", in_param);\r\n };\r\n /** Set Values of Virtual Hub Administration Options. Use this to change the values of Virtual Hub administration options that are set on the currently managed Virtual Hub. The purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. Only an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. There is an exception however. If allow_hub_admin_change_option is set to \"1\", even Virtual Hub administrators are able to edit the administration options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.SetHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"SetHubAdminOptions\", in_param);\r\n };\r\n /** Get List of Virtual Hub Extended Options. Use this to get a Virtual Hub Extended Options List that is set on the currently managed Virtual Hub. Virtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub. By default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options. However, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.GetHubExtOptions = function (in_param) {\r\n return _this.CallAsync(\"GetHubExtOptions\", in_param);\r\n };\r\n /** Set a Value of Virtual Hub Extended Options. Use this to set a value in the Virtual Hub Extended Options List that is set on the currently managed Virtual Hub. Virtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub. By default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options. However, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.SetHubExtOptions = function (in_param) {\r\n return _this.CallAsync(\"SetHubExtOptions\", in_param);\r\n };\r\n /** Define New Virtual Layer 3 Switch. Use this to define a new Virtual Layer 3 Switch on the VPN Server. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.AddL3Switch = function (in_param) {\r\n return _this.CallAsync(\"AddL3Switch\", in_param);\r\n };\r\n /** Delete Virtual Layer 3 Switch. Use this to delete an existing Virtual Layer 3 Switch that is defined on the VPN Server. When the specified Virtual Layer 3 Switch is operating, it will be automatically deleted after operation stops. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.DelL3Switch = function (in_param) {\r\n return _this.CallAsync(\"DelL3Switch\", in_param);\r\n };\r\n /** Get List of Virtual Layer 3 Switches. Use this to define a new Virtual Layer 3 Switch on the VPN Server. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.EnumL3Switch = function () {\r\n return _this.CallAsync(\"EnumL3Switch\", new VpnRpcEnumL3Sw());\r\n };\r\n /** Start Virtual Layer 3 Switch Operation. Use this to start the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently stopped. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.StartL3Switch = function (in_param) {\r\n return _this.CallAsync(\"StartL3Switch\", in_param);\r\n };\r\n /** Stop Virtual Layer 3 Switch Operation. Use this to stop the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently operating. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. */\r\n this.StopL3Switch = function (in_param) {\r\n return _this.CallAsync(\"StopL3Switch\", in_param);\r\n };\r\n /** Add Virtual Interface to Virtual Layer 3 Switch. Use this to add to a specified Virtual Layer 3 Switch, a virtual interface that connects to a Virtual Hub operating on the same VPN Server. You can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. A virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. You must define the IP network space that the virtual interface belongs to and the IP address of the interface itself. Also, you must specify the name of the Virtual Hub that the interface will connect to. You can specify a Virtual Hub that currently doesn't exist for the Virtual Hub name. The virtual interface must have one IP address in the Virtual Hub. You also must specify the subnet mask of an IP network that the IP address belongs to. Routing via the Virtual Layer 3 Switches of IP spaces of multiple virtual Hubs operates based on the IP address is specified here. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.AddL3If = function (in_param) {\r\n return _this.CallAsync(\"AddL3If\", in_param);\r\n };\r\n /** Delete Virtual Interface of Virtual Layer 3 Switch. Use this to delete a virtual interface already defined in the specified Virtual Layer 3 Switch. You can get a list of the virtual interfaces currently defined, by using the EnumL3If API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.DelL3If = function (in_param) {\r\n return _this.CallAsync(\"DelL3If\", in_param);\r\n };\r\n /** Get List of Interfaces Registered on the Virtual Layer 3 Switch. Use this to get a list of virtual interfaces when virtual interfaces have been defined on a specified Virtual Layer 3 Switch. You can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. A virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.EnumL3If = function (in_param) {\r\n return _this.CallAsync(\"EnumL3If\", in_param);\r\n };\r\n /** Add Routing Table Entry for Virtual Layer 3 Switch. Here you can add a new routing table entry to the routing table of the specified Virtual Layer 3 Switch. If the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference the routing table and execute routing. You must specify the contents of the routing table entry to be added to the Virtual Layer 3 Switch. You must specify any IP address that belongs to the same IP network in the virtual interface of this Virtual Layer 3 Switch as the gateway address. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.AddL3Table = function (in_param) {\r\n return _this.CallAsync(\"AddL3Table\", in_param);\r\n };\r\n /** Delete Routing Table Entry of Virtual Layer 3 Switch. Use this to delete a routing table entry that is defined in the specified Virtual Layer 3 Switch. You can get a list of the already defined routing table entries by using the EnumL3Table API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.DelL3Table = function (in_param) {\r\n return _this.CallAsync(\"DelL3Table\", in_param);\r\n };\r\n /** Get List of Routing Tables of Virtual Layer 3 Switch. Use this to get a list of routing tables when routing tables have been defined on a specified Virtual Layer 3 Switch. If the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference this routing table and execute routing. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.EnumL3Table = function (in_param) {\r\n return _this.CallAsync(\"EnumL3Table\", in_param);\r\n };\r\n /** Get List of Certificates Revocation List. Use this to get a Certificates Revocation List that is set on the currently managed Virtual Hub. By registering certificates in the Certificates Revocation List, the clients who provide these certificates will be unable to connect to this Virtual Hub using certificate authentication mode. Normally with this function, in cases where the security of a private key has been compromised or where a person holding a certificate has been stripped of their privileges, by registering that certificate as invalid on the Virtual Hub, it is possible to deny user authentication when that certificate is used by a client to connect to the Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumCrl = function (in_param) {\r\n return _this.CallAsync(\"EnumCrl\", in_param);\r\n };\r\n /** Add a Revoked Certificate. Use this to add a new revoked certificate definition in the Certificate Revocation List that is set on the currently managed Virtual Hub. Specify the contents to be registered in the Certificate Revocation List by using the parameters of this API. When a user connects to a Virtual Hub in certificate authentication mode and that certificate matches 1 or more of the contents registered in the certificates revocation list, the user is denied connection. A certificate that matches all the conditions that are defined by the parameters specified by this API will be judged as invalid. The items that can be set are as follows: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number (hexadecimal), MD5 Digest Value (hexadecimal, 128 bit), and SHA-1 Digest Value (hexadecimal, 160 bit). For the specification of a digest value (hash value) a certificate is optionally specified depending on the circumstances. Normally when a MD5 or SHA-1 digest value is input, it is not necessary to input the other items. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.AddCrl = function (in_param) {\r\n return _this.CallAsync(\"AddCrl\", in_param);\r\n };\r\n /** Delete a Revoked Certificate. Use this to specify and delete a revoked certificate definition from the certificate revocation list that is set on the currently managed Virtual Hub. To get the list of currently registered revoked certificate definitions, use the EnumCrl API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DelCrl = function (in_param) {\r\n return _this.CallAsync(\"DelCrl\", in_param);\r\n };\r\n /** Get a Revoked Certificate. Use this to specify and get the contents of a revoked certificate definition from the Certificates Revocation List that is set on the currently managed Virtual Hub. To get the list of currently registered revoked certificate definitions, use the EnumCrl API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetCrl = function (in_param) {\r\n return _this.CallAsync(\"GetCrl\", in_param);\r\n };\r\n /** Change Existing CRL (Certificate Revocation List) Entry. Use this to alter an existing revoked certificate definition in the Certificate Revocation List that is set on the currently managed Virtual Hub. Specify the contents to be registered in the Certificate Revocation List by using the parameters of this API. When a user connects to a Virtual Hub in certificate authentication mode and that certificate matches 1 or more of the contents registered in the certificates revocation list, the user is denied connection. A certificate that matches all the conditions that are defined by the parameters specified by this API will be judged as invalid. The items that can be set are as follows: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number (hexadecimal), MD5 Digest Value (hexadecimal, 128 bit), and SHA-1 Digest Value (hexadecimal, 160 bit). For the specification of a digest value (hash value) a certificate is optionally specified depending on the circumstances. Normally when a MD5 or SHA-1 digest value is input, it is not necessary to input the other items. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetCrl = function (in_param) {\r\n return _this.CallAsync(\"SetCrl\", in_param);\r\n };\r\n /** Add Rule to Source IP Address Limit List. Use this to add a new rule to the Source IP Address Limit List that is set on the currently managed Virtual Hub. The items set here will be used to decide whether to allow or deny connection from a VPN Client when this client attempts connection to the Virtual Hub. You can specify a client IP address, or IP address or mask to match the rule as the contents of the rule item. By specifying an IP address only, there will only be one specified computer that will match the rule, but by specifying an IP net mask address or subnet mask address, all the computers in the range of that subnet will match the rule. You can specify the priority for the rule. You can specify an integer of 1 or greater for the priority and the smaller the number, the higher the priority. To get a list of the currently registered Source IP Address Limit List, use the GetAcList API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetAcList = function (in_param) {\r\n return _this.CallAsync(\"SetAcList\", in_param);\r\n };\r\n /** Get List of Rule Items of Source IP Address Limit List. Use this to get a list of Source IP Address Limit List rules that is set on the currently managed Virtual Hub. You can allow or deny VPN connections to this Virtual Hub according to the client computer's source IP address. You can define multiple rules and set a priority for each rule. The search proceeds from the rule with the highest order or priority and based on the action of the rule that the IP address first matches, the connection from the client is either allowed or denied. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetAcList = function (in_param) {\r\n return _this.CallAsync(\"GetAcList\", in_param);\r\n };\r\n /** Get List of Log Files. Use this to display a list of log files outputted by the VPN Server that have been saved on the VPN Server computer. By specifying a log file file name displayed here and calling it using the ReadLogFile API you can download the contents of the log file. If you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. When connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management. */\r\n this.EnumLogFile = function () {\r\n return _this.CallAsync(\"EnumLogFile\", new VpnRpcEnumLogFile());\r\n };\r\n /** Download a part of Log File. Use this to download the log file that is saved on the VPN Server computer. To download the log file first get the list of log files using the EnumLogFile API and then download the log file using the ReadLogFile API. If you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. When connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management. */\r\n this.ReadLogFile = function (in_param) {\r\n return _this.CallAsync(\"ReadLogFile\", in_param);\r\n };\r\n /** Set syslog Send Function. Use this to set the usage of syslog send function and which syslog server to use. */\r\n this.SetSysLog = function (in_param) {\r\n return _this.CallAsync(\"SetSysLog\", in_param);\r\n };\r\n /** Get syslog Send Function. This allows you to get the current setting contents of the syslog send function. You can get the usage setting of the syslog function and the host name and port number of the syslog server to use. */\r\n this.GetSysLog = function (in_param) {\r\n return _this.CallAsync(\"GetSysLog\", in_param);\r\n };\r\n /** Set Today's Message of Virtual Hub. The message will be displayed on VPN Client UI when a user will establish a connection to the Virtual Hub. */\r\n this.SetHubMsg = function (in_param) {\r\n return _this.CallAsync(\"SetHubMsg\", in_param);\r\n };\r\n /** Get Today's Message of Virtual Hub. The message will be displayed on VPN Client UI when a user will establish a connection to the Virtual Hub. */\r\n this.GetHubMsg = function (in_param) {\r\n return _this.CallAsync(\"GetHubMsg\", in_param);\r\n };\r\n /** Raise a vital error on the VPN Server / Bridge to terminate the process forcefully. This API will raise a fatal error (memory access violation) on the VPN Server / Bridge running process in order to crash the process. As the result, VPN Server / Bridge will be terminated and restarted if it is running as a service mode. If the VPN Server is running as a user mode, the process will not automatically restarted. This API is for a situation when the VPN Server / Bridge is under a non-recoverable error or the process is in an infinite loop. This API will disconnect all VPN Sessions on the VPN Server / Bridge. All unsaved settings in the memory of VPN Server / Bridge will be lost. Before run this API, call the Flush API to try to save volatile data to the configuration file. To execute this API, you must have VPN Server / VPN Bridge administrator privileges. */\r\n this.Crash = function (in_param) {\r\n return _this.CallAsync(\"Crash\", in_param);\r\n };\r\n /** Get the message for administrators. */\r\n this.GetAdminMsg = function () {\r\n return _this.CallAsync(\"GetAdminMsg\", new VpnRpcMsg());\r\n };\r\n /** Save All Volatile Data of VPN Server / Bridge to the Configuration File. The number of configuration file bytes will be returned as the \"IntValue\" parameter. Normally, the VPN Server / VPN Bridge retains the volatile configuration data in memory. It is flushed to the disk as vpn_server.config or vpn_bridge.config periodically. The period is 300 seconds (5 minutes) by default. (The period can be altered by modifying the AutoSaveConfigSpan item in the configuration file.) The data will be saved on the timing of shutting down normally of the VPN Server / Bridge. Execute the Flush API to make the VPN Server / Bridge save the settings to the file immediately. The setting data will be stored on the disk drive of the server computer. Use the Flush API in a situation that you do not have an enough time to shut down the server process normally. To call this API, you must have VPN Server administrator privileges. To execute this API, you must have VPN Server / VPN Bridge administrator privileges. */\r\n this.Flush = function (in_param) {\r\n return _this.CallAsync(\"Flush\", in_param);\r\n };\r\n /** Enable or Disable IPsec VPN Server Function. Enable or Disable IPsec VPN Server Function on the VPN Server. If you enable this function, Virtual Hubs on the VPN Server will be able to accept Remote-Access VPN connections from L2TP-compatible PCs, Mac OS X and Smartphones, and also can accept EtherIP Site-to-Site VPN Connection. VPN Connections from Smartphones suchlike iPhone, iPad and Android, and also from native VPN Clients on Mac OS X and Windows can be accepted. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetIPsecServices = function (in_param) {\r\n return _this.CallAsync(\"SetIPsecServices\", in_param);\r\n };\r\n /** Get the Current IPsec VPN Server Settings. Get and view the current IPsec VPN Server settings on the VPN Server. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetIPsecServices = function () {\r\n return _this.CallAsync(\"GetIPsecServices\", new VpnIPsecServices());\r\n };\r\n /** Add New EtherIP / L2TPv3 over IPsec Client Setting to Accept EthreIP / L2TPv3 Client Devices. Add a new setting entry to enable the EtherIP / L2TPv3 over IPsec Server Function to accept client devices. In order to accept connections from routers by the EtherIP / L2TPv3 over IPsec Server Function, you have to define the relation table between an IPsec Phase 1 string which is presented by client devices of EtherIP / L2TPv3 over IPsec compatible router, and the designation of the destination Virtual Hub. After you add a definition entry by AddEtherIpId API, the defined connection setting to the Virtual Hub will be applied on the login-attepting session from an EtherIP / L2TPv3 over IPsec client device. The username and password in an entry must be registered on the Virtual Hub. An EtherIP / L2TPv3 client will be regarded as it connected the Virtual HUB with the identification of the above user information. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.AddEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"AddEtherIpId\", in_param);\r\n };\r\n /** Get the Current List of EtherIP / L2TPv3 Client Device Entry Definitions. This API gets and shows the list of entries to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"GetEtherIpId\", in_param);\r\n };\r\n /** Delete an EtherIP / L2TPv3 over IPsec Client Setting. This API deletes an entry to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DeleteEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"DeleteEtherIpId\", in_param);\r\n };\r\n /** Get the Current List of EtherIP / L2TPv3 Client Device Entry Definitions. This API gets and shows the list of entries to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumEtherIpId = function () {\r\n return _this.CallAsync(\"EnumEtherIpId\", new VpnRpcEnumEtherIpId());\r\n };\r\n /** Set Settings for OpenVPN Clone Server Function. The VPN Server has the clone functions of OpenVPN software products by OpenVPN Technologies, Inc. Any OpenVPN Clients can connect to this VPN Server. The manner to specify a username to connect to the Virtual Hub, and the selection rule of default Hub by using this clone server functions are same to the IPsec Server functions. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetOpenVpnSstpConfig = function (in_param) {\r\n return _this.CallAsync(\"SetOpenVpnSstpConfig\", in_param);\r\n };\r\n /** Get the Current Settings of OpenVPN Clone Server Function. Get and show the current settings of OpenVPN Clone Server Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetOpenVpnSstpConfig = function () {\r\n return _this.CallAsync(\"GetOpenVpnSstpConfig\", new VpnOpenVpnSstpConfig());\r\n };\r\n /** Show the Current Status of Dynamic DNS Function. Get and show the current status of the Dynamic DNS function. The Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name. Also, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address. Therefore, you need not any longer to keep static global IP addresses with expenses monthly costs. [Caution] To disable the Dynamic DNS Function, modify the configuration file of VPN Server. The \"declare root\" directive has the \"declare DDnsClient\" directive. In this directive, you can switch \"bool Disable\" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.GetDDnsClientStatus = function () {\r\n return _this.CallAsync(\"GetDDnsClientStatus\", new VpnDDnsClientStatus());\r\n };\r\n /** Set the Dynamic DNS Hostname. You must specify the new hostname on the StrValue_str field. You can use this API to change the hostname assigned by the Dynamic DNS function. The currently assigned hostname can be showen by the GetDDnsClientStatus API. The Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name. Also, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address. Therefore, you need not any longer to keep static global IP addresses with expenses monthly costs. [Caution] To disable the Dynamic DNS Function, modify the configuration file of VPN Server. The \"declare root\" directive has the \"declare DDnsClient\" directive. In this directive, you can switch \"bool Disable\" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.ChangeDDnsClientHostname = function (in_param) {\r\n return _this.CallAsync(\"ChangeDDnsClientHostname\", in_param);\r\n };\r\n /** Generate New Self-Signed Certificate with Specified CN (Common Name) and Register on VPN Server. You can specify the new CN (common name) value on the StrValue_str field. You can use this API to replace the current certificate on the VPN Server to a new self-signed certificate which has the CN (Common Name) value in the fields. This API is convenient if you are planning to use Microsoft SSTP VPN Clone Server Function. Because of the value of CN (Common Name) on the SSL certificate of VPN Server must match to the hostname specified on the SSTP VPN client. This API will delete the existing SSL certificate of the VPN Server. It is recommended to backup the current SSL certificate and private key by using the GetServerCert API beforehand. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.RegenerateServerCert = function (in_param) {\r\n return _this.CallAsync(\"RegenerateServerCert\", in_param);\r\n };\r\n /** Generate a Sample Setting File for OpenVPN Client. Originally, the OpenVPN Client requires a user to write a very difficult configuration file manually. This API helps you to make a useful configuration sample. What you need to generate the configuration file for the OpenVPN Client is to run this API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.MakeOpenVpnConfigFile = function () {\r\n return _this.CallAsync(\"MakeOpenVpnConfigFile\", new VpnRpcReadLogFile());\r\n };\r\n /** Enable / Disable the VPN over ICMP / VPN over DNS Server Function. You can establish a VPN only with ICMP or DNS packets even if there is a firewall or routers which blocks TCP/IP communications. You have to enable the following functions beforehand. Warning: Use this function for emergency only. It is helpful when a firewall or router is misconfigured to blocks TCP/IP, but either ICMP or DNS is not blocked. It is not for long-term stable using. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.SetSpecialListener = function (in_param) {\r\n return _this.CallAsync(\"SetSpecialListener\", in_param);\r\n };\r\n /** Get Current Setting of the VPN over ICMP / VPN over DNS Function. Get and show the current VPN over ICMP / VPN over DNS Function status. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.GetSpecialListener = function () {\r\n return _this.CallAsync(\"GetSpecialListener\", new VpnRpcSpecialListener());\r\n };\r\n /** Show the current status of VPN Azure function. Get and show the current status of the VPN Azure function. VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company. You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC. VPN Azure is a cloud VPN service operated by SoftEther Corporation. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions. The VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to \"vpnazure.net\". To change the hostname use the ChangeDDnsClientHostname API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetAzureStatus = function () {\r\n return _this.CallAsync(\"GetAzureStatus\", new VpnRpcAzureStatus());\r\n };\r\n /** Enable / Disable VPN Azure Function. Enable or disable the VPN Azure function. VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company. You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC. VPN Azure is a cloud VPN service operated by SoftEther Corporation. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions. The VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to \"vpnazure.net\". To change the hostname use the ChangeDDnsClientHostname API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetAzureStatus = function (in_param) {\r\n return _this.CallAsync(\"SetAzureStatus\", in_param);\r\n };\r\n /** Get the Proxy Settings for Connecting to the DDNS server. */\r\n this.GetDDnsInternetSettng = function () {\r\n return _this.CallAsync(\"GetDDnsInternetSettng\", new VpnInternetSetting());\r\n };\r\n /** Set the Proxy Settings for Connecting to the DDNS server. */\r\n this.SetDDnsInternetSettng = function (in_param) {\r\n return _this.CallAsync(\"SetDDnsInternetSettng\", in_param);\r\n };\r\n /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */\r\n this.SetVgsConfig = function (in_param) {\r\n return _this.CallAsync(\"SetVgsConfig\", in_param);\r\n };\r\n /** Get the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */\r\n this.GetVgsConfig = function () {\r\n return _this.CallAsync(\"GetVgsConfig\", new VpnVgsConfig());\r\n };\r\n var headers = {};\r\n var send_credentials = false;\r\n nodejs_https_client_reject_untrusted_server_cert = is_null(nodejs_https_client_reject_untrusted_server_cert) ? false : nodejs_https_client_reject_untrusted_server_cert;\r\n if (is_null(vpnserver_hostname)) {\r\n this.rpc_url = \"/api/\";\r\n send_credentials = true;\r\n }\r\n else {\r\n if (is_null(vpnserver_port))\r\n vpnserver_port = 443;\r\n this.rpc_url = \"https://\" + vpnserver_hostname + \":\" + vpnserver_port + \"/api/\";\r\n headers[\"X-VPNADMIN-HUBNAME\"] = is_null(hubname) ? \"\" : hubname;\r\n headers[\"X-VPNADMIN-PASSWORD\"] = is_null(password) ? \"\" : password;\r\n }\r\n if (is_null(nodejs_https_client_reject_untrusted_server_cert))\r\n nodejs_https_client_reject_untrusted_server_cert = false;\r\n this.rpc_client = new JsonRpcClient(this.rpc_url, headers, send_credentials, nodejs_https_client_reject_untrusted_server_cert);\r\n }\r\n /** Determine if this JavaScript environment is on the Node.js or not. */\r\n VpnServerRpc.IsNodeJS = function () {\r\n return is_node_js;\r\n };\r\n /** Set the debug mode flag */\r\n VpnServerRpc.SetDebugMode = function (flag) {\r\n debug_mode = flag;\r\n };\r\n // -- Utility functions --\r\n /** Call a RPC procedure */\r\n VpnServerRpc.prototype.CallAsync = function (method_name, request) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var response;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0: return [4 /*yield*/, this.rpc_client.CallAsync(method_name, request)];\r\n case 1:\r\n response = _a.sent();\r\n return [2 /*return*/, response];\r\n }\r\n });\r\n });\r\n };\r\n return VpnServerRpc;\r\n}());\r\nexports.VpnServerRpc = VpnServerRpc;\r\n// --- Types ---\r\n/** IP Protocol Numbers */\r\nvar VpnIpProtocolNumber;\r\n(function (VpnIpProtocolNumber) {\r\n /** ICMP for IPv4 */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"ICMPv4\"] = 1] = \"ICMPv4\";\r\n /** TCP */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"TCP\"] = 6] = \"TCP\";\r\n /** UDP */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"UDP\"] = 17] = \"UDP\";\r\n /** ICMP for IPv6 */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"ICMPv6\"] = 58] = \"ICMPv6\";\r\n})(VpnIpProtocolNumber = exports.VpnIpProtocolNumber || (exports.VpnIpProtocolNumber = {}));\r\n/** The body of the Access list */\r\nvar VpnAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnAccess' class: The body of the Access list */\r\n function VpnAccess(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Specify a description (note) for this rule */\r\n this.Note_utf = \"\";\r\n /** Enabled flag (true: enabled, false: disabled) */\r\n this.Active_bool = false;\r\n /** Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values. */\r\n this.Priority_u32 = 0;\r\n /** The flag if the rule is DISCARD operation or PASS operation. When a packet matches this rule condition, this operation is decided. When the operation of the rule is PASS, the packet is allowed to pass, otherwise the packet will be discarded. */\r\n this.Discard_bool = false;\r\n /** The flag if the rule is for IPv6. Specify false for IPv4, or specify true for IPv6. */\r\n this.IsIPv6_bool = false;\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a source IPv4 address as a rule condition. You must also specify the SrcSubnetMask_ip field. */\r\n this.SrcIpAddress_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a source IPv4 subnet mask as a rule condition. \"0.0.0.0\" means all hosts. \"255.255.255.255\" means one single host. */\r\n this.SrcSubnetMask_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a destination IPv4 address as a rule condition. You must also specify the DestSubnetMask_ip field. */\r\n this.DestIpAddress_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a destination IPv4 subnet mask as a rule condition. \"0.0.0.0\" means all hosts. \"255.255.255.255\" means one single host. */\r\n this.DestSubnetMask_ip = \"\";\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a source IPv6 address as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 address in binary form. You must also specify the SrcSubnetMask6_bin field. */\r\n this.SrcIpAddress6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a source IPv6 subnet mask as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 subnet mask in binary form. */\r\n this.SrcSubnetMask6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a destination IPv6 address as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 address in binary form. You must also specify the DestSubnetMask6_bin field. */\r\n this.DestIpAddress6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a destination IPv6 subnet mask as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 subnet mask in binary form. */\r\n this.DestSubnetMask6_bin = new Uint8Array([]);\r\n /** The IP protocol number */\r\n this.Protocol_u32 = 0;\r\n /** The Start Value of the Source Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.SrcPortStart_u32 = 0;\r\n /** The End Value of the Source Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.SrcPortEnd_u32 = 0;\r\n /** The Start Value of the Destination Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.DestPortStart_u32 = 0;\r\n /** The End Value of the Destination Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.DestPortEnd_u32 = 0;\r\n /** Source user name. You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name. */\r\n this.SrcUsername_str = \"\";\r\n /** Destination user name. You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name. */\r\n this.DestUsername_str = \"\";\r\n /** Specify true if you want to check the source MAC address. */\r\n this.CheckSrcMac_bool = false;\r\n /** Source MAC address (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.SrcMacAddress_bin = new Uint8Array([]);\r\n /** Source MAC address mask (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.SrcMacMask_bin = new Uint8Array([]);\r\n /** Specify true if you want to check the destination MAC address. */\r\n this.CheckDstMac_bool = false;\r\n /** Destination MAC address (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.DstMacAddress_bin = new Uint8Array([]);\r\n /** Destination MAC address mask (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.DstMacMask_bin = new Uint8Array([]);\r\n /** Specify true if you want to check the state of the TCP connection. */\r\n this.CheckTcpState_bool = false;\r\n /** Valid only if CheckTcpState_bool == true. Set this field true to match only TCP-established packets. Set this field false to match only TCP-non established packets. */\r\n this.Established_bool = false;\r\n /** Set this value to generate delays when packets is passing. Specify the delay period in milliseconds. Specify 0 means no delays to generate. The delays must be 10000 milliseconds at most. */\r\n this.Delay_u32 = 0;\r\n /** Set this value to generate jitters when packets is passing. Specify the ratio of fluctuation of jitters within 0% to 100% range. Specify 0 means no jitters to generate. */\r\n this.Jitter_u32 = 0;\r\n /** Set this value to generate packet losses when packets is passing. Specify the ratio of packet losses within 0% to 100% range. Specify 0 means no packet losses to generate. */\r\n this.Loss_u32 = 0;\r\n /** The specified URL will be mandatory replied to the client as a response for TCP connecting request packets which matches the conditions of this access list entry via this Virtual Hub. To use this setting, you can enforce the web browser of the VPN Client computer to show the specified web site when that web browser tries to access the specific IP address. */\r\n this.RedirectUrl_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAccess;\r\n}());\r\nexports.VpnAccess = VpnAccess;\r\n/** Add an item to Access List */\r\nvar VpnRpcAddAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAddAccess' class: Add an item to Access List */\r\n function VpnRpcAddAccess(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Access list (Must be a single item) */\r\n this.AccessListSingle = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAddAccess;\r\n}());\r\nexports.VpnRpcAddAccess = VpnRpcAddAccess;\r\n/** Add CA to HUB */\r\nvar VpnRpcHubAddCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubAddCA' class: Add CA to HUB */\r\n function VpnRpcHubAddCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The body of the X.509 certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubAddCA;\r\n}());\r\nexports.VpnRpcHubAddCA = VpnRpcHubAddCA;\r\n/** CRL entry */\r\nvar VpnRpcCrl = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCrl' class: CRL entry */\r\n function VpnRpcCrl(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** CN, optional */\r\n this.CommonName_utf = \"\";\r\n /** O, optional */\r\n this.Organization_utf = \"\";\r\n /** OU, optional */\r\n this.Unit_utf = \"\";\r\n /** C, optional */\r\n this.Country_utf = \"\";\r\n /** ST, optional */\r\n this.State_utf = \"\";\r\n /** L, optional */\r\n this.Local_utf = \"\";\r\n /** Serial, optional */\r\n this.Serial_bin = new Uint8Array([]);\r\n /** MD5 Digest, optional */\r\n this.DigestMD5_bin = new Uint8Array([]);\r\n /** SHA1 Digest, optional */\r\n this.DigestSHA1_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCrl;\r\n}());\r\nexports.VpnRpcCrl = VpnRpcCrl;\r\n/** EtherIP key list entry */\r\nvar VpnEtherIpId = /** @class */ (function () {\r\n /** Constructor for the 'VpnEtherIpId' class: EtherIP key list entry */\r\n function VpnEtherIpId(init) {\r\n /** Specify an ISAKMP Phase 1 ID. The ID must be exactly same as a ID in the configuration of the EtherIP / L2TPv3 Client. You can specify IP address as well as characters as ID, if the EtherIP Client uses IP address as Phase 1 ID. If you specify '*' (asterisk), it will be a wildcard to match any clients which doesn't match other explicit rules. */\r\n this.Id_str = \"\";\r\n /** Specify the name of the Virtual Hub to connect. */\r\n this.HubName_str = \"\";\r\n /** Specify the username to login to the destination Virtual Hub. */\r\n this.UserName_str = \"\";\r\n /** Specify the password to login to the destination Virtual Hub. */\r\n this.Password_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnEtherIpId;\r\n}());\r\nexports.VpnEtherIpId = VpnEtherIpId;\r\n/** Layer-3 virtual interface */\r\nvar VpnRpcL3If = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3If' class: Layer-3 virtual interface */\r\n function VpnRpcL3If(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Virtual HUB name */\r\n this.HubName_str = \"\";\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.SubnetMask_ip = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3If;\r\n}());\r\nexports.VpnRpcL3If = VpnRpcL3If;\r\n/** Layer-3 switch */\r\nvar VpnRpcL3Sw = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3Sw' class: Layer-3 switch */\r\n function VpnRpcL3Sw(init) {\r\n /** Layer-3 Switch name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3Sw;\r\n}());\r\nexports.VpnRpcL3Sw = VpnRpcL3Sw;\r\n/** Routing table */\r\nvar VpnRpcL3Table = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3Table' class: Routing table */\r\n function VpnRpcL3Table(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Network address */\r\n this.NetworkAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.SubnetMask_ip = \"\";\r\n /** Gateway address */\r\n this.GatewayAddress_ip = \"\";\r\n /** Metric */\r\n this.Metric_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3Table;\r\n}());\r\nexports.VpnRpcL3Table = VpnRpcL3Table;\r\n/** Generic parameter to contain u32, u64, ascii_string and unicode string */\r\nvar VpnRpcTest = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcTest' class: Generic parameter to contain u32, u64, ascii_string and unicode string */\r\n function VpnRpcTest(init) {\r\n /** A 32-bit integer field */\r\n this.IntValue_u32 = 0;\r\n /** A 64-bit integer field */\r\n this.Int64Value_u64 = 0;\r\n /** An Ascii string field */\r\n this.StrValue_str = \"\";\r\n /** An UTF-8 string field */\r\n this.UniStrValue_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcTest;\r\n}());\r\nexports.VpnRpcTest = VpnRpcTest;\r\n/** Local Bridge list item */\r\nvar VpnRpcLocalBridge = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLocalBridge' class: Local Bridge list item */\r\n function VpnRpcLocalBridge(init) {\r\n /** Physical Ethernet device name */\r\n this.DeviceName_str = \"\";\r\n /** The Virtual Hub name */\r\n this.HubNameLB_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** Running flag */\r\n this.Active_bool = false;\r\n /** Specify true if you are using a tap device rather than a network adapter for the bridge destination (only supported for Linux versions). */\r\n this.TapMode_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLocalBridge;\r\n}());\r\nexports.VpnRpcLocalBridge = VpnRpcLocalBridge;\r\n/** Create, configure, and get the group */\r\nvar VpnRpcSetGroup = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetGroup' class: Create, configure, and get the group */\r\n function VpnRpcSetGroup(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The group name */\r\n this.Name_str = \"\";\r\n /** Optional real name (full name) of the group, allow using any Unicode characters */\r\n this.Realname_utf = \"\";\r\n /** Optional, specify a description of the group */\r\n this.Note_utf = \"\";\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** The flag whether to use security policy */\r\n this.UsePolicy_bool = false;\r\n /** Security policy: Allow Access. The users, which this policy value is true, have permission to make VPN connection to VPN Server. */\r\n this[\"policy:Access_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Deny Bridge Operation. Bridge-mode connections are denied for user sessions that have this policy setting. Even in cases when the Ethernet Bridge is configured in the client side, communication will not be possible. */\r\n this[\"policy:NoBridge_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv4). IPv4 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRouting_bool\"] = false;\r\n /** Security policy: Deny MAC Addresses Duplication. The use of duplicating MAC addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckMac_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv4). The use of duplicating IPv4 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIP_bool\"] = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Allow Monitoring Mode. Users with this policy setting will be granted to connect to the Virtual Hub in Monitoring Mode. Sessions in Monitoring Mode are able to monitor (tap) all packets flowing through the Virtual Hub. */\r\n this[\"policy:MonitorPort_bool\"] = false;\r\n /** Security policy: Maximum Number of TCP Connections. For sessions with this policy setting, this sets the maximum number of physical TCP connections consists in a physical VPN session. */\r\n this[\"policy:MaxConnection_u32\"] = 0;\r\n /** Security policy: Time-out Period. For sessions with this policy setting, this sets, in seconds, the time-out period to wait before disconnecting a session when communication trouble occurs between the VPN Client / VPN Server. */\r\n this[\"policy:TimeOut_u32\"] = 0;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Deny Changing Password. The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar. */\r\n this[\"policy:FixPassword_bool\"] = false;\r\n /** Security policy: Maximum Number of Multiple Logins. Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. */\r\n this[\"policy:MultiLogins_u32\"] = 0;\r\n /** Security policy: Deny VoIP / QoS Function. Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. */\r\n this[\"policy:NoQoS_bool\"] = false;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter RA Packets (IPv6). All ICMPv6 packets which the message-type is 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, a malicious users will be unable to spread illegal IPv6 prefix or default gateway advertisements on the network. */\r\n this[\"policy:RAFilter_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv6). IPv6 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRoutingV6_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv6). The use of duplicating IPv6 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIPv6_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Disallow Password Save in VPN Client. For users with this policy setting, when the user is using *standard* password authentication, the user will be unable to save the password in VPN Client. The user will be required to input passwords for every time to connect a VPN. This will improve the security. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:NoSavePassword_bool\"] = false;\r\n /** Security policy: VPN Client Automatic Disconnect. For users with this policy setting, a user's VPN session will be disconnected automatically after the specific period will elapse. In this case no automatic re-connection will be performed. This can prevent a lot of inactive VPN Sessions. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:AutoDisconnect_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA (physical IPv6). In all VPN Sessions defines this policy (only when the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6), any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRAWhenIPv6_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetGroup;\r\n}());\r\nexports.VpnRpcSetGroup = VpnRpcSetGroup;\r\n/** Hub types */\r\nvar VpnRpcHubType;\r\n(function (VpnRpcHubType) {\r\n /** Stand-alone HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"Standalone\"] = 0] = \"Standalone\";\r\n /** Static HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"FarmStatic\"] = 1] = \"FarmStatic\";\r\n /** Dynamic HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"FarmDynamic\"] = 2] = \"FarmDynamic\";\r\n})(VpnRpcHubType = exports.VpnRpcHubType || (exports.VpnRpcHubType = {}));\r\n/** Create a HUB */\r\nvar VpnRpcCreateHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCreateHub' class: Create a HUB */\r\n function VpnRpcCreateHub(init) {\r\n /** Specify the name of the Virtual Hub to create / update. */\r\n this.HubName_str = \"\";\r\n /** Specify an administrator password when the administrator password is going to be set for the Virtual Hub. On the update, leave it to empty string if you don't want to change the password. */\r\n this.AdminPasswordPlainText_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** Maximum number of VPN sessions */\r\n this.MaxSession_u32 = 0;\r\n /** No Enum flag. By enabling this option, the VPN Client user will be unable to enumerate this Virtual Hub even if they send a Virtual Hub enumeration request to the VPN Server. */\r\n this.NoEnum_bool = false;\r\n /** Type of the Virtual Hub (Valid only for Clustered VPN Servers) */\r\n this.HubType_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCreateHub;\r\n}());\r\nexports.VpnRpcCreateHub = VpnRpcCreateHub;\r\nvar VpnRpcClientAuthType;\r\n(function (VpnRpcClientAuthType) {\r\n /** Anonymous authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"Anonymous\"] = 0] = \"Anonymous\";\r\n /** SHA-0 hashed password authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"SHA0_Hashed_Password\"] = 1] = \"SHA0_Hashed_Password\";\r\n /** Plain password authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"PlainPassword\"] = 2] = \"PlainPassword\";\r\n /** Certificate authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"Cert\"] = 3] = \"Cert\";\r\n})(VpnRpcClientAuthType = exports.VpnRpcClientAuthType || (exports.VpnRpcClientAuthType = {}));\r\n/** Create and set of link */\r\nvar VpnRpcCreateLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCreateLink' class: Create and set of link */\r\n function VpnRpcCreateLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_Ex_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** The flag to enable validation for the server certificate */\r\n this.CheckServerCert_bool = false;\r\n /** The body of server X.509 certificate to compare. Valid only if the CheckServerCert_bool flag is true. */\r\n this.ServerCert_bin = new Uint8Array([]);\r\n /** Client Option Parameters: Specify the name of the Cascade Connection */\r\n this.AccountName_utf = \"\";\r\n /** Client Option Parameters: Specify the hostname of the destination VPN Server. You can also specify by IP address. */\r\n this.Hostname_str = \"\";\r\n /** Client Option Parameters: Specify the port number of the destination VPN Server. */\r\n this.Port_u32 = 0;\r\n /** Client Option Parameters: The type of the proxy server */\r\n this.ProxyType_u32 = 0;\r\n /** Client Option Parameters: The hostname or IP address of the proxy server name */\r\n this.ProxyName_str = \"\";\r\n /** Client Option Parameters: The port number of the proxy server */\r\n this.ProxyPort_u32 = 0;\r\n /** Client Option Parameters: The username to connect to the proxy server */\r\n this.ProxyUsername_str = \"\";\r\n /** Client Option Parameters: The password to connect to the proxy server */\r\n this.ProxyPassword_str = \"\";\r\n /** Client Option Parameters: The Virtual Hub on the destination VPN Server */\r\n this.HubName_str = \"\";\r\n /** Client Option Parameters: Number of TCP Connections to Use in VPN Communication */\r\n this.MaxConnection_u32 = 0;\r\n /** Client Option Parameters: The flag to enable the encryption on the communication */\r\n this.UseEncrypt_bool = false;\r\n /** Client Option Parameters: Enable / Disable Data Compression when Communicating by Cascade Connection */\r\n this.UseCompress_bool = false;\r\n /** Client Option Parameters: Specify true when enabling half duplex mode. When using two or more TCP connections for VPN communication, it is possible to use Half Duplex Mode. By enabling half duplex mode it is possible to automatically fix data transmission direction as half and half for each TCP connection. In the case where a VPN using 8 TCP connections is established, for example, when half-duplex is enabled, communication can be fixes so that 4 TCP connections are dedicated to the upload direction and the other 4 connections are dedicated to the download direction. */\r\n this.HalfConnection_bool = false;\r\n /** Client Option Parameters: Connection attempt interval when additional connection will be established */\r\n this.AdditionalConnectionInterval_u32 = 0;\r\n /** Client Option Parameters: Connection Life of Each TCP Connection (0 for no keep-alive) */\r\n this.ConnectionDisconnectSpan_u32 = 0;\r\n /** Client Option Parameters: Disable QoS Control Function if the value is true */\r\n this.DisableQoS_bool = false;\r\n /** Client Option Parameters: Do not use TLS 1.x of the value is true */\r\n this.NoTls1_bool = false;\r\n /** Client Option Parameters: Do not use UDP acceleration mode if the value is true */\r\n this.NoUdpAcceleration_bool = false;\r\n /** Authentication type */\r\n this.AuthType_u32 = 0;\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(UpperCase(username_ascii_string) + password_ascii_string). */\r\n this.HashedPassword_bin = new Uint8Array([]);\r\n /** Plaintext Password. Valid only if ClientAuth_AuthType_u32 == PlainPassword (2). */\r\n this.PlainPassword_str = \"\";\r\n /** Client certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). */\r\n this.ClientX_bin = new Uint8Array([]);\r\n /** Client private key of the certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). */\r\n this.ClientK_bin = new Uint8Array([]);\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Prohibit the duplicate MAC address */\r\n this.SecPol_CheckMac_bool = false;\r\n /** Security policy: Prohibit a duplicate IP address (IPv4) */\r\n this.SecPol_CheckIP_bool = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter the router advertisement packet (IPv6) */\r\n this.SecPol_RAFilter_bool = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Prohibit the duplicate IP address (IPv6) */\r\n this.SecPol_CheckIPv6_bool = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCreateLink;\r\n}());\r\nexports.VpnRpcCreateLink = VpnRpcCreateLink;\r\n/** Listener */\r\nvar VpnRpcListener = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListener' class: Listener */\r\n function VpnRpcListener(init) {\r\n /** Port number (Range: 1 - 65535) */\r\n this.Port_u32 = 0;\r\n /** Active state */\r\n this.Enable_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListener;\r\n}());\r\nexports.VpnRpcListener = VpnRpcListener;\r\n/** User authentication type (server side) */\r\nvar VpnRpcUserAuthType;\r\n(function (VpnRpcUserAuthType) {\r\n /** Anonymous authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Anonymous\"] = 0] = \"Anonymous\";\r\n /** Password authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Password\"] = 1] = \"Password\";\r\n /** User certificate authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"UserCert\"] = 2] = \"UserCert\";\r\n /** Root certificate which is issued by trusted Certificate Authority */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"RootCert\"] = 3] = \"RootCert\";\r\n /** Radius authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Radius\"] = 4] = \"Radius\";\r\n /** Windows NT authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"NTDomain\"] = 5] = \"NTDomain\";\r\n})(VpnRpcUserAuthType = exports.VpnRpcUserAuthType || (exports.VpnRpcUserAuthType = {}));\r\n/** Create, configure, and get the user */\r\nvar VpnRpcSetUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetUser' class: Create, configure, and get the user */\r\n function VpnRpcSetUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Specify the user name of the user */\r\n this.Name_str = \"\";\r\n /** Assigned group name for the user */\r\n this.GroupName_str = \"\";\r\n /** Optional real name (full name) of the user, allow using any Unicode characters */\r\n this.Realname_utf = \"\";\r\n /** Optional User Description */\r\n this.Note_utf = \"\";\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last modified date and time */\r\n this.UpdatedTime_dt = new Date();\r\n /** Expiration date and time */\r\n this.ExpireTime_dt = new Date();\r\n /** Authentication method of the user */\r\n this.AuthType_u32 = 0;\r\n /** User password, valid only if AuthType_u32 == Password(1). Valid only to create or set operations. */\r\n this.Auth_Password_str = \"\";\r\n /** User certificate, valid only if AuthType_u32 == UserCert(2). */\r\n this.UserX_bin = new Uint8Array([]);\r\n /** Certificate Serial Number, optional, valid only if AuthType_u32 == RootCert(3). */\r\n this.Serial_bin = new Uint8Array([]);\r\n /** Certificate Common Name, optional, valid only if AuthType_u32 == RootCert(3). */\r\n this.CommonName_utf = \"\";\r\n /** Username in RADIUS server, optional, valid only if AuthType_u32 == Radius(4). */\r\n this.RadiusUsername_utf = \"\";\r\n /** Username in NT Domain server, optional, valid only if AuthType_u32 == NT(5). */\r\n this.NtUsername_utf = \"\";\r\n /** Number of total logins of the user */\r\n this.NumLogin_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** The flag whether to use security policy */\r\n this.UsePolicy_bool = false;\r\n /** Security policy: Allow Access. The users, which this policy value is true, have permission to make VPN connection to VPN Server. */\r\n this[\"policy:Access_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Deny Bridge Operation. Bridge-mode connections are denied for user sessions that have this policy setting. Even in cases when the Ethernet Bridge is configured in the client side, communication will not be possible. */\r\n this[\"policy:NoBridge_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv4). IPv4 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRouting_bool\"] = false;\r\n /** Security policy: Deny MAC Addresses Duplication. The use of duplicating MAC addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckMac_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv4). The use of duplicating IPv4 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIP_bool\"] = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Allow Monitoring Mode. Users with this policy setting will be granted to connect to the Virtual Hub in Monitoring Mode. Sessions in Monitoring Mode are able to monitor (tap) all packets flowing through the Virtual Hub. */\r\n this[\"policy:MonitorPort_bool\"] = false;\r\n /** Security policy: Maximum Number of TCP Connections. For sessions with this policy setting, this sets the maximum number of physical TCP connections consists in a physical VPN session. */\r\n this[\"policy:MaxConnection_u32\"] = 0;\r\n /** Security policy: Time-out Period. For sessions with this policy setting, this sets, in seconds, the time-out period to wait before disconnecting a session when communication trouble occurs between the VPN Client / VPN Server. */\r\n this[\"policy:TimeOut_u32\"] = 0;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Deny Changing Password. The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar. */\r\n this[\"policy:FixPassword_bool\"] = false;\r\n /** Security policy: Maximum Number of Multiple Logins. Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. */\r\n this[\"policy:MultiLogins_u32\"] = 0;\r\n /** Security policy: Deny VoIP / QoS Function. Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. */\r\n this[\"policy:NoQoS_bool\"] = false;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter RA Packets (IPv6). All ICMPv6 packets which the message-type is 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, a malicious users will be unable to spread illegal IPv6 prefix or default gateway advertisements on the network. */\r\n this[\"policy:RAFilter_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv6). IPv6 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRoutingV6_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv6). The use of duplicating IPv6 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIPv6_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Disallow Password Save in VPN Client. For users with this policy setting, when the user is using *standard* password authentication, the user will be unable to save the password in VPN Client. The user will be required to input passwords for every time to connect a VPN. This will improve the security. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:NoSavePassword_bool\"] = false;\r\n /** Security policy: VPN Client Automatic Disconnect. For users with this policy setting, a user's VPN session will be disconnected automatically after the specific period will elapse. In this case no automatic re-connection will be performed. This can prevent a lot of inactive VPN Sessions. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:AutoDisconnect_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA (physical IPv6). In all VPN Sessions defines this policy (only when the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6), any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRAWhenIPv6_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetUser;\r\n}());\r\nexports.VpnRpcSetUser = VpnRpcSetUser;\r\n/** Delete the access list */\r\nvar VpnRpcDeleteAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteAccess' class: Delete the access list */\r\n function VpnRpcDeleteAccess(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** ID */\r\n this.Id_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteAccess;\r\n}());\r\nexports.VpnRpcDeleteAccess = VpnRpcDeleteAccess;\r\n/** Delete the CA of HUB */\r\nvar VpnRpcHubDeleteCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubDeleteCA' class: Delete the CA of HUB */\r\n function VpnRpcHubDeleteCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Certificate key id to be deleted */\r\n this.Key_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubDeleteCA;\r\n}());\r\nexports.VpnRpcHubDeleteCA = VpnRpcHubDeleteCA;\r\n/** Deleting a user or group */\r\nvar VpnRpcDeleteUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteUser' class: Deleting a user or group */\r\n function VpnRpcDeleteUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** User or group name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteUser;\r\n}());\r\nexports.VpnRpcDeleteUser = VpnRpcDeleteUser;\r\n/** Delete the HUB */\r\nvar VpnRpcDeleteHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteHub' class: Delete the HUB */\r\n function VpnRpcDeleteHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteHub;\r\n}());\r\nexports.VpnRpcDeleteHub = VpnRpcDeleteHub;\r\n/** Delete the table */\r\nvar VpnRpcDeleteTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteTable' class: Delete the table */\r\n function VpnRpcDeleteTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteTable;\r\n}());\r\nexports.VpnRpcDeleteTable = VpnRpcDeleteTable;\r\n/** Specify the Link */\r\nvar VpnRpcLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLink' class: Specify the Link */\r\n function VpnRpcLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The name of the cascade connection */\r\n this.AccountName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLink;\r\n}());\r\nexports.VpnRpcLink = VpnRpcLink;\r\n/** Disconnect the session */\r\nvar VpnRpcDeleteSession = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteSession' class: Disconnect the session */\r\n function VpnRpcDeleteSession(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Session name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteSession;\r\n}());\r\nexports.VpnRpcDeleteSession = VpnRpcDeleteSession;\r\n/** Specify the HUB */\r\nvar VpnRpcHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHub' class: Specify the HUB */\r\n function VpnRpcHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHub;\r\n}());\r\nexports.VpnRpcHub = VpnRpcHub;\r\n/** Disconnect a connection */\r\nvar VpnRpcDisconnectConnection = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDisconnectConnection' class: Disconnect a connection */\r\n function VpnRpcDisconnectConnection(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDisconnectConnection;\r\n}());\r\nexports.VpnRpcDisconnectConnection = VpnRpcDisconnectConnection;\r\n/** Enumeration of the access list */\r\nvar VpnRpcEnumAccessList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumAccessList' class: Enumeration of the access list */\r\n function VpnRpcEnumAccessList(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Access list */\r\n this.AccessList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumAccessList;\r\n}());\r\nexports.VpnRpcEnumAccessList = VpnRpcEnumAccessList;\r\n/** CA enumeration items of HUB */\r\nvar VpnRpcHubEnumCAItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubEnumCAItem' class: CA enumeration items of HUB */\r\n function VpnRpcHubEnumCAItem(init) {\r\n /** The key id of the item */\r\n this.Key_u32 = 0;\r\n /** Subject */\r\n this.SubjectName_utf = \"\";\r\n /** Issuer */\r\n this.IssuerName_utf = \"\";\r\n /** Expiration date */\r\n this.Expires_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubEnumCAItem;\r\n}());\r\nexports.VpnRpcHubEnumCAItem = VpnRpcHubEnumCAItem;\r\n/** CA enumeration of HUB */\r\nvar VpnRpcHubEnumCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubEnumCA' class: CA enumeration of HUB */\r\n function VpnRpcHubEnumCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The list of CA */\r\n this.CAList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubEnumCA;\r\n}());\r\nexports.VpnRpcHubEnumCA = VpnRpcHubEnumCA;\r\n/** Type of connection */\r\nvar VpnRpcConnectionType;\r\n(function (VpnRpcConnectionType) {\r\n /** VPN Client */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Client\"] = 0] = \"Client\";\r\n /** During initialization */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Init\"] = 1] = \"Init\";\r\n /** Login connection */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Login\"] = 2] = \"Login\";\r\n /** Additional connection */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Additional\"] = 3] = \"Additional\";\r\n /** RPC for server farm */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"FarmRpc\"] = 4] = \"FarmRpc\";\r\n /** RPC for Management */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"AdminRpc\"] = 5] = \"AdminRpc\";\r\n /** HUB enumeration */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"EnumHub\"] = 6] = \"EnumHub\";\r\n /** Password change */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Password\"] = 7] = \"Password\";\r\n /** SSTP */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"SSTP\"] = 8] = \"SSTP\";\r\n /** OpenVPN */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"OpenVPN\"] = 9] = \"OpenVPN\";\r\n})(VpnRpcConnectionType = exports.VpnRpcConnectionType || (exports.VpnRpcConnectionType = {}));\r\n/** Connection enumeration items */\r\nvar VpnRpcEnumConnectionItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumConnectionItem' class: Connection enumeration items */\r\n function VpnRpcEnumConnectionItem(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Connected time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Connection type */\r\n this.Type_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumConnectionItem;\r\n}());\r\nexports.VpnRpcEnumConnectionItem = VpnRpcEnumConnectionItem;\r\n/** Connection enumeration */\r\nvar VpnRpcEnumConnection = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumConnection' class: Connection enumeration */\r\n function VpnRpcEnumConnection(init) {\r\n /** Number of connections */\r\n this.NumConnection_u32 = 0;\r\n /** Connection list */\r\n this.ConnectionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumConnection;\r\n}());\r\nexports.VpnRpcEnumConnection = VpnRpcEnumConnection;\r\n/** Enum CRL Item */\r\nvar VpnRpcEnumCrlItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumCrlItem' class: Enum CRL Item */\r\n function VpnRpcEnumCrlItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** The contents of the CRL item */\r\n this.CrlInfo_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumCrlItem;\r\n}());\r\nexports.VpnRpcEnumCrlItem = VpnRpcEnumCrlItem;\r\n/** Enum CRL */\r\nvar VpnRpcEnumCrl = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumCrl' class: Enum CRL */\r\n function VpnRpcEnumCrl(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** CRL list */\r\n this.CRLList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumCrl;\r\n}());\r\nexports.VpnRpcEnumCrl = VpnRpcEnumCrl;\r\n/** RPC_ENUM_DHCP_ITEM */\r\nvar VpnRpcEnumDhcpItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumDhcpItem' class: RPC_ENUM_DHCP_ITEM */\r\n function VpnRpcEnumDhcpItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Lease time */\r\n this.LeasedTime_dt = new Date();\r\n /** Expiration date */\r\n this.ExpireTime_dt = new Date();\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.Mask_u32 = 0;\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumDhcpItem;\r\n}());\r\nexports.VpnRpcEnumDhcpItem = VpnRpcEnumDhcpItem;\r\n/** RPC_ENUM_DHCP */\r\nvar VpnRpcEnumDhcp = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumDhcp' class: RPC_ENUM_DHCP */\r\n function VpnRpcEnumDhcp(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** DHCP Item */\r\n this.DhcpTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumDhcp;\r\n}());\r\nexports.VpnRpcEnumDhcp = VpnRpcEnumDhcp;\r\n/** EtherIP setting list */\r\nvar VpnRpcEnumEtherIpId = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEtherIpId' class: EtherIP setting list */\r\n function VpnRpcEnumEtherIpId(init) {\r\n /** Setting list */\r\n this.Settings = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEtherIpId;\r\n}());\r\nexports.VpnRpcEnumEtherIpId = VpnRpcEnumEtherIpId;\r\n/** Ethernet Network Adapters list item */\r\nvar VpnRpcEnumEthItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEthItem' class: Ethernet Network Adapters list item */\r\n function VpnRpcEnumEthItem(init) {\r\n /** Device name */\r\n this.DeviceName_str = \"\";\r\n /** Network connection name (description) */\r\n this.NetworkConnectionName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEthItem;\r\n}());\r\nexports.VpnRpcEnumEthItem = VpnRpcEnumEthItem;\r\n/** Ethernet Network Adapters list */\r\nvar VpnRpcEnumEth = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEth' class: Ethernet Network Adapters list */\r\n function VpnRpcEnumEth(init) {\r\n /** Ethernet Network Adapters list */\r\n this.EthList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEth;\r\n}());\r\nexports.VpnRpcEnumEth = VpnRpcEnumEth;\r\n/** Server farm members enumeration items */\r\nvar VpnRpcEnumFarmItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumFarmItem' class: Server farm members enumeration items */\r\n function VpnRpcEnumFarmItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Controller */\r\n this.Controller_bool = false;\r\n /** Connection time */\r\n this.ConnectedTime_dt = new Date();\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Point */\r\n this.Point_u32 = 0;\r\n /** Number of sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of HUBs */\r\n this.NumHubs_u32 = 0;\r\n /** Number of assigned client licenses */\r\n this.AssignedClientLicense_u32 = 0;\r\n /** Number of assigned bridge licenses */\r\n this.AssignedBridgeLicense_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumFarmItem;\r\n}());\r\nexports.VpnRpcEnumFarmItem = VpnRpcEnumFarmItem;\r\n/** Server farm member enumeration */\r\nvar VpnRpcEnumFarm = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumFarm' class: Server farm member enumeration */\r\n function VpnRpcEnumFarm(init) {\r\n /** Number of Cluster Members */\r\n this.NumFarm_u32 = 0;\r\n /** Cluster Members list */\r\n this.FarmMemberList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumFarm;\r\n}());\r\nexports.VpnRpcEnumFarm = VpnRpcEnumFarm;\r\n/** Enumeration items in the group */\r\nvar VpnRpcEnumGroupItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumGroupItem' class: Enumeration items in the group */\r\n function VpnRpcEnumGroupItem(init) {\r\n /** User name */\r\n this.Name_str = \"\";\r\n /** Real name */\r\n this.Realname_utf = \"\";\r\n /** Note */\r\n this.Note_utf = \"\";\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Access denied */\r\n this.DenyAccess_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumGroupItem;\r\n}());\r\nexports.VpnRpcEnumGroupItem = VpnRpcEnumGroupItem;\r\n/** Group enumeration */\r\nvar VpnRpcEnumGroup = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumGroup' class: Group enumeration */\r\n function VpnRpcEnumGroup(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Group list */\r\n this.GroupList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumGroup;\r\n}());\r\nexports.VpnRpcEnumGroup = VpnRpcEnumGroup;\r\n/** Enumeration items of HUB */\r\nvar VpnRpcEnumHubItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumHubItem' class: Enumeration items of HUB */\r\n function VpnRpcEnumHubItem(init) {\r\n /** The name of the Virtual Hub */\r\n this.HubName_str = \"\";\r\n /** Online state */\r\n this.Online_bool = false;\r\n /** Type of HUB (Valid only for Clustered VPN Servers) */\r\n this.HubType_u32 = 0;\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Number of registered groups */\r\n this.NumGroups_u32 = 0;\r\n /** Number of registered sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of current MAC table entries */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of current IP table entries */\r\n this.NumIpTables_u32 = 0;\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Number of accumulated logins */\r\n this.NumLogin_u32 = 0;\r\n /** Whether the traffic information is provided */\r\n this.IsTrafficFilled_bool = false;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Ex.Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Ex.Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Ex.Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Ex.Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Ex.Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Ex.Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastCount_u64\"] = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumHubItem;\r\n}());\r\nexports.VpnRpcEnumHubItem = VpnRpcEnumHubItem;\r\n/** Enumeration of HUB */\r\nvar VpnRpcEnumHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumHub' class: Enumeration of HUB */\r\n function VpnRpcEnumHub(init) {\r\n /** Number of Virtual Hubs */\r\n this.NumHub_u32 = 0;\r\n /** Virtual Hubs */\r\n this.HubList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumHub;\r\n}());\r\nexports.VpnRpcEnumHub = VpnRpcEnumHub;\r\n/** Enumeration items of IP table */\r\nvar VpnRpcEnumIpTableItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumIpTableItem' class: Enumeration items of IP table */\r\n function VpnRpcEnumIpTableItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Assigned by the DHCP */\r\n this.DhcpAllocated_bool = false;\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Updating date */\r\n this.UpdatedTime_dt = new Date();\r\n /** Remote items */\r\n this.RemoteItem_bool = false;\r\n /** Remote host name */\r\n this.RemoteHostname_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumIpTableItem;\r\n}());\r\nexports.VpnRpcEnumIpTableItem = VpnRpcEnumIpTableItem;\r\n/** Enumeration of IP table */\r\nvar VpnRpcEnumIpTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumIpTable' class: Enumeration of IP table */\r\n function VpnRpcEnumIpTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** MAC table */\r\n this.IpTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumIpTable;\r\n}());\r\nexports.VpnRpcEnumIpTable = VpnRpcEnumIpTable;\r\n/** Layer-3 interface enumeration */\r\nvar VpnRpcEnumL3If = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3If' class: Layer-3 interface enumeration */\r\n function VpnRpcEnumL3If(init) {\r\n /** Layer-3 switch name */\r\n this.Name_str = \"\";\r\n /** Layer-3 interface list */\r\n this.L3IFList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3If;\r\n}());\r\nexports.VpnRpcEnumL3If = VpnRpcEnumL3If;\r\n/** Layer-3 switch enumeration item */\r\nvar VpnRpcEnumL3SwItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3SwItem' class: Layer-3 switch enumeration item */\r\n function VpnRpcEnumL3SwItem(init) {\r\n /** Name of the layer-3 switch */\r\n this.Name_str = \"\";\r\n /** Number of layer-3 switch virtual interfaces */\r\n this.NumInterfaces_u32 = 0;\r\n /** Number of routing tables */\r\n this.NumTables_u32 = 0;\r\n /** Activated flag */\r\n this.Active_bool = false;\r\n /** Online flag */\r\n this.Online_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3SwItem;\r\n}());\r\nexports.VpnRpcEnumL3SwItem = VpnRpcEnumL3SwItem;\r\n/** Layer-3 switch enumeration */\r\nvar VpnRpcEnumL3Sw = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3Sw' class: Layer-3 switch enumeration */\r\n function VpnRpcEnumL3Sw(init) {\r\n /** Layer-3 switch list */\r\n this.L3SWList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3Sw;\r\n}());\r\nexports.VpnRpcEnumL3Sw = VpnRpcEnumL3Sw;\r\n/** Routing table enumeration */\r\nvar VpnRpcEnumL3Table = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3Table' class: Routing table enumeration */\r\n function VpnRpcEnumL3Table(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Routing table item list */\r\n this.L3Table = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3Table;\r\n}());\r\nexports.VpnRpcEnumL3Table = VpnRpcEnumL3Table;\r\n/** Cascade Connection Enumeration */\r\nvar VpnRpcEnumLinkItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLinkItem' class: Cascade Connection Enumeration */\r\n function VpnRpcEnumLinkItem(init) {\r\n /** The name of cascade connection */\r\n this.AccountName_utf = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** The flag indicates whether the cascade connection is established */\r\n this.Connected_bool = false;\r\n /** The error last occurred if the cascade connection is in the fail state */\r\n this.LastError_u32 = 0;\r\n /** Connection completion time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Host name of the destination VPN server */\r\n this.Hostname_str = \"\";\r\n /** The Virtual Hub name */\r\n this.TargetHubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLinkItem;\r\n}());\r\nexports.VpnRpcEnumLinkItem = VpnRpcEnumLinkItem;\r\n/** Enumeration of the link */\r\nvar VpnRpcEnumLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLink' class: Enumeration of the link */\r\n function VpnRpcEnumLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Number of cascade connections */\r\n this.NumLink_u32 = 0;\r\n /** The list of cascade connections */\r\n this.LinkList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLink;\r\n}());\r\nexports.VpnRpcEnumLink = VpnRpcEnumLink;\r\n/** List of listeners item */\r\nvar VpnRpcListenerListItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListenerListItem' class: List of listeners item */\r\n function VpnRpcListenerListItem(init) {\r\n /** TCP port number (range: 1 - 65535) */\r\n this.Ports_u32 = 0;\r\n /** Active state */\r\n this.Enables_bool = false;\r\n /** The flag to indicate if the error occurred on the listener port */\r\n this.Errors_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListenerListItem;\r\n}());\r\nexports.VpnRpcListenerListItem = VpnRpcListenerListItem;\r\n/** List of listeners */\r\nvar VpnRpcListenerList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListenerList' class: List of listeners */\r\n function VpnRpcListenerList(init) {\r\n /** List of listener items */\r\n this.ListenerList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListenerList;\r\n}());\r\nexports.VpnRpcListenerList = VpnRpcListenerList;\r\n/** Local Bridge enumeration */\r\nvar VpnRpcEnumLocalBridge = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLocalBridge' class: Local Bridge enumeration */\r\n function VpnRpcEnumLocalBridge(init) {\r\n /** Local Bridge list */\r\n this.LocalBridgeList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLocalBridge;\r\n}());\r\nexports.VpnRpcEnumLocalBridge = VpnRpcEnumLocalBridge;\r\n/** Log file enumeration */\r\nvar VpnRpcEnumLogFileItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLogFileItem' class: Log file enumeration */\r\n function VpnRpcEnumLogFileItem(init) {\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** File path */\r\n this.FilePath_str = \"\";\r\n /** File size */\r\n this.FileSize_u32 = 0;\r\n /** Last write date */\r\n this.UpdatedTime_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLogFileItem;\r\n}());\r\nexports.VpnRpcEnumLogFileItem = VpnRpcEnumLogFileItem;\r\n/** Log file enumeration */\r\nvar VpnRpcEnumLogFile = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLogFile' class: Log file enumeration */\r\n function VpnRpcEnumLogFile(init) {\r\n /** Log file list */\r\n this.LogFiles = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLogFile;\r\n}());\r\nexports.VpnRpcEnumLogFile = VpnRpcEnumLogFile;\r\n/** Enumeration items of the MAC table */\r\nvar VpnRpcEnumMacTableItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumMacTableItem' class: Enumeration items of the MAC table */\r\n function VpnRpcEnumMacTableItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Updating date */\r\n this.UpdatedTime_dt = new Date();\r\n /** Remote items */\r\n this.RemoteItem_bool = false;\r\n /** Remote host name */\r\n this.RemoteHostname_str = \"\";\r\n /** VLAN ID */\r\n this.VlanId_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumMacTableItem;\r\n}());\r\nexports.VpnRpcEnumMacTableItem = VpnRpcEnumMacTableItem;\r\n/** Enumeration of the MAC table */\r\nvar VpnRpcEnumMacTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumMacTable' class: Enumeration of the MAC table */\r\n function VpnRpcEnumMacTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** MAC table */\r\n this.MacTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumMacTable;\r\n}());\r\nexports.VpnRpcEnumMacTable = VpnRpcEnumMacTable;\r\n/** NAT Entry Protocol Number */\r\nvar VpnRpcNatProtocol;\r\n(function (VpnRpcNatProtocol) {\r\n /** TCP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"TCP\"] = 0] = \"TCP\";\r\n /** UDP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"UDP\"] = 1] = \"UDP\";\r\n /** DNS */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"DNS\"] = 2] = \"DNS\";\r\n /** ICMP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"ICMP\"] = 3] = \"ICMP\";\r\n})(VpnRpcNatProtocol = exports.VpnRpcNatProtocol || (exports.VpnRpcNatProtocol = {}));\r\n/** State of NAT session (TCP) */\r\nvar VpnRpcNatTcpState;\r\n(function (VpnRpcNatTcpState) {\r\n /** Connecting */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Connecting\"] = 0] = \"Connecting\";\r\n /** Send the RST (Connection failure or disconnected) */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"SendReset\"] = 1] = \"SendReset\";\r\n /** Connection complete */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Connected\"] = 2] = \"Connected\";\r\n /** Connection established */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Established\"] = 3] = \"Established\";\r\n /** Wait for socket disconnection */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"WaitDisconnect\"] = 4] = \"WaitDisconnect\";\r\n})(VpnRpcNatTcpState = exports.VpnRpcNatTcpState || (exports.VpnRpcNatTcpState = {}));\r\n/** VpnRpcEnumNat List Item */\r\nvar VpnRpcEnumNatItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumNatItem' class: VpnRpcEnumNat List Item */\r\n function VpnRpcEnumNatItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Protocol */\r\n this.Protocol_u32 = 0;\r\n /** Source IP address */\r\n this.SrcIp_ip = \"\";\r\n /** Source host name */\r\n this.SrcHost_str = \"\";\r\n /** Source port number */\r\n this.SrcPort_u32 = 0;\r\n /** Destination IP address */\r\n this.DestIp_ip = \"\";\r\n /** Destination host name */\r\n this.DestHost_str = \"\";\r\n /** Destination port number */\r\n this.DestPort_u32 = 0;\r\n /** Connection time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last communication time */\r\n this.LastCommTime_dt = new Date();\r\n /** Transmission size */\r\n this.SendSize_u64 = 0;\r\n /** Receive size */\r\n this.RecvSize_u64 = 0;\r\n /** TCP state */\r\n this.TcpStatus_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumNatItem;\r\n}());\r\nexports.VpnRpcEnumNatItem = VpnRpcEnumNatItem;\r\n/** RPC_ENUM_NAT */\r\nvar VpnRpcEnumNat = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumNat' class: RPC_ENUM_NAT */\r\n function VpnRpcEnumNat(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** NAT item */\r\n this.NatTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumNat;\r\n}());\r\nexports.VpnRpcEnumNat = VpnRpcEnumNat;\r\n/** Enumeration item of VPN session */\r\nvar VpnRpcEnumSessionItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumSessionItem' class: Enumeration item of VPN session */\r\n function VpnRpcEnumSessionItem(init) {\r\n /** Session name */\r\n this.Name_str = \"\";\r\n /** Remote session */\r\n this.RemoteSession_bool = false;\r\n /** Remote server name */\r\n this.RemoteHostname_str = \"\";\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** IP address */\r\n this.ClientIP_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Maximum number of underlying TCP connections */\r\n this.MaxNumTcp_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.CurrentNumTcp_u32 = 0;\r\n /** Packet size transmitted */\r\n this.PacketSize_u64 = 0;\r\n /** Number of packets transmitted */\r\n this.PacketNum_u64 = 0;\r\n /** Is a Cascade VPN session */\r\n this.LinkMode_bool = false;\r\n /** Is a SecureNAT VPN session */\r\n this.SecureNATMode_bool = false;\r\n /** Is the VPN session for Local Bridge */\r\n this.BridgeMode_bool = false;\r\n /** Is a Layer-3 Switch VPN session */\r\n this.Layer3Mode_bool = false;\r\n /** Is in Bridge Mode */\r\n this.Client_BridgeMode_bool = false;\r\n /** Is in Monitor Mode */\r\n this.Client_MonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n /** Unique ID of the VPN Session */\r\n this.UniqueId_bin = new Uint8Array([]);\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumSessionItem;\r\n}());\r\nexports.VpnRpcEnumSessionItem = VpnRpcEnumSessionItem;\r\n/** Enumerate VPN sessions */\r\nvar VpnRpcEnumSession = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumSession' class: Enumerate VPN sessions */\r\n function VpnRpcEnumSession(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** VPN sessions list */\r\n this.SessionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumSession;\r\n}());\r\nexports.VpnRpcEnumSession = VpnRpcEnumSession;\r\n/** Enumeration item of user */\r\nvar VpnRpcEnumUserItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumUserItem' class: Enumeration item of user */\r\n function VpnRpcEnumUserItem(init) {\r\n /** User name */\r\n this.Name_str = \"\";\r\n /** Group name */\r\n this.GroupName_str = \"\";\r\n /** Real name */\r\n this.Realname_utf = \"\";\r\n /** Note */\r\n this.Note_utf = \"\";\r\n /** Authentication method */\r\n this.AuthType_u32 = 0;\r\n /** Number of logins */\r\n this.NumLogin_u32 = 0;\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Access denied */\r\n this.DenyAccess_bool = false;\r\n /** Flag of whether the traffic variable is set */\r\n this.IsTrafficFilled_bool = false;\r\n /** Flag of whether expiration date variable is set */\r\n this.IsExpiresFilled_bool = false;\r\n /** Expiration date */\r\n this.Expires_dt = new Date();\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Ex.Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Ex.Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Ex.Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Ex.Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Ex.Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Ex.Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastCount_u64\"] = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumUserItem;\r\n}());\r\nexports.VpnRpcEnumUserItem = VpnRpcEnumUserItem;\r\n/** Enumeration of user */\r\nvar VpnRpcEnumUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumUser' class: Enumeration of user */\r\n function VpnRpcEnumUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** User list */\r\n this.UserList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumUser;\r\n}());\r\nexports.VpnRpcEnumUser = VpnRpcEnumUser;\r\n/** Source IP Address Limit List Item */\r\nvar VpnAc = /** @class */ (function () {\r\n /** Constructor for the 'VpnAc' class: Source IP Address Limit List Item */\r\n function VpnAc(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Priority */\r\n this.Priority_u32 = 0;\r\n /** Deny access */\r\n this.Deny_bool = false;\r\n /** Set true if you want to specify the SubnetMask_ip item. */\r\n this.Masked_bool = false;\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask, valid only if Masked_bool == true */\r\n this.SubnetMask_ip = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAc;\r\n}());\r\nexports.VpnAc = VpnAc;\r\n/** Source IP Address Limit List */\r\nvar VpnRpcAcList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAcList' class: Source IP Address Limit List */\r\n function VpnRpcAcList(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Source IP Address Limit List */\r\n this.ACList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAcList;\r\n}());\r\nexports.VpnRpcAcList = VpnRpcAcList;\r\n/** Message */\r\nvar VpnRpcMsg = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcMsg' class: Message */\r\n function VpnRpcMsg(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Message (Unicode strings acceptable) */\r\n this.Msg_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcMsg;\r\n}());\r\nexports.VpnRpcMsg = VpnRpcMsg;\r\n/** Get / Set the Azure state */\r\nvar VpnRpcAzureStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAzureStatus' class: Get / Set the Azure state */\r\n function VpnRpcAzureStatus(init) {\r\n /** Whether VPN Azure Function is Enabled */\r\n this.IsEnabled_bool = false;\r\n /** Whether connection to VPN Azure Cloud Server is established */\r\n this.IsConnected_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAzureStatus;\r\n}());\r\nexports.VpnRpcAzureStatus = VpnRpcAzureStatus;\r\n/** Local Bridge support information */\r\nvar VpnRpcBridgeSupport = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcBridgeSupport' class: Local Bridge support information */\r\n function VpnRpcBridgeSupport(init) {\r\n /** Whether the OS supports the Local Bridge function */\r\n this.IsBridgeSupportedOs_bool = false;\r\n /** Whether WinPcap is necessary to install */\r\n this.IsWinPcapNeeded_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcBridgeSupport;\r\n}());\r\nexports.VpnRpcBridgeSupport = VpnRpcBridgeSupport;\r\n/** Get the CA of HUB */\r\nvar VpnRpcHubGetCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubGetCA' class: Get the CA of HUB */\r\n function VpnRpcHubGetCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The key id of the certificate */\r\n this.Key_u32 = 0;\r\n /** The body of the X.509 certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubGetCA;\r\n}());\r\nexports.VpnRpcHubGetCA = VpnRpcHubGetCA;\r\n/** Caps item of the VPN Server */\r\nvar VpnCaps = /** @class */ (function () {\r\n /** Constructor for the 'VpnCaps' class: Caps item of the VPN Server */\r\n function VpnCaps(init) {\r\n /** Name */\r\n this.CapsName_str = \"\";\r\n /** Value */\r\n this.CapsValue_u32 = 0;\r\n /** Descrption */\r\n this.CapsDescrption_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnCaps;\r\n}());\r\nexports.VpnCaps = VpnCaps;\r\n/** Caps list of the VPN Server */\r\nvar VpnCapslist = /** @class */ (function () {\r\n /** Constructor for the 'VpnCapslist' class: Caps list of the VPN Server */\r\n function VpnCapslist(init) {\r\n /** Caps list of the VPN Server */\r\n this.CapsList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnCapslist;\r\n}());\r\nexports.VpnCapslist = VpnCapslist;\r\n/** Config operation */\r\nvar VpnRpcConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcConfig' class: Config operation */\r\n function VpnRpcConfig(init) {\r\n /** File name (valid only for returning from the server) */\r\n this.FileName_str = \"\";\r\n /** File data */\r\n this.FileData_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcConfig;\r\n}());\r\nexports.VpnRpcConfig = VpnRpcConfig;\r\n/** Connection information */\r\nvar VpnRpcConnectionInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcConnectionInfo' class: Connection information */\r\n function VpnRpcConnectionInfo(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n /** Type */\r\n this.Type_u32 = 0;\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Connected time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Server string */\r\n this.ServerStr_str = \"\";\r\n /** Server version */\r\n this.ServerVer_u32 = 0;\r\n /** Server build number */\r\n this.ServerBuild_u32 = 0;\r\n /** Client string */\r\n this.ClientStr_str = \"\";\r\n /** Client version */\r\n this.ClientVer_u32 = 0;\r\n /** Client build number */\r\n this.ClientBuild_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcConnectionInfo;\r\n}());\r\nexports.VpnRpcConnectionInfo = VpnRpcConnectionInfo;\r\n/** Proxy type */\r\nvar VpnRpcProxyType;\r\n(function (VpnRpcProxyType) {\r\n /** Direct TCP connection */\r\n VpnRpcProxyType[VpnRpcProxyType[\"Direct\"] = 0] = \"Direct\";\r\n /** Connection via HTTP proxy server */\r\n VpnRpcProxyType[VpnRpcProxyType[\"HTTP\"] = 1] = \"HTTP\";\r\n /** Connection via SOCKS proxy server */\r\n VpnRpcProxyType[VpnRpcProxyType[\"SOCKS\"] = 2] = \"SOCKS\";\r\n})(VpnRpcProxyType = exports.VpnRpcProxyType || (exports.VpnRpcProxyType = {}));\r\n/** The current status of the DDNS */\r\nvar VpnDDnsClientStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnDDnsClientStatus' class: The current status of the DDNS */\r\n function VpnDDnsClientStatus(init) {\r\n /** Last error code (IPv4) */\r\n this.Err_IPv4_u32 = 0;\r\n /** Last error string (IPv4) */\r\n this.ErrStr_IPv4_utf = \"\";\r\n /** Last error code (IPv6) */\r\n this.Err_IPv6_u32 = 0;\r\n /** Last error string (IPv6) */\r\n this.ErrStr_IPv6_utf = \"\";\r\n /** Current DDNS host name */\r\n this.CurrentHostName_str = \"\";\r\n /** Current FQDN of the DDNS hostname */\r\n this.CurrentFqdn_str = \"\";\r\n /** DDNS suffix */\r\n this.DnsSuffix_str = \"\";\r\n /** Current IPv4 address of the VPN Server */\r\n this.CurrentIPv4_str = \"\";\r\n /** Current IPv6 address of the VPN Server */\r\n this.CurrentIPv6_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnDDnsClientStatus;\r\n}());\r\nexports.VpnDDnsClientStatus = VpnDDnsClientStatus;\r\n/** Internet connection settings */\r\nvar VpnInternetSetting = /** @class */ (function () {\r\n /** Constructor for the 'VpnInternetSetting' class: Internet connection settings */\r\n function VpnInternetSetting(init) {\r\n /** Type of proxy server */\r\n this.ProxyType_u32 = 0;\r\n /** Proxy server host name */\r\n this.ProxyHostName_str = \"\";\r\n /** Proxy server port number */\r\n this.ProxyPort_u32 = 0;\r\n /** Proxy server user name */\r\n this.ProxyUsername_str = \"\";\r\n /** Proxy server password */\r\n this.ProxyPassword_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnInternetSetting;\r\n}());\r\nexports.VpnInternetSetting = VpnInternetSetting;\r\n/** Administration options */\r\nvar VpnAdminOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnAdminOption' class: Administration options */\r\n function VpnAdminOption(init) {\r\n /** Name */\r\n this.Name_str = \"\";\r\n /** Data */\r\n this.Value_u32 = 0;\r\n /** Descrption */\r\n this.Descrption_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAdminOption;\r\n}());\r\nexports.VpnAdminOption = VpnAdminOption;\r\n/** Administration options list */\r\nvar VpnRpcAdminOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAdminOption' class: Administration options list */\r\n function VpnRpcAdminOption(init) {\r\n /** Virtual HUB name */\r\n this.HubName_str = \"\";\r\n /** List data */\r\n this.AdminOptionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAdminOption;\r\n}());\r\nexports.VpnRpcAdminOption = VpnRpcAdminOption;\r\n/** Connection state to the controller */\r\nvar VpnRpcFarmConnectionStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmConnectionStatus' class: Connection state to the controller */\r\n function VpnRpcFarmConnectionStatus(init) {\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Online state */\r\n this.Online_bool = false;\r\n /** Last error code */\r\n this.LastError_u32 = 0;\r\n /** Connection start time */\r\n this.StartedTime_dt = new Date();\r\n /** First connection time */\r\n this.FirstConnectedTime_dt = new Date();\r\n /** Connection time of this time */\r\n this.CurrentConnectedTime_dt = new Date();\r\n /** Number of retries */\r\n this.NumTry_u32 = 0;\r\n /** Number of connection count */\r\n this.NumConnected_u32 = 0;\r\n /** Connection failure count */\r\n this.NumFailed_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmConnectionStatus;\r\n}());\r\nexports.VpnRpcFarmConnectionStatus = VpnRpcFarmConnectionStatus;\r\n/** HUB item of each farm member */\r\nvar VpnRpcFarmHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmHub' class: HUB item of each farm member */\r\n function VpnRpcFarmHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Dynamic HUB */\r\n this.DynamicHub_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmHub;\r\n}());\r\nexports.VpnRpcFarmHub = VpnRpcFarmHub;\r\n/** Server farm member information acquisition */\r\nvar VpnRpcFarmInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmInfo' class: Server farm member information acquisition */\r\n function VpnRpcFarmInfo(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** The flag if the server is Cluster Controller (false: Cluster Member servers) */\r\n this.Controller_bool = false;\r\n /** Connection Established Time */\r\n this.ConnectedTime_dt = new Date();\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Point */\r\n this.Point_u32 = 0;\r\n /** Number of Public Ports */\r\n this.NumPort_u32 = 0;\r\n /** Public Ports */\r\n this.Ports_u32 = [];\r\n /** Server certificate */\r\n this.ServerCert_bin = new Uint8Array([]);\r\n /** Number of farm HUB */\r\n this.NumFarmHub_u32 = 0;\r\n /** The hosted Virtual Hub list */\r\n this.HubsList = [];\r\n /** Number of hosted VPN sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Performance Standard Ratio */\r\n this.Weight_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmInfo;\r\n}());\r\nexports.VpnRpcFarmInfo = VpnRpcFarmInfo;\r\n/** Server farm configuration */\r\nvar VpnRpcFarm = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarm' class: Server farm configuration */\r\n function VpnRpcFarm(init) {\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Valid only for Cluster Member servers. Number of the Ports_u32 element. */\r\n this.NumPort_u32 = 0;\r\n /** Valid only for Cluster Member servers. Specify the list of public port numbers on this server. The list must have at least one public port number set, and it is also possible to set multiple public port numbers. */\r\n this.Ports_u32 = [];\r\n /** Valid only for Cluster Member servers. Specify the public IP address of this server. If you wish to leave public IP address unspecified, specify the empty string. When a public IP address is not specified, the IP address of the network interface used when connecting to the cluster controller will be automatically used. */\r\n this.PublicIp_ip = \"\";\r\n /** Valid only for Cluster Member servers. Specify the host name or IP address of the destination cluster controller. */\r\n this.ControllerName_str = \"\";\r\n /** Valid only for Cluster Member servers. Specify the TCP port number of the destination cluster controller. */\r\n this.ControllerPort_u32 = 0;\r\n /** Valid only for Cluster Member servers. Specify the password required to connect to the destination controller. It needs to be the same as an administrator password on the destination controller. */\r\n this.MemberPasswordPlaintext_str = \"\";\r\n /** This sets a value for the performance standard ratio of this VPN Server. This is the standard value for when load balancing is performed in the cluster. For example, making only one machine 200 while the other members have a status of 100, will regulate that machine to receive twice as many connections as the other members. Specify 1 or higher for the value. If this parameter is left unspecified, 100 will be used. */\r\n this.Weight_u32 = 0;\r\n /** Valid only for Cluster Controller server. By specifying true, the VPN Server will operate only as a controller on the cluster and it will always distribute general VPN Client connections to members other than itself. This function is used in high-load environments. */\r\n this.ControllerOnly_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarm;\r\n}());\r\nexports.VpnRpcFarm = VpnRpcFarm;\r\n/** Log switch type */\r\nvar VpnRpcLogSwitchType;\r\n(function (VpnRpcLogSwitchType) {\r\n /** No switching */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"No\"] = 0] = \"No\";\r\n /** Secondly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Second\"] = 1] = \"Second\";\r\n /** Minutely basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Minute\"] = 2] = \"Minute\";\r\n /** Hourly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Hour\"] = 3] = \"Hour\";\r\n /** Daily basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Day\"] = 4] = \"Day\";\r\n /** Monthly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Month\"] = 5] = \"Month\";\r\n})(VpnRpcLogSwitchType = exports.VpnRpcLogSwitchType || (exports.VpnRpcLogSwitchType = {}));\r\n/** Packet log settings */\r\nvar VpnRpcPacketLogSetting;\r\n(function (VpnRpcPacketLogSetting) {\r\n /** Not save */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"None\"] = 0] = \"None\";\r\n /** Only header */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"Header\"] = 1] = \"Header\";\r\n /** All payloads */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"All\"] = 2] = \"All\";\r\n})(VpnRpcPacketLogSetting = exports.VpnRpcPacketLogSetting || (exports.VpnRpcPacketLogSetting = {}));\r\n/** Packet log settings array index */\r\nvar VpnRpcPacketLogSettingIndex;\r\n(function (VpnRpcPacketLogSettingIndex) {\r\n /** TCP connection log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"TcpConnection\"] = 0] = \"TcpConnection\";\r\n /** TCP packet log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"TcpAll\"] = 1] = \"TcpAll\";\r\n /** DHCP Log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Dhcp\"] = 2] = \"Dhcp\";\r\n /** UDP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Udp\"] = 3] = \"Udp\";\r\n /** ICMP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Icmp\"] = 4] = \"Icmp\";\r\n /** IP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Ip\"] = 5] = \"Ip\";\r\n /** ARP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Arp\"] = 6] = \"Arp\";\r\n /** Ethernet log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Ethernet\"] = 7] = \"Ethernet\";\r\n})(VpnRpcPacketLogSettingIndex = exports.VpnRpcPacketLogSettingIndex || (exports.VpnRpcPacketLogSettingIndex = {}));\r\n/** HUB log settings */\r\nvar VpnRpcHubLog = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubLog' class: HUB log settings */\r\n function VpnRpcHubLog(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The flag to enable / disable saving the security log */\r\n this.SaveSecurityLog_bool = false;\r\n /** The log filename switching setting of the security log */\r\n this.SecurityLogSwitchType_u32 = 0;\r\n /** The flag to enable / disable saving the security log */\r\n this.SavePacketLog_bool = false;\r\n /** The log filename switching settings of the packet logs */\r\n this.PacketLogSwitchType_u32 = 0;\r\n /** Specify the save contents of the packet logs (uint * 16 array). The index numbers: TcpConnection = 0, TcpAll = 1, DHCP = 2, UDP = 3, ICMP = 4, IP = 5, ARP = 6, Ethernet = 7. */\r\n this.PacketLogConfig_u32 = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubLog;\r\n}());\r\nexports.VpnRpcHubLog = VpnRpcHubLog;\r\n/** RADIUS server options */\r\nvar VpnRpcRadius = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcRadius' class: RADIUS server options */\r\n function VpnRpcRadius(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** RADIUS server name */\r\n this.RadiusServerName_str = \"\";\r\n /** RADIUS port number */\r\n this.RadiusPort_u32 = 0;\r\n /** Secret key */\r\n this.RadiusSecret_str = \"\";\r\n /** Radius retry interval */\r\n this.RadiusRetryInterval_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcRadius;\r\n}());\r\nexports.VpnRpcRadius = VpnRpcRadius;\r\n/** Get the state HUB */\r\nvar VpnRpcHubStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubStatus' class: Get the state HUB */\r\n function VpnRpcHubStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Online */\r\n this.Online_bool = false;\r\n /** Type of HUB */\r\n this.HubType_u32 = 0;\r\n /** Number of sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of sessions (client mode) */\r\n this.NumSessionsClient_u32 = 0;\r\n /** Number of sessions (bridge mode) */\r\n this.NumSessionsBridge_u32 = 0;\r\n /** Number of Access list entries */\r\n this.NumAccessLists_u32 = 0;\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Number of groups */\r\n this.NumGroups_u32 = 0;\r\n /** Number of MAC table entries */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of IP table entries */\r\n this.NumIpTables_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** Whether SecureNAT is enabled */\r\n this.SecureNATEnabled_bool = false;\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Number of logins */\r\n this.NumLogin_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubStatus;\r\n}());\r\nexports.VpnRpcHubStatus = VpnRpcHubStatus;\r\n/** List of services provided by IPsec server */\r\nvar VpnIPsecServices = /** @class */ (function () {\r\n /** Constructor for the 'VpnIPsecServices' class: List of services provided by IPsec server */\r\n function VpnIPsecServices(init) {\r\n /** Enable or Disable the L2TP Server Function (Raw L2TP with No Encryptions). To accept special VPN clients, enable this option. */\r\n this.L2TP_Raw_bool = false;\r\n /** Enable or Disable the L2TP over IPsec Server Function. To accept VPN connections from iPhone, iPad, Android, Windows or Mac OS X, enable this option. */\r\n this.L2TP_IPsec_bool = false;\r\n /** Enable or Disable the EtherIP / L2TPv3 over IPsec Server Function (for site-to-site VPN Server function). Router Products which are compatible with EtherIP over IPsec can connect to Virtual Hubs on the VPN Server and establish Layer-2 (Ethernet) Bridging. */\r\n this.EtherIP_IPsec_bool = false;\r\n /** Specify the IPsec Pre-Shared Key. An IPsec Pre-Shared Key is also called as \"PSK\" or \"secret\". Specify it equal or less than 8 letters, and distribute it to every users who will connect to the VPN Server. Please note: Google Android 4.0 has a bug which a Pre-Shared Key with 10 or more letters causes a unexpected behavior. For that reason, the letters of a Pre-Shared Key should be 9 or less characters. */\r\n this.IPsec_Secret_str = \"\";\r\n /** Specify the default Virtual HUB in a case of omitting the name of HUB on the Username. Users should specify their username such as \"Username@Target Virtual HUB Name\" to connect this L2TP Server. If the designation of the Virtual Hub is omitted, the above HUB will be used as the target. */\r\n this.L2TP_DefaultHub_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnIPsecServices;\r\n}());\r\nexports.VpnIPsecServices = VpnIPsecServices;\r\n/** Keep alive protocol */\r\nvar VpnRpcKeepAliveProtocol;\r\n(function (VpnRpcKeepAliveProtocol) {\r\n /** TCP */\r\n VpnRpcKeepAliveProtocol[VpnRpcKeepAliveProtocol[\"TCP\"] = 0] = \"TCP\";\r\n /** UDP */\r\n VpnRpcKeepAliveProtocol[VpnRpcKeepAliveProtocol[\"UDP\"] = 1] = \"UDP\";\r\n})(VpnRpcKeepAliveProtocol = exports.VpnRpcKeepAliveProtocol || (exports.VpnRpcKeepAliveProtocol = {}));\r\n/** Keep Alive settings */\r\nvar VpnRpcKeep = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcKeep' class: Keep Alive settings */\r\n function VpnRpcKeep(init) {\r\n /** The flag to enable keep-alive to the Internet */\r\n this.UseKeepConnect_bool = false;\r\n /** Specify the host name or IP address of the destination */\r\n this.KeepConnectHost_str = \"\";\r\n /** Specify the port number of the destination */\r\n this.KeepConnectPort_u32 = 0;\r\n /** Protocol type */\r\n this.KeepConnectProtocol_u32 = 0;\r\n /** Interval Between Packets Sends (Seconds) */\r\n this.KeepConnectInterval_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcKeep;\r\n}());\r\nexports.VpnRpcKeep = VpnRpcKeep;\r\n/** State of the client session */\r\nvar VpnRpcClientSessionStatus;\r\n(function (VpnRpcClientSessionStatus) {\r\n /** Connecting */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Connecting\"] = 0] = \"Connecting\";\r\n /** Negotiating */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Negotiation\"] = 1] = \"Negotiation\";\r\n /** During user authentication */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Auth\"] = 2] = \"Auth\";\r\n /** Connection complete */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Established\"] = 3] = \"Established\";\r\n /** Wait to retry */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Retry\"] = 4] = \"Retry\";\r\n /** Idle state */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Idle\"] = 5] = \"Idle\";\r\n})(VpnRpcClientSessionStatus = exports.VpnRpcClientSessionStatus || (exports.VpnRpcClientSessionStatus = {}));\r\n/** Get the link state */\r\nvar VpnRpcLinkStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLinkStatus' class: Get the link state */\r\n function VpnRpcLinkStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_Ex_str = \"\";\r\n /** The name of the cascade connection */\r\n this.AccountName_utf = \"\";\r\n /** The flag whether the cascade connection is enabled */\r\n this.Active_bool = false;\r\n /** The flag whether the cascade connection is established */\r\n this.Connected_bool = false;\r\n /** The session status */\r\n this.SessionStatus_u32 = 0;\r\n /** The destination VPN server name */\r\n this.ServerName_str = \"\";\r\n /** The port number of the server */\r\n this.ServerPort_u32 = 0;\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server product version */\r\n this.ServerProductVer_u32 = 0;\r\n /** Server product build number */\r\n this.ServerProductBuild_u32 = 0;\r\n /** Server's X.509 certificate */\r\n this.ServerX_bin = new Uint8Array([]);\r\n /** Client certificate */\r\n this.ClientX_bin = new Uint8Array([]);\r\n /** Connection start time */\r\n this.StartTime_dt = new Date();\r\n /** Connection completion time of the first connection */\r\n this.FirstConnectionEstablisiedTime_dt = new Date();\r\n /** Connection completion time of this connection */\r\n this.CurrentConnectionEstablishTime_dt = new Date();\r\n /** Number of connections have been established so far */\r\n this.NumConnectionsEatablished_u32 = 0;\r\n /** Half-connection */\r\n this.HalfConnection_bool = false;\r\n /** VoIP / QoS */\r\n this.QoS_bool = false;\r\n /** Maximum number of the underlying TCP connections */\r\n this.MaxTcpConnections_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of underlying inbound TCP connections */\r\n this.NumTcpConnectionsUpload_u32 = 0;\r\n /** Number of underlying outbound TCP connections */\r\n this.NumTcpConnectionsDownload_u32 = 0;\r\n /** Use of encryption */\r\n this.UseEncrypt_bool = false;\r\n /** Cipher algorithm name */\r\n this.CipherName_str = \"\";\r\n /** Use of compression */\r\n this.UseCompress_bool = false;\r\n /** The flag whether this is a R-UDP session */\r\n this.IsRUDPSession_bool = false;\r\n /** Underlying physical communication protocol */\r\n this.UnderlayProtocol_str = \"\";\r\n /** The UDP acceleration is enabled */\r\n this.IsUdpAccelerationEnabled_bool = false;\r\n /** The UDP acceleration is being actually used */\r\n this.IsUsingUdpAcceleration_bool = false;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** Connection name */\r\n this.ConnectionName_str = \"\";\r\n /** Session key */\r\n this.SessionKey_bin = new Uint8Array([]);\r\n /** Total transmitted data size */\r\n this.TotalSendSize_u64 = 0;\r\n /** Total received data size */\r\n this.TotalRecvSize_u64 = 0;\r\n /** Total transmitted data size (no compression) */\r\n this.TotalSendSizeReal_u64 = 0;\r\n /** Total received data size (no compression) */\r\n this.TotalRecvSizeReal_u64 = 0;\r\n /** The flag whether the VPN session is Bridge Mode */\r\n this.IsBridgeMode_bool = false;\r\n /** The flag whether the VPN session is Monitor mode */\r\n this.IsMonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLinkStatus;\r\n}());\r\nexports.VpnRpcLinkStatus = VpnRpcLinkStatus;\r\n/** Setting of SSTP and OpenVPN */\r\nvar VpnOpenVpnSstpConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnOpenVpnSstpConfig' class: Setting of SSTP and OpenVPN */\r\n function VpnOpenVpnSstpConfig(init) {\r\n /** Specify true to enable the OpenVPN Clone Server Function. Specify false to disable. */\r\n this.EnableOpenVPN_bool = false;\r\n /** Specify UDP ports to listen for OpenVPN. Multiple UDP ports can be specified with splitting by space or comma letters, for example: \"1194, 2001, 2010, 2012\". The default port for OpenVPN is UDP 1194. You can specify any other UDP ports. */\r\n this.OpenVPNPortList_str = \"\";\r\n /** pecify true to enable the Microsoft SSTP VPN Clone Server Function. Specify false to disable. */\r\n this.EnableSSTP_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnOpenVpnSstpConfig;\r\n}());\r\nexports.VpnOpenVpnSstpConfig = VpnOpenVpnSstpConfig;\r\n/** Virtual host option */\r\nvar VpnVhOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnVhOption' class: Virtual host option */\r\n function VpnVhOption(init) {\r\n /** Target Virtual HUB name */\r\n this.RpcHubName_str = \"\";\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Subnet mask */\r\n this.Mask_ip = \"\";\r\n /** Use flag of the Virtual NAT function */\r\n this.UseNat_bool = false;\r\n /** MTU value (Standard: 1500) */\r\n this.Mtu_u32 = 0;\r\n /** NAT TCP timeout in seconds */\r\n this.NatTcpTimeout_u32 = 0;\r\n /** NAT UDP timeout in seconds */\r\n this.NatUdpTimeout_u32 = 0;\r\n /** Using flag of DHCP function */\r\n this.UseDhcp_bool = false;\r\n /** Specify the start point of the address band to be distributed to the client. (Example: 192.168.30.10) */\r\n this.DhcpLeaseIPStart_ip = \"\";\r\n /** Specify the end point of the address band to be distributed to the client. (Example: 192.168.30.200) */\r\n this.DhcpLeaseIPEnd_ip = \"\";\r\n /** Specify the subnet mask to be specified for the client. (Example: 255.255.255.0) */\r\n this.DhcpSubnetMask_ip = \"\";\r\n /** Specify the expiration date in second units for leasing an IP address to a client. */\r\n this.DhcpExpireTimeSpan_u32 = 0;\r\n /** Specify the IP address of the default gateway to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify 0 or none, then the client will not be notified of the default gateway. */\r\n this.DhcpGatewayAddress_ip = \"\";\r\n /** Specify the IP address of the primary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify empty, then the client will not be notified of the DNS Server address. */\r\n this.DhcpDnsServerAddress_ip = \"\";\r\n /** Specify the IP address of the secondary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify empty, then the client will not be notified of the DNS Server address. */\r\n this.DhcpDnsServerAddress2_ip = \"\";\r\n /** Specify the domain name to be notified to the client. If you specify none, then the client will not be notified of the domain name. */\r\n this.DhcpDomainName_str = \"\";\r\n /** Specify whether or not to save the Virtual DHCP Server operation in the Virtual Hub security log. Specify true to save it. This value is interlinked with the Virtual NAT Function log save setting. */\r\n this.SaveLog_bool = false;\r\n /** The flag to enable the DhcpPushRoutes_str field. */\r\n this.ApplyDhcpPushRoutes_bool = false;\r\n /** Specify the static routing table to push. Example: \"192.168.5.0/255.255.255.0/192.168.4.254, 10.0.0.0/255.0.0.0/192.168.4.253\" Split multiple entries (maximum: 64 entries) by comma or space characters. Each entry must be specified in the \"IP network address/subnet mask/gateway IP address\" format. This Virtual DHCP Server can push the classless static routes (RFC 3442) with DHCP reply messages to VPN clients. Whether or not a VPN client can recognize the classless static routes (RFC 3442) depends on the target VPN client software. SoftEther VPN Client and OpenVPN Client are supporting the classless static routes. On L2TP/IPsec and MS-SSTP protocols, the compatibility depends on the implementation of the client software. You can realize the split tunneling if you clear the default gateway field on the Virtual DHCP Server options. On the client side, L2TP/IPsec and MS-SSTP clients need to be configured not to set up the default gateway for the split tunneling usage. You can also push the classless static routes (RFC 3442) by your existing external DHCP server. In that case, disable the Virtual DHCP Server function on SecureNAT, and you need not to set up the classless routes on this API. See the RFC 3442 to understand the classless routes. */\r\n this.DhcpPushRoutes_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnVhOption;\r\n}());\r\nexports.VpnVhOption = VpnVhOption;\r\n/** RPC_NAT_STATUS */\r\nvar VpnRpcNatStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcNatStatus' class: RPC_NAT_STATUS */\r\n function VpnRpcNatStatus(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** Number of TCP sessions */\r\n this.NumTcpSessions_u32 = 0;\r\n /** Ntmber of UDP sessions */\r\n this.NumUdpSessions_u32 = 0;\r\n /** Nymber of ICMP sessions */\r\n this.NumIcmpSessions_u32 = 0;\r\n /** Number of DNS sessions */\r\n this.NumDnsSessions_u32 = 0;\r\n /** Number of DHCP clients */\r\n this.NumDhcpClients_u32 = 0;\r\n /** Whether the NAT is operating in the Kernel Mode */\r\n this.IsKernelMode_bool = false;\r\n /** Whether the NAT is operating in the Raw IP Mode */\r\n this.IsRawIpMode_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcNatStatus;\r\n}());\r\nexports.VpnRpcNatStatus = VpnRpcNatStatus;\r\n/** Key pair */\r\nvar VpnRpcKeyPair = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcKeyPair' class: Key pair */\r\n function VpnRpcKeyPair(init) {\r\n /** The body of the certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n /** The body of the private key */\r\n this.Key_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcKeyPair;\r\n}());\r\nexports.VpnRpcKeyPair = VpnRpcKeyPair;\r\n/** Single string value */\r\nvar VpnRpcStr = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcStr' class: Single string value */\r\n function VpnRpcStr(init) {\r\n /** A string value */\r\n this.String_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcStr;\r\n}());\r\nexports.VpnRpcStr = VpnRpcStr;\r\n/** Type of VPN Server */\r\nvar VpnRpcServerType;\r\n(function (VpnRpcServerType) {\r\n /** Stand-alone server */\r\n VpnRpcServerType[VpnRpcServerType[\"Standalone\"] = 0] = \"Standalone\";\r\n /** Farm controller server */\r\n VpnRpcServerType[VpnRpcServerType[\"FarmController\"] = 1] = \"FarmController\";\r\n /** Farm member server */\r\n VpnRpcServerType[VpnRpcServerType[\"FarmMember\"] = 2] = \"FarmMember\";\r\n})(VpnRpcServerType = exports.VpnRpcServerType || (exports.VpnRpcServerType = {}));\r\n/** Operating system type */\r\nvar VpnRpcOsType;\r\n(function (VpnRpcOsType) {\r\n /** Windows 95 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_95\"] = 1100] = \"WINDOWS_95\";\r\n /** Windows 98 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_98\"] = 1200] = \"WINDOWS_98\";\r\n /** Windows Me */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_ME\"] = 1300] = \"WINDOWS_ME\";\r\n /** Windows (unknown) */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_UNKNOWN\"] = 1400] = \"WINDOWS_UNKNOWN\";\r\n /** Windows NT 4.0 Workstation */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_WORKSTATION\"] = 2100] = \"WINDOWS_NT_4_WORKSTATION\";\r\n /** Windows NT 4.0 Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SERVER\"] = 2110] = \"WINDOWS_NT_4_SERVER\";\r\n /** Windows NT 4.0 Server, Enterprise Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SERVER_ENTERPRISE\"] = 2111] = \"WINDOWS_NT_4_SERVER_ENTERPRISE\";\r\n /** Windows NT 4.0 Terminal Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_TERMINAL_SERVER\"] = 2112] = \"WINDOWS_NT_4_TERMINAL_SERVER\";\r\n /** BackOffice Server 4.5 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_BACKOFFICE\"] = 2113] = \"WINDOWS_NT_4_BACKOFFICE\";\r\n /** Small Business Server 4.5 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SMS\"] = 2114] = \"WINDOWS_NT_4_SMS\";\r\n /** Windows 2000 Professional */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_PROFESSIONAL\"] = 2200] = \"WINDOWS_2000_PROFESSIONAL\";\r\n /** Windows 2000 Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_SERVER\"] = 2211] = \"WINDOWS_2000_SERVER\";\r\n /** Windows 2000 Advanced Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_ADVANCED_SERVER\"] = 2212] = \"WINDOWS_2000_ADVANCED_SERVER\";\r\n /** Windows 2000 Datacenter Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_DATACENTER_SERVER\"] = 2213] = \"WINDOWS_2000_DATACENTER_SERVER\";\r\n /** BackOffice Server 2000 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_BACKOFFICE\"] = 2214] = \"WINDOWS_2000_BACKOFFICE\";\r\n /** Small Business Server 2000 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_SBS\"] = 2215] = \"WINDOWS_2000_SBS\";\r\n /** Windows XP Home Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_XP_HOME\"] = 2300] = \"WINDOWS_XP_HOME\";\r\n /** Windows XP Professional */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_XP_PROFESSIONAL\"] = 2301] = \"WINDOWS_XP_PROFESSIONAL\";\r\n /** Windows Server 2003 Web Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_WEB\"] = 2410] = \"WINDOWS_2003_WEB\";\r\n /** Windows Server 2003 Standard Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_STANDARD\"] = 2411] = \"WINDOWS_2003_STANDARD\";\r\n /** Windows Server 2003 Enterprise Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_ENTERPRISE\"] = 2412] = \"WINDOWS_2003_ENTERPRISE\";\r\n /** Windows Server 2003 DataCenter Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_DATACENTER\"] = 2413] = \"WINDOWS_2003_DATACENTER\";\r\n /** BackOffice Server 2003 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_BACKOFFICE\"] = 2414] = \"WINDOWS_2003_BACKOFFICE\";\r\n /** Small Business Server 2003 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_SBS\"] = 2415] = \"WINDOWS_2003_SBS\";\r\n /** Windows Vista */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_LONGHORN_PROFESSIONAL\"] = 2500] = \"WINDOWS_LONGHORN_PROFESSIONAL\";\r\n /** Windows Server 2008 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_LONGHORN_SERVER\"] = 2510] = \"WINDOWS_LONGHORN_SERVER\";\r\n /** Windows 7 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_7\"] = 2600] = \"WINDOWS_7\";\r\n /** Windows Server 2008 R2 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_2008_R2\"] = 2610] = \"WINDOWS_SERVER_2008_R2\";\r\n /** Windows 8 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_8\"] = 2700] = \"WINDOWS_8\";\r\n /** Windows Server 2012 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_8\"] = 2710] = \"WINDOWS_SERVER_8\";\r\n /** Windows 8.1 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_81\"] = 2701] = \"WINDOWS_81\";\r\n /** Windows Server 2012 R2 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_81\"] = 2711] = \"WINDOWS_SERVER_81\";\r\n /** Windows 10 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_10\"] = 2702] = \"WINDOWS_10\";\r\n /** Windows Server 10 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_10\"] = 2712] = \"WINDOWS_SERVER_10\";\r\n /** Windows 11 or later */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_11\"] = 2800] = \"WINDOWS_11\";\r\n /** Windows Server 11 or later */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_11\"] = 2810] = \"WINDOWS_SERVER_11\";\r\n /** Unknown UNIX */\r\n VpnRpcOsType[VpnRpcOsType[\"UNIX_UNKNOWN\"] = 3000] = \"UNIX_UNKNOWN\";\r\n /** Linux */\r\n VpnRpcOsType[VpnRpcOsType[\"LINUX\"] = 3100] = \"LINUX\";\r\n /** Solaris */\r\n VpnRpcOsType[VpnRpcOsType[\"SOLARIS\"] = 3200] = \"SOLARIS\";\r\n /** Cygwin */\r\n VpnRpcOsType[VpnRpcOsType[\"CYGWIN\"] = 3300] = \"CYGWIN\";\r\n /** BSD */\r\n VpnRpcOsType[VpnRpcOsType[\"BSD\"] = 3400] = \"BSD\";\r\n /** MacOS X */\r\n VpnRpcOsType[VpnRpcOsType[\"MACOS_X\"] = 3500] = \"MACOS_X\";\r\n})(VpnRpcOsType = exports.VpnRpcOsType || (exports.VpnRpcOsType = {}));\r\n/** VPN Server Information */\r\nvar VpnRpcServerInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcServerInfo' class: VPN Server Information */\r\n function VpnRpcServerInfo(init) {\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server version string */\r\n this.ServerVersionString_str = \"\";\r\n /** Server build information string */\r\n this.ServerBuildInfoString_str = \"\";\r\n /** Server version integer value */\r\n this.ServerVerInt_u32 = 0;\r\n /** Server build number integer value */\r\n this.ServerBuildInt_u32 = 0;\r\n /** Server host name */\r\n this.ServerHostName_str = \"\";\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Build date and time of the server */\r\n this.ServerBuildDate_dt = new Date();\r\n /** Family name */\r\n this.ServerFamilyName_str = \"\";\r\n /** OS type */\r\n this.OsType_u32 = 0;\r\n /** Service pack number */\r\n this.OsServicePack_u32 = 0;\r\n /** OS system name */\r\n this.OsSystemName_str = \"\";\r\n /** OS product name */\r\n this.OsProductName_str = \"\";\r\n /** OS vendor name */\r\n this.OsVendorName_str = \"\";\r\n /** OS version */\r\n this.OsVersion_str = \"\";\r\n /** Kernel name */\r\n this.KernelName_str = \"\";\r\n /** Kernel version */\r\n this.KernelVersion_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcServerInfo;\r\n}());\r\nexports.VpnRpcServerInfo = VpnRpcServerInfo;\r\n/** Server status */\r\nvar VpnRpcServerStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcServerStatus' class: Server status */\r\n function VpnRpcServerStatus(init) {\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Total number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of Local TCP connections */\r\n this.NumTcpConnectionsLocal_u32 = 0;\r\n /** Number of remote TCP connections */\r\n this.NumTcpConnectionsRemote_u32 = 0;\r\n /** Total number of HUBs */\r\n this.NumHubTotal_u32 = 0;\r\n /** Nymber of stand-alone HUB */\r\n this.NumHubStandalone_u32 = 0;\r\n /** Number of static HUBs */\r\n this.NumHubStatic_u32 = 0;\r\n /** Number of Dynamic HUBs */\r\n this.NumHubDynamic_u32 = 0;\r\n /** Total number of sessions */\r\n this.NumSessionsTotal_u32 = 0;\r\n /** Number of local VPN sessions */\r\n this.NumSessionsLocal_u32 = 0;\r\n /** The number of remote sessions */\r\n this.NumSessionsRemote_u32 = 0;\r\n /** Number of MAC table entries (total sum of all Virtual Hubs) */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of IP table entries (total sum of all Virtual Hubs) */\r\n this.NumIpTables_u32 = 0;\r\n /** Number of users (total sum of all Virtual Hubs) */\r\n this.NumUsers_u32 = 0;\r\n /** Number of groups (total sum of all Virtual Hubs) */\r\n this.NumGroups_u32 = 0;\r\n /** Number of assigned bridge licenses (Useful to make a commercial version) */\r\n this.AssignedBridgeLicenses_u32 = 0;\r\n /** Number of assigned client licenses (Useful to make a commercial version) */\r\n this.AssignedClientLicenses_u32 = 0;\r\n /** Number of Assigned bridge license (cluster-wide), useful to make a commercial version */\r\n this.AssignedBridgeLicensesTotal_u32 = 0;\r\n /** Number of assigned client licenses (cluster-wide), useful to make a commercial version */\r\n this.AssignedClientLicensesTotal_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** Current time */\r\n this.CurrentTime_dt = new Date();\r\n /** 64 bit High-Precision Logical System Clock */\r\n this.CurrentTick_u64 = 0;\r\n /** VPN Server Start-up time */\r\n this.StartTime_dt = new Date();\r\n /** Memory information: Total Memory */\r\n this.TotalMemory_u64 = 0;\r\n /** Memory information: Used Memory */\r\n this.UsedMemory_u64 = 0;\r\n /** Memory information: Free Memory */\r\n this.FreeMemory_u64 = 0;\r\n /** Memory information: Total Phys */\r\n this.TotalPhys_u64 = 0;\r\n /** Memory information: Used Phys */\r\n this.UsedPhys_u64 = 0;\r\n /** Memory information: Free Phys */\r\n this.FreePhys_u64 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcServerStatus;\r\n}());\r\nexports.VpnRpcServerStatus = VpnRpcServerStatus;\r\n/** VPN Session status */\r\nvar VpnRpcSessionStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSessionStatus' class: VPN Session status */\r\n function VpnRpcSessionStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** VPN session name */\r\n this.Name_str = \"\";\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** Real user name which was used for the authentication */\r\n this.RealUsername_str = \"\";\r\n /** Group name */\r\n this.GroupName_str = \"\";\r\n /** Is Cascade Session */\r\n this.LinkMode_bool = false;\r\n /** Client IP address */\r\n this.Client_Ip_Address_ip = \"\";\r\n /** Client host name */\r\n this.SessionStatus_ClientHostName_str = \"\";\r\n /** Operation flag */\r\n this.Active_bool = false;\r\n /** Connected flag */\r\n this.Connected_bool = false;\r\n /** State of the client session */\r\n this.SessionStatus_u32 = 0;\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** Port number of the server */\r\n this.ServerPort_u32 = 0;\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server product version */\r\n this.ServerProductVer_u32 = 0;\r\n /** Server product build number */\r\n this.ServerProductBuild_u32 = 0;\r\n /** Connection start time */\r\n this.StartTime_dt = new Date();\r\n /** Connection completion time of the first connection */\r\n this.FirstConnectionEstablisiedTime_dt = new Date();\r\n /** Connection completion time of this connection */\r\n this.CurrentConnectionEstablishTime_dt = new Date();\r\n /** Number of connections have been established so far */\r\n this.NumConnectionsEatablished_u32 = 0;\r\n /** Half-connection */\r\n this.HalfConnection_bool = false;\r\n /** VoIP / QoS */\r\n this.QoS_bool = false;\r\n /** Maximum number of the underlying TCP connections */\r\n this.MaxTcpConnections_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of inbound underlying connections */\r\n this.NumTcpConnectionsUpload_u32 = 0;\r\n /** Number of outbound underlying connections */\r\n this.NumTcpConnectionsDownload_u32 = 0;\r\n /** Use of encryption */\r\n this.UseEncrypt_bool = false;\r\n /** Cipher algorithm name */\r\n this.CipherName_str = \"\";\r\n /** Use of compression */\r\n this.UseCompress_bool = false;\r\n /** Is R-UDP session */\r\n this.IsRUDPSession_bool = false;\r\n /** Physical underlying communication protocol */\r\n this.UnderlayProtocol_str = \"\";\r\n /** The UDP acceleration is enabled */\r\n this.IsUdpAccelerationEnabled_bool = false;\r\n /** Using the UDP acceleration function */\r\n this.IsUsingUdpAcceleration_bool = false;\r\n /** VPN session name */\r\n this.SessionName_str = \"\";\r\n /** Connection name */\r\n this.ConnectionName_str = \"\";\r\n /** Session key */\r\n this.SessionKey_bin = new Uint8Array([]);\r\n /** Total transmitted data size */\r\n this.TotalSendSize_u64 = 0;\r\n /** Total received data size */\r\n this.TotalRecvSize_u64 = 0;\r\n /** Total transmitted data size (no compression) */\r\n this.TotalSendSizeReal_u64 = 0;\r\n /** Total received data size (no compression) */\r\n this.TotalRecvSizeReal_u64 = 0;\r\n /** Is Bridge Mode */\r\n this.IsBridgeMode_bool = false;\r\n /** Is Monitor mode */\r\n this.IsMonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n /** Client product name */\r\n this.ClientProductName_str = \"\";\r\n /** Client version */\r\n this.ClientProductVer_u32 = 0;\r\n /** Client build number */\r\n this.ClientProductBuild_u32 = 0;\r\n /** Client OS name */\r\n this.ClientOsName_str = \"\";\r\n /** Client OS version */\r\n this.ClientOsVer_str = \"\";\r\n /** Client OS Product ID */\r\n this.ClientOsProductId_str = \"\";\r\n /** Client host name */\r\n this.ClientHostname_str = \"\";\r\n /** Unique ID */\r\n this.UniqueId_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSessionStatus;\r\n}());\r\nexports.VpnRpcSessionStatus = VpnRpcSessionStatus;\r\n/** Set the special listener */\r\nvar VpnRpcSpecialListener = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSpecialListener' class: Set the special listener */\r\n function VpnRpcSpecialListener(init) {\r\n /** The flag to activate the VPN over ICMP server function */\r\n this.VpnOverIcmpListener_bool = false;\r\n /** The flag to activate the VPN over DNS function */\r\n this.VpnOverDnsListener_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSpecialListener;\r\n}());\r\nexports.VpnRpcSpecialListener = VpnRpcSpecialListener;\r\n/** Syslog configuration */\r\nvar VpnSyslogSaveType;\r\n(function (VpnSyslogSaveType) {\r\n /** Do not use syslog */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"None\"] = 0] = \"None\";\r\n /** Only server log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerLog\"] = 1] = \"ServerLog\";\r\n /** Server and Virtual HUB security log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerAndHubSecurityLog\"] = 2] = \"ServerAndHubSecurityLog\";\r\n /** Server, Virtual HUB security, and packet log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerAndHubAllLog\"] = 3] = \"ServerAndHubAllLog\";\r\n})(VpnSyslogSaveType = exports.VpnSyslogSaveType || (exports.VpnSyslogSaveType = {}));\r\n/** Syslog configuration */\r\nvar VpnSyslogSetting = /** @class */ (function () {\r\n /** Constructor for the 'VpnSyslogSetting' class: Syslog configuration */\r\n function VpnSyslogSetting(init) {\r\n /** The behavior of the syslog function */\r\n this.SaveType_u32 = 0;\r\n /** Specify the host name or IP address of the syslog server */\r\n this.Hostname_str = \"\";\r\n /** Specify the port number of the syslog server */\r\n this.Port_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnSyslogSetting;\r\n}());\r\nexports.VpnSyslogSetting = VpnSyslogSetting;\r\n/** VPN Gate Server Config */\r\nvar VpnVgsConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnVgsConfig' class: VPN Gate Server Config */\r\n function VpnVgsConfig(init) {\r\n /** Active flag */\r\n this.IsEnabled_bool = false;\r\n /** Message */\r\n this.Message_utf = \"\";\r\n /** Owner name */\r\n this.Owner_utf = \"\";\r\n /** Abuse email */\r\n this.Abuse_utf = \"\";\r\n /** Log save flag */\r\n this.NoLog_bool = false;\r\n /** Save log permanently */\r\n this.LogPermanent_bool = false;\r\n /** Enable the L2TP VPN function */\r\n this.EnableL2TP_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnVgsConfig;\r\n}());\r\nexports.VpnVgsConfig = VpnVgsConfig;\r\n/** Read a Log file */\r\nvar VpnRpcReadLogFile = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcReadLogFile' class: Read a Log file */\r\n function VpnRpcReadLogFile(init) {\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** File Path */\r\n this.FilePath_str = \"\";\r\n /** Offset to download. You have to call the ReadLogFile API multiple times to download the entire log file with requesting a part of the file by specifying the Offset_u32 field. */\r\n this.Offset_u32 = 0;\r\n /** Received buffer */\r\n this.Buffer_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcReadLogFile;\r\n}());\r\nexports.VpnRpcReadLogFile = VpnRpcReadLogFile;\r\n/** Rename link */\r\nvar VpnRpcRenameLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcRenameLink' class: Rename link */\r\n function VpnRpcRenameLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The old name of the cascade connection */\r\n this.OldAccountName_utf = \"\";\r\n /** The new name of the cascade connection */\r\n this.NewAccountName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcRenameLink;\r\n}());\r\nexports.VpnRpcRenameLink = VpnRpcRenameLink;\r\n/** Online or offline the HUB */\r\nvar VpnRpcSetHubOnline = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetHubOnline' class: Online or offline the HUB */\r\n function VpnRpcSetHubOnline(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Online / offline flag */\r\n this.Online_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetHubOnline;\r\n}());\r\nexports.VpnRpcSetHubOnline = VpnRpcSetHubOnline;\r\n/** Set Password */\r\nvar VpnRpcSetPassword = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetPassword' class: Set Password */\r\n function VpnRpcSetPassword(init) {\r\n /** The plaintext password */\r\n this.PlainTextPassword_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetPassword;\r\n}());\r\nexports.VpnRpcSetPassword = VpnRpcSetPassword;\r\n// --- Utility codes ---\r\n/** JSON-RPC request class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcRequest = /** @class */ (function () {\r\n function JsonRpcRequest(method, param, id) {\r\n if (method === void 0) { method = \"\"; }\r\n if (param === void 0) { param = null; }\r\n if (id === void 0) { id = \"\"; }\r\n this.jsonrpc = \"2.0\";\r\n this.method = method;\r\n this.params = param;\r\n this.id = id;\r\n }\r\n return JsonRpcRequest;\r\n}());\r\nexports.JsonRpcRequest = JsonRpcRequest;\r\n/** JSON-RPC error class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcError = /** @class */ (function () {\r\n function JsonRpcError(code, message, data) {\r\n if (code === void 0) { code = 0; }\r\n if (message === void 0) { message = \"\"; }\r\n if (data === void 0) { data = null; }\r\n this.code = code;\r\n this.message = message;\r\n this.data = data;\r\n }\r\n return JsonRpcError;\r\n}());\r\nexports.JsonRpcError = JsonRpcError;\r\n/** JSON-RPC response class with generics */\r\nvar JsonRpcResponse = /** @class */ (function () {\r\n function JsonRpcResponse() {\r\n this.jsonrpc = \"2.0\";\r\n this.result = null;\r\n this.error = null;\r\n this.id = \"\";\r\n }\r\n return JsonRpcResponse;\r\n}());\r\nexports.JsonRpcResponse = JsonRpcResponse;\r\n/** JSON-RPC client class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcClient = /** @class */ (function () {\r\n /**\r\n * JSON-RPC client class constructor\r\n * @param url The URL\r\n * @param headers Additional HTTP headers\r\n * @param send_credential Set true to use the same credential with the browsing web site. Valid only if the code is running on the web browser.\r\n */\r\n function JsonRpcClient(url, headers, send_credential, nodejs_https_client_reject_untrusted_server_cert) {\r\n this.BaseUrl = url;\r\n this.headers = headers;\r\n this.client = new HttpClient();\r\n this.client.SendCredential = send_credential;\r\n this.client.NodeJS_HTTPS_Client_Reject_Unauthorized = nodejs_https_client_reject_untrusted_server_cert;\r\n }\r\n /** A utility function to convert any object to JSON string */\r\n JsonRpcClient.ObjectToJson = function (obj) {\r\n return JSON.stringify(obj, function (key, value) {\r\n if (key.endsWith(\"_bin\")) {\r\n return Util_Base64_Encode(value);\r\n }\r\n return value;\r\n }, 4);\r\n };\r\n /** A utility function to convert JSON string to object */\r\n JsonRpcClient.JsonToObject = function (str) {\r\n return JSON.parse(str, function (key, value) {\r\n if (key.endsWith(\"_bin\")) {\r\n return Util_Base64_Decode(value);\r\n }\r\n else if (key.endsWith(\"_dt\")) {\r\n return new Date(value);\r\n }\r\n return value;\r\n });\r\n };\r\n /**\r\n * Call a single RPC call (without error check). You can wait for the response with Promise or await statement.\r\n * @param method_name The name of RPC method\r\n * @param param The parameters\r\n */\r\n JsonRpcClient.prototype.CallInternalAsync = function (method_name, param) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var id, req, req_string, http_response, ret_string;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n id = \"1\";\r\n req = new JsonRpcRequest(method_name, param, id);\r\n req_string = JsonRpcClient.ObjectToJson(req);\r\n if (debug_mode) {\r\n console.log(\"--- RPC Request Body ---\");\r\n console.log(req_string);\r\n console.log(\"------------------------\");\r\n }\r\n return [4 /*yield*/, this.client.PostAsync(this.BaseUrl, this.headers, req_string, \"application/json\")];\r\n case 1:\r\n http_response = _a.sent();\r\n ret_string = http_response.Body;\r\n if (debug_mode) {\r\n console.log(\"--- RPC Response Body ---\");\r\n console.log(ret_string);\r\n console.log(\"-------------------------\");\r\n }\r\n return [2 /*return*/, ret_string];\r\n }\r\n });\r\n });\r\n };\r\n /**\r\n * Call a single RPC call (with error check). You can wait for the response with Promise or await statement. In the case of error, it will be thrown.\r\n * @param method_name The name of RPC method\r\n * @param param The parameters\r\n */\r\n JsonRpcClient.prototype.CallAsync = function (method_name, param) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var ret_string, ret;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0: return [4 /*yield*/, this.CallInternalAsync(method_name, param)];\r\n case 1:\r\n ret_string = _a.sent();\r\n ret = JSON.parse(ret_string);\r\n if (is_null(ret.error) === false) {\r\n throw new JsonRpcException(ret.error);\r\n }\r\n return [2 /*return*/, ret.result];\r\n }\r\n });\r\n });\r\n };\r\n return JsonRpcClient;\r\n}());\r\nexports.JsonRpcClient = JsonRpcClient;\r\n/** JSON-RPC exception class */\r\nvar JsonRpcException = /** @class */ (function (_super) {\r\n __extends(JsonRpcException, _super);\r\n function JsonRpcException(error) {\r\n var _this = _super.call(this, \"Code=\" + error.code + \", Message=\" + error.message) || this;\r\n _this.Error = error;\r\n return _this;\r\n }\r\n return JsonRpcException;\r\n}(Error));\r\nexports.JsonRpcException = JsonRpcException;\r\n/** HTTP client exception class */\r\nvar HttpClientException = /** @class */ (function (_super) {\r\n __extends(HttpClientException, _super);\r\n function HttpClientException(message) {\r\n return _super.call(this, message) || this;\r\n }\r\n return HttpClientException;\r\n}(Error));\r\nexports.HttpClientException = HttpClientException;\r\n/** HTTP client response class */\r\nvar HttpClientResponse = /** @class */ (function () {\r\n function HttpClientResponse() {\r\n this.Body = \"\";\r\n }\r\n return HttpClientResponse;\r\n}());\r\nexports.HttpClientResponse = HttpClientResponse;\r\n/** An HTTP client which can be used in both web browsers and Node.js */\r\nvar HttpClient = /** @class */ (function () {\r\n function HttpClient() {\r\n this.TimeoutMsecs = 60 * 5 * 1000;\r\n this.SendCredential = true;\r\n this.NodeJS_HTTPS_Client_Reject_Unauthorized = false;\r\n }\r\n /** Post method. In web browsers this function will process the request by itself. In Node.js this function will call PostAsync_NodeJS() instead. */\r\n HttpClient.prototype.PostAsync = function (url, headers, req_body, req_media_type) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var fetch_header_list, _i, _a, name_1, fetch_init, fetch_response, ret, _b;\r\n return __generator(this, function (_c) {\r\n switch (_c.label) {\r\n case 0:\r\n if (is_node_js) {\r\n return [2 /*return*/, this.PostAsync_NodeJS(url, headers, req_body, req_media_type)];\r\n }\r\n fetch_header_list = new Headers();\r\n for (_i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {\r\n name_1 = _a[_i];\r\n fetch_header_list.append(name_1, headers[name_1]);\r\n }\r\n fetch_init = {\r\n mode: \"cors\",\r\n headers: fetch_header_list,\r\n credentials: (this.SendCredential ? \"include\" : \"omit\"),\r\n method: \"POST\",\r\n cache: \"no-cache\",\r\n keepalive: true,\r\n redirect: \"follow\",\r\n body: req_body\r\n };\r\n return [4 /*yield*/, fetch(url, fetch_init)];\r\n case 1:\r\n fetch_response = _c.sent();\r\n if (fetch_response.ok === false) {\r\n throw new HttpClientException(\"HTTP Error: \" + fetch_response.status + \" \" + fetch_response.statusText);\r\n }\r\n ret = new HttpClientResponse();\r\n _b = ret;\r\n return [4 /*yield*/, fetch_response.text()];\r\n case 2:\r\n _b.Body = _c.sent();\r\n return [2 /*return*/, ret];\r\n }\r\n });\r\n });\r\n };\r\n /** Post method for Node.js. */\r\n HttpClient.prototype.PostAsync_NodeJS = function (url, headers, req_body, req_media_type) {\r\n var https = __webpack_require__(/*! https */ \"./node_modules/https-browserify/index.js\");\r\n var keepAliveAgent = new https.Agent({ keepAlive: true });\r\n var urlparse = __webpack_require__(/*! url */ \"./node_modules/url/url.js\");\r\n var urlobj = urlparse.parse(url);\r\n if (is_null(urlobj.host))\r\n throw new Error(\"URL is invalid.\");\r\n var options = {\r\n host: urlobj.hostname,\r\n port: urlobj.port,\r\n path: urlobj.path,\r\n rejectUnauthorized: this.NodeJS_HTTPS_Client_Reject_Unauthorized,\r\n method: \"POST\",\r\n timeout: this.TimeoutMsecs,\r\n agent: keepAliveAgent\r\n };\r\n return new Promise(function (resolve, reject) {\r\n var req = https.request(options, function (res) {\r\n if (res.statusCode !== 200) {\r\n reject(new HttpClientException(\"HTTP Error: \" + res.statusCode + \" \" + res.statusMessage));\r\n }\r\n var recv_str = \"\";\r\n res.on(\"data\", function (body) {\r\n recv_str += body;\r\n });\r\n res.on(\"end\", function () {\r\n var ret = new HttpClientResponse();\r\n ret.Body = recv_str;\r\n resolve(ret);\r\n });\r\n }).on(\"error\", function (err) {\r\n throw err;\r\n });\r\n for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {\r\n var name_2 = _a[_i];\r\n req.setHeader(name_2, !is_null(headers[name_2]) ? headers[name_2] : \"\");\r\n }\r\n req.setHeader(\"Content-Type\", req_media_type);\r\n req.setHeader(\"Content-Length\", Buffer.byteLength(req_body));\r\n req.write(req_body);\r\n req.end();\r\n });\r\n };\r\n return HttpClient;\r\n}());\r\nexports.HttpClient = HttpClient;\r\n//////// BEGIN: Base64 encode / decode utility functions from https://github.com/beatgammit/base64-js\r\n// The MIT License(MIT)\r\n// Copyright(c) 2014\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy\r\n// of this software and associated documentation files(the \"Software\"), to deal\r\n// in the Software without restriction, including without limitation the rights\r\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is\r\n// furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in\r\n// all copies or substantial portions of the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n// THE SOFTWARE.\r\nvar lookup = [];\r\nvar revLookup = [];\r\nvar code = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\r\nfor (var i = 0, len = code.length; i < len; ++i) {\r\n lookup[i] = code[i];\r\n revLookup[code.charCodeAt(i)] = i;\r\n}\r\n// Support decoding URL-safe base64 strings, as Node.js does.\r\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\r\nrevLookup[\"-\".charCodeAt(0)] = 62;\r\nrevLookup[\"_\".charCodeAt(0)] = 63;\r\nfunction getLens(b64) {\r\n var len = b64.length;\r\n if (len % 4 > 0) {\r\n throw new Error(\"Invalid string. Length must be a multiple of 4\");\r\n }\r\n // Trim off extra bytes after placeholder bytes are found\r\n // See: https://github.com/beatgammit/base64-js/issues/42\r\n var validLen = b64.indexOf(\"=\");\r\n if (validLen === -1)\r\n validLen = len;\r\n var placeHoldersLen = validLen === len\r\n ? 0\r\n : 4 - (validLen % 4);\r\n return [validLen, placeHoldersLen];\r\n}\r\n// base64 is 4/3 + up to two characters of the original data\r\nfunction byteLength(b64) {\r\n var lens = getLens(b64);\r\n var validLen = lens[0];\r\n var placeHoldersLen = lens[1];\r\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;\r\n}\r\nfunction _byteLength(b64, validLen, placeHoldersLen) {\r\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;\r\n}\r\nfunction Util_Base64_Decode(b64) {\r\n var tmp;\r\n var lens = getLens(b64);\r\n var validLen = lens[0];\r\n var placeHoldersLen = lens[1];\r\n var arr = new Uint8Array(_byteLength(b64, validLen, placeHoldersLen));\r\n var curByte = 0;\r\n // if there are placeholders, only get up to the last complete 4 chars\r\n var len = placeHoldersLen > 0\r\n ? validLen - 4\r\n : validLen;\r\n for (var i = 0; i < len; i += 4) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 18) |\r\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\r\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\r\n revLookup[b64.charCodeAt(i + 3)];\r\n arr[curByte++] = (tmp >> 16) & 0xFF;\r\n arr[curByte++] = (tmp >> 8) & 0xFF;\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n if (placeHoldersLen === 2) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 2) |\r\n (revLookup[b64.charCodeAt(i + 1)] >> 4);\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n if (placeHoldersLen === 1) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 10) |\r\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\r\n (revLookup[b64.charCodeAt(i + 2)] >> 2);\r\n arr[curByte++] = (tmp >> 8) & 0xFF;\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n return arr;\r\n}\r\nexports.Util_Base64_Decode = Util_Base64_Decode;\r\nfunction tripletToBase64(num) {\r\n return lookup[num >> 18 & 0x3F] +\r\n lookup[num >> 12 & 0x3F] +\r\n lookup[num >> 6 & 0x3F] +\r\n lookup[num & 0x3F];\r\n}\r\nfunction encodeChunk(uint8, start, end) {\r\n var tmp;\r\n var output = [];\r\n for (var i = start; i < end; i += 3) {\r\n tmp =\r\n ((uint8[i] << 16) & 0xFF0000) +\r\n ((uint8[i + 1] << 8) & 0xFF00) +\r\n (uint8[i + 2] & 0xFF);\r\n output.push(tripletToBase64(tmp));\r\n }\r\n return output.join(\"\");\r\n}\r\nfunction Util_Base64_Encode(uint8) {\r\n var tmp;\r\n var len = uint8.length;\r\n var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes\r\n var parts = [];\r\n var maxChunkLength = 16383; // must be multiple of 3\r\n // go through the array every three bytes, we'll deal with trailing stuff later\r\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\r\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)));\r\n }\r\n // pad the end with zeros, but make sure to not forget the extra bytes\r\n if (extraBytes === 1) {\r\n tmp = uint8[len - 1];\r\n parts.push(lookup[tmp >> 2] +\r\n lookup[(tmp << 4) & 0x3F] +\r\n \"==\");\r\n }\r\n else if (extraBytes === 2) {\r\n tmp = (uint8[len - 2] << 8) + uint8[len - 1];\r\n parts.push(lookup[tmp >> 10] +\r\n lookup[(tmp >> 4) & 0x3F] +\r\n lookup[(tmp << 2) & 0x3F] +\r\n \"=\");\r\n }\r\n return parts.join(\"\");\r\n}\r\nexports.Util_Base64_Encode = Util_Base64_Encode;\r\n//////// END: Base64 encode / decode utility functions from https://github.com/beatgammit/base64-js\r\n//# sourceMappingURL=vpnrpc.js.map\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../buffer/index.js */ \"./node_modules/buffer/index.js\").Buffer))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvdnBucnBjL2Rpc3QvdnBucnBjLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vSlMvLi9ub2RlX21vZHVsZXMvdnBucnBjL2Rpc3QvdnBucnBjLmpzPzQ2ZWYiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XHJcbi8vIFNvZnRFdGhlciBWUE4gU2VydmVyIEpTT04tUlBDIFN0dWIgY29kZSBmb3IgVHlwZVNjcmlwdFxyXG4vLyBcclxuLy8gdnBucnBjLnRzXHJcbi8vIEF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGF0IDIwMTktMDUtMjkgMTg6MjE6MzkgYnkgdnBuc2VydmVyLWpzb25ycGMtY29kZWdlblxyXG4vL1xyXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UgMi4wXHJcbi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDE5IFNvZnRFdGhlciBWUE4gUHJvamVjdFxyXG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XHJcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xyXG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG4gICAgfTtcclxufSkoKTtcclxudmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufTtcclxudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59O1xyXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xyXG4vLyBUcml2aWFsIHV0aWxpdHkgY29kZXNcclxudmFyIGlzX25vZGVfanMgPSAodHlwZW9mIG5hdmlnYXRvciA9PT0gXCJ1bmRlZmluZWRcIikgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwiTm9kZS5qc1wiKSAhPT0gLTEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwianNkb21cIikgIT09IC0xO1xyXG5mdW5jdGlvbiBpc19udWxsKG9iaikge1xyXG4gICAgcmV0dXJuICh0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiKSB8fCAob2JqID09PSBudWxsKTtcclxufVxyXG52YXIgZGVidWdfbW9kZSA9IGZhbHNlO1xyXG4vKiogVlBOIFNlcnZlciBSUEMgU3R1YnMgKi9cclxudmFyIFZwblNlcnZlclJwYyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKlxyXG4gICAgICogQ29uc3RydWN0b3Igb2YgdGhlIFZwblNlcnZlclJwYyBjbGFzc1xyXG4gICAgICogQHBhcmFtIHZwbnNlcnZlcl9ob3N0bmFtZSBUaGUgaG9zdG5hbWUgb3IgSVAgYWRkcmVzcyBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4gSW4gdGhlIHdlYiBicm93c2VyIHlvdSBjYW4gc3BlY2lmeSBudWxsIGlmIHlvdSB3YW50IHRvIGNvbm5lY3QgdG8gdGhlIHNlcnZlciBpdHNlbGYuXHJcbiAgICAgKiBAcGFyYW0gdnBuc2VydmVyX3BvcnQgVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLiBJbiB0aGUgd2ViIGJyb3dzZXIgeW91IGNhbiBzcGVjaWZ5IG51bGwgaWYgeW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgc2VydmVyIGl0c2VsZi5cclxuICAgICAqIEBwYXJhbSBodWJuYW1lIFRoZSBuYW1lIG9mIHRoZSBWaXJ0dWFsIEh1YiBpZiB5b3Ugd2FudCB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgVmlydHVhbCBIdWIgQWRtaW4gTW9kZS4gU3BlY2lmeSBudWxsIGlmIHlvdSB3YW50IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIgYXMgdGhlIEVudGlyZSBWUE4gU2VydmVyIEFkbWluIE1vZGUuXHJcbiAgICAgKiBAcGFyYW0gcGFzc3dvcmQgU3BlY2lmeSB0aGUgYWRtaW5pc3RyYXRpb24gcGFzc3dvcmQuIFRoaXMgdmFsdWUgaXMgdmFsaWQgb25seSBpZiB2cG5zZXJ2ZXJfaG9zdG5hbWUgaXMgc2VwY2lmaWVkLlxyXG4gICAgICogQHBhcmFtIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCBJbiBOb2RlLmpzIHNldCB0aGlzIHRydWUgdG8gY2hlY2sgdGhlIFNTTCBzZXJ2ZXIgY2VydGlmaWNhdGUgb24gdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuIFNldCB0aGlzIGZhbHNlIHRvIGlnbm9yZSB0aGUgU1NMIHNlcnZlciBjZXJ0aWZpY2F0aW9uLlxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBWcG5TZXJ2ZXJScGModnBuc2VydmVyX2hvc3RuYW1lLCB2cG5zZXJ2ZXJfcG9ydCwgaHVibmFtZSwgcGFzc3dvcmQsIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCkge1xyXG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XHJcbiAgICAgICAgLy8gLS0tIFN0dWJzIC0tLVxyXG4gICAgICAgIC8qKiBUZXN0IFJQQyBmdW5jdGlvbi4gSW5wdXQgYW55IGludGVnZXIgdmFsdWUgdG8gdGhlIEludFZhbHVlX3UzMiBmaWVsZC4gVGhlbiB0aGUgc2VydmVyIHdpbGwgY29udmVydCB0aGUgaW50ZWdlciB0byB0aGUgc3RyaW5nLCBhbmQgcmV0dXJuIHRoZSBzdHJpbmcgaW4gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gKi9cclxuICAgICAgICB0aGlzLlRlc3QgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlRlc3RcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBzZXJ2ZXIgaW5mb3JtYXRpb24uIFRoaXMgYWxsb3dzIHlvdSB0byBvYnRhaW4gdGhlIHNlcnZlciBpbmZvcm1hdGlvbiBvZiB0aGUgY3VycmVudGx5IGNvbm5lY3RlZCBWUE4gU2VydmVyIG9yIFZQTiBCcmlkZ2UuIEluY2x1ZGVkIGluIHRoZSBzZXJ2ZXIgaW5mb3JtYXRpb24gYXJlIHRoZSB2ZXJzaW9uIG51bWJlciwgYnVpbGQgbnVtYmVyIGFuZCBidWlsZCBpbmZvcm1hdGlvbi4gWW91IGNhbiBhbHNvIG9idGFpbiBpbmZvcm1hdGlvbiBvbiB0aGUgY3VycmVudCBzZXJ2ZXIgb3BlcmF0aW9uIG1vZGUgYW5kIHRoZSBpbmZvcm1hdGlvbiBvZiBvcGVyYXRpbmcgc3lzdGVtIHRoYXQgdGhlIHNlcnZlciBpcyBvcGVyYXRpbmcgb24uICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXJ2ZXJJbmZvID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VydmVySW5mb1wiLCBuZXcgVnBuUnBjU2VydmVySW5mbygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQ3VycmVudCBTZXJ2ZXIgU3RhdHVzLiBUaGlzIGFsbG93cyB5b3UgdG8gb2J0YWluIGluIHJlYWwtdGltZSB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIGN1cnJlbnRseSBjb25uZWN0ZWQgVlBOIFNlcnZlciBvciBWUE4gQnJpZGdlLiBZb3UgY2FuIGdldCBzdGF0aXN0aWNhbCBpbmZvcm1hdGlvbiBvbiBkYXRhIGNvbW11bmljYXRpb24gYW5kIHRoZSBudW1iZXIgb2YgZGlmZmVyZW50IGtpbmRzIG9mIG9iamVjdHMgdGhhdCBleGlzdCBvbiB0aGUgc2VydmVyLiBZb3UgY2FuIGdldCBpbmZvcm1hdGlvbiBvbiBob3cgbXVjaCBtZW1vcnkgaXMgYmVpbmcgdXNlZCBvbiB0aGUgY3VycmVudCBjb21wdXRlciBieSB0aGUgT1MuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXJ2ZXJTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRTZXJ2ZXJTdGF0dXNcIiwgbmV3IFZwblJwY1NlcnZlclN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgTmV3IFRDUCBMaXN0ZW5lci4gVGhpcyBhbGxvd3MgeW91IHRvIGNyZWF0ZSBhIG5ldyBUQ1AgTGlzdGVuZXIgb24gdGhlIHNlcnZlci4gQnkgY3JlYXRpbmcgdGhlIFRDUCBMaXN0ZW5lciB0aGUgc2VydmVyIHN0YXJ0cyBsaXN0ZW5pbmcgZm9yIGEgY29ubmVjdGlvbiBmcm9tIGNsaWVudHMgYXQgdGhlIHNwZWNpZmllZCBUQ1AvSVAgcG9ydCBudW1iZXIuIEEgVENQIExpc3RlbmVyIHRoYXQgaGFzIGJlZW4gY3JlYXRlZCBjYW4gYmUgZGVsZXRlZCBieSB0aGUgRGVsZXRlTGlzdGVuZXIgQVBJLiBZb3UgY2FuIGFsc28gZ2V0IGEgbGlzdCBvZiBUQ1AgTGlzdGVuZXJzIGN1cnJlbnRseSByZWdpc3RlcmVkIGJ5IHVzaW5nIHRoZSBFbnVtTGlzdGVuZXIgQVBJLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlTGlzdGVuZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNyZWF0ZUxpc3RlbmVyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBUQ1AgTGlzdGVuZXJzLiBUaGlzIGFsbG93cyB5b3UgdG8gZ2V0IGEgbGlzdCBvZiBUQ1AgbGlzdGVuZXJzIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnQgc2VydmVyLiBZb3UgY2FuIG9idGFpbiBpbmZvcm1hdGlvbiBvbiB3aGV0aGVyIHRoZSB2YXJpb3VzIFRDUCBsaXN0ZW5lcnMgaGF2ZSBhIHN0YXR1cyBvZiBvcGVyYXRpbmcgb3IgZXJyb3IuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTGlzdGVuZXJcIiwgbmV3IFZwblJwY0xpc3RlbmVyTGlzdCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgVENQIExpc3RlbmVyLiBUaGlzIGFsbG93cyB5b3UgdG8gZGVsZXRlIGEgVENQIExpc3RlbmVyIHRoYXQncyByZWdpc3RlcmVkIG9uIHRoZSBzZXJ2ZXIuIFdoZW4gdGhlIFRDUCBMaXN0ZW5lciBpcyBpbiBhIHN0YXRlIG9mIG9wZXJhdGlvbiwgdGhlIGxpc3RlbmVyIHdpbGwgYXV0b21hdGljYWxseSBiZSBkZWxldGVkIHdoZW4gaXRzIG9wZXJhdGlvbiBzdG9wcy4gWW91IGNhbiBhbHNvIGdldCBhIGxpc3Qgb2YgVENQIExpc3RlbmVycyBjdXJyZW50bHkgcmVnaXN0ZXJlZCBieSB1c2luZyB0aGUgRW51bUxpc3RlbmVyIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUxpc3RlbmVyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRW5hYmxlIC8gRGlzYWJsZSBUQ1AgTGlzdGVuZXIuIFRoaXMgc3RhcnRzIG9yIHN0b3BzIHRoZSBvcGVyYXRpb24gb2YgVENQIExpc3RlbmVycyByZWdpc3RlcmVkIG9uIHRoZSBjdXJyZW50IHNlcnZlci4gWW91IGNhbiBhbHNvIGdldCBhIGxpc3Qgb2YgVENQIExpc3RlbmVycyBjdXJyZW50bHkgcmVnaXN0ZXJlZCBieSB1c2luZyB0aGUgRW51bUxpc3RlbmVyIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkVuYWJsZUxpc3RlbmVyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbmFibGVMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFZQTiBTZXJ2ZXIgQWRtaW5pc3RyYXRvciBQYXNzd29yZC4gVGhpcyBzZXRzIHRoZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQuIFlvdSBjYW4gc3BlY2lmeSB0aGUgcGFzc3dvcmQgYXMgYSBwYXJhbWV0ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRTZXJ2ZXJQYXNzd29yZCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0U2VydmVyUGFzc3dvcmRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCB0aGUgVlBOIFNlcnZlciBjbHVzdGVyaW5nIGNvbmZpZ3VyYXRpb24uIFVzZSB0aGlzIHRvIHNldCB0aGUgVlBOIFNlcnZlciB0eXBlIGFzIFN0YW5kYWxvbmUgU2VydmVyLCBDbHVzdGVyIENvbnRyb2xsZXIgU2VydmVyIG9yIENsdXN0ZXIgTWVtYmVyIFNlcnZlci4gU3RhbmRhbG9uZSBzZXJ2ZXIgbWVhbnMgYSBWUE4gU2VydmVyIHRoYXQgZG9lcyBub3QgYmVsb25nIHRvIGFueSBjbHVzdGVyIGluIGl0cyBjdXJyZW50IHN0YXRlLiBXaGVuIFZQTiBTZXJ2ZXIgaXMgaW5zdGFsbGVkLCBieSBkZWZhdWx0IGl0IHdpbGwgYmUgaW4gc3RhbmRhbG9uZSBzZXJ2ZXIgbW9kZS4gVW5sZXNzIHlvdSBoYXZlIHBhcnRpY3VsYXIgcGxhbnMgdG8gY29uZmlndXJlIGEgY2x1c3Rlciwgd2UgcmVjb21tZW5kIHRoZSBWUE4gU2VydmVyIGJlIG9wZXJhdGVkIGluIHN0YW5kYWxvbmUgbW9kZS4gQSBjbHVzdGVyIGNvbnRyb2xsZXIgaXMgdGhlIGNlbnRyYWwgY29tcHV0ZXIgb2YgYWxsIG1lbWJlciBzZXJ2ZXJzIG9mIGEgY2x1c3RlciBpbiB0aGUgY2FzZSB3aGVyZSBhIGNsdXN0ZXJpbmcgZW52aXJvbm1lbnQgaXMgbWFkZSB1cCBvZiBtdWx0aXBsZSBWUE4gU2VydmVycy4gTXVsdGlwbGUgY2x1c3RlciBtZW1iZXJzIGNhbiBiZSBhZGRlZCB0byB0aGUgY2x1c3RlciBhcyByZXF1aXJlZC4gQSBjbHVzdGVyIHJlcXVpcmVzIG9uZSBjb21wdXRlciB0byBzZXJ2ZSB0aGlzIHJvbGUuIFRoZSBvdGhlciBjbHVzdGVyIG1lbWJlciBzZXJ2ZXJzIHRoYXQgYXJlIGNvbmZpZ3VyZWQgaW4gdGhlIHNhbWUgY2x1c3RlciBiZWdpbiBvcGVyYXRpb24gYXMgYSBjbHVzdGVyIG1lbWJlciBieSBjb25uZWN0aW5nIHRvIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHdoZW4gdGhpcyBBUEkgaXMgZXhlY3V0ZWQsIFZQTiBTZXJ2ZXIgd2lsbCBhdXRvbWF0aWNhbGx5IHJlc3RhcnQuIFRoaXMgQVBJIGNhbm5vdCBiZSBjYWxsZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLlNldEZhcm1TZXR0aW5nID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRGYXJtU2V0dGluZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IENsdXN0ZXJpbmcgQ29uZmlndXJhdGlvbiBvZiBDdXJyZW50IFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoaXMgdG8gYWNxdWlyZSB0aGUgY2x1c3RlcmluZyBjb25maWd1cmF0aW9uIG9mIHRoZSBjdXJyZW50IFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5HZXRGYXJtU2V0dGluZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEZhcm1TZXR0aW5nXCIsIG5ldyBWcG5ScGNGYXJtKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDbHVzdGVyIE1lbWJlciBJbmZvcm1hdGlvbi4gV2hlbiB0aGUgVlBOIFNlcnZlciBpcyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIsIHlvdSBjYW4gZ2V0IGluZm9ybWF0aW9uIG9uIGNsdXN0ZXIgbWVtYmVyIHNlcnZlcnMgb24gdGhhdCBjbHVzdGVyIGJ5IHNwZWNpZnlpbmcgdGhlIElEcyBvZiB0aGUgbWVtYmVyIHNlcnZlcnMuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNwZWNpZmllZCBjbHVzdGVyIG1lbWJlciBzZXJ2ZXI6IFNlcnZlciBUeXBlLCBUaW1lIENvbm5lY3Rpb24gaGFzIGJlZW4gRXN0YWJsaXNoZWQsIElQIEFkZHJlc3MsIEhvc3QgTmFtZSwgUG9pbnRzLCBQdWJsaWMgUG9ydCBMaXN0LCBOdW1iZXIgb2YgT3BlcmF0aW5nIFZpcnR1YWwgSHVicywgRmlyc3QgVmlydHVhbCBIdWIsIE51bWJlciBvZiBTZXNzaW9ucyBhbmQgTnVtYmVyIG9mIFRDUCBDb25uZWN0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkdldEZhcm1JbmZvID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRGYXJtSW5mb1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgQ2x1c3RlciBNZW1iZXJzLiBVc2UgdGhpcyBBUEkgd2hlbiB0aGUgVlBOIFNlcnZlciBpcyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIgdG8gZ2V0IGEgbGlzdCBvZiB0aGUgY2x1c3RlciBtZW1iZXIgc2VydmVycyBvbiB0aGUgc2FtZSBjbHVzdGVyLCBpbmNsdWRpbmcgdGhlIGNsdXN0ZXIgY29udHJvbGxlciBpdHNlbGYuIEZvciBlYWNoIG1lbWJlciwgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbiBpcyBhbHNvIGxpc3RlZDogVHlwZSwgQ29ubmVjdGlvbiBTdGFydCwgSG9zdCBOYW1lLCBQb2ludHMsIE51bWJlciBvZiBTZXNzaW9uLCBOdW1iZXIgb2YgVENQIENvbm5lY3Rpb25zLCBOdW1iZXIgb2YgT3BlcmF0aW5nIFZpcnR1YWwgSHVicywgVXNpbmcgQ2xpZW50IENvbm5lY3Rpb24gTGljZW5zZSBhbmQgVXNpbmcgQnJpZGdlIENvbm5lY3Rpb24gTGljZW5zZS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkVudW1GYXJtTWVtYmVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUZhcm1NZW1iZXJcIiwgbmV3IFZwblJwY0VudW1GYXJtKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDb25uZWN0aW9uIFN0YXR1cyB0byBDbHVzdGVyIENvbnRyb2xsZXIuIFVzZSB0aGlzIEFQSSB3aGVuIHRoZSBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIgY29udHJvbGxlciB0byBnZXQgdGhlIHN0YXR1cyBvZiBjb25uZWN0aW9uIHRvIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246IENvbnRyb2xsZXIgSVAgQWRkcmVzcywgUG9ydCBOdW1iZXIsIENvbm5lY3Rpb24gU3RhdHVzLCBDb25uZWN0aW9uIFN0YXJ0IFRpbWUsIEZpcnN0IENvbm5lY3Rpb24gRXN0YWJsaXNoZWQgVGltZSwgQ3VycmVudCBDb25uZWN0aW9uIEVzdGFibGlzaGVkIFRpbWUsIE51bWJlciBvZiBDb25uZWN0aW9uIEF0dGVtcHRzLCBOdW1iZXIgb2YgU3VjY2Vzc2Z1bCBDb25uZWN0aW9ucywgTnVtYmVyIG9mIEZhaWxlZCBDb25uZWN0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkdldEZhcm1Db25uZWN0aW9uU3RhdHVzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0RmFybUNvbm5lY3Rpb25TdGF0dXNcIiwgbmV3IFZwblJwY0Zhcm1Db25uZWN0aW9uU3RhdHVzKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBTU0wgQ2VydGlmaWNhdGUgYW5kIFByaXZhdGUgS2V5IG9mIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gc2V0IHRoZSBTU0wgY2VydGlmaWNhdGUgdGhhdCB0aGUgVlBOIFNlcnZlciBwcm92aWRlcyB0byB0aGUgY29ubmVjdGVkIGNsaWVudCBhbmQgdGhlIHByaXZhdGUga2V5IGZvciB0aGF0IGNlcnRpZmljYXRlLiBUaGUgY2VydGlmaWNhdGUgbXVzdCBiZSBpbiBYLjUwOSBmb3JtYXQgYW5kIHRoZSBwcml2YXRlIGtleSBtdXN0IGJlIEJhc2UgNjQgZW5jb2RlZCBmb3JtYXQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRTZXJ2ZXJDZXJ0ID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRTZXJ2ZXJDZXJ0XCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgU1NMIENlcnRpZmljYXRlIGFuZCBQcml2YXRlIEtleSBvZiBWUE4gU2VydmVyLiBVc2UgdGhpcyB0byBnZXQgdGhlIFNTTCBjZXJ0aWZpY2F0ZSBwcml2YXRlIGtleSB0aGF0IHRoZSBWUE4gU2VydmVyIHByb3ZpZGVzIHRvIHRoZSBjb25uZWN0ZWQgY2xpZW50LiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U2VydmVyQ2VydCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFNlcnZlckNlcnRcIiwgbmV3IFZwblJwY0tleVBhaXIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBFbmNyeXB0ZWQgQWxnb3JpdGhtIFVzZWQgZm9yIFZQTiBDb21tdW5pY2F0aW9uLiBVc2UgdGhpcyBBUEkgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgb2YgdGhlIGFsZ29yaXRobSB1c2VkIGZvciB0aGUgZWxlY3Ryb25pYyBzaWduYXR1cmUgYW5kIGVuY3J5cHRlZCBmb3IgU1NMIGNvbm5lY3Rpb24gdG8gYmUgdXNlZCBmb3IgY29tbXVuaWNhdGlvbiBiZXR3ZWVuIHRoZSBWUE4gU2VydmVyIGFuZCB0aGUgY29ubmVjdGVkIGNsaWVudCBhbmQgdGhlIGxpc3Qgb2YgYWxnb3JpdGhtcyB0aGF0IGNhbiBiZSB1c2VkIG9uIHRoZSBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U2VydmVyQ2lwaGVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VydmVyQ2lwaGVyXCIsIG5ldyBWcG5ScGNTdHIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IHRoZSBFbmNyeXB0ZWQgQWxnb3JpdGhtIFVzZWQgZm9yIFZQTiBDb21tdW5pY2F0aW9uLiBVc2UgdGhpcyBBUEkgdG8gc2V0IHRoZSBhbGdvcml0aG0gdXNlZCBmb3IgdGhlIGVsZWN0cm9uaWMgc2lnbmF0dXJlIGFuZCBlbmNyeXB0ZWQgZm9yIFNTTCBjb25uZWN0aW9ucyB0byBiZSB1c2VkIGZvciBjb21tdW5pY2F0aW9uIGJldHdlZW4gdGhlIFZQTiBTZXJ2ZXIgYW5kIHRoZSBjb25uZWN0ZWQgY2xpZW50LiBCeSBzcGVjaWZ5aW5nIHRoZSBhbGdvcml0aG0gbmFtZSwgdGhlIHNwZWNpZmllZCBhbGdvcml0aG0gd2lsbCBiZSB1c2VkIGxhdGVyIGJldHdlZW4gdGhlIFZQTiBDbGllbnQgYW5kIFZQTiBCcmlkZ2UgY29ubmVjdGVkIHRvIHRoaXMgc2VydmVyIGFuZCB0aGUgZGF0YSB3aWxsIGJlIGVuY3J5cHRlZC4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLlNldFNlcnZlckNpcGhlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0U2VydmVyQ2lwaGVyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgTmV3IFZpcnR1YWwgSHViLiBVc2UgdGhpcyB0byBjcmVhdGUgYSBuZXcgVmlydHVhbCBIdWIgb24gdGhlIFZQTiBTZXJ2ZXIuIFRoZSBjcmVhdGVkIFZpcnR1YWwgSHViIHdpbGwgYmVnaW4gb3BlcmF0aW9uIGltbWVkaWF0ZWx5LiBXaGVuIHRoZSBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBvbiBhIGNsdXN0ZXIsIHRoaXMgQVBJIGlzIG9ubHkgdmFsaWQgZm9yIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIEFsc28sIHRoZSBuZXcgVmlydHVhbCBIdWIgd2lsbCBvcGVyYXRlIGFzIGEgZHluYW1pYyBWaXJ0dWFsIEh1Yi4gWW91IGNhbiBjaGFuZ2UgaXQgdG8gYSBzdGF0aWMgVmlydHVhbCBIdWIgYnkgdXNpbmcgdGhlIFNldEh1YiBBUEkuIFRvIGdldCBhIGxpc3Qgb2YgVmlydHVhbCBIdWJzIHRoYXQgYXJlIGFscmVhZHkgb24gdGhlIFZQTiBTZXJ2ZXIsIHVzZSB0aGUgRW51bUh1YiBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIFNlcnZlcnMgdGhhdCBhcmUgb3BlcmF0aW5nIGFzIGEgVlBOIEJyaWRnZSBvciBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQ3JlYXRlSHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFZpcnR1YWwgSHViIGNvbmZpZ3VyYXRpb24uIFlvdSBjYW4gY2FsbCB0aGlzIEFQSSB0byBjaGFuZ2UgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHNwZWNpZmllZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbiBzZXQgdGhlIFZpcnR1YWwgSHViIG9ubGluZSBvciBvZmZsaW5lLiBZb3UgY2FuIHNldCB0aGUgbWF4aW11bSBudW1iZXIgb2Ygc2Vzc2lvbnMgdGhhdCBjYW4gYmUgY29uY3VycmVudGx5IGNvbm5lY3RlZCB0byB0aGUgVmlydHVhbCBIdWIgdGhhdCBpcyBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZC4gWW91IGNhbiBzZXQgdGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQuIFlvdSBjYW4gc2V0IG90aGVyIHBhcmFtZXRlcnMgZm9yIHRoZSBWaXJ0dWFsIEh1Yi4gQmVmb3JlIGNhbGwgdGhpcyBBUEksIHlvdSBuZWVkIHRvIG9idGFpbiB0aGUgbGF0ZXN0IHN0YXRlIG9mIHRoZSBWaXJ0dWFsIEh1YiBieSB1c2luZyB0aGUgR2V0SHViIEFQSS4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIFZpcnR1YWwgSHViIGNvbmZpZ3VyYXRpb24uIFlvdSBjYW4gY2FsbCB0aGlzIEFQSSB0byBnZXQgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBvZiB0aGUgc3BlY2lmaWVkIFZpcnR1YWwgSHViLiBUbyBjaGFuZ2UgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIFZpcnR1YWwgSHViLCBjYWxsIHRoZSBTZXRIdWIgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgSHVicy4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiBleGlzdGluZyBWaXJ0dWFsIEh1YnMgb24gdGhlIFZQTiBTZXJ2ZXIuIEZvciBlYWNoIFZpcnR1YWwgSHViLCB5b3UgY2FuIGdldCB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOiBWaXJ0dWFsIEh1YiBOYW1lLCBTdGF0dXMsIFR5cGUsIE51bWJlciBvZiBVc2VycywgTnVtYmVyIG9mIEdyb3VwcywgTnVtYmVyIG9mIFNlc3Npb25zLCBOdW1iZXIgb2YgTUFDIFRhYmxlcywgTnVtYmVyIG9mIElQIFRhYmxlcywgTnVtYmVyIG9mIExvZ2lucywgTGFzdCBMb2dpbiwgYW5kIExhc3QgQ29tbXVuaWNhdGlvbi4gTm90ZSB0aGF0IHdoZW4gY29ubmVjdGluZyBpbiBWaXJ0dWFsIEh1YiBBZG1pbiBNb2RlLCBpZiBpbiB0aGUgb3B0aW9ucyBvZiBhIFZpcnR1YWwgSHViIHRoYXQgeW91IGRvIG5vdCBoYXZlIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcyBmb3IsIHRoZSBvcHRpb24gRG9uJ3QgRW51bWVyYXRlIHRoaXMgVmlydHVhbCBIdWIgZm9yIEFub255bW91cyBVc2VycyBpcyBlbmFibGVkIHRoZW4gdGhhdCBWaXJ0dWFsIEh1YiB3aWxsIG5vdCBiZSBlbnVtZXJhdGVkLiBJZiB5b3UgYXJlIGNvbm5lY3RlZCBpbiBTZXJ2ZXIgQWRtaW4gTW9kZSwgdGhlbiB0aGUgbGlzdCBvZiBhbGwgVmlydHVhbCBIdWJzIHdpbGwgYmUgZGlzcGxheWVkLiBXaGVuIGNvbm5lY3RpbmcgdG8gYW5kIG1hbmFnaW5nIGEgbm9uLWNsdXN0ZXItY29udHJvbGxlciBjbHVzdGVyIG1lbWJlciBvZiBhIGNsdXN0ZXJpbmcgZW52aXJvbm1lbnQsIG9ubHkgdGhlIFZpcnR1YWwgSHViIGN1cnJlbnRseSBiZWluZyBob3N0ZWQgYnkgdGhhdCBWUE4gU2VydmVyIHdpbGwgYmUgZGlzcGxheWVkLiBXaGVuIGNvbm5lY3RpbmcgdG8gYSBjbHVzdGVyIGNvbnRyb2xsZXIgZm9yIGFkbWluaXN0cmF0aW9uIHB1cnBvc2VzLCBhbGwgdGhlIFZpcnR1YWwgSHVicyB3aWxsIGJlIGRpc3BsYXllZC4gKi9cclxuICAgICAgICB0aGlzLkVudW1IdWIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtSHViXCIsIG5ldyBWcG5ScGNFbnVtSHViKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIEh1Yi4gVXNlIHRoaXMgdG8gZGVsZXRlIGFuIGV4aXN0aW5nIFZpcnR1YWwgSHViIG9uIHRoZSBWUE4gU2VydmVyLiBJZiB5b3UgZGVsZXRlIHRoZSBWaXJ0dWFsIEh1YiwgYWxsIHNlc3Npb25zIHRoYXQgYXJlIGN1cnJlbnRseSBjb25uZWN0ZWQgdG8gdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgZGlzY29ubmVjdGVkIGFuZCBuZXcgc2Vzc2lvbnMgd2lsbCBiZSB1bmFibGUgdG8gY29ubmVjdCB0byB0aGUgVmlydHVhbCBIdWIuIEFsc28sIHRoaXMgd2lsbCBhbHNvIGRlbGV0ZSBhbGwgdGhlIEh1YiBzZXR0aW5ncywgdXNlciBvYmplY3RzLCBncm91cCBvYmplY3RzLCBjZXJ0aWZpY2F0ZXMgYW5kIENhc2NhZGUgQ29ubmVjdGlvbnMuIE9uY2UgeW91IGRlbGV0ZSB0aGUgVmlydHVhbCBIdWIsIGl0IGNhbm5vdCBiZSByZWNvdmVyZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIFNlcnZlcnMgdGhhdCBhcmUgb3BlcmF0aW5nIGFzIGEgVlBOIEJyaWRnZSBvciBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlSHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgU2V0dGluZyBvZiBSQURJVVMgU2VydmVyIFVzZWQgZm9yIFVzZXIgQXV0aGVudGljYXRpb24uIFVzZSB0aGlzIHRvIGdldCB0aGUgY3VycmVudCBzZXR0aW5ncyBmb3IgdGhlIFJBRElVUyBzZXJ2ZXIgdXNlZCB3aGVuIGEgdXNlciBjb25uZWN0cyB0byB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgdXNpbmcgUkFESVVTIFNlcnZlciBBdXRoZW50aWNhdGlvbiBNb2RlLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViUmFkaXVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJSYWRpdXNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBSQURJVVMgU2VydmVyIHRvIHVzZSBmb3IgVXNlciBBdXRoZW50aWNhdGlvbi4gVG8gYWNjZXB0IHVzZXJzIHRvIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBpbiBSQURJVVMgc2VydmVyIGF1dGhlbnRpY2F0aW9uIG1vZGUsIHlvdSBjYW4gc3BlY2lmeSBhbiBleHRlcm5hbCBSQURJVVMgc2VydmVyIHRoYXQgY29uZmlybXMgdGhlIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQuIChZb3UgY2FuIHNwZWNpZnkgbXVsdGlwbGUgaG9zdG5hbWUgYnkgc3BsaXR0aW5nIHdpdGggY29tbWEgb3Igc2VtaWNvbG9uLikgVGhlIFJBRElVUyBzZXJ2ZXIgbXVzdCBiZSBzZXQgdG8gcmVjZWl2ZSByZXF1ZXN0cyBmcm9tIElQIGFkZHJlc3NlcyBvZiB0aGlzIFZQTiBTZXJ2ZXIuIEFsc28sIGF1dGhlbnRpY2F0aW9uIGJ5IFBhc3N3b3JkIEF1dGhlbnRpY2F0aW9uIFByb3RvY29sIChQQVApIG11c3QgYmUgZW5hYmxlZC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YlJhZGl1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SHViUmFkaXVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBUQ1AgQ29ubmVjdGlvbnMgQ29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiBUQ1AvSVAgY29ubmVjdGlvbnMgdGhhdCBhcmUgY3VycmVudGx5IGNvbm5lY3RpbmcgdG8gdGhlIFZQTiBTZXJ2ZXIuIEl0IGRvZXMgbm90IGRpc3BsYXkgdGhlIFRDUCBjb25uZWN0aW9ucyB0aGF0IGhhdmUgYmVlbiBlc3RhYmxpc2hlZCBhcyBWUE4gc2Vzc2lvbnMuIFRvIGdldCB0aGUgbGlzdCBvZiBUQ1AvSVAgY29ubmVjdGlvbnMgdGhhdCBoYXZlIGJlZW4gZXN0YWJsaXNoZWQgYXMgVlBOIHNlc3Npb25zLCB5b3UgY2FuIHVzZSB0aGUgRW51bVNlc3Npb24gQVBJLiBZb3UgY2FuIGdldCB0aGUgZm9sbG93aW5nOiBDb25uZWN0aW9uIE5hbWUsIENvbm5lY3Rpb24gU291cmNlLCBDb25uZWN0aW9uIFN0YXJ0IGFuZCBUeXBlLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUNvbm5lY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtQ29ubmVjdGlvblwiLCBuZXcgVnBuUnBjRW51bUNvbm5lY3Rpb24oKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRGlzY29ubmVjdCBUQ1AgQ29ubmVjdGlvbnMgQ29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZm9yY2VmdWxseSBkaXNjb25uZWN0IHNwZWNpZmljIFRDUC9JUCBjb25uZWN0aW9ucyB0aGF0IGFyZSBjb25uZWN0aW5nIHRvIHRoZSBWUE4gU2VydmVyLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRGlzY29ubmVjdENvbm5lY3Rpb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRpc2Nvbm5lY3RDb25uZWN0aW9uXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgSW5mb3JtYXRpb24gb2YgVENQIENvbm5lY3Rpb25zIENvbm5lY3RpbmcgdG8gdGhlIFZQTiBTZXJ2ZXIuIFVzZSB0aGlzIHRvIGdldCBkZXRhaWxlZCBpbmZvcm1hdGlvbiBvZiBhIHNwZWNpZmljIFRDUC9JUCBjb25uZWN0aW9uIHRoYXQgaXMgY29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gWW91IGNhbiBnZXQgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjogQ29ubmVjdGlvbiBOYW1lLCBDb25uZWN0aW9uIFR5cGUsIFNvdXJjZSBIb3N0bmFtZSwgU291cmNlIElQIEFkZHJlc3MsIFNvdXJjZSBQb3J0IE51bWJlciAoVENQKSwgQ29ubmVjdGlvbiBTdGFydCwgU2VydmVyIFByb2R1Y3QgTmFtZSwgU2VydmVyIFZlcnNpb24sIFNlcnZlciBCdWlsZCBOdW1iZXIsIENsaWVudCBQcm9kdWN0IE5hbWUsIENsaWVudCBWZXJzaW9uLCBhbmQgQ2xpZW50IEJ1aWxkIE51bWJlci4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkdldENvbm5lY3Rpb25JbmZvID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRDb25uZWN0aW9uSW5mb1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU3dpdGNoIFZpcnR1YWwgSHViIHRvIE9ubGluZSBvciBPZmZsaW5lLiBVc2UgdGhpcyB0byBzZXQgdGhlIFZpcnR1YWwgSHViIHRvIG9ubGluZSBvciBvZmZsaW5lLiBBIFZpcnR1YWwgSHViIHdpdGggYW4gb2ZmbGluZSBzdGF0dXMgY2Fubm90IHJlY2VpdmUgVlBOIGNvbm5lY3Rpb25zIGZyb20gY2xpZW50cy4gV2hlbiB5b3Ugc2V0IHRoZSBWaXJ0dWFsIEh1YiBvZmZsaW5lLCBhbGwgc2Vzc2lvbnMgd2lsbCBiZSBkaXNjb25uZWN0ZWQuIEEgVmlydHVhbCBIdWIgd2l0aCBhbiBvZmZsaW5lIHN0YXR1cyBjYW5ub3QgcmVjZWl2ZSBWUE4gY29ubmVjdGlvbnMgZnJvbSBjbGllbnRzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViT25saW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJPbmxpbmVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDdXJyZW50IFN0YXR1cyBvZiBWaXJ0dWFsIEh1Yi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgVmlydHVhbCBIdWIgY3VycmVudGx5IGJlaW5nIG1hbmFnZWQuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246IFZpcnR1YWwgSHViIFR5cGUsIE51bWJlciBvZiBTZXNzaW9ucywgTnVtYmVyIG9mIEVhY2ggVHlwZSBvZiBPYmplY3QsIE51bWJlciBvZiBMb2dpbnMsIExhc3QgTG9naW4sIExhc3QgQ29tbXVuaWNhdGlvbiwgYW5kIENvbW11bmljYXRpb24gU3RhdGlzdGljYWwgRGF0YS4gKi9cclxuICAgICAgICB0aGlzLkdldEh1YlN0YXR1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0SHViU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIGxvZ2dpbmcgY29uZmlndXJhdGlvbiBvZiB0aGUgVmlydHVhbCBIdWIuIFVzZSB0aGlzIHRvIGVuYWJsZSBvciBkaXNhYmxlIGEgc2VjdXJpdHkgbG9nIG9yIHBhY2tldCBsb2dzIG9mIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZCwgc2V0IHRoZSBzYXZlIGNvbnRlbnRzIG9mIHRoZSBwYWNrZXQgbG9nIGZvciBlYWNoIHR5cGUgb2YgcGFja2V0IHRvIGJlIHNhdmVkLCBhbmQgc2V0IHRoZSBsb2cgZmlsZSBzd2l0Y2ggY3ljbGUgZm9yIHRoZSBzZWN1cml0eSBsb2cgb3IgcGFja2V0IGxvZyB0aGF0IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBzYXZlcy4gVGhlcmUgYXJlIHRoZSBmb2xsb3dpbmcgcGFja2V0IHR5cGVzOiBUQ1AgQ29ubmVjdGlvbiBMb2csIFRDUCBQYWNrZXQgTG9nLCBESENQIFBhY2tldCBMb2csIFVEUCBQYWNrZXQgTG9nLCBJQ01QIFBhY2tldCBMb2csIElQIFBhY2tldCBMb2csIEFSUCBQYWNrZXQgTG9nLCBhbmQgRXRoZXJuZXQgUGFja2V0IExvZy4gVG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcsIHlvdSBjYW4gdXNlIHRoZSBMb2dHZXQgQVBJLiBUaGUgbG9nIGZpbGUgc3dpdGNoIGN5Y2xlIGNhbiBiZSBjaGFuZ2VkIHRvIHN3aXRjaCBpbiBldmVyeSBzZWNvbmQsIGV2ZXJ5IG1pbnV0ZSwgZXZlcnkgaG91ciwgZXZlcnkgZGF5LCBldmVyeSBtb250aCBvciBub3Qgc3dpdGNoLiBUbyBnZXQgdGhlIGN1cnJlbnQgc2V0dGluZywgeW91IGNhbiB1c2UgdGhlIEdldEh1YkxvZyBBUEkuICovXHJcbiAgICAgICAgdGhpcy5TZXRIdWJMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEh1YkxvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBsb2dnaW5nIGNvbmZpZ3VyYXRpb24gb2YgdGhlIFZpcnR1YWwgSHViLiBVc2UgdGhpcyB0byBnZXQgdGhlIGNvbmZpZ3VyYXRpb24gZm9yIGEgc2VjdXJpdHkgbG9nIG9yIHBhY2tldCBsb2dzIG9mIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZCwgZ2V0IHRoZSBzZXR0aW5nIGZvciBzYXZlIGNvbnRlbnRzIG9mIHRoZSBwYWNrZXQgbG9nIGZvciBlYWNoIHR5cGUgb2YgcGFja2V0IHRvIGJlIHNhdmVkLCBhbmQgZ2V0IHRoZSBsb2cgZmlsZSBzd2l0Y2ggY3ljbGUgZm9yIHRoZSBzZWN1cml0eSBsb2cgb3IgcGFja2V0IGxvZyB0aGF0IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBzYXZlcy4gVG8gc2V0IHRoZSBjdXJyZW50IHNldHRpbmcsIHlvdSBjYW4gdXNlIHRoZSBTZXRIdWJMb2cgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViTG9nID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJMb2dcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBhZGQgYSBuZXcgY2VydGlmaWNhdGUgdG8gYSBsaXN0IG9mIENBIGNlcnRpZmljYXRlcyB0cnVzdGVkIGJ5IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGxpc3Qgb2YgY2VydGlmaWNhdGUgYXV0aG9yaXR5IGNlcnRpZmljYXRlcyB0aGF0IGFyZSByZWdpc3RlcmVkIGlzIHVzZWQgdG8gdmVyaWZ5IGNlcnRpZmljYXRlcyB3aGVuIGEgVlBOIENsaWVudCBpcyBjb25uZWN0ZWQgaW4gc2lnbmVkIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIFRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnQgY2VydGlmaWNhdGVzIHlvdSBjYW4gdXNlIHRoZSBFbnVtQ2EgQVBJLiBUaGUgY2VydGlmaWNhdGUgeW91IGFkZCBtdXN0IGJlIHNhdmVkIGluIHRoZSBYLjUwOSBmaWxlIGZvcm1hdC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5BZGRDYSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkQ2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFRydXN0ZWQgQ0EgQ2VydGlmaWNhdGVzLiBIZXJlIHlvdSBjYW4gbWFuYWdlIHRoZSBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkgY2VydGlmaWNhdGVzIHRoYXQgYXJlIHRydXN0ZWQgYnkgdGhpcyBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGxpc3Qgb2YgY2VydGlmaWNhdGUgYXV0aG9yaXR5IGNlcnRpZmljYXRlcyB0aGF0IGFyZSByZWdpc3RlcmVkIGlzIHVzZWQgdG8gdmVyaWZ5IGNlcnRpZmljYXRlcyB3aGVuIGEgVlBOIENsaWVudCBpcyBjb25uZWN0ZWQgaW4gc2lnbmVkIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUNhID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtQ2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBnZXQgYW4gZXhpc3RpbmcgY2VydGlmaWNhdGUgZnJvbSB0aGUgbGlzdCBvZiBDQSBjZXJ0aWZpY2F0ZXMgdHJ1c3RlZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIHNhdmUgaXQgYXMgYSBmaWxlIGluIFguNTA5IGZvcm1hdC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRDYSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0Q2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBkZWxldGUgYW4gZXhpc3RpbmcgY2VydGlmaWNhdGUgZnJvbSB0aGUgbGlzdCBvZiBDQSBjZXJ0aWZpY2F0ZXMgdHJ1c3RlZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnQgY2VydGlmaWNhdGVzIHlvdSBjYW4gdXNlIHRoZSBFbnVtQ2EgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUNhID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVDYVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ3JlYXRlIE5ldyBDYXNjYWRlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGNyZWF0ZSBhIG5ldyBDYXNjYWRlIENvbm5lY3Rpb24gb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBCeSB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiwgeW91IGNhbiBjb25uZWN0IHRoaXMgVmlydHVhbCBIdWIgYnkgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIGFub3RoZXIgVmlydHVhbCBIdWIgdGhhdCBpcyBvcGVyYXRpbmcgb24gdGhlIHNhbWUgb3IgYSBkaWZmZXJlbnQgY29tcHV0ZXIuIFRvIGNyZWF0ZSBhIENhc2NhZGUgQ29ubmVjdGlvbiwgeW91IG11c3Qgc3BlY2lmeSB0aGUgbmFtZSBvZiB0aGUgQ2FzY2FkZSBDb25uZWN0aW9uLCBkZXN0aW5hdGlvbiBzZXJ2ZXIgYW5kIGRlc3RpbmF0aW9uIFZpcnR1YWwgSHViIGFuZCB1c2VyIG5hbWUuIFdoZW4gYSBuZXcgQ2FzY2FkZSBDb25uZWN0aW9uIGlzIGNyZWF0ZWQsIHRoZSB0eXBlIG9mIHVzZXIgYXV0aGVudGljYXRpb24gaXMgaW5pdGlhbGx5IHNldCBhcyBBbm9ueW1vdXMgQXV0aGVudGljYXRpb24gYW5kIHRoZSBwcm94eSBzZXJ2ZXIgc2V0dGluZyBhbmQgdGhlIHZlcmlmaWNhdGlvbiBvcHRpb25zIG9mIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IHNldC4gVG8gY2hhbmdlIHRoZXNlIHNldHRpbmdzIGFuZCBvdGhlciBhZHZhbmNlZCBzZXR0aW5ncyBhZnRlciBhIENhc2NhZGUgQ29ubmVjdGlvbiBoYXMgYmVlbiBjcmVhdGVkLCB1c2UgdGhlIG90aGVyIEFQSXMgdGhhdCBpbmNsdWRlIHRoZSBuYW1lIFwiTGlua1wiLiBbV2FybmluZyBBYm91dCBDYXNjYWRlIENvbm5lY3Rpb25zXSBCeSBjb25uZWN0aW5nIHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHlvdSBjYW4gY3JlYXRlIGEgTGF5ZXIgMiBicmlkZ2UgYmV0d2VlbiBtdWx0aXBsZSBWaXJ0dWFsIEh1YnMgYnV0IGlmIHRoZSBjb25uZWN0aW9uIGlzIGluY29ycmVjdGx5IGNvbmZpZ3VyZWQsIGEgbG9vcGJhY2sgQ2FzY2FkZSBDb25uZWN0aW9uIGNvdWxkIGluYWR2ZXJ0ZW50bHkgYmUgY3JlYXRlZC4gV2hlbiB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiBmdW5jdGlvbiBwbGVhc2UgZGVzaWduIHRoZSBuZXR3b3JrIHRvcG9sb2d5IHdpdGggY2FyZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUxpbmsgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNyZWF0ZUxpbmtcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgQ2FzY2FkZSBDb25uZWN0aW9uIFNldHRpbmcuIFVzZSB0aGlzIHRvIGdldCB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nIG9mIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGNoYW5nZSB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nIGNvbnRlbnRzIG9mIHRoZSBDYXNjYWRlIENvbm5lY3Rpb24sIHVzZSB0aGUgQVBJcyB0aGF0IGluY2x1ZGUgdGhlIG5hbWUgXCJMaW5rXCIgYWZ0ZXIgY3JlYXRpbmcgdGhlIENhc2NhZGUgQ29ubmVjdGlvbi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldExpbmsgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldExpbmtcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIENoYW5nZSBFeGlzdGluZyBDYXNjYWRlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGFsdGVyIHRoZSBzZXR0aW5nIG9mIGFuIGV4aXN0aW5nIENhc2NhZGUgQ29ubmVjdGlvbiBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpcy5TZXRMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBDYXNjYWRlIENvbm5lY3Rpb25zLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIENhc2NhZGUgQ29ubmVjdGlvbnMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIEJ5IHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uLCB5b3UgY2FuIGNvbm5lY3QgdGhpcyBWaXJ0dWFsIEh1YiBieSBMYXllciAyIENhc2NhZGUgQ29ubmVjdGlvbiB0byBhbm90aGVyIFZpcnR1YWwgSHViIHRoYXQgaXMgb3BlcmF0aW5nIG9uIHRoZSBzYW1lIG9yIGEgZGlmZmVyZW50IGNvbXB1dGVyLiBbV2FybmluZyBBYm91dCBDYXNjYWRlIENvbm5lY3Rpb25zXSBCeSBjb25uZWN0aW5nIHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHlvdSBjYW4gY3JlYXRlIGEgTGF5ZXIgMiBicmlkZ2UgYmV0d2VlbiBtdWx0aXBsZSBWaXJ0dWFsIEh1YnMgYnV0IGlmIHRoZSBjb25uZWN0aW9uIGlzIGluY29ycmVjdGx5IGNvbmZpZ3VyZWQsIGEgbG9vcGJhY2sgQ2FzY2FkZSBDb25uZWN0aW9uIGNvdWxkIGluYWR2ZXJ0ZW50bHkgYmUgY3JlYXRlZC4gV2hlbiB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiBmdW5jdGlvbiBwbGVhc2UgZGVzaWduIHRoZSBuZXR3b3JrIHRvcG9sb2d5IHdpdGggY2FyZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1MaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTGlua1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU3dpdGNoIENhc2NhZGUgQ29ubmVjdGlvbiB0byBPbmxpbmUgU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCwgdXNlIHRoaXMgdG8gc3dpdGNoIHRoYXQgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIG9ubGluZSBzdGF0dXMuIFRoZSBDYXNjYWRlIENvbm5lY3Rpb24gdGhhdCBpcyBzd2l0Y2hlZCB0byBvbmxpbmUgc3RhdHVzIGJlZ2lucyB0aGUgcHJvY2VzcyBvZiBjb25uZWN0aW5nIHRvIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nLiBUaGUgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgc3dpdGNoZWQgdG8gb25saW5lIHN0YXR1cyB3aWxsIGVzdGFibGlzaCBub3JtYWwgY29ubmVjdGlvbiB0byB0aGUgVlBOIFNlcnZlciBvciBjb250aW51ZSB0byBhdHRlbXB0IGNvbm5lY3Rpb24gdW50aWwgaXQgaXMgc3dpdGNoZWQgdG8gb2ZmbGluZSBzdGF0dXMuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRMaW5rT25saW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rT25saW5lXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTd2l0Y2ggQ2FzY2FkZSBDb25uZWN0aW9uIHRvIE9mZmxpbmUgU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCwgdXNlIHRoaXMgdG8gc3dpdGNoIHRoYXQgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIG9mZmxpbmUgc3RhdHVzLiBUaGUgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgc3dpdGNoZWQgdG8gb2ZmbGluZSB3aWxsIG5vdCBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIHVudGlsIG5leHQgdGltZSBpdCBpcyBzd2l0Y2hlZCB0byB0aGUgb25saW5lIHN0YXR1cyB1c2luZyB0aGUgU2V0TGlua09ubGluZSBBUEkgWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldExpbmtPZmZsaW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rT2ZmbGluZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRGVsZXRlIENhc2NhZGUgQ29ubmVjdGlvbiBTZXR0aW5nLiBVc2UgdGhpcyB0byBkZWxldGUgYSBDYXNjYWRlIENvbm5lY3Rpb24gdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gSWYgdGhlIHNwZWNpZmllZCBDYXNjYWRlIENvbm5lY3Rpb24gaGFzIGEgc3RhdHVzIG9mIG9ubGluZSwgdGhlIGNvbm5lY3Rpb25zIHdpbGwgYmUgYXV0b21hdGljYWxseSBkaXNjb25uZWN0ZWQgYW5kIHRoZW4gdGhlIENhc2NhZGUgQ29ubmVjdGlvbiB3aWxsIGJlIGRlbGV0ZWQuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5EZWxldGVMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDaGFuZ2UgTmFtZSBvZiBDYXNjYWRlIENvbm5lY3Rpb24uIFdoZW4gYSBDYXNjYWRlIENvbm5lY3Rpb24gcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgaXMgc3BlY2lmaWVkLCB1c2UgdGhpcyB0byBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhhdCBDYXNjYWRlIENvbm5lY3Rpb24uIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5SZW5hbWVMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJSZW5hbWVMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQ3VycmVudCBDYXNjYWRlIENvbm5lY3Rpb24gU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCBhbmQgdGhhdCBDYXNjYWRlIENvbm5lY3Rpb24gaXMgY3VycmVudGx5IG9ubGluZSwgdXNlIHRoaXMgdG8gZ2V0IGl0cyBjb25uZWN0aW9uIHN0YXR1cyBhbmQgb3RoZXIgaW5mb3JtYXRpb24uIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRMaW5rU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRMaW5rU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBBZGQgQWNjZXNzIExpc3QgUnVsZS4gVXNlIHRoaXMgdG8gYWRkIGEgbmV3IHJ1bGUgdG8gdGhlIGFjY2VzcyBsaXN0IG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGFjY2VzcyBsaXN0IGlzIGEgc2V0IG9mIHBhY2tldCBmaWxlIHJ1bGVzIHRoYXQgYXJlIGFwcGxpZWQgdG8gcGFja2V0cyB0aGF0IGZsb3cgdGhyb3VnaCB0aGUgVmlydHVhbCBIdWIuIFlvdSBjYW4gcmVnaXN0ZXIgbXVsdGlwbGUgcnVsZXMgaW4gYW4gYWNjZXNzIGxpc3QgYW5kIHlvdSBjYW4gYWxzbyBkZWZpbmUgYW4gcHJpb3JpdHkgZm9yIGVhY2ggcnVsZS4gQWxsIHBhY2tldHMgYXJlIGNoZWNrZWQgZm9yIHRoZSBjb25kaXRpb25zIHNwZWNpZmllZCBieSB0aGUgcnVsZXMgcmVnaXN0ZXJlZCBpbiB0aGUgYWNjZXNzIGxpc3QgYW5kIGJhc2VkIG9uIHRoZSBvcGVyYXRpb24gdGhhdCBpcyBzdGlwdWxhdGVkIGJ5IHRoZSBmaXJzdCBtYXRjaGluZyBydWxlLCB0aGV5IGVpdGhlciBwYXNzIG9yIGFyZSBkaXNjYXJkZWQuIFBhY2tldHMgdGhhdCBkbyBub3QgbWF0Y2ggYW55IHJ1bGUgYXJlIGltcGxpY2l0bHkgYWxsb3dlZCB0byBwYXNzLiBZb3UgY2FuIGFsc28gdXNlIHRoZSBhY2Nlc3MgbGlzdCB0byBnZW5lcmF0ZSBkZWxheXMsIGppdHRlcnMgYW5kIHBhY2tldCBsb3NzZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQWRkQWNjZXNzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJBZGRBY2Nlc3NcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBSdWxlIGZyb20gQWNjZXNzIExpc3QuIFVzZSB0aGlzIHRvIHNwZWNpZnkgYSBwYWNrZXQgZmlsdGVyIHJ1bGUgcmVnaXN0ZXJlZCBvbiB0aGUgYWNjZXNzIGxpc3Qgb2YgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBkZWxldGUgaXQuIFRvIGRlbGV0ZSBhIHJ1bGUsIHlvdSBtdXN0IHNwZWNpZnkgdGhhdCBydWxlJ3MgSUQuIFlvdSBjYW4gZGlzcGxheSB0aGUgSUQgYnkgdXNpbmcgdGhlIEVudW1BY2Nlc3MgQVBJLiBJZiB5b3Ugd2lzaCBub3QgdG8gZGVsZXRlIHRoZSBydWxlIGJ1dCB0byBvbmx5IHRlbXBvcmFyaWx5IGRpc2FibGUgaXQsIHVzZSB0aGUgU2V0QWNjZXNzTGlzdCBBUEkgdG8gc2V0IHRoZSBydWxlIHN0YXR1cyB0byBkaXNhYmxlLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUFjY2VzcyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlQWNjZXNzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQWNjZXNzIExpc3QgUnVsZSBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIHBhY2tldCBmaWx0ZXIgcnVsZXMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiBhY2Nlc3MgbGlzdCBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSBhY2Nlc3MgbGlzdCBpcyBhIHNldCBvZiBwYWNrZXQgZmlsZSBydWxlcyB0aGF0IGFyZSBhcHBsaWVkIHRvIHBhY2tldHMgdGhhdCBmbG93IHRocm91Z2ggdGhlIFZpcnR1YWwgSHViLiBZb3UgY2FuIHJlZ2lzdGVyIG11bHRpcGxlIHJ1bGVzIGluIGFuIGFjY2VzcyBsaXN0IGFuZCB5b3UgY2FuIGFsc28gZGVmaW5lIGEgcHJpb3JpdHkgZm9yIGVhY2ggcnVsZS4gQWxsIHBhY2tldHMgYXJlIGNoZWNrZWQgZm9yIHRoZSBjb25kaXRpb25zIHNwZWNpZmllZCBieSB0aGUgcnVsZXMgcmVnaXN0ZXJlZCBpbiB0aGUgYWNjZXNzIGxpc3QgYW5kIGJhc2VkIG9uIHRoZSBvcGVyYXRpb24gdGhhdCBpcyBzdGlwdWxhdGVkIGJ5IHRoZSBmaXJzdCBtYXRjaGluZyBydWxlLCB0aGV5IGVpdGhlciBwYXNzIG9yIGFyZSBkaXNjYXJkZWQuIFBhY2tldHMgdGhhdCBkbyBub3QgbWF0Y2ggYW55IHJ1bGUgYXJlIGltcGxpY2l0bHkgYWxsb3dlZCB0byBwYXNzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1BY2Nlc3MgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1BY2Nlc3NcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFJlcGxhY2UgYWxsIGFjY2VzcyBsaXN0cyBvbiBhIHNpbmdsZSBidWxrIEFQSSBjYWxsLiBUaGlzIEFQSSByZW1vdmVzIGFsbCBleGlzdGluZyBhY2Nlc3MgbGlzdCBydWxlcyBvbiB0aGUgVmlydHVhbCBIdWIsIGFuZCByZXBsYWNlIHRoZW0gYnkgbmV3IGFjY2VzcyBsaXN0IHJ1bGVzIHNwZWNpZmllZCBieSB0aGUgcGFyYW1ldGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0QWNjZXNzTGlzdCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0QWNjZXNzTGlzdFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ3JlYXRlIGEgdXNlci4gVXNlIHRoaXMgdG8gY3JlYXRlIGEgbmV3IHVzZXIgaW4gdGhlIHNlY3VyaXR5IGFjY291bnQgZGF0YWJhc2Ugb2YgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBCeSBjcmVhdGluZyBhIHVzZXIsIHRoZSBWUE4gQ2xpZW50IGNhbiBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1YiBieSB1c2luZyB0aGUgYXV0aGVudGljYXRpb24gaW5mb3JtYXRpb24gb2YgdGhhdCB1c2VyLiBOb3RlIHRoYXQgYSB1c2VyIHdob3NlIHVzZXIgbmFtZSBoYXMgYmVlbiBjcmVhdGVkIGFzIFwiKlwiIChhIHNpbmdsZSBhc3RlcmlzayBjaGFyYWN0ZXIpIHdpbGwgYXV0b21hdGljYWxseSBiZSByZWdpc3RlcmVkIGFzIGEgUkFESVVTIGF1dGhlbnRpY2F0aW9uIHVzZXIuIEZvciBjYXNlcyB3aGVyZSB0aGVyZSBhcmUgdXNlcnMgd2l0aCBcIipcIiBhcyB0aGUgbmFtZSwgd2hlbiBhIHVzZXIsIHdob3NlIHVzZXIgbmFtZSB0aGF0IGhhcyBiZWVuIHByb3ZpZGVkIHdoZW4gYSBjbGllbnQgY29ubmVjdGVkIHRvIGEgVlBOIFNlcnZlciBkb2VzIG5vdCBtYXRjaCBleGlzdGluZyB1c2VyIG5hbWVzLCBpcyBhYmxlIHRvIGJlIGF1dGhlbnRpY2F0ZWQgYnkgYSBSQURJVVMgc2VydmVyIG9yIE5UIGRvbWFpbiBjb250cm9sbGVyIGJ5IGlucHV0dGluZyBhIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQsIHRoZSBhdXRoZW50aWNhdGlvbiBzZXR0aW5ncyBhbmQgc2VjdXJpdHkgcG9saWN5IHNldHRpbmdzIHdpbGwgZm9sbG93IHRoZSBzZXR0aW5nIGZvciB0aGUgdXNlciBcIipcIi4gVG8gY2hhbmdlIHRoZSB1c2VyIGluZm9ybWF0aW9uIG9mIGEgdXNlciB0aGF0IGhhcyBiZWVuIGNyZWF0ZWQsIHVzZSB0aGUgU2V0VXNlciBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlVXNlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQ3JlYXRlVXNlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIFVzZXIgU2V0dGluZ3MuIFVzZSB0aGlzIHRvIGNoYW5nZSB1c2VyIHNldHRpbmdzIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSB1c2VyIHNldHRpbmdzIHRoYXQgY2FuIGJlIGNoYW5nZWQgdXNpbmcgdGhpcyBBUEkgYXJlIHRoZSB0aHJlZSBpdGVtcyB0aGF0IGFyZSBzcGVjaWZpZWQgd2hlbiBhIG5ldyB1c2VyIGlzIGNyZWF0ZWQgdXNpbmcgdGhlIENyZWF0ZVVzZXIgQVBJOiBHcm91cCBOYW1lLCBGdWxsIE5hbWUsIGFuZCBEZXNjcmlwdGlvbi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHVzZXJzLCB1c2UgdGhlIEVudW1Vc2VyIEFQSS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRVc2VyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRVc2VyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgVXNlciBTZXR0aW5ncy4gVXNlIHRoaXMgdG8gZ2V0IHVzZXIgc2V0dGluZ3MgaW5mb3JtYXRpb24gdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGluZm9ybWF0aW9uIHRoYXQgeW91IGNhbiBnZXQgdXNpbmcgdGhpcyBBUEkgYXJlIFVzZXIgTmFtZSwgRnVsbCBOYW1lLCBHcm91cCBOYW1lLCBFeHBpcmF0aW9uIERhdGUsIFNlY3VyaXR5IFBvbGljeSwgYW5kIEF1dGggVHlwZSwgYXMgd2VsbCBhcyBwYXJhbWV0ZXJzIHRoYXQgYXJlIHNwZWNpZmllZCBhcyBhdXRoIHR5cGUgYXR0cmlidXRlcyBhbmQgdGhlIHN0YXRpc3RpY2FsIGRhdGEgb2YgdGhhdCB1c2VyLiBUbyBnZXQgdGhlIGxpc3Qgb2YgY3VycmVudGx5IHJlZ2lzdGVyZWQgdXNlcnMsIHVzZSB0aGUgRW51bVVzZXIgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldFVzZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFVzZXJcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBhIHVzZXIuIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHVzZXIgdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgZGVsZXRpbmcgdGhlIHVzZXIsIHRoYXQgdXNlciB3aWxsIG5vIGxvbmcgYmUgYWJsZSB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1Yi4gWW91IGNhbiB1c2UgdGhlIFNldFVzZXIgQVBJIHRvIHNldCB0aGUgdXNlcidzIHNlY3VyaXR5IHBvbGljeSB0byBkZW55IGFjY2VzcyBpbnN0ZWFkIG9mIGRlbGV0aW5nIGEgdXNlciwgc2V0IHRoZSB1c2VyIHRvIGJlIHRlbXBvcmFyaWx5IGRlbmllZCBmcm9tIGxvZ2dpbmcgaW4uIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgcmVnaXN0ZXJlZCB1c2VycywgdXNlIHRoZSBFbnVtVXNlciBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRGVsZXRlVXNlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlVXNlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgVXNlcnMuIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgdXNlcnMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bVVzZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1Vc2VyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgR3JvdXAuIFVzZSB0aGlzIHRvIGNyZWF0ZSBhIG5ldyBncm91cCBpbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFlvdSBjYW4gcmVnaXN0ZXIgbXVsdGlwbGUgdXNlcnMgaW4gYSBncm91cC4gVG8gcmVnaXN0ZXIgdXNlcnMgaW4gYSBncm91cCB1c2UgdGhlIFNldFVzZXIgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJDcmVhdGVHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IGdyb3VwIHNldHRpbmdzLiBVc2UgdGhpcyB0byBzZXQgZ3JvdXAgc2V0dGluZ3MgdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIGdyb3VwcywgdXNlIHRoZSBFbnVtR3JvdXAgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IEdyb3VwIFNldHRpbmcgKFN5bmMgbW9kZSkuIFVzZSB0aGlzIHRvIGdldCB0aGUgc2V0dGluZyBvZiBhIGdyb3VwIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgcmVnaXN0ZXJlZCBncm91cHMsIHVzZSB0aGUgRW51bUdyb3VwIEFQSS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRHcm91cCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0R3JvdXBcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBVc2VyIGZyb20gR3JvdXAuIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHNwZWNpZmllZCB1c2VyIGZyb20gdGhlIGdyb3VwIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIEJ5IGRlbGV0aW5nIGEgdXNlciBmcm9tIHRoZSBncm91cCwgdGhhdCB1c2VyIGJlY29tZXMgdW5hc3NpZ25lZC4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIGdyb3VwcywgdXNlIHRoZSBFbnVtR3JvdXAgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgR3JvdXBzLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIGdyb3VwcyB0aGF0IGFyZSByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5FbnVtR3JvdXAgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1Hcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgQ29ubmVjdGVkIFZQTiBTZXNzaW9ucy4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiB0aGUgc2Vzc2lvbnMgY29ubmVjdGVkIHRvIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZC4gSW4gdGhlIGxpc3Qgb2Ygc2Vzc2lvbnMsIHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb24gd2lsbCBiZSBvYnRhaW5lZCBmb3IgZWFjaCBjb25uZWN0aW9uOiBTZXNzaW9uIE5hbWUsIFNlc3Npb24gU2l0ZSwgVXNlciBOYW1lLCBTb3VyY2UgSG9zdCBOYW1lLCBUQ1AgQ29ubmVjdGlvbiwgVHJhbnNmZXIgQnl0ZXMgYW5kIFRyYW5zZmVyIFBhY2tldHMuIElmIHRoZSBjdXJyZW50bHkgY29ubmVjdGVkIFZQTiBTZXJ2ZXIgaXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIgYW5kIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBpcyBhIHN0YXRpYyBWaXJ0dWFsIEh1YiwgeW91IGNhbiBnZXQgYW4gYWxsLWxpbmtlZC10b2dldGhlciBsaXN0IG9mIGFsbCBzZXNzaW9ucyBjb25uZWN0ZWQgdG8gdGhhdCBWaXJ0dWFsIEh1YiBvbiBhbGwgY2x1c3RlciBtZW1iZXJzLiBJbiBhbGwgb3RoZXIgY2FzZXMsIG9ubHkgdGhlIGxpc3Qgb2Ygc2Vzc2lvbnMgdGhhdCBhcmUgYWN0dWFsbHkgY29ubmVjdGVkIHRvIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWUE4gU2VydmVyIHdpbGwgYmUgb2J0YWluZWQuICovXHJcbiAgICAgICAgdGhpcy5FbnVtU2Vzc2lvbiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bVNlc3Npb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBTZXNzaW9uIFN0YXR1cy4gVXNlIHRoaXMgdG8gc3BlY2lmeSBhIHNlc3Npb24gY3VycmVudGx5IGNvbm5lY3RlZCB0byB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIGdldCB0aGUgc2Vzc2lvbiBpbmZvcm1hdGlvbi4gVGhlIHNlc3Npb24gc3RhdHVzIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmc6IHNvdXJjZSBob3N0IG5hbWUgYW5kIHVzZXIgbmFtZSwgdmVyc2lvbiBpbmZvcm1hdGlvbiwgdGltZSBpbmZvcm1hdGlvbiwgbnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucywgY29tbXVuaWNhdGlvbiBwYXJhbWV0ZXJzLCBzZXNzaW9uIGtleSwgc3RhdGlzdGljYWwgaW5mb3JtYXRpb24gb24gZGF0YSB0cmFuc2ZlcnJlZCwgYW5kIG90aGVyIGNsaWVudCBhbmQgc2VydmVyIGluZm9ybWF0aW9uLiBUbyBnZXQgdGhlIGxpc3Qgb2YgY3VycmVudGx5IGNvbm5lY3RlZCBzZXNzaW9ucywgdXNlIHRoZSBFbnVtU2Vzc2lvbiBBUEkuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXNzaW9uU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRTZXNzaW9uU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEaXNjb25uZWN0IFNlc3Npb24uIFVzZSB0aGlzIHRvIHNwZWNpZnkgYSBzZXNzaW9uIGN1cnJlbnRseSBjb25uZWN0ZWQgdG8gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBmb3JjZWZ1bGx5IGRpc2Nvbm5lY3QgdGhhdCBzZXNzaW9uIHVzaW5nIG1hbmFnZXIgcHJpdmlsZWdlcy4gTm90ZSB0aGF0IHdoZW4gY29tbXVuaWNhdGlvbiBpcyBkaXNjb25uZWN0ZWQgYnkgc2V0dGluZ3Mgb24gdGhlIHNvdXJjZSBjbGllbnQgc2lkZSBhbmQgdGhlIGF1dG9tYXRpY2FsbHkgcmVjb25uZWN0IG9wdGlvbiBpcyBlbmFibGVkLCBpdCBpcyBwb3NzaWJsZSB0aGF0IHRoZSBjbGllbnQgd2lsbCByZWNvbm5lY3QuIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgY29ubmVjdGVkIHNlc3Npb25zLCB1c2UgdGhlIEVudW1TZXNzaW9uIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZVNlc3Npb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbGV0ZVNlc3Npb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgTUFDIEFkZHJlc3MgVGFibGUgRGF0YWJhc2UuIFVzZSB0aGlzIHRvIGdldCB0aGUgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdGhhdCBpcyBoZWxkIGJ5IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIE1BQyBhZGRyZXNzIHRhYmxlIGRhdGFiYXNlIGlzIGEgdGFibGUgdGhhdCB0aGUgVmlydHVhbCBIdWIgcmVxdWlyZXMgdG8gcGVyZm9ybSB0aGUgYWN0aW9uIG9mIHN3aXRjaGluZyBFdGhlcm5ldCBmcmFtZXMgYW5kIHRoZSBWaXJ0dWFsIEh1YiBkZWNpZGVzIHRoZSBzb3J0aW5nIGRlc3RpbmF0aW9uIHNlc3Npb24gb2YgZWFjaCBFdGhlcm5ldCBmcmFtZSBiYXNlZCBvbiB0aGUgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UuIFRoZSBNQUMgYWRkcmVzcyBkYXRhYmFzZSBpcyBidWlsdCBieSB0aGUgVmlydHVhbCBIdWIgYXV0b21hdGljYWxseSBhbmFseXppbmcgdGhlIGNvbnRlbnRzIG9mIHRoZSBjb21tdW5pY2F0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bU1hY1RhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTWFjVGFibGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBNQUMgQWRkcmVzcyBUYWJsZSBFbnRyeS4gVXNlIHRoaXMgQVBJIHRvIG9wZXJhdGUgdGhlIE1BQyBhZGRyZXNzIHRhYmxlIGRhdGFiYXNlIGhlbGQgYnkgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBkZWxldGUgYSBzcGVjaWZpZWQgTUFDIGFkZHJlc3MgdGFibGUgZW50cnkgZnJvbSB0aGUgZGF0YWJhc2UuIFRvIGdldCB0aGUgY29udGVudHMgb2YgdGhlIGN1cnJlbnQgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdXNlIHRoZSBFbnVtTWFjVGFibGUgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuRGVsZXRlTWFjVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbGV0ZU1hY1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIElQIEFkZHJlc3MgVGFibGUgRGF0YWJhc2UuIFVzZSB0aGlzIHRvIGdldCB0aGUgSVAgYWRkcmVzcyB0YWJsZSBkYXRhYmFzZSB0aGF0IGlzIGhlbGQgYnkgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgSVAgYWRkcmVzcyB0YWJsZSBkYXRhYmFzZSBpcyBhIHRhYmxlIHRoYXQgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYnkgYW5hbHl6aW5nIHRoZSBjb250ZW50cyBvZiBjb21tdW5pY2F0aW9uIHNvIHRoYXQgdGhlIFZpcnR1YWwgSHViIGNhbiBhbHdheXMga25vdyB3aGljaCBzZXNzaW9uIGlzIHVzaW5nIHdoaWNoIElQIGFkZHJlc3MgYW5kIGl0IGlzIGZyZXF1ZW50bHkgdXNlZCBieSB0aGUgZW5naW5lIHRoYXQgYXBwbGllcyB0aGUgVmlydHVhbCBIdWIgc2VjdXJpdHkgcG9saWN5LiBCeSBzcGVjaWZ5aW5nIHRoZSBzZXNzaW9uIG5hbWUgeW91IGNhbiBnZXQgdGhlIElQIGFkZHJlc3MgdGFibGUgZW50cnkgdGhhdCBoYXMgYmVlbiBhc3NvY2lhdGVkIHdpdGggdGhhdCBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUlwVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1JcFRhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgSVAgQWRkcmVzcyBUYWJsZSBFbnRyeS4gVXNlIHRoaXMgQVBJIHRvIG9wZXJhdGUgdGhlIElQIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgaGVsZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIGRlbGV0ZSBhIHNwZWNpZmllZCBJUCBhZGRyZXNzIHRhYmxlIGVudHJ5IGZyb20gdGhlIGRhdGFiYXNlLiBUbyBnZXQgdGhlIGNvbnRlbnRzIG9mIHRoZSBjdXJyZW50IElQIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdXNlIHRoZSBFbnVtSXBUYWJsZSBBUEkuICovXHJcbiAgICAgICAgdGhpcy5EZWxldGVJcFRhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVJcFRhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gc2V0IHRoZSBkZXN0aW5hdGlvbiBob3N0IG5hbWUgZXRjLiBvZiB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLiBGb3IgbmV0d29yayBjb25uZWN0aW9uIGVudmlyb25tZW50cyB3aGVyZSBjb25uZWN0aW9ucyB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzY29ubmVjdGVkIHdoZXJlIHRoZXJlIGFyZSBwZXJpb2RzIG9mIG5vIGNvbW11bmljYXRpb24gdGhhdCBhcmUgbG9uZ2VyIHRoYW4gYSBzZXQgcGVyaW9kLCBieSB1c2luZyB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLCBpdCBpcyBwb3NzaWJsZSB0byBrZWVwIGFsaXZlIHRoZSBJbnRlcm5ldCBjb25uZWN0aW9uIGJ5IHNlbmRpbmcgcGFja2V0cyB0byBhIG5vbWluYXRlZCBzZXJ2ZXIgb24gdGhlIEludGVybmV0IGF0IHNldCBpbnRlcnZhbHMuIFdoZW4gdXNpbmcgdGhpcyBBUEksIHlvdSBjYW4gc3BlY2lmeSB0aGUgZm9sbG93aW5nOiBIb3N0IE5hbWUsIFBvcnQgTnVtYmVyLCBQYWNrZXQgU2VuZCBJbnRlcnZhbCwgYW5kIFByb3RvY29sLiBQYWNrZXRzIHNlbnQgdG8ga2VlcCBhbGl2ZSB0aGUgSW50ZXJuZXQgY29ubmVjdGlvbiB3aWxsIGhhdmUgcmFuZG9tIGNvbnRlbnQgYW5kIHBlcnNvbmFsIGluZm9ybWF0aW9uIHRoYXQgY291bGQgaWRlbnRpZnkgYSBjb21wdXRlciBvciB1c2VyIGlzIG5vdCBzZW50LiBZb3UgY2FuIHVzZSB0aGUgU2V0S2VlcCBBUEkgdG8gZW5hYmxlL2Rpc2FibGUgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVG8gZXhlY3V0ZSB0aGlzIEFQSSBvbiBhIFZQTiBTZXJ2ZXIgb3IgVlBOIEJyaWRnZSwgeW91IG11c3QgaGF2ZSBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRLZWVwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRLZWVwXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgY29udGVudHMgb2YgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gSW4gYWRkaXRpb24gdG8gdGhlIGRlc3RpbmF0aW9uJ3MgSG9zdCBOYW1lLCBQb3J0IE51bWJlciwgUGFja2V0IFNlbmQgSW50ZXJ2YWwgYW5kIFByb3RvY29sLCB5b3UgY2FuIG9idGFpbiB0aGUgY3VycmVudCBlbmFibGVkL2Rpc2FibGVkIHN0YXR1cyBvZiB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0S2VlcCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0S2VlcFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRW5hYmxlIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgRnVuY3Rpb24gKFNlY3VyZU5BVCBGdW5jdGlvbikuIFVzZSB0aGlzIHRvIGVuYWJsZSB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBhbmQgYmVnaW4gaXRzIG9wZXJhdGlvbi4gQmVmb3JlIGV4ZWN1dGluZyB0aGlzIEFQSSwgeW91IG11c3QgZmlyc3QgY2hlY2sgdGhlIHNldHRpbmcgY29udGVudHMgb2YgdGhlIGN1cnJlbnQgVmlydHVhbCBOQVQgZnVuY3Rpb24gYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIHVzaW5nIHRoZSBTZXRTZWN1cmVOQVRPcHRpb24gQVBJIGFuZCBHZXRTZWN1cmVOQVRPcHRpb24gQVBJLiBCeSBlbmFibGluZyB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCB5b3UgY2FuIHZpcnR1YWxseSBvcGVyYXRlIGEgTkFUIHJvdXRlciAoSVAgbWFzcXVlcmFkZSkgYW5kIHRoZSBESENQIFNlcnZlciBmdW5jdGlvbiBvbiBhIHZpcnR1YWwgbmV0d29yayBvbiB0aGUgVmlydHVhbCBIdWIuIFtXYXJuaW5nIGFib3V0IFNlY3VyZU5BVCBGdW5jdGlvbl0gVGhlIFNlY3VyZU5BVCBmdW5jdGlvbiBpcyByZWNvbW1lbmRlZCBvbmx5IGZvciBzeXN0ZW0gYWRtaW5pc3RyYXRvcnMgYW5kIHBlb3BsZSB3aXRoIGEgZGV0YWlsZWQga25vd2xlZGdlIG9mIG5ldHdvcmtzLiBJZiB5b3UgdXNlIHRoZSBTZWN1cmVOQVQgZnVuY3Rpb24gY29ycmVjdGx5LCBpdCBpcyBwb3NzaWJsZSB0byBhY2hpZXZlIGEgc2FmZSBmb3JtIG9mIHJlbW90ZSBhY2Nlc3MgdmlhIGEgVlBOLiBIb3dldmVyIHdoZW4gdXNlZCBpbiB0aGUgd3Jvbmcgd2F5LCBpdCBjYW4gcHV0IHRoZSBlbnRpcmUgbmV0d29yayBpbiBkYW5nZXIuIEFueW9uZSB3aG8gZG9lcyBub3QgaGF2ZSBhIHRob3JvdWdoIGtub3dsZWRnZSBvZiBuZXR3b3JrcyBhbmQgYW55b25lIHdobyBkb2VzIG5vdCBoYXZlIHRoZSBuZXR3b3JrIGFkbWluaXN0cmF0b3IncyBwZXJtaXNzaW9uIG11c3Qgbm90IGVuYWJsZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLiBGb3IgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIFZQTiBTZXJ2ZXIncyBtYW51YWwgYW5kIG9ubGluZSBkb2N1bWVudGF0aW9uLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlU2VjdXJlTkFUID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbmFibGVTZWN1cmVOQVRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERpc2FibGUgdGhlIFZpcnR1YWwgTkFUIGFuZCBESENQIFNlcnZlciBGdW5jdGlvbiAoU2VjdXJlTkFUIEZ1bmN0aW9uKS4gVXNlIHRoaXMgdG8gZGlzYWJsZSB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgZXhlY3V0aW5nIHRoaXMgQVBJIHRoZSBWaXJ0dWFsIE5BVCBmdW5jdGlvbiBpbW1lZGlhdGVseSBzdG9wcyBvcGVyYXRpbmcgYW5kIHRoZSBWaXJ0dWFsIERIQ1AgU2VydmVyIGZ1bmN0aW9uIGRlbGV0ZXMgdGhlIERIQ1AgbGVhc2UgZGF0YWJhc2UgYW5kIHN0b3BzIHRoZSBzZXJ2aWNlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRGlzYWJsZVNlY3VyZU5BVCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGlzYWJsZVNlY3VyZU5BVFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIFNldHRpbmdzIG9mIFNlY3VyZU5BVCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gY2hhbmdlIGFuZCBzYXZlIHRoZSB2aXJ0dWFsIGhvc3QgbmV0d29yayBpbnRlcmZhY2Ugc2V0dGluZ3MsIHZpcnR1YWwgTkFUIGZ1bmN0aW9uIHNldHRpbmdzIGFuZCB2aXJ0dWFsIERIQ1Agc2VydmVyIHNldHRpbmdzIG9mIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgZnVuY3Rpb24gKFNlY3VyZU5BVCBmdW5jdGlvbikgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgU2VjdXJlTkFUIGZ1bmN0aW9uIGhvbGRzIG9uZSB2aXJ0dWFsIG5ldHdvcmsgYWRhcHRlciBvbiB0aGUgTDIgc2VnbWVudCBpbnNpZGUgdGhlIFZpcnR1YWwgSHViIGFuZCBpdCBoYXMgYmVlbiBhc3NpZ25lZCBhIE1BQyBhZGRyZXNzIGFuZCBhbiBJUCBhZGRyZXNzLiBCeSBkb2luZyB0aGlzLCBhbm90aGVyIGhvc3QgY29ubmVjdGVkIHRvIHRoZSBzYW1lIEwyIHNlZ21lbnQgaXMgYWJsZSB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBTZWN1cmVOQVQgdmlydHVhbCBob3N0IGFzIGlmIGl0IGlzIGFuIGFjdHVhbCBJUCBob3N0IGV4aXN0aW5nIG9uIHRoZSBuZXR3b3JrLiBbV2FybmluZyBhYm91dCBTZWN1cmVOQVQgRnVuY3Rpb25dIFRoZSBTZWN1cmVOQVQgZnVuY3Rpb24gaXMgcmVjb21tZW5kZWQgb25seSBmb3Igc3lzdGVtIGFkbWluaXN0cmF0b3JzIGFuZCBwZW9wbGUgd2l0aCBhIGRldGFpbGVkIGtub3dsZWRnZSBvZiBuZXR3b3Jrcy4gSWYgeW91IHVzZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uIGNvcnJlY3RseSwgaXQgaXMgcG9zc2libGUgdG8gYWNoaWV2ZSBhIHNhZmUgZm9ybSBvZiByZW1vdGUgYWNjZXNzIHZpYSBhIFZQTi4gSG93ZXZlciB3aGVuIHVzZWQgaW4gdGhlIHdyb25nIHdheSwgaXQgY2FuIHB1dCB0aGUgZW50aXJlIG5ldHdvcmsgaW4gZGFuZ2VyLiBBbnlvbmUgd2hvIGRvZXMgbm90IGhhdmUgYSB0aG9yb3VnaCBrbm93bGVkZ2Ugb2YgbmV0d29ya3MgYW5kIGFueW9uZSB3aG8gZG9lcyBub3QgaGF2ZSB0aGUgbmV0d29yayBhZG1pbmlzdHJhdG9ycyBwZXJtaXNzaW9uIG11c3Qgbm90IGVuYWJsZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLiBGb3IgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIFZQTiBTZXJ2ZXIncyBtYW51YWwgYW5kIG9ubGluZSBkb2N1bWVudGF0aW9uLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0U2VjdXJlTkFUT3B0aW9uID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRTZWN1cmVOQVRPcHRpb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBTZXR0aW5ncyBvZiBTZWN1cmVOQVQgRnVuY3Rpb24uIFRoaXMgQVBJIGdldCB0aGUgcmVnaXN0ZXJlZCBzZXR0aW5ncyBmb3IgdGhlIFNlY3VyZU5BVCBmdW5jdGlvbiB3aGljaCBpcyBzZXQgYnkgdGhlIFNldFNlY3VyZU5BVE9wdGlvbiBBUEkuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZWN1cmVOQVRPcHRpb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFNlY3VyZU5BVE9wdGlvblwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IFZpcnR1YWwgTkFUIEZ1bmN0aW9uIFNlc3Npb24gVGFibGUgb2YgU2VjdXJlTkFUIEZ1bmN0aW9uLiBVc2UgdGhpcyB0byBnZXQgdGhlIHRhYmxlIG9mIFRDUCBhbmQgVURQIHNlc3Npb25zIGN1cnJlbnRseSBjb21tdW5pY2F0aW5nIHZpYSB0aGUgVmlydHVhbCBOQVQgKE5BVCB0YWJsZSkgaW4gY2FzZXMgd2hlbiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1OQVQgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1OQVRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBWaXJ0dWFsIERIQ1AgU2VydmVyIEZ1bmN0aW9uIExlYXNlIFRhYmxlIG9mIFNlY3VyZU5BVCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBsZWFzZSB0YWJsZSBvZiBJUCBhZGRyZXNzZXMsIGhlbGQgYnkgdGhlIFZpcnR1YWwgREhDUCBTZXJ2ZXIsIHRoYXQgYXJlIGFzc2lnbmVkIHRvIGNsaWVudHMgaW4gY2FzZXMgd2hlbiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1ESENQID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtREhDUFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBPcGVyYXRpbmcgU3RhdHVzIG9mIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgRnVuY3Rpb24gKFNlY3VyZU5BVCBGdW5jdGlvbikuIFVzZSB0aGlzIHRvIGdldCB0aGUgb3BlcmF0aW5nIHN0YXR1cyBvZiB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIHdoZW4gaXQgaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldFNlY3VyZU5BVFN0YXR1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VjdXJlTkFUU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBOZXR3b3JrIEFkYXB0ZXJzIFVzYWJsZSBhcyBMb2NhbCBCcmlkZ2UuIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgRXRoZXJuZXQgZGV2aWNlcyAobmV0d29yayBhZGFwdGVycykgdGhhdCBjYW4gYmUgdXNlZCBhcyBhIGJyaWRnZSBkZXN0aW5hdGlvbiBkZXZpY2UgYXMgcGFydCBvZiBhIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uLiBJZiBwb3NzaWJsZSwgbmV0d29yayBjb25uZWN0aW9uIG5hbWUgaXMgZGlzcGxheWVkLiBZb3UgY2FuIHVzZSBhIGRldmljZSBkaXNwbGF5ZWQgaGVyZSBieSB1c2luZyB0aGUgQWRkTG9jYWxCcmlkZ2UgQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUV0aGVybmV0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUV0aGVybmV0XCIsIG5ldyBWcG5ScGNFbnVtRXRoKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIENyZWF0ZSBMb2NhbCBCcmlkZ2UgQ29ubmVjdGlvbi4gVXNlIHRoaXMgdG8gY3JlYXRlIGEgbmV3IExvY2FsIEJyaWRnZSBjb25uZWN0aW9uIG9uIHRoZSBWUE4gU2VydmVyLiBCeSB1c2luZyBhIExvY2FsIEJyaWRnZSwgeW91IGNhbiBjb25maWd1cmUgYSBMYXllciAyIGJyaWRnZSBjb25uZWN0aW9uIGJldHdlZW4gYSBWaXJ0dWFsIEh1YiBvcGVyYXRpbmcgb24gdGhpcyBWUE4gc2VydmVyIGFuZCBhIHBoeXNpY2FsIEV0aGVybmV0IERldmljZSAoTmV0d29yayBBZGFwdGVyKS4gWW91IGNhbiBjcmVhdGUgYSB0YXAgZGV2aWNlICh2aXJ0dWFsIG5ldHdvcmsgaW50ZXJmYWNlKSBvbiB0aGUgc3lzdGVtIGFuZCBjb25uZWN0IGEgYnJpZGdlIGJldHdlZW4gVmlydHVhbCBIdWJzICh0aGUgdGFwIGRldmljZSBpcyBvbmx5IHN1cHBvcnRlZCBieSBMaW51eCB2ZXJzaW9ucykuIEl0IGlzIHBvc3NpYmxlIHRvIGVzdGFibGlzaCBhIGJyaWRnZSB0byBhbiBvcGVyYXRpbmcgbmV0d29yayBhZGFwdGVyIG9mIHlvdXIgY2hvaWNlIGZvciB0aGUgYnJpZGdlIGRlc3RpbmF0aW9uIEV0aGVybmV0IGRldmljZSAobmV0d29yayBhZGFwdGVyKSwgYnV0IGluIGhpZ2ggbG9hZCBlbnZpcm9ubWVudHMsIHdlIHJlY29tbWVuZCB5b3UgcHJlcGFyZSBhIG5ldHdvcmsgYWRhcHRlciBkZWRpY2F0ZWQgdG8gc2VydmUgYXMgYSBicmlkZ2UuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5BZGRMb2NhbEJyaWRnZSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkTG9jYWxCcmlkZ2VcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBMb2NhbCBCcmlkZ2UgQ29ubmVjdGlvbi4gVXNlIHRoaXMgdG8gZGVsZXRlIGFuIGV4aXN0aW5nIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uLiBUbyBnZXQgYSBsaXN0IG9mIGN1cnJlbnQgTG9jYWwgQnJpZGdlIGNvbm5lY3Rpb25zIHVzZSB0aGUgRW51bUxvY2FsQnJpZGdlIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUxvY2FsQnJpZGdlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMb2NhbEJyaWRnZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgTG9jYWwgQnJpZGdlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnRseSBkZWZpbmVkIExvY2FsIEJyaWRnZSBjb25uZWN0aW9ucy4gWW91IGNhbiBnZXQgdGhlIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uIFZpcnR1YWwgSHViIG5hbWUgYW5kIHRoZSBicmlkZ2UgZGVzdGluYXRpb24gRXRoZXJuZXQgZGV2aWNlIChuZXR3b3JrIGFkYXB0ZXIpIG5hbWUgb3IgdGFwIGRldmljZSBuYW1lLCBhcyB3ZWxsIGFzIHRoZSBvcGVyYXRpbmcgc3RhdHVzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUxvY2FsQnJpZGdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUxvY2FsQnJpZGdlXCIsIG5ldyBWcG5ScGNFbnVtTG9jYWxCcmlkZ2UoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHdoZXRoZXIgdGhlIGxvY2FsYnJpZGdlIGZ1bmN0aW9uIGlzIHN1cHBvcnRlZCBvbiB0aGUgY3VycmVudCBzeXN0ZW0uICovXHJcbiAgICAgICAgdGhpcy5HZXRCcmlkZ2VTdXBwb3J0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QnJpZGdlU3VwcG9ydFwiLCBuZXcgVnBuUnBjQnJpZGdlU3VwcG9ydCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBSZWJvb3QgVlBOIFNlcnZlciBTZXJ2aWNlLiBVc2UgdGhpcyB0byByZXN0YXJ0IHRoZSBWUE4gU2VydmVyIHNlcnZpY2UuIFdoZW4geW91IHJlc3RhcnQgdGhlIFZQTiBTZXJ2ZXIsIGFsbCBjdXJyZW50bHkgY29ubmVjdGVkIHNlc3Npb25zIGFuZCBUQ1AgY29ubmVjdGlvbnMgd2lsbCBiZSBkaXNjb25uZWN0ZWQgYW5kIG5vIG5ldyBjb25uZWN0aW9ucyB3aWxsIGJlIGFjY2VwdGVkIHVudGlsIHRoZSByZXN0YXJ0IHByb2Nlc3MgaGFzIGNvbXBsZXRlZC4gQnkgdXNpbmcgdGhpcyBBUEksIG9ubHkgdGhlIFZQTiBTZXJ2ZXIgc2VydmljZSBwcm9ncmFtIHdpbGwgYmUgcmVzdGFydGVkIGFuZCB0aGUgcGh5c2ljYWwgY29tcHV0ZXIgdGhhdCBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBvbiBkb2VzIG5vdCByZXN0YXJ0LiBUaGlzIG1hbmFnZW1lbnQgc2Vzc2lvbiB3aWxsIGFsc28gYmUgZGlzY29ubmVjdGVkLCBzbyB5b3Ugd2lsbCBuZWVkIHRvIHJlY29ubmVjdCB0byBjb250aW51ZSBtYW5hZ2VtZW50LiBBbHNvLCBieSBzcGVjaWZ5aW5nIHRoZSBcIkludFZhbHVlXCIgcGFyYW1ldGVyIHRvIFwiMVwiLCB0aGUgY29udGVudHMgb2YgdGhlIGNvbmZpZ3VyYXRpb24gZmlsZSAoLmNvbmZpZykgaGVsZCBieSB0aGUgY3VycmVudCBWUE4gU2VydmVyIHdpbGwgYmUgaW5pdGlhbGl6ZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5SZWJvb3RTZXJ2ZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlJlYm9vdFNlcnZlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgU2VydmVyIEZ1bmN0aW9ucyAvIENhcGFiaWxpdHkuIFVzZSB0aGlzIGdldCBhIGxpc3Qgb2YgZnVuY3Rpb25zIGFuZCBjYXBhYmlsaXR5IG9mIHRoZSBWUE4gU2VydmVyIGN1cnJlbnRseSBjb25uZWN0ZWQgYW5kIGJlaW5nIG1hbmFnZWQuIFRoZSBmdW5jdGlvbiBhbmQgY2FwYWJpbGl0eSBvZiBWUE4gU2VydmVycyBhcmUgZGlmZmVyZW50IGRlcGVuZGluZyBvbiB0aGUgb3BlcmF0aW5nIFZQTiBzZXJ2ZXIncyBlZGl0aW9uIGFuZCB2ZXJzaW9uLiBVc2luZyB0aGlzIEFQSSwgeW91IGNhbiBmaW5kIG91dCB0aGUgY2FwYWJpbGl0eSBvZiB0aGUgdGFyZ2V0IFZQTiBTZXJ2ZXIgYW5kIHJlcG9ydCBpdC4gKi9cclxuICAgICAgICB0aGlzLkdldENhcHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRDYXBzXCIsIG5ldyBWcG5DYXBzbGlzdCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBvZiB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZ2V0IGEgdGV4dCBmaWxlICguY29uZmlnIGZpbGUpIHRoYXQgY29udGFpbnMgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBjb250ZW50cyBvZiB0aGUgVlBOIHNlcnZlci4gWW91IGNhbiBnZXQgdGhlIHN0YXR1cyBvbiB0aGUgVlBOIFNlcnZlciBhdCB0aGUgaW5zdGFudCB0aGlzIEFQSSBpcyBleGVjdXRlZC4gWW91IGNhbiBlZGl0IHRoZSBjb25maWd1cmF0aW9uIGZpbGUgYnkgdXNpbmcgYSByZWd1bGFyIHRleHQgZWRpdG9yLiBUbyB3cml0ZSBhbiBlZGl0ZWQgY29uZmlndXJhdGlvbiB0byB0aGUgVlBOIFNlcnZlciwgdXNlIHRoZSBTZXRDb25maWcgQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0Q29uZmlnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0Q29uZmlnXCIsIG5ldyBWcG5ScGNDb25maWcoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogV3JpdGUgQ29uZmlndXJhdGlvbiBGaWxlIHRvIFZQTiBTZXJ2ZXIuIFVzZSB0aGlzIHRvIHdyaXRlIHRoZSBjb25maWd1cmF0aW9uIGZpbGUgdG8gdGhlIFZQTiBTZXJ2ZXIuIEJ5IGV4ZWN1dGluZyB0aGlzIEFQSSwgdGhlIGNvbnRlbnRzIG9mIHRoZSBzcGVjaWZpZWQgY29uZmlndXJhdGlvbiBmaWxlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgVlBOIFNlcnZlciBhbmQgdGhlIFZQTiBTZXJ2ZXIgcHJvZ3JhbSB3aWxsIGF1dG9tYXRpY2FsbHkgcmVzdGFydCBhbmQgdXBvbiByZXN0YXJ0LCBvcGVyYXRlIGFjY29yZGluZyB0byB0aGUgbmV3IGNvbmZpZ3VyYXRpb24gY29udGVudHMuIEJlY2F1c2UgaXQgaXMgZGlmZmljdWx0IGZvciBhbiBhZG1pbmlzdHJhdG9yIHRvIHdyaXRlIGFsbCB0aGUgY29udGVudHMgb2YgYSBjb25maWd1cmF0aW9uIGZpbGUsIHdlIHJlY29tbWVuZCB5b3UgdXNlIHRoZSBHZXRDb25maWcgQVBJIHRvIGdldCB0aGUgY3VycmVudCBjb250ZW50cyBvZiB0aGUgVlBOIFNlcnZlciBjb25maWd1cmF0aW9uIGFuZCBzYXZlIGl0IHRvIGZpbGUuIFlvdSBjYW4gdGhlbiBlZGl0IHRoZXNlIGNvbnRlbnRzIGluIGEgcmVndWxhciB0ZXh0IGVkaXRvciBhbmQgdGhlbiB1c2UgdGhlIFNldENvbmZpZyBBUEkgdG8gcmV3cml0ZSB0aGUgY29udGVudHMgdG8gdGhlIFZQTiBTZXJ2ZXIuIFRoaXMgQVBJIGlzIGZvciBwZW9wbGUgd2l0aCBhIGRldGFpbGVkIGtub3dsZWRnZSBvZiB0aGUgVlBOIFNlcnZlciBhbmQgaWYgYW4gaW5jb3JyZWN0bHkgY29uZmlndXJlZCBjb25maWd1cmF0aW9uIGZpbGUgaXMgd3JpdHRlbiB0byB0aGUgVlBOIFNlcnZlciwgaXQgbm90IG9ubHkgY291bGQgY2F1c2UgZXJyb3JzLCBpdCBjb3VsZCBhbHNvIHJlc3VsdCBpbiB0aGUgbG9zdCBvZiB0aGUgY3VycmVudCBzZXR0aW5nIGRhdGEuIFRha2Ugc3BlY2lhbCBjYXJlIHdoZW4gY2Fycnlpbmcgb3V0IHRoaXMgYWN0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0Q29uZmlnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRDb25maWdcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb24gZGVmYXVsdCB2YWx1ZXMuICovXHJcbiAgICAgICAgdGhpcy5HZXREZWZhdWx0SHViQWRtaW5PcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXREZWZhdWx0SHViQWRtaW5PcHRpb25zXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb25zLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMgdGhhdCBhcmUgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIHB1cnBvc2Ugb2YgdGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMgaXMgZm9yIHRoZSBWUE4gU2VydmVyIEFkbWluaXN0cmF0b3IgdG8gc2V0IGxpbWl0cyBmb3IgdGhlIHNldHRpbmcgcmFuZ2VzIHdoZW4gdGhlIGFkbWluaXN0cmF0aW9uIG9mIHRoZSBWaXJ0dWFsIEh1YiBpcyB0byBiZSB0cnVzdGVkIHRvIGVhY2ggVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvci4gT25seSBhbiBhZG1pbmlzdHJhdG9yIHdpdGggYWRtaW5pc3RyYXRpb24gcHJpdmlsZWdlcyBmb3IgdGhpcyBlbnRpcmUgVlBOIFNlcnZlciBpcyBhYmxlIHRvIGFkZCwgZWRpdCBhbmQgZGVsZXRlIHRoZSBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zLiBUaGUgVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvcnMgYXJlIHVuYWJsZSB0byBtYWtlIGNoYW5nZXMgdG8gdGhlIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMsIGhvd2V2ZXIgdGhleSBhcmUgYWJsZSB0byB2aWV3IHRoZW0uIFRoZXJlIGlzIGFuIGV4Y2VwdGlvbiBob3dldmVyLiBJZiBhbGxvd19odWJfYWRtaW5fY2hhbmdlX29wdGlvbiBpcyBzZXQgdG8gXCIxXCIsIGV2ZW4gVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvcnMgYXJlIGFibGUgdG8gZWRpdCB0aGUgYWRtaW5pc3RyYXRpb24gb3B0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3RlciBtZW1iZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRIdWJBZG1pbk9wdGlvbnMgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEh1YkFkbWluT3B0aW9uc1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFZhbHVlcyBvZiBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb25zLiBVc2UgdGhpcyB0byBjaGFuZ2UgdGhlIHZhbHVlcyBvZiBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zIHRoYXQgYXJlIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSBwdXJwb3NlIG9mIHRoZSBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zIGlzIGZvciB0aGUgVlBOIFNlcnZlciBBZG1pbmlzdHJhdG9yIHRvIHNldCBsaW1pdHMgZm9yIHRoZSBzZXR0aW5nIHJhbmdlcyB3aGVuIHRoZSBhZG1pbmlzdHJhdGlvbiBvZiB0aGUgVmlydHVhbCBIdWIgaXMgdG8gYmUgdHJ1c3RlZCB0byBlYWNoIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3IuIE9ubHkgYW4gYWRtaW5pc3RyYXRvciB3aXRoIGFkbWluaXN0cmF0aW9uIHByaXZpbGVnZXMgZm9yIHRoaXMgZW50aXJlIFZQTiBTZXJ2ZXIgaXMgYWJsZSB0byBhZGQsIGVkaXQgYW5kIGRlbGV0ZSB0aGUgVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRpb24gb3B0aW9ucy4gVGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3JzIGFyZSB1bmFibGUgdG8gbWFrZSBjaGFuZ2VzIHRvIHRoZSBhZG1pbmlzdHJhdGlvbiBvcHRpb25zLCBob3dldmVyIHRoZXkgYXJlIGFibGUgdG8gdmlldyB0aGVtLiBUaGVyZSBpcyBhbiBleGNlcHRpb24gaG93ZXZlci4gSWYgYWxsb3dfaHViX2FkbWluX2NoYW5nZV9vcHRpb24gaXMgc2V0IHRvIFwiMVwiLCBldmVuIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3JzIGFyZSBhYmxlIHRvIGVkaXQgdGhlIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIgbWVtYmVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViQWRtaW5PcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJBZG1pbk9wdGlvbnNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMuIFVzZSB0aGlzIHRvIGdldCBhIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMgTGlzdCB0aGF0IGlzIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbiBlbmFibGVzIHlvdSB0byBjb25maWd1cmUgbW9yZSBkZXRhaWwgc2V0dGluZ3Mgb2YgdGhlIFZpcnR1YWwgSHViLiBCeSBkZWZhdWx0LCBib3RoIFZQTiBTZXJ2ZXIncyBnbG9iYWwgYWRtaW5pc3RyYXRvcnMgYW5kIGluZGl2aWR1YWwgVmlydHVhbCBIdWIncyBhZG1pbmlzdHJhdG9ycyBjYW4gbW9kaWZ5IHRoZSBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBIb3dldmVyLCBpZiB0aGUgZGVueV9odWJfYWRtaW5fY2hhbmdlX2V4dF9vcHRpb24gaXMgc2V0IHRvIDEgb24gdGhlIFZpcnR1YWwgSHViIEFkbWluIE9wdGlvbnMsIHRoZSBpbmRpdmlkdWFsIFZpcnR1YWwgSHViJ3MgYWRtaW5pc3RyYXRvcnMgY2Fubm90IG1vZGlmeSB0aGUgVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3RlciBtZW1iZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRIdWJFeHRPcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJFeHRPcHRpb25zXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgYSBWYWx1ZSBvZiBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBVc2UgdGhpcyB0byBzZXQgYSB2YWx1ZSBpbiB0aGUgVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9ucyBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9uIGVuYWJsZXMgeW91IHRvIGNvbmZpZ3VyZSBtb3JlIGRldGFpbCBzZXR0aW5ncyBvZiB0aGUgVmlydHVhbCBIdWIuIEJ5IGRlZmF1bHQsIGJvdGggVlBOIFNlcnZlcidzIGdsb2JhbCBhZG1pbmlzdHJhdG9ycyBhbmQgaW5kaXZpZHVhbCBWaXJ0dWFsIEh1YidzIGFkbWluaXN0cmF0b3JzIGNhbiBtb2RpZnkgdGhlIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMuIEhvd2V2ZXIsIGlmIHRoZSBkZW55X2h1Yl9hZG1pbl9jaGFuZ2VfZXh0X29wdGlvbiBpcyBzZXQgdG8gMSBvbiB0aGUgVmlydHVhbCBIdWIgQWRtaW4gT3B0aW9ucywgdGhlIGluZGl2aWR1YWwgVmlydHVhbCBIdWIncyBhZG1pbmlzdHJhdG9ycyBjYW5ub3QgbW9kaWZ5IHRoZSBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YkV4dE9wdGlvbnMgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEh1YkV4dE9wdGlvbnNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlZmluZSBOZXcgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gVXNlIHRoaXMgdG8gZGVmaW5lIGEgbmV3IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggb24gdGhlIFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5BZGRMM1N3aXRjaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBkZWxldGUgYW4gZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaCB0aGF0IGlzIGRlZmluZWQgb24gdGhlIFZQTiBTZXJ2ZXIuIFdoZW4gdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGlzIG9wZXJhdGluZywgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGRlbGV0ZWQgYWZ0ZXIgb3BlcmF0aW9uIHN0b3BzLiBUbyBnZXQgYSBsaXN0IG9mIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcywgdXNlIHRoZSBFbnVtTDNTd2l0Y2ggQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBBbHNvLCB0aGlzIEFQSSBkb2VzIG5vdCBvcGVyYXRlIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5EZWxMM1N3aXRjaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcy4gVXNlIHRoaXMgdG8gZGVmaW5lIGEgbmV3IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggb24gdGhlIFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTDNTd2l0Y2ggPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTDNTd2l0Y2hcIiwgbmV3IFZwblJwY0VudW1MM1N3KCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFN0YXJ0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggT3BlcmF0aW9uLiBVc2UgdGhpcyB0byBzdGFydCB0aGUgb3BlcmF0aW9uIG9mIGFuIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZGVmaW5lZCBvbiB0aGUgVlBOIFNlcnZlciB3aG9zZSBvcGVyYXRpb24gaXMgY3VycmVudGx5IHN0b3BwZWQuIFRvIGdldCBhIGxpc3Qgb2YgZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaGVzLCB1c2UgdGhlIEVudW1MM1N3aXRjaCBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5TdGFydEwzU3dpdGNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTdGFydEwzU3dpdGNoXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTdG9wIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggT3BlcmF0aW9uLiBVc2UgdGhpcyB0byBzdG9wIHRoZSBvcGVyYXRpb24gb2YgYW4gZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaCBkZWZpbmVkIG9uIHRoZSBWUE4gU2VydmVyIHdob3NlIG9wZXJhdGlvbiBpcyBjdXJyZW50bHkgb3BlcmF0aW5nLiBUbyBnZXQgYSBsaXN0IG9mIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcywgdXNlIHRoZSBFbnVtTDNTd2l0Y2ggQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuU3RvcEwzU3dpdGNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTdG9wTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBWaXJ0dWFsIEludGVyZmFjZSB0byBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBhZGQgdG8gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaCwgYSB2aXJ0dWFsIGludGVyZmFjZSB0aGF0IGNvbm5lY3RzIHRvIGEgVmlydHVhbCBIdWIgb3BlcmF0aW5nIG9uIHRoZSBzYW1lIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gZGVmaW5lIG11bHRpcGxlIHZpcnR1YWwgaW50ZXJmYWNlcyBhbmQgcm91dGluZyB0YWJsZXMgZm9yIGEgc2luZ2xlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2guIEEgdmlydHVhbCBpbnRlcmZhY2UgaXMgYXNzb2NpYXRlZCB0byBhIHZpcnR1YWwgSHViIGFuZCBvcGVyYXRlcyBhcyBhIHNpbmdsZSBJUCBob3N0IG9uIHRoZSBWaXJ0dWFsIEh1YiB3aGVuIHRoYXQgVmlydHVhbCBIdWIgaXMgb3BlcmF0aW5nLiBXaGVuIG11bHRpcGxlIHZpcnR1YWwgaW50ZXJmYWNlcyB0aGF0IHJlc3BlY3RpdmVseSBiZWxvbmcgdG8gYSBkaWZmZXJlbnQgSVAgbmV0d29yayBvZiBhIGRpZmZlcmVudCBWaXJ0dWFsIEh1YiBhcmUgZGVmaW5lZCwgSVAgcm91dGluZyB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcGVyZm9ybWVkIGJldHdlZW4gdGhlc2UgaW50ZXJmYWNlcy4gWW91IG11c3QgZGVmaW5lIHRoZSBJUCBuZXR3b3JrIHNwYWNlIHRoYXQgdGhlIHZpcnR1YWwgaW50ZXJmYWNlIGJlbG9uZ3MgdG8gYW5kIHRoZSBJUCBhZGRyZXNzIG9mIHRoZSBpbnRlcmZhY2UgaXRzZWxmLiBBbHNvLCB5b3UgbXVzdCBzcGVjaWZ5IHRoZSBuYW1lIG9mIHRoZSBWaXJ0dWFsIEh1YiB0aGF0IHRoZSBpbnRlcmZhY2Ugd2lsbCBjb25uZWN0IHRvLiBZb3UgY2FuIHNwZWNpZnkgYSBWaXJ0dWFsIEh1YiB0aGF0IGN1cnJlbnRseSBkb2Vzbid0IGV4aXN0IGZvciB0aGUgVmlydHVhbCBIdWIgbmFtZS4gVGhlIHZpcnR1YWwgaW50ZXJmYWNlIG11c3QgaGF2ZSBvbmUgSVAgYWRkcmVzcyBpbiB0aGUgVmlydHVhbCBIdWIuIFlvdSBhbHNvIG11c3Qgc3BlY2lmeSB0aGUgc3VibmV0IG1hc2sgb2YgYW4gSVAgbmV0d29yayB0aGF0IHRoZSBJUCBhZGRyZXNzIGJlbG9uZ3MgdG8uIFJvdXRpbmcgdmlhIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoZXMgb2YgSVAgc3BhY2VzIG9mIG11bHRpcGxlIHZpcnR1YWwgSHVicyBvcGVyYXRlcyBiYXNlZCBvbiB0aGUgSVAgYWRkcmVzcyBpcyBzcGVjaWZpZWQgaGVyZS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkFkZEwzSWYgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkFkZEwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIEludGVyZmFjZSBvZiBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBkZWxldGUgYSB2aXJ0dWFsIGludGVyZmFjZSBhbHJlYWR5IGRlZmluZWQgaW4gdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBZb3UgY2FuIGdldCBhIGxpc3Qgb2YgdGhlIHZpcnR1YWwgaW50ZXJmYWNlcyBjdXJyZW50bHkgZGVmaW5lZCwgYnkgdXNpbmcgdGhlIEVudW1MM0lmIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkRlbEwzSWYgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbEwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIEludGVyZmFjZXMgUmVnaXN0ZXJlZCBvbiB0aGUgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiB2aXJ0dWFsIGludGVyZmFjZXMgd2hlbiB2aXJ0dWFsIGludGVyZmFjZXMgaGF2ZSBiZWVuIGRlZmluZWQgb24gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gWW91IGNhbiBkZWZpbmUgbXVsdGlwbGUgdmlydHVhbCBpbnRlcmZhY2VzIGFuZCByb3V0aW5nIHRhYmxlcyBmb3IgYSBzaW5nbGUgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gQSB2aXJ0dWFsIGludGVyZmFjZSBpcyBhc3NvY2lhdGVkIHRvIGEgdmlydHVhbCBIdWIgYW5kIG9wZXJhdGVzIGFzIGEgc2luZ2xlIElQIGhvc3Qgb24gdGhlIFZpcnR1YWwgSHViIHdoZW4gdGhhdCBWaXJ0dWFsIEh1YiBpcyBvcGVyYXRpbmcuIFdoZW4gbXVsdGlwbGUgdmlydHVhbCBpbnRlcmZhY2VzIHRoYXQgcmVzcGVjdGl2ZWx5IGJlbG9uZyB0byBhIGRpZmZlcmVudCBJUCBuZXR3b3JrIG9mIGEgZGlmZmVyZW50IFZpcnR1YWwgSHViIGFyZSBkZWZpbmVkLCBJUCByb3V0aW5nIHdpbGwgYmUgYXV0b21hdGljYWxseSBwZXJmb3JtZWQgYmV0d2VlbiB0aGVzZSBpbnRlcmZhY2VzLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBBbHNvLCB0aGlzIEFQSSBkb2VzIG5vdCBvcGVyYXRlIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTDNJZiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBSb3V0aW5nIFRhYmxlIEVudHJ5IGZvciBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBIZXJlIHlvdSBjYW4gYWRkIGEgbmV3IHJvdXRpbmcgdGFibGUgZW50cnkgdG8gdGhlIHJvdXRpbmcgdGFibGUgb2YgdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBJZiB0aGUgZGVzdGluYXRpb24gSVAgYWRkcmVzcyBvZiB0aGUgSVAgcGFja2V0IGRvZXMgbm90IGJlbG9uZyB0byBhbnkgSVAgbmV0d29yayB0aGF0IGJlbG9uZ3MgdG8gYSB2aXJ0dWFsIGludGVyZmFjZSwgdGhlIElQIHJvdXRpbmcgZW5naW5lIG9mIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIHdpbGwgcmVmZXJlbmNlIHRoZSByb3V0aW5nIHRhYmxlIGFuZCBleGVjdXRlIHJvdXRpbmcuIFlvdSBtdXN0IHNwZWNpZnkgdGhlIGNvbnRlbnRzIG9mIHRoZSByb3V0aW5nIHRhYmxlIGVudHJ5IHRvIGJlIGFkZGVkIHRvIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBZb3UgbXVzdCBzcGVjaWZ5IGFueSBJUCBhZGRyZXNzIHRoYXQgYmVsb25ncyB0byB0aGUgc2FtZSBJUCBuZXR3b3JrIGluIHRoZSB2aXJ0dWFsIGludGVyZmFjZSBvZiB0aGlzIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggYXMgdGhlIGdhdGV3YXkgYWRkcmVzcy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkFkZEwzVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkFkZEwzVGFibGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBSb3V0aW5nIFRhYmxlIEVudHJ5IG9mIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2guIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHJvdXRpbmcgdGFibGUgZW50cnkgdGhhdCBpcyBkZWZpbmVkIGluIHRoZSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gWW91IGNhbiBnZXQgYSBsaXN0IG9mIHRoZSBhbHJlYWR5IGRlZmluZWQgcm91dGluZyB0YWJsZSBlbnRyaWVzIGJ5IHVzaW5nIHRoZSBFbnVtTDNUYWJsZSBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gVG8gZXhlY3V0ZSB0aGlzIEFQSSwgdGhlIHRhcmdldCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIG11c3QgYmUgc3RvcHBlZC4gSWYgaXQgaXMgbm90IHN0b3BwZWQsIGZpcnN0IHVzZSB0aGUgU3RvcEwzU3dpdGNoIEFQSSB0byBzdG9wIGl0IGFuZCB0aGVuIGV4ZWN1dGUgdGhpcyBBUEkuICovXHJcbiAgICAgICAgdGhpcy5EZWxMM1RhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxMM1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBSb3V0aW5nIFRhYmxlcyBvZiBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIHJvdXRpbmcgdGFibGVzIHdoZW4gcm91dGluZyB0YWJsZXMgaGF2ZSBiZWVuIGRlZmluZWQgb24gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gSWYgdGhlIGRlc3RpbmF0aW9uIElQIGFkZHJlc3Mgb2YgdGhlIElQIHBhY2tldCBkb2VzIG5vdCBiZWxvbmcgdG8gYW55IElQIG5ldHdvcmsgdGhhdCBiZWxvbmdzIHRvIGEgdmlydHVhbCBpbnRlcmZhY2UsIHRoZSBJUCByb3V0aW5nIGVuZ2luZSBvZiB0aGUgVmlydHVhbCBMYXllciAzIFN3aXRjaCB3aWxsIHJlZmVyZW5jZSB0aGlzIHJvdXRpbmcgdGFibGUgYW5kIGV4ZWN1dGUgcm91dGluZy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUwzVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1MM1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgcmVnaXN0ZXJpbmcgY2VydGlmaWNhdGVzIGluIHRoZSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0LCB0aGUgY2xpZW50cyB3aG8gcHJvdmlkZSB0aGVzZSBjZXJ0aWZpY2F0ZXMgd2lsbCBiZSB1bmFibGUgdG8gY29ubmVjdCB0byB0aGlzIFZpcnR1YWwgSHViIHVzaW5nIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIE5vcm1hbGx5IHdpdGggdGhpcyBmdW5jdGlvbiwgaW4gY2FzZXMgd2hlcmUgdGhlIHNlY3VyaXR5IG9mIGEgcHJpdmF0ZSBrZXkgaGFzIGJlZW4gY29tcHJvbWlzZWQgb3Igd2hlcmUgYSBwZXJzb24gaG9sZGluZyBhIGNlcnRpZmljYXRlIGhhcyBiZWVuIHN0cmlwcGVkIG9mIHRoZWlyIHByaXZpbGVnZXMsIGJ5IHJlZ2lzdGVyaW5nIHRoYXQgY2VydGlmaWNhdGUgYXMgaW52YWxpZCBvbiB0aGUgVmlydHVhbCBIdWIsIGl0IGlzIHBvc3NpYmxlIHRvIGRlbnkgdXNlciBhdXRoZW50aWNhdGlvbiB3aGVuIHRoYXQgY2VydGlmaWNhdGUgaXMgdXNlZCBieSBhIGNsaWVudCB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1Yi4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1DcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1DcmxcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBhIFJldm9rZWQgQ2VydGlmaWNhdGUuIFVzZSB0aGlzIHRvIGFkZCBhIG5ldyByZXZva2VkIGNlcnRpZmljYXRlIGRlZmluaXRpb24gaW4gdGhlIENlcnRpZmljYXRlIFJldm9jYXRpb24gTGlzdCB0aGF0IGlzIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFNwZWNpZnkgdGhlIGNvbnRlbnRzIHRvIGJlIHJlZ2lzdGVyZWQgaW4gdGhlIENlcnRpZmljYXRlIFJldm9jYXRpb24gTGlzdCBieSB1c2luZyB0aGUgcGFyYW1ldGVycyBvZiB0aGlzIEFQSS4gV2hlbiBhIHVzZXIgY29ubmVjdHMgdG8gYSBWaXJ0dWFsIEh1YiBpbiBjZXJ0aWZpY2F0ZSBhdXRoZW50aWNhdGlvbiBtb2RlIGFuZCB0aGF0IGNlcnRpZmljYXRlIG1hdGNoZXMgMSBvciBtb3JlIG9mIHRoZSBjb250ZW50cyByZWdpc3RlcmVkIGluIHRoZSBjZXJ0aWZpY2F0ZXMgcmV2b2NhdGlvbiBsaXN0LCB0aGUgdXNlciBpcyBkZW5pZWQgY29ubmVjdGlvbi4gQSBjZXJ0aWZpY2F0ZSB0aGF0IG1hdGNoZXMgYWxsIHRoZSBjb25kaXRpb25zIHRoYXQgYXJlIGRlZmluZWQgYnkgdGhlIHBhcmFtZXRlcnMgc3BlY2lmaWVkIGJ5IHRoaXMgQVBJIHdpbGwgYmUganVkZ2VkIGFzIGludmFsaWQuIFRoZSBpdGVtcyB0aGF0IGNhbiBiZSBzZXQgYXJlIGFzIGZvbGxvd3M6IE5hbWUgKENOKSwgT3JnYW5pemF0aW9uIChPKSwgT3JnYW5pemF0aW9uIFVuaXQgKE9VKSwgQ291bnRyeSAoQyksIFN0YXRlIChTVCksIExvY2FsZSAoTCksIFNlcmlhbCBOdW1iZXIgKGhleGFkZWNpbWFsKSwgTUQ1IERpZ2VzdCBWYWx1ZSAoaGV4YWRlY2ltYWwsIDEyOCBiaXQpLCBhbmQgU0hBLTEgRGlnZXN0IFZhbHVlIChoZXhhZGVjaW1hbCwgMTYwIGJpdCkuIEZvciB0aGUgc3BlY2lmaWNhdGlvbiBvZiBhIGRpZ2VzdCB2YWx1ZSAoaGFzaCB2YWx1ZSkgYSBjZXJ0aWZpY2F0ZSBpcyBvcHRpb25hbGx5IHNwZWNpZmllZCBkZXBlbmRpbmcgb24gdGhlIGNpcmN1bXN0YW5jZXMuIE5vcm1hbGx5IHdoZW4gYSBNRDUgb3IgU0hBLTEgZGlnZXN0IHZhbHVlIGlzIGlucHV0LCBpdCBpcyBub3QgbmVjZXNzYXJ5IHRvIGlucHV0IHRoZSBvdGhlciBpdGVtcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkFkZENybCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkQ3JsXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgYSBSZXZva2VkIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBzcGVjaWZ5IGFuZCBkZWxldGUgYSByZXZva2VkIGNlcnRpZmljYXRlIGRlZmluaXRpb24gZnJvbSB0aGUgY2VydGlmaWNhdGUgcmV2b2NhdGlvbiBsaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbnMsIHVzZSB0aGUgRW51bUNybCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5EZWxDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IGEgUmV2b2tlZCBDZXJ0aWZpY2F0ZS4gVXNlIHRoaXMgdG8gc3BlY2lmeSBhbmQgZ2V0IHRoZSBjb250ZW50cyBvZiBhIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbiBmcm9tIHRoZSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbnMsIHVzZSB0aGUgRW51bUNybCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIEV4aXN0aW5nIENSTCAoQ2VydGlmaWNhdGUgUmV2b2NhdGlvbiBMaXN0KSBFbnRyeS4gVXNlIHRoaXMgdG8gYWx0ZXIgYW4gZXhpc3RpbmcgcmV2b2tlZCBjZXJ0aWZpY2F0ZSBkZWZpbml0aW9uIGluIHRoZSBDZXJ0aWZpY2F0ZSBSZXZvY2F0aW9uIExpc3QgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBTcGVjaWZ5IHRoZSBjb250ZW50cyB0byBiZSByZWdpc3RlcmVkIGluIHRoZSBDZXJ0aWZpY2F0ZSBSZXZvY2F0aW9uIExpc3QgYnkgdXNpbmcgdGhlIHBhcmFtZXRlcnMgb2YgdGhpcyBBUEkuIFdoZW4gYSB1c2VyIGNvbm5lY3RzIHRvIGEgVmlydHVhbCBIdWIgaW4gY2VydGlmaWNhdGUgYXV0aGVudGljYXRpb24gbW9kZSBhbmQgdGhhdCBjZXJ0aWZpY2F0ZSBtYXRjaGVzIDEgb3IgbW9yZSBvZiB0aGUgY29udGVudHMgcmVnaXN0ZXJlZCBpbiB0aGUgY2VydGlmaWNhdGVzIHJldm9jYXRpb24gbGlzdCwgdGhlIHVzZXIgaXMgZGVuaWVkIGNvbm5lY3Rpb24uIEEgY2VydGlmaWNhdGUgdGhhdCBtYXRjaGVzIGFsbCB0aGUgY29uZGl0aW9ucyB0aGF0IGFyZSBkZWZpbmVkIGJ5IHRoZSBwYXJhbWV0ZXJzIHNwZWNpZmllZCBieSB0aGlzIEFQSSB3aWxsIGJlIGp1ZGdlZCBhcyBpbnZhbGlkLiBUaGUgaXRlbXMgdGhhdCBjYW4gYmUgc2V0IGFyZSBhcyBmb2xsb3dzOiBOYW1lIChDTiksIE9yZ2FuaXphdGlvbiAoTyksIE9yZ2FuaXphdGlvbiBVbml0IChPVSksIENvdW50cnkgKEMpLCBTdGF0ZSAoU1QpLCBMb2NhbGUgKEwpLCBTZXJpYWwgTnVtYmVyIChoZXhhZGVjaW1hbCksIE1ENSBEaWdlc3QgVmFsdWUgKGhleGFkZWNpbWFsLCAxMjggYml0KSwgYW5kIFNIQS0xIERpZ2VzdCBWYWx1ZSAoaGV4YWRlY2ltYWwsIDE2MCBiaXQpLiBGb3IgdGhlIHNwZWNpZmljYXRpb24gb2YgYSBkaWdlc3QgdmFsdWUgKGhhc2ggdmFsdWUpIGEgY2VydGlmaWNhdGUgaXMgb3B0aW9uYWxseSBzcGVjaWZpZWQgZGVwZW5kaW5nIG9uIHRoZSBjaXJjdW1zdGFuY2VzLiBOb3JtYWxseSB3aGVuIGEgTUQ1IG9yIFNIQS0xIGRpZ2VzdCB2YWx1ZSBpcyBpbnB1dCwgaXQgaXMgbm90IG5lY2Vzc2FyeSB0byBpbnB1dCB0aGUgb3RoZXIgaXRlbXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQWRkIFJ1bGUgdG8gU291cmNlIElQIEFkZHJlc3MgTGltaXQgTGlzdC4gVXNlIHRoaXMgdG8gYWRkIGEgbmV3IHJ1bGUgdG8gdGhlIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgaXRlbXMgc2V0IGhlcmUgd2lsbCBiZSB1c2VkIHRvIGRlY2lkZSB3aGV0aGVyIHRvIGFsbG93IG9yIGRlbnkgY29ubmVjdGlvbiBmcm9tIGEgVlBOIENsaWVudCB3aGVuIHRoaXMgY2xpZW50IGF0dGVtcHRzIGNvbm5lY3Rpb24gdG8gdGhlIFZpcnR1YWwgSHViLiBZb3UgY2FuIHNwZWNpZnkgYSBjbGllbnQgSVAgYWRkcmVzcywgb3IgSVAgYWRkcmVzcyBvciBtYXNrIHRvIG1hdGNoIHRoZSBydWxlIGFzIHRoZSBjb250ZW50cyBvZiB0aGUgcnVsZSBpdGVtLiBCeSBzcGVjaWZ5aW5nIGFuIElQIGFkZHJlc3Mgb25seSwgdGhlcmUgd2lsbCBvbmx5IGJlIG9uZSBzcGVjaWZpZWQgY29tcHV0ZXIgdGhhdCB3aWxsIG1hdGNoIHRoZSBydWxlLCBidXQgYnkgc3BlY2lmeWluZyBhbiBJUCBuZXQgbWFzayBhZGRyZXNzIG9yIHN1Ym5ldCBtYXNrIGFkZHJlc3MsIGFsbCB0aGUgY29tcHV0ZXJzIGluIHRoZSByYW5nZSBvZiB0aGF0IHN1Ym5ldCB3aWxsIG1hdGNoIHRoZSBydWxlLiBZb3UgY2FuIHNwZWNpZnkgdGhlIHByaW9yaXR5IGZvciB0aGUgcnVsZS4gWW91IGNhbiBzcGVjaWZ5IGFuIGludGVnZXIgb2YgMSBvciBncmVhdGVyIGZvciB0aGUgcHJpb3JpdHkgYW5kIHRoZSBzbWFsbGVyIHRoZSBudW1iZXIsIHRoZSBoaWdoZXIgdGhlIHByaW9yaXR5LiBUbyBnZXQgYSBsaXN0IG9mIHRoZSBjdXJyZW50bHkgcmVnaXN0ZXJlZCBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0LCB1c2UgdGhlIEdldEFjTGlzdCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRBY0xpc3QgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEFjTGlzdFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgUnVsZSBJdGVtcyBvZiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgcnVsZXMgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBZb3UgY2FuIGFsbG93IG9yIGRlbnkgVlBOIGNvbm5lY3Rpb25zIHRvIHRoaXMgVmlydHVhbCBIdWIgYWNjb3JkaW5nIHRvIHRoZSBjbGllbnQgY29tcHV0ZXIncyBzb3VyY2UgSVAgYWRkcmVzcy4gWW91IGNhbiBkZWZpbmUgbXVsdGlwbGUgcnVsZXMgYW5kIHNldCBhIHByaW9yaXR5IGZvciBlYWNoIHJ1bGUuIFRoZSBzZWFyY2ggcHJvY2VlZHMgZnJvbSB0aGUgcnVsZSB3aXRoIHRoZSBoaWdoZXN0IG9yZGVyIG9yIHByaW9yaXR5IGFuZCBiYXNlZCBvbiB0aGUgYWN0aW9uIG9mIHRoZSBydWxlIHRoYXQgdGhlIElQIGFkZHJlc3MgZmlyc3QgbWF0Y2hlcywgdGhlIGNvbm5lY3Rpb24gZnJvbSB0aGUgY2xpZW50IGlzIGVpdGhlciBhbGxvd2VkIG9yIGRlbmllZC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldEFjTGlzdCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QWNMaXN0XCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBMb2cgRmlsZXMuIFVzZSB0aGlzIHRvIGRpc3BsYXkgYSBsaXN0IG9mIGxvZyBmaWxlcyBvdXRwdXR0ZWQgYnkgdGhlIFZQTiBTZXJ2ZXIgdGhhdCBoYXZlIGJlZW4gc2F2ZWQgb24gdGhlIFZQTiBTZXJ2ZXIgY29tcHV0ZXIuIEJ5IHNwZWNpZnlpbmcgYSBsb2cgZmlsZSBmaWxlIG5hbWUgZGlzcGxheWVkIGhlcmUgYW5kIGNhbGxpbmcgaXQgdXNpbmcgdGhlIFJlYWRMb2dGaWxlIEFQSSB5b3UgY2FuIGRvd25sb2FkIHRoZSBjb250ZW50cyBvZiB0aGUgbG9nIGZpbGUuIElmIHlvdSBhcmUgY29ubmVjdGVkIHRvIHRoZSBWUE4gU2VydmVyIGluIHNlcnZlciBhZG1pbiBtb2RlLCB5b3UgY2FuIGRpc3BsYXkgb3IgZG93bmxvYWQgdGhlIHBhY2tldCBsb2dzIGFuZCBzZWN1cml0eSBsb2dzIG9mIGFsbCBWaXJ0dWFsIEh1YnMgYW5kIHRoZSBzZXJ2ZXIgbG9nIG9mIHRoZSBWUE4gU2VydmVyLiBXaGVuIGNvbm5lY3RlZCBpbiBWaXJ0dWFsIEh1YiBBZG1pbiBNb2RlLCB5b3UgYXJlIGFibGUgdG8gdmlldyBvciBkb3dubG9hZCBvbmx5IHRoZSBwYWNrZXQgbG9nIGFuZCBzZWN1cml0eSBsb2cgb2YgdGhlIFZpcnR1YWwgSHViIHRoYXQgaXMgdGhlIHRhcmdldCBvZiBtYW5hZ2VtZW50LiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUxvZ0ZpbGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTG9nRmlsZVwiLCBuZXcgVnBuUnBjRW51bUxvZ0ZpbGUoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRG93bmxvYWQgYSBwYXJ0IG9mIExvZyBGaWxlLiBVc2UgdGhpcyB0byBkb3dubG9hZCB0aGUgbG9nIGZpbGUgdGhhdCBpcyBzYXZlZCBvbiB0aGUgVlBOIFNlcnZlciBjb21wdXRlci4gVG8gZG93bmxvYWQgdGhlIGxvZyBmaWxlIGZpcnN0IGdldCB0aGUgbGlzdCBvZiBsb2cgZmlsZXMgdXNpbmcgdGhlIEVudW1Mb2dGaWxlIEFQSSBhbmQgdGhlbiBkb3dubG9hZCB0aGUgbG9nIGZpbGUgdXNpbmcgdGhlIFJlYWRMb2dGaWxlIEFQSS4gSWYgeW91IGFyZSBjb25uZWN0ZWQgdG8gdGhlIFZQTiBTZXJ2ZXIgaW4gc2VydmVyIGFkbWluIG1vZGUsIHlvdSBjYW4gZGlzcGxheSBvciBkb3dubG9hZCB0aGUgcGFja2V0IGxvZ3MgYW5kIHNlY3VyaXR5IGxvZ3Mgb2YgYWxsIFZpcnR1YWwgSHVicyBhbmQgdGhlIHNlcnZlciBsb2cgb2YgdGhlIFZQTiBTZXJ2ZXIuIFdoZW4gY29ubmVjdGVkIGluIFZpcnR1YWwgSHViIEFkbWluIE1vZGUsIHlvdSBhcmUgYWJsZSB0byB2aWV3IG9yIGRvd25sb2FkIG9ubHkgdGhlIHBhY2tldCBsb2cgYW5kIHNlY3VyaXR5IGxvZyBvZiB0aGUgVmlydHVhbCBIdWIgdGhhdCBpcyB0aGUgdGFyZ2V0IG9mIG1hbmFnZW1lbnQuICovXHJcbiAgICAgICAgdGhpcy5SZWFkTG9nRmlsZSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiUmVhZExvZ0ZpbGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBzeXNsb2cgU2VuZCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gc2V0IHRoZSB1c2FnZSBvZiBzeXNsb2cgc2VuZCBmdW5jdGlvbiBhbmQgd2hpY2ggc3lzbG9nIHNlcnZlciB0byB1c2UuICovXHJcbiAgICAgICAgdGhpcy5TZXRTeXNMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFN5c0xvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHN5c2xvZyBTZW5kIEZ1bmN0aW9uLiBUaGlzIGFsbG93cyB5b3UgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgY29udGVudHMgb2YgdGhlIHN5c2xvZyBzZW5kIGZ1bmN0aW9uLiBZb3UgY2FuIGdldCB0aGUgdXNhZ2Ugc2V0dGluZyBvZiB0aGUgc3lzbG9nIGZ1bmN0aW9uIGFuZCB0aGUgaG9zdCBuYW1lIGFuZCBwb3J0IG51bWJlciBvZiB0aGUgc3lzbG9nIHNlcnZlciB0byB1c2UuICovXHJcbiAgICAgICAgdGhpcy5HZXRTeXNMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFN5c0xvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFRvZGF5J3MgTWVzc2FnZSBvZiBWaXJ0dWFsIEh1Yi4gVGhlIG1lc3NhZ2Ugd2lsbCBiZSBkaXNwbGF5ZWQgb24gVlBOIENsaWVudCBVSSB3aGVuIGEgdXNlciB3aWxsIGVzdGFibGlzaCBhIGNvbm5lY3Rpb24gdG8gdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViTXNnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJNc2dcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBUb2RheSdzIE1lc3NhZ2Ugb2YgVmlydHVhbCBIdWIuIFRoZSBtZXNzYWdlIHdpbGwgYmUgZGlzcGxheWVkIG9uIFZQTiBDbGllbnQgVUkgd2hlbiBhIHVzZXIgd2lsbCBlc3RhYmxpc2ggYSBjb25uZWN0aW9uIHRvIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLkdldEh1Yk1zZyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0SHViTXNnXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBSYWlzZSBhIHZpdGFsIGVycm9yIG9uIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlIHRvIHRlcm1pbmF0ZSB0aGUgcHJvY2VzcyBmb3JjZWZ1bGx5LiBUaGlzIEFQSSB3aWxsIHJhaXNlIGEgZmF0YWwgZXJyb3IgKG1lbW9yeSBhY2Nlc3MgdmlvbGF0aW9uKSBvbiB0aGUgVlBOIFNlcnZlciAvIEJyaWRnZSBydW5uaW5nIHByb2Nlc3MgaW4gb3JkZXIgdG8gY3Jhc2ggdGhlIHByb2Nlc3MuIEFzIHRoZSByZXN1bHQsIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugd2lsbCBiZSB0ZXJtaW5hdGVkIGFuZCByZXN0YXJ0ZWQgaWYgaXQgaXMgcnVubmluZyBhcyBhIHNlcnZpY2UgbW9kZS4gSWYgdGhlIFZQTiBTZXJ2ZXIgaXMgcnVubmluZyBhcyBhIHVzZXIgbW9kZSwgdGhlIHByb2Nlc3Mgd2lsbCBub3QgYXV0b21hdGljYWxseSByZXN0YXJ0ZWQuIFRoaXMgQVBJIGlzIGZvciBhIHNpdHVhdGlvbiB3aGVuIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlIGlzIHVuZGVyIGEgbm9uLXJlY292ZXJhYmxlIGVycm9yIG9yIHRoZSBwcm9jZXNzIGlzIGluIGFuIGluZmluaXRlIGxvb3AuIFRoaXMgQVBJIHdpbGwgZGlzY29ubmVjdCBhbGwgVlBOIFNlc3Npb25zIG9uIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlLiBBbGwgdW5zYXZlZCBzZXR0aW5ncyBpbiB0aGUgbWVtb3J5IG9mIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugd2lsbCBiZSBsb3N0LiBCZWZvcmUgcnVuIHRoaXMgQVBJLCBjYWxsIHRoZSBGbHVzaCBBUEkgdG8gdHJ5IHRvIHNhdmUgdm9sYXRpbGUgZGF0YSB0byB0aGUgY29uZmlndXJhdGlvbiBmaWxlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgLyBWUE4gQnJpZGdlIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkNyYXNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJDcmFzaFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBtZXNzYWdlIGZvciBhZG1pbmlzdHJhdG9ycy4gKi9cclxuICAgICAgICB0aGlzLkdldEFkbWluTXNnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QWRtaW5Nc2dcIiwgbmV3IFZwblJwY01zZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTYXZlIEFsbCBWb2xhdGlsZSBEYXRhIG9mIFZQTiBTZXJ2ZXIgLyBCcmlkZ2UgdG8gdGhlIENvbmZpZ3VyYXRpb24gRmlsZS4gVGhlIG51bWJlciBvZiBjb25maWd1cmF0aW9uIGZpbGUgYnl0ZXMgd2lsbCBiZSByZXR1cm5lZCBhcyB0aGUgXCJJbnRWYWx1ZVwiIHBhcmFtZXRlci4gTm9ybWFsbHksIHRoZSBWUE4gU2VydmVyIC8gVlBOIEJyaWRnZSByZXRhaW5zIHRoZSB2b2xhdGlsZSBjb25maWd1cmF0aW9uIGRhdGEgaW4gbWVtb3J5LiBJdCBpcyBmbHVzaGVkIHRvIHRoZSBkaXNrIGFzIHZwbl9zZXJ2ZXIuY29uZmlnIG9yIHZwbl9icmlkZ2UuY29uZmlnIHBlcmlvZGljYWxseS4gVGhlIHBlcmlvZCBpcyAzMDAgc2Vjb25kcyAoNSBtaW51dGVzKSBieSBkZWZhdWx0LiAoVGhlIHBlcmlvZCBjYW4gYmUgYWx0ZXJlZCBieSBtb2RpZnlpbmcgdGhlIEF1dG9TYXZlQ29uZmlnU3BhbiBpdGVtIGluIHRoZSBjb25maWd1cmF0aW9uIGZpbGUuKSBUaGUgZGF0YSB3aWxsIGJlIHNhdmVkIG9uIHRoZSB0aW1pbmcgb2Ygc2h1dHRpbmcgZG93biBub3JtYWxseSBvZiB0aGUgVlBOIFNlcnZlciAvIEJyaWRnZS4gRXhlY3V0ZSB0aGUgRmx1c2ggQVBJIHRvIG1ha2UgdGhlIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugc2F2ZSB0aGUgc2V0dGluZ3MgdG8gdGhlIGZpbGUgaW1tZWRpYXRlbHkuIFRoZSBzZXR0aW5nIGRhdGEgd2lsbCBiZSBzdG9yZWQgb24gdGhlIGRpc2sgZHJpdmUgb2YgdGhlIHNlcnZlciBjb21wdXRlci4gVXNlIHRoZSBGbHVzaCBBUEkgaW4gYSBzaXR1YXRpb24gdGhhdCB5b3UgZG8gbm90IGhhdmUgYW4gZW5vdWdoIHRpbWUgdG8gc2h1dCBkb3duIHRoZSBzZXJ2ZXIgcHJvY2VzcyBub3JtYWxseS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVG8gZXhlY3V0ZSB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIC8gVlBOIEJyaWRnZSBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5GbHVzaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRmx1c2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEVuYWJsZSBvciBEaXNhYmxlIElQc2VjIFZQTiBTZXJ2ZXIgRnVuY3Rpb24uIEVuYWJsZSBvciBEaXNhYmxlIElQc2VjIFZQTiBTZXJ2ZXIgRnVuY3Rpb24gb24gdGhlIFZQTiBTZXJ2ZXIuIElmIHlvdSBlbmFibGUgdGhpcyBmdW5jdGlvbiwgVmlydHVhbCBIdWJzIG9uIHRoZSBWUE4gU2VydmVyIHdpbGwgYmUgYWJsZSB0byBhY2NlcHQgUmVtb3RlLUFjY2VzcyBWUE4gY29ubmVjdGlvbnMgZnJvbSBMMlRQLWNvbXBhdGlibGUgUENzLCBNYWMgT1MgWCBhbmQgU21hcnRwaG9uZXMsIGFuZCBhbHNvIGNhbiBhY2NlcHQgRXRoZXJJUCBTaXRlLXRvLVNpdGUgVlBOIENvbm5lY3Rpb24uIFZQTiBDb25uZWN0aW9ucyBmcm9tIFNtYXJ0cGhvbmVzIHN1Y2hsaWtlIGlQaG9uZSwgaVBhZCBhbmQgQW5kcm9pZCwgYW5kIGFsc28gZnJvbSBuYXRpdmUgVlBOIENsaWVudHMgb24gTWFjIE9TIFggYW5kIFdpbmRvd3MgY2FuIGJlIGFjY2VwdGVkLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SVBzZWNTZXJ2aWNlcyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SVBzZWNTZXJ2aWNlc1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBDdXJyZW50IElQc2VjIFZQTiBTZXJ2ZXIgU2V0dGluZ3MuIEdldCBhbmQgdmlldyB0aGUgY3VycmVudCBJUHNlYyBWUE4gU2VydmVyIHNldHRpbmdzIG9uIHRoZSBWUE4gU2VydmVyLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SVBzZWNTZXJ2aWNlcyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldElQc2VjU2VydmljZXNcIiwgbmV3IFZwbklQc2VjU2VydmljZXMoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQWRkIE5ldyBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgQ2xpZW50IFNldHRpbmcgdG8gQWNjZXB0IEV0aHJlSVAgLyBMMlRQdjMgQ2xpZW50IERldmljZXMuIEFkZCBhIG5ldyBzZXR0aW5nIGVudHJ5IHRvIGVuYWJsZSB0aGUgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIFNlcnZlciBGdW5jdGlvbiB0byBhY2NlcHQgY2xpZW50IGRldmljZXMuIEluIG9yZGVyIHRvIGFjY2VwdCBjb25uZWN0aW9ucyBmcm9tIHJvdXRlcnMgYnkgdGhlIEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBTZXJ2ZXIgRnVuY3Rpb24sIHlvdSBoYXZlIHRvIGRlZmluZSB0aGUgcmVsYXRpb24gdGFibGUgYmV0d2VlbiBhbiBJUHNlYyBQaGFzZSAxIHN0cmluZyB3aGljaCBpcyBwcmVzZW50ZWQgYnkgY2xpZW50IGRldmljZXMgb2YgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIGNvbXBhdGlibGUgcm91dGVyLCBhbmQgdGhlIGRlc2lnbmF0aW9uIG9mIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gQWZ0ZXIgeW91IGFkZCBhIGRlZmluaXRpb24gZW50cnkgYnkgQWRkRXRoZXJJcElkIEFQSSwgdGhlIGRlZmluZWQgY29ubmVjdGlvbiBzZXR0aW5nIHRvIHRoZSBWaXJ0dWFsIEh1YiB3aWxsIGJlIGFwcGxpZWQgb24gdGhlIGxvZ2luLWF0dGVwdGluZyBzZXNzaW9uIGZyb20gYW4gRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIGNsaWVudCBkZXZpY2UuIFRoZSB1c2VybmFtZSBhbmQgcGFzc3dvcmQgaW4gYW4gZW50cnkgbXVzdCBiZSByZWdpc3RlcmVkIG9uIHRoZSBWaXJ0dWFsIEh1Yi4gQW4gRXRoZXJJUCAvIEwyVFB2MyBjbGllbnQgd2lsbCBiZSByZWdhcmRlZCBhcyBpdCBjb25uZWN0ZWQgdGhlIFZpcnR1YWwgSFVCIHdpdGggdGhlIGlkZW50aWZpY2F0aW9uIG9mIHRoZSBhYm92ZSB1c2VyIGluZm9ybWF0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQWRkRXRoZXJJcElkID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJBZGRFdGhlcklwSWRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgQ3VycmVudCBMaXN0IG9mIEV0aGVySVAgLyBMMlRQdjMgQ2xpZW50IERldmljZSBFbnRyeSBEZWZpbml0aW9ucy4gVGhpcyBBUEkgZ2V0cyBhbmQgc2hvd3MgdGhlIGxpc3Qgb2YgZW50cmllcyB0byBhY2NlcHQgVlBOIGNsaWVudHMgYnkgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIEZ1bmN0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0RXRoZXJJcElkID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRFdGhlcklwSWRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBhbiBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgQ2xpZW50IFNldHRpbmcuIFRoaXMgQVBJIGRlbGV0ZXMgYW4gZW50cnkgdG8gYWNjZXB0IFZQTiBjbGllbnRzIGJ5IEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBGdW5jdGlvbi4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUV0aGVySXBJZCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlRXRoZXJJcElkXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIEN1cnJlbnQgTGlzdCBvZiBFdGhlcklQIC8gTDJUUHYzIENsaWVudCBEZXZpY2UgRW50cnkgRGVmaW5pdGlvbnMuIFRoaXMgQVBJIGdldHMgYW5kIHNob3dzIHRoZSBsaXN0IG9mIGVudHJpZXMgdG8gYWNjZXB0IFZQTiBjbGllbnRzIGJ5IEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBGdW5jdGlvbi4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1FdGhlcklwSWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtRXRoZXJJcElkXCIsIG5ldyBWcG5ScGNFbnVtRXRoZXJJcElkKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBTZXR0aW5ncyBmb3IgT3BlblZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFRoZSBWUE4gU2VydmVyIGhhcyB0aGUgY2xvbmUgZnVuY3Rpb25zIG9mIE9wZW5WUE4gc29mdHdhcmUgcHJvZHVjdHMgYnkgT3BlblZQTiBUZWNobm9sb2dpZXMsIEluYy4gQW55IE9wZW5WUE4gQ2xpZW50cyBjYW4gY29ubmVjdCB0byB0aGlzIFZQTiBTZXJ2ZXIuIFRoZSBtYW5uZXIgdG8gc3BlY2lmeSBhIHVzZXJuYW1lIHRvIGNvbm5lY3QgdG8gdGhlIFZpcnR1YWwgSHViLCBhbmQgdGhlIHNlbGVjdGlvbiBydWxlIG9mIGRlZmF1bHQgSHViIGJ5IHVzaW5nIHRoaXMgY2xvbmUgc2VydmVyIGZ1bmN0aW9ucyBhcmUgc2FtZSB0byB0aGUgSVBzZWMgU2VydmVyIGZ1bmN0aW9ucy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldE9wZW5WcG5Tc3RwQ29uZmlnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRPcGVuVnBuU3N0cENvbmZpZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBDdXJyZW50IFNldHRpbmdzIG9mIE9wZW5WUE4gQ2xvbmUgU2VydmVyIEZ1bmN0aW9uLiBHZXQgYW5kIHNob3cgdGhlIGN1cnJlbnQgc2V0dGluZ3Mgb2YgT3BlblZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRPcGVuVnBuU3N0cENvbmZpZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldE9wZW5WcG5Tc3RwQ29uZmlnXCIsIG5ldyBWcG5PcGVuVnBuU3N0cENvbmZpZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTaG93IHRoZSBDdXJyZW50IFN0YXR1cyBvZiBEeW5hbWljIEROUyBGdW5jdGlvbi4gR2V0IGFuZCBzaG93IHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgRHluYW1pYyBETlMgZnVuY3Rpb24uIFRoZSBEeW5hbWljIEROUyBhc3NpZ25zIGEgdW5pcXVlIGFuZCBwZXJtYW5lbnQgRE5TIGhvc3RuYW1lIGZvciB0aGlzIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoYXQgaG9zdG5hbWUgdG8gc3BlY2lmeSB0aGlzIFZQTiBTZXJ2ZXIgb24gdGhlIHNldHRpbmdzIGZvciBWUE4gQ2xpZW50IGFuZCBWUE4gQnJpZGdlLiBZb3UgbmVlZCBub3QgdG8gcmVnaXN0ZXIgYW5kIGtlZXAgYSBkb21haW4gbmFtZS4gQWxzbywgaWYgeW91ciBJU1AgYXNzaWduZXMgeW91IGEgZHluYW1pYyAobm90LWZpeGVkKSBJUCBhZGRyZXNzLCB0aGUgY29ycmVzcG9uZGluZyBJUCBhZGRyZXNzIG9mIHlvdXIgRHluYW1pYyBETlMgaG9zdG5hbWUgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNoYW5nZWQuIEl0IGVuYWJsZXMgeW91IHRvIGtlZXAgcnVubmluZyB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBvbmx5IGEgZHluYW1pYyBJUCBhZGRyZXNzLiBUaGVyZWZvcmUsIHlvdSBuZWVkIG5vdCBhbnkgbG9uZ2VyIHRvIGtlZXAgc3RhdGljIGdsb2JhbCBJUCBhZGRyZXNzZXMgd2l0aCBleHBlbnNlcyBtb250aGx5IGNvc3RzLiBbQ2F1dGlvbl0gVG8gZGlzYWJsZSB0aGUgRHluYW1pYyBETlMgRnVuY3Rpb24sIG1vZGlmeSB0aGUgY29uZmlndXJhdGlvbiBmaWxlIG9mIFZQTiBTZXJ2ZXIuIFRoZSBcImRlY2xhcmUgcm9vdFwiIGRpcmVjdGl2ZSBoYXMgdGhlIFwiZGVjbGFyZSBERG5zQ2xpZW50XCIgZGlyZWN0aXZlLiBJbiB0aGlzIGRpcmVjdGl2ZSwgeW91IGNhbiBzd2l0Y2ggXCJib29sIERpc2FibGVcIiBmcm9tIGZhbHNlIHRvIHRydWUsIGFuZCByZWJvb3QgdGhlIFZQTiBTZXJ2ZXIsIHRoZW4gdGhlIER5bmFtaWMgRE5TIEZ1bmN0aW9uIHdpbGwgYmUgZGlzYWJsZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5HZXRERG5zQ2xpZW50U3RhdHVzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0RERuc0NsaWVudFN0YXR1c1wiLCBuZXcgVnBuRERuc0NsaWVudFN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIER5bmFtaWMgRE5TIEhvc3RuYW1lLiBZb3UgbXVzdCBzcGVjaWZ5IHRoZSBuZXcgaG9zdG5hbWUgb24gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gWW91IGNhbiB1c2UgdGhpcyBBUEkgdG8gY2hhbmdlIHRoZSBob3N0bmFtZSBhc3NpZ25lZCBieSB0aGUgRHluYW1pYyBETlMgZnVuY3Rpb24uIFRoZSBjdXJyZW50bHkgYXNzaWduZWQgaG9zdG5hbWUgY2FuIGJlIHNob3dlbiBieSB0aGUgR2V0RERuc0NsaWVudFN0YXR1cyBBUEkuIFRoZSBEeW5hbWljIEROUyBhc3NpZ25zIGEgdW5pcXVlIGFuZCBwZXJtYW5lbnQgRE5TIGhvc3RuYW1lIGZvciB0aGlzIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoYXQgaG9zdG5hbWUgdG8gc3BlY2lmeSB0aGlzIFZQTiBTZXJ2ZXIgb24gdGhlIHNldHRpbmdzIGZvciBWUE4gQ2xpZW50IGFuZCBWUE4gQnJpZGdlLiBZb3UgbmVlZCBub3QgdG8gcmVnaXN0ZXIgYW5kIGtlZXAgYSBkb21haW4gbmFtZS4gQWxzbywgaWYgeW91ciBJU1AgYXNzaWduZXMgeW91IGEgZHluYW1pYyAobm90LWZpeGVkKSBJUCBhZGRyZXNzLCB0aGUgY29ycmVzcG9uZGluZyBJUCBhZGRyZXNzIG9mIHlvdXIgRHluYW1pYyBETlMgaG9zdG5hbWUgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNoYW5nZWQuIEl0IGVuYWJsZXMgeW91IHRvIGtlZXAgcnVubmluZyB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBvbmx5IGEgZHluYW1pYyBJUCBhZGRyZXNzLiBUaGVyZWZvcmUsIHlvdSBuZWVkIG5vdCBhbnkgbG9uZ2VyIHRvIGtlZXAgc3RhdGljIGdsb2JhbCBJUCBhZGRyZXNzZXMgd2l0aCBleHBlbnNlcyBtb250aGx5IGNvc3RzLiBbQ2F1dGlvbl0gVG8gZGlzYWJsZSB0aGUgRHluYW1pYyBETlMgRnVuY3Rpb24sIG1vZGlmeSB0aGUgY29uZmlndXJhdGlvbiBmaWxlIG9mIFZQTiBTZXJ2ZXIuIFRoZSBcImRlY2xhcmUgcm9vdFwiIGRpcmVjdGl2ZSBoYXMgdGhlIFwiZGVjbGFyZSBERG5zQ2xpZW50XCIgZGlyZWN0aXZlLiBJbiB0aGlzIGRpcmVjdGl2ZSwgeW91IGNhbiBzd2l0Y2ggXCJib29sIERpc2FibGVcIiBmcm9tIGZhbHNlIHRvIHRydWUsIGFuZCByZWJvb3QgdGhlIFZQTiBTZXJ2ZXIsIHRoZW4gdGhlIER5bmFtaWMgRE5TIEZ1bmN0aW9uIHdpbGwgYmUgZGlzYWJsZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5DaGFuZ2VERG5zQ2xpZW50SG9zdG5hbWUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNoYW5nZUREbnNDbGllbnRIb3N0bmFtZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2VuZXJhdGUgTmV3IFNlbGYtU2lnbmVkIENlcnRpZmljYXRlIHdpdGggU3BlY2lmaWVkIENOIChDb21tb24gTmFtZSkgYW5kIFJlZ2lzdGVyIG9uIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gc3BlY2lmeSB0aGUgbmV3IENOIChjb21tb24gbmFtZSkgdmFsdWUgb24gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gWW91IGNhbiB1c2UgdGhpcyBBUEkgdG8gcmVwbGFjZSB0aGUgY3VycmVudCBjZXJ0aWZpY2F0ZSBvbiB0aGUgVlBOIFNlcnZlciB0byBhIG5ldyBzZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSB3aGljaCBoYXMgdGhlIENOIChDb21tb24gTmFtZSkgdmFsdWUgaW4gdGhlIGZpZWxkcy4gVGhpcyBBUEkgaXMgY29udmVuaWVudCBpZiB5b3UgYXJlIHBsYW5uaW5nIHRvIHVzZSBNaWNyb3NvZnQgU1NUUCBWUE4gQ2xvbmUgU2VydmVyIEZ1bmN0aW9uLiBCZWNhdXNlIG9mIHRoZSB2YWx1ZSBvZiBDTiAoQ29tbW9uIE5hbWUpIG9uIHRoZSBTU0wgY2VydGlmaWNhdGUgb2YgVlBOIFNlcnZlciBtdXN0IG1hdGNoIHRvIHRoZSBob3N0bmFtZSBzcGVjaWZpZWQgb24gdGhlIFNTVFAgVlBOIGNsaWVudC4gVGhpcyBBUEkgd2lsbCBkZWxldGUgdGhlIGV4aXN0aW5nIFNTTCBjZXJ0aWZpY2F0ZSBvZiB0aGUgVlBOIFNlcnZlci4gSXQgaXMgcmVjb21tZW5kZWQgdG8gYmFja3VwIHRoZSBjdXJyZW50IFNTTCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgYnkgdXNpbmcgdGhlIEdldFNlcnZlckNlcnQgQVBJIGJlZm9yZWhhbmQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5SZWdlbmVyYXRlU2VydmVyQ2VydCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiUmVnZW5lcmF0ZVNlcnZlckNlcnRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdlbmVyYXRlIGEgU2FtcGxlIFNldHRpbmcgRmlsZSBmb3IgT3BlblZQTiBDbGllbnQuIE9yaWdpbmFsbHksIHRoZSBPcGVuVlBOIENsaWVudCByZXF1aXJlcyBhIHVzZXIgdG8gd3JpdGUgYSB2ZXJ5IGRpZmZpY3VsdCBjb25maWd1cmF0aW9uIGZpbGUgbWFudWFsbHkuIFRoaXMgQVBJIGhlbHBzIHlvdSB0byBtYWtlIGEgdXNlZnVsIGNvbmZpZ3VyYXRpb24gc2FtcGxlLiBXaGF0IHlvdSBuZWVkIHRvIGdlbmVyYXRlIHRoZSBjb25maWd1cmF0aW9uIGZpbGUgZm9yIHRoZSBPcGVuVlBOIENsaWVudCBpcyB0byBydW4gdGhpcyBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5NYWtlT3BlblZwbkNvbmZpZ0ZpbGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJNYWtlT3BlblZwbkNvbmZpZ0ZpbGVcIiwgbmV3IFZwblJwY1JlYWRMb2dGaWxlKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEVuYWJsZSAvIERpc2FibGUgdGhlIFZQTiBvdmVyIElDTVAgLyBWUE4gb3ZlciBETlMgU2VydmVyIEZ1bmN0aW9uLiBZb3UgY2FuIGVzdGFibGlzaCBhIFZQTiBvbmx5IHdpdGggSUNNUCBvciBETlMgcGFja2V0cyBldmVuIGlmIHRoZXJlIGlzIGEgZmlyZXdhbGwgb3Igcm91dGVycyB3aGljaCBibG9ja3MgVENQL0lQIGNvbW11bmljYXRpb25zLiBZb3UgaGF2ZSB0byBlbmFibGUgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnMgYmVmb3JlaGFuZC4gV2FybmluZzogVXNlIHRoaXMgZnVuY3Rpb24gZm9yIGVtZXJnZW5jeSBvbmx5LiBJdCBpcyBoZWxwZnVsIHdoZW4gYSBmaXJld2FsbCBvciByb3V0ZXIgaXMgbWlzY29uZmlndXJlZCB0byBibG9ja3MgVENQL0lQLCBidXQgZWl0aGVyIElDTVAgb3IgRE5TIGlzIG5vdCBibG9ja2VkLiBJdCBpcyBub3QgZm9yIGxvbmctdGVybSBzdGFibGUgdXNpbmcuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5TZXRTcGVjaWFsTGlzdGVuZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFNwZWNpYWxMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IEN1cnJlbnQgU2V0dGluZyBvZiB0aGUgVlBOIG92ZXIgSUNNUCAvIFZQTiBvdmVyIEROUyBGdW5jdGlvbi4gR2V0IGFuZCBzaG93IHRoZSBjdXJyZW50IFZQTiBvdmVyIElDTVAgLyBWUE4gb3ZlciBETlMgRnVuY3Rpb24gc3RhdHVzLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U3BlY2lhbExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U3BlY2lhbExpc3RlbmVyXCIsIG5ldyBWcG5ScGNTcGVjaWFsTGlzdGVuZXIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2hvdyB0aGUgY3VycmVudCBzdGF0dXMgb2YgVlBOIEF6dXJlIGZ1bmN0aW9uLiBHZXQgYW5kIHNob3cgdGhlIGN1cnJlbnQgc3RhdHVzIG9mIHRoZSBWUE4gQXp1cmUgZnVuY3Rpb24uIFZQTiBBenVyZSBtYWtlcyBpdCBlYXNpZXIgdG8gZXN0YWJsaXNoIGEgVlBOIFNlc3Npb24gZnJvbSB5b3VyIGhvbWUgUEMgdG8geW91ciBvZmZpY2UgUEMuIFdoaWxlIGEgVlBOIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQsIHlvdSBjYW4gYWNjZXNzIHRvIGFueSBvdGhlciBzZXJ2ZXJzIG9uIHRoZSBwcml2YXRlIG5ldHdvcmsgb2YgeW91ciBjb21wYW55LiBZb3UgZG9uJ3QgbmVlZCBhIGdsb2JhbCBJUCBhZGRyZXNzIG9uIHRoZSBvZmZpY2UgUEMgKFZQTiBTZXJ2ZXIpLiBJdCBjYW4gd29yayBiZWhpbmQgZmlyZXdhbGxzIG9yIE5BVHMuIE5vIG5ldHdvcmsgYWRtaW5pc3RyYXRvcidzIGNvbmZpZ3VyYXRpb24gcmVxdWlyZWQuIFlvdSBjYW4gdXNlIHRoZSBidWlsdC1pbiBTU1RQLVZQTiBDbGllbnQgb2YgV2luZG93cyBpbiB5b3VyIGhvbWUgUEMuIFZQTiBBenVyZSBpcyBhIGNsb3VkIFZQTiBzZXJ2aWNlIG9wZXJhdGVkIGJ5IFNvZnRFdGhlciBDb3Jwb3JhdGlvbi4gVlBOIEF6dXJlIGlzIGZyZWUgb2YgY2hhcmdlIGFuZCBhdmFpbGFibGUgdG8gYW55b25lLiBWaXNpdCBodHRwOi8vd3d3LnZwbmF6dXJlLm5ldC8gdG8gc2VlIGRldGFpbHMgYW5kIGhvdy10by11c2UgaW5zdHJ1Y3Rpb25zLiBUaGUgVlBOIEF6dXJlIGhvc3RuYW1lIGlzIHNhbWUgdG8gdGhlIGhvc3RuYW1lIG9mIHRoZSBEeW5hbWljIEROUyBzZXR0aW5nLCBidXQgYWx0ZXJpbmcgdGhlIGRvbWFpbiBzdWZmaXggdG8gXCJ2cG5henVyZS5uZXRcIi4gVG8gY2hhbmdlIHRoZSBob3N0bmFtZSB1c2UgdGhlIENoYW5nZUREbnNDbGllbnRIb3N0bmFtZSBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRBenVyZVN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEF6dXJlU3RhdHVzXCIsIG5ldyBWcG5ScGNBenVyZVN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBFbmFibGUgLyBEaXNhYmxlIFZQTiBBenVyZSBGdW5jdGlvbi4gRW5hYmxlIG9yIGRpc2FibGUgdGhlIFZQTiBBenVyZSBmdW5jdGlvbi4gVlBOIEF6dXJlIG1ha2VzIGl0IGVhc2llciB0byBlc3RhYmxpc2ggYSBWUE4gU2Vzc2lvbiBmcm9tIHlvdXIgaG9tZSBQQyB0byB5b3VyIG9mZmljZSBQQy4gV2hpbGUgYSBWUE4gY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZCwgeW91IGNhbiBhY2Nlc3MgdG8gYW55IG90aGVyIHNlcnZlcnMgb24gdGhlIHByaXZhdGUgbmV0d29yayBvZiB5b3VyIGNvbXBhbnkuIFlvdSBkb24ndCBuZWVkIGEgZ2xvYmFsIElQIGFkZHJlc3Mgb24gdGhlIG9mZmljZSBQQyAoVlBOIFNlcnZlcikuIEl0IGNhbiB3b3JrIGJlaGluZCBmaXJld2FsbHMgb3IgTkFUcy4gTm8gbmV0d29yayBhZG1pbmlzdHJhdG9yJ3MgY29uZmlndXJhdGlvbiByZXF1aXJlZC4gWW91IGNhbiB1c2UgdGhlIGJ1aWx0LWluIFNTVFAtVlBOIENsaWVudCBvZiBXaW5kb3dzIGluIHlvdXIgaG9tZSBQQy4gVlBOIEF6dXJlIGlzIGEgY2xvdWQgVlBOIHNlcnZpY2Ugb3BlcmF0ZWQgYnkgU29mdEV0aGVyIENvcnBvcmF0aW9uLiBWUE4gQXp1cmUgaXMgZnJlZSBvZiBjaGFyZ2UgYW5kIGF2YWlsYWJsZSB0byBhbnlvbmUuIFZpc2l0IGh0dHA6Ly93d3cudnBuYXp1cmUubmV0LyB0byBzZWUgZGV0YWlscyBhbmQgaG93LXRvLXVzZSBpbnN0cnVjdGlvbnMuIFRoZSBWUE4gQXp1cmUgaG9zdG5hbWUgaXMgc2FtZSB0byB0aGUgaG9zdG5hbWUgb2YgdGhlIER5bmFtaWMgRE5TIHNldHRpbmcsIGJ1dCBhbHRlcmluZyB0aGUgZG9tYWluIHN1ZmZpeCB0byBcInZwbmF6dXJlLm5ldFwiLiBUbyBjaGFuZ2UgdGhlIGhvc3RuYW1lIHVzZSB0aGUgQ2hhbmdlRERuc0NsaWVudEhvc3RuYW1lIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEF6dXJlU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRBenVyZVN0YXR1c1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBQcm94eSBTZXR0aW5ncyBmb3IgQ29ubmVjdGluZyB0byB0aGUgREROUyBzZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRERG5zSW50ZXJuZXRTZXR0bmcgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRERG5zSW50ZXJuZXRTZXR0bmdcIiwgbmV3IFZwbkludGVybmV0U2V0dGluZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFByb3h5IFNldHRpbmdzIGZvciBDb25uZWN0aW5nIHRvIHRoZSBERE5TIHNlcnZlci4gKi9cclxuICAgICAgICB0aGlzLlNldEREbnNJbnRlcm5ldFNldHRuZyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0RERuc0ludGVybmV0U2V0dG5nXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFZQTiBHYXRlIFNlcnZlciBDb25maWd1cmF0aW9uLiBUaGlzIEFQSSBpcyB2YWxpZCBmb3IgV2luMzIgYmluYXJ5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgU3RhYmxlIEVkaXRpb24gb2YgU29mdEV0aGVyIFZQTiBTZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRWZ3NDb25maWcgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFZnc0NvbmZpZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBWUE4gR2F0ZSBTZXJ2ZXIgQ29uZmlndXJhdGlvbi4gVGhpcyBBUEkgaXMgdmFsaWQgZm9yIFdpbjMyIGJpbmFyeSBkaXN0cmlidXRpb24gb2YgdGhlIFN0YWJsZSBFZGl0aW9uIG9mIFNvZnRFdGhlciBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0VmdzQ29uZmlnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0VmdzQ29uZmlnXCIsIG5ldyBWcG5WZ3NDb25maWcoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICB2YXIgaGVhZGVycyA9IHt9O1xyXG4gICAgICAgIHZhciBzZW5kX2NyZWRlbnRpYWxzID0gZmFsc2U7XHJcbiAgICAgICAgbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0ID0gaXNfbnVsbChub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQpID8gZmFsc2UgOiBub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQ7XHJcbiAgICAgICAgaWYgKGlzX251bGwodnBuc2VydmVyX2hvc3RuYW1lKSkge1xyXG4gICAgICAgICAgICB0aGlzLnJwY191cmwgPSBcIi9hcGkvXCI7XHJcbiAgICAgICAgICAgIHNlbmRfY3JlZGVudGlhbHMgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKGlzX251bGwodnBuc2VydmVyX3BvcnQpKVxyXG4gICAgICAgICAgICAgICAgdnBuc2VydmVyX3BvcnQgPSA0NDM7XHJcbiAgICAgICAgICAgIHRoaXMucnBjX3VybCA9IFwiaHR0cHM6Ly9cIiArIHZwbnNlcnZlcl9ob3N0bmFtZSArIFwiOlwiICsgdnBuc2VydmVyX3BvcnQgKyBcIi9hcGkvXCI7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbXCJYLVZQTkFETUlOLUhVQk5BTUVcIl0gPSBpc19udWxsKGh1Ym5hbWUpID8gXCJcIiA6IGh1Ym5hbWU7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbXCJYLVZQTkFETUlOLVBBU1NXT1JEXCJdID0gaXNfbnVsbChwYXNzd29yZCkgPyBcIlwiIDogcGFzc3dvcmQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc19udWxsKG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCkpXHJcbiAgICAgICAgICAgIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMucnBjX2NsaWVudCA9IG5ldyBKc29uUnBjQ2xpZW50KHRoaXMucnBjX3VybCwgaGVhZGVycywgc2VuZF9jcmVkZW50aWFscywgbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0KTtcclxuICAgIH1cclxuICAgIC8qKiBEZXRlcm1pbmUgaWYgdGhpcyBKYXZhU2NyaXB0IGVudmlyb25tZW50IGlzIG9uIHRoZSBOb2RlLmpzIG9yIG5vdC4gKi9cclxuICAgIFZwblNlcnZlclJwYy5Jc05vZGVKUyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gaXNfbm9kZV9qcztcclxuICAgIH07XHJcbiAgICAvKiogU2V0IHRoZSBkZWJ1ZyBtb2RlIGZsYWcgKi9cclxuICAgIFZwblNlcnZlclJwYy5TZXREZWJ1Z01vZGUgPSBmdW5jdGlvbiAoZmxhZykge1xyXG4gICAgICAgIGRlYnVnX21vZGUgPSBmbGFnO1xyXG4gICAgfTtcclxuICAgIC8vIC0tIFV0aWxpdHkgZnVuY3Rpb25zIC0tXHJcbiAgICAvKiogQ2FsbCBhIFJQQyBwcm9jZWR1cmUgKi9cclxuICAgIFZwblNlcnZlclJwYy5wcm90b3R5cGUuQ2FsbEFzeW5jID0gZnVuY3Rpb24gKG1ldGhvZF9uYW1lLCByZXF1ZXN0KSB7XHJcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzcG9uc2U7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6IHJldHVybiBbNCAvKnlpZWxkKi8sIHRoaXMucnBjX2NsaWVudC5DYWxsQXN5bmMobWV0aG9kX25hbWUsIHJlcXVlc3QpXTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gX2Euc2VudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgcmVzcG9uc2VdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gVnBuU2VydmVyUnBjO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblNlcnZlclJwYyA9IFZwblNlcnZlclJwYztcclxuLy8gLS0tIFR5cGVzIC0tLVxyXG4vKiogSVAgUHJvdG9jb2wgTnVtYmVycyAqL1xyXG52YXIgVnBuSXBQcm90b2NvbE51bWJlcjtcclxuKGZ1bmN0aW9uIChWcG5JcFByb3RvY29sTnVtYmVyKSB7XHJcbiAgICAvKiogSUNNUCBmb3IgSVB2NCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiSUNNUHY0XCJdID0gMV0gPSBcIklDTVB2NFwiO1xyXG4gICAgLyoqIFRDUCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiVENQXCJdID0gNl0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiVURQXCJdID0gMTddID0gXCJVRFBcIjtcclxuICAgIC8qKiBJQ01QIGZvciBJUHY2ICovXHJcbiAgICBWcG5JcFByb3RvY29sTnVtYmVyW1ZwbklwUHJvdG9jb2xOdW1iZXJbXCJJQ01QdjZcIl0gPSA1OF0gPSBcIklDTVB2NlwiO1xyXG59KShWcG5JcFByb3RvY29sTnVtYmVyID0gZXhwb3J0cy5WcG5JcFByb3RvY29sTnVtYmVyIHx8IChleHBvcnRzLlZwbklwUHJvdG9jb2xOdW1iZXIgPSB7fSkpO1xyXG4vKiogVGhlIGJvZHkgb2YgdGhlIEFjY2VzcyBsaXN0ICovXHJcbnZhciBWcG5BY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQWNjZXNzJyBjbGFzczogVGhlIGJvZHkgb2YgdGhlIEFjY2VzcyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5BY2Nlc3MoaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogU3BlY2lmeSBhIGRlc2NyaXB0aW9uIChub3RlKSBmb3IgdGhpcyBydWxlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEVuYWJsZWQgZmxhZyAodHJ1ZTogZW5hYmxlZCwgZmFsc2U6IGRpc2FibGVkKSAqL1xyXG4gICAgICAgIHRoaXMuQWN0aXZlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSBhbiBpbnRlZ2VyIG9mIDEgb3IgaGlnaGVyIHRvIGluZGljYXRlIHRoZSBwcmlvcml0eSBvZiB0aGUgcnVsZS4gSGlnaGVyIHByaW9yaXR5IGlzIGdpdmVuIHRvIHJ1bGVzIHdpdGggdGhlIGxvd2VyIHByaW9yaXR5IHZhbHVlcy4gKi9cclxuICAgICAgICB0aGlzLlByaW9yaXR5X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIGlmIHRoZSBydWxlIGlzIERJU0NBUkQgb3BlcmF0aW9uIG9yIFBBU1Mgb3BlcmF0aW9uLiBXaGVuIGEgcGFja2V0IG1hdGNoZXMgdGhpcyBydWxlIGNvbmRpdGlvbiwgdGhpcyBvcGVyYXRpb24gaXMgZGVjaWRlZC4gV2hlbiB0aGUgb3BlcmF0aW9uIG9mIHRoZSBydWxlIGlzIFBBU1MsIHRoZSBwYWNrZXQgaXMgYWxsb3dlZCB0byBwYXNzLCBvdGhlcndpc2UgdGhlIHBhY2tldCB3aWxsIGJlIGRpc2NhcmRlZC4gKi9cclxuICAgICAgICB0aGlzLkRpc2NhcmRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyBpZiB0aGUgcnVsZSBpcyBmb3IgSVB2Ni4gU3BlY2lmeSBmYWxzZSBmb3IgSVB2NCwgb3Igc3BlY2lmeSB0cnVlIGZvciBJUHY2LiAqL1xyXG4gICAgICAgIHRoaXMuSXNJUHY2X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY0IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gWW91IG11c3QgYWxzbyBzcGVjaWZ5IHRoZSBTcmNTdWJuZXRNYXNrX2lwIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY0IHN1Ym5ldCBtYXNrIGFzIGEgcnVsZSBjb25kaXRpb24uIFwiMC4wLjAuMFwiIG1lYW5zIGFsbCBob3N0cy4gXCIyNTUuMjU1LjI1NS4yNTVcIiBtZWFucyBvbmUgc2luZ2xlIGhvc3QuICovXHJcbiAgICAgICAgdGhpcy5TcmNTdWJuZXRNYXNrX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIGRlc3RpbmF0aW9uIElQdjQgYWRkcmVzcyBhcyBhIHJ1bGUgY29uZGl0aW9uLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIERlc3RTdWJuZXRNYXNrX2lwIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuRGVzdElwQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NCBtb2RlIChJc0lQdjZfYm9vbCA9PSBmYWxzZSkuIFNwZWNpZnkgYSBkZXN0aW5hdGlvbiBJUHY0IHN1Ym5ldCBtYXNrIGFzIGEgcnVsZSBjb25kaXRpb24uIFwiMC4wLjAuMFwiIG1lYW5zIGFsbCBob3N0cy4gXCIyNTUuMjU1LjI1NS4yNTVcIiBtZWFucyBvbmUgc2luZ2xlIGhvc3QuICovXHJcbiAgICAgICAgdGhpcy5EZXN0U3VibmV0TWFza19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NiBtb2RlIChJc0lQdjZfYm9vbCA9PSB0cnVlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY2IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBhZGRyZXNzIGluIGJpbmFyeSBmb3JtLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIFNyY1N1Ym5ldE1hc2s2X2JpbiBmaWVsZC4gKi9cclxuICAgICAgICB0aGlzLlNyY0lwQWRkcmVzczZfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGlmIHRoZSBydWxlIGlzIElQdjYgbW9kZSAoSXNJUHY2X2Jvb2wgPT0gdHJ1ZSkuIFNwZWNpZnkgYSBzb3VyY2UgSVB2NiBzdWJuZXQgbWFzayBhcyBhIHJ1bGUgY29uZGl0aW9uLiBUaGUgZmllbGQgbXVzdCBiZSBhIGJ5dGUgYXJyYXkgb2YgMTYgYnl0ZXMgKDEyOCBiaXRzKSB0byBjb250YWluIHRoZSBJUHY2IHN1Ym5ldCBtYXNrIGluIGJpbmFyeSBmb3JtLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjU3VibmV0TWFzazZfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGlmIHRoZSBydWxlIGlzIElQdjYgbW9kZSAoSXNJUHY2X2Jvb2wgPT0gdHJ1ZSkuIFNwZWNpZnkgYSBkZXN0aW5hdGlvbiBJUHY2IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBhZGRyZXNzIGluIGJpbmFyeSBmb3JtLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIERlc3RTdWJuZXRNYXNrNl9iaW4gZmllbGQuICovXHJcbiAgICAgICAgdGhpcy5EZXN0SXBBZGRyZXNzNl9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NiBtb2RlIChJc0lQdjZfYm9vbCA9PSB0cnVlKS4gU3BlY2lmeSBhIGRlc3RpbmF0aW9uIElQdjYgc3VibmV0IG1hc2sgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBzdWJuZXQgbWFzayBpbiBiaW5hcnkgZm9ybS4gKi9cclxuICAgICAgICB0aGlzLkRlc3RTdWJuZXRNYXNrNl9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFRoZSBJUCBwcm90b2NvbCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlByb3RvY29sX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBTdGFydCBWYWx1ZSBvZiB0aGUgU291cmNlIFBvcnQgTnVtYmVyIFJhbmdlLiBJZiB0aGUgc3BlY2lmaWVkIHByb3RvY29sIGlzIFRDUC9JUCBvciBVRFAvSVAsIHNwZWNpZnkgdGhlIHNvdXJjZSBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5TcmNQb3J0U3RhcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIEVuZCBWYWx1ZSBvZiB0aGUgU291cmNlIFBvcnQgTnVtYmVyIFJhbmdlLiBJZiB0aGUgc3BlY2lmaWVkIHByb3RvY29sIGlzIFRDUC9JUCBvciBVRFAvSVAsIHNwZWNpZnkgdGhlIHNvdXJjZSBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5TcmNQb3J0RW5kX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBTdGFydCBWYWx1ZSBvZiB0aGUgRGVzdGluYXRpb24gUG9ydCBOdW1iZXIgUmFuZ2UuIElmIHRoZSBzcGVjaWZpZWQgcHJvdG9jb2wgaXMgVENQL0lQIG9yIFVEUC9JUCwgc3BlY2lmeSB0aGUgZGVzdGluYXRpb24gcG9ydCBudW1iZXIgYXMgdGhlIHJ1bGUgY29uZGl0aW9uLiBQcm90b2NvbHMgb3RoZXIgdGhhbiB0aGlzIHdpbGwgYmUgaWdub3JlZC4gV2hlbiB0aGlzIHBhcmFtZXRlciBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgcnVsZXMgd2lsbCBhcHBseSB0byBhbGwgcG9ydCBudW1iZXJzLiAqL1xyXG4gICAgICAgIHRoaXMuRGVzdFBvcnRTdGFydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgRW5kIFZhbHVlIG9mIHRoZSBEZXN0aW5hdGlvbiBQb3J0IE51bWJlciBSYW5nZS4gSWYgdGhlIHNwZWNpZmllZCBwcm90b2NvbCBpcyBUQ1AvSVAgb3IgVURQL0lQLCBzcGVjaWZ5IHRoZSBkZXN0aW5hdGlvbiBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5EZXN0UG9ydEVuZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgdXNlciBuYW1lLiBZb3UgY2FuIGFwcGx5IHRoaXMgcnVsZSB0byBvbmx5IHRoZSBwYWNrZXRzIHNlbnQgYnkgYSB1c2VyIHNlc3Npb24gb2YgYSB1c2VyIG5hbWUgdGhhdCBoYXMgYmVlbiBzcGVjaWZpZWQgYXMgYSBydWxlIGNvbmRpdGlvbi4gSW4gdGhpcyBjYXNlLCBzcGVjaWZ5IHRoZSB1c2VyIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5TcmNVc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiB1c2VyIG5hbWUuIFlvdSBjYW4gYXBwbHkgdGhpcyBydWxlIHRvIG9ubHkgdGhlIHBhY2tldHMgcmVjZWl2ZWQgYnkgYSB1c2VyIHNlc3Npb24gb2YgYSB1c2VyIG5hbWUgdGhhdCBoYXMgYmVlbiBzcGVjaWZpZWQgYXMgYSBydWxlIGNvbmRpdGlvbi4gSW4gdGhpcyBjYXNlLCBzcGVjaWZ5IHRoZSB1c2VyIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5EZXN0VXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBzb3VyY2UgTUFDIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5DaGVja1NyY01hY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNvdXJjZSBNQUMgYWRkcmVzcyAoNiBieXRlcyksIHZhbGlkIG9ubHkgaWYgQ2hlY2tTcmNNYWNfYm9vbCA9PSB0cnVlLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjTWFjQWRkcmVzc19iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFNvdXJjZSBNQUMgYWRkcmVzcyBtYXNrICg2IGJ5dGVzKSwgdmFsaWQgb25seSBpZiBDaGVja1NyY01hY19ib29sID09IHRydWUuICovXHJcbiAgICAgICAgdGhpcy5TcmNNYWNNYXNrX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBkZXN0aW5hdGlvbiBNQUMgYWRkcmVzcy4gKi9cclxuICAgICAgICB0aGlzLkNoZWNrRHN0TWFjX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gTUFDIGFkZHJlc3MgKDYgYnl0ZXMpLCB2YWxpZCBvbmx5IGlmIENoZWNrU3JjTWFjX2Jvb2wgPT0gdHJ1ZS4gKi9cclxuICAgICAgICB0aGlzLkRzdE1hY0FkZHJlc3NfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiBNQUMgYWRkcmVzcyBtYXNrICg2IGJ5dGVzKSwgdmFsaWQgb25seSBpZiBDaGVja1NyY01hY19ib29sID09IHRydWUuICovXHJcbiAgICAgICAgdGhpcy5Ec3RNYWNNYXNrX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBzdGF0ZSBvZiB0aGUgVENQIGNvbm5lY3Rpb24uICovXHJcbiAgICAgICAgdGhpcy5DaGVja1RjcFN0YXRlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiBDaGVja1RjcFN0YXRlX2Jvb2wgPT0gdHJ1ZS4gU2V0IHRoaXMgZmllbGQgdHJ1ZSB0byBtYXRjaCBvbmx5IFRDUC1lc3RhYmxpc2hlZCBwYWNrZXRzLiBTZXQgdGhpcyBmaWVsZCBmYWxzZSB0byBtYXRjaCBvbmx5IFRDUC1ub24gZXN0YWJsaXNoZWQgcGFja2V0cy4gKi9cclxuICAgICAgICB0aGlzLkVzdGFibGlzaGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2V0IHRoaXMgdmFsdWUgdG8gZ2VuZXJhdGUgZGVsYXlzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSBkZWxheSBwZXJpb2QgaW4gbWlsbGlzZWNvbmRzLiBTcGVjaWZ5IDAgbWVhbnMgbm8gZGVsYXlzIHRvIGdlbmVyYXRlLiBUaGUgZGVsYXlzIG11c3QgYmUgMTAwMDAgbWlsbGlzZWNvbmRzIGF0IG1vc3QuICovXHJcbiAgICAgICAgdGhpcy5EZWxheV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXQgdGhpcyB2YWx1ZSB0byBnZW5lcmF0ZSBqaXR0ZXJzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSByYXRpbyBvZiBmbHVjdHVhdGlvbiBvZiBqaXR0ZXJzIHdpdGhpbiAwJSB0byAxMDAlIHJhbmdlLiBTcGVjaWZ5IDAgbWVhbnMgbm8gaml0dGVycyB0byBnZW5lcmF0ZS4gKi9cclxuICAgICAgICB0aGlzLkppdHRlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXQgdGhpcyB2YWx1ZSB0byBnZW5lcmF0ZSBwYWNrZXQgbG9zc2VzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSByYXRpbyBvZiBwYWNrZXQgbG9zc2VzIHdpdGhpbiAwJSB0byAxMDAlIHJhbmdlLiBTcGVjaWZ5IDAgbWVhbnMgbm8gcGFja2V0IGxvc3NlcyB0byBnZW5lcmF0ZS4gKi9cclxuICAgICAgICB0aGlzLkxvc3NfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIHNwZWNpZmllZCBVUkwgd2lsbCBiZSBtYW5kYXRvcnkgcmVwbGllZCB0byB0aGUgY2xpZW50IGFzIGEgcmVzcG9uc2UgZm9yIFRDUCBjb25uZWN0aW5nIHJlcXVlc3QgcGFja2V0cyB3aGljaCBtYXRjaGVzIHRoZSBjb25kaXRpb25zIG9mIHRoaXMgYWNjZXNzIGxpc3QgZW50cnkgdmlhIHRoaXMgVmlydHVhbCBIdWIuIFRvIHVzZSB0aGlzIHNldHRpbmcsIHlvdSBjYW4gZW5mb3JjZSB0aGUgd2ViIGJyb3dzZXIgb2YgdGhlIFZQTiBDbGllbnQgY29tcHV0ZXIgdG8gc2hvdyB0aGUgc3BlY2lmaWVkIHdlYiBzaXRlIHdoZW4gdGhhdCB3ZWIgYnJvd3NlciB0cmllcyB0byBhY2Nlc3MgdGhlIHNwZWNpZmljIElQIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5SZWRpcmVjdFVybF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQWNjZXNzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwbkFjY2VzcyA9IFZwbkFjY2VzcztcclxuLyoqIEFkZCBhbiBpdGVtIHRvIEFjY2VzcyBMaXN0ICovXHJcbnZhciBWcG5ScGNBZGRBY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQWRkQWNjZXNzJyBjbGFzczogQWRkIGFuIGl0ZW0gdG8gQWNjZXNzIExpc3QgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0FkZEFjY2Vzcyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEFjY2VzcyBsaXN0IChNdXN0IGJlIGEgc2luZ2xlIGl0ZW0pICovXHJcbiAgICAgICAgdGhpcy5BY2Nlc3NMaXN0U2luZ2xlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNBZGRBY2Nlc3M7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQWRkQWNjZXNzID0gVnBuUnBjQWRkQWNjZXNzO1xyXG4vKiogQWRkIENBIHRvIEhVQiAqL1xyXG52YXIgVnBuUnBjSHViQWRkQ0EgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViQWRkQ0EnIGNsYXNzOiBBZGQgQ0EgdG8gSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJBZGRDQShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBib2R5IG9mIHRoZSBYLjUwOSBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuQ2VydF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNIdWJBZGRDQTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJBZGRDQSA9IFZwblJwY0h1YkFkZENBO1xyXG4vKiogQ1JMIGVudHJ5ICovXHJcbnZhciBWcG5ScGNDcmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQ3JsJyBjbGFzczogQ1JMIGVudHJ5ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNDcmwoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBLZXkgSUQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDTiwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkNvbW1vbk5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTywgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLk9yZ2FuaXphdGlvbl91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPVSwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLlVuaXRfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogQywgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkNvdW50cnlfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogU1QsIG9wdGlvbmFsICovXHJcbiAgICAgICAgdGhpcy5TdGF0ZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBMLCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuTG9jYWxfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogU2VyaWFsLCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuU2VyaWFsX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogTUQ1IERpZ2VzdCwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkRpZ2VzdE1ENV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFNIQTEgRGlnZXN0LCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuRGlnZXN0U0hBMV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNDcmw7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQ3JsID0gVnBuUnBjQ3JsO1xyXG4vKiogRXRoZXJJUCBrZXkgbGlzdCBlbnRyeSAqL1xyXG52YXIgVnBuRXRoZXJJcElkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwbkV0aGVySXBJZCcgY2xhc3M6IEV0aGVySVAga2V5IGxpc3QgZW50cnkgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkV0aGVySXBJZChpbml0KSB7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgYW4gSVNBS01QIFBoYXNlIDEgSUQuIFRoZSBJRCBtdXN0IGJlIGV4YWN0bHkgc2FtZSBhcyBhIElEIGluIHRoZSBjb25maWd1cmF0aW9uIG9mIHRoZSBFdGhlcklQIC8gTDJUUHYzIENsaWVudC4gWW91IGNhbiBzcGVjaWZ5IElQIGFkZHJlc3MgYXMgd2VsbCBhcyBjaGFyYWN0ZXJzIGFzIElELCBpZiB0aGUgRXRoZXJJUCBDbGllbnQgdXNlcyBJUCBhZGRyZXNzIGFzIFBoYXNlIDEgSUQuIElmIHlvdSBzcGVjaWZ5ICcqJyAoYXN0ZXJpc2spLCBpdCB3aWxsIGJlIGEgd2lsZGNhcmQgdG8gbWF0Y2ggYW55IGNsaWVudHMgd2hpY2ggZG9lc24ndCBtYXRjaCBvdGhlciBleHBsaWNpdCBydWxlcy4gKi9cclxuICAgICAgICB0aGlzLklkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIG5hbWUgb2YgdGhlIFZpcnR1YWwgSHViIHRvIGNvbm5lY3QuICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHVzZXJuYW1lIHRvIGxvZ2luIHRvIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLlVzZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHBhc3N3b3JkIHRvIGxvZ2luIHRvIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLlBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5FdGhlcklwSWQ7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuRXRoZXJJcElkID0gVnBuRXRoZXJJcElkO1xyXG4vKiogTGF5ZXItMyB2aXJ0dWFsIGludGVyZmFjZSAqL1xyXG52YXIgVnBuUnBjTDNJZiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNMM0lmJyBjbGFzczogTGF5ZXItMyB2aXJ0dWFsIGludGVyZmFjZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTDNJZihpbml0KSB7XHJcbiAgICAgICAgLyoqIEwzIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSFVCIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLlN1Ym5ldE1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTDNJZjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMM0lmID0gVnBuUnBjTDNJZjtcclxuLyoqIExheWVyLTMgc3dpdGNoICovXHJcbnZhciBWcG5ScGNMM1N3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0wzU3cnIGNsYXNzOiBMYXllci0zIHN3aXRjaCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTDNTdyhpbml0KSB7XHJcbiAgICAgICAgLyoqIExheWVyLTMgU3dpdGNoIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0wzU3c7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTDNTdyA9IFZwblJwY0wzU3c7XHJcbi8qKiBSb3V0aW5nIHRhYmxlICovXHJcbnZhciBWcG5ScGNMM1RhYmxlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0wzVGFibGUnIGNsYXNzOiBSb3V0aW5nIHRhYmxlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMM1RhYmxlKGluaXQpIHtcclxuICAgICAgICAvKiogTDMgc3dpdGNoIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTmV0d29yayBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5OZXR3b3JrQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFN1Ym5ldCBtYXNrICovXHJcbiAgICAgICAgdGhpcy5TdWJuZXRNYXNrX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogR2F0ZXdheSBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5HYXRld2F5QWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE1ldHJpYyAqL1xyXG4gICAgICAgIHRoaXMuTWV0cmljX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMM1RhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0wzVGFibGUgPSBWcG5ScGNMM1RhYmxlO1xyXG4vKiogR2VuZXJpYyBwYXJhbWV0ZXIgdG8gY29udGFpbiB1MzIsIHU2NCwgYXNjaWlfc3RyaW5nIGFuZCB1bmljb2RlIHN0cmluZyAqL1xyXG52YXIgVnBuUnBjVGVzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNUZXN0JyBjbGFzczogR2VuZXJpYyBwYXJhbWV0ZXIgdG8gY29udGFpbiB1MzIsIHU2NCwgYXNjaWlfc3RyaW5nIGFuZCB1bmljb2RlIHN0cmluZyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjVGVzdChpbml0KSB7XHJcbiAgICAgICAgLyoqIEEgMzItYml0IGludGVnZXIgZmllbGQgKi9cclxuICAgICAgICB0aGlzLkludFZhbHVlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEEgNjQtYml0IGludGVnZXIgZmllbGQgKi9cclxuICAgICAgICB0aGlzLkludDY0VmFsdWVfdTY0ID0gMDtcclxuICAgICAgICAvKiogQW4gQXNjaWkgc3RyaW5nIGZpZWxkICovXHJcbiAgICAgICAgdGhpcy5TdHJWYWx1ZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBBbiBVVEYtOCBzdHJpbmcgZmllbGQgKi9cclxuICAgICAgICB0aGlzLlVuaVN0clZhbHVlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNUZXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1Rlc3QgPSBWcG5ScGNUZXN0O1xyXG4vKiogTG9jYWwgQnJpZGdlIGxpc3QgaXRlbSAqL1xyXG52YXIgVnBuUnBjTG9jYWxCcmlkZ2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTG9jYWxCcmlkZ2UnIGNsYXNzOiBMb2NhbCBCcmlkZ2UgbGlzdCBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMb2NhbEJyaWRnZShpbml0KSB7XHJcbiAgICAgICAgLyoqIFBoeXNpY2FsIEV0aGVybmV0IGRldmljZSBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXZpY2VOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lTEJfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT25saW5lIGZsYWcgKi9cclxuICAgICAgICB0aGlzLk9ubGluZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFJ1bm5pbmcgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuQWN0aXZlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSBhcmUgdXNpbmcgYSB0YXAgZGV2aWNlIHJhdGhlciB0aGFuIGEgbmV0d29yayBhZGFwdGVyIGZvciB0aGUgYnJpZGdlIGRlc3RpbmF0aW9uIChvbmx5IHN1cHBvcnRlZCBmb3IgTGludXggdmVyc2lvbnMpLiAqL1xyXG4gICAgICAgIHRoaXMuVGFwTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMb2NhbEJyaWRnZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMb2NhbEJyaWRnZSA9IFZwblJwY0xvY2FsQnJpZGdlO1xyXG4vKiogQ3JlYXRlLCBjb25maWd1cmUsIGFuZCBnZXQgdGhlIGdyb3VwICovXHJcbnZhciBWcG5ScGNTZXRHcm91cCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNTZXRHcm91cCcgY2xhc3M6IENyZWF0ZSwgY29uZmlndXJlLCBhbmQgZ2V0IHRoZSBncm91cCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2V0R3JvdXAoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgZ3JvdXAgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCByZWFsIG5hbWUgKGZ1bGwgbmFtZSkgb2YgdGhlIGdyb3VwLCBhbGxvdyB1c2luZyBhbnkgVW5pY29kZSBjaGFyYWN0ZXJzICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCwgc3BlY2lmeSBhIGRlc2NyaXB0aW9uIG9mIHRoZSBncm91cCAqL1xyXG4gICAgICAgIHRoaXMuTm90ZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0byB1c2Ugc2VjdXJpdHkgcG9saWN5ICovXHJcbiAgICAgICAgdGhpcy5Vc2VQb2xpY3lfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEFsbG93IEFjY2Vzcy4gVGhlIHVzZXJzLCB3aGljaCB0aGlzIHBvbGljeSB2YWx1ZSBpcyB0cnVlLCBoYXZlIHBlcm1pc3Npb24gdG8gbWFrZSBWUE4gY29ubmVjdGlvbiB0byBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6QWNjZXNzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY0KS4gQWxsIElQdjQgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1BGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERpc2FsbG93IERIQ1AgU2VydmVyIE9wZXJhdGlvbiAoSVB2NCkuIENvbXB1dGVycyBjb25uZWN0ZWQgdG8gc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBub3QgYmUgYWxsb3dlZCB0byBiZWNvbWUgYSBESENQIHNlcnZlciBhbmQgZGlzdHJpYnV0ZSBJUHY0IGFkZHJlc3NlcyB0byBESENQIGNsaWVudHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQTm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEVuZm9yY2UgREhDUCBBbGxvY2F0ZWQgSVAgQWRkcmVzc2VzIChJUHY0KS4gQ29tcHV0ZXJzIGluIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgb25seSBiZSBhYmxlIHRvIHVzZSBJUHY0IGFkZHJlc3NlcyBhbGxvY2F0ZWQgYnkgYSBESENQIHNlcnZlciBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHNpZGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRm9yY2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgQnJpZGdlIE9wZXJhdGlvbi4gQnJpZGdlLW1vZGUgY29ubmVjdGlvbnMgYXJlIGRlbmllZCBmb3IgdXNlciBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZy4gRXZlbiBpbiBjYXNlcyB3aGVuIHRoZSBFdGhlcm5ldCBCcmlkZ2UgaXMgY29uZmlndXJlZCBpbiB0aGUgY2xpZW50IHNpZGUsIGNvbW11bmljYXRpb24gd2lsbCBub3QgYmUgcG9zc2libGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0JyaWRnZV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBSb3V0aW5nIE9wZXJhdGlvbiAoSVB2NCkuIElQdjQgcm91dGluZyB3aWxsIGJlIGRlbmllZCBmb3Igc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcuIEV2ZW4gaW4gdGhlIGNhc2Ugd2hlcmUgdGhlIElQIHJvdXRlciBpcyBvcGVyYXRpbmcgb24gdGhlIHVzZXIgY2xpZW50IHNpZGUsIGNvbW11bmljYXRpb24gd2lsbCBub3QgYmUgcG9zc2libGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1JvdXRpbmdfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgTUFDIEFkZHJlc3NlcyBEdXBsaWNhdGlvbi4gVGhlIHVzZSBvZiBkdXBsaWNhdGluZyBNQUMgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrTWFjX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IElQIEFkZHJlc3MgRHVwbGljYXRpb24gKElQdjQpLiBUaGUgdXNlIG9mIGR1cGxpY2F0aW5nIElQdjQgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrSVBfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgTm9uLUFSUCAvIE5vbi1ESENQIC8gTm9uLUlDTVB2NiBicm9hZGNhc3RzLiBUaGUgc2VuZGluZyBvciByZWNlaXZpbmcgb2YgYnJvYWRjYXN0IHBhY2tldHMgdGhhdCBhcmUgbm90IEFSUCBwcm90b2NvbCwgREhDUCBwcm90b2NvbCwgbm9yIElDTVB2NiBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHdpbGwgbm90IGJlIGFsbG93ZWQgZm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkFycERoY3BPbmx5X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBQcml2YWN5IEZpbHRlciBNb2RlLiBBbGwgZGlyZWN0IGNvbW11bmljYXRpb24gYmV0d2VlbiBzZXNzaW9ucyB3aXRoIHRoZSBwcml2YWN5IGZpbHRlciBtb2RlIHBvbGljeSBzZXR0aW5nIHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpQcml2YWN5RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE9wZXJhdGlvbiBhcyBUQ1AvSVAgU2VydmVyIChJUHY0KS4gQ29tcHV0ZXJzIG9mIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBjYW4ndCBsaXN0ZW4gYW5kIGFjY2VwdCBUQ1AvSVAgY29ubmVjdGlvbnMgaW4gSVB2NC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBVbmxpbWl0ZWQgTnVtYmVyIG9mIEJyb2FkY2FzdHMuIElmIGEgY29tcHV0ZXIgb2YgYSBzZXNzaW9uIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBzZW5kcyBicm9hZGNhc3QgcGFja2V0cyBvZiBhIG51bWJlciB1bnVzdWFsbHkgbGFyZ2VyIHRoYW4gd2hhdCB3b3VsZCBiZSBjb25zaWRlcmVkIG5vcm1hbCBvbiB0aGUgdmlydHVhbCBuZXR3b3JrLCB0aGVyZSB3aWxsIGJlIG5vIGF1dG9tYXRpYyBsaW1pdGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vQnJvYWRjYXN0TGltaXRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogQWxsb3cgTW9uaXRvcmluZyBNb2RlLiBVc2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBiZSBncmFudGVkIHRvIGNvbm5lY3QgdG8gdGhlIFZpcnR1YWwgSHViIGluIE1vbml0b3JpbmcgTW9kZS4gU2Vzc2lvbnMgaW4gTW9uaXRvcmluZyBNb2RlIGFyZSBhYmxlIHRvIG1vbml0b3IgKHRhcCkgYWxsIHBhY2tldHMgZmxvd2luZyB0aHJvdWdoIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1vbml0b3JQb3J0X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBUQ1AgQ29ubmVjdGlvbnMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc2V0cyB0aGUgbWF4aW11bSBudW1iZXIgb2YgcGh5c2ljYWwgVENQIGNvbm5lY3Rpb25zIGNvbnNpc3RzIGluIGEgcGh5c2ljYWwgVlBOIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhDb25uZWN0aW9uX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVGltZS1vdXQgUGVyaW9kLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNldHMsIGluIHNlY29uZHMsIHRoZSB0aW1lLW91dCBwZXJpb2QgdG8gd2FpdCBiZWZvcmUgZGlzY29ubmVjdGluZyBhIHNlc3Npb24gd2hlbiBjb21tdW5pY2F0aW9uIHRyb3VibGUgb2NjdXJzIGJldHdlZW4gdGhlIFZQTiBDbGllbnQgLyBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6VGltZU91dF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE1BQyBBZGRyZXNzZXMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSBudW1iZXIgb2YgTUFDIGFkZHJlc3NlcyBwZXIgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heE1hY191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NCkuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NCBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVXBsb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIGlud2FyZHMgZGlyZWN0aW9uIGZyb20gb3V0c2lkZSB0byBpbnNpZGUgdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4VXBsb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRG93bmxvYWQgQmFuZHdpZHRoLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgdHJhZmZpYyBiYW5kd2lkdGggdGhhdCBpcyBpbiB0aGUgb3V0d2FyZHMgZGlyZWN0aW9uIGZyb20gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1YiB0byBvdXRzaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heERvd25sb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBDaGFuZ2luZyBQYXNzd29yZC4gVGhlIHVzZXJzIHdoaWNoIHVzZSBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgYXJlIG5vdCBhbGxvd2VkIHRvIGNoYW5nZSB0aGVpciBvd24gcGFzc3dvcmQgZnJvbSB0aGUgVlBOIENsaWVudCBNYW5hZ2VyIG9yIHNpbWlsYXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaXhQYXNzd29yZF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgTXVsdGlwbGUgTG9naW5zLiBVc2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgYXJlIHVuYWJsZSB0byBoYXZlIG1vcmUgdGhhbiB0aGlzIG51bWJlciBvZiBjb25jdXJyZW50IGxvZ2lucy4gQnJpZGdlIE1vZGUgc2Vzc2lvbnMgYXJlIG5vdCBzdWJqZWN0cyB0byB0aGlzIHBvbGljeS4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok11bHRpTG9naW5zX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBWb0lQIC8gUW9TIEZ1bmN0aW9uLiBVc2VycyB3aXRoIHRoaXMgc2VjdXJpdHkgcG9saWN5IGFyZSB1bmFibGUgdG8gdXNlIFZvSVAgLyBRb1MgZnVuY3Rpb25zIGluIFZQTiBjb25uZWN0aW9uIHNlc3Npb25zLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Rb1NfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBSUyAvIFJBIFBhY2tldHMgKElQdjYpLiBBbGwgSUNNUHY2IHBhY2tldHMgd2hpY2ggdGhlIG1lc3NhZ2UtdHlwZSBpcyAxMzMgKFJvdXRlciBTb2xpY2l0YXRpb24pIG9yIDEzNCAoUm91dGVyIEFkdmVydGlzZW1lbnQpIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gQXMgYSByZXN1bHQsIGFuIElQdjYgY2xpZW50IHdpbGwgYmUgdW5hYmxlIHRvIHVzZSBJUHY2IGFkZHJlc3MgcHJlZml4IGF1dG8gZGV0ZWN0aW9uIGFuZCBJUHY2IGRlZmF1bHQgZ2F0ZXdheSBhdXRvIGRldGVjdGlvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlJTYW5kUkFGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBSQSBQYWNrZXRzIChJUHY2KS4gQWxsIElDTVB2NiBwYWNrZXRzIHdoaWNoIHRoZSBtZXNzYWdlLXR5cGUgaXMgMTM0IChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBBcyBhIHJlc3VsdCwgYSBtYWxpY2lvdXMgdXNlcnMgd2lsbCBiZSB1bmFibGUgdG8gc3ByZWFkIGlsbGVnYWwgSVB2NiBwcmVmaXggb3IgZGVmYXVsdCBnYXRld2F5IGFkdmVydGlzZW1lbnRzIG9uIHRoZSBuZXR3b3JrLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UkFGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBESENQIFBhY2tldHMgKElQdjYpLiBBbGwgSVB2NiBESENQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjYpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NiBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2Tm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgUm91dGluZyBPcGVyYXRpb24gKElQdjYpLiBJUHY2IHJvdXRpbmcgd2lsbCBiZSBkZW5pZWQgZm9yIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nLiBFdmVuIGluIHRoZSBjYXNlIHdoZXJlIHRoZSBJUCByb3V0ZXIgaXMgb3BlcmF0aW5nIG9uIHRoZSB1c2VyIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Sb3V0aW5nVjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgSVAgQWRkcmVzcyBEdXBsaWNhdGlvbiAoSVB2NikuIFRoZSB1c2Ugb2YgZHVwbGljYXRpbmcgSVB2NiBhZGRyZXNzZXMgdGhhdCBhcmUgaW4gdXNlIGJ5IGNvbXB1dGVycyBvZiBkaWZmZXJlbnQgc2Vzc2lvbnMgY2Fubm90IGJlIHVzZWQgYnkgc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Q2hlY2tJUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE9wZXJhdGlvbiBhcyBUQ1AvSVAgU2VydmVyIChJUHY2KS4gQ29tcHV0ZXJzIG9mIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBjYW4ndCBsaXN0ZW4gYW5kIGFjY2VwdCBUQ1AvSVAgY29ubmVjdGlvbnMgaW4gSVB2Ni4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2VydmVyVjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NikuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NiBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQdjZfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBQYXNzd29yZCBTYXZlIGluIFZQTiBDbGllbnQuIEZvciB1c2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHdoZW4gdGhlIHVzZXIgaXMgdXNpbmcgKnN0YW5kYXJkKiBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiwgdGhlIHVzZXIgd2lsbCBiZSB1bmFibGUgdG8gc2F2ZSB0aGUgcGFzc3dvcmQgaW4gVlBOIENsaWVudC4gVGhlIHVzZXIgd2lsbCBiZSByZXF1aXJlZCB0byBpbnB1dCBwYXNzd29yZHMgZm9yIGV2ZXJ5IHRpbWUgdG8gY29ubmVjdCBhIFZQTi4gVGhpcyB3aWxsIGltcHJvdmUgdGhlIHNlY3VyaXR5LiBJZiB0aGlzIHBvbGljeSBpcyBlbmFibGVkLCBWUE4gQ2xpZW50IFZlcnNpb24gMi4wIHdpbGwgYmUgZGVuaWVkIHRvIGFjY2Vzcy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2F2ZVBhc3N3b3JkX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBWUE4gQ2xpZW50IEF1dG9tYXRpYyBEaXNjb25uZWN0LiBGb3IgdXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCBhIHVzZXIncyBWUE4gc2Vzc2lvbiB3aWxsIGJlIGRpc2Nvbm5lY3RlZCBhdXRvbWF0aWNhbGx5IGFmdGVyIHRoZSBzcGVjaWZpYyBwZXJpb2Qgd2lsbCBlbGFwc2UuIEluIHRoaXMgY2FzZSBubyBhdXRvbWF0aWMgcmUtY29ubmVjdGlvbiB3aWxsIGJlIHBlcmZvcm1lZC4gVGhpcyBjYW4gcHJldmVudCBhIGxvdCBvZiBpbmFjdGl2ZSBWUE4gU2Vzc2lvbnMuIElmIHRoaXMgcG9saWN5IGlzIGVuYWJsZWQsIFZQTiBDbGllbnQgVmVyc2lvbiAyLjAgd2lsbCBiZSBkZW5pZWQgdG8gYWNjZXNzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6QXV0b0Rpc2Nvbm5lY3RfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIElQdjQgUGFja2V0cy4gQWxsIElQdjQgYW5kIEFSUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlcklQdjRfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgSVB2NiBQYWNrZXRzLiBBbGwgSVB2NiBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlcklQdjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgTm9uLUlQIFBhY2tldHMuIEFsbCBub24tSVAgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuIFwiTm9uLUlQIHBhY2tldFwiIG1lYW4gYSBwYWNrZXQgd2hpY2ggaXMgbm90IElQdjQsIEFSUCBub3IgSVB2Ni4gQW55IHRhZ2dlZC1WTEFOIHBhY2tldHMgdmlhIHRoZSBWaXJ0dWFsIEh1YiB3aWxsIGJlIHJlZ2FyZGVkIGFzIG5vbi1JUCBwYWNrZXRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVyTm9uSVBfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE5vIERlZmF1bHQtUm91dGVyIG9uIElQdjYgUkEuIEluIGFsbCBWUE4gU2Vzc2lvbnMgZGVmaW5lcyB0aGlzIHBvbGljeSwgYW55IElQdjYgUkEgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBwYWNrZXQgd2l0aCBub24temVybyB2YWx1ZSBpbiB0aGUgcm91dGVyLWxpZmV0aW1lIHdpbGwgc2V0IHRvIHplcm8tdmFsdWUuIFRoaXMgaXMgZWZmZWN0aXZlIHRvIGF2b2lkIHRoZSBob3JyaWJsZSBiZWhhdmlvciBmcm9tIHRoZSBJUHY2IHJvdXRpbmcgY29uZnVzaW9uIHdoaWNoIGlzIGNhdXNlZCBieSB0aGUgVlBOIGNsaWVudCdzIGF0dGVtcHRzIHRvIHVzZSB0aGUgcmVtb3RlLXNpZGUgSVB2NiByb3V0ZXIgYXMgaXRzIGxvY2FsIElQdjYgcm91dGVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9JUHY2RGVmYXVsdFJvdXRlckluUkFfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE5vIERlZmF1bHQtUm91dGVyIG9uIElQdjYgUkEgKHBoeXNpY2FsIElQdjYpLiBJbiBhbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3kgKG9ubHkgd2hlbiB0aGUgcGh5c2ljYWwgY29tbXVuaWNhdGlvbiBwcm90b2NvbCBiZXR3ZWVuIFZQTiBDbGllbnQgLyBWUE4gQnJpZGdlIGFuZCBWUE4gU2VydmVyIGlzIElQdjYpLCBhbnkgSVB2NiBSQSAoUm91dGVyIEFkdmVydGlzZW1lbnQpIHBhY2tldCB3aXRoIG5vbi16ZXJvIHZhbHVlIGluIHRoZSByb3V0ZXItbGlmZXRpbWUgd2lsbCBzZXQgdG8gemVyby12YWx1ZS4gVGhpcyBpcyBlZmZlY3RpdmUgdG8gYXZvaWQgdGhlIGhvcnJpYmxlIGJlaGF2aW9yIGZyb20gdGhlIElQdjYgcm91dGluZyBjb25mdXNpb24gd2hpY2ggaXMgY2F1c2VkIGJ5IHRoZSBWUE4gY2xpZW50J3MgYXR0ZW1wdHMgdG8gdXNlIHRoZSByZW1vdGUtc2lkZSBJUHY2IHJvdXRlciBhcyBpdHMgbG9jYWwgSVB2NiByb3V0ZXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0lQdjZEZWZhdWx0Um91dGVySW5SQVdoZW5JUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBWTEFOIElEIChJRUVFODAyLjFRKS4gWW91IGNhbiBzcGVjaWZ5IHRoZSBWTEFOIElEIG9uIHRoZSBzZWN1cml0eSBwb2xpY3kuIEFsbCBWUE4gU2Vzc2lvbnMgZGVmaW5lcyB0aGlzIHBvbGljeSwgYWxsIEV0aGVybmV0IHBhY2tldHMgdG93YXJkIHRoZSBWaXJ0dWFsIEh1YiBmcm9tIHRoZSB1c2VyIHdpbGwgYmUgaW5zZXJ0ZWQgYSBWTEFOIHRhZyAoSUVFRSA4MDIuMVEpIHdpdGggdGhlIFZMQU4gSUQuIFRoZSB1c2VyIGNhbiBhbHNvIHJlY2VpdmUgb25seSBwYWNrZXRzIHdpdGggYSBWTEFOIHRhZyB3aGljaCBoYXMgdGhlIHNhbWUgVkxBTiBJRC4gKFJlY2VpdmluZyBwcm9jZXNzIHJlbW92ZXMgdGhlIFZMQU4gdGFnIGF1dG9tYXRpY2FsbHkuKSBBbnkgRXRoZXJuZXQgcGFja2V0cyB3aXRoIGFueSBvdGhlciBWTEFOIElEcyBvciBub24tVkxBTiBwYWNrZXRzIHdpbGwgbm90IGJlIHJlY2VpdmVkLiBBbGwgVlBOIFNlc3Npb25zIHdpdGhvdXQgdGhpcyBwb2xpY3kgZGVmaW5pdGlvbiBjYW4gc2VuZCAvIHJlY2VpdmUgYW55IGtpbmRzIG9mIEV0aGVybmV0IHBhY2tldHMgcmVnYXJkbGVzcyBvZiBWTEFOIHRhZ3MsIGFuZCBWTEFOIHRhZ3MgYXJlIG5vdCBpbnNlcnRlZCBvciByZW1vdmVkIGF1dG9tYXRpY2FsbHkuIEFueSB0YWdnZWQtVkxBTiBwYWNrZXRzIHZpYSB0aGUgVmlydHVhbCBIdWIgd2lsbCBiZSByZWdhcmRlZCBhcyBub24tSVAgcGFja2V0cy4gVGhlcmVmb3JlLCB0YWdnZWQtVkxBTiBwYWNrZXRzIGFyZSBub3Qgc3ViamVjdHMgZm9yIElQdjQgLyBJUHY2IHNlY3VyaXR5IHBvbGljaWVzLCBhY2Nlc3MgbGlzdHMgbm9yIG90aGVyIElQdjQgLyBJUHY2IHNwZWNpZmljIGRlZXAgcHJvY2Vzc2luZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlZMYW5JZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFdoZXRoZXIgdmVyc2lvbiAzLjAgKG11c3QgYmUgdHJ1ZSkgKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlZlcjNfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjU2V0R3JvdXA7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2V0R3JvdXAgPSBWcG5ScGNTZXRHcm91cDtcclxuLyoqIEh1YiB0eXBlcyAqL1xyXG52YXIgVnBuUnBjSHViVHlwZTtcclxuKGZ1bmN0aW9uIChWcG5ScGNIdWJUeXBlKSB7XHJcbiAgICAvKiogU3RhbmQtYWxvbmUgSFVCICovXHJcbiAgICBWcG5ScGNIdWJUeXBlW1ZwblJwY0h1YlR5cGVbXCJTdGFuZGFsb25lXCJdID0gMF0gPSBcIlN0YW5kYWxvbmVcIjtcclxuICAgIC8qKiBTdGF0aWMgSFVCICovXHJcbiAgICBWcG5ScGNIdWJUeXBlW1ZwblJwY0h1YlR5cGVbXCJGYXJtU3RhdGljXCJdID0gMV0gPSBcIkZhcm1TdGF0aWNcIjtcclxuICAgIC8qKiBEeW5hbWljIEhVQiAqL1xyXG4gICAgVnBuUnBjSHViVHlwZVtWcG5ScGNIdWJUeXBlW1wiRmFybUR5bmFtaWNcIl0gPSAyXSA9IFwiRmFybUR5bmFtaWNcIjtcclxufSkoVnBuUnBjSHViVHlwZSA9IGV4cG9ydHMuVnBuUnBjSHViVHlwZSB8fCAoZXhwb3J0cy5WcG5ScGNIdWJUeXBlID0ge30pKTtcclxuLyoqIENyZWF0ZSBhIEhVQiAqL1xyXG52YXIgVnBuUnBjQ3JlYXRlSHViID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0NyZWF0ZUh1YicgY2xhc3M6IENyZWF0ZSBhIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQ3JlYXRlSHViKGluaXQpIHtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgbmFtZSBvZiB0aGUgVmlydHVhbCBIdWIgdG8gY3JlYXRlIC8gdXBkYXRlLiAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IGFuIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQgd2hlbiB0aGUgYWRtaW5pc3RyYXRvciBwYXNzd29yZCBpcyBnb2luZyB0byBiZSBzZXQgZm9yIHRoZSBWaXJ0dWFsIEh1Yi4gT24gdGhlIHVwZGF0ZSwgbGVhdmUgaXQgdG8gZW1wdHkgc3RyaW5nIGlmIHlvdSBkb24ndCB3YW50IHRvIGNoYW5nZSB0aGUgcGFzc3dvcmQuICovXHJcbiAgICAgICAgdGhpcy5BZG1pblBhc3N3b3JkUGxhaW5UZXh0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiBWUE4gc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk1heFNlc3Npb25fdTMyID0gMDtcclxuICAgICAgICAvKiogTm8gRW51bSBmbGFnLiBCeSBlbmFibGluZyB0aGlzIG9wdGlvbiwgdGhlIFZQTiBDbGllbnQgdXNlciB3aWxsIGJlIHVuYWJsZSB0byBlbnVtZXJhdGUgdGhpcyBWaXJ0dWFsIEh1YiBldmVuIGlmIHRoZXkgc2VuZCBhIFZpcnR1YWwgSHViIGVudW1lcmF0aW9uIHJlcXVlc3QgdG8gdGhlIFZQTiBTZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5Ob0VudW1fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHRoZSBWaXJ0dWFsIEh1YiAoVmFsaWQgb25seSBmb3IgQ2x1c3RlcmVkIFZQTiBTZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuSHViVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjQ3JlYXRlSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0NyZWF0ZUh1YiA9IFZwblJwY0NyZWF0ZUh1YjtcclxudmFyIFZwblJwY0NsaWVudEF1dGhUeXBlO1xyXG4oZnVuY3Rpb24gKFZwblJwY0NsaWVudEF1dGhUeXBlKSB7XHJcbiAgICAvKiogQW5vbnltb3VzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNDbGllbnRBdXRoVHlwZVtWcG5ScGNDbGllbnRBdXRoVHlwZVtcIkFub255bW91c1wiXSA9IDBdID0gXCJBbm9ueW1vdXNcIjtcclxuICAgIC8qKiBTSEEtMCBoYXNoZWQgcGFzc3dvcmQgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY0NsaWVudEF1dGhUeXBlW1ZwblJwY0NsaWVudEF1dGhUeXBlW1wiU0hBMF9IYXNoZWRfUGFzc3dvcmRcIl0gPSAxXSA9IFwiU0hBMF9IYXNoZWRfUGFzc3dvcmRcIjtcclxuICAgIC8qKiBQbGFpbiBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiAqL1xyXG4gICAgVnBuUnBjQ2xpZW50QXV0aFR5cGVbVnBuUnBjQ2xpZW50QXV0aFR5cGVbXCJQbGFpblBhc3N3b3JkXCJdID0gMl0gPSBcIlBsYWluUGFzc3dvcmRcIjtcclxuICAgIC8qKiBDZXJ0aWZpY2F0ZSBhdXRoZW50aWNhdGlvbiAqL1xyXG4gICAgVnBuUnBjQ2xpZW50QXV0aFR5cGVbVnBuUnBjQ2xpZW50QXV0aFR5cGVbXCJDZXJ0XCJdID0gM10gPSBcIkNlcnRcIjtcclxufSkoVnBuUnBjQ2xpZW50QXV0aFR5cGUgPSBleHBvcnRzLlZwblJwY0NsaWVudEF1dGhUeXBlIHx8IChleHBvcnRzLlZwblJwY0NsaWVudEF1dGhUeXBlID0ge30pKTtcclxuLyoqIENyZWF0ZSBhbmQgc2V0IG9mIGxpbmsgKi9cclxudmFyIFZwblJwY0NyZWF0ZUxpbmsgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQ3JlYXRlTGluaycgY2xhc3M6IENyZWF0ZSBhbmQgc2V0IG9mIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0NyZWF0ZUxpbmsoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9FeF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPbmxpbmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuT25saW5lX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIHZhbGlkYXRpb24gZm9yIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNoZWNrU2VydmVyQ2VydF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBib2R5IG9mIHNlcnZlciBYLjUwOSBjZXJ0aWZpY2F0ZSB0byBjb21wYXJlLiBWYWxpZCBvbmx5IGlmIHRoZSBDaGVja1NlcnZlckNlcnRfYm9vbCBmbGFnIGlzIHRydWUuICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJDZXJ0X2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBTcGVjaWZ5IHRoZSBuYW1lIG9mIHRoZSBDYXNjYWRlIENvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkFjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogU3BlY2lmeSB0aGUgaG9zdG5hbWUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gYWxzbyBzcGVjaWZ5IGJ5IElQIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFNwZWNpZnkgdGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSB0eXBlIG9mIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5VHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSBob3N0bmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBwcm94eSBzZXJ2ZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5UG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSB1c2VybmFtZSB0byBjb25uZWN0IHRvIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5VXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBUaGUgcGFzc3dvcmQgdG8gY29ubmVjdCB0byB0aGUgcHJveHkgc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5Qcm94eVBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogVGhlIFZpcnR1YWwgSHViIG9uIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogTnVtYmVyIG9mIFRDUCBDb25uZWN0aW9ucyB0byBVc2UgaW4gVlBOIENvbW11bmljYXRpb24gKi9cclxuICAgICAgICB0aGlzLk1heENvbm5lY3Rpb25fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBUaGUgZmxhZyB0byBlbmFibGUgdGhlIGVuY3J5cHRpb24gb24gdGhlIGNvbW11bmljYXRpb24gKi9cclxuICAgICAgICB0aGlzLlVzZUVuY3J5cHRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IEVuYWJsZSAvIERpc2FibGUgRGF0YSBDb21wcmVzc2lvbiB3aGVuIENvbW11bmljYXRpbmcgYnkgQ2FzY2FkZSBDb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VDb21wcmVzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogU3BlY2lmeSB0cnVlIHdoZW4gZW5hYmxpbmcgaGFsZiBkdXBsZXggbW9kZS4gV2hlbiB1c2luZyB0d28gb3IgbW9yZSBUQ1AgY29ubmVjdGlvbnMgZm9yIFZQTiBjb21tdW5pY2F0aW9uLCBpdCBpcyBwb3NzaWJsZSB0byB1c2UgSGFsZiBEdXBsZXggTW9kZS4gQnkgZW5hYmxpbmcgaGFsZiBkdXBsZXggbW9kZSBpdCBpcyBwb3NzaWJsZSB0byBhdXRvbWF0aWNhbGx5IGZpeCBkYXRhIHRyYW5zbWlzc2lvbiBkaXJlY3Rpb24gYXMgaGFsZiBhbmQgaGFsZiBmb3IgZWFjaCBUQ1AgY29ubmVjdGlvbi4gSW4gdGhlIGNhc2Ugd2hlcmUgYSBWUE4gdXNpbmcgOCBUQ1AgY29ubmVjdGlvbnMgaXMgZXN0YWJsaXNoZWQsIGZvciBleGFtcGxlLCB3aGVuIGhhbGYtZHVwbGV4IGlzIGVuYWJsZWQsIGNvbW11bmljYXRpb24gY2FuIGJlIGZpeGVzIHNvIHRoYXQgNCBUQ1AgY29ubmVjdGlvbnMgYXJlIGRlZGljYXRlZCB0byB0aGUgdXBsb2FkIGRpcmVjdGlvbiBhbmQgdGhlIG90aGVyIDQgY29ubmVjdGlvbnMgYXJlIGRlZGljYXRlZCB0byB0aGUgZG93bmxvYWQgZGlyZWN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuSGFsZkNvbm5lY3Rpb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IENvbm5lY3Rpb24gYXR0ZW1wdCBpbnRlcnZhbCB3aGVuIGFkZGl0aW9uYWwgY29ubmVjdGlvbiB3aWxsIGJlIGVzdGFibGlzaGVkICovXHJcbiAgICAgICAgdGhpcy5BZGRpdGlvbmFsQ29ubmVjdGlvbkludGVydmFsX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogQ29ubmVjdGlvbiBMaWZlIG9mIEVhY2ggVENQIENvbm5lY3Rpb24gKDAgZm9yIG5vIGtlZXAtYWxpdmUpICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0aW9uRGlzY29ubmVjdFNwYW5fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBEaXNhYmxlIFFvUyBDb250cm9sIEZ1bmN0aW9uIGlmIHRoZSB2YWx1ZSBpcyB0cnVlICovXHJcbiAgICAgICAgdGhpcy5EaXNhYmxlUW9TX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBEbyBub3QgdXNlIFRMUyAxLnggb2YgdGhlIHZhbHVlIGlzIHRydWUgKi9cclxuICAgICAgICB0aGlzLk5vVGxzMV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogRG8gbm90IHVzZSBVRFAgYWNjZWxlcmF0aW9uIG1vZGUgaWYgdGhlIHZhbHVlIGlzIHRydWUgKi9cclxuICAgICAgICB0aGlzLk5vVWRwQWNjZWxlcmF0aW9uX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQXV0aGVudGljYXRpb24gdHlwZSAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Vc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTSEEtMCBIYXNoZWQgcGFzc3dvcmQuIFZhbGlkIG9ubHkgaWYgQ2xpZW50QXV0aF9BdXRoVHlwZV91MzIgPT0gU0hBMF9IYXNoZWRfUGFzc3dvcmQgKDEpLiBUaGUgU0hBLTAgaGFzaGVkIHBhc3N3b3JkIG11c3QgYmUgY2FsdWNsYXRlZCBieSB0aGUgU0hBMChVcHBlckNhc2UodXNlcm5hbWVfYXNjaWlfc3RyaW5nKSArIHBhc3N3b3JkX2FzY2lpX3N0cmluZykuICovXHJcbiAgICAgICAgdGhpcy5IYXNoZWRQYXNzd29yZF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFBsYWludGV4dCBQYXNzd29yZC4gVmFsaWQgb25seSBpZiBDbGllbnRBdXRoX0F1dGhUeXBlX3UzMiA9PSBQbGFpblBhc3N3b3JkICgyKS4gKi9cclxuICAgICAgICB0aGlzLlBsYWluUGFzc3dvcmRfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IGNlcnRpZmljYXRlLiBWYWxpZCBvbmx5IGlmIENsaWVudEF1dGhfQXV0aFR5cGVfdTMyID09IENlcnQgKDMpLiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50WF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENsaWVudCBwcml2YXRlIGtleSBvZiB0aGUgY2VydGlmaWNhdGUuIFZhbGlkIG9ubHkgaWYgQ2xpZW50QXV0aF9BdXRoVHlwZV91MzIgPT0gQ2VydCAoMykuICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRLX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY0KS4gQWxsIElQdjQgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1BGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERpc2FsbG93IERIQ1AgU2VydmVyIE9wZXJhdGlvbiAoSVB2NCkuIENvbXB1dGVycyBjb25uZWN0ZWQgdG8gc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBub3QgYmUgYWxsb3dlZCB0byBiZWNvbWUgYSBESENQIHNlcnZlciBhbmQgZGlzdHJpYnV0ZSBJUHY0IGFkZHJlc3NlcyB0byBESENQIGNsaWVudHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQTm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEVuZm9yY2UgREhDUCBBbGxvY2F0ZWQgSVAgQWRkcmVzc2VzIChJUHY0KS4gQ29tcHV0ZXJzIGluIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgb25seSBiZSBhYmxlIHRvIHVzZSBJUHY0IGFkZHJlc3NlcyBhbGxvY2F0ZWQgYnkgYSBESENQIHNlcnZlciBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHNpZGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRm9yY2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFByb2hpYml0IHRoZSBkdXBsaWNhdGUgTUFDIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja01hY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJvaGliaXQgYSBkdXBsaWNhdGUgSVAgYWRkcmVzcyAoSVB2NCkgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja0lQX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE5vbi1BUlAgLyBOb24tREhDUCAvIE5vbi1JQ01QdjYgYnJvYWRjYXN0cy4gVGhlIHNlbmRpbmcgb3IgcmVjZWl2aW5nIG9mIGJyb2FkY2FzdCBwYWNrZXRzIHRoYXQgYXJlIG5vdCBBUlAgcHJvdG9jb2wsIERIQ1AgcHJvdG9jb2wsIG5vciBJQ01QdjYgb24gdGhlIHZpcnR1YWwgbmV0d29yayB3aWxsIG5vdCBiZSBhbGxvd2VkIGZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpBcnBEaGNwT25seV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJpdmFjeSBGaWx0ZXIgTW9kZS4gQWxsIGRpcmVjdCBjb21tdW5pY2F0aW9uIGJldHdlZW4gc2Vzc2lvbnMgd2l0aCB0aGUgcHJpdmFjeSBmaWx0ZXIgbW9kZSBwb2xpY3kgc2V0dGluZyB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UHJpdmFjeUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NCkuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVW5saW1pdGVkIE51bWJlciBvZiBCcm9hZGNhc3RzLiBJZiBhIGNvbXB1dGVyIG9mIGEgc2Vzc2lvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgc2VuZHMgYnJvYWRjYXN0IHBhY2tldHMgb2YgYSBudW1iZXIgdW51c3VhbGx5IGxhcmdlciB0aGFuIHdoYXQgd291bGQgYmUgY29uc2lkZXJlZCBub3JtYWwgb24gdGhlIHZpcnR1YWwgbmV0d29yaywgdGhlcmUgd2lsbCBiZSBubyBhdXRvbWF0aWMgbGltaXRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0Jyb2FkY2FzdExpbWl0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE1BQyBBZGRyZXNzZXMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSBudW1iZXIgb2YgTUFDIGFkZHJlc3NlcyBwZXIgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heE1hY191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NCkuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NCBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVXBsb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIGlud2FyZHMgZGlyZWN0aW9uIGZyb20gb3V0c2lkZSB0byBpbnNpZGUgdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4VXBsb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRG93bmxvYWQgQmFuZHdpZHRoLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgdHJhZmZpYyBiYW5kd2lkdGggdGhhdCBpcyBpbiB0aGUgb3V0d2FyZHMgZGlyZWN0aW9uIGZyb20gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1YiB0byBvdXRzaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heERvd25sb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIFJTIC8gUkEgUGFja2V0cyAoSVB2NikuIEFsbCBJQ01QdjYgcGFja2V0cyB3aGljaCB0aGUgbWVzc2FnZS10eXBlIGlzIDEzMyAoUm91dGVyIFNvbGljaXRhdGlvbikgb3IgMTM0IChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBBcyBhIHJlc3VsdCwgYW4gSVB2NiBjbGllbnQgd2lsbCBiZSB1bmFibGUgdG8gdXNlIElQdjYgYWRkcmVzcyBwcmVmaXggYXV0byBkZXRlY3Rpb24gYW5kIElQdjYgZGVmYXVsdCBnYXRld2F5IGF1dG8gZGV0ZWN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UlNhbmRSQUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIHRoZSByb3V0ZXIgYWR2ZXJ0aXNlbWVudCBwYWNrZXQgKElQdjYpICovXHJcbiAgICAgICAgdGhpcy5TZWNQb2xfUkFGaWx0ZXJfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBESENQIFBhY2tldHMgKElQdjYpLiBBbGwgSVB2NiBESENQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjYpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NiBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2Tm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFByb2hpYml0IHRoZSBkdXBsaWNhdGUgSVAgYWRkcmVzcyAoSVB2NikgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja0lQdjZfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgT3BlcmF0aW9uIGFzIFRDUC9JUCBTZXJ2ZXIgKElQdjYpLiBDb21wdXRlcnMgb2Ygc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGNhbid0IGxpc3RlbiBhbmQgYWNjZXB0IFRDUC9JUCBjb25uZWN0aW9ucyBpbiBJUHY2LiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9TZXJ2ZXJWNl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgSVAgQWRkcmVzc2VzIChJUHY2KS4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBJUHY2IGFkZHJlc3NlcyB0aGF0IGNhbiBiZSByZWdpc3RlcmVkIGZvciBhIHNpbmdsZSBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4SVB2Nl91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgSVB2NCBQYWNrZXRzLiBBbGwgSVB2NCBhbmQgQVJQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVySVB2NF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBJUHY2IFBhY2tldHMuIEFsbCBJUHY2IHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVySVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBOb24tSVAgUGFja2V0cy4gQWxsIG5vbi1JUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gXCJOb24tSVAgcGFja2V0XCIgbWVhbiBhIHBhY2tldCB3aGljaCBpcyBub3QgSVB2NCwgQVJQIG5vciBJUHY2LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJOb25JUF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTm8gRGVmYXVsdC1Sb3V0ZXIgb24gSVB2NiBSQS4gSW4gYWxsIFZQTiBTZXNzaW9ucyBkZWZpbmVzIHRoaXMgcG9saWN5LCBhbnkgSVB2NiBSQSAoUm91dGVyIEFkdmVydGlzZW1lbnQpIHBhY2tldCB3aXRoIG5vbi16ZXJvIHZhbHVlIGluIHRoZSByb3V0ZXItbGlmZXRpbWUgd2lsbCBzZXQgdG8gemVyby12YWx1ZS4gVGhpcyBpcyBlZmZlY3RpdmUgdG8gYXZvaWQgdGhlIGhvcnJpYmxlIGJlaGF2aW9yIGZyb20gdGhlIElQdjYgcm91dGluZyBjb25mdXNpb24gd2hpY2ggaXMgY2F1c2VkIGJ5IHRoZSBWUE4gY2xpZW50J3MgYXR0ZW1wdHMgdG8gdXNlIHRoZSByZW1vdGUtc2lkZSBJUHY2IHJvdXRlciBhcyBpdHMgbG9jYWwgSVB2NiByb3V0ZXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0lQdjZEZWZhdWx0Um91dGVySW5SQV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVkxBTiBJRCAoSUVFRTgwMi4xUSkuIFlvdSBjYW4gc3BlY2lmeSB0aGUgVkxBTiBJRCBvbiB0aGUgc2VjdXJpdHkgcG9saWN5LiBBbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFsbCBFdGhlcm5ldCBwYWNrZXRzIHRvd2FyZCB0aGUgVmlydHVhbCBIdWIgZnJvbSB0aGUgdXNlciB3aWxsIGJlIGluc2VydGVkIGEgVkxBTiB0YWcgKElFRUUgODAyLjFRKSB3aXRoIHRoZSBWTEFOIElELiBUaGUgdXNlciBjYW4gYWxzbyByZWNlaXZlIG9ubHkgcGFja2V0cyB3aXRoIGEgVkxBTiB0YWcgd2hpY2ggaGFzIHRoZSBzYW1lIFZMQU4gSUQuIChSZWNlaXZpbmcgcHJvY2VzcyByZW1vdmVzIHRoZSBWTEFOIHRhZyBhdXRvbWF0aWNhbGx5LikgQW55IEV0aGVybmV0IHBhY2tldHMgd2l0aCBhbnkgb3RoZXIgVkxBTiBJRHMgb3Igbm9uLVZMQU4gcGFja2V0cyB3aWxsIG5vdCBiZSByZWNlaXZlZC4gQWxsIFZQTiBTZXNzaW9ucyB3aXRob3V0IHRoaXMgcG9saWN5IGRlZmluaXRpb24gY2FuIHNlbmQgLyByZWNlaXZlIGFueSBraW5kcyBvZiBFdGhlcm5ldCBwYWNrZXRzIHJlZ2FyZGxlc3Mgb2YgVkxBTiB0YWdzLCBhbmQgVkxBTiB0YWdzIGFyZSBub3QgaW5zZXJ0ZWQgb3IgcmVtb3ZlZCBhdXRvbWF0aWNhbGx5LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuIFRoZXJlZm9yZSwgdGFnZ2VkLVZMQU4gcGFja2V0cyBhcmUgbm90IHN1YmplY3RzIGZvciBJUHY0IC8gSVB2NiBzZWN1cml0eSBwb2xpY2llcywgYWNjZXNzIGxpc3RzIG5vciBvdGhlciBJUHY0IC8gSVB2NiBzcGVjaWZpYyBkZWVwIHByb2Nlc3NpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWTGFuSWRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBXaGV0aGVyIHZlcnNpb24gMy4wIChtdXN0IGJlIHRydWUpICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWZXIzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0NyZWF0ZUxpbms7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQ3JlYXRlTGluayA9IFZwblJwY0NyZWF0ZUxpbms7XHJcbi8qKiBMaXN0ZW5lciAqL1xyXG52YXIgVnBuUnBjTGlzdGVuZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTGlzdGVuZXInIGNsYXNzOiBMaXN0ZW5lciAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTGlzdGVuZXIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBQb3J0IG51bWJlciAoUmFuZ2U6IDEgLSA2NTUzNSkgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZlIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5FbmFibGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTGlzdGVuZXIgPSBWcG5ScGNMaXN0ZW5lcjtcclxuLyoqIFVzZXIgYXV0aGVudGljYXRpb24gdHlwZSAoc2VydmVyIHNpZGUpICovXHJcbnZhciBWcG5ScGNVc2VyQXV0aFR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjVXNlckF1dGhUeXBlKSB7XHJcbiAgICAvKiogQW5vbnltb3VzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiQW5vbnltb3VzXCJdID0gMF0gPSBcIkFub255bW91c1wiO1xyXG4gICAgLyoqIFBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiUGFzc3dvcmRcIl0gPSAxXSA9IFwiUGFzc3dvcmRcIjtcclxuICAgIC8qKiBVc2VyIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiVXNlckNlcnRcIl0gPSAyXSA9IFwiVXNlckNlcnRcIjtcclxuICAgIC8qKiBSb290IGNlcnRpZmljYXRlIHdoaWNoIGlzIGlzc3VlZCBieSB0cnVzdGVkIENlcnRpZmljYXRlIEF1dGhvcml0eSAqL1xyXG4gICAgVnBuUnBjVXNlckF1dGhUeXBlW1ZwblJwY1VzZXJBdXRoVHlwZVtcIlJvb3RDZXJ0XCJdID0gM10gPSBcIlJvb3RDZXJ0XCI7XHJcbiAgICAvKiogUmFkaXVzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiUmFkaXVzXCJdID0gNF0gPSBcIlJhZGl1c1wiO1xyXG4gICAgLyoqIFdpbmRvd3MgTlQgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY1VzZXJBdXRoVHlwZVtWcG5ScGNVc2VyQXV0aFR5cGVbXCJOVERvbWFpblwiXSA9IDVdID0gXCJOVERvbWFpblwiO1xyXG59KShWcG5ScGNVc2VyQXV0aFR5cGUgPSBleHBvcnRzLlZwblJwY1VzZXJBdXRoVHlwZSB8fCAoZXhwb3J0cy5WcG5ScGNVc2VyQXV0aFR5cGUgPSB7fSkpO1xyXG4vKiogQ3JlYXRlLCBjb25maWd1cmUsIGFuZCBnZXQgdGhlIHVzZXIgKi9cclxudmFyIFZwblJwY1NldFVzZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2V0VXNlcicgY2xhc3M6IENyZWF0ZSwgY29uZmlndXJlLCBhbmQgZ2V0IHRoZSB1c2VyICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNTZXRVc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgdXNlciBuYW1lIG9mIHRoZSB1c2VyICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEFzc2lnbmVkIGdyb3VwIG5hbWUgZm9yIHRoZSB1c2VyICovXHJcbiAgICAgICAgdGhpcy5Hcm91cE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT3B0aW9uYWwgcmVhbCBuYW1lIChmdWxsIG5hbWUpIG9mIHRoZSB1c2VyLCBhbGxvdyB1c2luZyBhbnkgVW5pY29kZSBjaGFyYWN0ZXJzICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCBVc2VyIERlc2NyaXB0aW9uICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENyZWF0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTGFzdCBtb2RpZmllZCBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5VcGRhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEV4cGlyYXRpb24gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuRXhwaXJlVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEF1dGhlbnRpY2F0aW9uIG1ldGhvZCBvZiB0aGUgdXNlciAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlciBwYXNzd29yZCwgdmFsaWQgb25seSBpZiBBdXRoVHlwZV91MzIgPT0gUGFzc3dvcmQoMSkuIFZhbGlkIG9ubHkgdG8gY3JlYXRlIG9yIHNldCBvcGVyYXRpb25zLiAqL1xyXG4gICAgICAgIHRoaXMuQXV0aF9QYXNzd29yZF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2VyIGNlcnRpZmljYXRlLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBVc2VyQ2VydCgyKS4gKi9cclxuICAgICAgICB0aGlzLlVzZXJYX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUgU2VyaWFsIE51bWJlciwgb3B0aW9uYWwsIHZhbGlkIG9ubHkgaWYgQXV0aFR5cGVfdTMyID09IFJvb3RDZXJ0KDMpLiAqL1xyXG4gICAgICAgIHRoaXMuU2VyaWFsX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUgQ29tbW9uIE5hbWUsIG9wdGlvbmFsLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBSb290Q2VydCgzKS4gKi9cclxuICAgICAgICB0aGlzLkNvbW1vbk5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlcm5hbWUgaW4gUkFESVVTIHNlcnZlciwgb3B0aW9uYWwsIHZhbGlkIG9ubHkgaWYgQXV0aFR5cGVfdTMyID09IFJhZGl1cyg0KS4gKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1VzZXJuYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFVzZXJuYW1lIGluIE5UIERvbWFpbiBzZXJ2ZXIsIG9wdGlvbmFsLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBOVCg1KS4gKi9cclxuICAgICAgICB0aGlzLk50VXNlcm5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHRvdGFsIGxvZ2lucyBvZiB0aGUgdXNlciAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGNvdW50IChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdG8gdXNlIHNlY3VyaXR5IHBvbGljeSAqL1xyXG4gICAgICAgIHRoaXMuVXNlUG9saWN5X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBBbGxvdyBBY2Nlc3MuIFRoZSB1c2Vycywgd2hpY2ggdGhpcyBwb2xpY3kgdmFsdWUgaXMgdHJ1ZSwgaGF2ZSBwZXJtaXNzaW9uIHRvIG1ha2UgVlBOIGNvbm5lY3Rpb24gdG8gVlBOIFNlcnZlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkFjY2Vzc19ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIERIQ1AgUGFja2V0cyAoSVB2NCkuIEFsbCBJUHY0IERIQ1AgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjQpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NCBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUE5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBFbmZvcmNlIERIQ1AgQWxsb2NhdGVkIElQIEFkZHJlc3NlcyAoSVB2NCkuIENvbXB1dGVycyBpbiBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZyB3aWxsIG9ubHkgYmUgYWJsZSB0byB1c2UgSVB2NCBhZGRyZXNzZXMgYWxsb2NhdGVkIGJ5IGEgREhDUCBzZXJ2ZXIgb24gdGhlIHZpcnR1YWwgbmV0d29yayBzaWRlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUEZvcmNlX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IEJyaWRnZSBPcGVyYXRpb24uIEJyaWRnZS1tb2RlIGNvbm5lY3Rpb25zIGFyZSBkZW5pZWQgZm9yIHVzZXIgc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcuIEV2ZW4gaW4gY2FzZXMgd2hlbiB0aGUgRXRoZXJuZXQgQnJpZGdlIGlzIGNvbmZpZ3VyZWQgaW4gdGhlIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9CcmlkZ2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgUm91dGluZyBPcGVyYXRpb24gKElQdjQpLiBJUHY0IHJvdXRpbmcgd2lsbCBiZSBkZW5pZWQgZm9yIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nLiBFdmVuIGluIHRoZSBjYXNlIHdoZXJlIHRoZSBJUCByb3V0ZXIgaXMgb3BlcmF0aW5nIG9uIHRoZSB1c2VyIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Sb3V0aW5nX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE1BQyBBZGRyZXNzZXMgRHVwbGljYXRpb24uIFRoZSB1c2Ugb2YgZHVwbGljYXRpbmcgTUFDIGFkZHJlc3NlcyB0aGF0IGFyZSBpbiB1c2UgYnkgY29tcHV0ZXJzIG9mIGRpZmZlcmVudCBzZXNzaW9ucyBjYW5ub3QgYmUgdXNlZCBieSBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpDaGVja01hY19ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBJUCBBZGRyZXNzIER1cGxpY2F0aW9uIChJUHY0KS4gVGhlIHVzZSBvZiBkdXBsaWNhdGluZyBJUHY0IGFkZHJlc3NlcyB0aGF0IGFyZSBpbiB1c2UgYnkgY29tcHV0ZXJzIG9mIGRpZmZlcmVudCBzZXNzaW9ucyBjYW5ub3QgYmUgdXNlZCBieSBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpDaGVja0lQX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE5vbi1BUlAgLyBOb24tREhDUCAvIE5vbi1JQ01QdjYgYnJvYWRjYXN0cy4gVGhlIHNlbmRpbmcgb3IgcmVjZWl2aW5nIG9mIGJyb2FkY2FzdCBwYWNrZXRzIHRoYXQgYXJlIG5vdCBBUlAgcHJvdG9jb2wsIERIQ1AgcHJvdG9jb2wsIG5vciBJQ01QdjYgb24gdGhlIHZpcnR1YWwgbmV0d29yayB3aWxsIG5vdCBiZSBhbGxvd2VkIGZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpBcnBEaGNwT25seV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJpdmFjeSBGaWx0ZXIgTW9kZS4gQWxsIGRpcmVjdCBjb21tdW5pY2F0aW9uIGJldHdlZW4gc2Vzc2lvbnMgd2l0aCB0aGUgcHJpdmFjeSBmaWx0ZXIgbW9kZSBwb2xpY3kgc2V0dGluZyB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UHJpdmFjeUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NCkuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVW5saW1pdGVkIE51bWJlciBvZiBCcm9hZGNhc3RzLiBJZiBhIGNvbXB1dGVyIG9mIGEgc2Vzc2lvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgc2VuZHMgYnJvYWRjYXN0IHBhY2tldHMgb2YgYSBudW1iZXIgdW51c3VhbGx5IGxhcmdlciB0aGFuIHdoYXQgd291bGQgYmUgY29uc2lkZXJlZCBub3JtYWwgb24gdGhlIHZpcnR1YWwgbmV0d29yaywgdGhlcmUgd2lsbCBiZSBubyBhdXRvbWF0aWMgbGltaXRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0Jyb2FkY2FzdExpbWl0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEFsbG93IE1vbml0b3JpbmcgTW9kZS4gVXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgYmUgZ3JhbnRlZCB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1YiBpbiBNb25pdG9yaW5nIE1vZGUuIFNlc3Npb25zIGluIE1vbml0b3JpbmcgTW9kZSBhcmUgYWJsZSB0byBtb25pdG9yICh0YXApIGFsbCBwYWNrZXRzIGZsb3dpbmcgdGhyb3VnaCB0aGUgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNb25pdG9yUG9ydF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgVENQIENvbm5lY3Rpb25zLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNldHMgdGhlIG1heGltdW0gbnVtYmVyIG9mIHBoeXNpY2FsIFRDUCBjb25uZWN0aW9ucyBjb25zaXN0cyBpbiBhIHBoeXNpY2FsIFZQTiBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4Q29ubmVjdGlvbl91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFRpbWUtb3V0IFBlcmlvZC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBzZXRzLCBpbiBzZWNvbmRzLCB0aGUgdGltZS1vdXQgcGVyaW9kIHRvIHdhaXQgYmVmb3JlIGRpc2Nvbm5lY3RpbmcgYSBzZXNzaW9uIHdoZW4gY29tbXVuaWNhdGlvbiB0cm91YmxlIG9jY3VycyBiZXR3ZWVuIHRoZSBWUE4gQ2xpZW50IC8gVlBOIFNlcnZlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlRpbWVPdXRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBNQUMgQWRkcmVzc2VzLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgbnVtYmVyIG9mIE1BQyBhZGRyZXNzZXMgcGVyIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhNYWNfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBJUCBBZGRyZXNzZXMgKElQdjQpLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIElQdjQgYWRkcmVzc2VzIHRoYXQgY2FuIGJlIHJlZ2lzdGVyZWQgZm9yIGEgc2luZ2xlIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhJUF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFVwbG9hZCBCYW5kd2lkdGguIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSB0cmFmZmljIGJhbmR3aWR0aCB0aGF0IGlzIGluIHRoZSBpbndhcmRzIGRpcmVjdGlvbiBmcm9tIG91dHNpZGUgdG8gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heFVwbG9hZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERvd25sb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIG91dHdhcmRzIGRpcmVjdGlvbiBmcm9tIGluc2lkZSB0aGUgVmlydHVhbCBIdWIgdG8gb3V0c2lkZSB0aGUgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhEb3dubG9hZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgQ2hhbmdpbmcgUGFzc3dvcmQuIFRoZSB1c2VycyB3aGljaCB1c2UgcGFzc3dvcmQgYXV0aGVudGljYXRpb24gd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGFyZSBub3QgYWxsb3dlZCB0byBjaGFuZ2UgdGhlaXIgb3duIHBhc3N3b3JkIGZyb20gdGhlIFZQTiBDbGllbnQgTWFuYWdlciBvciBzaW1pbGFyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Rml4UGFzc3dvcmRfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE11bHRpcGxlIExvZ2lucy4gVXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGFyZSB1bmFibGUgdG8gaGF2ZSBtb3JlIHRoYW4gdGhpcyBudW1iZXIgb2YgY29uY3VycmVudCBsb2dpbnMuIEJyaWRnZSBNb2RlIHNlc3Npb25zIGFyZSBub3Qgc3ViamVjdHMgdG8gdGhpcyBwb2xpY3kuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNdWx0aUxvZ2luc191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgVm9JUCAvIFFvUyBGdW5jdGlvbi4gVXNlcnMgd2l0aCB0aGlzIHNlY3VyaXR5IHBvbGljeSBhcmUgdW5hYmxlIHRvIHVzZSBWb0lQIC8gUW9TIGZ1bmN0aW9ucyBpbiBWUE4gY29ubmVjdGlvbiBzZXNzaW9ucy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vUW9TX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgUlMgLyBSQSBQYWNrZXRzIChJUHY2KS4gQWxsIElDTVB2NiBwYWNrZXRzIHdoaWNoIHRoZSBtZXNzYWdlLXR5cGUgaXMgMTMzIChSb3V0ZXIgU29saWNpdGF0aW9uKSBvciAxMzQgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuIEFzIGEgcmVzdWx0LCBhbiBJUHY2IGNsaWVudCB3aWxsIGJlIHVuYWJsZSB0byB1c2UgSVB2NiBhZGRyZXNzIHByZWZpeCBhdXRvIGRldGVjdGlvbiBhbmQgSVB2NiBkZWZhdWx0IGdhdGV3YXkgYXV0byBkZXRlY3Rpb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpSU2FuZFJBRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgUkEgUGFja2V0cyAoSVB2NikuIEFsbCBJQ01QdjYgcGFja2V0cyB3aGljaCB0aGUgbWVzc2FnZS10eXBlIGlzIDEzNCAoUm91dGVyIEFkdmVydGlzZW1lbnQpIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gQXMgYSByZXN1bHQsIGEgbWFsaWNpb3VzIHVzZXJzIHdpbGwgYmUgdW5hYmxlIHRvIHNwcmVhZCBpbGxlZ2FsIElQdjYgcHJlZml4IG9yIGRlZmF1bHQgZ2F0ZXdheSBhZHZlcnRpc2VtZW50cyBvbiB0aGUgbmV0d29yay4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlJBRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY2KS4gQWxsIElQdjYgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1B2NkZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGlzYWxsb3cgREhDUCBTZXJ2ZXIgT3BlcmF0aW9uIChJUHY2KS4gQ29tcHV0ZXJzIGNvbm5lY3RlZCB0byBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZyB3aWxsIG5vdCBiZSBhbGxvd2VkIHRvIGJlY29tZSBhIERIQ1Agc2VydmVyIGFuZCBkaXN0cmlidXRlIElQdjYgYWRkcmVzc2VzIHRvIERIQ1AgY2xpZW50cy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1B2Nk5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IFJvdXRpbmcgT3BlcmF0aW9uIChJUHY2KS4gSVB2NiByb3V0aW5nIHdpbGwgYmUgZGVuaWVkIGZvciBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZy4gRXZlbiBpbiB0aGUgY2FzZSB3aGVyZSB0aGUgSVAgcm91dGVyIGlzIG9wZXJhdGluZyBvbiB0aGUgdXNlciBjbGllbnQgc2lkZSwgY29tbXVuaWNhdGlvbiB3aWxsIG5vdCBiZSBwb3NzaWJsZS4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vUm91dGluZ1Y2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IElQIEFkZHJlc3MgRHVwbGljYXRpb24gKElQdjYpLiBUaGUgdXNlIG9mIGR1cGxpY2F0aW5nIElQdjYgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrSVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NikuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjYuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlclY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBJUCBBZGRyZXNzZXMgKElQdjYpLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIElQdjYgYWRkcmVzc2VzIHRoYXQgY2FuIGJlIHJlZ2lzdGVyZWQgZm9yIGEgc2luZ2xlIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhJUHY2X3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGlzYWxsb3cgUGFzc3dvcmQgU2F2ZSBpbiBWUE4gQ2xpZW50LiBGb3IgdXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB3aGVuIHRoZSB1c2VyIGlzIHVzaW5nICpzdGFuZGFyZCogcGFzc3dvcmQgYXV0aGVudGljYXRpb24sIHRoZSB1c2VyIHdpbGwgYmUgdW5hYmxlIHRvIHNhdmUgdGhlIHBhc3N3b3JkIGluIFZQTiBDbGllbnQuIFRoZSB1c2VyIHdpbGwgYmUgcmVxdWlyZWQgdG8gaW5wdXQgcGFzc3dvcmRzIGZvciBldmVyeSB0aW1lIHRvIGNvbm5lY3QgYSBWUE4uIFRoaXMgd2lsbCBpbXByb3ZlIHRoZSBzZWN1cml0eS4gSWYgdGhpcyBwb2xpY3kgaXMgZW5hYmxlZCwgVlBOIENsaWVudCBWZXJzaW9uIDIuMCB3aWxsIGJlIGRlbmllZCB0byBhY2Nlc3MuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NhdmVQYXNzd29yZF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVlBOIENsaWVudCBBdXRvbWF0aWMgRGlzY29ubmVjdC4gRm9yIHVzZXJzIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgYSB1c2VyJ3MgVlBOIHNlc3Npb24gd2lsbCBiZSBkaXNjb25uZWN0ZWQgYXV0b21hdGljYWxseSBhZnRlciB0aGUgc3BlY2lmaWMgcGVyaW9kIHdpbGwgZWxhcHNlLiBJbiB0aGlzIGNhc2Ugbm8gYXV0b21hdGljIHJlLWNvbm5lY3Rpb24gd2lsbCBiZSBwZXJmb3JtZWQuIFRoaXMgY2FuIHByZXZlbnQgYSBsb3Qgb2YgaW5hY3RpdmUgVlBOIFNlc3Npb25zLiBJZiB0aGlzIHBvbGljeSBpcyBlbmFibGVkLCBWUE4gQ2xpZW50IFZlcnNpb24gMi4wIHdpbGwgYmUgZGVuaWVkIHRvIGFjY2Vzcy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkF1dG9EaXNjb25uZWN0X3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBJUHY0IFBhY2tldHMuIEFsbCBJUHY0IGFuZCBBUlAgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJJUHY0X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIElQdjYgUGFja2V0cy4gQWxsIElQdjYgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJJUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIE5vbi1JUCBQYWNrZXRzLiBBbGwgbm9uLUlQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBcIk5vbi1JUCBwYWNrZXRcIiBtZWFuIGEgcGFja2V0IHdoaWNoIGlzIG5vdCBJUHY0LCBBUlAgbm9yIElQdjYuIEFueSB0YWdnZWQtVkxBTiBwYWNrZXRzIHZpYSB0aGUgVmlydHVhbCBIdWIgd2lsbCBiZSByZWdhcmRlZCBhcyBub24tSVAgcGFja2V0cy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlck5vbklQX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBObyBEZWZhdWx0LVJvdXRlciBvbiBJUHY2IFJBLiBJbiBhbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFueSBJUHY2IFJBIChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgcGFja2V0IHdpdGggbm9uLXplcm8gdmFsdWUgaW4gdGhlIHJvdXRlci1saWZldGltZSB3aWxsIHNldCB0byB6ZXJvLXZhbHVlLiBUaGlzIGlzIGVmZmVjdGl2ZSB0byBhdm9pZCB0aGUgaG9ycmlibGUgYmVoYXZpb3IgZnJvbSB0aGUgSVB2NiByb3V0aW5nIGNvbmZ1c2lvbiB3aGljaCBpcyBjYXVzZWQgYnkgdGhlIFZQTiBjbGllbnQncyBhdHRlbXB0cyB0byB1c2UgdGhlIHJlbW90ZS1zaWRlIElQdjYgcm91dGVyIGFzIGl0cyBsb2NhbCBJUHY2IHJvdXRlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vSVB2NkRlZmF1bHRSb3V0ZXJJblJBX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBObyBEZWZhdWx0LVJvdXRlciBvbiBJUHY2IFJBIChwaHlzaWNhbCBJUHY2KS4gSW4gYWxsIFZQTiBTZXNzaW9ucyBkZWZpbmVzIHRoaXMgcG9saWN5IChvbmx5IHdoZW4gdGhlIHBoeXNpY2FsIGNvbW11bmljYXRpb24gcHJvdG9jb2wgYmV0d2VlbiBWUE4gQ2xpZW50IC8gVlBOIEJyaWRnZSBhbmQgVlBOIFNlcnZlciBpcyBJUHY2KSwgYW55IElQdjYgUkEgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBwYWNrZXQgd2l0aCBub24temVybyB2YWx1ZSBpbiB0aGUgcm91dGVyLWxpZmV0aW1lIHdpbGwgc2V0IHRvIHplcm8tdmFsdWUuIFRoaXMgaXMgZWZmZWN0aXZlIHRvIGF2b2lkIHRoZSBob3JyaWJsZSBiZWhhdmlvciBmcm9tIHRoZSBJUHY2IHJvdXRpbmcgY29uZnVzaW9uIHdoaWNoIGlzIGNhdXNlZCBieSB0aGUgVlBOIGNsaWVudCdzIGF0dGVtcHRzIHRvIHVzZSB0aGUgcmVtb3RlLXNpZGUgSVB2NiByb3V0ZXIgYXMgaXRzIGxvY2FsIElQdjYgcm91dGVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9JUHY2RGVmYXVsdFJvdXRlckluUkFXaGVuSVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVkxBTiBJRCAoSUVFRTgwMi4xUSkuIFlvdSBjYW4gc3BlY2lmeSB0aGUgVkxBTiBJRCBvbiB0aGUgc2VjdXJpdHkgcG9saWN5LiBBbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFsbCBFdGhlcm5ldCBwYWNrZXRzIHRvd2FyZCB0aGUgVmlydHVhbCBIdWIgZnJvbSB0aGUgdXNlciB3aWxsIGJlIGluc2VydGVkIGEgVkxBTiB0YWcgKElFRUUgODAyLjFRKSB3aXRoIHRoZSBWTEFOIElELiBUaGUgdXNlciBjYW4gYWxzbyByZWNlaXZlIG9ubHkgcGFja2V0cyB3aXRoIGEgVkxBTiB0YWcgd2hpY2ggaGFzIHRoZSBzYW1lIFZMQU4gSUQuIChSZWNlaXZpbmcgcHJvY2VzcyByZW1vdmVzIHRoZSBWTEFOIHRhZyBhdXRvbWF0aWNhbGx5LikgQW55IEV0aGVybmV0IHBhY2tldHMgd2l0aCBhbnkgb3RoZXIgVkxBTiBJRHMgb3Igbm9uLVZMQU4gcGFja2V0cyB3aWxsIG5vdCBiZSByZWNlaXZlZC4gQWxsIFZQTiBTZXNzaW9ucyB3aXRob3V0IHRoaXMgcG9saWN5IGRlZmluaXRpb24gY2FuIHNlbmQgLyByZWNlaXZlIGFueSBraW5kcyBvZiBFdGhlcm5ldCBwYWNrZXRzIHJlZ2FyZGxlc3Mgb2YgVkxBTiB0YWdzLCBhbmQgVkxBTiB0YWdzIGFyZSBub3QgaW5zZXJ0ZWQgb3IgcmVtb3ZlZCBhdXRvbWF0aWNhbGx5LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuIFRoZXJlZm9yZSwgdGFnZ2VkLVZMQU4gcGFja2V0cyBhcmUgbm90IHN1YmplY3RzIGZvciBJUHY0IC8gSVB2NiBzZWN1cml0eSBwb2xpY2llcywgYWNjZXNzIGxpc3RzIG5vciBvdGhlciBJUHY0IC8gSVB2NiBzcGVjaWZpYyBkZWVwIHByb2Nlc3NpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWTGFuSWRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBXaGV0aGVyIHZlcnNpb24gMy4wIChtdXN0IGJlIHRydWUpICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWZXIzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NldFVzZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2V0VXNlciA9IFZwblJwY1NldFVzZXI7XHJcbi8qKiBEZWxldGUgdGhlIGFjY2VzcyBsaXN0ICovXHJcbnZhciBWcG5ScGNEZWxldGVBY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRGVsZXRlQWNjZXNzJyBjbGFzczogRGVsZXRlIHRoZSBhY2Nlc3MgbGlzdCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRGVsZXRlQWNjZXNzKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSUQgKi9cclxuICAgICAgICB0aGlzLklkX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVBY2Nlc3M7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRGVsZXRlQWNjZXNzID0gVnBuUnBjRGVsZXRlQWNjZXNzO1xyXG4vKiogRGVsZXRlIHRoZSBDQSBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkRlbGV0ZUNBID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YkRlbGV0ZUNBJyBjbGFzczogRGVsZXRlIHRoZSBDQSBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkRlbGV0ZUNBKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUga2V5IGlkIHRvIGJlIGRlbGV0ZWQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViRGVsZXRlQ0E7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViRGVsZXRlQ0EgPSBWcG5ScGNIdWJEZWxldGVDQTtcclxuLyoqIERlbGV0aW5nIGEgdXNlciBvciBncm91cCAqL1xyXG52YXIgVnBuUnBjRGVsZXRlVXNlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVVc2VyJyBjbGFzczogRGVsZXRpbmcgYSB1c2VyIG9yIGdyb3VwICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEZWxldGVVc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBvciBncm91cCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVVc2VyO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVVzZXIgPSBWcG5ScGNEZWxldGVVc2VyO1xyXG4vKiogRGVsZXRlIHRoZSBIVUIgKi9cclxudmFyIFZwblJwY0RlbGV0ZUh1YiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVIdWInIGNsYXNzOiBEZWxldGUgdGhlIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRGVsZXRlSHViKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0RlbGV0ZUh1YjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNEZWxldGVIdWIgPSBWcG5ScGNEZWxldGVIdWI7XHJcbi8qKiBEZWxldGUgdGhlIHRhYmxlICovXHJcbnZhciBWcG5ScGNEZWxldGVUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVUYWJsZScgY2xhc3M6IERlbGV0ZSB0aGUgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0RlbGV0ZVRhYmxlKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2V5IElEICovXHJcbiAgICAgICAgdGhpcy5LZXlfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0RlbGV0ZVRhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVRhYmxlID0gVnBuUnBjRGVsZXRlVGFibGU7XHJcbi8qKiBTcGVjaWZ5IHRoZSBMaW5rICovXHJcbnZhciBWcG5ScGNMaW5rID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0xpbmsnIGNsYXNzOiBTcGVjaWZ5IHRoZSBMaW5rICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaW5rKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0xpbms7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTGluayA9IFZwblJwY0xpbms7XHJcbi8qKiBEaXNjb25uZWN0IHRoZSBzZXNzaW9uICovXHJcbnZhciBWcG5ScGNEZWxldGVTZXNzaW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0RlbGV0ZVNlc3Npb24nIGNsYXNzOiBEaXNjb25uZWN0IHRoZSBzZXNzaW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEZWxldGVTZXNzaW9uKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2Vzc2lvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVTZXNzaW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVNlc3Npb24gPSBWcG5ScGNEZWxldGVTZXNzaW9uO1xyXG4vKiogU3BlY2lmeSB0aGUgSFVCICovXHJcbnZhciBWcG5ScGNIdWIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViJyBjbGFzczogU3BlY2lmeSB0aGUgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0h1YiA9IFZwblJwY0h1YjtcclxuLyoqIERpc2Nvbm5lY3QgYSBjb25uZWN0aW9uICovXHJcbnZhciBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbicgY2xhc3M6IERpc2Nvbm5lY3QgYSBjb25uZWN0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbihpbml0KSB7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRGlzY29ubmVjdENvbm5lY3Rpb247XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRGlzY29ubmVjdENvbm5lY3Rpb24gPSBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbjtcclxuLyoqIEVudW1lcmF0aW9uIG9mIHRoZSBhY2Nlc3MgbGlzdCAqL1xyXG52YXIgVnBuUnBjRW51bUFjY2Vzc0xpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUFjY2Vzc0xpc3QnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiB0aGUgYWNjZXNzIGxpc3QgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1BY2Nlc3NMaXN0KGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQWNjZXNzIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkFjY2Vzc0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1BY2Nlc3NMaXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1BY2Nlc3NMaXN0ID0gVnBuUnBjRW51bUFjY2Vzc0xpc3Q7XHJcbi8qKiBDQSBlbnVtZXJhdGlvbiBpdGVtcyBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkVudW1DQUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViRW51bUNBSXRlbScgY2xhc3M6IENBIGVudW1lcmF0aW9uIGl0ZW1zIG9mIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjSHViRW51bUNBSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBrZXkgaWQgb2YgdGhlIGl0ZW0gKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTdWJqZWN0ICovXHJcbiAgICAgICAgdGhpcy5TdWJqZWN0TmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBJc3N1ZXIgKi9cclxuICAgICAgICB0aGlzLklzc3Vlck5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogRXhwaXJhdGlvbiBkYXRlICovXHJcbiAgICAgICAgdGhpcy5FeHBpcmVzX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YkVudW1DQUl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViRW51bUNBSXRlbSA9IFZwblJwY0h1YkVudW1DQUl0ZW07XHJcbi8qKiBDQSBlbnVtZXJhdGlvbiBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkVudW1DQSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNIdWJFbnVtQ0EnIGNsYXNzOiBDQSBlbnVtZXJhdGlvbiBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkVudW1DQShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBsaXN0IG9mIENBICovXHJcbiAgICAgICAgdGhpcy5DQUxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YkVudW1DQTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJFbnVtQ0EgPSBWcG5ScGNIdWJFbnVtQ0E7XHJcbi8qKiBUeXBlIG9mIGNvbm5lY3Rpb24gKi9cclxudmFyIFZwblJwY0Nvbm5lY3Rpb25UeXBlO1xyXG4oZnVuY3Rpb24gKFZwblJwY0Nvbm5lY3Rpb25UeXBlKSB7XHJcbiAgICAvKiogVlBOIENsaWVudCAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJDbGllbnRcIl0gPSAwXSA9IFwiQ2xpZW50XCI7XHJcbiAgICAvKiogRHVyaW5nIGluaXRpYWxpemF0aW9uICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIkluaXRcIl0gPSAxXSA9IFwiSW5pdFwiO1xyXG4gICAgLyoqIExvZ2luIGNvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiTG9naW5cIl0gPSAyXSA9IFwiTG9naW5cIjtcclxuICAgIC8qKiBBZGRpdGlvbmFsIGNvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiQWRkaXRpb25hbFwiXSA9IDNdID0gXCJBZGRpdGlvbmFsXCI7XHJcbiAgICAvKiogUlBDIGZvciBzZXJ2ZXIgZmFybSAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJGYXJtUnBjXCJdID0gNF0gPSBcIkZhcm1ScGNcIjtcclxuICAgIC8qKiBSUEMgZm9yIE1hbmFnZW1lbnQgKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiQWRtaW5ScGNcIl0gPSA1XSA9IFwiQWRtaW5ScGNcIjtcclxuICAgIC8qKiBIVUIgZW51bWVyYXRpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiRW51bUh1YlwiXSA9IDZdID0gXCJFbnVtSHViXCI7XHJcbiAgICAvKiogUGFzc3dvcmQgY2hhbmdlICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIlBhc3N3b3JkXCJdID0gN10gPSBcIlBhc3N3b3JkXCI7XHJcbiAgICAvKiogU1NUUCAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJTU1RQXCJdID0gOF0gPSBcIlNTVFBcIjtcclxuICAgIC8qKiBPcGVuVlBOICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIk9wZW5WUE5cIl0gPSA5XSA9IFwiT3BlblZQTlwiO1xyXG59KShWcG5ScGNDb25uZWN0aW9uVHlwZSA9IGV4cG9ydHMuVnBuUnBjQ29ubmVjdGlvblR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjQ29ubmVjdGlvblR5cGUgPSB7fSkpO1xyXG4vKiogQ29ubmVjdGlvbiBlbnVtZXJhdGlvbiBpdGVtcyAqL1xyXG52YXIgVnBuUnBjRW51bUNvbm5lY3Rpb25JdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Db25uZWN0aW9uSXRlbScgY2xhc3M6IENvbm5lY3Rpb24gZW51bWVyYXRpb24gaXRlbXMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Db25uZWN0aW9uSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogUG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGVkIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHR5cGUgKi9cclxuICAgICAgICB0aGlzLlR5cGVfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Db25uZWN0aW9uSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtQ29ubmVjdGlvbkl0ZW0gPSBWcG5ScGNFbnVtQ29ubmVjdGlvbkl0ZW07XHJcbi8qKiBDb25uZWN0aW9uIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtQ29ubmVjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtQ29ubmVjdGlvbicgY2xhc3M6IENvbm5lY3Rpb24gZW51bWVyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Db25uZWN0aW9uKGluaXQpIHtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1Db25uZWN0aW9uX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGlvbkxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Db25uZWN0aW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Db25uZWN0aW9uID0gVnBuUnBjRW51bUNvbm5lY3Rpb247XHJcbi8qKiBFbnVtIENSTCBJdGVtICovXHJcbnZhciBWcG5ScGNFbnVtQ3JsSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtQ3JsSXRlbScgY2xhc3M6IEVudW0gQ1JMIEl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1DcmxJdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogS2V5IElEICovXHJcbiAgICAgICAgdGhpcy5LZXlfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGNvbnRlbnRzIG9mIHRoZSBDUkwgaXRlbSAqL1xyXG4gICAgICAgIHRoaXMuQ3JsSW5mb191dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUNybEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUNybEl0ZW0gPSBWcG5ScGNFbnVtQ3JsSXRlbTtcclxuLyoqIEVudW0gQ1JMICovXHJcbnZhciBWcG5ScGNFbnVtQ3JsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1DcmwnIGNsYXNzOiBFbnVtIENSTCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUNybChpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENSTCBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5DUkxMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtQ3JsO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1DcmwgPSBWcG5ScGNFbnVtQ3JsO1xyXG4vKiogUlBDX0VOVU1fREhDUF9JVEVNICovXHJcbnZhciBWcG5ScGNFbnVtRGhjcEl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bURoY3BJdGVtJyBjbGFzczogUlBDX0VOVU1fREhDUF9JVEVNICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRGhjcEl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogTGVhc2UgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuTGVhc2VkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEV4cGlyYXRpb24gZGF0ZSAqL1xyXG4gICAgICAgIHRoaXMuRXhwaXJlVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE1BQyBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5NYWNBZGRyZXNzX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLk1hc2tfdTMyID0gMDtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bURoY3BJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1EaGNwSXRlbSA9IFZwblJwY0VudW1EaGNwSXRlbTtcclxuLyoqIFJQQ19FTlVNX0RIQ1AgKi9cclxudmFyIFZwblJwY0VudW1EaGNwID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1EaGNwJyBjbGFzczogUlBDX0VOVU1fREhDUCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bURoY3AoaW5pdCkge1xyXG4gICAgICAgIC8qKiBWaXJ0dWFsIEh1YiBOYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIERIQ1AgSXRlbSAqL1xyXG4gICAgICAgIHRoaXMuRGhjcFRhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRGhjcDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRGhjcCA9IFZwblJwY0VudW1EaGNwO1xyXG4vKiogRXRoZXJJUCBzZXR0aW5nIGxpc3QgKi9cclxudmFyIFZwblJwY0VudW1FdGhlcklwSWQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUV0aGVySXBJZCcgY2xhc3M6IEV0aGVySVAgc2V0dGluZyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoZXJJcElkKGluaXQpIHtcclxuICAgICAgICAvKiogU2V0dGluZyBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5TZXR0aW5ncyA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUV0aGVySXBJZDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRXRoZXJJcElkID0gVnBuUnBjRW51bUV0aGVySXBJZDtcclxuLyoqIEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCBpdGVtICovXHJcbnZhciBWcG5ScGNFbnVtRXRoSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtRXRoSXRlbScgY2xhc3M6IEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIERldmljZSBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXZpY2VOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE5ldHdvcmsgY29ubmVjdGlvbiBuYW1lIChkZXNjcmlwdGlvbikgKi9cclxuICAgICAgICB0aGlzLk5ldHdvcmtDb25uZWN0aW9uTmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUV0aEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUV0aEl0ZW0gPSBWcG5ScGNFbnVtRXRoSXRlbTtcclxuLyoqIEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCAqL1xyXG52YXIgVnBuUnBjRW51bUV0aCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtRXRoJyBjbGFzczogRXRoZXJuZXQgTmV0d29yayBBZGFwdGVycyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoKGluaXQpIHtcclxuICAgICAgICAvKiogRXRoZXJuZXQgTmV0d29yayBBZGFwdGVycyBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5FdGhMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRXRoO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1FdGggPSBWcG5ScGNFbnVtRXRoO1xyXG4vKiogU2VydmVyIGZhcm0gbWVtYmVycyBlbnVtZXJhdGlvbiBpdGVtcyAqL1xyXG52YXIgVnBuUnBjRW51bUZhcm1JdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1GYXJtSXRlbScgY2xhc3M6IFNlcnZlciBmYXJtIG1lbWJlcnMgZW51bWVyYXRpb24gaXRlbXMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1GYXJtSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIElEICovXHJcbiAgICAgICAgdGhpcy5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb250cm9sbGVyICovXHJcbiAgICAgICAgdGhpcy5Db250cm9sbGVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvaW50ICovXHJcbiAgICAgICAgdGhpcy5Qb2ludF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2Ygc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBIVUJzICovXHJcbiAgICAgICAgdGhpcy5OdW1IdWJzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhc3NpZ25lZCBjbGllbnQgbGljZW5zZXMgKi9cclxuICAgICAgICB0aGlzLkFzc2lnbmVkQ2xpZW50TGljZW5zZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYXNzaWduZWQgYnJpZGdlIGxpY2Vuc2VzICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1GYXJtSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRmFybUl0ZW0gPSBWcG5ScGNFbnVtRmFybUl0ZW07XHJcbi8qKiBTZXJ2ZXIgZmFybSBtZW1iZXIgZW51bWVyYXRpb24gKi9cclxudmFyIFZwblJwY0VudW1GYXJtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1GYXJtJyBjbGFzczogU2VydmVyIGZhcm0gbWVtYmVyIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRmFybShpbml0KSB7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBDbHVzdGVyIE1lbWJlcnMgKi9cclxuICAgICAgICB0aGlzLk51bUZhcm1fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2x1c3RlciBNZW1iZXJzIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkZhcm1NZW1iZXJMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRmFybTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRmFybSA9IFZwblJwY0VudW1GYXJtO1xyXG4vKiogRW51bWVyYXRpb24gaXRlbXMgaW4gdGhlIGdyb3VwICovXHJcbnZhciBWcG5ScGNFbnVtR3JvdXBJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Hcm91cEl0ZW0nIGNsYXNzOiBFbnVtZXJhdGlvbiBpdGVtcyBpbiB0aGUgZ3JvdXAgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Hcm91cEl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBVc2VyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUmVhbCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOb3RlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiB1c2VycyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVXNlcnNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWNjZXNzIGRlbmllZCAqL1xyXG4gICAgICAgIHRoaXMuRGVueUFjY2Vzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtR3JvdXBJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Hcm91cEl0ZW0gPSBWcG5ScGNFbnVtR3JvdXBJdGVtO1xyXG4vKiogR3JvdXAgZW51bWVyYXRpb24gKi9cclxudmFyIFZwblJwY0VudW1Hcm91cCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtR3JvdXAnIGNsYXNzOiBHcm91cCBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUdyb3VwKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogR3JvdXAgbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuR3JvdXBMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtR3JvdXA7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUdyb3VwID0gVnBuUnBjRW51bUdyb3VwO1xyXG4vKiogRW51bWVyYXRpb24gaXRlbXMgb2YgSFVCICovXHJcbnZhciBWcG5ScGNFbnVtSHViSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtSHViSXRlbScgY2xhc3M6IEVudW1lcmF0aW9uIGl0ZW1zIG9mIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUh1Ykl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgVmlydHVhbCBIdWIgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT25saW5lIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIEhVQiAoVmFsaWQgb25seSBmb3IgQ2x1c3RlcmVkIFZQTiBTZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuSHViVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdXNlcnMgKi9cclxuICAgICAgICB0aGlzLk51bVVzZXJzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZWdpc3RlcmVkIGdyb3VwcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtR3JvdXBzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZWdpc3RlcmVkIHNlc3Npb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1TZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgY3VycmVudCBNQUMgdGFibGUgZW50cmllcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTWFjVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IElQIHRhYmxlIGVudHJpZXMgKi9cclxuICAgICAgICB0aGlzLk51bUlwVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBMYXN0IGxvZ2luIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkxhc3RMb2dpblRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhY2N1bXVsYXRlZCBsb2dpbnMgKi9cclxuICAgICAgICB0aGlzLk51bUxvZ2luX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFdoZXRoZXIgdGhlIHRyYWZmaWMgaW5mb3JtYXRpb24gaXMgcHJvdmlkZWQgKi9cclxuICAgICAgICB0aGlzLklzVHJhZmZpY0ZpbGxlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBjb3VudCAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUh1Ykl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUh1Ykl0ZW0gPSBWcG5ScGNFbnVtSHViSXRlbTtcclxuLyoqIEVudW1lcmF0aW9uIG9mIEhVQiAqL1xyXG52YXIgVnBuUnBjRW51bUh1YiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtSHViJyBjbGFzczogRW51bWVyYXRpb24gb2YgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtSHViKGluaXQpIHtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFZpcnR1YWwgSHVicyAqL1xyXG4gICAgICAgIHRoaXMuTnVtSHViX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSHVicyAqL1xyXG4gICAgICAgIHRoaXMuSHViTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUh1YjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtSHViID0gVnBuUnBjRW51bUh1YjtcclxuLyoqIEVudW1lcmF0aW9uIGl0ZW1zIG9mIElQIHRhYmxlICovXHJcbnZhciBWcG5ScGNFbnVtSXBUYWJsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUlwVGFibGVJdGVtJyBjbGFzczogRW51bWVyYXRpb24gaXRlbXMgb2YgSVAgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1JcFRhYmxlSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIEtleSBJRCAqL1xyXG4gICAgICAgIHRoaXMuS2V5X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlc3Npb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogQXNzaWduZWQgYnkgdGhlIERIQ1AgKi9cclxuICAgICAgICB0aGlzLkRoY3BBbGxvY2F0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIFVwZGF0aW5nIGRhdGUgKi9cclxuICAgICAgICB0aGlzLlVwZGF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogUmVtb3RlIGl0ZW1zICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVJdGVtX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogUmVtb3RlIGhvc3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUmVtb3RlSG9zdG5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1JcFRhYmxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtSXBUYWJsZUl0ZW0gPSBWcG5ScGNFbnVtSXBUYWJsZUl0ZW07XHJcbi8qKiBFbnVtZXJhdGlvbiBvZiBJUCB0YWJsZSAqL1xyXG52YXIgVnBuUnBjRW51bUlwVGFibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUlwVGFibGUnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiBJUCB0YWJsZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUlwVGFibGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgdGFibGUgKi9cclxuICAgICAgICB0aGlzLklwVGFibGUgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1JcFRhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1JcFRhYmxlID0gVnBuUnBjRW51bUlwVGFibGU7XHJcbi8qKiBMYXllci0zIGludGVyZmFjZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUwzSWYgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUwzSWYnIGNsYXNzOiBMYXllci0zIGludGVyZmFjZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUwzSWYoaW5pdCkge1xyXG4gICAgICAgIC8qKiBMYXllci0zIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIExheWVyLTMgaW50ZXJmYWNlIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkwzSUZMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNJZjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNJZiA9IFZwblJwY0VudW1MM0lmO1xyXG4vKiogTGF5ZXItMyBzd2l0Y2ggZW51bWVyYXRpb24gaXRlbSAqL1xyXG52YXIgVnBuUnBjRW51bUwzU3dJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1MM1N3SXRlbScgY2xhc3M6IExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uIGl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1MM1N3SXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIE5hbWUgb2YgdGhlIGxheWVyLTMgc3dpdGNoICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBsYXllci0zIHN3aXRjaCB2aXJ0dWFsIGludGVyZmFjZXMgKi9cclxuICAgICAgICB0aGlzLk51bUludGVyZmFjZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHJvdXRpbmcgdGFibGVzICovXHJcbiAgICAgICAgdGhpcy5OdW1UYWJsZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZhdGVkIGZsYWcgKi9cclxuICAgICAgICB0aGlzLkFjdGl2ZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUwzU3dJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1MM1N3SXRlbSA9IFZwblJwY0VudW1MM1N3SXRlbTtcclxuLyoqIExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTDNTdyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTDNTdycgY2xhc3M6IExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTDNTdyhpbml0KSB7XHJcbiAgICAgICAgLyoqIExheWVyLTMgc3dpdGNoIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkwzU1dMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNTdztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNTdyA9IFZwblJwY0VudW1MM1N3O1xyXG4vKiogUm91dGluZyB0YWJsZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUwzVGFibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUwzVGFibGUnIGNsYXNzOiBSb3V0aW5nIHRhYmxlIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTDNUYWJsZShpbml0KSB7XHJcbiAgICAgICAgLyoqIEwzIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFJvdXRpbmcgdGFibGUgaXRlbSBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5MM1RhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNUYWJsZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNUYWJsZSA9IFZwblJwY0VudW1MM1RhYmxlO1xyXG4vKiogQ2FzY2FkZSBDb25uZWN0aW9uIEVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTGlua0l0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxpbmtJdGVtJyBjbGFzczogQ2FzY2FkZSBDb25uZWN0aW9uIEVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTGlua0l0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgbmFtZSBvZiBjYXNjYWRlIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkFjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyBpbmRpY2F0ZXMgd2hldGhlciB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGVzdGFibGlzaGVkICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZXJyb3IgbGFzdCBvY2N1cnJlZCBpZiB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGluIHRoZSBmYWlsIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5MYXN0RXJyb3JfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBjb21wbGV0aW9uIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5UYXJnZXRIdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTGlua0l0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUxpbmtJdGVtID0gVnBuUnBjRW51bUxpbmtJdGVtO1xyXG4vKiogRW51bWVyYXRpb24gb2YgdGhlIGxpbmsgKi9cclxudmFyIFZwblJwY0VudW1MaW5rID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1MaW5rJyBjbGFzczogRW51bWVyYXRpb24gb2YgdGhlIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1MaW5rKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNhc2NhZGUgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bUxpbmtfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGxpc3Qgb2YgY2FzY2FkZSBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTGlua0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1MaW5rO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1MaW5rID0gVnBuUnBjRW51bUxpbms7XHJcbi8qKiBMaXN0IG9mIGxpc3RlbmVycyBpdGVtICovXHJcbnZhciBWcG5ScGNMaXN0ZW5lckxpc3RJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0xpc3RlbmVyTGlzdEl0ZW0nIGNsYXNzOiBMaXN0IG9mIGxpc3RlbmVycyBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaXN0ZW5lckxpc3RJdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogVENQIHBvcnQgbnVtYmVyIChyYW5nZTogMSAtIDY1NTM1KSAqL1xyXG4gICAgICAgIHRoaXMuUG9ydHNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZlIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5FbmFibGVzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIGVycm9yIG9jY3VycmVkIG9uIHRoZSBsaXN0ZW5lciBwb3J0ICovXHJcbiAgICAgICAgdGhpcy5FcnJvcnNfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXJMaXN0SXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMaXN0ZW5lckxpc3RJdGVtID0gVnBuUnBjTGlzdGVuZXJMaXN0SXRlbTtcclxuLyoqIExpc3Qgb2YgbGlzdGVuZXJzICovXHJcbnZhciBWcG5ScGNMaXN0ZW5lckxpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTGlzdGVuZXJMaXN0JyBjbGFzczogTGlzdCBvZiBsaXN0ZW5lcnMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0xpc3RlbmVyTGlzdChpbml0KSB7XHJcbiAgICAgICAgLyoqIExpc3Qgb2YgbGlzdGVuZXIgaXRlbXMgKi9cclxuICAgICAgICB0aGlzLkxpc3RlbmVyTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXJMaXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0xpc3RlbmVyTGlzdCA9IFZwblJwY0xpc3RlbmVyTGlzdDtcclxuLyoqIExvY2FsIEJyaWRnZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUxvY2FsQnJpZGdlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Mb2NhbEJyaWRnZScgY2xhc3M6IExvY2FsIEJyaWRnZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUxvY2FsQnJpZGdlKGluaXQpIHtcclxuICAgICAgICAvKiogTG9jYWwgQnJpZGdlIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkxvY2FsQnJpZGdlTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUxvY2FsQnJpZGdlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Mb2NhbEJyaWRnZSA9IFZwblJwY0VudW1Mb2NhbEJyaWRnZTtcclxuLyoqIExvZyBmaWxlIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTG9nRmlsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxvZ0ZpbGVJdGVtJyBjbGFzczogTG9nIGZpbGUgZW51bWVyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Mb2dGaWxlSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEZpbGUgcGF0aCAqL1xyXG4gICAgICAgIHRoaXMuRmlsZVBhdGhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogRmlsZSBzaXplICovXHJcbiAgICAgICAgdGhpcy5GaWxlU2l6ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBMYXN0IHdyaXRlIGRhdGUgKi9cclxuICAgICAgICB0aGlzLlVwZGF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Mb2dGaWxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTG9nRmlsZUl0ZW0gPSBWcG5ScGNFbnVtTG9nRmlsZUl0ZW07XHJcbi8qKiBMb2cgZmlsZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUxvZ0ZpbGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxvZ0ZpbGUnIGNsYXNzOiBMb2cgZmlsZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUxvZ0ZpbGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBMb2cgZmlsZSBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5Mb2dGaWxlcyA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUxvZ0ZpbGU7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUxvZ0ZpbGUgPSBWcG5ScGNFbnVtTG9nRmlsZTtcclxuLyoqIEVudW1lcmF0aW9uIGl0ZW1zIG9mIHRoZSBNQUMgdGFibGUgKi9cclxudmFyIFZwblJwY0VudW1NYWNUYWJsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bU1hY1RhYmxlSXRlbScgY2xhc3M6IEVudW1lcmF0aW9uIGl0ZW1zIG9mIHRoZSBNQUMgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1NYWNUYWJsZUl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBLZXkgSUQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE1BQyBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5NYWNBZGRyZXNzX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ3JlYXRpb24gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBVcGRhdGluZyBkYXRlICovXHJcbiAgICAgICAgdGhpcy5VcGRhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBpdGVtcyAqL1xyXG4gICAgICAgIHRoaXMuUmVtb3RlSXRlbV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlJlbW90ZUhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZMQU4gSUQgKi9cclxuICAgICAgICB0aGlzLlZsYW5JZF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bU1hY1RhYmxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTWFjVGFibGVJdGVtID0gVnBuUnBjRW51bU1hY1RhYmxlSXRlbTtcclxuLyoqIEVudW1lcmF0aW9uIG9mIHRoZSBNQUMgdGFibGUgKi9cclxudmFyIFZwblJwY0VudW1NYWNUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTWFjVGFibGUnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiB0aGUgTUFDIHRhYmxlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTWFjVGFibGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgdGFibGUgKi9cclxuICAgICAgICB0aGlzLk1hY1RhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTWFjVGFibGU7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU1hY1RhYmxlID0gVnBuUnBjRW51bU1hY1RhYmxlO1xyXG4vKiogTkFUIEVudHJ5IFByb3RvY29sIE51bWJlciAqL1xyXG52YXIgVnBuUnBjTmF0UHJvdG9jb2w7XHJcbihmdW5jdGlvbiAoVnBuUnBjTmF0UHJvdG9jb2wpIHtcclxuICAgIC8qKiBUQ1AgKi9cclxuICAgIFZwblJwY05hdFByb3RvY29sW1ZwblJwY05hdFByb3RvY29sW1wiVENQXCJdID0gMF0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuUnBjTmF0UHJvdG9jb2xbVnBuUnBjTmF0UHJvdG9jb2xbXCJVRFBcIl0gPSAxXSA9IFwiVURQXCI7XHJcbiAgICAvKiogRE5TICovXHJcbiAgICBWcG5ScGNOYXRQcm90b2NvbFtWcG5ScGNOYXRQcm90b2NvbFtcIkROU1wiXSA9IDJdID0gXCJETlNcIjtcclxuICAgIC8qKiBJQ01QICovXHJcbiAgICBWcG5ScGNOYXRQcm90b2NvbFtWcG5ScGNOYXRQcm90b2NvbFtcIklDTVBcIl0gPSAzXSA9IFwiSUNNUFwiO1xyXG59KShWcG5ScGNOYXRQcm90b2NvbCA9IGV4cG9ydHMuVnBuUnBjTmF0UHJvdG9jb2wgfHwgKGV4cG9ydHMuVnBuUnBjTmF0UHJvdG9jb2wgPSB7fSkpO1xyXG4vKiogU3RhdGUgb2YgTkFUIHNlc3Npb24gKFRDUCkgKi9cclxudmFyIFZwblJwY05hdFRjcFN0YXRlO1xyXG4oZnVuY3Rpb24gKFZwblJwY05hdFRjcFN0YXRlKSB7XHJcbiAgICAvKiogQ29ubmVjdGluZyAqL1xyXG4gICAgVnBuUnBjTmF0VGNwU3RhdGVbVnBuUnBjTmF0VGNwU3RhdGVbXCJDb25uZWN0aW5nXCJdID0gMF0gPSBcIkNvbm5lY3RpbmdcIjtcclxuICAgIC8qKiBTZW5kIHRoZSBSU1QgKENvbm5lY3Rpb24gZmFpbHVyZSBvciBkaXNjb25uZWN0ZWQpICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIlNlbmRSZXNldFwiXSA9IDFdID0gXCJTZW5kUmVzZXRcIjtcclxuICAgIC8qKiBDb25uZWN0aW9uIGNvbXBsZXRlICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIkNvbm5lY3RlZFwiXSA9IDJdID0gXCJDb25uZWN0ZWRcIjtcclxuICAgIC8qKiBDb25uZWN0aW9uIGVzdGFibGlzaGVkICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIkVzdGFibGlzaGVkXCJdID0gM10gPSBcIkVzdGFibGlzaGVkXCI7XHJcbiAgICAvKiogV2FpdCBmb3Igc29ja2V0IGRpc2Nvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY05hdFRjcFN0YXRlW1ZwblJwY05hdFRjcFN0YXRlW1wiV2FpdERpc2Nvbm5lY3RcIl0gPSA0XSA9IFwiV2FpdERpc2Nvbm5lY3RcIjtcclxufSkoVnBuUnBjTmF0VGNwU3RhdGUgPSBleHBvcnRzLlZwblJwY05hdFRjcFN0YXRlIHx8IChleHBvcnRzLlZwblJwY05hdFRjcFN0YXRlID0ge30pKTtcclxuLyoqIFZwblJwY0VudW1OYXQgTGlzdCBJdGVtICovXHJcbnZhciBWcG5ScGNFbnVtTmF0SXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTmF0SXRlbScgY2xhc3M6IFZwblJwY0VudW1OYXQgTGlzdCBJdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTmF0SXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIElEICovXHJcbiAgICAgICAgdGhpcy5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBQcm90b2NvbCAqL1xyXG4gICAgICAgIHRoaXMuUHJvdG9jb2xfdTMyID0gMDtcclxuICAgICAgICAvKiogU291cmNlIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLlNyY0lwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU291cmNlIGhvc3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU3JjSG9zdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgcG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNyY1BvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuRGVzdElwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gaG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXN0SG9zdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiBwb3J0IG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuRGVzdFBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBUcmFuc21pc3Npb24gc2l6ZSAqL1xyXG4gICAgICAgIHRoaXMuU2VuZFNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogUmVjZWl2ZSBzaXplICovXHJcbiAgICAgICAgdGhpcy5SZWN2U2l6ZV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUQ1Agc3RhdGUgKi9cclxuICAgICAgICB0aGlzLlRjcFN0YXR1c191MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bU5hdEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU5hdEl0ZW0gPSBWcG5ScGNFbnVtTmF0SXRlbTtcclxuLyoqIFJQQ19FTlVNX05BVCAqL1xyXG52YXIgVnBuUnBjRW51bU5hdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTmF0JyBjbGFzczogUlBDX0VOVU1fTkFUICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTmF0KGluaXQpIHtcclxuICAgICAgICAvKiogVmlydHVhbCBIdWIgTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOQVQgaXRlbSAqL1xyXG4gICAgICAgIHRoaXMuTmF0VGFibGUgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1OYXQ7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU5hdCA9IFZwblJwY0VudW1OYXQ7XHJcbi8qKiBFbnVtZXJhdGlvbiBpdGVtIG9mIFZQTiBzZXNzaW9uICovXHJcbnZhciBWcG5ScGNFbnVtU2Vzc2lvbkl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bVNlc3Npb25JdGVtJyBjbGFzczogRW51bWVyYXRpb24gaXRlbSBvZiBWUE4gc2Vzc2lvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bVNlc3Npb25JdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogU2Vzc2lvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVTZXNzaW9uX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogUmVtb3RlIHNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVIb3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2VyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlVzZXJuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLkNsaWVudElQX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiB1bmRlcmx5aW5nIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTWF4TnVtVGNwX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IHVuZGVybHlpbmcgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50TnVtVGNwX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFBhY2tldCBzaXplIHRyYW5zbWl0dGVkICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRTaXplX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBwYWNrZXRzIHRyYW5zbWl0dGVkICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXROdW1fdTY0ID0gMDtcclxuICAgICAgICAvKiogSXMgYSBDYXNjYWRlIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5MaW5rTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElzIGEgU2VjdXJlTkFUIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZWN1cmVOQVRNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgdGhlIFZQTiBzZXNzaW9uIGZvciBMb2NhbCBCcmlkZ2UgKi9cclxuICAgICAgICB0aGlzLkJyaWRnZU1vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBJcyBhIExheWVyLTMgU3dpdGNoIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5MYXllcjNNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgaW4gQnJpZGdlIE1vZGUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudF9CcmlkZ2VNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgaW4gTW9uaXRvciBNb2RlICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRfTW9uaXRvck1vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBWTEFOIElEICovXHJcbiAgICAgICAgdGhpcy5WTGFuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVW5pcXVlIElEIG9mIHRoZSBWUE4gU2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuVW5pcXVlSWRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bVNlc3Npb25JdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1TZXNzaW9uSXRlbSA9IFZwblJwY0VudW1TZXNzaW9uSXRlbTtcclxuLyoqIEVudW1lcmF0ZSBWUE4gc2Vzc2lvbnMgKi9cclxudmFyIFZwblJwY0VudW1TZXNzaW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1TZXNzaW9uJyBjbGFzczogRW51bWVyYXRlIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bVNlc3Npb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBWUE4gc2Vzc2lvbnMgbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbkxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1TZXNzaW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1TZXNzaW9uID0gVnBuUnBjRW51bVNlc3Npb247XHJcbi8qKiBFbnVtZXJhdGlvbiBpdGVtIG9mIHVzZXIgKi9cclxudmFyIFZwblJwY0VudW1Vc2VySXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtVXNlckl0ZW0nIGNsYXNzOiBFbnVtZXJhdGlvbiBpdGVtIG9mIHVzZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Vc2VySXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFVzZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBHcm91cCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Hcm91cE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUmVhbCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOb3RlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEF1dGhlbnRpY2F0aW9uIG1ldGhvZCAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvZ2lucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICAvKiogTGFzdCBsb2dpbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0TG9naW5UaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogQWNjZXNzIGRlbmllZCAqL1xyXG4gICAgICAgIHRoaXMuRGVueUFjY2Vzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEZsYWcgb2Ygd2hldGhlciB0aGUgdHJhZmZpYyB2YXJpYWJsZSBpcyBzZXQgKi9cclxuICAgICAgICB0aGlzLklzVHJhZmZpY0ZpbGxlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEZsYWcgb2Ygd2hldGhlciBleHBpcmF0aW9uIGRhdGUgdmFyaWFibGUgaXMgc2V0ICovXHJcbiAgICAgICAgdGhpcy5Jc0V4cGlyZXNGaWxsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBFeHBpcmF0aW9uIGRhdGUgKi9cclxuICAgICAgICB0aGlzLkV4cGlyZXNfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5SZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Vc2VySXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtVXNlckl0ZW0gPSBWcG5ScGNFbnVtVXNlckl0ZW07XHJcbi8qKiBFbnVtZXJhdGlvbiBvZiB1c2VyICovXHJcbnZhciBWcG5ScGNFbnVtVXNlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtVXNlcicgY2xhc3M6IEVudW1lcmF0aW9uIG9mIHVzZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Vc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5Vc2VyTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bVVzZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bVVzZXIgPSBWcG5ScGNFbnVtVXNlcjtcclxuLyoqIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgSXRlbSAqL1xyXG52YXIgVnBuQWMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQWMnIGNsYXNzOiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0IEl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwbkFjKGluaXQpIHtcclxuICAgICAgICAvKiogSUQgKi9cclxuICAgICAgICB0aGlzLklkX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByaW9yaXR5ICovXHJcbiAgICAgICAgdGhpcy5Qcmlvcml0eV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZW55IGFjY2VzcyAqL1xyXG4gICAgICAgIHRoaXMuRGVueV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNldCB0cnVlIGlmIHlvdSB3YW50IHRvIHNwZWNpZnkgdGhlIFN1Ym5ldE1hc2tfaXAgaXRlbS4gKi9cclxuICAgICAgICB0aGlzLk1hc2tlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFN1Ym5ldCBtYXNrLCB2YWxpZCBvbmx5IGlmIE1hc2tlZF9ib29sID09IHRydWUgKi9cclxuICAgICAgICB0aGlzLlN1Ym5ldE1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQWM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuQWMgPSBWcG5BYztcclxuLyoqIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgKi9cclxudmFyIFZwblJwY0FjTGlzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNBY0xpc3QnIGNsYXNzOiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNBY0xpc3QoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0ICovXHJcbiAgICAgICAgdGhpcy5BQ0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0FjTGlzdDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNBY0xpc3QgPSBWcG5ScGNBY0xpc3Q7XHJcbi8qKiBNZXNzYWdlICovXHJcbnZhciBWcG5ScGNNc2cgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTXNnJyBjbGFzczogTWVzc2FnZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTXNnKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTWVzc2FnZSAoVW5pY29kZSBzdHJpbmdzIGFjY2VwdGFibGUpICovXHJcbiAgICAgICAgdGhpcy5Nc2dfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTXNnO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY01zZyA9IFZwblJwY01zZztcclxuLyoqIEdldCAvIFNldCB0aGUgQXp1cmUgc3RhdGUgKi9cclxudmFyIFZwblJwY0F6dXJlU3RhdHVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0F6dXJlU3RhdHVzJyBjbGFzczogR2V0IC8gU2V0IHRoZSBBenVyZSBzdGF0ZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQXp1cmVTdGF0dXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFZQTiBBenVyZSBGdW5jdGlvbiBpcyBFbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5Jc0VuYWJsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIGNvbm5lY3Rpb24gdG8gVlBOIEF6dXJlIENsb3VkIFNlcnZlciBpcyBlc3RhYmxpc2hlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNDb25uZWN0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjQXp1cmVTdGF0dXM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQXp1cmVTdGF0dXMgPSBWcG5ScGNBenVyZVN0YXR1cztcclxuLyoqIExvY2FsIEJyaWRnZSBzdXBwb3J0IGluZm9ybWF0aW9uICovXHJcbnZhciBWcG5ScGNCcmlkZ2VTdXBwb3J0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0JyaWRnZVN1cHBvcnQnIGNsYXNzOiBMb2NhbCBCcmlkZ2Ugc3VwcG9ydCBpbmZvcm1hdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQnJpZGdlU3VwcG9ydChpbml0KSB7XHJcbiAgICAgICAgLyoqIFdoZXRoZXIgdGhlIE9TIHN1cHBvcnRzIHRoZSBMb2NhbCBCcmlkZ2UgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLklzQnJpZGdlU3VwcG9ydGVkT3NfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFdpblBjYXAgaXMgbmVjZXNzYXJ5IHRvIGluc3RhbGwgKi9cclxuICAgICAgICB0aGlzLklzV2luUGNhcE5lZWRlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNCcmlkZ2VTdXBwb3J0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0JyaWRnZVN1cHBvcnQgPSBWcG5ScGNCcmlkZ2VTdXBwb3J0O1xyXG4vKiogR2V0IHRoZSBDQSBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkdldENBID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YkdldENBJyBjbGFzczogR2V0IHRoZSBDQSBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkdldENBKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIGtleSBpZCBvZiB0aGUgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgWC41MDkgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViR2V0Q0E7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViR2V0Q0EgPSBWcG5ScGNIdWJHZXRDQTtcclxuLyoqIENhcHMgaXRlbSBvZiB0aGUgVlBOIFNlcnZlciAqL1xyXG52YXIgVnBuQ2FwcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5DYXBzJyBjbGFzczogQ2FwcyBpdGVtIG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICBmdW5jdGlvbiBWcG5DYXBzKGluaXQpIHtcclxuICAgICAgICAvKiogTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ2Fwc05hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsdWUgKi9cclxuICAgICAgICB0aGlzLkNhcHNWYWx1ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZXNjcnB0aW9uICovXHJcbiAgICAgICAgdGhpcy5DYXBzRGVzY3JwdGlvbl91dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQ2FwcztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5DYXBzID0gVnBuQ2FwcztcclxuLyoqIENhcHMgbGlzdCBvZiB0aGUgVlBOIFNlcnZlciAqL1xyXG52YXIgVnBuQ2Fwc2xpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQ2Fwc2xpc3QnIGNsYXNzOiBDYXBzIGxpc3Qgb2YgdGhlIFZQTiBTZXJ2ZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkNhcHNsaXN0KGluaXQpIHtcclxuICAgICAgICAvKiogQ2FwcyBsaXN0IG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5DYXBzTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQ2Fwc2xpc3Q7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuQ2Fwc2xpc3QgPSBWcG5DYXBzbGlzdDtcclxuLyoqIENvbmZpZyBvcGVyYXRpb24gKi9cclxudmFyIFZwblJwY0NvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNDb25maWcnIGNsYXNzOiBDb25maWcgb3BlcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBGaWxlIG5hbWUgKHZhbGlkIG9ubHkgZm9yIHJldHVybmluZyBmcm9tIHRoZSBzZXJ2ZXIpICovXHJcbiAgICAgICAgdGhpcy5GaWxlTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBGaWxlIGRhdGEgKi9cclxuICAgICAgICB0aGlzLkZpbGVEYXRhX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0NvbmZpZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNDb25maWcgPSBWcG5ScGNDb25maWc7XHJcbi8qKiBDb25uZWN0aW9uIGluZm9ybWF0aW9uICovXHJcbnZhciBWcG5ScGNDb25uZWN0aW9uSW5mbyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNDb25uZWN0aW9uSW5mbycgY2xhc3M6IENvbm5lY3Rpb24gaW5mb3JtYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Nvbm5lY3Rpb25JbmZvKGluaXQpIHtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFR5cGUgKi9cclxuICAgICAgICB0aGlzLlR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBJUCBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5JcF9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5Qb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENvbm5lY3RlZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogU2VydmVyIHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyU3RyX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNlcnZlciB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJWZXJfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIGJ1aWxkIG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50U3RyX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRWZXJfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IGJ1aWxkIG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50QnVpbGRfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0Nvbm5lY3Rpb25JbmZvO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0Nvbm5lY3Rpb25JbmZvID0gVnBuUnBjQ29ubmVjdGlvbkluZm87XHJcbi8qKiBQcm94eSB0eXBlICovXHJcbnZhciBWcG5ScGNQcm94eVR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjUHJveHlUeXBlKSB7XHJcbiAgICAvKiogRGlyZWN0IFRDUCBjb25uZWN0aW9uICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiRGlyZWN0XCJdID0gMF0gPSBcIkRpcmVjdFwiO1xyXG4gICAgLyoqIENvbm5lY3Rpb24gdmlhIEhUVFAgcHJveHkgc2VydmVyICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiSFRUUFwiXSA9IDFdID0gXCJIVFRQXCI7XHJcbiAgICAvKiogQ29ubmVjdGlvbiB2aWEgU09DS1MgcHJveHkgc2VydmVyICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiU09DS1NcIl0gPSAyXSA9IFwiU09DS1NcIjtcclxufSkoVnBuUnBjUHJveHlUeXBlID0gZXhwb3J0cy5WcG5ScGNQcm94eVR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjUHJveHlUeXBlID0ge30pKTtcclxuLyoqIFRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgREROUyAqL1xyXG52YXIgVnBuRERuc0NsaWVudFN0YXR1cyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ERG5zQ2xpZW50U3RhdHVzJyBjbGFzczogVGhlIGN1cnJlbnQgc3RhdHVzIG9mIHRoZSBERE5TICovXHJcbiAgICBmdW5jdGlvbiBWcG5ERG5zQ2xpZW50U3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogTGFzdCBlcnJvciBjb2RlIChJUHY0KSAqL1xyXG4gICAgICAgIHRoaXMuRXJyX0lQdjRfdTMyID0gMDtcclxuICAgICAgICAvKiogTGFzdCBlcnJvciBzdHJpbmcgKElQdjQpICovXHJcbiAgICAgICAgdGhpcy5FcnJTdHJfSVB2NF91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIGNvZGUgKElQdjYpICovXHJcbiAgICAgICAgdGhpcy5FcnJfSVB2Nl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIHN0cmluZyAoSVB2NikgKi9cclxuICAgICAgICB0aGlzLkVyclN0cl9JUHY2X3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEN1cnJlbnQgREROUyBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRIb3N0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDdXJyZW50IEZRRE4gb2YgdGhlIERETlMgaG9zdG5hbWUgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRGcWRuX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIERETlMgc3VmZml4ICovXHJcbiAgICAgICAgdGhpcy5EbnNTdWZmaXhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ3VycmVudCBJUHY0IGFkZHJlc3Mgb2YgdGhlIFZQTiBTZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRJUHY0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEN1cnJlbnQgSVB2NiBhZGRyZXNzIG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50SVB2Nl9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuRERuc0NsaWVudFN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ERG5zQ2xpZW50U3RhdHVzID0gVnBuRERuc0NsaWVudFN0YXR1cztcclxuLyoqIEludGVybmV0IGNvbm5lY3Rpb24gc2V0dGluZ3MgKi9cclxudmFyIFZwbkludGVybmV0U2V0dGluZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5JbnRlcm5ldFNldHRpbmcnIGNsYXNzOiBJbnRlcm5ldCBjb25uZWN0aW9uIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5JbnRlcm5ldFNldHRpbmcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHByb3h5IHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByb3h5IHNlcnZlciBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlByb3h5SG9zdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUHJveHkgc2VydmVyIHBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5Qcm94eVBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogUHJveHkgc2VydmVyIHVzZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlVc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBQcm94eSBzZXJ2ZXIgcGFzc3dvcmQgKi9cclxuICAgICAgICB0aGlzLlByb3h5UGFzc3dvcmRfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwbkludGVybmV0U2V0dGluZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5JbnRlcm5ldFNldHRpbmcgPSBWcG5JbnRlcm5ldFNldHRpbmc7XHJcbi8qKiBBZG1pbmlzdHJhdGlvbiBvcHRpb25zICovXHJcbnZhciBWcG5BZG1pbk9wdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5BZG1pbk9wdGlvbicgY2xhc3M6IEFkbWluaXN0cmF0aW9uIG9wdGlvbnMgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkFkbWluT3B0aW9uKGluaXQpIHtcclxuICAgICAgICAvKiogTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEYXRhICovXHJcbiAgICAgICAgdGhpcy5WYWx1ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZXNjcnB0aW9uICovXHJcbiAgICAgICAgdGhpcy5EZXNjcnB0aW9uX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5BZG1pbk9wdGlvbjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5BZG1pbk9wdGlvbiA9IFZwbkFkbWluT3B0aW9uO1xyXG4vKiogQWRtaW5pc3RyYXRpb24gb3B0aW9ucyBsaXN0ICovXHJcbnZhciBWcG5ScGNBZG1pbk9wdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNBZG1pbk9wdGlvbicgY2xhc3M6IEFkbWluaXN0cmF0aW9uIG9wdGlvbnMgbGlzdCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQWRtaW5PcHRpb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBWaXJ0dWFsIEhVQiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIExpc3QgZGF0YSAqL1xyXG4gICAgICAgIHRoaXMuQWRtaW5PcHRpb25MaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNBZG1pbk9wdGlvbjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNBZG1pbk9wdGlvbiA9IFZwblJwY0FkbWluT3B0aW9uO1xyXG4vKiogQ29ubmVjdGlvbiBzdGF0ZSB0byB0aGUgY29udHJvbGxlciAqL1xyXG52YXIgVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMnIGNsYXNzOiBDb25uZWN0aW9uIHN0YXRlIHRvIHRoZSBjb250cm9sbGVyICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNGYXJtQ29ubmVjdGlvblN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogUG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogT25saW5lIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIGNvZGUgKi9cclxuICAgICAgICB0aGlzLkxhc3RFcnJvcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHN0YXJ0IHRpbWUgKi9cclxuICAgICAgICB0aGlzLlN0YXJ0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogRmlyc3QgY29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5GaXJzdENvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHRpbWUgb2YgdGhpcyB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50Q29ubmVjdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZXRyaWVzICovXHJcbiAgICAgICAgdGhpcy5OdW1UcnlfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb24gY291bnQgKi9cclxuICAgICAgICB0aGlzLk51bUNvbm5lY3RlZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIGZhaWx1cmUgY291bnQgKi9cclxuICAgICAgICB0aGlzLk51bUZhaWxlZF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMgPSBWcG5ScGNGYXJtQ29ubmVjdGlvblN0YXR1cztcclxuLyoqIEhVQiBpdGVtIG9mIGVhY2ggZmFybSBtZW1iZXIgKi9cclxudmFyIFZwblJwY0Zhcm1IdWIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybUh1YicgY2xhc3M6IEhVQiBpdGVtIG9mIGVhY2ggZmFybSBtZW1iZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Zhcm1IdWIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEeW5hbWljIEhVQiAqL1xyXG4gICAgICAgIHRoaXMuRHluYW1pY0h1Yl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNGYXJtSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0Zhcm1IdWIgPSBWcG5ScGNGYXJtSHViO1xyXG4vKiogU2VydmVyIGZhcm0gbWVtYmVyIGluZm9ybWF0aW9uIGFjcXVpc2l0aW9uICovXHJcbnZhciBWcG5ScGNGYXJtSW5mbyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNGYXJtSW5mbycgY2xhc3M6IFNlcnZlciBmYXJtIG1lbWJlciBpbmZvcm1hdGlvbiBhY3F1aXNpdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRmFybUluZm8oaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGZsYWcgaWYgdGhlIHNlcnZlciBpcyBDbHVzdGVyIENvbnRyb2xsZXIgKGZhbHNlOiBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuQ29udHJvbGxlcl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gRXN0YWJsaXNoZWQgVGltZSAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBQb2ludCAqL1xyXG4gICAgICAgIHRoaXMuUG9pbnRfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFB1YmxpYyBQb3J0cyAqL1xyXG4gICAgICAgIHRoaXMuTnVtUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBQdWJsaWMgUG9ydHMgKi9cclxuICAgICAgICB0aGlzLlBvcnRzX3UzMiA9IFtdO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgZmFybSBIVUIgKi9cclxuICAgICAgICB0aGlzLk51bUZhcm1IdWJfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGhvc3RlZCBWaXJ0dWFsIEh1YiBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5IdWJzTGlzdCA9IFtdO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgaG9zdGVkIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogUGVyZm9ybWFuY2UgU3RhbmRhcmQgUmF0aW8gKi9cclxuICAgICAgICB0aGlzLldlaWdodF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRmFybUluZm87XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybUluZm8gPSBWcG5ScGNGYXJtSW5mbztcclxuLyoqIFNlcnZlciBmYXJtIGNvbmZpZ3VyYXRpb24gKi9cclxudmFyIFZwblJwY0Zhcm0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybScgY2xhc3M6IFNlcnZlciBmYXJtIGNvbmZpZ3VyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Zhcm0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGZvciBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzLiBOdW1iZXIgb2YgdGhlIFBvcnRzX3UzMiBlbGVtZW50LiAqL1xyXG4gICAgICAgIHRoaXMuTnVtUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGZvciBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzLiBTcGVjaWZ5IHRoZSBsaXN0IG9mIHB1YmxpYyBwb3J0IG51bWJlcnMgb24gdGhpcyBzZXJ2ZXIuIFRoZSBsaXN0IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgcHVibGljIHBvcnQgbnVtYmVyIHNldCwgYW5kIGl0IGlzIGFsc28gcG9zc2libGUgdG8gc2V0IG11bHRpcGxlIHB1YmxpYyBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5Qb3J0c191MzIgPSBbXTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgcHVibGljIElQIGFkZHJlc3Mgb2YgdGhpcyBzZXJ2ZXIuIElmIHlvdSB3aXNoIHRvIGxlYXZlIHB1YmxpYyBJUCBhZGRyZXNzIHVuc3BlY2lmaWVkLCBzcGVjaWZ5IHRoZSBlbXB0eSBzdHJpbmcuIFdoZW4gYSBwdWJsaWMgSVAgYWRkcmVzcyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgSVAgYWRkcmVzcyBvZiB0aGUgbmV0d29yayBpbnRlcmZhY2UgdXNlZCB3aGVuIGNvbm5lY3RpbmcgdG8gdGhlIGNsdXN0ZXIgY29udHJvbGxlciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgdXNlZC4gKi9cclxuICAgICAgICB0aGlzLlB1YmxpY0lwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgaG9zdCBuYW1lIG9yIElQIGFkZHJlc3Mgb2YgdGhlIGRlc3RpbmF0aW9uIGNsdXN0ZXIgY29udHJvbGxlci4gKi9cclxuICAgICAgICB0aGlzLkNvbnRyb2xsZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgZm9yIENsdXN0ZXIgTWVtYmVyIHNlcnZlcnMuIFNwZWNpZnkgdGhlIFRDUCBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gY2x1c3RlciBjb250cm9sbGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQ29udHJvbGxlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgcGFzc3dvcmQgcmVxdWlyZWQgdG8gY29ubmVjdCB0byB0aGUgZGVzdGluYXRpb24gY29udHJvbGxlci4gSXQgbmVlZHMgdG8gYmUgdGhlIHNhbWUgYXMgYW4gYWRtaW5pc3RyYXRvciBwYXNzd29yZCBvbiB0aGUgZGVzdGluYXRpb24gY29udHJvbGxlci4gKi9cclxuICAgICAgICB0aGlzLk1lbWJlclBhc3N3b3JkUGxhaW50ZXh0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoaXMgc2V0cyBhIHZhbHVlIGZvciB0aGUgcGVyZm9ybWFuY2Ugc3RhbmRhcmQgcmF0aW8gb2YgdGhpcyBWUE4gU2VydmVyLiBUaGlzIGlzIHRoZSBzdGFuZGFyZCB2YWx1ZSBmb3Igd2hlbiBsb2FkIGJhbGFuY2luZyBpcyBwZXJmb3JtZWQgaW4gdGhlIGNsdXN0ZXIuIEZvciBleGFtcGxlLCBtYWtpbmcgb25seSBvbmUgbWFjaGluZSAyMDAgd2hpbGUgdGhlIG90aGVyIG1lbWJlcnMgaGF2ZSBhIHN0YXR1cyBvZiAxMDAsIHdpbGwgcmVndWxhdGUgdGhhdCBtYWNoaW5lIHRvIHJlY2VpdmUgdHdpY2UgYXMgbWFueSBjb25uZWN0aW9ucyBhcyB0aGUgb3RoZXIgbWVtYmVycy4gU3BlY2lmeSAxIG9yIGhpZ2hlciBmb3IgdGhlIHZhbHVlLiBJZiB0aGlzIHBhcmFtZXRlciBpcyBsZWZ0IHVuc3BlY2lmaWVkLCAxMDAgd2lsbCBiZSB1c2VkLiAqL1xyXG4gICAgICAgIHRoaXMuV2VpZ2h0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgZm9yIENsdXN0ZXIgQ29udHJvbGxlciBzZXJ2ZXIuIEJ5IHNwZWNpZnlpbmcgdHJ1ZSwgdGhlIFZQTiBTZXJ2ZXIgd2lsbCBvcGVyYXRlIG9ubHkgYXMgYSBjb250cm9sbGVyIG9uIHRoZSBjbHVzdGVyIGFuZCBpdCB3aWxsIGFsd2F5cyBkaXN0cmlidXRlIGdlbmVyYWwgVlBOIENsaWVudCBjb25uZWN0aW9ucyB0byBtZW1iZXJzIG90aGVyIHRoYW4gaXRzZWxmLiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gaGlnaC1sb2FkIGVudmlyb25tZW50cy4gKi9cclxuICAgICAgICB0aGlzLkNvbnRyb2xsZXJPbmx5X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0Zhcm07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybSA9IFZwblJwY0Zhcm07XHJcbi8qKiBMb2cgc3dpdGNoIHR5cGUgKi9cclxudmFyIFZwblJwY0xvZ1N3aXRjaFR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjTG9nU3dpdGNoVHlwZSkge1xyXG4gICAgLyoqIE5vIHN3aXRjaGluZyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiTm9cIl0gPSAwXSA9IFwiTm9cIjtcclxuICAgIC8qKiBTZWNvbmRseSBiYXNpcyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiU2Vjb25kXCJdID0gMV0gPSBcIlNlY29uZFwiO1xyXG4gICAgLyoqIE1pbnV0ZWx5IGJhc2lzICovXHJcbiAgICBWcG5ScGNMb2dTd2l0Y2hUeXBlW1ZwblJwY0xvZ1N3aXRjaFR5cGVbXCJNaW51dGVcIl0gPSAyXSA9IFwiTWludXRlXCI7XHJcbiAgICAvKiogSG91cmx5IGJhc2lzICovXHJcbiAgICBWcG5ScGNMb2dTd2l0Y2hUeXBlW1ZwblJwY0xvZ1N3aXRjaFR5cGVbXCJIb3VyXCJdID0gM10gPSBcIkhvdXJcIjtcclxuICAgIC8qKiBEYWlseSBiYXNpcyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiRGF5XCJdID0gNF0gPSBcIkRheVwiO1xyXG4gICAgLyoqIE1vbnRobHkgYmFzaXMgKi9cclxuICAgIFZwblJwY0xvZ1N3aXRjaFR5cGVbVnBuUnBjTG9nU3dpdGNoVHlwZVtcIk1vbnRoXCJdID0gNV0gPSBcIk1vbnRoXCI7XHJcbn0pKFZwblJwY0xvZ1N3aXRjaFR5cGUgPSBleHBvcnRzLlZwblJwY0xvZ1N3aXRjaFR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjTG9nU3dpdGNoVHlwZSA9IHt9KSk7XHJcbi8qKiBQYWNrZXQgbG9nIHNldHRpbmdzICovXHJcbnZhciBWcG5ScGNQYWNrZXRMb2dTZXR0aW5nO1xyXG4oZnVuY3Rpb24gKFZwblJwY1BhY2tldExvZ1NldHRpbmcpIHtcclxuICAgIC8qKiBOb3Qgc2F2ZSAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tWcG5ScGNQYWNrZXRMb2dTZXR0aW5nW1wiTm9uZVwiXSA9IDBdID0gXCJOb25lXCI7XHJcbiAgICAvKiogT25seSBoZWFkZXIgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdbVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tcIkhlYWRlclwiXSA9IDFdID0gXCJIZWFkZXJcIjtcclxuICAgIC8qKiBBbGwgcGF5bG9hZHMgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdbVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tcIkFsbFwiXSA9IDJdID0gXCJBbGxcIjtcclxufSkoVnBuUnBjUGFja2V0TG9nU2V0dGluZyA9IGV4cG9ydHMuVnBuUnBjUGFja2V0TG9nU2V0dGluZyB8fCAoZXhwb3J0cy5WcG5ScGNQYWNrZXRMb2dTZXR0aW5nID0ge30pKTtcclxuLyoqIFBhY2tldCBsb2cgc2V0dGluZ3MgYXJyYXkgaW5kZXggKi9cclxudmFyIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleDtcclxuKGZ1bmN0aW9uIChWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXgpIHtcclxuICAgIC8qKiBUQ1AgY29ubmVjdGlvbiBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJUY3BDb25uZWN0aW9uXCJdID0gMF0gPSBcIlRjcENvbm5lY3Rpb25cIjtcclxuICAgIC8qKiBUQ1AgcGFja2V0IGxvZyAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1ZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtcIlRjcEFsbFwiXSA9IDFdID0gXCJUY3BBbGxcIjtcclxuICAgIC8qKiBESENQIExvZyAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1ZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtcIkRoY3BcIl0gPSAyXSA9IFwiRGhjcFwiO1xyXG4gICAgLyoqIFVEUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJVZHBcIl0gPSAzXSA9IFwiVWRwXCI7XHJcbiAgICAvKiogSUNNUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJJY21wXCJdID0gNF0gPSBcIkljbXBcIjtcclxuICAgIC8qKiBJUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJJcFwiXSA9IDVdID0gXCJJcFwiO1xyXG4gICAgLyoqIEFSUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJBcnBcIl0gPSA2XSA9IFwiQXJwXCI7XHJcbiAgICAvKiogRXRoZXJuZXQgbG9nICovXHJcbiAgICBWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1wiRXRoZXJuZXRcIl0gPSA3XSA9IFwiRXRoZXJuZXRcIjtcclxufSkoVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4ID0gZXhwb3J0cy5WcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXggfHwgKGV4cG9ydHMuVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4ID0ge30pKTtcclxuLyoqIEhVQiBsb2cgc2V0dGluZ3MgKi9cclxudmFyIFZwblJwY0h1YkxvZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNIdWJMb2cnIGNsYXNzOiBIVUIgbG9nIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJMb2coaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB0byBlbmFibGUgLyBkaXNhYmxlIHNhdmluZyB0aGUgc2VjdXJpdHkgbG9nICovXHJcbiAgICAgICAgdGhpcy5TYXZlU2VjdXJpdHlMb2dfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgbG9nIGZpbGVuYW1lIHN3aXRjaGluZyBzZXR0aW5nIG9mIHRoZSBzZWN1cml0eSBsb2cgKi9cclxuICAgICAgICB0aGlzLlNlY3VyaXR5TG9nU3dpdGNoVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB0byBlbmFibGUgLyBkaXNhYmxlIHNhdmluZyB0aGUgc2VjdXJpdHkgbG9nICovXHJcbiAgICAgICAgdGhpcy5TYXZlUGFja2V0TG9nX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGxvZyBmaWxlbmFtZSBzd2l0Y2hpbmcgc2V0dGluZ3Mgb2YgdGhlIHBhY2tldCBsb2dzICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRMb2dTd2l0Y2hUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHNhdmUgY29udGVudHMgb2YgdGhlIHBhY2tldCBsb2dzICh1aW50ICogMTYgYXJyYXkpLiBUaGUgaW5kZXggbnVtYmVyczogVGNwQ29ubmVjdGlvbiA9IDAsIFRjcEFsbCA9IDEsIERIQ1AgPSAyLCBVRFAgPSAzLCBJQ01QID0gNCwgSVAgPSA1LCBBUlAgPSA2LCBFdGhlcm5ldCA9IDcuICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRMb2dDb25maWdfdTMyID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNIdWJMb2c7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViTG9nID0gVnBuUnBjSHViTG9nO1xyXG4vKiogUkFESVVTIHNlcnZlciBvcHRpb25zICovXHJcbnZhciBWcG5ScGNSYWRpdXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjUmFkaXVzJyBjbGFzczogUkFESVVTIHNlcnZlciBvcHRpb25zICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNSYWRpdXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSQURJVVMgc2VydmVyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1NlcnZlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUkFESVVTIHBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5SYWRpdXNQb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3JldCBrZXkgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1NlY3JldF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSYWRpdXMgcmV0cnkgaW50ZXJ2YWwgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1JldHJ5SW50ZXJ2YWxfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1JhZGl1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNSYWRpdXMgPSBWcG5ScGNSYWRpdXM7XHJcbi8qKiBHZXQgdGhlIHN0YXRlIEhVQiAqL1xyXG52YXIgVnBuUnBjSHViU3RhdHVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YlN0YXR1cycgY2xhc3M6IEdldCB0aGUgc3RhdGUgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJTdGF0dXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPbmxpbmUgKi9cclxuICAgICAgICB0aGlzLk9ubGluZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFR5cGUgb2YgSFVCICovXHJcbiAgICAgICAgdGhpcy5IdWJUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHNlc3Npb25zIChjbGllbnQgbW9kZSkgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zQ2xpZW50X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBzZXNzaW9ucyAoYnJpZGdlIG1vZGUpICovXHJcbiAgICAgICAgdGhpcy5OdW1TZXNzaW9uc0JyaWRnZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgQWNjZXNzIGxpc3QgZW50cmllcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtQWNjZXNzTGlzdHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHVzZXJzICovXHJcbiAgICAgICAgdGhpcy5OdW1Vc2Vyc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgZ3JvdXBzICovXHJcbiAgICAgICAgdGhpcy5OdW1Hcm91cHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIE1BQyB0YWJsZSBlbnRyaWVzICovXHJcbiAgICAgICAgdGhpcy5OdW1NYWNUYWJsZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIElQIHRhYmxlIGVudHJpZXMgKi9cclxuICAgICAgICB0aGlzLk51bUlwVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBjb3VudCAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFNlY3VyZU5BVCBpcyBlbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5TZWN1cmVOQVRFbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogTGFzdCBjb21tdW5pY2F0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkxhc3RDb21tVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgbG9naW4gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuTGFzdExvZ2luVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENyZWF0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvZ2lucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YlN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJTdGF0dXMgPSBWcG5ScGNIdWJTdGF0dXM7XHJcbi8qKiBMaXN0IG9mIHNlcnZpY2VzIHByb3ZpZGVkIGJ5IElQc2VjIHNlcnZlciAqL1xyXG52YXIgVnBuSVBzZWNTZXJ2aWNlcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5JUHNlY1NlcnZpY2VzJyBjbGFzczogTGlzdCBvZiBzZXJ2aWNlcyBwcm92aWRlZCBieSBJUHNlYyBzZXJ2ZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwbklQc2VjU2VydmljZXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBFbmFibGUgb3IgRGlzYWJsZSB0aGUgTDJUUCBTZXJ2ZXIgRnVuY3Rpb24gKFJhdyBMMlRQIHdpdGggTm8gRW5jcnlwdGlvbnMpLiBUbyBhY2NlcHQgc3BlY2lhbCBWUE4gY2xpZW50cywgZW5hYmxlIHRoaXMgb3B0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9SYXdfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBFbmFibGUgb3IgRGlzYWJsZSB0aGUgTDJUUCBvdmVyIElQc2VjIFNlcnZlciBGdW5jdGlvbi4gVG8gYWNjZXB0IFZQTiBjb25uZWN0aW9ucyBmcm9tIGlQaG9uZSwgaVBhZCwgQW5kcm9pZCwgV2luZG93cyBvciBNYWMgT1MgWCwgZW5hYmxlIHRoaXMgb3B0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9JUHNlY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEVuYWJsZSBvciBEaXNhYmxlIHRoZSBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgU2VydmVyIEZ1bmN0aW9uIChmb3Igc2l0ZS10by1zaXRlIFZQTiBTZXJ2ZXIgZnVuY3Rpb24pLiBSb3V0ZXIgUHJvZHVjdHMgd2hpY2ggYXJlIGNvbXBhdGlibGUgd2l0aCBFdGhlcklQIG92ZXIgSVBzZWMgY2FuIGNvbm5lY3QgdG8gVmlydHVhbCBIdWJzIG9uIHRoZSBWUE4gU2VydmVyIGFuZCBlc3RhYmxpc2ggTGF5ZXItMiAoRXRoZXJuZXQpIEJyaWRnaW5nLiAqL1xyXG4gICAgICAgIHRoaXMuRXRoZXJJUF9JUHNlY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQc2VjIFByZS1TaGFyZWQgS2V5LiBBbiBJUHNlYyBQcmUtU2hhcmVkIEtleSBpcyBhbHNvIGNhbGxlZCBhcyBcIlBTS1wiIG9yIFwic2VjcmV0XCIuIFNwZWNpZnkgaXQgZXF1YWwgb3IgbGVzcyB0aGFuIDggbGV0dGVycywgYW5kIGRpc3RyaWJ1dGUgaXQgdG8gZXZlcnkgdXNlcnMgd2hvIHdpbGwgY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4gUGxlYXNlIG5vdGU6IEdvb2dsZSBBbmRyb2lkIDQuMCBoYXMgYSBidWcgd2hpY2ggYSBQcmUtU2hhcmVkIEtleSB3aXRoIDEwIG9yIG1vcmUgbGV0dGVycyBjYXVzZXMgYSB1bmV4cGVjdGVkIGJlaGF2aW9yLiBGb3IgdGhhdCByZWFzb24sIHRoZSBsZXR0ZXJzIG9mIGEgUHJlLVNoYXJlZCBLZXkgc2hvdWxkIGJlIDkgb3IgbGVzcyBjaGFyYWN0ZXJzLiAqL1xyXG4gICAgICAgIHRoaXMuSVBzZWNfU2VjcmV0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGRlZmF1bHQgVmlydHVhbCBIVUIgaW4gYSBjYXNlIG9mIG9taXR0aW5nIHRoZSBuYW1lIG9mIEhVQiBvbiB0aGUgVXNlcm5hbWUuIFVzZXJzIHNob3VsZCBzcGVjaWZ5IHRoZWlyIHVzZXJuYW1lIHN1Y2ggYXMgXCJVc2VybmFtZUBUYXJnZXQgVmlydHVhbCBIVUIgTmFtZVwiIHRvIGNvbm5lY3QgdGhpcyBMMlRQIFNlcnZlci4gSWYgdGhlIGRlc2lnbmF0aW9uIG9mIHRoZSBWaXJ0dWFsIEh1YiBpcyBvbWl0dGVkLCB0aGUgYWJvdmUgSFVCIHdpbGwgYmUgdXNlZCBhcyB0aGUgdGFyZ2V0LiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9EZWZhdWx0SHViX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5JUHNlY1NlcnZpY2VzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwbklQc2VjU2VydmljZXMgPSBWcG5JUHNlY1NlcnZpY2VzO1xyXG4vKiogS2VlcCBhbGl2ZSBwcm90b2NvbCAqL1xyXG52YXIgVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2w7XHJcbihmdW5jdGlvbiAoVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2wpIHtcclxuICAgIC8qKiBUQ1AgKi9cclxuICAgIFZwblJwY0tlZXBBbGl2ZVByb3RvY29sW1ZwblJwY0tlZXBBbGl2ZVByb3RvY29sW1wiVENQXCJdID0gMF0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2xbVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2xbXCJVRFBcIl0gPSAxXSA9IFwiVURQXCI7XHJcbn0pKFZwblJwY0tlZXBBbGl2ZVByb3RvY29sID0gZXhwb3J0cy5WcG5ScGNLZWVwQWxpdmVQcm90b2NvbCB8fCAoZXhwb3J0cy5WcG5ScGNLZWVwQWxpdmVQcm90b2NvbCA9IHt9KSk7XHJcbi8qKiBLZWVwIEFsaXZlIHNldHRpbmdzICovXHJcbnZhciBWcG5ScGNLZWVwID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0tlZXAnIGNsYXNzOiBLZWVwIEFsaXZlIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNLZWVwKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIGtlZXAtYWxpdmUgdG8gdGhlIEludGVybmV0ICovXHJcbiAgICAgICAgdGhpcy5Vc2VLZWVwQ29ubmVjdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGhvc3QgbmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBkZXN0aW5hdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RIb3N0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RQb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByb3RvY29sIHR5cGUgKi9cclxuICAgICAgICB0aGlzLktlZXBDb25uZWN0UHJvdG9jb2xfdTMyID0gMDtcclxuICAgICAgICAvKiogSW50ZXJ2YWwgQmV0d2VlbiBQYWNrZXRzIFNlbmRzIChTZWNvbmRzKSAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RJbnRlcnZhbF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjS2VlcDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNLZWVwID0gVnBuUnBjS2VlcDtcclxuLyoqIFN0YXRlIG9mIHRoZSBjbGllbnQgc2Vzc2lvbiAqL1xyXG52YXIgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cztcclxuKGZ1bmN0aW9uIChWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzKSB7XHJcbiAgICAvKiogQ29ubmVjdGluZyAqL1xyXG4gICAgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1wiQ29ubmVjdGluZ1wiXSA9IDBdID0gXCJDb25uZWN0aW5nXCI7XHJcbiAgICAvKiogTmVnb3RpYXRpbmcgKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIk5lZ290aWF0aW9uXCJdID0gMV0gPSBcIk5lZ290aWF0aW9uXCI7XHJcbiAgICAvKiogRHVyaW5nIHVzZXIgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIkF1dGhcIl0gPSAyXSA9IFwiQXV0aFwiO1xyXG4gICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGUgKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIkVzdGFibGlzaGVkXCJdID0gM10gPSBcIkVzdGFibGlzaGVkXCI7XHJcbiAgICAvKiogV2FpdCB0byByZXRyeSAqL1xyXG4gICAgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1wiUmV0cnlcIl0gPSA0XSA9IFwiUmV0cnlcIjtcclxuICAgIC8qKiBJZGxlIHN0YXRlICovXHJcbiAgICBWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1ZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbXCJJZGxlXCJdID0gNV0gPSBcIklkbGVcIjtcclxufSkoVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cyA9IGV4cG9ydHMuVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cyB8fCAoZXhwb3J0cy5WcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzID0ge30pKTtcclxuLyoqIEdldCB0aGUgbGluayBzdGF0ZSAqL1xyXG52YXIgVnBuUnBjTGlua1N0YXR1cyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNMaW5rU3RhdHVzJyBjbGFzczogR2V0IHRoZSBsaW5rIHN0YXRlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaW5rU3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfRXhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGVuYWJsZWQgKi9cclxuICAgICAgICB0aGlzLkFjdGl2ZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZCAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIHNlc3Npb24gc3RhdHVzICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBkZXN0aW5hdGlvbiBWUE4gc2VydmVyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBidWlsZCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclByb2R1Y3RCdWlsZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIncyBYLjUwOSBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyWF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENsaWVudCBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50WF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gc3RhcnQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuU3RhcnRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBjb21wbGV0aW9uIHRpbWUgb2YgdGhlIGZpcnN0IGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkZpcnN0Q29ubmVjdGlvbkVzdGFibGlzaWVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGlvbiB0aW1lIG9mIHRoaXMgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQ3VycmVudENvbm5lY3Rpb25Fc3RhYmxpc2hUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb25zIGhhdmUgYmVlbiBlc3RhYmxpc2hlZCBzbyBmYXIgKi9cclxuICAgICAgICB0aGlzLk51bUNvbm5lY3Rpb25zRWF0YWJsaXNoZWRfdTMyID0gMDtcclxuICAgICAgICAvKiogSGFsZi1jb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5IYWxmQ29ubmVjdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZvSVAgLyBRb1MgKi9cclxuICAgICAgICB0aGlzLlFvU19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE1heGltdW0gbnVtYmVyIG9mIHRoZSB1bmRlcmx5aW5nIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTWF4VGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGN1cnJlbnQgdW5kZXJseWluZyBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiB1bmRlcmx5aW5nIGluYm91bmQgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc1VwbG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdW5kZXJseWluZyBvdXRib3VuZCBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zRG93bmxvYWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlIG9mIGVuY3J5cHRpb24gKi9cclxuICAgICAgICB0aGlzLlVzZUVuY3J5cHRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDaXBoZXIgYWxnb3JpdGhtIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNpcGhlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlIG9mIGNvbXByZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VDb21wcmVzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdGhpcyBpcyBhIFItVURQIHNlc3Npb24gKi9cclxuICAgICAgICB0aGlzLklzUlVEUFNlc3Npb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBVbmRlcmx5aW5nIHBoeXNpY2FsIGNvbW11bmljYXRpb24gcHJvdG9jb2wgKi9cclxuICAgICAgICB0aGlzLlVuZGVybGF5UHJvdG9jb2xfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIFVEUCBhY2NlbGVyYXRpb24gaXMgZW5hYmxlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNVZHBBY2NlbGVyYXRpb25FbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIFVEUCBhY2NlbGVyYXRpb24gaXMgYmVpbmcgYWN0dWFsbHkgdXNlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNVc2luZ1VkcEFjY2VsZXJhdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlc3Npb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0aW9uTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTZXNzaW9uIGtleSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbktleV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFRvdGFsIHRyYW5zbWl0dGVkIGRhdGEgc2l6ZSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxTZW5kU2l6ZV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCByZWNlaXZlZCBkYXRhIHNpemUgKi9cclxuICAgICAgICB0aGlzLlRvdGFsUmVjdlNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogVG90YWwgdHJhbnNtaXR0ZWQgZGF0YSBzaXplIChubyBjb21wcmVzc2lvbikgKi9cclxuICAgICAgICB0aGlzLlRvdGFsU2VuZFNpemVSZWFsX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIFRvdGFsIHJlY2VpdmVkIGRhdGEgc2l6ZSAobm8gY29tcHJlc3Npb24pICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFJlY3ZTaXplUmVhbF91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB3aGV0aGVyIHRoZSBWUE4gc2Vzc2lvbiBpcyBCcmlkZ2UgTW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNCcmlkZ2VNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0aGUgVlBOIHNlc3Npb24gaXMgTW9uaXRvciBtb2RlICovXHJcbiAgICAgICAgdGhpcy5Jc01vbml0b3JNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVkxBTiBJRCAqL1xyXG4gICAgICAgIHRoaXMuVkxhbklkX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMaW5rU3RhdHVzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0xpbmtTdGF0dXMgPSBWcG5ScGNMaW5rU3RhdHVzO1xyXG4vKiogU2V0dGluZyBvZiBTU1RQIGFuZCBPcGVuVlBOICovXHJcbnZhciBWcG5PcGVuVnBuU3N0cENvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5PcGVuVnBuU3N0cENvbmZpZycgY2xhc3M6IFNldHRpbmcgb2YgU1NUUCBhbmQgT3BlblZQTiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuT3BlblZwblNzdHBDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRydWUgdG8gZW5hYmxlIHRoZSBPcGVuVlBOIENsb25lIFNlcnZlciBGdW5jdGlvbi4gU3BlY2lmeSBmYWxzZSB0byBkaXNhYmxlLiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlT3BlblZQTl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgVURQIHBvcnRzIHRvIGxpc3RlbiBmb3IgT3BlblZQTi4gTXVsdGlwbGUgVURQIHBvcnRzIGNhbiBiZSBzcGVjaWZpZWQgd2l0aCBzcGxpdHRpbmcgYnkgc3BhY2Ugb3IgY29tbWEgbGV0dGVycywgZm9yIGV4YW1wbGU6IFwiMTE5NCwgMjAwMSwgMjAxMCwgMjAxMlwiLiBUaGUgZGVmYXVsdCBwb3J0IGZvciBPcGVuVlBOIGlzIFVEUCAxMTk0LiBZb3UgY2FuIHNwZWNpZnkgYW55IG90aGVyIFVEUCBwb3J0cy4gKi9cclxuICAgICAgICB0aGlzLk9wZW5WUE5Qb3J0TGlzdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBwZWNpZnkgdHJ1ZSB0byBlbmFibGUgdGhlIE1pY3Jvc29mdCBTU1RQIFZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFNwZWNpZnkgZmFsc2UgdG8gZGlzYWJsZS4gKi9cclxuICAgICAgICB0aGlzLkVuYWJsZVNTVFBfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuT3BlblZwblNzdHBDb25maWc7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuT3BlblZwblNzdHBDb25maWcgPSBWcG5PcGVuVnBuU3N0cENvbmZpZztcclxuLyoqIFZpcnR1YWwgaG9zdCBvcHRpb24gKi9cclxudmFyIFZwblZoT3B0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblZoT3B0aW9uJyBjbGFzczogVmlydHVhbCBob3N0IG9wdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuVmhPcHRpb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUYXJnZXQgVmlydHVhbCBIVUIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUnBjSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuTWFjQWRkcmVzc19iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLk1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2UgZmxhZyBvZiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLlVzZU5hdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE1UVSB2YWx1ZSAoU3RhbmRhcmQ6IDE1MDApICovXHJcbiAgICAgICAgdGhpcy5NdHVfdTMyID0gMDtcclxuICAgICAgICAvKiogTkFUIFRDUCB0aW1lb3V0IGluIHNlY29uZHMgKi9cclxuICAgICAgICB0aGlzLk5hdFRjcFRpbWVvdXRfdTMyID0gMDtcclxuICAgICAgICAvKiogTkFUIFVEUCB0aW1lb3V0IGluIHNlY29uZHMgKi9cclxuICAgICAgICB0aGlzLk5hdFVkcFRpbWVvdXRfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNpbmcgZmxhZyBvZiBESENQIGZ1bmN0aW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VEaGNwX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgc3RhcnQgcG9pbnQgb2YgdGhlIGFkZHJlc3MgYmFuZCB0byBiZSBkaXN0cmlidXRlZCB0byB0aGUgY2xpZW50LiAoRXhhbXBsZTogMTkyLjE2OC4zMC4xMCkgKi9cclxuICAgICAgICB0aGlzLkRoY3BMZWFzZUlQU3RhcnRfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBlbmQgcG9pbnQgb2YgdGhlIGFkZHJlc3MgYmFuZCB0byBiZSBkaXN0cmlidXRlZCB0byB0aGUgY2xpZW50LiAoRXhhbXBsZTogMTkyLjE2OC4zMC4yMDApICovXHJcbiAgICAgICAgdGhpcy5EaGNwTGVhc2VJUEVuZF9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHN1Ym5ldCBtYXNrIHRvIGJlIHNwZWNpZmllZCBmb3IgdGhlIGNsaWVudC4gKEV4YW1wbGU6IDI1NS4yNTUuMjU1LjApICovXHJcbiAgICAgICAgdGhpcy5EaGNwU3VibmV0TWFza19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGV4cGlyYXRpb24gZGF0ZSBpbiBzZWNvbmQgdW5pdHMgZm9yIGxlYXNpbmcgYW4gSVAgYWRkcmVzcyB0byBhIGNsaWVudC4gKi9cclxuICAgICAgICB0aGlzLkRoY3BFeHBpcmVUaW1lU3Bhbl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIG9mIHRoZSBkZWZhdWx0IGdhdGV3YXkgdG8gYmUgbm90aWZpZWQgdG8gdGhlIGNsaWVudC4gWW91IGNhbiBzcGVjaWZ5IGEgU2VjdXJlTkFUIFZpcnR1YWwgSG9zdCBJUCBhZGRyZXNzIGZvciB0aGlzIHdoZW4gdGhlIFNlY3VyZU5BVCBGdW5jdGlvbidzIFZpcnR1YWwgTkFUIEZ1bmN0aW9uIGhhcyBiZWVuIGVuYWJsZWQgYW5kIGlzIGJlaW5nIHVzZWQgYWxzby4gSWYgeW91IHNwZWNpZnkgMCBvciBub25lLCB0aGVuIHRoZSBjbGllbnQgd2lsbCBub3QgYmUgbm90aWZpZWQgb2YgdGhlIGRlZmF1bHQgZ2F0ZXdheS4gKi9cclxuICAgICAgICB0aGlzLkRoY3BHYXRld2F5QWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQIGFkZHJlc3Mgb2YgdGhlIHByaW1hcnkgRE5TIFNlcnZlciB0byBiZSBub3RpZmllZCB0byB0aGUgY2xpZW50LiBZb3UgY2FuIHNwZWNpZnkgYSBTZWN1cmVOQVQgVmlydHVhbCBIb3N0IElQIGFkZHJlc3MgZm9yIHRoaXMgd2hlbiB0aGUgU2VjdXJlTkFUIEZ1bmN0aW9uJ3MgVmlydHVhbCBOQVQgRnVuY3Rpb24gaGFzIGJlZW4gZW5hYmxlZCBhbmQgaXMgYmVpbmcgdXNlZCBhbHNvLiBJZiB5b3Ugc3BlY2lmeSBlbXB0eSwgdGhlbiB0aGUgY2xpZW50IHdpbGwgbm90IGJlIG5vdGlmaWVkIG9mIHRoZSBETlMgU2VydmVyIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5EaGNwRG5zU2VydmVyQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQIGFkZHJlc3Mgb2YgdGhlIHNlY29uZGFyeSBETlMgU2VydmVyIHRvIGJlIG5vdGlmaWVkIHRvIHRoZSBjbGllbnQuIFlvdSBjYW4gc3BlY2lmeSBhIFNlY3VyZU5BVCBWaXJ0dWFsIEhvc3QgSVAgYWRkcmVzcyBmb3IgdGhpcyB3aGVuIHRoZSBTZWN1cmVOQVQgRnVuY3Rpb24ncyBWaXJ0dWFsIE5BVCBGdW5jdGlvbiBoYXMgYmVlbiBlbmFibGVkIGFuZCBpcyBiZWluZyB1c2VkIGFsc28uIElmIHlvdSBzcGVjaWZ5IGVtcHR5LCB0aGVuIHRoZSBjbGllbnQgd2lsbCBub3QgYmUgbm90aWZpZWQgb2YgdGhlIEROUyBTZXJ2ZXIgYWRkcmVzcy4gKi9cclxuICAgICAgICB0aGlzLkRoY3BEbnNTZXJ2ZXJBZGRyZXNzMl9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGRvbWFpbiBuYW1lIHRvIGJlIG5vdGlmaWVkIHRvIHRoZSBjbGllbnQuIElmIHlvdSBzcGVjaWZ5IG5vbmUsIHRoZW4gdGhlIGNsaWVudCB3aWxsIG5vdCBiZSBub3RpZmllZCBvZiB0aGUgZG9tYWluIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5EaGNwRG9tYWluTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHdoZXRoZXIgb3Igbm90IHRvIHNhdmUgdGhlIFZpcnR1YWwgREhDUCBTZXJ2ZXIgb3BlcmF0aW9uIGluIHRoZSBWaXJ0dWFsIEh1YiBzZWN1cml0eSBsb2cuIFNwZWNpZnkgdHJ1ZSB0byBzYXZlIGl0LiBUaGlzIHZhbHVlIGlzIGludGVybGlua2VkIHdpdGggdGhlIFZpcnR1YWwgTkFUIEZ1bmN0aW9uIGxvZyBzYXZlIHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpcy5TYXZlTG9nX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIHRoZSBEaGNwUHVzaFJvdXRlc19zdHIgZmllbGQuICovXHJcbiAgICAgICAgdGhpcy5BcHBseURoY3BQdXNoUm91dGVzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgc3RhdGljIHJvdXRpbmcgdGFibGUgdG8gcHVzaC4gRXhhbXBsZTogXCIxOTIuMTY4LjUuMC8yNTUuMjU1LjI1NS4wLzE5Mi4xNjguNC4yNTQsIDEwLjAuMC4wLzI1NS4wLjAuMC8xOTIuMTY4LjQuMjUzXCIgU3BsaXQgbXVsdGlwbGUgZW50cmllcyAobWF4aW11bTogNjQgZW50cmllcykgYnkgY29tbWEgb3Igc3BhY2UgY2hhcmFjdGVycy4gRWFjaCBlbnRyeSBtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGUgXCJJUCBuZXR3b3JrIGFkZHJlc3Mvc3VibmV0IG1hc2svZ2F0ZXdheSBJUCBhZGRyZXNzXCIgZm9ybWF0LiBUaGlzIFZpcnR1YWwgREhDUCBTZXJ2ZXIgY2FuIHB1c2ggdGhlIGNsYXNzbGVzcyBzdGF0aWMgcm91dGVzIChSRkMgMzQ0Mikgd2l0aCBESENQIHJlcGx5IG1lc3NhZ2VzIHRvIFZQTiBjbGllbnRzLiBXaGV0aGVyIG9yIG5vdCBhIFZQTiBjbGllbnQgY2FuIHJlY29nbml6ZSB0aGUgY2xhc3NsZXNzIHN0YXRpYyByb3V0ZXMgKFJGQyAzNDQyKSBkZXBlbmRzIG9uIHRoZSB0YXJnZXQgVlBOIGNsaWVudCBzb2Z0d2FyZS4gU29mdEV0aGVyIFZQTiBDbGllbnQgYW5kIE9wZW5WUE4gQ2xpZW50IGFyZSBzdXBwb3J0aW5nIHRoZSBjbGFzc2xlc3Mgc3RhdGljIHJvdXRlcy4gT24gTDJUUC9JUHNlYyBhbmQgTVMtU1NUUCBwcm90b2NvbHMsIHRoZSBjb21wYXRpYmlsaXR5IGRlcGVuZHMgb24gdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBjbGllbnQgc29mdHdhcmUuIFlvdSBjYW4gcmVhbGl6ZSB0aGUgc3BsaXQgdHVubmVsaW5nIGlmIHlvdSBjbGVhciB0aGUgZGVmYXVsdCBnYXRld2F5IGZpZWxkIG9uIHRoZSBWaXJ0dWFsIERIQ1AgU2VydmVyIG9wdGlvbnMuIE9uIHRoZSBjbGllbnQgc2lkZSwgTDJUUC9JUHNlYyBhbmQgTVMtU1NUUCBjbGllbnRzIG5lZWQgdG8gYmUgY29uZmlndXJlZCBub3QgdG8gc2V0IHVwIHRoZSBkZWZhdWx0IGdhdGV3YXkgZm9yIHRoZSBzcGxpdCB0dW5uZWxpbmcgdXNhZ2UuIFlvdSBjYW4gYWxzbyBwdXNoIHRoZSBjbGFzc2xlc3Mgc3RhdGljIHJvdXRlcyAoUkZDIDM0NDIpIGJ5IHlvdXIgZXhpc3RpbmcgZXh0ZXJuYWwgREhDUCBzZXJ2ZXIuIEluIHRoYXQgY2FzZSwgZGlzYWJsZSB0aGUgVmlydHVhbCBESENQIFNlcnZlciBmdW5jdGlvbiBvbiBTZWN1cmVOQVQsIGFuZCB5b3UgbmVlZCBub3QgdG8gc2V0IHVwIHRoZSBjbGFzc2xlc3Mgcm91dGVzIG9uIHRoaXMgQVBJLiBTZWUgdGhlIFJGQyAzNDQyIHRvIHVuZGVyc3RhbmQgdGhlIGNsYXNzbGVzcyByb3V0ZXMuICovXHJcbiAgICAgICAgdGhpcy5EaGNwUHVzaFJvdXRlc19zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuVmhPcHRpb247XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuVmhPcHRpb24gPSBWcG5WaE9wdGlvbjtcclxuLyoqIFJQQ19OQVRfU1RBVFVTICovXHJcbnZhciBWcG5ScGNOYXRTdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTmF0U3RhdHVzJyBjbGFzczogUlBDX05BVF9TVEFUVVMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY05hdFN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSHViIE5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFRDUCBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnRtYmVyIG9mIFVEUCBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVWRwU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnltYmVyIG9mIElDTVAgc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bUljbXBTZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgRE5TIHNlc3Npb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1EbnNTZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgREhDUCBjbGllbnRzICovXHJcbiAgICAgICAgdGhpcy5OdW1EaGNwQ2xpZW50c191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIHRoZSBOQVQgaXMgb3BlcmF0aW5nIGluIHRoZSBLZXJuZWwgTW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNLZXJuZWxNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogV2hldGhlciB0aGUgTkFUIGlzIG9wZXJhdGluZyBpbiB0aGUgUmF3IElQIE1vZGUgKi9cclxuICAgICAgICB0aGlzLklzUmF3SXBNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY05hdFN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNOYXRTdGF0dXMgPSBWcG5ScGNOYXRTdGF0dXM7XHJcbi8qKiBLZXkgcGFpciAqL1xyXG52YXIgVnBuUnBjS2V5UGFpciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNLZXlQYWlyJyBjbGFzczogS2V5IHBhaXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0tleVBhaXIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgcHJpdmF0ZSBrZXkgKi9cclxuICAgICAgICB0aGlzLktleV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNLZXlQYWlyO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0tleVBhaXIgPSBWcG5ScGNLZXlQYWlyO1xyXG4vKiogU2luZ2xlIHN0cmluZyB2YWx1ZSAqL1xyXG52YXIgVnBuUnBjU3RyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1N0cicgY2xhc3M6IFNpbmdsZSBzdHJpbmcgdmFsdWUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1N0cihpbml0KSB7XHJcbiAgICAgICAgLyoqIEEgc3RyaW5nIHZhbHVlICovXHJcbiAgICAgICAgdGhpcy5TdHJpbmdfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1N0cjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTdHIgPSBWcG5ScGNTdHI7XHJcbi8qKiBUeXBlIG9mIFZQTiBTZXJ2ZXIgKi9cclxudmFyIFZwblJwY1NlcnZlclR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjU2VydmVyVHlwZSkge1xyXG4gICAgLyoqIFN0YW5kLWFsb25lIHNlcnZlciAqL1xyXG4gICAgVnBuUnBjU2VydmVyVHlwZVtWcG5ScGNTZXJ2ZXJUeXBlW1wiU3RhbmRhbG9uZVwiXSA9IDBdID0gXCJTdGFuZGFsb25lXCI7XHJcbiAgICAvKiogRmFybSBjb250cm9sbGVyIHNlcnZlciAqL1xyXG4gICAgVnBuUnBjU2VydmVyVHlwZVtWcG5ScGNTZXJ2ZXJUeXBlW1wiRmFybUNvbnRyb2xsZXJcIl0gPSAxXSA9IFwiRmFybUNvbnRyb2xsZXJcIjtcclxuICAgIC8qKiBGYXJtIG1lbWJlciBzZXJ2ZXIgKi9cclxuICAgIFZwblJwY1NlcnZlclR5cGVbVnBuUnBjU2VydmVyVHlwZVtcIkZhcm1NZW1iZXJcIl0gPSAyXSA9IFwiRmFybU1lbWJlclwiO1xyXG59KShWcG5ScGNTZXJ2ZXJUeXBlID0gZXhwb3J0cy5WcG5ScGNTZXJ2ZXJUeXBlIHx8IChleHBvcnRzLlZwblJwY1NlcnZlclR5cGUgPSB7fSkpO1xyXG4vKiogT3BlcmF0aW5nIHN5c3RlbSB0eXBlICovXHJcbnZhciBWcG5ScGNPc1R5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjT3NUeXBlKSB7XHJcbiAgICAvKiogV2luZG93cyA5NSAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfOTVcIl0gPSAxMTAwXSA9IFwiV0lORE9XU185NVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgOTggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzk4XCJdID0gMTIwMF0gPSBcIldJTkRPV1NfOThcIjtcclxuICAgIC8qKiBXaW5kb3dzIE1lICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19NRVwiXSA9IDEzMDBdID0gXCJXSU5ET1dTX01FXCI7XHJcbiAgICAvKiogV2luZG93cyAodW5rbm93bikgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1VOS05PV05cIl0gPSAxNDAwXSA9IFwiV0lORE9XU19VTktOT1dOXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgV29ya3N0YXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX05UXzRfV09SS1NUQVRJT05cIl0gPSAyMTAwXSA9IFwiV0lORE9XU19OVF80X1dPUktTVEFUSU9OXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1NFUlZFUlwiXSA9IDIxMTBdID0gXCJXSU5ET1dTX05UXzRfU0VSVkVSXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgU2VydmVyLCBFbnRlcnByaXNlIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX05UXzRfU0VSVkVSX0VOVEVSUFJJU0VcIl0gPSAyMTExXSA9IFwiV0lORE9XU19OVF80X1NFUlZFUl9FTlRFUlBSSVNFXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgVGVybWluYWwgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1RFUk1JTkFMX1NFUlZFUlwiXSA9IDIxMTJdID0gXCJXSU5ET1dTX05UXzRfVEVSTUlOQUxfU0VSVkVSXCI7XHJcbiAgICAvKiogQmFja09mZmljZSBTZXJ2ZXIgNC41ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X0JBQ0tPRkZJQ0VcIl0gPSAyMTEzXSA9IFwiV0lORE9XU19OVF80X0JBQ0tPRkZJQ0VcIjtcclxuICAgIC8qKiBTbWFsbCBCdXNpbmVzcyBTZXJ2ZXIgNC41ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1NNU1wiXSA9IDIxMTRdID0gXCJXSU5ET1dTX05UXzRfU01TXCI7XHJcbiAgICAvKiogV2luZG93cyAyMDAwIFByb2Zlc3Npb25hbCAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMjAwMF9QUk9GRVNTSU9OQUxcIl0gPSAyMjAwXSA9IFwiV0lORE9XU18yMDAwX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgMjAwMCBTZXJ2ZXIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDBfU0VSVkVSXCJdID0gMjIxMV0gPSBcIldJTkRPV1NfMjAwMF9TRVJWRVJcIjtcclxuICAgIC8qKiBXaW5kb3dzIDIwMDAgQWR2YW5jZWQgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX0FEVkFOQ0VEX1NFUlZFUlwiXSA9IDIyMTJdID0gXCJXSU5ET1dTXzIwMDBfQURWQU5DRURfU0VSVkVSXCI7XHJcbiAgICAvKiogV2luZG93cyAyMDAwIERhdGFjZW50ZXIgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX0RBVEFDRU5URVJfU0VSVkVSXCJdID0gMjIxM10gPSBcIldJTkRPV1NfMjAwMF9EQVRBQ0VOVEVSX1NFUlZFUlwiO1xyXG4gICAgLyoqIEJhY2tPZmZpY2UgU2VydmVyIDIwMDAgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDBfQkFDS09GRklDRVwiXSA9IDIyMTRdID0gXCJXSU5ET1dTXzIwMDBfQkFDS09GRklDRVwiO1xyXG4gICAgLyoqIFNtYWxsIEJ1c2luZXNzIFNlcnZlciAyMDAwICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX1NCU1wiXSA9IDIyMTVdID0gXCJXSU5ET1dTXzIwMDBfU0JTXCI7XHJcbiAgICAvKiogV2luZG93cyBYUCBIb21lIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1hQX0hPTUVcIl0gPSAyMzAwXSA9IFwiV0lORE9XU19YUF9IT01FXCI7XHJcbiAgICAvKiogV2luZG93cyBYUCBQcm9mZXNzaW9uYWwgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1hQX1BST0ZFU1NJT05BTFwiXSA9IDIzMDFdID0gXCJXSU5ET1dTX1hQX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDMgV2ViIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfV0VCXCJdID0gMjQxMF0gPSBcIldJTkRPV1NfMjAwM19XRUJcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAyMDAzIFN0YW5kYXJkIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfU1RBTkRBUkRcIl0gPSAyNDExXSA9IFwiV0lORE9XU18yMDAzX1NUQU5EQVJEXCI7XHJcbiAgICAvKiogV2luZG93cyBTZXJ2ZXIgMjAwMyBFbnRlcnByaXNlIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfRU5URVJQUklTRVwiXSA9IDI0MTJdID0gXCJXSU5ET1dTXzIwMDNfRU5URVJQUklTRVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDMgRGF0YUNlbnRlciBFZGl0aW9uICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAzX0RBVEFDRU5URVJcIl0gPSAyNDEzXSA9IFwiV0lORE9XU18yMDAzX0RBVEFDRU5URVJcIjtcclxuICAgIC8qKiBCYWNrT2ZmaWNlIFNlcnZlciAyMDAzICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAzX0JBQ0tPRkZJQ0VcIl0gPSAyNDE0XSA9IFwiV0lORE9XU18yMDAzX0JBQ0tPRkZJQ0VcIjtcclxuICAgIC8qKiBTbWFsbCBCdXNpbmVzcyBTZXJ2ZXIgMjAwMyAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMjAwM19TQlNcIl0gPSAyNDE1XSA9IFwiV0lORE9XU18yMDAzX1NCU1wiO1xyXG4gICAgLyoqIFdpbmRvd3MgVmlzdGEgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX0xPTkdIT1JOX1BST0ZFU1NJT05BTFwiXSA9IDI1MDBdID0gXCJXSU5ET1dTX0xPTkdIT1JOX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX0xPTkdIT1JOX1NFUlZFUlwiXSA9IDI1MTBdID0gXCJXSU5ET1dTX0xPTkdIT1JOX1NFUlZFUlwiO1xyXG4gICAgLyoqIFdpbmRvd3MgNyAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfN1wiXSA9IDI2MDBdID0gXCJXSU5ET1dTXzdcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAyMDA4IFIyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19TRVJWRVJfMjAwOF9SMlwiXSA9IDI2MTBdID0gXCJXSU5ET1dTX1NFUlZFUl8yMDA4X1IyXCI7XHJcbiAgICAvKiogV2luZG93cyA4ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU184XCJdID0gMjcwMF0gPSBcIldJTkRPV1NfOFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMTIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1NFUlZFUl84XCJdID0gMjcxMF0gPSBcIldJTkRPV1NfU0VSVkVSXzhcIjtcclxuICAgIC8qKiBXaW5kb3dzIDguMSAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfODFcIl0gPSAyNzAxXSA9IFwiV0lORE9XU184MVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMTIgUjIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1NFUlZFUl84MVwiXSA9IDI3MTFdID0gXCJXSU5ET1dTX1NFUlZFUl84MVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgMTAgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzEwXCJdID0gMjcwMl0gPSBcIldJTkRPV1NfMTBcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAxMCAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfU0VSVkVSXzEwXCJdID0gMjcxMl0gPSBcIldJTkRPV1NfU0VSVkVSXzEwXCI7XHJcbiAgICAvKiogV2luZG93cyAxMSBvciBsYXRlciAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMTFcIl0gPSAyODAwXSA9IFwiV0lORE9XU18xMVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDExIG9yIGxhdGVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19TRVJWRVJfMTFcIl0gPSAyODEwXSA9IFwiV0lORE9XU19TRVJWRVJfMTFcIjtcclxuICAgIC8qKiBVbmtub3duIFVOSVggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJVTklYX1VOS05PV05cIl0gPSAzMDAwXSA9IFwiVU5JWF9VTktOT1dOXCI7XHJcbiAgICAvKiogTGludXggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJMSU5VWFwiXSA9IDMxMDBdID0gXCJMSU5VWFwiO1xyXG4gICAgLyoqIFNvbGFyaXMgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJTT0xBUklTXCJdID0gMzIwMF0gPSBcIlNPTEFSSVNcIjtcclxuICAgIC8qKiBDeWd3aW4gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJDWUdXSU5cIl0gPSAzMzAwXSA9IFwiQ1lHV0lOXCI7XHJcbiAgICAvKiogQlNEICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiQlNEXCJdID0gMzQwMF0gPSBcIkJTRFwiO1xyXG4gICAgLyoqIE1hY09TIFggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJNQUNPU19YXCJdID0gMzUwMF0gPSBcIk1BQ09TX1hcIjtcclxufSkoVnBuUnBjT3NUeXBlID0gZXhwb3J0cy5WcG5ScGNPc1R5cGUgfHwgKGV4cG9ydHMuVnBuUnBjT3NUeXBlID0ge30pKTtcclxuLyoqIFZQTiBTZXJ2ZXIgSW5mb3JtYXRpb24gKi9cclxudmFyIFZwblJwY1NlcnZlckluZm8gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2VydmVySW5mbycgY2xhc3M6IFZQTiBTZXJ2ZXIgSW5mb3JtYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1NlcnZlckluZm8oaW5pdCkge1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJQcm9kdWN0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgdmVyc2lvbiBzdHJpbmcgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclZlcnNpb25TdHJpbmdfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIGJ1aWxkIGluZm9ybWF0aW9uIHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGRJbmZvU3RyaW5nX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNlcnZlciB2ZXJzaW9uIGludGVnZXIgdmFsdWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclZlckludF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgYnVpbGQgbnVtYmVyIGludGVnZXIgdmFsdWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckJ1aWxkSW50X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZlciBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckhvc3ROYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFR5cGUgb2Ygc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEJ1aWxkIGRhdGUgYW5kIHRpbWUgb2YgdGhlIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGREYXRlX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogRmFtaWx5IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckZhbWlseU5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT1MgdHlwZSAqL1xyXG4gICAgICAgIHRoaXMuT3NUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZpY2UgcGFjayBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLk9zU2VydmljZVBhY2tfdTMyID0gMDtcclxuICAgICAgICAvKiogT1Mgc3lzdGVtIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zU3lzdGVtTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPUyBwcm9kdWN0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT1MgdmVuZG9yIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zVmVuZG9yTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPUyB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5Pc1ZlcnNpb25fc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2VybmVsIG5hbWUgKi9cclxuICAgICAgICB0aGlzLktlcm5lbE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2VybmVsIHZlcnNpb24gKi9cclxuICAgICAgICB0aGlzLktlcm5lbFZlcnNpb25fc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NlcnZlckluZm87XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2VydmVySW5mbyA9IFZwblJwY1NlcnZlckluZm87XHJcbi8qKiBTZXJ2ZXIgc3RhdHVzICovXHJcbnZhciBWcG5ScGNTZXJ2ZXJTdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2VydmVyU3RhdHVzJyBjbGFzczogU2VydmVyIHN0YXR1cyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2VydmVyU3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogVHlwZSBvZiBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVG90YWwgbnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIExvY2FsIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNMb2NhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgcmVtb3RlIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNSZW1vdGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVG90YWwgbnVtYmVyIG9mIEhVQnMgKi9cclxuICAgICAgICB0aGlzLk51bUh1YlRvdGFsX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE55bWJlciBvZiBzdGFuZC1hbG9uZSBIVUIgKi9cclxuICAgICAgICB0aGlzLk51bUh1YlN0YW5kYWxvbmVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHN0YXRpYyBIVUJzICovXHJcbiAgICAgICAgdGhpcy5OdW1IdWJTdGF0aWNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIER5bmFtaWMgSFVCcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtSHViRHluYW1pY191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCBudW1iZXIgb2Ygc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zVG90YWxfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvY2FsIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNMb2NhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgbnVtYmVyIG9mIHJlbW90ZSBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNSZW1vdGVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIE1BQyB0YWJsZSBlbnRyaWVzICh0b3RhbCBzdW0gb2YgYWxsIFZpcnR1YWwgSHVicykgKi9cclxuICAgICAgICB0aGlzLk51bU1hY1RhYmxlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgSVAgdGFibGUgZW50cmllcyAodG90YWwgc3VtIG9mIGFsbCBWaXJ0dWFsIEh1YnMpICovXHJcbiAgICAgICAgdGhpcy5OdW1JcFRhYmxlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdXNlcnMgKHRvdGFsIHN1bSBvZiBhbGwgVmlydHVhbCBIdWJzKSAqL1xyXG4gICAgICAgIHRoaXMuTnVtVXNlcnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGdyb3VwcyAodG90YWwgc3VtIG9mIGFsbCBWaXJ0dWFsIEh1YnMpICovXHJcbiAgICAgICAgdGhpcy5OdW1Hcm91cHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGFzc2lnbmVkIGJyaWRnZSBsaWNlbnNlcyAoVXNlZnVsIHRvIG1ha2UgYSBjb21tZXJjaWFsIHZlcnNpb24pICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhc3NpZ25lZCBjbGllbnQgbGljZW5zZXMgKFVzZWZ1bCB0byBtYWtlIGEgY29tbWVyY2lhbCB2ZXJzaW9uKSAqL1xyXG4gICAgICAgIHRoaXMuQXNzaWduZWRDbGllbnRMaWNlbnNlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgQXNzaWduZWQgYnJpZGdlIGxpY2Vuc2UgKGNsdXN0ZXItd2lkZSksIHVzZWZ1bCB0byBtYWtlIGEgY29tbWVyY2lhbCB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VzVG90YWxfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGFzc2lnbmVkIGNsaWVudCBsaWNlbnNlcyAoY2x1c3Rlci13aWRlKSwgdXNlZnVsIHRvIG1ha2UgYSBjb21tZXJjaWFsIHZlcnNpb24gKi9cclxuICAgICAgICB0aGlzLkFzc2lnbmVkQ2xpZW50TGljZW5zZXNUb3RhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQ3VycmVudCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50VGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIDY0IGJpdCBIaWdoLVByZWNpc2lvbiBMb2dpY2FsIFN5c3RlbSBDbG9jayAqL1xyXG4gICAgICAgIHRoaXMuQ3VycmVudFRpY2tfdTY0ID0gMDtcclxuICAgICAgICAvKiogVlBOIFNlcnZlciBTdGFydC11cCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5TdGFydFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IFRvdGFsIE1lbW9yeSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxNZW1vcnlfdTY0ID0gMDtcclxuICAgICAgICAvKiogTWVtb3J5IGluZm9ybWF0aW9uOiBVc2VkIE1lbW9yeSAqL1xyXG4gICAgICAgIHRoaXMuVXNlZE1lbW9yeV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IEZyZWUgTWVtb3J5ICovXHJcbiAgICAgICAgdGhpcy5GcmVlTWVtb3J5X3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE1lbW9yeSBpbmZvcm1hdGlvbjogVG90YWwgUGh5cyAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxQaHlzX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE1lbW9yeSBpbmZvcm1hdGlvbjogVXNlZCBQaHlzICovXHJcbiAgICAgICAgdGhpcy5Vc2VkUGh5c191NjQgPSAwO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IEZyZWUgUGh5cyAqL1xyXG4gICAgICAgIHRoaXMuRnJlZVBoeXNfdTY0ID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NlcnZlclN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXJ2ZXJTdGF0dXMgPSBWcG5ScGNTZXJ2ZXJTdGF0dXM7XHJcbi8qKiBWUE4gU2Vzc2lvbiBzdGF0dXMgKi9cclxudmFyIFZwblJwY1Nlc3Npb25TdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2Vzc2lvblN0YXR1cycgY2xhc3M6IFZQTiBTZXNzaW9uIHN0YXR1cyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2Vzc2lvblN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZQTiBzZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Vc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSZWFsIHVzZXIgbmFtZSB3aGljaCB3YXMgdXNlZCBmb3IgdGhlIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICAgICAgdGhpcy5SZWFsVXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogR3JvdXAgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuR3JvdXBOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElzIENhc2NhZGUgU2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuTGlua01vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50X0lwX0FkZHJlc3NfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgaG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX0NsaWVudEhvc3ROYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9wZXJhdGlvbiBmbGFnICovXHJcbiAgICAgICAgdGhpcy5BY3RpdmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDb25uZWN0ZWQgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3RhdGUgb2YgdGhlIGNsaWVudCBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvcnQgbnVtYmVyIG9mIHRoZSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBidWlsZCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclByb2R1Y3RCdWlsZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHN0YXJ0IHRpbWUgKi9cclxuICAgICAgICB0aGlzLlN0YXJ0VGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGlvbiB0aW1lIG9mIHRoZSBmaXJzdCBjb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5GaXJzdENvbm5lY3Rpb25Fc3RhYmxpc2llZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIGNvbXBsZXRpb24gdGltZSBvZiB0aGlzIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRDb25uZWN0aW9uRXN0YWJsaXNoVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjb25uZWN0aW9ucyBoYXZlIGJlZW4gZXN0YWJsaXNoZWQgc28gZmFyICovXHJcbiAgICAgICAgdGhpcy5OdW1Db25uZWN0aW9uc0VhdGFibGlzaGVkX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEhhbGYtY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuSGFsZkNvbm5lY3Rpb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBWb0lQIC8gUW9TICovXHJcbiAgICAgICAgdGhpcy5Rb1NfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiB0aGUgdW5kZXJseWluZyBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk1heFRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IHVuZGVybHlpbmcgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgaW5ib3VuZCB1bmRlcmx5aW5nIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc1VwbG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2Ygb3V0Ym91bmQgdW5kZXJseWluZyBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNEb3dubG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBVc2Ugb2YgZW5jcnlwdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuVXNlRW5jcnlwdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENpcGhlciBhbGdvcml0aG0gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ2lwaGVyTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2Ugb2YgY29tcHJlc3Npb24gKi9cclxuICAgICAgICB0aGlzLlVzZUNvbXByZXNzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgUi1VRFAgc2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuSXNSVURQU2Vzc2lvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFBoeXNpY2FsIHVuZGVybHlpbmcgY29tbXVuaWNhdGlvbiBwcm90b2NvbCAqL1xyXG4gICAgICAgIHRoaXMuVW5kZXJsYXlQcm90b2NvbF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgVURQIGFjY2VsZXJhdGlvbiBpcyBlbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5Jc1VkcEFjY2VsZXJhdGlvbkVuYWJsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBVc2luZyB0aGUgVURQIGFjY2VsZXJhdGlvbiBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuSXNVc2luZ1VkcEFjY2VsZXJhdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZQTiBzZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGlvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2Vzc2lvbiBrZXkgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25LZXlfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBUb3RhbCB0cmFuc21pdHRlZCBkYXRhIHNpemUgKi9cclxuICAgICAgICB0aGlzLlRvdGFsU2VuZFNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogVG90YWwgcmVjZWl2ZWQgZGF0YSBzaXplICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFJlY3ZTaXplX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIFRvdGFsIHRyYW5zbWl0dGVkIGRhdGEgc2l6ZSAobm8gY29tcHJlc3Npb24pICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFNlbmRTaXplUmVhbF91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCByZWNlaXZlZCBkYXRhIHNpemUgKG5vIGNvbXByZXNzaW9uKSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxSZWN2U2l6ZVJlYWxfdTY0ID0gMDtcclxuICAgICAgICAvKiogSXMgQnJpZGdlIE1vZGUgKi9cclxuICAgICAgICB0aGlzLklzQnJpZGdlTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElzIE1vbml0b3IgbW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNNb25pdG9yTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZMQU4gSUQgKi9cclxuICAgICAgICB0aGlzLlZMYW5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgcHJvZHVjdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRQcm9kdWN0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50UHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgYnVpbGQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRQcm9kdWN0QnVpbGRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9TIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudE9zTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT1MgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50T3NWZXJfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IE9TIFByb2R1Y3QgSUQgKi9cclxuICAgICAgICB0aGlzLkNsaWVudE9zUHJvZHVjdElkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudEhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFVuaXF1ZSBJRCAqL1xyXG4gICAgICAgIHRoaXMuVW5pcXVlSWRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjU2Vzc2lvblN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXNzaW9uU3RhdHVzID0gVnBuUnBjU2Vzc2lvblN0YXR1cztcclxuLyoqIFNldCB0aGUgc3BlY2lhbCBsaXN0ZW5lciAqL1xyXG52YXIgVnBuUnBjU3BlY2lhbExpc3RlbmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NwZWNpYWxMaXN0ZW5lcicgY2xhc3M6IFNldCB0aGUgc3BlY2lhbCBsaXN0ZW5lciAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU3BlY2lhbExpc3RlbmVyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gYWN0aXZhdGUgdGhlIFZQTiBvdmVyIElDTVAgc2VydmVyIGZ1bmN0aW9uICovXHJcbiAgICAgICAgdGhpcy5WcG5PdmVySWNtcExpc3RlbmVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gYWN0aXZhdGUgdGhlIFZQTiBvdmVyIEROUyBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuVnBuT3ZlckRuc0xpc3RlbmVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NwZWNpYWxMaXN0ZW5lcjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTcGVjaWFsTGlzdGVuZXIgPSBWcG5ScGNTcGVjaWFsTGlzdGVuZXI7XHJcbi8qKiBTeXNsb2cgY29uZmlndXJhdGlvbiAqL1xyXG52YXIgVnBuU3lzbG9nU2F2ZVR5cGU7XHJcbihmdW5jdGlvbiAoVnBuU3lzbG9nU2F2ZVR5cGUpIHtcclxuICAgIC8qKiBEbyBub3QgdXNlIHN5c2xvZyAqL1xyXG4gICAgVnBuU3lzbG9nU2F2ZVR5cGVbVnBuU3lzbG9nU2F2ZVR5cGVbXCJOb25lXCJdID0gMF0gPSBcIk5vbmVcIjtcclxuICAgIC8qKiBPbmx5IHNlcnZlciBsb2cgKi9cclxuICAgIFZwblN5c2xvZ1NhdmVUeXBlW1ZwblN5c2xvZ1NhdmVUeXBlW1wiU2VydmVyTG9nXCJdID0gMV0gPSBcIlNlcnZlckxvZ1wiO1xyXG4gICAgLyoqIFNlcnZlciBhbmQgVmlydHVhbCBIVUIgc2VjdXJpdHkgbG9nICovXHJcbiAgICBWcG5TeXNsb2dTYXZlVHlwZVtWcG5TeXNsb2dTYXZlVHlwZVtcIlNlcnZlckFuZEh1YlNlY3VyaXR5TG9nXCJdID0gMl0gPSBcIlNlcnZlckFuZEh1YlNlY3VyaXR5TG9nXCI7XHJcbiAgICAvKiogU2VydmVyLCBWaXJ0dWFsIEhVQiBzZWN1cml0eSwgYW5kIHBhY2tldCBsb2cgKi9cclxuICAgIFZwblN5c2xvZ1NhdmVUeXBlW1ZwblN5c2xvZ1NhdmVUeXBlW1wiU2VydmVyQW5kSHViQWxsTG9nXCJdID0gM10gPSBcIlNlcnZlckFuZEh1YkFsbExvZ1wiO1xyXG59KShWcG5TeXNsb2dTYXZlVHlwZSA9IGV4cG9ydHMuVnBuU3lzbG9nU2F2ZVR5cGUgfHwgKGV4cG9ydHMuVnBuU3lzbG9nU2F2ZVR5cGUgPSB7fSkpO1xyXG4vKiogU3lzbG9nIGNvbmZpZ3VyYXRpb24gKi9cclxudmFyIFZwblN5c2xvZ1NldHRpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuU3lzbG9nU2V0dGluZycgY2xhc3M6IFN5c2xvZyBjb25maWd1cmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5TeXNsb2dTZXR0aW5nKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGJlaGF2aW9yIG9mIHRoZSBzeXNsb2cgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLlNhdmVUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGhvc3QgbmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBzeXNsb2cgc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBwb3J0IG51bWJlciBvZiB0aGUgc3lzbG9nIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuU3lzbG9nU2V0dGluZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5TeXNsb2dTZXR0aW5nID0gVnBuU3lzbG9nU2V0dGluZztcclxuLyoqIFZQTiBHYXRlIFNlcnZlciBDb25maWcgKi9cclxudmFyIFZwblZnc0NvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5WZ3NDb25maWcnIGNsYXNzOiBWUE4gR2F0ZSBTZXJ2ZXIgQ29uZmlnICovXHJcbiAgICBmdW5jdGlvbiBWcG5WZ3NDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBBY3RpdmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuSXNFbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogTWVzc2FnZSAqL1xyXG4gICAgICAgIHRoaXMuTWVzc2FnZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPd25lciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Pd25lcl91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBBYnVzZSBlbWFpbCAqL1xyXG4gICAgICAgIHRoaXMuQWJ1c2VfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTG9nIHNhdmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuTm9Mb2dfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTYXZlIGxvZyBwZXJtYW5lbnRseSAqL1xyXG4gICAgICAgIHRoaXMuTG9nUGVybWFuZW50X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogRW5hYmxlIHRoZSBMMlRQIFZQTiBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlTDJUUF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5WZ3NDb25maWc7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuVmdzQ29uZmlnID0gVnBuVmdzQ29uZmlnO1xyXG4vKiogUmVhZCBhIExvZyBmaWxlICovXHJcbnZhciBWcG5ScGNSZWFkTG9nRmlsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNSZWFkTG9nRmlsZScgY2xhc3M6IFJlYWQgYSBMb2cgZmlsZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjUmVhZExvZ0ZpbGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBGaWxlIFBhdGggKi9cclxuICAgICAgICB0aGlzLkZpbGVQYXRoX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9mZnNldCB0byBkb3dubG9hZC4gWW91IGhhdmUgdG8gY2FsbCB0aGUgUmVhZExvZ0ZpbGUgQVBJIG11bHRpcGxlIHRpbWVzIHRvIGRvd25sb2FkIHRoZSBlbnRpcmUgbG9nIGZpbGUgd2l0aCByZXF1ZXN0aW5nIGEgcGFydCBvZiB0aGUgZmlsZSBieSBzcGVjaWZ5aW5nIHRoZSBPZmZzZXRfdTMyIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuT2Zmc2V0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFJlY2VpdmVkIGJ1ZmZlciAqL1xyXG4gICAgICAgIHRoaXMuQnVmZmVyX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1JlYWRMb2dGaWxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1JlYWRMb2dGaWxlID0gVnBuUnBjUmVhZExvZ0ZpbGU7XHJcbi8qKiBSZW5hbWUgbGluayAqL1xyXG52YXIgVnBuUnBjUmVuYW1lTGluayA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNSZW5hbWVMaW5rJyBjbGFzczogUmVuYW1lIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1JlbmFtZUxpbmsoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgb2xkIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuT2xkQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5ldyBuYW1lIG9mIHRoZSBjYXNjYWRlIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLk5ld0FjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNSZW5hbWVMaW5rO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1JlbmFtZUxpbmsgPSBWcG5ScGNSZW5hbWVMaW5rO1xyXG4vKiogT25saW5lIG9yIG9mZmxpbmUgdGhlIEhVQiAqL1xyXG52YXIgVnBuUnBjU2V0SHViT25saW5lID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NldEh1Yk9ubGluZScgY2xhc3M6IE9ubGluZSBvciBvZmZsaW5lIHRoZSBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1NldEh1Yk9ubGluZShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSAvIG9mZmxpbmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuT25saW5lX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NldEh1Yk9ubGluZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXRIdWJPbmxpbmUgPSBWcG5ScGNTZXRIdWJPbmxpbmU7XHJcbi8qKiBTZXQgUGFzc3dvcmQgKi9cclxudmFyIFZwblJwY1NldFBhc3N3b3JkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NldFBhc3N3b3JkJyBjbGFzczogU2V0IFBhc3N3b3JkICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNTZXRQYXNzd29yZChpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBwbGFpbnRleHQgcGFzc3dvcmQgKi9cclxuICAgICAgICB0aGlzLlBsYWluVGV4dFBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNTZXRQYXNzd29yZDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXRQYXNzd29yZCA9IFZwblJwY1NldFBhc3N3b3JkO1xyXG4vLyAtLS0gVXRpbGl0eSBjb2RlcyAtLS1cclxuLyoqIEpTT04tUlBDIHJlcXVlc3QgY2xhc3MuIFNlZSBodHRwczovL3d3dy5qc29ucnBjLm9yZy9zcGVjaWZpY2F0aW9uICovXHJcbnZhciBKc29uUnBjUmVxdWVzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW0sIGlkKSB7XHJcbiAgICAgICAgaWYgKG1ldGhvZCA9PT0gdm9pZCAwKSB7IG1ldGhvZCA9IFwiXCI7IH1cclxuICAgICAgICBpZiAocGFyYW0gPT09IHZvaWQgMCkgeyBwYXJhbSA9IG51bGw7IH1cclxuICAgICAgICBpZiAoaWQgPT09IHZvaWQgMCkgeyBpZCA9IFwiXCI7IH1cclxuICAgICAgICB0aGlzLmpzb25ycGMgPSBcIjIuMFwiO1xyXG4gICAgICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xyXG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW07XHJcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIEpzb25ScGNSZXF1ZXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLkpzb25ScGNSZXF1ZXN0ID0gSnNvblJwY1JlcXVlc3Q7XHJcbi8qKiBKU09OLVJQQyBlcnJvciBjbGFzcy4gU2VlIGh0dHBzOi8vd3d3Lmpzb25ycGMub3JnL3NwZWNpZmljYXRpb24gKi9cclxudmFyIEpzb25ScGNFcnJvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNFcnJvcihjb2RlLCBtZXNzYWdlLCBkYXRhKSB7XHJcbiAgICAgICAgaWYgKGNvZGUgPT09IHZvaWQgMCkgeyBjb2RlID0gMDsgfVxyXG4gICAgICAgIGlmIChtZXNzYWdlID09PSB2b2lkIDApIHsgbWVzc2FnZSA9IFwiXCI7IH1cclxuICAgICAgICBpZiAoZGF0YSA9PT0gdm9pZCAwKSB7IGRhdGEgPSBudWxsOyB9XHJcbiAgICAgICAgdGhpcy5jb2RlID0gY29kZTtcclxuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xyXG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSnNvblJwY0Vycm9yO1xyXG59KCkpO1xyXG5leHBvcnRzLkpzb25ScGNFcnJvciA9IEpzb25ScGNFcnJvcjtcclxuLyoqIEpTT04tUlBDIHJlc3BvbnNlIGNsYXNzIHdpdGggZ2VuZXJpY3MgKi9cclxudmFyIEpzb25ScGNSZXNwb25zZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNSZXNwb25zZSgpIHtcclxuICAgICAgICB0aGlzLmpzb25ycGMgPSBcIjIuMFwiO1xyXG4gICAgICAgIHRoaXMucmVzdWx0ID0gbnVsbDtcclxuICAgICAgICB0aGlzLmVycm9yID0gbnVsbDtcclxuICAgICAgICB0aGlzLmlkID0gXCJcIjtcclxuICAgIH1cclxuICAgIHJldHVybiBKc29uUnBjUmVzcG9uc2U7XHJcbn0oKSk7XHJcbmV4cG9ydHMuSnNvblJwY1Jlc3BvbnNlID0gSnNvblJwY1Jlc3BvbnNlO1xyXG4vKiogSlNPTi1SUEMgY2xpZW50IGNsYXNzLiBTZWUgaHR0cHM6Ly93d3cuanNvbnJwYy5vcmcvc3BlY2lmaWNhdGlvbiAqL1xyXG52YXIgSnNvblJwY0NsaWVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKlxyXG4gICAgICogSlNPTi1SUEMgY2xpZW50IGNsYXNzIGNvbnN0cnVjdG9yXHJcbiAgICAgKiBAcGFyYW0gdXJsIFRoZSBVUkxcclxuICAgICAqIEBwYXJhbSBoZWFkZXJzIEFkZGl0aW9uYWwgSFRUUCBoZWFkZXJzXHJcbiAgICAgKiBAcGFyYW0gc2VuZF9jcmVkZW50aWFsIFNldCB0cnVlIHRvIHVzZSB0aGUgc2FtZSBjcmVkZW50aWFsIHdpdGggdGhlIGJyb3dzaW5nIHdlYiBzaXRlLiBWYWxpZCBvbmx5IGlmIHRoZSBjb2RlIGlzIHJ1bm5pbmcgb24gdGhlIHdlYiBicm93c2VyLlxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBKc29uUnBjQ2xpZW50KHVybCwgaGVhZGVycywgc2VuZF9jcmVkZW50aWFsLCBub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQpIHtcclxuICAgICAgICB0aGlzLkJhc2VVcmwgPSB1cmw7XHJcbiAgICAgICAgdGhpcy5oZWFkZXJzID0gaGVhZGVycztcclxuICAgICAgICB0aGlzLmNsaWVudCA9IG5ldyBIdHRwQ2xpZW50KCk7XHJcbiAgICAgICAgdGhpcy5jbGllbnQuU2VuZENyZWRlbnRpYWwgPSBzZW5kX2NyZWRlbnRpYWw7XHJcbiAgICAgICAgdGhpcy5jbGllbnQuTm9kZUpTX0hUVFBTX0NsaWVudF9SZWplY3RfVW5hdXRob3JpemVkID0gbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0O1xyXG4gICAgfVxyXG4gICAgLyoqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjb252ZXJ0IGFueSBvYmplY3QgdG8gSlNPTiBzdHJpbmcgKi9cclxuICAgIEpzb25ScGNDbGllbnQuT2JqZWN0VG9Kc29uID0gZnVuY3Rpb24gKG9iaikge1xyXG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XHJcbiAgICAgICAgICAgIGlmIChrZXkuZW5kc1dpdGgoXCJfYmluXCIpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVXRpbF9CYXNlNjRfRW5jb2RlKHZhbHVlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICAgfSwgNCk7XHJcbiAgICB9O1xyXG4gICAgLyoqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjb252ZXJ0IEpTT04gc3RyaW5nIHRvIG9iamVjdCAqL1xyXG4gICAgSnNvblJwY0NsaWVudC5Kc29uVG9PYmplY3QgPSBmdW5jdGlvbiAoc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoc3RyLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xyXG4gICAgICAgICAgICBpZiAoa2V5LmVuZHNXaXRoKFwiX2JpblwiKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFV0aWxfQmFzZTY0X0RlY29kZSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoa2V5LmVuZHNXaXRoKFwiX2R0XCIpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIENhbGwgYSBzaW5nbGUgUlBDIGNhbGwgKHdpdGhvdXQgZXJyb3IgY2hlY2spLiBZb3UgY2FuIHdhaXQgZm9yIHRoZSByZXNwb25zZSB3aXRoIFByb21pc2U8c3RyaW5nPiBvciBhd2FpdCBzdGF0ZW1lbnQuXHJcbiAgICAgKiBAcGFyYW0gbWV0aG9kX25hbWUgVGhlIG5hbWUgb2YgUlBDIG1ldGhvZFxyXG4gICAgICogQHBhcmFtIHBhcmFtIFRoZSBwYXJhbWV0ZXJzXHJcbiAgICAgKi9cclxuICAgIEpzb25ScGNDbGllbnQucHJvdG90eXBlLkNhbGxJbnRlcm5hbEFzeW5jID0gZnVuY3Rpb24gKG1ldGhvZF9uYW1lLCBwYXJhbSkge1xyXG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIGlkLCByZXEsIHJlcV9zdHJpbmcsIGh0dHBfcmVzcG9uc2UsIHJldF9zdHJpbmc7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gXCIxXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcSA9IG5ldyBKc29uUnBjUmVxdWVzdChtZXRob2RfbmFtZSwgcGFyYW0sIGlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxX3N0cmluZyA9IEpzb25ScGNDbGllbnQuT2JqZWN0VG9Kc29uKHJlcSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWJ1Z19tb2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIi0tLSBSUEMgUmVxdWVzdCBCb2R5IC0tLVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlcV9zdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgdGhpcy5jbGllbnQuUG9zdEFzeW5jKHRoaXMuQmFzZVVybCwgdGhpcy5oZWFkZXJzLCByZXFfc3RyaW5nLCBcImFwcGxpY2F0aW9uL2pzb25cIildO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cF9yZXNwb25zZSA9IF9hLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0X3N0cmluZyA9IGh0dHBfcmVzcG9uc2UuQm9keTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlYnVnX21vZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiLS0tIFJQQyBSZXNwb25zZSBCb2R5IC0tLVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJldF9zdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovLCByZXRfc3RyaW5nXTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9O1xyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsIGEgc2luZ2xlIFJQQyBjYWxsICh3aXRoIGVycm9yIGNoZWNrKS4gWW91IGNhbiB3YWl0IGZvciB0aGUgcmVzcG9uc2Ugd2l0aCBQcm9taXNlPFRSZXN1bHQ+IG9yIGF3YWl0IHN0YXRlbWVudC4gSW4gdGhlIGNhc2Ugb2YgZXJyb3IsIGl0IHdpbGwgYmUgdGhyb3duLlxyXG4gICAgICogQHBhcmFtIG1ldGhvZF9uYW1lIFRoZSBuYW1lIG9mIFJQQyBtZXRob2RcclxuICAgICAqIEBwYXJhbSBwYXJhbSBUaGUgcGFyYW1ldGVyc1xyXG4gICAgICovXHJcbiAgICBKc29uUnBjQ2xpZW50LnByb3RvdHlwZS5DYWxsQXN5bmMgPSBmdW5jdGlvbiAobWV0aG9kX25hbWUsIHBhcmFtKSB7XHJcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmV0X3N0cmluZywgcmV0O1xyXG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQgLyp5aWVsZCovLCB0aGlzLkNhbGxJbnRlcm5hbEFzeW5jKG1ldGhvZF9uYW1lLCBwYXJhbSldO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0X3N0cmluZyA9IF9hLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0ID0gSlNPTi5wYXJzZShyZXRfc3RyaW5nKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzX251bGwocmV0LmVycm9yKSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBKc29uUnBjRXhjZXB0aW9uKHJldC5lcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIHJldC5yZXN1bHRdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gSnNvblJwY0NsaWVudDtcclxufSgpKTtcclxuZXhwb3J0cy5Kc29uUnBjQ2xpZW50ID0gSnNvblJwY0NsaWVudDtcclxuLyoqIEpTT04tUlBDIGV4Y2VwdGlvbiBjbGFzcyAqL1xyXG52YXIgSnNvblJwY0V4Y2VwdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcclxuICAgIF9fZXh0ZW5kcyhKc29uUnBjRXhjZXB0aW9uLCBfc3VwZXIpO1xyXG4gICAgZnVuY3Rpb24gSnNvblJwY0V4Y2VwdGlvbihlcnJvcikge1xyXG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIFwiQ29kZT1cIiArIGVycm9yLmNvZGUgKyBcIiwgTWVzc2FnZT1cIiArIGVycm9yLm1lc3NhZ2UpIHx8IHRoaXM7XHJcbiAgICAgICAgX3RoaXMuRXJyb3IgPSBlcnJvcjtcclxuICAgICAgICByZXR1cm4gX3RoaXM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSnNvblJwY0V4Y2VwdGlvbjtcclxufShFcnJvcikpO1xyXG5leHBvcnRzLkpzb25ScGNFeGNlcHRpb24gPSBKc29uUnBjRXhjZXB0aW9uO1xyXG4vKiogSFRUUCBjbGllbnQgZXhjZXB0aW9uIGNsYXNzICovXHJcbnZhciBIdHRwQ2xpZW50RXhjZXB0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xyXG4gICAgX19leHRlbmRzKEh0dHBDbGllbnRFeGNlcHRpb24sIF9zdXBlcik7XHJcbiAgICBmdW5jdGlvbiBIdHRwQ2xpZW50RXhjZXB0aW9uKG1lc3NhZ2UpIHtcclxuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgbWVzc2FnZSkgfHwgdGhpcztcclxuICAgIH1cclxuICAgIHJldHVybiBIdHRwQ2xpZW50RXhjZXB0aW9uO1xyXG59KEVycm9yKSk7XHJcbmV4cG9ydHMuSHR0cENsaWVudEV4Y2VwdGlvbiA9IEh0dHBDbGllbnRFeGNlcHRpb247XHJcbi8qKiBIVFRQIGNsaWVudCByZXNwb25zZSBjbGFzcyAqL1xyXG52YXIgSHR0cENsaWVudFJlc3BvbnNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gSHR0cENsaWVudFJlc3BvbnNlKCkge1xyXG4gICAgICAgIHRoaXMuQm9keSA9IFwiXCI7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSHR0cENsaWVudFJlc3BvbnNlO1xyXG59KCkpO1xyXG5leHBvcnRzLkh0dHBDbGllbnRSZXNwb25zZSA9IEh0dHBDbGllbnRSZXNwb25zZTtcclxuLyoqIEFuIEhUVFAgY2xpZW50IHdoaWNoIGNhbiBiZSB1c2VkIGluIGJvdGggd2ViIGJyb3dzZXJzIGFuZCBOb2RlLmpzICovXHJcbnZhciBIdHRwQ2xpZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gSHR0cENsaWVudCgpIHtcclxuICAgICAgICB0aGlzLlRpbWVvdXRNc2VjcyA9IDYwICogNSAqIDEwMDA7XHJcbiAgICAgICAgdGhpcy5TZW5kQ3JlZGVudGlhbCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5Ob2RlSlNfSFRUUFNfQ2xpZW50X1JlamVjdF9VbmF1dGhvcml6ZWQgPSBmYWxzZTtcclxuICAgIH1cclxuICAgIC8qKiBQb3N0IG1ldGhvZC4gSW4gd2ViIGJyb3dzZXJzIHRoaXMgZnVuY3Rpb24gd2lsbCBwcm9jZXNzIHRoZSByZXF1ZXN0IGJ5IGl0c2VsZi4gSW4gTm9kZS5qcyB0aGlzIGZ1bmN0aW9uIHdpbGwgY2FsbCBQb3N0QXN5bmNfTm9kZUpTKCkgaW5zdGVhZC4gKi9cclxuICAgIEh0dHBDbGllbnQucHJvdG90eXBlLlBvc3RBc3luYyA9IGZ1bmN0aW9uICh1cmwsIGhlYWRlcnMsIHJlcV9ib2R5LCByZXFfbWVkaWFfdHlwZSkge1xyXG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIGZldGNoX2hlYWRlcl9saXN0LCBfaSwgX2EsIG5hbWVfMSwgZmV0Y2hfaW5pdCwgZmV0Y2hfcmVzcG9uc2UsIHJldCwgX2I7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2MpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2MubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc19ub2RlX2pzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgdGhpcy5Qb3N0QXN5bmNfTm9kZUpTKHVybCwgaGVhZGVycywgcmVxX2JvZHksIHJlcV9tZWRpYV90eXBlKV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZmV0Y2hfaGVhZGVyX2xpc3QgPSBuZXcgSGVhZGVycygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgX2EgPSBPYmplY3Qua2V5cyhoZWFkZXJzKTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVfMSA9IF9hW19pXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoX2hlYWRlcl9saXN0LmFwcGVuZChuYW1lXzEsIGhlYWRlcnNbbmFtZV8xXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZmV0Y2hfaW5pdCA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU6IFwiY29yc1wiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczogZmV0Y2hfaGVhZGVyX2xpc3QsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVkZW50aWFsczogKHRoaXMuU2VuZENyZWRlbnRpYWwgPyBcImluY2x1ZGVcIiA6IFwib21pdFwiKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZTogXCJuby1jYWNoZVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGFsaXZlOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkaXJlY3Q6IFwiZm9sbG93XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5OiByZXFfYm9keVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBmZXRjaCh1cmwsIGZldGNoX2luaXQpXTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoX3Jlc3BvbnNlID0gX2Muc2VudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmV0Y2hfcmVzcG9uc2Uub2sgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSHR0cENsaWVudEV4Y2VwdGlvbihcIkhUVFAgRXJyb3I6IFwiICsgZmV0Y2hfcmVzcG9uc2Uuc3RhdHVzICsgXCIgXCIgKyBmZXRjaF9yZXNwb25zZS5zdGF0dXNUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXQgPSBuZXcgSHR0cENsaWVudFJlc3BvbnNlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIF9iID0gcmV0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBmZXRjaF9yZXNwb25zZS50ZXh0KCldO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgX2IuQm9keSA9IF9jLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIHJldF07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIC8qKiBQb3N0IG1ldGhvZCBmb3IgTm9kZS5qcy4gKi9cclxuICAgIEh0dHBDbGllbnQucHJvdG90eXBlLlBvc3RBc3luY19Ob2RlSlMgPSBmdW5jdGlvbiAodXJsLCBoZWFkZXJzLCByZXFfYm9keSwgcmVxX21lZGlhX3R5cGUpIHtcclxuICAgICAgICB2YXIgaHR0cHMgPSByZXF1aXJlKFwiaHR0cHNcIik7XHJcbiAgICAgICAgdmFyIGtlZXBBbGl2ZUFnZW50ID0gbmV3IGh0dHBzLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pO1xyXG4gICAgICAgIHZhciB1cmxwYXJzZSA9IHJlcXVpcmUoXCJ1cmxcIik7XHJcbiAgICAgICAgdmFyIHVybG9iaiA9IHVybHBhcnNlLnBhcnNlKHVybCk7XHJcbiAgICAgICAgaWYgKGlzX251bGwodXJsb2JqLmhvc3QpKVxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVUkwgaXMgaW52YWxpZC5cIik7XHJcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIGhvc3Q6IHVybG9iai5ob3N0bmFtZSxcclxuICAgICAgICAgICAgcG9ydDogdXJsb2JqLnBvcnQsXHJcbiAgICAgICAgICAgIHBhdGg6IHVybG9iai5wYXRoLFxyXG4gICAgICAgICAgICByZWplY3RVbmF1dGhvcml6ZWQ6IHRoaXMuTm9kZUpTX0hUVFBTX0NsaWVudF9SZWplY3RfVW5hdXRob3JpemVkLFxyXG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxyXG4gICAgICAgICAgICB0aW1lb3V0OiB0aGlzLlRpbWVvdXRNc2VjcyxcclxuICAgICAgICAgICAgYWdlbnQ6IGtlZXBBbGl2ZUFnZW50XHJcbiAgICAgICAgfTtcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgICAgICB2YXIgcmVxID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBmdW5jdGlvbiAocmVzKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAocmVzLnN0YXR1c0NvZGUgIT09IDIwMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgSHR0cENsaWVudEV4Y2VwdGlvbihcIkhUVFAgRXJyb3I6IFwiICsgcmVzLnN0YXR1c0NvZGUgKyBcIiBcIiArIHJlcy5zdGF0dXNNZXNzYWdlKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgcmVjdl9zdHIgPSBcIlwiO1xyXG4gICAgICAgICAgICAgICAgcmVzLm9uKFwiZGF0YVwiLCBmdW5jdGlvbiAoYm9keSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlY3Zfc3RyICs9IGJvZHk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJlcy5vbihcImVuZFwiLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJldCA9IG5ldyBIdHRwQ2xpZW50UmVzcG9uc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICByZXQuQm9keSA9IHJlY3Zfc3RyO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUocmV0KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KS5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnIpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBPYmplY3Qua2V5cyhoZWFkZXJzKTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcclxuICAgICAgICAgICAgICAgIHZhciBuYW1lXzIgPSBfYVtfaV07XHJcbiAgICAgICAgICAgICAgICByZXEuc2V0SGVhZGVyKG5hbWVfMiwgIWlzX251bGwoaGVhZGVyc1tuYW1lXzJdKSA/IGhlYWRlcnNbbmFtZV8yXSA6IFwiXCIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlcS5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgcmVxX21lZGlhX3R5cGUpO1xyXG4gICAgICAgICAgICByZXEuc2V0SGVhZGVyKFwiQ29udGVudC1MZW5ndGhcIiwgQnVmZmVyLmJ5dGVMZW5ndGgocmVxX2JvZHkpKTtcclxuICAgICAgICAgICAgcmVxLndyaXRlKHJlcV9ib2R5KTtcclxuICAgICAgICAgICAgcmVxLmVuZCgpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBIdHRwQ2xpZW50O1xyXG59KCkpO1xyXG5leHBvcnRzLkh0dHBDbGllbnQgPSBIdHRwQ2xpZW50O1xyXG4vLy8vLy8vLyBCRUdJTjogQmFzZTY0IGVuY29kZSAvIGRlY29kZSB1dGlsaXR5IGZ1bmN0aW9ucyBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9iZWF0Z2FtbWl0L2Jhc2U2NC1qc1xyXG4vLyBUaGUgTUlUIExpY2Vuc2UoTUlUKVxyXG4vLyBDb3B5cmlnaHQoYykgMjAxNFxyXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XHJcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxyXG4vLyAgICAgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xyXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZCAvIG9yIHNlbGxcclxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXHJcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XHJcbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXHJcbi8vICAgICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cclxuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxyXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcclxuLy8gICAgIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuSU4gTk8gRVZFTlQgU0hBTEwgVEhFXHJcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcclxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcclxuLy8gICAgIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cclxuLy8gVEhFIFNPRlRXQVJFLlxyXG52YXIgbG9va3VwID0gW107XHJcbnZhciByZXZMb29rdXAgPSBbXTtcclxudmFyIGNvZGUgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky9cIjtcclxuZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNvZGUubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgIGxvb2t1cFtpXSA9IGNvZGVbaV07XHJcbiAgICByZXZMb29rdXBbY29kZS5jaGFyQ29kZUF0KGkpXSA9IGk7XHJcbn1cclxuLy8gU3VwcG9ydCBkZWNvZGluZyBVUkwtc2FmZSBiYXNlNjQgc3RyaW5ncywgYXMgTm9kZS5qcyBkb2VzLlxyXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXHJcbnJldkxvb2t1cFtcIi1cIi5jaGFyQ29kZUF0KDApXSA9IDYyO1xyXG5yZXZMb29rdXBbXCJfXCIuY2hhckNvZGVBdCgwKV0gPSA2MztcclxuZnVuY3Rpb24gZ2V0TGVucyhiNjQpIHtcclxuICAgIHZhciBsZW4gPSBiNjQubGVuZ3RoO1xyXG4gICAgaWYgKGxlbiAlIDQgPiAwKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNFwiKTtcclxuICAgIH1cclxuICAgIC8vIFRyaW0gb2ZmIGV4dHJhIGJ5dGVzIGFmdGVyIHBsYWNlaG9sZGVyIGJ5dGVzIGFyZSBmb3VuZFxyXG4gICAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vYmVhdGdhbW1pdC9iYXNlNjQtanMvaXNzdWVzLzQyXHJcbiAgICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZihcIj1cIik7XHJcbiAgICBpZiAodmFsaWRMZW4gPT09IC0xKVxyXG4gICAgICAgIHZhbGlkTGVuID0gbGVuO1xyXG4gICAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cclxuICAgICAgICA/IDBcclxuICAgICAgICA6IDQgLSAodmFsaWRMZW4gJSA0KTtcclxuICAgIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl07XHJcbn1cclxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXHJcbmZ1bmN0aW9uIGJ5dGVMZW5ndGgoYjY0KSB7XHJcbiAgICB2YXIgbGVucyA9IGdldExlbnMoYjY0KTtcclxuICAgIHZhciB2YWxpZExlbiA9IGxlbnNbMF07XHJcbiAgICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXTtcclxuICAgIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlbjtcclxufVxyXG5mdW5jdGlvbiBfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pIHtcclxuICAgIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlbjtcclxufVxyXG5mdW5jdGlvbiBVdGlsX0Jhc2U2NF9EZWNvZGUoYjY0KSB7XHJcbiAgICB2YXIgdG1wO1xyXG4gICAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NCk7XHJcbiAgICB2YXIgdmFsaWRMZW4gPSBsZW5zWzBdO1xyXG4gICAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV07XHJcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoX2J5dGVMZW5ndGgoYjY0LCB2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuKSk7XHJcbiAgICB2YXIgY3VyQnl0ZSA9IDA7XHJcbiAgICAvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXHJcbiAgICB2YXIgbGVuID0gcGxhY2VIb2xkZXJzTGVuID4gMFxyXG4gICAgICAgID8gdmFsaWRMZW4gLSA0XHJcbiAgICAgICAgOiB2YWxpZExlbjtcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcclxuICAgICAgICB0bXAgPVxyXG4gICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxOCkgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDEyKSB8XHJcbiAgICAgICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPDwgNikgfFxyXG4gICAgICAgICAgICAgICAgcmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAzKV07XHJcbiAgICAgICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDE2KSAmIDB4RkY7XHJcbiAgICAgICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRjtcclxuICAgICAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkY7XHJcbiAgICB9XHJcbiAgICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAyKSB7XHJcbiAgICAgICAgdG1wID1cclxuICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMikgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldID4+IDQpO1xyXG4gICAgICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRjtcclxuICAgIH1cclxuICAgIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDEpIHtcclxuICAgICAgICB0bXAgPVxyXG4gICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDQpIHxcclxuICAgICAgICAgICAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKTtcclxuICAgICAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGO1xyXG4gICAgICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRjtcclxuICAgIH1cclxuICAgIHJldHVybiBhcnI7XHJcbn1cclxuZXhwb3J0cy5VdGlsX0Jhc2U2NF9EZWNvZGUgPSBVdGlsX0Jhc2U2NF9EZWNvZGU7XHJcbmZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NChudW0pIHtcclxuICAgIHJldHVybiBsb29rdXBbbnVtID4+IDE4ICYgMHgzRl0gK1xyXG4gICAgICAgIGxvb2t1cFtudW0gPj4gMTIgJiAweDNGXSArXHJcbiAgICAgICAgbG9va3VwW251bSA+PiA2ICYgMHgzRl0gK1xyXG4gICAgICAgIGxvb2t1cFtudW0gJiAweDNGXTtcclxufVxyXG5mdW5jdGlvbiBlbmNvZGVDaHVuayh1aW50OCwgc3RhcnQsIGVuZCkge1xyXG4gICAgdmFyIHRtcDtcclxuICAgIHZhciBvdXRwdXQgPSBbXTtcclxuICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSArPSAzKSB7XHJcbiAgICAgICAgdG1wID1cclxuICAgICAgICAgICAgKCh1aW50OFtpXSA8PCAxNikgJiAweEZGMDAwMCkgK1xyXG4gICAgICAgICAgICAgICAgKCh1aW50OFtpICsgMV0gPDwgOCkgJiAweEZGMDApICtcclxuICAgICAgICAgICAgICAgICh1aW50OFtpICsgMl0gJiAweEZGKTtcclxuICAgICAgICBvdXRwdXQucHVzaCh0cmlwbGV0VG9CYXNlNjQodG1wKSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gb3V0cHV0LmpvaW4oXCJcIik7XHJcbn1cclxuZnVuY3Rpb24gVXRpbF9CYXNlNjRfRW5jb2RlKHVpbnQ4KSB7XHJcbiAgICB2YXIgdG1wO1xyXG4gICAgdmFyIGxlbiA9IHVpbnQ4Lmxlbmd0aDtcclxuICAgIHZhciBleHRyYUJ5dGVzID0gbGVuICUgMzsgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcclxuICAgIHZhciBwYXJ0cyA9IFtdO1xyXG4gICAgdmFyIG1heENodW5rTGVuZ3RoID0gMTYzODM7IC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xyXG4gICAgLy8gZ28gdGhyb3VnaCB0aGUgYXJyYXkgZXZlcnkgdGhyZWUgYnl0ZXMsIHdlJ2xsIGRlYWwgd2l0aCB0cmFpbGluZyBzdHVmZiBsYXRlclxyXG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xyXG4gICAgICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsodWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKSkpO1xyXG4gICAgfVxyXG4gICAgLy8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xyXG4gICAgaWYgKGV4dHJhQnl0ZXMgPT09IDEpIHtcclxuICAgICAgICB0bXAgPSB1aW50OFtsZW4gLSAxXTtcclxuICAgICAgICBwYXJ0cy5wdXNoKGxvb2t1cFt0bXAgPj4gMl0gK1xyXG4gICAgICAgICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcclxuICAgICAgICAgICAgXCI9PVwiKTtcclxuICAgIH1cclxuICAgIGVsc2UgaWYgKGV4dHJhQnl0ZXMgPT09IDIpIHtcclxuICAgICAgICB0bXAgPSAodWludDhbbGVuIC0gMl0gPDwgOCkgKyB1aW50OFtsZW4gLSAxXTtcclxuICAgICAgICBwYXJ0cy5wdXNoKGxvb2t1cFt0bXAgPj4gMTBdICtcclxuICAgICAgICAgICAgbG9va3VwWyh0bXAgPj4gNCkgJiAweDNGXSArXHJcbiAgICAgICAgICAgIGxvb2t1cFsodG1wIDw8IDIpICYgMHgzRl0gK1xyXG4gICAgICAgICAgICBcIj1cIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcGFydHMuam9pbihcIlwiKTtcclxufVxyXG5leHBvcnRzLlV0aWxfQmFzZTY0X0VuY29kZSA9IFV0aWxfQmFzZTY0X0VuY29kZTtcclxuLy8vLy8vLy8gRU5EOiBCYXNlNjQgZW5jb2RlIC8gZGVjb2RlIHV0aWxpdHkgZnVuY3Rpb25zIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzXHJcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXZwbnJwYy5qcy5tYXAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBIiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/vpnrpc/dist/vpnrpc.js\n"); +eval("/* WEBPACK VAR INJECTION */(function(Buffer) {\r\n// SoftEther VPN Server JSON-RPC Stub code for TypeScript\r\n// \r\n// vpnrpc.ts\r\n// Automatically generated at 2019-05-29 18:21:39 by vpnserver-jsonrpc-codegen\r\n//\r\n// Licensed under the Apache License 2.0\r\n// Copyright (c) 2014-2019 SoftEther VPN Project\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = function (d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nexports.__esModule = true;\r\n// Trivial utility codes\r\nvar is_node_js = (typeof navigator === \"undefined\") || navigator.userAgent.indexOf(\"Node.js\") !== -1 || navigator.userAgent.indexOf(\"jsdom\") !== -1;\r\nfunction is_null(obj) {\r\n return (typeof obj === \"undefined\") || (obj === null);\r\n}\r\nvar debug_mode = false;\r\n/** VPN Server RPC Stubs */\r\nvar VpnServerRpc = /** @class */ (function () {\r\n /**\r\n * Constructor of the VpnServerRpc class\r\n * @param vpnserver_hostname The hostname or IP address of the destination VPN Server. In the web browser you can specify null if you want to connect to the server itself.\r\n * @param vpnserver_port The port number of the destination VPN Server. In the web browser you can specify null if you want to connect to the server itself.\r\n * @param hubname The name of the Virtual Hub if you want to connect to the VPN Server as a Virtual Hub Admin Mode. Specify null if you want to connect to the VPN Server as the Entire VPN Server Admin Mode.\r\n * @param password Specify the administration password. This value is valid only if vpnserver_hostname is sepcified.\r\n * @param nodejs_https_client_reject_untrusted_server_cert In Node.js set this true to check the SSL server certificate on the destination VPN Server. Set this false to ignore the SSL server certification.\r\n */\r\n function VpnServerRpc(vpnserver_hostname, vpnserver_port, hubname, password, nodejs_https_client_reject_untrusted_server_cert) {\r\n var _this = this;\r\n // --- Stubs ---\r\n /** Test RPC function. Input any integer value to the IntValue_u32 field. Then the server will convert the integer to the string, and return the string in the StrValue_str field. */\r\n this.Test = function (in_param) {\r\n return _this.CallAsync(\"Test\", in_param);\r\n };\r\n /** Get server information. This allows you to obtain the server information of the currently connected VPN Server or VPN Bridge. Included in the server information are the version number, build number and build information. You can also obtain information on the current server operation mode and the information of operating system that the server is operating on. */\r\n this.GetServerInfo = function () {\r\n return _this.CallAsync(\"GetServerInfo\", new VpnRpcServerInfo());\r\n };\r\n /** Get Current Server Status. This allows you to obtain in real-time the current status of the currently connected VPN Server or VPN Bridge. You can get statistical information on data communication and the number of different kinds of objects that exist on the server. You can get information on how much memory is being used on the current computer by the OS. */\r\n this.GetServerStatus = function () {\r\n return _this.CallAsync(\"GetServerStatus\", new VpnRpcServerStatus());\r\n };\r\n /** Create New TCP Listener. This allows you to create a new TCP Listener on the server. By creating the TCP Listener the server starts listening for a connection from clients at the specified TCP/IP port number. A TCP Listener that has been created can be deleted by the DeleteListener API. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To execute this API, you must have VPN Server administrator privileges. */\r\n this.CreateListener = function (in_param) {\r\n return _this.CallAsync(\"CreateListener\", in_param);\r\n };\r\n /** Get List of TCP Listeners. This allows you to get a list of TCP listeners registered on the current server. You can obtain information on whether the various TCP listeners have a status of operating or error. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumListener = function () {\r\n return _this.CallAsync(\"EnumListener\", new VpnRpcListenerList());\r\n };\r\n /** Delete TCP Listener. This allows you to delete a TCP Listener that's registered on the server. When the TCP Listener is in a state of operation, the listener will automatically be deleted when its operation stops. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To call this API, you must have VPN Server administrator privileges. */\r\n this.DeleteListener = function (in_param) {\r\n return _this.CallAsync(\"DeleteListener\", in_param);\r\n };\r\n /** Enable / Disable TCP Listener. This starts or stops the operation of TCP Listeners registered on the current server. You can also get a list of TCP Listeners currently registered by using the EnumListener API. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnableListener = function (in_param) {\r\n return _this.CallAsync(\"EnableListener\", in_param);\r\n };\r\n /** Set VPN Server Administrator Password. This sets the VPN Server administrator password. You can specify the password as a parameter. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerPassword = function (in_param) {\r\n return _this.CallAsync(\"SetServerPassword\", in_param);\r\n };\r\n /** Set the VPN Server clustering configuration. Use this to set the VPN Server type as Standalone Server, Cluster Controller Server or Cluster Member Server. Standalone server means a VPN Server that does not belong to any cluster in its current state. When VPN Server is installed, by default it will be in standalone server mode. Unless you have particular plans to configure a cluster, we recommend the VPN Server be operated in standalone mode. A cluster controller is the central computer of all member servers of a cluster in the case where a clustering environment is made up of multiple VPN Servers. Multiple cluster members can be added to the cluster as required. A cluster requires one computer to serve this role. The other cluster member servers that are configured in the same cluster begin operation as a cluster member by connecting to the cluster controller. To call this API, you must have VPN Server administrator privileges. Also, when this API is executed, VPN Server will automatically restart. This API cannot be called on VPN Bridge. */\r\n this.SetFarmSetting = function (in_param) {\r\n return _this.CallAsync(\"SetFarmSetting\", in_param);\r\n };\r\n /** Get Clustering Configuration of Current VPN Server. You can use this to acquire the clustering configuration of the current VPN Server. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetFarmSetting = function () {\r\n return _this.CallAsync(\"GetFarmSetting\", new VpnRpcFarm());\r\n };\r\n /** Get Cluster Member Information. When the VPN Server is operating as a cluster controller, you can get information on cluster member servers on that cluster by specifying the IDs of the member servers. You can get the following information about the specified cluster member server: Server Type, Time Connection has been Established, IP Address, Host Name, Points, Public Port List, Number of Operating Virtual Hubs, First Virtual Hub, Number of Sessions and Number of TCP Connections. This API cannot be invoked on VPN Bridge. */\r\n this.GetFarmInfo = function (in_param) {\r\n return _this.CallAsync(\"GetFarmInfo\", in_param);\r\n };\r\n /** Get List of Cluster Members. Use this API when the VPN Server is operating as a cluster controller to get a list of the cluster member servers on the same cluster, including the cluster controller itself. For each member, the following information is also listed: Type, Connection Start, Host Name, Points, Number of Session, Number of TCP Connections, Number of Operating Virtual Hubs, Using Client Connection License and Using Bridge Connection License. This API cannot be invoked on VPN Bridge. */\r\n this.EnumFarmMember = function () {\r\n return _this.CallAsync(\"EnumFarmMember\", new VpnRpcEnumFarm());\r\n };\r\n /** Get Connection Status to Cluster Controller. Use this API when the VPN Server is operating as a cluster controller to get the status of connection to the cluster controller. You can get the following information: Controller IP Address, Port Number, Connection Status, Connection Start Time, First Connection Established Time, Current Connection Established Time, Number of Connection Attempts, Number of Successful Connections, Number of Failed Connections. This API cannot be invoked on VPN Bridge. */\r\n this.GetFarmConnectionStatus = function () {\r\n return _this.CallAsync(\"GetFarmConnectionStatus\", new VpnRpcFarmConnectionStatus());\r\n };\r\n /** Set SSL Certificate and Private Key of VPN Server. You can set the SSL certificate that the VPN Server provides to the connected client and the private key for that certificate. The certificate must be in X.509 format and the private key must be Base 64 encoded format. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerCert = function (in_param) {\r\n return _this.CallAsync(\"SetServerCert\", in_param);\r\n };\r\n /** Get SSL Certificate and Private Key of VPN Server. Use this to get the SSL certificate private key that the VPN Server provides to the connected client. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetServerCert = function () {\r\n return _this.CallAsync(\"GetServerCert\", new VpnRpcKeyPair());\r\n };\r\n /** Get the Encrypted Algorithm Used for VPN Communication. Use this API to get the current setting of the algorithm used for the electronic signature and encrypted for SSL connection to be used for communication between the VPN Server and the connected client and the list of algorithms that can be used on the VPN Server. */\r\n this.GetServerCipher = function () {\r\n return _this.CallAsync(\"GetServerCipher\", new VpnRpcStr());\r\n };\r\n /** Set the Encrypted Algorithm Used for VPN Communication. Use this API to set the algorithm used for the electronic signature and encrypted for SSL connections to be used for communication between the VPN Server and the connected client. By specifying the algorithm name, the specified algorithm will be used later between the VPN Client and VPN Bridge connected to this server and the data will be encrypted. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetServerCipher = function (in_param) {\r\n return _this.CallAsync(\"SetServerCipher\", in_param);\r\n };\r\n /** Create New Virtual Hub. Use this to create a new Virtual Hub on the VPN Server. The created Virtual Hub will begin operation immediately. When the VPN Server is operating on a cluster, this API is only valid for the cluster controller. Also, the new Virtual Hub will operate as a dynamic Virtual Hub. You can change it to a static Virtual Hub by using the SetHub API. To get a list of Virtual Hubs that are already on the VPN Server, use the EnumHub API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Servers that are operating as a VPN Bridge or cluster member. */\r\n this.CreateHub = function (in_param) {\r\n return _this.CallAsync(\"CreateHub\", in_param);\r\n };\r\n /** Set the Virtual Hub configuration. You can call this API to change the configuration of the specified Virtual Hub. You can set the Virtual Hub online or offline. You can set the maximum number of sessions that can be concurrently connected to the Virtual Hub that is currently being managed. You can set the Virtual Hub administrator password. You can set other parameters for the Virtual Hub. Before call this API, you need to obtain the latest state of the Virtual Hub by using the GetHub API. */\r\n this.SetHub = function (in_param) {\r\n return _this.CallAsync(\"SetHub\", in_param);\r\n };\r\n /** Get the Virtual Hub configuration. You can call this API to get the current configuration of the specified Virtual Hub. To change the configuration of the Virtual Hub, call the SetHub API. */\r\n this.GetHub = function (in_param) {\r\n return _this.CallAsync(\"GetHub\", in_param);\r\n };\r\n /** Get List of Virtual Hubs. Use this to get a list of existing Virtual Hubs on the VPN Server. For each Virtual Hub, you can get the following information: Virtual Hub Name, Status, Type, Number of Users, Number of Groups, Number of Sessions, Number of MAC Tables, Number of IP Tables, Number of Logins, Last Login, and Last Communication. Note that when connecting in Virtual Hub Admin Mode, if in the options of a Virtual Hub that you do not have administrator privileges for, the option Don't Enumerate this Virtual Hub for Anonymous Users is enabled then that Virtual Hub will not be enumerated. If you are connected in Server Admin Mode, then the list of all Virtual Hubs will be displayed. When connecting to and managing a non-cluster-controller cluster member of a clustering environment, only the Virtual Hub currently being hosted by that VPN Server will be displayed. When connecting to a cluster controller for administration purposes, all the Virtual Hubs will be displayed. */\r\n this.EnumHub = function () {\r\n return _this.CallAsync(\"EnumHub\", new VpnRpcEnumHub());\r\n };\r\n /** Delete Virtual Hub. Use this to delete an existing Virtual Hub on the VPN Server. If you delete the Virtual Hub, all sessions that are currently connected to the Virtual Hub will be disconnected and new sessions will be unable to connect to the Virtual Hub. Also, this will also delete all the Hub settings, user objects, group objects, certificates and Cascade Connections. Once you delete the Virtual Hub, it cannot be recovered. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Servers that are operating as a VPN Bridge or cluster member. */\r\n this.DeleteHub = function (in_param) {\r\n return _this.CallAsync(\"DeleteHub\", in_param);\r\n };\r\n /** Get Setting of RADIUS Server Used for User Authentication. Use this to get the current settings for the RADIUS server used when a user connects to the currently managed Virtual Hub using RADIUS Server Authentication Mode. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetHubRadius = function (in_param) {\r\n return _this.CallAsync(\"GetHubRadius\", in_param);\r\n };\r\n /** Set RADIUS Server to use for User Authentication. To accept users to the currently managed Virtual Hub in RADIUS server authentication mode, you can specify an external RADIUS server that confirms the user name and password. (You can specify multiple hostname by splitting with comma or semicolon.) The RADIUS server must be set to receive requests from IP addresses of this VPN Server. Also, authentication by Password Authentication Protocol (PAP) must be enabled. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetHubRadius = function (in_param) {\r\n return _this.CallAsync(\"SetHubRadius\", in_param);\r\n };\r\n /** Get List of TCP Connections Connecting to the VPN Server. Use this to get a list of TCP/IP connections that are currently connecting to the VPN Server. It does not display the TCP connections that have been established as VPN sessions. To get the list of TCP/IP connections that have been established as VPN sessions, you can use the EnumSession API. You can get the following: Connection Name, Connection Source, Connection Start and Type. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumConnection = function () {\r\n return _this.CallAsync(\"EnumConnection\", new VpnRpcEnumConnection());\r\n };\r\n /** Disconnect TCP Connections Connecting to the VPN Server. Use this to forcefully disconnect specific TCP/IP connections that are connecting to the VPN Server. To call this API, you must have VPN Server administrator privileges. */\r\n this.DisconnectConnection = function (in_param) {\r\n return _this.CallAsync(\"DisconnectConnection\", in_param);\r\n };\r\n /** Get Information of TCP Connections Connecting to the VPN Server. Use this to get detailed information of a specific TCP/IP connection that is connecting to the VPN Server. You can get the following information: Connection Name, Connection Type, Source Hostname, Source IP Address, Source Port Number (TCP), Connection Start, Server Product Name, Server Version, Server Build Number, Client Product Name, Client Version, and Client Build Number. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetConnectionInfo = function (in_param) {\r\n return _this.CallAsync(\"GetConnectionInfo\", in_param);\r\n };\r\n /** Switch Virtual Hub to Online or Offline. Use this to set the Virtual Hub to online or offline. A Virtual Hub with an offline status cannot receive VPN connections from clients. When you set the Virtual Hub offline, all sessions will be disconnected. A Virtual Hub with an offline status cannot receive VPN connections from clients. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetHubOnline = function (in_param) {\r\n return _this.CallAsync(\"SetHubOnline\", in_param);\r\n };\r\n /** Get Current Status of Virtual Hub. Use this to get the current status of the Virtual Hub currently being managed. You can get the following information: Virtual Hub Type, Number of Sessions, Number of Each Type of Object, Number of Logins, Last Login, Last Communication, and Communication Statistical Data. */\r\n this.GetHubStatus = function (in_param) {\r\n return _this.CallAsync(\"GetHubStatus\", in_param);\r\n };\r\n /** Set the logging configuration of the Virtual Hub. Use this to enable or disable a security log or packet logs of the Virtual Hub currently being managed, set the save contents of the packet log for each type of packet to be saved, and set the log file switch cycle for the security log or packet log that the currently managed Virtual Hub saves. There are the following packet types: TCP Connection Log, TCP Packet Log, DHCP Packet Log, UDP Packet Log, ICMP Packet Log, IP Packet Log, ARP Packet Log, and Ethernet Packet Log. To get the current setting, you can use the LogGet API. The log file switch cycle can be changed to switch in every second, every minute, every hour, every day, every month or not switch. To get the current setting, you can use the GetHubLog API. */\r\n this.SetHubLog = function (in_param) {\r\n return _this.CallAsync(\"SetHubLog\", in_param);\r\n };\r\n /** Get the logging configuration of the Virtual Hub. Use this to get the configuration for a security log or packet logs of the Virtual Hub currently being managed, get the setting for save contents of the packet log for each type of packet to be saved, and get the log file switch cycle for the security log or packet log that the currently managed Virtual Hub saves. To set the current setting, you can use the SetHubLog API. */\r\n this.GetHubLog = function (in_param) {\r\n return _this.CallAsync(\"GetHubLog\", in_param);\r\n };\r\n /** Add Trusted CA Certificate. Use this to add a new certificate to a list of CA certificates trusted by the currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. To get a list of the current certificates you can use the EnumCa API. The certificate you add must be saved in the X.509 file format. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.AddCa = function (in_param) {\r\n return _this.CallAsync(\"AddCa\", in_param);\r\n };\r\n /** Get List of Trusted CA Certificates. Here you can manage the certificate authority certificates that are trusted by this currently managed Virtual Hub. The list of certificate authority certificates that are registered is used to verify certificates when a VPN Client is connected in signed certificate authentication mode. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumCa = function (in_param) {\r\n return _this.CallAsync(\"EnumCa\", in_param);\r\n };\r\n /** Get Trusted CA Certificate. Use this to get an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub and save it as a file in X.509 format. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetCa = function (in_param) {\r\n return _this.CallAsync(\"GetCa\", in_param);\r\n };\r\n /** Delete Trusted CA Certificate. Use this to delete an existing certificate from the list of CA certificates trusted by the currently managed Virtual Hub. To get a list of the current certificates you can use the EnumCa API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteCa = function (in_param) {\r\n return _this.CallAsync(\"DeleteCa\", in_param);\r\n };\r\n /** Create New Cascade Connection. Use this to create a new Cascade Connection on the currently managed Virtual Hub. By using a Cascade Connection, you can connect this Virtual Hub by Cascade Connection to another Virtual Hub that is operating on the same or a different computer. To create a Cascade Connection, you must specify the name of the Cascade Connection, destination server and destination Virtual Hub and user name. When a new Cascade Connection is created, the type of user authentication is initially set as Anonymous Authentication and the proxy server setting and the verification options of the server certificate is not set. To change these settings and other advanced settings after a Cascade Connection has been created, use the other APIs that include the name \"Link\". [Warning About Cascade Connections] By connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.CreateLink = function (in_param) {\r\n return _this.CallAsync(\"CreateLink\", in_param);\r\n };\r\n /** Get the Cascade Connection Setting. Use this to get the Connection Setting of a Cascade Connection that is registered on the currently managed Virtual Hub. To change the Connection Setting contents of the Cascade Connection, use the APIs that include the name \"Link\" after creating the Cascade Connection. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetLink = function (in_param) {\r\n return _this.CallAsync(\"GetLink\", in_param);\r\n };\r\n /** Change Existing Cascade Connection. Use this to alter the setting of an existing Cascade Connection on the currently managed Virtual Hub. */\r\n this.SetLink = function (in_param) {\r\n return _this.CallAsync(\"SetLink\", in_param);\r\n };\r\n /** Get List of Cascade Connections. Use this to get a list of Cascade Connections that are registered on the currently managed Virtual Hub. By using a Cascade Connection, you can connect this Virtual Hub by Layer 2 Cascade Connection to another Virtual Hub that is operating on the same or a different computer. [Warning About Cascade Connections] By connecting using a Cascade Connection you can create a Layer 2 bridge between multiple Virtual Hubs but if the connection is incorrectly configured, a loopback Cascade Connection could inadvertently be created. When using a Cascade Connection function please design the network topology with care. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumLink = function (in_param) {\r\n return _this.CallAsync(\"EnumLink\", in_param);\r\n };\r\n /** Switch Cascade Connection to Online Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to online status. The Cascade Connection that is switched to online status begins the process of connecting to the destination VPN Server in accordance with the Connection Setting. The Cascade Connection that is switched to online status will establish normal connection to the VPN Server or continue to attempt connection until it is switched to offline status. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetLinkOnline = function (in_param) {\r\n return _this.CallAsync(\"SetLinkOnline\", in_param);\r\n };\r\n /** Switch Cascade Connection to Offline Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to switch that Cascade Connection to offline status. The Cascade Connection that is switched to offline will not connect to the VPN Server until next time it is switched to the online status using the SetLinkOnline API You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetLinkOffline = function (in_param) {\r\n return _this.CallAsync(\"SetLinkOffline\", in_param);\r\n };\r\n /** Delete Cascade Connection Setting. Use this to delete a Cascade Connection that is registered on the currently managed Virtual Hub. If the specified Cascade Connection has a status of online, the connections will be automatically disconnected and then the Cascade Connection will be deleted. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DeleteLink = function (in_param) {\r\n return _this.CallAsync(\"DeleteLink\", in_param);\r\n };\r\n /** Change Name of Cascade Connection. When a Cascade Connection registered on the currently managed Virtual Hub is specified, use this to change the name of that Cascade Connection. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.RenameLink = function (in_param) {\r\n return _this.CallAsync(\"RenameLink\", in_param);\r\n };\r\n /** Get Current Cascade Connection Status. When a Cascade Connection registered on the currently managed Virtual Hub is specified and that Cascade Connection is currently online, use this to get its connection status and other information. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetLinkStatus = function (in_param) {\r\n return _this.CallAsync(\"GetLinkStatus\", in_param);\r\n };\r\n /** Add Access List Rule. Use this to add a new rule to the access list of the currently managed Virtual Hub. The access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define an priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. You can also use the access list to generate delays, jitters and packet losses. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.AddAccess = function (in_param) {\r\n return _this.CallAsync(\"AddAccess\", in_param);\r\n };\r\n /** Delete Rule from Access List. Use this to specify a packet filter rule registered on the access list of the currently managed Virtual Hub and delete it. To delete a rule, you must specify that rule's ID. You can display the ID by using the EnumAccess API. If you wish not to delete the rule but to only temporarily disable it, use the SetAccessList API to set the rule status to disable. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteAccess = function (in_param) {\r\n return _this.CallAsync(\"DeleteAccess\", in_param);\r\n };\r\n /** Get Access List Rule List. Use this to get a list of packet filter rules that are registered on access list of the currently managed Virtual Hub. The access list is a set of packet file rules that are applied to packets that flow through the Virtual Hub. You can register multiple rules in an access list and you can also define a priority for each rule. All packets are checked for the conditions specified by the rules registered in the access list and based on the operation that is stipulated by the first matching rule, they either pass or are discarded. Packets that do not match any rule are implicitly allowed to pass. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumAccess = function (in_param) {\r\n return _this.CallAsync(\"EnumAccess\", in_param);\r\n };\r\n /** Replace all access lists on a single bulk API call. This API removes all existing access list rules on the Virtual Hub, and replace them by new access list rules specified by the parameter. */\r\n this.SetAccessList = function (in_param) {\r\n return _this.CallAsync(\"SetAccessList\", in_param);\r\n };\r\n /** Create a user. Use this to create a new user in the security account database of the currently managed Virtual Hub. By creating a user, the VPN Client can connect to the Virtual Hub by using the authentication information of that user. Note that a user whose user name has been created as \"*\" (a single asterisk character) will automatically be registered as a RADIUS authentication user. For cases where there are users with \"*\" as the name, when a user, whose user name that has been provided when a client connected to a VPN Server does not match existing user names, is able to be authenticated by a RADIUS server or NT domain controller by inputting a user name and password, the authentication settings and security policy settings will follow the setting for the user \"*\". To change the user information of a user that has been created, use the SetUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.CreateUser = function (in_param) {\r\n return _this.CallAsync(\"CreateUser\", in_param);\r\n };\r\n /** Change User Settings. Use this to change user settings that is registered on the security account database of the currently managed Virtual Hub. The user settings that can be changed using this API are the three items that are specified when a new user is created using the CreateUser API: Group Name, Full Name, and Description. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.SetUser = function (in_param) {\r\n return _this.CallAsync(\"SetUser\", in_param);\r\n };\r\n /** Get User Settings. Use this to get user settings information that is registered on the security account database of the currently managed Virtual Hub. The information that you can get using this API are User Name, Full Name, Group Name, Expiration Date, Security Policy, and Auth Type, as well as parameters that are specified as auth type attributes and the statistical data of that user. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetUser = function (in_param) {\r\n return _this.CallAsync(\"GetUser\", in_param);\r\n };\r\n /** Delete a user. Use this to delete a user that is registered on the security account database of the currently managed Virtual Hub. By deleting the user, that user will no long be able to connect to the Virtual Hub. You can use the SetUser API to set the user's security policy to deny access instead of deleting a user, set the user to be temporarily denied from logging in. To get the list of currently registered users, use the EnumUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteUser = function (in_param) {\r\n return _this.CallAsync(\"DeleteUser\", in_param);\r\n };\r\n /** Get List of Users. Use this to get a list of users that are registered on the security account database of the currently managed Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumUser = function (in_param) {\r\n return _this.CallAsync(\"EnumUser\", in_param);\r\n };\r\n /** Create Group. Use this to create a new group in the security account database of the currently managed Virtual Hub. You can register multiple users in a group. To register users in a group use the SetUser API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.CreateGroup = function (in_param) {\r\n return _this.CallAsync(\"CreateGroup\", in_param);\r\n };\r\n /** Set group settings. Use this to set group settings that is registered on the security account database of the currently managed Virtual Hub. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.SetGroup = function (in_param) {\r\n return _this.CallAsync(\"SetGroup\", in_param);\r\n };\r\n /** Get Group Setting (Sync mode). Use this to get the setting of a group that is registered on the security account database of the currently managed Virtual Hub. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.GetGroup = function (in_param) {\r\n return _this.CallAsync(\"GetGroup\", in_param);\r\n };\r\n /** Delete User from Group. Use this to delete a specified user from the group that is registered on the security account database of the currently managed Virtual Hub. By deleting a user from the group, that user becomes unassigned. To get the list of currently registered groups, use the EnumGroup API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.DeleteGroup = function (in_param) {\r\n return _this.CallAsync(\"DeleteGroup\", in_param);\r\n };\r\n /** Get List of Groups. Use this to get a list of groups that are registered on the security account database of the currently managed Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a member server on a cluster. */\r\n this.EnumGroup = function (in_param) {\r\n return _this.CallAsync(\"EnumGroup\", in_param);\r\n };\r\n /** Get List of Connected VPN Sessions. Use this to get a list of the sessions connected to the Virtual Hub currently being managed. In the list of sessions, the following information will be obtained for each connection: Session Name, Session Site, User Name, Source Host Name, TCP Connection, Transfer Bytes and Transfer Packets. If the currently connected VPN Server is a cluster controller and the currently managed Virtual Hub is a static Virtual Hub, you can get an all-linked-together list of all sessions connected to that Virtual Hub on all cluster members. In all other cases, only the list of sessions that are actually connected to the currently managed VPN Server will be obtained. */\r\n this.EnumSession = function (in_param) {\r\n return _this.CallAsync(\"EnumSession\", in_param);\r\n };\r\n /** Get Session Status. Use this to specify a session currently connected to the currently managed Virtual Hub and get the session information. The session status includes the following: source host name and user name, version information, time information, number of TCP connections, communication parameters, session key, statistical information on data transferred, and other client and server information. To get the list of currently connected sessions, use the EnumSession API. */\r\n this.GetSessionStatus = function (in_param) {\r\n return _this.CallAsync(\"GetSessionStatus\", in_param);\r\n };\r\n /** Disconnect Session. Use this to specify a session currently connected to the currently managed Virtual Hub and forcefully disconnect that session using manager privileges. Note that when communication is disconnected by settings on the source client side and the automatically reconnect option is enabled, it is possible that the client will reconnect. To get the list of currently connected sessions, use the EnumSession API. */\r\n this.DeleteSession = function (in_param) {\r\n return _this.CallAsync(\"DeleteSession\", in_param);\r\n };\r\n /** Get the MAC Address Table Database. Use this to get the MAC address table database that is held by the currently managed Virtual Hub. The MAC address table database is a table that the Virtual Hub requires to perform the action of switching Ethernet frames and the Virtual Hub decides the sorting destination session of each Ethernet frame based on the MAC address table database. The MAC address database is built by the Virtual Hub automatically analyzing the contents of the communication. */\r\n this.EnumMacTable = function (in_param) {\r\n return _this.CallAsync(\"EnumMacTable\", in_param);\r\n };\r\n /** Delete MAC Address Table Entry. Use this API to operate the MAC address table database held by the currently managed Virtual Hub and delete a specified MAC address table entry from the database. To get the contents of the current MAC address table database use the EnumMacTable API. */\r\n this.DeleteMacTable = function (in_param) {\r\n return _this.CallAsync(\"DeleteMacTable\", in_param);\r\n };\r\n /** Get the IP Address Table Database. Use this to get the IP address table database that is held by the currently managed Virtual Hub. The IP address table database is a table that is automatically generated by analyzing the contents of communication so that the Virtual Hub can always know which session is using which IP address and it is frequently used by the engine that applies the Virtual Hub security policy. By specifying the session name you can get the IP address table entry that has been associated with that session. */\r\n this.EnumIpTable = function (in_param) {\r\n return _this.CallAsync(\"EnumIpTable\", in_param);\r\n };\r\n /** Delete IP Address Table Entry. Use this API to operate the IP address table database held by the currently managed Virtual Hub and delete a specified IP address table entry from the database. To get the contents of the current IP address table database use the EnumIpTable API. */\r\n this.DeleteIpTable = function (in_param) {\r\n return _this.CallAsync(\"DeleteIpTable\", in_param);\r\n };\r\n /** Set the Keep Alive Internet Connection Function. Use this to set the destination host name etc. of the Keep Alive Internet Connection Function. For network connection environments where connections will automatically be disconnected where there are periods of no communication that are longer than a set period, by using the Keep Alive Internet Connection Function, it is possible to keep alive the Internet connection by sending packets to a nominated server on the Internet at set intervals. When using this API, you can specify the following: Host Name, Port Number, Packet Send Interval, and Protocol. Packets sent to keep alive the Internet connection will have random content and personal information that could identify a computer or user is not sent. You can use the SetKeep API to enable/disable the Keep Alive Internet Connection Function. To execute this API on a VPN Server or VPN Bridge, you must have administrator privileges. */\r\n this.SetKeep = function (in_param) {\r\n return _this.CallAsync(\"SetKeep\", in_param);\r\n };\r\n /** Get the Keep Alive Internet Connection Function. Use this to get the current setting contents of the Keep Alive Internet Connection Function. In addition to the destination's Host Name, Port Number, Packet Send Interval and Protocol, you can obtain the current enabled/disabled status of the Keep Alive Internet Connection Function. */\r\n this.GetKeep = function (in_param) {\r\n return _this.CallAsync(\"GetKeep\", in_param);\r\n };\r\n /** Enable the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to enable the Virtual NAT and DHCP Server function (SecureNAT Function) on the currently managed Virtual Hub and begin its operation. Before executing this API, you must first check the setting contents of the current Virtual NAT function and DHCP Server function using the SetSecureNATOption API and GetSecureNATOption API. By enabling the SecureNAT function, you can virtually operate a NAT router (IP masquerade) and the DHCP Server function on a virtual network on the Virtual Hub. [Warning about SecureNAT Function] The SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. If you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrator's permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnableSecureNAT = function (in_param) {\r\n return _this.CallAsync(\"EnableSecureNAT\", in_param);\r\n };\r\n /** Disable the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to disable the Virtual NAT and DHCP Server function (SecureNAT Function) on the currently managed Virtual Hub. By executing this API the Virtual NAT function immediately stops operating and the Virtual DHCP Server function deletes the DHCP lease database and stops the service. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DisableSecureNAT = function (in_param) {\r\n return _this.CallAsync(\"DisableSecureNAT\", in_param);\r\n };\r\n /** Change Settings of SecureNAT Function. Use this to change and save the virtual host network interface settings, virtual NAT function settings and virtual DHCP server settings of the Virtual NAT and DHCP Server function (SecureNAT function) on the currently managed Virtual Hub. The SecureNAT function holds one virtual network adapter on the L2 segment inside the Virtual Hub and it has been assigned a MAC address and an IP address. By doing this, another host connected to the same L2 segment is able to communicate with the SecureNAT virtual host as if it is an actual IP host existing on the network. [Warning about SecureNAT Function] The SecureNAT function is recommended only for system administrators and people with a detailed knowledge of networks. If you use the SecureNAT function correctly, it is possible to achieve a safe form of remote access via a VPN. However when used in the wrong way, it can put the entire network in danger. Anyone who does not have a thorough knowledge of networks and anyone who does not have the network administrators permission must not enable the SecureNAT function. For a detailed explanation of the SecureNAT function, please refer to the VPN Server's manual and online documentation. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetSecureNATOption = function (in_param) {\r\n return _this.CallAsync(\"SetSecureNATOption\", in_param);\r\n };\r\n /** Get Settings of SecureNAT Function. This API get the registered settings for the SecureNAT function which is set by the SetSecureNATOption API. */\r\n this.GetSecureNATOption = function (in_param) {\r\n return _this.CallAsync(\"GetSecureNATOption\", in_param);\r\n };\r\n /** Get Virtual NAT Function Session Table of SecureNAT Function. Use this to get the table of TCP and UDP sessions currently communicating via the Virtual NAT (NAT table) in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumNAT = function (in_param) {\r\n return _this.CallAsync(\"EnumNAT\", in_param);\r\n };\r\n /** Get Virtual DHCP Server Function Lease Table of SecureNAT Function. Use this to get the lease table of IP addresses, held by the Virtual DHCP Server, that are assigned to clients in cases when the Virtual NAT function is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumDHCP = function (in_param) {\r\n return _this.CallAsync(\"EnumDHCP\", in_param);\r\n };\r\n /** Get the Operating Status of the Virtual NAT and DHCP Server Function (SecureNAT Function). Use this to get the operating status of the Virtual NAT and DHCP Server function (SecureNAT Function) when it is operating on the currently managed Virtual Hub. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetSecureNATStatus = function (in_param) {\r\n return _this.CallAsync(\"GetSecureNATStatus\", in_param);\r\n };\r\n /** Get List of Network Adapters Usable as Local Bridge. Use this to get a list of Ethernet devices (network adapters) that can be used as a bridge destination device as part of a Local Bridge connection. If possible, network connection name is displayed. You can use a device displayed here by using the AddLocalBridge API. To call this API, you must have VPN Server administrator privileges. */\r\n this.EnumEthernet = function () {\r\n return _this.CallAsync(\"EnumEthernet\", new VpnRpcEnumEth());\r\n };\r\n /** Create Local Bridge Connection. Use this to create a new Local Bridge connection on the VPN Server. By using a Local Bridge, you can configure a Layer 2 bridge connection between a Virtual Hub operating on this VPN server and a physical Ethernet Device (Network Adapter). You can create a tap device (virtual network interface) on the system and connect a bridge between Virtual Hubs (the tap device is only supported by Linux versions). It is possible to establish a bridge to an operating network adapter of your choice for the bridge destination Ethernet device (network adapter), but in high load environments, we recommend you prepare a network adapter dedicated to serve as a bridge. To call this API, you must have VPN Server administrator privileges. */\r\n this.AddLocalBridge = function (in_param) {\r\n return _this.CallAsync(\"AddLocalBridge\", in_param);\r\n };\r\n /** Delete Local Bridge Connection. Use this to delete an existing Local Bridge connection. To get a list of current Local Bridge connections use the EnumLocalBridge API. To call this API, you must have VPN Server administrator privileges. */\r\n this.DeleteLocalBridge = function (in_param) {\r\n return _this.CallAsync(\"DeleteLocalBridge\", in_param);\r\n };\r\n /** Get List of Local Bridge Connection. Use this to get a list of the currently defined Local Bridge connections. You can get the Local Bridge connection Virtual Hub name and the bridge destination Ethernet device (network adapter) name or tap device name, as well as the operating status. */\r\n this.EnumLocalBridge = function () {\r\n return _this.CallAsync(\"EnumLocalBridge\", new VpnRpcEnumLocalBridge());\r\n };\r\n /** Get whether the localbridge function is supported on the current system. */\r\n this.GetBridgeSupport = function () {\r\n return _this.CallAsync(\"GetBridgeSupport\", new VpnRpcBridgeSupport());\r\n };\r\n /** Reboot VPN Server Service. Use this to restart the VPN Server service. When you restart the VPN Server, all currently connected sessions and TCP connections will be disconnected and no new connections will be accepted until the restart process has completed. By using this API, only the VPN Server service program will be restarted and the physical computer that VPN Server is operating on does not restart. This management session will also be disconnected, so you will need to reconnect to continue management. Also, by specifying the \"IntValue\" parameter to \"1\", the contents of the configuration file (.config) held by the current VPN Server will be initialized. To call this API, you must have VPN Server administrator privileges. */\r\n this.RebootServer = function (in_param) {\r\n return _this.CallAsync(\"RebootServer\", in_param);\r\n };\r\n /** Get List of Server Functions / Capability. Use this get a list of functions and capability of the VPN Server currently connected and being managed. The function and capability of VPN Servers are different depending on the operating VPN server's edition and version. Using this API, you can find out the capability of the target VPN Server and report it. */\r\n this.GetCaps = function () {\r\n return _this.CallAsync(\"GetCaps\", new VpnCapslist());\r\n };\r\n /** Get the current configuration of the VPN Server. Use this to get a text file (.config file) that contains the current configuration contents of the VPN server. You can get the status on the VPN Server at the instant this API is executed. You can edit the configuration file by using a regular text editor. To write an edited configuration to the VPN Server, use the SetConfig API. To call this API, you must have VPN Server administrator privileges. */\r\n this.GetConfig = function () {\r\n return _this.CallAsync(\"GetConfig\", new VpnRpcConfig());\r\n };\r\n /** Write Configuration File to VPN Server. Use this to write the configuration file to the VPN Server. By executing this API, the contents of the specified configuration file will be applied to the VPN Server and the VPN Server program will automatically restart and upon restart, operate according to the new configuration contents. Because it is difficult for an administrator to write all the contents of a configuration file, we recommend you use the GetConfig API to get the current contents of the VPN Server configuration and save it to file. You can then edit these contents in a regular text editor and then use the SetConfig API to rewrite the contents to the VPN Server. This API is for people with a detailed knowledge of the VPN Server and if an incorrectly configured configuration file is written to the VPN Server, it not only could cause errors, it could also result in the lost of the current setting data. Take special care when carrying out this action. To call this API, you must have VPN Server administrator privileges. */\r\n this.SetConfig = function (in_param) {\r\n return _this.CallAsync(\"SetConfig\", in_param);\r\n };\r\n /** Get Virtual Hub Administration Option default values. */\r\n this.GetDefaultHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"GetDefaultHubAdminOptions\", in_param);\r\n };\r\n /** Get List of Virtual Hub Administration Options. Use this to get a list of Virtual Hub administration options that are set on the currently managed Virtual Hub. The purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. Only an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. There is an exception however. If allow_hub_admin_change_option is set to \"1\", even Virtual Hub administrators are able to edit the administration options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.GetHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"GetHubAdminOptions\", in_param);\r\n };\r\n /** Set Values of Virtual Hub Administration Options. Use this to change the values of Virtual Hub administration options that are set on the currently managed Virtual Hub. The purpose of the Virtual Hub administration options is for the VPN Server Administrator to set limits for the setting ranges when the administration of the Virtual Hub is to be trusted to each Virtual Hub administrator. Only an administrator with administration privileges for this entire VPN Server is able to add, edit and delete the Virtual Hub administration options. The Virtual Hub administrators are unable to make changes to the administration options, however they are able to view them. There is an exception however. If allow_hub_admin_change_option is set to \"1\", even Virtual Hub administrators are able to edit the administration options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.SetHubAdminOptions = function (in_param) {\r\n return _this.CallAsync(\"SetHubAdminOptions\", in_param);\r\n };\r\n /** Get List of Virtual Hub Extended Options. Use this to get a Virtual Hub Extended Options List that is set on the currently managed Virtual Hub. Virtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub. By default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options. However, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.GetHubExtOptions = function (in_param) {\r\n return _this.CallAsync(\"GetHubExtOptions\", in_param);\r\n };\r\n /** Set a Value of Virtual Hub Extended Options. Use this to set a value in the Virtual Hub Extended Options List that is set on the currently managed Virtual Hub. Virtual Hub Extended Option enables you to configure more detail settings of the Virtual Hub. By default, both VPN Server's global administrators and individual Virtual Hub's administrators can modify the Virtual Hub Extended Options. However, if the deny_hub_admin_change_ext_option is set to 1 on the Virtual Hub Admin Options, the individual Virtual Hub's administrators cannot modify the Virtual Hub Extended Options. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster member. */\r\n this.SetHubExtOptions = function (in_param) {\r\n return _this.CallAsync(\"SetHubExtOptions\", in_param);\r\n };\r\n /** Define New Virtual Layer 3 Switch. Use this to define a new Virtual Layer 3 Switch on the VPN Server. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.AddL3Switch = function (in_param) {\r\n return _this.CallAsync(\"AddL3Switch\", in_param);\r\n };\r\n /** Delete Virtual Layer 3 Switch. Use this to delete an existing Virtual Layer 3 Switch that is defined on the VPN Server. When the specified Virtual Layer 3 Switch is operating, it will be automatically deleted after operation stops. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.DelL3Switch = function (in_param) {\r\n return _this.CallAsync(\"DelL3Switch\", in_param);\r\n };\r\n /** Get List of Virtual Layer 3 Switches. Use this to define a new Virtual Layer 3 Switch on the VPN Server. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.EnumL3Switch = function () {\r\n return _this.CallAsync(\"EnumL3Switch\", new VpnRpcEnumL3Sw());\r\n };\r\n /** Start Virtual Layer 3 Switch Operation. Use this to start the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently stopped. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. [Explanation on Virtual Layer 3 Switch Function] You can define Virtual Layer 3 Switches between multiple Virtual Hubs operating on this VPN Server and configure routing between different IP networks. [Caution about the Virtual Layer 3 Switch Function] The Virtual Layer 3 Switch functions are provided for network administrators and other people who know a lot about networks and IP routing. If you are using the regular VPN functions, you do not need to use the Virtual Layer 3 Switch functions. If the Virtual Layer 3 Switch functions are to be used, the person who configures them must have sufficient knowledge of IP routing and be perfectly capable of not impacting the network. */\r\n this.StartL3Switch = function (in_param) {\r\n return _this.CallAsync(\"StartL3Switch\", in_param);\r\n };\r\n /** Stop Virtual Layer 3 Switch Operation. Use this to stop the operation of an existing Virtual Layer 3 Switch defined on the VPN Server whose operation is currently operating. To get a list of existing Virtual Layer 3 Switches, use the EnumL3Switch API. To call this API, you must have VPN Server administrator privileges. */\r\n this.StopL3Switch = function (in_param) {\r\n return _this.CallAsync(\"StopL3Switch\", in_param);\r\n };\r\n /** Add Virtual Interface to Virtual Layer 3 Switch. Use this to add to a specified Virtual Layer 3 Switch, a virtual interface that connects to a Virtual Hub operating on the same VPN Server. You can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. A virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. You must define the IP network space that the virtual interface belongs to and the IP address of the interface itself. Also, you must specify the name of the Virtual Hub that the interface will connect to. You can specify a Virtual Hub that currently doesn't exist for the Virtual Hub name. The virtual interface must have one IP address in the Virtual Hub. You also must specify the subnet mask of an IP network that the IP address belongs to. Routing via the Virtual Layer 3 Switches of IP spaces of multiple virtual Hubs operates based on the IP address is specified here. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.AddL3If = function (in_param) {\r\n return _this.CallAsync(\"AddL3If\", in_param);\r\n };\r\n /** Delete Virtual Interface of Virtual Layer 3 Switch. Use this to delete a virtual interface already defined in the specified Virtual Layer 3 Switch. You can get a list of the virtual interfaces currently defined, by using the EnumL3If API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.DelL3If = function (in_param) {\r\n return _this.CallAsync(\"DelL3If\", in_param);\r\n };\r\n /** Get List of Interfaces Registered on the Virtual Layer 3 Switch. Use this to get a list of virtual interfaces when virtual interfaces have been defined on a specified Virtual Layer 3 Switch. You can define multiple virtual interfaces and routing tables for a single Virtual Layer 3 Switch. A virtual interface is associated to a virtual Hub and operates as a single IP host on the Virtual Hub when that Virtual Hub is operating. When multiple virtual interfaces that respectively belong to a different IP network of a different Virtual Hub are defined, IP routing will be automatically performed between these interfaces. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.EnumL3If = function (in_param) {\r\n return _this.CallAsync(\"EnumL3If\", in_param);\r\n };\r\n /** Add Routing Table Entry for Virtual Layer 3 Switch. Here you can add a new routing table entry to the routing table of the specified Virtual Layer 3 Switch. If the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference the routing table and execute routing. You must specify the contents of the routing table entry to be added to the Virtual Layer 3 Switch. You must specify any IP address that belongs to the same IP network in the virtual interface of this Virtual Layer 3 Switch as the gateway address. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.AddL3Table = function (in_param) {\r\n return _this.CallAsync(\"AddL3Table\", in_param);\r\n };\r\n /** Delete Routing Table Entry of Virtual Layer 3 Switch. Use this to delete a routing table entry that is defined in the specified Virtual Layer 3 Switch. You can get a list of the already defined routing table entries by using the EnumL3Table API. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. To execute this API, the target Virtual Layer 3 Switch must be stopped. If it is not stopped, first use the StopL3Switch API to stop it and then execute this API. */\r\n this.DelL3Table = function (in_param) {\r\n return _this.CallAsync(\"DelL3Table\", in_param);\r\n };\r\n /** Get List of Routing Tables of Virtual Layer 3 Switch. Use this to get a list of routing tables when routing tables have been defined on a specified Virtual Layer 3 Switch. If the destination IP address of the IP packet does not belong to any IP network that belongs to a virtual interface, the IP routing engine of the Virtual Layer 3 Switch will reference this routing table and execute routing. To call this API, you must have VPN Server administrator privileges. Also, this API does not operate on VPN Bridge. */\r\n this.EnumL3Table = function (in_param) {\r\n return _this.CallAsync(\"EnumL3Table\", in_param);\r\n };\r\n /** Get List of Certificates Revocation List. Use this to get a Certificates Revocation List that is set on the currently managed Virtual Hub. By registering certificates in the Certificates Revocation List, the clients who provide these certificates will be unable to connect to this Virtual Hub using certificate authentication mode. Normally with this function, in cases where the security of a private key has been compromised or where a person holding a certificate has been stripped of their privileges, by registering that certificate as invalid on the Virtual Hub, it is possible to deny user authentication when that certificate is used by a client to connect to the Virtual Hub. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumCrl = function (in_param) {\r\n return _this.CallAsync(\"EnumCrl\", in_param);\r\n };\r\n /** Add a Revoked Certificate. Use this to add a new revoked certificate definition in the Certificate Revocation List that is set on the currently managed Virtual Hub. Specify the contents to be registered in the Certificate Revocation List by using the parameters of this API. When a user connects to a Virtual Hub in certificate authentication mode and that certificate matches 1 or more of the contents registered in the certificates revocation list, the user is denied connection. A certificate that matches all the conditions that are defined by the parameters specified by this API will be judged as invalid. The items that can be set are as follows: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number (hexadecimal), MD5 Digest Value (hexadecimal, 128 bit), and SHA-1 Digest Value (hexadecimal, 160 bit). For the specification of a digest value (hash value) a certificate is optionally specified depending on the circumstances. Normally when a MD5 or SHA-1 digest value is input, it is not necessary to input the other items. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.AddCrl = function (in_param) {\r\n return _this.CallAsync(\"AddCrl\", in_param);\r\n };\r\n /** Delete a Revoked Certificate. Use this to specify and delete a revoked certificate definition from the certificate revocation list that is set on the currently managed Virtual Hub. To get the list of currently registered revoked certificate definitions, use the EnumCrl API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DelCrl = function (in_param) {\r\n return _this.CallAsync(\"DelCrl\", in_param);\r\n };\r\n /** Get a Revoked Certificate. Use this to specify and get the contents of a revoked certificate definition from the Certificates Revocation List that is set on the currently managed Virtual Hub. To get the list of currently registered revoked certificate definitions, use the EnumCrl API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetCrl = function (in_param) {\r\n return _this.CallAsync(\"GetCrl\", in_param);\r\n };\r\n /** Change Existing CRL (Certificate Revocation List) Entry. Use this to alter an existing revoked certificate definition in the Certificate Revocation List that is set on the currently managed Virtual Hub. Specify the contents to be registered in the Certificate Revocation List by using the parameters of this API. When a user connects to a Virtual Hub in certificate authentication mode and that certificate matches 1 or more of the contents registered in the certificates revocation list, the user is denied connection. A certificate that matches all the conditions that are defined by the parameters specified by this API will be judged as invalid. The items that can be set are as follows: Name (CN), Organization (O), Organization Unit (OU), Country (C), State (ST), Locale (L), Serial Number (hexadecimal), MD5 Digest Value (hexadecimal, 128 bit), and SHA-1 Digest Value (hexadecimal, 160 bit). For the specification of a digest value (hash value) a certificate is optionally specified depending on the circumstances. Normally when a MD5 or SHA-1 digest value is input, it is not necessary to input the other items. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetCrl = function (in_param) {\r\n return _this.CallAsync(\"SetCrl\", in_param);\r\n };\r\n /** Add Rule to Source IP Address Limit List. Use this to add a new rule to the Source IP Address Limit List that is set on the currently managed Virtual Hub. The items set here will be used to decide whether to allow or deny connection from a VPN Client when this client attempts connection to the Virtual Hub. You can specify a client IP address, or IP address or mask to match the rule as the contents of the rule item. By specifying an IP address only, there will only be one specified computer that will match the rule, but by specifying an IP net mask address or subnet mask address, all the computers in the range of that subnet will match the rule. You can specify the priority for the rule. You can specify an integer of 1 or greater for the priority and the smaller the number, the higher the priority. To get a list of the currently registered Source IP Address Limit List, use the GetAcList API. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetAcList = function (in_param) {\r\n return _this.CallAsync(\"SetAcList\", in_param);\r\n };\r\n /** Get List of Rule Items of Source IP Address Limit List. Use this to get a list of Source IP Address Limit List rules that is set on the currently managed Virtual Hub. You can allow or deny VPN connections to this Virtual Hub according to the client computer's source IP address. You can define multiple rules and set a priority for each rule. The search proceeds from the rule with the highest order or priority and based on the action of the rule that the IP address first matches, the connection from the client is either allowed or denied. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetAcList = function (in_param) {\r\n return _this.CallAsync(\"GetAcList\", in_param);\r\n };\r\n /** Get List of Log Files. Use this to display a list of log files outputted by the VPN Server that have been saved on the VPN Server computer. By specifying a log file file name displayed here and calling it using the ReadLogFile API you can download the contents of the log file. If you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. When connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management. */\r\n this.EnumLogFile = function () {\r\n return _this.CallAsync(\"EnumLogFile\", new VpnRpcEnumLogFile());\r\n };\r\n /** Download a part of Log File. Use this to download the log file that is saved on the VPN Server computer. To download the log file first get the list of log files using the EnumLogFile API and then download the log file using the ReadLogFile API. If you are connected to the VPN Server in server admin mode, you can display or download the packet logs and security logs of all Virtual Hubs and the server log of the VPN Server. When connected in Virtual Hub Admin Mode, you are able to view or download only the packet log and security log of the Virtual Hub that is the target of management. */\r\n this.ReadLogFile = function (in_param) {\r\n return _this.CallAsync(\"ReadLogFile\", in_param);\r\n };\r\n /** Set syslog Send Function. Use this to set the usage of syslog send function and which syslog server to use. */\r\n this.SetSysLog = function (in_param) {\r\n return _this.CallAsync(\"SetSysLog\", in_param);\r\n };\r\n /** Get syslog Send Function. This allows you to get the current setting contents of the syslog send function. You can get the usage setting of the syslog function and the host name and port number of the syslog server to use. */\r\n this.GetSysLog = function (in_param) {\r\n return _this.CallAsync(\"GetSysLog\", in_param);\r\n };\r\n /** Set Today's Message of Virtual Hub. The message will be displayed on VPN Client UI when a user will establish a connection to the Virtual Hub. */\r\n this.SetHubMsg = function (in_param) {\r\n return _this.CallAsync(\"SetHubMsg\", in_param);\r\n };\r\n /** Get Today's Message of Virtual Hub. The message will be displayed on VPN Client UI when a user will establish a connection to the Virtual Hub. */\r\n this.GetHubMsg = function (in_param) {\r\n return _this.CallAsync(\"GetHubMsg\", in_param);\r\n };\r\n /** Raise a vital error on the VPN Server / Bridge to terminate the process forcefully. This API will raise a fatal error (memory access violation) on the VPN Server / Bridge running process in order to crash the process. As the result, VPN Server / Bridge will be terminated and restarted if it is running as a service mode. If the VPN Server is running as a user mode, the process will not automatically restarted. This API is for a situation when the VPN Server / Bridge is under a non-recoverable error or the process is in an infinite loop. This API will disconnect all VPN Sessions on the VPN Server / Bridge. All unsaved settings in the memory of VPN Server / Bridge will be lost. Before run this API, call the Flush API to try to save volatile data to the configuration file. To execute this API, you must have VPN Server / VPN Bridge administrator privileges. */\r\n this.Crash = function (in_param) {\r\n return _this.CallAsync(\"Crash\", in_param);\r\n };\r\n /** Get the message for administrators. */\r\n this.GetAdminMsg = function () {\r\n return _this.CallAsync(\"GetAdminMsg\", new VpnRpcMsg());\r\n };\r\n /** Save All Volatile Data of VPN Server / Bridge to the Configuration File. The number of configuration file bytes will be returned as the \"IntValue\" parameter. Normally, the VPN Server / VPN Bridge retains the volatile configuration data in memory. It is flushed to the disk as vpn_server.config or vpn_bridge.config periodically. The period is 300 seconds (5 minutes) by default. (The period can be altered by modifying the AutoSaveConfigSpan item in the configuration file.) The data will be saved on the timing of shutting down normally of the VPN Server / Bridge. Execute the Flush API to make the VPN Server / Bridge save the settings to the file immediately. The setting data will be stored on the disk drive of the server computer. Use the Flush API in a situation that you do not have an enough time to shut down the server process normally. To call this API, you must have VPN Server administrator privileges. To execute this API, you must have VPN Server / VPN Bridge administrator privileges. */\r\n this.Flush = function (in_param) {\r\n return _this.CallAsync(\"Flush\", in_param);\r\n };\r\n /** Enable or Disable IPsec VPN Server Function. Enable or Disable IPsec VPN Server Function on the VPN Server. If you enable this function, Virtual Hubs on the VPN Server will be able to accept Remote-Access VPN connections from L2TP-compatible PCs, Mac OS X and Smartphones, and also can accept EtherIP Site-to-Site VPN Connection. VPN Connections from Smartphones suchlike iPhone, iPad and Android, and also from native VPN Clients on Mac OS X and Windows can be accepted. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetIPsecServices = function (in_param) {\r\n return _this.CallAsync(\"SetIPsecServices\", in_param);\r\n };\r\n /** Get the Current IPsec VPN Server Settings. Get and view the current IPsec VPN Server settings on the VPN Server. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetIPsecServices = function () {\r\n return _this.CallAsync(\"GetIPsecServices\", new VpnIPsecServices());\r\n };\r\n /** Add New EtherIP / L2TPv3 over IPsec Client Setting to Accept EthreIP / L2TPv3 Client Devices. Add a new setting entry to enable the EtherIP / L2TPv3 over IPsec Server Function to accept client devices. In order to accept connections from routers by the EtherIP / L2TPv3 over IPsec Server Function, you have to define the relation table between an IPsec Phase 1 string which is presented by client devices of EtherIP / L2TPv3 over IPsec compatible router, and the designation of the destination Virtual Hub. After you add a definition entry by AddEtherIpId API, the defined connection setting to the Virtual Hub will be applied on the login-attepting session from an EtherIP / L2TPv3 over IPsec client device. The username and password in an entry must be registered on the Virtual Hub. An EtherIP / L2TPv3 client will be regarded as it connected the Virtual HUB with the identification of the above user information. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.AddEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"AddEtherIpId\", in_param);\r\n };\r\n /** Get the Current List of EtherIP / L2TPv3 Client Device Entry Definitions. This API gets and shows the list of entries to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"GetEtherIpId\", in_param);\r\n };\r\n /** Delete an EtherIP / L2TPv3 over IPsec Client Setting. This API deletes an entry to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.DeleteEtherIpId = function (in_param) {\r\n return _this.CallAsync(\"DeleteEtherIpId\", in_param);\r\n };\r\n /** Get the Current List of EtherIP / L2TPv3 Client Device Entry Definitions. This API gets and shows the list of entries to accept VPN clients by EtherIP / L2TPv3 over IPsec Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.EnumEtherIpId = function () {\r\n return _this.CallAsync(\"EnumEtherIpId\", new VpnRpcEnumEtherIpId());\r\n };\r\n /** Set Settings for OpenVPN Clone Server Function. The VPN Server has the clone functions of OpenVPN software products by OpenVPN Technologies, Inc. Any OpenVPN Clients can connect to this VPN Server. The manner to specify a username to connect to the Virtual Hub, and the selection rule of default Hub by using this clone server functions are same to the IPsec Server functions. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetOpenVpnSstpConfig = function (in_param) {\r\n return _this.CallAsync(\"SetOpenVpnSstpConfig\", in_param);\r\n };\r\n /** Get the Current Settings of OpenVPN Clone Server Function. Get and show the current settings of OpenVPN Clone Server Function. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetOpenVpnSstpConfig = function () {\r\n return _this.CallAsync(\"GetOpenVpnSstpConfig\", new VpnOpenVpnSstpConfig());\r\n };\r\n /** Show the Current Status of Dynamic DNS Function. Get and show the current status of the Dynamic DNS function. The Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name. Also, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address. Therefore, you need not any longer to keep static global IP addresses with expenses monthly costs. [Caution] To disable the Dynamic DNS Function, modify the configuration file of VPN Server. The \"declare root\" directive has the \"declare DDnsClient\" directive. In this directive, you can switch \"bool Disable\" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.GetDDnsClientStatus = function () {\r\n return _this.CallAsync(\"GetDDnsClientStatus\", new VpnDDnsClientStatus());\r\n };\r\n /** Set the Dynamic DNS Hostname. You must specify the new hostname on the StrValue_str field. You can use this API to change the hostname assigned by the Dynamic DNS function. The currently assigned hostname can be showen by the GetDDnsClientStatus API. The Dynamic DNS assigns a unique and permanent DNS hostname for this VPN Server. You can use that hostname to specify this VPN Server on the settings for VPN Client and VPN Bridge. You need not to register and keep a domain name. Also, if your ISP assignes you a dynamic (not-fixed) IP address, the corresponding IP address of your Dynamic DNS hostname will be automatically changed. It enables you to keep running the VPN Server by using only a dynamic IP address. Therefore, you need not any longer to keep static global IP addresses with expenses monthly costs. [Caution] To disable the Dynamic DNS Function, modify the configuration file of VPN Server. The \"declare root\" directive has the \"declare DDnsClient\" directive. In this directive, you can switch \"bool Disable\" from false to true, and reboot the VPN Server, then the Dynamic DNS Function will be disabled. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.ChangeDDnsClientHostname = function (in_param) {\r\n return _this.CallAsync(\"ChangeDDnsClientHostname\", in_param);\r\n };\r\n /** Generate New Self-Signed Certificate with Specified CN (Common Name) and Register on VPN Server. You can specify the new CN (common name) value on the StrValue_str field. You can use this API to replace the current certificate on the VPN Server to a new self-signed certificate which has the CN (Common Name) value in the fields. This API is convenient if you are planning to use Microsoft SSTP VPN Clone Server Function. Because of the value of CN (Common Name) on the SSL certificate of VPN Server must match to the hostname specified on the SSTP VPN client. This API will delete the existing SSL certificate of the VPN Server. It is recommended to backup the current SSL certificate and private key by using the GetServerCert API beforehand. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.RegenerateServerCert = function (in_param) {\r\n return _this.CallAsync(\"RegenerateServerCert\", in_param);\r\n };\r\n /** Generate a Sample Setting File for OpenVPN Client. Originally, the OpenVPN Client requires a user to write a very difficult configuration file manually. This API helps you to make a useful configuration sample. What you need to generate the configuration file for the OpenVPN Client is to run this API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.MakeOpenVpnConfigFile = function () {\r\n return _this.CallAsync(\"MakeOpenVpnConfigFile\", new VpnRpcReadLogFile());\r\n };\r\n /** Enable / Disable the VPN over ICMP / VPN over DNS Server Function. You can establish a VPN only with ICMP or DNS packets even if there is a firewall or routers which blocks TCP/IP communications. You have to enable the following functions beforehand. Warning: Use this function for emergency only. It is helpful when a firewall or router is misconfigured to blocks TCP/IP, but either ICMP or DNS is not blocked. It is not for long-term stable using. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.SetSpecialListener = function (in_param) {\r\n return _this.CallAsync(\"SetSpecialListener\", in_param);\r\n };\r\n /** Get Current Setting of the VPN over ICMP / VPN over DNS Function. Get and show the current VPN over ICMP / VPN over DNS Function status. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. */\r\n this.GetSpecialListener = function () {\r\n return _this.CallAsync(\"GetSpecialListener\", new VpnRpcSpecialListener());\r\n };\r\n /** Show the current status of VPN Azure function. Get and show the current status of the VPN Azure function. VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company. You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC. VPN Azure is a cloud VPN service operated by SoftEther Corporation. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions. The VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to \"vpnazure.net\". To change the hostname use the ChangeDDnsClientHostname API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.GetAzureStatus = function () {\r\n return _this.CallAsync(\"GetAzureStatus\", new VpnRpcAzureStatus());\r\n };\r\n /** Enable / Disable VPN Azure Function. Enable or disable the VPN Azure function. VPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company. You don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC. VPN Azure is a cloud VPN service operated by SoftEther Corporation. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions. The VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to \"vpnazure.net\". To change the hostname use the ChangeDDnsClientHostname API. To call this API, you must have VPN Server administrator privileges. This API cannot be invoked on VPN Bridge. You cannot execute this API for Virtual Hubs of VPN Servers operating as a cluster. */\r\n this.SetAzureStatus = function (in_param) {\r\n return _this.CallAsync(\"SetAzureStatus\", in_param);\r\n };\r\n /** Get the Proxy Settings for Connecting to the DDNS server. */\r\n this.GetDDnsInternetSetting = function () {\r\n return _this.CallAsync(\"GetDDnsInternetSetting\", new VpnInternetSetting());\r\n };\r\n /** Set the Proxy Settings for Connecting to the DDNS server. */\r\n this.SetDDnsInternetSetting = function (in_param) {\r\n return _this.CallAsync(\"SetDDnsInternetSetting\", in_param);\r\n };\r\n /** Set the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */\r\n this.SetVgsConfig = function (in_param) {\r\n return _this.CallAsync(\"SetVgsConfig\", in_param);\r\n };\r\n /** Get the VPN Gate Server Configuration. This API is valid for Win32 binary distribution of the Stable Edition of SoftEther VPN Server. */\r\n this.GetVgsConfig = function () {\r\n return _this.CallAsync(\"GetVgsConfig\", new VpnVgsConfig());\r\n };\r\n var headers = {};\r\n var send_credentials = false;\r\n nodejs_https_client_reject_untrusted_server_cert = is_null(nodejs_https_client_reject_untrusted_server_cert) ? false : nodejs_https_client_reject_untrusted_server_cert;\r\n if (is_null(vpnserver_hostname)) {\r\n this.rpc_url = \"/api/\";\r\n send_credentials = true;\r\n }\r\n else {\r\n if (is_null(vpnserver_port))\r\n vpnserver_port = 443;\r\n this.rpc_url = \"https://\" + vpnserver_hostname + \":\" + vpnserver_port + \"/api/\";\r\n headers[\"X-VPNADMIN-HUBNAME\"] = is_null(hubname) ? \"\" : hubname;\r\n headers[\"X-VPNADMIN-PASSWORD\"] = is_null(password) ? \"\" : password;\r\n }\r\n if (is_null(nodejs_https_client_reject_untrusted_server_cert))\r\n nodejs_https_client_reject_untrusted_server_cert = false;\r\n this.rpc_client = new JsonRpcClient(this.rpc_url, headers, send_credentials, nodejs_https_client_reject_untrusted_server_cert);\r\n }\r\n /** Determine if this JavaScript environment is on the Node.js or not. */\r\n VpnServerRpc.IsNodeJS = function () {\r\n return is_node_js;\r\n };\r\n /** Set the debug mode flag */\r\n VpnServerRpc.SetDebugMode = function (flag) {\r\n debug_mode = flag;\r\n };\r\n // -- Utility functions --\r\n /** Call a RPC procedure */\r\n VpnServerRpc.prototype.CallAsync = function (method_name, request) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var response;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0: return [4 /*yield*/, this.rpc_client.CallAsync(method_name, request)];\r\n case 1:\r\n response = _a.sent();\r\n return [2 /*return*/, response];\r\n }\r\n });\r\n });\r\n };\r\n return VpnServerRpc;\r\n}());\r\nexports.VpnServerRpc = VpnServerRpc;\r\n// --- Types ---\r\n/** IP Protocol Numbers */\r\nvar VpnIpProtocolNumber;\r\n(function (VpnIpProtocolNumber) {\r\n /** ICMP for IPv4 */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"ICMPv4\"] = 1] = \"ICMPv4\";\r\n /** TCP */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"TCP\"] = 6] = \"TCP\";\r\n /** UDP */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"UDP\"] = 17] = \"UDP\";\r\n /** ICMP for IPv6 */\r\n VpnIpProtocolNumber[VpnIpProtocolNumber[\"ICMPv6\"] = 58] = \"ICMPv6\";\r\n})(VpnIpProtocolNumber = exports.VpnIpProtocolNumber || (exports.VpnIpProtocolNumber = {}));\r\n/** The body of the Access list */\r\nvar VpnAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnAccess' class: The body of the Access list */\r\n function VpnAccess(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Specify a description (note) for this rule */\r\n this.Note_utf = \"\";\r\n /** Enabled flag (true: enabled, false: disabled) */\r\n this.Active_bool = false;\r\n /** Specify an integer of 1 or higher to indicate the priority of the rule. Higher priority is given to rules with the lower priority values. */\r\n this.Priority_u32 = 0;\r\n /** The flag if the rule is DISCARD operation or PASS operation. When a packet matches this rule condition, this operation is decided. When the operation of the rule is PASS, the packet is allowed to pass, otherwise the packet will be discarded. */\r\n this.Discard_bool = false;\r\n /** The flag if the rule is for IPv6. Specify false for IPv4, or specify true for IPv6. */\r\n this.IsIPv6_bool = false;\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a source IPv4 address as a rule condition. You must also specify the SrcSubnetMask_ip field. */\r\n this.SrcIpAddress_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a source IPv4 subnet mask as a rule condition. \"0.0.0.0\" means all hosts. \"255.255.255.255\" means one single host. */\r\n this.SrcSubnetMask_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a destination IPv4 address as a rule condition. You must also specify the DestSubnetMask_ip field. */\r\n this.DestIpAddress_ip = \"\";\r\n /** Valid only if the rule is IPv4 mode (IsIPv6_bool == false). Specify a destination IPv4 subnet mask as a rule condition. \"0.0.0.0\" means all hosts. \"255.255.255.255\" means one single host. */\r\n this.DestSubnetMask_ip = \"\";\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a source IPv6 address as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 address in binary form. You must also specify the SrcSubnetMask6_bin field. */\r\n this.SrcIpAddress6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a source IPv6 subnet mask as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 subnet mask in binary form. */\r\n this.SrcSubnetMask6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a destination IPv6 address as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 address in binary form. You must also specify the DestSubnetMask6_bin field. */\r\n this.DestIpAddress6_bin = new Uint8Array([]);\r\n /** Valid only if the rule is IPv6 mode (IsIPv6_bool == true). Specify a destination IPv6 subnet mask as a rule condition. The field must be a byte array of 16 bytes (128 bits) to contain the IPv6 subnet mask in binary form. */\r\n this.DestSubnetMask6_bin = new Uint8Array([]);\r\n /** The IP protocol number */\r\n this.Protocol_u32 = 0;\r\n /** The Start Value of the Source Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.SrcPortStart_u32 = 0;\r\n /** The End Value of the Source Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the source port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.SrcPortEnd_u32 = 0;\r\n /** The Start Value of the Destination Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.DestPortStart_u32 = 0;\r\n /** The End Value of the Destination Port Number Range. If the specified protocol is TCP/IP or UDP/IP, specify the destination port number as the rule condition. Protocols other than this will be ignored. When this parameter is not specified, the rules will apply to all port numbers. */\r\n this.DestPortEnd_u32 = 0;\r\n /** Source user name. You can apply this rule to only the packets sent by a user session of a user name that has been specified as a rule condition. In this case, specify the user name. */\r\n this.SrcUsername_str = \"\";\r\n /** Destination user name. You can apply this rule to only the packets received by a user session of a user name that has been specified as a rule condition. In this case, specify the user name. */\r\n this.DestUsername_str = \"\";\r\n /** Specify true if you want to check the source MAC address. */\r\n this.CheckSrcMac_bool = false;\r\n /** Source MAC address (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.SrcMacAddress_bin = new Uint8Array([]);\r\n /** Source MAC address mask (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.SrcMacMask_bin = new Uint8Array([]);\r\n /** Specify true if you want to check the destination MAC address. */\r\n this.CheckDstMac_bool = false;\r\n /** Destination MAC address (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.DstMacAddress_bin = new Uint8Array([]);\r\n /** Destination MAC address mask (6 bytes), valid only if CheckSrcMac_bool == true. */\r\n this.DstMacMask_bin = new Uint8Array([]);\r\n /** Specify true if you want to check the state of the TCP connection. */\r\n this.CheckTcpState_bool = false;\r\n /** Valid only if CheckTcpState_bool == true. Set this field true to match only TCP-established packets. Set this field false to match only TCP-non established packets. */\r\n this.Established_bool = false;\r\n /** Set this value to generate delays when packets is passing. Specify the delay period in milliseconds. Specify 0 means no delays to generate. The delays must be 10000 milliseconds at most. */\r\n this.Delay_u32 = 0;\r\n /** Set this value to generate jitters when packets is passing. Specify the ratio of fluctuation of jitters within 0% to 100% range. Specify 0 means no jitters to generate. */\r\n this.Jitter_u32 = 0;\r\n /** Set this value to generate packet losses when packets is passing. Specify the ratio of packet losses within 0% to 100% range. Specify 0 means no packet losses to generate. */\r\n this.Loss_u32 = 0;\r\n /** The specified URL will be mandatory replied to the client as a response for TCP connecting request packets which matches the conditions of this access list entry via this Virtual Hub. To use this setting, you can enforce the web browser of the VPN Client computer to show the specified web site when that web browser tries to access the specific IP address. */\r\n this.RedirectUrl_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAccess;\r\n}());\r\nexports.VpnAccess = VpnAccess;\r\n/** Add an item to Access List */\r\nvar VpnRpcAddAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAddAccess' class: Add an item to Access List */\r\n function VpnRpcAddAccess(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Access list (Must be a single item) */\r\n this.AccessListSingle = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAddAccess;\r\n}());\r\nexports.VpnRpcAddAccess = VpnRpcAddAccess;\r\n/** Add CA to HUB */\r\nvar VpnRpcHubAddCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubAddCA' class: Add CA to HUB */\r\n function VpnRpcHubAddCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The body of the X.509 certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubAddCA;\r\n}());\r\nexports.VpnRpcHubAddCA = VpnRpcHubAddCA;\r\n/** CRL entry */\r\nvar VpnRpcCrl = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCrl' class: CRL entry */\r\n function VpnRpcCrl(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** CN, optional */\r\n this.CommonName_utf = \"\";\r\n /** O, optional */\r\n this.Organization_utf = \"\";\r\n /** OU, optional */\r\n this.Unit_utf = \"\";\r\n /** C, optional */\r\n this.Country_utf = \"\";\r\n /** ST, optional */\r\n this.State_utf = \"\";\r\n /** L, optional */\r\n this.Local_utf = \"\";\r\n /** Serial, optional */\r\n this.Serial_bin = new Uint8Array([]);\r\n /** MD5 Digest, optional */\r\n this.DigestMD5_bin = new Uint8Array([]);\r\n /** SHA1 Digest, optional */\r\n this.DigestSHA1_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCrl;\r\n}());\r\nexports.VpnRpcCrl = VpnRpcCrl;\r\n/** EtherIP key list entry */\r\nvar VpnEtherIpId = /** @class */ (function () {\r\n /** Constructor for the 'VpnEtherIpId' class: EtherIP key list entry */\r\n function VpnEtherIpId(init) {\r\n /** Specify an ISAKMP Phase 1 ID. The ID must be exactly same as a ID in the configuration of the EtherIP / L2TPv3 Client. You can specify IP address as well as characters as ID, if the EtherIP Client uses IP address as Phase 1 ID. If you specify '*' (asterisk), it will be a wildcard to match any clients which doesn't match other explicit rules. */\r\n this.Id_str = \"\";\r\n /** Specify the name of the Virtual Hub to connect. */\r\n this.HubName_str = \"\";\r\n /** Specify the username to login to the destination Virtual Hub. */\r\n this.UserName_str = \"\";\r\n /** Specify the password to login to the destination Virtual Hub. */\r\n this.Password_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnEtherIpId;\r\n}());\r\nexports.VpnEtherIpId = VpnEtherIpId;\r\n/** Layer-3 virtual interface */\r\nvar VpnRpcL3If = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3If' class: Layer-3 virtual interface */\r\n function VpnRpcL3If(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Virtual HUB name */\r\n this.HubName_str = \"\";\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.SubnetMask_ip = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3If;\r\n}());\r\nexports.VpnRpcL3If = VpnRpcL3If;\r\n/** Layer-3 switch */\r\nvar VpnRpcL3Sw = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3Sw' class: Layer-3 switch */\r\n function VpnRpcL3Sw(init) {\r\n /** Layer-3 Switch name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3Sw;\r\n}());\r\nexports.VpnRpcL3Sw = VpnRpcL3Sw;\r\n/** Routing table */\r\nvar VpnRpcL3Table = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcL3Table' class: Routing table */\r\n function VpnRpcL3Table(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Network address */\r\n this.NetworkAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.SubnetMask_ip = \"\";\r\n /** Gateway address */\r\n this.GatewayAddress_ip = \"\";\r\n /** Metric */\r\n this.Metric_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcL3Table;\r\n}());\r\nexports.VpnRpcL3Table = VpnRpcL3Table;\r\n/** Generic parameter to contain u32, u64, ascii_string and unicode string */\r\nvar VpnRpcTest = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcTest' class: Generic parameter to contain u32, u64, ascii_string and unicode string */\r\n function VpnRpcTest(init) {\r\n /** A 32-bit integer field */\r\n this.IntValue_u32 = 0;\r\n /** A 64-bit integer field */\r\n this.Int64Value_u64 = 0;\r\n /** An Ascii string field */\r\n this.StrValue_str = \"\";\r\n /** An UTF-8 string field */\r\n this.UniStrValue_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcTest;\r\n}());\r\nexports.VpnRpcTest = VpnRpcTest;\r\n/** Local Bridge list item */\r\nvar VpnRpcLocalBridge = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLocalBridge' class: Local Bridge list item */\r\n function VpnRpcLocalBridge(init) {\r\n /** Physical Ethernet device name */\r\n this.DeviceName_str = \"\";\r\n /** The Virtual Hub name */\r\n this.HubNameLB_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** Running flag */\r\n this.Active_bool = false;\r\n /** Specify true if you are using a tap device rather than a network adapter for the bridge destination (only supported for Linux versions). */\r\n this.TapMode_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLocalBridge;\r\n}());\r\nexports.VpnRpcLocalBridge = VpnRpcLocalBridge;\r\n/** Create, configure, and get the group */\r\nvar VpnRpcSetGroup = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetGroup' class: Create, configure, and get the group */\r\n function VpnRpcSetGroup(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The group name */\r\n this.Name_str = \"\";\r\n /** Optional real name (full name) of the group, allow using any Unicode characters */\r\n this.Realname_utf = \"\";\r\n /** Optional, specify a description of the group */\r\n this.Note_utf = \"\";\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** The flag whether to use security policy */\r\n this.UsePolicy_bool = false;\r\n /** Security policy: Allow Access. The users, which this policy value is true, have permission to make VPN connection to VPN Server. */\r\n this[\"policy:Access_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Deny Bridge Operation. Bridge-mode connections are denied for user sessions that have this policy setting. Even in cases when the Ethernet Bridge is configured in the client side, communication will not be possible. */\r\n this[\"policy:NoBridge_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv4). IPv4 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRouting_bool\"] = false;\r\n /** Security policy: Deny MAC Addresses Duplication. The use of duplicating MAC addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckMac_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv4). The use of duplicating IPv4 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIP_bool\"] = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Allow Monitoring Mode. Users with this policy setting will be granted to connect to the Virtual Hub in Monitoring Mode. Sessions in Monitoring Mode are able to monitor (tap) all packets flowing through the Virtual Hub. */\r\n this[\"policy:MonitorPort_bool\"] = false;\r\n /** Security policy: Maximum Number of TCP Connections. For sessions with this policy setting, this sets the maximum number of physical TCP connections consists in a physical VPN session. */\r\n this[\"policy:MaxConnection_u32\"] = 0;\r\n /** Security policy: Time-out Period. For sessions with this policy setting, this sets, in seconds, the time-out period to wait before disconnecting a session when communication trouble occurs between the VPN Client / VPN Server. */\r\n this[\"policy:TimeOut_u32\"] = 0;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Deny Changing Password. The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar. */\r\n this[\"policy:FixPassword_bool\"] = false;\r\n /** Security policy: Maximum Number of Multiple Logins. Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. */\r\n this[\"policy:MultiLogins_u32\"] = 0;\r\n /** Security policy: Deny VoIP / QoS Function. Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. */\r\n this[\"policy:NoQoS_bool\"] = false;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter RA Packets (IPv6). All ICMPv6 packets which the message-type is 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, a malicious users will be unable to spread illegal IPv6 prefix or default gateway advertisements on the network. */\r\n this[\"policy:RAFilter_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv6). IPv6 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRoutingV6_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv6). The use of duplicating IPv6 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIPv6_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Disallow Password Save in VPN Client. For users with this policy setting, when the user is using *standard* password authentication, the user will be unable to save the password in VPN Client. The user will be required to input passwords for every time to connect a VPN. This will improve the security. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:NoSavePassword_bool\"] = false;\r\n /** Security policy: VPN Client Automatic Disconnect. For users with this policy setting, a user's VPN session will be disconnected automatically after the specific period will elapse. In this case no automatic re-connection will be performed. This can prevent a lot of inactive VPN Sessions. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:AutoDisconnect_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA (physical IPv6). In all VPN Sessions defines this policy (only when the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6), any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRAWhenIPv6_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetGroup;\r\n}());\r\nexports.VpnRpcSetGroup = VpnRpcSetGroup;\r\n/** Hub types */\r\nvar VpnRpcHubType;\r\n(function (VpnRpcHubType) {\r\n /** Stand-alone HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"Standalone\"] = 0] = \"Standalone\";\r\n /** Static HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"FarmStatic\"] = 1] = \"FarmStatic\";\r\n /** Dynamic HUB */\r\n VpnRpcHubType[VpnRpcHubType[\"FarmDynamic\"] = 2] = \"FarmDynamic\";\r\n})(VpnRpcHubType = exports.VpnRpcHubType || (exports.VpnRpcHubType = {}));\r\n/** Create a HUB */\r\nvar VpnRpcCreateHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCreateHub' class: Create a HUB */\r\n function VpnRpcCreateHub(init) {\r\n /** Specify the name of the Virtual Hub to create / update. */\r\n this.HubName_str = \"\";\r\n /** Specify an administrator password when the administrator password is going to be set for the Virtual Hub. On the update, leave it to empty string if you don't want to change the password. */\r\n this.AdminPasswordPlainText_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** Maximum number of VPN sessions */\r\n this.MaxSession_u32 = 0;\r\n /** No Enum flag. By enabling this option, the VPN Client user will be unable to enumerate this Virtual Hub even if they send a Virtual Hub enumeration request to the VPN Server. */\r\n this.NoEnum_bool = false;\r\n /** Type of the Virtual Hub (Valid only for Clustered VPN Servers) */\r\n this.HubType_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCreateHub;\r\n}());\r\nexports.VpnRpcCreateHub = VpnRpcCreateHub;\r\nvar VpnRpcClientAuthType;\r\n(function (VpnRpcClientAuthType) {\r\n /** Anonymous authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"Anonymous\"] = 0] = \"Anonymous\";\r\n /** SHA-0 hashed password authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"SHA0_Hashed_Password\"] = 1] = \"SHA0_Hashed_Password\";\r\n /** Plain password authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"PlainPassword\"] = 2] = \"PlainPassword\";\r\n /** Certificate authentication */\r\n VpnRpcClientAuthType[VpnRpcClientAuthType[\"Cert\"] = 3] = \"Cert\";\r\n})(VpnRpcClientAuthType = exports.VpnRpcClientAuthType || (exports.VpnRpcClientAuthType = {}));\r\n/** Create and set of link */\r\nvar VpnRpcCreateLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcCreateLink' class: Create and set of link */\r\n function VpnRpcCreateLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_Ex_str = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** The flag to enable validation for the server certificate */\r\n this.CheckServerCert_bool = false;\r\n /** The body of server X.509 certificate to compare. Valid only if the CheckServerCert_bool flag is true. */\r\n this.ServerCert_bin = new Uint8Array([]);\r\n /** Client Option Parameters: Specify the name of the Cascade Connection */\r\n this.AccountName_utf = \"\";\r\n /** Client Option Parameters: Specify the hostname of the destination VPN Server. You can also specify by IP address. */\r\n this.Hostname_str = \"\";\r\n /** Client Option Parameters: Specify the port number of the destination VPN Server. */\r\n this.Port_u32 = 0;\r\n /** Client Option Parameters: The type of the proxy server */\r\n this.ProxyType_u32 = 0;\r\n /** Client Option Parameters: The hostname or IP address of the proxy server name */\r\n this.ProxyName_str = \"\";\r\n /** Client Option Parameters: The port number of the proxy server */\r\n this.ProxyPort_u32 = 0;\r\n /** Client Option Parameters: The username to connect to the proxy server */\r\n this.ProxyUsername_str = \"\";\r\n /** Client Option Parameters: The password to connect to the proxy server */\r\n this.ProxyPassword_str = \"\";\r\n /** Client Option Parameters: The Virtual Hub on the destination VPN Server */\r\n this.HubName_str = \"\";\r\n /** Client Option Parameters: Number of TCP Connections to Use in VPN Communication */\r\n this.MaxConnection_u32 = 0;\r\n /** Client Option Parameters: The flag to enable the encryption on the communication */\r\n this.UseEncrypt_bool = false;\r\n /** Client Option Parameters: Enable / Disable Data Compression when Communicating by Cascade Connection */\r\n this.UseCompress_bool = false;\r\n /** Client Option Parameters: Specify true when enabling half duplex mode. When using two or more TCP connections for VPN communication, it is possible to use Half Duplex Mode. By enabling half duplex mode it is possible to automatically fix data transmission direction as half and half for each TCP connection. In the case where a VPN using 8 TCP connections is established, for example, when half-duplex is enabled, communication can be fixes so that 4 TCP connections are dedicated to the upload direction and the other 4 connections are dedicated to the download direction. */\r\n this.HalfConnection_bool = false;\r\n /** Client Option Parameters: Connection attempt interval when additional connection will be established */\r\n this.AdditionalConnectionInterval_u32 = 0;\r\n /** Client Option Parameters: Connection Life of Each TCP Connection (0 for no keep-alive) */\r\n this.ConnectionDisconnectSpan_u32 = 0;\r\n /** Client Option Parameters: Disable QoS Control Function if the value is true */\r\n this.DisableQoS_bool = false;\r\n /** Client Option Parameters: Do not use TLS 1.x of the value is true */\r\n this.NoTls1_bool = false;\r\n /** Client Option Parameters: Do not use UDP acceleration mode if the value is true */\r\n this.NoUdpAcceleration_bool = false;\r\n /** Authentication type */\r\n this.AuthType_u32 = 0;\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** SHA-0 Hashed password. Valid only if ClientAuth_AuthType_u32 == SHA0_Hashed_Password (1). The SHA-0 hashed password must be caluclated by the SHA0(UpperCase(username_ascii_string) + password_ascii_string). */\r\n this.HashedPassword_bin = new Uint8Array([]);\r\n /** Plaintext Password. Valid only if ClientAuth_AuthType_u32 == PlainPassword (2). */\r\n this.PlainPassword_str = \"\";\r\n /** Client certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). */\r\n this.ClientX_bin = new Uint8Array([]);\r\n /** Client private key of the certificate. Valid only if ClientAuth_AuthType_u32 == Cert (3). */\r\n this.ClientK_bin = new Uint8Array([]);\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Prohibit the duplicate MAC address */\r\n this.SecPol_CheckMac_bool = false;\r\n /** Security policy: Prohibit a duplicate IP address (IPv4) */\r\n this.SecPol_CheckIP_bool = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter the router advertisement packet (IPv6) */\r\n this.SecPol_RAFilter_bool = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Prohibit the duplicate IP address (IPv6) */\r\n this.SecPol_CheckIPv6_bool = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcCreateLink;\r\n}());\r\nexports.VpnRpcCreateLink = VpnRpcCreateLink;\r\n/** Listener */\r\nvar VpnRpcListener = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListener' class: Listener */\r\n function VpnRpcListener(init) {\r\n /** Port number (Range: 1 - 65535) */\r\n this.Port_u32 = 0;\r\n /** Active state */\r\n this.Enable_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListener;\r\n}());\r\nexports.VpnRpcListener = VpnRpcListener;\r\n/** User authentication type (server side) */\r\nvar VpnRpcUserAuthType;\r\n(function (VpnRpcUserAuthType) {\r\n /** Anonymous authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Anonymous\"] = 0] = \"Anonymous\";\r\n /** Password authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Password\"] = 1] = \"Password\";\r\n /** User certificate authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"UserCert\"] = 2] = \"UserCert\";\r\n /** Root certificate which is issued by trusted Certificate Authority */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"RootCert\"] = 3] = \"RootCert\";\r\n /** Radius authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"Radius\"] = 4] = \"Radius\";\r\n /** Windows NT authentication */\r\n VpnRpcUserAuthType[VpnRpcUserAuthType[\"NTDomain\"] = 5] = \"NTDomain\";\r\n})(VpnRpcUserAuthType = exports.VpnRpcUserAuthType || (exports.VpnRpcUserAuthType = {}));\r\n/** Create, configure, and get the user */\r\nvar VpnRpcSetUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetUser' class: Create, configure, and get the user */\r\n function VpnRpcSetUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Specify the user name of the user */\r\n this.Name_str = \"\";\r\n /** Assigned group name for the user */\r\n this.GroupName_str = \"\";\r\n /** Optional real name (full name) of the user, allow using any Unicode characters */\r\n this.Realname_utf = \"\";\r\n /** Optional User Description */\r\n this.Note_utf = \"\";\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last modified date and time */\r\n this.UpdatedTime_dt = new Date();\r\n /** Expiration date and time */\r\n this.ExpireTime_dt = new Date();\r\n /** Authentication method of the user */\r\n this.AuthType_u32 = 0;\r\n /** User password, valid only if AuthType_u32 == Password(1). Valid only to create or set operations. */\r\n this.Auth_Password_str = \"\";\r\n /** User certificate, valid only if AuthType_u32 == UserCert(2). */\r\n this.UserX_bin = new Uint8Array([]);\r\n /** Certificate Serial Number, optional, valid only if AuthType_u32 == RootCert(3). */\r\n this.Serial_bin = new Uint8Array([]);\r\n /** Certificate Common Name, optional, valid only if AuthType_u32 == RootCert(3). */\r\n this.CommonName_utf = \"\";\r\n /** Username in RADIUS server, optional, valid only if AuthType_u32 == Radius(4). */\r\n this.RadiusUsername_utf = \"\";\r\n /** Username in NT Domain server, optional, valid only if AuthType_u32 == NT(5). */\r\n this.NtUsername_utf = \"\";\r\n /** Number of total logins of the user */\r\n this.NumLogin_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** The flag whether to use security policy */\r\n this.UsePolicy_bool = false;\r\n /** Security policy: Allow Access. The users, which this policy value is true, have permission to make VPN connection to VPN Server. */\r\n this[\"policy:Access_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv4). All IPv4 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPFilter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv4). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv4 addresses to DHCP clients. */\r\n this[\"policy:DHCPNoServer_bool\"] = false;\r\n /** Security policy: Enforce DHCP Allocated IP Addresses (IPv4). Computers in sessions that have this policy setting will only be able to use IPv4 addresses allocated by a DHCP server on the virtual network side. */\r\n this[\"policy:DHCPForce_bool\"] = false;\r\n /** Security policy: Deny Bridge Operation. Bridge-mode connections are denied for user sessions that have this policy setting. Even in cases when the Ethernet Bridge is configured in the client side, communication will not be possible. */\r\n this[\"policy:NoBridge_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv4). IPv4 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRouting_bool\"] = false;\r\n /** Security policy: Deny MAC Addresses Duplication. The use of duplicating MAC addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckMac_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv4). The use of duplicating IPv4 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIP_bool\"] = false;\r\n /** Security policy: Deny Non-ARP / Non-DHCP / Non-ICMPv6 broadcasts. The sending or receiving of broadcast packets that are not ARP protocol, DHCP protocol, nor ICMPv6 on the virtual network will not be allowed for sessions with this policy setting. */\r\n this[\"policy:ArpDhcpOnly_bool\"] = false;\r\n /** Security policy: Privacy Filter Mode. All direct communication between sessions with the privacy filter mode policy setting will be filtered. */\r\n this[\"policy:PrivacyFilter_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv4). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv4. */\r\n this[\"policy:NoServer_bool\"] = false;\r\n /** Security policy: Unlimited Number of Broadcasts. If a computer of a session with this policy setting sends broadcast packets of a number unusually larger than what would be considered normal on the virtual network, there will be no automatic limiting. */\r\n this[\"policy:NoBroadcastLimiter_bool\"] = false;\r\n /** Security policy: Allow Monitoring Mode. Users with this policy setting will be granted to connect to the Virtual Hub in Monitoring Mode. Sessions in Monitoring Mode are able to monitor (tap) all packets flowing through the Virtual Hub. */\r\n this[\"policy:MonitorPort_bool\"] = false;\r\n /** Security policy: Maximum Number of TCP Connections. For sessions with this policy setting, this sets the maximum number of physical TCP connections consists in a physical VPN session. */\r\n this[\"policy:MaxConnection_u32\"] = 0;\r\n /** Security policy: Time-out Period. For sessions with this policy setting, this sets, in seconds, the time-out period to wait before disconnecting a session when communication trouble occurs between the VPN Client / VPN Server. */\r\n this[\"policy:TimeOut_u32\"] = 0;\r\n /** Security policy: Maximum Number of MAC Addresses. For sessions with this policy setting, this limits the number of MAC addresses per session. */\r\n this[\"policy:MaxMac_u32\"] = 0;\r\n /** Security policy: Maximum Number of IP Addresses (IPv4). For sessions with this policy setting, this specifies the number of IPv4 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIP_u32\"] = 0;\r\n /** Security policy: Upload Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the inwards direction from outside to inside the Virtual Hub. */\r\n this[\"policy:MaxUpload_u32\"] = 0;\r\n /** Security policy: Download Bandwidth. For sessions with this policy setting, this limits the traffic bandwidth that is in the outwards direction from inside the Virtual Hub to outside the Virtual Hub. */\r\n this[\"policy:MaxDownload_u32\"] = 0;\r\n /** Security policy: Deny Changing Password. The users which use password authentication with this policy setting are not allowed to change their own password from the VPN Client Manager or similar. */\r\n this[\"policy:FixPassword_bool\"] = false;\r\n /** Security policy: Maximum Number of Multiple Logins. Users with this policy setting are unable to have more than this number of concurrent logins. Bridge Mode sessions are not subjects to this policy. */\r\n this[\"policy:MultiLogins_u32\"] = 0;\r\n /** Security policy: Deny VoIP / QoS Function. Users with this security policy are unable to use VoIP / QoS functions in VPN connection sessions. */\r\n this[\"policy:NoQoS_bool\"] = false;\r\n /** Security policy: Filter RS / RA Packets (IPv6). All ICMPv6 packets which the message-type is 133 (Router Solicitation) or 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, an IPv6 client will be unable to use IPv6 address prefix auto detection and IPv6 default gateway auto detection. */\r\n this[\"policy:RSandRAFilter_bool\"] = false;\r\n /** Security policy: Filter RA Packets (IPv6). All ICMPv6 packets which the message-type is 134 (Router Advertisement) in sessions defined this policy will be filtered. As a result, a malicious users will be unable to spread illegal IPv6 prefix or default gateway advertisements on the network. */\r\n this[\"policy:RAFilter_bool\"] = false;\r\n /** Security policy: Filter DHCP Packets (IPv6). All IPv6 DHCP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:DHCPv6Filter_bool\"] = false;\r\n /** Security policy: Disallow DHCP Server Operation (IPv6). Computers connected to sessions that have this policy setting will not be allowed to become a DHCP server and distribute IPv6 addresses to DHCP clients. */\r\n this[\"policy:DHCPv6NoServer_bool\"] = false;\r\n /** Security policy: Deny Routing Operation (IPv6). IPv6 routing will be denied for sessions that have this policy setting. Even in the case where the IP router is operating on the user client side, communication will not be possible. */\r\n this[\"policy:NoRoutingV6_bool\"] = false;\r\n /** Security policy: Deny IP Address Duplication (IPv6). The use of duplicating IPv6 addresses that are in use by computers of different sessions cannot be used by sessions with this policy setting. */\r\n this[\"policy:CheckIPv6_bool\"] = false;\r\n /** Security policy: Deny Operation as TCP/IP Server (IPv6). Computers of sessions with this policy setting can't listen and accept TCP/IP connections in IPv6. */\r\n this[\"policy:NoServerV6_bool\"] = false;\r\n /** Security policy: Maximum Number of IP Addresses (IPv6). For sessions with this policy setting, this specifies the number of IPv6 addresses that can be registered for a single session. */\r\n this[\"policy:MaxIPv6_u32\"] = 0;\r\n /** Security policy: Disallow Password Save in VPN Client. For users with this policy setting, when the user is using *standard* password authentication, the user will be unable to save the password in VPN Client. The user will be required to input passwords for every time to connect a VPN. This will improve the security. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:NoSavePassword_bool\"] = false;\r\n /** Security policy: VPN Client Automatic Disconnect. For users with this policy setting, a user's VPN session will be disconnected automatically after the specific period will elapse. In this case no automatic re-connection will be performed. This can prevent a lot of inactive VPN Sessions. If this policy is enabled, VPN Client Version 2.0 will be denied to access. */\r\n this[\"policy:AutoDisconnect_u32\"] = 0;\r\n /** Security policy: Filter All IPv4 Packets. All IPv4 and ARP packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv4_bool\"] = false;\r\n /** Security policy: Filter All IPv6 Packets. All IPv6 packets in sessions defined this policy will be filtered. */\r\n this[\"policy:FilterIPv6_bool\"] = false;\r\n /** Security policy: Filter All Non-IP Packets. All non-IP packets in sessions defined this policy will be filtered. \"Non-IP packet\" mean a packet which is not IPv4, ARP nor IPv6. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. */\r\n this[\"policy:FilterNonIP_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA. In all VPN Sessions defines this policy, any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRA_bool\"] = false;\r\n /** Security policy: No Default-Router on IPv6 RA (physical IPv6). In all VPN Sessions defines this policy (only when the physical communication protocol between VPN Client / VPN Bridge and VPN Server is IPv6), any IPv6 RA (Router Advertisement) packet with non-zero value in the router-lifetime will set to zero-value. This is effective to avoid the horrible behavior from the IPv6 routing confusion which is caused by the VPN client's attempts to use the remote-side IPv6 router as its local IPv6 router. */\r\n this[\"policy:NoIPv6DefaultRouterInRAWhenIPv6_bool\"] = false;\r\n /** Security policy: VLAN ID (IEEE802.1Q). You can specify the VLAN ID on the security policy. All VPN Sessions defines this policy, all Ethernet packets toward the Virtual Hub from the user will be inserted a VLAN tag (IEEE 802.1Q) with the VLAN ID. The user can also receive only packets with a VLAN tag which has the same VLAN ID. (Receiving process removes the VLAN tag automatically.) Any Ethernet packets with any other VLAN IDs or non-VLAN packets will not be received. All VPN Sessions without this policy definition can send / receive any kinds of Ethernet packets regardless of VLAN tags, and VLAN tags are not inserted or removed automatically. Any tagged-VLAN packets via the Virtual Hub will be regarded as non-IP packets. Therefore, tagged-VLAN packets are not subjects for IPv4 / IPv6 security policies, access lists nor other IPv4 / IPv6 specific deep processing. */\r\n this[\"policy:VLanId_u32\"] = 0;\r\n /** Security policy: Whether version 3.0 (must be true) */\r\n this[\"policy:Ver3_bool\"] = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetUser;\r\n}());\r\nexports.VpnRpcSetUser = VpnRpcSetUser;\r\n/** Delete the access list */\r\nvar VpnRpcDeleteAccess = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteAccess' class: Delete the access list */\r\n function VpnRpcDeleteAccess(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** ID */\r\n this.Id_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteAccess;\r\n}());\r\nexports.VpnRpcDeleteAccess = VpnRpcDeleteAccess;\r\n/** Delete the CA of HUB */\r\nvar VpnRpcHubDeleteCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubDeleteCA' class: Delete the CA of HUB */\r\n function VpnRpcHubDeleteCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Certificate key id to be deleted */\r\n this.Key_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubDeleteCA;\r\n}());\r\nexports.VpnRpcHubDeleteCA = VpnRpcHubDeleteCA;\r\n/** Deleting a user or group */\r\nvar VpnRpcDeleteUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteUser' class: Deleting a user or group */\r\n function VpnRpcDeleteUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** User or group name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteUser;\r\n}());\r\nexports.VpnRpcDeleteUser = VpnRpcDeleteUser;\r\n/** Delete the HUB */\r\nvar VpnRpcDeleteHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteHub' class: Delete the HUB */\r\n function VpnRpcDeleteHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteHub;\r\n}());\r\nexports.VpnRpcDeleteHub = VpnRpcDeleteHub;\r\n/** Delete the table */\r\nvar VpnRpcDeleteTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteTable' class: Delete the table */\r\n function VpnRpcDeleteTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteTable;\r\n}());\r\nexports.VpnRpcDeleteTable = VpnRpcDeleteTable;\r\n/** Specify the Link */\r\nvar VpnRpcLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLink' class: Specify the Link */\r\n function VpnRpcLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The name of the cascade connection */\r\n this.AccountName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLink;\r\n}());\r\nexports.VpnRpcLink = VpnRpcLink;\r\n/** Disconnect the session */\r\nvar VpnRpcDeleteSession = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDeleteSession' class: Disconnect the session */\r\n function VpnRpcDeleteSession(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Session name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDeleteSession;\r\n}());\r\nexports.VpnRpcDeleteSession = VpnRpcDeleteSession;\r\n/** Specify the HUB */\r\nvar VpnRpcHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHub' class: Specify the HUB */\r\n function VpnRpcHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHub;\r\n}());\r\nexports.VpnRpcHub = VpnRpcHub;\r\n/** Disconnect a connection */\r\nvar VpnRpcDisconnectConnection = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcDisconnectConnection' class: Disconnect a connection */\r\n function VpnRpcDisconnectConnection(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcDisconnectConnection;\r\n}());\r\nexports.VpnRpcDisconnectConnection = VpnRpcDisconnectConnection;\r\n/** Enumeration of the access list */\r\nvar VpnRpcEnumAccessList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumAccessList' class: Enumeration of the access list */\r\n function VpnRpcEnumAccessList(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Access list */\r\n this.AccessList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumAccessList;\r\n}());\r\nexports.VpnRpcEnumAccessList = VpnRpcEnumAccessList;\r\n/** CA enumeration items of HUB */\r\nvar VpnRpcHubEnumCAItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubEnumCAItem' class: CA enumeration items of HUB */\r\n function VpnRpcHubEnumCAItem(init) {\r\n /** The key id of the item */\r\n this.Key_u32 = 0;\r\n /** Subject */\r\n this.SubjectName_utf = \"\";\r\n /** Issuer */\r\n this.IssuerName_utf = \"\";\r\n /** Expiration date */\r\n this.Expires_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubEnumCAItem;\r\n}());\r\nexports.VpnRpcHubEnumCAItem = VpnRpcHubEnumCAItem;\r\n/** CA enumeration of HUB */\r\nvar VpnRpcHubEnumCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubEnumCA' class: CA enumeration of HUB */\r\n function VpnRpcHubEnumCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The list of CA */\r\n this.CAList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubEnumCA;\r\n}());\r\nexports.VpnRpcHubEnumCA = VpnRpcHubEnumCA;\r\n/** Type of connection */\r\nvar VpnRpcConnectionType;\r\n(function (VpnRpcConnectionType) {\r\n /** VPN Client */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Client\"] = 0] = \"Client\";\r\n /** During initialization */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Init\"] = 1] = \"Init\";\r\n /** Login connection */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Login\"] = 2] = \"Login\";\r\n /** Additional connection */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Additional\"] = 3] = \"Additional\";\r\n /** RPC for server farm */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"FarmRpc\"] = 4] = \"FarmRpc\";\r\n /** RPC for Management */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"AdminRpc\"] = 5] = \"AdminRpc\";\r\n /** HUB enumeration */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"EnumHub\"] = 6] = \"EnumHub\";\r\n /** Password change */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"Password\"] = 7] = \"Password\";\r\n /** SSTP */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"SSTP\"] = 8] = \"SSTP\";\r\n /** OpenVPN */\r\n VpnRpcConnectionType[VpnRpcConnectionType[\"OpenVPN\"] = 9] = \"OpenVPN\";\r\n})(VpnRpcConnectionType = exports.VpnRpcConnectionType || (exports.VpnRpcConnectionType = {}));\r\n/** Connection enumeration items */\r\nvar VpnRpcEnumConnectionItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumConnectionItem' class: Connection enumeration items */\r\n function VpnRpcEnumConnectionItem(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Connected time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Connection type */\r\n this.Type_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumConnectionItem;\r\n}());\r\nexports.VpnRpcEnumConnectionItem = VpnRpcEnumConnectionItem;\r\n/** Connection enumeration */\r\nvar VpnRpcEnumConnection = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumConnection' class: Connection enumeration */\r\n function VpnRpcEnumConnection(init) {\r\n /** Number of connections */\r\n this.NumConnection_u32 = 0;\r\n /** Connection list */\r\n this.ConnectionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumConnection;\r\n}());\r\nexports.VpnRpcEnumConnection = VpnRpcEnumConnection;\r\n/** Enum CRL Item */\r\nvar VpnRpcEnumCrlItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumCrlItem' class: Enum CRL Item */\r\n function VpnRpcEnumCrlItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** The contents of the CRL item */\r\n this.CrlInfo_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumCrlItem;\r\n}());\r\nexports.VpnRpcEnumCrlItem = VpnRpcEnumCrlItem;\r\n/** Enum CRL */\r\nvar VpnRpcEnumCrl = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumCrl' class: Enum CRL */\r\n function VpnRpcEnumCrl(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** CRL list */\r\n this.CRLList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumCrl;\r\n}());\r\nexports.VpnRpcEnumCrl = VpnRpcEnumCrl;\r\n/** RPC_ENUM_DHCP_ITEM */\r\nvar VpnRpcEnumDhcpItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumDhcpItem' class: RPC_ENUM_DHCP_ITEM */\r\n function VpnRpcEnumDhcpItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Lease time */\r\n this.LeasedTime_dt = new Date();\r\n /** Expiration date */\r\n this.ExpireTime_dt = new Date();\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask */\r\n this.Mask_u32 = 0;\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumDhcpItem;\r\n}());\r\nexports.VpnRpcEnumDhcpItem = VpnRpcEnumDhcpItem;\r\n/** RPC_ENUM_DHCP */\r\nvar VpnRpcEnumDhcp = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumDhcp' class: RPC_ENUM_DHCP */\r\n function VpnRpcEnumDhcp(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** DHCP Item */\r\n this.DhcpTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumDhcp;\r\n}());\r\nexports.VpnRpcEnumDhcp = VpnRpcEnumDhcp;\r\n/** EtherIP setting list */\r\nvar VpnRpcEnumEtherIpId = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEtherIpId' class: EtherIP setting list */\r\n function VpnRpcEnumEtherIpId(init) {\r\n /** Setting list */\r\n this.Settings = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEtherIpId;\r\n}());\r\nexports.VpnRpcEnumEtherIpId = VpnRpcEnumEtherIpId;\r\n/** Ethernet Network Adapters list item */\r\nvar VpnRpcEnumEthItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEthItem' class: Ethernet Network Adapters list item */\r\n function VpnRpcEnumEthItem(init) {\r\n /** Device name */\r\n this.DeviceName_str = \"\";\r\n /** Network connection name (description) */\r\n this.NetworkConnectionName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEthItem;\r\n}());\r\nexports.VpnRpcEnumEthItem = VpnRpcEnumEthItem;\r\n/** Ethernet Network Adapters list */\r\nvar VpnRpcEnumEth = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumEth' class: Ethernet Network Adapters list */\r\n function VpnRpcEnumEth(init) {\r\n /** Ethernet Network Adapters list */\r\n this.EthList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumEth;\r\n}());\r\nexports.VpnRpcEnumEth = VpnRpcEnumEth;\r\n/** Server farm members enumeration items */\r\nvar VpnRpcEnumFarmItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumFarmItem' class: Server farm members enumeration items */\r\n function VpnRpcEnumFarmItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Controller */\r\n this.Controller_bool = false;\r\n /** Connection time */\r\n this.ConnectedTime_dt = new Date();\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Point */\r\n this.Point_u32 = 0;\r\n /** Number of sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of HUBs */\r\n this.NumHubs_u32 = 0;\r\n /** Number of assigned client licenses */\r\n this.AssignedClientLicense_u32 = 0;\r\n /** Number of assigned bridge licenses */\r\n this.AssignedBridgeLicense_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumFarmItem;\r\n}());\r\nexports.VpnRpcEnumFarmItem = VpnRpcEnumFarmItem;\r\n/** Server farm member enumeration */\r\nvar VpnRpcEnumFarm = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumFarm' class: Server farm member enumeration */\r\n function VpnRpcEnumFarm(init) {\r\n /** Number of Cluster Members */\r\n this.NumFarm_u32 = 0;\r\n /** Cluster Members list */\r\n this.FarmMemberList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumFarm;\r\n}());\r\nexports.VpnRpcEnumFarm = VpnRpcEnumFarm;\r\n/** Enumeration items in the group */\r\nvar VpnRpcEnumGroupItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumGroupItem' class: Enumeration items in the group */\r\n function VpnRpcEnumGroupItem(init) {\r\n /** User name */\r\n this.Name_str = \"\";\r\n /** Real name */\r\n this.Realname_utf = \"\";\r\n /** Note */\r\n this.Note_utf = \"\";\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Access denied */\r\n this.DenyAccess_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumGroupItem;\r\n}());\r\nexports.VpnRpcEnumGroupItem = VpnRpcEnumGroupItem;\r\n/** Group enumeration */\r\nvar VpnRpcEnumGroup = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumGroup' class: Group enumeration */\r\n function VpnRpcEnumGroup(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Group list */\r\n this.GroupList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumGroup;\r\n}());\r\nexports.VpnRpcEnumGroup = VpnRpcEnumGroup;\r\n/** Enumeration items of HUB */\r\nvar VpnRpcEnumHubItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumHubItem' class: Enumeration items of HUB */\r\n function VpnRpcEnumHubItem(init) {\r\n /** The name of the Virtual Hub */\r\n this.HubName_str = \"\";\r\n /** Online state */\r\n this.Online_bool = false;\r\n /** Type of HUB (Valid only for Clustered VPN Servers) */\r\n this.HubType_u32 = 0;\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Number of registered groups */\r\n this.NumGroups_u32 = 0;\r\n /** Number of registered sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of current MAC table entries */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of current IP table entries */\r\n this.NumIpTables_u32 = 0;\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Number of accumulated logins */\r\n this.NumLogin_u32 = 0;\r\n /** Whether the traffic information is provided */\r\n this.IsTrafficFilled_bool = false;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Ex.Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Ex.Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Ex.Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Ex.Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Ex.Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Ex.Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastCount_u64\"] = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumHubItem;\r\n}());\r\nexports.VpnRpcEnumHubItem = VpnRpcEnumHubItem;\r\n/** Enumeration of HUB */\r\nvar VpnRpcEnumHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumHub' class: Enumeration of HUB */\r\n function VpnRpcEnumHub(init) {\r\n /** Number of Virtual Hubs */\r\n this.NumHub_u32 = 0;\r\n /** Virtual Hubs */\r\n this.HubList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumHub;\r\n}());\r\nexports.VpnRpcEnumHub = VpnRpcEnumHub;\r\n/** Enumeration items of IP table */\r\nvar VpnRpcEnumIpTableItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumIpTableItem' class: Enumeration items of IP table */\r\n function VpnRpcEnumIpTableItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Assigned by the DHCP */\r\n this.DhcpAllocated_bool = false;\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Updating date */\r\n this.UpdatedTime_dt = new Date();\r\n /** Remote items */\r\n this.RemoteItem_bool = false;\r\n /** Remote host name */\r\n this.RemoteHostname_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumIpTableItem;\r\n}());\r\nexports.VpnRpcEnumIpTableItem = VpnRpcEnumIpTableItem;\r\n/** Enumeration of IP table */\r\nvar VpnRpcEnumIpTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumIpTable' class: Enumeration of IP table */\r\n function VpnRpcEnumIpTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** MAC table */\r\n this.IpTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumIpTable;\r\n}());\r\nexports.VpnRpcEnumIpTable = VpnRpcEnumIpTable;\r\n/** Layer-3 interface enumeration */\r\nvar VpnRpcEnumL3If = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3If' class: Layer-3 interface enumeration */\r\n function VpnRpcEnumL3If(init) {\r\n /** Layer-3 switch name */\r\n this.Name_str = \"\";\r\n /** Layer-3 interface list */\r\n this.L3IFList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3If;\r\n}());\r\nexports.VpnRpcEnumL3If = VpnRpcEnumL3If;\r\n/** Layer-3 switch enumeration item */\r\nvar VpnRpcEnumL3SwItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3SwItem' class: Layer-3 switch enumeration item */\r\n function VpnRpcEnumL3SwItem(init) {\r\n /** Name of the layer-3 switch */\r\n this.Name_str = \"\";\r\n /** Number of layer-3 switch virtual interfaces */\r\n this.NumInterfaces_u32 = 0;\r\n /** Number of routing tables */\r\n this.NumTables_u32 = 0;\r\n /** Activated flag */\r\n this.Active_bool = false;\r\n /** Online flag */\r\n this.Online_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3SwItem;\r\n}());\r\nexports.VpnRpcEnumL3SwItem = VpnRpcEnumL3SwItem;\r\n/** Layer-3 switch enumeration */\r\nvar VpnRpcEnumL3Sw = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3Sw' class: Layer-3 switch enumeration */\r\n function VpnRpcEnumL3Sw(init) {\r\n /** Layer-3 switch list */\r\n this.L3SWList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3Sw;\r\n}());\r\nexports.VpnRpcEnumL3Sw = VpnRpcEnumL3Sw;\r\n/** Routing table enumeration */\r\nvar VpnRpcEnumL3Table = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumL3Table' class: Routing table enumeration */\r\n function VpnRpcEnumL3Table(init) {\r\n /** L3 switch name */\r\n this.Name_str = \"\";\r\n /** Routing table item list */\r\n this.L3Table = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumL3Table;\r\n}());\r\nexports.VpnRpcEnumL3Table = VpnRpcEnumL3Table;\r\n/** Cascade Connection Enumeration */\r\nvar VpnRpcEnumLinkItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLinkItem' class: Cascade Connection Enumeration */\r\n function VpnRpcEnumLinkItem(init) {\r\n /** The name of cascade connection */\r\n this.AccountName_utf = \"\";\r\n /** Online flag */\r\n this.Online_bool = false;\r\n /** The flag indicates whether the cascade connection is established */\r\n this.Connected_bool = false;\r\n /** The error last occurred if the cascade connection is in the fail state */\r\n this.LastError_u32 = 0;\r\n /** Connection completion time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Host name of the destination VPN server */\r\n this.Hostname_str = \"\";\r\n /** The Virtual Hub name */\r\n this.TargetHubName_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLinkItem;\r\n}());\r\nexports.VpnRpcEnumLinkItem = VpnRpcEnumLinkItem;\r\n/** Enumeration of the link */\r\nvar VpnRpcEnumLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLink' class: Enumeration of the link */\r\n function VpnRpcEnumLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Number of cascade connections */\r\n this.NumLink_u32 = 0;\r\n /** The list of cascade connections */\r\n this.LinkList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLink;\r\n}());\r\nexports.VpnRpcEnumLink = VpnRpcEnumLink;\r\n/** List of listeners item */\r\nvar VpnRpcListenerListItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListenerListItem' class: List of listeners item */\r\n function VpnRpcListenerListItem(init) {\r\n /** TCP port number (range: 1 - 65535) */\r\n this.Ports_u32 = 0;\r\n /** Active state */\r\n this.Enables_bool = false;\r\n /** The flag to indicate if the error occurred on the listener port */\r\n this.Errors_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListenerListItem;\r\n}());\r\nexports.VpnRpcListenerListItem = VpnRpcListenerListItem;\r\n/** List of listeners */\r\nvar VpnRpcListenerList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcListenerList' class: List of listeners */\r\n function VpnRpcListenerList(init) {\r\n /** List of listener items */\r\n this.ListenerList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcListenerList;\r\n}());\r\nexports.VpnRpcListenerList = VpnRpcListenerList;\r\n/** Local Bridge enumeration */\r\nvar VpnRpcEnumLocalBridge = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLocalBridge' class: Local Bridge enumeration */\r\n function VpnRpcEnumLocalBridge(init) {\r\n /** Local Bridge list */\r\n this.LocalBridgeList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLocalBridge;\r\n}());\r\nexports.VpnRpcEnumLocalBridge = VpnRpcEnumLocalBridge;\r\n/** Log file enumeration */\r\nvar VpnRpcEnumLogFileItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLogFileItem' class: Log file enumeration */\r\n function VpnRpcEnumLogFileItem(init) {\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** File path */\r\n this.FilePath_str = \"\";\r\n /** File size */\r\n this.FileSize_u32 = 0;\r\n /** Last write date */\r\n this.UpdatedTime_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLogFileItem;\r\n}());\r\nexports.VpnRpcEnumLogFileItem = VpnRpcEnumLogFileItem;\r\n/** Log file enumeration */\r\nvar VpnRpcEnumLogFile = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumLogFile' class: Log file enumeration */\r\n function VpnRpcEnumLogFile(init) {\r\n /** Log file list */\r\n this.LogFiles = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumLogFile;\r\n}());\r\nexports.VpnRpcEnumLogFile = VpnRpcEnumLogFile;\r\n/** Enumeration items of the MAC table */\r\nvar VpnRpcEnumMacTableItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumMacTableItem' class: Enumeration items of the MAC table */\r\n function VpnRpcEnumMacTableItem(init) {\r\n /** Key ID */\r\n this.Key_u32 = 0;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Updating date */\r\n this.UpdatedTime_dt = new Date();\r\n /** Remote items */\r\n this.RemoteItem_bool = false;\r\n /** Remote host name */\r\n this.RemoteHostname_str = \"\";\r\n /** VLAN ID */\r\n this.VlanId_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumMacTableItem;\r\n}());\r\nexports.VpnRpcEnumMacTableItem = VpnRpcEnumMacTableItem;\r\n/** Enumeration of the MAC table */\r\nvar VpnRpcEnumMacTable = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumMacTable' class: Enumeration of the MAC table */\r\n function VpnRpcEnumMacTable(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** MAC table */\r\n this.MacTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumMacTable;\r\n}());\r\nexports.VpnRpcEnumMacTable = VpnRpcEnumMacTable;\r\n/** NAT Entry Protocol Number */\r\nvar VpnRpcNatProtocol;\r\n(function (VpnRpcNatProtocol) {\r\n /** TCP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"TCP\"] = 0] = \"TCP\";\r\n /** UDP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"UDP\"] = 1] = \"UDP\";\r\n /** DNS */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"DNS\"] = 2] = \"DNS\";\r\n /** ICMP */\r\n VpnRpcNatProtocol[VpnRpcNatProtocol[\"ICMP\"] = 3] = \"ICMP\";\r\n})(VpnRpcNatProtocol = exports.VpnRpcNatProtocol || (exports.VpnRpcNatProtocol = {}));\r\n/** State of NAT session (TCP) */\r\nvar VpnRpcNatTcpState;\r\n(function (VpnRpcNatTcpState) {\r\n /** Connecting */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Connecting\"] = 0] = \"Connecting\";\r\n /** Send the RST (Connection failure or disconnected) */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"SendReset\"] = 1] = \"SendReset\";\r\n /** Connection complete */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Connected\"] = 2] = \"Connected\";\r\n /** Connection established */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"Established\"] = 3] = \"Established\";\r\n /** Wait for socket disconnection */\r\n VpnRpcNatTcpState[VpnRpcNatTcpState[\"WaitDisconnect\"] = 4] = \"WaitDisconnect\";\r\n})(VpnRpcNatTcpState = exports.VpnRpcNatTcpState || (exports.VpnRpcNatTcpState = {}));\r\n/** VpnRpcEnumNat List Item */\r\nvar VpnRpcEnumNatItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumNatItem' class: VpnRpcEnumNat List Item */\r\n function VpnRpcEnumNatItem(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Protocol */\r\n this.Protocol_u32 = 0;\r\n /** Source IP address */\r\n this.SrcIp_ip = \"\";\r\n /** Source host name */\r\n this.SrcHost_str = \"\";\r\n /** Source port number */\r\n this.SrcPort_u32 = 0;\r\n /** Destination IP address */\r\n this.DestIp_ip = \"\";\r\n /** Destination host name */\r\n this.DestHost_str = \"\";\r\n /** Destination port number */\r\n this.DestPort_u32 = 0;\r\n /** Connection time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last communication time */\r\n this.LastCommTime_dt = new Date();\r\n /** Transmission size */\r\n this.SendSize_u64 = 0;\r\n /** Receive size */\r\n this.RecvSize_u64 = 0;\r\n /** TCP state */\r\n this.TcpStatus_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumNatItem;\r\n}());\r\nexports.VpnRpcEnumNatItem = VpnRpcEnumNatItem;\r\n/** RPC_ENUM_NAT */\r\nvar VpnRpcEnumNat = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumNat' class: RPC_ENUM_NAT */\r\n function VpnRpcEnumNat(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** NAT item */\r\n this.NatTable = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumNat;\r\n}());\r\nexports.VpnRpcEnumNat = VpnRpcEnumNat;\r\n/** Enumeration item of VPN session */\r\nvar VpnRpcEnumSessionItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumSessionItem' class: Enumeration item of VPN session */\r\n function VpnRpcEnumSessionItem(init) {\r\n /** Session name */\r\n this.Name_str = \"\";\r\n /** Remote session */\r\n this.RemoteSession_bool = false;\r\n /** Remote server name */\r\n this.RemoteHostname_str = \"\";\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** IP address */\r\n this.ClientIP_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Maximum number of underlying TCP connections */\r\n this.MaxNumTcp_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.CurrentNumTcp_u32 = 0;\r\n /** Packet size transmitted */\r\n this.PacketSize_u64 = 0;\r\n /** Number of packets transmitted */\r\n this.PacketNum_u64 = 0;\r\n /** Is a Cascade VPN session */\r\n this.LinkMode_bool = false;\r\n /** Is a SecureNAT VPN session */\r\n this.SecureNATMode_bool = false;\r\n /** Is the VPN session for Local Bridge */\r\n this.BridgeMode_bool = false;\r\n /** Is a Layer-3 Switch VPN session */\r\n this.Layer3Mode_bool = false;\r\n /** Is in Bridge Mode */\r\n this.Client_BridgeMode_bool = false;\r\n /** Is in Monitor Mode */\r\n this.Client_MonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n /** Unique ID of the VPN Session */\r\n this.UniqueId_bin = new Uint8Array([]);\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumSessionItem;\r\n}());\r\nexports.VpnRpcEnumSessionItem = VpnRpcEnumSessionItem;\r\n/** Enumerate VPN sessions */\r\nvar VpnRpcEnumSession = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumSession' class: Enumerate VPN sessions */\r\n function VpnRpcEnumSession(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** VPN sessions list */\r\n this.SessionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumSession;\r\n}());\r\nexports.VpnRpcEnumSession = VpnRpcEnumSession;\r\n/** Enumeration item of user */\r\nvar VpnRpcEnumUserItem = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumUserItem' class: Enumeration item of user */\r\n function VpnRpcEnumUserItem(init) {\r\n /** User name */\r\n this.Name_str = \"\";\r\n /** Group name */\r\n this.GroupName_str = \"\";\r\n /** Real name */\r\n this.Realname_utf = \"\";\r\n /** Note */\r\n this.Note_utf = \"\";\r\n /** Authentication method */\r\n this.AuthType_u32 = 0;\r\n /** Number of logins */\r\n this.NumLogin_u32 = 0;\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Access denied */\r\n this.DenyAccess_bool = false;\r\n /** Flag of whether the traffic variable is set */\r\n this.IsTrafficFilled_bool = false;\r\n /** Flag of whether expiration date variable is set */\r\n this.IsExpiresFilled_bool = false;\r\n /** Expiration date */\r\n this.Expires_dt = new Date();\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Ex.Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Ex.Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Ex.Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Ex.Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Ex.Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Ex.Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Ex.Send.UnicastCount_u64\"] = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumUserItem;\r\n}());\r\nexports.VpnRpcEnumUserItem = VpnRpcEnumUserItem;\r\n/** Enumeration of user */\r\nvar VpnRpcEnumUser = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcEnumUser' class: Enumeration of user */\r\n function VpnRpcEnumUser(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** User list */\r\n this.UserList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcEnumUser;\r\n}());\r\nexports.VpnRpcEnumUser = VpnRpcEnumUser;\r\n/** Source IP Address Limit List Item */\r\nvar VpnAc = /** @class */ (function () {\r\n /** Constructor for the 'VpnAc' class: Source IP Address Limit List Item */\r\n function VpnAc(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** Priority */\r\n this.Priority_u32 = 0;\r\n /** Deny access */\r\n this.Deny_bool = false;\r\n /** Set true if you want to specify the SubnetMask_ip item. */\r\n this.Masked_bool = false;\r\n /** IP address */\r\n this.IpAddress_ip = \"\";\r\n /** Subnet mask, valid only if Masked_bool == true */\r\n this.SubnetMask_ip = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAc;\r\n}());\r\nexports.VpnAc = VpnAc;\r\n/** Source IP Address Limit List */\r\nvar VpnRpcAcList = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAcList' class: Source IP Address Limit List */\r\n function VpnRpcAcList(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Source IP Address Limit List */\r\n this.ACList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAcList;\r\n}());\r\nexports.VpnRpcAcList = VpnRpcAcList;\r\n/** Message */\r\nvar VpnRpcMsg = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcMsg' class: Message */\r\n function VpnRpcMsg(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Message (Unicode strings acceptable) */\r\n this.Msg_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcMsg;\r\n}());\r\nexports.VpnRpcMsg = VpnRpcMsg;\r\n/** Get / Set the Azure state */\r\nvar VpnRpcAzureStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAzureStatus' class: Get / Set the Azure state */\r\n function VpnRpcAzureStatus(init) {\r\n /** Whether VPN Azure Function is Enabled */\r\n this.IsEnabled_bool = false;\r\n /** Whether connection to VPN Azure Cloud Server is established */\r\n this.IsConnected_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAzureStatus;\r\n}());\r\nexports.VpnRpcAzureStatus = VpnRpcAzureStatus;\r\n/** Local Bridge support information */\r\nvar VpnRpcBridgeSupport = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcBridgeSupport' class: Local Bridge support information */\r\n function VpnRpcBridgeSupport(init) {\r\n /** Whether the OS supports the Local Bridge function */\r\n this.IsBridgeSupportedOs_bool = false;\r\n /** Whether WinPcap is necessary to install */\r\n this.IsWinPcapNeeded_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcBridgeSupport;\r\n}());\r\nexports.VpnRpcBridgeSupport = VpnRpcBridgeSupport;\r\n/** Get the CA of HUB */\r\nvar VpnRpcHubGetCA = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubGetCA' class: Get the CA of HUB */\r\n function VpnRpcHubGetCA(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The key id of the certificate */\r\n this.Key_u32 = 0;\r\n /** The body of the X.509 certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubGetCA;\r\n}());\r\nexports.VpnRpcHubGetCA = VpnRpcHubGetCA;\r\n/** Caps item of the VPN Server */\r\nvar VpnCaps = /** @class */ (function () {\r\n /** Constructor for the 'VpnCaps' class: Caps item of the VPN Server */\r\n function VpnCaps(init) {\r\n /** Name */\r\n this.CapsName_str = \"\";\r\n /** Value */\r\n this.CapsValue_u32 = 0;\r\n /** Descrption */\r\n this.CapsDescrption_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnCaps;\r\n}());\r\nexports.VpnCaps = VpnCaps;\r\n/** Caps list of the VPN Server */\r\nvar VpnCapslist = /** @class */ (function () {\r\n /** Constructor for the 'VpnCapslist' class: Caps list of the VPN Server */\r\n function VpnCapslist(init) {\r\n /** Caps list of the VPN Server */\r\n this.CapsList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnCapslist;\r\n}());\r\nexports.VpnCapslist = VpnCapslist;\r\n/** Config operation */\r\nvar VpnRpcConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcConfig' class: Config operation */\r\n function VpnRpcConfig(init) {\r\n /** File name (valid only for returning from the server) */\r\n this.FileName_str = \"\";\r\n /** File data */\r\n this.FileData_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcConfig;\r\n}());\r\nexports.VpnRpcConfig = VpnRpcConfig;\r\n/** Connection information */\r\nvar VpnRpcConnectionInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcConnectionInfo' class: Connection information */\r\n function VpnRpcConnectionInfo(init) {\r\n /** Connection name */\r\n this.Name_str = \"\";\r\n /** Type */\r\n this.Type_u32 = 0;\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Connected time */\r\n this.ConnectedTime_dt = new Date();\r\n /** Server string */\r\n this.ServerStr_str = \"\";\r\n /** Server version */\r\n this.ServerVer_u32 = 0;\r\n /** Server build number */\r\n this.ServerBuild_u32 = 0;\r\n /** Client string */\r\n this.ClientStr_str = \"\";\r\n /** Client version */\r\n this.ClientVer_u32 = 0;\r\n /** Client build number */\r\n this.ClientBuild_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcConnectionInfo;\r\n}());\r\nexports.VpnRpcConnectionInfo = VpnRpcConnectionInfo;\r\n/** Proxy type */\r\nvar VpnRpcProxyType;\r\n(function (VpnRpcProxyType) {\r\n /** Direct TCP connection */\r\n VpnRpcProxyType[VpnRpcProxyType[\"Direct\"] = 0] = \"Direct\";\r\n /** Connection via HTTP proxy server */\r\n VpnRpcProxyType[VpnRpcProxyType[\"HTTP\"] = 1] = \"HTTP\";\r\n /** Connection via SOCKS proxy server */\r\n VpnRpcProxyType[VpnRpcProxyType[\"SOCKS\"] = 2] = \"SOCKS\";\r\n})(VpnRpcProxyType = exports.VpnRpcProxyType || (exports.VpnRpcProxyType = {}));\r\n/** The current status of the DDNS */\r\nvar VpnDDnsClientStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnDDnsClientStatus' class: The current status of the DDNS */\r\n function VpnDDnsClientStatus(init) {\r\n /** Last error code (IPv4) */\r\n this.Err_IPv4_u32 = 0;\r\n /** Last error string (IPv4) */\r\n this.ErrStr_IPv4_utf = \"\";\r\n /** Last error code (IPv6) */\r\n this.Err_IPv6_u32 = 0;\r\n /** Last error string (IPv6) */\r\n this.ErrStr_IPv6_utf = \"\";\r\n /** Current DDNS host name */\r\n this.CurrentHostName_str = \"\";\r\n /** Current FQDN of the DDNS hostname */\r\n this.CurrentFqdn_str = \"\";\r\n /** DDNS suffix */\r\n this.DnsSuffix_str = \"\";\r\n /** Current IPv4 address of the VPN Server */\r\n this.CurrentIPv4_str = \"\";\r\n /** Current IPv6 address of the VPN Server */\r\n this.CurrentIPv6_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnDDnsClientStatus;\r\n}());\r\nexports.VpnDDnsClientStatus = VpnDDnsClientStatus;\r\n/** Internet connection settings */\r\nvar VpnInternetSetting = /** @class */ (function () {\r\n /** Constructor for the 'VpnInternetSetting' class: Internet connection settings */\r\n function VpnInternetSetting(init) {\r\n /** Type of proxy server */\r\n this.ProxyType_u32 = 0;\r\n /** Proxy server host name */\r\n this.ProxyHostName_str = \"\";\r\n /** Proxy server port number */\r\n this.ProxyPort_u32 = 0;\r\n /** Proxy server user name */\r\n this.ProxyUsername_str = \"\";\r\n /** Proxy server password */\r\n this.ProxyPassword_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnInternetSetting;\r\n}());\r\nexports.VpnInternetSetting = VpnInternetSetting;\r\n/** Administration options */\r\nvar VpnAdminOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnAdminOption' class: Administration options */\r\n function VpnAdminOption(init) {\r\n /** Name */\r\n this.Name_str = \"\";\r\n /** Data */\r\n this.Value_u32 = 0;\r\n /** Descrption */\r\n this.Descrption_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnAdminOption;\r\n}());\r\nexports.VpnAdminOption = VpnAdminOption;\r\n/** Administration options list */\r\nvar VpnRpcAdminOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcAdminOption' class: Administration options list */\r\n function VpnRpcAdminOption(init) {\r\n /** Virtual HUB name */\r\n this.HubName_str = \"\";\r\n /** List data */\r\n this.AdminOptionList = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcAdminOption;\r\n}());\r\nexports.VpnRpcAdminOption = VpnRpcAdminOption;\r\n/** Connection state to the controller */\r\nvar VpnRpcFarmConnectionStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmConnectionStatus' class: Connection state to the controller */\r\n function VpnRpcFarmConnectionStatus(init) {\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Port number */\r\n this.Port_u32 = 0;\r\n /** Online state */\r\n this.Online_bool = false;\r\n /** Last error code */\r\n this.LastError_u32 = 0;\r\n /** Connection start time */\r\n this.StartedTime_dt = new Date();\r\n /** First connection time */\r\n this.FirstConnectedTime_dt = new Date();\r\n /** Connection time of this time */\r\n this.CurrentConnectedTime_dt = new Date();\r\n /** Number of retries */\r\n this.NumTry_u32 = 0;\r\n /** Number of connection count */\r\n this.NumConnected_u32 = 0;\r\n /** Connection failure count */\r\n this.NumFailed_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmConnectionStatus;\r\n}());\r\nexports.VpnRpcFarmConnectionStatus = VpnRpcFarmConnectionStatus;\r\n/** HUB item of each farm member */\r\nvar VpnRpcFarmHub = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmHub' class: HUB item of each farm member */\r\n function VpnRpcFarmHub(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Dynamic HUB */\r\n this.DynamicHub_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmHub;\r\n}());\r\nexports.VpnRpcFarmHub = VpnRpcFarmHub;\r\n/** Server farm member information acquisition */\r\nvar VpnRpcFarmInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarmInfo' class: Server farm member information acquisition */\r\n function VpnRpcFarmInfo(init) {\r\n /** ID */\r\n this.Id_u32 = 0;\r\n /** The flag if the server is Cluster Controller (false: Cluster Member servers) */\r\n this.Controller_bool = false;\r\n /** Connection Established Time */\r\n this.ConnectedTime_dt = new Date();\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Host name */\r\n this.Hostname_str = \"\";\r\n /** Point */\r\n this.Point_u32 = 0;\r\n /** Number of Public Ports */\r\n this.NumPort_u32 = 0;\r\n /** Public Ports */\r\n this.Ports_u32 = [];\r\n /** Server certificate */\r\n this.ServerCert_bin = new Uint8Array([]);\r\n /** Number of farm HUB */\r\n this.NumFarmHub_u32 = 0;\r\n /** The hosted Virtual Hub list */\r\n this.HubsList = [];\r\n /** Number of hosted VPN sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Performance Standard Ratio */\r\n this.Weight_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarmInfo;\r\n}());\r\nexports.VpnRpcFarmInfo = VpnRpcFarmInfo;\r\n/** Server farm configuration */\r\nvar VpnRpcFarm = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcFarm' class: Server farm configuration */\r\n function VpnRpcFarm(init) {\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Valid only for Cluster Member servers. Number of the Ports_u32 element. */\r\n this.NumPort_u32 = 0;\r\n /** Valid only for Cluster Member servers. Specify the list of public port numbers on this server. The list must have at least one public port number set, and it is also possible to set multiple public port numbers. */\r\n this.Ports_u32 = [];\r\n /** Valid only for Cluster Member servers. Specify the public IP address of this server. If you wish to leave public IP address unspecified, specify the empty string. When a public IP address is not specified, the IP address of the network interface used when connecting to the cluster controller will be automatically used. */\r\n this.PublicIp_ip = \"\";\r\n /** Valid only for Cluster Member servers. Specify the host name or IP address of the destination cluster controller. */\r\n this.ControllerName_str = \"\";\r\n /** Valid only for Cluster Member servers. Specify the TCP port number of the destination cluster controller. */\r\n this.ControllerPort_u32 = 0;\r\n /** Valid only for Cluster Member servers. Specify the password required to connect to the destination controller. It needs to be the same as an administrator password on the destination controller. */\r\n this.MemberPasswordPlaintext_str = \"\";\r\n /** This sets a value for the performance standard ratio of this VPN Server. This is the standard value for when load balancing is performed in the cluster. For example, making only one machine 200 while the other members have a status of 100, will regulate that machine to receive twice as many connections as the other members. Specify 1 or higher for the value. If this parameter is left unspecified, 100 will be used. */\r\n this.Weight_u32 = 0;\r\n /** Valid only for Cluster Controller server. By specifying true, the VPN Server will operate only as a controller on the cluster and it will always distribute general VPN Client connections to members other than itself. This function is used in high-load environments. */\r\n this.ControllerOnly_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcFarm;\r\n}());\r\nexports.VpnRpcFarm = VpnRpcFarm;\r\n/** Log switch type */\r\nvar VpnRpcLogSwitchType;\r\n(function (VpnRpcLogSwitchType) {\r\n /** No switching */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"No\"] = 0] = \"No\";\r\n /** Secondly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Second\"] = 1] = \"Second\";\r\n /** Minutely basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Minute\"] = 2] = \"Minute\";\r\n /** Hourly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Hour\"] = 3] = \"Hour\";\r\n /** Daily basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Day\"] = 4] = \"Day\";\r\n /** Monthly basis */\r\n VpnRpcLogSwitchType[VpnRpcLogSwitchType[\"Month\"] = 5] = \"Month\";\r\n})(VpnRpcLogSwitchType = exports.VpnRpcLogSwitchType || (exports.VpnRpcLogSwitchType = {}));\r\n/** Packet log settings */\r\nvar VpnRpcPacketLogSetting;\r\n(function (VpnRpcPacketLogSetting) {\r\n /** Not save */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"None\"] = 0] = \"None\";\r\n /** Only header */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"Header\"] = 1] = \"Header\";\r\n /** All payloads */\r\n VpnRpcPacketLogSetting[VpnRpcPacketLogSetting[\"All\"] = 2] = \"All\";\r\n})(VpnRpcPacketLogSetting = exports.VpnRpcPacketLogSetting || (exports.VpnRpcPacketLogSetting = {}));\r\n/** Packet log settings array index */\r\nvar VpnRpcPacketLogSettingIndex;\r\n(function (VpnRpcPacketLogSettingIndex) {\r\n /** TCP connection log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"TcpConnection\"] = 0] = \"TcpConnection\";\r\n /** TCP packet log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"TcpAll\"] = 1] = \"TcpAll\";\r\n /** DHCP Log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Dhcp\"] = 2] = \"Dhcp\";\r\n /** UDP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Udp\"] = 3] = \"Udp\";\r\n /** ICMP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Icmp\"] = 4] = \"Icmp\";\r\n /** IP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Ip\"] = 5] = \"Ip\";\r\n /** ARP log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Arp\"] = 6] = \"Arp\";\r\n /** Ethernet log */\r\n VpnRpcPacketLogSettingIndex[VpnRpcPacketLogSettingIndex[\"Ethernet\"] = 7] = \"Ethernet\";\r\n})(VpnRpcPacketLogSettingIndex = exports.VpnRpcPacketLogSettingIndex || (exports.VpnRpcPacketLogSettingIndex = {}));\r\n/** HUB log settings */\r\nvar VpnRpcHubLog = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubLog' class: HUB log settings */\r\n function VpnRpcHubLog(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The flag to enable / disable saving the security log */\r\n this.SaveSecurityLog_bool = false;\r\n /** The log filename switching setting of the security log */\r\n this.SecurityLogSwitchType_u32 = 0;\r\n /** The flag to enable / disable saving the security log */\r\n this.SavePacketLog_bool = false;\r\n /** The log filename switching settings of the packet logs */\r\n this.PacketLogSwitchType_u32 = 0;\r\n /** Specify the save contents of the packet logs (uint * 16 array). The index numbers: TcpConnection = 0, TcpAll = 1, DHCP = 2, UDP = 3, ICMP = 4, IP = 5, ARP = 6, Ethernet = 7. */\r\n this.PacketLogConfig_u32 = [];\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubLog;\r\n}());\r\nexports.VpnRpcHubLog = VpnRpcHubLog;\r\n/** RADIUS server options */\r\nvar VpnRpcRadius = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcRadius' class: RADIUS server options */\r\n function VpnRpcRadius(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** RADIUS server name */\r\n this.RadiusServerName_str = \"\";\r\n /** RADIUS port number */\r\n this.RadiusPort_u32 = 0;\r\n /** Secret key */\r\n this.RadiusSecret_str = \"\";\r\n /** Radius retry interval */\r\n this.RadiusRetryInterval_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcRadius;\r\n}());\r\nexports.VpnRpcRadius = VpnRpcRadius;\r\n/** Get the state HUB */\r\nvar VpnRpcHubStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcHubStatus' class: Get the state HUB */\r\n function VpnRpcHubStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Online */\r\n this.Online_bool = false;\r\n /** Type of HUB */\r\n this.HubType_u32 = 0;\r\n /** Number of sessions */\r\n this.NumSessions_u32 = 0;\r\n /** Number of sessions (client mode) */\r\n this.NumSessionsClient_u32 = 0;\r\n /** Number of sessions (bridge mode) */\r\n this.NumSessionsBridge_u32 = 0;\r\n /** Number of Access list entries */\r\n this.NumAccessLists_u32 = 0;\r\n /** Number of users */\r\n this.NumUsers_u32 = 0;\r\n /** Number of groups */\r\n this.NumGroups_u32 = 0;\r\n /** Number of MAC table entries */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of IP table entries */\r\n this.NumIpTables_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** Whether SecureNAT is enabled */\r\n this.SecureNATEnabled_bool = false;\r\n /** Last communication date and time */\r\n this.LastCommTime_dt = new Date();\r\n /** Last login date and time */\r\n this.LastLoginTime_dt = new Date();\r\n /** Creation date and time */\r\n this.CreatedTime_dt = new Date();\r\n /** Number of logins */\r\n this.NumLogin_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcHubStatus;\r\n}());\r\nexports.VpnRpcHubStatus = VpnRpcHubStatus;\r\n/** List of services provided by IPsec server */\r\nvar VpnIPsecServices = /** @class */ (function () {\r\n /** Constructor for the 'VpnIPsecServices' class: List of services provided by IPsec server */\r\n function VpnIPsecServices(init) {\r\n /** Enable or Disable the L2TP Server Function (Raw L2TP with No Encryptions). To accept special VPN clients, enable this option. */\r\n this.L2TP_Raw_bool = false;\r\n /** Enable or Disable the L2TP over IPsec Server Function. To accept VPN connections from iPhone, iPad, Android, Windows or Mac OS X, enable this option. */\r\n this.L2TP_IPsec_bool = false;\r\n /** Enable or Disable the EtherIP / L2TPv3 over IPsec Server Function (for site-to-site VPN Server function). Router Products which are compatible with EtherIP over IPsec can connect to Virtual Hubs on the VPN Server and establish Layer-2 (Ethernet) Bridging. */\r\n this.EtherIP_IPsec_bool = false;\r\n /** Specify the IPsec Pre-Shared Key. An IPsec Pre-Shared Key is also called as \"PSK\" or \"secret\". Specify it equal or less than 8 letters, and distribute it to every users who will connect to the VPN Server. Please note: Google Android 4.0 has a bug which a Pre-Shared Key with 10 or more letters causes a unexpected behavior. For that reason, the letters of a Pre-Shared Key should be 9 or less characters. */\r\n this.IPsec_Secret_str = \"\";\r\n /** Specify the default Virtual HUB in a case of omitting the name of HUB on the Username. Users should specify their username such as \"Username@Target Virtual HUB Name\" to connect this L2TP Server. If the designation of the Virtual Hub is omitted, the above HUB will be used as the target. */\r\n this.L2TP_DefaultHub_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnIPsecServices;\r\n}());\r\nexports.VpnIPsecServices = VpnIPsecServices;\r\n/** Keep alive protocol */\r\nvar VpnRpcKeepAliveProtocol;\r\n(function (VpnRpcKeepAliveProtocol) {\r\n /** TCP */\r\n VpnRpcKeepAliveProtocol[VpnRpcKeepAliveProtocol[\"TCP\"] = 0] = \"TCP\";\r\n /** UDP */\r\n VpnRpcKeepAliveProtocol[VpnRpcKeepAliveProtocol[\"UDP\"] = 1] = \"UDP\";\r\n})(VpnRpcKeepAliveProtocol = exports.VpnRpcKeepAliveProtocol || (exports.VpnRpcKeepAliveProtocol = {}));\r\n/** Keep Alive settings */\r\nvar VpnRpcKeep = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcKeep' class: Keep Alive settings */\r\n function VpnRpcKeep(init) {\r\n /** The flag to enable keep-alive to the Internet */\r\n this.UseKeepConnect_bool = false;\r\n /** Specify the host name or IP address of the destination */\r\n this.KeepConnectHost_str = \"\";\r\n /** Specify the port number of the destination */\r\n this.KeepConnectPort_u32 = 0;\r\n /** Protocol type */\r\n this.KeepConnectProtocol_u32 = 0;\r\n /** Interval Between Packets Sends (Seconds) */\r\n this.KeepConnectInterval_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcKeep;\r\n}());\r\nexports.VpnRpcKeep = VpnRpcKeep;\r\n/** State of the client session */\r\nvar VpnRpcClientSessionStatus;\r\n(function (VpnRpcClientSessionStatus) {\r\n /** Connecting */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Connecting\"] = 0] = \"Connecting\";\r\n /** Negotiating */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Negotiation\"] = 1] = \"Negotiation\";\r\n /** During user authentication */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Auth\"] = 2] = \"Auth\";\r\n /** Connection complete */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Established\"] = 3] = \"Established\";\r\n /** Wait to retry */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Retry\"] = 4] = \"Retry\";\r\n /** Idle state */\r\n VpnRpcClientSessionStatus[VpnRpcClientSessionStatus[\"Idle\"] = 5] = \"Idle\";\r\n})(VpnRpcClientSessionStatus = exports.VpnRpcClientSessionStatus || (exports.VpnRpcClientSessionStatus = {}));\r\n/** Get the link state */\r\nvar VpnRpcLinkStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcLinkStatus' class: Get the link state */\r\n function VpnRpcLinkStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_Ex_str = \"\";\r\n /** The name of the cascade connection */\r\n this.AccountName_utf = \"\";\r\n /** The flag whether the cascade connection is enabled */\r\n this.Active_bool = false;\r\n /** The flag whether the cascade connection is established */\r\n this.Connected_bool = false;\r\n /** The session status */\r\n this.SessionStatus_u32 = 0;\r\n /** The destination VPN server name */\r\n this.ServerName_str = \"\";\r\n /** The port number of the server */\r\n this.ServerPort_u32 = 0;\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server product version */\r\n this.ServerProductVer_u32 = 0;\r\n /** Server product build number */\r\n this.ServerProductBuild_u32 = 0;\r\n /** Server's X.509 certificate */\r\n this.ServerX_bin = new Uint8Array([]);\r\n /** Client certificate */\r\n this.ClientX_bin = new Uint8Array([]);\r\n /** Connection start time */\r\n this.StartTime_dt = new Date();\r\n /** Connection completion time of the first connection */\r\n this.FirstConnectionEstablisiedTime_dt = new Date();\r\n /** Connection completion time of this connection */\r\n this.CurrentConnectionEstablishTime_dt = new Date();\r\n /** Number of connections have been established so far */\r\n this.NumConnectionsEatablished_u32 = 0;\r\n /** Half-connection */\r\n this.HalfConnection_bool = false;\r\n /** VoIP / QoS */\r\n this.QoS_bool = false;\r\n /** Maximum number of the underlying TCP connections */\r\n this.MaxTcpConnections_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of underlying inbound TCP connections */\r\n this.NumTcpConnectionsUpload_u32 = 0;\r\n /** Number of underlying outbound TCP connections */\r\n this.NumTcpConnectionsDownload_u32 = 0;\r\n /** Use of encryption */\r\n this.UseEncrypt_bool = false;\r\n /** Cipher algorithm name */\r\n this.CipherName_str = \"\";\r\n /** Use of compression */\r\n this.UseCompress_bool = false;\r\n /** The flag whether this is a R-UDP session */\r\n this.IsRUDPSession_bool = false;\r\n /** Underlying physical communication protocol */\r\n this.UnderlayProtocol_str = \"\";\r\n /** The UDP acceleration is enabled */\r\n this.IsUdpAccelerationEnabled_bool = false;\r\n /** The UDP acceleration is being actually used */\r\n this.IsUsingUdpAcceleration_bool = false;\r\n /** Session name */\r\n this.SessionName_str = \"\";\r\n /** Connection name */\r\n this.ConnectionName_str = \"\";\r\n /** Session key */\r\n this.SessionKey_bin = new Uint8Array([]);\r\n /** Total transmitted data size */\r\n this.TotalSendSize_u64 = 0;\r\n /** Total received data size */\r\n this.TotalRecvSize_u64 = 0;\r\n /** Total transmitted data size (no compression) */\r\n this.TotalSendSizeReal_u64 = 0;\r\n /** Total received data size (no compression) */\r\n this.TotalRecvSizeReal_u64 = 0;\r\n /** The flag whether the VPN session is Bridge Mode */\r\n this.IsBridgeMode_bool = false;\r\n /** The flag whether the VPN session is Monitor mode */\r\n this.IsMonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcLinkStatus;\r\n}());\r\nexports.VpnRpcLinkStatus = VpnRpcLinkStatus;\r\n/** Setting of SSTP and OpenVPN */\r\nvar VpnOpenVpnSstpConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnOpenVpnSstpConfig' class: Setting of SSTP and OpenVPN */\r\n function VpnOpenVpnSstpConfig(init) {\r\n /** Specify true to enable the OpenVPN Clone Server Function. Specify false to disable. */\r\n this.EnableOpenVPN_bool = false;\r\n /** Specify UDP ports to listen for OpenVPN. Multiple UDP ports can be specified with splitting by space or comma letters, for example: \"1194, 2001, 2010, 2012\". The default port for OpenVPN is UDP 1194. You can specify any other UDP ports. */\r\n this.OpenVPNPortList_str = \"\";\r\n /** pecify true to enable the Microsoft SSTP VPN Clone Server Function. Specify false to disable. */\r\n this.EnableSSTP_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnOpenVpnSstpConfig;\r\n}());\r\nexports.VpnOpenVpnSstpConfig = VpnOpenVpnSstpConfig;\r\n/** Virtual host option */\r\nvar VpnVhOption = /** @class */ (function () {\r\n /** Constructor for the 'VpnVhOption' class: Virtual host option */\r\n function VpnVhOption(init) {\r\n /** Target Virtual HUB name */\r\n this.RpcHubName_str = \"\";\r\n /** MAC address */\r\n this.MacAddress_bin = new Uint8Array([]);\r\n /** IP address */\r\n this.Ip_ip = \"\";\r\n /** Subnet mask */\r\n this.Mask_ip = \"\";\r\n /** Use flag of the Virtual NAT function */\r\n this.UseNat_bool = false;\r\n /** MTU value (Standard: 1500) */\r\n this.Mtu_u32 = 0;\r\n /** NAT TCP timeout in seconds */\r\n this.NatTcpTimeout_u32 = 0;\r\n /** NAT UDP timeout in seconds */\r\n this.NatUdpTimeout_u32 = 0;\r\n /** Using flag of DHCP function */\r\n this.UseDhcp_bool = false;\r\n /** Specify the start point of the address band to be distributed to the client. (Example: 192.168.30.10) */\r\n this.DhcpLeaseIPStart_ip = \"\";\r\n /** Specify the end point of the address band to be distributed to the client. (Example: 192.168.30.200) */\r\n this.DhcpLeaseIPEnd_ip = \"\";\r\n /** Specify the subnet mask to be specified for the client. (Example: 255.255.255.0) */\r\n this.DhcpSubnetMask_ip = \"\";\r\n /** Specify the expiration date in second units for leasing an IP address to a client. */\r\n this.DhcpExpireTimeSpan_u32 = 0;\r\n /** Specify the IP address of the default gateway to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify 0 or none, then the client will not be notified of the default gateway. */\r\n this.DhcpGatewayAddress_ip = \"\";\r\n /** Specify the IP address of the primary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify empty, then the client will not be notified of the DNS Server address. */\r\n this.DhcpDnsServerAddress_ip = \"\";\r\n /** Specify the IP address of the secondary DNS Server to be notified to the client. You can specify a SecureNAT Virtual Host IP address for this when the SecureNAT Function's Virtual NAT Function has been enabled and is being used also. If you specify empty, then the client will not be notified of the DNS Server address. */\r\n this.DhcpDnsServerAddress2_ip = \"\";\r\n /** Specify the domain name to be notified to the client. If you specify none, then the client will not be notified of the domain name. */\r\n this.DhcpDomainName_str = \"\";\r\n /** Specify whether or not to save the Virtual DHCP Server operation in the Virtual Hub security log. Specify true to save it. This value is interlinked with the Virtual NAT Function log save setting. */\r\n this.SaveLog_bool = false;\r\n /** The flag to enable the DhcpPushRoutes_str field. */\r\n this.ApplyDhcpPushRoutes_bool = false;\r\n /** Specify the static routing table to push. Example: \"192.168.5.0/255.255.255.0/192.168.4.254, 10.0.0.0/255.0.0.0/192.168.4.253\" Split multiple entries (maximum: 64 entries) by comma or space characters. Each entry must be specified in the \"IP network address/subnet mask/gateway IP address\" format. This Virtual DHCP Server can push the classless static routes (RFC 3442) with DHCP reply messages to VPN clients. Whether or not a VPN client can recognize the classless static routes (RFC 3442) depends on the target VPN client software. SoftEther VPN Client and OpenVPN Client are supporting the classless static routes. On L2TP/IPsec and MS-SSTP protocols, the compatibility depends on the implementation of the client software. You can realize the split tunneling if you clear the default gateway field on the Virtual DHCP Server options. On the client side, L2TP/IPsec and MS-SSTP clients need to be configured not to set up the default gateway for the split tunneling usage. You can also push the classless static routes (RFC 3442) by your existing external DHCP server. In that case, disable the Virtual DHCP Server function on SecureNAT, and you need not to set up the classless routes on this API. See the RFC 3442 to understand the classless routes. */\r\n this.DhcpPushRoutes_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnVhOption;\r\n}());\r\nexports.VpnVhOption = VpnVhOption;\r\n/** RPC_NAT_STATUS */\r\nvar VpnRpcNatStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcNatStatus' class: RPC_NAT_STATUS */\r\n function VpnRpcNatStatus(init) {\r\n /** Virtual Hub Name */\r\n this.HubName_str = \"\";\r\n /** Number of TCP sessions */\r\n this.NumTcpSessions_u32 = 0;\r\n /** Ntmber of UDP sessions */\r\n this.NumUdpSessions_u32 = 0;\r\n /** Nymber of ICMP sessions */\r\n this.NumIcmpSessions_u32 = 0;\r\n /** Number of DNS sessions */\r\n this.NumDnsSessions_u32 = 0;\r\n /** Number of DHCP clients */\r\n this.NumDhcpClients_u32 = 0;\r\n /** Whether the NAT is operating in the Kernel Mode */\r\n this.IsKernelMode_bool = false;\r\n /** Whether the NAT is operating in the Raw IP Mode */\r\n this.IsRawIpMode_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcNatStatus;\r\n}());\r\nexports.VpnRpcNatStatus = VpnRpcNatStatus;\r\n/** Key pair */\r\nvar VpnRpcKeyPair = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcKeyPair' class: Key pair */\r\n function VpnRpcKeyPair(init) {\r\n /** The body of the certificate */\r\n this.Cert_bin = new Uint8Array([]);\r\n /** The body of the private key */\r\n this.Key_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcKeyPair;\r\n}());\r\nexports.VpnRpcKeyPair = VpnRpcKeyPair;\r\n/** Single string value */\r\nvar VpnRpcStr = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcStr' class: Single string value */\r\n function VpnRpcStr(init) {\r\n /** A string value */\r\n this.String_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcStr;\r\n}());\r\nexports.VpnRpcStr = VpnRpcStr;\r\n/** Type of VPN Server */\r\nvar VpnRpcServerType;\r\n(function (VpnRpcServerType) {\r\n /** Stand-alone server */\r\n VpnRpcServerType[VpnRpcServerType[\"Standalone\"] = 0] = \"Standalone\";\r\n /** Farm controller server */\r\n VpnRpcServerType[VpnRpcServerType[\"FarmController\"] = 1] = \"FarmController\";\r\n /** Farm member server */\r\n VpnRpcServerType[VpnRpcServerType[\"FarmMember\"] = 2] = \"FarmMember\";\r\n})(VpnRpcServerType = exports.VpnRpcServerType || (exports.VpnRpcServerType = {}));\r\n/** Operating system type */\r\nvar VpnRpcOsType;\r\n(function (VpnRpcOsType) {\r\n /** Windows 95 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_95\"] = 1100] = \"WINDOWS_95\";\r\n /** Windows 98 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_98\"] = 1200] = \"WINDOWS_98\";\r\n /** Windows Me */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_ME\"] = 1300] = \"WINDOWS_ME\";\r\n /** Windows (unknown) */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_UNKNOWN\"] = 1400] = \"WINDOWS_UNKNOWN\";\r\n /** Windows NT 4.0 Workstation */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_WORKSTATION\"] = 2100] = \"WINDOWS_NT_4_WORKSTATION\";\r\n /** Windows NT 4.0 Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SERVER\"] = 2110] = \"WINDOWS_NT_4_SERVER\";\r\n /** Windows NT 4.0 Server, Enterprise Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SERVER_ENTERPRISE\"] = 2111] = \"WINDOWS_NT_4_SERVER_ENTERPRISE\";\r\n /** Windows NT 4.0 Terminal Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_TERMINAL_SERVER\"] = 2112] = \"WINDOWS_NT_4_TERMINAL_SERVER\";\r\n /** BackOffice Server 4.5 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_BACKOFFICE\"] = 2113] = \"WINDOWS_NT_4_BACKOFFICE\";\r\n /** Small Business Server 4.5 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_NT_4_SMS\"] = 2114] = \"WINDOWS_NT_4_SMS\";\r\n /** Windows 2000 Professional */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_PROFESSIONAL\"] = 2200] = \"WINDOWS_2000_PROFESSIONAL\";\r\n /** Windows 2000 Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_SERVER\"] = 2211] = \"WINDOWS_2000_SERVER\";\r\n /** Windows 2000 Advanced Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_ADVANCED_SERVER\"] = 2212] = \"WINDOWS_2000_ADVANCED_SERVER\";\r\n /** Windows 2000 Datacenter Server */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_DATACENTER_SERVER\"] = 2213] = \"WINDOWS_2000_DATACENTER_SERVER\";\r\n /** BackOffice Server 2000 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_BACKOFFICE\"] = 2214] = \"WINDOWS_2000_BACKOFFICE\";\r\n /** Small Business Server 2000 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2000_SBS\"] = 2215] = \"WINDOWS_2000_SBS\";\r\n /** Windows XP Home Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_XP_HOME\"] = 2300] = \"WINDOWS_XP_HOME\";\r\n /** Windows XP Professional */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_XP_PROFESSIONAL\"] = 2301] = \"WINDOWS_XP_PROFESSIONAL\";\r\n /** Windows Server 2003 Web Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_WEB\"] = 2410] = \"WINDOWS_2003_WEB\";\r\n /** Windows Server 2003 Standard Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_STANDARD\"] = 2411] = \"WINDOWS_2003_STANDARD\";\r\n /** Windows Server 2003 Enterprise Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_ENTERPRISE\"] = 2412] = \"WINDOWS_2003_ENTERPRISE\";\r\n /** Windows Server 2003 DataCenter Edition */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_DATACENTER\"] = 2413] = \"WINDOWS_2003_DATACENTER\";\r\n /** BackOffice Server 2003 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_BACKOFFICE\"] = 2414] = \"WINDOWS_2003_BACKOFFICE\";\r\n /** Small Business Server 2003 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_2003_SBS\"] = 2415] = \"WINDOWS_2003_SBS\";\r\n /** Windows Vista */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_LONGHORN_PROFESSIONAL\"] = 2500] = \"WINDOWS_LONGHORN_PROFESSIONAL\";\r\n /** Windows Server 2008 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_LONGHORN_SERVER\"] = 2510] = \"WINDOWS_LONGHORN_SERVER\";\r\n /** Windows 7 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_7\"] = 2600] = \"WINDOWS_7\";\r\n /** Windows Server 2008 R2 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_2008_R2\"] = 2610] = \"WINDOWS_SERVER_2008_R2\";\r\n /** Windows 8 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_8\"] = 2700] = \"WINDOWS_8\";\r\n /** Windows Server 2012 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_8\"] = 2710] = \"WINDOWS_SERVER_8\";\r\n /** Windows 8.1 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_81\"] = 2701] = \"WINDOWS_81\";\r\n /** Windows Server 2012 R2 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_81\"] = 2711] = \"WINDOWS_SERVER_81\";\r\n /** Windows 10 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_10\"] = 2702] = \"WINDOWS_10\";\r\n /** Windows Server 10 */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_10\"] = 2712] = \"WINDOWS_SERVER_10\";\r\n /** Windows 11 or later */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_11\"] = 2800] = \"WINDOWS_11\";\r\n /** Windows Server 11 or later */\r\n VpnRpcOsType[VpnRpcOsType[\"WINDOWS_SERVER_11\"] = 2810] = \"WINDOWS_SERVER_11\";\r\n /** Unknown UNIX */\r\n VpnRpcOsType[VpnRpcOsType[\"UNIX_UNKNOWN\"] = 3000] = \"UNIX_UNKNOWN\";\r\n /** Linux */\r\n VpnRpcOsType[VpnRpcOsType[\"LINUX\"] = 3100] = \"LINUX\";\r\n /** Solaris */\r\n VpnRpcOsType[VpnRpcOsType[\"SOLARIS\"] = 3200] = \"SOLARIS\";\r\n /** Cygwin */\r\n VpnRpcOsType[VpnRpcOsType[\"CYGWIN\"] = 3300] = \"CYGWIN\";\r\n /** BSD */\r\n VpnRpcOsType[VpnRpcOsType[\"BSD\"] = 3400] = \"BSD\";\r\n /** MacOS X */\r\n VpnRpcOsType[VpnRpcOsType[\"MACOS_X\"] = 3500] = \"MACOS_X\";\r\n})(VpnRpcOsType = exports.VpnRpcOsType || (exports.VpnRpcOsType = {}));\r\n/** VPN Server Information */\r\nvar VpnRpcServerInfo = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcServerInfo' class: VPN Server Information */\r\n function VpnRpcServerInfo(init) {\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server version string */\r\n this.ServerVersionString_str = \"\";\r\n /** Server build information string */\r\n this.ServerBuildInfoString_str = \"\";\r\n /** Server version integer value */\r\n this.ServerVerInt_u32 = 0;\r\n /** Server build number integer value */\r\n this.ServerBuildInt_u32 = 0;\r\n /** Server host name */\r\n this.ServerHostName_str = \"\";\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Build date and time of the server */\r\n this.ServerBuildDate_dt = new Date();\r\n /** Family name */\r\n this.ServerFamilyName_str = \"\";\r\n /** OS type */\r\n this.OsType_u32 = 0;\r\n /** Service pack number */\r\n this.OsServicePack_u32 = 0;\r\n /** OS system name */\r\n this.OsSystemName_str = \"\";\r\n /** OS product name */\r\n this.OsProductName_str = \"\";\r\n /** OS vendor name */\r\n this.OsVendorName_str = \"\";\r\n /** OS version */\r\n this.OsVersion_str = \"\";\r\n /** Kernel name */\r\n this.KernelName_str = \"\";\r\n /** Kernel version */\r\n this.KernelVersion_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcServerInfo;\r\n}());\r\nexports.VpnRpcServerInfo = VpnRpcServerInfo;\r\n/** Server status */\r\nvar VpnRpcServerStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcServerStatus' class: Server status */\r\n function VpnRpcServerStatus(init) {\r\n /** Type of server */\r\n this.ServerType_u32 = 0;\r\n /** Total number of TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of Local TCP connections */\r\n this.NumTcpConnectionsLocal_u32 = 0;\r\n /** Number of remote TCP connections */\r\n this.NumTcpConnectionsRemote_u32 = 0;\r\n /** Total number of HUBs */\r\n this.NumHubTotal_u32 = 0;\r\n /** Nymber of stand-alone HUB */\r\n this.NumHubStandalone_u32 = 0;\r\n /** Number of static HUBs */\r\n this.NumHubStatic_u32 = 0;\r\n /** Number of Dynamic HUBs */\r\n this.NumHubDynamic_u32 = 0;\r\n /** Total number of sessions */\r\n this.NumSessionsTotal_u32 = 0;\r\n /** Number of local VPN sessions */\r\n this.NumSessionsLocal_u32 = 0;\r\n /** The number of remote sessions */\r\n this.NumSessionsRemote_u32 = 0;\r\n /** Number of MAC table entries (total sum of all Virtual Hubs) */\r\n this.NumMacTables_u32 = 0;\r\n /** Number of IP table entries (total sum of all Virtual Hubs) */\r\n this.NumIpTables_u32 = 0;\r\n /** Number of users (total sum of all Virtual Hubs) */\r\n this.NumUsers_u32 = 0;\r\n /** Number of groups (total sum of all Virtual Hubs) */\r\n this.NumGroups_u32 = 0;\r\n /** Number of assigned bridge licenses (Useful to make a commercial version) */\r\n this.AssignedBridgeLicenses_u32 = 0;\r\n /** Number of assigned client licenses (Useful to make a commercial version) */\r\n this.AssignedClientLicenses_u32 = 0;\r\n /** Number of Assigned bridge license (cluster-wide), useful to make a commercial version */\r\n this.AssignedBridgeLicensesTotal_u32 = 0;\r\n /** Number of assigned client licenses (cluster-wide), useful to make a commercial version */\r\n this.AssignedClientLicensesTotal_u32 = 0;\r\n /** Number of broadcast packets (Recv) */\r\n this[\"Recv.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Recv) */\r\n this[\"Recv.BroadcastCount_u64\"] = 0;\r\n /** Unicast count (Recv) */\r\n this[\"Recv.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Recv) */\r\n this[\"Recv.UnicastCount_u64\"] = 0;\r\n /** Number of broadcast packets (Send) */\r\n this[\"Send.BroadcastBytes_u64\"] = 0;\r\n /** Broadcast bytes (Send) */\r\n this[\"Send.BroadcastCount_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastBytes_u64\"] = 0;\r\n /** Unicast bytes (Send) */\r\n this[\"Send.UnicastCount_u64\"] = 0;\r\n /** Current time */\r\n this.CurrentTime_dt = new Date();\r\n /** 64 bit High-Precision Logical System Clock */\r\n this.CurrentTick_u64 = 0;\r\n /** VPN Server Start-up time */\r\n this.StartTime_dt = new Date();\r\n /** Memory information: Total Memory */\r\n this.TotalMemory_u64 = 0;\r\n /** Memory information: Used Memory */\r\n this.UsedMemory_u64 = 0;\r\n /** Memory information: Free Memory */\r\n this.FreeMemory_u64 = 0;\r\n /** Memory information: Total Phys */\r\n this.TotalPhys_u64 = 0;\r\n /** Memory information: Used Phys */\r\n this.UsedPhys_u64 = 0;\r\n /** Memory information: Free Phys */\r\n this.FreePhys_u64 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcServerStatus;\r\n}());\r\nexports.VpnRpcServerStatus = VpnRpcServerStatus;\r\n/** VPN Session status */\r\nvar VpnRpcSessionStatus = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSessionStatus' class: VPN Session status */\r\n function VpnRpcSessionStatus(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** VPN session name */\r\n this.Name_str = \"\";\r\n /** User name */\r\n this.Username_str = \"\";\r\n /** Real user name which was used for the authentication */\r\n this.RealUsername_str = \"\";\r\n /** Group name */\r\n this.GroupName_str = \"\";\r\n /** Is Cascade Session */\r\n this.LinkMode_bool = false;\r\n /** Client IP address */\r\n this.Client_Ip_Address_ip = \"\";\r\n /** Client host name */\r\n this.SessionStatus_ClientHostName_str = \"\";\r\n /** Operation flag */\r\n this.Active_bool = false;\r\n /** Connected flag */\r\n this.Connected_bool = false;\r\n /** State of the client session */\r\n this.SessionStatus_u32 = 0;\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** Port number of the server */\r\n this.ServerPort_u32 = 0;\r\n /** Server product name */\r\n this.ServerProductName_str = \"\";\r\n /** Server product version */\r\n this.ServerProductVer_u32 = 0;\r\n /** Server product build number */\r\n this.ServerProductBuild_u32 = 0;\r\n /** Connection start time */\r\n this.StartTime_dt = new Date();\r\n /** Connection completion time of the first connection */\r\n this.FirstConnectionEstablisiedTime_dt = new Date();\r\n /** Connection completion time of this connection */\r\n this.CurrentConnectionEstablishTime_dt = new Date();\r\n /** Number of connections have been established so far */\r\n this.NumConnectionsEatablished_u32 = 0;\r\n /** Half-connection */\r\n this.HalfConnection_bool = false;\r\n /** VoIP / QoS */\r\n this.QoS_bool = false;\r\n /** Maximum number of the underlying TCP connections */\r\n this.MaxTcpConnections_u32 = 0;\r\n /** Number of current underlying TCP connections */\r\n this.NumTcpConnections_u32 = 0;\r\n /** Number of inbound underlying connections */\r\n this.NumTcpConnectionsUpload_u32 = 0;\r\n /** Number of outbound underlying connections */\r\n this.NumTcpConnectionsDownload_u32 = 0;\r\n /** Use of encryption */\r\n this.UseEncrypt_bool = false;\r\n /** Cipher algorithm name */\r\n this.CipherName_str = \"\";\r\n /** Use of compression */\r\n this.UseCompress_bool = false;\r\n /** Is R-UDP session */\r\n this.IsRUDPSession_bool = false;\r\n /** Physical underlying communication protocol */\r\n this.UnderlayProtocol_str = \"\";\r\n /** The UDP acceleration is enabled */\r\n this.IsUdpAccelerationEnabled_bool = false;\r\n /** Using the UDP acceleration function */\r\n this.IsUsingUdpAcceleration_bool = false;\r\n /** VPN session name */\r\n this.SessionName_str = \"\";\r\n /** Connection name */\r\n this.ConnectionName_str = \"\";\r\n /** Session key */\r\n this.SessionKey_bin = new Uint8Array([]);\r\n /** Total transmitted data size */\r\n this.TotalSendSize_u64 = 0;\r\n /** Total received data size */\r\n this.TotalRecvSize_u64 = 0;\r\n /** Total transmitted data size (no compression) */\r\n this.TotalSendSizeReal_u64 = 0;\r\n /** Total received data size (no compression) */\r\n this.TotalRecvSizeReal_u64 = 0;\r\n /** Is Bridge Mode */\r\n this.IsBridgeMode_bool = false;\r\n /** Is Monitor mode */\r\n this.IsMonitorMode_bool = false;\r\n /** VLAN ID */\r\n this.VLanId_u32 = 0;\r\n /** Client product name */\r\n this.ClientProductName_str = \"\";\r\n /** Client version */\r\n this.ClientProductVer_u32 = 0;\r\n /** Client build number */\r\n this.ClientProductBuild_u32 = 0;\r\n /** Client OS name */\r\n this.ClientOsName_str = \"\";\r\n /** Client OS version */\r\n this.ClientOsVer_str = \"\";\r\n /** Client OS Product ID */\r\n this.ClientOsProductId_str = \"\";\r\n /** Client host name */\r\n this.ClientHostname_str = \"\";\r\n /** Unique ID */\r\n this.UniqueId_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSessionStatus;\r\n}());\r\nexports.VpnRpcSessionStatus = VpnRpcSessionStatus;\r\n/** Set the special listener */\r\nvar VpnRpcSpecialListener = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSpecialListener' class: Set the special listener */\r\n function VpnRpcSpecialListener(init) {\r\n /** The flag to activate the VPN over ICMP server function */\r\n this.VpnOverIcmpListener_bool = false;\r\n /** The flag to activate the VPN over DNS function */\r\n this.VpnOverDnsListener_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSpecialListener;\r\n}());\r\nexports.VpnRpcSpecialListener = VpnRpcSpecialListener;\r\n/** Syslog configuration */\r\nvar VpnSyslogSaveType;\r\n(function (VpnSyslogSaveType) {\r\n /** Do not use syslog */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"None\"] = 0] = \"None\";\r\n /** Only server log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerLog\"] = 1] = \"ServerLog\";\r\n /** Server and Virtual HUB security log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerAndHubSecurityLog\"] = 2] = \"ServerAndHubSecurityLog\";\r\n /** Server, Virtual HUB security, and packet log */\r\n VpnSyslogSaveType[VpnSyslogSaveType[\"ServerAndHubAllLog\"] = 3] = \"ServerAndHubAllLog\";\r\n})(VpnSyslogSaveType = exports.VpnSyslogSaveType || (exports.VpnSyslogSaveType = {}));\r\n/** Syslog configuration */\r\nvar VpnSyslogSetting = /** @class */ (function () {\r\n /** Constructor for the 'VpnSyslogSetting' class: Syslog configuration */\r\n function VpnSyslogSetting(init) {\r\n /** The behavior of the syslog function */\r\n this.SaveType_u32 = 0;\r\n /** Specify the host name or IP address of the syslog server */\r\n this.Hostname_str = \"\";\r\n /** Specify the port number of the syslog server */\r\n this.Port_u32 = 0;\r\n Object.assign(this, init);\r\n }\r\n return VpnSyslogSetting;\r\n}());\r\nexports.VpnSyslogSetting = VpnSyslogSetting;\r\n/** VPN Gate Server Config */\r\nvar VpnVgsConfig = /** @class */ (function () {\r\n /** Constructor for the 'VpnVgsConfig' class: VPN Gate Server Config */\r\n function VpnVgsConfig(init) {\r\n /** Active flag */\r\n this.IsEnabled_bool = false;\r\n /** Message */\r\n this.Message_utf = \"\";\r\n /** Owner name */\r\n this.Owner_utf = \"\";\r\n /** Abuse email */\r\n this.Abuse_utf = \"\";\r\n /** Log save flag */\r\n this.NoLog_bool = false;\r\n /** Save log permanently */\r\n this.LogPermanent_bool = false;\r\n /** Enable the L2TP VPN function */\r\n this.EnableL2TP_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnVgsConfig;\r\n}());\r\nexports.VpnVgsConfig = VpnVgsConfig;\r\n/** Read a Log file */\r\nvar VpnRpcReadLogFile = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcReadLogFile' class: Read a Log file */\r\n function VpnRpcReadLogFile(init) {\r\n /** Server name */\r\n this.ServerName_str = \"\";\r\n /** File Path */\r\n this.FilePath_str = \"\";\r\n /** Offset to download. You have to call the ReadLogFile API multiple times to download the entire log file with requesting a part of the file by specifying the Offset_u32 field. */\r\n this.Offset_u32 = 0;\r\n /** Received buffer */\r\n this.Buffer_bin = new Uint8Array([]);\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcReadLogFile;\r\n}());\r\nexports.VpnRpcReadLogFile = VpnRpcReadLogFile;\r\n/** Rename link */\r\nvar VpnRpcRenameLink = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcRenameLink' class: Rename link */\r\n function VpnRpcRenameLink(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** The old name of the cascade connection */\r\n this.OldAccountName_utf = \"\";\r\n /** The new name of the cascade connection */\r\n this.NewAccountName_utf = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcRenameLink;\r\n}());\r\nexports.VpnRpcRenameLink = VpnRpcRenameLink;\r\n/** Online or offline the HUB */\r\nvar VpnRpcSetHubOnline = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetHubOnline' class: Online or offline the HUB */\r\n function VpnRpcSetHubOnline(init) {\r\n /** The Virtual Hub name */\r\n this.HubName_str = \"\";\r\n /** Online / offline flag */\r\n this.Online_bool = false;\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetHubOnline;\r\n}());\r\nexports.VpnRpcSetHubOnline = VpnRpcSetHubOnline;\r\n/** Set Password */\r\nvar VpnRpcSetPassword = /** @class */ (function () {\r\n /** Constructor for the 'VpnRpcSetPassword' class: Set Password */\r\n function VpnRpcSetPassword(init) {\r\n /** The plaintext password */\r\n this.PlainTextPassword_str = \"\";\r\n Object.assign(this, init);\r\n }\r\n return VpnRpcSetPassword;\r\n}());\r\nexports.VpnRpcSetPassword = VpnRpcSetPassword;\r\n// --- Utility codes ---\r\n/** JSON-RPC request class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcRequest = /** @class */ (function () {\r\n function JsonRpcRequest(method, param, id) {\r\n if (method === void 0) { method = \"\"; }\r\n if (param === void 0) { param = null; }\r\n if (id === void 0) { id = \"\"; }\r\n this.jsonrpc = \"2.0\";\r\n this.method = method;\r\n this.params = param;\r\n this.id = id;\r\n }\r\n return JsonRpcRequest;\r\n}());\r\nexports.JsonRpcRequest = JsonRpcRequest;\r\n/** JSON-RPC error class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcError = /** @class */ (function () {\r\n function JsonRpcError(code, message, data) {\r\n if (code === void 0) { code = 0; }\r\n if (message === void 0) { message = \"\"; }\r\n if (data === void 0) { data = null; }\r\n this.code = code;\r\n this.message = message;\r\n this.data = data;\r\n }\r\n return JsonRpcError;\r\n}());\r\nexports.JsonRpcError = JsonRpcError;\r\n/** JSON-RPC response class with generics */\r\nvar JsonRpcResponse = /** @class */ (function () {\r\n function JsonRpcResponse() {\r\n this.jsonrpc = \"2.0\";\r\n this.result = null;\r\n this.error = null;\r\n this.id = \"\";\r\n }\r\n return JsonRpcResponse;\r\n}());\r\nexports.JsonRpcResponse = JsonRpcResponse;\r\n/** JSON-RPC client class. See https://www.jsonrpc.org/specification */\r\nvar JsonRpcClient = /** @class */ (function () {\r\n /**\r\n * JSON-RPC client class constructor\r\n * @param url The URL\r\n * @param headers Additional HTTP headers\r\n * @param send_credential Set true to use the same credential with the browsing web site. Valid only if the code is running on the web browser.\r\n */\r\n function JsonRpcClient(url, headers, send_credential, nodejs_https_client_reject_untrusted_server_cert) {\r\n this.BaseUrl = url;\r\n this.headers = headers;\r\n this.client = new HttpClient();\r\n this.client.SendCredential = send_credential;\r\n this.client.NodeJS_HTTPS_Client_Reject_Unauthorized = nodejs_https_client_reject_untrusted_server_cert;\r\n }\r\n /** A utility function to convert any object to JSON string */\r\n JsonRpcClient.ObjectToJson = function (obj) {\r\n return JSON.stringify(obj, function (key, value) {\r\n if (key.endsWith(\"_bin\")) {\r\n return Util_Base64_Encode(value);\r\n }\r\n return value;\r\n }, 4);\r\n };\r\n /** A utility function to convert JSON string to object */\r\n JsonRpcClient.JsonToObject = function (str) {\r\n return JSON.parse(str, function (key, value) {\r\n if (key.endsWith(\"_bin\")) {\r\n return Util_Base64_Decode(value);\r\n }\r\n else if (key.endsWith(\"_dt\")) {\r\n return new Date(value);\r\n }\r\n return value;\r\n });\r\n };\r\n /**\r\n * Call a single RPC call (without error check). You can wait for the response with Promise or await statement.\r\n * @param method_name The name of RPC method\r\n * @param param The parameters\r\n */\r\n JsonRpcClient.prototype.CallInternalAsync = function (method_name, param) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var id, req, req_string, http_response, ret_string;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n id = \"1\";\r\n req = new JsonRpcRequest(method_name, param, id);\r\n req_string = JsonRpcClient.ObjectToJson(req);\r\n if (debug_mode) {\r\n console.log(\"--- RPC Request Body ---\");\r\n console.log(req_string);\r\n console.log(\"------------------------\");\r\n }\r\n return [4 /*yield*/, this.client.PostAsync(this.BaseUrl, this.headers, req_string, \"application/json\")];\r\n case 1:\r\n http_response = _a.sent();\r\n ret_string = http_response.Body;\r\n if (debug_mode) {\r\n console.log(\"--- RPC Response Body ---\");\r\n console.log(ret_string);\r\n console.log(\"-------------------------\");\r\n }\r\n return [2 /*return*/, ret_string];\r\n }\r\n });\r\n });\r\n };\r\n /**\r\n * Call a single RPC call (with error check). You can wait for the response with Promise or await statement. In the case of error, it will be thrown.\r\n * @param method_name The name of RPC method\r\n * @param param The parameters\r\n */\r\n JsonRpcClient.prototype.CallAsync = function (method_name, param) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var ret_string, ret;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0: return [4 /*yield*/, this.CallInternalAsync(method_name, param)];\r\n case 1:\r\n ret_string = _a.sent();\r\n ret = JSON.parse(ret_string);\r\n if (is_null(ret.error) === false) {\r\n throw new JsonRpcException(ret.error);\r\n }\r\n return [2 /*return*/, ret.result];\r\n }\r\n });\r\n });\r\n };\r\n return JsonRpcClient;\r\n}());\r\nexports.JsonRpcClient = JsonRpcClient;\r\n/** JSON-RPC exception class */\r\nvar JsonRpcException = /** @class */ (function (_super) {\r\n __extends(JsonRpcException, _super);\r\n function JsonRpcException(error) {\r\n var _this = _super.call(this, \"Code=\" + error.code + \", Message=\" + error.message) || this;\r\n _this.Error = error;\r\n return _this;\r\n }\r\n return JsonRpcException;\r\n}(Error));\r\nexports.JsonRpcException = JsonRpcException;\r\n/** HTTP client exception class */\r\nvar HttpClientException = /** @class */ (function (_super) {\r\n __extends(HttpClientException, _super);\r\n function HttpClientException(message) {\r\n return _super.call(this, message) || this;\r\n }\r\n return HttpClientException;\r\n}(Error));\r\nexports.HttpClientException = HttpClientException;\r\n/** HTTP client response class */\r\nvar HttpClientResponse = /** @class */ (function () {\r\n function HttpClientResponse() {\r\n this.Body = \"\";\r\n }\r\n return HttpClientResponse;\r\n}());\r\nexports.HttpClientResponse = HttpClientResponse;\r\n/** An HTTP client which can be used in both web browsers and Node.js */\r\nvar HttpClient = /** @class */ (function () {\r\n function HttpClient() {\r\n this.TimeoutMsecs = 60 * 5 * 1000;\r\n this.SendCredential = true;\r\n this.NodeJS_HTTPS_Client_Reject_Unauthorized = false;\r\n }\r\n /** Post method. In web browsers this function will process the request by itself. In Node.js this function will call PostAsync_NodeJS() instead. */\r\n HttpClient.prototype.PostAsync = function (url, headers, req_body, req_media_type) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var fetch_header_list, _i, _a, name_1, fetch_init, fetch_response, ret, _b;\r\n return __generator(this, function (_c) {\r\n switch (_c.label) {\r\n case 0:\r\n if (is_node_js) {\r\n return [2 /*return*/, this.PostAsync_NodeJS(url, headers, req_body, req_media_type)];\r\n }\r\n fetch_header_list = new Headers();\r\n for (_i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {\r\n name_1 = _a[_i];\r\n fetch_header_list.append(name_1, headers[name_1]);\r\n }\r\n fetch_init = {\r\n mode: \"cors\",\r\n headers: fetch_header_list,\r\n credentials: (this.SendCredential ? \"include\" : \"omit\"),\r\n method: \"POST\",\r\n cache: \"no-cache\",\r\n keepalive: true,\r\n redirect: \"follow\",\r\n body: req_body\r\n };\r\n return [4 /*yield*/, fetch(url, fetch_init)];\r\n case 1:\r\n fetch_response = _c.sent();\r\n if (fetch_response.ok === false) {\r\n throw new HttpClientException(\"HTTP Error: \" + fetch_response.status + \" \" + fetch_response.statusText);\r\n }\r\n ret = new HttpClientResponse();\r\n _b = ret;\r\n return [4 /*yield*/, fetch_response.text()];\r\n case 2:\r\n _b.Body = _c.sent();\r\n return [2 /*return*/, ret];\r\n }\r\n });\r\n });\r\n };\r\n /** Post method for Node.js. */\r\n HttpClient.prototype.PostAsync_NodeJS = function (url, headers, req_body, req_media_type) {\r\n var https = __webpack_require__(/*! https */ \"./node_modules/https-browserify/index.js\");\r\n var keepAliveAgent = new https.Agent({ keepAlive: true });\r\n var urlparse = __webpack_require__(/*! url */ \"./node_modules/url/url.js\");\r\n var urlobj = urlparse.parse(url);\r\n if (is_null(urlobj.host))\r\n throw new Error(\"URL is invalid.\");\r\n var options = {\r\n host: urlobj.hostname,\r\n port: urlobj.port,\r\n path: urlobj.path,\r\n rejectUnauthorized: this.NodeJS_HTTPS_Client_Reject_Unauthorized,\r\n method: \"POST\",\r\n timeout: this.TimeoutMsecs,\r\n agent: keepAliveAgent\r\n };\r\n return new Promise(function (resolve, reject) {\r\n var req = https.request(options, function (res) {\r\n if (res.statusCode !== 200) {\r\n reject(new HttpClientException(\"HTTP Error: \" + res.statusCode + \" \" + res.statusMessage));\r\n }\r\n var recv_str = \"\";\r\n res.on(\"data\", function (body) {\r\n recv_str += body;\r\n });\r\n res.on(\"end\", function () {\r\n var ret = new HttpClientResponse();\r\n ret.Body = recv_str;\r\n resolve(ret);\r\n });\r\n }).on(\"error\", function (err) {\r\n throw err;\r\n });\r\n for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {\r\n var name_2 = _a[_i];\r\n req.setHeader(name_2, !is_null(headers[name_2]) ? headers[name_2] : \"\");\r\n }\r\n req.setHeader(\"Content-Type\", req_media_type);\r\n req.setHeader(\"Content-Length\", Buffer.byteLength(req_body));\r\n req.write(req_body);\r\n req.end();\r\n });\r\n };\r\n return HttpClient;\r\n}());\r\nexports.HttpClient = HttpClient;\r\n//////// BEGIN: Base64 encode / decode utility functions from https://github.com/beatgammit/base64-js\r\n// The MIT License(MIT)\r\n// Copyright(c) 2014\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy\r\n// of this software and associated documentation files(the \"Software\"), to deal\r\n// in the Software without restriction, including without limitation the rights\r\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is\r\n// furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in\r\n// all copies or substantial portions of the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n// THE SOFTWARE.\r\nvar lookup = [];\r\nvar revLookup = [];\r\nvar code = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\r\nfor (var i = 0, len = code.length; i < len; ++i) {\r\n lookup[i] = code[i];\r\n revLookup[code.charCodeAt(i)] = i;\r\n}\r\n// Support decoding URL-safe base64 strings, as Node.js does.\r\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\r\nrevLookup[\"-\".charCodeAt(0)] = 62;\r\nrevLookup[\"_\".charCodeAt(0)] = 63;\r\nfunction getLens(b64) {\r\n var len = b64.length;\r\n if (len % 4 > 0) {\r\n throw new Error(\"Invalid string. Length must be a multiple of 4\");\r\n }\r\n // Trim off extra bytes after placeholder bytes are found\r\n // See: https://github.com/beatgammit/base64-js/issues/42\r\n var validLen = b64.indexOf(\"=\");\r\n if (validLen === -1)\r\n validLen = len;\r\n var placeHoldersLen = validLen === len\r\n ? 0\r\n : 4 - (validLen % 4);\r\n return [validLen, placeHoldersLen];\r\n}\r\n// base64 is 4/3 + up to two characters of the original data\r\nfunction byteLength(b64) {\r\n var lens = getLens(b64);\r\n var validLen = lens[0];\r\n var placeHoldersLen = lens[1];\r\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;\r\n}\r\nfunction _byteLength(b64, validLen, placeHoldersLen) {\r\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;\r\n}\r\nfunction Util_Base64_Decode(b64) {\r\n var tmp;\r\n var lens = getLens(b64);\r\n var validLen = lens[0];\r\n var placeHoldersLen = lens[1];\r\n var arr = new Uint8Array(_byteLength(b64, validLen, placeHoldersLen));\r\n var curByte = 0;\r\n // if there are placeholders, only get up to the last complete 4 chars\r\n var len = placeHoldersLen > 0\r\n ? validLen - 4\r\n : validLen;\r\n for (var i = 0; i < len; i += 4) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 18) |\r\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\r\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\r\n revLookup[b64.charCodeAt(i + 3)];\r\n arr[curByte++] = (tmp >> 16) & 0xFF;\r\n arr[curByte++] = (tmp >> 8) & 0xFF;\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n if (placeHoldersLen === 2) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 2) |\r\n (revLookup[b64.charCodeAt(i + 1)] >> 4);\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n if (placeHoldersLen === 1) {\r\n tmp =\r\n (revLookup[b64.charCodeAt(i)] << 10) |\r\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\r\n (revLookup[b64.charCodeAt(i + 2)] >> 2);\r\n arr[curByte++] = (tmp >> 8) & 0xFF;\r\n arr[curByte++] = tmp & 0xFF;\r\n }\r\n return arr;\r\n}\r\nexports.Util_Base64_Decode = Util_Base64_Decode;\r\nfunction tripletToBase64(num) {\r\n return lookup[num >> 18 & 0x3F] +\r\n lookup[num >> 12 & 0x3F] +\r\n lookup[num >> 6 & 0x3F] +\r\n lookup[num & 0x3F];\r\n}\r\nfunction encodeChunk(uint8, start, end) {\r\n var tmp;\r\n var output = [];\r\n for (var i = start; i < end; i += 3) {\r\n tmp =\r\n ((uint8[i] << 16) & 0xFF0000) +\r\n ((uint8[i + 1] << 8) & 0xFF00) +\r\n (uint8[i + 2] & 0xFF);\r\n output.push(tripletToBase64(tmp));\r\n }\r\n return output.join(\"\");\r\n}\r\nfunction Util_Base64_Encode(uint8) {\r\n var tmp;\r\n var len = uint8.length;\r\n var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes\r\n var parts = [];\r\n var maxChunkLength = 16383; // must be multiple of 3\r\n // go through the array every three bytes, we'll deal with trailing stuff later\r\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\r\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)));\r\n }\r\n // pad the end with zeros, but make sure to not forget the extra bytes\r\n if (extraBytes === 1) {\r\n tmp = uint8[len - 1];\r\n parts.push(lookup[tmp >> 2] +\r\n lookup[(tmp << 4) & 0x3F] +\r\n \"==\");\r\n }\r\n else if (extraBytes === 2) {\r\n tmp = (uint8[len - 2] << 8) + uint8[len - 1];\r\n parts.push(lookup[tmp >> 10] +\r\n lookup[(tmp >> 4) & 0x3F] +\r\n lookup[(tmp << 2) & 0x3F] +\r\n \"=\");\r\n }\r\n return parts.join(\"\");\r\n}\r\nexports.Util_Base64_Encode = Util_Base64_Encode;\r\n//////// END: Base64 encode / decode utility functions from https://github.com/beatgammit/base64-js\r\n//# sourceMappingURL=vpnrpc.js.map\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../buffer/index.js */ \"./node_modules/buffer/index.js\").Buffer))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvdnBucnBjL2Rpc3QvdnBucnBjLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vSlMvLi9ub2RlX21vZHVsZXMvdnBucnBjL2Rpc3QvdnBucnBjLmpzPzQ2ZWYiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XHJcbi8vIFNvZnRFdGhlciBWUE4gU2VydmVyIEpTT04tUlBDIFN0dWIgY29kZSBmb3IgVHlwZVNjcmlwdFxyXG4vLyBcclxuLy8gdnBucnBjLnRzXHJcbi8vIEF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGF0IDIwMTktMDUtMjkgMTg6MjE6MzkgYnkgdnBuc2VydmVyLWpzb25ycGMtY29kZWdlblxyXG4vL1xyXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UgMi4wXHJcbi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDE5IFNvZnRFdGhlciBWUE4gUHJvamVjdFxyXG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XHJcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xyXG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG4gICAgfTtcclxufSkoKTtcclxudmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufTtcclxudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59O1xyXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xyXG4vLyBUcml2aWFsIHV0aWxpdHkgY29kZXNcclxudmFyIGlzX25vZGVfanMgPSAodHlwZW9mIG5hdmlnYXRvciA9PT0gXCJ1bmRlZmluZWRcIikgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwiTm9kZS5qc1wiKSAhPT0gLTEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwianNkb21cIikgIT09IC0xO1xyXG5mdW5jdGlvbiBpc19udWxsKG9iaikge1xyXG4gICAgcmV0dXJuICh0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiKSB8fCAob2JqID09PSBudWxsKTtcclxufVxyXG52YXIgZGVidWdfbW9kZSA9IGZhbHNlO1xyXG4vKiogVlBOIFNlcnZlciBSUEMgU3R1YnMgKi9cclxudmFyIFZwblNlcnZlclJwYyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKlxyXG4gICAgICogQ29uc3RydWN0b3Igb2YgdGhlIFZwblNlcnZlclJwYyBjbGFzc1xyXG4gICAgICogQHBhcmFtIHZwbnNlcnZlcl9ob3N0bmFtZSBUaGUgaG9zdG5hbWUgb3IgSVAgYWRkcmVzcyBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4gSW4gdGhlIHdlYiBicm93c2VyIHlvdSBjYW4gc3BlY2lmeSBudWxsIGlmIHlvdSB3YW50IHRvIGNvbm5lY3QgdG8gdGhlIHNlcnZlciBpdHNlbGYuXHJcbiAgICAgKiBAcGFyYW0gdnBuc2VydmVyX3BvcnQgVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLiBJbiB0aGUgd2ViIGJyb3dzZXIgeW91IGNhbiBzcGVjaWZ5IG51bGwgaWYgeW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgc2VydmVyIGl0c2VsZi5cclxuICAgICAqIEBwYXJhbSBodWJuYW1lIFRoZSBuYW1lIG9mIHRoZSBWaXJ0dWFsIEh1YiBpZiB5b3Ugd2FudCB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgVmlydHVhbCBIdWIgQWRtaW4gTW9kZS4gU3BlY2lmeSBudWxsIGlmIHlvdSB3YW50IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIgYXMgdGhlIEVudGlyZSBWUE4gU2VydmVyIEFkbWluIE1vZGUuXHJcbiAgICAgKiBAcGFyYW0gcGFzc3dvcmQgU3BlY2lmeSB0aGUgYWRtaW5pc3RyYXRpb24gcGFzc3dvcmQuIFRoaXMgdmFsdWUgaXMgdmFsaWQgb25seSBpZiB2cG5zZXJ2ZXJfaG9zdG5hbWUgaXMgc2VwY2lmaWVkLlxyXG4gICAgICogQHBhcmFtIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCBJbiBOb2RlLmpzIHNldCB0aGlzIHRydWUgdG8gY2hlY2sgdGhlIFNTTCBzZXJ2ZXIgY2VydGlmaWNhdGUgb24gdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuIFNldCB0aGlzIGZhbHNlIHRvIGlnbm9yZSB0aGUgU1NMIHNlcnZlciBjZXJ0aWZpY2F0aW9uLlxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBWcG5TZXJ2ZXJScGModnBuc2VydmVyX2hvc3RuYW1lLCB2cG5zZXJ2ZXJfcG9ydCwgaHVibmFtZSwgcGFzc3dvcmQsIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCkge1xyXG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XHJcbiAgICAgICAgLy8gLS0tIFN0dWJzIC0tLVxyXG4gICAgICAgIC8qKiBUZXN0IFJQQyBmdW5jdGlvbi4gSW5wdXQgYW55IGludGVnZXIgdmFsdWUgdG8gdGhlIEludFZhbHVlX3UzMiBmaWVsZC4gVGhlbiB0aGUgc2VydmVyIHdpbGwgY29udmVydCB0aGUgaW50ZWdlciB0byB0aGUgc3RyaW5nLCBhbmQgcmV0dXJuIHRoZSBzdHJpbmcgaW4gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gKi9cclxuICAgICAgICB0aGlzLlRlc3QgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlRlc3RcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBzZXJ2ZXIgaW5mb3JtYXRpb24uIFRoaXMgYWxsb3dzIHlvdSB0byBvYnRhaW4gdGhlIHNlcnZlciBpbmZvcm1hdGlvbiBvZiB0aGUgY3VycmVudGx5IGNvbm5lY3RlZCBWUE4gU2VydmVyIG9yIFZQTiBCcmlkZ2UuIEluY2x1ZGVkIGluIHRoZSBzZXJ2ZXIgaW5mb3JtYXRpb24gYXJlIHRoZSB2ZXJzaW9uIG51bWJlciwgYnVpbGQgbnVtYmVyIGFuZCBidWlsZCBpbmZvcm1hdGlvbi4gWW91IGNhbiBhbHNvIG9idGFpbiBpbmZvcm1hdGlvbiBvbiB0aGUgY3VycmVudCBzZXJ2ZXIgb3BlcmF0aW9uIG1vZGUgYW5kIHRoZSBpbmZvcm1hdGlvbiBvZiBvcGVyYXRpbmcgc3lzdGVtIHRoYXQgdGhlIHNlcnZlciBpcyBvcGVyYXRpbmcgb24uICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXJ2ZXJJbmZvID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VydmVySW5mb1wiLCBuZXcgVnBuUnBjU2VydmVySW5mbygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQ3VycmVudCBTZXJ2ZXIgU3RhdHVzLiBUaGlzIGFsbG93cyB5b3UgdG8gb2J0YWluIGluIHJlYWwtdGltZSB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIGN1cnJlbnRseSBjb25uZWN0ZWQgVlBOIFNlcnZlciBvciBWUE4gQnJpZGdlLiBZb3UgY2FuIGdldCBzdGF0aXN0aWNhbCBpbmZvcm1hdGlvbiBvbiBkYXRhIGNvbW11bmljYXRpb24gYW5kIHRoZSBudW1iZXIgb2YgZGlmZmVyZW50IGtpbmRzIG9mIG9iamVjdHMgdGhhdCBleGlzdCBvbiB0aGUgc2VydmVyLiBZb3UgY2FuIGdldCBpbmZvcm1hdGlvbiBvbiBob3cgbXVjaCBtZW1vcnkgaXMgYmVpbmcgdXNlZCBvbiB0aGUgY3VycmVudCBjb21wdXRlciBieSB0aGUgT1MuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXJ2ZXJTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRTZXJ2ZXJTdGF0dXNcIiwgbmV3IFZwblJwY1NlcnZlclN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgTmV3IFRDUCBMaXN0ZW5lci4gVGhpcyBhbGxvd3MgeW91IHRvIGNyZWF0ZSBhIG5ldyBUQ1AgTGlzdGVuZXIgb24gdGhlIHNlcnZlci4gQnkgY3JlYXRpbmcgdGhlIFRDUCBMaXN0ZW5lciB0aGUgc2VydmVyIHN0YXJ0cyBsaXN0ZW5pbmcgZm9yIGEgY29ubmVjdGlvbiBmcm9tIGNsaWVudHMgYXQgdGhlIHNwZWNpZmllZCBUQ1AvSVAgcG9ydCBudW1iZXIuIEEgVENQIExpc3RlbmVyIHRoYXQgaGFzIGJlZW4gY3JlYXRlZCBjYW4gYmUgZGVsZXRlZCBieSB0aGUgRGVsZXRlTGlzdGVuZXIgQVBJLiBZb3UgY2FuIGFsc28gZ2V0IGEgbGlzdCBvZiBUQ1AgTGlzdGVuZXJzIGN1cnJlbnRseSByZWdpc3RlcmVkIGJ5IHVzaW5nIHRoZSBFbnVtTGlzdGVuZXIgQVBJLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlTGlzdGVuZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNyZWF0ZUxpc3RlbmVyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBUQ1AgTGlzdGVuZXJzLiBUaGlzIGFsbG93cyB5b3UgdG8gZ2V0IGEgbGlzdCBvZiBUQ1AgbGlzdGVuZXJzIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnQgc2VydmVyLiBZb3UgY2FuIG9idGFpbiBpbmZvcm1hdGlvbiBvbiB3aGV0aGVyIHRoZSB2YXJpb3VzIFRDUCBsaXN0ZW5lcnMgaGF2ZSBhIHN0YXR1cyBvZiBvcGVyYXRpbmcgb3IgZXJyb3IuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTGlzdGVuZXJcIiwgbmV3IFZwblJwY0xpc3RlbmVyTGlzdCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgVENQIExpc3RlbmVyLiBUaGlzIGFsbG93cyB5b3UgdG8gZGVsZXRlIGEgVENQIExpc3RlbmVyIHRoYXQncyByZWdpc3RlcmVkIG9uIHRoZSBzZXJ2ZXIuIFdoZW4gdGhlIFRDUCBMaXN0ZW5lciBpcyBpbiBhIHN0YXRlIG9mIG9wZXJhdGlvbiwgdGhlIGxpc3RlbmVyIHdpbGwgYXV0b21hdGljYWxseSBiZSBkZWxldGVkIHdoZW4gaXRzIG9wZXJhdGlvbiBzdG9wcy4gWW91IGNhbiBhbHNvIGdldCBhIGxpc3Qgb2YgVENQIExpc3RlbmVycyBjdXJyZW50bHkgcmVnaXN0ZXJlZCBieSB1c2luZyB0aGUgRW51bUxpc3RlbmVyIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUxpc3RlbmVyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRW5hYmxlIC8gRGlzYWJsZSBUQ1AgTGlzdGVuZXIuIFRoaXMgc3RhcnRzIG9yIHN0b3BzIHRoZSBvcGVyYXRpb24gb2YgVENQIExpc3RlbmVycyByZWdpc3RlcmVkIG9uIHRoZSBjdXJyZW50IHNlcnZlci4gWW91IGNhbiBhbHNvIGdldCBhIGxpc3Qgb2YgVENQIExpc3RlbmVycyBjdXJyZW50bHkgcmVnaXN0ZXJlZCBieSB1c2luZyB0aGUgRW51bUxpc3RlbmVyIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkVuYWJsZUxpc3RlbmVyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbmFibGVMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFZQTiBTZXJ2ZXIgQWRtaW5pc3RyYXRvciBQYXNzd29yZC4gVGhpcyBzZXRzIHRoZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQuIFlvdSBjYW4gc3BlY2lmeSB0aGUgcGFzc3dvcmQgYXMgYSBwYXJhbWV0ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRTZXJ2ZXJQYXNzd29yZCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0U2VydmVyUGFzc3dvcmRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCB0aGUgVlBOIFNlcnZlciBjbHVzdGVyaW5nIGNvbmZpZ3VyYXRpb24uIFVzZSB0aGlzIHRvIHNldCB0aGUgVlBOIFNlcnZlciB0eXBlIGFzIFN0YW5kYWxvbmUgU2VydmVyLCBDbHVzdGVyIENvbnRyb2xsZXIgU2VydmVyIG9yIENsdXN0ZXIgTWVtYmVyIFNlcnZlci4gU3RhbmRhbG9uZSBzZXJ2ZXIgbWVhbnMgYSBWUE4gU2VydmVyIHRoYXQgZG9lcyBub3QgYmVsb25nIHRvIGFueSBjbHVzdGVyIGluIGl0cyBjdXJyZW50IHN0YXRlLiBXaGVuIFZQTiBTZXJ2ZXIgaXMgaW5zdGFsbGVkLCBieSBkZWZhdWx0IGl0IHdpbGwgYmUgaW4gc3RhbmRhbG9uZSBzZXJ2ZXIgbW9kZS4gVW5sZXNzIHlvdSBoYXZlIHBhcnRpY3VsYXIgcGxhbnMgdG8gY29uZmlndXJlIGEgY2x1c3Rlciwgd2UgcmVjb21tZW5kIHRoZSBWUE4gU2VydmVyIGJlIG9wZXJhdGVkIGluIHN0YW5kYWxvbmUgbW9kZS4gQSBjbHVzdGVyIGNvbnRyb2xsZXIgaXMgdGhlIGNlbnRyYWwgY29tcHV0ZXIgb2YgYWxsIG1lbWJlciBzZXJ2ZXJzIG9mIGEgY2x1c3RlciBpbiB0aGUgY2FzZSB3aGVyZSBhIGNsdXN0ZXJpbmcgZW52aXJvbm1lbnQgaXMgbWFkZSB1cCBvZiBtdWx0aXBsZSBWUE4gU2VydmVycy4gTXVsdGlwbGUgY2x1c3RlciBtZW1iZXJzIGNhbiBiZSBhZGRlZCB0byB0aGUgY2x1c3RlciBhcyByZXF1aXJlZC4gQSBjbHVzdGVyIHJlcXVpcmVzIG9uZSBjb21wdXRlciB0byBzZXJ2ZSB0aGlzIHJvbGUuIFRoZSBvdGhlciBjbHVzdGVyIG1lbWJlciBzZXJ2ZXJzIHRoYXQgYXJlIGNvbmZpZ3VyZWQgaW4gdGhlIHNhbWUgY2x1c3RlciBiZWdpbiBvcGVyYXRpb24gYXMgYSBjbHVzdGVyIG1lbWJlciBieSBjb25uZWN0aW5nIHRvIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHdoZW4gdGhpcyBBUEkgaXMgZXhlY3V0ZWQsIFZQTiBTZXJ2ZXIgd2lsbCBhdXRvbWF0aWNhbGx5IHJlc3RhcnQuIFRoaXMgQVBJIGNhbm5vdCBiZSBjYWxsZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLlNldEZhcm1TZXR0aW5nID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRGYXJtU2V0dGluZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IENsdXN0ZXJpbmcgQ29uZmlndXJhdGlvbiBvZiBDdXJyZW50IFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoaXMgdG8gYWNxdWlyZSB0aGUgY2x1c3RlcmluZyBjb25maWd1cmF0aW9uIG9mIHRoZSBjdXJyZW50IFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5HZXRGYXJtU2V0dGluZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEZhcm1TZXR0aW5nXCIsIG5ldyBWcG5ScGNGYXJtKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDbHVzdGVyIE1lbWJlciBJbmZvcm1hdGlvbi4gV2hlbiB0aGUgVlBOIFNlcnZlciBpcyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIsIHlvdSBjYW4gZ2V0IGluZm9ybWF0aW9uIG9uIGNsdXN0ZXIgbWVtYmVyIHNlcnZlcnMgb24gdGhhdCBjbHVzdGVyIGJ5IHNwZWNpZnlpbmcgdGhlIElEcyBvZiB0aGUgbWVtYmVyIHNlcnZlcnMuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNwZWNpZmllZCBjbHVzdGVyIG1lbWJlciBzZXJ2ZXI6IFNlcnZlciBUeXBlLCBUaW1lIENvbm5lY3Rpb24gaGFzIGJlZW4gRXN0YWJsaXNoZWQsIElQIEFkZHJlc3MsIEhvc3QgTmFtZSwgUG9pbnRzLCBQdWJsaWMgUG9ydCBMaXN0LCBOdW1iZXIgb2YgT3BlcmF0aW5nIFZpcnR1YWwgSHVicywgRmlyc3QgVmlydHVhbCBIdWIsIE51bWJlciBvZiBTZXNzaW9ucyBhbmQgTnVtYmVyIG9mIFRDUCBDb25uZWN0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkdldEZhcm1JbmZvID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRGYXJtSW5mb1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgQ2x1c3RlciBNZW1iZXJzLiBVc2UgdGhpcyBBUEkgd2hlbiB0aGUgVlBOIFNlcnZlciBpcyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIgdG8gZ2V0IGEgbGlzdCBvZiB0aGUgY2x1c3RlciBtZW1iZXIgc2VydmVycyBvbiB0aGUgc2FtZSBjbHVzdGVyLCBpbmNsdWRpbmcgdGhlIGNsdXN0ZXIgY29udHJvbGxlciBpdHNlbGYuIEZvciBlYWNoIG1lbWJlciwgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbiBpcyBhbHNvIGxpc3RlZDogVHlwZSwgQ29ubmVjdGlvbiBTdGFydCwgSG9zdCBOYW1lLCBQb2ludHMsIE51bWJlciBvZiBTZXNzaW9uLCBOdW1iZXIgb2YgVENQIENvbm5lY3Rpb25zLCBOdW1iZXIgb2YgT3BlcmF0aW5nIFZpcnR1YWwgSHVicywgVXNpbmcgQ2xpZW50IENvbm5lY3Rpb24gTGljZW5zZSBhbmQgVXNpbmcgQnJpZGdlIENvbm5lY3Rpb24gTGljZW5zZS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkVudW1GYXJtTWVtYmVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUZhcm1NZW1iZXJcIiwgbmV3IFZwblJwY0VudW1GYXJtKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDb25uZWN0aW9uIFN0YXR1cyB0byBDbHVzdGVyIENvbnRyb2xsZXIuIFVzZSB0aGlzIEFQSSB3aGVuIHRoZSBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIgY29udHJvbGxlciB0byBnZXQgdGhlIHN0YXR1cyBvZiBjb25uZWN0aW9uIHRvIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246IENvbnRyb2xsZXIgSVAgQWRkcmVzcywgUG9ydCBOdW1iZXIsIENvbm5lY3Rpb24gU3RhdHVzLCBDb25uZWN0aW9uIFN0YXJ0IFRpbWUsIEZpcnN0IENvbm5lY3Rpb24gRXN0YWJsaXNoZWQgVGltZSwgQ3VycmVudCBDb25uZWN0aW9uIEVzdGFibGlzaGVkIFRpbWUsIE51bWJlciBvZiBDb25uZWN0aW9uIEF0dGVtcHRzLCBOdW1iZXIgb2YgU3VjY2Vzc2Z1bCBDb25uZWN0aW9ucywgTnVtYmVyIG9mIEZhaWxlZCBDb25uZWN0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gKi9cclxuICAgICAgICB0aGlzLkdldEZhcm1Db25uZWN0aW9uU3RhdHVzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0RmFybUNvbm5lY3Rpb25TdGF0dXNcIiwgbmV3IFZwblJwY0Zhcm1Db25uZWN0aW9uU3RhdHVzKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBTU0wgQ2VydGlmaWNhdGUgYW5kIFByaXZhdGUgS2V5IG9mIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gc2V0IHRoZSBTU0wgY2VydGlmaWNhdGUgdGhhdCB0aGUgVlBOIFNlcnZlciBwcm92aWRlcyB0byB0aGUgY29ubmVjdGVkIGNsaWVudCBhbmQgdGhlIHByaXZhdGUga2V5IGZvciB0aGF0IGNlcnRpZmljYXRlLiBUaGUgY2VydGlmaWNhdGUgbXVzdCBiZSBpbiBYLjUwOSBmb3JtYXQgYW5kIHRoZSBwcml2YXRlIGtleSBtdXN0IGJlIEJhc2UgNjQgZW5jb2RlZCBmb3JtYXQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRTZXJ2ZXJDZXJ0ID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRTZXJ2ZXJDZXJ0XCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgU1NMIENlcnRpZmljYXRlIGFuZCBQcml2YXRlIEtleSBvZiBWUE4gU2VydmVyLiBVc2UgdGhpcyB0byBnZXQgdGhlIFNTTCBjZXJ0aWZpY2F0ZSBwcml2YXRlIGtleSB0aGF0IHRoZSBWUE4gU2VydmVyIHByb3ZpZGVzIHRvIHRoZSBjb25uZWN0ZWQgY2xpZW50LiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U2VydmVyQ2VydCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFNlcnZlckNlcnRcIiwgbmV3IFZwblJwY0tleVBhaXIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBFbmNyeXB0ZWQgQWxnb3JpdGhtIFVzZWQgZm9yIFZQTiBDb21tdW5pY2F0aW9uLiBVc2UgdGhpcyBBUEkgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgb2YgdGhlIGFsZ29yaXRobSB1c2VkIGZvciB0aGUgZWxlY3Ryb25pYyBzaWduYXR1cmUgYW5kIGVuY3J5cHRlZCBmb3IgU1NMIGNvbm5lY3Rpb24gdG8gYmUgdXNlZCBmb3IgY29tbXVuaWNhdGlvbiBiZXR3ZWVuIHRoZSBWUE4gU2VydmVyIGFuZCB0aGUgY29ubmVjdGVkIGNsaWVudCBhbmQgdGhlIGxpc3Qgb2YgYWxnb3JpdGhtcyB0aGF0IGNhbiBiZSB1c2VkIG9uIHRoZSBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U2VydmVyQ2lwaGVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VydmVyQ2lwaGVyXCIsIG5ldyBWcG5ScGNTdHIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IHRoZSBFbmNyeXB0ZWQgQWxnb3JpdGhtIFVzZWQgZm9yIFZQTiBDb21tdW5pY2F0aW9uLiBVc2UgdGhpcyBBUEkgdG8gc2V0IHRoZSBhbGdvcml0aG0gdXNlZCBmb3IgdGhlIGVsZWN0cm9uaWMgc2lnbmF0dXJlIGFuZCBlbmNyeXB0ZWQgZm9yIFNTTCBjb25uZWN0aW9ucyB0byBiZSB1c2VkIGZvciBjb21tdW5pY2F0aW9uIGJldHdlZW4gdGhlIFZQTiBTZXJ2ZXIgYW5kIHRoZSBjb25uZWN0ZWQgY2xpZW50LiBCeSBzcGVjaWZ5aW5nIHRoZSBhbGdvcml0aG0gbmFtZSwgdGhlIHNwZWNpZmllZCBhbGdvcml0aG0gd2lsbCBiZSB1c2VkIGxhdGVyIGJldHdlZW4gdGhlIFZQTiBDbGllbnQgYW5kIFZQTiBCcmlkZ2UgY29ubmVjdGVkIHRvIHRoaXMgc2VydmVyIGFuZCB0aGUgZGF0YSB3aWxsIGJlIGVuY3J5cHRlZC4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLlNldFNlcnZlckNpcGhlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0U2VydmVyQ2lwaGVyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgTmV3IFZpcnR1YWwgSHViLiBVc2UgdGhpcyB0byBjcmVhdGUgYSBuZXcgVmlydHVhbCBIdWIgb24gdGhlIFZQTiBTZXJ2ZXIuIFRoZSBjcmVhdGVkIFZpcnR1YWwgSHViIHdpbGwgYmVnaW4gb3BlcmF0aW9uIGltbWVkaWF0ZWx5LiBXaGVuIHRoZSBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBvbiBhIGNsdXN0ZXIsIHRoaXMgQVBJIGlzIG9ubHkgdmFsaWQgZm9yIHRoZSBjbHVzdGVyIGNvbnRyb2xsZXIuIEFsc28sIHRoZSBuZXcgVmlydHVhbCBIdWIgd2lsbCBvcGVyYXRlIGFzIGEgZHluYW1pYyBWaXJ0dWFsIEh1Yi4gWW91IGNhbiBjaGFuZ2UgaXQgdG8gYSBzdGF0aWMgVmlydHVhbCBIdWIgYnkgdXNpbmcgdGhlIFNldEh1YiBBUEkuIFRvIGdldCBhIGxpc3Qgb2YgVmlydHVhbCBIdWJzIHRoYXQgYXJlIGFscmVhZHkgb24gdGhlIFZQTiBTZXJ2ZXIsIHVzZSB0aGUgRW51bUh1YiBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIFNlcnZlcnMgdGhhdCBhcmUgb3BlcmF0aW5nIGFzIGEgVlBOIEJyaWRnZSBvciBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQ3JlYXRlSHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFZpcnR1YWwgSHViIGNvbmZpZ3VyYXRpb24uIFlvdSBjYW4gY2FsbCB0aGlzIEFQSSB0byBjaGFuZ2UgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHNwZWNpZmllZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbiBzZXQgdGhlIFZpcnR1YWwgSHViIG9ubGluZSBvciBvZmZsaW5lLiBZb3UgY2FuIHNldCB0aGUgbWF4aW11bSBudW1iZXIgb2Ygc2Vzc2lvbnMgdGhhdCBjYW4gYmUgY29uY3VycmVudGx5IGNvbm5lY3RlZCB0byB0aGUgVmlydHVhbCBIdWIgdGhhdCBpcyBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZC4gWW91IGNhbiBzZXQgdGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQuIFlvdSBjYW4gc2V0IG90aGVyIHBhcmFtZXRlcnMgZm9yIHRoZSBWaXJ0dWFsIEh1Yi4gQmVmb3JlIGNhbGwgdGhpcyBBUEksIHlvdSBuZWVkIHRvIG9idGFpbiB0aGUgbGF0ZXN0IHN0YXRlIG9mIHRoZSBWaXJ0dWFsIEh1YiBieSB1c2luZyB0aGUgR2V0SHViIEFQSS4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIFZpcnR1YWwgSHViIGNvbmZpZ3VyYXRpb24uIFlvdSBjYW4gY2FsbCB0aGlzIEFQSSB0byBnZXQgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBvZiB0aGUgc3BlY2lmaWVkIFZpcnR1YWwgSHViLiBUbyBjaGFuZ2UgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIFZpcnR1YWwgSHViLCBjYWxsIHRoZSBTZXRIdWIgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgSHVicy4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiBleGlzdGluZyBWaXJ0dWFsIEh1YnMgb24gdGhlIFZQTiBTZXJ2ZXIuIEZvciBlYWNoIFZpcnR1YWwgSHViLCB5b3UgY2FuIGdldCB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOiBWaXJ0dWFsIEh1YiBOYW1lLCBTdGF0dXMsIFR5cGUsIE51bWJlciBvZiBVc2VycywgTnVtYmVyIG9mIEdyb3VwcywgTnVtYmVyIG9mIFNlc3Npb25zLCBOdW1iZXIgb2YgTUFDIFRhYmxlcywgTnVtYmVyIG9mIElQIFRhYmxlcywgTnVtYmVyIG9mIExvZ2lucywgTGFzdCBMb2dpbiwgYW5kIExhc3QgQ29tbXVuaWNhdGlvbi4gTm90ZSB0aGF0IHdoZW4gY29ubmVjdGluZyBpbiBWaXJ0dWFsIEh1YiBBZG1pbiBNb2RlLCBpZiBpbiB0aGUgb3B0aW9ucyBvZiBhIFZpcnR1YWwgSHViIHRoYXQgeW91IGRvIG5vdCBoYXZlIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcyBmb3IsIHRoZSBvcHRpb24gRG9uJ3QgRW51bWVyYXRlIHRoaXMgVmlydHVhbCBIdWIgZm9yIEFub255bW91cyBVc2VycyBpcyBlbmFibGVkIHRoZW4gdGhhdCBWaXJ0dWFsIEh1YiB3aWxsIG5vdCBiZSBlbnVtZXJhdGVkLiBJZiB5b3UgYXJlIGNvbm5lY3RlZCBpbiBTZXJ2ZXIgQWRtaW4gTW9kZSwgdGhlbiB0aGUgbGlzdCBvZiBhbGwgVmlydHVhbCBIdWJzIHdpbGwgYmUgZGlzcGxheWVkLiBXaGVuIGNvbm5lY3RpbmcgdG8gYW5kIG1hbmFnaW5nIGEgbm9uLWNsdXN0ZXItY29udHJvbGxlciBjbHVzdGVyIG1lbWJlciBvZiBhIGNsdXN0ZXJpbmcgZW52aXJvbm1lbnQsIG9ubHkgdGhlIFZpcnR1YWwgSHViIGN1cnJlbnRseSBiZWluZyBob3N0ZWQgYnkgdGhhdCBWUE4gU2VydmVyIHdpbGwgYmUgZGlzcGxheWVkLiBXaGVuIGNvbm5lY3RpbmcgdG8gYSBjbHVzdGVyIGNvbnRyb2xsZXIgZm9yIGFkbWluaXN0cmF0aW9uIHB1cnBvc2VzLCBhbGwgdGhlIFZpcnR1YWwgSHVicyB3aWxsIGJlIGRpc3BsYXllZC4gKi9cclxuICAgICAgICB0aGlzLkVudW1IdWIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtSHViXCIsIG5ldyBWcG5ScGNFbnVtSHViKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIEh1Yi4gVXNlIHRoaXMgdG8gZGVsZXRlIGFuIGV4aXN0aW5nIFZpcnR1YWwgSHViIG9uIHRoZSBWUE4gU2VydmVyLiBJZiB5b3UgZGVsZXRlIHRoZSBWaXJ0dWFsIEh1YiwgYWxsIHNlc3Npb25zIHRoYXQgYXJlIGN1cnJlbnRseSBjb25uZWN0ZWQgdG8gdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgZGlzY29ubmVjdGVkIGFuZCBuZXcgc2Vzc2lvbnMgd2lsbCBiZSB1bmFibGUgdG8gY29ubmVjdCB0byB0aGUgVmlydHVhbCBIdWIuIEFsc28sIHRoaXMgd2lsbCBhbHNvIGRlbGV0ZSBhbGwgdGhlIEh1YiBzZXR0aW5ncywgdXNlciBvYmplY3RzLCBncm91cCBvYmplY3RzLCBjZXJ0aWZpY2F0ZXMgYW5kIENhc2NhZGUgQ29ubmVjdGlvbnMuIE9uY2UgeW91IGRlbGV0ZSB0aGUgVmlydHVhbCBIdWIsIGl0IGNhbm5vdCBiZSByZWNvdmVyZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIFNlcnZlcnMgdGhhdCBhcmUgb3BlcmF0aW5nIGFzIGEgVlBOIEJyaWRnZSBvciBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUh1YiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlSHViXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgU2V0dGluZyBvZiBSQURJVVMgU2VydmVyIFVzZWQgZm9yIFVzZXIgQXV0aGVudGljYXRpb24uIFVzZSB0aGlzIHRvIGdldCB0aGUgY3VycmVudCBzZXR0aW5ncyBmb3IgdGhlIFJBRElVUyBzZXJ2ZXIgdXNlZCB3aGVuIGEgdXNlciBjb25uZWN0cyB0byB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgdXNpbmcgUkFESVVTIFNlcnZlciBBdXRoZW50aWNhdGlvbiBNb2RlLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViUmFkaXVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJSYWRpdXNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBSQURJVVMgU2VydmVyIHRvIHVzZSBmb3IgVXNlciBBdXRoZW50aWNhdGlvbi4gVG8gYWNjZXB0IHVzZXJzIHRvIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBpbiBSQURJVVMgc2VydmVyIGF1dGhlbnRpY2F0aW9uIG1vZGUsIHlvdSBjYW4gc3BlY2lmeSBhbiBleHRlcm5hbCBSQURJVVMgc2VydmVyIHRoYXQgY29uZmlybXMgdGhlIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQuIChZb3UgY2FuIHNwZWNpZnkgbXVsdGlwbGUgaG9zdG5hbWUgYnkgc3BsaXR0aW5nIHdpdGggY29tbWEgb3Igc2VtaWNvbG9uLikgVGhlIFJBRElVUyBzZXJ2ZXIgbXVzdCBiZSBzZXQgdG8gcmVjZWl2ZSByZXF1ZXN0cyBmcm9tIElQIGFkZHJlc3NlcyBvZiB0aGlzIFZQTiBTZXJ2ZXIuIEFsc28sIGF1dGhlbnRpY2F0aW9uIGJ5IFBhc3N3b3JkIEF1dGhlbnRpY2F0aW9uIFByb3RvY29sIChQQVApIG11c3QgYmUgZW5hYmxlZC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YlJhZGl1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SHViUmFkaXVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBUQ1AgQ29ubmVjdGlvbnMgQ29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiBUQ1AvSVAgY29ubmVjdGlvbnMgdGhhdCBhcmUgY3VycmVudGx5IGNvbm5lY3RpbmcgdG8gdGhlIFZQTiBTZXJ2ZXIuIEl0IGRvZXMgbm90IGRpc3BsYXkgdGhlIFRDUCBjb25uZWN0aW9ucyB0aGF0IGhhdmUgYmVlbiBlc3RhYmxpc2hlZCBhcyBWUE4gc2Vzc2lvbnMuIFRvIGdldCB0aGUgbGlzdCBvZiBUQ1AvSVAgY29ubmVjdGlvbnMgdGhhdCBoYXZlIGJlZW4gZXN0YWJsaXNoZWQgYXMgVlBOIHNlc3Npb25zLCB5b3UgY2FuIHVzZSB0aGUgRW51bVNlc3Npb24gQVBJLiBZb3UgY2FuIGdldCB0aGUgZm9sbG93aW5nOiBDb25uZWN0aW9uIE5hbWUsIENvbm5lY3Rpb24gU291cmNlLCBDb25uZWN0aW9uIFN0YXJ0IGFuZCBUeXBlLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUNvbm5lY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtQ29ubmVjdGlvblwiLCBuZXcgVnBuUnBjRW51bUNvbm5lY3Rpb24oKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRGlzY29ubmVjdCBUQ1AgQ29ubmVjdGlvbnMgQ29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZm9yY2VmdWxseSBkaXNjb25uZWN0IHNwZWNpZmljIFRDUC9JUCBjb25uZWN0aW9ucyB0aGF0IGFyZSBjb25uZWN0aW5nIHRvIHRoZSBWUE4gU2VydmVyLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRGlzY29ubmVjdENvbm5lY3Rpb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRpc2Nvbm5lY3RDb25uZWN0aW9uXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgSW5mb3JtYXRpb24gb2YgVENQIENvbm5lY3Rpb25zIENvbm5lY3RpbmcgdG8gdGhlIFZQTiBTZXJ2ZXIuIFVzZSB0aGlzIHRvIGdldCBkZXRhaWxlZCBpbmZvcm1hdGlvbiBvZiBhIHNwZWNpZmljIFRDUC9JUCBjb25uZWN0aW9uIHRoYXQgaXMgY29ubmVjdGluZyB0byB0aGUgVlBOIFNlcnZlci4gWW91IGNhbiBnZXQgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjogQ29ubmVjdGlvbiBOYW1lLCBDb25uZWN0aW9uIFR5cGUsIFNvdXJjZSBIb3N0bmFtZSwgU291cmNlIElQIEFkZHJlc3MsIFNvdXJjZSBQb3J0IE51bWJlciAoVENQKSwgQ29ubmVjdGlvbiBTdGFydCwgU2VydmVyIFByb2R1Y3QgTmFtZSwgU2VydmVyIFZlcnNpb24sIFNlcnZlciBCdWlsZCBOdW1iZXIsIENsaWVudCBQcm9kdWN0IE5hbWUsIENsaWVudCBWZXJzaW9uLCBhbmQgQ2xpZW50IEJ1aWxkIE51bWJlci4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkdldENvbm5lY3Rpb25JbmZvID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRDb25uZWN0aW9uSW5mb1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU3dpdGNoIFZpcnR1YWwgSHViIHRvIE9ubGluZSBvciBPZmZsaW5lLiBVc2UgdGhpcyB0byBzZXQgdGhlIFZpcnR1YWwgSHViIHRvIG9ubGluZSBvciBvZmZsaW5lLiBBIFZpcnR1YWwgSHViIHdpdGggYW4gb2ZmbGluZSBzdGF0dXMgY2Fubm90IHJlY2VpdmUgVlBOIGNvbm5lY3Rpb25zIGZyb20gY2xpZW50cy4gV2hlbiB5b3Ugc2V0IHRoZSBWaXJ0dWFsIEh1YiBvZmZsaW5lLCBhbGwgc2Vzc2lvbnMgd2lsbCBiZSBkaXNjb25uZWN0ZWQuIEEgVmlydHVhbCBIdWIgd2l0aCBhbiBvZmZsaW5lIHN0YXR1cyBjYW5ub3QgcmVjZWl2ZSBWUE4gY29ubmVjdGlvbnMgZnJvbSBjbGllbnRzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViT25saW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJPbmxpbmVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBDdXJyZW50IFN0YXR1cyBvZiBWaXJ0dWFsIEh1Yi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgVmlydHVhbCBIdWIgY3VycmVudGx5IGJlaW5nIG1hbmFnZWQuIFlvdSBjYW4gZ2V0IHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246IFZpcnR1YWwgSHViIFR5cGUsIE51bWJlciBvZiBTZXNzaW9ucywgTnVtYmVyIG9mIEVhY2ggVHlwZSBvZiBPYmplY3QsIE51bWJlciBvZiBMb2dpbnMsIExhc3QgTG9naW4sIExhc3QgQ29tbXVuaWNhdGlvbiwgYW5kIENvbW11bmljYXRpb24gU3RhdGlzdGljYWwgRGF0YS4gKi9cclxuICAgICAgICB0aGlzLkdldEh1YlN0YXR1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0SHViU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIGxvZ2dpbmcgY29uZmlndXJhdGlvbiBvZiB0aGUgVmlydHVhbCBIdWIuIFVzZSB0aGlzIHRvIGVuYWJsZSBvciBkaXNhYmxlIGEgc2VjdXJpdHkgbG9nIG9yIHBhY2tldCBsb2dzIG9mIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZCwgc2V0IHRoZSBzYXZlIGNvbnRlbnRzIG9mIHRoZSBwYWNrZXQgbG9nIGZvciBlYWNoIHR5cGUgb2YgcGFja2V0IHRvIGJlIHNhdmVkLCBhbmQgc2V0IHRoZSBsb2cgZmlsZSBzd2l0Y2ggY3ljbGUgZm9yIHRoZSBzZWN1cml0eSBsb2cgb3IgcGFja2V0IGxvZyB0aGF0IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBzYXZlcy4gVGhlcmUgYXJlIHRoZSBmb2xsb3dpbmcgcGFja2V0IHR5cGVzOiBUQ1AgQ29ubmVjdGlvbiBMb2csIFRDUCBQYWNrZXQgTG9nLCBESENQIFBhY2tldCBMb2csIFVEUCBQYWNrZXQgTG9nLCBJQ01QIFBhY2tldCBMb2csIElQIFBhY2tldCBMb2csIEFSUCBQYWNrZXQgTG9nLCBhbmQgRXRoZXJuZXQgUGFja2V0IExvZy4gVG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcsIHlvdSBjYW4gdXNlIHRoZSBMb2dHZXQgQVBJLiBUaGUgbG9nIGZpbGUgc3dpdGNoIGN5Y2xlIGNhbiBiZSBjaGFuZ2VkIHRvIHN3aXRjaCBpbiBldmVyeSBzZWNvbmQsIGV2ZXJ5IG1pbnV0ZSwgZXZlcnkgaG91ciwgZXZlcnkgZGF5LCBldmVyeSBtb250aCBvciBub3Qgc3dpdGNoLiBUbyBnZXQgdGhlIGN1cnJlbnQgc2V0dGluZywgeW91IGNhbiB1c2UgdGhlIEdldEh1YkxvZyBBUEkuICovXHJcbiAgICAgICAgdGhpcy5TZXRIdWJMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEh1YkxvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBsb2dnaW5nIGNvbmZpZ3VyYXRpb24gb2YgdGhlIFZpcnR1YWwgSHViLiBVc2UgdGhpcyB0byBnZXQgdGhlIGNvbmZpZ3VyYXRpb24gZm9yIGEgc2VjdXJpdHkgbG9nIG9yIHBhY2tldCBsb2dzIG9mIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZCwgZ2V0IHRoZSBzZXR0aW5nIGZvciBzYXZlIGNvbnRlbnRzIG9mIHRoZSBwYWNrZXQgbG9nIGZvciBlYWNoIHR5cGUgb2YgcGFja2V0IHRvIGJlIHNhdmVkLCBhbmQgZ2V0IHRoZSBsb2cgZmlsZSBzd2l0Y2ggY3ljbGUgZm9yIHRoZSBzZWN1cml0eSBsb2cgb3IgcGFja2V0IGxvZyB0aGF0IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBzYXZlcy4gVG8gc2V0IHRoZSBjdXJyZW50IHNldHRpbmcsIHlvdSBjYW4gdXNlIHRoZSBTZXRIdWJMb2cgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SHViTG9nID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJMb2dcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBhZGQgYSBuZXcgY2VydGlmaWNhdGUgdG8gYSBsaXN0IG9mIENBIGNlcnRpZmljYXRlcyB0cnVzdGVkIGJ5IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGxpc3Qgb2YgY2VydGlmaWNhdGUgYXV0aG9yaXR5IGNlcnRpZmljYXRlcyB0aGF0IGFyZSByZWdpc3RlcmVkIGlzIHVzZWQgdG8gdmVyaWZ5IGNlcnRpZmljYXRlcyB3aGVuIGEgVlBOIENsaWVudCBpcyBjb25uZWN0ZWQgaW4gc2lnbmVkIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIFRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnQgY2VydGlmaWNhdGVzIHlvdSBjYW4gdXNlIHRoZSBFbnVtQ2EgQVBJLiBUaGUgY2VydGlmaWNhdGUgeW91IGFkZCBtdXN0IGJlIHNhdmVkIGluIHRoZSBYLjUwOSBmaWxlIGZvcm1hdC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5BZGRDYSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkQ2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFRydXN0ZWQgQ0EgQ2VydGlmaWNhdGVzLiBIZXJlIHlvdSBjYW4gbWFuYWdlIHRoZSBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkgY2VydGlmaWNhdGVzIHRoYXQgYXJlIHRydXN0ZWQgYnkgdGhpcyBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGxpc3Qgb2YgY2VydGlmaWNhdGUgYXV0aG9yaXR5IGNlcnRpZmljYXRlcyB0aGF0IGFyZSByZWdpc3RlcmVkIGlzIHVzZWQgdG8gdmVyaWZ5IGNlcnRpZmljYXRlcyB3aGVuIGEgVlBOIENsaWVudCBpcyBjb25uZWN0ZWQgaW4gc2lnbmVkIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUNhID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtQ2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBnZXQgYW4gZXhpc3RpbmcgY2VydGlmaWNhdGUgZnJvbSB0aGUgbGlzdCBvZiBDQSBjZXJ0aWZpY2F0ZXMgdHJ1c3RlZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIHNhdmUgaXQgYXMgYSBmaWxlIGluIFguNTA5IGZvcm1hdC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRDYSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0Q2FcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBUcnVzdGVkIENBIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBkZWxldGUgYW4gZXhpc3RpbmcgY2VydGlmaWNhdGUgZnJvbSB0aGUgbGlzdCBvZiBDQSBjZXJ0aWZpY2F0ZXMgdHJ1c3RlZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnQgY2VydGlmaWNhdGVzIHlvdSBjYW4gdXNlIHRoZSBFbnVtQ2EgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUNhID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVDYVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ3JlYXRlIE5ldyBDYXNjYWRlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGNyZWF0ZSBhIG5ldyBDYXNjYWRlIENvbm5lY3Rpb24gb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBCeSB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiwgeW91IGNhbiBjb25uZWN0IHRoaXMgVmlydHVhbCBIdWIgYnkgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIGFub3RoZXIgVmlydHVhbCBIdWIgdGhhdCBpcyBvcGVyYXRpbmcgb24gdGhlIHNhbWUgb3IgYSBkaWZmZXJlbnQgY29tcHV0ZXIuIFRvIGNyZWF0ZSBhIENhc2NhZGUgQ29ubmVjdGlvbiwgeW91IG11c3Qgc3BlY2lmeSB0aGUgbmFtZSBvZiB0aGUgQ2FzY2FkZSBDb25uZWN0aW9uLCBkZXN0aW5hdGlvbiBzZXJ2ZXIgYW5kIGRlc3RpbmF0aW9uIFZpcnR1YWwgSHViIGFuZCB1c2VyIG5hbWUuIFdoZW4gYSBuZXcgQ2FzY2FkZSBDb25uZWN0aW9uIGlzIGNyZWF0ZWQsIHRoZSB0eXBlIG9mIHVzZXIgYXV0aGVudGljYXRpb24gaXMgaW5pdGlhbGx5IHNldCBhcyBBbm9ueW1vdXMgQXV0aGVudGljYXRpb24gYW5kIHRoZSBwcm94eSBzZXJ2ZXIgc2V0dGluZyBhbmQgdGhlIHZlcmlmaWNhdGlvbiBvcHRpb25zIG9mIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IHNldC4gVG8gY2hhbmdlIHRoZXNlIHNldHRpbmdzIGFuZCBvdGhlciBhZHZhbmNlZCBzZXR0aW5ncyBhZnRlciBhIENhc2NhZGUgQ29ubmVjdGlvbiBoYXMgYmVlbiBjcmVhdGVkLCB1c2UgdGhlIG90aGVyIEFQSXMgdGhhdCBpbmNsdWRlIHRoZSBuYW1lIFwiTGlua1wiLiBbV2FybmluZyBBYm91dCBDYXNjYWRlIENvbm5lY3Rpb25zXSBCeSBjb25uZWN0aW5nIHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHlvdSBjYW4gY3JlYXRlIGEgTGF5ZXIgMiBicmlkZ2UgYmV0d2VlbiBtdWx0aXBsZSBWaXJ0dWFsIEh1YnMgYnV0IGlmIHRoZSBjb25uZWN0aW9uIGlzIGluY29ycmVjdGx5IGNvbmZpZ3VyZWQsIGEgbG9vcGJhY2sgQ2FzY2FkZSBDb25uZWN0aW9uIGNvdWxkIGluYWR2ZXJ0ZW50bHkgYmUgY3JlYXRlZC4gV2hlbiB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiBmdW5jdGlvbiBwbGVhc2UgZGVzaWduIHRoZSBuZXR3b3JrIHRvcG9sb2d5IHdpdGggY2FyZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUxpbmsgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNyZWF0ZUxpbmtcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgQ2FzY2FkZSBDb25uZWN0aW9uIFNldHRpbmcuIFVzZSB0aGlzIHRvIGdldCB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nIG9mIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGNoYW5nZSB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nIGNvbnRlbnRzIG9mIHRoZSBDYXNjYWRlIENvbm5lY3Rpb24sIHVzZSB0aGUgQVBJcyB0aGF0IGluY2x1ZGUgdGhlIG5hbWUgXCJMaW5rXCIgYWZ0ZXIgY3JlYXRpbmcgdGhlIENhc2NhZGUgQ29ubmVjdGlvbi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldExpbmsgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldExpbmtcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIENoYW5nZSBFeGlzdGluZyBDYXNjYWRlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGFsdGVyIHRoZSBzZXR0aW5nIG9mIGFuIGV4aXN0aW5nIENhc2NhZGUgQ29ubmVjdGlvbiBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpcy5TZXRMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBDYXNjYWRlIENvbm5lY3Rpb25zLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIENhc2NhZGUgQ29ubmVjdGlvbnMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIEJ5IHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uLCB5b3UgY2FuIGNvbm5lY3QgdGhpcyBWaXJ0dWFsIEh1YiBieSBMYXllciAyIENhc2NhZGUgQ29ubmVjdGlvbiB0byBhbm90aGVyIFZpcnR1YWwgSHViIHRoYXQgaXMgb3BlcmF0aW5nIG9uIHRoZSBzYW1lIG9yIGEgZGlmZmVyZW50IGNvbXB1dGVyLiBbV2FybmluZyBBYm91dCBDYXNjYWRlIENvbm5lY3Rpb25zXSBCeSBjb25uZWN0aW5nIHVzaW5nIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHlvdSBjYW4gY3JlYXRlIGEgTGF5ZXIgMiBicmlkZ2UgYmV0d2VlbiBtdWx0aXBsZSBWaXJ0dWFsIEh1YnMgYnV0IGlmIHRoZSBjb25uZWN0aW9uIGlzIGluY29ycmVjdGx5IGNvbmZpZ3VyZWQsIGEgbG9vcGJhY2sgQ2FzY2FkZSBDb25uZWN0aW9uIGNvdWxkIGluYWR2ZXJ0ZW50bHkgYmUgY3JlYXRlZC4gV2hlbiB1c2luZyBhIENhc2NhZGUgQ29ubmVjdGlvbiBmdW5jdGlvbiBwbGVhc2UgZGVzaWduIHRoZSBuZXR3b3JrIHRvcG9sb2d5IHdpdGggY2FyZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1MaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTGlua1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU3dpdGNoIENhc2NhZGUgQ29ubmVjdGlvbiB0byBPbmxpbmUgU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCwgdXNlIHRoaXMgdG8gc3dpdGNoIHRoYXQgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIG9ubGluZSBzdGF0dXMuIFRoZSBDYXNjYWRlIENvbm5lY3Rpb24gdGhhdCBpcyBzd2l0Y2hlZCB0byBvbmxpbmUgc3RhdHVzIGJlZ2lucyB0aGUgcHJvY2VzcyBvZiBjb25uZWN0aW5nIHRvIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ29ubmVjdGlvbiBTZXR0aW5nLiBUaGUgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgc3dpdGNoZWQgdG8gb25saW5lIHN0YXR1cyB3aWxsIGVzdGFibGlzaCBub3JtYWwgY29ubmVjdGlvbiB0byB0aGUgVlBOIFNlcnZlciBvciBjb250aW51ZSB0byBhdHRlbXB0IGNvbm5lY3Rpb24gdW50aWwgaXQgaXMgc3dpdGNoZWQgdG8gb2ZmbGluZSBzdGF0dXMuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRMaW5rT25saW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rT25saW5lXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTd2l0Y2ggQ2FzY2FkZSBDb25uZWN0aW9uIHRvIE9mZmxpbmUgU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCwgdXNlIHRoaXMgdG8gc3dpdGNoIHRoYXQgQ2FzY2FkZSBDb25uZWN0aW9uIHRvIG9mZmxpbmUgc3RhdHVzLiBUaGUgQ2FzY2FkZSBDb25uZWN0aW9uIHRoYXQgaXMgc3dpdGNoZWQgdG8gb2ZmbGluZSB3aWxsIG5vdCBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIHVudGlsIG5leHQgdGltZSBpdCBpcyBzd2l0Y2hlZCB0byB0aGUgb25saW5lIHN0YXR1cyB1c2luZyB0aGUgU2V0TGlua09ubGluZSBBUEkgWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldExpbmtPZmZsaW5lID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRMaW5rT2ZmbGluZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRGVsZXRlIENhc2NhZGUgQ29ubmVjdGlvbiBTZXR0aW5nLiBVc2UgdGhpcyB0byBkZWxldGUgYSBDYXNjYWRlIENvbm5lY3Rpb24gdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gSWYgdGhlIHNwZWNpZmllZCBDYXNjYWRlIENvbm5lY3Rpb24gaGFzIGEgc3RhdHVzIG9mIG9ubGluZSwgdGhlIGNvbm5lY3Rpb25zIHdpbGwgYmUgYXV0b21hdGljYWxseSBkaXNjb25uZWN0ZWQgYW5kIHRoZW4gdGhlIENhc2NhZGUgQ29ubmVjdGlvbiB3aWxsIGJlIGRlbGV0ZWQuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5EZWxldGVMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDaGFuZ2UgTmFtZSBvZiBDYXNjYWRlIENvbm5lY3Rpb24uIFdoZW4gYSBDYXNjYWRlIENvbm5lY3Rpb24gcmVnaXN0ZXJlZCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgaXMgc3BlY2lmaWVkLCB1c2UgdGhpcyB0byBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhhdCBDYXNjYWRlIENvbm5lY3Rpb24uIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5SZW5hbWVMaW5rID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJSZW5hbWVMaW5rXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQ3VycmVudCBDYXNjYWRlIENvbm5lY3Rpb24gU3RhdHVzLiBXaGVuIGEgQ2FzY2FkZSBDb25uZWN0aW9uIHJlZ2lzdGVyZWQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGlzIHNwZWNpZmllZCBhbmQgdGhhdCBDYXNjYWRlIENvbm5lY3Rpb24gaXMgY3VycmVudGx5IG9ubGluZSwgdXNlIHRoaXMgdG8gZ2V0IGl0cyBjb25uZWN0aW9uIHN0YXR1cyBhbmQgb3RoZXIgaW5mb3JtYXRpb24uIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRMaW5rU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRMaW5rU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBBZGQgQWNjZXNzIExpc3QgUnVsZS4gVXNlIHRoaXMgdG8gYWRkIGEgbmV3IHJ1bGUgdG8gdGhlIGFjY2VzcyBsaXN0IG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGFjY2VzcyBsaXN0IGlzIGEgc2V0IG9mIHBhY2tldCBmaWxlIHJ1bGVzIHRoYXQgYXJlIGFwcGxpZWQgdG8gcGFja2V0cyB0aGF0IGZsb3cgdGhyb3VnaCB0aGUgVmlydHVhbCBIdWIuIFlvdSBjYW4gcmVnaXN0ZXIgbXVsdGlwbGUgcnVsZXMgaW4gYW4gYWNjZXNzIGxpc3QgYW5kIHlvdSBjYW4gYWxzbyBkZWZpbmUgYW4gcHJpb3JpdHkgZm9yIGVhY2ggcnVsZS4gQWxsIHBhY2tldHMgYXJlIGNoZWNrZWQgZm9yIHRoZSBjb25kaXRpb25zIHNwZWNpZmllZCBieSB0aGUgcnVsZXMgcmVnaXN0ZXJlZCBpbiB0aGUgYWNjZXNzIGxpc3QgYW5kIGJhc2VkIG9uIHRoZSBvcGVyYXRpb24gdGhhdCBpcyBzdGlwdWxhdGVkIGJ5IHRoZSBmaXJzdCBtYXRjaGluZyBydWxlLCB0aGV5IGVpdGhlciBwYXNzIG9yIGFyZSBkaXNjYXJkZWQuIFBhY2tldHMgdGhhdCBkbyBub3QgbWF0Y2ggYW55IHJ1bGUgYXJlIGltcGxpY2l0bHkgYWxsb3dlZCB0byBwYXNzLiBZb3UgY2FuIGFsc28gdXNlIHRoZSBhY2Nlc3MgbGlzdCB0byBnZW5lcmF0ZSBkZWxheXMsIGppdHRlcnMgYW5kIHBhY2tldCBsb3NzZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQWRkQWNjZXNzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJBZGRBY2Nlc3NcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBSdWxlIGZyb20gQWNjZXNzIExpc3QuIFVzZSB0aGlzIHRvIHNwZWNpZnkgYSBwYWNrZXQgZmlsdGVyIHJ1bGUgcmVnaXN0ZXJlZCBvbiB0aGUgYWNjZXNzIGxpc3Qgb2YgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBkZWxldGUgaXQuIFRvIGRlbGV0ZSBhIHJ1bGUsIHlvdSBtdXN0IHNwZWNpZnkgdGhhdCBydWxlJ3MgSUQuIFlvdSBjYW4gZGlzcGxheSB0aGUgSUQgYnkgdXNpbmcgdGhlIEVudW1BY2Nlc3MgQVBJLiBJZiB5b3Ugd2lzaCBub3QgdG8gZGVsZXRlIHRoZSBydWxlIGJ1dCB0byBvbmx5IHRlbXBvcmFyaWx5IGRpc2FibGUgaXQsIHVzZSB0aGUgU2V0QWNjZXNzTGlzdCBBUEkgdG8gc2V0IHRoZSBydWxlIHN0YXR1cyB0byBkaXNhYmxlLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUFjY2VzcyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlQWNjZXNzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgQWNjZXNzIExpc3QgUnVsZSBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIHBhY2tldCBmaWx0ZXIgcnVsZXMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiBhY2Nlc3MgbGlzdCBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSBhY2Nlc3MgbGlzdCBpcyBhIHNldCBvZiBwYWNrZXQgZmlsZSBydWxlcyB0aGF0IGFyZSBhcHBsaWVkIHRvIHBhY2tldHMgdGhhdCBmbG93IHRocm91Z2ggdGhlIFZpcnR1YWwgSHViLiBZb3UgY2FuIHJlZ2lzdGVyIG11bHRpcGxlIHJ1bGVzIGluIGFuIGFjY2VzcyBsaXN0IGFuZCB5b3UgY2FuIGFsc28gZGVmaW5lIGEgcHJpb3JpdHkgZm9yIGVhY2ggcnVsZS4gQWxsIHBhY2tldHMgYXJlIGNoZWNrZWQgZm9yIHRoZSBjb25kaXRpb25zIHNwZWNpZmllZCBieSB0aGUgcnVsZXMgcmVnaXN0ZXJlZCBpbiB0aGUgYWNjZXNzIGxpc3QgYW5kIGJhc2VkIG9uIHRoZSBvcGVyYXRpb24gdGhhdCBpcyBzdGlwdWxhdGVkIGJ5IHRoZSBmaXJzdCBtYXRjaGluZyBydWxlLCB0aGV5IGVpdGhlciBwYXNzIG9yIGFyZSBkaXNjYXJkZWQuIFBhY2tldHMgdGhhdCBkbyBub3QgbWF0Y2ggYW55IHJ1bGUgYXJlIGltcGxpY2l0bHkgYWxsb3dlZCB0byBwYXNzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1BY2Nlc3MgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1BY2Nlc3NcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFJlcGxhY2UgYWxsIGFjY2VzcyBsaXN0cyBvbiBhIHNpbmdsZSBidWxrIEFQSSBjYWxsLiBUaGlzIEFQSSByZW1vdmVzIGFsbCBleGlzdGluZyBhY2Nlc3MgbGlzdCBydWxlcyBvbiB0aGUgVmlydHVhbCBIdWIsIGFuZCByZXBsYWNlIHRoZW0gYnkgbmV3IGFjY2VzcyBsaXN0IHJ1bGVzIHNwZWNpZmllZCBieSB0aGUgcGFyYW1ldGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0QWNjZXNzTGlzdCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0QWNjZXNzTGlzdFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ3JlYXRlIGEgdXNlci4gVXNlIHRoaXMgdG8gY3JlYXRlIGEgbmV3IHVzZXIgaW4gdGhlIHNlY3VyaXR5IGFjY291bnQgZGF0YWJhc2Ugb2YgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBCeSBjcmVhdGluZyBhIHVzZXIsIHRoZSBWUE4gQ2xpZW50IGNhbiBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1YiBieSB1c2luZyB0aGUgYXV0aGVudGljYXRpb24gaW5mb3JtYXRpb24gb2YgdGhhdCB1c2VyLiBOb3RlIHRoYXQgYSB1c2VyIHdob3NlIHVzZXIgbmFtZSBoYXMgYmVlbiBjcmVhdGVkIGFzIFwiKlwiIChhIHNpbmdsZSBhc3RlcmlzayBjaGFyYWN0ZXIpIHdpbGwgYXV0b21hdGljYWxseSBiZSByZWdpc3RlcmVkIGFzIGEgUkFESVVTIGF1dGhlbnRpY2F0aW9uIHVzZXIuIEZvciBjYXNlcyB3aGVyZSB0aGVyZSBhcmUgdXNlcnMgd2l0aCBcIipcIiBhcyB0aGUgbmFtZSwgd2hlbiBhIHVzZXIsIHdob3NlIHVzZXIgbmFtZSB0aGF0IGhhcyBiZWVuIHByb3ZpZGVkIHdoZW4gYSBjbGllbnQgY29ubmVjdGVkIHRvIGEgVlBOIFNlcnZlciBkb2VzIG5vdCBtYXRjaCBleGlzdGluZyB1c2VyIG5hbWVzLCBpcyBhYmxlIHRvIGJlIGF1dGhlbnRpY2F0ZWQgYnkgYSBSQURJVVMgc2VydmVyIG9yIE5UIGRvbWFpbiBjb250cm9sbGVyIGJ5IGlucHV0dGluZyBhIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQsIHRoZSBhdXRoZW50aWNhdGlvbiBzZXR0aW5ncyBhbmQgc2VjdXJpdHkgcG9saWN5IHNldHRpbmdzIHdpbGwgZm9sbG93IHRoZSBzZXR0aW5nIGZvciB0aGUgdXNlciBcIipcIi4gVG8gY2hhbmdlIHRoZSB1c2VyIGluZm9ybWF0aW9uIG9mIGEgdXNlciB0aGF0IGhhcyBiZWVuIGNyZWF0ZWQsIHVzZSB0aGUgU2V0VXNlciBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlVXNlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQ3JlYXRlVXNlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIFVzZXIgU2V0dGluZ3MuIFVzZSB0aGlzIHRvIGNoYW5nZSB1c2VyIHNldHRpbmdzIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSB1c2VyIHNldHRpbmdzIHRoYXQgY2FuIGJlIGNoYW5nZWQgdXNpbmcgdGhpcyBBUEkgYXJlIHRoZSB0aHJlZSBpdGVtcyB0aGF0IGFyZSBzcGVjaWZpZWQgd2hlbiBhIG5ldyB1c2VyIGlzIGNyZWF0ZWQgdXNpbmcgdGhlIENyZWF0ZVVzZXIgQVBJOiBHcm91cCBOYW1lLCBGdWxsIE5hbWUsIGFuZCBEZXNjcmlwdGlvbi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHVzZXJzLCB1c2UgdGhlIEVudW1Vc2VyIEFQSS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRVc2VyID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRVc2VyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgVXNlciBTZXR0aW5ncy4gVXNlIHRoaXMgdG8gZ2V0IHVzZXIgc2V0dGluZ3MgaW5mb3JtYXRpb24gdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIGluZm9ybWF0aW9uIHRoYXQgeW91IGNhbiBnZXQgdXNpbmcgdGhpcyBBUEkgYXJlIFVzZXIgTmFtZSwgRnVsbCBOYW1lLCBHcm91cCBOYW1lLCBFeHBpcmF0aW9uIERhdGUsIFNlY3VyaXR5IFBvbGljeSwgYW5kIEF1dGggVHlwZSwgYXMgd2VsbCBhcyBwYXJhbWV0ZXJzIHRoYXQgYXJlIHNwZWNpZmllZCBhcyBhdXRoIHR5cGUgYXR0cmlidXRlcyBhbmQgdGhlIHN0YXRpc3RpY2FsIGRhdGEgb2YgdGhhdCB1c2VyLiBUbyBnZXQgdGhlIGxpc3Qgb2YgY3VycmVudGx5IHJlZ2lzdGVyZWQgdXNlcnMsIHVzZSB0aGUgRW51bVVzZXIgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldFVzZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFVzZXJcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBhIHVzZXIuIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHVzZXIgdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgZGVsZXRpbmcgdGhlIHVzZXIsIHRoYXQgdXNlciB3aWxsIG5vIGxvbmcgYmUgYWJsZSB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1Yi4gWW91IGNhbiB1c2UgdGhlIFNldFVzZXIgQVBJIHRvIHNldCB0aGUgdXNlcidzIHNlY3VyaXR5IHBvbGljeSB0byBkZW55IGFjY2VzcyBpbnN0ZWFkIG9mIGRlbGV0aW5nIGEgdXNlciwgc2V0IHRoZSB1c2VyIHRvIGJlIHRlbXBvcmFyaWx5IGRlbmllZCBmcm9tIGxvZ2dpbmcgaW4uIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgcmVnaXN0ZXJlZCB1c2VycywgdXNlIHRoZSBFbnVtVXNlciBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRGVsZXRlVXNlciA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlVXNlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgVXNlcnMuIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgdXNlcnMgdGhhdCBhcmUgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIG1lbWJlciBzZXJ2ZXIgb24gYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bVVzZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1Vc2VyXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBDcmVhdGUgR3JvdXAuIFVzZSB0aGlzIHRvIGNyZWF0ZSBhIG5ldyBncm91cCBpbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFlvdSBjYW4gcmVnaXN0ZXIgbXVsdGlwbGUgdXNlcnMgaW4gYSBncm91cC4gVG8gcmVnaXN0ZXIgdXNlcnMgaW4gYSBncm91cCB1c2UgdGhlIFNldFVzZXIgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZUdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJDcmVhdGVHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IGdyb3VwIHNldHRpbmdzLiBVc2UgdGhpcyB0byBzZXQgZ3JvdXAgc2V0dGluZ3MgdGhhdCBpcyByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIGdyb3VwcywgdXNlIHRoZSBFbnVtR3JvdXAgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IEdyb3VwIFNldHRpbmcgKFN5bmMgbW9kZSkuIFVzZSB0aGlzIHRvIGdldCB0aGUgc2V0dGluZyBvZiBhIGdyb3VwIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgcmVnaXN0ZXJlZCBncm91cHMsIHVzZSB0aGUgRW51bUdyb3VwIEFQSS4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRHcm91cCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0R3JvdXBcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBVc2VyIGZyb20gR3JvdXAuIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHNwZWNpZmllZCB1c2VyIGZyb20gdGhlIGdyb3VwIHRoYXQgaXMgcmVnaXN0ZXJlZCBvbiB0aGUgc2VjdXJpdHkgYWNjb3VudCBkYXRhYmFzZSBvZiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIEJ5IGRlbGV0aW5nIGEgdXNlciBmcm9tIHRoZSBncm91cCwgdGhhdCB1c2VyIGJlY29tZXMgdW5hc3NpZ25lZC4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIGdyb3VwcywgdXNlIHRoZSBFbnVtR3JvdXAgQVBJLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBtZW1iZXIgc2VydmVyIG9uIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUdyb3VwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVHcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgR3JvdXBzLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIGdyb3VwcyB0aGF0IGFyZSByZWdpc3RlcmVkIG9uIHRoZSBzZWN1cml0eSBhY2NvdW50IGRhdGFiYXNlIG9mIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgbWVtYmVyIHNlcnZlciBvbiBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5FbnVtR3JvdXAgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1Hcm91cFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgQ29ubmVjdGVkIFZQTiBTZXNzaW9ucy4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiB0aGUgc2Vzc2lvbnMgY29ubmVjdGVkIHRvIHRoZSBWaXJ0dWFsIEh1YiBjdXJyZW50bHkgYmVpbmcgbWFuYWdlZC4gSW4gdGhlIGxpc3Qgb2Ygc2Vzc2lvbnMsIHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb24gd2lsbCBiZSBvYnRhaW5lZCBmb3IgZWFjaCBjb25uZWN0aW9uOiBTZXNzaW9uIE5hbWUsIFNlc3Npb24gU2l0ZSwgVXNlciBOYW1lLCBTb3VyY2UgSG9zdCBOYW1lLCBUQ1AgQ29ubmVjdGlvbiwgVHJhbnNmZXIgQnl0ZXMgYW5kIFRyYW5zZmVyIFBhY2tldHMuIElmIHRoZSBjdXJyZW50bHkgY29ubmVjdGVkIFZQTiBTZXJ2ZXIgaXMgYSBjbHVzdGVyIGNvbnRyb2xsZXIgYW5kIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBpcyBhIHN0YXRpYyBWaXJ0dWFsIEh1YiwgeW91IGNhbiBnZXQgYW4gYWxsLWxpbmtlZC10b2dldGhlciBsaXN0IG9mIGFsbCBzZXNzaW9ucyBjb25uZWN0ZWQgdG8gdGhhdCBWaXJ0dWFsIEh1YiBvbiBhbGwgY2x1c3RlciBtZW1iZXJzLiBJbiBhbGwgb3RoZXIgY2FzZXMsIG9ubHkgdGhlIGxpc3Qgb2Ygc2Vzc2lvbnMgdGhhdCBhcmUgYWN0dWFsbHkgY29ubmVjdGVkIHRvIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWUE4gU2VydmVyIHdpbGwgYmUgb2J0YWluZWQuICovXHJcbiAgICAgICAgdGhpcy5FbnVtU2Vzc2lvbiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bVNlc3Npb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBTZXNzaW9uIFN0YXR1cy4gVXNlIHRoaXMgdG8gc3BlY2lmeSBhIHNlc3Npb24gY3VycmVudGx5IGNvbm5lY3RlZCB0byB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIGdldCB0aGUgc2Vzc2lvbiBpbmZvcm1hdGlvbi4gVGhlIHNlc3Npb24gc3RhdHVzIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmc6IHNvdXJjZSBob3N0IG5hbWUgYW5kIHVzZXIgbmFtZSwgdmVyc2lvbiBpbmZvcm1hdGlvbiwgdGltZSBpbmZvcm1hdGlvbiwgbnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucywgY29tbXVuaWNhdGlvbiBwYXJhbWV0ZXJzLCBzZXNzaW9uIGtleSwgc3RhdGlzdGljYWwgaW5mb3JtYXRpb24gb24gZGF0YSB0cmFuc2ZlcnJlZCwgYW5kIG90aGVyIGNsaWVudCBhbmQgc2VydmVyIGluZm9ybWF0aW9uLiBUbyBnZXQgdGhlIGxpc3Qgb2YgY3VycmVudGx5IGNvbm5lY3RlZCBzZXNzaW9ucywgdXNlIHRoZSBFbnVtU2Vzc2lvbiBBUEkuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZXNzaW9uU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRTZXNzaW9uU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEaXNjb25uZWN0IFNlc3Npb24uIFVzZSB0aGlzIHRvIHNwZWNpZnkgYSBzZXNzaW9uIGN1cnJlbnRseSBjb25uZWN0ZWQgdG8gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBmb3JjZWZ1bGx5IGRpc2Nvbm5lY3QgdGhhdCBzZXNzaW9uIHVzaW5nIG1hbmFnZXIgcHJpdmlsZWdlcy4gTm90ZSB0aGF0IHdoZW4gY29tbXVuaWNhdGlvbiBpcyBkaXNjb25uZWN0ZWQgYnkgc2V0dGluZ3Mgb24gdGhlIHNvdXJjZSBjbGllbnQgc2lkZSBhbmQgdGhlIGF1dG9tYXRpY2FsbHkgcmVjb25uZWN0IG9wdGlvbiBpcyBlbmFibGVkLCBpdCBpcyBwb3NzaWJsZSB0aGF0IHRoZSBjbGllbnQgd2lsbCByZWNvbm5lY3QuIFRvIGdldCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgY29ubmVjdGVkIHNlc3Npb25zLCB1c2UgdGhlIEVudW1TZXNzaW9uIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZVNlc3Npb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbGV0ZVNlc3Npb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgTUFDIEFkZHJlc3MgVGFibGUgRGF0YWJhc2UuIFVzZSB0aGlzIHRvIGdldCB0aGUgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdGhhdCBpcyBoZWxkIGJ5IHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIE1BQyBhZGRyZXNzIHRhYmxlIGRhdGFiYXNlIGlzIGEgdGFibGUgdGhhdCB0aGUgVmlydHVhbCBIdWIgcmVxdWlyZXMgdG8gcGVyZm9ybSB0aGUgYWN0aW9uIG9mIHN3aXRjaGluZyBFdGhlcm5ldCBmcmFtZXMgYW5kIHRoZSBWaXJ0dWFsIEh1YiBkZWNpZGVzIHRoZSBzb3J0aW5nIGRlc3RpbmF0aW9uIHNlc3Npb24gb2YgZWFjaCBFdGhlcm5ldCBmcmFtZSBiYXNlZCBvbiB0aGUgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UuIFRoZSBNQUMgYWRkcmVzcyBkYXRhYmFzZSBpcyBidWlsdCBieSB0aGUgVmlydHVhbCBIdWIgYXV0b21hdGljYWxseSBhbmFseXppbmcgdGhlIGNvbnRlbnRzIG9mIHRoZSBjb21tdW5pY2F0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bU1hY1RhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTWFjVGFibGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBNQUMgQWRkcmVzcyBUYWJsZSBFbnRyeS4gVXNlIHRoaXMgQVBJIHRvIG9wZXJhdGUgdGhlIE1BQyBhZGRyZXNzIHRhYmxlIGRhdGFiYXNlIGhlbGQgYnkgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViIGFuZCBkZWxldGUgYSBzcGVjaWZpZWQgTUFDIGFkZHJlc3MgdGFibGUgZW50cnkgZnJvbSB0aGUgZGF0YWJhc2UuIFRvIGdldCB0aGUgY29udGVudHMgb2YgdGhlIGN1cnJlbnQgTUFDIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdXNlIHRoZSBFbnVtTWFjVGFibGUgQVBJLiAqL1xyXG4gICAgICAgIHRoaXMuRGVsZXRlTWFjVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbGV0ZU1hY1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIElQIEFkZHJlc3MgVGFibGUgRGF0YWJhc2UuIFVzZSB0aGlzIHRvIGdldCB0aGUgSVAgYWRkcmVzcyB0YWJsZSBkYXRhYmFzZSB0aGF0IGlzIGhlbGQgYnkgdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgSVAgYWRkcmVzcyB0YWJsZSBkYXRhYmFzZSBpcyBhIHRhYmxlIHRoYXQgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYnkgYW5hbHl6aW5nIHRoZSBjb250ZW50cyBvZiBjb21tdW5pY2F0aW9uIHNvIHRoYXQgdGhlIFZpcnR1YWwgSHViIGNhbiBhbHdheXMga25vdyB3aGljaCBzZXNzaW9uIGlzIHVzaW5nIHdoaWNoIElQIGFkZHJlc3MgYW5kIGl0IGlzIGZyZXF1ZW50bHkgdXNlZCBieSB0aGUgZW5naW5lIHRoYXQgYXBwbGllcyB0aGUgVmlydHVhbCBIdWIgc2VjdXJpdHkgcG9saWN5LiBCeSBzcGVjaWZ5aW5nIHRoZSBzZXNzaW9uIG5hbWUgeW91IGNhbiBnZXQgdGhlIElQIGFkZHJlc3MgdGFibGUgZW50cnkgdGhhdCBoYXMgYmVlbiBhc3NvY2lhdGVkIHdpdGggdGhhdCBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUlwVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1JcFRhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgSVAgQWRkcmVzcyBUYWJsZSBFbnRyeS4gVXNlIHRoaXMgQVBJIHRvIG9wZXJhdGUgdGhlIElQIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgaGVsZCBieSB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIgYW5kIGRlbGV0ZSBhIHNwZWNpZmllZCBJUCBhZGRyZXNzIHRhYmxlIGVudHJ5IGZyb20gdGhlIGRhdGFiYXNlLiBUbyBnZXQgdGhlIGNvbnRlbnRzIG9mIHRoZSBjdXJyZW50IElQIGFkZHJlc3MgdGFibGUgZGF0YWJhc2UgdXNlIHRoZSBFbnVtSXBUYWJsZSBBUEkuICovXHJcbiAgICAgICAgdGhpcy5EZWxldGVJcFRhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVJcFRhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gc2V0IHRoZSBkZXN0aW5hdGlvbiBob3N0IG5hbWUgZXRjLiBvZiB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLiBGb3IgbmV0d29yayBjb25uZWN0aW9uIGVudmlyb25tZW50cyB3aGVyZSBjb25uZWN0aW9ucyB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzY29ubmVjdGVkIHdoZXJlIHRoZXJlIGFyZSBwZXJpb2RzIG9mIG5vIGNvbW11bmljYXRpb24gdGhhdCBhcmUgbG9uZ2VyIHRoYW4gYSBzZXQgcGVyaW9kLCBieSB1c2luZyB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLCBpdCBpcyBwb3NzaWJsZSB0byBrZWVwIGFsaXZlIHRoZSBJbnRlcm5ldCBjb25uZWN0aW9uIGJ5IHNlbmRpbmcgcGFja2V0cyB0byBhIG5vbWluYXRlZCBzZXJ2ZXIgb24gdGhlIEludGVybmV0IGF0IHNldCBpbnRlcnZhbHMuIFdoZW4gdXNpbmcgdGhpcyBBUEksIHlvdSBjYW4gc3BlY2lmeSB0aGUgZm9sbG93aW5nOiBIb3N0IE5hbWUsIFBvcnQgTnVtYmVyLCBQYWNrZXQgU2VuZCBJbnRlcnZhbCwgYW5kIFByb3RvY29sLiBQYWNrZXRzIHNlbnQgdG8ga2VlcCBhbGl2ZSB0aGUgSW50ZXJuZXQgY29ubmVjdGlvbiB3aWxsIGhhdmUgcmFuZG9tIGNvbnRlbnQgYW5kIHBlcnNvbmFsIGluZm9ybWF0aW9uIHRoYXQgY291bGQgaWRlbnRpZnkgYSBjb21wdXRlciBvciB1c2VyIGlzIG5vdCBzZW50LiBZb3UgY2FuIHVzZSB0aGUgU2V0S2VlcCBBUEkgdG8gZW5hYmxlL2Rpc2FibGUgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVG8gZXhlY3V0ZSB0aGlzIEFQSSBvbiBhIFZQTiBTZXJ2ZXIgb3IgVlBOIEJyaWRnZSwgeW91IG11c3QgaGF2ZSBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5TZXRLZWVwID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRLZWVwXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgY29udGVudHMgb2YgdGhlIEtlZXAgQWxpdmUgSW50ZXJuZXQgQ29ubmVjdGlvbiBGdW5jdGlvbi4gSW4gYWRkaXRpb24gdG8gdGhlIGRlc3RpbmF0aW9uJ3MgSG9zdCBOYW1lLCBQb3J0IE51bWJlciwgUGFja2V0IFNlbmQgSW50ZXJ2YWwgYW5kIFByb3RvY29sLCB5b3UgY2FuIG9idGFpbiB0aGUgY3VycmVudCBlbmFibGVkL2Rpc2FibGVkIHN0YXR1cyBvZiB0aGUgS2VlcCBBbGl2ZSBJbnRlcm5ldCBDb25uZWN0aW9uIEZ1bmN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0S2VlcCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0S2VlcFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRW5hYmxlIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgRnVuY3Rpb24gKFNlY3VyZU5BVCBGdW5jdGlvbikuIFVzZSB0aGlzIHRvIGVuYWJsZSB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1YiBhbmQgYmVnaW4gaXRzIG9wZXJhdGlvbi4gQmVmb3JlIGV4ZWN1dGluZyB0aGlzIEFQSSwgeW91IG11c3QgZmlyc3QgY2hlY2sgdGhlIHNldHRpbmcgY29udGVudHMgb2YgdGhlIGN1cnJlbnQgVmlydHVhbCBOQVQgZnVuY3Rpb24gYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIHVzaW5nIHRoZSBTZXRTZWN1cmVOQVRPcHRpb24gQVBJIGFuZCBHZXRTZWN1cmVOQVRPcHRpb24gQVBJLiBCeSBlbmFibGluZyB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCB5b3UgY2FuIHZpcnR1YWxseSBvcGVyYXRlIGEgTkFUIHJvdXRlciAoSVAgbWFzcXVlcmFkZSkgYW5kIHRoZSBESENQIFNlcnZlciBmdW5jdGlvbiBvbiBhIHZpcnR1YWwgbmV0d29yayBvbiB0aGUgVmlydHVhbCBIdWIuIFtXYXJuaW5nIGFib3V0IFNlY3VyZU5BVCBGdW5jdGlvbl0gVGhlIFNlY3VyZU5BVCBmdW5jdGlvbiBpcyByZWNvbW1lbmRlZCBvbmx5IGZvciBzeXN0ZW0gYWRtaW5pc3RyYXRvcnMgYW5kIHBlb3BsZSB3aXRoIGEgZGV0YWlsZWQga25vd2xlZGdlIG9mIG5ldHdvcmtzLiBJZiB5b3UgdXNlIHRoZSBTZWN1cmVOQVQgZnVuY3Rpb24gY29ycmVjdGx5LCBpdCBpcyBwb3NzaWJsZSB0byBhY2hpZXZlIGEgc2FmZSBmb3JtIG9mIHJlbW90ZSBhY2Nlc3MgdmlhIGEgVlBOLiBIb3dldmVyIHdoZW4gdXNlZCBpbiB0aGUgd3Jvbmcgd2F5LCBpdCBjYW4gcHV0IHRoZSBlbnRpcmUgbmV0d29yayBpbiBkYW5nZXIuIEFueW9uZSB3aG8gZG9lcyBub3QgaGF2ZSBhIHRob3JvdWdoIGtub3dsZWRnZSBvZiBuZXR3b3JrcyBhbmQgYW55b25lIHdobyBkb2VzIG5vdCBoYXZlIHRoZSBuZXR3b3JrIGFkbWluaXN0cmF0b3IncyBwZXJtaXNzaW9uIG11c3Qgbm90IGVuYWJsZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLiBGb3IgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIFZQTiBTZXJ2ZXIncyBtYW51YWwgYW5kIG9ubGluZSBkb2N1bWVudGF0aW9uLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlU2VjdXJlTkFUID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbmFibGVTZWN1cmVOQVRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERpc2FibGUgdGhlIFZpcnR1YWwgTkFUIGFuZCBESENQIFNlcnZlciBGdW5jdGlvbiAoU2VjdXJlTkFUIEZ1bmN0aW9uKS4gVXNlIHRoaXMgdG8gZGlzYWJsZSB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgZXhlY3V0aW5nIHRoaXMgQVBJIHRoZSBWaXJ0dWFsIE5BVCBmdW5jdGlvbiBpbW1lZGlhdGVseSBzdG9wcyBvcGVyYXRpbmcgYW5kIHRoZSBWaXJ0dWFsIERIQ1AgU2VydmVyIGZ1bmN0aW9uIGRlbGV0ZXMgdGhlIERIQ1AgbGVhc2UgZGF0YWJhc2UgYW5kIHN0b3BzIHRoZSBzZXJ2aWNlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuRGlzYWJsZVNlY3VyZU5BVCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGlzYWJsZVNlY3VyZU5BVFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIFNldHRpbmdzIG9mIFNlY3VyZU5BVCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gY2hhbmdlIGFuZCBzYXZlIHRoZSB2aXJ0dWFsIGhvc3QgbmV0d29yayBpbnRlcmZhY2Ugc2V0dGluZ3MsIHZpcnR1YWwgTkFUIGZ1bmN0aW9uIHNldHRpbmdzIGFuZCB2aXJ0dWFsIERIQ1Agc2VydmVyIHNldHRpbmdzIG9mIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgZnVuY3Rpb24gKFNlY3VyZU5BVCBmdW5jdGlvbikgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgU2VjdXJlTkFUIGZ1bmN0aW9uIGhvbGRzIG9uZSB2aXJ0dWFsIG5ldHdvcmsgYWRhcHRlciBvbiB0aGUgTDIgc2VnbWVudCBpbnNpZGUgdGhlIFZpcnR1YWwgSHViIGFuZCBpdCBoYXMgYmVlbiBhc3NpZ25lZCBhIE1BQyBhZGRyZXNzIGFuZCBhbiBJUCBhZGRyZXNzLiBCeSBkb2luZyB0aGlzLCBhbm90aGVyIGhvc3QgY29ubmVjdGVkIHRvIHRoZSBzYW1lIEwyIHNlZ21lbnQgaXMgYWJsZSB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBTZWN1cmVOQVQgdmlydHVhbCBob3N0IGFzIGlmIGl0IGlzIGFuIGFjdHVhbCBJUCBob3N0IGV4aXN0aW5nIG9uIHRoZSBuZXR3b3JrLiBbV2FybmluZyBhYm91dCBTZWN1cmVOQVQgRnVuY3Rpb25dIFRoZSBTZWN1cmVOQVQgZnVuY3Rpb24gaXMgcmVjb21tZW5kZWQgb25seSBmb3Igc3lzdGVtIGFkbWluaXN0cmF0b3JzIGFuZCBwZW9wbGUgd2l0aCBhIGRldGFpbGVkIGtub3dsZWRnZSBvZiBuZXR3b3Jrcy4gSWYgeW91IHVzZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uIGNvcnJlY3RseSwgaXQgaXMgcG9zc2libGUgdG8gYWNoaWV2ZSBhIHNhZmUgZm9ybSBvZiByZW1vdGUgYWNjZXNzIHZpYSBhIFZQTi4gSG93ZXZlciB3aGVuIHVzZWQgaW4gdGhlIHdyb25nIHdheSwgaXQgY2FuIHB1dCB0aGUgZW50aXJlIG5ldHdvcmsgaW4gZGFuZ2VyLiBBbnlvbmUgd2hvIGRvZXMgbm90IGhhdmUgYSB0aG9yb3VnaCBrbm93bGVkZ2Ugb2YgbmV0d29ya3MgYW5kIGFueW9uZSB3aG8gZG9lcyBub3QgaGF2ZSB0aGUgbmV0d29yayBhZG1pbmlzdHJhdG9ycyBwZXJtaXNzaW9uIG11c3Qgbm90IGVuYWJsZSB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLiBGb3IgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgU2VjdXJlTkFUIGZ1bmN0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIFZQTiBTZXJ2ZXIncyBtYW51YWwgYW5kIG9ubGluZSBkb2N1bWVudGF0aW9uLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0U2VjdXJlTkFUT3B0aW9uID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRTZWN1cmVOQVRPcHRpb25cIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBTZXR0aW5ncyBvZiBTZWN1cmVOQVQgRnVuY3Rpb24uIFRoaXMgQVBJIGdldCB0aGUgcmVnaXN0ZXJlZCBzZXR0aW5ncyBmb3IgdGhlIFNlY3VyZU5BVCBmdW5jdGlvbiB3aGljaCBpcyBzZXQgYnkgdGhlIFNldFNlY3VyZU5BVE9wdGlvbiBBUEkuICovXHJcbiAgICAgICAgdGhpcy5HZXRTZWN1cmVOQVRPcHRpb24gPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFNlY3VyZU5BVE9wdGlvblwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IFZpcnR1YWwgTkFUIEZ1bmN0aW9uIFNlc3Npb24gVGFibGUgb2YgU2VjdXJlTkFUIEZ1bmN0aW9uLiBVc2UgdGhpcyB0byBnZXQgdGhlIHRhYmxlIG9mIFRDUCBhbmQgVURQIHNlc3Npb25zIGN1cnJlbnRseSBjb21tdW5pY2F0aW5nIHZpYSB0aGUgVmlydHVhbCBOQVQgKE5BVCB0YWJsZSkgaW4gY2FzZXMgd2hlbiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1OQVQgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1OQVRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBWaXJ0dWFsIERIQ1AgU2VydmVyIEZ1bmN0aW9uIExlYXNlIFRhYmxlIG9mIFNlY3VyZU5BVCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gZ2V0IHRoZSBsZWFzZSB0YWJsZSBvZiBJUCBhZGRyZXNzZXMsIGhlbGQgYnkgdGhlIFZpcnR1YWwgREhDUCBTZXJ2ZXIsIHRoYXQgYXJlIGFzc2lnbmVkIHRvIGNsaWVudHMgaW4gY2FzZXMgd2hlbiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1ESENQID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtREhDUFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBPcGVyYXRpbmcgU3RhdHVzIG9mIHRoZSBWaXJ0dWFsIE5BVCBhbmQgREhDUCBTZXJ2ZXIgRnVuY3Rpb24gKFNlY3VyZU5BVCBGdW5jdGlvbikuIFVzZSB0aGlzIHRvIGdldCB0aGUgb3BlcmF0aW5nIHN0YXR1cyBvZiB0aGUgVmlydHVhbCBOQVQgYW5kIERIQ1AgU2VydmVyIGZ1bmN0aW9uIChTZWN1cmVOQVQgRnVuY3Rpb24pIHdoZW4gaXQgaXMgb3BlcmF0aW5nIG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldFNlY3VyZU5BVFN0YXR1cyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U2VjdXJlTkFUU3RhdHVzXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBOZXR3b3JrIEFkYXB0ZXJzIFVzYWJsZSBhcyBMb2NhbCBCcmlkZ2UuIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgRXRoZXJuZXQgZGV2aWNlcyAobmV0d29yayBhZGFwdGVycykgdGhhdCBjYW4gYmUgdXNlZCBhcyBhIGJyaWRnZSBkZXN0aW5hdGlvbiBkZXZpY2UgYXMgcGFydCBvZiBhIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uLiBJZiBwb3NzaWJsZSwgbmV0d29yayBjb25uZWN0aW9uIG5hbWUgaXMgZGlzcGxheWVkLiBZb3UgY2FuIHVzZSBhIGRldmljZSBkaXNwbGF5ZWQgaGVyZSBieSB1c2luZyB0aGUgQWRkTG9jYWxCcmlkZ2UgQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUV0aGVybmV0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUV0aGVybmV0XCIsIG5ldyBWcG5ScGNFbnVtRXRoKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIENyZWF0ZSBMb2NhbCBCcmlkZ2UgQ29ubmVjdGlvbi4gVXNlIHRoaXMgdG8gY3JlYXRlIGEgbmV3IExvY2FsIEJyaWRnZSBjb25uZWN0aW9uIG9uIHRoZSBWUE4gU2VydmVyLiBCeSB1c2luZyBhIExvY2FsIEJyaWRnZSwgeW91IGNhbiBjb25maWd1cmUgYSBMYXllciAyIGJyaWRnZSBjb25uZWN0aW9uIGJldHdlZW4gYSBWaXJ0dWFsIEh1YiBvcGVyYXRpbmcgb24gdGhpcyBWUE4gc2VydmVyIGFuZCBhIHBoeXNpY2FsIEV0aGVybmV0IERldmljZSAoTmV0d29yayBBZGFwdGVyKS4gWW91IGNhbiBjcmVhdGUgYSB0YXAgZGV2aWNlICh2aXJ0dWFsIG5ldHdvcmsgaW50ZXJmYWNlKSBvbiB0aGUgc3lzdGVtIGFuZCBjb25uZWN0IGEgYnJpZGdlIGJldHdlZW4gVmlydHVhbCBIdWJzICh0aGUgdGFwIGRldmljZSBpcyBvbmx5IHN1cHBvcnRlZCBieSBMaW51eCB2ZXJzaW9ucykuIEl0IGlzIHBvc3NpYmxlIHRvIGVzdGFibGlzaCBhIGJyaWRnZSB0byBhbiBvcGVyYXRpbmcgbmV0d29yayBhZGFwdGVyIG9mIHlvdXIgY2hvaWNlIGZvciB0aGUgYnJpZGdlIGRlc3RpbmF0aW9uIEV0aGVybmV0IGRldmljZSAobmV0d29yayBhZGFwdGVyKSwgYnV0IGluIGhpZ2ggbG9hZCBlbnZpcm9ubWVudHMsIHdlIHJlY29tbWVuZCB5b3UgcHJlcGFyZSBhIG5ldHdvcmsgYWRhcHRlciBkZWRpY2F0ZWQgdG8gc2VydmUgYXMgYSBicmlkZ2UuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5BZGRMb2NhbEJyaWRnZSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkTG9jYWxCcmlkZ2VcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBMb2NhbCBCcmlkZ2UgQ29ubmVjdGlvbi4gVXNlIHRoaXMgdG8gZGVsZXRlIGFuIGV4aXN0aW5nIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uLiBUbyBnZXQgYSBsaXN0IG9mIGN1cnJlbnQgTG9jYWwgQnJpZGdlIGNvbm5lY3Rpb25zIHVzZSB0aGUgRW51bUxvY2FsQnJpZGdlIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUxvY2FsQnJpZGdlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxldGVMb2NhbEJyaWRnZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgTG9jYWwgQnJpZGdlIENvbm5lY3Rpb24uIFVzZSB0aGlzIHRvIGdldCBhIGxpc3Qgb2YgdGhlIGN1cnJlbnRseSBkZWZpbmVkIExvY2FsIEJyaWRnZSBjb25uZWN0aW9ucy4gWW91IGNhbiBnZXQgdGhlIExvY2FsIEJyaWRnZSBjb25uZWN0aW9uIFZpcnR1YWwgSHViIG5hbWUgYW5kIHRoZSBicmlkZ2UgZGVzdGluYXRpb24gRXRoZXJuZXQgZGV2aWNlIChuZXR3b3JrIGFkYXB0ZXIpIG5hbWUgb3IgdGFwIGRldmljZSBuYW1lLCBhcyB3ZWxsIGFzIHRoZSBvcGVyYXRpbmcgc3RhdHVzLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUxvY2FsQnJpZGdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUxvY2FsQnJpZGdlXCIsIG5ldyBWcG5ScGNFbnVtTG9jYWxCcmlkZ2UoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHdoZXRoZXIgdGhlIGxvY2FsYnJpZGdlIGZ1bmN0aW9uIGlzIHN1cHBvcnRlZCBvbiB0aGUgY3VycmVudCBzeXN0ZW0uICovXHJcbiAgICAgICAgdGhpcy5HZXRCcmlkZ2VTdXBwb3J0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QnJpZGdlU3VwcG9ydFwiLCBuZXcgVnBuUnBjQnJpZGdlU3VwcG9ydCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBSZWJvb3QgVlBOIFNlcnZlciBTZXJ2aWNlLiBVc2UgdGhpcyB0byByZXN0YXJ0IHRoZSBWUE4gU2VydmVyIHNlcnZpY2UuIFdoZW4geW91IHJlc3RhcnQgdGhlIFZQTiBTZXJ2ZXIsIGFsbCBjdXJyZW50bHkgY29ubmVjdGVkIHNlc3Npb25zIGFuZCBUQ1AgY29ubmVjdGlvbnMgd2lsbCBiZSBkaXNjb25uZWN0ZWQgYW5kIG5vIG5ldyBjb25uZWN0aW9ucyB3aWxsIGJlIGFjY2VwdGVkIHVudGlsIHRoZSByZXN0YXJ0IHByb2Nlc3MgaGFzIGNvbXBsZXRlZC4gQnkgdXNpbmcgdGhpcyBBUEksIG9ubHkgdGhlIFZQTiBTZXJ2ZXIgc2VydmljZSBwcm9ncmFtIHdpbGwgYmUgcmVzdGFydGVkIGFuZCB0aGUgcGh5c2ljYWwgY29tcHV0ZXIgdGhhdCBWUE4gU2VydmVyIGlzIG9wZXJhdGluZyBvbiBkb2VzIG5vdCByZXN0YXJ0LiBUaGlzIG1hbmFnZW1lbnQgc2Vzc2lvbiB3aWxsIGFsc28gYmUgZGlzY29ubmVjdGVkLCBzbyB5b3Ugd2lsbCBuZWVkIHRvIHJlY29ubmVjdCB0byBjb250aW51ZSBtYW5hZ2VtZW50LiBBbHNvLCBieSBzcGVjaWZ5aW5nIHRoZSBcIkludFZhbHVlXCIgcGFyYW1ldGVyIHRvIFwiMVwiLCB0aGUgY29udGVudHMgb2YgdGhlIGNvbmZpZ3VyYXRpb24gZmlsZSAoLmNvbmZpZykgaGVsZCBieSB0aGUgY3VycmVudCBWUE4gU2VydmVyIHdpbGwgYmUgaW5pdGlhbGl6ZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5SZWJvb3RTZXJ2ZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlJlYm9vdFNlcnZlclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgU2VydmVyIEZ1bmN0aW9ucyAvIENhcGFiaWxpdHkuIFVzZSB0aGlzIGdldCBhIGxpc3Qgb2YgZnVuY3Rpb25zIGFuZCBjYXBhYmlsaXR5IG9mIHRoZSBWUE4gU2VydmVyIGN1cnJlbnRseSBjb25uZWN0ZWQgYW5kIGJlaW5nIG1hbmFnZWQuIFRoZSBmdW5jdGlvbiBhbmQgY2FwYWJpbGl0eSBvZiBWUE4gU2VydmVycyBhcmUgZGlmZmVyZW50IGRlcGVuZGluZyBvbiB0aGUgb3BlcmF0aW5nIFZQTiBzZXJ2ZXIncyBlZGl0aW9uIGFuZCB2ZXJzaW9uLiBVc2luZyB0aGlzIEFQSSwgeW91IGNhbiBmaW5kIG91dCB0aGUgY2FwYWJpbGl0eSBvZiB0aGUgdGFyZ2V0IFZQTiBTZXJ2ZXIgYW5kIHJlcG9ydCBpdC4gKi9cclxuICAgICAgICB0aGlzLkdldENhcHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRDYXBzXCIsIG5ldyBWcG5DYXBzbGlzdCgpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBvZiB0aGUgVlBOIFNlcnZlci4gVXNlIHRoaXMgdG8gZ2V0IGEgdGV4dCBmaWxlICguY29uZmlnIGZpbGUpIHRoYXQgY29udGFpbnMgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiBjb250ZW50cyBvZiB0aGUgVlBOIHNlcnZlci4gWW91IGNhbiBnZXQgdGhlIHN0YXR1cyBvbiB0aGUgVlBOIFNlcnZlciBhdCB0aGUgaW5zdGFudCB0aGlzIEFQSSBpcyBleGVjdXRlZC4gWW91IGNhbiBlZGl0IHRoZSBjb25maWd1cmF0aW9uIGZpbGUgYnkgdXNpbmcgYSByZWd1bGFyIHRleHQgZWRpdG9yLiBUbyB3cml0ZSBhbiBlZGl0ZWQgY29uZmlndXJhdGlvbiB0byB0aGUgVlBOIFNlcnZlciwgdXNlIHRoZSBTZXRDb25maWcgQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0Q29uZmlnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0Q29uZmlnXCIsIG5ldyBWcG5ScGNDb25maWcoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogV3JpdGUgQ29uZmlndXJhdGlvbiBGaWxlIHRvIFZQTiBTZXJ2ZXIuIFVzZSB0aGlzIHRvIHdyaXRlIHRoZSBjb25maWd1cmF0aW9uIGZpbGUgdG8gdGhlIFZQTiBTZXJ2ZXIuIEJ5IGV4ZWN1dGluZyB0aGlzIEFQSSwgdGhlIGNvbnRlbnRzIG9mIHRoZSBzcGVjaWZpZWQgY29uZmlndXJhdGlvbiBmaWxlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgVlBOIFNlcnZlciBhbmQgdGhlIFZQTiBTZXJ2ZXIgcHJvZ3JhbSB3aWxsIGF1dG9tYXRpY2FsbHkgcmVzdGFydCBhbmQgdXBvbiByZXN0YXJ0LCBvcGVyYXRlIGFjY29yZGluZyB0byB0aGUgbmV3IGNvbmZpZ3VyYXRpb24gY29udGVudHMuIEJlY2F1c2UgaXQgaXMgZGlmZmljdWx0IGZvciBhbiBhZG1pbmlzdHJhdG9yIHRvIHdyaXRlIGFsbCB0aGUgY29udGVudHMgb2YgYSBjb25maWd1cmF0aW9uIGZpbGUsIHdlIHJlY29tbWVuZCB5b3UgdXNlIHRoZSBHZXRDb25maWcgQVBJIHRvIGdldCB0aGUgY3VycmVudCBjb250ZW50cyBvZiB0aGUgVlBOIFNlcnZlciBjb25maWd1cmF0aW9uIGFuZCBzYXZlIGl0IHRvIGZpbGUuIFlvdSBjYW4gdGhlbiBlZGl0IHRoZXNlIGNvbnRlbnRzIGluIGEgcmVndWxhciB0ZXh0IGVkaXRvciBhbmQgdGhlbiB1c2UgdGhlIFNldENvbmZpZyBBUEkgdG8gcmV3cml0ZSB0aGUgY29udGVudHMgdG8gdGhlIFZQTiBTZXJ2ZXIuIFRoaXMgQVBJIGlzIGZvciBwZW9wbGUgd2l0aCBhIGRldGFpbGVkIGtub3dsZWRnZSBvZiB0aGUgVlBOIFNlcnZlciBhbmQgaWYgYW4gaW5jb3JyZWN0bHkgY29uZmlndXJlZCBjb25maWd1cmF0aW9uIGZpbGUgaXMgd3JpdHRlbiB0byB0aGUgVlBOIFNlcnZlciwgaXQgbm90IG9ubHkgY291bGQgY2F1c2UgZXJyb3JzLCBpdCBjb3VsZCBhbHNvIHJlc3VsdCBpbiB0aGUgbG9zdCBvZiB0aGUgY3VycmVudCBzZXR0aW5nIGRhdGEuIFRha2Ugc3BlY2lhbCBjYXJlIHdoZW4gY2Fycnlpbmcgb3V0IHRoaXMgYWN0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0Q29uZmlnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRDb25maWdcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb24gZGVmYXVsdCB2YWx1ZXMuICovXHJcbiAgICAgICAgdGhpcy5HZXREZWZhdWx0SHViQWRtaW5PcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXREZWZhdWx0SHViQWRtaW5PcHRpb25zXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb25zLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMgdGhhdCBhcmUgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVGhlIHB1cnBvc2Ugb2YgdGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMgaXMgZm9yIHRoZSBWUE4gU2VydmVyIEFkbWluaXN0cmF0b3IgdG8gc2V0IGxpbWl0cyBmb3IgdGhlIHNldHRpbmcgcmFuZ2VzIHdoZW4gdGhlIGFkbWluaXN0cmF0aW9uIG9mIHRoZSBWaXJ0dWFsIEh1YiBpcyB0byBiZSB0cnVzdGVkIHRvIGVhY2ggVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvci4gT25seSBhbiBhZG1pbmlzdHJhdG9yIHdpdGggYWRtaW5pc3RyYXRpb24gcHJpdmlsZWdlcyBmb3IgdGhpcyBlbnRpcmUgVlBOIFNlcnZlciBpcyBhYmxlIHRvIGFkZCwgZWRpdCBhbmQgZGVsZXRlIHRoZSBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zLiBUaGUgVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvcnMgYXJlIHVuYWJsZSB0byBtYWtlIGNoYW5nZXMgdG8gdGhlIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMsIGhvd2V2ZXIgdGhleSBhcmUgYWJsZSB0byB2aWV3IHRoZW0uIFRoZXJlIGlzIGFuIGV4Y2VwdGlvbiBob3dldmVyLiBJZiBhbGxvd19odWJfYWRtaW5fY2hhbmdlX29wdGlvbiBpcyBzZXQgdG8gXCIxXCIsIGV2ZW4gVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRvcnMgYXJlIGFibGUgdG8gZWRpdCB0aGUgYWRtaW5pc3RyYXRpb24gb3B0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3RlciBtZW1iZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRIdWJBZG1pbk9wdGlvbnMgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEh1YkFkbWluT3B0aW9uc1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFZhbHVlcyBvZiBWaXJ0dWFsIEh1YiBBZG1pbmlzdHJhdGlvbiBPcHRpb25zLiBVc2UgdGhpcyB0byBjaGFuZ2UgdGhlIHZhbHVlcyBvZiBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zIHRoYXQgYXJlIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFRoZSBwdXJwb3NlIG9mIHRoZSBWaXJ0dWFsIEh1YiBhZG1pbmlzdHJhdGlvbiBvcHRpb25zIGlzIGZvciB0aGUgVlBOIFNlcnZlciBBZG1pbmlzdHJhdG9yIHRvIHNldCBsaW1pdHMgZm9yIHRoZSBzZXR0aW5nIHJhbmdlcyB3aGVuIHRoZSBhZG1pbmlzdHJhdGlvbiBvZiB0aGUgVmlydHVhbCBIdWIgaXMgdG8gYmUgdHJ1c3RlZCB0byBlYWNoIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3IuIE9ubHkgYW4gYWRtaW5pc3RyYXRvciB3aXRoIGFkbWluaXN0cmF0aW9uIHByaXZpbGVnZXMgZm9yIHRoaXMgZW50aXJlIFZQTiBTZXJ2ZXIgaXMgYWJsZSB0byBhZGQsIGVkaXQgYW5kIGRlbGV0ZSB0aGUgVmlydHVhbCBIdWIgYWRtaW5pc3RyYXRpb24gb3B0aW9ucy4gVGhlIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3JzIGFyZSB1bmFibGUgdG8gbWFrZSBjaGFuZ2VzIHRvIHRoZSBhZG1pbmlzdHJhdGlvbiBvcHRpb25zLCBob3dldmVyIHRoZXkgYXJlIGFibGUgdG8gdmlldyB0aGVtLiBUaGVyZSBpcyBhbiBleGNlcHRpb24gaG93ZXZlci4gSWYgYWxsb3dfaHViX2FkbWluX2NoYW5nZV9vcHRpb24gaXMgc2V0IHRvIFwiMVwiLCBldmVuIFZpcnR1YWwgSHViIGFkbWluaXN0cmF0b3JzIGFyZSBhYmxlIHRvIGVkaXQgdGhlIGFkbWluaXN0cmF0aW9uIG9wdGlvbnMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIgbWVtYmVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViQWRtaW5PcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJBZG1pbk9wdGlvbnNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMuIFVzZSB0aGlzIHRvIGdldCBhIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMgTGlzdCB0aGF0IGlzIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbiBlbmFibGVzIHlvdSB0byBjb25maWd1cmUgbW9yZSBkZXRhaWwgc2V0dGluZ3Mgb2YgdGhlIFZpcnR1YWwgSHViLiBCeSBkZWZhdWx0LCBib3RoIFZQTiBTZXJ2ZXIncyBnbG9iYWwgYWRtaW5pc3RyYXRvcnMgYW5kIGluZGl2aWR1YWwgVmlydHVhbCBIdWIncyBhZG1pbmlzdHJhdG9ycyBjYW4gbW9kaWZ5IHRoZSBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBIb3dldmVyLCBpZiB0aGUgZGVueV9odWJfYWRtaW5fY2hhbmdlX2V4dF9vcHRpb24gaXMgc2V0IHRvIDEgb24gdGhlIFZpcnR1YWwgSHViIEFkbWluIE9wdGlvbnMsIHRoZSBpbmRpdmlkdWFsIFZpcnR1YWwgSHViJ3MgYWRtaW5pc3RyYXRvcnMgY2Fubm90IG1vZGlmeSB0aGUgVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9ucy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3RlciBtZW1iZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRIdWJFeHRPcHRpb25zID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRIdWJFeHRPcHRpb25zXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgYSBWYWx1ZSBvZiBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBVc2UgdGhpcyB0byBzZXQgYSB2YWx1ZSBpbiB0aGUgVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9ucyBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVmlydHVhbCBIdWIgRXh0ZW5kZWQgT3B0aW9uIGVuYWJsZXMgeW91IHRvIGNvbmZpZ3VyZSBtb3JlIGRldGFpbCBzZXR0aW5ncyBvZiB0aGUgVmlydHVhbCBIdWIuIEJ5IGRlZmF1bHQsIGJvdGggVlBOIFNlcnZlcidzIGdsb2JhbCBhZG1pbmlzdHJhdG9ycyBhbmQgaW5kaXZpZHVhbCBWaXJ0dWFsIEh1YidzIGFkbWluaXN0cmF0b3JzIGNhbiBtb2RpZnkgdGhlIFZpcnR1YWwgSHViIEV4dGVuZGVkIE9wdGlvbnMuIEhvd2V2ZXIsIGlmIHRoZSBkZW55X2h1Yl9hZG1pbl9jaGFuZ2VfZXh0X29wdGlvbiBpcyBzZXQgdG8gMSBvbiB0aGUgVmlydHVhbCBIdWIgQWRtaW4gT3B0aW9ucywgdGhlIGluZGl2aWR1YWwgVmlydHVhbCBIdWIncyBhZG1pbmlzdHJhdG9ycyBjYW5ub3QgbW9kaWZ5IHRoZSBWaXJ0dWFsIEh1YiBFeHRlbmRlZCBPcHRpb25zLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyIG1lbWJlci4gKi9cclxuICAgICAgICB0aGlzLlNldEh1YkV4dE9wdGlvbnMgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEh1YkV4dE9wdGlvbnNcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlZmluZSBOZXcgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gVXNlIHRoaXMgdG8gZGVmaW5lIGEgbmV3IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggb24gdGhlIFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5BZGRMM1N3aXRjaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBkZWxldGUgYW4gZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaCB0aGF0IGlzIGRlZmluZWQgb24gdGhlIFZQTiBTZXJ2ZXIuIFdoZW4gdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGlzIG9wZXJhdGluZywgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGRlbGV0ZWQgYWZ0ZXIgb3BlcmF0aW9uIHN0b3BzLiBUbyBnZXQgYSBsaXN0IG9mIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcywgdXNlIHRoZSBFbnVtTDNTd2l0Y2ggQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBBbHNvLCB0aGlzIEFQSSBkb2VzIG5vdCBvcGVyYXRlIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5EZWxMM1N3aXRjaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcy4gVXNlIHRoaXMgdG8gZGVmaW5lIGEgbmV3IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggb24gdGhlIFZQTiBTZXJ2ZXIuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTDNTd2l0Y2ggPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTDNTd2l0Y2hcIiwgbmV3IFZwblJwY0VudW1MM1N3KCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFN0YXJ0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggT3BlcmF0aW9uLiBVc2UgdGhpcyB0byBzdGFydCB0aGUgb3BlcmF0aW9uIG9mIGFuIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZGVmaW5lZCBvbiB0aGUgVlBOIFNlcnZlciB3aG9zZSBvcGVyYXRpb24gaXMgY3VycmVudGx5IHN0b3BwZWQuIFRvIGdldCBhIGxpc3Qgb2YgZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaGVzLCB1c2UgdGhlIEVudW1MM1N3aXRjaCBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gW0V4cGxhbmF0aW9uIG9uIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFlvdSBjYW4gZGVmaW5lIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcyBiZXR3ZWVuIG11bHRpcGxlIFZpcnR1YWwgSHVicyBvcGVyYXRpbmcgb24gdGhpcyBWUE4gU2VydmVyIGFuZCBjb25maWd1cmUgcm91dGluZyBiZXR3ZWVuIGRpZmZlcmVudCBJUCBuZXR3b3Jrcy4gW0NhdXRpb24gYWJvdXQgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggRnVuY3Rpb25dIFRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucyBhcmUgcHJvdmlkZWQgZm9yIG5ldHdvcmsgYWRtaW5pc3RyYXRvcnMgYW5kIG90aGVyIHBlb3BsZSB3aG8ga25vdyBhIGxvdCBhYm91dCBuZXR3b3JrcyBhbmQgSVAgcm91dGluZy4gSWYgeW91IGFyZSB1c2luZyB0aGUgcmVndWxhciBWUE4gZnVuY3Rpb25zLCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIGZ1bmN0aW9ucy4gSWYgdGhlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggZnVuY3Rpb25zIGFyZSB0byBiZSB1c2VkLCB0aGUgcGVyc29uIHdobyBjb25maWd1cmVzIHRoZW0gbXVzdCBoYXZlIHN1ZmZpY2llbnQga25vd2xlZGdlIG9mIElQIHJvdXRpbmcgYW5kIGJlIHBlcmZlY3RseSBjYXBhYmxlIG9mIG5vdCBpbXBhY3RpbmcgdGhlIG5ldHdvcmsuICovXHJcbiAgICAgICAgdGhpcy5TdGFydEwzU3dpdGNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTdGFydEwzU3dpdGNoXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTdG9wIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggT3BlcmF0aW9uLiBVc2UgdGhpcyB0byBzdG9wIHRoZSBvcGVyYXRpb24gb2YgYW4gZXhpc3RpbmcgVmlydHVhbCBMYXllciAzIFN3aXRjaCBkZWZpbmVkIG9uIHRoZSBWUE4gU2VydmVyIHdob3NlIG9wZXJhdGlvbiBpcyBjdXJyZW50bHkgb3BlcmF0aW5nLiBUbyBnZXQgYSBsaXN0IG9mIGV4aXN0aW5nIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2hlcywgdXNlIHRoZSBFbnVtTDNTd2l0Y2ggQVBJLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiAqL1xyXG4gICAgICAgIHRoaXMuU3RvcEwzU3dpdGNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTdG9wTDNTd2l0Y2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBWaXJ0dWFsIEludGVyZmFjZSB0byBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBhZGQgdG8gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaCwgYSB2aXJ0dWFsIGludGVyZmFjZSB0aGF0IGNvbm5lY3RzIHRvIGEgVmlydHVhbCBIdWIgb3BlcmF0aW5nIG9uIHRoZSBzYW1lIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gZGVmaW5lIG11bHRpcGxlIHZpcnR1YWwgaW50ZXJmYWNlcyBhbmQgcm91dGluZyB0YWJsZXMgZm9yIGEgc2luZ2xlIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2guIEEgdmlydHVhbCBpbnRlcmZhY2UgaXMgYXNzb2NpYXRlZCB0byBhIHZpcnR1YWwgSHViIGFuZCBvcGVyYXRlcyBhcyBhIHNpbmdsZSBJUCBob3N0IG9uIHRoZSBWaXJ0dWFsIEh1YiB3aGVuIHRoYXQgVmlydHVhbCBIdWIgaXMgb3BlcmF0aW5nLiBXaGVuIG11bHRpcGxlIHZpcnR1YWwgaW50ZXJmYWNlcyB0aGF0IHJlc3BlY3RpdmVseSBiZWxvbmcgdG8gYSBkaWZmZXJlbnQgSVAgbmV0d29yayBvZiBhIGRpZmZlcmVudCBWaXJ0dWFsIEh1YiBhcmUgZGVmaW5lZCwgSVAgcm91dGluZyB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcGVyZm9ybWVkIGJldHdlZW4gdGhlc2UgaW50ZXJmYWNlcy4gWW91IG11c3QgZGVmaW5lIHRoZSBJUCBuZXR3b3JrIHNwYWNlIHRoYXQgdGhlIHZpcnR1YWwgaW50ZXJmYWNlIGJlbG9uZ3MgdG8gYW5kIHRoZSBJUCBhZGRyZXNzIG9mIHRoZSBpbnRlcmZhY2UgaXRzZWxmLiBBbHNvLCB5b3UgbXVzdCBzcGVjaWZ5IHRoZSBuYW1lIG9mIHRoZSBWaXJ0dWFsIEh1YiB0aGF0IHRoZSBpbnRlcmZhY2Ugd2lsbCBjb25uZWN0IHRvLiBZb3UgY2FuIHNwZWNpZnkgYSBWaXJ0dWFsIEh1YiB0aGF0IGN1cnJlbnRseSBkb2Vzbid0IGV4aXN0IGZvciB0aGUgVmlydHVhbCBIdWIgbmFtZS4gVGhlIHZpcnR1YWwgaW50ZXJmYWNlIG11c3QgaGF2ZSBvbmUgSVAgYWRkcmVzcyBpbiB0aGUgVmlydHVhbCBIdWIuIFlvdSBhbHNvIG11c3Qgc3BlY2lmeSB0aGUgc3VibmV0IG1hc2sgb2YgYW4gSVAgbmV0d29yayB0aGF0IHRoZSBJUCBhZGRyZXNzIGJlbG9uZ3MgdG8uIFJvdXRpbmcgdmlhIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoZXMgb2YgSVAgc3BhY2VzIG9mIG11bHRpcGxlIHZpcnR1YWwgSHVicyBvcGVyYXRlcyBiYXNlZCBvbiB0aGUgSVAgYWRkcmVzcyBpcyBzcGVjaWZpZWQgaGVyZS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkFkZEwzSWYgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkFkZEwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBWaXJ0dWFsIEludGVyZmFjZSBvZiBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBkZWxldGUgYSB2aXJ0dWFsIGludGVyZmFjZSBhbHJlYWR5IGRlZmluZWQgaW4gdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBZb3UgY2FuIGdldCBhIGxpc3Qgb2YgdGhlIHZpcnR1YWwgaW50ZXJmYWNlcyBjdXJyZW50bHkgZGVmaW5lZCwgYnkgdXNpbmcgdGhlIEVudW1MM0lmIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkRlbEwzSWYgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbEwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBMaXN0IG9mIEludGVyZmFjZXMgUmVnaXN0ZXJlZCBvbiB0aGUgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gVXNlIHRoaXMgdG8gZ2V0IGEgbGlzdCBvZiB2aXJ0dWFsIGludGVyZmFjZXMgd2hlbiB2aXJ0dWFsIGludGVyZmFjZXMgaGF2ZSBiZWVuIGRlZmluZWQgb24gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gWW91IGNhbiBkZWZpbmUgbXVsdGlwbGUgdmlydHVhbCBpbnRlcmZhY2VzIGFuZCByb3V0aW5nIHRhYmxlcyBmb3IgYSBzaW5nbGUgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gQSB2aXJ0dWFsIGludGVyZmFjZSBpcyBhc3NvY2lhdGVkIHRvIGEgdmlydHVhbCBIdWIgYW5kIG9wZXJhdGVzIGFzIGEgc2luZ2xlIElQIGhvc3Qgb24gdGhlIFZpcnR1YWwgSHViIHdoZW4gdGhhdCBWaXJ0dWFsIEh1YiBpcyBvcGVyYXRpbmcuIFdoZW4gbXVsdGlwbGUgdmlydHVhbCBpbnRlcmZhY2VzIHRoYXQgcmVzcGVjdGl2ZWx5IGJlbG9uZyB0byBhIGRpZmZlcmVudCBJUCBuZXR3b3JrIG9mIGEgZGlmZmVyZW50IFZpcnR1YWwgSHViIGFyZSBkZWZpbmVkLCBJUCByb3V0aW5nIHdpbGwgYmUgYXV0b21hdGljYWxseSBwZXJmb3JtZWQgYmV0d2VlbiB0aGVzZSBpbnRlcmZhY2VzLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBBbHNvLCB0aGlzIEFQSSBkb2VzIG5vdCBvcGVyYXRlIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5FbnVtTDNJZiA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRW51bUwzSWZcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBSb3V0aW5nIFRhYmxlIEVudHJ5IGZvciBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBIZXJlIHlvdSBjYW4gYWRkIGEgbmV3IHJvdXRpbmcgdGFibGUgZW50cnkgdG8gdGhlIHJvdXRpbmcgdGFibGUgb2YgdGhlIHNwZWNpZmllZCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBJZiB0aGUgZGVzdGluYXRpb24gSVAgYWRkcmVzcyBvZiB0aGUgSVAgcGFja2V0IGRvZXMgbm90IGJlbG9uZyB0byBhbnkgSVAgbmV0d29yayB0aGF0IGJlbG9uZ3MgdG8gYSB2aXJ0dWFsIGludGVyZmFjZSwgdGhlIElQIHJvdXRpbmcgZW5naW5lIG9mIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIHdpbGwgcmVmZXJlbmNlIHRoZSByb3V0aW5nIHRhYmxlIGFuZCBleGVjdXRlIHJvdXRpbmcuIFlvdSBtdXN0IHNwZWNpZnkgdGhlIGNvbnRlbnRzIG9mIHRoZSByb3V0aW5nIHRhYmxlIGVudHJ5IHRvIGJlIGFkZGVkIHRvIHRoZSBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBZb3UgbXVzdCBzcGVjaWZ5IGFueSBJUCBhZGRyZXNzIHRoYXQgYmVsb25ncyB0byB0aGUgc2FtZSBJUCBuZXR3b3JrIGluIHRoZSB2aXJ0dWFsIGludGVyZmFjZSBvZiB0aGlzIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggYXMgdGhlIGdhdGV3YXkgYWRkcmVzcy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB0aGUgdGFyZ2V0IFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2ggbXVzdCBiZSBzdG9wcGVkLiBJZiBpdCBpcyBub3Qgc3RvcHBlZCwgZmlyc3QgdXNlIHRoZSBTdG9wTDNTd2l0Y2ggQVBJIHRvIHN0b3AgaXQgYW5kIHRoZW4gZXhlY3V0ZSB0aGlzIEFQSS4gKi9cclxuICAgICAgICB0aGlzLkFkZEwzVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkFkZEwzVGFibGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBSb3V0aW5nIFRhYmxlIEVudHJ5IG9mIFZpcnR1YWwgTGF5ZXIgMyBTd2l0Y2guIFVzZSB0aGlzIHRvIGRlbGV0ZSBhIHJvdXRpbmcgdGFibGUgZW50cnkgdGhhdCBpcyBkZWZpbmVkIGluIHRoZSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gWW91IGNhbiBnZXQgYSBsaXN0IG9mIHRoZSBhbHJlYWR5IGRlZmluZWQgcm91dGluZyB0YWJsZSBlbnRyaWVzIGJ5IHVzaW5nIHRoZSBFbnVtTDNUYWJsZSBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFsc28sIHRoaXMgQVBJIGRvZXMgbm90IG9wZXJhdGUgb24gVlBOIEJyaWRnZS4gVG8gZXhlY3V0ZSB0aGlzIEFQSSwgdGhlIHRhcmdldCBWaXJ0dWFsIExheWVyIDMgU3dpdGNoIG11c3QgYmUgc3RvcHBlZC4gSWYgaXQgaXMgbm90IHN0b3BwZWQsIGZpcnN0IHVzZSB0aGUgU3RvcEwzU3dpdGNoIEFQSSB0byBzdG9wIGl0IGFuZCB0aGVuIGV4ZWN1dGUgdGhpcyBBUEkuICovXHJcbiAgICAgICAgdGhpcy5EZWxMM1RhYmxlID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJEZWxMM1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBSb3V0aW5nIFRhYmxlcyBvZiBWaXJ0dWFsIExheWVyIDMgU3dpdGNoLiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIHJvdXRpbmcgdGFibGVzIHdoZW4gcm91dGluZyB0YWJsZXMgaGF2ZSBiZWVuIGRlZmluZWQgb24gYSBzcGVjaWZpZWQgVmlydHVhbCBMYXllciAzIFN3aXRjaC4gSWYgdGhlIGRlc3RpbmF0aW9uIElQIGFkZHJlc3Mgb2YgdGhlIElQIHBhY2tldCBkb2VzIG5vdCBiZWxvbmcgdG8gYW55IElQIG5ldHdvcmsgdGhhdCBiZWxvbmdzIHRvIGEgdmlydHVhbCBpbnRlcmZhY2UsIHRoZSBJUCByb3V0aW5nIGVuZ2luZSBvZiB0aGUgVmlydHVhbCBMYXllciAzIFN3aXRjaCB3aWxsIHJlZmVyZW5jZSB0aGlzIHJvdXRpbmcgdGFibGUgYW5kIGV4ZWN1dGUgcm91dGluZy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gQWxzbywgdGhpcyBBUEkgZG9lcyBub3Qgb3BlcmF0ZSBvbiBWUE4gQnJpZGdlLiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUwzVGFibGUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1MM1RhYmxlXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gQnkgcmVnaXN0ZXJpbmcgY2VydGlmaWNhdGVzIGluIHRoZSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0LCB0aGUgY2xpZW50cyB3aG8gcHJvdmlkZSB0aGVzZSBjZXJ0aWZpY2F0ZXMgd2lsbCBiZSB1bmFibGUgdG8gY29ubmVjdCB0byB0aGlzIFZpcnR1YWwgSHViIHVzaW5nIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uIG1vZGUuIE5vcm1hbGx5IHdpdGggdGhpcyBmdW5jdGlvbiwgaW4gY2FzZXMgd2hlcmUgdGhlIHNlY3VyaXR5IG9mIGEgcHJpdmF0ZSBrZXkgaGFzIGJlZW4gY29tcHJvbWlzZWQgb3Igd2hlcmUgYSBwZXJzb24gaG9sZGluZyBhIGNlcnRpZmljYXRlIGhhcyBiZWVuIHN0cmlwcGVkIG9mIHRoZWlyIHByaXZpbGVnZXMsIGJ5IHJlZ2lzdGVyaW5nIHRoYXQgY2VydGlmaWNhdGUgYXMgaW52YWxpZCBvbiB0aGUgVmlydHVhbCBIdWIsIGl0IGlzIHBvc3NpYmxlIHRvIGRlbnkgdXNlciBhdXRoZW50aWNhdGlvbiB3aGVuIHRoYXQgY2VydGlmaWNhdGUgaXMgdXNlZCBieSBhIGNsaWVudCB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1Yi4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1DcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkVudW1DcmxcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEFkZCBhIFJldm9rZWQgQ2VydGlmaWNhdGUuIFVzZSB0aGlzIHRvIGFkZCBhIG5ldyByZXZva2VkIGNlcnRpZmljYXRlIGRlZmluaXRpb24gaW4gdGhlIENlcnRpZmljYXRlIFJldm9jYXRpb24gTGlzdCB0aGF0IGlzIHNldCBvbiB0aGUgY3VycmVudGx5IG1hbmFnZWQgVmlydHVhbCBIdWIuIFNwZWNpZnkgdGhlIGNvbnRlbnRzIHRvIGJlIHJlZ2lzdGVyZWQgaW4gdGhlIENlcnRpZmljYXRlIFJldm9jYXRpb24gTGlzdCBieSB1c2luZyB0aGUgcGFyYW1ldGVycyBvZiB0aGlzIEFQSS4gV2hlbiBhIHVzZXIgY29ubmVjdHMgdG8gYSBWaXJ0dWFsIEh1YiBpbiBjZXJ0aWZpY2F0ZSBhdXRoZW50aWNhdGlvbiBtb2RlIGFuZCB0aGF0IGNlcnRpZmljYXRlIG1hdGNoZXMgMSBvciBtb3JlIG9mIHRoZSBjb250ZW50cyByZWdpc3RlcmVkIGluIHRoZSBjZXJ0aWZpY2F0ZXMgcmV2b2NhdGlvbiBsaXN0LCB0aGUgdXNlciBpcyBkZW5pZWQgY29ubmVjdGlvbi4gQSBjZXJ0aWZpY2F0ZSB0aGF0IG1hdGNoZXMgYWxsIHRoZSBjb25kaXRpb25zIHRoYXQgYXJlIGRlZmluZWQgYnkgdGhlIHBhcmFtZXRlcnMgc3BlY2lmaWVkIGJ5IHRoaXMgQVBJIHdpbGwgYmUganVkZ2VkIGFzIGludmFsaWQuIFRoZSBpdGVtcyB0aGF0IGNhbiBiZSBzZXQgYXJlIGFzIGZvbGxvd3M6IE5hbWUgKENOKSwgT3JnYW5pemF0aW9uIChPKSwgT3JnYW5pemF0aW9uIFVuaXQgKE9VKSwgQ291bnRyeSAoQyksIFN0YXRlIChTVCksIExvY2FsZSAoTCksIFNlcmlhbCBOdW1iZXIgKGhleGFkZWNpbWFsKSwgTUQ1IERpZ2VzdCBWYWx1ZSAoaGV4YWRlY2ltYWwsIDEyOCBiaXQpLCBhbmQgU0hBLTEgRGlnZXN0IFZhbHVlIChoZXhhZGVjaW1hbCwgMTYwIGJpdCkuIEZvciB0aGUgc3BlY2lmaWNhdGlvbiBvZiBhIGRpZ2VzdCB2YWx1ZSAoaGFzaCB2YWx1ZSkgYSBjZXJ0aWZpY2F0ZSBpcyBvcHRpb25hbGx5IHNwZWNpZmllZCBkZXBlbmRpbmcgb24gdGhlIGNpcmN1bXN0YW5jZXMuIE5vcm1hbGx5IHdoZW4gYSBNRDUgb3IgU0hBLTEgZGlnZXN0IHZhbHVlIGlzIGlucHV0LCBpdCBpcyBub3QgbmVjZXNzYXJ5IHRvIGlucHV0IHRoZSBvdGhlciBpdGVtcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkFkZENybCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiQWRkQ3JsXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBEZWxldGUgYSBSZXZva2VkIENlcnRpZmljYXRlLiBVc2UgdGhpcyB0byBzcGVjaWZ5IGFuZCBkZWxldGUgYSByZXZva2VkIGNlcnRpZmljYXRlIGRlZmluaXRpb24gZnJvbSB0aGUgY2VydGlmaWNhdGUgcmV2b2NhdGlvbiBsaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbnMsIHVzZSB0aGUgRW51bUNybCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5EZWxDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkRlbENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IGEgUmV2b2tlZCBDZXJ0aWZpY2F0ZS4gVXNlIHRoaXMgdG8gc3BlY2lmeSBhbmQgZ2V0IHRoZSBjb250ZW50cyBvZiBhIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbiBmcm9tIHRoZSBDZXJ0aWZpY2F0ZXMgUmV2b2NhdGlvbiBMaXN0IHRoYXQgaXMgc2V0IG9uIHRoZSBjdXJyZW50bHkgbWFuYWdlZCBWaXJ0dWFsIEh1Yi4gVG8gZ2V0IHRoZSBsaXN0IG9mIGN1cnJlbnRseSByZWdpc3RlcmVkIHJldm9rZWQgY2VydGlmaWNhdGUgZGVmaW5pdGlvbnMsIHVzZSB0aGUgRW51bUNybCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQ2hhbmdlIEV4aXN0aW5nIENSTCAoQ2VydGlmaWNhdGUgUmV2b2NhdGlvbiBMaXN0KSBFbnRyeS4gVXNlIHRoaXMgdG8gYWx0ZXIgYW4gZXhpc3RpbmcgcmV2b2tlZCBjZXJ0aWZpY2F0ZSBkZWZpbml0aW9uIGluIHRoZSBDZXJ0aWZpY2F0ZSBSZXZvY2F0aW9uIExpc3QgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBTcGVjaWZ5IHRoZSBjb250ZW50cyB0byBiZSByZWdpc3RlcmVkIGluIHRoZSBDZXJ0aWZpY2F0ZSBSZXZvY2F0aW9uIExpc3QgYnkgdXNpbmcgdGhlIHBhcmFtZXRlcnMgb2YgdGhpcyBBUEkuIFdoZW4gYSB1c2VyIGNvbm5lY3RzIHRvIGEgVmlydHVhbCBIdWIgaW4gY2VydGlmaWNhdGUgYXV0aGVudGljYXRpb24gbW9kZSBhbmQgdGhhdCBjZXJ0aWZpY2F0ZSBtYXRjaGVzIDEgb3IgbW9yZSBvZiB0aGUgY29udGVudHMgcmVnaXN0ZXJlZCBpbiB0aGUgY2VydGlmaWNhdGVzIHJldm9jYXRpb24gbGlzdCwgdGhlIHVzZXIgaXMgZGVuaWVkIGNvbm5lY3Rpb24uIEEgY2VydGlmaWNhdGUgdGhhdCBtYXRjaGVzIGFsbCB0aGUgY29uZGl0aW9ucyB0aGF0IGFyZSBkZWZpbmVkIGJ5IHRoZSBwYXJhbWV0ZXJzIHNwZWNpZmllZCBieSB0aGlzIEFQSSB3aWxsIGJlIGp1ZGdlZCBhcyBpbnZhbGlkLiBUaGUgaXRlbXMgdGhhdCBjYW4gYmUgc2V0IGFyZSBhcyBmb2xsb3dzOiBOYW1lIChDTiksIE9yZ2FuaXphdGlvbiAoTyksIE9yZ2FuaXphdGlvbiBVbml0IChPVSksIENvdW50cnkgKEMpLCBTdGF0ZSAoU1QpLCBMb2NhbGUgKEwpLCBTZXJpYWwgTnVtYmVyIChoZXhhZGVjaW1hbCksIE1ENSBEaWdlc3QgVmFsdWUgKGhleGFkZWNpbWFsLCAxMjggYml0KSwgYW5kIFNIQS0xIERpZ2VzdCBWYWx1ZSAoaGV4YWRlY2ltYWwsIDE2MCBiaXQpLiBGb3IgdGhlIHNwZWNpZmljYXRpb24gb2YgYSBkaWdlc3QgdmFsdWUgKGhhc2ggdmFsdWUpIGEgY2VydGlmaWNhdGUgaXMgb3B0aW9uYWxseSBzcGVjaWZpZWQgZGVwZW5kaW5nIG9uIHRoZSBjaXJjdW1zdGFuY2VzLiBOb3JtYWxseSB3aGVuIGEgTUQ1IG9yIFNIQS0xIGRpZ2VzdCB2YWx1ZSBpcyBpbnB1dCwgaXQgaXMgbm90IG5lY2Vzc2FyeSB0byBpbnB1dCB0aGUgb3RoZXIgaXRlbXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRDcmwgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldENybFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQWRkIFJ1bGUgdG8gU291cmNlIElQIEFkZHJlc3MgTGltaXQgTGlzdC4gVXNlIHRoaXMgdG8gYWRkIGEgbmV3IHJ1bGUgdG8gdGhlIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBUaGUgaXRlbXMgc2V0IGhlcmUgd2lsbCBiZSB1c2VkIHRvIGRlY2lkZSB3aGV0aGVyIHRvIGFsbG93IG9yIGRlbnkgY29ubmVjdGlvbiBmcm9tIGEgVlBOIENsaWVudCB3aGVuIHRoaXMgY2xpZW50IGF0dGVtcHRzIGNvbm5lY3Rpb24gdG8gdGhlIFZpcnR1YWwgSHViLiBZb3UgY2FuIHNwZWNpZnkgYSBjbGllbnQgSVAgYWRkcmVzcywgb3IgSVAgYWRkcmVzcyBvciBtYXNrIHRvIG1hdGNoIHRoZSBydWxlIGFzIHRoZSBjb250ZW50cyBvZiB0aGUgcnVsZSBpdGVtLiBCeSBzcGVjaWZ5aW5nIGFuIElQIGFkZHJlc3Mgb25seSwgdGhlcmUgd2lsbCBvbmx5IGJlIG9uZSBzcGVjaWZpZWQgY29tcHV0ZXIgdGhhdCB3aWxsIG1hdGNoIHRoZSBydWxlLCBidXQgYnkgc3BlY2lmeWluZyBhbiBJUCBuZXQgbWFzayBhZGRyZXNzIG9yIHN1Ym5ldCBtYXNrIGFkZHJlc3MsIGFsbCB0aGUgY29tcHV0ZXJzIGluIHRoZSByYW5nZSBvZiB0aGF0IHN1Ym5ldCB3aWxsIG1hdGNoIHRoZSBydWxlLiBZb3UgY2FuIHNwZWNpZnkgdGhlIHByaW9yaXR5IGZvciB0aGUgcnVsZS4gWW91IGNhbiBzcGVjaWZ5IGFuIGludGVnZXIgb2YgMSBvciBncmVhdGVyIGZvciB0aGUgcHJpb3JpdHkgYW5kIHRoZSBzbWFsbGVyIHRoZSBudW1iZXIsIHRoZSBoaWdoZXIgdGhlIHByaW9yaXR5LiBUbyBnZXQgYSBsaXN0IG9mIHRoZSBjdXJyZW50bHkgcmVnaXN0ZXJlZCBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0LCB1c2UgdGhlIEdldEFjTGlzdCBBUEkuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRBY0xpc3QgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldEFjTGlzdFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IExpc3Qgb2YgUnVsZSBJdGVtcyBvZiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0LiBVc2UgdGhpcyB0byBnZXQgYSBsaXN0IG9mIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgcnVsZXMgdGhhdCBpcyBzZXQgb24gdGhlIGN1cnJlbnRseSBtYW5hZ2VkIFZpcnR1YWwgSHViLiBZb3UgY2FuIGFsbG93IG9yIGRlbnkgVlBOIGNvbm5lY3Rpb25zIHRvIHRoaXMgVmlydHVhbCBIdWIgYWNjb3JkaW5nIHRvIHRoZSBjbGllbnQgY29tcHV0ZXIncyBzb3VyY2UgSVAgYWRkcmVzcy4gWW91IGNhbiBkZWZpbmUgbXVsdGlwbGUgcnVsZXMgYW5kIHNldCBhIHByaW9yaXR5IGZvciBlYWNoIHJ1bGUuIFRoZSBzZWFyY2ggcHJvY2VlZHMgZnJvbSB0aGUgcnVsZSB3aXRoIHRoZSBoaWdoZXN0IG9yZGVyIG9yIHByaW9yaXR5IGFuZCBiYXNlZCBvbiB0aGUgYWN0aW9uIG9mIHRoZSBydWxlIHRoYXQgdGhlIElQIGFkZHJlc3MgZmlyc3QgbWF0Y2hlcywgdGhlIGNvbm5lY3Rpb24gZnJvbSB0aGUgY2xpZW50IGlzIGVpdGhlciBhbGxvd2VkIG9yIGRlbmllZC4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkdldEFjTGlzdCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QWNMaXN0XCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgTGlzdCBvZiBMb2cgRmlsZXMuIFVzZSB0aGlzIHRvIGRpc3BsYXkgYSBsaXN0IG9mIGxvZyBmaWxlcyBvdXRwdXR0ZWQgYnkgdGhlIFZQTiBTZXJ2ZXIgdGhhdCBoYXZlIGJlZW4gc2F2ZWQgb24gdGhlIFZQTiBTZXJ2ZXIgY29tcHV0ZXIuIEJ5IHNwZWNpZnlpbmcgYSBsb2cgZmlsZSBmaWxlIG5hbWUgZGlzcGxheWVkIGhlcmUgYW5kIGNhbGxpbmcgaXQgdXNpbmcgdGhlIFJlYWRMb2dGaWxlIEFQSSB5b3UgY2FuIGRvd25sb2FkIHRoZSBjb250ZW50cyBvZiB0aGUgbG9nIGZpbGUuIElmIHlvdSBhcmUgY29ubmVjdGVkIHRvIHRoZSBWUE4gU2VydmVyIGluIHNlcnZlciBhZG1pbiBtb2RlLCB5b3UgY2FuIGRpc3BsYXkgb3IgZG93bmxvYWQgdGhlIHBhY2tldCBsb2dzIGFuZCBzZWN1cml0eSBsb2dzIG9mIGFsbCBWaXJ0dWFsIEh1YnMgYW5kIHRoZSBzZXJ2ZXIgbG9nIG9mIHRoZSBWUE4gU2VydmVyLiBXaGVuIGNvbm5lY3RlZCBpbiBWaXJ0dWFsIEh1YiBBZG1pbiBNb2RlLCB5b3UgYXJlIGFibGUgdG8gdmlldyBvciBkb3dubG9hZCBvbmx5IHRoZSBwYWNrZXQgbG9nIGFuZCBzZWN1cml0eSBsb2cgb2YgdGhlIFZpcnR1YWwgSHViIHRoYXQgaXMgdGhlIHRhcmdldCBvZiBtYW5hZ2VtZW50LiAqL1xyXG4gICAgICAgIHRoaXMuRW51bUxvZ0ZpbGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtTG9nRmlsZVwiLCBuZXcgVnBuUnBjRW51bUxvZ0ZpbGUoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogRG93bmxvYWQgYSBwYXJ0IG9mIExvZyBGaWxlLiBVc2UgdGhpcyB0byBkb3dubG9hZCB0aGUgbG9nIGZpbGUgdGhhdCBpcyBzYXZlZCBvbiB0aGUgVlBOIFNlcnZlciBjb21wdXRlci4gVG8gZG93bmxvYWQgdGhlIGxvZyBmaWxlIGZpcnN0IGdldCB0aGUgbGlzdCBvZiBsb2cgZmlsZXMgdXNpbmcgdGhlIEVudW1Mb2dGaWxlIEFQSSBhbmQgdGhlbiBkb3dubG9hZCB0aGUgbG9nIGZpbGUgdXNpbmcgdGhlIFJlYWRMb2dGaWxlIEFQSS4gSWYgeW91IGFyZSBjb25uZWN0ZWQgdG8gdGhlIFZQTiBTZXJ2ZXIgaW4gc2VydmVyIGFkbWluIG1vZGUsIHlvdSBjYW4gZGlzcGxheSBvciBkb3dubG9hZCB0aGUgcGFja2V0IGxvZ3MgYW5kIHNlY3VyaXR5IGxvZ3Mgb2YgYWxsIFZpcnR1YWwgSHVicyBhbmQgdGhlIHNlcnZlciBsb2cgb2YgdGhlIFZQTiBTZXJ2ZXIuIFdoZW4gY29ubmVjdGVkIGluIFZpcnR1YWwgSHViIEFkbWluIE1vZGUsIHlvdSBhcmUgYWJsZSB0byB2aWV3IG9yIGRvd25sb2FkIG9ubHkgdGhlIHBhY2tldCBsb2cgYW5kIHNlY3VyaXR5IGxvZyBvZiB0aGUgVmlydHVhbCBIdWIgdGhhdCBpcyB0aGUgdGFyZ2V0IG9mIG1hbmFnZW1lbnQuICovXHJcbiAgICAgICAgdGhpcy5SZWFkTG9nRmlsZSA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiUmVhZExvZ0ZpbGVcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBzeXNsb2cgU2VuZCBGdW5jdGlvbi4gVXNlIHRoaXMgdG8gc2V0IHRoZSB1c2FnZSBvZiBzeXNsb2cgc2VuZCBmdW5jdGlvbiBhbmQgd2hpY2ggc3lzbG9nIHNlcnZlciB0byB1c2UuICovXHJcbiAgICAgICAgdGhpcy5TZXRTeXNMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFN5c0xvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHN5c2xvZyBTZW5kIEZ1bmN0aW9uLiBUaGlzIGFsbG93cyB5b3UgdG8gZ2V0IHRoZSBjdXJyZW50IHNldHRpbmcgY29udGVudHMgb2YgdGhlIHN5c2xvZyBzZW5kIGZ1bmN0aW9uLiBZb3UgY2FuIGdldCB0aGUgdXNhZ2Ugc2V0dGluZyBvZiB0aGUgc3lzbG9nIGZ1bmN0aW9uIGFuZCB0aGUgaG9zdCBuYW1lIGFuZCBwb3J0IG51bWJlciBvZiB0aGUgc3lzbG9nIHNlcnZlciB0byB1c2UuICovXHJcbiAgICAgICAgdGhpcy5HZXRTeXNMb2cgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldFN5c0xvZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2V0IFRvZGF5J3MgTWVzc2FnZSBvZiBWaXJ0dWFsIEh1Yi4gVGhlIG1lc3NhZ2Ugd2lsbCBiZSBkaXNwbGF5ZWQgb24gVlBOIENsaWVudCBVSSB3aGVuIGEgdXNlciB3aWxsIGVzdGFibGlzaCBhIGNvbm5lY3Rpb24gdG8gdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SHViTXNnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRIdWJNc2dcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCBUb2RheSdzIE1lc3NhZ2Ugb2YgVmlydHVhbCBIdWIuIFRoZSBtZXNzYWdlIHdpbGwgYmUgZGlzcGxheWVkIG9uIFZQTiBDbGllbnQgVUkgd2hlbiBhIHVzZXIgd2lsbCBlc3RhYmxpc2ggYSBjb25uZWN0aW9uIHRvIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLkdldEh1Yk1zZyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0SHViTXNnXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBSYWlzZSBhIHZpdGFsIGVycm9yIG9uIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlIHRvIHRlcm1pbmF0ZSB0aGUgcHJvY2VzcyBmb3JjZWZ1bGx5LiBUaGlzIEFQSSB3aWxsIHJhaXNlIGEgZmF0YWwgZXJyb3IgKG1lbW9yeSBhY2Nlc3MgdmlvbGF0aW9uKSBvbiB0aGUgVlBOIFNlcnZlciAvIEJyaWRnZSBydW5uaW5nIHByb2Nlc3MgaW4gb3JkZXIgdG8gY3Jhc2ggdGhlIHByb2Nlc3MuIEFzIHRoZSByZXN1bHQsIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugd2lsbCBiZSB0ZXJtaW5hdGVkIGFuZCByZXN0YXJ0ZWQgaWYgaXQgaXMgcnVubmluZyBhcyBhIHNlcnZpY2UgbW9kZS4gSWYgdGhlIFZQTiBTZXJ2ZXIgaXMgcnVubmluZyBhcyBhIHVzZXIgbW9kZSwgdGhlIHByb2Nlc3Mgd2lsbCBub3QgYXV0b21hdGljYWxseSByZXN0YXJ0ZWQuIFRoaXMgQVBJIGlzIGZvciBhIHNpdHVhdGlvbiB3aGVuIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlIGlzIHVuZGVyIGEgbm9uLXJlY292ZXJhYmxlIGVycm9yIG9yIHRoZSBwcm9jZXNzIGlzIGluIGFuIGluZmluaXRlIGxvb3AuIFRoaXMgQVBJIHdpbGwgZGlzY29ubmVjdCBhbGwgVlBOIFNlc3Npb25zIG9uIHRoZSBWUE4gU2VydmVyIC8gQnJpZGdlLiBBbGwgdW5zYXZlZCBzZXR0aW5ncyBpbiB0aGUgbWVtb3J5IG9mIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugd2lsbCBiZSBsb3N0LiBCZWZvcmUgcnVuIHRoaXMgQVBJLCBjYWxsIHRoZSBGbHVzaCBBUEkgdG8gdHJ5IHRvIHNhdmUgdm9sYXRpbGUgZGF0YSB0byB0aGUgY29uZmlndXJhdGlvbiBmaWxlLiBUbyBleGVjdXRlIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgLyBWUE4gQnJpZGdlIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gKi9cclxuICAgICAgICB0aGlzLkNyYXNoID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJDcmFzaFwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBtZXNzYWdlIGZvciBhZG1pbmlzdHJhdG9ycy4gKi9cclxuICAgICAgICB0aGlzLkdldEFkbWluTXNnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0QWRtaW5Nc2dcIiwgbmV3IFZwblJwY01zZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTYXZlIEFsbCBWb2xhdGlsZSBEYXRhIG9mIFZQTiBTZXJ2ZXIgLyBCcmlkZ2UgdG8gdGhlIENvbmZpZ3VyYXRpb24gRmlsZS4gVGhlIG51bWJlciBvZiBjb25maWd1cmF0aW9uIGZpbGUgYnl0ZXMgd2lsbCBiZSByZXR1cm5lZCBhcyB0aGUgXCJJbnRWYWx1ZVwiIHBhcmFtZXRlci4gTm9ybWFsbHksIHRoZSBWUE4gU2VydmVyIC8gVlBOIEJyaWRnZSByZXRhaW5zIHRoZSB2b2xhdGlsZSBjb25maWd1cmF0aW9uIGRhdGEgaW4gbWVtb3J5LiBJdCBpcyBmbHVzaGVkIHRvIHRoZSBkaXNrIGFzIHZwbl9zZXJ2ZXIuY29uZmlnIG9yIHZwbl9icmlkZ2UuY29uZmlnIHBlcmlvZGljYWxseS4gVGhlIHBlcmlvZCBpcyAzMDAgc2Vjb25kcyAoNSBtaW51dGVzKSBieSBkZWZhdWx0LiAoVGhlIHBlcmlvZCBjYW4gYmUgYWx0ZXJlZCBieSBtb2RpZnlpbmcgdGhlIEF1dG9TYXZlQ29uZmlnU3BhbiBpdGVtIGluIHRoZSBjb25maWd1cmF0aW9uIGZpbGUuKSBUaGUgZGF0YSB3aWxsIGJlIHNhdmVkIG9uIHRoZSB0aW1pbmcgb2Ygc2h1dHRpbmcgZG93biBub3JtYWxseSBvZiB0aGUgVlBOIFNlcnZlciAvIEJyaWRnZS4gRXhlY3V0ZSB0aGUgRmx1c2ggQVBJIHRvIG1ha2UgdGhlIFZQTiBTZXJ2ZXIgLyBCcmlkZ2Ugc2F2ZSB0aGUgc2V0dGluZ3MgdG8gdGhlIGZpbGUgaW1tZWRpYXRlbHkuIFRoZSBzZXR0aW5nIGRhdGEgd2lsbCBiZSBzdG9yZWQgb24gdGhlIGRpc2sgZHJpdmUgb2YgdGhlIHNlcnZlciBjb21wdXRlci4gVXNlIHRoZSBGbHVzaCBBUEkgaW4gYSBzaXR1YXRpb24gdGhhdCB5b3UgZG8gbm90IGhhdmUgYW4gZW5vdWdoIHRpbWUgdG8gc2h1dCBkb3duIHRoZSBzZXJ2ZXIgcHJvY2VzcyBub3JtYWxseS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVG8gZXhlY3V0ZSB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIC8gVlBOIEJyaWRnZSBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuICovXHJcbiAgICAgICAgdGhpcy5GbHVzaCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRmx1c2hcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEVuYWJsZSBvciBEaXNhYmxlIElQc2VjIFZQTiBTZXJ2ZXIgRnVuY3Rpb24uIEVuYWJsZSBvciBEaXNhYmxlIElQc2VjIFZQTiBTZXJ2ZXIgRnVuY3Rpb24gb24gdGhlIFZQTiBTZXJ2ZXIuIElmIHlvdSBlbmFibGUgdGhpcyBmdW5jdGlvbiwgVmlydHVhbCBIdWJzIG9uIHRoZSBWUE4gU2VydmVyIHdpbGwgYmUgYWJsZSB0byBhY2NlcHQgUmVtb3RlLUFjY2VzcyBWUE4gY29ubmVjdGlvbnMgZnJvbSBMMlRQLWNvbXBhdGlibGUgUENzLCBNYWMgT1MgWCBhbmQgU21hcnRwaG9uZXMsIGFuZCBhbHNvIGNhbiBhY2NlcHQgRXRoZXJJUCBTaXRlLXRvLVNpdGUgVlBOIENvbm5lY3Rpb24uIFZQTiBDb25uZWN0aW9ucyBmcm9tIFNtYXJ0cGhvbmVzIHN1Y2hsaWtlIGlQaG9uZSwgaVBhZCBhbmQgQW5kcm9pZCwgYW5kIGFsc28gZnJvbSBuYXRpdmUgVlBOIENsaWVudHMgb24gTWFjIE9TIFggYW5kIFdpbmRvd3MgY2FuIGJlIGFjY2VwdGVkLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuU2V0SVBzZWNTZXJ2aWNlcyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0SVBzZWNTZXJ2aWNlc1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBDdXJyZW50IElQc2VjIFZQTiBTZXJ2ZXIgU2V0dGluZ3MuIEdldCBhbmQgdmlldyB0aGUgY3VycmVudCBJUHNlYyBWUE4gU2VydmVyIHNldHRpbmdzIG9uIHRoZSBWUE4gU2VydmVyLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0SVBzZWNTZXJ2aWNlcyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldElQc2VjU2VydmljZXNcIiwgbmV3IFZwbklQc2VjU2VydmljZXMoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogQWRkIE5ldyBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgQ2xpZW50IFNldHRpbmcgdG8gQWNjZXB0IEV0aHJlSVAgLyBMMlRQdjMgQ2xpZW50IERldmljZXMuIEFkZCBhIG5ldyBzZXR0aW5nIGVudHJ5IHRvIGVuYWJsZSB0aGUgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIFNlcnZlciBGdW5jdGlvbiB0byBhY2NlcHQgY2xpZW50IGRldmljZXMuIEluIG9yZGVyIHRvIGFjY2VwdCBjb25uZWN0aW9ucyBmcm9tIHJvdXRlcnMgYnkgdGhlIEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBTZXJ2ZXIgRnVuY3Rpb24sIHlvdSBoYXZlIHRvIGRlZmluZSB0aGUgcmVsYXRpb24gdGFibGUgYmV0d2VlbiBhbiBJUHNlYyBQaGFzZSAxIHN0cmluZyB3aGljaCBpcyBwcmVzZW50ZWQgYnkgY2xpZW50IGRldmljZXMgb2YgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIGNvbXBhdGlibGUgcm91dGVyLCBhbmQgdGhlIGRlc2lnbmF0aW9uIG9mIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gQWZ0ZXIgeW91IGFkZCBhIGRlZmluaXRpb24gZW50cnkgYnkgQWRkRXRoZXJJcElkIEFQSSwgdGhlIGRlZmluZWQgY29ubmVjdGlvbiBzZXR0aW5nIHRvIHRoZSBWaXJ0dWFsIEh1YiB3aWxsIGJlIGFwcGxpZWQgb24gdGhlIGxvZ2luLWF0dGVwdGluZyBzZXNzaW9uIGZyb20gYW4gRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIGNsaWVudCBkZXZpY2UuIFRoZSB1c2VybmFtZSBhbmQgcGFzc3dvcmQgaW4gYW4gZW50cnkgbXVzdCBiZSByZWdpc3RlcmVkIG9uIHRoZSBWaXJ0dWFsIEh1Yi4gQW4gRXRoZXJJUCAvIEwyVFB2MyBjbGllbnQgd2lsbCBiZSByZWdhcmRlZCBhcyBpdCBjb25uZWN0ZWQgdGhlIFZpcnR1YWwgSFVCIHdpdGggdGhlIGlkZW50aWZpY2F0aW9uIG9mIHRoZSBhYm92ZSB1c2VyIGluZm9ybWF0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQWRkRXRoZXJJcElkID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJBZGRFdGhlcklwSWRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdldCB0aGUgQ3VycmVudCBMaXN0IG9mIEV0aGVySVAgLyBMMlRQdjMgQ2xpZW50IERldmljZSBFbnRyeSBEZWZpbml0aW9ucy4gVGhpcyBBUEkgZ2V0cyBhbmQgc2hvd3MgdGhlIGxpc3Qgb2YgZW50cmllcyB0byBhY2NlcHQgVlBOIGNsaWVudHMgYnkgRXRoZXJJUCAvIEwyVFB2MyBvdmVyIElQc2VjIEZ1bmN0aW9uLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiBZb3UgY2Fubm90IGV4ZWN1dGUgdGhpcyBBUEkgZm9yIFZpcnR1YWwgSHVicyBvZiBWUE4gU2VydmVycyBvcGVyYXRpbmcgYXMgYSBjbHVzdGVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0RXRoZXJJcElkID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRFdGhlcklwSWRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIERlbGV0ZSBhbiBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgQ2xpZW50IFNldHRpbmcuIFRoaXMgQVBJIGRlbGV0ZXMgYW4gZW50cnkgdG8gYWNjZXB0IFZQTiBjbGllbnRzIGJ5IEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBGdW5jdGlvbi4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkRlbGV0ZUV0aGVySXBJZCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiRGVsZXRlRXRoZXJJcElkXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBHZXQgdGhlIEN1cnJlbnQgTGlzdCBvZiBFdGhlcklQIC8gTDJUUHYzIENsaWVudCBEZXZpY2UgRW50cnkgRGVmaW5pdGlvbnMuIFRoaXMgQVBJIGdldHMgYW5kIHNob3dzIHRoZSBsaXN0IG9mIGVudHJpZXMgdG8gYWNjZXB0IFZQTiBjbGllbnRzIGJ5IEV0aGVySVAgLyBMMlRQdjMgb3ZlciBJUHNlYyBGdW5jdGlvbi4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLkVudW1FdGhlcklwSWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJFbnVtRXRoZXJJcElkXCIsIG5ldyBWcG5ScGNFbnVtRXRoZXJJcElkKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIFNldCBTZXR0aW5ncyBmb3IgT3BlblZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFRoZSBWUE4gU2VydmVyIGhhcyB0aGUgY2xvbmUgZnVuY3Rpb25zIG9mIE9wZW5WUE4gc29mdHdhcmUgcHJvZHVjdHMgYnkgT3BlblZQTiBUZWNobm9sb2dpZXMsIEluYy4gQW55IE9wZW5WUE4gQ2xpZW50cyBjYW4gY29ubmVjdCB0byB0aGlzIFZQTiBTZXJ2ZXIuIFRoZSBtYW5uZXIgdG8gc3BlY2lmeSBhIHVzZXJuYW1lIHRvIGNvbm5lY3QgdG8gdGhlIFZpcnR1YWwgSHViLCBhbmQgdGhlIHNlbGVjdGlvbiBydWxlIG9mIGRlZmF1bHQgSHViIGJ5IHVzaW5nIHRoaXMgY2xvbmUgc2VydmVyIGZ1bmN0aW9ucyBhcmUgc2FtZSB0byB0aGUgSVBzZWMgU2VydmVyIGZ1bmN0aW9ucy4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldE9wZW5WcG5Tc3RwQ29uZmlnID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRPcGVuVnBuU3N0cENvbmZpZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBDdXJyZW50IFNldHRpbmdzIG9mIE9wZW5WUE4gQ2xvbmUgU2VydmVyIEZ1bmN0aW9uLiBHZXQgYW5kIHNob3cgdGhlIGN1cnJlbnQgc2V0dGluZ3Mgb2YgT3BlblZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRPcGVuVnBuU3N0cENvbmZpZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldE9wZW5WcG5Tc3RwQ29uZmlnXCIsIG5ldyBWcG5PcGVuVnBuU3N0cENvbmZpZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTaG93IHRoZSBDdXJyZW50IFN0YXR1cyBvZiBEeW5hbWljIEROUyBGdW5jdGlvbi4gR2V0IGFuZCBzaG93IHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgRHluYW1pYyBETlMgZnVuY3Rpb24uIFRoZSBEeW5hbWljIEROUyBhc3NpZ25zIGEgdW5pcXVlIGFuZCBwZXJtYW5lbnQgRE5TIGhvc3RuYW1lIGZvciB0aGlzIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoYXQgaG9zdG5hbWUgdG8gc3BlY2lmeSB0aGlzIFZQTiBTZXJ2ZXIgb24gdGhlIHNldHRpbmdzIGZvciBWUE4gQ2xpZW50IGFuZCBWUE4gQnJpZGdlLiBZb3UgbmVlZCBub3QgdG8gcmVnaXN0ZXIgYW5kIGtlZXAgYSBkb21haW4gbmFtZS4gQWxzbywgaWYgeW91ciBJU1AgYXNzaWduZXMgeW91IGEgZHluYW1pYyAobm90LWZpeGVkKSBJUCBhZGRyZXNzLCB0aGUgY29ycmVzcG9uZGluZyBJUCBhZGRyZXNzIG9mIHlvdXIgRHluYW1pYyBETlMgaG9zdG5hbWUgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNoYW5nZWQuIEl0IGVuYWJsZXMgeW91IHRvIGtlZXAgcnVubmluZyB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBvbmx5IGEgZHluYW1pYyBJUCBhZGRyZXNzLiBUaGVyZWZvcmUsIHlvdSBuZWVkIG5vdCBhbnkgbG9uZ2VyIHRvIGtlZXAgc3RhdGljIGdsb2JhbCBJUCBhZGRyZXNzZXMgd2l0aCBleHBlbnNlcyBtb250aGx5IGNvc3RzLiBbQ2F1dGlvbl0gVG8gZGlzYWJsZSB0aGUgRHluYW1pYyBETlMgRnVuY3Rpb24sIG1vZGlmeSB0aGUgY29uZmlndXJhdGlvbiBmaWxlIG9mIFZQTiBTZXJ2ZXIuIFRoZSBcImRlY2xhcmUgcm9vdFwiIGRpcmVjdGl2ZSBoYXMgdGhlIFwiZGVjbGFyZSBERG5zQ2xpZW50XCIgZGlyZWN0aXZlLiBJbiB0aGlzIGRpcmVjdGl2ZSwgeW91IGNhbiBzd2l0Y2ggXCJib29sIERpc2FibGVcIiBmcm9tIGZhbHNlIHRvIHRydWUsIGFuZCByZWJvb3QgdGhlIFZQTiBTZXJ2ZXIsIHRoZW4gdGhlIER5bmFtaWMgRE5TIEZ1bmN0aW9uIHdpbGwgYmUgZGlzYWJsZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5HZXRERG5zQ2xpZW50U3RhdHVzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0RERuc0NsaWVudFN0YXR1c1wiLCBuZXcgVnBuRERuc0NsaWVudFN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIER5bmFtaWMgRE5TIEhvc3RuYW1lLiBZb3UgbXVzdCBzcGVjaWZ5IHRoZSBuZXcgaG9zdG5hbWUgb24gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gWW91IGNhbiB1c2UgdGhpcyBBUEkgdG8gY2hhbmdlIHRoZSBob3N0bmFtZSBhc3NpZ25lZCBieSB0aGUgRHluYW1pYyBETlMgZnVuY3Rpb24uIFRoZSBjdXJyZW50bHkgYXNzaWduZWQgaG9zdG5hbWUgY2FuIGJlIHNob3dlbiBieSB0aGUgR2V0RERuc0NsaWVudFN0YXR1cyBBUEkuIFRoZSBEeW5hbWljIEROUyBhc3NpZ25zIGEgdW5pcXVlIGFuZCBwZXJtYW5lbnQgRE5TIGhvc3RuYW1lIGZvciB0aGlzIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gdXNlIHRoYXQgaG9zdG5hbWUgdG8gc3BlY2lmeSB0aGlzIFZQTiBTZXJ2ZXIgb24gdGhlIHNldHRpbmdzIGZvciBWUE4gQ2xpZW50IGFuZCBWUE4gQnJpZGdlLiBZb3UgbmVlZCBub3QgdG8gcmVnaXN0ZXIgYW5kIGtlZXAgYSBkb21haW4gbmFtZS4gQWxzbywgaWYgeW91ciBJU1AgYXNzaWduZXMgeW91IGEgZHluYW1pYyAobm90LWZpeGVkKSBJUCBhZGRyZXNzLCB0aGUgY29ycmVzcG9uZGluZyBJUCBhZGRyZXNzIG9mIHlvdXIgRHluYW1pYyBETlMgaG9zdG5hbWUgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNoYW5nZWQuIEl0IGVuYWJsZXMgeW91IHRvIGtlZXAgcnVubmluZyB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBvbmx5IGEgZHluYW1pYyBJUCBhZGRyZXNzLiBUaGVyZWZvcmUsIHlvdSBuZWVkIG5vdCBhbnkgbG9uZ2VyIHRvIGtlZXAgc3RhdGljIGdsb2JhbCBJUCBhZGRyZXNzZXMgd2l0aCBleHBlbnNlcyBtb250aGx5IGNvc3RzLiBbQ2F1dGlvbl0gVG8gZGlzYWJsZSB0aGUgRHluYW1pYyBETlMgRnVuY3Rpb24sIG1vZGlmeSB0aGUgY29uZmlndXJhdGlvbiBmaWxlIG9mIFZQTiBTZXJ2ZXIuIFRoZSBcImRlY2xhcmUgcm9vdFwiIGRpcmVjdGl2ZSBoYXMgdGhlIFwiZGVjbGFyZSBERG5zQ2xpZW50XCIgZGlyZWN0aXZlLiBJbiB0aGlzIGRpcmVjdGl2ZSwgeW91IGNhbiBzd2l0Y2ggXCJib29sIERpc2FibGVcIiBmcm9tIGZhbHNlIHRvIHRydWUsIGFuZCByZWJvb3QgdGhlIFZQTiBTZXJ2ZXIsIHRoZW4gdGhlIER5bmFtaWMgRE5TIEZ1bmN0aW9uIHdpbGwgYmUgZGlzYWJsZWQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5DaGFuZ2VERG5zQ2xpZW50SG9zdG5hbWUgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkNoYW5nZUREbnNDbGllbnRIb3N0bmFtZVwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2VuZXJhdGUgTmV3IFNlbGYtU2lnbmVkIENlcnRpZmljYXRlIHdpdGggU3BlY2lmaWVkIENOIChDb21tb24gTmFtZSkgYW5kIFJlZ2lzdGVyIG9uIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gc3BlY2lmeSB0aGUgbmV3IENOIChjb21tb24gbmFtZSkgdmFsdWUgb24gdGhlIFN0clZhbHVlX3N0ciBmaWVsZC4gWW91IGNhbiB1c2UgdGhpcyBBUEkgdG8gcmVwbGFjZSB0aGUgY3VycmVudCBjZXJ0aWZpY2F0ZSBvbiB0aGUgVlBOIFNlcnZlciB0byBhIG5ldyBzZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSB3aGljaCBoYXMgdGhlIENOIChDb21tb24gTmFtZSkgdmFsdWUgaW4gdGhlIGZpZWxkcy4gVGhpcyBBUEkgaXMgY29udmVuaWVudCBpZiB5b3UgYXJlIHBsYW5uaW5nIHRvIHVzZSBNaWNyb3NvZnQgU1NUUCBWUE4gQ2xvbmUgU2VydmVyIEZ1bmN0aW9uLiBCZWNhdXNlIG9mIHRoZSB2YWx1ZSBvZiBDTiAoQ29tbW9uIE5hbWUpIG9uIHRoZSBTU0wgY2VydGlmaWNhdGUgb2YgVlBOIFNlcnZlciBtdXN0IG1hdGNoIHRvIHRoZSBob3N0bmFtZSBzcGVjaWZpZWQgb24gdGhlIFNTVFAgVlBOIGNsaWVudC4gVGhpcyBBUEkgd2lsbCBkZWxldGUgdGhlIGV4aXN0aW5nIFNTTCBjZXJ0aWZpY2F0ZSBvZiB0aGUgVlBOIFNlcnZlci4gSXQgaXMgcmVjb21tZW5kZWQgdG8gYmFja3VwIHRoZSBjdXJyZW50IFNTTCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgYnkgdXNpbmcgdGhlIEdldFNlcnZlckNlcnQgQVBJIGJlZm9yZWhhbmQuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5SZWdlbmVyYXRlU2VydmVyQ2VydCA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiUmVnZW5lcmF0ZVNlcnZlckNlcnRcIiwgaW5fcGFyYW0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEdlbmVyYXRlIGEgU2FtcGxlIFNldHRpbmcgRmlsZSBmb3IgT3BlblZQTiBDbGllbnQuIE9yaWdpbmFsbHksIHRoZSBPcGVuVlBOIENsaWVudCByZXF1aXJlcyBhIHVzZXIgdG8gd3JpdGUgYSB2ZXJ5IGRpZmZpY3VsdCBjb25maWd1cmF0aW9uIGZpbGUgbWFudWFsbHkuIFRoaXMgQVBJIGhlbHBzIHlvdSB0byBtYWtlIGEgdXNlZnVsIGNvbmZpZ3VyYXRpb24gc2FtcGxlLiBXaGF0IHlvdSBuZWVkIHRvIGdlbmVyYXRlIHRoZSBjb25maWd1cmF0aW9uIGZpbGUgZm9yIHRoZSBPcGVuVlBOIENsaWVudCBpcyB0byBydW4gdGhpcyBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5NYWtlT3BlblZwbkNvbmZpZ0ZpbGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJNYWtlT3BlblZwbkNvbmZpZ0ZpbGVcIiwgbmV3IFZwblJwY1JlYWRMb2dGaWxlKCkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLyoqIEVuYWJsZSAvIERpc2FibGUgdGhlIFZQTiBvdmVyIElDTVAgLyBWUE4gb3ZlciBETlMgU2VydmVyIEZ1bmN0aW9uLiBZb3UgY2FuIGVzdGFibGlzaCBhIFZQTiBvbmx5IHdpdGggSUNNUCBvciBETlMgcGFja2V0cyBldmVuIGlmIHRoZXJlIGlzIGEgZmlyZXdhbGwgb3Igcm91dGVycyB3aGljaCBibG9ja3MgVENQL0lQIGNvbW11bmljYXRpb25zLiBZb3UgaGF2ZSB0byBlbmFibGUgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnMgYmVmb3JlaGFuZC4gV2FybmluZzogVXNlIHRoaXMgZnVuY3Rpb24gZm9yIGVtZXJnZW5jeSBvbmx5LiBJdCBpcyBoZWxwZnVsIHdoZW4gYSBmaXJld2FsbCBvciByb3V0ZXIgaXMgbWlzY29uZmlndXJlZCB0byBibG9ja3MgVENQL0lQLCBidXQgZWl0aGVyIElDTVAgb3IgRE5TIGlzIG5vdCBibG9ja2VkLiBJdCBpcyBub3QgZm9yIGxvbmctdGVybSBzdGFibGUgdXNpbmcuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuICovXHJcbiAgICAgICAgdGhpcy5TZXRTcGVjaWFsTGlzdGVuZXIgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFNwZWNpYWxMaXN0ZW5lclwiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IEN1cnJlbnQgU2V0dGluZyBvZiB0aGUgVlBOIG92ZXIgSUNNUCAvIFZQTiBvdmVyIEROUyBGdW5jdGlvbi4gR2V0IGFuZCBzaG93IHRoZSBjdXJyZW50IFZQTiBvdmVyIElDTVAgLyBWUE4gb3ZlciBETlMgRnVuY3Rpb24gc3RhdHVzLiBUbyBjYWxsIHRoaXMgQVBJLCB5b3UgbXVzdCBoYXZlIFZQTiBTZXJ2ZXIgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzLiBUaGlzIEFQSSBjYW5ub3QgYmUgaW52b2tlZCBvbiBWUE4gQnJpZGdlLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0U3BlY2lhbExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0U3BlY2lhbExpc3RlbmVyXCIsIG5ldyBWcG5ScGNTcGVjaWFsTGlzdGVuZXIoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogU2hvdyB0aGUgY3VycmVudCBzdGF0dXMgb2YgVlBOIEF6dXJlIGZ1bmN0aW9uLiBHZXQgYW5kIHNob3cgdGhlIGN1cnJlbnQgc3RhdHVzIG9mIHRoZSBWUE4gQXp1cmUgZnVuY3Rpb24uIFZQTiBBenVyZSBtYWtlcyBpdCBlYXNpZXIgdG8gZXN0YWJsaXNoIGEgVlBOIFNlc3Npb24gZnJvbSB5b3VyIGhvbWUgUEMgdG8geW91ciBvZmZpY2UgUEMuIFdoaWxlIGEgVlBOIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQsIHlvdSBjYW4gYWNjZXNzIHRvIGFueSBvdGhlciBzZXJ2ZXJzIG9uIHRoZSBwcml2YXRlIG5ldHdvcmsgb2YgeW91ciBjb21wYW55LiBZb3UgZG9uJ3QgbmVlZCBhIGdsb2JhbCBJUCBhZGRyZXNzIG9uIHRoZSBvZmZpY2UgUEMgKFZQTiBTZXJ2ZXIpLiBJdCBjYW4gd29yayBiZWhpbmQgZmlyZXdhbGxzIG9yIE5BVHMuIE5vIG5ldHdvcmsgYWRtaW5pc3RyYXRvcidzIGNvbmZpZ3VyYXRpb24gcmVxdWlyZWQuIFlvdSBjYW4gdXNlIHRoZSBidWlsdC1pbiBTU1RQLVZQTiBDbGllbnQgb2YgV2luZG93cyBpbiB5b3VyIGhvbWUgUEMuIFZQTiBBenVyZSBpcyBhIGNsb3VkIFZQTiBzZXJ2aWNlIG9wZXJhdGVkIGJ5IFNvZnRFdGhlciBDb3Jwb3JhdGlvbi4gVlBOIEF6dXJlIGlzIGZyZWUgb2YgY2hhcmdlIGFuZCBhdmFpbGFibGUgdG8gYW55b25lLiBWaXNpdCBodHRwOi8vd3d3LnZwbmF6dXJlLm5ldC8gdG8gc2VlIGRldGFpbHMgYW5kIGhvdy10by11c2UgaW5zdHJ1Y3Rpb25zLiBUaGUgVlBOIEF6dXJlIGhvc3RuYW1lIGlzIHNhbWUgdG8gdGhlIGhvc3RuYW1lIG9mIHRoZSBEeW5hbWljIEROUyBzZXR0aW5nLCBidXQgYWx0ZXJpbmcgdGhlIGRvbWFpbiBzdWZmaXggdG8gXCJ2cG5henVyZS5uZXRcIi4gVG8gY2hhbmdlIHRoZSBob3N0bmFtZSB1c2UgdGhlIENoYW5nZUREbnNDbGllbnRIb3N0bmFtZSBBUEkuIFRvIGNhbGwgdGhpcyBBUEksIHlvdSBtdXN0IGhhdmUgVlBOIFNlcnZlciBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIFRoaXMgQVBJIGNhbm5vdCBiZSBpbnZva2VkIG9uIFZQTiBCcmlkZ2UuIFlvdSBjYW5ub3QgZXhlY3V0ZSB0aGlzIEFQSSBmb3IgVmlydHVhbCBIdWJzIG9mIFZQTiBTZXJ2ZXJzIG9wZXJhdGluZyBhcyBhIGNsdXN0ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRBenVyZVN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIkdldEF6dXJlU3RhdHVzXCIsIG5ldyBWcG5ScGNBenVyZVN0YXR1cygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBFbmFibGUgLyBEaXNhYmxlIFZQTiBBenVyZSBGdW5jdGlvbi4gRW5hYmxlIG9yIGRpc2FibGUgdGhlIFZQTiBBenVyZSBmdW5jdGlvbi4gVlBOIEF6dXJlIG1ha2VzIGl0IGVhc2llciB0byBlc3RhYmxpc2ggYSBWUE4gU2Vzc2lvbiBmcm9tIHlvdXIgaG9tZSBQQyB0byB5b3VyIG9mZmljZSBQQy4gV2hpbGUgYSBWUE4gY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZCwgeW91IGNhbiBhY2Nlc3MgdG8gYW55IG90aGVyIHNlcnZlcnMgb24gdGhlIHByaXZhdGUgbmV0d29yayBvZiB5b3VyIGNvbXBhbnkuIFlvdSBkb24ndCBuZWVkIGEgZ2xvYmFsIElQIGFkZHJlc3Mgb24gdGhlIG9mZmljZSBQQyAoVlBOIFNlcnZlcikuIEl0IGNhbiB3b3JrIGJlaGluZCBmaXJld2FsbHMgb3IgTkFUcy4gTm8gbmV0d29yayBhZG1pbmlzdHJhdG9yJ3MgY29uZmlndXJhdGlvbiByZXF1aXJlZC4gWW91IGNhbiB1c2UgdGhlIGJ1aWx0LWluIFNTVFAtVlBOIENsaWVudCBvZiBXaW5kb3dzIGluIHlvdXIgaG9tZSBQQy4gVlBOIEF6dXJlIGlzIGEgY2xvdWQgVlBOIHNlcnZpY2Ugb3BlcmF0ZWQgYnkgU29mdEV0aGVyIENvcnBvcmF0aW9uLiBWUE4gQXp1cmUgaXMgZnJlZSBvZiBjaGFyZ2UgYW5kIGF2YWlsYWJsZSB0byBhbnlvbmUuIFZpc2l0IGh0dHA6Ly93d3cudnBuYXp1cmUubmV0LyB0byBzZWUgZGV0YWlscyBhbmQgaG93LXRvLXVzZSBpbnN0cnVjdGlvbnMuIFRoZSBWUE4gQXp1cmUgaG9zdG5hbWUgaXMgc2FtZSB0byB0aGUgaG9zdG5hbWUgb2YgdGhlIER5bmFtaWMgRE5TIHNldHRpbmcsIGJ1dCBhbHRlcmluZyB0aGUgZG9tYWluIHN1ZmZpeCB0byBcInZwbmF6dXJlLm5ldFwiLiBUbyBjaGFuZ2UgdGhlIGhvc3RuYW1lIHVzZSB0aGUgQ2hhbmdlRERuc0NsaWVudEhvc3RuYW1lIEFQSS4gVG8gY2FsbCB0aGlzIEFQSSwgeW91IG11c3QgaGF2ZSBWUE4gU2VydmVyIGFkbWluaXN0cmF0b3IgcHJpdmlsZWdlcy4gVGhpcyBBUEkgY2Fubm90IGJlIGludm9rZWQgb24gVlBOIEJyaWRnZS4gWW91IGNhbm5vdCBleGVjdXRlIHRoaXMgQVBJIGZvciBWaXJ0dWFsIEh1YnMgb2YgVlBOIFNlcnZlcnMgb3BlcmF0aW5nIGFzIGEgY2x1c3Rlci4gKi9cclxuICAgICAgICB0aGlzLlNldEF6dXJlU3RhdHVzID0gZnVuY3Rpb24gKGluX3BhcmFtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJTZXRBenVyZVN0YXR1c1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBQcm94eSBTZXR0aW5ncyBmb3IgQ29ubmVjdGluZyB0byB0aGUgREROUyBzZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5HZXRERG5zSW50ZXJuZXRTZXR0bmcgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5DYWxsQXN5bmMoXCJHZXRERG5zSW50ZXJuZXRTZXR0bmdcIiwgbmV3IFZwbkludGVybmV0U2V0dGluZygpKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFByb3h5IFNldHRpbmdzIGZvciBDb25uZWN0aW5nIHRvIHRoZSBERE5TIHNlcnZlci4gKi9cclxuICAgICAgICB0aGlzLlNldEREbnNJbnRlcm5ldFNldHRuZyA9IGZ1bmN0aW9uIChpbl9wYXJhbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiU2V0RERuc0ludGVybmV0U2V0dG5nXCIsIGluX3BhcmFtKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKiBTZXQgdGhlIFZQTiBHYXRlIFNlcnZlciBDb25maWd1cmF0aW9uLiBUaGlzIEFQSSBpcyB2YWxpZCBmb3IgV2luMzIgYmluYXJ5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgU3RhYmxlIEVkaXRpb24gb2YgU29mdEV0aGVyIFZQTiBTZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5TZXRWZ3NDb25maWcgPSBmdW5jdGlvbiAoaW5fcGFyYW0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIF90aGlzLkNhbGxBc3luYyhcIlNldFZnc0NvbmZpZ1wiLCBpbl9wYXJhbSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKiogR2V0IHRoZSBWUE4gR2F0ZSBTZXJ2ZXIgQ29uZmlndXJhdGlvbi4gVGhpcyBBUEkgaXMgdmFsaWQgZm9yIFdpbjMyIGJpbmFyeSBkaXN0cmlidXRpb24gb2YgdGhlIFN0YWJsZSBFZGl0aW9uIG9mIFNvZnRFdGhlciBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuR2V0VmdzQ29uZmlnID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuQ2FsbEFzeW5jKFwiR2V0VmdzQ29uZmlnXCIsIG5ldyBWcG5WZ3NDb25maWcoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICB2YXIgaGVhZGVycyA9IHt9O1xyXG4gICAgICAgIHZhciBzZW5kX2NyZWRlbnRpYWxzID0gZmFsc2U7XHJcbiAgICAgICAgbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0ID0gaXNfbnVsbChub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQpID8gZmFsc2UgOiBub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQ7XHJcbiAgICAgICAgaWYgKGlzX251bGwodnBuc2VydmVyX2hvc3RuYW1lKSkge1xyXG4gICAgICAgICAgICB0aGlzLnJwY191cmwgPSBcIi9hcGkvXCI7XHJcbiAgICAgICAgICAgIHNlbmRfY3JlZGVudGlhbHMgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKGlzX251bGwodnBuc2VydmVyX3BvcnQpKVxyXG4gICAgICAgICAgICAgICAgdnBuc2VydmVyX3BvcnQgPSA0NDM7XHJcbiAgICAgICAgICAgIHRoaXMucnBjX3VybCA9IFwiaHR0cHM6Ly9cIiArIHZwbnNlcnZlcl9ob3N0bmFtZSArIFwiOlwiICsgdnBuc2VydmVyX3BvcnQgKyBcIi9hcGkvXCI7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbXCJYLVZQTkFETUlOLUhVQk5BTUVcIl0gPSBpc19udWxsKGh1Ym5hbWUpID8gXCJcIiA6IGh1Ym5hbWU7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbXCJYLVZQTkFETUlOLVBBU1NXT1JEXCJdID0gaXNfbnVsbChwYXNzd29yZCkgPyBcIlwiIDogcGFzc3dvcmQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc19udWxsKG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCkpXHJcbiAgICAgICAgICAgIG5vZGVqc19odHRwc19jbGllbnRfcmVqZWN0X3VudHJ1c3RlZF9zZXJ2ZXJfY2VydCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMucnBjX2NsaWVudCA9IG5ldyBKc29uUnBjQ2xpZW50KHRoaXMucnBjX3VybCwgaGVhZGVycywgc2VuZF9jcmVkZW50aWFscywgbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0KTtcclxuICAgIH1cclxuICAgIC8qKiBEZXRlcm1pbmUgaWYgdGhpcyBKYXZhU2NyaXB0IGVudmlyb25tZW50IGlzIG9uIHRoZSBOb2RlLmpzIG9yIG5vdC4gKi9cclxuICAgIFZwblNlcnZlclJwYy5Jc05vZGVKUyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gaXNfbm9kZV9qcztcclxuICAgIH07XHJcbiAgICAvKiogU2V0IHRoZSBkZWJ1ZyBtb2RlIGZsYWcgKi9cclxuICAgIFZwblNlcnZlclJwYy5TZXREZWJ1Z01vZGUgPSBmdW5jdGlvbiAoZmxhZykge1xyXG4gICAgICAgIGRlYnVnX21vZGUgPSBmbGFnO1xyXG4gICAgfTtcclxuICAgIC8vIC0tIFV0aWxpdHkgZnVuY3Rpb25zIC0tXHJcbiAgICAvKiogQ2FsbCBhIFJQQyBwcm9jZWR1cmUgKi9cclxuICAgIFZwblNlcnZlclJwYy5wcm90b3R5cGUuQ2FsbEFzeW5jID0gZnVuY3Rpb24gKG1ldGhvZF9uYW1lLCByZXF1ZXN0KSB7XHJcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzcG9uc2U7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6IHJldHVybiBbNCAvKnlpZWxkKi8sIHRoaXMucnBjX2NsaWVudC5DYWxsQXN5bmMobWV0aG9kX25hbWUsIHJlcXVlc3QpXTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gX2Euc2VudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgcmVzcG9uc2VdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gVnBuU2VydmVyUnBjO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblNlcnZlclJwYyA9IFZwblNlcnZlclJwYztcclxuLy8gLS0tIFR5cGVzIC0tLVxyXG4vKiogSVAgUHJvdG9jb2wgTnVtYmVycyAqL1xyXG52YXIgVnBuSXBQcm90b2NvbE51bWJlcjtcclxuKGZ1bmN0aW9uIChWcG5JcFByb3RvY29sTnVtYmVyKSB7XHJcbiAgICAvKiogSUNNUCBmb3IgSVB2NCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiSUNNUHY0XCJdID0gMV0gPSBcIklDTVB2NFwiO1xyXG4gICAgLyoqIFRDUCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiVENQXCJdID0gNl0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuSXBQcm90b2NvbE51bWJlcltWcG5JcFByb3RvY29sTnVtYmVyW1wiVURQXCJdID0gMTddID0gXCJVRFBcIjtcclxuICAgIC8qKiBJQ01QIGZvciBJUHY2ICovXHJcbiAgICBWcG5JcFByb3RvY29sTnVtYmVyW1ZwbklwUHJvdG9jb2xOdW1iZXJbXCJJQ01QdjZcIl0gPSA1OF0gPSBcIklDTVB2NlwiO1xyXG59KShWcG5JcFByb3RvY29sTnVtYmVyID0gZXhwb3J0cy5WcG5JcFByb3RvY29sTnVtYmVyIHx8IChleHBvcnRzLlZwbklwUHJvdG9jb2xOdW1iZXIgPSB7fSkpO1xyXG4vKiogVGhlIGJvZHkgb2YgdGhlIEFjY2VzcyBsaXN0ICovXHJcbnZhciBWcG5BY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQWNjZXNzJyBjbGFzczogVGhlIGJvZHkgb2YgdGhlIEFjY2VzcyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5BY2Nlc3MoaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogU3BlY2lmeSBhIGRlc2NyaXB0aW9uIChub3RlKSBmb3IgdGhpcyBydWxlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEVuYWJsZWQgZmxhZyAodHJ1ZTogZW5hYmxlZCwgZmFsc2U6IGRpc2FibGVkKSAqL1xyXG4gICAgICAgIHRoaXMuQWN0aXZlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSBhbiBpbnRlZ2VyIG9mIDEgb3IgaGlnaGVyIHRvIGluZGljYXRlIHRoZSBwcmlvcml0eSBvZiB0aGUgcnVsZS4gSGlnaGVyIHByaW9yaXR5IGlzIGdpdmVuIHRvIHJ1bGVzIHdpdGggdGhlIGxvd2VyIHByaW9yaXR5IHZhbHVlcy4gKi9cclxuICAgICAgICB0aGlzLlByaW9yaXR5X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIGlmIHRoZSBydWxlIGlzIERJU0NBUkQgb3BlcmF0aW9uIG9yIFBBU1Mgb3BlcmF0aW9uLiBXaGVuIGEgcGFja2V0IG1hdGNoZXMgdGhpcyBydWxlIGNvbmRpdGlvbiwgdGhpcyBvcGVyYXRpb24gaXMgZGVjaWRlZC4gV2hlbiB0aGUgb3BlcmF0aW9uIG9mIHRoZSBydWxlIGlzIFBBU1MsIHRoZSBwYWNrZXQgaXMgYWxsb3dlZCB0byBwYXNzLCBvdGhlcndpc2UgdGhlIHBhY2tldCB3aWxsIGJlIGRpc2NhcmRlZC4gKi9cclxuICAgICAgICB0aGlzLkRpc2NhcmRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyBpZiB0aGUgcnVsZSBpcyBmb3IgSVB2Ni4gU3BlY2lmeSBmYWxzZSBmb3IgSVB2NCwgb3Igc3BlY2lmeSB0cnVlIGZvciBJUHY2LiAqL1xyXG4gICAgICAgIHRoaXMuSXNJUHY2X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY0IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gWW91IG11c3QgYWxzbyBzcGVjaWZ5IHRoZSBTcmNTdWJuZXRNYXNrX2lwIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY0IHN1Ym5ldCBtYXNrIGFzIGEgcnVsZSBjb25kaXRpb24uIFwiMC4wLjAuMFwiIG1lYW5zIGFsbCBob3N0cy4gXCIyNTUuMjU1LjI1NS4yNTVcIiBtZWFucyBvbmUgc2luZ2xlIGhvc3QuICovXHJcbiAgICAgICAgdGhpcy5TcmNTdWJuZXRNYXNrX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiB0aGUgcnVsZSBpcyBJUHY0IG1vZGUgKElzSVB2Nl9ib29sID09IGZhbHNlKS4gU3BlY2lmeSBhIGRlc3RpbmF0aW9uIElQdjQgYWRkcmVzcyBhcyBhIHJ1bGUgY29uZGl0aW9uLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIERlc3RTdWJuZXRNYXNrX2lwIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuRGVzdElwQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NCBtb2RlIChJc0lQdjZfYm9vbCA9PSBmYWxzZSkuIFNwZWNpZnkgYSBkZXN0aW5hdGlvbiBJUHY0IHN1Ym5ldCBtYXNrIGFzIGEgcnVsZSBjb25kaXRpb24uIFwiMC4wLjAuMFwiIG1lYW5zIGFsbCBob3N0cy4gXCIyNTUuMjU1LjI1NS4yNTVcIiBtZWFucyBvbmUgc2luZ2xlIGhvc3QuICovXHJcbiAgICAgICAgdGhpcy5EZXN0U3VibmV0TWFza19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NiBtb2RlIChJc0lQdjZfYm9vbCA9PSB0cnVlKS4gU3BlY2lmeSBhIHNvdXJjZSBJUHY2IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBhZGRyZXNzIGluIGJpbmFyeSBmb3JtLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIFNyY1N1Ym5ldE1hc2s2X2JpbiBmaWVsZC4gKi9cclxuICAgICAgICB0aGlzLlNyY0lwQWRkcmVzczZfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGlmIHRoZSBydWxlIGlzIElQdjYgbW9kZSAoSXNJUHY2X2Jvb2wgPT0gdHJ1ZSkuIFNwZWNpZnkgYSBzb3VyY2UgSVB2NiBzdWJuZXQgbWFzayBhcyBhIHJ1bGUgY29uZGl0aW9uLiBUaGUgZmllbGQgbXVzdCBiZSBhIGJ5dGUgYXJyYXkgb2YgMTYgYnl0ZXMgKDEyOCBiaXRzKSB0byBjb250YWluIHRoZSBJUHY2IHN1Ym5ldCBtYXNrIGluIGJpbmFyeSBmb3JtLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjU3VibmV0TWFzazZfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGlmIHRoZSBydWxlIGlzIElQdjYgbW9kZSAoSXNJUHY2X2Jvb2wgPT0gdHJ1ZSkuIFNwZWNpZnkgYSBkZXN0aW5hdGlvbiBJUHY2IGFkZHJlc3MgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBhZGRyZXNzIGluIGJpbmFyeSBmb3JtLiBZb3UgbXVzdCBhbHNvIHNwZWNpZnkgdGhlIERlc3RTdWJuZXRNYXNrNl9iaW4gZmllbGQuICovXHJcbiAgICAgICAgdGhpcy5EZXN0SXBBZGRyZXNzNl9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgaWYgdGhlIHJ1bGUgaXMgSVB2NiBtb2RlIChJc0lQdjZfYm9vbCA9PSB0cnVlKS4gU3BlY2lmeSBhIGRlc3RpbmF0aW9uIElQdjYgc3VibmV0IG1hc2sgYXMgYSBydWxlIGNvbmRpdGlvbi4gVGhlIGZpZWxkIG11c3QgYmUgYSBieXRlIGFycmF5IG9mIDE2IGJ5dGVzICgxMjggYml0cykgdG8gY29udGFpbiB0aGUgSVB2NiBzdWJuZXQgbWFzayBpbiBiaW5hcnkgZm9ybS4gKi9cclxuICAgICAgICB0aGlzLkRlc3RTdWJuZXRNYXNrNl9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFRoZSBJUCBwcm90b2NvbCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlByb3RvY29sX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBTdGFydCBWYWx1ZSBvZiB0aGUgU291cmNlIFBvcnQgTnVtYmVyIFJhbmdlLiBJZiB0aGUgc3BlY2lmaWVkIHByb3RvY29sIGlzIFRDUC9JUCBvciBVRFAvSVAsIHNwZWNpZnkgdGhlIHNvdXJjZSBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5TcmNQb3J0U3RhcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIEVuZCBWYWx1ZSBvZiB0aGUgU291cmNlIFBvcnQgTnVtYmVyIFJhbmdlLiBJZiB0aGUgc3BlY2lmaWVkIHByb3RvY29sIGlzIFRDUC9JUCBvciBVRFAvSVAsIHNwZWNpZnkgdGhlIHNvdXJjZSBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5TcmNQb3J0RW5kX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBTdGFydCBWYWx1ZSBvZiB0aGUgRGVzdGluYXRpb24gUG9ydCBOdW1iZXIgUmFuZ2UuIElmIHRoZSBzcGVjaWZpZWQgcHJvdG9jb2wgaXMgVENQL0lQIG9yIFVEUC9JUCwgc3BlY2lmeSB0aGUgZGVzdGluYXRpb24gcG9ydCBudW1iZXIgYXMgdGhlIHJ1bGUgY29uZGl0aW9uLiBQcm90b2NvbHMgb3RoZXIgdGhhbiB0aGlzIHdpbGwgYmUgaWdub3JlZC4gV2hlbiB0aGlzIHBhcmFtZXRlciBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgcnVsZXMgd2lsbCBhcHBseSB0byBhbGwgcG9ydCBudW1iZXJzLiAqL1xyXG4gICAgICAgIHRoaXMuRGVzdFBvcnRTdGFydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgRW5kIFZhbHVlIG9mIHRoZSBEZXN0aW5hdGlvbiBQb3J0IE51bWJlciBSYW5nZS4gSWYgdGhlIHNwZWNpZmllZCBwcm90b2NvbCBpcyBUQ1AvSVAgb3IgVURQL0lQLCBzcGVjaWZ5IHRoZSBkZXN0aW5hdGlvbiBwb3J0IG51bWJlciBhcyB0aGUgcnVsZSBjb25kaXRpb24uIFByb3RvY29scyBvdGhlciB0aGFuIHRoaXMgd2lsbCBiZSBpZ25vcmVkLiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBydWxlcyB3aWxsIGFwcGx5IHRvIGFsbCBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5EZXN0UG9ydEVuZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgdXNlciBuYW1lLiBZb3UgY2FuIGFwcGx5IHRoaXMgcnVsZSB0byBvbmx5IHRoZSBwYWNrZXRzIHNlbnQgYnkgYSB1c2VyIHNlc3Npb24gb2YgYSB1c2VyIG5hbWUgdGhhdCBoYXMgYmVlbiBzcGVjaWZpZWQgYXMgYSBydWxlIGNvbmRpdGlvbi4gSW4gdGhpcyBjYXNlLCBzcGVjaWZ5IHRoZSB1c2VyIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5TcmNVc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiB1c2VyIG5hbWUuIFlvdSBjYW4gYXBwbHkgdGhpcyBydWxlIHRvIG9ubHkgdGhlIHBhY2tldHMgcmVjZWl2ZWQgYnkgYSB1c2VyIHNlc3Npb24gb2YgYSB1c2VyIG5hbWUgdGhhdCBoYXMgYmVlbiBzcGVjaWZpZWQgYXMgYSBydWxlIGNvbmRpdGlvbi4gSW4gdGhpcyBjYXNlLCBzcGVjaWZ5IHRoZSB1c2VyIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5EZXN0VXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBzb3VyY2UgTUFDIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5DaGVja1NyY01hY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNvdXJjZSBNQUMgYWRkcmVzcyAoNiBieXRlcyksIHZhbGlkIG9ubHkgaWYgQ2hlY2tTcmNNYWNfYm9vbCA9PSB0cnVlLiAqL1xyXG4gICAgICAgIHRoaXMuU3JjTWFjQWRkcmVzc19iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFNvdXJjZSBNQUMgYWRkcmVzcyBtYXNrICg2IGJ5dGVzKSwgdmFsaWQgb25seSBpZiBDaGVja1NyY01hY19ib29sID09IHRydWUuICovXHJcbiAgICAgICAgdGhpcy5TcmNNYWNNYXNrX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBkZXN0aW5hdGlvbiBNQUMgYWRkcmVzcy4gKi9cclxuICAgICAgICB0aGlzLkNoZWNrRHN0TWFjX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gTUFDIGFkZHJlc3MgKDYgYnl0ZXMpLCB2YWxpZCBvbmx5IGlmIENoZWNrU3JjTWFjX2Jvb2wgPT0gdHJ1ZS4gKi9cclxuICAgICAgICB0aGlzLkRzdE1hY0FkZHJlc3NfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiBNQUMgYWRkcmVzcyBtYXNrICg2IGJ5dGVzKSwgdmFsaWQgb25seSBpZiBDaGVja1NyY01hY19ib29sID09IHRydWUuICovXHJcbiAgICAgICAgdGhpcy5Ec3RNYWNNYXNrX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSB3YW50IHRvIGNoZWNrIHRoZSBzdGF0ZSBvZiB0aGUgVENQIGNvbm5lY3Rpb24uICovXHJcbiAgICAgICAgdGhpcy5DaGVja1RjcFN0YXRlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBpZiBDaGVja1RjcFN0YXRlX2Jvb2wgPT0gdHJ1ZS4gU2V0IHRoaXMgZmllbGQgdHJ1ZSB0byBtYXRjaCBvbmx5IFRDUC1lc3RhYmxpc2hlZCBwYWNrZXRzLiBTZXQgdGhpcyBmaWVsZCBmYWxzZSB0byBtYXRjaCBvbmx5IFRDUC1ub24gZXN0YWJsaXNoZWQgcGFja2V0cy4gKi9cclxuICAgICAgICB0aGlzLkVzdGFibGlzaGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2V0IHRoaXMgdmFsdWUgdG8gZ2VuZXJhdGUgZGVsYXlzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSBkZWxheSBwZXJpb2QgaW4gbWlsbGlzZWNvbmRzLiBTcGVjaWZ5IDAgbWVhbnMgbm8gZGVsYXlzIHRvIGdlbmVyYXRlLiBUaGUgZGVsYXlzIG11c3QgYmUgMTAwMDAgbWlsbGlzZWNvbmRzIGF0IG1vc3QuICovXHJcbiAgICAgICAgdGhpcy5EZWxheV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXQgdGhpcyB2YWx1ZSB0byBnZW5lcmF0ZSBqaXR0ZXJzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSByYXRpbyBvZiBmbHVjdHVhdGlvbiBvZiBqaXR0ZXJzIHdpdGhpbiAwJSB0byAxMDAlIHJhbmdlLiBTcGVjaWZ5IDAgbWVhbnMgbm8gaml0dGVycyB0byBnZW5lcmF0ZS4gKi9cclxuICAgICAgICB0aGlzLkppdHRlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXQgdGhpcyB2YWx1ZSB0byBnZW5lcmF0ZSBwYWNrZXQgbG9zc2VzIHdoZW4gcGFja2V0cyBpcyBwYXNzaW5nLiBTcGVjaWZ5IHRoZSByYXRpbyBvZiBwYWNrZXQgbG9zc2VzIHdpdGhpbiAwJSB0byAxMDAlIHJhbmdlLiBTcGVjaWZ5IDAgbWVhbnMgbm8gcGFja2V0IGxvc3NlcyB0byBnZW5lcmF0ZS4gKi9cclxuICAgICAgICB0aGlzLkxvc3NfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIHNwZWNpZmllZCBVUkwgd2lsbCBiZSBtYW5kYXRvcnkgcmVwbGllZCB0byB0aGUgY2xpZW50IGFzIGEgcmVzcG9uc2UgZm9yIFRDUCBjb25uZWN0aW5nIHJlcXVlc3QgcGFja2V0cyB3aGljaCBtYXRjaGVzIHRoZSBjb25kaXRpb25zIG9mIHRoaXMgYWNjZXNzIGxpc3QgZW50cnkgdmlhIHRoaXMgVmlydHVhbCBIdWIuIFRvIHVzZSB0aGlzIHNldHRpbmcsIHlvdSBjYW4gZW5mb3JjZSB0aGUgd2ViIGJyb3dzZXIgb2YgdGhlIFZQTiBDbGllbnQgY29tcHV0ZXIgdG8gc2hvdyB0aGUgc3BlY2lmaWVkIHdlYiBzaXRlIHdoZW4gdGhhdCB3ZWIgYnJvd3NlciB0cmllcyB0byBhY2Nlc3MgdGhlIHNwZWNpZmljIElQIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5SZWRpcmVjdFVybF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQWNjZXNzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwbkFjY2VzcyA9IFZwbkFjY2VzcztcclxuLyoqIEFkZCBhbiBpdGVtIHRvIEFjY2VzcyBMaXN0ICovXHJcbnZhciBWcG5ScGNBZGRBY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQWRkQWNjZXNzJyBjbGFzczogQWRkIGFuIGl0ZW0gdG8gQWNjZXNzIExpc3QgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0FkZEFjY2Vzcyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEFjY2VzcyBsaXN0IChNdXN0IGJlIGEgc2luZ2xlIGl0ZW0pICovXHJcbiAgICAgICAgdGhpcy5BY2Nlc3NMaXN0U2luZ2xlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNBZGRBY2Nlc3M7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQWRkQWNjZXNzID0gVnBuUnBjQWRkQWNjZXNzO1xyXG4vKiogQWRkIENBIHRvIEhVQiAqL1xyXG52YXIgVnBuUnBjSHViQWRkQ0EgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViQWRkQ0EnIGNsYXNzOiBBZGQgQ0EgdG8gSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJBZGRDQShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBib2R5IG9mIHRoZSBYLjUwOSBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuQ2VydF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNIdWJBZGRDQTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJBZGRDQSA9IFZwblJwY0h1YkFkZENBO1xyXG4vKiogQ1JMIGVudHJ5ICovXHJcbnZhciBWcG5ScGNDcmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQ3JsJyBjbGFzczogQ1JMIGVudHJ5ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNDcmwoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBLZXkgSUQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDTiwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkNvbW1vbk5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTywgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLk9yZ2FuaXphdGlvbl91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPVSwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLlVuaXRfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogQywgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkNvdW50cnlfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogU1QsIG9wdGlvbmFsICovXHJcbiAgICAgICAgdGhpcy5TdGF0ZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBMLCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuTG9jYWxfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogU2VyaWFsLCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuU2VyaWFsX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogTUQ1IERpZ2VzdCwgb3B0aW9uYWwgKi9cclxuICAgICAgICB0aGlzLkRpZ2VzdE1ENV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFNIQTEgRGlnZXN0LCBvcHRpb25hbCAqL1xyXG4gICAgICAgIHRoaXMuRGlnZXN0U0hBMV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNDcmw7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQ3JsID0gVnBuUnBjQ3JsO1xyXG4vKiogRXRoZXJJUCBrZXkgbGlzdCBlbnRyeSAqL1xyXG52YXIgVnBuRXRoZXJJcElkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwbkV0aGVySXBJZCcgY2xhc3M6IEV0aGVySVAga2V5IGxpc3QgZW50cnkgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkV0aGVySXBJZChpbml0KSB7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgYW4gSVNBS01QIFBoYXNlIDEgSUQuIFRoZSBJRCBtdXN0IGJlIGV4YWN0bHkgc2FtZSBhcyBhIElEIGluIHRoZSBjb25maWd1cmF0aW9uIG9mIHRoZSBFdGhlcklQIC8gTDJUUHYzIENsaWVudC4gWW91IGNhbiBzcGVjaWZ5IElQIGFkZHJlc3MgYXMgd2VsbCBhcyBjaGFyYWN0ZXJzIGFzIElELCBpZiB0aGUgRXRoZXJJUCBDbGllbnQgdXNlcyBJUCBhZGRyZXNzIGFzIFBoYXNlIDEgSUQuIElmIHlvdSBzcGVjaWZ5ICcqJyAoYXN0ZXJpc2spLCBpdCB3aWxsIGJlIGEgd2lsZGNhcmQgdG8gbWF0Y2ggYW55IGNsaWVudHMgd2hpY2ggZG9lc24ndCBtYXRjaCBvdGhlciBleHBsaWNpdCBydWxlcy4gKi9cclxuICAgICAgICB0aGlzLklkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIG5hbWUgb2YgdGhlIFZpcnR1YWwgSHViIHRvIGNvbm5lY3QuICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHVzZXJuYW1lIHRvIGxvZ2luIHRvIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLlVzZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHBhc3N3b3JkIHRvIGxvZ2luIHRvIHRoZSBkZXN0aW5hdGlvbiBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzLlBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5FdGhlcklwSWQ7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuRXRoZXJJcElkID0gVnBuRXRoZXJJcElkO1xyXG4vKiogTGF5ZXItMyB2aXJ0dWFsIGludGVyZmFjZSAqL1xyXG52YXIgVnBuUnBjTDNJZiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNMM0lmJyBjbGFzczogTGF5ZXItMyB2aXJ0dWFsIGludGVyZmFjZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTDNJZihpbml0KSB7XHJcbiAgICAgICAgLyoqIEwzIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSFVCIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLlN1Ym5ldE1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTDNJZjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMM0lmID0gVnBuUnBjTDNJZjtcclxuLyoqIExheWVyLTMgc3dpdGNoICovXHJcbnZhciBWcG5ScGNMM1N3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0wzU3cnIGNsYXNzOiBMYXllci0zIHN3aXRjaCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTDNTdyhpbml0KSB7XHJcbiAgICAgICAgLyoqIExheWVyLTMgU3dpdGNoIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0wzU3c7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTDNTdyA9IFZwblJwY0wzU3c7XHJcbi8qKiBSb3V0aW5nIHRhYmxlICovXHJcbnZhciBWcG5ScGNMM1RhYmxlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0wzVGFibGUnIGNsYXNzOiBSb3V0aW5nIHRhYmxlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMM1RhYmxlKGluaXQpIHtcclxuICAgICAgICAvKiogTDMgc3dpdGNoIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTmV0d29yayBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5OZXR3b3JrQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFN1Ym5ldCBtYXNrICovXHJcbiAgICAgICAgdGhpcy5TdWJuZXRNYXNrX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogR2F0ZXdheSBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5HYXRld2F5QWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE1ldHJpYyAqL1xyXG4gICAgICAgIHRoaXMuTWV0cmljX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMM1RhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0wzVGFibGUgPSBWcG5ScGNMM1RhYmxlO1xyXG4vKiogR2VuZXJpYyBwYXJhbWV0ZXIgdG8gY29udGFpbiB1MzIsIHU2NCwgYXNjaWlfc3RyaW5nIGFuZCB1bmljb2RlIHN0cmluZyAqL1xyXG52YXIgVnBuUnBjVGVzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNUZXN0JyBjbGFzczogR2VuZXJpYyBwYXJhbWV0ZXIgdG8gY29udGFpbiB1MzIsIHU2NCwgYXNjaWlfc3RyaW5nIGFuZCB1bmljb2RlIHN0cmluZyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjVGVzdChpbml0KSB7XHJcbiAgICAgICAgLyoqIEEgMzItYml0IGludGVnZXIgZmllbGQgKi9cclxuICAgICAgICB0aGlzLkludFZhbHVlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEEgNjQtYml0IGludGVnZXIgZmllbGQgKi9cclxuICAgICAgICB0aGlzLkludDY0VmFsdWVfdTY0ID0gMDtcclxuICAgICAgICAvKiogQW4gQXNjaWkgc3RyaW5nIGZpZWxkICovXHJcbiAgICAgICAgdGhpcy5TdHJWYWx1ZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBBbiBVVEYtOCBzdHJpbmcgZmllbGQgKi9cclxuICAgICAgICB0aGlzLlVuaVN0clZhbHVlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNUZXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1Rlc3QgPSBWcG5ScGNUZXN0O1xyXG4vKiogTG9jYWwgQnJpZGdlIGxpc3QgaXRlbSAqL1xyXG52YXIgVnBuUnBjTG9jYWxCcmlkZ2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTG9jYWxCcmlkZ2UnIGNsYXNzOiBMb2NhbCBCcmlkZ2UgbGlzdCBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMb2NhbEJyaWRnZShpbml0KSB7XHJcbiAgICAgICAgLyoqIFBoeXNpY2FsIEV0aGVybmV0IGRldmljZSBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXZpY2VOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lTEJfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT25saW5lIGZsYWcgKi9cclxuICAgICAgICB0aGlzLk9ubGluZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFJ1bm5pbmcgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuQWN0aXZlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0cnVlIGlmIHlvdSBhcmUgdXNpbmcgYSB0YXAgZGV2aWNlIHJhdGhlciB0aGFuIGEgbmV0d29yayBhZGFwdGVyIGZvciB0aGUgYnJpZGdlIGRlc3RpbmF0aW9uIChvbmx5IHN1cHBvcnRlZCBmb3IgTGludXggdmVyc2lvbnMpLiAqL1xyXG4gICAgICAgIHRoaXMuVGFwTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMb2NhbEJyaWRnZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMb2NhbEJyaWRnZSA9IFZwblJwY0xvY2FsQnJpZGdlO1xyXG4vKiogQ3JlYXRlLCBjb25maWd1cmUsIGFuZCBnZXQgdGhlIGdyb3VwICovXHJcbnZhciBWcG5ScGNTZXRHcm91cCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNTZXRHcm91cCcgY2xhc3M6IENyZWF0ZSwgY29uZmlndXJlLCBhbmQgZ2V0IHRoZSBncm91cCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2V0R3JvdXAoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgZ3JvdXAgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCByZWFsIG5hbWUgKGZ1bGwgbmFtZSkgb2YgdGhlIGdyb3VwLCBhbGxvdyB1c2luZyBhbnkgVW5pY29kZSBjaGFyYWN0ZXJzICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCwgc3BlY2lmeSBhIGRlc2NyaXB0aW9uIG9mIHRoZSBncm91cCAqL1xyXG4gICAgICAgIHRoaXMuTm90ZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0byB1c2Ugc2VjdXJpdHkgcG9saWN5ICovXHJcbiAgICAgICAgdGhpcy5Vc2VQb2xpY3lfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEFsbG93IEFjY2Vzcy4gVGhlIHVzZXJzLCB3aGljaCB0aGlzIHBvbGljeSB2YWx1ZSBpcyB0cnVlLCBoYXZlIHBlcm1pc3Npb24gdG8gbWFrZSBWUE4gY29ubmVjdGlvbiB0byBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6QWNjZXNzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY0KS4gQWxsIElQdjQgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1BGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERpc2FsbG93IERIQ1AgU2VydmVyIE9wZXJhdGlvbiAoSVB2NCkuIENvbXB1dGVycyBjb25uZWN0ZWQgdG8gc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBub3QgYmUgYWxsb3dlZCB0byBiZWNvbWUgYSBESENQIHNlcnZlciBhbmQgZGlzdHJpYnV0ZSBJUHY0IGFkZHJlc3NlcyB0byBESENQIGNsaWVudHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQTm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEVuZm9yY2UgREhDUCBBbGxvY2F0ZWQgSVAgQWRkcmVzc2VzIChJUHY0KS4gQ29tcHV0ZXJzIGluIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgb25seSBiZSBhYmxlIHRvIHVzZSBJUHY0IGFkZHJlc3NlcyBhbGxvY2F0ZWQgYnkgYSBESENQIHNlcnZlciBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHNpZGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRm9yY2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgQnJpZGdlIE9wZXJhdGlvbi4gQnJpZGdlLW1vZGUgY29ubmVjdGlvbnMgYXJlIGRlbmllZCBmb3IgdXNlciBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZy4gRXZlbiBpbiBjYXNlcyB3aGVuIHRoZSBFdGhlcm5ldCBCcmlkZ2UgaXMgY29uZmlndXJlZCBpbiB0aGUgY2xpZW50IHNpZGUsIGNvbW11bmljYXRpb24gd2lsbCBub3QgYmUgcG9zc2libGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0JyaWRnZV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBSb3V0aW5nIE9wZXJhdGlvbiAoSVB2NCkuIElQdjQgcm91dGluZyB3aWxsIGJlIGRlbmllZCBmb3Igc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcuIEV2ZW4gaW4gdGhlIGNhc2Ugd2hlcmUgdGhlIElQIHJvdXRlciBpcyBvcGVyYXRpbmcgb24gdGhlIHVzZXIgY2xpZW50IHNpZGUsIGNvbW11bmljYXRpb24gd2lsbCBub3QgYmUgcG9zc2libGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1JvdXRpbmdfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgTUFDIEFkZHJlc3NlcyBEdXBsaWNhdGlvbi4gVGhlIHVzZSBvZiBkdXBsaWNhdGluZyBNQUMgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrTWFjX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IElQIEFkZHJlc3MgRHVwbGljYXRpb24gKElQdjQpLiBUaGUgdXNlIG9mIGR1cGxpY2F0aW5nIElQdjQgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrSVBfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgTm9uLUFSUCAvIE5vbi1ESENQIC8gTm9uLUlDTVB2NiBicm9hZGNhc3RzLiBUaGUgc2VuZGluZyBvciByZWNlaXZpbmcgb2YgYnJvYWRjYXN0IHBhY2tldHMgdGhhdCBhcmUgbm90IEFSUCBwcm90b2NvbCwgREhDUCBwcm90b2NvbCwgbm9yIElDTVB2NiBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHdpbGwgbm90IGJlIGFsbG93ZWQgZm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkFycERoY3BPbmx5X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBQcml2YWN5IEZpbHRlciBNb2RlLiBBbGwgZGlyZWN0IGNvbW11bmljYXRpb24gYmV0d2VlbiBzZXNzaW9ucyB3aXRoIHRoZSBwcml2YWN5IGZpbHRlciBtb2RlIHBvbGljeSBzZXR0aW5nIHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpQcml2YWN5RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE9wZXJhdGlvbiBhcyBUQ1AvSVAgU2VydmVyIChJUHY0KS4gQ29tcHV0ZXJzIG9mIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBjYW4ndCBsaXN0ZW4gYW5kIGFjY2VwdCBUQ1AvSVAgY29ubmVjdGlvbnMgaW4gSVB2NC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBVbmxpbWl0ZWQgTnVtYmVyIG9mIEJyb2FkY2FzdHMuIElmIGEgY29tcHV0ZXIgb2YgYSBzZXNzaW9uIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBzZW5kcyBicm9hZGNhc3QgcGFja2V0cyBvZiBhIG51bWJlciB1bnVzdWFsbHkgbGFyZ2VyIHRoYW4gd2hhdCB3b3VsZCBiZSBjb25zaWRlcmVkIG5vcm1hbCBvbiB0aGUgdmlydHVhbCBuZXR3b3JrLCB0aGVyZSB3aWxsIGJlIG5vIGF1dG9tYXRpYyBsaW1pdGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vQnJvYWRjYXN0TGltaXRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogQWxsb3cgTW9uaXRvcmluZyBNb2RlLiBVc2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBiZSBncmFudGVkIHRvIGNvbm5lY3QgdG8gdGhlIFZpcnR1YWwgSHViIGluIE1vbml0b3JpbmcgTW9kZS4gU2Vzc2lvbnMgaW4gTW9uaXRvcmluZyBNb2RlIGFyZSBhYmxlIHRvIG1vbml0b3IgKHRhcCkgYWxsIHBhY2tldHMgZmxvd2luZyB0aHJvdWdoIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1vbml0b3JQb3J0X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBUQ1AgQ29ubmVjdGlvbnMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc2V0cyB0aGUgbWF4aW11bSBudW1iZXIgb2YgcGh5c2ljYWwgVENQIGNvbm5lY3Rpb25zIGNvbnNpc3RzIGluIGEgcGh5c2ljYWwgVlBOIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhDb25uZWN0aW9uX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVGltZS1vdXQgUGVyaW9kLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNldHMsIGluIHNlY29uZHMsIHRoZSB0aW1lLW91dCBwZXJpb2QgdG8gd2FpdCBiZWZvcmUgZGlzY29ubmVjdGluZyBhIHNlc3Npb24gd2hlbiBjb21tdW5pY2F0aW9uIHRyb3VibGUgb2NjdXJzIGJldHdlZW4gdGhlIFZQTiBDbGllbnQgLyBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6VGltZU91dF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE1BQyBBZGRyZXNzZXMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSBudW1iZXIgb2YgTUFDIGFkZHJlc3NlcyBwZXIgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heE1hY191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NCkuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NCBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVXBsb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIGlud2FyZHMgZGlyZWN0aW9uIGZyb20gb3V0c2lkZSB0byBpbnNpZGUgdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4VXBsb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRG93bmxvYWQgQmFuZHdpZHRoLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgdHJhZmZpYyBiYW5kd2lkdGggdGhhdCBpcyBpbiB0aGUgb3V0d2FyZHMgZGlyZWN0aW9uIGZyb20gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1YiB0byBvdXRzaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heERvd25sb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBDaGFuZ2luZyBQYXNzd29yZC4gVGhlIHVzZXJzIHdoaWNoIHVzZSBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgYXJlIG5vdCBhbGxvd2VkIHRvIGNoYW5nZSB0aGVpciBvd24gcGFzc3dvcmQgZnJvbSB0aGUgVlBOIENsaWVudCBNYW5hZ2VyIG9yIHNpbWlsYXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaXhQYXNzd29yZF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgTXVsdGlwbGUgTG9naW5zLiBVc2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgYXJlIHVuYWJsZSB0byBoYXZlIG1vcmUgdGhhbiB0aGlzIG51bWJlciBvZiBjb25jdXJyZW50IGxvZ2lucy4gQnJpZGdlIE1vZGUgc2Vzc2lvbnMgYXJlIG5vdCBzdWJqZWN0cyB0byB0aGlzIHBvbGljeS4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok11bHRpTG9naW5zX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBWb0lQIC8gUW9TIEZ1bmN0aW9uLiBVc2VycyB3aXRoIHRoaXMgc2VjdXJpdHkgcG9saWN5IGFyZSB1bmFibGUgdG8gdXNlIFZvSVAgLyBRb1MgZnVuY3Rpb25zIGluIFZQTiBjb25uZWN0aW9uIHNlc3Npb25zLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Rb1NfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBSUyAvIFJBIFBhY2tldHMgKElQdjYpLiBBbGwgSUNNUHY2IHBhY2tldHMgd2hpY2ggdGhlIG1lc3NhZ2UtdHlwZSBpcyAxMzMgKFJvdXRlciBTb2xpY2l0YXRpb24pIG9yIDEzNCAoUm91dGVyIEFkdmVydGlzZW1lbnQpIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gQXMgYSByZXN1bHQsIGFuIElQdjYgY2xpZW50IHdpbGwgYmUgdW5hYmxlIHRvIHVzZSBJUHY2IGFkZHJlc3MgcHJlZml4IGF1dG8gZGV0ZWN0aW9uIGFuZCBJUHY2IGRlZmF1bHQgZ2F0ZXdheSBhdXRvIGRldGVjdGlvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlJTYW5kUkFGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBSQSBQYWNrZXRzIChJUHY2KS4gQWxsIElDTVB2NiBwYWNrZXRzIHdoaWNoIHRoZSBtZXNzYWdlLXR5cGUgaXMgMTM0IChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBBcyBhIHJlc3VsdCwgYSBtYWxpY2lvdXMgdXNlcnMgd2lsbCBiZSB1bmFibGUgdG8gc3ByZWFkIGlsbGVnYWwgSVB2NiBwcmVmaXggb3IgZGVmYXVsdCBnYXRld2F5IGFkdmVydGlzZW1lbnRzIG9uIHRoZSBuZXR3b3JrLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UkFGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBESENQIFBhY2tldHMgKElQdjYpLiBBbGwgSVB2NiBESENQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjYpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NiBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2Tm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgUm91dGluZyBPcGVyYXRpb24gKElQdjYpLiBJUHY2IHJvdXRpbmcgd2lsbCBiZSBkZW5pZWQgZm9yIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nLiBFdmVuIGluIHRoZSBjYXNlIHdoZXJlIHRoZSBJUCByb3V0ZXIgaXMgb3BlcmF0aW5nIG9uIHRoZSB1c2VyIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Sb3V0aW5nVjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgSVAgQWRkcmVzcyBEdXBsaWNhdGlvbiAoSVB2NikuIFRoZSB1c2Ugb2YgZHVwbGljYXRpbmcgSVB2NiBhZGRyZXNzZXMgdGhhdCBhcmUgaW4gdXNlIGJ5IGNvbXB1dGVycyBvZiBkaWZmZXJlbnQgc2Vzc2lvbnMgY2Fubm90IGJlIHVzZWQgYnkgc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Q2hlY2tJUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE9wZXJhdGlvbiBhcyBUQ1AvSVAgU2VydmVyIChJUHY2KS4gQ29tcHV0ZXJzIG9mIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZyBjYW4ndCBsaXN0ZW4gYW5kIGFjY2VwdCBUQ1AvSVAgY29ubmVjdGlvbnMgaW4gSVB2Ni4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2VydmVyVjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NikuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NiBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQdjZfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBQYXNzd29yZCBTYXZlIGluIFZQTiBDbGllbnQuIEZvciB1c2VycyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHdoZW4gdGhlIHVzZXIgaXMgdXNpbmcgKnN0YW5kYXJkKiBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiwgdGhlIHVzZXIgd2lsbCBiZSB1bmFibGUgdG8gc2F2ZSB0aGUgcGFzc3dvcmQgaW4gVlBOIENsaWVudC4gVGhlIHVzZXIgd2lsbCBiZSByZXF1aXJlZCB0byBpbnB1dCBwYXNzd29yZHMgZm9yIGV2ZXJ5IHRpbWUgdG8gY29ubmVjdCBhIFZQTi4gVGhpcyB3aWxsIGltcHJvdmUgdGhlIHNlY3VyaXR5LiBJZiB0aGlzIHBvbGljeSBpcyBlbmFibGVkLCBWUE4gQ2xpZW50IFZlcnNpb24gMi4wIHdpbGwgYmUgZGVuaWVkIHRvIGFjY2Vzcy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vU2F2ZVBhc3N3b3JkX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBWUE4gQ2xpZW50IEF1dG9tYXRpYyBEaXNjb25uZWN0LiBGb3IgdXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCBhIHVzZXIncyBWUE4gc2Vzc2lvbiB3aWxsIGJlIGRpc2Nvbm5lY3RlZCBhdXRvbWF0aWNhbGx5IGFmdGVyIHRoZSBzcGVjaWZpYyBwZXJpb2Qgd2lsbCBlbGFwc2UuIEluIHRoaXMgY2FzZSBubyBhdXRvbWF0aWMgcmUtY29ubmVjdGlvbiB3aWxsIGJlIHBlcmZvcm1lZC4gVGhpcyBjYW4gcHJldmVudCBhIGxvdCBvZiBpbmFjdGl2ZSBWUE4gU2Vzc2lvbnMuIElmIHRoaXMgcG9saWN5IGlzIGVuYWJsZWQsIFZQTiBDbGllbnQgVmVyc2lvbiAyLjAgd2lsbCBiZSBkZW5pZWQgdG8gYWNjZXNzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6QXV0b0Rpc2Nvbm5lY3RfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIElQdjQgUGFja2V0cy4gQWxsIElQdjQgYW5kIEFSUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlcklQdjRfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgSVB2NiBQYWNrZXRzLiBBbGwgSVB2NiBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlcklQdjZfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgTm9uLUlQIFBhY2tldHMuIEFsbCBub24tSVAgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuIFwiTm9uLUlQIHBhY2tldFwiIG1lYW4gYSBwYWNrZXQgd2hpY2ggaXMgbm90IElQdjQsIEFSUCBub3IgSVB2Ni4gQW55IHRhZ2dlZC1WTEFOIHBhY2tldHMgdmlhIHRoZSBWaXJ0dWFsIEh1YiB3aWxsIGJlIHJlZ2FyZGVkIGFzIG5vbi1JUCBwYWNrZXRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVyTm9uSVBfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE5vIERlZmF1bHQtUm91dGVyIG9uIElQdjYgUkEuIEluIGFsbCBWUE4gU2Vzc2lvbnMgZGVmaW5lcyB0aGlzIHBvbGljeSwgYW55IElQdjYgUkEgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBwYWNrZXQgd2l0aCBub24temVybyB2YWx1ZSBpbiB0aGUgcm91dGVyLWxpZmV0aW1lIHdpbGwgc2V0IHRvIHplcm8tdmFsdWUuIFRoaXMgaXMgZWZmZWN0aXZlIHRvIGF2b2lkIHRoZSBob3JyaWJsZSBiZWhhdmlvciBmcm9tIHRoZSBJUHY2IHJvdXRpbmcgY29uZnVzaW9uIHdoaWNoIGlzIGNhdXNlZCBieSB0aGUgVlBOIGNsaWVudCdzIGF0dGVtcHRzIHRvIHVzZSB0aGUgcmVtb3RlLXNpZGUgSVB2NiByb3V0ZXIgYXMgaXRzIGxvY2FsIElQdjYgcm91dGVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9JUHY2RGVmYXVsdFJvdXRlckluUkFfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE5vIERlZmF1bHQtUm91dGVyIG9uIElQdjYgUkEgKHBoeXNpY2FsIElQdjYpLiBJbiBhbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3kgKG9ubHkgd2hlbiB0aGUgcGh5c2ljYWwgY29tbXVuaWNhdGlvbiBwcm90b2NvbCBiZXR3ZWVuIFZQTiBDbGllbnQgLyBWUE4gQnJpZGdlIGFuZCBWUE4gU2VydmVyIGlzIElQdjYpLCBhbnkgSVB2NiBSQSAoUm91dGVyIEFkdmVydGlzZW1lbnQpIHBhY2tldCB3aXRoIG5vbi16ZXJvIHZhbHVlIGluIHRoZSByb3V0ZXItbGlmZXRpbWUgd2lsbCBzZXQgdG8gemVyby12YWx1ZS4gVGhpcyBpcyBlZmZlY3RpdmUgdG8gYXZvaWQgdGhlIGhvcnJpYmxlIGJlaGF2aW9yIGZyb20gdGhlIElQdjYgcm91dGluZyBjb25mdXNpb24gd2hpY2ggaXMgY2F1c2VkIGJ5IHRoZSBWUE4gY2xpZW50J3MgYXR0ZW1wdHMgdG8gdXNlIHRoZSByZW1vdGUtc2lkZSBJUHY2IHJvdXRlciBhcyBpdHMgbG9jYWwgSVB2NiByb3V0ZXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0lQdjZEZWZhdWx0Um91dGVySW5SQVdoZW5JUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBWTEFOIElEIChJRUVFODAyLjFRKS4gWW91IGNhbiBzcGVjaWZ5IHRoZSBWTEFOIElEIG9uIHRoZSBzZWN1cml0eSBwb2xpY3kuIEFsbCBWUE4gU2Vzc2lvbnMgZGVmaW5lcyB0aGlzIHBvbGljeSwgYWxsIEV0aGVybmV0IHBhY2tldHMgdG93YXJkIHRoZSBWaXJ0dWFsIEh1YiBmcm9tIHRoZSB1c2VyIHdpbGwgYmUgaW5zZXJ0ZWQgYSBWTEFOIHRhZyAoSUVFRSA4MDIuMVEpIHdpdGggdGhlIFZMQU4gSUQuIFRoZSB1c2VyIGNhbiBhbHNvIHJlY2VpdmUgb25seSBwYWNrZXRzIHdpdGggYSBWTEFOIHRhZyB3aGljaCBoYXMgdGhlIHNhbWUgVkxBTiBJRC4gKFJlY2VpdmluZyBwcm9jZXNzIHJlbW92ZXMgdGhlIFZMQU4gdGFnIGF1dG9tYXRpY2FsbHkuKSBBbnkgRXRoZXJuZXQgcGFja2V0cyB3aXRoIGFueSBvdGhlciBWTEFOIElEcyBvciBub24tVkxBTiBwYWNrZXRzIHdpbGwgbm90IGJlIHJlY2VpdmVkLiBBbGwgVlBOIFNlc3Npb25zIHdpdGhvdXQgdGhpcyBwb2xpY3kgZGVmaW5pdGlvbiBjYW4gc2VuZCAvIHJlY2VpdmUgYW55IGtpbmRzIG9mIEV0aGVybmV0IHBhY2tldHMgcmVnYXJkbGVzcyBvZiBWTEFOIHRhZ3MsIGFuZCBWTEFOIHRhZ3MgYXJlIG5vdCBpbnNlcnRlZCBvciByZW1vdmVkIGF1dG9tYXRpY2FsbHkuIEFueSB0YWdnZWQtVkxBTiBwYWNrZXRzIHZpYSB0aGUgVmlydHVhbCBIdWIgd2lsbCBiZSByZWdhcmRlZCBhcyBub24tSVAgcGFja2V0cy4gVGhlcmVmb3JlLCB0YWdnZWQtVkxBTiBwYWNrZXRzIGFyZSBub3Qgc3ViamVjdHMgZm9yIElQdjQgLyBJUHY2IHNlY3VyaXR5IHBvbGljaWVzLCBhY2Nlc3MgbGlzdHMgbm9yIG90aGVyIElQdjQgLyBJUHY2IHNwZWNpZmljIGRlZXAgcHJvY2Vzc2luZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlZMYW5JZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFdoZXRoZXIgdmVyc2lvbiAzLjAgKG11c3QgYmUgdHJ1ZSkgKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlZlcjNfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjU2V0R3JvdXA7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2V0R3JvdXAgPSBWcG5ScGNTZXRHcm91cDtcclxuLyoqIEh1YiB0eXBlcyAqL1xyXG52YXIgVnBuUnBjSHViVHlwZTtcclxuKGZ1bmN0aW9uIChWcG5ScGNIdWJUeXBlKSB7XHJcbiAgICAvKiogU3RhbmQtYWxvbmUgSFVCICovXHJcbiAgICBWcG5ScGNIdWJUeXBlW1ZwblJwY0h1YlR5cGVbXCJTdGFuZGFsb25lXCJdID0gMF0gPSBcIlN0YW5kYWxvbmVcIjtcclxuICAgIC8qKiBTdGF0aWMgSFVCICovXHJcbiAgICBWcG5ScGNIdWJUeXBlW1ZwblJwY0h1YlR5cGVbXCJGYXJtU3RhdGljXCJdID0gMV0gPSBcIkZhcm1TdGF0aWNcIjtcclxuICAgIC8qKiBEeW5hbWljIEhVQiAqL1xyXG4gICAgVnBuUnBjSHViVHlwZVtWcG5ScGNIdWJUeXBlW1wiRmFybUR5bmFtaWNcIl0gPSAyXSA9IFwiRmFybUR5bmFtaWNcIjtcclxufSkoVnBuUnBjSHViVHlwZSA9IGV4cG9ydHMuVnBuUnBjSHViVHlwZSB8fCAoZXhwb3J0cy5WcG5ScGNIdWJUeXBlID0ge30pKTtcclxuLyoqIENyZWF0ZSBhIEhVQiAqL1xyXG52YXIgVnBuUnBjQ3JlYXRlSHViID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0NyZWF0ZUh1YicgY2xhc3M6IENyZWF0ZSBhIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQ3JlYXRlSHViKGluaXQpIHtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgbmFtZSBvZiB0aGUgVmlydHVhbCBIdWIgdG8gY3JlYXRlIC8gdXBkYXRlLiAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IGFuIGFkbWluaXN0cmF0b3IgcGFzc3dvcmQgd2hlbiB0aGUgYWRtaW5pc3RyYXRvciBwYXNzd29yZCBpcyBnb2luZyB0byBiZSBzZXQgZm9yIHRoZSBWaXJ0dWFsIEh1Yi4gT24gdGhlIHVwZGF0ZSwgbGVhdmUgaXQgdG8gZW1wdHkgc3RyaW5nIGlmIHlvdSBkb24ndCB3YW50IHRvIGNoYW5nZSB0aGUgcGFzc3dvcmQuICovXHJcbiAgICAgICAgdGhpcy5BZG1pblBhc3N3b3JkUGxhaW5UZXh0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiBWUE4gc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk1heFNlc3Npb25fdTMyID0gMDtcclxuICAgICAgICAvKiogTm8gRW51bSBmbGFnLiBCeSBlbmFibGluZyB0aGlzIG9wdGlvbiwgdGhlIFZQTiBDbGllbnQgdXNlciB3aWxsIGJlIHVuYWJsZSB0byBlbnVtZXJhdGUgdGhpcyBWaXJ0dWFsIEh1YiBldmVuIGlmIHRoZXkgc2VuZCBhIFZpcnR1YWwgSHViIGVudW1lcmF0aW9uIHJlcXVlc3QgdG8gdGhlIFZQTiBTZXJ2ZXIuICovXHJcbiAgICAgICAgdGhpcy5Ob0VudW1fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHRoZSBWaXJ0dWFsIEh1YiAoVmFsaWQgb25seSBmb3IgQ2x1c3RlcmVkIFZQTiBTZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuSHViVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjQ3JlYXRlSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0NyZWF0ZUh1YiA9IFZwblJwY0NyZWF0ZUh1YjtcclxudmFyIFZwblJwY0NsaWVudEF1dGhUeXBlO1xyXG4oZnVuY3Rpb24gKFZwblJwY0NsaWVudEF1dGhUeXBlKSB7XHJcbiAgICAvKiogQW5vbnltb3VzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNDbGllbnRBdXRoVHlwZVtWcG5ScGNDbGllbnRBdXRoVHlwZVtcIkFub255bW91c1wiXSA9IDBdID0gXCJBbm9ueW1vdXNcIjtcclxuICAgIC8qKiBTSEEtMCBoYXNoZWQgcGFzc3dvcmQgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY0NsaWVudEF1dGhUeXBlW1ZwblJwY0NsaWVudEF1dGhUeXBlW1wiU0hBMF9IYXNoZWRfUGFzc3dvcmRcIl0gPSAxXSA9IFwiU0hBMF9IYXNoZWRfUGFzc3dvcmRcIjtcclxuICAgIC8qKiBQbGFpbiBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiAqL1xyXG4gICAgVnBuUnBjQ2xpZW50QXV0aFR5cGVbVnBuUnBjQ2xpZW50QXV0aFR5cGVbXCJQbGFpblBhc3N3b3JkXCJdID0gMl0gPSBcIlBsYWluUGFzc3dvcmRcIjtcclxuICAgIC8qKiBDZXJ0aWZpY2F0ZSBhdXRoZW50aWNhdGlvbiAqL1xyXG4gICAgVnBuUnBjQ2xpZW50QXV0aFR5cGVbVnBuUnBjQ2xpZW50QXV0aFR5cGVbXCJDZXJ0XCJdID0gM10gPSBcIkNlcnRcIjtcclxufSkoVnBuUnBjQ2xpZW50QXV0aFR5cGUgPSBleHBvcnRzLlZwblJwY0NsaWVudEF1dGhUeXBlIHx8IChleHBvcnRzLlZwblJwY0NsaWVudEF1dGhUeXBlID0ge30pKTtcclxuLyoqIENyZWF0ZSBhbmQgc2V0IG9mIGxpbmsgKi9cclxudmFyIFZwblJwY0NyZWF0ZUxpbmsgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjQ3JlYXRlTGluaycgY2xhc3M6IENyZWF0ZSBhbmQgc2V0IG9mIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0NyZWF0ZUxpbmsoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9FeF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPbmxpbmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuT25saW5lX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIHZhbGlkYXRpb24gZm9yIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNoZWNrU2VydmVyQ2VydF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBib2R5IG9mIHNlcnZlciBYLjUwOSBjZXJ0aWZpY2F0ZSB0byBjb21wYXJlLiBWYWxpZCBvbmx5IGlmIHRoZSBDaGVja1NlcnZlckNlcnRfYm9vbCBmbGFnIGlzIHRydWUuICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJDZXJ0X2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBTcGVjaWZ5IHRoZSBuYW1lIG9mIHRoZSBDYXNjYWRlIENvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkFjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogU3BlY2lmeSB0aGUgaG9zdG5hbWUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuIFlvdSBjYW4gYWxzbyBzcGVjaWZ5IGJ5IElQIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFNwZWNpZnkgdGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLiAqL1xyXG4gICAgICAgIHRoaXMuUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSB0eXBlIG9mIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5VHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSBob3N0bmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBwcm94eSBzZXJ2ZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5UG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IFRoZSB1c2VybmFtZSB0byBjb25uZWN0IHRvIHRoZSBwcm94eSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlByb3h5VXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBUaGUgcGFzc3dvcmQgdG8gY29ubmVjdCB0byB0aGUgcHJveHkgc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5Qcm94eVBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogVGhlIFZpcnR1YWwgSHViIG9uIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogTnVtYmVyIG9mIFRDUCBDb25uZWN0aW9ucyB0byBVc2UgaW4gVlBOIENvbW11bmljYXRpb24gKi9cclxuICAgICAgICB0aGlzLk1heENvbm5lY3Rpb25fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBUaGUgZmxhZyB0byBlbmFibGUgdGhlIGVuY3J5cHRpb24gb24gdGhlIGNvbW11bmljYXRpb24gKi9cclxuICAgICAgICB0aGlzLlVzZUVuY3J5cHRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IEVuYWJsZSAvIERpc2FibGUgRGF0YSBDb21wcmVzc2lvbiB3aGVuIENvbW11bmljYXRpbmcgYnkgQ2FzY2FkZSBDb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VDb21wcmVzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogU3BlY2lmeSB0cnVlIHdoZW4gZW5hYmxpbmcgaGFsZiBkdXBsZXggbW9kZS4gV2hlbiB1c2luZyB0d28gb3IgbW9yZSBUQ1AgY29ubmVjdGlvbnMgZm9yIFZQTiBjb21tdW5pY2F0aW9uLCBpdCBpcyBwb3NzaWJsZSB0byB1c2UgSGFsZiBEdXBsZXggTW9kZS4gQnkgZW5hYmxpbmcgaGFsZiBkdXBsZXggbW9kZSBpdCBpcyBwb3NzaWJsZSB0byBhdXRvbWF0aWNhbGx5IGZpeCBkYXRhIHRyYW5zbWlzc2lvbiBkaXJlY3Rpb24gYXMgaGFsZiBhbmQgaGFsZiBmb3IgZWFjaCBUQ1AgY29ubmVjdGlvbi4gSW4gdGhlIGNhc2Ugd2hlcmUgYSBWUE4gdXNpbmcgOCBUQ1AgY29ubmVjdGlvbnMgaXMgZXN0YWJsaXNoZWQsIGZvciBleGFtcGxlLCB3aGVuIGhhbGYtZHVwbGV4IGlzIGVuYWJsZWQsIGNvbW11bmljYXRpb24gY2FuIGJlIGZpeGVzIHNvIHRoYXQgNCBUQ1AgY29ubmVjdGlvbnMgYXJlIGRlZGljYXRlZCB0byB0aGUgdXBsb2FkIGRpcmVjdGlvbiBhbmQgdGhlIG90aGVyIDQgY29ubmVjdGlvbnMgYXJlIGRlZGljYXRlZCB0byB0aGUgZG93bmxvYWQgZGlyZWN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuSGFsZkNvbm5lY3Rpb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT3B0aW9uIFBhcmFtZXRlcnM6IENvbm5lY3Rpb24gYXR0ZW1wdCBpbnRlcnZhbCB3aGVuIGFkZGl0aW9uYWwgY29ubmVjdGlvbiB3aWxsIGJlIGVzdGFibGlzaGVkICovXHJcbiAgICAgICAgdGhpcy5BZGRpdGlvbmFsQ29ubmVjdGlvbkludGVydmFsX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogQ29ubmVjdGlvbiBMaWZlIG9mIEVhY2ggVENQIENvbm5lY3Rpb24gKDAgZm9yIG5vIGtlZXAtYWxpdmUpICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0aW9uRGlzY29ubmVjdFNwYW5fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBEaXNhYmxlIFFvUyBDb250cm9sIEZ1bmN0aW9uIGlmIHRoZSB2YWx1ZSBpcyB0cnVlICovXHJcbiAgICAgICAgdGhpcy5EaXNhYmxlUW9TX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQ2xpZW50IE9wdGlvbiBQYXJhbWV0ZXJzOiBEbyBub3QgdXNlIFRMUyAxLnggb2YgdGhlIHZhbHVlIGlzIHRydWUgKi9cclxuICAgICAgICB0aGlzLk5vVGxzMV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENsaWVudCBPcHRpb24gUGFyYW1ldGVyczogRG8gbm90IHVzZSBVRFAgYWNjZWxlcmF0aW9uIG1vZGUgaWYgdGhlIHZhbHVlIGlzIHRydWUgKi9cclxuICAgICAgICB0aGlzLk5vVWRwQWNjZWxlcmF0aW9uX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQXV0aGVudGljYXRpb24gdHlwZSAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Vc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTSEEtMCBIYXNoZWQgcGFzc3dvcmQuIFZhbGlkIG9ubHkgaWYgQ2xpZW50QXV0aF9BdXRoVHlwZV91MzIgPT0gU0hBMF9IYXNoZWRfUGFzc3dvcmQgKDEpLiBUaGUgU0hBLTAgaGFzaGVkIHBhc3N3b3JkIG11c3QgYmUgY2FsdWNsYXRlZCBieSB0aGUgU0hBMChVcHBlckNhc2UodXNlcm5hbWVfYXNjaWlfc3RyaW5nKSArIHBhc3N3b3JkX2FzY2lpX3N0cmluZykuICovXHJcbiAgICAgICAgdGhpcy5IYXNoZWRQYXNzd29yZF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFBsYWludGV4dCBQYXNzd29yZC4gVmFsaWQgb25seSBpZiBDbGllbnRBdXRoX0F1dGhUeXBlX3UzMiA9PSBQbGFpblBhc3N3b3JkICgyKS4gKi9cclxuICAgICAgICB0aGlzLlBsYWluUGFzc3dvcmRfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IGNlcnRpZmljYXRlLiBWYWxpZCBvbmx5IGlmIENsaWVudEF1dGhfQXV0aFR5cGVfdTMyID09IENlcnQgKDMpLiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50WF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENsaWVudCBwcml2YXRlIGtleSBvZiB0aGUgY2VydGlmaWNhdGUuIFZhbGlkIG9ubHkgaWYgQ2xpZW50QXV0aF9BdXRoVHlwZV91MzIgPT0gQ2VydCAoMykuICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRLX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY0KS4gQWxsIElQdjQgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1BGaWx0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERpc2FsbG93IERIQ1AgU2VydmVyIE9wZXJhdGlvbiAoSVB2NCkuIENvbXB1dGVycyBjb25uZWN0ZWQgdG8gc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcgd2lsbCBub3QgYmUgYWxsb3dlZCB0byBiZWNvbWUgYSBESENQIHNlcnZlciBhbmQgZGlzdHJpYnV0ZSBJUHY0IGFkZHJlc3NlcyB0byBESENQIGNsaWVudHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQTm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEVuZm9yY2UgREhDUCBBbGxvY2F0ZWQgSVAgQWRkcmVzc2VzIChJUHY0KS4gQ29tcHV0ZXJzIGluIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgb25seSBiZSBhYmxlIHRvIHVzZSBJUHY0IGFkZHJlc3NlcyBhbGxvY2F0ZWQgYnkgYSBESENQIHNlcnZlciBvbiB0aGUgdmlydHVhbCBuZXR3b3JrIHNpZGUuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRm9yY2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFByb2hpYml0IHRoZSBkdXBsaWNhdGUgTUFDIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja01hY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJvaGliaXQgYSBkdXBsaWNhdGUgSVAgYWRkcmVzcyAoSVB2NCkgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja0lQX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE5vbi1BUlAgLyBOb24tREhDUCAvIE5vbi1JQ01QdjYgYnJvYWRjYXN0cy4gVGhlIHNlbmRpbmcgb3IgcmVjZWl2aW5nIG9mIGJyb2FkY2FzdCBwYWNrZXRzIHRoYXQgYXJlIG5vdCBBUlAgcHJvdG9jb2wsIERIQ1AgcHJvdG9jb2wsIG5vciBJQ01QdjYgb24gdGhlIHZpcnR1YWwgbmV0d29yayB3aWxsIG5vdCBiZSBhbGxvd2VkIGZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpBcnBEaGNwT25seV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJpdmFjeSBGaWx0ZXIgTW9kZS4gQWxsIGRpcmVjdCBjb21tdW5pY2F0aW9uIGJldHdlZW4gc2Vzc2lvbnMgd2l0aCB0aGUgcHJpdmFjeSBmaWx0ZXIgbW9kZSBwb2xpY3kgc2V0dGluZyB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UHJpdmFjeUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NCkuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVW5saW1pdGVkIE51bWJlciBvZiBCcm9hZGNhc3RzLiBJZiBhIGNvbXB1dGVyIG9mIGEgc2Vzc2lvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgc2VuZHMgYnJvYWRjYXN0IHBhY2tldHMgb2YgYSBudW1iZXIgdW51c3VhbGx5IGxhcmdlciB0aGFuIHdoYXQgd291bGQgYmUgY29uc2lkZXJlZCBub3JtYWwgb24gdGhlIHZpcnR1YWwgbmV0d29yaywgdGhlcmUgd2lsbCBiZSBubyBhdXRvbWF0aWMgbGltaXRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0Jyb2FkY2FzdExpbWl0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE1BQyBBZGRyZXNzZXMuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSBudW1iZXIgb2YgTUFDIGFkZHJlc3NlcyBwZXIgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heE1hY191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIElQIEFkZHJlc3NlcyAoSVB2NCkuIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgSVB2NCBhZGRyZXNzZXMgdGhhdCBjYW4gYmUgcmVnaXN0ZXJlZCBmb3IgYSBzaW5nbGUgc2Vzc2lvbi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heElQX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVXBsb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIGlud2FyZHMgZGlyZWN0aW9uIGZyb20gb3V0c2lkZSB0byBpbnNpZGUgdGhlIFZpcnR1YWwgSHViLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4VXBsb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRG93bmxvYWQgQmFuZHdpZHRoLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgdHJhZmZpYyBiYW5kd2lkdGggdGhhdCBpcyBpbiB0aGUgb3V0d2FyZHMgZGlyZWN0aW9uIGZyb20gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1YiB0byBvdXRzaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heERvd25sb2FkX3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIFJTIC8gUkEgUGFja2V0cyAoSVB2NikuIEFsbCBJQ01QdjYgcGFja2V0cyB3aGljaCB0aGUgbWVzc2FnZS10eXBlIGlzIDEzMyAoUm91dGVyIFNvbGljaXRhdGlvbikgb3IgMTM0IChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBBcyBhIHJlc3VsdCwgYW4gSVB2NiBjbGllbnQgd2lsbCBiZSB1bmFibGUgdG8gdXNlIElQdjYgYWRkcmVzcyBwcmVmaXggYXV0byBkZXRlY3Rpb24gYW5kIElQdjYgZGVmYXVsdCBnYXRld2F5IGF1dG8gZGV0ZWN0aW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UlNhbmRSQUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIHRoZSByb3V0ZXIgYWR2ZXJ0aXNlbWVudCBwYWNrZXQgKElQdjYpICovXHJcbiAgICAgICAgdGhpcy5TZWNQb2xfUkFGaWx0ZXJfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBESENQIFBhY2tldHMgKElQdjYpLiBBbGwgSVB2NiBESENQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2RmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjYpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NiBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUHY2Tm9TZXJ2ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFByb2hpYml0IHRoZSBkdXBsaWNhdGUgSVAgYWRkcmVzcyAoSVB2NikgKi9cclxuICAgICAgICB0aGlzLlNlY1BvbF9DaGVja0lQdjZfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgT3BlcmF0aW9uIGFzIFRDUC9JUCBTZXJ2ZXIgKElQdjYpLiBDb21wdXRlcnMgb2Ygc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGNhbid0IGxpc3RlbiBhbmQgYWNjZXB0IFRDUC9JUCBjb25uZWN0aW9ucyBpbiBJUHY2LiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9TZXJ2ZXJWNl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgSVAgQWRkcmVzc2VzIChJUHY2KS4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBJUHY2IGFkZHJlc3NlcyB0aGF0IGNhbiBiZSByZWdpc3RlcmVkIGZvciBhIHNpbmdsZSBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4SVB2Nl91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEZpbHRlciBBbGwgSVB2NCBQYWNrZXRzLiBBbGwgSVB2NCBhbmQgQVJQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVySVB2NF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBJUHY2IFBhY2tldHMuIEFsbCBJUHY2IHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6RmlsdGVySVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBOb24tSVAgUGFja2V0cy4gQWxsIG5vbi1JUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gXCJOb24tSVAgcGFja2V0XCIgbWVhbiBhIHBhY2tldCB3aGljaCBpcyBub3QgSVB2NCwgQVJQIG5vciBJUHY2LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJOb25JUF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTm8gRGVmYXVsdC1Sb3V0ZXIgb24gSVB2NiBSQS4gSW4gYWxsIFZQTiBTZXNzaW9ucyBkZWZpbmVzIHRoaXMgcG9saWN5LCBhbnkgSVB2NiBSQSAoUm91dGVyIEFkdmVydGlzZW1lbnQpIHBhY2tldCB3aXRoIG5vbi16ZXJvIHZhbHVlIGluIHRoZSByb3V0ZXItbGlmZXRpbWUgd2lsbCBzZXQgdG8gemVyby12YWx1ZS4gVGhpcyBpcyBlZmZlY3RpdmUgdG8gYXZvaWQgdGhlIGhvcnJpYmxlIGJlaGF2aW9yIGZyb20gdGhlIElQdjYgcm91dGluZyBjb25mdXNpb24gd2hpY2ggaXMgY2F1c2VkIGJ5IHRoZSBWUE4gY2xpZW50J3MgYXR0ZW1wdHMgdG8gdXNlIHRoZSByZW1vdGUtc2lkZSBJUHY2IHJvdXRlciBhcyBpdHMgbG9jYWwgSVB2NiByb3V0ZXIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0lQdjZEZWZhdWx0Um91dGVySW5SQV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVkxBTiBJRCAoSUVFRTgwMi4xUSkuIFlvdSBjYW4gc3BlY2lmeSB0aGUgVkxBTiBJRCBvbiB0aGUgc2VjdXJpdHkgcG9saWN5LiBBbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFsbCBFdGhlcm5ldCBwYWNrZXRzIHRvd2FyZCB0aGUgVmlydHVhbCBIdWIgZnJvbSB0aGUgdXNlciB3aWxsIGJlIGluc2VydGVkIGEgVkxBTiB0YWcgKElFRUUgODAyLjFRKSB3aXRoIHRoZSBWTEFOIElELiBUaGUgdXNlciBjYW4gYWxzbyByZWNlaXZlIG9ubHkgcGFja2V0cyB3aXRoIGEgVkxBTiB0YWcgd2hpY2ggaGFzIHRoZSBzYW1lIFZMQU4gSUQuIChSZWNlaXZpbmcgcHJvY2VzcyByZW1vdmVzIHRoZSBWTEFOIHRhZyBhdXRvbWF0aWNhbGx5LikgQW55IEV0aGVybmV0IHBhY2tldHMgd2l0aCBhbnkgb3RoZXIgVkxBTiBJRHMgb3Igbm9uLVZMQU4gcGFja2V0cyB3aWxsIG5vdCBiZSByZWNlaXZlZC4gQWxsIFZQTiBTZXNzaW9ucyB3aXRob3V0IHRoaXMgcG9saWN5IGRlZmluaXRpb24gY2FuIHNlbmQgLyByZWNlaXZlIGFueSBraW5kcyBvZiBFdGhlcm5ldCBwYWNrZXRzIHJlZ2FyZGxlc3Mgb2YgVkxBTiB0YWdzLCBhbmQgVkxBTiB0YWdzIGFyZSBub3QgaW5zZXJ0ZWQgb3IgcmVtb3ZlZCBhdXRvbWF0aWNhbGx5LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuIFRoZXJlZm9yZSwgdGFnZ2VkLVZMQU4gcGFja2V0cyBhcmUgbm90IHN1YmplY3RzIGZvciBJUHY0IC8gSVB2NiBzZWN1cml0eSBwb2xpY2llcywgYWNjZXNzIGxpc3RzIG5vciBvdGhlciBJUHY0IC8gSVB2NiBzcGVjaWZpYyBkZWVwIHByb2Nlc3NpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWTGFuSWRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBXaGV0aGVyIHZlcnNpb24gMy4wIChtdXN0IGJlIHRydWUpICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWZXIzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0NyZWF0ZUxpbms7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQ3JlYXRlTGluayA9IFZwblJwY0NyZWF0ZUxpbms7XHJcbi8qKiBMaXN0ZW5lciAqL1xyXG52YXIgVnBuUnBjTGlzdGVuZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTGlzdGVuZXInIGNsYXNzOiBMaXN0ZW5lciAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTGlzdGVuZXIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBQb3J0IG51bWJlciAoUmFuZ2U6IDEgLSA2NTUzNSkgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZlIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5FbmFibGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTGlzdGVuZXIgPSBWcG5ScGNMaXN0ZW5lcjtcclxuLyoqIFVzZXIgYXV0aGVudGljYXRpb24gdHlwZSAoc2VydmVyIHNpZGUpICovXHJcbnZhciBWcG5ScGNVc2VyQXV0aFR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjVXNlckF1dGhUeXBlKSB7XHJcbiAgICAvKiogQW5vbnltb3VzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiQW5vbnltb3VzXCJdID0gMF0gPSBcIkFub255bW91c1wiO1xyXG4gICAgLyoqIFBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiUGFzc3dvcmRcIl0gPSAxXSA9IFwiUGFzc3dvcmRcIjtcclxuICAgIC8qKiBVc2VyIGNlcnRpZmljYXRlIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiVXNlckNlcnRcIl0gPSAyXSA9IFwiVXNlckNlcnRcIjtcclxuICAgIC8qKiBSb290IGNlcnRpZmljYXRlIHdoaWNoIGlzIGlzc3VlZCBieSB0cnVzdGVkIENlcnRpZmljYXRlIEF1dGhvcml0eSAqL1xyXG4gICAgVnBuUnBjVXNlckF1dGhUeXBlW1ZwblJwY1VzZXJBdXRoVHlwZVtcIlJvb3RDZXJ0XCJdID0gM10gPSBcIlJvb3RDZXJ0XCI7XHJcbiAgICAvKiogUmFkaXVzIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICBWcG5ScGNVc2VyQXV0aFR5cGVbVnBuUnBjVXNlckF1dGhUeXBlW1wiUmFkaXVzXCJdID0gNF0gPSBcIlJhZGl1c1wiO1xyXG4gICAgLyoqIFdpbmRvd3MgTlQgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY1VzZXJBdXRoVHlwZVtWcG5ScGNVc2VyQXV0aFR5cGVbXCJOVERvbWFpblwiXSA9IDVdID0gXCJOVERvbWFpblwiO1xyXG59KShWcG5ScGNVc2VyQXV0aFR5cGUgPSBleHBvcnRzLlZwblJwY1VzZXJBdXRoVHlwZSB8fCAoZXhwb3J0cy5WcG5ScGNVc2VyQXV0aFR5cGUgPSB7fSkpO1xyXG4vKiogQ3JlYXRlLCBjb25maWd1cmUsIGFuZCBnZXQgdGhlIHVzZXIgKi9cclxudmFyIFZwblJwY1NldFVzZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2V0VXNlcicgY2xhc3M6IENyZWF0ZSwgY29uZmlndXJlLCBhbmQgZ2V0IHRoZSB1c2VyICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNTZXRVc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgdXNlciBuYW1lIG9mIHRoZSB1c2VyICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEFzc2lnbmVkIGdyb3VwIG5hbWUgZm9yIHRoZSB1c2VyICovXHJcbiAgICAgICAgdGhpcy5Hcm91cE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT3B0aW9uYWwgcmVhbCBuYW1lIChmdWxsIG5hbWUpIG9mIHRoZSB1c2VyLCBhbGxvdyB1c2luZyBhbnkgVW5pY29kZSBjaGFyYWN0ZXJzICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPcHRpb25hbCBVc2VyIERlc2NyaXB0aW9uICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENyZWF0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTGFzdCBtb2RpZmllZCBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5VcGRhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEV4cGlyYXRpb24gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuRXhwaXJlVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEF1dGhlbnRpY2F0aW9uIG1ldGhvZCBvZiB0aGUgdXNlciAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlciBwYXNzd29yZCwgdmFsaWQgb25seSBpZiBBdXRoVHlwZV91MzIgPT0gUGFzc3dvcmQoMSkuIFZhbGlkIG9ubHkgdG8gY3JlYXRlIG9yIHNldCBvcGVyYXRpb25zLiAqL1xyXG4gICAgICAgIHRoaXMuQXV0aF9QYXNzd29yZF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2VyIGNlcnRpZmljYXRlLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBVc2VyQ2VydCgyKS4gKi9cclxuICAgICAgICB0aGlzLlVzZXJYX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUgU2VyaWFsIE51bWJlciwgb3B0aW9uYWwsIHZhbGlkIG9ubHkgaWYgQXV0aFR5cGVfdTMyID09IFJvb3RDZXJ0KDMpLiAqL1xyXG4gICAgICAgIHRoaXMuU2VyaWFsX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUgQ29tbW9uIE5hbWUsIG9wdGlvbmFsLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBSb290Q2VydCgzKS4gKi9cclxuICAgICAgICB0aGlzLkNvbW1vbk5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlcm5hbWUgaW4gUkFESVVTIHNlcnZlciwgb3B0aW9uYWwsIHZhbGlkIG9ubHkgaWYgQXV0aFR5cGVfdTMyID09IFJhZGl1cyg0KS4gKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1VzZXJuYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFVzZXJuYW1lIGluIE5UIERvbWFpbiBzZXJ2ZXIsIG9wdGlvbmFsLCB2YWxpZCBvbmx5IGlmIEF1dGhUeXBlX3UzMiA9PSBOVCg1KS4gKi9cclxuICAgICAgICB0aGlzLk50VXNlcm5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHRvdGFsIGxvZ2lucyBvZiB0aGUgdXNlciAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGNvdW50IChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdG8gdXNlIHNlY3VyaXR5IHBvbGljeSAqL1xyXG4gICAgICAgIHRoaXMuVXNlUG9saWN5X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBBbGxvdyBBY2Nlc3MuIFRoZSB1c2Vycywgd2hpY2ggdGhpcyBwb2xpY3kgdmFsdWUgaXMgdHJ1ZSwgaGF2ZSBwZXJtaXNzaW9uIHRvIG1ha2UgVlBOIGNvbm5lY3Rpb24gdG8gVlBOIFNlcnZlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkFjY2Vzc19ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIERIQ1AgUGFja2V0cyAoSVB2NCkuIEFsbCBJUHY0IERIQ1AgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpESENQRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEaXNhbGxvdyBESENQIFNlcnZlciBPcGVyYXRpb24gKElQdjQpLiBDb21wdXRlcnMgY29ubmVjdGVkIHRvIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgbm90IGJlIGFsbG93ZWQgdG8gYmVjb21lIGEgREhDUCBzZXJ2ZXIgYW5kIGRpc3RyaWJ1dGUgSVB2NCBhZGRyZXNzZXMgdG8gREhDUCBjbGllbnRzLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUE5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBFbmZvcmNlIERIQ1AgQWxsb2NhdGVkIElQIEFkZHJlc3NlcyAoSVB2NCkuIENvbXB1dGVycyBpbiBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZyB3aWxsIG9ubHkgYmUgYWJsZSB0byB1c2UgSVB2NCBhZGRyZXNzZXMgYWxsb2NhdGVkIGJ5IGEgREhDUCBzZXJ2ZXIgb24gdGhlIHZpcnR1YWwgbmV0d29yayBzaWRlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6REhDUEZvcmNlX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IEJyaWRnZSBPcGVyYXRpb24uIEJyaWRnZS1tb2RlIGNvbm5lY3Rpb25zIGFyZSBkZW5pZWQgZm9yIHVzZXIgc2Vzc2lvbnMgdGhhdCBoYXZlIHRoaXMgcG9saWN5IHNldHRpbmcuIEV2ZW4gaW4gY2FzZXMgd2hlbiB0aGUgRXRoZXJuZXQgQnJpZGdlIGlzIGNvbmZpZ3VyZWQgaW4gdGhlIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9CcmlkZ2VfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgUm91dGluZyBPcGVyYXRpb24gKElQdjQpLiBJUHY0IHJvdXRpbmcgd2lsbCBiZSBkZW5pZWQgZm9yIHNlc3Npb25zIHRoYXQgaGF2ZSB0aGlzIHBvbGljeSBzZXR0aW5nLiBFdmVuIGluIHRoZSBjYXNlIHdoZXJlIHRoZSBJUCByb3V0ZXIgaXMgb3BlcmF0aW5nIG9uIHRoZSB1c2VyIGNsaWVudCBzaWRlLCBjb21tdW5pY2F0aW9uIHdpbGwgbm90IGJlIHBvc3NpYmxlLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9Sb3V0aW5nX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE1BQyBBZGRyZXNzZXMgRHVwbGljYXRpb24uIFRoZSB1c2Ugb2YgZHVwbGljYXRpbmcgTUFDIGFkZHJlc3NlcyB0aGF0IGFyZSBpbiB1c2UgYnkgY29tcHV0ZXJzIG9mIGRpZmZlcmVudCBzZXNzaW9ucyBjYW5ub3QgYmUgdXNlZCBieSBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpDaGVja01hY19ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBJUCBBZGRyZXNzIER1cGxpY2F0aW9uIChJUHY0KS4gVGhlIHVzZSBvZiBkdXBsaWNhdGluZyBJUHY0IGFkZHJlc3NlcyB0aGF0IGFyZSBpbiB1c2UgYnkgY29tcHV0ZXJzIG9mIGRpZmZlcmVudCBzZXNzaW9ucyBjYW5ub3QgYmUgdXNlZCBieSBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpDaGVja0lQX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IE5vbi1BUlAgLyBOb24tREhDUCAvIE5vbi1JQ01QdjYgYnJvYWRjYXN0cy4gVGhlIHNlbmRpbmcgb3IgcmVjZWl2aW5nIG9mIGJyb2FkY2FzdCBwYWNrZXRzIHRoYXQgYXJlIG5vdCBBUlAgcHJvdG9jb2wsIERIQ1AgcHJvdG9jb2wsIG5vciBJQ01QdjYgb24gdGhlIHZpcnR1YWwgbmV0d29yayB3aWxsIG5vdCBiZSBhbGxvd2VkIGZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpBcnBEaGNwT25seV9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogUHJpdmFjeSBGaWx0ZXIgTW9kZS4gQWxsIGRpcmVjdCBjb21tdW5pY2F0aW9uIGJldHdlZW4gc2Vzc2lvbnMgd2l0aCB0aGUgcHJpdmFjeSBmaWx0ZXIgbW9kZSBwb2xpY3kgc2V0dGluZyB3aWxsIGJlIGZpbHRlcmVkLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6UHJpdmFjeUZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NCkuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVW5saW1pdGVkIE51bWJlciBvZiBCcm9hZGNhc3RzLiBJZiBhIGNvbXB1dGVyIG9mIGEgc2Vzc2lvbiB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgc2VuZHMgYnJvYWRjYXN0IHBhY2tldHMgb2YgYSBudW1iZXIgdW51c3VhbGx5IGxhcmdlciB0aGFuIHdoYXQgd291bGQgYmUgY29uc2lkZXJlZCBub3JtYWwgb24gdGhlIHZpcnR1YWwgbmV0d29yaywgdGhlcmUgd2lsbCBiZSBubyBhdXRvbWF0aWMgbGltaXRpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb0Jyb2FkY2FzdExpbWl0ZXJfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IEFsbG93IE1vbml0b3JpbmcgTW9kZS4gVXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIHdpbGwgYmUgZ3JhbnRlZCB0byBjb25uZWN0IHRvIHRoZSBWaXJ0dWFsIEh1YiBpbiBNb25pdG9yaW5nIE1vZGUuIFNlc3Npb25zIGluIE1vbml0b3JpbmcgTW9kZSBhcmUgYWJsZSB0byBtb25pdG9yICh0YXApIGFsbCBwYWNrZXRzIGZsb3dpbmcgdGhyb3VnaCB0aGUgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNb25pdG9yUG9ydF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogTWF4aW11bSBOdW1iZXIgb2YgVENQIENvbm5lY3Rpb25zLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNldHMgdGhlIG1heGltdW0gbnVtYmVyIG9mIHBoeXNpY2FsIFRDUCBjb25uZWN0aW9ucyBjb25zaXN0cyBpbiBhIHBoeXNpY2FsIFZQTiBzZXNzaW9uLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6TWF4Q29ubmVjdGlvbl91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFRpbWUtb3V0IFBlcmlvZC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBzZXRzLCBpbiBzZWNvbmRzLCB0aGUgdGltZS1vdXQgcGVyaW9kIHRvIHdhaXQgYmVmb3JlIGRpc2Nvbm5lY3RpbmcgYSBzZXNzaW9uIHdoZW4gY29tbXVuaWNhdGlvbiB0cm91YmxlIG9jY3VycyBiZXR3ZWVuIHRoZSBWUE4gQ2xpZW50IC8gVlBOIFNlcnZlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlRpbWVPdXRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBNQUMgQWRkcmVzc2VzLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIGxpbWl0cyB0aGUgbnVtYmVyIG9mIE1BQyBhZGRyZXNzZXMgcGVyIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhNYWNfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBJUCBBZGRyZXNzZXMgKElQdjQpLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIElQdjQgYWRkcmVzc2VzIHRoYXQgY2FuIGJlIHJlZ2lzdGVyZWQgZm9yIGEgc2luZ2xlIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhJUF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IFVwbG9hZCBCYW5kd2lkdGguIEZvciBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcsIHRoaXMgbGltaXRzIHRoZSB0cmFmZmljIGJhbmR3aWR0aCB0aGF0IGlzIGluIHRoZSBpbndhcmRzIGRpcmVjdGlvbiBmcm9tIG91dHNpZGUgdG8gaW5zaWRlIHRoZSBWaXJ0dWFsIEh1Yi4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok1heFVwbG9hZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERvd25sb2FkIEJhbmR3aWR0aC4gRm9yIHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgdGhpcyBsaW1pdHMgdGhlIHRyYWZmaWMgYmFuZHdpZHRoIHRoYXQgaXMgaW4gdGhlIG91dHdhcmRzIGRpcmVjdGlvbiBmcm9tIGluc2lkZSB0aGUgVmlydHVhbCBIdWIgdG8gb3V0c2lkZSB0aGUgVmlydHVhbCBIdWIuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhEb3dubG9hZF91MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgQ2hhbmdpbmcgUGFzc3dvcmQuIFRoZSB1c2VycyB3aGljaCB1c2UgcGFzc3dvcmQgYXV0aGVudGljYXRpb24gd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGFyZSBub3QgYWxsb3dlZCB0byBjaGFuZ2UgdGhlaXIgb3duIHBhc3N3b3JkIGZyb20gdGhlIFZQTiBDbGllbnQgTWFuYWdlciBvciBzaW1pbGFyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Rml4UGFzc3dvcmRfYm9vbFwiXSA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IE1heGltdW0gTnVtYmVyIG9mIE11bHRpcGxlIExvZ2lucy4gVXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nIGFyZSB1bmFibGUgdG8gaGF2ZSBtb3JlIHRoYW4gdGhpcyBudW1iZXIgb2YgY29uY3VycmVudCBsb2dpbnMuIEJyaWRnZSBNb2RlIHNlc3Npb25zIGFyZSBub3Qgc3ViamVjdHMgdG8gdGhpcyBwb2xpY3kuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNdWx0aUxvZ2luc191MzJcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBTZWN1cml0eSBwb2xpY3k6IERlbnkgVm9JUCAvIFFvUyBGdW5jdGlvbi4gVXNlcnMgd2l0aCB0aGlzIHNlY3VyaXR5IHBvbGljeSBhcmUgdW5hYmxlIHRvIHVzZSBWb0lQIC8gUW9TIGZ1bmN0aW9ucyBpbiBWUE4gY29ubmVjdGlvbiBzZXNzaW9ucy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vUW9TX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgUlMgLyBSQSBQYWNrZXRzIChJUHY2KS4gQWxsIElDTVB2NiBwYWNrZXRzIHdoaWNoIHRoZSBtZXNzYWdlLXR5cGUgaXMgMTMzIChSb3V0ZXIgU29saWNpdGF0aW9uKSBvciAxMzQgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuIEFzIGEgcmVzdWx0LCBhbiBJUHY2IGNsaWVudCB3aWxsIGJlIHVuYWJsZSB0byB1c2UgSVB2NiBhZGRyZXNzIHByZWZpeCBhdXRvIGRldGVjdGlvbiBhbmQgSVB2NiBkZWZhdWx0IGdhdGV3YXkgYXV0byBkZXRlY3Rpb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpSU2FuZFJBRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgUkEgUGFja2V0cyAoSVB2NikuIEFsbCBJQ01QdjYgcGFja2V0cyB3aGljaCB0aGUgbWVzc2FnZS10eXBlIGlzIDEzNCAoUm91dGVyIEFkdmVydGlzZW1lbnQpIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gQXMgYSByZXN1bHQsIGEgbWFsaWNpb3VzIHVzZXJzIHdpbGwgYmUgdW5hYmxlIHRvIHNwcmVhZCBpbGxlZ2FsIElQdjYgcHJlZml4IG9yIGRlZmF1bHQgZ2F0ZXdheSBhZHZlcnRpc2VtZW50cyBvbiB0aGUgbmV0d29yay4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OlJBRmlsdGVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgREhDUCBQYWNrZXRzIChJUHY2KS4gQWxsIElQdjYgREhDUCBwYWNrZXRzIGluIHNlc3Npb25zIGRlZmluZWQgdGhpcyBwb2xpY3kgd2lsbCBiZSBmaWx0ZXJlZC4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1B2NkZpbHRlcl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGlzYWxsb3cgREhDUCBTZXJ2ZXIgT3BlcmF0aW9uIChJUHY2KS4gQ29tcHV0ZXJzIGNvbm5lY3RlZCB0byBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZyB3aWxsIG5vdCBiZSBhbGxvd2VkIHRvIGJlY29tZSBhIERIQ1Agc2VydmVyIGFuZCBkaXN0cmlidXRlIElQdjYgYWRkcmVzc2VzIHRvIERIQ1AgY2xpZW50cy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkRIQ1B2Nk5vU2VydmVyX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IFJvdXRpbmcgT3BlcmF0aW9uIChJUHY2KS4gSVB2NiByb3V0aW5nIHdpbGwgYmUgZGVuaWVkIGZvciBzZXNzaW9ucyB0aGF0IGhhdmUgdGhpcyBwb2xpY3kgc2V0dGluZy4gRXZlbiBpbiB0aGUgY2FzZSB3aGVyZSB0aGUgSVAgcm91dGVyIGlzIG9wZXJhdGluZyBvbiB0aGUgdXNlciBjbGllbnQgc2lkZSwgY29tbXVuaWNhdGlvbiB3aWxsIG5vdCBiZSBwb3NzaWJsZS4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vUm91dGluZ1Y2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBEZW55IElQIEFkZHJlc3MgRHVwbGljYXRpb24gKElQdjYpLiBUaGUgdXNlIG9mIGR1cGxpY2F0aW5nIElQdjYgYWRkcmVzc2VzIHRoYXQgYXJlIGluIHVzZSBieSBjb21wdXRlcnMgb2YgZGlmZmVyZW50IHNlc3Npb25zIGNhbm5vdCBiZSB1c2VkIGJ5IHNlc3Npb25zIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkNoZWNrSVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGVueSBPcGVyYXRpb24gYXMgVENQL0lQIFNlcnZlciAoSVB2NikuIENvbXB1dGVycyBvZiBzZXNzaW9ucyB3aXRoIHRoaXMgcG9saWN5IHNldHRpbmcgY2FuJ3QgbGlzdGVuIGFuZCBhY2NlcHQgVENQL0lQIGNvbm5lY3Rpb25zIGluIElQdjYuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NlcnZlclY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBNYXhpbXVtIE51bWJlciBvZiBJUCBBZGRyZXNzZXMgKElQdjYpLiBGb3Igc2Vzc2lvbnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB0aGlzIHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIElQdjYgYWRkcmVzc2VzIHRoYXQgY2FuIGJlIHJlZ2lzdGVyZWQgZm9yIGEgc2luZ2xlIHNlc3Npb24uICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpNYXhJUHY2X3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRGlzYWxsb3cgUGFzc3dvcmQgU2F2ZSBpbiBWUE4gQ2xpZW50LiBGb3IgdXNlcnMgd2l0aCB0aGlzIHBvbGljeSBzZXR0aW5nLCB3aGVuIHRoZSB1c2VyIGlzIHVzaW5nICpzdGFuZGFyZCogcGFzc3dvcmQgYXV0aGVudGljYXRpb24sIHRoZSB1c2VyIHdpbGwgYmUgdW5hYmxlIHRvIHNhdmUgdGhlIHBhc3N3b3JkIGluIFZQTiBDbGllbnQuIFRoZSB1c2VyIHdpbGwgYmUgcmVxdWlyZWQgdG8gaW5wdXQgcGFzc3dvcmRzIGZvciBldmVyeSB0aW1lIHRvIGNvbm5lY3QgYSBWUE4uIFRoaXMgd2lsbCBpbXByb3ZlIHRoZSBzZWN1cml0eS4gSWYgdGhpcyBwb2xpY3kgaXMgZW5hYmxlZCwgVlBOIENsaWVudCBWZXJzaW9uIDIuMCB3aWxsIGJlIGRlbmllZCB0byBhY2Nlc3MuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpOb1NhdmVQYXNzd29yZF9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVlBOIENsaWVudCBBdXRvbWF0aWMgRGlzY29ubmVjdC4gRm9yIHVzZXJzIHdpdGggdGhpcyBwb2xpY3kgc2V0dGluZywgYSB1c2VyJ3MgVlBOIHNlc3Npb24gd2lsbCBiZSBkaXNjb25uZWN0ZWQgYXV0b21hdGljYWxseSBhZnRlciB0aGUgc3BlY2lmaWMgcGVyaW9kIHdpbGwgZWxhcHNlLiBJbiB0aGlzIGNhc2Ugbm8gYXV0b21hdGljIHJlLWNvbm5lY3Rpb24gd2lsbCBiZSBwZXJmb3JtZWQuIFRoaXMgY2FuIHByZXZlbnQgYSBsb3Qgb2YgaW5hY3RpdmUgVlBOIFNlc3Npb25zLiBJZiB0aGlzIHBvbGljeSBpcyBlbmFibGVkLCBWUE4gQ2xpZW50IFZlcnNpb24gMi4wIHdpbGwgYmUgZGVuaWVkIHRvIGFjY2Vzcy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkF1dG9EaXNjb25uZWN0X3UzMlwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogRmlsdGVyIEFsbCBJUHY0IFBhY2tldHMuIEFsbCBJUHY0IGFuZCBBUlAgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJJUHY0X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIElQdjYgUGFja2V0cy4gQWxsIElQdjYgcGFja2V0cyBpbiBzZXNzaW9ucyBkZWZpbmVkIHRoaXMgcG9saWN5IHdpbGwgYmUgZmlsdGVyZWQuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpGaWx0ZXJJUHY2X2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBGaWx0ZXIgQWxsIE5vbi1JUCBQYWNrZXRzLiBBbGwgbm9uLUlQIHBhY2tldHMgaW4gc2Vzc2lvbnMgZGVmaW5lZCB0aGlzIHBvbGljeSB3aWxsIGJlIGZpbHRlcmVkLiBcIk5vbi1JUCBwYWNrZXRcIiBtZWFuIGEgcGFja2V0IHdoaWNoIGlzIG5vdCBJUHY0LCBBUlAgbm9yIElQdjYuIEFueSB0YWdnZWQtVkxBTiBwYWNrZXRzIHZpYSB0aGUgVmlydHVhbCBIdWIgd2lsbCBiZSByZWdhcmRlZCBhcyBub24tSVAgcGFja2V0cy4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5OkZpbHRlck5vbklQX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBObyBEZWZhdWx0LVJvdXRlciBvbiBJUHY2IFJBLiBJbiBhbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFueSBJUHY2IFJBIChSb3V0ZXIgQWR2ZXJ0aXNlbWVudCkgcGFja2V0IHdpdGggbm9uLXplcm8gdmFsdWUgaW4gdGhlIHJvdXRlci1saWZldGltZSB3aWxsIHNldCB0byB6ZXJvLXZhbHVlLiBUaGlzIGlzIGVmZmVjdGl2ZSB0byBhdm9pZCB0aGUgaG9ycmlibGUgYmVoYXZpb3IgZnJvbSB0aGUgSVB2NiByb3V0aW5nIGNvbmZ1c2lvbiB3aGljaCBpcyBjYXVzZWQgYnkgdGhlIFZQTiBjbGllbnQncyBhdHRlbXB0cyB0byB1c2UgdGhlIHJlbW90ZS1zaWRlIElQdjYgcm91dGVyIGFzIGl0cyBsb2NhbCBJUHY2IHJvdXRlci4gKi9cclxuICAgICAgICB0aGlzW1wicG9saWN5Ok5vSVB2NkRlZmF1bHRSb3V0ZXJJblJBX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBObyBEZWZhdWx0LVJvdXRlciBvbiBJUHY2IFJBIChwaHlzaWNhbCBJUHY2KS4gSW4gYWxsIFZQTiBTZXNzaW9ucyBkZWZpbmVzIHRoaXMgcG9saWN5IChvbmx5IHdoZW4gdGhlIHBoeXNpY2FsIGNvbW11bmljYXRpb24gcHJvdG9jb2wgYmV0d2VlbiBWUE4gQ2xpZW50IC8gVlBOIEJyaWRnZSBhbmQgVlBOIFNlcnZlciBpcyBJUHY2KSwgYW55IElQdjYgUkEgKFJvdXRlciBBZHZlcnRpc2VtZW50KSBwYWNrZXQgd2l0aCBub24temVybyB2YWx1ZSBpbiB0aGUgcm91dGVyLWxpZmV0aW1lIHdpbGwgc2V0IHRvIHplcm8tdmFsdWUuIFRoaXMgaXMgZWZmZWN0aXZlIHRvIGF2b2lkIHRoZSBob3JyaWJsZSBiZWhhdmlvciBmcm9tIHRoZSBJUHY2IHJvdXRpbmcgY29uZnVzaW9uIHdoaWNoIGlzIGNhdXNlZCBieSB0aGUgVlBOIGNsaWVudCdzIGF0dGVtcHRzIHRvIHVzZSB0aGUgcmVtb3RlLXNpZGUgSVB2NiByb3V0ZXIgYXMgaXRzIGxvY2FsIElQdjYgcm91dGVyLiAqL1xyXG4gICAgICAgIHRoaXNbXCJwb2xpY3k6Tm9JUHY2RGVmYXVsdFJvdXRlckluUkFXaGVuSVB2Nl9ib29sXCJdID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlY3VyaXR5IHBvbGljeTogVkxBTiBJRCAoSUVFRTgwMi4xUSkuIFlvdSBjYW4gc3BlY2lmeSB0aGUgVkxBTiBJRCBvbiB0aGUgc2VjdXJpdHkgcG9saWN5LiBBbGwgVlBOIFNlc3Npb25zIGRlZmluZXMgdGhpcyBwb2xpY3ksIGFsbCBFdGhlcm5ldCBwYWNrZXRzIHRvd2FyZCB0aGUgVmlydHVhbCBIdWIgZnJvbSB0aGUgdXNlciB3aWxsIGJlIGluc2VydGVkIGEgVkxBTiB0YWcgKElFRUUgODAyLjFRKSB3aXRoIHRoZSBWTEFOIElELiBUaGUgdXNlciBjYW4gYWxzbyByZWNlaXZlIG9ubHkgcGFja2V0cyB3aXRoIGEgVkxBTiB0YWcgd2hpY2ggaGFzIHRoZSBzYW1lIFZMQU4gSUQuIChSZWNlaXZpbmcgcHJvY2VzcyByZW1vdmVzIHRoZSBWTEFOIHRhZyBhdXRvbWF0aWNhbGx5LikgQW55IEV0aGVybmV0IHBhY2tldHMgd2l0aCBhbnkgb3RoZXIgVkxBTiBJRHMgb3Igbm9uLVZMQU4gcGFja2V0cyB3aWxsIG5vdCBiZSByZWNlaXZlZC4gQWxsIFZQTiBTZXNzaW9ucyB3aXRob3V0IHRoaXMgcG9saWN5IGRlZmluaXRpb24gY2FuIHNlbmQgLyByZWNlaXZlIGFueSBraW5kcyBvZiBFdGhlcm5ldCBwYWNrZXRzIHJlZ2FyZGxlc3Mgb2YgVkxBTiB0YWdzLCBhbmQgVkxBTiB0YWdzIGFyZSBub3QgaW5zZXJ0ZWQgb3IgcmVtb3ZlZCBhdXRvbWF0aWNhbGx5LiBBbnkgdGFnZ2VkLVZMQU4gcGFja2V0cyB2aWEgdGhlIFZpcnR1YWwgSHViIHdpbGwgYmUgcmVnYXJkZWQgYXMgbm9uLUlQIHBhY2tldHMuIFRoZXJlZm9yZSwgdGFnZ2VkLVZMQU4gcGFja2V0cyBhcmUgbm90IHN1YmplY3RzIGZvciBJUHY0IC8gSVB2NiBzZWN1cml0eSBwb2xpY2llcywgYWNjZXNzIGxpc3RzIG5vciBvdGhlciBJUHY0IC8gSVB2NiBzcGVjaWZpYyBkZWVwIHByb2Nlc3NpbmcuICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWTGFuSWRfdTMyXCJdID0gMDtcclxuICAgICAgICAvKiogU2VjdXJpdHkgcG9saWN5OiBXaGV0aGVyIHZlcnNpb24gMy4wIChtdXN0IGJlIHRydWUpICovXHJcbiAgICAgICAgdGhpc1tcInBvbGljeTpWZXIzX2Jvb2xcIl0gPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NldFVzZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2V0VXNlciA9IFZwblJwY1NldFVzZXI7XHJcbi8qKiBEZWxldGUgdGhlIGFjY2VzcyBsaXN0ICovXHJcbnZhciBWcG5ScGNEZWxldGVBY2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRGVsZXRlQWNjZXNzJyBjbGFzczogRGVsZXRlIHRoZSBhY2Nlc3MgbGlzdCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRGVsZXRlQWNjZXNzKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSUQgKi9cclxuICAgICAgICB0aGlzLklkX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVBY2Nlc3M7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRGVsZXRlQWNjZXNzID0gVnBuUnBjRGVsZXRlQWNjZXNzO1xyXG4vKiogRGVsZXRlIHRoZSBDQSBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkRlbGV0ZUNBID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YkRlbGV0ZUNBJyBjbGFzczogRGVsZXRlIHRoZSBDQSBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkRlbGV0ZUNBKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2VydGlmaWNhdGUga2V5IGlkIHRvIGJlIGRlbGV0ZWQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViRGVsZXRlQ0E7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViRGVsZXRlQ0EgPSBWcG5ScGNIdWJEZWxldGVDQTtcclxuLyoqIERlbGV0aW5nIGEgdXNlciBvciBncm91cCAqL1xyXG52YXIgVnBuUnBjRGVsZXRlVXNlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVVc2VyJyBjbGFzczogRGVsZXRpbmcgYSB1c2VyIG9yIGdyb3VwICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEZWxldGVVc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBvciBncm91cCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVVc2VyO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVVzZXIgPSBWcG5ScGNEZWxldGVVc2VyO1xyXG4vKiogRGVsZXRlIHRoZSBIVUIgKi9cclxudmFyIFZwblJwY0RlbGV0ZUh1YiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVIdWInIGNsYXNzOiBEZWxldGUgdGhlIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRGVsZXRlSHViKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0RlbGV0ZUh1YjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNEZWxldGVIdWIgPSBWcG5ScGNEZWxldGVIdWI7XHJcbi8qKiBEZWxldGUgdGhlIHRhYmxlICovXHJcbnZhciBWcG5ScGNEZWxldGVUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEZWxldGVUYWJsZScgY2xhc3M6IERlbGV0ZSB0aGUgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0RlbGV0ZVRhYmxlKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2V5IElEICovXHJcbiAgICAgICAgdGhpcy5LZXlfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0RlbGV0ZVRhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVRhYmxlID0gVnBuUnBjRGVsZXRlVGFibGU7XHJcbi8qKiBTcGVjaWZ5IHRoZSBMaW5rICovXHJcbnZhciBWcG5ScGNMaW5rID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0xpbmsnIGNsYXNzOiBTcGVjaWZ5IHRoZSBMaW5rICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaW5rKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0xpbms7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjTGluayA9IFZwblJwY0xpbms7XHJcbi8qKiBEaXNjb25uZWN0IHRoZSBzZXNzaW9uICovXHJcbnZhciBWcG5ScGNEZWxldGVTZXNzaW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0RlbGV0ZVNlc3Npb24nIGNsYXNzOiBEaXNjb25uZWN0IHRoZSBzZXNzaW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEZWxldGVTZXNzaW9uKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2Vzc2lvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNEZWxldGVTZXNzaW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0RlbGV0ZVNlc3Npb24gPSBWcG5ScGNEZWxldGVTZXNzaW9uO1xyXG4vKiogU3BlY2lmeSB0aGUgSFVCICovXHJcbnZhciBWcG5ScGNIdWIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViJyBjbGFzczogU3BlY2lmeSB0aGUgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0h1YiA9IFZwblJwY0h1YjtcclxuLyoqIERpc2Nvbm5lY3QgYSBjb25uZWN0aW9uICovXHJcbnZhciBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbicgY2xhc3M6IERpc2Nvbm5lY3QgYSBjb25uZWN0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbihpbml0KSB7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRGlzY29ubmVjdENvbm5lY3Rpb247XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRGlzY29ubmVjdENvbm5lY3Rpb24gPSBWcG5ScGNEaXNjb25uZWN0Q29ubmVjdGlvbjtcclxuLyoqIEVudW1lcmF0aW9uIG9mIHRoZSBhY2Nlc3MgbGlzdCAqL1xyXG52YXIgVnBuUnBjRW51bUFjY2Vzc0xpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUFjY2Vzc0xpc3QnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiB0aGUgYWNjZXNzIGxpc3QgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1BY2Nlc3NMaXN0KGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQWNjZXNzIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkFjY2Vzc0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1BY2Nlc3NMaXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1BY2Nlc3NMaXN0ID0gVnBuUnBjRW51bUFjY2Vzc0xpc3Q7XHJcbi8qKiBDQSBlbnVtZXJhdGlvbiBpdGVtcyBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkVudW1DQUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjSHViRW51bUNBSXRlbScgY2xhc3M6IENBIGVudW1lcmF0aW9uIGl0ZW1zIG9mIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjSHViRW51bUNBSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBrZXkgaWQgb2YgdGhlIGl0ZW0gKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTdWJqZWN0ICovXHJcbiAgICAgICAgdGhpcy5TdWJqZWN0TmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBJc3N1ZXIgKi9cclxuICAgICAgICB0aGlzLklzc3Vlck5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogRXhwaXJhdGlvbiBkYXRlICovXHJcbiAgICAgICAgdGhpcy5FeHBpcmVzX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YkVudW1DQUl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViRW51bUNBSXRlbSA9IFZwblJwY0h1YkVudW1DQUl0ZW07XHJcbi8qKiBDQSBlbnVtZXJhdGlvbiBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkVudW1DQSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNIdWJFbnVtQ0EnIGNsYXNzOiBDQSBlbnVtZXJhdGlvbiBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkVudW1DQShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBsaXN0IG9mIENBICovXHJcbiAgICAgICAgdGhpcy5DQUxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YkVudW1DQTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJFbnVtQ0EgPSBWcG5ScGNIdWJFbnVtQ0E7XHJcbi8qKiBUeXBlIG9mIGNvbm5lY3Rpb24gKi9cclxudmFyIFZwblJwY0Nvbm5lY3Rpb25UeXBlO1xyXG4oZnVuY3Rpb24gKFZwblJwY0Nvbm5lY3Rpb25UeXBlKSB7XHJcbiAgICAvKiogVlBOIENsaWVudCAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJDbGllbnRcIl0gPSAwXSA9IFwiQ2xpZW50XCI7XHJcbiAgICAvKiogRHVyaW5nIGluaXRpYWxpemF0aW9uICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIkluaXRcIl0gPSAxXSA9IFwiSW5pdFwiO1xyXG4gICAgLyoqIExvZ2luIGNvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiTG9naW5cIl0gPSAyXSA9IFwiTG9naW5cIjtcclxuICAgIC8qKiBBZGRpdGlvbmFsIGNvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiQWRkaXRpb25hbFwiXSA9IDNdID0gXCJBZGRpdGlvbmFsXCI7XHJcbiAgICAvKiogUlBDIGZvciBzZXJ2ZXIgZmFybSAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJGYXJtUnBjXCJdID0gNF0gPSBcIkZhcm1ScGNcIjtcclxuICAgIC8qKiBSUEMgZm9yIE1hbmFnZW1lbnQgKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiQWRtaW5ScGNcIl0gPSA1XSA9IFwiQWRtaW5ScGNcIjtcclxuICAgIC8qKiBIVUIgZW51bWVyYXRpb24gKi9cclxuICAgIFZwblJwY0Nvbm5lY3Rpb25UeXBlW1ZwblJwY0Nvbm5lY3Rpb25UeXBlW1wiRW51bUh1YlwiXSA9IDZdID0gXCJFbnVtSHViXCI7XHJcbiAgICAvKiogUGFzc3dvcmQgY2hhbmdlICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIlBhc3N3b3JkXCJdID0gN10gPSBcIlBhc3N3b3JkXCI7XHJcbiAgICAvKiogU1NUUCAqL1xyXG4gICAgVnBuUnBjQ29ubmVjdGlvblR5cGVbVnBuUnBjQ29ubmVjdGlvblR5cGVbXCJTU1RQXCJdID0gOF0gPSBcIlNTVFBcIjtcclxuICAgIC8qKiBPcGVuVlBOICovXHJcbiAgICBWcG5ScGNDb25uZWN0aW9uVHlwZVtWcG5ScGNDb25uZWN0aW9uVHlwZVtcIk9wZW5WUE5cIl0gPSA5XSA9IFwiT3BlblZQTlwiO1xyXG59KShWcG5ScGNDb25uZWN0aW9uVHlwZSA9IGV4cG9ydHMuVnBuUnBjQ29ubmVjdGlvblR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjQ29ubmVjdGlvblR5cGUgPSB7fSkpO1xyXG4vKiogQ29ubmVjdGlvbiBlbnVtZXJhdGlvbiBpdGVtcyAqL1xyXG52YXIgVnBuUnBjRW51bUNvbm5lY3Rpb25JdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Db25uZWN0aW9uSXRlbScgY2xhc3M6IENvbm5lY3Rpb24gZW51bWVyYXRpb24gaXRlbXMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Db25uZWN0aW9uSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogUG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGVkIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHR5cGUgKi9cclxuICAgICAgICB0aGlzLlR5cGVfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Db25uZWN0aW9uSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtQ29ubmVjdGlvbkl0ZW0gPSBWcG5ScGNFbnVtQ29ubmVjdGlvbkl0ZW07XHJcbi8qKiBDb25uZWN0aW9uIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtQ29ubmVjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtQ29ubmVjdGlvbicgY2xhc3M6IENvbm5lY3Rpb24gZW51bWVyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Db25uZWN0aW9uKGluaXQpIHtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1Db25uZWN0aW9uX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGlvbkxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Db25uZWN0aW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Db25uZWN0aW9uID0gVnBuUnBjRW51bUNvbm5lY3Rpb247XHJcbi8qKiBFbnVtIENSTCBJdGVtICovXHJcbnZhciBWcG5ScGNFbnVtQ3JsSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtQ3JsSXRlbScgY2xhc3M6IEVudW0gQ1JMIEl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1DcmxJdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogS2V5IElEICovXHJcbiAgICAgICAgdGhpcy5LZXlfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGNvbnRlbnRzIG9mIHRoZSBDUkwgaXRlbSAqL1xyXG4gICAgICAgIHRoaXMuQ3JsSW5mb191dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUNybEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUNybEl0ZW0gPSBWcG5ScGNFbnVtQ3JsSXRlbTtcclxuLyoqIEVudW0gQ1JMICovXHJcbnZhciBWcG5ScGNFbnVtQ3JsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1DcmwnIGNsYXNzOiBFbnVtIENSTCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUNybChpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENSTCBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5DUkxMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtQ3JsO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1DcmwgPSBWcG5ScGNFbnVtQ3JsO1xyXG4vKiogUlBDX0VOVU1fREhDUF9JVEVNICovXHJcbnZhciBWcG5ScGNFbnVtRGhjcEl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bURoY3BJdGVtJyBjbGFzczogUlBDX0VOVU1fREhDUF9JVEVNICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRGhjcEl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogTGVhc2UgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuTGVhc2VkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIEV4cGlyYXRpb24gZGF0ZSAqL1xyXG4gICAgICAgIHRoaXMuRXhwaXJlVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE1BQyBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5NYWNBZGRyZXNzX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLk1hc2tfdTMyID0gMDtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bURoY3BJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1EaGNwSXRlbSA9IFZwblJwY0VudW1EaGNwSXRlbTtcclxuLyoqIFJQQ19FTlVNX0RIQ1AgKi9cclxudmFyIFZwblJwY0VudW1EaGNwID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1EaGNwJyBjbGFzczogUlBDX0VOVU1fREhDUCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bURoY3AoaW5pdCkge1xyXG4gICAgICAgIC8qKiBWaXJ0dWFsIEh1YiBOYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIERIQ1AgSXRlbSAqL1xyXG4gICAgICAgIHRoaXMuRGhjcFRhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRGhjcDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRGhjcCA9IFZwblJwY0VudW1EaGNwO1xyXG4vKiogRXRoZXJJUCBzZXR0aW5nIGxpc3QgKi9cclxudmFyIFZwblJwY0VudW1FdGhlcklwSWQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUV0aGVySXBJZCcgY2xhc3M6IEV0aGVySVAgc2V0dGluZyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoZXJJcElkKGluaXQpIHtcclxuICAgICAgICAvKiogU2V0dGluZyBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5TZXR0aW5ncyA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUV0aGVySXBJZDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRXRoZXJJcElkID0gVnBuUnBjRW51bUV0aGVySXBJZDtcclxuLyoqIEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCBpdGVtICovXHJcbnZhciBWcG5ScGNFbnVtRXRoSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtRXRoSXRlbScgY2xhc3M6IEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIERldmljZSBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXZpY2VOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE5ldHdvcmsgY29ubmVjdGlvbiBuYW1lIChkZXNjcmlwdGlvbikgKi9cclxuICAgICAgICB0aGlzLk5ldHdvcmtDb25uZWN0aW9uTmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUV0aEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUV0aEl0ZW0gPSBWcG5ScGNFbnVtRXRoSXRlbTtcclxuLyoqIEV0aGVybmV0IE5ldHdvcmsgQWRhcHRlcnMgbGlzdCAqL1xyXG52YXIgVnBuUnBjRW51bUV0aCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtRXRoJyBjbGFzczogRXRoZXJuZXQgTmV0d29yayBBZGFwdGVycyBsaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRXRoKGluaXQpIHtcclxuICAgICAgICAvKiogRXRoZXJuZXQgTmV0d29yayBBZGFwdGVycyBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5FdGhMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRXRoO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1FdGggPSBWcG5ScGNFbnVtRXRoO1xyXG4vKiogU2VydmVyIGZhcm0gbWVtYmVycyBlbnVtZXJhdGlvbiBpdGVtcyAqL1xyXG52YXIgVnBuUnBjRW51bUZhcm1JdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1GYXJtSXRlbScgY2xhc3M6IFNlcnZlciBmYXJtIG1lbWJlcnMgZW51bWVyYXRpb24gaXRlbXMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1GYXJtSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIElEICovXHJcbiAgICAgICAgdGhpcy5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb250cm9sbGVyICovXHJcbiAgICAgICAgdGhpcy5Db250cm9sbGVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvaW50ICovXHJcbiAgICAgICAgdGhpcy5Qb2ludF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2Ygc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBIVUJzICovXHJcbiAgICAgICAgdGhpcy5OdW1IdWJzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhc3NpZ25lZCBjbGllbnQgbGljZW5zZXMgKi9cclxuICAgICAgICB0aGlzLkFzc2lnbmVkQ2xpZW50TGljZW5zZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYXNzaWduZWQgYnJpZGdlIGxpY2Vuc2VzICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1GYXJtSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRmFybUl0ZW0gPSBWcG5ScGNFbnVtRmFybUl0ZW07XHJcbi8qKiBTZXJ2ZXIgZmFybSBtZW1iZXIgZW51bWVyYXRpb24gKi9cclxudmFyIFZwblJwY0VudW1GYXJtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1GYXJtJyBjbGFzczogU2VydmVyIGZhcm0gbWVtYmVyIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtRmFybShpbml0KSB7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBDbHVzdGVyIE1lbWJlcnMgKi9cclxuICAgICAgICB0aGlzLk51bUZhcm1fdTMyID0gMDtcclxuICAgICAgICAvKiogQ2x1c3RlciBNZW1iZXJzIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkZhcm1NZW1iZXJMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtRmFybTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtRmFybSA9IFZwblJwY0VudW1GYXJtO1xyXG4vKiogRW51bWVyYXRpb24gaXRlbXMgaW4gdGhlIGdyb3VwICovXHJcbnZhciBWcG5ScGNFbnVtR3JvdXBJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Hcm91cEl0ZW0nIGNsYXNzOiBFbnVtZXJhdGlvbiBpdGVtcyBpbiB0aGUgZ3JvdXAgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Hcm91cEl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBVc2VyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUmVhbCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOb3RlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiB1c2VycyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVXNlcnNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWNjZXNzIGRlbmllZCAqL1xyXG4gICAgICAgIHRoaXMuRGVueUFjY2Vzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtR3JvdXBJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Hcm91cEl0ZW0gPSBWcG5ScGNFbnVtR3JvdXBJdGVtO1xyXG4vKiogR3JvdXAgZW51bWVyYXRpb24gKi9cclxudmFyIFZwblJwY0VudW1Hcm91cCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtR3JvdXAnIGNsYXNzOiBHcm91cCBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUdyb3VwKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogR3JvdXAgbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuR3JvdXBMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtR3JvdXA7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUdyb3VwID0gVnBuUnBjRW51bUdyb3VwO1xyXG4vKiogRW51bWVyYXRpb24gaXRlbXMgb2YgSFVCICovXHJcbnZhciBWcG5ScGNFbnVtSHViSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtSHViSXRlbScgY2xhc3M6IEVudW1lcmF0aW9uIGl0ZW1zIG9mIEhVQiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUh1Ykl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgVmlydHVhbCBIdWIgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT25saW5lIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIEhVQiAoVmFsaWQgb25seSBmb3IgQ2x1c3RlcmVkIFZQTiBTZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuSHViVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdXNlcnMgKi9cclxuICAgICAgICB0aGlzLk51bVVzZXJzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZWdpc3RlcmVkIGdyb3VwcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtR3JvdXBzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZWdpc3RlcmVkIHNlc3Npb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1TZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgY3VycmVudCBNQUMgdGFibGUgZW50cmllcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTWFjVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IElQIHRhYmxlIGVudHJpZXMgKi9cclxuICAgICAgICB0aGlzLk51bUlwVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBMYXN0IGxvZ2luIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkxhc3RMb2dpblRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhY2N1bXVsYXRlZCBsb2dpbnMgKi9cclxuICAgICAgICB0aGlzLk51bUxvZ2luX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFdoZXRoZXIgdGhlIHRyYWZmaWMgaW5mb3JtYXRpb24gaXMgcHJvdmlkZWQgKi9cclxuICAgICAgICB0aGlzLklzVHJhZmZpY0ZpbGxlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBjb3VudCAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiRXguUmVjdi5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5TZW5kLlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUh1Ykl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUh1Ykl0ZW0gPSBWcG5ScGNFbnVtSHViSXRlbTtcclxuLyoqIEVudW1lcmF0aW9uIG9mIEhVQiAqL1xyXG52YXIgVnBuUnBjRW51bUh1YiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtSHViJyBjbGFzczogRW51bWVyYXRpb24gb2YgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtSHViKGluaXQpIHtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFZpcnR1YWwgSHVicyAqL1xyXG4gICAgICAgIHRoaXMuTnVtSHViX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSHVicyAqL1xyXG4gICAgICAgIHRoaXMuSHViTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUh1YjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtSHViID0gVnBuUnBjRW51bUh1YjtcclxuLyoqIEVudW1lcmF0aW9uIGl0ZW1zIG9mIElQIHRhYmxlICovXHJcbnZhciBWcG5ScGNFbnVtSXBUYWJsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUlwVGFibGVJdGVtJyBjbGFzczogRW51bWVyYXRpb24gaXRlbXMgb2YgSVAgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1JcFRhYmxlSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIEtleSBJRCAqL1xyXG4gICAgICAgIHRoaXMuS2V5X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlc3Npb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuSXBBZGRyZXNzX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogQXNzaWduZWQgYnkgdGhlIERIQ1AgKi9cclxuICAgICAgICB0aGlzLkRoY3BBbGxvY2F0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIFVwZGF0aW5nIGRhdGUgKi9cclxuICAgICAgICB0aGlzLlVwZGF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogUmVtb3RlIGl0ZW1zICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVJdGVtX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogUmVtb3RlIGhvc3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUmVtb3RlSG9zdG5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1JcFRhYmxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtSXBUYWJsZUl0ZW0gPSBWcG5ScGNFbnVtSXBUYWJsZUl0ZW07XHJcbi8qKiBFbnVtZXJhdGlvbiBvZiBJUCB0YWJsZSAqL1xyXG52YXIgVnBuUnBjRW51bUlwVGFibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUlwVGFibGUnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiBJUCB0YWJsZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUlwVGFibGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgdGFibGUgKi9cclxuICAgICAgICB0aGlzLklwVGFibGUgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1JcFRhYmxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1JcFRhYmxlID0gVnBuUnBjRW51bUlwVGFibGU7XHJcbi8qKiBMYXllci0zIGludGVyZmFjZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUwzSWYgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUwzSWYnIGNsYXNzOiBMYXllci0zIGludGVyZmFjZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUwzSWYoaW5pdCkge1xyXG4gICAgICAgIC8qKiBMYXllci0zIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIExheWVyLTMgaW50ZXJmYWNlIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkwzSUZMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNJZjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNJZiA9IFZwblJwY0VudW1MM0lmO1xyXG4vKiogTGF5ZXItMyBzd2l0Y2ggZW51bWVyYXRpb24gaXRlbSAqL1xyXG52YXIgVnBuUnBjRW51bUwzU3dJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1MM1N3SXRlbScgY2xhc3M6IExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uIGl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1MM1N3SXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIE5hbWUgb2YgdGhlIGxheWVyLTMgc3dpdGNoICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBsYXllci0zIHN3aXRjaCB2aXJ0dWFsIGludGVyZmFjZXMgKi9cclxuICAgICAgICB0aGlzLk51bUludGVyZmFjZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHJvdXRpbmcgdGFibGVzICovXHJcbiAgICAgICAgdGhpcy5OdW1UYWJsZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZhdGVkIGZsYWcgKi9cclxuICAgICAgICB0aGlzLkFjdGl2ZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUwzU3dJdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1MM1N3SXRlbSA9IFZwblJwY0VudW1MM1N3SXRlbTtcclxuLyoqIExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTDNTdyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTDNTdycgY2xhc3M6IExheWVyLTMgc3dpdGNoIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTDNTdyhpbml0KSB7XHJcbiAgICAgICAgLyoqIExheWVyLTMgc3dpdGNoIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkwzU1dMaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNTdztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNTdyA9IFZwblJwY0VudW1MM1N3O1xyXG4vKiogUm91dGluZyB0YWJsZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUwzVGFibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUwzVGFibGUnIGNsYXNzOiBSb3V0aW5nIHRhYmxlIGVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTDNUYWJsZShpbml0KSB7XHJcbiAgICAgICAgLyoqIEwzIHN3aXRjaCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFJvdXRpbmcgdGFibGUgaXRlbSBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5MM1RhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTDNUYWJsZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTDNUYWJsZSA9IFZwblJwY0VudW1MM1RhYmxlO1xyXG4vKiogQ2FzY2FkZSBDb25uZWN0aW9uIEVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTGlua0l0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxpbmtJdGVtJyBjbGFzczogQ2FzY2FkZSBDb25uZWN0aW9uIEVudW1lcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTGlua0l0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgbmFtZSBvZiBjYXNjYWRlIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkFjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSBmbGFnICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyBpbmRpY2F0ZXMgd2hldGhlciB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGVzdGFibGlzaGVkICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgZXJyb3IgbGFzdCBvY2N1cnJlZCBpZiB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGluIHRoZSBmYWlsIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5MYXN0RXJyb3JfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBjb21wbGV0aW9uIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBIb3N0IG5hbWUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLkhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5UYXJnZXRIdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTGlua0l0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUxpbmtJdGVtID0gVnBuUnBjRW51bUxpbmtJdGVtO1xyXG4vKiogRW51bWVyYXRpb24gb2YgdGhlIGxpbmsgKi9cclxudmFyIFZwblJwY0VudW1MaW5rID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1MaW5rJyBjbGFzczogRW51bWVyYXRpb24gb2YgdGhlIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1MaW5rKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNhc2NhZGUgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bUxpbmtfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGxpc3Qgb2YgY2FzY2FkZSBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTGlua0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1MaW5rO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1MaW5rID0gVnBuUnBjRW51bUxpbms7XHJcbi8qKiBMaXN0IG9mIGxpc3RlbmVycyBpdGVtICovXHJcbnZhciBWcG5ScGNMaXN0ZW5lckxpc3RJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0xpc3RlbmVyTGlzdEl0ZW0nIGNsYXNzOiBMaXN0IG9mIGxpc3RlbmVycyBpdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaXN0ZW5lckxpc3RJdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogVENQIHBvcnQgbnVtYmVyIChyYW5nZTogMSAtIDY1NTM1KSAqL1xyXG4gICAgICAgIHRoaXMuUG9ydHNfdTMyID0gMDtcclxuICAgICAgICAvKiogQWN0aXZlIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5FbmFibGVzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIGVycm9yIG9jY3VycmVkIG9uIHRoZSBsaXN0ZW5lciBwb3J0ICovXHJcbiAgICAgICAgdGhpcy5FcnJvcnNfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXJMaXN0SXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNMaXN0ZW5lckxpc3RJdGVtID0gVnBuUnBjTGlzdGVuZXJMaXN0SXRlbTtcclxuLyoqIExpc3Qgb2YgbGlzdGVuZXJzICovXHJcbnZhciBWcG5ScGNMaXN0ZW5lckxpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTGlzdGVuZXJMaXN0JyBjbGFzczogTGlzdCBvZiBsaXN0ZW5lcnMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0xpc3RlbmVyTGlzdChpbml0KSB7XHJcbiAgICAgICAgLyoqIExpc3Qgb2YgbGlzdGVuZXIgaXRlbXMgKi9cclxuICAgICAgICB0aGlzLkxpc3RlbmVyTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTGlzdGVuZXJMaXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0xpc3RlbmVyTGlzdCA9IFZwblJwY0xpc3RlbmVyTGlzdDtcclxuLyoqIExvY2FsIEJyaWRnZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUxvY2FsQnJpZGdlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1Mb2NhbEJyaWRnZScgY2xhc3M6IExvY2FsIEJyaWRnZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUxvY2FsQnJpZGdlKGluaXQpIHtcclxuICAgICAgICAvKiogTG9jYWwgQnJpZGdlIGxpc3QgKi9cclxuICAgICAgICB0aGlzLkxvY2FsQnJpZGdlTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUxvY2FsQnJpZGdlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1Mb2NhbEJyaWRnZSA9IFZwblJwY0VudW1Mb2NhbEJyaWRnZTtcclxuLyoqIExvZyBmaWxlIGVudW1lcmF0aW9uICovXHJcbnZhciBWcG5ScGNFbnVtTG9nRmlsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxvZ0ZpbGVJdGVtJyBjbGFzczogTG9nIGZpbGUgZW51bWVyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Mb2dGaWxlSXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEZpbGUgcGF0aCAqL1xyXG4gICAgICAgIHRoaXMuRmlsZVBhdGhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogRmlsZSBzaXplICovXHJcbiAgICAgICAgdGhpcy5GaWxlU2l6ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBMYXN0IHdyaXRlIGRhdGUgKi9cclxuICAgICAgICB0aGlzLlVwZGF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Mb2dGaWxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTG9nRmlsZUl0ZW0gPSBWcG5ScGNFbnVtTG9nRmlsZUl0ZW07XHJcbi8qKiBMb2cgZmlsZSBlbnVtZXJhdGlvbiAqL1xyXG52YXIgVnBuUnBjRW51bUxvZ0ZpbGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bUxvZ0ZpbGUnIGNsYXNzOiBMb2cgZmlsZSBlbnVtZXJhdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bUxvZ0ZpbGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBMb2cgZmlsZSBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5Mb2dGaWxlcyA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bUxvZ0ZpbGU7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bUxvZ0ZpbGUgPSBWcG5ScGNFbnVtTG9nRmlsZTtcclxuLyoqIEVudW1lcmF0aW9uIGl0ZW1zIG9mIHRoZSBNQUMgdGFibGUgKi9cclxudmFyIFZwblJwY0VudW1NYWNUYWJsZUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bU1hY1RhYmxlSXRlbScgY2xhc3M6IEVudW1lcmF0aW9uIGl0ZW1zIG9mIHRoZSBNQUMgdGFibGUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1NYWNUYWJsZUl0ZW0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBLZXkgSUQgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE1BQyBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5NYWNBZGRyZXNzX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICAvKiogQ3JlYXRpb24gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuQ3JlYXRlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBVcGRhdGluZyBkYXRlICovXHJcbiAgICAgICAgdGhpcy5VcGRhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBpdGVtcyAqL1xyXG4gICAgICAgIHRoaXMuUmVtb3RlSXRlbV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlJlbW90ZUhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZMQU4gSUQgKi9cclxuICAgICAgICB0aGlzLlZsYW5JZF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bU1hY1RhYmxlSXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtTWFjVGFibGVJdGVtID0gVnBuUnBjRW51bU1hY1RhYmxlSXRlbTtcclxuLyoqIEVudW1lcmF0aW9uIG9mIHRoZSBNQUMgdGFibGUgKi9cclxudmFyIFZwblJwY0VudW1NYWNUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTWFjVGFibGUnIGNsYXNzOiBFbnVtZXJhdGlvbiBvZiB0aGUgTUFDIHRhYmxlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTWFjVGFibGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgdGFibGUgKi9cclxuICAgICAgICB0aGlzLk1hY1RhYmxlID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNFbnVtTWFjVGFibGU7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU1hY1RhYmxlID0gVnBuUnBjRW51bU1hY1RhYmxlO1xyXG4vKiogTkFUIEVudHJ5IFByb3RvY29sIE51bWJlciAqL1xyXG52YXIgVnBuUnBjTmF0UHJvdG9jb2w7XHJcbihmdW5jdGlvbiAoVnBuUnBjTmF0UHJvdG9jb2wpIHtcclxuICAgIC8qKiBUQ1AgKi9cclxuICAgIFZwblJwY05hdFByb3RvY29sW1ZwblJwY05hdFByb3RvY29sW1wiVENQXCJdID0gMF0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuUnBjTmF0UHJvdG9jb2xbVnBuUnBjTmF0UHJvdG9jb2xbXCJVRFBcIl0gPSAxXSA9IFwiVURQXCI7XHJcbiAgICAvKiogRE5TICovXHJcbiAgICBWcG5ScGNOYXRQcm90b2NvbFtWcG5ScGNOYXRQcm90b2NvbFtcIkROU1wiXSA9IDJdID0gXCJETlNcIjtcclxuICAgIC8qKiBJQ01QICovXHJcbiAgICBWcG5ScGNOYXRQcm90b2NvbFtWcG5ScGNOYXRQcm90b2NvbFtcIklDTVBcIl0gPSAzXSA9IFwiSUNNUFwiO1xyXG59KShWcG5ScGNOYXRQcm90b2NvbCA9IGV4cG9ydHMuVnBuUnBjTmF0UHJvdG9jb2wgfHwgKGV4cG9ydHMuVnBuUnBjTmF0UHJvdG9jb2wgPSB7fSkpO1xyXG4vKiogU3RhdGUgb2YgTkFUIHNlc3Npb24gKFRDUCkgKi9cclxudmFyIFZwblJwY05hdFRjcFN0YXRlO1xyXG4oZnVuY3Rpb24gKFZwblJwY05hdFRjcFN0YXRlKSB7XHJcbiAgICAvKiogQ29ubmVjdGluZyAqL1xyXG4gICAgVnBuUnBjTmF0VGNwU3RhdGVbVnBuUnBjTmF0VGNwU3RhdGVbXCJDb25uZWN0aW5nXCJdID0gMF0gPSBcIkNvbm5lY3RpbmdcIjtcclxuICAgIC8qKiBTZW5kIHRoZSBSU1QgKENvbm5lY3Rpb24gZmFpbHVyZSBvciBkaXNjb25uZWN0ZWQpICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIlNlbmRSZXNldFwiXSA9IDFdID0gXCJTZW5kUmVzZXRcIjtcclxuICAgIC8qKiBDb25uZWN0aW9uIGNvbXBsZXRlICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIkNvbm5lY3RlZFwiXSA9IDJdID0gXCJDb25uZWN0ZWRcIjtcclxuICAgIC8qKiBDb25uZWN0aW9uIGVzdGFibGlzaGVkICovXHJcbiAgICBWcG5ScGNOYXRUY3BTdGF0ZVtWcG5ScGNOYXRUY3BTdGF0ZVtcIkVzdGFibGlzaGVkXCJdID0gM10gPSBcIkVzdGFibGlzaGVkXCI7XHJcbiAgICAvKiogV2FpdCBmb3Igc29ja2V0IGRpc2Nvbm5lY3Rpb24gKi9cclxuICAgIFZwblJwY05hdFRjcFN0YXRlW1ZwblJwY05hdFRjcFN0YXRlW1wiV2FpdERpc2Nvbm5lY3RcIl0gPSA0XSA9IFwiV2FpdERpc2Nvbm5lY3RcIjtcclxufSkoVnBuUnBjTmF0VGNwU3RhdGUgPSBleHBvcnRzLlZwblJwY05hdFRjcFN0YXRlIHx8IChleHBvcnRzLlZwblJwY05hdFRjcFN0YXRlID0ge30pKTtcclxuLyoqIFZwblJwY0VudW1OYXQgTGlzdCBJdGVtICovXHJcbnZhciBWcG5ScGNFbnVtTmF0SXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTmF0SXRlbScgY2xhc3M6IFZwblJwY0VudW1OYXQgTGlzdCBJdGVtICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTmF0SXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIElEICovXHJcbiAgICAgICAgdGhpcy5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBQcm90b2NvbCAqL1xyXG4gICAgICAgIHRoaXMuUHJvdG9jb2xfdTMyID0gMDtcclxuICAgICAgICAvKiogU291cmNlIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLlNyY0lwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU291cmNlIGhvc3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU3JjSG9zdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgcG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNyY1BvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuRGVzdElwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogRGVzdGluYXRpb24gaG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5EZXN0SG9zdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEZXN0aW5hdGlvbiBwb3J0IG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuRGVzdFBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBUcmFuc21pc3Npb24gc2l6ZSAqL1xyXG4gICAgICAgIHRoaXMuU2VuZFNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogUmVjZWl2ZSBzaXplICovXHJcbiAgICAgICAgdGhpcy5SZWN2U2l6ZV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUQ1Agc3RhdGUgKi9cclxuICAgICAgICB0aGlzLlRjcFN0YXR1c191MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bU5hdEl0ZW07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU5hdEl0ZW0gPSBWcG5ScGNFbnVtTmF0SXRlbTtcclxuLyoqIFJQQ19FTlVNX05BVCAqL1xyXG52YXIgVnBuUnBjRW51bU5hdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtTmF0JyBjbGFzczogUlBDX0VOVU1fTkFUICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNFbnVtTmF0KGluaXQpIHtcclxuICAgICAgICAvKiogVmlydHVhbCBIdWIgTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOQVQgaXRlbSAqL1xyXG4gICAgICAgIHRoaXMuTmF0VGFibGUgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1OYXQ7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bU5hdCA9IFZwblJwY0VudW1OYXQ7XHJcbi8qKiBFbnVtZXJhdGlvbiBpdGVtIG9mIFZQTiBzZXNzaW9uICovXHJcbnZhciBWcG5ScGNFbnVtU2Vzc2lvbkl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRW51bVNlc3Npb25JdGVtJyBjbGFzczogRW51bWVyYXRpb24gaXRlbSBvZiBWUE4gc2Vzc2lvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bVNlc3Npb25JdGVtKGluaXQpIHtcclxuICAgICAgICAvKiogU2Vzc2lvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFJlbW90ZSBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVTZXNzaW9uX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogUmVtb3RlIHNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZW1vdGVIb3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2VyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlVzZXJuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLkNsaWVudElQX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiB1bmRlcmx5aW5nIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTWF4TnVtVGNwX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IHVuZGVybHlpbmcgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50TnVtVGNwX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFBhY2tldCBzaXplIHRyYW5zbWl0dGVkICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRTaXplX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBwYWNrZXRzIHRyYW5zbWl0dGVkICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXROdW1fdTY0ID0gMDtcclxuICAgICAgICAvKiogSXMgYSBDYXNjYWRlIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5MaW5rTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElzIGEgU2VjdXJlTkFUIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZWN1cmVOQVRNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgdGhlIFZQTiBzZXNzaW9uIGZvciBMb2NhbCBCcmlkZ2UgKi9cclxuICAgICAgICB0aGlzLkJyaWRnZU1vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBJcyBhIExheWVyLTMgU3dpdGNoIFZQTiBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5MYXllcjNNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgaW4gQnJpZGdlIE1vZGUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudF9CcmlkZ2VNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgaW4gTW9uaXRvciBNb2RlICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRfTW9uaXRvck1vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBWTEFOIElEICovXHJcbiAgICAgICAgdGhpcy5WTGFuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVW5pcXVlIElEIG9mIHRoZSBWUE4gU2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuVW5pcXVlSWRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBDcmVhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DcmVhdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgY29tbXVuaWNhdGlvbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0Q29tbVRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bVNlc3Npb25JdGVtO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1TZXNzaW9uSXRlbSA9IFZwblJwY0VudW1TZXNzaW9uSXRlbTtcclxuLyoqIEVudW1lcmF0ZSBWUE4gc2Vzc2lvbnMgKi9cclxudmFyIFZwblJwY0VudW1TZXNzaW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0VudW1TZXNzaW9uJyBjbGFzczogRW51bWVyYXRlIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRW51bVNlc3Npb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBWUE4gc2Vzc2lvbnMgbGlzdCAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbkxpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1TZXNzaW9uO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0VudW1TZXNzaW9uID0gVnBuUnBjRW51bVNlc3Npb247XHJcbi8qKiBFbnVtZXJhdGlvbiBpdGVtIG9mIHVzZXIgKi9cclxudmFyIFZwblJwY0VudW1Vc2VySXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtVXNlckl0ZW0nIGNsYXNzOiBFbnVtZXJhdGlvbiBpdGVtIG9mIHVzZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Vc2VySXRlbShpbml0KSB7XHJcbiAgICAgICAgLyoqIFVzZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBHcm91cCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Hcm91cE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUmVhbCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5SZWFsbmFtZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBOb3RlICovXHJcbiAgICAgICAgdGhpcy5Ob3RlX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEF1dGhlbnRpY2F0aW9uIG1ldGhvZCAqL1xyXG4gICAgICAgIHRoaXMuQXV0aFR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvZ2lucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICAvKiogTGFzdCBsb2dpbiBkYXRlIGFuZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5MYXN0TG9naW5UaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogQWNjZXNzIGRlbmllZCAqL1xyXG4gICAgICAgIHRoaXMuRGVueUFjY2Vzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEZsYWcgb2Ygd2hldGhlciB0aGUgdHJhZmZpYyB2YXJpYWJsZSBpcyBzZXQgKi9cclxuICAgICAgICB0aGlzLklzVHJhZmZpY0ZpbGxlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEZsYWcgb2Ygd2hldGhlciBleHBpcmF0aW9uIGRhdGUgdmFyaWFibGUgaXMgc2V0ICovXHJcbiAgICAgICAgdGhpcy5Jc0V4cGlyZXNGaWxsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBFeHBpcmF0aW9uIGRhdGUgKi9cclxuICAgICAgICB0aGlzLkV4cGlyZXNfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJFeC5SZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIkV4LlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiRXguU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0VudW1Vc2VySXRlbTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNFbnVtVXNlckl0ZW0gPSBWcG5ScGNFbnVtVXNlckl0ZW07XHJcbi8qKiBFbnVtZXJhdGlvbiBvZiB1c2VyICovXHJcbnZhciBWcG5ScGNFbnVtVXNlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNFbnVtVXNlcicgY2xhc3M6IEVudW1lcmF0aW9uIG9mIHVzZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0VudW1Vc2VyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5Vc2VyTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRW51bVVzZXI7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRW51bVVzZXIgPSBWcG5ScGNFbnVtVXNlcjtcclxuLyoqIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgSXRlbSAqL1xyXG52YXIgVnBuQWMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQWMnIGNsYXNzOiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0IEl0ZW0gKi9cclxuICAgIGZ1bmN0aW9uIFZwbkFjKGluaXQpIHtcclxuICAgICAgICAvKiogSUQgKi9cclxuICAgICAgICB0aGlzLklkX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByaW9yaXR5ICovXHJcbiAgICAgICAgdGhpcy5Qcmlvcml0eV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZW55IGFjY2VzcyAqL1xyXG4gICAgICAgIHRoaXMuRGVueV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNldCB0cnVlIGlmIHlvdSB3YW50IHRvIHNwZWNpZnkgdGhlIFN1Ym5ldE1hc2tfaXAgaXRlbS4gKi9cclxuICAgICAgICB0aGlzLk1hc2tlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFN1Ym5ldCBtYXNrLCB2YWxpZCBvbmx5IGlmIE1hc2tlZF9ib29sID09IHRydWUgKi9cclxuICAgICAgICB0aGlzLlN1Ym5ldE1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQWM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuQWMgPSBWcG5BYztcclxuLyoqIFNvdXJjZSBJUCBBZGRyZXNzIExpbWl0IExpc3QgKi9cclxudmFyIFZwblJwY0FjTGlzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNBY0xpc3QnIGNsYXNzOiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0ICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNBY0xpc3QoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTb3VyY2UgSVAgQWRkcmVzcyBMaW1pdCBMaXN0ICovXHJcbiAgICAgICAgdGhpcy5BQ0xpc3QgPSBbXTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0FjTGlzdDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNBY0xpc3QgPSBWcG5ScGNBY0xpc3Q7XHJcbi8qKiBNZXNzYWdlICovXHJcbnZhciBWcG5ScGNNc2cgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTXNnJyBjbGFzczogTWVzc2FnZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjTXNnKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTWVzc2FnZSAoVW5pY29kZSBzdHJpbmdzIGFjY2VwdGFibGUpICovXHJcbiAgICAgICAgdGhpcy5Nc2dfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjTXNnO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY01zZyA9IFZwblJwY01zZztcclxuLyoqIEdldCAvIFNldCB0aGUgQXp1cmUgc3RhdGUgKi9cclxudmFyIFZwblJwY0F6dXJlU3RhdHVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0F6dXJlU3RhdHVzJyBjbGFzczogR2V0IC8gU2V0IHRoZSBBenVyZSBzdGF0ZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQXp1cmVTdGF0dXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFZQTiBBenVyZSBGdW5jdGlvbiBpcyBFbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5Jc0VuYWJsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIGNvbm5lY3Rpb24gdG8gVlBOIEF6dXJlIENsb3VkIFNlcnZlciBpcyBlc3RhYmxpc2hlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNDb25uZWN0ZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjQXp1cmVTdGF0dXM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjQXp1cmVTdGF0dXMgPSBWcG5ScGNBenVyZVN0YXR1cztcclxuLyoqIExvY2FsIEJyaWRnZSBzdXBwb3J0IGluZm9ybWF0aW9uICovXHJcbnZhciBWcG5ScGNCcmlkZ2VTdXBwb3J0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0JyaWRnZVN1cHBvcnQnIGNsYXNzOiBMb2NhbCBCcmlkZ2Ugc3VwcG9ydCBpbmZvcm1hdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQnJpZGdlU3VwcG9ydChpbml0KSB7XHJcbiAgICAgICAgLyoqIFdoZXRoZXIgdGhlIE9TIHN1cHBvcnRzIHRoZSBMb2NhbCBCcmlkZ2UgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLklzQnJpZGdlU3VwcG9ydGVkT3NfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFdpblBjYXAgaXMgbmVjZXNzYXJ5IHRvIGluc3RhbGwgKi9cclxuICAgICAgICB0aGlzLklzV2luUGNhcE5lZWRlZF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNCcmlkZ2VTdXBwb3J0O1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0JyaWRnZVN1cHBvcnQgPSBWcG5ScGNCcmlkZ2VTdXBwb3J0O1xyXG4vKiogR2V0IHRoZSBDQSBvZiBIVUIgKi9cclxudmFyIFZwblJwY0h1YkdldENBID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YkdldENBJyBjbGFzczogR2V0IHRoZSBDQSBvZiBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0h1YkdldENBKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIGtleSBpZCBvZiB0aGUgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLktleV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgWC41MDkgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjSHViR2V0Q0E7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViR2V0Q0EgPSBWcG5ScGNIdWJHZXRDQTtcclxuLyoqIENhcHMgaXRlbSBvZiB0aGUgVlBOIFNlcnZlciAqL1xyXG52YXIgVnBuQ2FwcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5DYXBzJyBjbGFzczogQ2FwcyBpdGVtIG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICBmdW5jdGlvbiBWcG5DYXBzKGluaXQpIHtcclxuICAgICAgICAvKiogTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ2Fwc05hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsdWUgKi9cclxuICAgICAgICB0aGlzLkNhcHNWYWx1ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZXNjcnB0aW9uICovXHJcbiAgICAgICAgdGhpcy5DYXBzRGVzY3JwdGlvbl91dGYgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQ2FwcztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5DYXBzID0gVnBuQ2FwcztcclxuLyoqIENhcHMgbGlzdCBvZiB0aGUgVlBOIFNlcnZlciAqL1xyXG52YXIgVnBuQ2Fwc2xpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuQ2Fwc2xpc3QnIGNsYXNzOiBDYXBzIGxpc3Qgb2YgdGhlIFZQTiBTZXJ2ZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkNhcHNsaXN0KGluaXQpIHtcclxuICAgICAgICAvKiogQ2FwcyBsaXN0IG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5DYXBzTGlzdCA9IFtdO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuQ2Fwc2xpc3Q7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuQ2Fwc2xpc3QgPSBWcG5DYXBzbGlzdDtcclxuLyoqIENvbmZpZyBvcGVyYXRpb24gKi9cclxudmFyIFZwblJwY0NvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNDb25maWcnIGNsYXNzOiBDb25maWcgb3BlcmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBGaWxlIG5hbWUgKHZhbGlkIG9ubHkgZm9yIHJldHVybmluZyBmcm9tIHRoZSBzZXJ2ZXIpICovXHJcbiAgICAgICAgdGhpcy5GaWxlTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBGaWxlIGRhdGEgKi9cclxuICAgICAgICB0aGlzLkZpbGVEYXRhX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0NvbmZpZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNDb25maWcgPSBWcG5ScGNDb25maWc7XHJcbi8qKiBDb25uZWN0aW9uIGluZm9ybWF0aW9uICovXHJcbnZhciBWcG5ScGNDb25uZWN0aW9uSW5mbyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNDb25uZWN0aW9uSW5mbycgY2xhc3M6IENvbm5lY3Rpb24gaW5mb3JtYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Nvbm5lY3Rpb25JbmZvKGluaXQpIHtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFR5cGUgKi9cclxuICAgICAgICB0aGlzLlR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBJUCBhZGRyZXNzICovXHJcbiAgICAgICAgdGhpcy5JcF9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5Qb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIENvbm5lY3RlZCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogU2VydmVyIHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyU3RyX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNlcnZlciB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJWZXJfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIGJ1aWxkIG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50U3RyX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRWZXJfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IGJ1aWxkIG51bWJlciAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50QnVpbGRfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0Nvbm5lY3Rpb25JbmZvO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0Nvbm5lY3Rpb25JbmZvID0gVnBuUnBjQ29ubmVjdGlvbkluZm87XHJcbi8qKiBQcm94eSB0eXBlICovXHJcbnZhciBWcG5ScGNQcm94eVR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjUHJveHlUeXBlKSB7XHJcbiAgICAvKiogRGlyZWN0IFRDUCBjb25uZWN0aW9uICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiRGlyZWN0XCJdID0gMF0gPSBcIkRpcmVjdFwiO1xyXG4gICAgLyoqIENvbm5lY3Rpb24gdmlhIEhUVFAgcHJveHkgc2VydmVyICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiSFRUUFwiXSA9IDFdID0gXCJIVFRQXCI7XHJcbiAgICAvKiogQ29ubmVjdGlvbiB2aWEgU09DS1MgcHJveHkgc2VydmVyICovXHJcbiAgICBWcG5ScGNQcm94eVR5cGVbVnBuUnBjUHJveHlUeXBlW1wiU09DS1NcIl0gPSAyXSA9IFwiU09DS1NcIjtcclxufSkoVnBuUnBjUHJveHlUeXBlID0gZXhwb3J0cy5WcG5ScGNQcm94eVR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjUHJveHlUeXBlID0ge30pKTtcclxuLyoqIFRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgREROUyAqL1xyXG52YXIgVnBuRERuc0NsaWVudFN0YXR1cyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ERG5zQ2xpZW50U3RhdHVzJyBjbGFzczogVGhlIGN1cnJlbnQgc3RhdHVzIG9mIHRoZSBERE5TICovXHJcbiAgICBmdW5jdGlvbiBWcG5ERG5zQ2xpZW50U3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogTGFzdCBlcnJvciBjb2RlIChJUHY0KSAqL1xyXG4gICAgICAgIHRoaXMuRXJyX0lQdjRfdTMyID0gMDtcclxuICAgICAgICAvKiogTGFzdCBlcnJvciBzdHJpbmcgKElQdjQpICovXHJcbiAgICAgICAgdGhpcy5FcnJTdHJfSVB2NF91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIGNvZGUgKElQdjYpICovXHJcbiAgICAgICAgdGhpcy5FcnJfSVB2Nl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIHN0cmluZyAoSVB2NikgKi9cclxuICAgICAgICB0aGlzLkVyclN0cl9JUHY2X3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEN1cnJlbnQgREROUyBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRIb3N0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDdXJyZW50IEZRRE4gb2YgdGhlIERETlMgaG9zdG5hbWUgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRGcWRuX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIERETlMgc3VmZml4ICovXHJcbiAgICAgICAgdGhpcy5EbnNTdWZmaXhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ3VycmVudCBJUHY0IGFkZHJlc3Mgb2YgdGhlIFZQTiBTZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRJUHY0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIEN1cnJlbnQgSVB2NiBhZGRyZXNzIG9mIHRoZSBWUE4gU2VydmVyICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50SVB2Nl9zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuRERuc0NsaWVudFN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ERG5zQ2xpZW50U3RhdHVzID0gVnBuRERuc0NsaWVudFN0YXR1cztcclxuLyoqIEludGVybmV0IGNvbm5lY3Rpb24gc2V0dGluZ3MgKi9cclxudmFyIFZwbkludGVybmV0U2V0dGluZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5JbnRlcm5ldFNldHRpbmcnIGNsYXNzOiBJbnRlcm5ldCBjb25uZWN0aW9uIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5JbnRlcm5ldFNldHRpbmcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHByb3h5IHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByb3h5IHNlcnZlciBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlByb3h5SG9zdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUHJveHkgc2VydmVyIHBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5Qcm94eVBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogUHJveHkgc2VydmVyIHVzZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUHJveHlVc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBQcm94eSBzZXJ2ZXIgcGFzc3dvcmQgKi9cclxuICAgICAgICB0aGlzLlByb3h5UGFzc3dvcmRfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwbkludGVybmV0U2V0dGluZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5JbnRlcm5ldFNldHRpbmcgPSBWcG5JbnRlcm5ldFNldHRpbmc7XHJcbi8qKiBBZG1pbmlzdHJhdGlvbiBvcHRpb25zICovXHJcbnZhciBWcG5BZG1pbk9wdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5BZG1pbk9wdGlvbicgY2xhc3M6IEFkbWluaXN0cmF0aW9uIG9wdGlvbnMgKi9cclxuICAgIGZ1bmN0aW9uIFZwbkFkbWluT3B0aW9uKGluaXQpIHtcclxuICAgICAgICAvKiogTmFtZSAqL1xyXG4gICAgICAgIHRoaXMuTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEYXRhICovXHJcbiAgICAgICAgdGhpcy5WYWx1ZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBEZXNjcnB0aW9uICovXHJcbiAgICAgICAgdGhpcy5EZXNjcnB0aW9uX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5BZG1pbk9wdGlvbjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5BZG1pbk9wdGlvbiA9IFZwbkFkbWluT3B0aW9uO1xyXG4vKiogQWRtaW5pc3RyYXRpb24gb3B0aW9ucyBsaXN0ICovXHJcbnZhciBWcG5ScGNBZG1pbk9wdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNBZG1pbk9wdGlvbicgY2xhc3M6IEFkbWluaXN0cmF0aW9uIG9wdGlvbnMgbGlzdCAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjQWRtaW5PcHRpb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBWaXJ0dWFsIEhVQiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIExpc3QgZGF0YSAqL1xyXG4gICAgICAgIHRoaXMuQWRtaW5PcHRpb25MaXN0ID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNBZG1pbk9wdGlvbjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNBZG1pbk9wdGlvbiA9IFZwblJwY0FkbWluT3B0aW9uO1xyXG4vKiogQ29ubmVjdGlvbiBzdGF0ZSB0byB0aGUgY29udHJvbGxlciAqL1xyXG52YXIgVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMnIGNsYXNzOiBDb25uZWN0aW9uIHN0YXRlIHRvIHRoZSBjb250cm9sbGVyICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNGYXJtQ29ubmVjdGlvblN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogUG9ydCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogT25saW5lIHN0YXRlICovXHJcbiAgICAgICAgdGhpcy5PbmxpbmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBMYXN0IGVycm9yIGNvZGUgKi9cclxuICAgICAgICB0aGlzLkxhc3RFcnJvcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHN0YXJ0IHRpbWUgKi9cclxuICAgICAgICB0aGlzLlN0YXJ0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogRmlyc3QgY29ubmVjdGlvbiB0aW1lICovXHJcbiAgICAgICAgdGhpcy5GaXJzdENvbm5lY3RlZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHRpbWUgb2YgdGhpcyB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50Q29ubmVjdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiByZXRyaWVzICovXHJcbiAgICAgICAgdGhpcy5OdW1UcnlfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb24gY291bnQgKi9cclxuICAgICAgICB0aGlzLk51bUNvbm5lY3RlZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIGZhaWx1cmUgY291bnQgKi9cclxuICAgICAgICB0aGlzLk51bUZhaWxlZF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXM7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybUNvbm5lY3Rpb25TdGF0dXMgPSBWcG5ScGNGYXJtQ29ubmVjdGlvblN0YXR1cztcclxuLyoqIEhVQiBpdGVtIG9mIGVhY2ggZmFybSBtZW1iZXIgKi9cclxudmFyIFZwblJwY0Zhcm1IdWIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybUh1YicgY2xhc3M6IEhVQiBpdGVtIG9mIGVhY2ggZmFybSBtZW1iZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Zhcm1IdWIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBEeW5hbWljIEhVQiAqL1xyXG4gICAgICAgIHRoaXMuRHluYW1pY0h1Yl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNGYXJtSHViO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0Zhcm1IdWIgPSBWcG5ScGNGYXJtSHViO1xyXG4vKiogU2VydmVyIGZhcm0gbWVtYmVyIGluZm9ybWF0aW9uIGFjcXVpc2l0aW9uICovXHJcbnZhciBWcG5ScGNGYXJtSW5mbyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNGYXJtSW5mbycgY2xhc3M6IFNlcnZlciBmYXJtIG1lbWJlciBpbmZvcm1hdGlvbiBhY3F1aXNpdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjRmFybUluZm8oaW5pdCkge1xyXG4gICAgICAgIC8qKiBJRCAqL1xyXG4gICAgICAgIHRoaXMuSWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGZsYWcgaWYgdGhlIHNlcnZlciBpcyBDbHVzdGVyIENvbnRyb2xsZXIgKGZhbHNlOiBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzKSAqL1xyXG4gICAgICAgIHRoaXMuQ29udHJvbGxlcl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gRXN0YWJsaXNoZWQgVGltZSAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogSG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBQb2ludCAqL1xyXG4gICAgICAgIHRoaXMuUG9pbnRfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFB1YmxpYyBQb3J0cyAqL1xyXG4gICAgICAgIHRoaXMuTnVtUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBQdWJsaWMgUG9ydHMgKi9cclxuICAgICAgICB0aGlzLlBvcnRzX3UzMiA9IFtdO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgZmFybSBIVUIgKi9cclxuICAgICAgICB0aGlzLk51bUZhcm1IdWJfdTMyID0gMDtcclxuICAgICAgICAvKiogVGhlIGhvc3RlZCBWaXJ0dWFsIEh1YiBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5IdWJzTGlzdCA9IFtdO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgaG9zdGVkIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogUGVyZm9ybWFuY2UgU3RhbmRhcmQgUmF0aW8gKi9cclxuICAgICAgICB0aGlzLldlaWdodF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjRmFybUluZm87XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybUluZm8gPSBWcG5ScGNGYXJtSW5mbztcclxuLyoqIFNlcnZlciBmYXJtIGNvbmZpZ3VyYXRpb24gKi9cclxudmFyIFZwblJwY0Zhcm0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjRmFybScgY2xhc3M6IFNlcnZlciBmYXJtIGNvbmZpZ3VyYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0Zhcm0oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUeXBlIG9mIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGZvciBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzLiBOdW1iZXIgb2YgdGhlIFBvcnRzX3UzMiBlbGVtZW50LiAqL1xyXG4gICAgICAgIHRoaXMuTnVtUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBWYWxpZCBvbmx5IGZvciBDbHVzdGVyIE1lbWJlciBzZXJ2ZXJzLiBTcGVjaWZ5IHRoZSBsaXN0IG9mIHB1YmxpYyBwb3J0IG51bWJlcnMgb24gdGhpcyBzZXJ2ZXIuIFRoZSBsaXN0IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgcHVibGljIHBvcnQgbnVtYmVyIHNldCwgYW5kIGl0IGlzIGFsc28gcG9zc2libGUgdG8gc2V0IG11bHRpcGxlIHB1YmxpYyBwb3J0IG51bWJlcnMuICovXHJcbiAgICAgICAgdGhpcy5Qb3J0c191MzIgPSBbXTtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgcHVibGljIElQIGFkZHJlc3Mgb2YgdGhpcyBzZXJ2ZXIuIElmIHlvdSB3aXNoIHRvIGxlYXZlIHB1YmxpYyBJUCBhZGRyZXNzIHVuc3BlY2lmaWVkLCBzcGVjaWZ5IHRoZSBlbXB0eSBzdHJpbmcuIFdoZW4gYSBwdWJsaWMgSVAgYWRkcmVzcyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgSVAgYWRkcmVzcyBvZiB0aGUgbmV0d29yayBpbnRlcmZhY2UgdXNlZCB3aGVuIGNvbm5lY3RpbmcgdG8gdGhlIGNsdXN0ZXIgY29udHJvbGxlciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgdXNlZC4gKi9cclxuICAgICAgICB0aGlzLlB1YmxpY0lwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgaG9zdCBuYW1lIG9yIElQIGFkZHJlc3Mgb2YgdGhlIGRlc3RpbmF0aW9uIGNsdXN0ZXIgY29udHJvbGxlci4gKi9cclxuICAgICAgICB0aGlzLkNvbnRyb2xsZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgZm9yIENsdXN0ZXIgTWVtYmVyIHNlcnZlcnMuIFNwZWNpZnkgdGhlIFRDUCBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gY2x1c3RlciBjb250cm9sbGVyLiAqL1xyXG4gICAgICAgIHRoaXMuQ29udHJvbGxlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogVmFsaWQgb25seSBmb3IgQ2x1c3RlciBNZW1iZXIgc2VydmVycy4gU3BlY2lmeSB0aGUgcGFzc3dvcmQgcmVxdWlyZWQgdG8gY29ubmVjdCB0byB0aGUgZGVzdGluYXRpb24gY29udHJvbGxlci4gSXQgbmVlZHMgdG8gYmUgdGhlIHNhbWUgYXMgYW4gYWRtaW5pc3RyYXRvciBwYXNzd29yZCBvbiB0aGUgZGVzdGluYXRpb24gY29udHJvbGxlci4gKi9cclxuICAgICAgICB0aGlzLk1lbWJlclBhc3N3b3JkUGxhaW50ZXh0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFRoaXMgc2V0cyBhIHZhbHVlIGZvciB0aGUgcGVyZm9ybWFuY2Ugc3RhbmRhcmQgcmF0aW8gb2YgdGhpcyBWUE4gU2VydmVyLiBUaGlzIGlzIHRoZSBzdGFuZGFyZCB2YWx1ZSBmb3Igd2hlbiBsb2FkIGJhbGFuY2luZyBpcyBwZXJmb3JtZWQgaW4gdGhlIGNsdXN0ZXIuIEZvciBleGFtcGxlLCBtYWtpbmcgb25seSBvbmUgbWFjaGluZSAyMDAgd2hpbGUgdGhlIG90aGVyIG1lbWJlcnMgaGF2ZSBhIHN0YXR1cyBvZiAxMDAsIHdpbGwgcmVndWxhdGUgdGhhdCBtYWNoaW5lIHRvIHJlY2VpdmUgdHdpY2UgYXMgbWFueSBjb25uZWN0aW9ucyBhcyB0aGUgb3RoZXIgbWVtYmVycy4gU3BlY2lmeSAxIG9yIGhpZ2hlciBmb3IgdGhlIHZhbHVlLiBJZiB0aGlzIHBhcmFtZXRlciBpcyBsZWZ0IHVuc3BlY2lmaWVkLCAxMDAgd2lsbCBiZSB1c2VkLiAqL1xyXG4gICAgICAgIHRoaXMuV2VpZ2h0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFZhbGlkIG9ubHkgZm9yIENsdXN0ZXIgQ29udHJvbGxlciBzZXJ2ZXIuIEJ5IHNwZWNpZnlpbmcgdHJ1ZSwgdGhlIFZQTiBTZXJ2ZXIgd2lsbCBvcGVyYXRlIG9ubHkgYXMgYSBjb250cm9sbGVyIG9uIHRoZSBjbHVzdGVyIGFuZCBpdCB3aWxsIGFsd2F5cyBkaXN0cmlidXRlIGdlbmVyYWwgVlBOIENsaWVudCBjb25uZWN0aW9ucyB0byBtZW1iZXJzIG90aGVyIHRoYW4gaXRzZWxmLiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gaGlnaC1sb2FkIGVudmlyb25tZW50cy4gKi9cclxuICAgICAgICB0aGlzLkNvbnRyb2xsZXJPbmx5X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0Zhcm07XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjRmFybSA9IFZwblJwY0Zhcm07XHJcbi8qKiBMb2cgc3dpdGNoIHR5cGUgKi9cclxudmFyIFZwblJwY0xvZ1N3aXRjaFR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjTG9nU3dpdGNoVHlwZSkge1xyXG4gICAgLyoqIE5vIHN3aXRjaGluZyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiTm9cIl0gPSAwXSA9IFwiTm9cIjtcclxuICAgIC8qKiBTZWNvbmRseSBiYXNpcyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiU2Vjb25kXCJdID0gMV0gPSBcIlNlY29uZFwiO1xyXG4gICAgLyoqIE1pbnV0ZWx5IGJhc2lzICovXHJcbiAgICBWcG5ScGNMb2dTd2l0Y2hUeXBlW1ZwblJwY0xvZ1N3aXRjaFR5cGVbXCJNaW51dGVcIl0gPSAyXSA9IFwiTWludXRlXCI7XHJcbiAgICAvKiogSG91cmx5IGJhc2lzICovXHJcbiAgICBWcG5ScGNMb2dTd2l0Y2hUeXBlW1ZwblJwY0xvZ1N3aXRjaFR5cGVbXCJIb3VyXCJdID0gM10gPSBcIkhvdXJcIjtcclxuICAgIC8qKiBEYWlseSBiYXNpcyAqL1xyXG4gICAgVnBuUnBjTG9nU3dpdGNoVHlwZVtWcG5ScGNMb2dTd2l0Y2hUeXBlW1wiRGF5XCJdID0gNF0gPSBcIkRheVwiO1xyXG4gICAgLyoqIE1vbnRobHkgYmFzaXMgKi9cclxuICAgIFZwblJwY0xvZ1N3aXRjaFR5cGVbVnBuUnBjTG9nU3dpdGNoVHlwZVtcIk1vbnRoXCJdID0gNV0gPSBcIk1vbnRoXCI7XHJcbn0pKFZwblJwY0xvZ1N3aXRjaFR5cGUgPSBleHBvcnRzLlZwblJwY0xvZ1N3aXRjaFR5cGUgfHwgKGV4cG9ydHMuVnBuUnBjTG9nU3dpdGNoVHlwZSA9IHt9KSk7XHJcbi8qKiBQYWNrZXQgbG9nIHNldHRpbmdzICovXHJcbnZhciBWcG5ScGNQYWNrZXRMb2dTZXR0aW5nO1xyXG4oZnVuY3Rpb24gKFZwblJwY1BhY2tldExvZ1NldHRpbmcpIHtcclxuICAgIC8qKiBOb3Qgc2F2ZSAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tWcG5ScGNQYWNrZXRMb2dTZXR0aW5nW1wiTm9uZVwiXSA9IDBdID0gXCJOb25lXCI7XHJcbiAgICAvKiogT25seSBoZWFkZXIgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdbVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tcIkhlYWRlclwiXSA9IDFdID0gXCJIZWFkZXJcIjtcclxuICAgIC8qKiBBbGwgcGF5bG9hZHMgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdbVnBuUnBjUGFja2V0TG9nU2V0dGluZ1tcIkFsbFwiXSA9IDJdID0gXCJBbGxcIjtcclxufSkoVnBuUnBjUGFja2V0TG9nU2V0dGluZyA9IGV4cG9ydHMuVnBuUnBjUGFja2V0TG9nU2V0dGluZyB8fCAoZXhwb3J0cy5WcG5ScGNQYWNrZXRMb2dTZXR0aW5nID0ge30pKTtcclxuLyoqIFBhY2tldCBsb2cgc2V0dGluZ3MgYXJyYXkgaW5kZXggKi9cclxudmFyIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleDtcclxuKGZ1bmN0aW9uIChWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXgpIHtcclxuICAgIC8qKiBUQ1AgY29ubmVjdGlvbiBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJUY3BDb25uZWN0aW9uXCJdID0gMF0gPSBcIlRjcENvbm5lY3Rpb25cIjtcclxuICAgIC8qKiBUQ1AgcGFja2V0IGxvZyAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1ZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtcIlRjcEFsbFwiXSA9IDFdID0gXCJUY3BBbGxcIjtcclxuICAgIC8qKiBESENQIExvZyAqL1xyXG4gICAgVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1ZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtcIkRoY3BcIl0gPSAyXSA9IFwiRGhjcFwiO1xyXG4gICAgLyoqIFVEUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJVZHBcIl0gPSAzXSA9IFwiVWRwXCI7XHJcbiAgICAvKiogSUNNUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJJY21wXCJdID0gNF0gPSBcIkljbXBcIjtcclxuICAgIC8qKiBJUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJJcFwiXSA9IDVdID0gXCJJcFwiO1xyXG4gICAgLyoqIEFSUCBsb2cgKi9cclxuICAgIFZwblJwY1BhY2tldExvZ1NldHRpbmdJbmRleFtWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbXCJBcnBcIl0gPSA2XSA9IFwiQXJwXCI7XHJcbiAgICAvKiogRXRoZXJuZXQgbG9nICovXHJcbiAgICBWcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXhbVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4W1wiRXRoZXJuZXRcIl0gPSA3XSA9IFwiRXRoZXJuZXRcIjtcclxufSkoVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4ID0gZXhwb3J0cy5WcG5ScGNQYWNrZXRMb2dTZXR0aW5nSW5kZXggfHwgKGV4cG9ydHMuVnBuUnBjUGFja2V0TG9nU2V0dGluZ0luZGV4ID0ge30pKTtcclxuLyoqIEhVQiBsb2cgc2V0dGluZ3MgKi9cclxudmFyIFZwblJwY0h1YkxvZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNIdWJMb2cnIGNsYXNzOiBIVUIgbG9nIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJMb2coaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB0byBlbmFibGUgLyBkaXNhYmxlIHNhdmluZyB0aGUgc2VjdXJpdHkgbG9nICovXHJcbiAgICAgICAgdGhpcy5TYXZlU2VjdXJpdHlMb2dfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBUaGUgbG9nIGZpbGVuYW1lIHN3aXRjaGluZyBzZXR0aW5nIG9mIHRoZSBzZWN1cml0eSBsb2cgKi9cclxuICAgICAgICB0aGlzLlNlY3VyaXR5TG9nU3dpdGNoVHlwZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB0byBlbmFibGUgLyBkaXNhYmxlIHNhdmluZyB0aGUgc2VjdXJpdHkgbG9nICovXHJcbiAgICAgICAgdGhpcy5TYXZlUGFja2V0TG9nX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGxvZyBmaWxlbmFtZSBzd2l0Y2hpbmcgc2V0dGluZ3Mgb2YgdGhlIHBhY2tldCBsb2dzICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRMb2dTd2l0Y2hUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHNhdmUgY29udGVudHMgb2YgdGhlIHBhY2tldCBsb2dzICh1aW50ICogMTYgYXJyYXkpLiBUaGUgaW5kZXggbnVtYmVyczogVGNwQ29ubmVjdGlvbiA9IDAsIFRjcEFsbCA9IDEsIERIQ1AgPSAyLCBVRFAgPSAzLCBJQ01QID0gNCwgSVAgPSA1LCBBUlAgPSA2LCBFdGhlcm5ldCA9IDcuICovXHJcbiAgICAgICAgdGhpcy5QYWNrZXRMb2dDb25maWdfdTMyID0gW107XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNIdWJMb2c7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjSHViTG9nID0gVnBuUnBjSHViTG9nO1xyXG4vKiogUkFESVVTIHNlcnZlciBvcHRpb25zICovXHJcbnZhciBWcG5ScGNSYWRpdXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjUmFkaXVzJyBjbGFzczogUkFESVVTIHNlcnZlciBvcHRpb25zICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNSYWRpdXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSQURJVVMgc2VydmVyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1NlcnZlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogUkFESVVTIHBvcnQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5SYWRpdXNQb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlY3JldCBrZXkgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1NlY3JldF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSYWRpdXMgcmV0cnkgaW50ZXJ2YWwgKi9cclxuICAgICAgICB0aGlzLlJhZGl1c1JldHJ5SW50ZXJ2YWxfdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1JhZGl1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNSYWRpdXMgPSBWcG5ScGNSYWRpdXM7XHJcbi8qKiBHZXQgdGhlIHN0YXRlIEhVQiAqL1xyXG52YXIgVnBuUnBjSHViU3RhdHVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0h1YlN0YXR1cycgY2xhc3M6IEdldCB0aGUgc3RhdGUgSFVCICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNIdWJTdGF0dXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPbmxpbmUgKi9cclxuICAgICAgICB0aGlzLk9ubGluZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFR5cGUgb2YgSFVCICovXHJcbiAgICAgICAgdGhpcy5IdWJUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHNlc3Npb25zIChjbGllbnQgbW9kZSkgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zQ2xpZW50X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBzZXNzaW9ucyAoYnJpZGdlIG1vZGUpICovXHJcbiAgICAgICAgdGhpcy5OdW1TZXNzaW9uc0JyaWRnZV91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgQWNjZXNzIGxpc3QgZW50cmllcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtQWNjZXNzTGlzdHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHVzZXJzICovXHJcbiAgICAgICAgdGhpcy5OdW1Vc2Vyc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgZ3JvdXBzICovXHJcbiAgICAgICAgdGhpcy5OdW1Hcm91cHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIE1BQyB0YWJsZSBlbnRyaWVzICovXHJcbiAgICAgICAgdGhpcy5OdW1NYWNUYWJsZXNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIElQIHRhYmxlIGVudHJpZXMgKi9cclxuICAgICAgICB0aGlzLk51bUlwVGFibGVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBjb3VudCAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoUmVjdikgKi9cclxuICAgICAgICB0aGlzW1wiUmVjdi5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGJyb2FkY2FzdCBwYWNrZXRzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLkJyb2FkY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIEJyb2FkY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLlVuaWNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBVbmljYXN0IGJ5dGVzIChTZW5kKSAqL1xyXG4gICAgICAgIHRoaXNbXCJTZW5kLlVuaWNhc3RDb3VudF91NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIFNlY3VyZU5BVCBpcyBlbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5TZWN1cmVOQVRFbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogTGFzdCBjb21tdW5pY2F0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkxhc3RDb21tVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIExhc3QgbG9naW4gZGF0ZSBhbmQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuTGFzdExvZ2luVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENyZWF0aW9uIGRhdGUgYW5kIHRpbWUgKi9cclxuICAgICAgICB0aGlzLkNyZWF0ZWRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvZ2lucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtTG9naW5fdTMyID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY0h1YlN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNIdWJTdGF0dXMgPSBWcG5ScGNIdWJTdGF0dXM7XHJcbi8qKiBMaXN0IG9mIHNlcnZpY2VzIHByb3ZpZGVkIGJ5IElQc2VjIHNlcnZlciAqL1xyXG52YXIgVnBuSVBzZWNTZXJ2aWNlcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5JUHNlY1NlcnZpY2VzJyBjbGFzczogTGlzdCBvZiBzZXJ2aWNlcyBwcm92aWRlZCBieSBJUHNlYyBzZXJ2ZXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwbklQc2VjU2VydmljZXMoaW5pdCkge1xyXG4gICAgICAgIC8qKiBFbmFibGUgb3IgRGlzYWJsZSB0aGUgTDJUUCBTZXJ2ZXIgRnVuY3Rpb24gKFJhdyBMMlRQIHdpdGggTm8gRW5jcnlwdGlvbnMpLiBUbyBhY2NlcHQgc3BlY2lhbCBWUE4gY2xpZW50cywgZW5hYmxlIHRoaXMgb3B0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9SYXdfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBFbmFibGUgb3IgRGlzYWJsZSB0aGUgTDJUUCBvdmVyIElQc2VjIFNlcnZlciBGdW5jdGlvbi4gVG8gYWNjZXB0IFZQTiBjb25uZWN0aW9ucyBmcm9tIGlQaG9uZSwgaVBhZCwgQW5kcm9pZCwgV2luZG93cyBvciBNYWMgT1MgWCwgZW5hYmxlIHRoaXMgb3B0aW9uLiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9JUHNlY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIEVuYWJsZSBvciBEaXNhYmxlIHRoZSBFdGhlcklQIC8gTDJUUHYzIG92ZXIgSVBzZWMgU2VydmVyIEZ1bmN0aW9uIChmb3Igc2l0ZS10by1zaXRlIFZQTiBTZXJ2ZXIgZnVuY3Rpb24pLiBSb3V0ZXIgUHJvZHVjdHMgd2hpY2ggYXJlIGNvbXBhdGlibGUgd2l0aCBFdGhlcklQIG92ZXIgSVBzZWMgY2FuIGNvbm5lY3QgdG8gVmlydHVhbCBIdWJzIG9uIHRoZSBWUE4gU2VydmVyIGFuZCBlc3RhYmxpc2ggTGF5ZXItMiAoRXRoZXJuZXQpIEJyaWRnaW5nLiAqL1xyXG4gICAgICAgIHRoaXMuRXRoZXJJUF9JUHNlY19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQc2VjIFByZS1TaGFyZWQgS2V5LiBBbiBJUHNlYyBQcmUtU2hhcmVkIEtleSBpcyBhbHNvIGNhbGxlZCBhcyBcIlBTS1wiIG9yIFwic2VjcmV0XCIuIFNwZWNpZnkgaXQgZXF1YWwgb3IgbGVzcyB0aGFuIDggbGV0dGVycywgYW5kIGRpc3RyaWJ1dGUgaXQgdG8gZXZlcnkgdXNlcnMgd2hvIHdpbGwgY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4gUGxlYXNlIG5vdGU6IEdvb2dsZSBBbmRyb2lkIDQuMCBoYXMgYSBidWcgd2hpY2ggYSBQcmUtU2hhcmVkIEtleSB3aXRoIDEwIG9yIG1vcmUgbGV0dGVycyBjYXVzZXMgYSB1bmV4cGVjdGVkIGJlaGF2aW9yLiBGb3IgdGhhdCByZWFzb24sIHRoZSBsZXR0ZXJzIG9mIGEgUHJlLVNoYXJlZCBLZXkgc2hvdWxkIGJlIDkgb3IgbGVzcyBjaGFyYWN0ZXJzLiAqL1xyXG4gICAgICAgIHRoaXMuSVBzZWNfU2VjcmV0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGRlZmF1bHQgVmlydHVhbCBIVUIgaW4gYSBjYXNlIG9mIG9taXR0aW5nIHRoZSBuYW1lIG9mIEhVQiBvbiB0aGUgVXNlcm5hbWUuIFVzZXJzIHNob3VsZCBzcGVjaWZ5IHRoZWlyIHVzZXJuYW1lIHN1Y2ggYXMgXCJVc2VybmFtZUBUYXJnZXQgVmlydHVhbCBIVUIgTmFtZVwiIHRvIGNvbm5lY3QgdGhpcyBMMlRQIFNlcnZlci4gSWYgdGhlIGRlc2lnbmF0aW9uIG9mIHRoZSBWaXJ0dWFsIEh1YiBpcyBvbWl0dGVkLCB0aGUgYWJvdmUgSFVCIHdpbGwgYmUgdXNlZCBhcyB0aGUgdGFyZ2V0LiAqL1xyXG4gICAgICAgIHRoaXMuTDJUUF9EZWZhdWx0SHViX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5JUHNlY1NlcnZpY2VzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwbklQc2VjU2VydmljZXMgPSBWcG5JUHNlY1NlcnZpY2VzO1xyXG4vKiogS2VlcCBhbGl2ZSBwcm90b2NvbCAqL1xyXG52YXIgVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2w7XHJcbihmdW5jdGlvbiAoVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2wpIHtcclxuICAgIC8qKiBUQ1AgKi9cclxuICAgIFZwblJwY0tlZXBBbGl2ZVByb3RvY29sW1ZwblJwY0tlZXBBbGl2ZVByb3RvY29sW1wiVENQXCJdID0gMF0gPSBcIlRDUFwiO1xyXG4gICAgLyoqIFVEUCAqL1xyXG4gICAgVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2xbVnBuUnBjS2VlcEFsaXZlUHJvdG9jb2xbXCJVRFBcIl0gPSAxXSA9IFwiVURQXCI7XHJcbn0pKFZwblJwY0tlZXBBbGl2ZVByb3RvY29sID0gZXhwb3J0cy5WcG5ScGNLZWVwQWxpdmVQcm90b2NvbCB8fCAoZXhwb3J0cy5WcG5ScGNLZWVwQWxpdmVQcm90b2NvbCA9IHt9KSk7XHJcbi8qKiBLZWVwIEFsaXZlIHNldHRpbmdzICovXHJcbnZhciBWcG5ScGNLZWVwID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY0tlZXAnIGNsYXNzOiBLZWVwIEFsaXZlIHNldHRpbmdzICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNLZWVwKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIGtlZXAtYWxpdmUgdG8gdGhlIEludGVybmV0ICovXHJcbiAgICAgICAgdGhpcy5Vc2VLZWVwQ29ubmVjdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGhvc3QgbmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBkZXN0aW5hdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RIb3N0X3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBkZXN0aW5hdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RQb3J0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFByb3RvY29sIHR5cGUgKi9cclxuICAgICAgICB0aGlzLktlZXBDb25uZWN0UHJvdG9jb2xfdTMyID0gMDtcclxuICAgICAgICAvKiogSW50ZXJ2YWwgQmV0d2VlbiBQYWNrZXRzIFNlbmRzIChTZWNvbmRzKSAqL1xyXG4gICAgICAgIHRoaXMuS2VlcENvbm5lY3RJbnRlcnZhbF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjS2VlcDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNLZWVwID0gVnBuUnBjS2VlcDtcclxuLyoqIFN0YXRlIG9mIHRoZSBjbGllbnQgc2Vzc2lvbiAqL1xyXG52YXIgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cztcclxuKGZ1bmN0aW9uIChWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzKSB7XHJcbiAgICAvKiogQ29ubmVjdGluZyAqL1xyXG4gICAgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1wiQ29ubmVjdGluZ1wiXSA9IDBdID0gXCJDb25uZWN0aW5nXCI7XHJcbiAgICAvKiogTmVnb3RpYXRpbmcgKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIk5lZ290aWF0aW9uXCJdID0gMV0gPSBcIk5lZ290aWF0aW9uXCI7XHJcbiAgICAvKiogRHVyaW5nIHVzZXIgYXV0aGVudGljYXRpb24gKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIkF1dGhcIl0gPSAyXSA9IFwiQXV0aFwiO1xyXG4gICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGUgKi9cclxuICAgIFZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tcIkVzdGFibGlzaGVkXCJdID0gM10gPSBcIkVzdGFibGlzaGVkXCI7XHJcbiAgICAvKiogV2FpdCB0byByZXRyeSAqL1xyXG4gICAgVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1c1tWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1wiUmV0cnlcIl0gPSA0XSA9IFwiUmV0cnlcIjtcclxuICAgIC8qKiBJZGxlIHN0YXRlICovXHJcbiAgICBWcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzW1ZwblJwY0NsaWVudFNlc3Npb25TdGF0dXNbXCJJZGxlXCJdID0gNV0gPSBcIklkbGVcIjtcclxufSkoVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cyA9IGV4cG9ydHMuVnBuUnBjQ2xpZW50U2Vzc2lvblN0YXR1cyB8fCAoZXhwb3J0cy5WcG5ScGNDbGllbnRTZXNzaW9uU3RhdHVzID0ge30pKTtcclxuLyoqIEdldCB0aGUgbGluayBzdGF0ZSAqL1xyXG52YXIgVnBuUnBjTGlua1N0YXR1cyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNMaW5rU3RhdHVzJyBjbGFzczogR2V0IHRoZSBsaW5rIHN0YXRlICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNMaW5rU3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIFZpcnR1YWwgSHViIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfRXhfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0aGUgY2FzY2FkZSBjb25uZWN0aW9uIGlzIGVuYWJsZWQgKi9cclxuICAgICAgICB0aGlzLkFjdGl2ZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiBpcyBlc3RhYmxpc2hlZCAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIHNlc3Npb24gc3RhdHVzICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFRoZSBkZXN0aW5hdGlvbiBWUE4gc2VydmVyIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIHBvcnQgbnVtYmVyIG9mIHRoZSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBidWlsZCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclByb2R1Y3RCdWlsZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIncyBYLjUwOSBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyWF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENsaWVudCBjZXJ0aWZpY2F0ZSAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50WF9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gc3RhcnQgdGltZSAqL1xyXG4gICAgICAgIHRoaXMuU3RhcnRUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBjb21wbGV0aW9uIHRpbWUgb2YgdGhlIGZpcnN0IGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkZpcnN0Q29ubmVjdGlvbkVzdGFibGlzaWVkVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGlvbiB0aW1lIG9mIHRoaXMgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuQ3VycmVudENvbm5lY3Rpb25Fc3RhYmxpc2hUaW1lX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGNvbm5lY3Rpb25zIGhhdmUgYmVlbiBlc3RhYmxpc2hlZCBzbyBmYXIgKi9cclxuICAgICAgICB0aGlzLk51bUNvbm5lY3Rpb25zRWF0YWJsaXNoZWRfdTMyID0gMDtcclxuICAgICAgICAvKiogSGFsZi1jb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5IYWxmQ29ubmVjdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZvSVAgLyBRb1MgKi9cclxuICAgICAgICB0aGlzLlFvU19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE1heGltdW0gbnVtYmVyIG9mIHRoZSB1bmRlcmx5aW5nIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTWF4VGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGN1cnJlbnQgdW5kZXJseWluZyBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiB1bmRlcmx5aW5nIGluYm91bmQgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc1VwbG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdW5kZXJseWluZyBvdXRib3VuZCBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVRjcENvbm5lY3Rpb25zRG93bmxvYWRfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNlIG9mIGVuY3J5cHRpb24gKi9cclxuICAgICAgICB0aGlzLlVzZUVuY3J5cHRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDaXBoZXIgYWxnb3JpdGhtIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNpcGhlck5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlIG9mIGNvbXByZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VDb21wcmVzc19ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFRoZSBmbGFnIHdoZXRoZXIgdGhpcyBpcyBhIFItVURQIHNlc3Npb24gKi9cclxuICAgICAgICB0aGlzLklzUlVEUFNlc3Npb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBVbmRlcmx5aW5nIHBoeXNpY2FsIGNvbW11bmljYXRpb24gcHJvdG9jb2wgKi9cclxuICAgICAgICB0aGlzLlVuZGVybGF5UHJvdG9jb2xfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIFVEUCBhY2NlbGVyYXRpb24gaXMgZW5hYmxlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNVZHBBY2NlbGVyYXRpb25FbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIFVEUCBhY2NlbGVyYXRpb24gaXMgYmVpbmcgYWN0dWFsbHkgdXNlZCAqL1xyXG4gICAgICAgIHRoaXMuSXNVc2luZ1VkcEFjY2VsZXJhdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNlc3Npb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ29ubmVjdGlvbiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Db25uZWN0aW9uTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTZXNzaW9uIGtleSAqL1xyXG4gICAgICAgIHRoaXMuU2Vzc2lvbktleV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIFRvdGFsIHRyYW5zbWl0dGVkIGRhdGEgc2l6ZSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxTZW5kU2l6ZV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCByZWNlaXZlZCBkYXRhIHNpemUgKi9cclxuICAgICAgICB0aGlzLlRvdGFsUmVjdlNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogVG90YWwgdHJhbnNtaXR0ZWQgZGF0YSBzaXplIChubyBjb21wcmVzc2lvbikgKi9cclxuICAgICAgICB0aGlzLlRvdGFsU2VuZFNpemVSZWFsX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIFRvdGFsIHJlY2VpdmVkIGRhdGEgc2l6ZSAobm8gY29tcHJlc3Npb24pICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFJlY3ZTaXplUmVhbF91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgZmxhZyB3aGV0aGVyIHRoZSBWUE4gc2Vzc2lvbiBpcyBCcmlkZ2UgTW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNCcmlkZ2VNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgd2hldGhlciB0aGUgVlBOIHNlc3Npb24gaXMgTW9uaXRvciBtb2RlICovXHJcbiAgICAgICAgdGhpcy5Jc01vbml0b3JNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVkxBTiBJRCAqL1xyXG4gICAgICAgIHRoaXMuVkxhbklkX3UzMiA9IDA7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNMaW5rU3RhdHVzO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0xpbmtTdGF0dXMgPSBWcG5ScGNMaW5rU3RhdHVzO1xyXG4vKiogU2V0dGluZyBvZiBTU1RQIGFuZCBPcGVuVlBOICovXHJcbnZhciBWcG5PcGVuVnBuU3N0cENvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5PcGVuVnBuU3N0cENvbmZpZycgY2xhc3M6IFNldHRpbmcgb2YgU1NUUCBhbmQgT3BlblZQTiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuT3BlblZwblNzdHBDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRydWUgdG8gZW5hYmxlIHRoZSBPcGVuVlBOIENsb25lIFNlcnZlciBGdW5jdGlvbi4gU3BlY2lmeSBmYWxzZSB0byBkaXNhYmxlLiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlT3BlblZQTl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgVURQIHBvcnRzIHRvIGxpc3RlbiBmb3IgT3BlblZQTi4gTXVsdGlwbGUgVURQIHBvcnRzIGNhbiBiZSBzcGVjaWZpZWQgd2l0aCBzcGxpdHRpbmcgYnkgc3BhY2Ugb3IgY29tbWEgbGV0dGVycywgZm9yIGV4YW1wbGU6IFwiMTE5NCwgMjAwMSwgMjAxMCwgMjAxMlwiLiBUaGUgZGVmYXVsdCBwb3J0IGZvciBPcGVuVlBOIGlzIFVEUCAxMTk0LiBZb3UgY2FuIHNwZWNpZnkgYW55IG90aGVyIFVEUCBwb3J0cy4gKi9cclxuICAgICAgICB0aGlzLk9wZW5WUE5Qb3J0TGlzdF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBwZWNpZnkgdHJ1ZSB0byBlbmFibGUgdGhlIE1pY3Jvc29mdCBTU1RQIFZQTiBDbG9uZSBTZXJ2ZXIgRnVuY3Rpb24uIFNwZWNpZnkgZmFsc2UgdG8gZGlzYWJsZS4gKi9cclxuICAgICAgICB0aGlzLkVuYWJsZVNTVFBfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuT3BlblZwblNzdHBDb25maWc7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuT3BlblZwblNzdHBDb25maWcgPSBWcG5PcGVuVnBuU3N0cENvbmZpZztcclxuLyoqIFZpcnR1YWwgaG9zdCBvcHRpb24gKi9cclxudmFyIFZwblZoT3B0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblZoT3B0aW9uJyBjbGFzczogVmlydHVhbCBob3N0IG9wdGlvbiAqL1xyXG4gICAgZnVuY3Rpb24gVnBuVmhPcHRpb24oaW5pdCkge1xyXG4gICAgICAgIC8qKiBUYXJnZXQgVmlydHVhbCBIVUIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuUnBjSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBNQUMgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuTWFjQWRkcmVzc19iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgLyoqIElQIGFkZHJlc3MgKi9cclxuICAgICAgICB0aGlzLklwX2lwID0gXCJcIjtcclxuICAgICAgICAvKiogU3VibmV0IG1hc2sgKi9cclxuICAgICAgICB0aGlzLk1hc2tfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2UgZmxhZyBvZiB0aGUgVmlydHVhbCBOQVQgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLlVzZU5hdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIE1UVSB2YWx1ZSAoU3RhbmRhcmQ6IDE1MDApICovXHJcbiAgICAgICAgdGhpcy5NdHVfdTMyID0gMDtcclxuICAgICAgICAvKiogTkFUIFRDUCB0aW1lb3V0IGluIHNlY29uZHMgKi9cclxuICAgICAgICB0aGlzLk5hdFRjcFRpbWVvdXRfdTMyID0gMDtcclxuICAgICAgICAvKiogTkFUIFVEUCB0aW1lb3V0IGluIHNlY29uZHMgKi9cclxuICAgICAgICB0aGlzLk5hdFVkcFRpbWVvdXRfdTMyID0gMDtcclxuICAgICAgICAvKiogVXNpbmcgZmxhZyBvZiBESENQIGZ1bmN0aW9uICovXHJcbiAgICAgICAgdGhpcy5Vc2VEaGNwX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgc3RhcnQgcG9pbnQgb2YgdGhlIGFkZHJlc3MgYmFuZCB0byBiZSBkaXN0cmlidXRlZCB0byB0aGUgY2xpZW50LiAoRXhhbXBsZTogMTkyLjE2OC4zMC4xMCkgKi9cclxuICAgICAgICB0aGlzLkRoY3BMZWFzZUlQU3RhcnRfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBlbmQgcG9pbnQgb2YgdGhlIGFkZHJlc3MgYmFuZCB0byBiZSBkaXN0cmlidXRlZCB0byB0aGUgY2xpZW50LiAoRXhhbXBsZTogMTkyLjE2OC4zMC4yMDApICovXHJcbiAgICAgICAgdGhpcy5EaGNwTGVhc2VJUEVuZF9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIHN1Ym5ldCBtYXNrIHRvIGJlIHNwZWNpZmllZCBmb3IgdGhlIGNsaWVudC4gKEV4YW1wbGU6IDI1NS4yNTUuMjU1LjApICovXHJcbiAgICAgICAgdGhpcy5EaGNwU3VibmV0TWFza19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGV4cGlyYXRpb24gZGF0ZSBpbiBzZWNvbmQgdW5pdHMgZm9yIGxlYXNpbmcgYW4gSVAgYWRkcmVzcyB0byBhIGNsaWVudC4gKi9cclxuICAgICAgICB0aGlzLkRoY3BFeHBpcmVUaW1lU3Bhbl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIG9mIHRoZSBkZWZhdWx0IGdhdGV3YXkgdG8gYmUgbm90aWZpZWQgdG8gdGhlIGNsaWVudC4gWW91IGNhbiBzcGVjaWZ5IGEgU2VjdXJlTkFUIFZpcnR1YWwgSG9zdCBJUCBhZGRyZXNzIGZvciB0aGlzIHdoZW4gdGhlIFNlY3VyZU5BVCBGdW5jdGlvbidzIFZpcnR1YWwgTkFUIEZ1bmN0aW9uIGhhcyBiZWVuIGVuYWJsZWQgYW5kIGlzIGJlaW5nIHVzZWQgYWxzby4gSWYgeW91IHNwZWNpZnkgMCBvciBub25lLCB0aGVuIHRoZSBjbGllbnQgd2lsbCBub3QgYmUgbm90aWZpZWQgb2YgdGhlIGRlZmF1bHQgZ2F0ZXdheS4gKi9cclxuICAgICAgICB0aGlzLkRoY3BHYXRld2F5QWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQIGFkZHJlc3Mgb2YgdGhlIHByaW1hcnkgRE5TIFNlcnZlciB0byBiZSBub3RpZmllZCB0byB0aGUgY2xpZW50LiBZb3UgY2FuIHNwZWNpZnkgYSBTZWN1cmVOQVQgVmlydHVhbCBIb3N0IElQIGFkZHJlc3MgZm9yIHRoaXMgd2hlbiB0aGUgU2VjdXJlTkFUIEZ1bmN0aW9uJ3MgVmlydHVhbCBOQVQgRnVuY3Rpb24gaGFzIGJlZW4gZW5hYmxlZCBhbmQgaXMgYmVpbmcgdXNlZCBhbHNvLiBJZiB5b3Ugc3BlY2lmeSBlbXB0eSwgdGhlbiB0aGUgY2xpZW50IHdpbGwgbm90IGJlIG5vdGlmaWVkIG9mIHRoZSBETlMgU2VydmVyIGFkZHJlc3MuICovXHJcbiAgICAgICAgdGhpcy5EaGNwRG5zU2VydmVyQWRkcmVzc19pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIElQIGFkZHJlc3Mgb2YgdGhlIHNlY29uZGFyeSBETlMgU2VydmVyIHRvIGJlIG5vdGlmaWVkIHRvIHRoZSBjbGllbnQuIFlvdSBjYW4gc3BlY2lmeSBhIFNlY3VyZU5BVCBWaXJ0dWFsIEhvc3QgSVAgYWRkcmVzcyBmb3IgdGhpcyB3aGVuIHRoZSBTZWN1cmVOQVQgRnVuY3Rpb24ncyBWaXJ0dWFsIE5BVCBGdW5jdGlvbiBoYXMgYmVlbiBlbmFibGVkIGFuZCBpcyBiZWluZyB1c2VkIGFsc28uIElmIHlvdSBzcGVjaWZ5IGVtcHR5LCB0aGVuIHRoZSBjbGllbnQgd2lsbCBub3QgYmUgbm90aWZpZWQgb2YgdGhlIEROUyBTZXJ2ZXIgYWRkcmVzcy4gKi9cclxuICAgICAgICB0aGlzLkRoY3BEbnNTZXJ2ZXJBZGRyZXNzMl9pcCA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGRvbWFpbiBuYW1lIHRvIGJlIG5vdGlmaWVkIHRvIHRoZSBjbGllbnQuIElmIHlvdSBzcGVjaWZ5IG5vbmUsIHRoZW4gdGhlIGNsaWVudCB3aWxsIG5vdCBiZSBub3RpZmllZCBvZiB0aGUgZG9tYWluIG5hbWUuICovXHJcbiAgICAgICAgdGhpcy5EaGNwRG9tYWluTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHdoZXRoZXIgb3Igbm90IHRvIHNhdmUgdGhlIFZpcnR1YWwgREhDUCBTZXJ2ZXIgb3BlcmF0aW9uIGluIHRoZSBWaXJ0dWFsIEh1YiBzZWN1cml0eSBsb2cuIFNwZWNpZnkgdHJ1ZSB0byBzYXZlIGl0LiBUaGlzIHZhbHVlIGlzIGludGVybGlua2VkIHdpdGggdGhlIFZpcnR1YWwgTkFUIEZ1bmN0aW9uIGxvZyBzYXZlIHNldHRpbmcuICovXHJcbiAgICAgICAgdGhpcy5TYXZlTG9nX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gZW5hYmxlIHRoZSBEaGNwUHVzaFJvdXRlc19zdHIgZmllbGQuICovXHJcbiAgICAgICAgdGhpcy5BcHBseURoY3BQdXNoUm91dGVzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3BlY2lmeSB0aGUgc3RhdGljIHJvdXRpbmcgdGFibGUgdG8gcHVzaC4gRXhhbXBsZTogXCIxOTIuMTY4LjUuMC8yNTUuMjU1LjI1NS4wLzE5Mi4xNjguNC4yNTQsIDEwLjAuMC4wLzI1NS4wLjAuMC8xOTIuMTY4LjQuMjUzXCIgU3BsaXQgbXVsdGlwbGUgZW50cmllcyAobWF4aW11bTogNjQgZW50cmllcykgYnkgY29tbWEgb3Igc3BhY2UgY2hhcmFjdGVycy4gRWFjaCBlbnRyeSBtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGUgXCJJUCBuZXR3b3JrIGFkZHJlc3Mvc3VibmV0IG1hc2svZ2F0ZXdheSBJUCBhZGRyZXNzXCIgZm9ybWF0LiBUaGlzIFZpcnR1YWwgREhDUCBTZXJ2ZXIgY2FuIHB1c2ggdGhlIGNsYXNzbGVzcyBzdGF0aWMgcm91dGVzIChSRkMgMzQ0Mikgd2l0aCBESENQIHJlcGx5IG1lc3NhZ2VzIHRvIFZQTiBjbGllbnRzLiBXaGV0aGVyIG9yIG5vdCBhIFZQTiBjbGllbnQgY2FuIHJlY29nbml6ZSB0aGUgY2xhc3NsZXNzIHN0YXRpYyByb3V0ZXMgKFJGQyAzNDQyKSBkZXBlbmRzIG9uIHRoZSB0YXJnZXQgVlBOIGNsaWVudCBzb2Z0d2FyZS4gU29mdEV0aGVyIFZQTiBDbGllbnQgYW5kIE9wZW5WUE4gQ2xpZW50IGFyZSBzdXBwb3J0aW5nIHRoZSBjbGFzc2xlc3Mgc3RhdGljIHJvdXRlcy4gT24gTDJUUC9JUHNlYyBhbmQgTVMtU1NUUCBwcm90b2NvbHMsIHRoZSBjb21wYXRpYmlsaXR5IGRlcGVuZHMgb24gdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBjbGllbnQgc29mdHdhcmUuIFlvdSBjYW4gcmVhbGl6ZSB0aGUgc3BsaXQgdHVubmVsaW5nIGlmIHlvdSBjbGVhciB0aGUgZGVmYXVsdCBnYXRld2F5IGZpZWxkIG9uIHRoZSBWaXJ0dWFsIERIQ1AgU2VydmVyIG9wdGlvbnMuIE9uIHRoZSBjbGllbnQgc2lkZSwgTDJUUC9JUHNlYyBhbmQgTVMtU1NUUCBjbGllbnRzIG5lZWQgdG8gYmUgY29uZmlndXJlZCBub3QgdG8gc2V0IHVwIHRoZSBkZWZhdWx0IGdhdGV3YXkgZm9yIHRoZSBzcGxpdCB0dW5uZWxpbmcgdXNhZ2UuIFlvdSBjYW4gYWxzbyBwdXNoIHRoZSBjbGFzc2xlc3Mgc3RhdGljIHJvdXRlcyAoUkZDIDM0NDIpIGJ5IHlvdXIgZXhpc3RpbmcgZXh0ZXJuYWwgREhDUCBzZXJ2ZXIuIEluIHRoYXQgY2FzZSwgZGlzYWJsZSB0aGUgVmlydHVhbCBESENQIFNlcnZlciBmdW5jdGlvbiBvbiBTZWN1cmVOQVQsIGFuZCB5b3UgbmVlZCBub3QgdG8gc2V0IHVwIHRoZSBjbGFzc2xlc3Mgcm91dGVzIG9uIHRoaXMgQVBJLiBTZWUgdGhlIFJGQyAzNDQyIHRvIHVuZGVyc3RhbmQgdGhlIGNsYXNzbGVzcyByb3V0ZXMuICovXHJcbiAgICAgICAgdGhpcy5EaGNwUHVzaFJvdXRlc19zdHIgPSBcIlwiO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuVmhPcHRpb247XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuVmhPcHRpb24gPSBWcG5WaE9wdGlvbjtcclxuLyoqIFJQQ19OQVRfU1RBVFVTICovXHJcbnZhciBWcG5ScGNOYXRTdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjTmF0U3RhdHVzJyBjbGFzczogUlBDX05BVF9TVEFUVVMgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY05hdFN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFZpcnR1YWwgSHViIE5hbWUgKi9cclxuICAgICAgICB0aGlzLkh1Yk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIFRDUCBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnRtYmVyIG9mIFVEUCBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVWRwU2Vzc2lvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnltYmVyIG9mIElDTVAgc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bUljbXBTZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgRE5TIHNlc3Npb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1EbnNTZXNzaW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgREhDUCBjbGllbnRzICovXHJcbiAgICAgICAgdGhpcy5OdW1EaGNwQ2xpZW50c191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBXaGV0aGVyIHRoZSBOQVQgaXMgb3BlcmF0aW5nIGluIHRoZSBLZXJuZWwgTW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNLZXJuZWxNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogV2hldGhlciB0aGUgTkFUIGlzIG9wZXJhdGluZyBpbiB0aGUgUmF3IElQIE1vZGUgKi9cclxuICAgICAgICB0aGlzLklzUmF3SXBNb2RlX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY05hdFN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNOYXRTdGF0dXMgPSBWcG5ScGNOYXRTdGF0dXM7XHJcbi8qKiBLZXkgcGFpciAqL1xyXG52YXIgVnBuUnBjS2V5UGFpciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNLZXlQYWlyJyBjbGFzczogS2V5IHBhaXIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY0tleVBhaXIoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgY2VydGlmaWNhdGUgKi9cclxuICAgICAgICB0aGlzLkNlcnRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBUaGUgYm9keSBvZiB0aGUgcHJpdmF0ZSBrZXkgKi9cclxuICAgICAgICB0aGlzLktleV9iaW4gPSBuZXcgVWludDhBcnJheShbXSk7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNLZXlQYWlyO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY0tleVBhaXIgPSBWcG5ScGNLZXlQYWlyO1xyXG4vKiogU2luZ2xlIHN0cmluZyB2YWx1ZSAqL1xyXG52YXIgVnBuUnBjU3RyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1N0cicgY2xhc3M6IFNpbmdsZSBzdHJpbmcgdmFsdWUgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1N0cihpbml0KSB7XHJcbiAgICAgICAgLyoqIEEgc3RyaW5nIHZhbHVlICovXHJcbiAgICAgICAgdGhpcy5TdHJpbmdfc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1N0cjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTdHIgPSBWcG5ScGNTdHI7XHJcbi8qKiBUeXBlIG9mIFZQTiBTZXJ2ZXIgKi9cclxudmFyIFZwblJwY1NlcnZlclR5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjU2VydmVyVHlwZSkge1xyXG4gICAgLyoqIFN0YW5kLWFsb25lIHNlcnZlciAqL1xyXG4gICAgVnBuUnBjU2VydmVyVHlwZVtWcG5ScGNTZXJ2ZXJUeXBlW1wiU3RhbmRhbG9uZVwiXSA9IDBdID0gXCJTdGFuZGFsb25lXCI7XHJcbiAgICAvKiogRmFybSBjb250cm9sbGVyIHNlcnZlciAqL1xyXG4gICAgVnBuUnBjU2VydmVyVHlwZVtWcG5ScGNTZXJ2ZXJUeXBlW1wiRmFybUNvbnRyb2xsZXJcIl0gPSAxXSA9IFwiRmFybUNvbnRyb2xsZXJcIjtcclxuICAgIC8qKiBGYXJtIG1lbWJlciBzZXJ2ZXIgKi9cclxuICAgIFZwblJwY1NlcnZlclR5cGVbVnBuUnBjU2VydmVyVHlwZVtcIkZhcm1NZW1iZXJcIl0gPSAyXSA9IFwiRmFybU1lbWJlclwiO1xyXG59KShWcG5ScGNTZXJ2ZXJUeXBlID0gZXhwb3J0cy5WcG5ScGNTZXJ2ZXJUeXBlIHx8IChleHBvcnRzLlZwblJwY1NlcnZlclR5cGUgPSB7fSkpO1xyXG4vKiogT3BlcmF0aW5nIHN5c3RlbSB0eXBlICovXHJcbnZhciBWcG5ScGNPc1R5cGU7XHJcbihmdW5jdGlvbiAoVnBuUnBjT3NUeXBlKSB7XHJcbiAgICAvKiogV2luZG93cyA5NSAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfOTVcIl0gPSAxMTAwXSA9IFwiV0lORE9XU185NVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgOTggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzk4XCJdID0gMTIwMF0gPSBcIldJTkRPV1NfOThcIjtcclxuICAgIC8qKiBXaW5kb3dzIE1lICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19NRVwiXSA9IDEzMDBdID0gXCJXSU5ET1dTX01FXCI7XHJcbiAgICAvKiogV2luZG93cyAodW5rbm93bikgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1VOS05PV05cIl0gPSAxNDAwXSA9IFwiV0lORE9XU19VTktOT1dOXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgV29ya3N0YXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX05UXzRfV09SS1NUQVRJT05cIl0gPSAyMTAwXSA9IFwiV0lORE9XU19OVF80X1dPUktTVEFUSU9OXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1NFUlZFUlwiXSA9IDIxMTBdID0gXCJXSU5ET1dTX05UXzRfU0VSVkVSXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgU2VydmVyLCBFbnRlcnByaXNlIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX05UXzRfU0VSVkVSX0VOVEVSUFJJU0VcIl0gPSAyMTExXSA9IFwiV0lORE9XU19OVF80X1NFUlZFUl9FTlRFUlBSSVNFXCI7XHJcbiAgICAvKiogV2luZG93cyBOVCA0LjAgVGVybWluYWwgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1RFUk1JTkFMX1NFUlZFUlwiXSA9IDIxMTJdID0gXCJXSU5ET1dTX05UXzRfVEVSTUlOQUxfU0VSVkVSXCI7XHJcbiAgICAvKiogQmFja09mZmljZSBTZXJ2ZXIgNC41ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X0JBQ0tPRkZJQ0VcIl0gPSAyMTEzXSA9IFwiV0lORE9XU19OVF80X0JBQ0tPRkZJQ0VcIjtcclxuICAgIC8qKiBTbWFsbCBCdXNpbmVzcyBTZXJ2ZXIgNC41ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19OVF80X1NNU1wiXSA9IDIxMTRdID0gXCJXSU5ET1dTX05UXzRfU01TXCI7XHJcbiAgICAvKiogV2luZG93cyAyMDAwIFByb2Zlc3Npb25hbCAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMjAwMF9QUk9GRVNTSU9OQUxcIl0gPSAyMjAwXSA9IFwiV0lORE9XU18yMDAwX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgMjAwMCBTZXJ2ZXIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDBfU0VSVkVSXCJdID0gMjIxMV0gPSBcIldJTkRPV1NfMjAwMF9TRVJWRVJcIjtcclxuICAgIC8qKiBXaW5kb3dzIDIwMDAgQWR2YW5jZWQgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX0FEVkFOQ0VEX1NFUlZFUlwiXSA9IDIyMTJdID0gXCJXSU5ET1dTXzIwMDBfQURWQU5DRURfU0VSVkVSXCI7XHJcbiAgICAvKiogV2luZG93cyAyMDAwIERhdGFjZW50ZXIgU2VydmVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX0RBVEFDRU5URVJfU0VSVkVSXCJdID0gMjIxM10gPSBcIldJTkRPV1NfMjAwMF9EQVRBQ0VOVEVSX1NFUlZFUlwiO1xyXG4gICAgLyoqIEJhY2tPZmZpY2UgU2VydmVyIDIwMDAgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDBfQkFDS09GRklDRVwiXSA9IDIyMTRdID0gXCJXSU5ET1dTXzIwMDBfQkFDS09GRklDRVwiO1xyXG4gICAgLyoqIFNtYWxsIEJ1c2luZXNzIFNlcnZlciAyMDAwICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAwX1NCU1wiXSA9IDIyMTVdID0gXCJXSU5ET1dTXzIwMDBfU0JTXCI7XHJcbiAgICAvKiogV2luZG93cyBYUCBIb21lIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1hQX0hPTUVcIl0gPSAyMzAwXSA9IFwiV0lORE9XU19YUF9IT01FXCI7XHJcbiAgICAvKiogV2luZG93cyBYUCBQcm9mZXNzaW9uYWwgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1hQX1BST0ZFU1NJT05BTFwiXSA9IDIzMDFdID0gXCJXSU5ET1dTX1hQX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDMgV2ViIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfV0VCXCJdID0gMjQxMF0gPSBcIldJTkRPV1NfMjAwM19XRUJcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAyMDAzIFN0YW5kYXJkIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfU1RBTkRBUkRcIl0gPSAyNDExXSA9IFwiV0lORE9XU18yMDAzX1NUQU5EQVJEXCI7XHJcbiAgICAvKiogV2luZG93cyBTZXJ2ZXIgMjAwMyBFbnRlcnByaXNlIEVkaXRpb24gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzIwMDNfRU5URVJQUklTRVwiXSA9IDI0MTJdID0gXCJXSU5ET1dTXzIwMDNfRU5URVJQUklTRVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDMgRGF0YUNlbnRlciBFZGl0aW9uICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAzX0RBVEFDRU5URVJcIl0gPSAyNDEzXSA9IFwiV0lORE9XU18yMDAzX0RBVEFDRU5URVJcIjtcclxuICAgIC8qKiBCYWNrT2ZmaWNlIFNlcnZlciAyMDAzICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU18yMDAzX0JBQ0tPRkZJQ0VcIl0gPSAyNDE0XSA9IFwiV0lORE9XU18yMDAzX0JBQ0tPRkZJQ0VcIjtcclxuICAgIC8qKiBTbWFsbCBCdXNpbmVzcyBTZXJ2ZXIgMjAwMyAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMjAwM19TQlNcIl0gPSAyNDE1XSA9IFwiV0lORE9XU18yMDAzX1NCU1wiO1xyXG4gICAgLyoqIFdpbmRvd3MgVmlzdGEgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX0xPTkdIT1JOX1BST0ZFU1NJT05BTFwiXSA9IDI1MDBdID0gXCJXSU5ET1dTX0xPTkdIT1JOX1BST0ZFU1NJT05BTFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMDggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX0xPTkdIT1JOX1NFUlZFUlwiXSA9IDI1MTBdID0gXCJXSU5ET1dTX0xPTkdIT1JOX1NFUlZFUlwiO1xyXG4gICAgLyoqIFdpbmRvd3MgNyAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfN1wiXSA9IDI2MDBdID0gXCJXSU5ET1dTXzdcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAyMDA4IFIyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19TRVJWRVJfMjAwOF9SMlwiXSA9IDI2MTBdID0gXCJXSU5ET1dTX1NFUlZFUl8yMDA4X1IyXCI7XHJcbiAgICAvKiogV2luZG93cyA4ICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU184XCJdID0gMjcwMF0gPSBcIldJTkRPV1NfOFwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMTIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1NFUlZFUl84XCJdID0gMjcxMF0gPSBcIldJTkRPV1NfU0VSVkVSXzhcIjtcclxuICAgIC8qKiBXaW5kb3dzIDguMSAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfODFcIl0gPSAyNzAxXSA9IFwiV0lORE9XU184MVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDIwMTIgUjIgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTX1NFUlZFUl84MVwiXSA9IDI3MTFdID0gXCJXSU5ET1dTX1NFUlZFUl84MVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgMTAgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJXSU5ET1dTXzEwXCJdID0gMjcwMl0gPSBcIldJTkRPV1NfMTBcIjtcclxuICAgIC8qKiBXaW5kb3dzIFNlcnZlciAxMCAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfU0VSVkVSXzEwXCJdID0gMjcxMl0gPSBcIldJTkRPV1NfU0VSVkVSXzEwXCI7XHJcbiAgICAvKiogV2luZG93cyAxMSBvciBsYXRlciAqL1xyXG4gICAgVnBuUnBjT3NUeXBlW1ZwblJwY09zVHlwZVtcIldJTkRPV1NfMTFcIl0gPSAyODAwXSA9IFwiV0lORE9XU18xMVwiO1xyXG4gICAgLyoqIFdpbmRvd3MgU2VydmVyIDExIG9yIGxhdGVyICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiV0lORE9XU19TRVJWRVJfMTFcIl0gPSAyODEwXSA9IFwiV0lORE9XU19TRVJWRVJfMTFcIjtcclxuICAgIC8qKiBVbmtub3duIFVOSVggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJVTklYX1VOS05PV05cIl0gPSAzMDAwXSA9IFwiVU5JWF9VTktOT1dOXCI7XHJcbiAgICAvKiogTGludXggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJMSU5VWFwiXSA9IDMxMDBdID0gXCJMSU5VWFwiO1xyXG4gICAgLyoqIFNvbGFyaXMgKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJTT0xBUklTXCJdID0gMzIwMF0gPSBcIlNPTEFSSVNcIjtcclxuICAgIC8qKiBDeWd3aW4gKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJDWUdXSU5cIl0gPSAzMzAwXSA9IFwiQ1lHV0lOXCI7XHJcbiAgICAvKiogQlNEICovXHJcbiAgICBWcG5ScGNPc1R5cGVbVnBuUnBjT3NUeXBlW1wiQlNEXCJdID0gMzQwMF0gPSBcIkJTRFwiO1xyXG4gICAgLyoqIE1hY09TIFggKi9cclxuICAgIFZwblJwY09zVHlwZVtWcG5ScGNPc1R5cGVbXCJNQUNPU19YXCJdID0gMzUwMF0gPSBcIk1BQ09TX1hcIjtcclxufSkoVnBuUnBjT3NUeXBlID0gZXhwb3J0cy5WcG5ScGNPc1R5cGUgfHwgKGV4cG9ydHMuVnBuUnBjT3NUeXBlID0ge30pKTtcclxuLyoqIFZQTiBTZXJ2ZXIgSW5mb3JtYXRpb24gKi9cclxudmFyIFZwblJwY1NlcnZlckluZm8gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2VydmVySW5mbycgY2xhc3M6IFZQTiBTZXJ2ZXIgSW5mb3JtYXRpb24gKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1NlcnZlckluZm8oaW5pdCkge1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJQcm9kdWN0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgdmVyc2lvbiBzdHJpbmcgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclZlcnNpb25TdHJpbmdfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIGJ1aWxkIGluZm9ybWF0aW9uIHN0cmluZyAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGRJbmZvU3RyaW5nX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFNlcnZlciB2ZXJzaW9uIGludGVnZXIgdmFsdWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclZlckludF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgYnVpbGQgbnVtYmVyIGludGVnZXIgdmFsdWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckJ1aWxkSW50X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZlciBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckhvc3ROYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFR5cGUgb2Ygc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEJ1aWxkIGRhdGUgYW5kIHRpbWUgb2YgdGhlIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyQnVpbGREYXRlX2R0ID0gbmV3IERhdGUoKTtcclxuICAgICAgICAvKiogRmFtaWx5IG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlcnZlckZhbWlseU5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT1MgdHlwZSAqL1xyXG4gICAgICAgIHRoaXMuT3NUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZpY2UgcGFjayBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLk9zU2VydmljZVBhY2tfdTMyID0gMDtcclxuICAgICAgICAvKiogT1Mgc3lzdGVtIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zU3lzdGVtTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPUyBwcm9kdWN0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogT1MgdmVuZG9yIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk9zVmVuZG9yTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPUyB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5Pc1ZlcnNpb25fc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2VybmVsIG5hbWUgKi9cclxuICAgICAgICB0aGlzLktlcm5lbE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogS2VybmVsIHZlcnNpb24gKi9cclxuICAgICAgICB0aGlzLktlcm5lbFZlcnNpb25fc3RyID0gXCJcIjtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NlcnZlckluZm87XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuUnBjU2VydmVySW5mbyA9IFZwblJwY1NlcnZlckluZm87XHJcbi8qKiBTZXJ2ZXIgc3RhdHVzICovXHJcbnZhciBWcG5ScGNTZXJ2ZXJTdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2VydmVyU3RhdHVzJyBjbGFzczogU2VydmVyIHN0YXR1cyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2VydmVyU3RhdHVzKGluaXQpIHtcclxuICAgICAgICAvKiogVHlwZSBvZiBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclR5cGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVG90YWwgbnVtYmVyIG9mIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIExvY2FsIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNMb2NhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgcmVtb3RlIFRDUCBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNSZW1vdGVfdTMyID0gMDtcclxuICAgICAgICAvKiogVG90YWwgbnVtYmVyIG9mIEhVQnMgKi9cclxuICAgICAgICB0aGlzLk51bUh1YlRvdGFsX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE55bWJlciBvZiBzdGFuZC1hbG9uZSBIVUIgKi9cclxuICAgICAgICB0aGlzLk51bUh1YlN0YW5kYWxvbmVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIHN0YXRpYyBIVUJzICovXHJcbiAgICAgICAgdGhpcy5OdW1IdWJTdGF0aWNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIER5bmFtaWMgSFVCcyAqL1xyXG4gICAgICAgIHRoaXMuTnVtSHViRHluYW1pY191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCBudW1iZXIgb2Ygc2Vzc2lvbnMgKi9cclxuICAgICAgICB0aGlzLk51bVNlc3Npb25zVG90YWxfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGxvY2FsIFZQTiBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNMb2NhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBUaGUgbnVtYmVyIG9mIHJlbW90ZSBzZXNzaW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtU2Vzc2lvbnNSZW1vdGVfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIE1BQyB0YWJsZSBlbnRyaWVzICh0b3RhbCBzdW0gb2YgYWxsIFZpcnR1YWwgSHVicykgKi9cclxuICAgICAgICB0aGlzLk51bU1hY1RhYmxlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgSVAgdGFibGUgZW50cmllcyAodG90YWwgc3VtIG9mIGFsbCBWaXJ0dWFsIEh1YnMpICovXHJcbiAgICAgICAgdGhpcy5OdW1JcFRhYmxlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgdXNlcnMgKHRvdGFsIHN1bSBvZiBhbGwgVmlydHVhbCBIdWJzKSAqL1xyXG4gICAgICAgIHRoaXMuTnVtVXNlcnNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGdyb3VwcyAodG90YWwgc3VtIG9mIGFsbCBWaXJ0dWFsIEh1YnMpICovXHJcbiAgICAgICAgdGhpcy5OdW1Hcm91cHNfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGFzc2lnbmVkIGJyaWRnZSBsaWNlbnNlcyAoVXNlZnVsIHRvIG1ha2UgYSBjb21tZXJjaWFsIHZlcnNpb24pICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBhc3NpZ25lZCBjbGllbnQgbGljZW5zZXMgKFVzZWZ1bCB0byBtYWtlIGEgY29tbWVyY2lhbCB2ZXJzaW9uKSAqL1xyXG4gICAgICAgIHRoaXMuQXNzaWduZWRDbGllbnRMaWNlbnNlc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgQXNzaWduZWQgYnJpZGdlIGxpY2Vuc2UgKGNsdXN0ZXItd2lkZSksIHVzZWZ1bCB0byBtYWtlIGEgY29tbWVyY2lhbCB2ZXJzaW9uICovXHJcbiAgICAgICAgdGhpcy5Bc3NpZ25lZEJyaWRnZUxpY2Vuc2VzVG90YWxfdTMyID0gMDtcclxuICAgICAgICAvKiogTnVtYmVyIG9mIGFzc2lnbmVkIGNsaWVudCBsaWNlbnNlcyAoY2x1c3Rlci13aWRlKSwgdXNlZnVsIHRvIG1ha2UgYSBjb21tZXJjaWFsIHZlcnNpb24gKi9cclxuICAgICAgICB0aGlzLkFzc2lnbmVkQ2xpZW50TGljZW5zZXNUb3RhbF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgYnJvYWRjYXN0IHBhY2tldHMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuQnJvYWRjYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQnJvYWRjYXN0IGJ5dGVzIChSZWN2KSAqL1xyXG4gICAgICAgIHRoaXNbXCJSZWN2LkJyb2FkY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgY291bnQgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdEJ5dGVzX3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIFVuaWNhc3QgYnl0ZXMgKFJlY3YpICovXHJcbiAgICAgICAgdGhpc1tcIlJlY3YuVW5pY2FzdENvdW50X3U2NFwiXSA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBicm9hZGNhc3QgcGFja2V0cyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5Ccm9hZGNhc3RCeXRlc191NjRcIl0gPSAwO1xyXG4gICAgICAgIC8qKiBCcm9hZGNhc3QgYnl0ZXMgKFNlbmQpICovXHJcbiAgICAgICAgdGhpc1tcIlNlbmQuQnJvYWRjYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Qnl0ZXNfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogVW5pY2FzdCBieXRlcyAoU2VuZCkgKi9cclxuICAgICAgICB0aGlzW1wiU2VuZC5VbmljYXN0Q291bnRfdTY0XCJdID0gMDtcclxuICAgICAgICAvKiogQ3VycmVudCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5DdXJyZW50VGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIDY0IGJpdCBIaWdoLVByZWNpc2lvbiBMb2dpY2FsIFN5c3RlbSBDbG9jayAqL1xyXG4gICAgICAgIHRoaXMuQ3VycmVudFRpY2tfdTY0ID0gMDtcclxuICAgICAgICAvKiogVlBOIFNlcnZlciBTdGFydC11cCB0aW1lICovXHJcbiAgICAgICAgdGhpcy5TdGFydFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IFRvdGFsIE1lbW9yeSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxNZW1vcnlfdTY0ID0gMDtcclxuICAgICAgICAvKiogTWVtb3J5IGluZm9ybWF0aW9uOiBVc2VkIE1lbW9yeSAqL1xyXG4gICAgICAgIHRoaXMuVXNlZE1lbW9yeV91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IEZyZWUgTWVtb3J5ICovXHJcbiAgICAgICAgdGhpcy5GcmVlTWVtb3J5X3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE1lbW9yeSBpbmZvcm1hdGlvbjogVG90YWwgUGh5cyAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxQaHlzX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIE1lbW9yeSBpbmZvcm1hdGlvbjogVXNlZCBQaHlzICovXHJcbiAgICAgICAgdGhpcy5Vc2VkUGh5c191NjQgPSAwO1xyXG4gICAgICAgIC8qKiBNZW1vcnkgaW5mb3JtYXRpb246IEZyZWUgUGh5cyAqL1xyXG4gICAgICAgIHRoaXMuRnJlZVBoeXNfdTY0ID0gMDtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NlcnZlclN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXJ2ZXJTdGF0dXMgPSBWcG5ScGNTZXJ2ZXJTdGF0dXM7XHJcbi8qKiBWUE4gU2Vzc2lvbiBzdGF0dXMgKi9cclxudmFyIFZwblJwY1Nlc3Npb25TdGF0dXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuUnBjU2Vzc2lvblN0YXR1cycgY2xhc3M6IFZQTiBTZXNzaW9uIHN0YXR1cyAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU2Vzc2lvblN0YXR1cyhpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFZQTiBzZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogVXNlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Vc2VybmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBSZWFsIHVzZXIgbmFtZSB3aGljaCB3YXMgdXNlZCBmb3IgdGhlIGF1dGhlbnRpY2F0aW9uICovXHJcbiAgICAgICAgdGhpcy5SZWFsVXNlcm5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogR3JvdXAgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuR3JvdXBOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIElzIENhc2NhZGUgU2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuTGlua01vZGVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDbGllbnQgSVAgYWRkcmVzcyAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50X0lwX0FkZHJlc3NfaXAgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgaG9zdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX0NsaWVudEhvc3ROYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9wZXJhdGlvbiBmbGFnICovXHJcbiAgICAgICAgdGhpcy5BY3RpdmVfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBDb25uZWN0ZWQgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogU3RhdGUgb2YgdGhlIGNsaWVudCBzZXNzaW9uICovXHJcbiAgICAgICAgdGhpcy5TZXNzaW9uU3RhdHVzX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNlcnZlciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5TZXJ2ZXJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFBvcnQgbnVtYmVyIG9mIHRoZSBzZXJ2ZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclBvcnRfdTMyID0gMDtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdE5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2VydmVyIHByb2R1Y3QgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyUHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgcHJvZHVjdCBidWlsZCBudW1iZXIgKi9cclxuICAgICAgICB0aGlzLlNlcnZlclByb2R1Y3RCdWlsZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIHN0YXJ0IHRpbWUgKi9cclxuICAgICAgICB0aGlzLlN0YXJ0VGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gY29tcGxldGlvbiB0aW1lIG9mIHRoZSBmaXJzdCBjb25uZWN0aW9uICovXHJcbiAgICAgICAgdGhpcy5GaXJzdENvbm5lY3Rpb25Fc3RhYmxpc2llZFRpbWVfZHQgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICAgIC8qKiBDb25uZWN0aW9uIGNvbXBsZXRpb24gdGltZSBvZiB0aGlzIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLkN1cnJlbnRDb25uZWN0aW9uRXN0YWJsaXNoVGltZV9kdCA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjb25uZWN0aW9ucyBoYXZlIGJlZW4gZXN0YWJsaXNoZWQgc28gZmFyICovXHJcbiAgICAgICAgdGhpcy5OdW1Db25uZWN0aW9uc0VhdGFibGlzaGVkX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIEhhbGYtY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuSGFsZkNvbm5lY3Rpb25fYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBWb0lQIC8gUW9TICovXHJcbiAgICAgICAgdGhpcy5Rb1NfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBNYXhpbXVtIG51bWJlciBvZiB0aGUgdW5kZXJseWluZyBUQ1AgY29ubmVjdGlvbnMgKi9cclxuICAgICAgICB0aGlzLk1heFRjcENvbm5lY3Rpb25zX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIE51bWJlciBvZiBjdXJyZW50IHVuZGVybHlpbmcgVENQIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc191MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2YgaW5ib3VuZCB1bmRlcmx5aW5nIGNvbm5lY3Rpb25zICovXHJcbiAgICAgICAgdGhpcy5OdW1UY3BDb25uZWN0aW9uc1VwbG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBOdW1iZXIgb2Ygb3V0Ym91bmQgdW5kZXJseWluZyBjb25uZWN0aW9ucyAqL1xyXG4gICAgICAgIHRoaXMuTnVtVGNwQ29ubmVjdGlvbnNEb3dubG9hZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBVc2Ugb2YgZW5jcnlwdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuVXNlRW5jcnlwdF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIENpcGhlciBhbGdvcml0aG0gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ2lwaGVyTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBVc2Ugb2YgY29tcHJlc3Npb24gKi9cclxuICAgICAgICB0aGlzLlVzZUNvbXByZXNzX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogSXMgUi1VRFAgc2Vzc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuSXNSVURQU2Vzc2lvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFBoeXNpY2FsIHVuZGVybHlpbmcgY29tbXVuaWNhdGlvbiBwcm90b2NvbCAqL1xyXG4gICAgICAgIHRoaXMuVW5kZXJsYXlQcm90b2NvbF9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgVURQIGFjY2VsZXJhdGlvbiBpcyBlbmFibGVkICovXHJcbiAgICAgICAgdGhpcy5Jc1VkcEFjY2VsZXJhdGlvbkVuYWJsZWRfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBVc2luZyB0aGUgVURQIGFjY2VsZXJhdGlvbiBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuSXNVc2luZ1VkcEFjY2VsZXJhdGlvbl9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZQTiBzZXNzaW9uIG5hbWUgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25OYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENvbm5lY3Rpb24gbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuQ29ubmVjdGlvbk5hbWVfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogU2Vzc2lvbiBrZXkgKi9cclxuICAgICAgICB0aGlzLlNlc3Npb25LZXlfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIC8qKiBUb3RhbCB0cmFuc21pdHRlZCBkYXRhIHNpemUgKi9cclxuICAgICAgICB0aGlzLlRvdGFsU2VuZFNpemVfdTY0ID0gMDtcclxuICAgICAgICAvKiogVG90YWwgcmVjZWl2ZWQgZGF0YSBzaXplICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFJlY3ZTaXplX3U2NCA9IDA7XHJcbiAgICAgICAgLyoqIFRvdGFsIHRyYW5zbWl0dGVkIGRhdGEgc2l6ZSAobm8gY29tcHJlc3Npb24pICovXHJcbiAgICAgICAgdGhpcy5Ub3RhbFNlbmRTaXplUmVhbF91NjQgPSAwO1xyXG4gICAgICAgIC8qKiBUb3RhbCByZWNlaXZlZCBkYXRhIHNpemUgKG5vIGNvbXByZXNzaW9uKSAqL1xyXG4gICAgICAgIHRoaXMuVG90YWxSZWN2U2l6ZVJlYWxfdTY0ID0gMDtcclxuICAgICAgICAvKiogSXMgQnJpZGdlIE1vZGUgKi9cclxuICAgICAgICB0aGlzLklzQnJpZGdlTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIElzIE1vbml0b3IgbW9kZSAqL1xyXG4gICAgICAgIHRoaXMuSXNNb25pdG9yTW9kZV9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgLyoqIFZMQU4gSUQgKi9cclxuICAgICAgICB0aGlzLlZMYW5JZF91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgcHJvZHVjdCBuYW1lICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRQcm9kdWN0TmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50UHJvZHVjdFZlcl91MzIgPSAwO1xyXG4gICAgICAgIC8qKiBDbGllbnQgYnVpbGQgbnVtYmVyICovXHJcbiAgICAgICAgdGhpcy5DbGllbnRQcm9kdWN0QnVpbGRfdTMyID0gMDtcclxuICAgICAgICAvKiogQ2xpZW50IE9TIG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudE9zTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBDbGllbnQgT1MgdmVyc2lvbiAqL1xyXG4gICAgICAgIHRoaXMuQ2xpZW50T3NWZXJfc3RyID0gXCJcIjtcclxuICAgICAgICAvKiogQ2xpZW50IE9TIFByb2R1Y3QgSUQgKi9cclxuICAgICAgICB0aGlzLkNsaWVudE9zUHJvZHVjdElkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIENsaWVudCBob3N0IG5hbWUgKi9cclxuICAgICAgICB0aGlzLkNsaWVudEhvc3RuYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIFVuaXF1ZSBJRCAqL1xyXG4gICAgICAgIHRoaXMuVW5pcXVlSWRfYmluID0gbmV3IFVpbnQ4QXJyYXkoW10pO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuUnBjU2Vzc2lvblN0YXR1cztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXNzaW9uU3RhdHVzID0gVnBuUnBjU2Vzc2lvblN0YXR1cztcclxuLyoqIFNldCB0aGUgc3BlY2lhbCBsaXN0ZW5lciAqL1xyXG52YXIgVnBuUnBjU3BlY2lhbExpc3RlbmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NwZWNpYWxMaXN0ZW5lcicgY2xhc3M6IFNldCB0aGUgc3BlY2lhbCBsaXN0ZW5lciAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjU3BlY2lhbExpc3RlbmVyKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gYWN0aXZhdGUgdGhlIFZQTiBvdmVyIElDTVAgc2VydmVyIGZ1bmN0aW9uICovXHJcbiAgICAgICAgdGhpcy5WcG5PdmVySWNtcExpc3RlbmVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogVGhlIGZsYWcgdG8gYWN0aXZhdGUgdGhlIFZQTiBvdmVyIEROUyBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuVnBuT3ZlckRuc0xpc3RlbmVyX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NwZWNpYWxMaXN0ZW5lcjtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTcGVjaWFsTGlzdGVuZXIgPSBWcG5ScGNTcGVjaWFsTGlzdGVuZXI7XHJcbi8qKiBTeXNsb2cgY29uZmlndXJhdGlvbiAqL1xyXG52YXIgVnBuU3lzbG9nU2F2ZVR5cGU7XHJcbihmdW5jdGlvbiAoVnBuU3lzbG9nU2F2ZVR5cGUpIHtcclxuICAgIC8qKiBEbyBub3QgdXNlIHN5c2xvZyAqL1xyXG4gICAgVnBuU3lzbG9nU2F2ZVR5cGVbVnBuU3lzbG9nU2F2ZVR5cGVbXCJOb25lXCJdID0gMF0gPSBcIk5vbmVcIjtcclxuICAgIC8qKiBPbmx5IHNlcnZlciBsb2cgKi9cclxuICAgIFZwblN5c2xvZ1NhdmVUeXBlW1ZwblN5c2xvZ1NhdmVUeXBlW1wiU2VydmVyTG9nXCJdID0gMV0gPSBcIlNlcnZlckxvZ1wiO1xyXG4gICAgLyoqIFNlcnZlciBhbmQgVmlydHVhbCBIVUIgc2VjdXJpdHkgbG9nICovXHJcbiAgICBWcG5TeXNsb2dTYXZlVHlwZVtWcG5TeXNsb2dTYXZlVHlwZVtcIlNlcnZlckFuZEh1YlNlY3VyaXR5TG9nXCJdID0gMl0gPSBcIlNlcnZlckFuZEh1YlNlY3VyaXR5TG9nXCI7XHJcbiAgICAvKiogU2VydmVyLCBWaXJ0dWFsIEhVQiBzZWN1cml0eSwgYW5kIHBhY2tldCBsb2cgKi9cclxuICAgIFZwblN5c2xvZ1NhdmVUeXBlW1ZwblN5c2xvZ1NhdmVUeXBlW1wiU2VydmVyQW5kSHViQWxsTG9nXCJdID0gM10gPSBcIlNlcnZlckFuZEh1YkFsbExvZ1wiO1xyXG59KShWcG5TeXNsb2dTYXZlVHlwZSA9IGV4cG9ydHMuVnBuU3lzbG9nU2F2ZVR5cGUgfHwgKGV4cG9ydHMuVnBuU3lzbG9nU2F2ZVR5cGUgPSB7fSkpO1xyXG4vKiogU3lzbG9nIGNvbmZpZ3VyYXRpb24gKi9cclxudmFyIFZwblN5c2xvZ1NldHRpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAvKiogQ29uc3RydWN0b3IgZm9yIHRoZSAnVnBuU3lzbG9nU2V0dGluZycgY2xhc3M6IFN5c2xvZyBjb25maWd1cmF0aW9uICovXHJcbiAgICBmdW5jdGlvbiBWcG5TeXNsb2dTZXR0aW5nKGluaXQpIHtcclxuICAgICAgICAvKiogVGhlIGJlaGF2aW9yIG9mIHRoZSBzeXNsb2cgZnVuY3Rpb24gKi9cclxuICAgICAgICB0aGlzLlNhdmVUeXBlX3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFNwZWNpZnkgdGhlIGhvc3QgbmFtZSBvciBJUCBhZGRyZXNzIG9mIHRoZSBzeXNsb2cgc2VydmVyICovXHJcbiAgICAgICAgdGhpcy5Ib3N0bmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBTcGVjaWZ5IHRoZSBwb3J0IG51bWJlciBvZiB0aGUgc3lzbG9nIHNlcnZlciAqL1xyXG4gICAgICAgIHRoaXMuUG9ydF91MzIgPSAwO1xyXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gVnBuU3lzbG9nU2V0dGluZztcclxufSgpKTtcclxuZXhwb3J0cy5WcG5TeXNsb2dTZXR0aW5nID0gVnBuU3lzbG9nU2V0dGluZztcclxuLyoqIFZQTiBHYXRlIFNlcnZlciBDb25maWcgKi9cclxudmFyIFZwblZnc0NvbmZpZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5WZ3NDb25maWcnIGNsYXNzOiBWUE4gR2F0ZSBTZXJ2ZXIgQ29uZmlnICovXHJcbiAgICBmdW5jdGlvbiBWcG5WZ3NDb25maWcoaW5pdCkge1xyXG4gICAgICAgIC8qKiBBY3RpdmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuSXNFbmFibGVkX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogTWVzc2FnZSAqL1xyXG4gICAgICAgIHRoaXMuTWVzc2FnZV91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBPd25lciBuYW1lICovXHJcbiAgICAgICAgdGhpcy5Pd25lcl91dGYgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBBYnVzZSBlbWFpbCAqL1xyXG4gICAgICAgIHRoaXMuQWJ1c2VfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogTG9nIHNhdmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuTm9Mb2dfYm9vbCA9IGZhbHNlO1xyXG4gICAgICAgIC8qKiBTYXZlIGxvZyBwZXJtYW5lbnRseSAqL1xyXG4gICAgICAgIHRoaXMuTG9nUGVybWFuZW50X2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICAvKiogRW5hYmxlIHRoZSBMMlRQIFZQTiBmdW5jdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuRW5hYmxlTDJUUF9ib29sID0gZmFsc2U7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5WZ3NDb25maWc7XHJcbn0oKSk7XHJcbmV4cG9ydHMuVnBuVmdzQ29uZmlnID0gVnBuVmdzQ29uZmlnO1xyXG4vKiogUmVhZCBhIExvZyBmaWxlICovXHJcbnZhciBWcG5ScGNSZWFkTG9nRmlsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNSZWFkTG9nRmlsZScgY2xhc3M6IFJlYWQgYSBMb2cgZmlsZSAqL1xyXG4gICAgZnVuY3Rpb24gVnBuUnBjUmVhZExvZ0ZpbGUoaW5pdCkge1xyXG4gICAgICAgIC8qKiBTZXJ2ZXIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuU2VydmVyTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBGaWxlIFBhdGggKi9cclxuICAgICAgICB0aGlzLkZpbGVQYXRoX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9mZnNldCB0byBkb3dubG9hZC4gWW91IGhhdmUgdG8gY2FsbCB0aGUgUmVhZExvZ0ZpbGUgQVBJIG11bHRpcGxlIHRpbWVzIHRvIGRvd25sb2FkIHRoZSBlbnRpcmUgbG9nIGZpbGUgd2l0aCByZXF1ZXN0aW5nIGEgcGFydCBvZiB0aGUgZmlsZSBieSBzcGVjaWZ5aW5nIHRoZSBPZmZzZXRfdTMyIGZpZWxkLiAqL1xyXG4gICAgICAgIHRoaXMuT2Zmc2V0X3UzMiA9IDA7XHJcbiAgICAgICAgLyoqIFJlY2VpdmVkIGJ1ZmZlciAqL1xyXG4gICAgICAgIHRoaXMuQnVmZmVyX2JpbiA9IG5ldyBVaW50OEFycmF5KFtdKTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1JlYWRMb2dGaWxlO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1JlYWRMb2dGaWxlID0gVnBuUnBjUmVhZExvZ0ZpbGU7XHJcbi8qKiBSZW5hbWUgbGluayAqL1xyXG52YXIgVnBuUnBjUmVuYW1lTGluayA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKiBDb25zdHJ1Y3RvciBmb3IgdGhlICdWcG5ScGNSZW5hbWVMaW5rJyBjbGFzczogUmVuYW1lIGxpbmsgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1JlbmFtZUxpbmsoaW5pdCkge1xyXG4gICAgICAgIC8qKiBUaGUgVmlydHVhbCBIdWIgbmFtZSAqL1xyXG4gICAgICAgIHRoaXMuSHViTmFtZV9zdHIgPSBcIlwiO1xyXG4gICAgICAgIC8qKiBUaGUgb2xkIG5hbWUgb2YgdGhlIGNhc2NhZGUgY29ubmVjdGlvbiAqL1xyXG4gICAgICAgIHRoaXMuT2xkQWNjb3VudE5hbWVfdXRmID0gXCJcIjtcclxuICAgICAgICAvKiogVGhlIG5ldyBuYW1lIG9mIHRoZSBjYXNjYWRlIGNvbm5lY3Rpb24gKi9cclxuICAgICAgICB0aGlzLk5ld0FjY291bnROYW1lX3V0ZiA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNSZW5hbWVMaW5rO1xyXG59KCkpO1xyXG5leHBvcnRzLlZwblJwY1JlbmFtZUxpbmsgPSBWcG5ScGNSZW5hbWVMaW5rO1xyXG4vKiogT25saW5lIG9yIG9mZmxpbmUgdGhlIEhVQiAqL1xyXG52YXIgVnBuUnBjU2V0SHViT25saW5lID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NldEh1Yk9ubGluZScgY2xhc3M6IE9ubGluZSBvciBvZmZsaW5lIHRoZSBIVUIgKi9cclxuICAgIGZ1bmN0aW9uIFZwblJwY1NldEh1Yk9ubGluZShpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBWaXJ0dWFsIEh1YiBuYW1lICovXHJcbiAgICAgICAgdGhpcy5IdWJOYW1lX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgLyoqIE9ubGluZSAvIG9mZmxpbmUgZmxhZyAqL1xyXG4gICAgICAgIHRoaXMuT25saW5lX2Jvb2wgPSBmYWxzZTtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFZwblJwY1NldEh1Yk9ubGluZTtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXRIdWJPbmxpbmUgPSBWcG5ScGNTZXRIdWJPbmxpbmU7XHJcbi8qKiBTZXQgUGFzc3dvcmQgKi9cclxudmFyIFZwblJwY1NldFBhc3N3b3JkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgLyoqIENvbnN0cnVjdG9yIGZvciB0aGUgJ1ZwblJwY1NldFBhc3N3b3JkJyBjbGFzczogU2V0IFBhc3N3b3JkICovXHJcbiAgICBmdW5jdGlvbiBWcG5ScGNTZXRQYXNzd29yZChpbml0KSB7XHJcbiAgICAgICAgLyoqIFRoZSBwbGFpbnRleHQgcGFzc3dvcmQgKi9cclxuICAgICAgICB0aGlzLlBsYWluVGV4dFBhc3N3b3JkX3N0ciA9IFwiXCI7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBWcG5ScGNTZXRQYXNzd29yZDtcclxufSgpKTtcclxuZXhwb3J0cy5WcG5ScGNTZXRQYXNzd29yZCA9IFZwblJwY1NldFBhc3N3b3JkO1xyXG4vLyAtLS0gVXRpbGl0eSBjb2RlcyAtLS1cclxuLyoqIEpTT04tUlBDIHJlcXVlc3QgY2xhc3MuIFNlZSBodHRwczovL3d3dy5qc29ucnBjLm9yZy9zcGVjaWZpY2F0aW9uICovXHJcbnZhciBKc29uUnBjUmVxdWVzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW0sIGlkKSB7XHJcbiAgICAgICAgaWYgKG1ldGhvZCA9PT0gdm9pZCAwKSB7IG1ldGhvZCA9IFwiXCI7IH1cclxuICAgICAgICBpZiAocGFyYW0gPT09IHZvaWQgMCkgeyBwYXJhbSA9IG51bGw7IH1cclxuICAgICAgICBpZiAoaWQgPT09IHZvaWQgMCkgeyBpZCA9IFwiXCI7IH1cclxuICAgICAgICB0aGlzLmpzb25ycGMgPSBcIjIuMFwiO1xyXG4gICAgICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xyXG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW07XHJcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIEpzb25ScGNSZXF1ZXN0O1xyXG59KCkpO1xyXG5leHBvcnRzLkpzb25ScGNSZXF1ZXN0ID0gSnNvblJwY1JlcXVlc3Q7XHJcbi8qKiBKU09OLVJQQyBlcnJvciBjbGFzcy4gU2VlIGh0dHBzOi8vd3d3Lmpzb25ycGMub3JnL3NwZWNpZmljYXRpb24gKi9cclxudmFyIEpzb25ScGNFcnJvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNFcnJvcihjb2RlLCBtZXNzYWdlLCBkYXRhKSB7XHJcbiAgICAgICAgaWYgKGNvZGUgPT09IHZvaWQgMCkgeyBjb2RlID0gMDsgfVxyXG4gICAgICAgIGlmIChtZXNzYWdlID09PSB2b2lkIDApIHsgbWVzc2FnZSA9IFwiXCI7IH1cclxuICAgICAgICBpZiAoZGF0YSA9PT0gdm9pZCAwKSB7IGRhdGEgPSBudWxsOyB9XHJcbiAgICAgICAgdGhpcy5jb2RlID0gY29kZTtcclxuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xyXG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSnNvblJwY0Vycm9yO1xyXG59KCkpO1xyXG5leHBvcnRzLkpzb25ScGNFcnJvciA9IEpzb25ScGNFcnJvcjtcclxuLyoqIEpTT04tUlBDIHJlc3BvbnNlIGNsYXNzIHdpdGggZ2VuZXJpY3MgKi9cclxudmFyIEpzb25ScGNSZXNwb25zZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEpzb25ScGNSZXNwb25zZSgpIHtcclxuICAgICAgICB0aGlzLmpzb25ycGMgPSBcIjIuMFwiO1xyXG4gICAgICAgIHRoaXMucmVzdWx0ID0gbnVsbDtcclxuICAgICAgICB0aGlzLmVycm9yID0gbnVsbDtcclxuICAgICAgICB0aGlzLmlkID0gXCJcIjtcclxuICAgIH1cclxuICAgIHJldHVybiBKc29uUnBjUmVzcG9uc2U7XHJcbn0oKSk7XHJcbmV4cG9ydHMuSnNvblJwY1Jlc3BvbnNlID0gSnNvblJwY1Jlc3BvbnNlO1xyXG4vKiogSlNPTi1SUEMgY2xpZW50IGNsYXNzLiBTZWUgaHR0cHM6Ly93d3cuanNvbnJwYy5vcmcvc3BlY2lmaWNhdGlvbiAqL1xyXG52YXIgSnNvblJwY0NsaWVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgIC8qKlxyXG4gICAgICogSlNPTi1SUEMgY2xpZW50IGNsYXNzIGNvbnN0cnVjdG9yXHJcbiAgICAgKiBAcGFyYW0gdXJsIFRoZSBVUkxcclxuICAgICAqIEBwYXJhbSBoZWFkZXJzIEFkZGl0aW9uYWwgSFRUUCBoZWFkZXJzXHJcbiAgICAgKiBAcGFyYW0gc2VuZF9jcmVkZW50aWFsIFNldCB0cnVlIHRvIHVzZSB0aGUgc2FtZSBjcmVkZW50aWFsIHdpdGggdGhlIGJyb3dzaW5nIHdlYiBzaXRlLiBWYWxpZCBvbmx5IGlmIHRoZSBjb2RlIGlzIHJ1bm5pbmcgb24gdGhlIHdlYiBicm93c2VyLlxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBKc29uUnBjQ2xpZW50KHVybCwgaGVhZGVycywgc2VuZF9jcmVkZW50aWFsLCBub2RlanNfaHR0cHNfY2xpZW50X3JlamVjdF91bnRydXN0ZWRfc2VydmVyX2NlcnQpIHtcclxuICAgICAgICB0aGlzLkJhc2VVcmwgPSB1cmw7XHJcbiAgICAgICAgdGhpcy5oZWFkZXJzID0gaGVhZGVycztcclxuICAgICAgICB0aGlzLmNsaWVudCA9IG5ldyBIdHRwQ2xpZW50KCk7XHJcbiAgICAgICAgdGhpcy5jbGllbnQuU2VuZENyZWRlbnRpYWwgPSBzZW5kX2NyZWRlbnRpYWw7XHJcbiAgICAgICAgdGhpcy5jbGllbnQuTm9kZUpTX0hUVFBTX0NsaWVudF9SZWplY3RfVW5hdXRob3JpemVkID0gbm9kZWpzX2h0dHBzX2NsaWVudF9yZWplY3RfdW50cnVzdGVkX3NlcnZlcl9jZXJ0O1xyXG4gICAgfVxyXG4gICAgLyoqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjb252ZXJ0IGFueSBvYmplY3QgdG8gSlNPTiBzdHJpbmcgKi9cclxuICAgIEpzb25ScGNDbGllbnQuT2JqZWN0VG9Kc29uID0gZnVuY3Rpb24gKG9iaikge1xyXG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XHJcbiAgICAgICAgICAgIGlmIChrZXkuZW5kc1dpdGgoXCJfYmluXCIpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVXRpbF9CYXNlNjRfRW5jb2RlKHZhbHVlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICAgfSwgNCk7XHJcbiAgICB9O1xyXG4gICAgLyoqIEEgdXRpbGl0eSBmdW5jdGlvbiB0byBjb252ZXJ0IEpTT04gc3RyaW5nIHRvIG9iamVjdCAqL1xyXG4gICAgSnNvblJwY0NsaWVudC5Kc29uVG9PYmplY3QgPSBmdW5jdGlvbiAoc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoc3RyLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xyXG4gICAgICAgICAgICBpZiAoa2V5LmVuZHNXaXRoKFwiX2JpblwiKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFV0aWxfQmFzZTY0X0RlY29kZSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoa2V5LmVuZHNXaXRoKFwiX2R0XCIpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIENhbGwgYSBzaW5nbGUgUlBDIGNhbGwgKHdpdGhvdXQgZXJyb3IgY2hlY2spLiBZb3UgY2FuIHdhaXQgZm9yIHRoZSByZXNwb25zZSB3aXRoIFByb21pc2U8c3RyaW5nPiBvciBhd2FpdCBzdGF0ZW1lbnQuXHJcbiAgICAgKiBAcGFyYW0gbWV0aG9kX25hbWUgVGhlIG5hbWUgb2YgUlBDIG1ldGhvZFxyXG4gICAgICogQHBhcmFtIHBhcmFtIFRoZSBwYXJhbWV0ZXJzXHJcbiAgICAgKi9cclxuICAgIEpzb25ScGNDbGllbnQucHJvdG90eXBlLkNhbGxJbnRlcm5hbEFzeW5jID0gZnVuY3Rpb24gKG1ldGhvZF9uYW1lLCBwYXJhbSkge1xyXG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIGlkLCByZXEsIHJlcV9zdHJpbmcsIGh0dHBfcmVzcG9uc2UsIHJldF9zdHJpbmc7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gXCIxXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcSA9IG5ldyBKc29uUnBjUmVxdWVzdChtZXRob2RfbmFtZSwgcGFyYW0sIGlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxX3N0cmluZyA9IEpzb25ScGNDbGllbnQuT2JqZWN0VG9Kc29uKHJlcSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWJ1Z19tb2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIi0tLSBSUEMgUmVxdWVzdCBCb2R5IC0tLVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlcV9zdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgdGhpcy5jbGllbnQuUG9zdEFzeW5jKHRoaXMuQmFzZVVybCwgdGhpcy5oZWFkZXJzLCByZXFfc3RyaW5nLCBcImFwcGxpY2F0aW9uL2pzb25cIildO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cF9yZXNwb25zZSA9IF9hLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0X3N0cmluZyA9IGh0dHBfcmVzcG9uc2UuQm9keTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlYnVnX21vZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiLS0tIFJQQyBSZXNwb25zZSBCb2R5IC0tLVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJldF9zdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovLCByZXRfc3RyaW5nXTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9O1xyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsIGEgc2luZ2xlIFJQQyBjYWxsICh3aXRoIGVycm9yIGNoZWNrKS4gWW91IGNhbiB3YWl0IGZvciB0aGUgcmVzcG9uc2Ugd2l0aCBQcm9taXNlPFRSZXN1bHQ+IG9yIGF3YWl0IHN0YXRlbWVudC4gSW4gdGhlIGNhc2Ugb2YgZXJyb3IsIGl0IHdpbGwgYmUgdGhyb3duLlxyXG4gICAgICogQHBhcmFtIG1ldGhvZF9uYW1lIFRoZSBuYW1lIG9mIFJQQyBtZXRob2RcclxuICAgICAqIEBwYXJhbSBwYXJhbSBUaGUgcGFyYW1ldGVyc1xyXG4gICAgICovXHJcbiAgICBKc29uUnBjQ2xpZW50LnByb3RvdHlwZS5DYWxsQXN5bmMgPSBmdW5jdGlvbiAobWV0aG9kX25hbWUsIHBhcmFtKSB7XHJcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmV0X3N0cmluZywgcmV0O1xyXG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQgLyp5aWVsZCovLCB0aGlzLkNhbGxJbnRlcm5hbEFzeW5jKG1ldGhvZF9uYW1lLCBwYXJhbSldO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0X3N0cmluZyA9IF9hLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0ID0gSlNPTi5wYXJzZShyZXRfc3RyaW5nKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzX251bGwocmV0LmVycm9yKSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBKc29uUnBjRXhjZXB0aW9uKHJldC5lcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIHJldC5yZXN1bHRdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gSnNvblJwY0NsaWVudDtcclxufSgpKTtcclxuZXhwb3J0cy5Kc29uUnBjQ2xpZW50ID0gSnNvblJwY0NsaWVudDtcclxuLyoqIEpTT04tUlBDIGV4Y2VwdGlvbiBjbGFzcyAqL1xyXG52YXIgSnNvblJwY0V4Y2VwdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcclxuICAgIF9fZXh0ZW5kcyhKc29uUnBjRXhjZXB0aW9uLCBfc3VwZXIpO1xyXG4gICAgZnVuY3Rpb24gSnNvblJwY0V4Y2VwdGlvbihlcnJvcikge1xyXG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIFwiQ29kZT1cIiArIGVycm9yLmNvZGUgKyBcIiwgTWVzc2FnZT1cIiArIGVycm9yLm1lc3NhZ2UpIHx8IHRoaXM7XHJcbiAgICAgICAgX3RoaXMuRXJyb3IgPSBlcnJvcjtcclxuICAgICAgICByZXR1cm4gX3RoaXM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSnNvblJwY0V4Y2VwdGlvbjtcclxufShFcnJvcikpO1xyXG5leHBvcnRzLkpzb25ScGNFeGNlcHRpb24gPSBKc29uUnBjRXhjZXB0aW9uO1xyXG4vKiogSFRUUCBjbGllbnQgZXhjZXB0aW9uIGNsYXNzICovXHJcbnZhciBIdHRwQ2xpZW50RXhjZXB0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xyXG4gICAgX19leHRlbmRzKEh0dHBDbGllbnRFeGNlcHRpb24sIF9zdXBlcik7XHJcbiAgICBmdW5jdGlvbiBIdHRwQ2xpZW50RXhjZXB0aW9uKG1lc3NhZ2UpIHtcclxuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgbWVzc2FnZSkgfHwgdGhpcztcclxuICAgIH1cclxuICAgIHJldHVybiBIdHRwQ2xpZW50RXhjZXB0aW9uO1xyXG59KEVycm9yKSk7XHJcbmV4cG9ydHMuSHR0cENsaWVudEV4Y2VwdGlvbiA9IEh0dHBDbGllbnRFeGNlcHRpb247XHJcbi8qKiBIVFRQIGNsaWVudCByZXNwb25zZSBjbGFzcyAqL1xyXG52YXIgSHR0cENsaWVudFJlc3BvbnNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gSHR0cENsaWVudFJlc3BvbnNlKCkge1xyXG4gICAgICAgIHRoaXMuQm9keSA9IFwiXCI7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gSHR0cENsaWVudFJlc3BvbnNlO1xyXG59KCkpO1xyXG5leHBvcnRzLkh0dHBDbGllbnRSZXNwb25zZSA9IEh0dHBDbGllbnRSZXNwb25zZTtcclxuLyoqIEFuIEhUVFAgY2xpZW50IHdoaWNoIGNhbiBiZSB1c2VkIGluIGJvdGggd2ViIGJyb3dzZXJzIGFuZCBOb2RlLmpzICovXHJcbnZhciBIdHRwQ2xpZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gSHR0cENsaWVudCgpIHtcclxuICAgICAgICB0aGlzLlRpbWVvdXRNc2VjcyA9IDYwICogNSAqIDEwMDA7XHJcbiAgICAgICAgdGhpcy5TZW5kQ3JlZGVudGlhbCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5Ob2RlSlNfSFRUUFNfQ2xpZW50X1JlamVjdF9VbmF1dGhvcml6ZWQgPSBmYWxzZTtcclxuICAgIH1cclxuICAgIC8qKiBQb3N0IG1ldGhvZC4gSW4gd2ViIGJyb3dzZXJzIHRoaXMgZnVuY3Rpb24gd2lsbCBwcm9jZXNzIHRoZSByZXF1ZXN0IGJ5IGl0c2VsZi4gSW4gTm9kZS5qcyB0aGlzIGZ1bmN0aW9uIHdpbGwgY2FsbCBQb3N0QXN5bmNfTm9kZUpTKCkgaW5zdGVhZC4gKi9cclxuICAgIEh0dHBDbGllbnQucHJvdG90eXBlLlBvc3RBc3luYyA9IGZ1bmN0aW9uICh1cmwsIGhlYWRlcnMsIHJlcV9ib2R5LCByZXFfbWVkaWFfdHlwZSkge1xyXG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIGZldGNoX2hlYWRlcl9saXN0LCBfaSwgX2EsIG5hbWVfMSwgZmV0Y2hfaW5pdCwgZmV0Y2hfcmVzcG9uc2UsIHJldCwgX2I7XHJcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2MpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2MubGFiZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc19ub2RlX2pzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgdGhpcy5Qb3N0QXN5bmNfTm9kZUpTKHVybCwgaGVhZGVycywgcmVxX2JvZHksIHJlcV9tZWRpYV90eXBlKV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZmV0Y2hfaGVhZGVyX2xpc3QgPSBuZXcgSGVhZGVycygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgX2EgPSBPYmplY3Qua2V5cyhoZWFkZXJzKTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVfMSA9IF9hW19pXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoX2hlYWRlcl9saXN0LmFwcGVuZChuYW1lXzEsIGhlYWRlcnNbbmFtZV8xXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZmV0Y2hfaW5pdCA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU6IFwiY29yc1wiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczogZmV0Y2hfaGVhZGVyX2xpc3QsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVkZW50aWFsczogKHRoaXMuU2VuZENyZWRlbnRpYWwgPyBcImluY2x1ZGVcIiA6IFwib21pdFwiKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZTogXCJuby1jYWNoZVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGFsaXZlOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkaXJlY3Q6IFwiZm9sbG93XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5OiByZXFfYm9keVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBmZXRjaCh1cmwsIGZldGNoX2luaXQpXTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoX3Jlc3BvbnNlID0gX2Muc2VudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmV0Y2hfcmVzcG9uc2Uub2sgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSHR0cENsaWVudEV4Y2VwdGlvbihcIkhUVFAgRXJyb3I6IFwiICsgZmV0Y2hfcmVzcG9uc2Uuc3RhdHVzICsgXCIgXCIgKyBmZXRjaF9yZXNwb25zZS5zdGF0dXNUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXQgPSBuZXcgSHR0cENsaWVudFJlc3BvbnNlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIF9iID0gcmV0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBmZXRjaF9yZXNwb25zZS50ZXh0KCldO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgX2IuQm9keSA9IF9jLnNlbnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIHJldF07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIC8qKiBQb3N0IG1ldGhvZCBmb3IgTm9kZS5qcy4gKi9cclxuICAgIEh0dHBDbGllbnQucHJvdG90eXBlLlBvc3RBc3luY19Ob2RlSlMgPSBmdW5jdGlvbiAodXJsLCBoZWFkZXJzLCByZXFfYm9keSwgcmVxX21lZGlhX3R5cGUpIHtcclxuICAgICAgICB2YXIgaHR0cHMgPSByZXF1aXJlKFwiaHR0cHNcIik7XHJcbiAgICAgICAgdmFyIGtlZXBBbGl2ZUFnZW50ID0gbmV3IGh0dHBzLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pO1xyXG4gICAgICAgIHZhciB1cmxwYXJzZSA9IHJlcXVpcmUoXCJ1cmxcIik7XHJcbiAgICAgICAgdmFyIHVybG9iaiA9IHVybHBhcnNlLnBhcnNlKHVybCk7XHJcbiAgICAgICAgaWYgKGlzX251bGwodXJsb2JqLmhvc3QpKVxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVUkwgaXMgaW52YWxpZC5cIik7XHJcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIGhvc3Q6IHVybG9iai5ob3N0bmFtZSxcclxuICAgICAgICAgICAgcG9ydDogdXJsb2JqLnBvcnQsXHJcbiAgICAgICAgICAgIHBhdGg6IHVybG9iai5wYXRoLFxyXG4gICAgICAgICAgICByZWplY3RVbmF1dGhvcml6ZWQ6IHRoaXMuTm9kZUpTX0hUVFBTX0NsaWVudF9SZWplY3RfVW5hdXRob3JpemVkLFxyXG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxyXG4gICAgICAgICAgICB0aW1lb3V0OiB0aGlzLlRpbWVvdXRNc2VjcyxcclxuICAgICAgICAgICAgYWdlbnQ6IGtlZXBBbGl2ZUFnZW50XHJcbiAgICAgICAgfTtcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgICAgICB2YXIgcmVxID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBmdW5jdGlvbiAocmVzKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAocmVzLnN0YXR1c0NvZGUgIT09IDIwMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgSHR0cENsaWVudEV4Y2VwdGlvbihcIkhUVFAgRXJyb3I6IFwiICsgcmVzLnN0YXR1c0NvZGUgKyBcIiBcIiArIHJlcy5zdGF0dXNNZXNzYWdlKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgcmVjdl9zdHIgPSBcIlwiO1xyXG4gICAgICAgICAgICAgICAgcmVzLm9uKFwiZGF0YVwiLCBmdW5jdGlvbiAoYm9keSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlY3Zfc3RyICs9IGJvZHk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJlcy5vbihcImVuZFwiLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJldCA9IG5ldyBIdHRwQ2xpZW50UmVzcG9uc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICByZXQuQm9keSA9IHJlY3Zfc3RyO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUocmV0KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KS5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnIpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBPYmplY3Qua2V5cyhoZWFkZXJzKTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcclxuICAgICAgICAgICAgICAgIHZhciBuYW1lXzIgPSBfYVtfaV07XHJcbiAgICAgICAgICAgICAgICByZXEuc2V0SGVhZGVyKG5hbWVfMiwgIWlzX251bGwoaGVhZGVyc1tuYW1lXzJdKSA/IGhlYWRlcnNbbmFtZV8yXSA6IFwiXCIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlcS5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgcmVxX21lZGlhX3R5cGUpO1xyXG4gICAgICAgICAgICByZXEuc2V0SGVhZGVyKFwiQ29udGVudC1MZW5ndGhcIiwgQnVmZmVyLmJ5dGVMZW5ndGgocmVxX2JvZHkpKTtcclxuICAgICAgICAgICAgcmVxLndyaXRlKHJlcV9ib2R5KTtcclxuICAgICAgICAgICAgcmVxLmVuZCgpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBIdHRwQ2xpZW50O1xyXG59KCkpO1xyXG5leHBvcnRzLkh0dHBDbGllbnQgPSBIdHRwQ2xpZW50O1xyXG4vLy8vLy8vLyBCRUdJTjogQmFzZTY0IGVuY29kZSAvIGRlY29kZSB1dGlsaXR5IGZ1bmN0aW9ucyBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9iZWF0Z2FtbWl0L2Jhc2U2NC1qc1xyXG4vLyBUaGUgTUlUIExpY2Vuc2UoTUlUKVxyXG4vLyBDb3B5cmlnaHQoYykgMjAxNFxyXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XHJcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxyXG4vLyAgICAgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xyXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZCAvIG9yIHNlbGxcclxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXHJcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XHJcbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXHJcbi8vICAgICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cclxuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxyXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcclxuLy8gICAgIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuSU4gTk8gRVZFTlQgU0hBTEwgVEhFXHJcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcclxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcclxuLy8gICAgIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cclxuLy8gVEhFIFNPRlRXQVJFLlxyXG52YXIgbG9va3VwID0gW107XHJcbnZhciByZXZMb29rdXAgPSBbXTtcclxudmFyIGNvZGUgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky9cIjtcclxuZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNvZGUubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgIGxvb2t1cFtpXSA9IGNvZGVbaV07XHJcbiAgICByZXZMb29rdXBbY29kZS5jaGFyQ29kZUF0KGkpXSA9IGk7XHJcbn1cclxuLy8gU3VwcG9ydCBkZWNvZGluZyBVUkwtc2FmZSBiYXNlNjQgc3RyaW5ncywgYXMgTm9kZS5qcyBkb2VzLlxyXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXHJcbnJldkxvb2t1cFtcIi1cIi5jaGFyQ29kZUF0KDApXSA9IDYyO1xyXG5yZXZMb29rdXBbXCJfXCIuY2hhckNvZGVBdCgwKV0gPSA2MztcclxuZnVuY3Rpb24gZ2V0TGVucyhiNjQpIHtcclxuICAgIHZhciBsZW4gPSBiNjQubGVuZ3RoO1xyXG4gICAgaWYgKGxlbiAlIDQgPiAwKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNFwiKTtcclxuICAgIH1cclxuICAgIC8vIFRyaW0gb2ZmIGV4dHJhIGJ5dGVzIGFmdGVyIHBsYWNlaG9sZGVyIGJ5dGVzIGFyZSBmb3VuZFxyXG4gICAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vYmVhdGdhbW1pdC9iYXNlNjQtanMvaXNzdWVzLzQyXHJcbiAgICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZihcIj1cIik7XHJcbiAgICBpZiAodmFsaWRMZW4gPT09IC0xKVxyXG4gICAgICAgIHZhbGlkTGVuID0gbGVuO1xyXG4gICAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cclxuICAgICAgICA/IDBcclxuICAgICAgICA6IDQgLSAodmFsaWRMZW4gJSA0KTtcclxuICAgIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl07XHJcbn1cclxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXHJcbmZ1bmN0aW9uIGJ5dGVMZW5ndGgoYjY0KSB7XHJcbiAgICB2YXIgbGVucyA9IGdldExlbnMoYjY0KTtcclxuICAgIHZhciB2YWxpZExlbiA9IGxlbnNbMF07XHJcbiAgICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXTtcclxuICAgIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlbjtcclxufVxyXG5mdW5jdGlvbiBfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pIHtcclxuICAgIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlbjtcclxufVxyXG5mdW5jdGlvbiBVdGlsX0Jhc2U2NF9EZWNvZGUoYjY0KSB7XHJcbiAgICB2YXIgdG1wO1xyXG4gICAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NCk7XHJcbiAgICB2YXIgdmFsaWRMZW4gPSBsZW5zWzBdO1xyXG4gICAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV07XHJcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoX2J5dGVMZW5ndGgoYjY0LCB2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuKSk7XHJcbiAgICB2YXIgY3VyQnl0ZSA9IDA7XHJcbiAgICAvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXHJcbiAgICB2YXIgbGVuID0gcGxhY2VIb2xkZXJzTGVuID4gMFxyXG4gICAgICAgID8gdmFsaWRMZW4gLSA0XHJcbiAgICAgICAgOiB2YWxpZExlbjtcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcclxuICAgICAgICB0bXAgPVxyXG4gICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxOCkgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDEyKSB8XHJcbiAgICAgICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPDwgNikgfFxyXG4gICAgICAgICAgICAgICAgcmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAzKV07XHJcbiAgICAgICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDE2KSAmIDB4RkY7XHJcbiAgICAgICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRjtcclxuICAgICAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkY7XHJcbiAgICB9XHJcbiAgICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAyKSB7XHJcbiAgICAgICAgdG1wID1cclxuICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMikgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldID4+IDQpO1xyXG4gICAgICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRjtcclxuICAgIH1cclxuICAgIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDEpIHtcclxuICAgICAgICB0bXAgPVxyXG4gICAgICAgICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfFxyXG4gICAgICAgICAgICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDQpIHxcclxuICAgICAgICAgICAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKTtcclxuICAgICAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGO1xyXG4gICAgICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRjtcclxuICAgIH1cclxuICAgIHJldHVybiBhcnI7XHJcbn1cclxuZXhwb3J0cy5VdGlsX0Jhc2U2NF9EZWNvZGUgPSBVdGlsX0Jhc2U2NF9EZWNvZGU7XHJcbmZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NChudW0pIHtcclxuICAgIHJldHVybiBsb29rdXBbbnVtID4+IDE4ICYgMHgzRl0gK1xyXG4gICAgICAgIGxvb2t1cFtudW0gPj4gMTIgJiAweDNGXSArXHJcbiAgICAgICAgbG9va3VwW251bSA+PiA2ICYgMHgzRl0gK1xyXG4gICAgICAgIGxvb2t1cFtudW0gJiAweDNGXTtcclxufVxyXG5mdW5jdGlvbiBlbmNvZGVDaHVuayh1aW50OCwgc3RhcnQsIGVuZCkge1xyXG4gICAgdmFyIHRtcDtcclxuICAgIHZhciBvdXRwdXQgPSBbXTtcclxuICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSArPSAzKSB7XHJcbiAgICAgICAgdG1wID1cclxuICAgICAgICAgICAgKCh1aW50OFtpXSA8PCAxNikgJiAweEZGMDAwMCkgK1xyXG4gICAgICAgICAgICAgICAgKCh1aW50OFtpICsgMV0gPDwgOCkgJiAweEZGMDApICtcclxuICAgICAgICAgICAgICAgICh1aW50OFtpICsgMl0gJiAweEZGKTtcclxuICAgICAgICBvdXRwdXQucHVzaCh0cmlwbGV0VG9CYXNlNjQodG1wKSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gb3V0cHV0LmpvaW4oXCJcIik7XHJcbn1cclxuZnVuY3Rpb24gVXRpbF9CYXNlNjRfRW5jb2RlKHVpbnQ4KSB7XHJcbiAgICB2YXIgdG1wO1xyXG4gICAgdmFyIGxlbiA9IHVpbnQ4Lmxlbmd0aDtcclxuICAgIHZhciBleHRyYUJ5dGVzID0gbGVuICUgMzsgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcclxuICAgIHZhciBwYXJ0cyA9IFtdO1xyXG4gICAgdmFyIG1heENodW5rTGVuZ3RoID0gMTYzODM7IC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xyXG4gICAgLy8gZ28gdGhyb3VnaCB0aGUgYXJyYXkgZXZlcnkgdGhyZWUgYnl0ZXMsIHdlJ2xsIGRlYWwgd2l0aCB0cmFpbGluZyBzdHVmZiBsYXRlclxyXG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xyXG4gICAgICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsodWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKSkpO1xyXG4gICAgfVxyXG4gICAgLy8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xyXG4gICAgaWYgKGV4dHJhQnl0ZXMgPT09IDEpIHtcclxuICAgICAgICB0bXAgPSB1aW50OFtsZW4gLSAxXTtcclxuICAgICAgICBwYXJ0cy5wdXNoKGxvb2t1cFt0bXAgPj4gMl0gK1xyXG4gICAgICAgICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcclxuICAgICAgICAgICAgXCI9PVwiKTtcclxuICAgIH1cclxuICAgIGVsc2UgaWYgKGV4dHJhQnl0ZXMgPT09IDIpIHtcclxuICAgICAgICB0bXAgPSAodWludDhbbGVuIC0gMl0gPDwgOCkgKyB1aW50OFtsZW4gLSAxXTtcclxuICAgICAgICBwYXJ0cy5wdXNoKGxvb2t1cFt0bXAgPj4gMTBdICtcclxuICAgICAgICAgICAgbG9va3VwWyh0bXAgPj4gNCkgJiAweDNGXSArXHJcbiAgICAgICAgICAgIGxvb2t1cFsodG1wIDw8IDIpICYgMHgzRl0gK1xyXG4gICAgICAgICAgICBcIj1cIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcGFydHMuam9pbihcIlwiKTtcclxufVxyXG5leHBvcnRzLlV0aWxfQmFzZTY0X0VuY29kZSA9IFV0aWxfQmFzZTY0X0VuY29kZTtcclxuLy8vLy8vLy8gRU5EOiBCYXNlNjQgZW5jb2RlIC8gZGVjb2RlIHV0aWxpdHkgZnVuY3Rpb25zIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzXHJcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXZwbnJwYy5qcy5tYXAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBIiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/vpnrpc/dist/vpnrpc.js\n"); /***/ }), From e4330ca71ab0b97c9b90e6aee151e2a301d6226f Mon Sep 17 00:00:00 2001 From: hiura Date: Wed, 28 Jun 2023 23:18:09 +0900 Subject: [PATCH 03/63] bind outgoing connection --- src/Cedar/CM.c | 61 +++++++++ src/Cedar/Client.c | 10 +- src/Cedar/Connection.h | 2 + src/Cedar/Protocol.c | 122 ++++++++++++++++-- src/Cedar/Protocol.h | 9 ++ src/Cedar/SMInner.h | 5 +- src/Cedar/Session.c | 1 + src/Cedar/Session.h | 1 + src/Mayaqua/Network.c | 213 +++++++++++++++++++++++++++++++- src/Mayaqua/Network.h | 14 +++ src/Mayaqua/Proxy.c | 40 +++++- src/Mayaqua/Proxy.h | 7 ++ src/PenCore/PenCore.rc | 20 +-- src/PenCore/resource.h | 1 + src/bin/hamcore/strtable_en.stb | 1 + src/bin/hamcore/strtable_ja.stb | 1 + 16 files changed, 479 insertions(+), 29 deletions(-) diff --git a/src/Cedar/CM.c b/src/Cedar/CM.c index 42a2b412..6d535bc2 100644 --- a/src/Cedar/CM.c +++ b/src/Cedar/CM.c @@ -6150,6 +6150,7 @@ void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite) t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode; t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode; t->ClientOption->DisableQoS = old_option->DisableQoS; + t->ClientOption->BindLocalIP = old_option->BindLocalIP;// Source IP address for outgoing connection // Inherit the authentication data CiFreeClientAuth(t->ClientAuth); @@ -6456,9 +6457,54 @@ void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a) Disable(hWnd, R_BRIDGE); Disable(hWnd, R_MONITOR); Disable(hWnd, R_NO_ROUTING); +#if TYPE_BINDLOCALIP + Disable(hWnd, E_BIND_LOCALIP);// Source IP address for outgoing connection +#endif + } } +#if TYPE_BINDLOCALIP +// Set the value of the IP type +void SetIp(HWND hWnd, UINT id, IP* ip) +{ + char tmp[MAX_SIZE]; + // Validate arguments + if (hWnd == NULL || ip == NULL) + { + return; + } + + IPToStr(tmp, sizeof(tmp), ip); + SetTextA(hWnd, id, tmp); +} + +// Get an IP address +bool GetIp(HWND hWnd, UINT id, IP* ip) +{ + char tmp[MAX_SIZE]; + // Validate arguments + if (hWnd == NULL || ip == NULL) + { + return false; + } + + Zero(ip, sizeof(IP)); + + if (GetTxtA(hWnd, id, tmp, sizeof(tmp)) == false) + { + return false; + } + + if (StrToIP(ip, tmp) == false) + { + return false; + } + + return true; +} +#endif + // Advanced Settings dialog procedure UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { @@ -6495,6 +6541,9 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking); Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS); Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration); +#if TYPE_BINDLOCALIP + SetIp(hWnd, E_BIND_LOCALIP, &a->ClientOption->BindLocalIP);// Source IP address for outgoing connection +#endif // Select the Connection Mode if (a->LinkMode == false) @@ -6542,6 +6591,15 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa Focus(hWnd, E_INTERVAL); break; } +#if TYPE_BINDLOCALIP + // Source IP address for outgoing connection + IP tmpIP; + if (GetIp(hWnd, E_BIND_LOCALIP, &tmpIP) == false) + { + FocusEx(hWnd, E_BIND_LOCALIP); + break; + } +#endif a->ClientOption->MaxConnection = num; a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL); @@ -6559,6 +6617,9 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING); a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS); a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP); +#if TYPE_BINDLOCALIP + a->ClientOption->BindLocalIP = tmpIP;// Source IP address for outgoing connection +#endif if (a->LinkMode) { diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c index a4175a3c..3e4c26d4 100644 --- a/src/Cedar/Client.c +++ b/src/Cedar/Client.c @@ -4342,6 +4342,9 @@ void InRpcClientOption(CLIENT_OPTION *c, PACK *p) PackGetStr(p, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader)); PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName)); PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName)); +#if TYPE_BINDLOCALIP + PackGetIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection +#endif c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false; c->UseCompress = PackGetInt(p, "UseCompress") ? true : false; c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false; @@ -4402,6 +4405,9 @@ void OutRpcClientOption(PACK *p, CLIENT_OPTION *c) PackAddBool(p, "FromAdminPack", c->FromAdminPack); PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration); PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE); +#if TYPE_BINDLOCALIP + PackAddIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection +#endif } // CLIENT_AUTH @@ -9296,7 +9302,8 @@ CLIENT_OPTION *CiLoadClientOption(FOLDER *f) o->DisableQoS = CfgGetBool(f, "DisableQoS"); o->FromAdminPack = CfgGetBool(f, "FromAdminPack"); o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration"); - + CfgGetIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection + b = CfgGetBuf(f, "HostUniqueKey"); if (b != NULL) { @@ -9850,6 +9857,7 @@ void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o) CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode); CfgAddBool(f, "DisableQoS", o->DisableQoS); CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration); + CfgAddIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection if (o->FromAdminPack) { diff --git a/src/Cedar/Connection.h b/src/Cedar/Connection.h index 16c44f4b..d691fcdb 100644 --- a/src/Cedar/Connection.h +++ b/src/Cedar/Connection.h @@ -58,6 +58,7 @@ struct RC4_KEY_PAIR UCHAR ServerToClientKey[16]; UCHAR ClientToServerKey[16]; }; +#define TYPE_BINDLOCALIP 1 // Enable HMI user to edit Source IP address for outgoing connection // Client Options // Do not change item size or order and only add new items at the end! @@ -106,6 +107,7 @@ struct CLIENT_OPTION UCHAR HostUniqueKey[SHA1_SIZE]; // Host unique key char CustomHttpHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; // Custom HTTP proxy header char HintStr[MAX_HOST_NAME_LEN + 1]; // Hint string for NAT-T + IP BindLocalIP; // Source IP address for outgoing connection }; // Client authentication data diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index e2efd2b9..7eb98ea8 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -6219,6 +6219,8 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) { volatile bool *cancel_flag = NULL; char hostname[MAX_HOST_NAME_LEN]; + char localaddr[MAX_HOST_NAME_LEN]; + bool save_resolved_ip = false; CLIENT_OPTION *o; SESSION *sess; @@ -6278,10 +6280,37 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) if (o->PortUDP == 0) { + IP *localIP; + IP tmpIP; + UINT localport = BIND_LOCALPORT_NULL; + + // Top of Bind outgoing connection + // Decide the binding operation which is explicitly executed on the client-side + + // In the case of first TCP/IP connection + if (additional_connect == false) { + if (sess->ClientOption->NoRoutingTracking == false) { + StrToIP(&tmpIP, "0::0"); // Zero address is for dummy not to bind + } + else { + Debug("ClientConnectGetSocket(): Using client option %r for source IP address\n", sess->ClientOption->BindLocalIP); + // Nonzero address is for source IP address to bind. Zero address is for dummy not to bind. + tmpIP = sess->ClientOption->BindLocalIP; + } + localIP = &tmpIP; + } + // In the case of second and subsequent TCP/IP connections + else { + // Bind the socket to the actual local IP address of first TCP / IP connection + localIP = &sess->LocalIP_CacheForNextConnect; + //localIP = BIND_LOCALIP_NULL; // Specify not to bind for test + } + // Bottom of Bind outgoing connection + // If additional_connect == false, enable trying to NAT-T connection // If additional_connect == true, follow the IsRUDPSession setting in this session // In additional connect or redirect we do not need ssl verification as the certificate is always compared with a saved one - sock = TcpIpConnectEx2(hostname, c->ServerPort, + sock = BindTcpIpConnectEx2(localIP, localport, hostname, c->ServerPort, (bool *)cancel_flag, c->hWndForUI, &nat_t_err, (additional_connect ? (!sess->IsRUDPSession) : false), true, ((additional_connect || c->UseTicket) ? NULL : sess->SslOption), &ssl_err, o->HintStr, &resolved_ip); } @@ -6351,6 +6380,25 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) StrCpy(in.HttpCustomHeader, sizeof(in.HttpCustomHeader), o->CustomHttpHeader); StrCpy(in.HttpUserAgent, sizeof(in.HttpUserAgent), c->Cedar->HttpUserAgent); + // Top of Bind outgoing connection + // In the case of first TCP/IP connection + if (additional_connect == false) { + if (sess->ClientOption->NoRoutingTracking == false) { + IP tmpIP; + StrToIP(&tmpIP, "0::0"); + in.BindLocalIP = tmpIP; + } + else { + in.BindLocalIP = sess->ClientOption->BindLocalIP; + } + } + // In the case of second and subsequent TCP/IP connections + else { + in.BindLocalIP = sess->LocalIP_CacheForNextConnect; + } + in.BindLocalPort = BIND_LOCALPORT_NULL; + // Bottom of Bind outgoing connection + #ifdef OS_WIN32 in.Hwnd = c->hWndForUI; #endif @@ -6361,13 +6409,16 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) switch (o->ProxyType) { case PROXY_HTTP: - ret = ProxyHttpConnect(&out, &in, cancel_flag); +// ret = ProxyHttpConnect(&out, &in, cancel_flag); + ret = BindProxyHttpConnect(&out, &in, cancel_flag); // Bind outgoing connection break; case PROXY_SOCKS: - ret = ProxySocks4Connect(&out, &in, cancel_flag); +// ret = ProxySocks4Connect(&out, &in, cancel_flag); + ret = BindProxySocks4Connect(&out, &in, cancel_flag); // Bind outgoing connection break; case PROXY_SOCKS5: - ret = ProxySocks5Connect(&out, &in, cancel_flag); +// ret = ProxySocks5Connect(&out, &in, cancel_flag); + ret = BindProxySocks5Connect(&out, &in, cancel_flag); // Bind outgoing connection break; default: c->Err = ERR_INTERNAL_ERROR; @@ -6402,6 +6453,25 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) Debug("ClientConnectGetSocket(): Saved %s IP address %r for future connections.\n", hostname, &resolved_ip); } + // Top of Bind outgoing connection + IPToStr(localaddr, sizeof(localaddr), &sock->LocalIP); + + // In the case of first TCP/IP connection, save the local IP address + if (additional_connect == false) { + c->Session->LocalIP_CacheForNextConnect = sock->LocalIP; + Debug("ClientConnectGetSocket(): Saved local IP address %r for future connections.\n", &sock->LocalIP); + } + // In the case of second and subsequent TCP/IP connections, check to see whether or not the local IP address is same as the first one + else { + if (memcmp(sock->LocalIP.address, c->Session->LocalIP_CacheForNextConnect.address, sizeof(sock->LocalIP.address)) == 0) { + Debug("ClientConnectGetSocket(): Binded local IP address %s OK\n", localaddr); + } + else { + Debug("ClientConnectGetSocket(): Binded local IP address %s NG\n", localaddr); + } + } + // Bottom of Bind outgoing connection + return sock; } @@ -6432,15 +6502,41 @@ UINT ProxyCodeToCedar(UINT code) // TCP connection function SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip) { - return TcpConnectEx4(hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip); + return BindTcpConnectEx3(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ret_ip); } -SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) + +SOCK *TcpConnectEx4(char * hostname, UINT port, UINT timeout, bool * cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +{ + return BindTcpConnectEx4(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); +} + +// Connect with TCP/IP +SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip) +{ + return BindTcpIpConnectEx(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, ret_ip); +} + +SOCK *TcpIpConnectEx2(char * hostname, UINT port, bool * cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +{ + return BindTcpIpConnectEx2(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); +} + +// TCP connection function +//SOCK* TcpConnectEx3(char* hostname, UINT port, UINT timeout, bool* cancel_flag, void* hWnd, bool no_nat_t, UINT* nat_t_error_code, bool try_start_ssl, IP* ret_ip) +SOCK *BindTcpConnectEx3(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip) +{ +// return TcpConnectEx4(hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip); + return BindTcpConnectEx4(localIP, localport, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip); +} +//SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +SOCK *BindTcpConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) { #ifdef OS_WIN32 if (hWnd == NULL) { #endif // OS_WIN32 - return ConnectEx5(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip); +// return ConnectEx5(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip); + return BindConnectEx5(localIP, localport, hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip); #ifdef OS_WIN32 } else @@ -6451,11 +6547,14 @@ SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, } // Connect with TCP/IP -SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip) +//SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip) +SOCK *BindTcpIpConnectEx(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip) { - return TcpIpConnectEx2(hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip); +// return TcpIpConnectEx2(hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip); + return BindTcpIpConnectEx2(localIP, localport, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip); } -SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +//SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +SOCK *BindTcpIpConnectEx2(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) { SOCK *s = NULL; UINT dummy_int = 0; @@ -6470,7 +6569,8 @@ SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, return NULL; } - s = TcpConnectEx4(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); +// s = TcpConnectEx4(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); + s = BindTcpConnectEx4(localIP, localport, hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); if (s == NULL) { return NULL; diff --git a/src/Cedar/Protocol.h b/src/Cedar/Protocol.h index ebcc1052..f1b1f6b9 100644 --- a/src/Cedar/Protocol.h +++ b/src/Cedar/Protocol.h @@ -115,6 +115,11 @@ bool ClientConnect(CONNECTION *c); SOCK *ClientConnectToServer(CONNECTION *c); SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip); SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); + +// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one. +SOCK* BindTcpIpConnectEx(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip); +SOCK* BindTcpIpConnectEx2(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); + bool ClientUploadSignature(SOCK *s); bool ClientDownloadHello(CONNECTION *c, SOCK *s); bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str); @@ -124,6 +129,10 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect); SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip); SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); +// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one. +SOCK* BindTcpConnectEx3(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip); +SOCK* BindTcpConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); + UINT ProxyCodeToCedar(UINT code); void InitProtocol(); diff --git a/src/Cedar/SMInner.h b/src/Cedar/SMInner.h index 2a9158ec..9c10bbb5 100644 --- a/src/Cedar/SMInner.h +++ b/src/Cedar/SMInner.h @@ -41,7 +41,10 @@ typedef struct SETTING char HubName[MAX_HUBNAME_LEN + 1]; // HUB name UCHAR HashedPassword[SHA1_SIZE]; // Password CLIENT_OPTION ClientOption; // Client Option - UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1]; // Reserved area + +#define IP_SIZE sizeof(IP) // Source IP address for outgoing connection +// UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1]; // Reserved area + UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1 - IP_SIZE]; // Reserved area } SETTING; // Structure declaration diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c index d680a73a..3df84e75 100644 --- a/src/Cedar/Session.c +++ b/src/Cedar/Session.c @@ -1430,6 +1430,7 @@ void ClientThread(THREAD *t, void *param) while (true) { Zero(&s->ServerIP_CacheForNextConnect, sizeof(IP)); + Zero(&s->LocalIP_CacheForNextConnect, sizeof(IP)); Zero(s->UnderlayProtocol, sizeof(s->UnderlayProtocol)); Zero(s->ProtocolDetails, sizeof(s->ProtocolDetails)); diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h index 992a56f4..8056446a 100644 --- a/src/Cedar/Session.h +++ b/src/Cedar/Session.h @@ -130,6 +130,7 @@ struct SESSION UCHAR Padding[2]; IP ServerIP_CacheForNextConnect; // Server IP, cached for next connect + IP LocalIP_CacheForNextConnect; // Local IP, cached for next connect (2nd and subsequent), assigned by first outgoing connection UINT64 CreatedTime; // Creation date and time UINT64 LastCommTime; // Last communication date and time diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 6cc39318..0c548ad6 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -13634,6 +13634,54 @@ int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool } } #else +#if 0 +LPSTR PrintError(int ErrorCode) +{ + static char Message[1024]; + + // If this program was multithreaded, we'd want to use + // FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here. + // (And of course, free the buffer when we were done with it) + + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)Message, 1024, NULL); + return Message; +} +#else +char *PrintError(int ErrorCode) +{ + char *Message; + switch (ErrorCode) { + case WSAEWOULDBLOCK: + Message = "Resource temporarily unavailable."; + break; + + case WSAEINPROGRESS: + Message = "Operation now in progress."; + break; + + case WSAEALREADY: + Message = "Operation already in progress."; + break; + + case WSAEADDRINUSE: + Message = "Address already in use."; + break; + + case WSAEADDRNOTAVAIL: + Message = "Cannot assign requested address."; + break; + + default: + Message = ""; + break; + } + return Message; +} +#endif + // Connection with timeout (Win32 version) int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag) { @@ -13765,8 +13813,63 @@ void SetSockHighPriority(SOCK *s, bool flag) SetSockTos(s, (flag ? 16 : 0)); } +// Bind the socket to IPv4 or IPV6 address +int bind_sock(SOCKET sock, IP* ip, UINT port) +{ + //char tmp[MAX_HOST_NAME_LEN + 1]; + //IPToStr(tmp, sizeof(tmp), ip); + //Debug("_____ bind_sock(): Binding... IP address %s:%d\n", tmp, port); + + if (IsIP4(ip)) + { + // Declare variables + struct sockaddr_in sockaddr_in; + struct in_addr in_addr; + + Zero(&sockaddr_in, sizeof(sockaddr_in)); + Zero(&in_addr, sizeof(in_addr)); + + IPToInAddr(&in_addr, ip); + + // Set up the sockaddr structure + sockaddr_in.sin_family = AF_INET; + //inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr); + sockaddr_in.sin_addr.s_addr = in_addr.s_addr; + sockaddr_in.sin_port = htons((USHORT)port); + + // Bind the socket using the information in the sockaddr structure + return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in))); + } + else + { + // Declare variables + struct sockaddr_in6 sockaddr_in; + struct in6_addr in_addr; + + Zero(&sockaddr_in, sizeof(sockaddr_in)); + Zero(&in_addr, sizeof(in_addr)); + + IPToInAddr6(&in_addr, ip); + + // Set up the sockaddr structure + sockaddr_in.sin6_family = AF_INET6; + //inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes); + Copy(&sockaddr_in.sin6_addr, &in_addr, sizeof(in_addr)); + sockaddr_in.sin6_port = htons((USHORT)port); + + // Bind the socket using the information in the sockaddr structure + return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in))); + } +} + // Connect to the IPv4 host using a socket -SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag) +SOCKET ConnectTimeoutIPv4(IP* ip, UINT port, UINT timeout, bool* cancel_flag) +{ + return BindConnectTimeoutIPv4(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, ip, port, timeout, cancel_flag); +} + +// Connect to the IPv4 host using a socket +SOCKET BindConnectTimeoutIPv4(IP* localIP, UINT localport, IP* ip, UINT port, UINT timeout, bool* cancel_flag) { SOCKET s; struct sockaddr_in sockaddr4; @@ -13783,6 +13886,28 @@ SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag) // Socket creation s = socket(AF_INET, SOCK_STREAM, 0); + + // Top of Bind outgoing connection + if (s != INVALID_SOCKET) { + int ier; + + if ((IsZeroIP(localIP) == false) || (localport != 0)) { + + // Bind the socket + if (bind_sock(s, localIP, localport) != 0) { +#ifdef OS_WIN32 + ier = WSAGetLastError(); + Debug("IPv4 bind() failed with error: %d %s\n", ier, PrintError(ier)); +#else + Debug("IPv4 bind() failed with error: %d %s\n", errno, strerror(errno)); +#endif + closesocket(s); + s = INVALID_SOCKET; + } + } + } + // Bottom of Bind outgoing connection + if (s != INVALID_SOCKET) { // Connection @@ -14045,7 +14170,21 @@ void ConnectThreadForRUDP(THREAD *thread, void *param) } // IPv4 connection thread (multiple protocols, multiple addresses) -void ConnectThreadForIPv4(THREAD *thread, void *param) +void ConnectThreadForIPv4(THREAD* thread, void* param) +{ + CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param; + if (thread == NULL || p == NULL) + { + return; + } + StrToIP(&p->LocalIP, "0.0.0.0"); + p->LocalPort = 0; + return BindConnectThreadForIPv4(thread, param); +} + +// IPv4 connection thread (multiple protocols, multiple addresses) +//void ConnectThreadForIPv4(THREAD* thread, void* param) +void BindConnectThreadForIPv4(THREAD *thread, void *param) { SOCKET s = INVALID_SOCKET; IP current_ip; @@ -14098,7 +14237,8 @@ void ConnectThreadForIPv4(THREAD *thread, void *param) if (use_natt == false) { // Normal connection without using NAT-T - s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag); +// s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag); + s = BindConnectTimeoutIPv4(&p->LocalIP, p->LocalPort, ip, p->Port, p->Timeout, p->CancelFlag); if (s != INVALID_SOCKET) { @@ -14400,7 +14540,21 @@ void ConnectThreadForIPv4(THREAD *thread, void *param) } // IPv6 connection thread (multiple addresses) -void ConnectThreadForIPv6(THREAD *thread, void *param) +void ConnectThreadForIPv6(THREAD* thread, void* param) +{ + CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param; + if (thread == NULL || p == NULL) + { + return; + } + StrToIP(&p->LocalIP, "0::0"); + p->LocalPort = 0; + return BindConnectThreadForIPv6(thread, param); +} + +// IPv6 connection thread (multiple addresses) +//void ConnectThreadForIPv6(THREAD *thread, void *param) +void BindConnectThreadForIPv6(THREAD* thread, void* param) { SOCKET s = INVALID_SOCKET; IP current_ip; @@ -14455,6 +14609,28 @@ void ConnectThreadForIPv6(THREAD *thread, void *param) // Socket creation s = socket(AF_INET6, SOCK_STREAM, 0); + + // Top of Bind outgoing connection + if (s != INVALID_SOCKET){ + int ier; + + if ((IsZeroIP(&p->LocalIP) == false) || (p->LocalPort != 0)){ + + // Bind the socket + if (bind_sock(s, &p->LocalIP, p->LocalPort) != 0) { +#ifdef OS_WIN32 + ier = WSAGetLastError(); + Debug("IPv6 bind() failed with error: %d %s\n", ier, PrintError(ier)); +#else + Debug("IPv6 bind() failed with error: %d %s\n", errno, strerror(errno)); +#endif + closesocket(s); + s = INVALID_SOCKET; + } + } + } + // Bottom of Bind outgoing connection + if (s != INVALID_SOCKET) { // Connection @@ -14580,6 +14756,18 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip); } SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +{ + return BindConnectEx5(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, ssl_option, ssl_err, hint_str, ret_ip); +} + +//SOCK* ConnectEx4(char* hostname, UINT port, UINT timeout, bool* cancel_flag, char* nat_t_svc_name, UINT* nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP* ret_ip) +SOCK *BindConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip) +{ +// return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip); + return BindConnectEx5(localIP, localport, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip); +} +//SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) +SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) { bool dummy = false; bool use_natt = false; @@ -14675,6 +14863,12 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha if (LIST_NUM(iplist_v6) > 0) { p6.IpList = iplist_v6; + + //ZeroIP6(&p6.LocalIP); + Zero(&p6.LocalIP, sizeof(p6.LocalIP)); // Zero IP6 must be used when argument localIP is NULL + CopyIP(&p6.LocalIP, localIP); + p6.LocalPort = localport; + p6.Port = port; p6.Timeout = timeout; StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname); @@ -14688,13 +14882,19 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha p6.Ret_Ip = &ret_ip6; p6.RetryDelay = 250; p6.Delay = 0; - t6 = NewThread(ConnectThreadForIPv6, &p6); +// t6 = NewThread(ConnectThreadForIPv6, &p6); + t6 = NewThread(BindConnectThreadForIPv6, &p6); // For binding a socket } // IPv4 connection thread if (LIST_NUM(iplist_v4) > 0) { p4.IpList = iplist_v4; + + ZeroIP4(&p4.LocalIP); // Zero IP4 must be used when argument localIP is NULL + CopyIP(&p4.LocalIP, localIP); + p4.LocalPort = localport; + p4.Port = port; p4.Timeout = timeout; StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname); @@ -14713,7 +14913,8 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha p4.Ret_Ip = &ret_ip4; p4.RetryDelay = 250; p4.Delay = 250; // Delay by 250ms to prioritize IPv6 (RFC 6555 recommends 150-250ms, Chrome uses 300ms) - t4 = NewThread(ConnectThreadForIPv4, &p4); +// t4 = NewThread(ConnectThreadForIPv4, &p4); + t4 = NewThread(BindConnectThreadForIPv4, &p4); // For binding a socket } if (t6 == NULL || t4 == NULL) diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 202df410..526b9005 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -808,6 +808,8 @@ struct RUDP_STACK struct CONNECT_SERIAL_PARAM { LIST *IpList; + UINT LocalPort; // Local port number to bind + IP LocalIP; // Local IP address to bind UINT Port; UINT Timeout; char Hostname[MAX_SIZE]; @@ -946,6 +948,10 @@ void ConnectThreadForRUDP(THREAD *thread, void *param); void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param); void ConnectThreadForIPv4(THREAD *thread, void *param); void ConnectThreadForIPv6(THREAD *thread, void *param); + +void BindConnectThreadForIPv4(THREAD *thread, void *param); +void BindConnectThreadForIPv6(THREAD *thread, void *param); + SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original); SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname); RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip); @@ -1109,6 +1115,14 @@ SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip); SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag); + +// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one. +#define BIND_LOCALIP_NULL NULL // NULL IP address specifies no binding +#define BIND_LOCALPORT_NULL 0 // NULL port number specifies no binding +SOCK *BindConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip); +SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); +SOCKET BindConnectTimeoutIPv4(IP *localIP, UINT localport, IP *ip, UINT port, UINT timeout, bool *cancel_flag); + bool SetSocketBufferSize(SOCKET s, bool send, UINT size); UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size); void InitUdpSocketBufferSize(SOCKET s); diff --git a/src/Mayaqua/Proxy.c b/src/Mayaqua/Proxy.c index 37f5c159..8d4f1c6a 100644 --- a/src/Mayaqua/Proxy.c +++ b/src/Mayaqua/Proxy.c @@ -16,11 +16,25 @@ SOCK *Internal_ProxyTcpConnect(PROXY_PARAM_IN *param, volatile bool *cancel_flag } #endif - return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip); + //return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool*)cancel_flag, NULL, NULL, false, true, resolved_ip); + return BindConnectEx4(¶m->BindLocalIP, param->BindLocalPort, param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip); } // Connect to an HTTP proxy UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) +{ + // Validate arguments + if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname)) + { + return PROXY_ERROR_PARAMETER; + } + StrToIP(&in->BindLocalIP, "0::0"); + in->BindLocalPort = 0; + return BindProxyHttpConnect(out, in, cancel_flag); +} + +// Connect to an HTTP proxy +UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) { bool dummy_cancel_flag = false, use_auth = false; char target_hostname[MAX_HOST_NAME_LEN + 1]; @@ -208,6 +222,19 @@ FAILURE: // Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication) UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) +{ + // Validate arguments + if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname)) + { + return PROXY_ERROR_PARAMETER; + } + StrToIP(&in->BindLocalIP, "0::0"); + in->BindLocalPort = 0; + return BindProxySocks5Connect(out, in, cancel_flag); +} + +// Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication) +UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) { bool dummy_cancel_flag = false; UCHAR tmp, recv_buf[2], *recv_buf_final; @@ -521,6 +548,17 @@ FAILURE: // Connect to a SOCKS4 proxy UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) +{ + // Validate arguments + if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname)) + { + return PROXY_ERROR_PARAMETER; + } + return BindProxySocks4Connect(out, in, cancel_flag); +} + +// Connect to a SOCKS4 proxy +UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) { bool dummy_cancel_flag = false; UCHAR tmp, recv_buf[8]; diff --git a/src/Mayaqua/Proxy.h b/src/Mayaqua/Proxy.h index 2f8325ca..3b5abb91 100644 --- a/src/Mayaqua/Proxy.h +++ b/src/Mayaqua/Proxy.h @@ -30,6 +30,8 @@ struct PROXY_PARAM_IN UINT Timeout; char HttpCustomHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; char HttpUserAgent[HTTP_HEADER_USER_AGENT_MAX_SIZE + 1]; + IP BindLocalIP; // Source IP address for outgoing connection + UINT BindLocalPort; // UINT used not USHORT // Source port number for outgoing connection #ifdef OS_WIN32 void *Hwnd; #endif @@ -45,4 +47,9 @@ UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *c UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); +// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one. +UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); +UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); +UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); + #endif diff --git a/src/PenCore/PenCore.rc b/src/PenCore/PenCore.rc index 3d356d3c..c43db768 100644 --- a/src/PenCore/PenCore.rc +++ b/src/PenCore/PenCore.rc @@ -13,7 +13,7 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// resources +// 餁Eresources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) #ifdef _WIN32 @@ -1654,10 +1654,12 @@ BEGIN LTEXT "@S_MODE",S_MODE,254,169,166,17 CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,191,166,9 CONTROL "@R_MONITOR",R_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,205,166,9 - GROUPBOX "@STATIC17",IDC_STATIC,222,225,205,30 + GROUPBOX "@STATIC17", IDC_STATIC, 222, 225, 205, 42 CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,238,181,9 - ICON ICO_WARNING,S_WARNING_ICON,223,261,18,18 - LTEXT "@STATIC18",IDC_STATIC,247,261,180,26 + LTEXT "@STATIC20", IDC_STATIC, 233, 249, 56, 17 + EDITTEXT E_BIND_LOCALIP, 289, 249, 126, 11, ES_RIGHT | ES_AUTOHSCROLL + ICON ICO_WARNING,S_WARNING_ICON,223,270,18,18 + LTEXT "@STATIC18",IDC_STATIC,247,270,180,26 DEFPUSHBUTTON "@IDOK",IDOK,294,291,64,15 PUSHBUTTON "@IDCANCEL",IDCANCEL,363,291,64,15 ICON ICO_SWITCH,IDC_STATIC,230,169,18,18 @@ -4865,12 +4867,12 @@ END // BIN_WINPCAP BIN "Dummy.bin" -#endif // resources +#endif // 餁Eresources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// (xW) resources +// E(xW) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHT) #ifdef _WIN32 @@ -4886,12 +4888,12 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. ICO_LANG_TRADITIONAL_CHINESE ICON "LANG_TRADITIONAL_CHINESE.ico" -#endif // (xW) resources +#endif // E(xW) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// ^ () resources +// ^E(EE resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 @@ -4952,7 +4954,7 @@ BMP_ZURUKKO BITMAP "Zurukko.bmp" BMP_VPNGATEEN BITMAP "VPNGateEN.bmp" BMP_VPNGATEJA BITMAP "VPNGateJA.bmp" BMP_UNIVTSUKUBA BITMAP "UnivTsukuba.bmp" -#endif // ^ () resources +#endif // ^E(EE resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/PenCore/resource.h b/src/PenCore/resource.h index 384d3ff9..c6379093 100644 --- a/src/PenCore/resource.h +++ b/src/PenCore/resource.h @@ -339,6 +339,7 @@ #define C_NUM_TCP 1075 #define B_TRUST 1076 #define E_INTERVAL 1076 +#define E_BIND_LOCALIP 9076 // Bind source IP #define B_PROXY_CONFIG 1077 #define B_SERVER_CERT 1078 #define B_VIEW_SERVER_CERT 1079 diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index 508960b7..6a078a65 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -2420,6 +2420,7 @@ STATIC17 Other Confi&gurations: R_NO_ROUTING No Adjustments of &Routing Table STATIC18 Keep the settings default in this dialog unless you are told to do so by a system administrator, or you have expertise for networking and security. STATIC19 The VoIP / QoS functions handle high priority packets such as IP telephone packets (VoIP) to be transmitted faster. +STATIC20 Source IP Address\n(IP Address on NIC): R_DISABLE_QOS Disable VoIP / &QoS Functions IDOK &OK IDCANCEL Cancel diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index 5462b57b..76e895a5 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -2423,6 +2423,7 @@ STATIC17 その他の設定(&G): R_NO_ROUTING ルーティングテーブルの調整処理を行わない(&R) STATIC18 この設定画面の設定項目は、システム管理者から指示があった場合や、ネットワークやセキュリティに関して詳しい知識をお持ちの場合以外は変更しないでください。 STATIC19 VoIP / QoS 対応機能を使用すると、IP 電話パケットなどの優先度の高いパケットを VPN 内で高速に伝送できます。 +STATIC20 送信元IPアドレス\n(NICのIPアドレス): R_DISABLE_QOS VoIP / QoS 対応機能を無効にする(&Q) IDOK &OK IDCANCEL キャンセル From c2fe874865558d8d2ccd05b36ff4504848cd2c06 Mon Sep 17 00:00:00 2001 From: hiura Date: Tue, 8 Aug 2023 18:14:22 +0900 Subject: [PATCH 04/63] Bind outgoing connection to a specific IP address No.2 --- src/Cedar/CM.c | 12 ++++- src/Cedar/Client.c | 9 ++-- src/Cedar/Connection.h | 3 +- src/Cedar/Protocol.c | 43 ++++++++++----- src/Cedar/SMInner.h | 4 +- src/Cedar/Session.c | 20 ++++++- src/Mayaqua/Network.c | 94 +++++++++++++++++++++++---------- src/Mayaqua/Network.h | 3 +- src/Mayaqua/Proxy.c | 12 +++-- src/Mayaqua/Proxy.h | 2 +- src/PenCore/PenCore.rc | 12 +++-- src/PenCore/resource.h | 3 +- src/bin/hamcore/strtable_en.stb | 3 +- src/bin/hamcore/strtable_ja.stb | 3 +- 14 files changed, 158 insertions(+), 65 deletions(-) diff --git a/src/Cedar/CM.c b/src/Cedar/CM.c index 6d535bc2..f982a2cb 100644 --- a/src/Cedar/CM.c +++ b/src/Cedar/CM.c @@ -6151,6 +6151,7 @@ void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite) t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode; t->ClientOption->DisableQoS = old_option->DisableQoS; t->ClientOption->BindLocalIP = old_option->BindLocalIP;// Source IP address for outgoing connection + t->ClientOption->BindLocalPort = old_option->BindLocalPort;// Source port number for outgoing connection // Inherit the authentication data CiFreeClientAuth(t->ClientAuth); @@ -6459,6 +6460,7 @@ void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a) Disable(hWnd, R_NO_ROUTING); #if TYPE_BINDLOCALIP Disable(hWnd, E_BIND_LOCALIP);// Source IP address for outgoing connection + Disable(hWnd, E_BIND_LOCALPORT);// Source port number for outgoing connection #endif } @@ -6543,6 +6545,8 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration); #if TYPE_BINDLOCALIP SetIp(hWnd, E_BIND_LOCALIP, &a->ClientOption->BindLocalIP);// Source IP address for outgoing connection + SetIntEx(hWnd, E_BIND_LOCALPORT, a->ClientOption->BindLocalPort);// Source port number for outgoing connection + //Disable(hWnd, E_BIND_LOCALPORT); // You can not edit #endif // Select the Connection Mode @@ -6594,11 +6598,16 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa #if TYPE_BINDLOCALIP // Source IP address for outgoing connection IP tmpIP; - if (GetIp(hWnd, E_BIND_LOCALIP, &tmpIP) == false) + if (GetIp(hWnd, E_BIND_LOCALIP, &tmpIP) == false) { FocusEx(hWnd, E_BIND_LOCALIP); break; } + // Source port number for outgoing connection + if ((GetInt(hWnd, E_BIND_LOCALPORT) < 0) || (GetInt(hWnd, E_BIND_LOCALPORT) > 65535)){ + FocusEx(hWnd, E_BIND_LOCALPORT); + break; + } #endif a->ClientOption->MaxConnection = num; @@ -6619,6 +6628,7 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP); #if TYPE_BINDLOCALIP a->ClientOption->BindLocalIP = tmpIP;// Source IP address for outgoing connection + a->ClientOption->BindLocalPort = GetInt(hWnd, E_BIND_LOCALPORT);// Source port number for outgoing connection #endif if (a->LinkMode) diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c index 3e4c26d4..e2755d8d 100644 --- a/src/Cedar/Client.c +++ b/src/Cedar/Client.c @@ -4342,9 +4342,9 @@ void InRpcClientOption(CLIENT_OPTION *c, PACK *p) PackGetStr(p, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader)); PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName)); PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName)); -#if TYPE_BINDLOCALIP PackGetIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection -#endif + c->BindLocalPort = PackGetInt(p, "BindLocalPort");// Source port nubmer for outgoing connection + c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false; c->UseCompress = PackGetInt(p, "UseCompress") ? true : false; c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false; @@ -4405,9 +4405,8 @@ void OutRpcClientOption(PACK *p, CLIENT_OPTION *c) PackAddBool(p, "FromAdminPack", c->FromAdminPack); PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration); PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE); -#if TYPE_BINDLOCALIP PackAddIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection -#endif + PackAddInt(p, "BindLocalPort", c->BindLocalPort);// Source port number for outgoing connection } // CLIENT_AUTH @@ -9303,6 +9302,7 @@ CLIENT_OPTION *CiLoadClientOption(FOLDER *f) o->FromAdminPack = CfgGetBool(f, "FromAdminPack"); o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration"); CfgGetIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection + o->BindLocalPort = CfgGetInt(f, "BindLocalPort");// Source port number for outgoing connection b = CfgGetBuf(f, "HostUniqueKey"); if (b != NULL) @@ -9858,6 +9858,7 @@ void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o) CfgAddBool(f, "DisableQoS", o->DisableQoS); CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration); CfgAddIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection + CfgAddInt(f, "BindLocalPort", o->BindLocalPort);// Source port number for outgoing connection if (o->FromAdminPack) { diff --git a/src/Cedar/Connection.h b/src/Cedar/Connection.h index d691fcdb..954738fe 100644 --- a/src/Cedar/Connection.h +++ b/src/Cedar/Connection.h @@ -58,7 +58,7 @@ struct RC4_KEY_PAIR UCHAR ServerToClientKey[16]; UCHAR ClientToServerKey[16]; }; -#define TYPE_BINDLOCALIP 1 // Enable HMI user to edit Source IP address for outgoing connection +#define TYPE_BINDLOCALIP 1 // Enable HMI user to edit Source IP address & Source port number for outgoing connection // Client Options // Do not change item size or order and only add new items at the end! @@ -108,6 +108,7 @@ struct CLIENT_OPTION char CustomHttpHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; // Custom HTTP proxy header char HintStr[MAX_HOST_NAME_LEN + 1]; // Hint string for NAT-T IP BindLocalIP; // Source IP address for outgoing connection + UINT BindLocalPort; // Source port number for outgoing connection }; // Client authentication data diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index 7eb98ea8..feb29ece 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -6281,8 +6281,7 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) if (o->PortUDP == 0) { IP *localIP; - IP tmpIP; - UINT localport = BIND_LOCALPORT_NULL; + UINT localport; // Top of Bind outgoing connection // Decide the binding operation which is explicitly executed on the client-side @@ -6290,14 +6289,19 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) // In the case of first TCP/IP connection if (additional_connect == false) { if (sess->ClientOption->NoRoutingTracking == false) { - StrToIP(&tmpIP, "0::0"); // Zero address is for dummy not to bind + localIP = BIND_LOCALIP_NULL; // Specify not to bind } else { - Debug("ClientConnectGetSocket(): Using client option %r for source IP address\n", sess->ClientOption->BindLocalIP); + Debug("ClientConnectGetSocket(): Using client option %r and %d for binding\n" + , sess->ClientOption->BindLocalIP, sess->ClientOption->BindLocalPort); // Nonzero address is for source IP address to bind. Zero address is for dummy not to bind. - tmpIP = sess->ClientOption->BindLocalIP; + if (IsZeroIP(&sess->ClientOption->BindLocalIP) == true) { + localIP = BIND_LOCALIP_NULL; + } + else { + localIP = &sess->ClientOption->BindLocalIP; + } } - localIP = &tmpIP; } // In the case of second and subsequent TCP/IP connections else { @@ -6305,6 +6309,13 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) localIP = &sess->LocalIP_CacheForNextConnect; //localIP = BIND_LOCALIP_NULL; // Specify not to bind for test } + if (sess->ClientOption->BindLocalPort == 0) { + localport = BIND_LOCALPORT_NULL; + } + else { + localport = sess->ClientOption->BindLocalPort + Count(sess->Connection->CurrentNumConnection) - 1; + Debug("ClientConnectGetSocket(): Additional port number %u\n", localport); + } // Bottom of Bind outgoing connection // If additional_connect == false, enable trying to NAT-T connection @@ -6384,19 +6395,27 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) // In the case of first TCP/IP connection if (additional_connect == false) { if (sess->ClientOption->NoRoutingTracking == false) { - IP tmpIP; - StrToIP(&tmpIP, "0::0"); - in.BindLocalIP = tmpIP; + in.BindLocalIP = BIND_LOCALIP_NULL; // Specify not to bind } else { - in.BindLocalIP = sess->ClientOption->BindLocalIP; + if (IsZeroIP(&sess->ClientOption->BindLocalIP) == true) { + in.BindLocalIP = BIND_LOCALIP_NULL; + } + else { + in.BindLocalIP = &sess->ClientOption->BindLocalIP; + } } } // In the case of second and subsequent TCP/IP connections else { - in.BindLocalIP = sess->LocalIP_CacheForNextConnect; + in.BindLocalIP = &sess->LocalIP_CacheForNextConnect; + } + if (sess->ClientOption->BindLocalPort == 0) { + in.BindLocalPort = BIND_LOCALPORT_NULL; + } + else { + in.BindLocalPort = sess->ClientOption->BindLocalPort + Count(sess->Connection->CurrentNumConnection) - 1; } - in.BindLocalPort = BIND_LOCALPORT_NULL; // Bottom of Bind outgoing connection #ifdef OS_WIN32 diff --git a/src/Cedar/SMInner.h b/src/Cedar/SMInner.h index 9c10bbb5..f54ea8c0 100644 --- a/src/Cedar/SMInner.h +++ b/src/Cedar/SMInner.h @@ -42,9 +42,9 @@ typedef struct SETTING UCHAR HashedPassword[SHA1_SIZE]; // Password CLIENT_OPTION ClientOption; // Client Option -#define IP_SIZE sizeof(IP) // Source IP address for outgoing connection +#define SRC_SIZE (sizeof(IP) + sizeof(UINT)) // Source IP address & port number for outgoing connection // UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1]; // Reserved area - UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1 - IP_SIZE]; // Reserved area + UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1 - SRC_SIZE]; // Reserved area } SETTING; // Structure declaration diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c index 3df84e75..00a9e817 100644 --- a/src/Cedar/Session.c +++ b/src/Cedar/Session.c @@ -609,6 +609,24 @@ void SessionMain(SESSION *s) WHERE; } } + + // If all the specified number of tcp connections are not alive continuously, then terminate the session. + UINT num_tcp_conn = LIST_NUM(s->Connection->Tcp->TcpSockList); + UINT max_conn = s->ClientOption->MaxConnection; + + if ((s->CurrentConnectionEstablishTime + + (UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2)) + <= Tick64()) + { + if (s->ClientOption->BindLocalPort != 0 || num_tcp_conn == 0) + { + timeouted = true; + WHERE; + } + } + //Debug("SessionMain(): The number of TCP connections short... Num_Tcp_Conn=%d Max_Conn=%d Curr_Conn_Time=%llu Tick64=%llu\n" + // , num_tcp_conn, max_conn, s->CurrentConnectionEstablishTime, Tick64()); + } } @@ -1430,7 +1448,7 @@ void ClientThread(THREAD *t, void *param) while (true) { Zero(&s->ServerIP_CacheForNextConnect, sizeof(IP)); - Zero(&s->LocalIP_CacheForNextConnect, sizeof(IP)); + Zero(&s->LocalIP_CacheForNextConnect, sizeof(IP)); // Assigned by first outgoing connection Zero(s->UnderlayProtocol, sizeof(s->UnderlayProtocol)); Zero(s->ProtocolDetails, sizeof(s->ProtocolDetails)); diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 0c548ad6..b81fe5e1 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -13108,7 +13108,6 @@ SOCK *ListenEx63(UINT port, bool local_only, bool enable_ca, IP *listen_ip) #ifdef OS_WIN32 if (enable_ca) { - setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(true_flag)); backlog = 1; } #endif @@ -13654,6 +13653,10 @@ char *PrintError(int ErrorCode) { char *Message; switch (ErrorCode) { + case WSAEFAULT: + Message = "Bad address."; + break; + case WSAEWOULDBLOCK: Message = "Resource temporarily unavailable."; break; @@ -13666,6 +13669,10 @@ char *PrintError(int ErrorCode) Message = "Operation already in progress."; break; + case WSAEAFNOSUPPORT: + Message = "Address family not supported by protocol family."; + break; + case WSAEADDRINUSE: Message = "Address already in use."; break; @@ -13814,28 +13821,30 @@ void SetSockHighPriority(SOCK *s, bool flag) } // Bind the socket to IPv4 or IPV6 address -int bind_sock(SOCKET sock, IP* ip, UINT port) +int bind_sock(SOCKET sock, IP *ip, UINT port) { //char tmp[MAX_HOST_NAME_LEN + 1]; + //memset(tmp, 0, sizeof(tmp)); //IPToStr(tmp, sizeof(tmp), ip); - //Debug("_____ bind_sock(): Binding... IP address %s:%d\n", tmp, port); + //Debug("bind_sock(): Binding... IP address %s:%d\n", tmp, port); if (IsIP4(ip)) { // Declare variables struct sockaddr_in sockaddr_in; - struct in_addr in_addr; Zero(&sockaddr_in, sizeof(sockaddr_in)); - Zero(&in_addr, sizeof(in_addr)); - - IPToInAddr(&in_addr, ip); // Set up the sockaddr structure sockaddr_in.sin_family = AF_INET; - //inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr); - sockaddr_in.sin_addr.s_addr = in_addr.s_addr; + IPToInAddr(&sockaddr_in.sin_addr, ip); sockaddr_in.sin_port = htons((USHORT)port); + //inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr); + + UINT true_flag = 1; + // This only have enabled for UNIX system since there is a bug + // in the implementation of REUSEADDR in Windows OS + (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag)); // Bind the socket using the information in the sockaddr structure return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in))); @@ -13844,18 +13853,24 @@ int bind_sock(SOCKET sock, IP* ip, UINT port) { // Declare variables struct sockaddr_in6 sockaddr_in; - struct in6_addr in_addr; Zero(&sockaddr_in, sizeof(sockaddr_in)); - Zero(&in_addr, sizeof(in_addr)); - - IPToInAddr6(&in_addr, ip); // Set up the sockaddr structure sockaddr_in.sin6_family = AF_INET6; - //inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes); - Copy(&sockaddr_in.sin6_addr, &in_addr, sizeof(in_addr)); + IPToInAddr6(&sockaddr_in.sin6_addr, ip); + sockaddr_in.sin6_scope_id = ip->ipv6_scope_id; sockaddr_in.sin6_port = htons((USHORT)port); + //inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes); + + UINT true_flag = 1; +#ifdef OS_UNIX + // It is necessary to set the IPv6 Only flag on a UNIX system + (void)setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag)); +#endif // OS_UNIX + // This only have enabled for UNIX system since there is a bug + // in the implementation of REUSEADDR in Windows OS + (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag)); // Bind the socket using the information in the sockaddr structure return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in))); @@ -13890,6 +13905,12 @@ SOCKET BindConnectTimeoutIPv4(IP* localIP, UINT localport, IP* ip, UINT port, UI // Top of Bind outgoing connection if (s != INVALID_SOCKET) { int ier; + IP tmpIP; + + if (localIP == BIND_LOCALIP_NULL) { + StrToIP(&tmpIP, "0.0.0.0"); // A NULL address for the argument "localIP" is treated as if "0::0" in IPV4 was specified. + localIP = &tmpIP; + } if ((IsZeroIP(localIP) == false) || (localport != 0)) { @@ -14177,8 +14198,8 @@ void ConnectThreadForIPv4(THREAD* thread, void* param) { return; } - StrToIP(&p->LocalIP, "0.0.0.0"); - p->LocalPort = 0; + p->LocalIP = BIND_LOCALIP_NULL; + p->LocalPort = BIND_LOCALPORT_NULL; return BindConnectThreadForIPv4(thread, param); } @@ -14238,7 +14259,7 @@ void BindConnectThreadForIPv4(THREAD *thread, void *param) { // Normal connection without using NAT-T // s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag); - s = BindConnectTimeoutIPv4(&p->LocalIP, p->LocalPort, ip, p->Port, p->Timeout, p->CancelFlag); + s = BindConnectTimeoutIPv4(p->LocalIP, p->LocalPort, ip, p->Port, p->Timeout, p->CancelFlag); if (s != INVALID_SOCKET) { @@ -14547,8 +14568,8 @@ void ConnectThreadForIPv6(THREAD* thread, void* param) { return; } - StrToIP(&p->LocalIP, "0::0"); - p->LocalPort = 0; + p->LocalIP = BIND_LOCALIP_NULL; + p->LocalPort = BIND_LOCALPORT_NULL; return BindConnectThreadForIPv6(thread, param); } @@ -14613,11 +14634,17 @@ void BindConnectThreadForIPv6(THREAD* thread, void* param) // Top of Bind outgoing connection if (s != INVALID_SOCKET){ int ier; + IP tmpIP; - if ((IsZeroIP(&p->LocalIP) == false) || (p->LocalPort != 0)){ + if (p->LocalIP == BIND_LOCALIP_NULL) { + StrToIP(&tmpIP, "0::0"); // A NULL address for the argument "p->LocalIP" is treated as if "0::0" in IPV6 was specified. + p->LocalIP = &tmpIP; + } + + if ((IsZeroIP(p->LocalIP) == false) || (p->LocalPort != 0)){ // Bind the socket - if (bind_sock(s, &p->LocalIP, p->LocalPort) != 0) { + if (bind_sock(s, p->LocalIP, p->LocalPort) != 0) { #ifdef OS_WIN32 ier = WSAGetLastError(); Debug("IPv6 bind() failed with error: %d %s\n", ier, PrintError(ier)); @@ -14864,10 +14891,14 @@ SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UIN { p6.IpList = iplist_v6; - //ZeroIP6(&p6.LocalIP); - Zero(&p6.LocalIP, sizeof(p6.LocalIP)); // Zero IP6 must be used when argument localIP is NULL - CopyIP(&p6.LocalIP, localIP); - p6.LocalPort = localport; + if (localIP == BIND_LOCALIP_NULL) { + p6.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through + } + else { + CopyIP(&p6.LocalIP_Cache, localIP); + p6.LocalIP = &p6.LocalIP_Cache; + } + p6.LocalPort = localport; p6.Port = port; p6.Timeout = timeout; @@ -14891,9 +14922,14 @@ SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UIN { p4.IpList = iplist_v4; - ZeroIP4(&p4.LocalIP); // Zero IP4 must be used when argument localIP is NULL - CopyIP(&p4.LocalIP, localIP); - p4.LocalPort = localport; + if (localIP == BIND_LOCALIP_NULL) { + p4.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through + } + else { + CopyIP(&p4.LocalIP_Cache, localIP); + p4.LocalIP = &p4.LocalIP_Cache; + } + p4.LocalPort = localport; p4.Port = port; p4.Timeout = timeout; diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 526b9005..b1142145 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -809,7 +809,8 @@ struct CONNECT_SERIAL_PARAM { LIST *IpList; UINT LocalPort; // Local port number to bind - IP LocalIP; // Local IP address to bind + IP *LocalIP; // Local IP address to bind. NULL address allowed to use. + IP LocalIP_Cache; // Local IP address to bind UINT Port; UINT Timeout; char Hostname[MAX_SIZE]; diff --git a/src/Mayaqua/Proxy.c b/src/Mayaqua/Proxy.c index 8d4f1c6a..fa0ea096 100644 --- a/src/Mayaqua/Proxy.c +++ b/src/Mayaqua/Proxy.c @@ -17,7 +17,7 @@ SOCK *Internal_ProxyTcpConnect(PROXY_PARAM_IN *param, volatile bool *cancel_flag #endif //return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool*)cancel_flag, NULL, NULL, false, true, resolved_ip); - return BindConnectEx4(¶m->BindLocalIP, param->BindLocalPort, param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip); + return BindConnectEx4(param->BindLocalIP, param->BindLocalPort, param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip); } // Connect to an HTTP proxy @@ -28,8 +28,8 @@ UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *c { return PROXY_ERROR_PARAMETER; } - StrToIP(&in->BindLocalIP, "0::0"); - in->BindLocalPort = 0; + in->BindLocalIP = BIND_LOCALIP_NULL; + in->BindLocalPort = BIND_LOCALPORT_NULL; return BindProxyHttpConnect(out, in, cancel_flag); } @@ -228,8 +228,8 @@ UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool { return PROXY_ERROR_PARAMETER; } - StrToIP(&in->BindLocalIP, "0::0"); - in->BindLocalPort = 0; + in->BindLocalIP = BIND_LOCALIP_NULL; + in->BindLocalPort = BIND_LOCALPORT_NULL; return BindProxySocks5Connect(out, in, cancel_flag); } @@ -554,6 +554,8 @@ UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool { return PROXY_ERROR_PARAMETER; } + in->BindLocalIP = BIND_LOCALIP_NULL; + in->BindLocalPort = BIND_LOCALPORT_NULL; return BindProxySocks4Connect(out, in, cancel_flag); } diff --git a/src/Mayaqua/Proxy.h b/src/Mayaqua/Proxy.h index 3b5abb91..626bd886 100644 --- a/src/Mayaqua/Proxy.h +++ b/src/Mayaqua/Proxy.h @@ -30,7 +30,7 @@ struct PROXY_PARAM_IN UINT Timeout; char HttpCustomHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; char HttpUserAgent[HTTP_HEADER_USER_AGENT_MAX_SIZE + 1]; - IP BindLocalIP; // Source IP address for outgoing connection + IP *BindLocalIP; // Source IP address for outgoing connection UINT BindLocalPort; // UINT used not USHORT // Source port number for outgoing connection #ifdef OS_WIN32 void *Hwnd; diff --git a/src/PenCore/PenCore.rc b/src/PenCore/PenCore.rc index c43db768..47ca1f5c 100644 --- a/src/PenCore/PenCore.rc +++ b/src/PenCore/PenCore.rc @@ -1654,16 +1654,18 @@ BEGIN LTEXT "@S_MODE",S_MODE,254,169,166,17 CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,191,166,9 CONTROL "@R_MONITOR",R_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,205,166,9 - GROUPBOX "@STATIC17", IDC_STATIC, 222, 225, 205, 42 - CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,238,181,9 - LTEXT "@STATIC20", IDC_STATIC, 233, 249, 56, 17 - EDITTEXT E_BIND_LOCALIP, 289, 249, 126, 11, ES_RIGHT | ES_AUTOHSCROLL + GROUPBOX "@STATIC17", IDC_STATIC, 222, 225, 205, 43 + CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,234,181,9 + LTEXT "@STATIC20", IDC_STATIC, 233, 243, 58, 17 + EDITTEXT E_BIND_LOCALIP, 292, 243, 126, 11, ES_RIGHT | ES_AUTOHSCROLL + LTEXT "@STATIC21", IDC_STATIC, 233, 255, 58, 12 + EDITTEXT E_BIND_LOCALPORT, 292, 255, 40, 11, ES_RIGHT | ES_AUTOHSCROLL ICON ICO_WARNING,S_WARNING_ICON,223,270,18,18 LTEXT "@STATIC18",IDC_STATIC,247,270,180,26 DEFPUSHBUTTON "@IDOK",IDOK,294,291,64,15 PUSHBUTTON "@IDCANCEL",IDCANCEL,363,291,64,15 ICON ICO_SWITCH,IDC_STATIC,230,169,18,18 -END + END D_CM_NEW_VLAN DIALOGEX 0, 0, 251, 98 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU diff --git a/src/PenCore/resource.h b/src/PenCore/resource.h index c6379093..2c886a3a 100644 --- a/src/PenCore/resource.h +++ b/src/PenCore/resource.h @@ -339,7 +339,8 @@ #define C_NUM_TCP 1075 #define B_TRUST 1076 #define E_INTERVAL 1076 -#define E_BIND_LOCALIP 9076 // Bind source IP +#define E_BIND_LOCALIP 9076 // Bind source IP address +#define E_BIND_LOCALPORT 9077 // Bind source port number #define B_PROXY_CONFIG 1077 #define B_SERVER_CERT 1078 #define B_VIEW_SERVER_CERT 1079 diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index 6a078a65..6be54546 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -2420,7 +2420,8 @@ STATIC17 Other Confi&gurations: R_NO_ROUTING No Adjustments of &Routing Table STATIC18 Keep the settings default in this dialog unless you are told to do so by a system administrator, or you have expertise for networking and security. STATIC19 The VoIP / QoS functions handle high priority packets such as IP telephone packets (VoIP) to be transmitted faster. -STATIC20 Source IP Address\n(IP Address on NIC): +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS Disable VoIP / &QoS Functions IDOK &OK IDCANCEL Cancel diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index 76e895a5..970b3180 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -2423,7 +2423,8 @@ STATIC17 その他の設定(&G): R_NO_ROUTING ルーティングテーブルの調整処理を行わない(&R) STATIC18 この設定画面の設定項目は、システム管理者から指示があった場合や、ネットワークやセキュリティに関して詳しい知識をお持ちの場合以外は変更しないでください。 STATIC19 VoIP / QoS 対応機能を使用すると、IP 電話パケットなどの優先度の高いパケットを VPN 内で高速に伝送できます。 -STATIC20 送信元IPアドレス\n(NICのIPアドレス): +STATIC20 送信元IPアドレス: +STATIC21 送信元ポート番号: R_DISABLE_QOS VoIP / QoS 対応機能を無効にする(&Q) IDOK &OK IDCANCEL キャンセル From aa65e11fc80d5c78afb582157aac6354a2b0063c Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 25 Aug 2023 22:05:08 +0200 Subject: [PATCH 05/63] stbchecker: retarget against net7.0 --- developer_tools/stbchecker/stbchecker.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer_tools/stbchecker/stbchecker.csproj b/developer_tools/stbchecker/stbchecker.csproj index 3483b250..077d3d65 100644 --- a/developer_tools/stbchecker/stbchecker.csproj +++ b/developer_tools/stbchecker/stbchecker.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + net7.0 From 107c4ba362fe1ecf365f32b3bbc7fb4b89f14d95 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 25 Aug 2023 22:06:09 +0200 Subject: [PATCH 06/63] CI: add stb check --- .github/workflows/stb_check.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/stb_check.yml diff --git a/.github/workflows/stb_check.yml b/.github/workflows/stb_check.yml new file mode 100644 index 00000000..5353250e --- /dev/null +++ b/.github/workflows/stb_check.yml @@ -0,0 +1,16 @@ +on: [push, pull_request] + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - name: Check + run: | + cd developer_tools/stbchecker + dotnet run ../../src/bin/hamcore \ No newline at end of file From 7fe3e6a80018bcf1066c90a6584e540afa87398d Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 25 Aug 2023 22:07:07 +0200 Subject: [PATCH 07/63] CI: travis: cleanup stb check --- .travis.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 00cbf76a..25553258 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,16 +38,6 @@ matrix: before_install: - sudo apt-get -y install libsodium-dev - bash .ci/build-libressl.sh > build-deps.log 2>&1 || (cat build-deps.log && exit 1) - - env: LABEL="check stb files" - os: linux - language: csharp - mono: none - dotnet: 2.2.203 - before_install: - - true - script: - - cd developer_tools/stbchecker - - dotnet run ../../src/bin/hamcore cache: directories: From 63595f79c5c751af198f1c129daf68c2938c3f85 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 25 Aug 2023 22:24:53 +0200 Subject: [PATCH 08/63] fix some missing localization --- src/bin/hamcore/strtable_pt_br.stb | 2 +- src/bin/hamcore/strtable_tw.stb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/hamcore/strtable_pt_br.stb b/src/bin/hamcore/strtable_pt_br.stb index f78a8179..89083eeb 100644 --- a/src/bin/hamcore/strtable_pt_br.stb +++ b/src/bin/hamcore/strtable_pt_br.stb @@ -479,7 +479,7 @@ NATT_MSG ** Connected with NAT traversal - might be unstable **\r\n\r\nThis VPN # Virtual HUB Admin Options HUB_AO_CLICK Select an item to view the description here. HUB_AO_UNKNOWN The description of the item was not found. Refer to the documents, or speculate the meaning and purpose of the item from the name of the item. -HUB_AO_allow_eap_tls_match_user_by_cert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificate CNs during the PPP EAP authentication flow. +HUB_AO_allow_hub_admin_change_option This is a special item. If you are enable (set to 1) this option, then not only the VPN Server's global administrator but also the Virtual Hub's administrator will be granted to modify the Virtual Hub Admin Options by himself. HUB_AO_deny_hub_admin_change_ext_option If you are enable (set to 1) this option, the Virtual Hub's administrator will be forbidden to modify any values on the Virtual Hub Extended Options, then only the VPN Server's global administrator can modify them. HUB_AO_no_delay_jitter_packet_loss If you set this option to non-zero value, then all parameters of delay, jitter and packet-loss on the access-list entry will be ignored even if these parameters are set when the administrator adds a new access list entry. Therefore, delay, jitter and packet-loss generating function will be virtually disabled. Because of the delay generating function sometimes make a high volume of load on the CPU and RAM, a Virtual Hub which is shared by several users should have this option enabled. HUB_AO_max_users If you set this option to non-zero value, the maximum number of user objects registered on the Virtual Hub will be limited to this value, then greater number of user objects than this value cannot be added. diff --git a/src/bin/hamcore/strtable_tw.stb b/src/bin/hamcore/strtable_tw.stb index 69dc3818..0eec56e3 100644 --- a/src/bin/hamcore/strtable_tw.stb +++ b/src/bin/hamcore/strtable_tw.stb @@ -574,6 +574,7 @@ HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.) HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied. HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow. +HUB_AO_AllowSameUserInPrivacyFilterMode Allow packets if both the source and destination session users are the same, even in PrivacyFilter mode. #關於失敗連接對話方塊 From 68e704097d96b22f3920a3c69881c9d0907735b5 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sun, 27 Aug 2023 21:11:53 +0200 Subject: [PATCH 09/63] fix another stb complaints --- src/bin/hamcore/strtable_ru.stb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/hamcore/strtable_ru.stb b/src/bin/hamcore/strtable_ru.stb index 1916982f..bc29456c 100644 --- a/src/bin/hamcore/strtable_ru.stb +++ b/src/bin/hamcore/strtable_ru.stb @@ -989,7 +989,7 @@ CM_TRAY_MENU_ABOUT &О VPN клиенте... CM_TRAY_MENU_SETTING Изменить режим работы... CM_TRAY_MENU_CANCEL Закрыть это меню CM_EXIT_MESSAGE Это действие закроет VPN клиент. \r\nВы действительно хотите это сделать? -CM_IMPORT_MESSAGE Настройки VPN подключения "%s" из файла "%S" были установлены. +CM_IMPORT_MESSAGE Из файла "%S" были импортированы настройки "%s". CM_VLAN_CREATING Создание нового Виртуального Сетевого Адаптера для Windows. \r\n\r\nЭтот процесс может занять несколько секунд или более минуты. \r\nПожалуйста, подождите...\r\n\r\n(Пожалуйста, не выполняйте другие операции во время создания Виртуального Сетевого Адаптера.) CM_SETTING_PASSWORD Настройки заблокированы. Чтобы отключить блокировку, необходимо ввести пароль. CM_EASY_MODE_NOT_ON_REMOTE Невозможно подключиться, так как VPN клиент на удаленном компьютере работает в Упрощенном режиме. From a9a93a28245ce028eb44809a88c7a7f68bb2c1a8 Mon Sep 17 00:00:00 2001 From: puripuri2100 Date: Thu, 31 Aug 2023 01:30:15 +0900 Subject: [PATCH 10/63] fixed VpnAzureSetStatus to VpnAzureSetEnable --- src/bin/hamcore/strtable_cn.stb | 2 +- src/bin/hamcore/strtable_en.stb | 2 +- src/bin/hamcore/strtable_ja.stb | 2 +- src/bin/hamcore/strtable_ko.stb | 2 +- src/bin/hamcore/strtable_ru.stb | 2 +- src/bin/hamcore/strtable_tw.stb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb index efc11a1e..abda7401 100644 --- a/src/bin/hamcore/strtable_cn.stb +++ b/src/bin/hamcore/strtable_cn.stb @@ -6476,7 +6476,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED 至 VPN Azure 云服务器的连接建立 CMD_VpnAzureGetStatus_PRINT_HOSTNAME 在 VPN Azure 服务上的本 VPN 服务器的主机名 -# VpnAzureSetStatus command +# VpnAzureSetEnable command CMD_VpnAzureSetEnable 启用/禁用 VPN Azure 功能 CMD_VpnAzureSetEnable_Help 启用或禁用 VPN Azure 功能。\n\nVPN Azure 可以更容易地从你家里的计算机到你办公室的计算机建立一个 VPN 会话。当一个 VPN 连接建立了,您可以访问您公司专用网络上的任何其他服务器。\n在办公室的计算机(VPN 服务器)上,你并不需要一个全球 IP 地址。它可以在防火墙或 NAT 后面工作。无需网络管理员的配置。您可以在您的家用电脑使用 Windows 内置的 SSTP VPN 客户端。\nVPN Azure 是一个云 VPN 服务由 SoftEther 公司经营。VPN Azure 是免费的,可提供给任何人。访问 http://www.vpnazure.net/ 查看详细信息和如何使用的说明。\n\nVPN Azure 主机名与动态 DNS 设置的主机名相同,但改变的域名后缀为“vpnazure.net”。要改变主机名使用 DynamicDnsSetHostname 命令。\n\n要执行此命令,你必须具有 VPN 服务器管理员权限。\n此命令不能在 VPN 网桥上运行。\n以集群成员运行的 VPN 服务器的虚拟 HUB 不能执行此命令。 CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index c7e9698c..0f79db28 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -6463,7 +6463,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED Connection to VPN Azure Cloud Server is Es CMD_VpnAzureGetStatus_PRINT_HOSTNAME Hostname of this VPN Server on VPN Azure Service -# VpnAzureSetStatus command +# VpnAzureSetEnable command CMD_VpnAzureSetEnable Enable / Disable VPN Azure Function CMD_VpnAzureSetEnable_Help Enable or disable the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster. CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index c6dd947e..b7e2f4eb 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -6470,7 +6470,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED VPN Azure クラウドサーバーへ接 CMD_VpnAzureGetStatus_PRINT_HOSTNAME VPN Azure サービス上でのホスト名 -# VpnAzureSetStatus コマンド +# VpnAzureSetEnable コマンド CMD_VpnAzureSetEnable VPN Azure 機能の有効化 / 無効化 CMD_VpnAzureSetEnable_Help VPN Azure 機能を有効または無効にします。\n\nVPN Azure により、会社のパソコンに自宅や外出先のパソコンから非常に簡単に VPN 接続できるようになります。VPN 接続中は会社のパソコンを経由して、社内 LAN の他のサーバーにもアクセスできます。\n会社のパソコン (VPN Server) にはグローバル IP アドレスは不要です。ファイアウォールや NAT の内側であっても動作し、ネットワーク管理者による設定は一切必要ありません。VPN クライアントとなる自宅のパソコンでは、Windows に標準付属の SSTP VPN クライアントを使用できます。\nVPN Azure は、SoftEther VPN Server をお使いの方はどなたでも無料で利用できるクラウド VPN サービスです。ソフトイーサ株式会社によって運営されています。使い方は http://www.vpnazure.net/ に掲載されています。\n\nVPN Azure ホスト名はダイナミック DNS サービスのホスト名のドメイン部分を "vpnazure.net" に変更したものが使用されます。ホスト名を変更するには DynamicDnsSetHostname コマンドを使用してください。\n\nこのコマンドを実行するには、VPN Server の管理者権限が必要です。\nこのコマンドは、VPN Bridge では実行できません。\nこのコマンドは、クラスタとして動作している VPN Server の仮想 HUB では実行できません。 CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] diff --git a/src/bin/hamcore/strtable_ko.stb b/src/bin/hamcore/strtable_ko.stb index de30a1d2..de81e586 100644 --- a/src/bin/hamcore/strtable_ko.stb +++ b/src/bin/hamcore/strtable_ko.stb @@ -6445,7 +6445,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED VPN Azure 클라우드 서버에 연결 CMD_VpnAzureGetStatus_PRINT_HOSTNAME VPN Azure 서비스에서 호스트 이름 -# VpnAzureSetStatus 명령 +# VpnAzureSetEnable 명령 CMD_VpnAzureSetEnable VPN Azure 기능의 활성화/비활성화 CMD_VpnAzureSetEnable_Help VPN Azure 기능을 활성화하거나 비활성화합니다. \n \nVPN Azure하여 회사의 PC에 가정이나 이동 PC에서 매우 쉽게 VPN 연결 할 수 있습니다. VPN 연결 중에 회사의 컴퓨터를 통해 사내 LAN의 다른 서버에 액세스 할 수 있습니다. \n 회사 컴퓨터 (VPN Server)는 글로벌 IP 주소는 필요하지 않습니다. 방화벽이나 NAT 뒤에라도 작동하고 네트워크 관리자의 설정은 필요하지 않습니다. VPN 클라이언트가 될 자택의 PC에서는 Windows에 표준 부속의 SSTP VPN 클라이언트를 사용할 수 있습니다. \nVPN Azure는 SoftEther VPN Server를 사용하시는 분들은 누구나 무료로 이용할 수 클라우드 VPN 서비스입니다. 소프트 이사 회사에 의해 운영되고 있습니다. 사용법은 http://www.vpnazure.net/에 게재되어 있습니다. \n \nVPN Azure 호스트 이름은 동적 DNS 서비스 호스트 이름의 도메인 부분을 "vpnazure.net"로 변경 한 것이 사용됩니다. 호스트 이름을 변경하려면 DynamicDnsSetHostname 명령을 사용하십시오. \n \n이 명령을 실행하려면 VPN Server 관리자 권한이 있어야합니다. \n이 명령은 VPN Bridge에서는 실행되지 않습니다. \n이 명령은 클러스터로 작동하는 VPN Server의 가상 HUB에서는 실행되지 않습니다. CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] diff --git a/src/bin/hamcore/strtable_ru.stb b/src/bin/hamcore/strtable_ru.stb index bc29456c..e7a2fda1 100644 --- a/src/bin/hamcore/strtable_ru.stb +++ b/src/bin/hamcore/strtable_ru.stb @@ -6463,7 +6463,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED Connection to VPN Azure Cloud Server is Es CMD_VpnAzureGetStatus_PRINT_HOSTNAME Hostname of this VPN Server on VPN Azure Service -# VpnAzureSetStatus command +# VpnAzureSetEnable command CMD_VpnAzureSetEnable Enable / Disable VPN Azure Function CMD_VpnAzureSetEnable_Help Enable or disable the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster. CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] diff --git a/src/bin/hamcore/strtable_tw.stb b/src/bin/hamcore/strtable_tw.stb index 0eec56e3..289506ec 100644 --- a/src/bin/hamcore/strtable_tw.stb +++ b/src/bin/hamcore/strtable_tw.stb @@ -6478,7 +6478,7 @@ CMD_VpnAzureGetStatus_PRINT_CONNECTED 至 VPN Azure 雲伺服器的連接建立 CMD_VpnAzureGetStatus_PRINT_HOSTNAME 在 VPN Azure 服務上的本 VPN 伺服器的主機名稱 -# VpnAzureSetStatus command +# VpnAzureSetEnable command CMD_VpnAzureSetEnable 啟用/禁用 VPN Azure 功能 CMD_VpnAzureSetEnable_Help 啟用或禁用 VPN Azure 功能。\n\nVPN Azure 可以更容易地從你家裡的電腦到你辦公室的電腦建立一個 VPN 會話。當一個 VPN 連接建立了,您可以訪問您公司私人網路絡上的任何其他伺服器。\n在辦公室的電腦(VPN 伺服器)上,你並不需要一個全球 IP 位址。它可以在防火牆或 NAT 後面工作。無需網路系統管理員的配置。您可以在您的家用電腦使用 Windows 內置的 SSTP VPN 用戶端。\nVPN Azure 是一個雲 VPN 服務由 SoftEther 公司經營。VPN Azure 是免費的,可提供給任何人。訪問 http://www.vpnazure.net/ 查看詳細資訊和如何使用的說明。\n\nVPN Azure 主機名稱與動態 DNS 設置的主機名稱相同,但改變的功能變數名稱尾碼為“vpnazure.net”。要改變主機名稱使用 DynamicDnsSetHostname 命令。\n\n要執行此命令,你必須具有 VPN 伺服器管理員許可權。\n此命令不能在 VPN 橋接器上運行。\n以集群成員運行的 VPN 伺服器的虛擬 HUB 不能執行此命令。 CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] From 643cbbbf88b88416737675d6af5eae24a5872f47 Mon Sep 17 00:00:00 2001 From: hiura Date: Tue, 12 Sep 2023 10:20:51 +0900 Subject: [PATCH 11/63] Bind outgoing connection to a specific IP address (avoid illegal access) --- src/Mayaqua/Network.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index b81fe5e1..15fd704d 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -13681,6 +13681,14 @@ char *PrintError(int ErrorCode) Message = "Cannot assign requested address."; break; + case WSAEISCONN: + Message = "Socket is already connected."; // Added on AUG.10, 2023 + break; + + case WSAEINVAL: + Message = "Invalid argument."; // Added on AUG.10, 2023 + break; + default: Message = ""; break; @@ -13906,16 +13914,20 @@ SOCKET BindConnectTimeoutIPv4(IP* localIP, UINT localport, IP* ip, UINT port, UI if (s != INVALID_SOCKET) { int ier; IP tmpIP; + IP *tmpIP2; if (localIP == BIND_LOCALIP_NULL) { - StrToIP(&tmpIP, "0.0.0.0"); // A NULL address for the argument "localIP" is treated as if "0::0" in IPV4 was specified. - localIP = &tmpIP; + StrToIP(&tmpIP, "0.0.0.0"); // A NULL address for the argument "localIP" is treated as if "0.0.0.0" in IPV4 was specified. + tmpIP2 = &tmpIP; + } + else { + tmpIP2 = localIP; } - if ((IsZeroIP(localIP) == false) || (localport != 0)) { + if ((IsZeroIP(tmpIP2) == false) || (localport != 0)) { // Bind the socket - if (bind_sock(s, localIP, localport) != 0) { + if (bind_sock(s, tmpIP2, localport) != 0) { #ifdef OS_WIN32 ier = WSAGetLastError(); Debug("IPv4 bind() failed with error: %d %s\n", ier, PrintError(ier)); @@ -14635,16 +14647,20 @@ void BindConnectThreadForIPv6(THREAD* thread, void* param) if (s != INVALID_SOCKET){ int ier; IP tmpIP; + IP *tmpIP2; if (p->LocalIP == BIND_LOCALIP_NULL) { StrToIP(&tmpIP, "0::0"); // A NULL address for the argument "p->LocalIP" is treated as if "0::0" in IPV6 was specified. - p->LocalIP = &tmpIP; + tmpIP2 = &tmpIP; + } + else { + tmpIP2 = p->LocalIP; } - if ((IsZeroIP(p->LocalIP) == false) || (p->LocalPort != 0)){ + if ((IsZeroIP(tmpIP2) == false) || (p->LocalPort != 0)){ // Bind the socket - if (bind_sock(s, p->LocalIP, p->LocalPort) != 0) { + if (bind_sock(s, tmpIP2, p->LocalPort) != 0) { #ifdef OS_WIN32 ier = WSAGetLastError(); Debug("IPv6 bind() failed with error: %d %s\n", ier, PrintError(ier)); From 2fd6c0b76a5beaeb6b664a3ee9bafbf0173fca8a Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Tue, 12 Sep 2023 22:43:01 +0200 Subject: [PATCH 12/63] add missing localization this is a follow up of https://github.com/SoftEtherVPN/SoftEtherVPN/pull/1867 English localization is added for now --- src/bin/hamcore/strtable_cn.stb | 2 ++ src/bin/hamcore/strtable_ko.stb | 2 ++ src/bin/hamcore/strtable_pt_br.stb | 2 ++ src/bin/hamcore/strtable_ru.stb | 2 ++ src/bin/hamcore/strtable_tw.stb | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb index abda7401..fa462554 100644 --- a/src/bin/hamcore/strtable_cn.stb +++ b/src/bin/hamcore/strtable_cn.stb @@ -2437,6 +2437,8 @@ STATIC17 其它配置(&G): R_NO_ROUTING 不要调整路由表(&R) STATIC18 除非你得到系统管理员的同意或者你有网络和安全方面的专业知识,否则请保持此对话框的默认设置。 STATIC19 VoIP / QoS 功能可以处理高优先级数据包,如 IP 电话数据包 (VoIP) 可以被更快的传输。 +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS 禁用 VoIP / &QoS 功能 IDOK 确定(&O) IDCANCEL 取消 diff --git a/src/bin/hamcore/strtable_ko.stb b/src/bin/hamcore/strtable_ko.stb index de81e586..f1576dab 100644 --- a/src/bin/hamcore/strtable_ko.stb +++ b/src/bin/hamcore/strtable_ko.stb @@ -2402,6 +2402,8 @@ STATIC17 기타 설정 (&G): R_NO_ROUTING 라우팅 테이블의 조정 작업을 수행하지 (&R) STATIC18 이 설정 화면의 설정은 시스템 관리자의 지시가있을 경우, 네트워크 및 보안에 대해 상세한 지식을 가지고있는 경우를 제외하고는 변경하지 마십시오. STATIC19 VoIP/QoS 지원 기능을 사용하면 IP 전화 패킷 등의 우선 순위가 높은 패킷을 VPN에서 고속으로 전송할 수 있습니다. +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS VoIP/QoS 지원 기능을 비활성화 (&Q) IDOK & OK IDCANCEL 취소 diff --git a/src/bin/hamcore/strtable_pt_br.stb b/src/bin/hamcore/strtable_pt_br.stb index 89083eeb..183e30eb 100644 --- a/src/bin/hamcore/strtable_pt_br.stb +++ b/src/bin/hamcore/strtable_pt_br.stb @@ -2390,6 +2390,8 @@ STATIC17 Outras confi&gurações: R_NO_ROUTING Sem ajustes na tabela de &roteamento STATIC18 Mantenha as configurações padrão nesta caixa de diálogo, a menos que seja solicitado por um administrador do sistema ou se você possui experiência em redes e segurança. STATIC19 As funções VoIP/QoS lidam com pacotes de alta prioridade, para serem transmitidos mais rapidamente. +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS Desativar função VoIP / &QoS IDOK &OK IDCANCEL Cancelar diff --git a/src/bin/hamcore/strtable_ru.stb b/src/bin/hamcore/strtable_ru.stb index e7a2fda1..5bc1653d 100644 --- a/src/bin/hamcore/strtable_ru.stb +++ b/src/bin/hamcore/strtable_ru.stb @@ -2421,6 +2421,8 @@ STATIC17 Другие конфигурации: R_NO_ROUTING Не вносить изменения в таблицу маршрутизации STATIC18 Если у вас нет опыта работы с сетью и безопасностью, то оставьте настройки в этом окне по умолчанию. STATIC19 Функции VoIP/QoS обрабатывают пакеты (например VoIP) с высоким приоритетом для более быстрой передачи. +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS Отключить функции VoIP / QoS IDOK &OK IDCANCEL Отмена diff --git a/src/bin/hamcore/strtable_tw.stb b/src/bin/hamcore/strtable_tw.stb index 289506ec..0f5d500d 100644 --- a/src/bin/hamcore/strtable_tw.stb +++ b/src/bin/hamcore/strtable_tw.stb @@ -2439,6 +2439,8 @@ STATIC17 其它配置(&G): R_NO_ROUTING 不要調整路由表(&R) STATIC18 除非你得到系統管理員的同意或者你有網路和安全方面的專業知識,否則請保持此對話方塊的默認設置。 STATIC19 VoIP / QoS 功能可以處理高優先級封包,如 IP 電話封包 (VoIP) 可以被更快的傳輸。 +STATIC20 Source IP Address: +STATIC21 Source Port Number: R_DISABLE_QOS 禁用 VoIP / &QoS 功能 IDOK 確定(&O) IDCANCEL 取消 From fc2a33d1f32b598849fc8210f8c052f57f0397c0 Mon Sep 17 00:00:00 2001 From: puripuri2100 Date: Fri, 15 Sep 2023 09:39:11 +0900 Subject: [PATCH 13/63] fix missing arg --- src/bin/hamcore/strtable_pt_br.stb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/hamcore/strtable_pt_br.stb b/src/bin/hamcore/strtable_pt_br.stb index 183e30eb..52540cb4 100644 --- a/src/bin/hamcore/strtable_pt_br.stb +++ b/src/bin/hamcore/strtable_pt_br.stb @@ -4443,7 +4443,7 @@ CMD_Debug_Msg2 The debug command has executed.\nResults: \"%S\" # Crash command CMD_Crash Raise a error on the VPN Server / Bridge to terminate the process forcefully. CMD_Crash_Help This command will raise a fatal error (memory access violation) on the VPN Server / Bridge running process in order to crash the process. As the result, VPN Server / Bridge will be terminated and restarted if it is running as a service mode. If the VPN Server is running as a user mode, the process will not automatically restarted.\nThis command is for a situation when the VPN Server / Bridge is under a non-recoverable error or the process is in an infinite loop. This command will disconnect all VPN Sessions on the VPN Server / Bridge. All unsaved settings in the memory of VPN Server / Bridge will be lost.\nBefore run this command, run the Flush command to try to save volatile data to the configuration file.\nTo execute this command, you must have VPN Server / VPN Bridge administrator privileges. -CMD_Crash_Args Crash [sim] +CMD_Crash_Args Crash [yes] CMD_Crash_[yes] Input "yes" for confirmation. CMD_Crash_Msg Sending the Crush command to the VPN Server. The VPN Server will be let to crash immediately, so you can never get the result value of this command. After this moment, vpncmd will be disconnected from the VPN Server. CMD_Crash_Confirm Do you really want to crash the VPN Server?\nInput "yes" if it is ok: From 1be55ebb94161923258fe317a8ecb8496d46ab8b Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sat, 16 Sep 2023 00:02:29 +0200 Subject: [PATCH 14/63] src/vpndrvinst/main.c: add missing header file --- src/vpndrvinst/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vpndrvinst/main.c b/src/vpndrvinst/main.c index 658f92a1..e947ac97 100644 --- a/src/vpndrvinst/main.c +++ b/src/vpndrvinst/main.c @@ -2,6 +2,7 @@ #include "Dialog.h" #include +#include void ShowUsage() { From f736d18267e48918a5e1e2fac6b38a8fc8f4d224 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sat, 16 Sep 2023 00:03:03 +0200 Subject: [PATCH 15/63] temporarily suppress clang warnings on "-Wincompatible-function-pointer-types" --- src/Cedar/SW.c | 6 ++++++ src/Cedar/SeLowUser.c | 3 +++ src/Cedar/WinUi.c | 6 ++++++ src/Mayaqua/Win32.c | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/Cedar/SW.c b/src/Cedar/SW.c index 4e4ca3c9..a953021c 100644 --- a/src/Cedar/SW.c +++ b/src/Cedar/SW.c @@ -113,9 +113,12 @@ bool SwCompileSfx(LIST *o, wchar_t *dst_filename) } // Get the API related to the resource editing + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" _BeginUpdateResourceW = (HANDLE (__stdcall *)(LPCWSTR,UINT))GetProcAddress(hKernel32, "BeginUpdateResourceW"); _UpdateResourceA = (UINT (__stdcall *)(HANDLE,LPCSTR,LPCSTR,WORD,LPVOID,DWORD))GetProcAddress(hKernel32, "UpdateResourceA"); _EndUpdateResourceW = (UINT (__stdcall *)(HANDLE,UINT))GetProcAddress(hKernel32, "EndUpdateResourceW"); + #pragma clang diagnostic pop if (_BeginUpdateResourceW != NULL && _UpdateResourceA != NULL && _EndUpdateResourceW != NULL) { @@ -647,7 +650,10 @@ UINT SWExec() bool is_datafile_exists = false; // Examine whether DATAFILE resources are stored in setup.exe that is currently running + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" EnumResourceNamesA(NULL, SW_SFX_RESOURCE_TYPE, SwEnumResourceNamesProc, (LONG_PTR)(&is_datafile_exists)); + #pragma clang diagnostic pop if (is_datafile_exists) { diff --git a/src/Cedar/SeLowUser.c b/src/Cedar/SeLowUser.c index 80c38fa9..f6b40777 100644 --- a/src/Cedar/SeLowUser.c +++ b/src/Cedar/SeLowUser.c @@ -93,9 +93,12 @@ void SuDeleteGarbageInfsInner() return; } + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" _SetupUninstallOEMInfA = (UINT (__stdcall *)(PCSTR,DWORD,PVOID)) GetProcAddress(hSetupApiDll, "SetupUninstallOEMInfA"); + #pragma clang diagnostic pop if (_SetupUninstallOEMInfA != NULL) { diff --git a/src/Cedar/WinUi.c b/src/Cedar/WinUi.c index 904db691..8b1de535 100644 --- a/src/Cedar/WinUi.c +++ b/src/Cedar/WinUi.c @@ -903,7 +903,10 @@ void ShowWizard(HWND hWndParent, WIZARD *w, UINT start_id) h.phpage = (HPROPSHEETPAGE *)pages_array; h.pszbmHeader = MAKEINTRESOURCEW(w->Bitmap); h.pszCaption = w->Caption; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" h.pfnCallback = WizardDlgProc; + #pragma clang diagnostic pop start_page = GetWizardPage(w, start_id); if (start_page != NULL) @@ -3487,7 +3490,10 @@ HWND SearchWindow(wchar_t *caption) p.caption = caption; p.hWndFound = NULL; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" EnumWindows(SearchWindowEnumProc, (LPARAM)&p); + #pragma clang diagnostic pop return p.hWndFound; } diff --git a/src/Mayaqua/Win32.c b/src/Mayaqua/Win32.c index 32d30be4..7ed778cb 100644 --- a/src/Mayaqua/Win32.c +++ b/src/Mayaqua/Win32.c @@ -2846,7 +2846,10 @@ bool Win32InitThread(THREAD *t) // Thread creation t->pData = w; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" hThread = (HANDLE)_beginthreadex(NULL, 0, Win32DefaultThreadProc, info, 0, &thread_id); + #pragma clang diagnostic pop if (hThread == NULL) { // Thread creation failure From f57f05a5999d0ee370630a4bc8993db396d06556 Mon Sep 17 00:00:00 2001 From: hiura Date: Sun, 17 Sep 2023 16:36:57 +0900 Subject: [PATCH 16/63] Bind outgoing connection to a specific IP address (fix a bug) --- src/Cedar/Protocol.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index feb29ece..643af069 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -6292,8 +6292,6 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) localIP = BIND_LOCALIP_NULL; // Specify not to bind } else { - Debug("ClientConnectGetSocket(): Using client option %r and %d for binding\n" - , sess->ClientOption->BindLocalIP, sess->ClientOption->BindLocalPort); // Nonzero address is for source IP address to bind. Zero address is for dummy not to bind. if (IsZeroIP(&sess->ClientOption->BindLocalIP) == true) { localIP = BIND_LOCALIP_NULL; @@ -6301,6 +6299,8 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) else { localIP = &sess->ClientOption->BindLocalIP; } + Debug("ClientConnectGetSocket(): Source IP address %r and source port number %d for binding\n" + , &sess->ClientOption->BindLocalIP, sess->ClientOption->BindLocalPort); } } // In the case of second and subsequent TCP/IP connections @@ -6314,7 +6314,7 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect) } else { localport = sess->ClientOption->BindLocalPort + Count(sess->Connection->CurrentNumConnection) - 1; - Debug("ClientConnectGetSocket(): Additional port number %u\n", localport); + Debug("ClientConnectGetSocket(): Additional source port number %u\n", localport); } // Bottom of Bind outgoing connection From b8e542105f748b88e518a969c2189eca2e92f7dd Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 18:24:12 +0900 Subject: [PATCH 17/63] Fix Vulnerability: CVE-2023-27395 TALOS-2023-1735 SoftEther VPN vpnserver WpcParsePacket () heap-based buffer overflow vulnerability https://www.softether.org/9-about/News/904-SEVPN202301 https://jvn.jp/en/jp/JVN64316789/ --- src/Cedar/DDNS.c | 4 ---- src/Cedar/Wpc.c | 12 ++++++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Cedar/DDNS.c b/src/Cedar/DDNS.c index 87cd49f1..486c3bfe 100644 --- a/src/Cedar/DDNS.c +++ b/src/Cedar/DDNS.c @@ -541,13 +541,9 @@ UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace } } - - Format(url2, sizeof(url2), "%s?v=%I64u", url, Rand64()); Format(url3, sizeof(url3), url2, key_hash_str[2], key_hash_str[3]); - ReplaceStr(url3, sizeof(url3), url3, "https://", "http://"); - ReplaceStr(url3, sizeof(url3), url3, ".servers", ".open.servers"); cert_hash = StrToBin(DDNS_CERT_HASH); diff --git a/src/Cedar/Wpc.c b/src/Cedar/Wpc.c index 64e8a952..c53a32aa 100644 --- a/src/Cedar/Wpc.c +++ b/src/Cedar/Wpc.c @@ -313,8 +313,16 @@ BUF *WpcDataEntryToBuf(WPC_ENTRY *e) } data_size = e->Size + 4096; - data = Malloc(data_size); - size = DecodeSafe64(data, e->Data, e->Size); + data = ZeroMalloc(data_size); + + if (e->Size >= 1) + { + size = DecodeSafe64(data, e->Data, e->Size); + } + else + { + size = 0; + } b = NewBuf(); WriteBuf(b, data, size); From c49e462ed1e7df813bc14022896bb26fa75546de Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 18:26:17 +0900 Subject: [PATCH 18/63] Fix Vulnerability: CVE-2023-22325 TALOS-2023-1736 SoftEther VPN DCRegister DDNS_RPC_MAX_RECV_SIZE denial of service vulnerability https://www.softether.org/9-about/News/904-SEVPN202301 https://jvn.jp/en/jp/JVN64316789/ --- src/Cedar/DDNS.h | 2 +- src/Mayaqua/Memory.c | 4 ++++ src/Mayaqua/Network.c | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Cedar/DDNS.h b/src/Cedar/DDNS.h index 0775766f..c8fa0207 100644 --- a/src/Cedar/DDNS.h +++ b/src/Cedar/DDNS.h @@ -43,7 +43,7 @@ #define DDNS_URL2_V4_ALT "http://get-my-ip.ddns.uxcom.jp/ddns/getmyip.ashx" #define DDNS_URL2_V6_ALT "http://get-my-ip-v6.ddns.uxcom.jp/ddns/getmyip.ashx" -#define DDNS_RPC_MAX_RECV_SIZE DYN32(DDNS_RPC_MAX_RECV_SIZE, (128 * 1024 * 1024)) +#define DDNS_RPC_MAX_RECV_SIZE DYN32(DDNS_RPC_MAX_RECV_SIZE, (38 * 1024 * 1024)) // Connection Timeout #define DDNS_CONNECT_TIMEOUT DYN32(DDNS_CONNECT_TIMEOUT, (15 * 1000)) diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c index 96ff994a..aa793d70 100644 --- a/src/Mayaqua/Memory.c +++ b/src/Mayaqua/Memory.c @@ -3114,6 +3114,10 @@ void AdjustBufSize(BUF *b, UINT new_size) while (b->SizeReserved < new_size) { + if (b->SizeReserved > 0x7FFFFFFF) + { + AbortExitEx("AdjustBufSize(): too large buffer size"); + } b->SizeReserved = b->SizeReserved * 2; } b->Buf = ReAlloc(b->Buf, b->SizeReserved); diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 04aebdea..b170d130 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -1191,7 +1191,9 @@ void RUDPProcess_NatT_Recv(RUDP_STACK *r, UDPPACKET *udp) bool is_ok = PackGetBool(p, "ok"); UINT64 tran_id = PackGetInt64(p, "tran_id"); - ExtractAndApplyDynList(p); + // This ExtractAndApplyDynList() calling was removed because it is not actually used and could be abused by + // illegal UDP packets that spoof the source IP address. 2023-6-14 Daiyuu Nobori + // ExtractAndApplyDynList(p); if (r->ServerMode) { From 2dec52b875fec5ebc57fc57632f8b1dfdda9ccd2 Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Sat, 7 Oct 2023 04:42:00 +0200 Subject: [PATCH 19/63] Heap area protection of memory has been enhanced. When memory is released and reallocated, a random security value called a canary is written to the before/after area of memory, and if the value has been modified, the process is terminated (restarted) for safety, assuming it is a buffer overflow of the memory area. This feature may effectively prevent confidentiality or integrity violations in the event that some heap area overflow vulnerability is discovered in this system in the future. --- src/Mayaqua/Kernel.c | 24 ++++ src/Mayaqua/MayaType.h | 3 +- src/Mayaqua/Mayaqua.c | 2 + src/Mayaqua/Memory.c | 248 ++++++++++++++++++++++++++++++++++------- src/Mayaqua/Memory.h | 41 +++++-- src/Mayaqua/Tick64.c | 17 +++ src/Mayaqua/Tick64.h | 1 + src/Mayaqua/Unix.c | 62 +++++++++++ src/Mayaqua/Unix.h | 1 + 9 files changed, 347 insertions(+), 52 deletions(-) diff --git a/src/Mayaqua/Kernel.c b/src/Mayaqua/Kernel.c index 99890a08..ec4621f7 100644 --- a/src/Mayaqua/Kernel.c +++ b/src/Mayaqua/Kernel.c @@ -2100,7 +2100,31 @@ void AbortExitEx(char *msg) f = fopen("abort_error_log.txt", "w"); if (f != NULL) { + SYSTEMTIME time = { 0 }; + char time_str[128] = { 0 }; + char *crlf = "\r\n"; + char *tag = "---------"; + + LocalTime(&time); + + sprintf(time_str, "%04u-%02u-%02u %02u:%02u:%02u", + time.wYear, time.wMonth, time.wDay, + time.wHour, time.wMinute, time.wSecond); + + fwrite(tag, 1, strlen(tag), f); + + fwrite(crlf, 1, strlen(crlf), f); + + fwrite(time_str, 1, strlen(time_str), f); + + fwrite(crlf, 1, strlen(crlf), f); + fwrite(msg, 1, strlen(msg), f); + + fwrite(crlf, 1, strlen(crlf), f); + + fwrite(crlf, 1, strlen(crlf), f); + fclose(f); } diff --git a/src/Mayaqua/MayaType.h b/src/Mayaqua/MayaType.h index efdfaa59..483fedad 100644 --- a/src/Mayaqua/MayaType.h +++ b/src/Mayaqua/MayaType.h @@ -282,7 +282,8 @@ typedef struct TRACKING_LIST TRACKING_LIST; typedef struct IO IO; // Memory.h -typedef struct MEMTAG MEMTAG; +typedef struct MEMTAG1 MEMTAG1; +typedef struct MEMTAG2 MEMTAG2; typedef struct BUF BUF; typedef struct FIFO FIFO; typedef struct LIST LIST; diff --git a/src/Mayaqua/Mayaqua.c b/src/Mayaqua/Mayaqua.c index 88f03684..86492751 100644 --- a/src/Mayaqua/Mayaqua.c +++ b/src/Mayaqua/Mayaqua.c @@ -65,6 +65,8 @@ void InitProcessCallOnce() { init_proc_once_flag = true; + InitCanaryRand(); + #ifdef OS_WIN32 MsInitProcessCallOnce(); #endif // OS_WIN32 diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c index aa793d70..67929483 100644 --- a/src/Mayaqua/Memory.c +++ b/src/Mayaqua/Memory.c @@ -16,10 +16,16 @@ #include "Object.h" #include "OS.h" #include "Str.h" +#include "Tick64.h" #include "Tracking.h" #include #include +#include + +#ifdef OS_UNIX +#include +#endif #include @@ -34,6 +40,105 @@ static UINT fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE; +static bool canary_inited = false; +typedef struct CANARY_RAND_DATA +{ + UCHAR Data[CANARY_RAND_SIZE + 4]; +} CANARY_RAND_DATA; + +static CANARY_RAND_DATA canary_rand_data[NUM_CANARY_RAND] = { 0 }; + +static UINT64 canary_memtag_magic1 = 0; +static UINT64 canary_memtag_magic2 = 0; + +UCHAR *GetCanaryRand(UINT id) +{ + if (id >= NUM_CANARY_RAND) + { + id = NUM_CANARY_RAND - 1; + } + + return &((canary_rand_data[id].Data)[0]); +} + +void InitCanaryRand() +{ + SYSTEMTIME st = { 0 }; + char random_seed[1024] = { 0 }; + UINT64 t1 = 0, t2 = 0; + if (canary_inited) + { + return; + } + +#ifdef OS_WIN32 + Win32GetSystemTime(&st); + memcpy(&t1, ((UCHAR *)&st) + 0, 8); + memcpy(&t2, ((UCHAR *)&st) + 8, 8); +#else // OS_WIN32 + struct timeval tv = { 0 }; + struct timezone tz = { 0 }; + gettimeofday(&tv, &tz); + t1 = (UINT64)tv.tv_sec; + t2 = (UINT64)tv.tv_usec; +#endif // OS_WIN32 + + { + UINT64 dos_rand = (UINT64)rand(); + UINT64 tick1 = TickHighresNano64(true); + UINT64 tick2 = TickHighresNano64(true); + + UINT i; + + void *p1 = malloc(1); + void *p2 = malloc(1); + + for (i = 0;i < NUM_CANARY_RAND;i++) + { + // using sprintf() here is safe. + sprintf(random_seed, + "%u " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%llu " + "%u " + , + i, + (UINT64)InitCanaryRand, + (UINT64)&canary_inited, + (UINT64) & ((canary_rand_data[0].Data)[0]), + (UINT64)&random_seed[0], + tick1, + tick2, + dos_rand, + (UINT64)p1, + (UINT64)p2, + t1, + t2, + ~i + ); + + Sha0(canary_rand_data[i].Data, random_seed, (UINT)strlen(random_seed)); + } + + free(p1); + free(p2); + + canary_memtag_magic1 = *((UINT64 *)(GetCanaryRand(CANARY_RAND_ID_MEMTAG_MAGIC) + 0)); + canary_memtag_magic2 = *((UINT64 *)(GetCanaryRand(CANARY_RAND_ID_MEMTAG_MAGIC) + 8)); + + canary_inited = true; + } +} + // New PRand PRAND *NewPRand(void *key, UINT key_size) { @@ -3519,33 +3624,52 @@ void *Malloc(UINT size) } void *MallocEx(UINT size, bool zero_clear_when_free) { - MEMTAG *tag; + MEMTAG1 *tag1; + MEMTAG2 *tag2; UINT real_size; + if (canary_inited == false) + { + InitCanaryRand(); + } + + if (size > MAX_MALLOC_MEM_SIZE) + { + AbortExitEx("MallocEx() error: too large size"); + } + real_size = CALC_MALLOCSIZE(size); - tag = InternalMalloc(real_size); + tag1 = InternalMalloc(real_size); - Zero(tag, sizeof(MEMTAG)); - tag->Magic = MEMTAG_MAGIC; - tag->Size = size; - tag->ZeroFree = zero_clear_when_free; + tag1->Magic = canary_memtag_magic1 ^ ((UINT64)tag1 * GOLDEN_RATION_PRIME_U64); + tag1->Size = size; + tag1->ZeroFree = zero_clear_when_free; - return MEMTAG_TO_POINTER(tag); + tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2)); + tag2->Magic = canary_memtag_magic2 ^ ((UINT64)tag2 * GOLDEN_RATION_PRIME_U64); + + return MEMTAG1_TO_POINTER(tag1); } // Get memory size UINT GetMemSize(void *addr) { - MEMTAG *tag; + MEMTAG1 *tag; + + if (canary_inited == false) + { + InitCanaryRand(); + } + // Validate arguments if (IS_NULL_POINTER(addr)) { return 0; } - tag = POINTER_TO_MEMTAG(addr); - CheckMemTag(tag); + tag = POINTER_TO_MEMTAG1(addr); + CheckMemTag1(tag); return tag->Size; } @@ -3553,20 +3677,35 @@ UINT GetMemSize(void *addr) // ReAlloc void *ReAlloc(void *addr, UINT size) { - MEMTAG *tag; + MEMTAG1 *tag1; + MEMTAG2 *tag2; bool zerofree; + + if (canary_inited == false) + { + InitCanaryRand(); + } + + if (size > MAX_MALLOC_MEM_SIZE) + { + AbortExitEx("ReAlloc() error: too large size"); + } + // Validate arguments if (IS_NULL_POINTER(addr)) { return NULL; } - tag = POINTER_TO_MEMTAG(addr); - CheckMemTag(tag); + tag1 = POINTER_TO_MEMTAG1(addr); + CheckMemTag1(tag1); - zerofree = tag->ZeroFree; + tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2)); + CheckMemTag2(tag2); - if (tag->Size == size) + zerofree = tag1->ZeroFree; + + if (tag1->Size == size) { // No size change return addr; @@ -3578,10 +3717,10 @@ void *ReAlloc(void *addr, UINT size) // Size changed (zero clearing required) void *new_p = MallocEx(size, true); - if (tag->Size <= size) + if (tag1->Size <= size) { // Size expansion - Copy(new_p, addr, tag->Size); + Copy(new_p, addr, tag1->Size); } else { @@ -3597,13 +3736,22 @@ void *ReAlloc(void *addr, UINT size) else { // Size changed - MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size)); + MEMTAG1 *tag1_new; + MEMTAG2 *tag2_new; - Zero(tag2, sizeof(MEMTAG)); - tag2->Magic = MEMTAG_MAGIC; - tag2->Size = size; + tag1->Magic = 0; + tag2->Magic = 0; - return MEMTAG_TO_POINTER(tag2); + tag1_new = InternalReAlloc(tag1, CALC_MALLOCSIZE(size)); + + tag1_new->Magic = canary_memtag_magic1 ^ ((UINT64)tag1_new * GOLDEN_RATION_PRIME_U64); + tag1_new->Size = size; + tag1_new->ZeroFree = 0; + + tag2_new = (MEMTAG2 *)(((UCHAR *)tag1_new) + CALC_MALLOCSIZE(size) - sizeof(MEMTAG2)); + tag2_new->Magic = canary_memtag_magic2 ^ ((UINT64)tag2_new * GOLDEN_RATION_PRIME_U64); + + return MEMTAG1_TO_POINTER(tag1_new); } } } @@ -3611,25 +3759,35 @@ void *ReAlloc(void *addr, UINT size) // Free void Free(void *addr) { - MEMTAG *tag; + MEMTAG1 *tag1; + MEMTAG2 *tag2; // Validate arguments if (IS_NULL_POINTER(addr)) { return; } - tag = POINTER_TO_MEMTAG(addr); - CheckMemTag(tag); + if (canary_inited == false) + { + InitCanaryRand(); + } - if (tag->ZeroFree) + tag1 = POINTER_TO_MEMTAG1(addr); + CheckMemTag1(tag1); + + tag2 = (MEMTAG2 *)(((UCHAR *)tag1) + CALC_MALLOCSIZE(tag1->Size) - sizeof(MEMTAG2)); + CheckMemTag2(tag2); + + if (tag1->ZeroFree) { // Zero clear - Zero(addr, tag->Size); + Zero(addr, tag1->Size); } // Memory release - tag->Magic = 0; - InternalFree(tag); + tag1->Magic = 0; + tag2->Magic = 0; + InternalFree(tag1); } // Free and set pointer's value to NULL @@ -3639,24 +3797,36 @@ void FreeSafe(void **addr) *addr = NULL; } -// Check the memtag -void CheckMemTag(MEMTAG *tag) +// Check the memtag1 +void CheckMemTag1(MEMTAG1 *tag) { - if (IsTrackingEnabled() == false) - { - return; - } - // Validate arguments if (tag == NULL) { - AbortExitEx("CheckMemTag: tag == NULL"); + AbortExitEx("CheckMemTag1: tag1 == NULL"); return; } - if (tag->Magic != MEMTAG_MAGIC) + if (tag->Magic != (canary_memtag_magic1 ^ ((UINT64)tag * GOLDEN_RATION_PRIME_U64))) { - AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC"); + AbortExitEx("CheckMemTag1: tag1->Magic != canary_memtag_magic1"); + return; + } +} + +// Check the memtag2 +void CheckMemTag2(MEMTAG2 *tag) +{ + // Validate arguments + if (tag == NULL) + { + AbortExitEx("CheckMemTag2: tag2 == NULL"); + return; + } + + if (tag->Magic != (canary_memtag_magic2 ^ ((UINT64)tag * GOLDEN_RATION_PRIME_U64))) + { + AbortExitEx("CheckMemTag2: tag2->Magic != canary_memtag_magic2"); return; } } diff --git a/src/Mayaqua/Memory.h b/src/Mayaqua/Memory.h index 8b39cd9d..cb94a06d 100644 --- a/src/Mayaqua/Memory.h +++ b/src/Mayaqua/Memory.h @@ -14,29 +14,38 @@ #define MallocFast Malloc #define ZeroMallocFast ZeroMalloc +#define MAX_MALLOC_MEM_SIZE (0xffffffff - 64) + // Memory size that can be passed to the kernel at a time #define MAX_SEND_BUF_MEM_SIZE (10 * 1024 * 1024) -// The magic number for memory tag -#define MEMTAG_MAGIC 0x49414449 - -#define CALC_MALLOCSIZE(size) ((MAX(size, 1)) + sizeof(MEMTAG)) -#define MEMTAG_TO_POINTER(p) ((void *)(((UCHAR *)(p)) + sizeof(MEMTAG))) -#define POINTER_TO_MEMTAG(p) ((MEMTAG *)(((UCHAR *)(p)) - sizeof(MEMTAG))) -#define IS_NULL_POINTER(p) (((p) == NULL) || ((POINTER_TO_UINT64(p) == (UINT64)sizeof(MEMTAG)))) +#define CALC_MALLOCSIZE(size) (((MAX(size, 1) + 7) / 8) * 8 + sizeof(MEMTAG1) + sizeof(MEMTAG2)) +#define MEMTAG1_TO_POINTER(p) ((void *)(((UCHAR *)(p)) + sizeof(MEMTAG1))) +#define POINTER_TO_MEMTAG1(p) ((MEMTAG1 *)(((UCHAR *)(p)) - sizeof(MEMTAG1))) +#define IS_NULL_POINTER(p) (((p) == NULL) || ((POINTER_TO_UINT64(p) == (UINT64)sizeof(MEMTAG1)))) #define PTR_TO_PTR(p) ((void **)(&p)) +// Golden Ratio Prime +// From https://github.com/torvalds/linux/blob/88c5083442454e5e8a505b11fa16f32d2879651e/include/linux/hash.h +#define GOLDEN_RATION_PRIME_U32 ((UINT32)0x61C88647) +#define GOLDEN_RATION_PRIME_U64 ((UINT64)7046029254386353131ULL) // 0x61C8864680B583EB + // Fixed size of a block of memory pool #define MEMPOOL_MAX_SIZE 3000 -// Memory tag -struct MEMTAG +// Memory tag 1 +struct MEMTAG1 { - UINT Magic; + UINT64 Magic; UINT Size; bool ZeroFree; - UINT Padding; +}; + +// Memory tag 2 +struct MEMTAG2 +{ + UINT64 Magic; }; // Buffer @@ -174,7 +183,8 @@ void *ZeroMallocEx(UINT size, bool zero_clear_when_free); void *ReAlloc(void *addr, UINT size); void Free(void *addr); void FreeSafe(void **addr); -void CheckMemTag(MEMTAG *tag); +void CheckMemTag1(MEMTAG1 *tag); +void CheckMemTag2(MEMTAG2 *tag); UINT GetMemSize(void *addr); void *InternalMalloc(UINT size); @@ -364,5 +374,12 @@ LIST *NewStrList(); void ReleaseStrList(LIST *o); bool AddStrToStrListDistinct(LIST *o, char *str); +#define NUM_CANARY_RAND 32 +#define CANARY_RAND_ID_MEMTAG_MAGIC 0 +#define CANARY_RAND_SIZE 20 + +void InitCanaryRand(); +UCHAR *GetCanaryRand(UINT id); + #endif // MEMORY_H diff --git a/src/Mayaqua/Tick64.c b/src/Mayaqua/Tick64.c index f99a623f..02932677 100644 --- a/src/Mayaqua/Tick64.c +++ b/src/Mayaqua/Tick64.c @@ -34,6 +34,23 @@ UINT64 TickHighres64() } +UINT64 TickHighresNano64(bool raw) +{ + UINT64 ret = 0; + +#ifdef OS_WIN32 + + ret = (UINT64)(MsGetHiResTimeSpan(MsGetHiResCounter()) * 1000000000.0f); + +#else // OS_WIN32 + + ret = UnixGetHighresTickNano64(raw); + +#endif // OS_WIN32 + + return ret; +} + // Convert the Tick value to time UINT64 Tick64ToTime64(UINT64 tick) { diff --git a/src/Mayaqua/Tick64.h b/src/Mayaqua/Tick64.h index 1791c517..bde8517d 100644 --- a/src/Mayaqua/Tick64.h +++ b/src/Mayaqua/Tick64.h @@ -49,6 +49,7 @@ UINT64 Diff64(UINT64 a, UINT64 b); UINT64 Tick64ToTime64(UINT64 tick); UINT64 TickToTime(UINT64 tick); UINT64 TickHighres64(); +UINT64 TickHighresNano64(bool raw); #endif // TICK64_H diff --git a/src/Mayaqua/Unix.c b/src/Mayaqua/Unix.c index bd1263c9..0c3778df 100755 --- a/src/Mayaqua/Unix.c +++ b/src/Mayaqua/Unix.c @@ -2008,6 +2008,68 @@ void UnixGetSystemTime(SYSTEMTIME *system_time) pthread_mutex_unlock(&get_time_lock); } +UINT64 UnixGetHighresTickNano64(bool raw) +{ +#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES) + struct timespec t; + UINT64 ret; + static bool akirame = false; + + if (akirame) + { + return UnixGetTick64() * 1000000ULL; + } + + Zero(&t, sizeof(t)); + + if (raw == false) + { + // Function to get the boot time of the system + // Be careful. The Implementation is depend on the system. +#ifdef CLOCK_HIGHRES + clock_gettime(CLOCK_HIGHRES, &t); +#else // CLOCK_HIGHRES +#ifdef CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &t); +#else // CLOCK_MONOTONIC + clock_gettime(CLOCK_REALTIME, &t); +#endif // CLOCK_MONOTONIC +#endif // CLOCK_HIGHRES + } + else + { + // Function to get the boot time of the system + // Be careful. The Implementation is depend on the system. +#ifdef CLOCK_HIGHRES + clock_gettime(CLOCK_HIGHRES, &t); +#else // CLOCK_HIGHRES +#ifdef CLOCK_MONOTONIC_RAW + clock_gettime(CLOCK_MONOTONIC_RAW, &t); +#else // CLOCK_MONOTONIC_RAW +#ifdef CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &t); +#else // CLOCK_MONOTONIC + clock_gettime(CLOCK_REALTIME, &t); +#endif // CLOCK_MONOTONIC +#endif // CLOCK_MONOTONIC_RAW +#endif // CLOCK_HIGHRES + } + + ret = ((UINT64)((UINT)t.tv_sec)) * 1000000000LL + (UINT64)t.tv_nsec; + + if (akirame == false && ret == 0) + { + ret = UnixGetTick64() * 1000000ULL; + akirame = true; + } + + return ret; + +#else + return UnixGetTick64() * 1000000ULL; +#endif +} + // Get the system timer (64bit) UINT64 UnixGetTick64() { diff --git a/src/Mayaqua/Unix.h b/src/Mayaqua/Unix.h index e382d686..9777564f 100644 --- a/src/Mayaqua/Unix.h +++ b/src/Mayaqua/Unix.h @@ -117,6 +117,7 @@ void UnixSetThreadPriorityRealtime(); void UnixSetResourceLimit(UINT id, UINT64 value); bool UnixIs64BitRlimSupported(); UINT64 UnixGetTick64(); +UINT64 UnixGetHighresTickNano64(bool raw); void UnixSigChldHandler(int sig); void UnixCloseIO(); void UnixGetCurrentDir(char *dir, UINT size); From f4bbe476beedc502b30ed8478d28ead727c03d4b Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 19:08:40 +0900 Subject: [PATCH 20/63] Fix Vulnerability: CVE-2023-32275 TALOS-2023-1753 SoftEther VPN CtEnumCa () information disclosure vulnerability https://www.softether.org/9-about/News/904-SEVPN202301 https://jvn.jp/en/jp/JVN64316789/ --- src/Mayaqua/Encrypt.c | 9 +++++++-- src/Mayaqua/MayaType.h | 6 +----- src/Mayaqua/Memory.h | 2 ++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Mayaqua/Encrypt.c b/src/Mayaqua/Encrypt.c index b0535fc3..fed18bdb 100644 --- a/src/Mayaqua/Encrypt.c +++ b/src/Mayaqua/Encrypt.c @@ -712,7 +712,8 @@ UINT RsaPublicSize(K *k) // Hash a pointer to a 32-bit UINT HashPtrToUINT(void *p) { - UCHAR hash_data[MD5_SIZE]; + UCHAR hash_data[SHA256_SIZE]; + UCHAR hash_src[CANARY_RAND_SIZE + sizeof(void *)]; UINT ret; // Validate arguments if (p == NULL) @@ -720,7 +721,11 @@ UINT HashPtrToUINT(void *p) return 0; } - Md5(hash_data, &p, sizeof(p)); + Zero(hash_src, sizeof(hash_src)); + Copy(hash_src + 0, GetCanaryRand(CANARY_RAND_ID_PTR_KEY_HASH), CANARY_RAND_SIZE); + Copy(hash_src + CANARY_RAND_SIZE, p, sizeof(void *)); + + Sha2_256(hash_data, hash_src, sizeof(hash_src)); Copy(&ret, hash_data, sizeof(ret)); diff --git a/src/Mayaqua/MayaType.h b/src/Mayaqua/MayaType.h index 483fedad..73307cba 100644 --- a/src/Mayaqua/MayaType.h +++ b/src/Mayaqua/MayaType.h @@ -123,11 +123,7 @@ typedef int (COMPARE)(void *p1, void *p2); #define GET_ABS(a) ((a) >= 0 ? (a) : -(a)) // Convert the pointer to UINT -#ifdef CPU_64 -#define POINTER_TO_KEY(p) HashPtrToUINT(p) -#else -#define POINTER_TO_KEY(p) (UINT)(p) -#endif +#define POINTER_TO_KEY(p) (HashPtrToUINT(p)) // Compare the pointer and UINT #define COMPARE_POINTER_AND_KEY(p, i) (POINTER_TO_KEY(p) == (i)) diff --git a/src/Mayaqua/Memory.h b/src/Mayaqua/Memory.h index cb94a06d..49c9c5cd 100644 --- a/src/Mayaqua/Memory.h +++ b/src/Mayaqua/Memory.h @@ -378,6 +378,8 @@ bool AddStrToStrListDistinct(LIST *o, char *str); #define CANARY_RAND_ID_MEMTAG_MAGIC 0 #define CANARY_RAND_SIZE 20 +#define CANARY_RAND_ID_PTR_KEY_HASH 1 + void InitCanaryRand(); UCHAR *GetCanaryRand(UINT id); From 3b932f5fee4640ff5020b029d346eb93a076a57d Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 19:18:58 +0900 Subject: [PATCH 21/63] Fix Vulnerability: CVE-2023-27516 TALOS-2023-1754 and CVE-2023-32634 TALOS-2023-1755 SoftEther VPN CiRpcAccepted () authentication bypass vulnerability and SoftEther VPN CiRpcServerThread () MitM authentication bypass vulnerability https://www.softether.org/9-about/News/904-SEVPN202301 https://jvn.jp/en/jp/JVN64316789/ --- src/Cedar/Client.c | 51 ++++++++++++++++++++++++++++++--- src/Cedar/Client.h | 1 + src/bin/hamcore/strtable_cn.stb | 6 ++-- src/bin/hamcore/strtable_en.stb | 6 ++-- src/bin/hamcore/strtable_ja.stb | 6 ++-- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c index 1432228e..fd0496e8 100644 --- a/src/Cedar/Client.c +++ b/src/Cedar/Client.c @@ -5155,6 +5155,22 @@ void CiRpcAccepted(CLIENT *c, SOCK *s) retcode = 0; } + if (retcode == 0) + { + if (IsLocalHostIP(&s->RemoteIP) == false) + { + // If the RPC client is from network check whether the password is empty + UCHAR empty_password_hash[20]; + Sha0(empty_password_hash, "", 0); + if (Cmp(empty_password_hash, hashed_password, SHA1_SIZE) == 0 || + IsZero(hashed_password, SHA1_SIZE)) + { + // Regard it as incorrect password + retcode = 1; + } + } + } + Lock(c->lock); { if (c->Config.AllowRemoteConfig == false) @@ -5258,14 +5274,21 @@ void CiRpcServerThread(THREAD *thread, void *param) // Open the port listener = NULL; - for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++) + if (c->Config.DisableRpcDynamicPortListener == false) { - listener = Listen(i); - if (listener != NULL) + for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++) { - break; + listener = ListenEx(i, !c->Config.AllowRemoteConfig); + if (listener != NULL) + { + break; + } } } + else + { + listener = ListenEx(CLIENT_CONFIG_PORT, !c->Config.AllowRemoteConfig); + } if (listener == NULL) { @@ -9028,6 +9051,12 @@ void CiInitConfiguration(CLIENT *c) c->Config.UseKeepConnect = false; // Don't use the connection maintenance function by default in the Client // Eraser c->Eraser = NewEraser(c->Logger, 0); + +#ifdef OS_WIN32 + c->Config.DisableRpcDynamicPortListener = false; +#else // OS_WIN32 + c->Config.DisableRpcDynamicPortListener = true; +#endif // OS_WIN32 } else { @@ -9174,6 +9203,19 @@ void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f) c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig"); c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX); c->NoChangeWcmNetworkSettingOnWindows8 = CfgGetBool(f, "NoChangeWcmNetworkSettingOnWindows8"); + + if (CfgIsItem(f, "DisableRpcDynamicPortListener")) + { + c->DisableRpcDynamicPortListener = CfgGetBool(f, "DisableRpcDynamicPortListener"); + } + else + { +#ifdef OS_WIN32 + c->DisableRpcDynamicPortListener = false; +#else // OS_WIN32 + c->DisableRpcDynamicPortListener = true; +#endif // OS_WIN32 + } } // Read the client authentication data @@ -9748,6 +9790,7 @@ void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config) CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig); CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval); CfgAddBool(cc, "NoChangeWcmNetworkSettingOnWindows8", config->NoChangeWcmNetworkSettingOnWindows8); + CfgAddBool(cc, "DisableRpcDynamicPortListener", config->DisableRpcDynamicPortListener); } // Write the client authentication data diff --git a/src/Cedar/Client.h b/src/Cedar/Client.h index 533996d9..13e44d32 100644 --- a/src/Cedar/Client.h +++ b/src/Cedar/Client.h @@ -87,6 +87,7 @@ struct CLIENT_CONFIG UINT KeepConnectProtocol; // Protocol UINT KeepConnectInterval; // Interval bool NoChangeWcmNetworkSettingOnWindows8; // Don't change the WCM network settings on Windows 8 + bool DisableRpcDynamicPortListener; }; // Version acquisition diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb index fa462554..14486000 100644 --- a/src/bin/hamcore/strtable_cn.stb +++ b/src/bin/hamcore/strtable_cn.stb @@ -2482,7 +2482,7 @@ STATIC1 您可以更改 VPN Client 的设置 STATIC2 远程管理(&E) STATIC3 您可以通过使用 VPN Client 管理器远程模式从另一台计算机上远程管理 VPN Client 服务程序。 R_ALLOW_REMOTE_CONFIG 允许 VPN Client 服务的远程管理(&R) -S_WARNING 建议您在允许远程管理时设置密码。在菜单里选择“工具” >“设置密码”来设置密码。 +S_WARNING 如果你允许远程管理,你必须设置一个密码。在菜单里选择“工具” >“设置密码”来设置密码。必须重新启动 VPN Client 服务,以应用远程管理可用性的配置变化。 STATIC4 在通讯闲置一段时间后自动断开互联网连接的环境下,可以通过向互联网上任意主机发送假数据包的方式来保持互联网连接。 R_USE_KEEP_CONNECT 使用保持 Internet 连接功能(&K) S_HOSTNAME 主机名(&H): @@ -7028,13 +7028,13 @@ CMD_AccountImport_OK 连接设置 "%s" 已导入。 # RemoteEnable 命令 CMD_RemoteEnable 允许 VPN 客户服务的远程管理 -CMD_RemoteEnable_Help 对 VPN Client 服务,从本地主机以外的远程计算机上,允许通过命令行管理设施或 VPN Client 管理器员进行连接和管理。 +CMD_RemoteEnable_Help 对 VPN Client 服务,从本地主机以外的远程计算机上,允许通过命令行管理设施或 VPN Client 管理器员进行连接和管理。必须重新启动 VPN Client 服务,以应用远程管理可用性的配置变化。如果你允许远程管理,你必须设置一个密码。 CMD_RemoteEnable_Args RemoteEnable # RemoteDisable 命令 CMD_RemoteDisable 禁止 VPN 客户服务的远程管理 -CMD_RemoteDisable_Help 对 VPN Client 服务,从本地主机以外的远程计算机上,禁止通过命令行管理设施或 VPN Client 管理器员进行连接和管理。 +CMD_RemoteDisable_Help 对 VPN Client 服务,从本地主机以外的远程计算机上,禁止通过命令行管理设施或 VPN Client 管理器员进行连接和管理。必须重新启动 VPN 客户端服务,以应用远程管理可用性的配置变化。 CMD_RemoteDisable_Args RemoteDisable diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index 5634379f..be3f9aa5 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -2466,7 +2466,7 @@ STATIC1 You can modify the settings for VPN Client. STATIC2 R&emote Management: STATIC3 You can remotely manage the VPN Client Service Program from another computer by using VPN Client Manager Remote Mode. R_ALLOW_REMOTE_CONFIG Allow &Remote Management of VPN Client Service -S_WARNING It is recommended to set a password if you allow remote management. From the menu bar, choose Tools -> Set Password to set the password. +S_WARNING You must set a password if you allow remote management. From the menu bar, choose Tools -> Set Password to set the password. The VPN Client service must be restarted to apply the change of remote management availability. STATIC4 For environments where Internet connections will automatically be disconnected when idle, you can keep alive the Internet connection by sending dummy packets to any host on the Internet. R_USE_KEEP_CONNECT Use &Keep Alive Internet Connection Function S_HOSTNAME &Host Name: @@ -7016,13 +7016,13 @@ CMD_AccountImport_OK The VPN Connection Setting "%s" has been imported. # RemoteEnable command CMD_RemoteEnable Allow Remote Management of VPN Client Service -CMD_RemoteEnable_Help Use this to allow management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager. +CMD_RemoteEnable_Help Use this to allow management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager. The VPN Client service must be restarted to apply the change of remote management availability. You must set a password if you allow remote management. CMD_RemoteEnable_Args RemoteEnable # RemoteDisable command CMD_RemoteDisable Deny Remote Management of VPN Client Service -CMD_RemoteDisable_Help Use this to deny management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager. +CMD_RemoteDisable_Help Use this to deny management of a VPN Client service from a remote computer that is not localhost, via a remote connection by Command Line Management Utility or VPN Client Manager. The VPN Client service must be restarted to apply the change of remote management availability. CMD_RemoteDisable_Args RemoteDisable diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index 3e195742..12021c36 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -2469,7 +2469,7 @@ STATIC1 VPN Client の動作に関する設定を変更できます。 STATIC2 リモート管理の設定(&E) STATIC3 VPN Client サービスプログラムを別のコンピュータ上から VPN クライアント接続マネージャによってリモート管理することが可能です。 R_ALLOW_REMOTE_CONFIG VPN Client サービスのリモート管理を許可する(&R) -S_WARNING リモート管理を許可する場合、パスワードを設定しておくことを強くお勧めします。パスワードは [ツール] メニューの [パスワードの設定] をクリックして設定することができます。 +S_WARNING リモート管理を許可する場合、パスワードを設定する必要があります。パスワードは [ツール] メニューの [パスワードの設定] をクリックして設定することができます。リモート管理の可否の変更の設定適用には、VPN Client サービスを再起動する必要があります。 STATIC4 一定期間無通信状態が続くと接続が自動的に切断されるようなネットワーク接続環境の場合、インターネット上の任意のサーバーに対して一定間隔ごとにパケットを送信することにより、インターネット接続を維持することができます。 R_USE_KEEP_CONNECT インターネット接続の維持機能を使用する(&K) S_HOSTNAME ホスト名(&H): @@ -7022,13 +7022,13 @@ CMD_AccountImport_OK 接続設定 "%s" としてインポートしました。 # RemoteEnable コマンド CMD_RemoteEnable VPN Client サービスのリモート管理の許可 -CMD_RemoteEnable_Help VPN Client サービスに、localhost 以外のリモートコンピュータから、コマンドライン管理ユーティリティまたは VPN クライアント接続マネージャでリモート接続して管理することを許可します。 +CMD_RemoteEnable_Help VPN Client サービスに、localhost 以外のリモートコンピュータから、コマンドライン管理ユーティリティまたは VPN クライアント接続マネージャでリモート接続して管理することを許可します。注意: リモート管理の可否の変更の設定適用には、VPN Client サービスを再起動する必要があります。リモート管理を許可する場合、パスワードを設定する必要があります。 CMD_RemoteEnable_Args RemoteEnable # RemoteDisable コマンド CMD_RemoteDisable VPN Client サービスのリモート管理の禁止 -CMD_RemoteDisable_Help VPN Client サービスに、localhost 以外のリモートコンピュータからコマンドライン管理ユーティリティまたは VPN クライアント接続マネージャでリモート接続して管理することを禁止します。 +CMD_RemoteDisable_Help VPN Client サービスに、localhost 以外のリモートコンピュータからコマンドライン管理ユーティリティまたは VPN クライアント接続マネージャでリモート接続して管理することを禁止します。注意: リモート管理の可否の変更の設定適用には、VPN Client サービスを再起動する必要があります。 CMD_RemoteDisable_Args RemoteDisable From 35077deaf14f824af53d38b2ba86834b66fa288c Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Mon, 9 Oct 2023 17:13:41 +0200 Subject: [PATCH 22/63] Fix Vulnerability: CVE-2023-25774 TALOS-2023-1743 SoftEther VPN vpnserver ConnectionAccept () denial of service vulnerability --- src/Cedar/Admin.c | 12 +-- src/Cedar/Cedar.c | 69 ++++++++++++++ src/Cedar/Cedar.h | 2 + src/Cedar/Listener.c | 217 +++++++++++++++++++++++++++++++++++++++++++ src/Cedar/Listener.h | 19 ++++ 5 files changed, 309 insertions(+), 10 deletions(-) diff --git a/src/Cedar/Admin.c b/src/Cedar/Admin.c index 85f9bd9b..b79a5cea 100644 --- a/src/Cedar/Admin.c +++ b/src/Cedar/Admin.c @@ -726,9 +726,8 @@ void AdminWebProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_siz if (RecvAll(s, data, post_data_size, s->SecureMode)) { c->JsonRpcAuthed = true; -#ifndef GC_SOFTETHER_OSS + RemoveDosEntry(c->Listener, s); -#endif // GC_SOFTETHER_OSS // Divide url_target into URL and query string StrCpy(url, sizeof(url), url_target); @@ -767,9 +766,8 @@ void AdminWebProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target) } c->JsonRpcAuthed = true; -#ifndef GC_SOFTETHER_OSS + RemoveDosEntry(c->Listener, s); -#endif // GC_SOFTETHER_OSS // Divide url_target into URL and query string StrCpy(url, sizeof(url), url_target); @@ -1199,9 +1197,7 @@ void JsonRpcProcOptions(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target c->JsonRpcAuthed = true; -#ifndef GC_SOFTETHER_OSS RemoveDosEntry(c->Listener, s); -#endif // GC_SOFTETHER_OSS AdminWebSendBody(s, 200, "OK", NULL, 0, NULL, NULL, NULL, h); } @@ -1228,9 +1224,7 @@ void JsonRpcProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target) c->JsonRpcAuthed = true; -#ifndef GC_SOFTETHER_OSS RemoveDosEntry(c->Listener, s); -#endif // GC_SOFTETHER_OSS // Divide url_target into URL and query string StrCpy(url, sizeof(url), url_target); @@ -1357,9 +1351,7 @@ void JsonRpcProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_size c->JsonRpcAuthed = true; -#ifndef GC_SOFTETHER_OSS RemoveDosEntry(c->Listener, s); -#endif // GC_SOFTETHER_OSS if (json_req == NULL || json_req_object == NULL) { diff --git a/src/Cedar/Cedar.c b/src/Cedar/Cedar.c index 02b4ee2b..6f3e32c2 100644 --- a/src/Cedar/Cedar.c +++ b/src/Cedar/Cedar.c @@ -322,6 +322,34 @@ void DecrementNoSsl(CEDAR *c, IP *ip, UINT num_dec) UnlockList(c->NonSslList); } +// Check whether the specified IP address is in Non-SSL connection list +bool IsInNoSsl(CEDAR *c, IP *ip) +{ + bool ret = false; + // Validate arguments + if (c == NULL || ip == NULL) + { + return false; + } + + LockList(c->NonSslList); + { + NON_SSL *n = SearchNoSslList(c, ip); + + if (n != NULL) + { + if (n->EntryExpires > Tick64() && n->Count > NON_SSL_MIN_COUNT) + { + n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES; + ret = true; + } + } + } + UnlockList(c->NonSslList); + + return ret; +} + // Add new entry to Non-SSL connection list bool AddNoSsl(CEDAR *c, IP *ip) { @@ -704,6 +732,47 @@ void DelConnection(CEDAR *cedar, CONNECTION *c) UnlockList(cedar->ConnectionList); } +// Get the number of unestablished connections +UINT GetUnestablishedConnections(CEDAR *cedar) +{ + UINT i, ret; + // Validate arguments + if (cedar == NULL) + { + return 0; + } + + ret = 0; + + LockList(cedar->ConnectionList); + { + for (i = 0;i < LIST_NUM(cedar->ConnectionList);i++) + { + CONNECTION *c = LIST_DATA(cedar->ConnectionList, i); + + switch (c->Type) + { + case CONNECTION_TYPE_CLIENT: + case CONNECTION_TYPE_INIT: + case CONNECTION_TYPE_LOGIN: + case CONNECTION_TYPE_ADDITIONAL: + switch (c->Status) + { + case CONNECTION_STATUS_ACCEPTED: + case CONNECTION_STATUS_NEGOTIATION: + case CONNECTION_STATUS_USERAUTH: + ret++; + break; + } + break; + } + } + } + UnlockList(cedar->ConnectionList); + + return ret + Count(cedar->AcceptingSockets); +} + // Add connection to Cedar void AddConnection(CEDAR *cedar, CONNECTION *c) { diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h index ec1b18b9..699263a9 100644 --- a/src/Cedar/Cedar.h +++ b/src/Cedar/Cedar.h @@ -1022,6 +1022,7 @@ void DelHubEx(CEDAR *c, HUB *h, bool no_lock); void StopAllHub(CEDAR *c); void StopAllConnection(CEDAR *c); void AddConnection(CEDAR *cedar, CONNECTION *c); +UINT GetUnestablishedConnections(CEDAR *cedar); void DelConnection(CEDAR *cedar, CONNECTION *c); void SetCedarCipherList(CEDAR *cedar, char *name); void InitCedar(); @@ -1046,6 +1047,7 @@ bool AddNoSsl(CEDAR *c, IP *ip); void DecrementNoSsl(CEDAR *c, IP *ip, UINT num_dec); void DeleteOldNoSsl(CEDAR *c); NON_SSL *SearchNoSslList(CEDAR *c, IP *ip); +bool IsInNoSsl(CEDAR *c, IP *ip); void FreeTinyLog(TINY_LOG *t); void WriteTinyLog(TINY_LOG *t, char *str); TINY_LOG *NewTinyLog(); diff --git a/src/Cedar/Listener.c b/src/Cedar/Listener.c index 6ea0d5cc..ec295403 100644 --- a/src/Cedar/Listener.c +++ b/src/Cedar/Listener.c @@ -17,6 +17,7 @@ #include "Mayaqua/Memory.h" #include "Mayaqua/Object.h" #include "Mayaqua/Str.h" +#include "Mayaqua/Tick64.h" static bool disable_dos = false; static UINT max_connections_per_ip = DEFAULT_MAX_CONNECTIONS_PER_IP; @@ -181,6 +182,11 @@ void TCPAcceptedThread(THREAD *t, void *param) ConnectionAccept(c); flag1 = c->flag1; + if (c->JsonRpcAuthed) + { + RemoveDosEntry(r, s); + } + // Release SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name); ReleaseListener(c->Listener); @@ -221,6 +227,46 @@ void TCPAccepted(LISTENER *r, SOCK *s) num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP); +#ifdef USE_DOS_ATTACK_DETECTION + if (disable_dos == false && r->DisableDos == false && r->Protocol != LISTENER_INPROC) + { + UINT max_uec, now_uec; + // DOS attack check + if (CheckDosAttack(r, s) == false) + { + Debug("DOS Attack 1 !!\n"); + IPToStr(tmp, sizeof(tmp), &s->RemoteIP); + SLog(r->Cedar, "LS_LISTENER_DOS", r->Port, tmp, s->RemotePort); + return; + } + if (StrCmpi(s->UnderlayProtocol, SOCK_UNDERLAY_NATIVE_V6) == 0 || + StrCmpi(s->UnderlayProtocol, SOCK_UNDERLAY_NATIVE_V4) == 0) + { + if (IsInNoSsl(r->Cedar, &s->RemoteIP)) + { + Debug("DOS Attack 2 !!\n"); + IPToStr(tmp, sizeof(tmp), &s->RemoteIP); + SLog(r->Cedar, "LS_LISTENER_DOS", r->Port, tmp, s->RemotePort); + return; + } + } + if (num_clients_from_this_ip > GetMaxConnectionsPerIp()) + { + Debug("DOS Attack 3 !!\n"); + IPToStr(tmp, sizeof(tmp), &s->RemoteIP); + SLog(r->Cedar, "LS_LISTENER_DOS", r->Port, tmp, s->RemotePort); + return; + } + max_uec = GetMaxUnestablishedConnections(); + now_uec = GetUnestablishedConnections(cedar); + if (now_uec > max_uec) + { + Debug("DOS Attack 4 !!\n"); + SLog(r->Cedar, "LS_LISTENER_MAXUEC", max_uec, now_uec); + return; + } + } +#endif // USE_DOS_ATTACK_DETECTION IPToStr(tmp, sizeof(tmp), &s->RemoteIP); @@ -239,6 +285,169 @@ void TCPAccepted(LISTENER *r, SOCK *s) ReleaseThread(t); } +// Remove a DOS entry +bool RemoveDosEntry(LISTENER *r, SOCK *s) +{ + DOS *d; + bool ok = false; + // Validate arguments + if (r == NULL || s == NULL) + { + return false; + } + + LockList(r->DosList); + { + // Delete old entries from the DOS attack list + RefreshDosList(r); + + // Search the table + d = SearchDosList(r, &s->RemoteIP); + + if (d != NULL) + { + Delete(r->DosList, d); + Free(d); + ok = true; + } + } + UnlockList(r->DosList); + + return ok; +} + +// Check whether this is a DOS attack +bool CheckDosAttack(LISTENER *r, SOCK *s) +{ + DOS *d; + bool ok = true; + // Validate arguments + if (r == NULL || s == NULL) + { + return false; + } + + LockList(r->DosList); + { + // Delete old entries from the DOS attack list + RefreshDosList(r); + + // Search the table + d = SearchDosList(r, &s->RemoteIP); + + if (d != NULL) + { + // There is a entry already + // This should mean being under a DOS attack + d->LastConnectedTick = Tick64(); + d->CurrentExpireSpan = MIN(d->CurrentExpireSpan * (UINT64)2, DOS_TABLE_EXPIRES_MAX); + d->AccessCount++; + if (d->AccessCount > DOS_TABLE_MAX_LIMIT_PER_IP) + { + ok = false; + } + } + else + { + // Create a new entry + d = ZeroMalloc(sizeof(DOS)); + d->CurrentExpireSpan = (UINT64)DOS_TABLE_EXPIRES_FIRST; + d->FirstConnectedTick = d->LastConnectedTick = Tick64(); + d->AccessCount = 1; + d->DeleteEntryTick = d->FirstConnectedTick + (UINT64)DOS_TABLE_EXPIRES_TOTAL; + Copy(&d->IpAddress, &s->RemoteIP, sizeof(IP)); + Add(r->DosList, d); + } + } + UnlockList(r->DosList); + + return ok; +} + +// Delete old entries from the DOS attack list +void RefreshDosList(LISTENER *r) +{ + // Validate arguments + if (r == NULL) + { + return; + } + + if (r->DosListLastRefreshTime == 0 || + (r->DosListLastRefreshTime + (UINT64)DOS_TABLE_REFRESH_INTERVAL) <= Tick64()) + { + UINT i; + LIST *o; + r->DosListLastRefreshTime = Tick64(); + + o = NewListFast(NULL); + for (i = 0;i < LIST_NUM(r->DosList);i++) + { + DOS *d = LIST_DATA(r->DosList, i); + if ((d->LastConnectedTick + d->CurrentExpireSpan) <= Tick64() || + (d->DeleteEntryTick <= Tick64())) + { + Add(o, d); + } + } + + for (i = 0;i < LIST_NUM(o);i++) + { + DOS *d = LIST_DATA(o, i); + Delete(r->DosList, d); + Free(d); + } + + ReleaseList(o); + } +} + +// Search the DOS attack list by the IP address +DOS *SearchDosList(LISTENER *r, IP *ip) +{ + DOS *d, t; + // Validate arguments + if (r == NULL || ip == NULL) + { + return NULL; + } + + Copy(&t.IpAddress, ip, sizeof(IP)); + + d = Search(r->DosList, &t); + + if (d != NULL) + { + if ((d->LastConnectedTick + d->CurrentExpireSpan) <= Tick64() || + (d->DeleteEntryTick <= Tick64())) + { + // Delete old entries + Delete(r->DosList, d); + Free(d); + return NULL; + } + } + + return d; +} + +// Comparison of DOS attack list entries +int CompareDos(void *p1, void *p2) +{ + DOS *d1, *d2; + if (p1 == NULL || p2 == NULL) + { + return 0; + } + d1 = *(DOS **)p1; + d2 = *(DOS **)p2; + if (d1 == NULL || d2 == NULL) + { + return 0; + } + + return CmpIpAddr(&d1->IpAddress, &d2->IpAddress); +} // UDP listener main loop void ListenerUDPMainLoop(LISTENER *r) @@ -653,6 +862,13 @@ void CleanupListener(LISTENER *r) return; } + // Release the DOS attack list + for (i = 0;i < LIST_NUM(r->DosList);i++) + { + DOS *d = LIST_DATA(r->DosList, i); + Free(d); + } + ReleaseList(r->DosList); if (r->Sock != NULL) { @@ -802,6 +1018,7 @@ LISTENER *NewListenerEx5(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, r->Port = port; r->Event = NewEvent(); + r->DosList = NewList(CompareDos); r->LocalOnly = local_only; r->ShadowIPv6 = shadow_ipv6; diff --git a/src/Cedar/Listener.h b/src/Cedar/Listener.h index 40b816f1..e3609df5 100644 --- a/src/Cedar/Listener.h +++ b/src/Cedar/Listener.h @@ -10,12 +10,24 @@ #include "CedarType.h" +#include "Mayaqua/MayaType.h" #include "Mayaqua/Kernel.h" +#include "Mayaqua/Network.h" // Function to call when receiving a new connection typedef void (NEW_CONNECTION_PROC)(CONNECTION *c); +// DOS attack list +struct DOS +{ + IP IpAddress; // IP address + UINT64 FirstConnectedTick; // Time which a client connects at the first time + UINT64 LastConnectedTick; // Time which a client connected at the last time + UINT64 CurrentExpireSpan; // Current time-out period of this record + UINT64 DeleteEntryTick; // Time planned to delete this entry + UINT AccessCount; // The number of accesses +}; // Listener structure struct LISTENER @@ -31,6 +43,8 @@ struct LISTENER volatile bool Halt; // Halting flag UINT Status; // State + LIST *DosList; // DOS attack list + UINT64 DosListLastRefreshTime; // Time that the DOS list is refreshed at the last THREAD_PROC *ThreadProc; // Thread procedure void *ThreadParam; // Thread parameters @@ -105,6 +119,11 @@ void FreeDynamicListener(DYNAMIC_LISTENER *d); bool ListenerRUDPRpcRecvProc(RUDP_STACK *r, UDPPACKET *p); void ListenerSetProcRecvRpcEnable(bool b); +int CompareDos(void *p1, void *p2); +DOS *SearchDosList(LISTENER *r, IP *ip); +void RefreshDosList(LISTENER *r); +bool CheckDosAttack(LISTENER *r, SOCK *s); +bool RemoveDosEntry(LISTENER *r, SOCK *s); #endif // LISTENER_H From 54ae7f725bf10f7521d1a62b74ee8f0f9d5f43a5 Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 19:56:41 +0900 Subject: [PATCH 23/63] Add four new certificate hashes to the DDNS_CERT_HASH list by Daiyuu Nobori. These certificates will be used to University of Tsukuba's built-in "softether.net" DDNS server after year 2038. --- src/Cedar/DDNS.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Cedar/DDNS.h b/src/Cedar/DDNS.h index c8fa0207..75546109 100644 --- a/src/Cedar/DDNS.h +++ b/src/Cedar/DDNS.h @@ -18,7 +18,11 @@ "439BAFA75A6EE5671FC9F9A02D34FF29881761A0" \ "EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3" \ "74DF99D4B1B5F0488A388B50D347D26013DC67A5" \ - "6EBB39AFCA8C900635CFC11218CF293A612457E4" + "6EBB39AFCA8C900635CFC11218CF293A612457E4" \ + "05A9386C5E2B233F7BAB2479620EAAA2793709ED" \ + "A811C64BB715351E36B6C1E022648D8BE0ACD128" \ + "BD264DB3B0B1B3ABA0AF3074AA574ED1EF3B42D7" \ + "9AB61D691536645DD55A8730FC6D2CDF33C8C73F" #define DDNS_SNI_VER_STRING "DDNS" From 6dbf7e9ae27ab3191210742e2075fe08b6c7c43a Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Thu, 28 Sep 2023 20:24:44 +0900 Subject: [PATCH 24/63] Showing an explanation of the purpose of the Developer Edition and the difference from the Stable Editon by Daiyuu Nobori --- src/Cedar/Command.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Cedar/Command.c b/src/Cedar/Command.c index 8969ee7b..dce502bb 100644 --- a/src/Cedar/Command.c +++ b/src/Cedar/Command.c @@ -24496,6 +24496,34 @@ void CmdPrintAbout(CONSOLE *c) c->Write(c, tmp); + // Showing an explanation of the purpose of the Developer Edition and the difference from the Stable Editon by Daiyuu Nobori + /* + * Welcome to the Developer Edition of SoftEther VPN. + + Please note: SoftEther VPN Developer Edition (Version 5.x) has accepted + great code contributions on GitHub from many excellent open source + developers. This edition contains some very bright experimental code. + The experimental code in this Developer Edition has *NOT* been fully + reviewed by Daiyuu Nobori (the first original author of SoftEther VPN) + and has not been endorsed by him for stability and quality. It is his + policy to encourage many developers to contribute code with their + creative minds and ambitions. The succession of low-level system + software and network developers is of critical importance worldwide, + and SoftEther VPN Developer Edition is very important to increase + the number of such great developers. + - If you are a programmer of VPN software, or if you want a variety of + experimental code, this edition is very suitable for you. + - On the other hand, if you are building VPNs for mission-critical + business systems that require stability and security, + Stable Edition (Version 4.x) is highly recommended. + - All code in Stable Edition is reviewed by Daiyuu Nobori. He is also + responsible for porting features from the Developer Edition + to the Stable Edition. + - SoftEther VPN Stable Edition can be downloaded at: + https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/ +*/ + c->Write(c, L"\nWelcome to the Developer Edition of SoftEther VPN.\n\nPlease note: SoftEther VPN Developer Edition (Version 5.x) has accepted\ngreat code contributions on GitHub from many excellent open source\ndevelopers. This edition contains some very bright experimental code.\n The experimental code in this Developer Edition has *NOT* been fully\nreviewed by Daiyuu Nobori (the first original author of SoftEther VPN)\nand has not been endorsed by him for stability and quality. It is his\npolicy to encourage many developers to contribute code with their\ncreative minds and ambitions. The succession of low-level system\nsoftware and network developers is of critical importance worldwide,\nand SoftEther VPN Developer Edition is very important to increase\nthe number of such great developers.\n- If you are a programmer of VPN software, or if you want a variety of\n experimental code, this edition is very suitable for you.\n- On the other hand, if you are building VPNs for mission-critical\n business systems that require stability and security,\n Stable Edition (Version 4.x) is highly recommended.\n- All code in Stable Edition is reviewed by Daiyuu Nobori. He is also\n responsible for porting features from the Developer Edition\n to the Stable Edition.\n- SoftEther VPN Stable Edition can be downloaded at:\n https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/\n\n"); + ReleaseCedar(cedar); } From 895c16e3e8d043511fd8ae730a44eacfc7bffe4d Mon Sep 17 00:00:00 2001 From: Yihong Wu Date: Sun, 15 Oct 2023 06:13:59 +0000 Subject: [PATCH 25/63] Revert "README.md: Add me to members" This reverts commit 1f40de2ddac90b31c909d4c501251b1b90e6e581. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 4f16a3d1..bf2ae5d6 100644 --- a/README.md +++ b/README.md @@ -101,9 +101,6 @@ https://github.com/davidebeatrici Ilya Shipitsin (Since Jul 21, 2018) https://github.com/chipitsine -Yihong Wu (Since Jul 16, 2021) -https://github.com/domosekai - # SOFTETHER VPN ADVANTAGES From 3574f8aa98257d6b732bd3cb4b48a5b31e8e2d9d Mon Sep 17 00:00:00 2001 From: hiura Date: Thu, 2 Nov 2023 18:42:12 +0900 Subject: [PATCH 26/63] Fix azure pipelines: Publish separate artifacts for both x64 and x86. --- .ci/azure-pipelines/windows-steps.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/azure-pipelines/windows-steps.yml b/.ci/azure-pipelines/windows-steps.yml index 326a9df7..79bd5fdf 100644 --- a/.ci/azure-pipelines/windows-steps.yml +++ b/.ci/azure-pipelines/windows-steps.yml @@ -29,12 +29,12 @@ steps: inputs: sourceFolder: '$(Build.BinariesDirectory)' contents: '?(*.exe|*.se2|*.pdb)' - TargetFolder: '$(Build.StagingDirectory)/binaries' + TargetFolder: '$(Build.StagingDirectory)/binaries/${{parameters.architecture}}' flattenFolders: true - task: PublishBuildArtifacts@1 inputs: - pathtoPublish: '$(Build.StagingDirectory)/binaries' - artifactName: 'Binaries' + pathtoPublish: '$(Build.StagingDirectory)/binaries/${{parameters.architecture}}' + artifactName: 'Binaries_${{parameters.architecture}}' - task: PublishBuildArtifacts@1 inputs: pathtoPublish: '$(Build.StagingDirectory)/installers' From e6792d889332b6fb36bfc6e1fd454abe466e98e8 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sun, 19 Nov 2023 10:57:28 +0100 Subject: [PATCH 27/63] fix nullptr deref Co-authored-by: icy17 <1061499390@qq.com> --- src/Mayaqua/Network.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 83c4d283..52db2b2c 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5785,6 +5785,10 @@ SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, b } ssl = SSL_new(ssl_ctx); + if (ssl == NULL) + { + return NULL; + } SSL_set_ex_data(ssl, GetSslClientCertIndex(), clientcert); } From 7398bf2724a8fcfa24e6f868db884085c49550d1 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sat, 2 Dec 2023 22:30:26 +0100 Subject: [PATCH 28/63] CI: use OPENSSL_ROOT_DIR for cirrus-ci builds --- .cirrus.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 7261b207..68b66ab5 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,8 +2,10 @@ FreeBSD_task: matrix: env: SSL: openssl + OPENSSL_ROOT_DIR: /usr/local env: - SSL: openssl31 + SSL: openssl32 + OPENSSL_ROOT_DIR: /usr/local env: # base openssl SSL: From 4e4bd79ad289d98c70e00e01ac9823ad250cd1ff Mon Sep 17 00:00:00 2001 From: hiura Date: Tue, 20 Feb 2024 12:01:35 +0900 Subject: [PATCH 29/63] IPC.c:Cast the pointer to a defined size due to the error in compiling. --- src/Cedar/IPC.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index 67dfdf23..85e58a7f 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -1537,7 +1537,8 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now) // Remove link-layer address options for Windows clients (required on Windows 11) if (header_size > 0) { - UCHAR *src = p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer + header_size; + //UCHAR *src = p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer + header_size; + UCHAR* src = (UCHAR *)p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer + header_size;// Cast the pointer to UCHAR *. UINT opt_size = p->ICMPv6HeaderPacketInfo.DataSize - header_size; UCHAR *dst = src; UINT removed = 0; From 60ee4630442c4458896553060c795732fd4a04de Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 23 Feb 2024 11:06:27 +0100 Subject: [PATCH 30/63] adjust types of variables gcc14 is not happy on "error: passing argument .. from incompatible pointer type [-Wincompatible-pointer-types]" --- src/Mayaqua/pkcs11f.h | 6 +++--- src/Mayaqua/pkcs11t.h | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Mayaqua/pkcs11f.h b/src/Mayaqua/pkcs11f.h index 30097535..33550c3d 100644 --- a/src/Mayaqua/pkcs11f.h +++ b/src/Mayaqua/pkcs11f.h @@ -73,7 +73,7 @@ CK_PKCS11_FUNCTION_INFO(C_GetSlotList) ( CK_BBOOL tokenPresent, /* only slots with tokens? */ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ - CK_ULONG_PTR pulCount /* receives number of slots */ + CK_UINT_PTR pulCount /* receives number of slots */ ); #endif @@ -351,7 +351,7 @@ CK_PKCS11_FUNCTION_INFO(C_FindObjects) CK_SESSION_HANDLE hSession, /* session's handle */ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ CK_ULONG ulMaxObjectCount, /* max handles to get */ - CK_ULONG_PTR pulObjectCount /* actual # returned */ + CK_UINT_PTR pulObjectCount /* actual # returned */ ); #endif @@ -558,7 +558,7 @@ CK_PKCS11_FUNCTION_INFO(C_Sign) CK_BYTE_PTR pData, /* the data to sign */ CK_ULONG ulDataLen, /* count of bytes to sign */ CK_BYTE_PTR pSignature, /* gets the signature */ - CK_ULONG_PTR pulSignatureLen /* gets signature length */ + CK_UINT_PTR pulSignatureLen /* gets signature length */ ); #endif diff --git a/src/Mayaqua/pkcs11t.h b/src/Mayaqua/pkcs11t.h index c04b5719..f157ce73 100644 --- a/src/Mayaqua/pkcs11t.h +++ b/src/Mayaqua/pkcs11t.h @@ -51,6 +51,8 @@ typedef CK_BYTE CK_BBOOL; /* an unsigned value, at least 32 bits long */ typedef unsigned long int CK_ULONG; +typedef unsigned int CK_UINT; + /* a signed value, the same size as a CK_ULONG */ /* CK_LONG is new for v2.0 */ typedef long int CK_LONG; @@ -68,6 +70,7 @@ typedef CK_BYTE CK_PTR CK_BYTE_PTR; typedef CK_CHAR CK_PTR CK_CHAR_PTR; typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef CK_UINT CK_PTR CK_UINT_PTR; typedef void CK_PTR CK_VOID_PTR; /* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ @@ -110,7 +113,7 @@ typedef CK_ULONG CK_NOTIFICATION; #define CKN_SURRENDER 0 -typedef CK_ULONG CK_SLOT_ID; +typedef CK_UINT CK_SLOT_ID; typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; @@ -262,7 +265,7 @@ typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; /* CK_SESSION_HANDLE is a Cryptoki-assigned value that * identifies a session */ -typedef CK_ULONG CK_SESSION_HANDLE; +typedef CK_UINT CK_SESSION_HANDLE; typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; @@ -310,7 +313,7 @@ typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; /* CK_OBJECT_HANDLE is a token-specific identifier for an * object */ -typedef CK_ULONG CK_OBJECT_HANDLE; +typedef CK_UINT CK_OBJECT_HANDLE; typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; From 01b05af33316ec222dd76e96d1d328ca0ad40d1c Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Fri, 23 Feb 2024 16:28:11 +0100 Subject: [PATCH 31/63] add "vcpkg_installed" to gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c00f4b74..78d81534 100644 --- a/.gitignore +++ b/.gitignore @@ -209,4 +209,4 @@ developer_tools/stbchecker/**/ASALocalRun/ developer_tools/stbchecker/**/*.binlog developer_tools/stbchecker/**/*.nvuser developer_tools/stbchecker/**/.mfractor/ - +/vcpkg_installed From 442885deb5a65fadb6ba51068696c9037f77ddcb Mon Sep 17 00:00:00 2001 From: Thomas Winkler Date: Sat, 24 Feb 2024 22:24:15 +0100 Subject: [PATCH 32/63] Update CMakeLists.txt with version bump (upcoming 5182) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ededd63..e1120daa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10) set(BUILD_NUMBER CACHE STRING "The number of the current build.") if ("${BUILD_NUMBER}" STREQUAL "") - set(BUILD_NUMBER "5180") + set(BUILD_NUMBER "5182") endif() if (BUILD_NUMBER LESS 5180) From 913934f7c08aba3b840d499202145a4388e84da0 Mon Sep 17 00:00:00 2001 From: Thomas Winkler Date: Sat, 24 Feb 2024 22:24:41 +0100 Subject: [PATCH 33/63] Update CMakeSettings.json with version bump (upcoming 5182) --- CMakeSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeSettings.json b/CMakeSettings.json index fa46663d..82a5e910 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,5 +1,5 @@ { - "environments": [ { "BuildNumber": "5180" } ], + "environments": [ { "BuildNumber": "5182" } ], "configurations": [ { "name": "x64-native", From 0dfc82c14e93c2b46d60f9b1edcd1cd0f0bfc8f7 Mon Sep 17 00:00:00 2001 From: Kensei Sakai <24488142+libnumafly@users.noreply.github.com> Date: Tue, 27 Feb 2024 03:27:20 +0900 Subject: [PATCH 34/63] Update BUILD_UNIX.md for fix location # Using SoftEther without installation Correct location for build output dir. --- src/BUILD_UNIX.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BUILD_UNIX.md b/src/BUILD_UNIX.md index 340afabc..7034dd4e 100644 --- a/src/BUILD_UNIX.md +++ b/src/BUILD_UNIX.md @@ -228,7 +228,7 @@ You can write your own VPN Server management application in your favorite langua You can use any SoftEtherVPN component (server, client, bridge) without installing it, if you wish so. -In this case please do not run the `make install` command after compiling the source code, and head directly to the **bin/** directory. There you will find the generated binaries for SoftEtherVPN and those could be used without installing SoftEtherVPN. +In this case please do not run the `make install` command after compiling the source code, and head directly to the **build/** directory. There you will find the generated binaries for SoftEtherVPN and those could be used without installing SoftEtherVPN. ************************************ Thank You Using SoftEther VPN ! From 645d5ebb55968150e6e41776818d627cae4c3859 Mon Sep 17 00:00:00 2001 From: hiura Date: Wed, 6 Mar 2024 11:33:56 +0900 Subject: [PATCH 35/63] Change bridge function: Make the NIC appear in the 'Local Bridge Settings' list regardless of a NULL character consisted in 'FriendlyName' --- src/Cedar/BridgeWin32.c | 24 ++++++++++++++++-------- src/Cedar/SeLowUser.c | 4 +++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Cedar/BridgeWin32.c b/src/Cedar/BridgeWin32.c index 00d3ada0..b5df92f2 100644 --- a/src/Cedar/BridgeWin32.c +++ b/src/Cedar/BridgeWin32.c @@ -1161,7 +1161,9 @@ void Win32EthMakeCombinedName(char *dst, UINT dst_size, char *nicname, char *gui if (IsEmptyStr(guid) == false) { - Format(dst, dst_size, "%s (ID=%010u)", nicname, Win32EthGenIdFromGuid(guid)); + // Allow to combine "FriendlyName" consisting of a NULL character and ID. + //Format(dst, dst_size, "%s (ID=%010u)", nicname, Win32EthGenIdFromGuid(guid)); + Format(dst, dst_size, "%s(ID=%010u)", nicname, Win32EthGenIdFromGuid(guid)); } else { @@ -1185,18 +1187,19 @@ UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str) len = StrLen(str); - if (len >= 16) + // Allow to combine "FriendlyName" consisting of a NULL character and ID. + if (len >= 15) { - StrCpy(id_str, sizeof(id_str), str + len - 16); + StrCpy(id_str, sizeof(id_str), str + len - 15); - if (StartWith(id_str, " (ID=")) + if (StartWith(id_str, "(ID=")) { if (EndWith(id_str, ")")) { char num[MAX_SIZE]; Zero(num, sizeof(num)); - StrCpy(num, sizeof(num), id_str + 5); + StrCpy(num, sizeof(num), id_str + 4); num[StrLen(num) - 1] = 0; @@ -1204,7 +1207,7 @@ UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str) if (ret != 0) { - name[len - 16] = 0; + name[len - 15] = 0; } } } @@ -1346,6 +1349,8 @@ TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, boo Debug("%s - %s\n", a->Guid, a->Title); } + // Make sure that "FriendlyName" does not cosist a NULL character. + Debug("%s,- s=%d, t=%s, %s,\n", a->Guid, show, tmp, a->Title[0] == 0 ? "check=NG FriendlyName(Title) is NULL !" : "check=OK"); } *total_num_including_hidden = ret->NumTokens; @@ -1405,7 +1410,8 @@ LIST *GetEthAdapterListInternal() UINT size; char *buf; UINT i, j; - char *qos_tag = " (Microsoft's Packet Scheduler)"; + //char *qos_tag = " (Microsoft's Packet Scheduler)"; + char *qos_tag = "(Microsoft's Packet Scheduler)"; // Allow to combine "FriendlyName" consisting of a NULL character and QOS. SU *su = NULL; LIST *su_adapter_list = NULL; @@ -1660,7 +1666,9 @@ ANSI_STR: } else { - Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1); + // Allow to combine "FriendlyName" consisting of a NULL character and ID. + //Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1); + Format(tmp, sizeof(tmp), "%s(%u)", a->Title, k + 1); } ok = true; diff --git a/src/Cedar/SeLowUser.c b/src/Cedar/SeLowUser.c index f6b40777..29967464 100644 --- a/src/Cedar/SeLowUser.c +++ b/src/Cedar/SeLowUser.c @@ -827,7 +827,9 @@ SU_ADAPTER_LIST *SuAdapterInfoToAdapterList(SL_ADAPTER_INFO *info) Copy(&t.Info, info, sizeof(SL_ADAPTER_INFO)); UniToStr(tmp, sizeof(tmp), info->AdapterId); - if (IsEmptyStr(tmp) || IsEmptyStr(info->FriendlyName) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) + // Make the NIC appear in the "Local Bridge Settings" list regardless of a NULL character consisted in "FriendlyName". + //if (IsEmptyStr(tmp) || IsEmptyStr(info->FriendlyName) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) + if (IsEmptyStr(tmp) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) { // Name is invalid return NULL; From 370d83ffa0e2c591736228a469a586d094d20496 Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Fri, 8 Mar 2024 11:45:02 +0900 Subject: [PATCH 36/63] Introduce new issue form --- .github/ISSUE_TEMPLATE.md | 51 ----------- .../bug_report_or_issue_report.yml | 87 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++ 3 files changed, 95 insertions(+), 51 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report_or_issue_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 160aa871..00000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,51 +0,0 @@ -Hi, there! - -Thank you for using SoftEther. - -If you are running SoftEther VPN 4.x (i.e. Stable Edition), please read the comparison with Developer Edition at: - -https://github.com/SoftEtherVPN/SoftEtherVPN#comparison-with-stable-edition - -Before you submit an issue, please read the following: - -Is this a question? - -- If the answer is "yes", then please ask your question on [www.vpnusers.com](http://www.vpnusers.com). -The issue section on GitHub is reserved for bugs and feature requests. - -- If the answer is "no", please read the following: - -We provide a template which is specifically made for bug reports, in order to be sure that the report includes enough details to be helpful. - -Please use or adapt it as needed. - ---- - -### Prerequisites - -* [ ] Can you reproduce? -* [ ] Are you running the latest version of SoftEtherVPN? - -**SoftEther version:** -**Component:** [Server, Client, Bridge, etc.] -**Operating system:** [Windows, Linux, BSD, macOS, etc.] -**Architecture:** [64 bit, 32 bit] - -[In case it's a computer with known specs, such as the Raspberry Pi, you can specify it omitting the details.] -**Processor:** [Specify brand and model. Example: AMD Ryzen 7 1800x] - -### Description - -[Description of the bug] - -**Expected behavior:** -[What you expected to happen] - -**Actual behavior:** -[What actually happened] - -### Steps to reproduce - -1. [First step] -2. [Second step] -3. [And so on...] diff --git a/.github/ISSUE_TEMPLATE/bug_report_or_issue_report.yml b/.github/ISSUE_TEMPLATE/bug_report_or_issue_report.yml new file mode 100644 index 00000000..cd9bc40f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_or_issue_report.yml @@ -0,0 +1,87 @@ +name: Bug Report or Issue Report +description: File a bug report or an issue report +labels: "needs-triage" +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + We provide a template which is specifically made for bug reports, to be sure that the report includes enough details to be helpful. + + - type: checkboxes + attributes: + label: Are you using SoftEther VPN 5.x? + description: | + This issue tracker is for SoftEther VPN Developer Edition versioned 5.x. + Please report issues about SoftEther VPN Stable Edition versioned 4.x through the correct path. + See also [the top of the issue tracker](https://github.com/SoftEtherVPN/SoftEtherVPN/issues/new/choose). + options: + - label: Yes, I'm using SoftEther VPN 5.x, not 4.x. + required: true + + - type: input + attributes: + label: Version + description: | + The exact version you are using. + It would be very nice if you let us know version tag or commit hash. + placeholder: "5.02.5180 / 09b7e4f / 5.01.9674+git20200806+8181039+dfsg2-2build1" + + - type: dropdown + attributes: + label: Component + description: Which component did you encounter an issue with? + multiple: true + options: + - VPN Server + - VPN Bridge + - VPN Client + - VPN Tools + - Other + validations: + required: true + + - type: input + attributes: + label: Operating system & version + placeholder: "Windows 11 Pro 23H2 / Ubuntu 22.04 / FreeBSD 14.0 / macOS Sonoma / Independent" + description: | + Let us know about your operating system and version. + validations: + required: true + + - type: input + attributes: + label: Architecture or Hardware model + placeholder: "amd64 / aarch64 / Raspberry Pi 4B+ / Apple M2" + description: | + Necessary if your issue is architecture-specific. + + - type: textarea + attributes: + label: Steps to reproduce + placeholder: Having detailed steps helps us reproduce the bug. + validations: + required: true + + - type: textarea + attributes: + label: ✔️ Expected Behavior + placeholder: What do you expect to happen? + validations: + required: false + + - type: textarea + attributes: + label: ❌ Actual Behavior + placeholder: What happened actually? + validations: + required: false + + - type: textarea + attributes: + label: Anything else? + description: | + Links? References? + Anything that will give us more context about the issue you are encountering! + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..e67472a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +contact_links: + - name: Are you using SoftEther VPN 4.x? + about: This repository is for SoftEther VPN 5.x Developer Edition, developed independently from SoftEther VPN 4.x. Visit vpnusers.com if you would like to report issues or ask questions about version 4.x! + url: https://www.vpnusers.com/ + + - name: Questions about SoftEtherVPN 5.x + about: Visit Discussions to ask community to help. + url: https://github.com/SoftEtherVPN/SoftEtherVPN/discussions/new?category=q-a From 64cb8e1efff329add2904b8ece3186fe0f1adbfc Mon Sep 17 00:00:00 2001 From: hiura Date: Mon, 11 Mar 2024 00:16:22 +0900 Subject: [PATCH 37/63] Change bridge function: Make the NIC appear in the 'Local Bridge Settings' list No.2 --- src/Cedar/BridgeWin32.c | 9 +++------ src/Cedar/SeLowUser.c | 43 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/Cedar/BridgeWin32.c b/src/Cedar/BridgeWin32.c index b5df92f2..2941ae81 100644 --- a/src/Cedar/BridgeWin32.c +++ b/src/Cedar/BridgeWin32.c @@ -1162,7 +1162,6 @@ void Win32EthMakeCombinedName(char *dst, UINT dst_size, char *nicname, char *gui if (IsEmptyStr(guid) == false) { // Allow to combine "FriendlyName" consisting of a NULL character and ID. - //Format(dst, dst_size, "%s (ID=%010u)", nicname, Win32EthGenIdFromGuid(guid)); Format(dst, dst_size, "%s(ID=%010u)", nicname, Win32EthGenIdFromGuid(guid)); } else @@ -1187,7 +1186,7 @@ UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str) len = StrLen(str); - // Allow to combine "FriendlyName" consisting of a NULL character and ID. + // Allow to combine "FriendlyName" consisting of a NULL character and ID beginning with "(ID=". if (len >= 15) { StrCpy(id_str, sizeof(id_str), str + len - 15); @@ -1410,8 +1409,7 @@ LIST *GetEthAdapterListInternal() UINT size; char *buf; UINT i, j; - //char *qos_tag = " (Microsoft's Packet Scheduler)"; - char *qos_tag = "(Microsoft's Packet Scheduler)"; // Allow to combine "FriendlyName" consisting of a NULL character and QOS. + char *qos_tag = "(Microsoft's Packet Scheduler)"; // Allow to combine "FriendlyName" consisting of a NULL character and QOS tag. SU *su = NULL; LIST *su_adapter_list = NULL; @@ -1666,8 +1664,7 @@ ANSI_STR: } else { - // Allow to combine "FriendlyName" consisting of a NULL character and ID. - //Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1); + // Allow to combine "FriendlyName" consisting of a NULL character and SEQ number. Format(tmp, sizeof(tmp), "%s(%u)", a->Title, k + 1); } diff --git a/src/Cedar/SeLowUser.c b/src/Cedar/SeLowUser.c index 29967464..1074adf9 100644 --- a/src/Cedar/SeLowUser.c +++ b/src/Cedar/SeLowUser.c @@ -753,11 +753,45 @@ LIST *SuGetAdapterList(SU *u) for (i = 0;i < u->AdapterInfoList.NumAdapters;i++) { SL_ADAPTER_INFO *info = &u->AdapterInfoList.Adapters[i]; - SU_ADAPTER_LIST *a = SuAdapterInfoToAdapterList(info); - if (a != NULL) + if (IsEmptyStr(info->FriendlyName)) { - Add(ret, a); + // Some NetAdapterCx drivers doesn't report the FriendlyName in the kernel mode. + // So we attempt to obtain the DriverDesc string from NetCfg registry key alternatively. + char regkey[MAX_PATH] = {0}; + char tmp[MAX_PATH] = {0}; + char adapter_guid[MAX_PATH] = {0}; + + UniToStr(adapter_guid, sizeof(adapter_guid), info->AdapterId + StrLen(SL_ADAPTER_ID_PREFIX)); + + if (GetClassRegKeyWin32(regkey, sizeof(regkey), tmp, sizeof(tmp), adapter_guid)) + { + char *driver_desc = MsRegReadStrEx2(REG_LOCAL_MACHINE, regkey, "DriverDesc", false, true); + + if (driver_desc != NULL) + { + StrCpy(info->FriendlyName, sizeof(info->FriendlyName), driver_desc); + Free(driver_desc); + } + } + } + + { + SU_ADAPTER_LIST *a = SuAdapterInfoToAdapterList(info); + + char macstr[128] = {0}; + BinToStr(macstr, sizeof(macstr), info->MacAddress, sizeof(info->MacAddress)); + + if (a != NULL) + { + // Debug("SU: Adapter %u (OK): ID=%S, MAC=%s, FriendlyName=%s\n", i, info->AdapterId, macstr, info->FriendlyName); + + Add(ret, a); + } + else + { + // Debug("SU: Adapter %u (NG): ID=%S, MAC=%s, FriendlyName=%s\n", i, info->AdapterId, macstr, info->FriendlyName); + } } } @@ -828,8 +862,7 @@ SU_ADAPTER_LIST *SuAdapterInfoToAdapterList(SL_ADAPTER_INFO *info) UniToStr(tmp, sizeof(tmp), info->AdapterId); // Make the NIC appear in the "Local Bridge Settings" list regardless of a NULL character consisted in "FriendlyName". - //if (IsEmptyStr(tmp) || IsEmptyStr(info->FriendlyName) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) - if (IsEmptyStr(tmp) || StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) + if (IsEmptyStr(tmp) || /* IsEmptyStr(info->FriendlyName) || */ StartWith(tmp, SL_ADAPTER_ID_PREFIX) == false) { // Name is invalid return NULL; From 2789b16c120c29b151fde7e61ea96a5d23922a16 Mon Sep 17 00:00:00 2001 From: hiura Date: Sat, 16 Mar 2024 12:52:46 +0900 Subject: [PATCH 38/63] Fix hamcore access: Correcting path separator for hamcore. --- src/Mayaqua/FileIO.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Mayaqua/FileIO.c b/src/Mayaqua/FileIO.c index c03c3906..5e4b9c97 100644 --- a/src/Mayaqua/FileIO.c +++ b/src/Mayaqua/FileIO.c @@ -2124,6 +2124,24 @@ IO *FileOpenEx(char *name, bool write_mode, bool read_lock) return ret; } + +// Replace the specified character in the string with a new character +wchar_t *UniReplaceCharW(wchar_t *src, UINT size, wchar_t c, wchar_t newc) { + if (src == NULL) + { + return NULL; + } + for (; *src; src++, size -= sizeof(wchar_t)) { + if (size < sizeof(wchar_t)) { + break; + } + if (*src == c) { + *src = newc; + } + } + return (wchar_t *)src; +} + IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock) { wchar_t tmp[MAX_SIZE]; @@ -2140,9 +2158,12 @@ IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock) IO *o = ZeroMalloc(sizeof(IO)); name++; UniStrCpy(o->NameW, sizeof(o->NameW), name); +#ifdef OS_WIN32 + UniReplaceCharW(o->NameW, sizeof(o->NameW), L'\\', L'/'); // Path separator "/" is used. +#endif // OS_WIN32 UniToStr(o->Name, sizeof(o->Name), o->NameW); o->HamMode = true; - o->HamBuf = ReadHamcoreW(name); + o->HamBuf = ReadHamcoreW(o->NameW); if (o->HamBuf == NULL) { Free(o); From e8c14cba68f89e2ef226cf2756acfafc84d98190 Mon Sep 17 00:00:00 2001 From: hiura Date: Sun, 24 Mar 2024 19:11:24 +0900 Subject: [PATCH 39/63] Fix 'Session Timeouted.': Change the time for checking wether all the TCP connectins are alive or not. --- src/Cedar/Session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c index 00a9e817..e0bb58a6 100644 --- a/src/Cedar/Session.c +++ b/src/Cedar/Session.c @@ -615,7 +615,7 @@ void SessionMain(SESSION *s) UINT max_conn = s->ClientOption->MaxConnection; if ((s->CurrentConnectionEstablishTime + - (UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2)) + (UINT64)(num_tcp_conn * s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2)) <= Tick64()) { if (s->ClientOption->BindLocalPort != 0 || num_tcp_conn == 0) From 495cddd518a88caff2322fc1a7c93d360efef30f Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sun, 24 Mar 2024 20:18:38 +0100 Subject: [PATCH 40/63] bump version for upcoming 5183 release --- .vscode/settings.json | 3 +++ CMakeLists.txt | 2 +- CMakeSettings.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cad7657d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.configureOnOpen": false +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e1120daa..88278a43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10) set(BUILD_NUMBER CACHE STRING "The number of the current build.") if ("${BUILD_NUMBER}" STREQUAL "") - set(BUILD_NUMBER "5182") + set(BUILD_NUMBER "5183") endif() if (BUILD_NUMBER LESS 5180) diff --git a/CMakeSettings.json b/CMakeSettings.json index 82a5e910..22cda99d 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,5 +1,5 @@ { - "environments": [ { "BuildNumber": "5182" } ], + "environments": [ { "BuildNumber": "5183" } ], "configurations": [ { "name": "x64-native", From 97203568e7d5540ae2cefffed0881be4966c2d05 Mon Sep 17 00:00:00 2001 From: hiura Date: Sun, 31 Mar 2024 23:07:16 +0900 Subject: [PATCH 41/63] Fix 'RemoveDefGwOnDhcpForLocalhost' function: Change to exclude unplugged device from MAC address list. --- src/Mayaqua/Microsoft.c | 1 + src/Mayaqua/Microsoft.h | 1 + src/Mayaqua/Network.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/src/Mayaqua/Microsoft.c b/src/Mayaqua/Microsoft.c index 5f9e015e..4579b301 100644 --- a/src/Mayaqua/Microsoft.c +++ b/src/Mayaqua/Microsoft.c @@ -2568,6 +2568,7 @@ MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info) UniStrCpy(a->TitleW, sizeof(a->TitleW), title); UniToStr(a->Title, sizeof(a->Title), title); a->Index = r->InterfaceIndex; + a->MediaConnectState = r->MediaConnectState; a->Type = r->Type; a->Status = ConvertMidStatusVistaToXp(r->OperStatus); a->Mtu = r->Mtu; diff --git a/src/Mayaqua/Microsoft.h b/src/Mayaqua/Microsoft.h index c0d6a5ab..0044bbda 100644 --- a/src/Mayaqua/Microsoft.h +++ b/src/Mayaqua/Microsoft.h @@ -281,6 +281,7 @@ typedef struct MS_ADAPTER char Title[MAX_PATH]; // Display name wchar_t TitleW[MAX_PATH]; // Display Name (Unicode) UINT Index; // Index + UINT MediaConnectState; // Media Connect State UINT Type; // Type UINT Status; // Status UINT Mtu; // MTU diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 465ae836..c9ea7595 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -540,6 +540,13 @@ LIST *Win32GetNicList() if (a->Type == 6 && a->AddressSize == 6) { + // If the connection state of the interface is unknown, then exclude it. + // Unknown means that the device is not plugged into the local host. + if (a->MediaConnectState == MediaConnectStateUnknown) + { + continue; + } + NIC_ENTRY *e = ZeroMalloc(sizeof(NIC_ENTRY)); StrCpy(e->IfName, sizeof(e->IfName), a->Title); From 62e7f0ba8adfdad2766537ce427fc2716d784443 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Fri, 5 Apr 2024 22:08:51 +0200 Subject: [PATCH 42/63] CI: adopt windows_build.bat for GitHub actions --- .ci/azure-pipelines/windows_build.bat | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.ci/azure-pipelines/windows_build.bat b/.ci/azure-pipelines/windows_build.bat index 6f533c72..b8491266 100644 --- a/.ci/azure-pipelines/windows_build.bat +++ b/.ci/azure-pipelines/windows_build.bat @@ -14,6 +14,12 @@ if %SE_BUILD_NUMBER_TOKEN_LENGTH% equ 64 ( set BUILD_NUMBER=0 ) + +if "%BUILD_BINARIESDIRECTORY%"=="" (set BUILD_BINARIESDIRECTORY=build) +if "%BUILD_SOURCESDIRECTORY%"=="" (set BUILD_SOURCESDIRECTORY=%cd%) + +if not exist %BUILD_BINARIESDIRECTORY% mkdir %BUILD_BINARIESDIRECTORY% + cd %BUILD_BINARIESDIRECTORY% call "%VCVARS_PATH%" @@ -21,6 +27,7 @@ call "%VCVARS_PATH%" cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% "%BUILD_SOURCESDIRECTORY%" cmake --build . +if "%BUILD_STAGINGDIRECTORY%"=="" (set BUILD_STAGINGDIRECTORY=%cd%) mkdir "%BUILD_STAGINGDIRECTORY%\installers" vpnsetup /SFXMODE:vpnclient /SFXOUT:"%BUILD_STAGINGDIRECTORY%\installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" vpnsetup /SFXMODE:vpnserver_vpnbridge /SFXOUT:"%BUILD_STAGINGDIRECTORY%\installers\softether-vpnserver_vpnbridge-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" From 7981e16e0bd6329d79721621fb202e6213b6ecc1 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Fri, 5 Apr 2024 22:09:39 +0200 Subject: [PATCH 43/63] CI: add windows GitHub Actions --- .github/workflows/windows.yml | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..4b798b6b --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,46 @@ +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build_and_test: + strategy: + matrix: + platform: [ + { ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat"}, + { ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"} + ] + runs-on: windows-latest + name: ${{ matrix.platform.ARCHITECTURE }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Cache vcpkg + uses: actions/cache@v4 + with: + path: 'build/vcpkg_installed/' + key: vcpkg-${{ matrix.platform.VCPKG_TRIPLET }} + - name: Build + env: + ARCHITECTURE: ${{ matrix.platform.ARCHITECTURE }} + COMPILER_PATH: ${{ matrix.platform.COMPILER_PATH }} + VCPKG_TRIPLET: ${{ matrix.platform.VCPKG_TRIPLET }} + VCVARS_PATH: ${{ matrix.platform.VCVARS_PATH }} + run: .ci/azure-pipelines/windows_build.bat + - name: Test + shell: powershell + run: | + . .ci/appveyor-vpntest.ps1 + - uses: actions/upload-artifact@v4 + with: + name: Binaries-${{ matrix.platform.ARCHITECTURE }} + path: | + build/*.exe + build/*.pdb + build/*.se2 + - uses: actions/upload-artifact@v4 + with: + name: Installers-${{ matrix.platform.ARCHITECTURE }} + path: build/installers \ No newline at end of file From 4c1eeb717baf5772a84ac5b00a2c6e4fedbb2362 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Fri, 5 Apr 2024 22:15:35 +0200 Subject: [PATCH 44/63] CI: harden artifacts upload --- .github/workflows/windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 4b798b6b..66a32ccf 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -35,6 +35,7 @@ jobs: . .ci/appveyor-vpntest.ps1 - uses: actions/upload-artifact@v4 with: + if-no-files-found: error name: Binaries-${{ matrix.platform.ARCHITECTURE }} path: | build/*.exe @@ -42,5 +43,6 @@ jobs: build/*.se2 - uses: actions/upload-artifact@v4 with: + if-no-files-found: error name: Installers-${{ matrix.platform.ARCHITECTURE }} path: build/installers \ No newline at end of file From 23e9f74e7e516b6c393c4cb8910d24b13ac6c679 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Sun, 7 Apr 2024 17:16:45 +0200 Subject: [PATCH 45/63] CI: move linux builds to GHA, drop ADO --- .azure-pipelines.yml | 4 --- .ci/azure-pipelines/linux.yml | 20 ------------- .ci/azure-pipelines/macos.yml | 14 --------- .ci/azure-pipelines/windows-steps.yml | 41 --------------------------- .ci/azure-pipelines/windows.yml | 27 ------------------ .github/workflows/linux.yml | 34 ++++++++++++++++++++++ 6 files changed, 34 insertions(+), 106 deletions(-) delete mode 100644 .azure-pipelines.yml delete mode 100644 .ci/azure-pipelines/linux.yml delete mode 100644 .ci/azure-pipelines/macos.yml delete mode 100644 .ci/azure-pipelines/windows-steps.yml delete mode 100644 .ci/azure-pipelines/windows.yml create mode 100644 .github/workflows/linux.yml diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml deleted file mode 100644 index e4d8739a..00000000 --- a/.azure-pipelines.yml +++ /dev/null @@ -1,4 +0,0 @@ -jobs: - - template: .ci/azure-pipelines/linux.yml - - template: .ci/azure-pipelines/windows.yml - - template: .ci/azure-pipelines/macos.yml diff --git a/.ci/azure-pipelines/linux.yml b/.ci/azure-pipelines/linux.yml deleted file mode 100644 index fbb8aeb5..00000000 --- a/.ci/azure-pipelines/linux.yml +++ /dev/null @@ -1,20 +0,0 @@ -jobs: -- job: Ubuntu_x64 - pool: - vmImage: ubuntu-22.04 - steps: - - checkout: self - submodules: true - persistCredentials: true - - script: sudo apt update && sudo apt-get -y install cmake gcc g++ ninja-build libncurses5-dev libreadline-dev libsodium-dev libssl-dev make zlib1g-dev liblz4-dev libnl-genl-3-dev - displayName: 'Prepare environment' - - script: "$(Build.SourcesDirectory)/.ci/azure-pipelines/linux_build.sh" - env: - SE_BUILD_NUMBER_TOKEN: $(BUILD_NUMBER_TOKEN) - displayName: 'Build' - - script: | - .ci/appveyor-deb-install-test.sh - sudo apt-get -y install autoconf libtool liblzo2-dev libpam-dev fping unzip libcap-ng-dev # To build OpenVPN - sudo BUILD_BINARIESDIRECTORY=$BUILD_BINARIESDIRECTORY .ci/start-se-openvpn.sh - sudo BUILD_BINARIESDIRECTORY=$BUILD_BINARIESDIRECTORY .ci/run-openvpn-tests.sh - displayName: 'Test' diff --git a/.ci/azure-pipelines/macos.yml b/.ci/azure-pipelines/macos.yml deleted file mode 100644 index da8fa2f8..00000000 --- a/.ci/azure-pipelines/macos.yml +++ /dev/null @@ -1,14 +0,0 @@ -jobs: -- job: macOS - pool: - vmImage: macOS-latest - steps: - - checkout: self - submodules: true - persistCredentials: true - - script: brew install pkg-config cmake ninja ncurses readline libsodium openssl zlib - displayName: 'Prepare environment' - - script: '$(Build.SourcesDirectory)/.ci/azure-pipelines/macos_build.sh' - env: - SE_BUILD_NUMBER_TOKEN: $(BUILD_NUMBER_TOKEN) - displayName: 'Build' diff --git a/.ci/azure-pipelines/windows-steps.yml b/.ci/azure-pipelines/windows-steps.yml deleted file mode 100644 index 79bd5fdf..00000000 --- a/.ci/azure-pipelines/windows-steps.yml +++ /dev/null @@ -1,41 +0,0 @@ -parameters: -- name: architecture - type: string -- name: compilerPath - type: string -- name: vcpkgTriplet - type: string -- name: vcvarsPath - type: string - -steps: -- task: Cache@2 - inputs: - key: '"vcpkg-manifest" | "$(Agent.OS)" | "${{parameters.vcpkgTriplet}}" | C:/vcpkg/.git/refs/heads/master' - path: '$(Build.BinariesDirectory)/vcpkg_installed' - displayName: 'Environment storage' -- script: '$(Build.SourcesDirectory)/.ci/azure-pipelines/windows_build.bat' - env: - ARCHITECTURE: ${{parameters.architecture}} - COMPILER_PATH: ${{parameters.compilerPath}} - VCPKG_TRIPLET: ${{parameters.vcpkgTriplet}} - VCVARS_PATH: ${{parameters.vcvarsPath}} - SE_BUILD_NUMBER_TOKEN: $(BUILD_NUMBER_TOKEN) - displayName: 'Build' -- powershell: | - . .ci/appveyor-vpntest.ps1 - displayName: 'Test' -- task: CopyFiles@2 - inputs: - sourceFolder: '$(Build.BinariesDirectory)' - contents: '?(*.exe|*.se2|*.pdb)' - TargetFolder: '$(Build.StagingDirectory)/binaries/${{parameters.architecture}}' - flattenFolders: true -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: '$(Build.StagingDirectory)/binaries/${{parameters.architecture}}' - artifactName: 'Binaries_${{parameters.architecture}}' -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: '$(Build.StagingDirectory)/installers' - artifactName: 'Installers' diff --git a/.ci/azure-pipelines/windows.yml b/.ci/azure-pipelines/windows.yml deleted file mode 100644 index 6c6a75e8..00000000 --- a/.ci/azure-pipelines/windows.yml +++ /dev/null @@ -1,27 +0,0 @@ -jobs: -- job: Windows_x64 - pool: - vmImage: windows-latest - steps: - - checkout: self - submodules: true - persistCredentials: true - - template: "windows-steps.yml" - parameters: - architecture: "x64" - compilerPath: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe" - vcpkgTriplet: "x64-windows-static" - vcvarsPath: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat" -- job: Windows_x86 - pool: - vmImage: windows-latest - steps: - - checkout: self - submodules: true - persistCredentials: true - - template: "windows-steps.yml" - parameters: - architecture: "x86" - compilerPath: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe" - vcpkgTriplet: "x86-windows-static" - vcvarsPath: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat" diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 00000000..799f4b8f --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,34 @@ +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build_and_test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Install dependencies + run: sudo apt update && sudo apt-get -y install cmake gcc g++ ninja-build libncurses5-dev libreadline-dev libsodium-dev libssl-dev make zlib1g-dev liblz4-dev libnl-genl-3-dev + + - name: Build + run: | + mkdir build + cd build + cmake -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + cmake --build . + + - name: Build deb packages + run: | + cd build + cpack -C Release -G DEB + + - name: Test + run: | + .ci/appveyor-deb-install-test.sh + sudo apt-get -y install autoconf libtool liblzo2-dev libpam-dev fping unzip libcap-ng-dev # To build OpenVPN + sudo .ci/start-se-openvpn.sh + sudo .ci/run-openvpn-tests.sh From 74ea87d725e5c1379db3be7410d0ea9d107d4aa8 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Fri, 12 Apr 2024 12:44:19 +0200 Subject: [PATCH 46/63] CI: drop app veyor in favour of GHA --- .appveyor.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 5170a90c..00000000 --- a/.appveyor.yml +++ /dev/null @@ -1,33 +0,0 @@ -version: '{build}' - -image: Ubuntu2004 - -configuration: Release - -skip_branch_with_pr: true -clone_depth: 1 - -skip_commits: - files: - - .travis.yml - - .gitlab-ci.yml - - .azure-pipelines.yml - - .cirrus.yml - -init: - - ps: Update-AppveyorBuild -Version "build-$env:APPVEYOR_BUILD_NUMBER-$($env:APPVEYOR_REPO_COMMIT.substring(0,7))" - -install: - - sudo apt-get -y install libsodium-dev libcap-ng-dev -before_build: - - git submodule update --init --recursive - - ./configure -build_script: - - make package -C build -j $(nproc || sysctl -n hw.ncpu || echo 4) - - .ci/memory-leak-test.sh -test_script: - - .ci/appveyor-deb-install-test.sh - - sudo apt-get update && sudo apt-get -y install autoconf libtool liblzo2-dev libpam-dev fping unzip liblz4-dev libnl-genl-3-dev # openvpn build deps - - sudo .ci/start-se-openvpn.sh - - sudo .ci/run-openvpn-tests.sh - From 71d71e51db30ab9816977523313a32df941114ee Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Fri, 12 Apr 2024 23:08:24 +0500 Subject: [PATCH 47/63] OpenVPN certificate authorization with cn_username in 'email' format --- src/Cedar/Protocol.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index 6075f3ff..3829b563 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -6773,7 +6773,6 @@ PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x) p = NewPack(); PackAddStr(p, "method", "login"); - PackAddStr(p, "hubname", hubname); if (IsEmptyStr(username)) { @@ -6782,12 +6781,25 @@ PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x) FreePack(p); return NULL; } + UniToStr(cn_username, sizeof(cn_username), x->subject_name->CommonName); - PackAddStr(p, "username", cn_username); + + if(strchr(cn_username, '@') != NULL) + { + PackAddStr(p, "username", strtok(cn_username, "@")); + PackAddStr(p, "hubname", strtok(NULL, "")); + } + else + { + PackAddStr(p, "username", cn_username); + PackAddStr(p, "hubname", hubname); + } + } else { PackAddStr(p, "username", username); + PackAddStr(p, "hubname", hubname); } PackAddInt(p, "authtype", AUTHTYPE_OPENVPN_CERT); From 6582955cfa4158d889bf96da9f91e8b8bbbfae82 Mon Sep 17 00:00:00 2001 From: Ilya Shipitsin Date: Sun, 14 Apr 2024 10:36:55 +0200 Subject: [PATCH 48/63] Update src/Cedar/Protocol.c Co-authored-by: Davide Beatrici --- src/Cedar/Protocol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index 3829b563..a0da6c70 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -6784,7 +6784,8 @@ PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x) UniToStr(cn_username, sizeof(cn_username), x->subject_name->CommonName); - if(strchr(cn_username, '@') != NULL) + if (strchr(cn_username, '@') != NULL) + { PackAddStr(p, "username", strtok(cn_username, "@")); PackAddStr(p, "hubname", strtok(NULL, "")); From c36d7187a8de4b39d7879a752f5933de9689de6b Mon Sep 17 00:00:00 2001 From: hiura Date: Tue, 16 Apr 2024 10:30:10 +0900 Subject: [PATCH 49/63] Fix 'RemoveDefGwOnDhcpForLocalhost' function No.2: Change the minimum size of DHCP reply --- src/Mayaqua/TcpIp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Mayaqua/TcpIp.c b/src/Mayaqua/TcpIp.c index 7c3abddb..21cc14e9 100644 --- a/src/Mayaqua/TcpIp.c +++ b/src/Mayaqua/TcpIp.c @@ -4168,6 +4168,7 @@ BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size) LIST *opt_list2 = NULL; UINT src_size = size; UINT i; + UINT dhcp_min_size; // Validate arguments if (m == NULL || data == NULL || size == 0) { @@ -4270,11 +4271,13 @@ BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size) // Rewrite if anything changes. Do not rewrite if there is no change ret_ok = true; - if (ret->Size < DHCP_MIN_SIZE) + // If src_size is greater than DHCP_MIN_SIZE, then use the src_size as minimum size of DHCP. + dhcp_min_size = max(src_size, DHCP_MIN_SIZE); + if (ret->Size < dhcp_min_size) { // Padding UCHAR *pad_buf; - UINT pad_size = DHCP_MIN_SIZE - ret->Size; + UINT pad_size = dhcp_min_size - ret->Size; pad_buf = ZeroMalloc(pad_size); From 9a009d750aac2416ee15515df8639eed2ba8215f Mon Sep 17 00:00:00 2001 From: hiura Date: Tue, 16 Apr 2024 19:14:44 +0900 Subject: [PATCH 50/63] Use macro 'MAX' instead of 'max' --- src/Mayaqua/TcpIp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mayaqua/TcpIp.c b/src/Mayaqua/TcpIp.c index 21cc14e9..8dba45e2 100644 --- a/src/Mayaqua/TcpIp.c +++ b/src/Mayaqua/TcpIp.c @@ -4272,7 +4272,7 @@ BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size) ret_ok = true; // If src_size is greater than DHCP_MIN_SIZE, then use the src_size as minimum size of DHCP. - dhcp_min_size = max(src_size, DHCP_MIN_SIZE); + dhcp_min_size = MAX(src_size, DHCP_MIN_SIZE); if (ret->Size < dhcp_min_size) { // Padding From 9982e128effee1f4b7d5b1f634b2cc9d70010a64 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Tue, 16 Apr 2024 22:26:00 +0200 Subject: [PATCH 51/63] CI: simplify GHA windows workflow --- .ci/azure-pipelines/windows_build.bat | 33 --------------------------- .github/workflows/windows.yml | 17 +++++++++++++- 2 files changed, 16 insertions(+), 34 deletions(-) delete mode 100644 .ci/azure-pipelines/windows_build.bat diff --git a/.ci/azure-pipelines/windows_build.bat b/.ci/azure-pipelines/windows_build.bat deleted file mode 100644 index b8491266..00000000 --- a/.ci/azure-pipelines/windows_build.bat +++ /dev/null @@ -1,33 +0,0 @@ -@echo on - -:: The method we use to store a command's output into a variable: -:: https://stackoverflow.com/a/6362922 -for /f "tokens=* USEBACKQ" %%g in (`python "version.py"`) do (set "VERSION=%%g") - -:: https://stackoverflow.com/a/8566001 -echo %SE_BUILD_NUMBER_TOKEN%> "%tmp%\length.txt" -for %%? in ("%tmp%\length.txt") do ( set /A SE_BUILD_NUMBER_TOKEN_LENGTH=%%~z? - 2 ) - -if %SE_BUILD_NUMBER_TOKEN_LENGTH% equ 64 ( - for /f "tokens=* USEBACKQ" %%g in (`curl "https://softether.network/get-build-number?commit=%BUILD_SOURCEVERSION%&version=%VERSION%&token=%SE_BUILD_NUMBER_TOKEN%"`) do (set "BUILD_NUMBER=%%g") -) else ( - set BUILD_NUMBER=0 -) - - -if "%BUILD_BINARIESDIRECTORY%"=="" (set BUILD_BINARIESDIRECTORY=build) -if "%BUILD_SOURCESDIRECTORY%"=="" (set BUILD_SOURCESDIRECTORY=%cd%) - -if not exist %BUILD_BINARIESDIRECTORY% mkdir %BUILD_BINARIESDIRECTORY% - -cd %BUILD_BINARIESDIRECTORY% - -call "%VCVARS_PATH%" - -cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% "%BUILD_SOURCESDIRECTORY%" -cmake --build . - -if "%BUILD_STAGINGDIRECTORY%"=="" (set BUILD_STAGINGDIRECTORY=%cd%) -mkdir "%BUILD_STAGINGDIRECTORY%\installers" -vpnsetup /SFXMODE:vpnclient /SFXOUT:"%BUILD_STAGINGDIRECTORY%\installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" -vpnsetup /SFXMODE:vpnserver_vpnbridge /SFXOUT:"%BUILD_STAGINGDIRECTORY%\installers\softether-vpnserver_vpnbridge-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 66a32ccf..d5cccba3 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -22,13 +22,28 @@ jobs: with: path: 'build/vcpkg_installed/' key: vcpkg-${{ matrix.platform.VCPKG_TRIPLET }} + - name: Set version variables + run: | + $v = python version.py + echo "VERSION=$v" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + shell: pwsh - name: Build env: ARCHITECTURE: ${{ matrix.platform.ARCHITECTURE }} COMPILER_PATH: ${{ matrix.platform.COMPILER_PATH }} VCPKG_TRIPLET: ${{ matrix.platform.VCPKG_TRIPLET }} VCVARS_PATH: ${{ matrix.platform.VCVARS_PATH }} - run: .ci/azure-pipelines/windows_build.bat + run: | + set BUILD_NUMBER=0 + mkdir build + cd build + call "%VCVARS_PATH%" + cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% .. + cmake --build . + mkdir installers + vpnsetup /SFXMODE:vpnclient /SFXOUT:"installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" + vpnsetup /SFXMODE:vpnserver_vpnbridge /SFXOUT:"installers\softether-vpnserver_vpnbridge-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" + shell: cmd - name: Test shell: powershell run: | From c838ba0009a2419e81f75f9f3ce2ebd6f0bfe57e Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Tue, 16 Apr 2024 22:26:51 +0200 Subject: [PATCH 52/63] CI: create windows installer on release --- .github/workflows/windows_release.yml | 94 +++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 .github/workflows/windows_release.yml diff --git a/.github/workflows/windows_release.yml b/.github/workflows/windows_release.yml new file mode 100644 index 00000000..d9198934 --- /dev/null +++ b/.github/workflows/windows_release.yml @@ -0,0 +1,94 @@ +name: "Release" + +on: + push: + tags: + - '*' + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +permissions: + contents: write + +jobs: + release: + runs-on: windows-latest + outputs: + upload_url: "${{ steps.create_release.outputs.upload_url }}" + steps: + - name: "Checkout repository" + uses: actions/checkout@v4 + + - name: "Create GitHub release" + id: create_release + uses: softprops/action-gh-release@v1 + build-windows: + name: ${{ matrix.platform.ARCHITECTURE }} + runs-on: windows-latest + needs: ["release"] + strategy: + matrix: + platform: [ + { ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat"}, + { ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"} + ] + steps: + - name: "Checkout repository" + uses: actions/checkout@v4 + with: + submodules: true + - name: Cache vcpkg + uses: actions/cache@v4 + with: + path: 'build/vcpkg_installed/' + key: vcpkg-release-${{ matrix.platform.VCPKG_TRIPLET }} + - name: Set version variables + run: | + $b=(Get-Content CMakeSettings.json | Out-String | ConvertFrom-Json).environments.BuildNumber + echo "BUILD_NUMBER=$b" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + $v = python version.py + echo "VERSION=$v" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + shell: pwsh + - name: Build + env: + ARCHITECTURE: ${{ matrix.platform.ARCHITECTURE }} + COMPILER_PATH: ${{ matrix.platform.COMPILER_PATH }} + VCPKG_TRIPLET: ${{ matrix.platform.VCPKG_TRIPLET }} + VCVARS_PATH: ${{ matrix.platform.VCVARS_PATH }} + run: | + mkdir build + cd build + call "%VCVARS_PATH%" + cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% .. + cmake --build . + mkdir installers + vpnsetup /SFXMODE:vpnclient /SFXOUT:"installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" + vpnsetup /SFXMODE:vpnserver_vpnbridge /SFXOUT:"installers\softether-vpnserver_vpnbridge-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe" + shell: cmd + + - name: dir + run: | + Get-ChildItem -Recurse build/installers + shell: pwsh + + - name: "Upload softether-vpnclient" + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: "${{ github.token }}" + with: + upload_url: "${{ needs.release.outputs.upload_url }}" + asset_path: "build/installers/softether-vpnclient-${{ env.VERSION }}.${{ env.BUILD_NUMBER }}.${{ matrix.platform.ARCHITECTURE }}.exe" + asset_name: "softether-vpnclient-${{ env.VERSION }}.${{ env.BUILD_NUMBER }}.${{ matrix.platform.ARCHITECTURE }}.exe" + asset_content_type: "application/octet-stream" + - name: "Upload softether-vpnserver_vpnbridge" + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: "${{ github.token }}" + with: + upload_url: "${{ needs.release.outputs.upload_url }}" + asset_path: "build/installers/softether-vpnserver_vpnbridge-${{ env.VERSION }}.${{ env.BUILD_NUMBER }}.${{ matrix.platform.ARCHITECTURE }}.exe" + asset_name: "softether-vpnserver_vpnbridge-${{ env.VERSION }}.${{ env.BUILD_NUMBER }}.${{ matrix.platform.ARCHITECTURE }}.exe" + asset_content_type: "application/octet-stream" + From 5ee8e3f00c20a5557ea3db78a4534f4a6dc0403d Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Wed, 17 Apr 2024 09:10:07 +0200 Subject: [PATCH 53/63] CI: cleanup azure pipeline helpers --- .ci/azure-pipelines/linux_build.sh | 15 --------------- .ci/azure-pipelines/macos_build.sh | 13 ------------- 2 files changed, 28 deletions(-) delete mode 100755 .ci/azure-pipelines/linux_build.sh delete mode 100755 .ci/azure-pipelines/macos_build.sh diff --git a/.ci/azure-pipelines/linux_build.sh b/.ci/azure-pipelines/linux_build.sh deleted file mode 100755 index 87537491..00000000 --- a/.ci/azure-pipelines/linux_build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -if [[ "${#SE_BUILD_NUMBER_TOKEN}" -eq 64 ]]; then - VERSION=$(python3 "version.py") - BUILD_NUMBER=$(curl "https://softether.network/get-build-number?commit=${BUILD_SOURCEVERSION}&version=${VERSION}&token=${SE_BUILD_NUMBER_TOKEN}") -else - BUILD_NUMBER=0 -fi - -cd ${BUILD_BINARIESDIRECTORY} - -cmake -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_NUMBER=${BUILD_NUMBER} ${BUILD_SOURCESDIRECTORY} -cmake --build . - -cpack -C Release -G DEB diff --git a/.ci/azure-pipelines/macos_build.sh b/.ci/azure-pipelines/macos_build.sh deleted file mode 100755 index a7418e74..00000000 --- a/.ci/azure-pipelines/macos_build.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -if [[ "${#SE_BUILD_NUMBER_TOKEN}" -eq 64 ]]; then - VERSION=$(python3 "version.py") - BUILD_NUMBER=$(curl "https://softether.network/get-build-number?commit=${BUILD_SOURCEVERSION}&version=${VERSION}&token=${SE_BUILD_NUMBER_TOKEN}") -else - BUILD_NUMBER=0 -fi - -cd ${BUILD_BINARIESDIRECTORY} - -cmake -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_NUMBER=${BUILD_NUMBER} -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" ${BUILD_SOURCESDIRECTORY} -cmake --build . From 831905d281a7539df863044b8ef12ddfdc2ac935 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Wed, 17 Apr 2024 09:18:00 +0200 Subject: [PATCH 54/63] doc: remove badges of deprecated CI --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index bf2ae5d6..5cab02e2 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,8 @@ ||Badges| |---|---| -|AppVeyor|[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/softethervpn/softethervpn?branch=master&svg=true)](https://ci.appveyor.com/project/softethervpn/softethervpn) | |GitLab CI|[![GitLab CI build status](https://gitlab.com/SoftEther/SoftEtherVPN/badges/master/pipeline.svg)](https://gitlab.com/SoftEther/SoftEtherVPN/pipelines)| |Coverity Scan|[![Coverity Scan build status](https://scan.coverity.com/projects/16304/badge.svg)](https://scan.coverity.com/projects/softethervpn-softethervpn)| -|Azure Pipelines|[![Azure Pipelines build status for Nightly](https://dev.azure.com/SoftEther-VPN/SoftEther%20VPN/_apis/build/status/6?api-version=6.0-preview.1)](https://dev.azure.com/SoftEther-VPN/SoftEther%20VPN/_build?definitionId=6)| |Cirrus CI|[![Cirrus CI build status](https://api.cirrus-ci.com/github/SoftEtherVPN/SoftEtherVPN.svg)](https://cirrus-ci.com/github/SoftEtherVPN/SoftEtherVPN)| - [SoftEther VPN](#softether-vpn) From 071a87297b49475dda1e2b160ef7f01d8d2eade9 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Wed, 17 Apr 2024 13:20:04 +0200 Subject: [PATCH 55/63] bump version for upcoming 5184 release --- CMakeLists.txt | 2 +- CMakeSettings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88278a43..80ecd5d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10) set(BUILD_NUMBER CACHE STRING "The number of the current build.") if ("${BUILD_NUMBER}" STREQUAL "") - set(BUILD_NUMBER "5183") + set(BUILD_NUMBER "5184") endif() if (BUILD_NUMBER LESS 5180) diff --git a/CMakeSettings.json b/CMakeSettings.json index 22cda99d..2d05d087 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,5 +1,5 @@ { - "environments": [ { "BuildNumber": "5183" } ], + "environments": [ { "BuildNumber": "5184" } ], "configurations": [ { "name": "x64-native", From f8c5fa53843d0f15d6146d46f203e10bc1ac28ca Mon Sep 17 00:00:00 2001 From: panakuma Date: Sat, 20 Apr 2024 00:48:24 +0900 Subject: [PATCH 56/63] Change var of CMAKE_INSTALL_RPATH --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80ecd5d3..60e4d50d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ if(UNIX) # # use rpath for locating installed libraries # - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) include(CheckIncludeFile) From 7f074d0c0b6a06c637bf4508cf832ed0e5b8b07c Mon Sep 17 00:00:00 2001 From: hiura Date: Fri, 26 Apr 2024 12:42:27 +0900 Subject: [PATCH 57/63] Fix Virtual DHCP Server: Correct HDCP Sequence --- src/Cedar/Virtual.c | 58 ++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/Cedar/Virtual.c b/src/Cedar/Virtual.c index c9cb0fd6..4fe0c84f 100644 --- a/src/Cedar/Virtual.c +++ b/src/Cedar/Virtual.c @@ -9710,36 +9710,40 @@ void VirtualDhcpServer(VH *v, PKT *p) } else { - // There is no IP address that can be provided - DHCP_OPTION_LIST ret; - LIST *o; - Zero(&ret, sizeof(ret)); - - ret.Opcode = DHCP_NACK; - ret.ServerAddress = v->HostIP; - StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain); - ret.SubnetMask = v->DhcpMask; - - // Build the DHCP option - o = BuildDhcpOption(&ret); - if (o != NULL) + // Reply of DHCP_REQUEST must be either DHCP_ACK or DHCP_NAK. + if (opt->Opcode == DHCP_REQUEST) { - BUF *b = BuildDhcpOptionsBuf(o); - if (b != NULL) - { - UINT dest_ip = p->L3.IPv4Header->SrcIP; - if (dest_ip == 0) - { - dest_ip = 0xffffffff; - } - // Transmission - VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort), - ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize); + // There is no IP address that can be provided + DHCP_OPTION_LIST ret; + LIST *o; + Zero(&ret, sizeof(ret)); - // Release the memory - FreeBuf(b); + ret.Opcode = DHCP_NACK; + ret.ServerAddress = v->HostIP; + StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain); + ret.SubnetMask = v->DhcpMask; + + // Build the DHCP option + o = BuildDhcpOption(&ret); + if (o != NULL) + { + BUF *b = BuildDhcpOptionsBuf(o); + if (b != NULL) + { + UINT dest_ip = p->L3.IPv4Header->SrcIP; + if (dest_ip == 0) + { + dest_ip = 0xffffffff; + } + // Transmission + VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort), + ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize); + + // Release the memory + FreeBuf(b); + } + FreeDhcpOptions(o); } - FreeDhcpOptions(o); } } } From c9b5e25c8733dfc208782b685408a8ce8e66b911 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 27 Apr 2024 02:01:48 +0300 Subject: [PATCH 58/63] Fix memory access error when IPv6 prefix reading, should resolve #1972 --- src/Cedar/IPC.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index 85e58a7f..6d408069 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -2354,7 +2354,14 @@ void IPCIPv6AddRouterPrefixes(IPC *ipc, ICMPV6_OPTION_LIST *recvPrefix, UCHAR *m IntToSubnetMask6(&newRA->RoutedMask, recvPrefix->Prefix[i]->SubnetLength); CopyIP(&newRA->RouterAddress, ip); Copy(newRA->RouterMacAddress, macAddress, 6); - Copy(newRA->RouterLinkLayerAddress, recvPrefix->SourceLinkLayer->Address, 6); + if (recvPrefix->SourceLinkLayer != NULL) + { + Copy(newRA->RouterLinkLayerAddress, recvPrefix->SourceLinkLayer->Address, 6); + } + else + { + Zero(newRA->RouterLinkLayerAddress, 6); + } Add(ipc->IPv6RouterAdvs, newRA); } } @@ -2657,7 +2664,7 @@ void IPCIPv6SendUnicast(IPC *ipc, void *data, UINT size, IP *next_ip) } destMac = ra.RouterMacAddress; - if (!IsMacUnicast(destMac) && !IsMacInvalid(ra.RouterMacAddress)) + if (!IsMacUnicast(destMac) && !IsMacInvalid(ra.RouterLinkLayerAddress)) { destMac = ra.RouterLinkLayerAddress; } From d568cc172771a1f6399c954d63d0e17655081f6d Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 27 Apr 2024 21:57:36 +0300 Subject: [PATCH 59/63] Fix another memory access error again because of a missing MAC address in IPv6 headers --- src/Cedar/IPC.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index 6d408069..6cfc8369 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -1517,7 +1517,9 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now) // We save the router advertisement data for later use IPCIPv6AddRouterPrefixes(ipc, &p->ICMPv6HeaderPacketInfo.OptionList, src_mac, &ip_src); IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true); - IPCIPv6AssociateOnNDTEx(ipc, &ip_src, p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, true); + if (p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer != NULL) { + IPCIPv6AssociateOnNDTEx(ipc, &ip_src, p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, true); + } ndtProcessed = true; header_size = sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER); break; From 6e5395cc8d0262fa2bb1d44116cac80b32f34cf9 Mon Sep 17 00:00:00 2001 From: hiura Date: Fri, 3 May 2024 17:18:13 +0900 Subject: [PATCH 60/63] Fix Virtual DHCP Server: Correct DHCP renewal request --- src/Cedar/Virtual.c | 69 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/src/Cedar/Virtual.c b/src/Cedar/Virtual.c index 4fe0c84f..fa2367dc 100644 --- a/src/Cedar/Virtual.c +++ b/src/Cedar/Virtual.c @@ -9340,20 +9340,75 @@ UINT ServeDhcpDiscoverEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip) return 0; } + UINT ret = 0; DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip); + if (d != NULL) { - // The requested IP address is used already - return 0; + // If an entry for the same IP address already exists, + // check whether it is a request from the same MAC address + if (Cmp(mac, d->MacAddress, 6) == 0) + { + // Examine whether the specified IP address is within the range of assignment + if (Endian32(v->DhcpIpStart) > Endian32(request_ip) || + Endian32(request_ip) > Endian32(v->DhcpIpEnd)) + { + // Accept if within the range + ret = request_ip; + } + } + else { + // Duplicated IPV4 address found. The DHCP server replies to DHCPREQUEST with DHCP NAK. + char ipstr[MAX_HOST_NAME_LEN + 1] = { 0 }; + char macstr[128] = { 0 }; + IPToStr32(ipstr, sizeof(ipstr), request_ip); + BinToStr(macstr, sizeof(macstr), d->MacAddress, 6); + Debug("Virtual DHC Server: Duplicated IP address detected. Static IP: %s, Used by MAC:%s\n", ipstr, macstr); + return ret; + } } - - // For static IP, the requested IP address must NOT be within the range of the DHCP pool - if (Endian32(request_ip) < Endian32(v->DhcpIpStart) || Endian32(request_ip) > Endian32(v->DhcpIpEnd)) + else { - return request_ip; + // Examine whether the specified IP address is within the range of assignment + if (Endian32(v->DhcpIpStart) > Endian32(request_ip) || + Endian32(request_ip) > Endian32(v->DhcpIpEnd)) + { + // Accept if within the range + ret = request_ip; + } + else + { + // Propose an IP in the range since it's a Discover although It is out of range + } + } + if (ret == 0) + { + // If there is any entry with the same MAC address + // that are already registered, use it with priority + DHCP_LEASE *d = SearchDhcpLeaseByMac(v, mac); + + if (d != NULL) + { + // Examine whether the found IP address is in the allocation region + if (Endian32(v->DhcpIpStart) > Endian32(d->IpAddress) || + Endian32(d->IpAddress) > Endian32(v->DhcpIpEnd)) + { + // Use the IP address if it's found within the range + ret = d->IpAddress; + } + } + } + if (ret == 0) + { + // For static IP, the requested IP address must NOT be within the range of the DHCP pool + if (Endian32(v->DhcpIpStart) > Endian32(request_ip) || + Endian32(request_ip) > Endian32(v->DhcpIpEnd)) + { + ret = request_ip; + } } - return 0; + return ret; } // Take an appropriate IP addresses that can be assigned newly From 37231ac0061649295e0a5b38666ac33c6389a888 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Sat, 4 May 2024 21:23:00 +0200 Subject: [PATCH 61/63] bump version for upcoming 5185 release --- CMakeLists.txt | 2 +- CMakeSettings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60e4d50d..a4d1d827 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10) set(BUILD_NUMBER CACHE STRING "The number of the current build.") if ("${BUILD_NUMBER}" STREQUAL "") - set(BUILD_NUMBER "5184") + set(BUILD_NUMBER "5185") endif() if (BUILD_NUMBER LESS 5180) diff --git a/CMakeSettings.json b/CMakeSettings.json index 2d05d087..b5d3b77e 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,5 +1,5 @@ { - "environments": [ { "BuildNumber": "5184" } ], + "environments": [ { "BuildNumber": "5185" } ], "configurations": [ { "name": "x64-native", From 186d48fba2722ab1ce9d5d38e92c44ba2e588f32 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Sat, 4 May 2024 21:25:39 +0200 Subject: [PATCH 62/63] CI: add macos-14 --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dd58217a..621aee5f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -7,7 +7,7 @@ jobs: build_and_test: strategy: matrix: - os: [macos-13, macos-12, macos-11] + os: [macos-14, macos-13, macos-12, macos-11] name: ${{ matrix.os }} runs-on: ${{ matrix.os }} steps: From 141060101d6fc11955ef91cb48fdd80ec51f3443 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Mon, 20 May 2024 21:50:07 +0200 Subject: [PATCH 63/63] CI: drop macos-11 more details: https://github.blog/changelog/2024-05-20-actions-upcoming-changes-to-github-hosted-macos-runners/ --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 621aee5f..f6821b9b 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -7,7 +7,7 @@ jobs: build_and_test: strategy: matrix: - os: [macos-14, macos-13, macos-12, macos-11] + os: [macos-14, macos-13, macos-12] name: ${{ matrix.os }} runs-on: ${{ matrix.os }} steps: