@decaf-ts/for-fabric 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. package/dist/for-fabric.cjs +2 -1726
  2. package/dist/for-fabric.cjs.map +1 -0
  3. package/dist/for-fabric.js +2 -1831
  4. package/dist/for-fabric.js.map +1 -0
  5. package/lib/bin/build-contract.cjs +1 -2
  6. package/lib/bin/build-contract.js.map +1 -0
  7. package/lib/bin/build-contracts.cjs +1 -2
  8. package/lib/bin/build-contracts.js.map +1 -0
  9. package/lib/bin/build-contracts2.cjs +1 -2
  10. package/lib/bin/build-contracts2.js.map +1 -0
  11. package/lib/bin/compile-indexes.cjs +1 -2
  12. package/lib/bin/compile-indexes.js.map +1 -0
  13. package/lib/cli-module.cjs +1 -1
  14. package/lib/cli-module.js.map +1 -0
  15. package/lib/client/FabricClientAdapter.cjs +21 -5
  16. package/lib/client/FabricClientAdapter.d.ts +2 -2
  17. package/lib/client/FabricClientAdapter.js.map +1 -0
  18. package/lib/client/FabricClientDispatch.cjs +1 -1
  19. package/lib/client/FabricClientDispatch.js.map +1 -0
  20. package/lib/client/FabricClientPaginator.cjs +1 -1
  21. package/lib/client/FabricClientPaginator.js.map +1 -0
  22. package/lib/client/FabricClientRepository.cjs +23 -1
  23. package/lib/client/FabricClientRepository.d.ts +1 -0
  24. package/lib/client/FabricClientRepository.js.map +1 -0
  25. package/lib/client/FabricClientStatement.cjs +1 -1
  26. package/lib/client/FabricClientStatement.js.map +1 -0
  27. package/lib/client/erc20/FabricERC20ClientRepository.cjs +1 -1
  28. package/lib/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  29. package/lib/client/erc20/index.cjs +1 -1
  30. package/lib/client/erc20/index.js.map +1 -0
  31. package/lib/client/fabric-fs.cjs +1 -1
  32. package/lib/client/fabric-fs.js.map +1 -0
  33. package/lib/client/fabric-hsm.cjs +1 -1
  34. package/lib/client/fabric-hsm.js.map +1 -0
  35. package/lib/client/index.cjs +1 -1
  36. package/lib/client/index.js.map +1 -0
  37. package/lib/client/indexes/generation.cjs +1 -1
  38. package/lib/client/indexes/generation.js.map +1 -0
  39. package/lib/client/indexes/index.cjs +1 -1
  40. package/lib/client/indexes/index.js.map +1 -0
  41. package/lib/client/logging.cjs +1 -1
  42. package/lib/client/logging.js.map +1 -0
  43. package/lib/client/services/FabricEnrollmentService.cjs +1 -2
  44. package/lib/client/services/FabricEnrollmentService.js.map +1 -0
  45. package/lib/client/services/constants.cjs +1 -1
  46. package/lib/client/services/constants.js.map +1 -0
  47. package/lib/client/services/index.cjs +1 -1
  48. package/lib/client/services/index.js.map +1 -0
  49. package/lib/contract/Address.cjs +73 -0
  50. package/lib/contract/Address.d.ts +13 -0
  51. package/lib/contract/Address.js.map +1 -0
  52. package/lib/contract/AddressContract.cjs +34 -0
  53. package/lib/contract/AddressContract.d.ts +5 -0
  54. package/lib/contract/AddressContract.js.map +1 -0
  55. package/lib/contract/Product.cjs +1 -1
  56. package/lib/contract/Product.js.map +1 -0
  57. package/lib/contract/ProductContract.cjs +1 -1
  58. package/lib/contract/ProductContract.js.map +1 -0
  59. package/lib/contract/User.cjs +1 -1
  60. package/lib/contract/User.js.map +1 -0
  61. package/lib/contract/UserContract.cjs +1 -1
  62. package/lib/contract/UserContract.js.map +1 -0
  63. package/lib/contract/index.cjs +7 -2
  64. package/lib/contract/index.js.map +1 -0
  65. package/lib/contracts/ContractAdapter.cjs +84 -47
  66. package/lib/contracts/ContractAdapter.js.map +1 -0
  67. package/lib/contracts/ContractContext.cjs +1 -1
  68. package/lib/contracts/ContractContext.js.map +1 -0
  69. package/lib/contracts/ContractPrivateDataAdapter.cjs +1 -1
  70. package/lib/contracts/ContractPrivateDataAdapter.js.map +1 -0
  71. package/lib/contracts/FabricConstruction.cjs +1 -1
  72. package/lib/contracts/FabricConstruction.js.map +1 -0
  73. package/lib/contracts/FabricContractRepository.cjs +8 -1
  74. package/lib/contracts/FabricContractRepository.d.ts +12 -0
  75. package/lib/contracts/FabricContractRepository.js.map +1 -0
  76. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +1 -1
  77. package/lib/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  78. package/lib/contracts/FabricContractStatement.cjs +1 -1
  79. package/lib/contracts/FabricContractStatement.js.map +1 -0
  80. package/lib/contracts/PrivateSequence.cjs +1 -1
  81. package/lib/contracts/PrivateSequence.js.map +1 -0
  82. package/lib/contracts/crud/crud-contract.cjs +3 -5
  83. package/lib/contracts/crud/crud-contract.d.ts +6 -6
  84. package/lib/contracts/crud/crud-contract.js.map +1 -0
  85. package/lib/contracts/crud/index.cjs +1 -1
  86. package/lib/contracts/crud/index.js.map +1 -0
  87. package/lib/contracts/crud/serialized-crud-contract.cjs +19 -13
  88. package/lib/contracts/crud/serialized-crud-contract.d.ts +5 -6
  89. package/lib/contracts/crud/serialized-crud-contract.js.map +1 -0
  90. package/lib/contracts/erc20/erc20contract.cjs +1 -1
  91. package/lib/contracts/erc20/erc20contract.js.map +1 -0
  92. package/lib/contracts/erc20/index.cjs +1 -1
  93. package/lib/contracts/erc20/index.js.map +1 -0
  94. package/lib/contracts/erc20/models.cjs +1 -1
  95. package/lib/contracts/erc20/models.js.map +1 -0
  96. package/lib/contracts/index.cjs +1 -1
  97. package/lib/contracts/index.js.map +1 -0
  98. package/lib/contracts/logging.cjs +1 -1
  99. package/lib/contracts/logging.js.map +1 -0
  100. package/lib/contracts/private-data.cjs +1 -1
  101. package/lib/contracts/private-data.js.map +1 -0
  102. package/lib/contracts/types.cjs +1 -1
  103. package/lib/contracts/types.js.map +1 -0
  104. package/lib/esm/bin/build-contract.js +1 -1
  105. package/lib/esm/bin/build-contract.js.map +1 -0
  106. package/lib/esm/bin/build-contracts.js +1 -1
  107. package/lib/esm/bin/build-contracts.js.map +1 -0
  108. package/lib/esm/bin/build-contracts2.js +1 -1
  109. package/lib/esm/bin/build-contracts2.js.map +1 -0
  110. package/lib/esm/bin/compile-indexes.js +1 -1
  111. package/lib/esm/bin/compile-indexes.js.map +1 -0
  112. package/lib/esm/cli-module.js +1 -1
  113. package/lib/esm/cli-module.js.map +1 -0
  114. package/lib/esm/client/FabricClientAdapter.d.ts +2 -2
  115. package/lib/esm/client/FabricClientAdapter.js +21 -5
  116. package/lib/esm/client/FabricClientAdapter.js.map +1 -0
  117. package/lib/esm/client/FabricClientDispatch.js +1 -1
  118. package/lib/esm/client/FabricClientDispatch.js.map +1 -0
  119. package/lib/esm/client/FabricClientPaginator.js +1 -1
  120. package/lib/esm/client/FabricClientPaginator.js.map +1 -0
  121. package/lib/esm/client/FabricClientRepository.d.ts +1 -0
  122. package/lib/esm/client/FabricClientRepository.js +23 -1
  123. package/lib/esm/client/FabricClientRepository.js.map +1 -0
  124. package/lib/esm/client/FabricClientStatement.js +1 -1
  125. package/lib/esm/client/FabricClientStatement.js.map +1 -0
  126. package/lib/esm/client/erc20/FabricERC20ClientRepository.js +1 -1
  127. package/lib/esm/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  128. package/lib/esm/client/erc20/index.js +1 -1
  129. package/lib/esm/client/erc20/index.js.map +1 -0
  130. package/lib/esm/client/fabric-fs.js +1 -1
  131. package/lib/esm/client/fabric-fs.js.map +1 -0
  132. package/lib/esm/client/fabric-hsm.js +1 -1
  133. package/lib/esm/client/fabric-hsm.js.map +1 -0
  134. package/lib/esm/client/index.js +1 -1
  135. package/lib/esm/client/index.js.map +1 -0
  136. package/lib/esm/client/indexes/generation.js +1 -1
  137. package/lib/esm/client/indexes/generation.js.map +1 -0
  138. package/lib/esm/client/indexes/index.js +1 -1
  139. package/lib/esm/client/indexes/index.js.map +1 -0
  140. package/lib/esm/client/logging.js +1 -1
  141. package/lib/esm/client/logging.js.map +1 -0
  142. package/lib/esm/client/services/FabricEnrollmentService.js +1 -2
  143. package/lib/esm/client/services/FabricEnrollmentService.js.map +1 -0
  144. package/lib/esm/client/services/constants.js +1 -1
  145. package/lib/esm/client/services/constants.js.map +1 -0
  146. package/lib/esm/client/services/index.js +1 -1
  147. package/lib/esm/client/services/index.js.map +1 -0
  148. package/lib/esm/contract/Address.d.ts +13 -0
  149. package/lib/esm/contract/Address.js +70 -0
  150. package/lib/esm/contract/Address.js.map +1 -0
  151. package/lib/esm/contract/AddressContract.d.ts +5 -0
  152. package/lib/esm/contract/AddressContract.js +31 -0
  153. package/lib/esm/contract/AddressContract.js.map +1 -0
  154. package/lib/esm/contract/Product.js +1 -1
  155. package/lib/esm/contract/Product.js.map +1 -0
  156. package/lib/esm/contract/ProductContract.js +1 -1
  157. package/lib/esm/contract/ProductContract.js.map +1 -0
  158. package/lib/esm/contract/User.js +1 -1
  159. package/lib/esm/contract/User.js.map +1 -0
  160. package/lib/esm/contract/UserContract.js +1 -1
  161. package/lib/esm/contract/UserContract.js.map +1 -0
  162. package/lib/esm/contract/index.js +7 -2
  163. package/lib/esm/contract/index.js.map +1 -0
  164. package/lib/esm/contracts/ContractAdapter.js +88 -51
  165. package/lib/esm/contracts/ContractAdapter.js.map +1 -0
  166. package/lib/esm/contracts/ContractContext.js +1 -1
  167. package/lib/esm/contracts/ContractContext.js.map +1 -0
  168. package/lib/esm/contracts/ContractPrivateDataAdapter.js +1 -1
  169. package/lib/esm/contracts/ContractPrivateDataAdapter.js.map +1 -0
  170. package/lib/esm/contracts/FabricConstruction.js +1 -1
  171. package/lib/esm/contracts/FabricConstruction.js.map +1 -0
  172. package/lib/esm/contracts/FabricContractRepository.d.ts +12 -0
  173. package/lib/esm/contracts/FabricContractRepository.js +8 -1
  174. package/lib/esm/contracts/FabricContractRepository.js.map +1 -0
  175. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +1 -1
  176. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  177. package/lib/esm/contracts/FabricContractStatement.js +1 -1
  178. package/lib/esm/contracts/FabricContractStatement.js.map +1 -0
  179. package/lib/esm/contracts/PrivateSequence.js +1 -1
  180. package/lib/esm/contracts/PrivateSequence.js.map +1 -0
  181. package/lib/esm/contracts/crud/crud-contract.d.ts +6 -6
  182. package/lib/esm/contracts/crud/crud-contract.js +3 -5
  183. package/lib/esm/contracts/crud/crud-contract.js.map +1 -0
  184. package/lib/esm/contracts/crud/index.js +1 -1
  185. package/lib/esm/contracts/crud/index.js.map +1 -0
  186. package/lib/esm/contracts/crud/serialized-crud-contract.d.ts +5 -6
  187. package/lib/esm/contracts/crud/serialized-crud-contract.js +19 -13
  188. package/lib/esm/contracts/crud/serialized-crud-contract.js.map +1 -0
  189. package/lib/esm/contracts/erc20/erc20contract.js +1 -1
  190. package/lib/esm/contracts/erc20/erc20contract.js.map +1 -0
  191. package/lib/esm/contracts/erc20/index.js +1 -1
  192. package/lib/esm/contracts/erc20/index.js.map +1 -0
  193. package/lib/esm/contracts/erc20/models.js +1 -1
  194. package/lib/esm/contracts/erc20/models.js.map +1 -0
  195. package/lib/esm/contracts/index.js +1 -1
  196. package/lib/esm/contracts/index.js.map +1 -0
  197. package/lib/esm/contracts/logging.js +1 -1
  198. package/lib/esm/contracts/logging.js.map +1 -0
  199. package/lib/esm/contracts/private-data.js +1 -1
  200. package/lib/esm/contracts/private-data.js.map +1 -0
  201. package/lib/esm/contracts/types.js +1 -1
  202. package/lib/esm/contracts/types.js.map +1 -0
  203. package/lib/esm/index.js +1 -1
  204. package/lib/esm/index.js.map +1 -0
  205. package/lib/esm/shared/ClientSerializer.js +1 -1
  206. package/lib/esm/shared/ClientSerializer.js.map +1 -0
  207. package/lib/esm/shared/DeterministicSerializer.js +1 -1
  208. package/lib/esm/shared/DeterministicSerializer.js.map +1 -0
  209. package/lib/esm/shared/SimpleDeterministicSerializer.js +1 -1
  210. package/lib/esm/shared/SimpleDeterministicSerializer.js.map +1 -0
  211. package/lib/esm/shared/constants.js +1 -1
  212. package/lib/esm/shared/constants.js.map +1 -0
  213. package/lib/esm/shared/crypto.js +1 -1
  214. package/lib/esm/shared/crypto.js.map +1 -0
  215. package/lib/esm/shared/decorators.d.ts +1 -1
  216. package/lib/esm/shared/decorators.js +2 -2
  217. package/lib/esm/shared/decorators.js.map +1 -0
  218. package/lib/esm/shared/erc20/erc20-constants.js +1 -1
  219. package/lib/esm/shared/erc20/erc20-constants.js.map +1 -0
  220. package/lib/esm/shared/errors.js +1 -1
  221. package/lib/esm/shared/errors.js.map +1 -0
  222. package/lib/esm/shared/events.js +1 -1
  223. package/lib/esm/shared/events.js.map +1 -0
  224. package/lib/esm/shared/fabric-types.d.ts +0 -1
  225. package/lib/esm/shared/fabric-types.js +2 -2
  226. package/lib/esm/shared/fabric-types.js.map +1 -0
  227. package/lib/esm/shared/index.js +1 -1
  228. package/lib/esm/shared/index.js.map +1 -0
  229. package/lib/esm/shared/interfaces/Checkable.js +1 -1
  230. package/lib/esm/shared/interfaces/Checkable.js.map +1 -0
  231. package/lib/esm/shared/math.js +1 -1
  232. package/lib/esm/shared/math.js.map +1 -0
  233. package/lib/esm/shared/model/FabricBaseModel.js +1 -1
  234. package/lib/esm/shared/model/FabricBaseModel.js.map +1 -0
  235. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js +1 -1
  236. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  237. package/lib/esm/shared/model/Identity.js +1 -1
  238. package/lib/esm/shared/model/Identity.js.map +1 -0
  239. package/lib/esm/shared/model/IdentityCredentials.js +1 -1
  240. package/lib/esm/shared/model/IdentityCredentials.js.map +1 -0
  241. package/lib/esm/shared/model/index.js +1 -1
  242. package/lib/esm/shared/model/index.js.map +1 -0
  243. package/lib/esm/shared/overrides/Model.js +1 -1
  244. package/lib/esm/shared/overrides/Model.js.map +1 -0
  245. package/lib/esm/shared/overrides/index.js +1 -1
  246. package/lib/esm/shared/overrides/index.js.map +1 -0
  247. package/lib/esm/shared/overrides/overrides.js +1 -1
  248. package/lib/esm/shared/overrides/overrides.js.map +1 -0
  249. package/lib/esm/shared/types.js +1 -1
  250. package/lib/esm/shared/types.js.map +1 -0
  251. package/lib/esm/shared/utils.js +1 -1
  252. package/lib/esm/shared/utils.js.map +1 -0
  253. package/lib/esm/version.d.ts +1 -1
  254. package/lib/esm/version.js +2 -2
  255. package/lib/esm/version.js.map +1 -0
  256. package/lib/index.cjs +1 -1
  257. package/lib/index.js.map +1 -0
  258. package/lib/shared/ClientSerializer.cjs +1 -1
  259. package/lib/shared/ClientSerializer.js.map +1 -0
  260. package/lib/shared/DeterministicSerializer.cjs +1 -1
  261. package/lib/shared/DeterministicSerializer.js.map +1 -0
  262. package/lib/shared/SimpleDeterministicSerializer.cjs +1 -1
  263. package/lib/shared/SimpleDeterministicSerializer.js.map +1 -0
  264. package/lib/shared/constants.cjs +1 -1
  265. package/lib/shared/constants.js.map +1 -0
  266. package/lib/shared/crypto.cjs +1 -1
  267. package/lib/shared/crypto.js.map +1 -0
  268. package/lib/shared/decorators.cjs +3 -3
  269. package/lib/shared/decorators.d.ts +1 -1
  270. package/lib/shared/decorators.js.map +1 -0
  271. package/lib/shared/erc20/erc20-constants.cjs +1 -1
  272. package/lib/shared/erc20/erc20-constants.js.map +1 -0
  273. package/lib/shared/errors.cjs +1 -1
  274. package/lib/shared/errors.js.map +1 -0
  275. package/lib/shared/events.cjs +1 -1
  276. package/lib/shared/events.js.map +1 -0
  277. package/lib/shared/fabric-types.cjs +1 -2
  278. package/lib/shared/fabric-types.d.ts +0 -1
  279. package/lib/shared/fabric-types.js.map +1 -0
  280. package/lib/shared/index.cjs +1 -1
  281. package/lib/shared/index.js.map +1 -0
  282. package/lib/shared/interfaces/Checkable.cjs +1 -1
  283. package/lib/shared/interfaces/Checkable.js.map +1 -0
  284. package/lib/shared/math.cjs +1 -1
  285. package/lib/shared/math.js.map +1 -0
  286. package/lib/shared/model/FabricBaseModel.cjs +1 -1
  287. package/lib/shared/model/FabricBaseModel.js.map +1 -0
  288. package/lib/shared/model/FabricIdentifiedBaseModel.cjs +1 -1
  289. package/lib/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  290. package/lib/shared/model/Identity.cjs +1 -1
  291. package/lib/shared/model/Identity.js.map +1 -0
  292. package/lib/shared/model/IdentityCredentials.cjs +1 -1
  293. package/lib/shared/model/IdentityCredentials.js.map +1 -0
  294. package/lib/shared/model/index.cjs +1 -1
  295. package/lib/shared/model/index.js.map +1 -0
  296. package/lib/shared/overrides/Model.cjs +1 -1
  297. package/lib/shared/overrides/Model.js.map +1 -0
  298. package/lib/shared/overrides/index.cjs +1 -1
  299. package/lib/shared/overrides/index.js.map +1 -0
  300. package/lib/shared/overrides/overrides.cjs +1 -1
  301. package/lib/shared/overrides/overrides.js.map +1 -0
  302. package/lib/shared/types.cjs +1 -1
  303. package/lib/shared/types.js.map +1 -0
  304. package/lib/shared/utils.cjs +1 -1
  305. package/lib/shared/utils.js.map +1 -0
  306. package/lib/version.cjs +2 -2
  307. package/lib/version.d.ts +1 -1
  308. package/lib/version.js.map +1 -0
  309. package/package.json +1 -1
@@ -1,1831 +1,2 @@
1
- import { CouchDBStatement, CouchDBKeys, CouchDBGroupOperator, CouchDBOperator, CouchDBAdapter } from "@decaf-ts/for-couchdb";
2
-
3
- import { Model, JSONSerializer, required, type, list, stringFormat, model } from "@decaf-ts/decorator-validation";
4
-
5
- import { Context, ObserverHandler, Adapter, Repository, Condition, repositoryFromTypeMetadata, cacheModelForPopulate, Cascade, createOrUpdate, getPopulateKey, UnsupportedError, QueryError, PagingError, MigrationError, ObserverError, AuthorizationError, ForbiddenError, ConnectionError, PersistenceKeys, relation, oneToManyOnUpdate, OrderDirection, BaseModel, pk, column, table } from "@decaf-ts/core";
6
-
7
- import { OperationKeys, BulkCrudOperationKeys, DBKeys, InternalError, SerializationError, NotFoundError, ConflictError, BadRequestError, onCreate, onCreateUpdate, readonly, onUpdate, onDelete, afterAny, BaseError, ValidationError, transient, onRead } from "@decaf-ts/db-decorators";
8
-
9
- import { Property, Object as Object$1, Contract, Context as Context$1, Transaction } from "fabric-contract-api";
10
-
11
- import { Metadata, Decoration, propMetadata, apply, prop, metadata } from "@decaf-ts/decoration";
12
-
13
- import { MiniLogger, NumericLogLevels, LogLevel, Logging } from "@decaf-ts/logging";
14
-
15
- import { __decorate, __metadata } from "tslib";
16
-
17
- class FabricContractContext extends Context {
18
- constructor() {
19
- super();
20
- }
21
- get stub() {
22
- return this.get("stub");
23
- }
24
- get timestamp() {
25
- return this.stub.getDateTimestamp();
26
- }
27
- get identity() {
28
- return this.get("identity");
29
- }
30
- toString() {
31
- return `fabric ctx${this.stub ? " with stub" : "without stub"}`;
32
- }
33
- }
34
-
35
- function generateFabricEventName(table, event, owner) {
36
- const params = [ table, event ];
37
- if (owner) params.push(owner);
38
- return params.join("_");
39
- }
40
-
41
- function parseEventName(name) {
42
- const parts = name.split("_");
43
- if (parts.length < 2 || parts.length > 3) return {
44
- table: undefined,
45
- event: name,
46
- owner: undefined
47
- };
48
- return {
49
- table: parts[0],
50
- event: parts[1],
51
- owner: parts[2]
52
- };
53
- }
54
-
55
- class FabricContractRepositoryObservableHandler extends ObserverHandler {
56
- constructor(supportedEvents = [ OperationKeys.CREATE, OperationKeys.UPDATE, OperationKeys.DELETE, BulkCrudOperationKeys.CREATE_ALL, BulkCrudOperationKeys.UPDATE_ALL, BulkCrudOperationKeys.DELETE_ALL ]) {
57
- super();
58
- this.supportedEvents = supportedEvents;
59
- }
60
- async updateObservers(clazz, event, id, ...args) {
61
- const {log: log, ctx: ctx} = Adapter.logCtx(args, this.updateObservers);
62
- const {stub: stub} = ctx;
63
- const [owner, payload] = args;
64
- const table = typeof clazz === "string" ? clazz : clazz.name;
65
- if (this.supportedEvents.indexOf(event) !== -1) {
66
- log.debug(`Emitting ${event} event`);
67
- const eventName = generateFabricEventName(table, event, owner);
68
- stub.setEvent(eventName, Buffer.from(JSON.stringify({
69
- id: id
70
- })));
71
- } else {
72
- stub.setEvent(event, Buffer.from(JSON.stringify(payload)));
73
- }
74
- }
75
- }
76
-
77
- class FabricContractRepository extends Repository {
78
- constructor(adapter, clazz, trackedEvents) {
79
- super(adapter, clazz);
80
- this.trackedEvents = trackedEvents;
81
- }
82
- ObserverHandler() {
83
- return new FabricContractRepositoryObservableHandler;
84
- }
85
- async updateObservers(table, event, id, ...args) {
86
- if (!this.trackedEvents || this.trackedEvents.indexOf(event) !== -1) return await super.updateObservers(table, event, id, ...args);
87
- }
88
- }
89
-
90
- class FabricStatement extends CouchDBStatement {
91
- constructor(adapter) {
92
- super(adapter);
93
- }
94
- async raw(rawInput, ...args) {
95
- const {ctx: ctx} = this.logCtx(args, this.raw);
96
- const results = await this.adapter.raw(rawInput, true, ctx);
97
- const pkAttr = Model.pk(this.fromSelector);
98
- const type = Metadata.get(this.fromSelector, Metadata.key(DBKeys.ID, pkAttr))?.type;
99
- if (!this.selectSelector) return results.map(r => this.processRecord(r, pkAttr, type, ctx));
100
- return results;
101
- }
102
- build() {
103
- const selectors = {};
104
- selectors[CouchDBKeys.TABLE] = {};
105
- selectors[CouchDBKeys.TABLE] = Model.tableName(this.fromSelector);
106
- const query = {
107
- selector: selectors
108
- };
109
- if (this.selectSelector) query.fields = this.selectSelector;
110
- if (this.whereCondition) {
111
- const condition = this.parseCondition(Condition.and(this.whereCondition, Condition.attribute(CouchDBKeys.TABLE).eq(query.selector[CouchDBKeys.TABLE]))).selector;
112
- const selectorKeys = Object.keys(condition);
113
- if (selectorKeys.length === 1 && Object.values(CouchDBGroupOperator).indexOf(selectorKeys[0]) !== -1) switch (selectorKeys[0]) {
114
- case CouchDBGroupOperator.AND:
115
- condition[CouchDBGroupOperator.AND] = [ ...Object.values(condition[CouchDBGroupOperator.AND]).reduce((accum, val) => {
116
- const keys = Object.keys(val);
117
- if (keys.length !== 1) throw new Error("Too many keys in query selector. should be one");
118
- const k = keys[0];
119
- if (k === CouchDBGroupOperator.AND) accum.push(...val[k]); else accum.push(val);
120
- return accum;
121
- }, []) ];
122
- query.selector = condition;
123
- break;
124
-
125
- case CouchDBGroupOperator.OR:
126
- {
127
- const s = {};
128
- s[CouchDBGroupOperator.AND] = [ condition, ...Object.entries(query.selector).map(([key, val]) => {
129
- const result = {};
130
- result[key] = val;
131
- return result;
132
- }) ];
133
- query.selector = s;
134
- break;
135
- }
136
-
137
- default:
138
- throw new Error("This should be impossible");
139
- } else {
140
- Object.entries(condition).forEach(([key, val]) => {
141
- if (query.selector[key]) console.warn(`A ${key} query param is about to be overridden: ${query.selector[key]} by ${val}`);
142
- query.selector[key] = val;
143
- });
144
- }
145
- }
146
- if (this.orderBySelector) {
147
- query.sort = query.sort || [];
148
- query.selector = query.selector || {};
149
- const [selector, value] = this.orderBySelector;
150
- const rec = {};
151
- rec[selector] = value;
152
- query.sort.push(rec);
153
- if (!query.selector[selector]) {
154
- query.selector[selector] = {};
155
- query.selector[selector][CouchDBOperator.BIGGER] = null;
156
- }
157
- }
158
- if (this.limitSelector) query.limit = this.limitSelector;
159
- if (this.offsetSelector) query.skip = this.offsetSelector;
160
- return query;
161
- }
162
- }
163
-
164
- var FabricModelKeys;
165
-
166
- (function(FabricModelKeys) {
167
- FabricModelKeys["PRIVATE"] = "private";
168
- FabricModelKeys["SHARED"] = "shared";
169
- FabricModelKeys["FABRIC"] = "fabric.";
170
- FabricModelKeys["OWNEDBY"] = "owned-by";
171
- })(FabricModelKeys || (FabricModelKeys = {}));
172
-
173
- var IdentityType;
174
-
175
- (function(IdentityType) {
176
- IdentityType["X509"] = "X.509";
177
- })(IdentityType || (IdentityType = {}));
178
-
179
- const FabricFlavour = "hlf-fabric";
180
-
181
- class SimpleDeterministicSerializer extends JSONSerializer {
182
- constructor() {
183
- super();
184
- }
185
- deserialize(str, tableName) {
186
- const deserialization = JSON.parse(str);
187
- return deserialization;
188
- }
189
- serialize(model) {
190
- const stringify = require("json-stringify-deterministic");
191
- const sortKeysRecursive = require("sort-keys-recursive");
192
- return stringify(sortKeysRecursive(this.preSerialize(model)));
193
- }
194
- preSerialize(model) {
195
- const toSerialize = Object.assign({}, model);
196
- return toSerialize;
197
- }
198
- }
199
-
200
- async function oneToOneOnCreate(context, data, key, model) {
201
- const propertyValue = model[key];
202
- if (!propertyValue) return;
203
- if (typeof propertyValue !== "object") {
204
- const innerRepo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
205
- const read = await innerRepo.read(propertyValue, context);
206
- await cacheModelForPopulate(context, model, key, propertyValue, read);
207
- model[key] = propertyValue;
208
- return;
209
- }
210
- data.class = typeof data.class === "string" ? data.class : data.class().name;
211
- const constructor = Model.get(data.class);
212
- if (!constructor) throw new InternalError(`Could not find model ${data.class}`);
213
- const repo = Repository.forModel(constructor, this.adapter.alias);
214
- const created = await repo.create(propertyValue, context);
215
- const pk = Model.pk(created);
216
- await cacheModelForPopulate(context, model, key, created[pk], created);
217
- model[key] = created[pk];
218
- }
219
-
220
- async function oneToOneOnUpdate(context, data, key, model) {
221
- const propertyValue = model[key];
222
- if (!propertyValue) return;
223
- if (data.cascade.update !== Cascade.CASCADE) return;
224
- if (typeof propertyValue !== "object") {
225
- const innerRepo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
226
- const read = await innerRepo.read(propertyValue, context);
227
- await cacheModelForPopulate(context, model, key, propertyValue, read);
228
- model[key] = propertyValue;
229
- return;
230
- }
231
- const updated = await createOrUpdate(model[key], context, this.adapter.alias);
232
- const pk = Model.pk(updated);
233
- await cacheModelForPopulate(context, model, key, updated[pk], updated);
234
- model[key] = updated[pk];
235
- }
236
-
237
- async function oneToOneOnDelete(context, data, key, model) {
238
- const propertyValue = model[key];
239
- if (!propertyValue) return;
240
- if (data.cascade.update !== Cascade.CASCADE) return;
241
- const innerRepo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
242
- let deleted;
243
- if (!(propertyValue instanceof Model)) deleted = await innerRepo.delete(model[key], context); else deleted = await innerRepo.delete(model[key][Model.pk(innerRepo.class)], context);
244
- await cacheModelForPopulate(context, model, key, deleted[Model.pk(innerRepo.class)], deleted);
245
- }
246
-
247
- async function oneToManyOnCreate(context, data, key, model) {
248
- const propertyValues = model[key];
249
- if (!propertyValues || !propertyValues.length) return;
250
- const arrayType = typeof propertyValues[0];
251
- if (!propertyValues.every(item => typeof item === arrayType)) throw new InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
252
- const uniqueValues = new Set([ ...propertyValues ]);
253
- if (arrayType !== "object") {
254
- const repo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
255
- for (const id of uniqueValues) {
256
- const read = await repo.read(id, context);
257
- await cacheModelForPopulate(context, model, key, id, read);
258
- }
259
- model[key] = [ ...uniqueValues ];
260
- return;
261
- }
262
- const pkName = Model.pk(propertyValues[0]);
263
- const result = new Set;
264
- for (const m of propertyValues) {
265
- const record = await createOrUpdate(m, context, this.adapter.alias);
266
- await cacheModelForPopulate(context, model, key, record[pkName], record);
267
- result.add(record[pkName]);
268
- }
269
- model[key] = [ ...result ];
270
- }
271
-
272
- async function oneToManyOnDelete(context, data, key, model) {
273
- if (data.cascade.delete !== Cascade.CASCADE) return;
274
- const values = model[key];
275
- if (!values || !values.length) return;
276
- const arrayType = typeof values[0];
277
- const areAllSameType = values.every(item => typeof item === arrayType);
278
- if (!areAllSameType) throw new InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
279
- const isInstantiated = arrayType === "object";
280
- const repo = isInstantiated ? Repository.forModel(values[0], this.adapter.alias) : repositoryFromTypeMetadata(model, key, this.adapter.alias);
281
- const uniqueValues = new Set([ ...isInstantiated ? values.map(v => v[Model.pk(this.class)]) : values ]);
282
- for (const id of uniqueValues.values()) {
283
- const deleted = await repo.delete(id, context);
284
- await cacheModelForPopulate(context, model, key, id, deleted);
285
- }
286
- model[key] = [ ...uniqueValues ];
287
- }
288
-
289
- async function populate(context, data, key, model) {
290
- if (!data.populate) return;
291
- const nested = model[key];
292
- const isArr = Array.isArray(nested);
293
- if (typeof nested === "undefined" || isArr && nested.length === 0) return;
294
- async function fetchPopulateValues(c, model, propName, propKeyValues, alias) {
295
- let cacheKey;
296
- let val;
297
- const results = [];
298
- for (const proKeyValue of propKeyValues) {
299
- cacheKey = getPopulateKey(model.constructor.name, propName, proKeyValue);
300
- try {
301
- val = await c.get(cacheKey);
302
- } catch (e) {
303
- const repo = repositoryFromTypeMetadata(model, propName, alias);
304
- if (!repo) throw new InternalError("Could not find repo");
305
- val = await repo.read(proKeyValue, context);
306
- }
307
- results.push(val);
308
- }
309
- return results;
310
- }
311
- const res = await fetchPopulateValues(context, model, key, isArr ? nested : [ nested ], this.adapter.alias);
312
- model[key] = isArr ? res : res[0];
313
- }
314
-
315
- class ContractLogger extends MiniLogger {
316
- constructor(context, conf, ctx) {
317
- super(context, conf);
318
- if (!ctx) {
319
- this.logger = new MiniLogger(context, conf);
320
- } else {
321
- this.logger = ctx.logging.getLogger(context);
322
- }
323
- }
324
- log(level, msg, stack) {
325
- if (NumericLogLevels[this.config("level")] < NumericLogLevels[level]) return;
326
- let method;
327
- switch (level) {
328
- case LogLevel.info:
329
- method = this.logger.info;
330
- break;
331
-
332
- case LogLevel.verbose:
333
- method = this.logger.verbose;
334
- break;
335
-
336
- case LogLevel.debug:
337
- method = this.logger.debug;
338
- break;
339
-
340
- case LogLevel.error:
341
- method = this.logger.error;
342
- break;
343
-
344
- case LogLevel.silly:
345
- method = this.logger.silly;
346
- break;
347
-
348
- default:
349
- throw new InternalError("Invalid log level");
350
- }
351
- method.call(this.logger, this.createLog(level, msg, stack));
352
- }
353
- }
354
-
355
- const factory = (object, config, ctx) => new ContractLogger(object || ContractLogger.name, config || {}, ctx);
356
-
357
- Logging.setFactory(factory);
358
-
359
- async function createdByOnFabricCreateUpdate(context, data, key, model) {
360
- try {
361
- const user = context.get("identity");
362
- model[key] = user.getID();
363
- } catch (e) {
364
- throw new UnsupportedError("No User found in context. Please provide a user in the context");
365
- }
366
- }
367
-
368
- async function pkFabricOnCreate(context, data, key, model) {
369
- if (!data.type || model[key]) {
370
- return;
371
- }
372
- const setPrimaryKeyValue = function(target, propertyKey, value) {
373
- Object.defineProperty(target, propertyKey, {
374
- enumerable: true,
375
- writable: false,
376
- configurable: true,
377
- value: value
378
- });
379
- };
380
- if (!data.name) data.name = Model.sequenceName(model, "pk");
381
- let sequence;
382
- try {
383
- sequence = await this.adapter.Sequence(data);
384
- } catch (e) {
385
- throw new InternalError(`Failed to instantiate Sequence ${data.name}: ${e}`);
386
- }
387
- const next = await sequence.next(context);
388
- setPrimaryKeyValue(model, key, next);
389
- }
390
-
391
- class FabricContractAdapter extends CouchDBAdapter {
392
- getClient() {
393
- throw new UnsupportedError("Client is not supported in Fabric contracts");
394
- }
395
- static {
396
- this.textDecoder = new TextDecoder("utf8");
397
- }
398
- static {
399
- this.serializer = new SimpleDeterministicSerializer;
400
- }
401
- repository() {
402
- return FabricContractRepository;
403
- }
404
- constructor(scope, alias) {
405
- super(scope, FabricFlavour, alias);
406
- this.Context = FabricContractContext;
407
- }
408
- for(config, ...args) {
409
- return super.for(config, ...args);
410
- }
411
- async create(clazz, id, model, ...args) {
412
- const {ctx: ctx, log: log, stub: stub} = this.logCtx(args, this.create);
413
- log.info(`in ADAPTER create with args ${args}`);
414
- const tableName = Model.tableName(clazz);
415
- try {
416
- log.info(`adding entry to ${tableName} table with pk ${id}`);
417
- const composedKey = stub.createCompositeKey(tableName, [ String(id) ]);
418
- model = await this.putState(composedKey, model, ctx);
419
- } catch (e) {
420
- throw this.parseError(e);
421
- }
422
- return model;
423
- }
424
- async read(clazz, id, ...args) {
425
- const {ctx: ctx, log: log, stub: stub} = this.logCtx(args, this.read);
426
- log.info(`in ADAPTER read with args ${args}`);
427
- const tableName = Model.tableName(clazz);
428
- let model;
429
- try {
430
- const composedKey = stub.createCompositeKey(tableName, [ String(id) ]);
431
- model = await this.readState(composedKey, ctx);
432
- } catch (e) {
433
- throw this.parseError(e);
434
- }
435
- return model;
436
- }
437
- async update(clazz, id, model, ...args) {
438
- const {ctx: ctx, log: log, stub: stub} = this.logCtx(args, this.update);
439
- const tableName = Model.tableName(clazz);
440
- try {
441
- log.verbose(`updating entry to ${tableName} table with pk ${id}`);
442
- const composedKey = stub.createCompositeKey(tableName, [ String(id) ]);
443
- model = await this.putState(composedKey, model, ctx);
444
- } catch (e) {
445
- throw this.parseError(e);
446
- }
447
- return model;
448
- }
449
- async delete(clazz, id, ...args) {
450
- const {ctx: ctx, log: log, ctxArgs: ctxArgs, stub: stub} = this.logCtx(args, this.delete);
451
- const tableName = Model.tableName(clazz);
452
- let model;
453
- try {
454
- const composedKey = stub.createCompositeKey(tableName, [ String(id) ]);
455
- model = await this.read(clazz, id, ...ctxArgs);
456
- log.verbose(`deleting entry with pk ${id} from ${tableName} table`);
457
- await this.deleteState(composedKey, ctx);
458
- } catch (e) {
459
- throw this.parseError(e);
460
- }
461
- return model;
462
- }
463
- async deleteState(id, ctx) {
464
- const {stub: stub} = this.logCtx([ ctx ], this.deleteState);
465
- await stub.deleteState(id);
466
- }
467
- forPrivate(collection) {
468
- const toOverride = [ this.putState, this.readState, this.deleteState, this.queryResult, this.queryResultPaginated ].map(fn => fn.name);
469
- return new Proxy(this, {
470
- get(target, prop, receiver) {
471
- if (!toOverride.includes(prop)) return Reflect.get(target, prop, receiver);
472
- return new Proxy(target[prop], {
473
- async apply(fn, thisArg, argsList) {
474
- switch (prop) {
475
- case "putState":
476
- {
477
- const [stub, id, model] = argsList;
478
- await stub.putPrivateData(collection, id.toString(), model);
479
- return model;
480
- }
481
-
482
- case "deleteState":
483
- {
484
- const [stub, id] = argsList;
485
- return stub.deletePrivateData(collection, id);
486
- }
487
-
488
- case "readState":
489
- {
490
- const [stub, id] = argsList;
491
- return stub.getPrivateData(collection, id);
492
- }
493
-
494
- case "queryResult":
495
- {
496
- const [stub, rawInput] = argsList;
497
- return stub.getPrivateDataQueryResult(collection, rawInput);
498
- }
499
-
500
- case "queryResultPaginated":
501
- {
502
- const [stub, rawInput, limit, skip] = argsList;
503
- const iterator = await stub.getPrivateDataQueryResult(collection, rawInput);
504
- const results = [];
505
- let count = 0;
506
- let reachedBookmark = skip ? false : true;
507
- let lastKey = null;
508
- while (true) {
509
- const res = await iterator.next();
510
- if (res.value && res.value.value.toString()) {
511
- const recordKey = res.value.key;
512
- const recordValue = res.value.value.toString("utf8");
513
- if (!reachedBookmark) {
514
- if (recordKey === skip?.toString()) {
515
- reachedBookmark = true;
516
- }
517
- continue;
518
- }
519
- results.push({
520
- Key: recordKey,
521
- Record: JSON.parse(recordValue)
522
- });
523
- lastKey = recordKey;
524
- count++;
525
- if (count >= limit) {
526
- await iterator.close();
527
- return {
528
- iterator: results,
529
- metadata: {
530
- fetchedRecordsCount: results.length,
531
- bookmark: lastKey
532
- }
533
- };
534
- }
535
- }
536
- if (res.done) {
537
- await iterator.close();
538
- return {
539
- iterator: results,
540
- metadata: {
541
- fetchedRecordsCount: results.length,
542
- bookmark: ""
543
- }
544
- };
545
- }
546
- }
547
- }
548
-
549
- default:
550
- throw new InternalError(`Unsupported method override ${String(prop)}`);
551
- }
552
- }
553
- });
554
- }
555
- });
556
- }
557
- async putState(id, model, ctx) {
558
- let data;
559
- const {stub: stub, log: log} = this.logCtx([ ctx ], this.putState);
560
- try {
561
- data = Buffer.from(FabricContractAdapter.serializer.serialize(model));
562
- } catch (e) {
563
- throw new SerializationError(`Failed to serialize record with id ${id}: ${e}`);
564
- }
565
- const collection = ctx.get("segregated");
566
- if (collection) await stub.putPrivateData(collection, id.toString(), data); else await stub.putState(id.toString(), data);
567
- log.silly(`state stored${collection ? ` in ${collection} collection` : ""} under id ${id}`);
568
- return model;
569
- }
570
- async readState(id, ctx) {
571
- let result;
572
- const {stub: stub, log: log} = this.logCtx([ ctx ], this.readState);
573
- let res;
574
- const collection = ctx.get("segregated");
575
- if (collection) res = (await stub.getPrivateData(collection, id.toString())).toString(); else res = (await stub.getState(id.toString())).toString();
576
- if (!res) throw new NotFoundError(`Record with id ${id}${collection ? ` in ${collection} collection` : ""} not found`);
577
- log.silly(`state retrieved from${collection ? ` ${collection} collection` : ""} under id ${id}`);
578
- try {
579
- result = FabricContractAdapter.serializer.deserialize(res.toString());
580
- } catch (e) {
581
- throw new SerializationError(`Failed to parse record: ${e}`);
582
- }
583
- return result;
584
- }
585
- async queryResult(stub, rawInput, ...args) {
586
- const {ctx: ctx} = this.logCtx(args, this.readState);
587
- let res;
588
- const collection = ctx.get("segregated");
589
- if (collection) res = await stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput)); else res = await stub.getQueryResult(JSON.stringify(rawInput));
590
- return res;
591
- }
592
- async queryResultPaginated(stub, rawInput, limit = 250, skip, ...args) {
593
- const {ctx: ctx} = this.logCtx(args, this.readState);
594
- let res;
595
- const collection = ctx.get("segregated");
596
- if (collection) {
597
- rawInput.selector = {
598
- ...rawInput.selector,
599
- _id: skip ? {
600
- $gt: skip.toString()
601
- } : {
602
- $gte: ""
603
- }
604
- };
605
- const it = await stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput));
606
- res = {
607
- iterator: it,
608
- metadata: {
609
- fetchedRecordsCount: limit,
610
- bookmark: ""
611
- }
612
- };
613
- } else res = await stub.getQueryResultWithPagination(JSON.stringify(rawInput), limit, skip?.toString());
614
- return res;
615
- }
616
- mergeModels(results) {
617
- const extract = model => Object.entries(model).reduce((accum, [key, val]) => {
618
- if (typeof val !== "undefined") accum[key] = val;
619
- return accum;
620
- }, {});
621
- let finalModel = results.pop();
622
- for (const res of results) {
623
- finalModel = Object.assign({}, extract(finalModel), extract(res));
624
- }
625
- return finalModel;
626
- }
627
- decode(buffer) {
628
- return FabricContractAdapter.textDecoder.decode(buffer);
629
- }
630
- async flags(operation, model, flags, ctx, ...args) {
631
- const baseFlags = {
632
- stub: ctx.stub,
633
- segregated: false
634
- };
635
- if (ctx instanceof FabricContractContext) {
636
- Object.assign(baseFlags, {
637
- logger: ctx.logger,
638
- identity: ctx.identity,
639
- correlationId: ctx.stub.getTxID()
640
- });
641
- } else {
642
- Object.assign(baseFlags, {
643
- identity: ctx.clientIdentity,
644
- logger: new ContractLogger(this, undefined, ctx),
645
- correlationId: ctx.stub.getTxID()
646
- });
647
- }
648
- flags = await super.flags(operation, model, baseFlags, ...args);
649
- return flags;
650
- }
651
- index(models) {
652
- return Promise.resolve(undefined);
653
- }
654
- async resultIterator(log, iterator, isHistory = false) {
655
- const allResults = [];
656
- let res = await iterator.next();
657
- while (!res.done) {
658
- if (res.value && res.value.value.toString()) {
659
- let jsonRes = {};
660
- log.debug(res.value.value.toString("utf8"));
661
- if (isHistory) {
662
- jsonRes.TxId = res.value.txId;
663
- jsonRes.Timestamp = res.value.timestamp;
664
- try {
665
- jsonRes.Value = JSON.parse(res.value.value.toString("utf8"));
666
- } catch (err) {
667
- log.error(err);
668
- jsonRes.Value = res.value.value.toString("utf8");
669
- }
670
- } else {
671
- try {
672
- jsonRes = JSON.parse(res.value.value.toString("utf8"));
673
- } catch (err) {
674
- log.error(err);
675
- jsonRes = res.value.value.toString("utf8");
676
- }
677
- }
678
- allResults.push(jsonRes);
679
- }
680
- res = await iterator.next();
681
- }
682
- log.debug(`Closing iterator after ${allResults.length} results`);
683
- iterator.close();
684
- return allResults;
685
- }
686
- async raw(rawInput, docsOnly = true, ...args) {
687
- const {log: log, stub: stub} = this.logCtx(args, this.raw);
688
- const {skip: skip, limit: limit} = rawInput;
689
- let iterator;
690
- if (limit || skip) {
691
- delete rawInput["limit"];
692
- delete rawInput["skip"];
693
- log.debug(`Retrieving paginated iterator: limit: ${limit}/ skip: ${skip}`);
694
- const response = await this.queryResultPaginated(stub, rawInput, limit || 250, skip?.toString());
695
- iterator = response.iterator;
696
- } else {
697
- log.debug("Retrieving iterator");
698
- iterator = await this.queryResult(stub, rawInput);
699
- }
700
- log.debug("Iterator acquired");
701
- const results = await this.resultIterator(log, iterator);
702
- log.debug(`returning ${Array.isArray(results) ? results.length : 1} results`);
703
- return results;
704
- }
705
- Statement() {
706
- return new FabricStatement(this);
707
- }
708
- async createAll(tableName, id, model, ...args) {
709
- if (id.length !== model.length) throw new InternalError("Ids and models must have the same length");
710
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.createAll);
711
- const tableLabel = Model.tableName(tableName);
712
- log.debug(`Creating ${id.length} entries ${tableLabel} table`);
713
- return Promise.all(id.map((i, count) => this.create(tableName, i, model[count], ...ctxArgs)));
714
- }
715
- async updateAll(tableName, id, model, ...args) {
716
- if (id.length !== model.length) throw new InternalError("Ids and models must have the same length");
717
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateAll);
718
- const tableLabel = Model.tableName(tableName);
719
- log.debug(`Updating ${id.length} entries ${tableLabel} table`);
720
- return Promise.all(id.map((i, count) => this.update(tableName, i, model[count], ...ctxArgs)));
721
- }
722
- prepare(model, ...args) {
723
- const {log: log} = this.logCtx(args, this.prepare);
724
- const tableName = Model.tableName(model.constructor);
725
- const pk = Model.pk(model.constructor);
726
- const split = Model.segregate(model);
727
- const result = Object.entries(split.model).reduce((accum, [key, val]) => {
728
- if (typeof val === "undefined") return accum;
729
- const mappedProp = Model.columnName(model, key);
730
- if (this.isReserved(mappedProp)) throw new InternalError(`Property name ${mappedProp} is reserved`);
731
- accum[mappedProp] = val;
732
- return accum;
733
- }, {});
734
- log.silly(`Preparing record for ${tableName} table with pk ${model[pk]}`);
735
- return {
736
- record: result,
737
- id: model[pk],
738
- transient: split.transient
739
- };
740
- }
741
- revert(obj, clazz, id, transient, ...args) {
742
- const {log: log} = this.logCtx(args, this.revert);
743
- const ob = {};
744
- const pk = Model.pk(clazz);
745
- ob[pk] = id;
746
- const m = typeof clazz === "string" ? Model.build(ob, clazz) : new clazz(ob);
747
- log.silly(`Rebuilding model ${m.constructor.name} id ${id}`);
748
- const result = Object.keys(m).reduce((accum, key) => {
749
- accum[key] = obj[Model.columnName(accum, key)];
750
- return accum;
751
- }, m);
752
- if (transient) {
753
- log.debug(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
754
- Object.entries(transient).forEach(([key, val]) => {
755
- if (key in result && result[key] !== undefined) throw new InternalError(`Transient property ${key} already exists on model ${m.constructor.name}. should be impossible`);
756
- result[key] = val;
757
- });
758
- }
759
- return result;
760
- }
761
- createPrefix(tableName, id, model, ...args) {
762
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.createPrefix);
763
- const record = {};
764
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
765
- Object.assign(record, model);
766
- return [ tableName, id, record, ...ctxArgs ];
767
- }
768
- updatePrefix(tableName, id, model, ...args) {
769
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.updatePrefix);
770
- const record = {};
771
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
772
- Object.assign(record, model);
773
- return [ tableName, id, record, ...ctxArgs ];
774
- }
775
- createAllPrefix(tableName, ids, models, ...args) {
776
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
777
- const ctx = args.pop();
778
- const records = ids.map((id, count) => {
779
- const record = {};
780
- record[CouchDBKeys.TABLE] = tableName;
781
- Object.assign(record, models[count]);
782
- return record;
783
- });
784
- return [ tableName, ids, records, ctx ];
785
- }
786
- updateAllPrefix(tableName, ids, models, ...args) {
787
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
788
- const ctx = args.pop();
789
- const records = ids.map((id, count) => {
790
- const record = {};
791
- record[CouchDBKeys.TABLE] = tableName;
792
- Object.assign(record, models[count]);
793
- return record;
794
- });
795
- return [ tableName, ids, records, ctx ];
796
- }
797
- parseError(err, reason) {
798
- return FabricContractAdapter.parseError(reason || err);
799
- }
800
- logCtx(args, method) {
801
- return FabricContractAdapter.logCtx.call(this, args, method);
802
- }
803
- static logCtx(args, method) {
804
- if (args.length < 1) throw new InternalError("No context provided");
805
- const ctx = args.pop();
806
- if (!(ctx instanceof Context)) throw new InternalError("No context provided");
807
- if (args.filter(a => a instanceof Context).length > 1) throw new Error("here");
808
- const log = this ? ctx.logger.for(this).for(method) : ctx.logger.clear().for(this).for(method);
809
- return {
810
- ctx: ctx,
811
- log: method ? log.for(method) : log,
812
- stub: ctx.stub,
813
- identity: ctx.identity,
814
- ctxArgs: [ ...args, ctx ]
815
- };
816
- }
817
- static parseError(err) {
818
- const msg = typeof err === "string" ? err : err.message;
819
- if (msg.includes(NotFoundError.name)) return new NotFoundError(err);
820
- if (msg.includes(ConflictError.name)) return new ConflictError(err);
821
- if (msg.includes(BadRequestError.name)) return new BadRequestError(err);
822
- if (msg.includes(QueryError.name)) return new QueryError(err);
823
- if (msg.includes(PagingError.name)) return new PagingError(err);
824
- if (msg.includes(UnsupportedError.name)) return new UnsupportedError(err);
825
- if (msg.includes(MigrationError.name)) return new MigrationError(err);
826
- if (msg.includes(ObserverError.name)) return new ObserverError(err);
827
- if (msg.includes(AuthorizationError.name)) return new AuthorizationError(err);
828
- if (msg.includes(ForbiddenError.name)) return new ForbiddenError(err);
829
- if (msg.includes(ConnectionError.name)) return new ConnectionError(err);
830
- if (msg.includes(SerializationError.name)) return new SerializationError(err);
831
- return new InternalError(err);
832
- }
833
- static decoration() {
834
- super.decoration();
835
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.CREATED_BY).define(onCreate(createdByOnFabricCreateUpdate), propMetadata(PersistenceKeys.CREATED_BY, {})).apply();
836
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.UPDATED_BY).define(onCreateUpdate(createdByOnFabricCreateUpdate), propMetadata(PersistenceKeys.UPDATED_BY, {})).apply();
837
- Decoration.flavouredAs(FabricFlavour).for(DBKeys.ID).define({
838
- decorator: function pkDec(options, groupsort) {
839
- return function pkDec(obj, attr) {
840
- return apply(required(), readonly(), propMetadata(Metadata.key(DBKeys.ID, attr), options), onCreate(pkFabricOnCreate, options, groupsort))(obj, attr);
841
- };
842
- }
843
- }).apply();
844
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.COLUMN).extend(Property()).apply();
845
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.TABLE).extend(function table(obj) {
846
- return Object$1()(obj);
847
- }).apply();
848
- function oneToOneDec(clazz, cascade, populate$1, joinColumnOpts, fk) {
849
- const meta = {
850
- class: clazz,
851
- cascade: cascade,
852
- populate: populate$1
853
- };
854
- if (joinColumnOpts) meta.joinTable = joinColumnOpts;
855
- if (fk) meta.name = fk;
856
- return apply(prop(), relation(PersistenceKeys.ONE_TO_ONE, meta), type([ clazz, String, Number, BigInt ]), onCreate(oneToOneOnCreate, meta), onUpdate(oneToOneOnUpdate, meta), onDelete(oneToOneOnDelete, meta), afterAny(populate, meta), propMetadata(PersistenceKeys.ONE_TO_ONE, meta));
857
- }
858
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.ONE_TO_ONE).define({
859
- decorator: oneToOneDec
860
- }).apply();
861
- function oneToManyDec(clazz, cascade, populate$1, joinTableOpts, fk) {
862
- const metadata = {
863
- class: clazz,
864
- cascade: cascade,
865
- populate: populate$1
866
- };
867
- if (joinTableOpts) metadata.joinTable = joinTableOpts;
868
- if (fk) metadata.name = fk;
869
- return apply(prop(), relation(PersistenceKeys.ONE_TO_MANY, metadata), list([ clazz, String, Number ]), onCreate(oneToManyOnCreate, metadata), onUpdate(oneToManyOnUpdate, metadata), onDelete(oneToManyOnDelete, metadata), afterAny(populate, metadata), propMetadata(PersistenceKeys.ONE_TO_MANY, metadata));
870
- }
871
- Decoration.for(PersistenceKeys.ONE_TO_MANY).define({
872
- decorator: oneToManyDec
873
- }).apply();
874
- }
875
- }
876
-
877
- FabricContractAdapter.decoration();
878
-
879
- Adapter.setCurrent(FabricFlavour);
880
-
881
- class DeterministicSerializer extends JSONSerializer {
882
- constructor() {
883
- super();
884
- }
885
- deserialize(str) {
886
- return super.deserialize(str);
887
- }
888
- serialize(model) {
889
- const stringify = require("json-stringify-deterministic");
890
- const sortKeysRecursive = require("sort-keys-recursive");
891
- return stringify(sortKeysRecursive(this.preSerialize(model)));
892
- }
893
- }
894
-
895
- class FabricCrudContract extends Contract {
896
- static {
897
- this.adapter = new FabricContractAdapter;
898
- }
899
- static {
900
- this.serializer = new DeterministicSerializer;
901
- }
902
- constructor(name, clazz) {
903
- super(name);
904
- this.clazz = clazz;
905
- this.initialized = false;
906
- this.repo = Repository.forModel(clazz);
907
- }
908
- async listBy(ctx, key, order, ...args) {
909
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.listBy);
910
- return this.repo.listBy(key, order, ...ctxArgs);
911
- }
912
- async paginateBy(ctx, key, order, size, ...args) {
913
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.paginateBy);
914
- return this.repo.paginateBy(key, order, size, ...ctxArgs);
915
- }
916
- async findOneBy(ctx, key, value, ...args) {
917
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.findOneBy);
918
- return this.repo.findOneBy(key, value, ...ctxArgs);
919
- }
920
- async statement(ctx, method, ...args) {
921
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.statement);
922
- return this.repo.statement(method, ...ctxArgs);
923
- }
924
- async create(ctx, model, ...args) {
925
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.create);
926
- log.info(`CONTRACT CREATE, ${ctxArgs}`);
927
- if (typeof model === "string") model = this.deserialize(model);
928
- log.info(`Creating model: ${JSON.stringify(model)}`);
929
- const transient = this.getTransientData(ctx);
930
- log.info(`Merging transient data...`);
931
- model = Model.merge(model, transient, this.clazz);
932
- return this.repo.create(model, ...ctxArgs);
933
- }
934
- async read(ctx, key, ...args) {
935
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.read);
936
- log.info(`reading entry with pk ${key} `);
937
- return this.repo.read(key, ...ctxArgs);
938
- }
939
- getTransientData(ctx) {
940
- const transientMap = ctx.stub.getTransient();
941
- let transient = {};
942
- if (transientMap.has(this.repo.tableName)) {
943
- transient = JSON.parse(transientMap.get(this.repo.tableName)?.toString("utf8"));
944
- }
945
- return transient;
946
- }
947
- async update(ctx, model, ...args) {
948
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.update);
949
- if (typeof model === "string") model = this.deserialize(model);
950
- log.info(`Updating model: ${JSON.stringify(model)}`);
951
- const transient = this.getTransientData(ctx);
952
- log.info(`Merging transient data...`);
953
- model = Model.merge(model, transient, this.clazz);
954
- return this.repo.update(model, ...ctxArgs);
955
- }
956
- async delete(ctx, key, ...args) {
957
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.delete);
958
- log.info(`deleting entry with pk ${key} `);
959
- return this.repo.delete(String(key), ...ctxArgs);
960
- }
961
- async deleteAll(ctx, keys, ...args) {
962
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.readAll);
963
- if (typeof keys === "string") keys = JSON.parse(keys);
964
- return this.repo.deleteAll(keys, ...ctxArgs);
965
- }
966
- async readAll(ctx, keys, ...args) {
967
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.readAll);
968
- if (typeof keys === "string") keys = JSON.parse(keys);
969
- return this.repo.readAll(keys, ...ctxArgs);
970
- }
971
- async updateAll(ctx, models, ...args) {
972
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.updateAll);
973
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
974
- log.info(`updating ${models.length} entries to the table`);
975
- return this.repo.updateAll(models, ...ctxArgs);
976
- }
977
- async query(context, condition, orderBy, order = OrderDirection.ASC, limit, skip, ...args) {
978
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, context ], this.query);
979
- return this.repo.query(condition, orderBy, order, limit, skip, ...ctxArgs);
980
- }
981
- async raw(ctx, rawInput, docsOnly, ...args) {
982
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.raw);
983
- if (typeof rawInput === "string") rawInput = JSON.parse(rawInput);
984
- return FabricCrudContract.adapter.raw(rawInput, docsOnly, ...ctxArgs);
985
- }
986
- serialize(model) {
987
- return FabricCrudContract.serializer.serialize(model);
988
- }
989
- deserialize(str) {
990
- return FabricCrudContract.serializer.deserialize(str);
991
- }
992
- async init(ctx) {
993
- const {log: log} = await this.logCtx([ ctx ], this.init);
994
- log.info(`Running contract ${this.getName()} initialization...`);
995
- this.initialized = true;
996
- log.info(`Contract initialization completed.`);
997
- }
998
- async healthcheck(ctx) {
999
- const {log: log} = await this.logCtx([ ctx ], this.healthcheck);
1000
- log.info(`Running Healthcheck: ${this.initialized}...`);
1001
- return {
1002
- healthcheck: this.initialized
1003
- };
1004
- }
1005
- async createAll(ctx, models, ...args) {
1006
- const {log: log} = await this.logCtx([ ...args, ctx ], this.createAll);
1007
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
1008
- log.info(`adding ${models.length} entries to the table`);
1009
- return this.repo.createAll(models, ctx, ...args);
1010
- }
1011
- async logCtx(args, method) {
1012
- return FabricCrudContract.logCtx.bind(this)(args, method);
1013
- }
1014
- static async logCtx(args, method) {
1015
- if (args.length < 1) throw new InternalError("No context provided");
1016
- const ctx = args.pop();
1017
- if (ctx instanceof FabricContractContext) return {
1018
- ctx: ctx,
1019
- log: ctx.logger.clear().for(this).for(method),
1020
- ctxArgs: [ ...args, ctx ],
1021
- stub: ctx.stub,
1022
- identity: ctx.identity
1023
- };
1024
- if (!(ctx instanceof Context$1)) throw new InternalError("No valid context provided");
1025
- function getOp() {
1026
- if (typeof method === "string") return method;
1027
- switch (method.name) {
1028
- case OperationKeys.CREATE:
1029
- case OperationKeys.READ:
1030
- case OperationKeys.UPDATE:
1031
- case OperationKeys.DELETE:
1032
- case BulkCrudOperationKeys.CREATE_ALL:
1033
- case BulkCrudOperationKeys.READ_ALL:
1034
- case BulkCrudOperationKeys.UPDATE_ALL:
1035
- case BulkCrudOperationKeys.DELETE_ALL:
1036
- return method.name;
1037
-
1038
- default:
1039
- return method.name;
1040
- }
1041
- }
1042
- const overrides = {
1043
- correlationId: ctx.stub.getTxID()
1044
- };
1045
- const context = await FabricCrudContract.adapter.context(getOp(), overrides, this.clazz, ctx);
1046
- const log = this ? context.logger.for(this).for(method) : context.logger.clear().for(this).for(method);
1047
- return {
1048
- ctx: context,
1049
- log: log,
1050
- stub: context.stub,
1051
- identity: context.identity,
1052
- ctxArgs: [ ...args, context ]
1053
- };
1054
- }
1055
- }
1056
-
1057
- class SerializedCrudContract extends FabricCrudContract {
1058
- constructor(name, clazz) {
1059
- super(name, clazz);
1060
- }
1061
- async create(context, model) {
1062
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.create);
1063
- log.info(`Creating model: ${model}`);
1064
- const m = this.deserialize(model);
1065
- log.info(`Model deserialized: ${JSON.stringify(m)}`);
1066
- return this.serialize(await super.create(ctx, m));
1067
- }
1068
- async read(context, key) {
1069
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.read);
1070
- log.info(`Reading id: ${key}`);
1071
- return this.serialize(await super.read(ctx, key));
1072
- }
1073
- async update(context, model) {
1074
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.update);
1075
- log.info(`Updating model: ${model}`);
1076
- return this.serialize(await super.update(ctx, model));
1077
- }
1078
- async delete(context, key) {
1079
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.delete);
1080
- log.info(`Deleting id: ${key}`);
1081
- return this.serialize(await super.delete(ctx, key));
1082
- }
1083
- async deleteAll(context, keys) {
1084
- const parsedKeys = JSON.parse(keys);
1085
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.deleteAll);
1086
- log.info(`deleting ${parsedKeys.length} entries from the table`);
1087
- return JSON.stringify((await super.deleteAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1088
- }
1089
- async readAll(context, keys) {
1090
- const parsedKeys = JSON.parse(keys);
1091
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.readAll);
1092
- log.info(`reading ${parsedKeys.length} entries from the table`);
1093
- return JSON.stringify((await super.readAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1094
- }
1095
- async updateAll(context, models) {
1096
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.updateAll);
1097
- const list = JSON.parse(models);
1098
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1099
- log.info(`Updating ${modelList.length} entries to the table`);
1100
- return JSON.stringify((await super.updateAll(ctx, modelList)).map(m => this.serialize(m)));
1101
- }
1102
- async statement(context, method, ...args) {
1103
- const {ctx: ctx, log: log} = await this.logCtx([ ...args, context ], this.statement);
1104
- args = args.map(a => {
1105
- try {
1106
- return JSON.parse(a);
1107
- } catch (e) {
1108
- return a;
1109
- }
1110
- });
1111
- log.info(`calling prepared statement ${method}`);
1112
- log.debug(`with args ${args}`);
1113
- return super.statement(ctx, method, ...args);
1114
- }
1115
- async listBy(context, key, order, ...args) {
1116
- const {ctx: ctx} = await this.logCtx([ ...args, context ], this.listBy);
1117
- return super.listBy(ctx, key, order);
1118
- }
1119
- async paginateBy(context, key, order, size, ...args) {
1120
- const {ctx: ctx} = await this.logCtx([ ...args, context ], this.paginateBy);
1121
- return super.paginateBy(ctx, key, order, size);
1122
- }
1123
- async findOneBy(context, key, value, ...args) {
1124
- const {ctx: ctx} = await this.logCtx([ ...args, context ], this.paginateBy);
1125
- return super.findOneBy(ctx, key, value, ...args);
1126
- }
1127
- async query(context, condition, orderBy, order, limit, skip, ...args) {
1128
- const {ctx: ctx} = await this.logCtx([ context ], this.query);
1129
- let cond;
1130
- try {
1131
- cond = Condition.from(JSON.parse(condition));
1132
- } catch (e) {
1133
- throw new SerializationError(`Invalid condition: ${e}`);
1134
- }
1135
- return super.query(ctx, cond, orderBy, order, limit, skip, ...args);
1136
- }
1137
- async raw(context, rawInput, docsOnly, ...args) {
1138
- const {ctx: ctx} = await this.logCtx([ context ], this.raw);
1139
- const parsedInput = JSON.parse(rawInput);
1140
- return super.raw(ctx, parsedInput, docsOnly, ...args);
1141
- }
1142
- async init(ctx) {
1143
- await super.init(ctx);
1144
- }
1145
- async healthcheck(context) {
1146
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.updateAll);
1147
- log.debug(`Running Healthcheck: ${this.initialized}...`);
1148
- return JSON.stringify(await super.healthcheck(ctx));
1149
- }
1150
- async createAll(context, models) {
1151
- const {log: log} = await this.logCtx([ context ], this.createAll);
1152
- const list = JSON.parse(models);
1153
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1154
- log.info(`Adding ${modelList.length} entries to the table`);
1155
- return JSON.stringify((await super.createAll(context, modelList)).map(m => this.serialize(m)));
1156
- }
1157
- }
1158
-
1159
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "create", null);
1160
-
1161
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "read", null);
1162
-
1163
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "update", null);
1164
-
1165
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "delete", null);
1166
-
1167
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "deleteAll", null);
1168
-
1169
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "readAll", null);
1170
-
1171
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "updateAll", null);
1172
-
1173
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "statement", null);
1174
-
1175
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "listBy", null);
1176
-
1177
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, Number, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "paginateBy", null);
1178
-
1179
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "findOneBy", null);
1180
-
1181
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "init", null);
1182
-
1183
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "healthcheck", null);
1184
-
1185
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "createAll", null);
1186
-
1187
- class OverflowError extends InternalError {
1188
- constructor(msg) {
1189
- super(msg, OverflowError.name);
1190
- }
1191
- }
1192
-
1193
- class BalanceError extends InternalError {
1194
- constructor(msg) {
1195
- super(msg, BalanceError.name);
1196
- }
1197
- }
1198
-
1199
- class AllowanceError extends InternalError {
1200
- constructor(msg) {
1201
- super(msg, AllowanceError.name);
1202
- }
1203
- }
1204
-
1205
- class RegistrationError extends AuthorizationError {
1206
- constructor(msg) {
1207
- super(msg, RegistrationError.name);
1208
- }
1209
- }
1210
-
1211
- class MissingContextError extends InternalError {
1212
- constructor(msg) {
1213
- super(msg, MissingContextError.name, 500);
1214
- }
1215
- }
1216
-
1217
- class UnauthorizedPrivateDataAccess extends BaseError {
1218
- constructor(msg = "MISSING_PRIVATE_DATA_ERROR_MESSAGE") {
1219
- super(UnauthorizedPrivateDataAccess.name, msg, 403);
1220
- }
1221
- }
1222
-
1223
- class NotInitializedError extends BaseError {
1224
- constructor(msg) {
1225
- super(NotInitializedError.name, msg, 409);
1226
- }
1227
- }
1228
-
1229
- class MissingPKCSS11Lib extends InternalError {
1230
- constructor(msg) {
1231
- super(msg, MissingPKCSS11Lib.name, 500);
1232
- }
1233
- }
1234
-
1235
- class EndorsementError extends InternalError {
1236
- constructor(message) {
1237
- super(message, EndorsementError.name, 500);
1238
- }
1239
- }
1240
-
1241
- function add(a, b) {
1242
- const c = a + b;
1243
- if (a !== c - b || b !== c - a) {
1244
- throw new OverflowError(`Addition overflow: ${a} + ${b}`);
1245
- }
1246
- return c;
1247
- }
1248
-
1249
- function sub(a, b) {
1250
- const c = a - b;
1251
- if (a !== c + b || b !== a - c) {
1252
- throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
1253
- }
1254
- return c;
1255
- }
1256
-
1257
- function safeParseInt(string) {
1258
- const digitRegex = /^\d+$/;
1259
- if (!digitRegex.test(string)) {
1260
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string contains digits"));
1261
- }
1262
- const parsedint = parseInt(string);
1263
- if (isNaN(parsedint)) {
1264
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string is not a parsable integer"));
1265
- }
1266
- return parsedint;
1267
- }
1268
-
1269
- let ERC20Token = class ERC20Token extends BaseModel {
1270
- constructor(m) {
1271
- super(m);
1272
- }
1273
- };
1274
-
1275
- __decorate([ pk({
1276
- type: "String"
1277
- }), __metadata("design:type", String) ], ERC20Token.prototype, "name", void 0);
1278
-
1279
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "owner", void 0);
1280
-
1281
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "symbol", void 0);
1282
-
1283
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Token.prototype, "decimals", void 0);
1284
-
1285
- ERC20Token = __decorate([ table("erc20_tokens"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Token);
1286
-
1287
- let ERC20Wallet = class ERC20Wallet extends BaseModel {
1288
- constructor(m) {
1289
- super(m);
1290
- }
1291
- };
1292
-
1293
- __decorate([ pk({
1294
- type: "String"
1295
- }), __metadata("design:type", String) ], ERC20Wallet.prototype, "id", void 0);
1296
-
1297
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Wallet.prototype, "token", void 0);
1298
-
1299
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Wallet.prototype, "balance", void 0);
1300
-
1301
- __decorate([ column(), __metadata("design:type", String) ], ERC20Wallet.prototype, "captive", void 0);
1302
-
1303
- ERC20Wallet = __decorate([ table("erc20_wallets"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Wallet);
1304
-
1305
- let Allowance = class Allowance extends BaseModel {
1306
- constructor(m) {
1307
- super(m);
1308
- }
1309
- };
1310
-
1311
- __decorate([ pk({
1312
- type: "String"
1313
- }), column(), required(), __metadata("design:type", String) ], Allowance.prototype, "owner", void 0);
1314
-
1315
- __decorate([ column(), required(), __metadata("design:type", String) ], Allowance.prototype, "spender", void 0);
1316
-
1317
- __decorate([ column(), required(), __metadata("design:type", Number) ], Allowance.prototype, "value", void 0);
1318
-
1319
- Allowance = __decorate([ table("erc20_allowances"), model(), __metadata("design:paramtypes", [ Object ]) ], Allowance);
1320
-
1321
- function Owner() {
1322
- return function(target, propertyKey, descriptor) {
1323
- const originalMethod = descriptor.value;
1324
- descriptor.value = async function(...args) {
1325
- const ctx = args[0];
1326
- const acountId = ctx.clientIdentity.getID();
1327
- const select = await this["tokenRepository"].select();
1328
- const tokens = await select.execute(ctx);
1329
- if (tokens.length == 0) {
1330
- throw new NotFoundError("No tokens avaialble");
1331
- }
1332
- if (tokens.length > 1) {
1333
- throw new NotFoundError(`To many token available : ${tokens.length}`);
1334
- }
1335
- if (tokens[0].owner != acountId) {
1336
- throw new AuthorizationError(`User not authorized to run ${propertyKey} on the token`);
1337
- }
1338
- return await originalMethod.apply(this, args);
1339
- };
1340
- return descriptor;
1341
- };
1342
- }
1343
-
1344
- async function ownedByOnCreate(context, data, key, model) {
1345
- const {stub: stub} = context;
1346
- const creator = await stub.getCreator();
1347
- const owner = creator.mspid;
1348
- const setOwnedByKeyValue = function(target, propertyKey, value) {
1349
- Object.defineProperty(target, propertyKey, {
1350
- enumerable: true,
1351
- writable: false,
1352
- configurable: true,
1353
- value: value
1354
- });
1355
- };
1356
- setOwnedByKeyValue(model, key, owner);
1357
- }
1358
-
1359
- function OwnedBy() {
1360
- const key = getFabricModelKey(FabricModelKeys.OWNEDBY);
1361
- function ownedBy() {
1362
- return function(obj, attribute) {
1363
- return apply(required(), readonly(), onCreate(ownedByOnCreate), propMetadata(getFabricModelKey(FabricModelKeys.OWNEDBY), attribute))(obj, attribute);
1364
- };
1365
- }
1366
- return Decoration.for(key).define({
1367
- decorator: ownedBy,
1368
- args: []
1369
- }).apply();
1370
- }
1371
-
1372
- function getFabricModelKey(key) {
1373
- return Metadata.key(FabricModelKeys.FABRIC + key);
1374
- }
1375
-
1376
- const ImplicitPrivateCollection = model => `__${model.constructor.name}PrivateCollection`;
1377
-
1378
- async function segregatedDataOnCreate(context, data, keys, model) {
1379
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1380
- const collectionResolver = data[0].collections;
1381
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1382
- const rebuilt = keys.reduce((acc, k, i) => {
1383
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1384
- if (c !== collection) throw new UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1385
- acc[k] = model[k];
1386
- return acc;
1387
- }, {});
1388
- const toCreate = new this.class(rebuilt);
1389
- const created = await this.override({
1390
- segregated: collection
1391
- }).create(toCreate, context);
1392
- Object.assign(model, created);
1393
- }
1394
-
1395
- async function segregatedDataOnRead(context, data, keys, model) {
1396
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1397
- const collectionResolver = data[0].collections;
1398
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1399
- const rebuilt = keys.reduce((acc, k, i) => {
1400
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1401
- if (c !== collection) throw new UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1402
- acc[k] = model[k];
1403
- return acc;
1404
- }, {});
1405
- const toCreate = new this.class(rebuilt);
1406
- const created = await this.override({
1407
- segregated: collection
1408
- }).create(toCreate, context);
1409
- Object.assign(model, created);
1410
- }
1411
-
1412
- async function segregatedDataOnUpdate(context, data, key, model, oldModel) {}
1413
-
1414
- async function segregatedDataOnDelete(context, data, key, model) {}
1415
-
1416
- function segregated(collection, type) {
1417
- return function innerSegregated(target, propertyKey) {
1418
- function segregatedDec(target, propertyKey) {
1419
- if (!propertyKey) {
1420
- const props = Metadata.properties(target) || [];
1421
- for (const prop of props) segregated(collection, type)(target, prop);
1422
- return target;
1423
- }
1424
- const key = Metadata.key(type, propertyKey);
1425
- const constr = target.constructor;
1426
- const meta = Metadata.get(constr, key) || {};
1427
- const collections = new Set(meta.collections || []);
1428
- collections.add(collection);
1429
- meta.collections = [ ...collections ];
1430
- Metadata.set(constr, key, meta);
1431
- }
1432
- const decs = [];
1433
- if (!propertyKey) {
1434
- Metadata.properties(target)?.forEach(p => segregated(collection, type)(target, p));
1435
- return metadata(type, true)(target);
1436
- } else {
1437
- decs.push(transient(), segregatedDec, onCreate(segregatedDataOnCreate, {
1438
- collections: collection
1439
- }, {
1440
- priority: 95,
1441
- group: typeof collection === "string" ? collection : collection.toString()
1442
- }), onRead(segregatedDataOnRead, {
1443
- collections: collection
1444
- }, {
1445
- priority: 95,
1446
- group: typeof collection === "string" ? collection : collection.toString()
1447
- }), onUpdate(segregatedDataOnUpdate, {
1448
- collections: collection
1449
- }, {
1450
- priority: 95,
1451
- group: typeof collection === "string" ? collection : collection.toString()
1452
- }), onDelete(segregatedDataOnDelete, {
1453
- collections: collection
1454
- }, {
1455
- priority: 95,
1456
- group: typeof collection === "string" ? collection : collection.toString()
1457
- }));
1458
- }
1459
- return apply(...decs)(target, propertyKey);
1460
- };
1461
- }
1462
-
1463
- function privateData(collection = ImplicitPrivateCollection) {
1464
- function privateData(collection) {
1465
- return segregated(collection, FabricModelKeys.PRIVATE);
1466
- }
1467
- return Decoration.for(FabricModelKeys.PRIVATE).define({
1468
- decorator: privateData,
1469
- args: [ collection ]
1470
- }).apply();
1471
- }
1472
-
1473
- function sharedData(collection) {
1474
- function sharedData(collection) {
1475
- return segregated(collection, FabricModelKeys.SHARED);
1476
- }
1477
- return Decoration.for(FabricModelKeys.SHARED).define({
1478
- decorator: sharedData,
1479
- args: [ collection ]
1480
- }).apply();
1481
- }
1482
-
1483
- var ERC20Events;
1484
-
1485
- (function(ERC20Events) {
1486
- ERC20Events["TRANSFER"] = "Transfer";
1487
- ERC20Events["APPROVAL"] = "Approval";
1488
- })(ERC20Events || (ERC20Events = {}));
1489
-
1490
- class FabricERC20Contract extends FabricCrudContract {
1491
- constructor(name) {
1492
- super(name, ERC20Wallet);
1493
- FabricERC20Contract.adapter = FabricERC20Contract.adapter || new FabricContractAdapter;
1494
- this.walletRepository = FabricContractRepository.forModel(ERC20Wallet, FabricERC20Contract.adapter.alias);
1495
- this.tokenRepository = FabricContractRepository.forModel(ERC20Token, FabricERC20Contract.adapter.alias);
1496
- this.allowanceRepository = FabricContractRepository.forModel(Allowance, FabricERC20Contract.adapter.alias);
1497
- }
1498
- async TokenName(context) {
1499
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1500
- await this.CheckInitialized(ctx);
1501
- const select = this.tokenRepository.select();
1502
- const token = (await select.execute(ctx))[0];
1503
- return token.name;
1504
- }
1505
- async Symbol(context) {
1506
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1507
- await this.CheckInitialized(ctx);
1508
- const select = this.tokenRepository.select();
1509
- const token = (await select.execute(ctx))[0];
1510
- return token.symbol;
1511
- }
1512
- async Decimals(context) {
1513
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1514
- await this.CheckInitialized(ctx);
1515
- const select = this.tokenRepository.select();
1516
- const token = (await select.execute(ctx))[0];
1517
- return token.decimals;
1518
- }
1519
- async TotalSupply(context) {
1520
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1521
- await this.CheckInitialized(ctx);
1522
- const select = this.walletRepository.select();
1523
- const wallets = await select.execute(ctx);
1524
- if (wallets.length == 0) {
1525
- throw new NotFoundError(`The token ${this.getName()} does not exist`);
1526
- }
1527
- let total = 0;
1528
- wallets.forEach(wallet => {
1529
- total += wallet.balance;
1530
- });
1531
- return total;
1532
- }
1533
- async BalanceOf(context, owner) {
1534
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1535
- await this.CheckInitialized(ctx);
1536
- const wallet = await this.walletRepository.read(owner, ctx);
1537
- return wallet.balance;
1538
- }
1539
- async Transfer(context, to, value) {
1540
- const {ctx: ctx} = await this.logCtx([ context ], this.Transfer);
1541
- await this.CheckInitialized(ctx);
1542
- const from = ctx.identity.getID();
1543
- const transferResp = await this._transfer(from, to, value, ctx);
1544
- if (!transferResp) {
1545
- throw new InternalError("Failed to transfer");
1546
- }
1547
- return true;
1548
- }
1549
- async TransferFrom(context, from, to, value) {
1550
- const {ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1551
- await this.CheckInitialized(ctx);
1552
- const spender = ctx.identity.getID();
1553
- const allowance = await this._getAllowance(from, spender, ctx);
1554
- if (!allowance || allowance.value < 0) {
1555
- throw new AllowanceError(`spender ${spender} has no allowance from ${from}`);
1556
- }
1557
- const currentAllowance = allowance.value;
1558
- if (currentAllowance < value) {
1559
- throw new BalanceError("The spender does not have enough allowance to spend.");
1560
- }
1561
- const updatedAllowance = sub(currentAllowance, value);
1562
- const newAllowance = Object.assign({}, allowance, {
1563
- value: updatedAllowance
1564
- });
1565
- await this.allowanceRepository.update(newAllowance, ctx);
1566
- const transferResp = await this._transfer(from, to, value, ctx);
1567
- if (!transferResp) {
1568
- throw new InternalError("Failed to transfer");
1569
- }
1570
- return true;
1571
- }
1572
- async _transfer(from, to, value, ctx) {
1573
- const log = ctx.logger;
1574
- if (from === to) {
1575
- throw new AuthorizationError("cannot transfer to and from same client account");
1576
- }
1577
- if (value < 0) {
1578
- throw new BalanceError("transfer amount cannot be negative");
1579
- }
1580
- const fromWallet = await this.walletRepository.read(from, ctx);
1581
- const fromBalance = fromWallet.balance;
1582
- if (fromBalance < value) {
1583
- throw new BalanceError(`client account ${from} has insufficient funds.`);
1584
- }
1585
- let toWallet;
1586
- let newToWallet = false;
1587
- try {
1588
- toWallet = await this.walletRepository.read(to, ctx);
1589
- } catch (e) {
1590
- if (e instanceof BaseError) {
1591
- if (e.code === 404) {
1592
- toWallet = new ERC20Wallet({
1593
- id: to,
1594
- balance: 0,
1595
- token: await this.TokenName(ctx)
1596
- });
1597
- newToWallet = true;
1598
- } else {
1599
- throw new InternalError(e.message);
1600
- }
1601
- } else {
1602
- throw new InternalError(e);
1603
- }
1604
- }
1605
- const toBalance = toWallet.balance;
1606
- const fromUpdatedBalance = sub(fromBalance, value);
1607
- const toUpdatedBalance = add(toBalance, value);
1608
- const updatedFromWallet = Object.assign({}, fromWallet, {
1609
- balance: fromUpdatedBalance
1610
- });
1611
- await this.walletRepository.update(updatedFromWallet, ctx);
1612
- const updatedToWallet = Object.assign({}, toWallet, {
1613
- balance: toUpdatedBalance
1614
- });
1615
- if (newToWallet) {
1616
- await this.walletRepository.create(updatedToWallet, ctx);
1617
- } else {
1618
- await this.walletRepository.update(updatedToWallet, ctx);
1619
- }
1620
- const transferEvent = {
1621
- from: from,
1622
- to: to,
1623
- value: value
1624
- };
1625
- this.repo.refresh(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx).catch(e => log.error(`Failed to notify transfer: ${e}`));
1626
- return true;
1627
- }
1628
- async Approve(context, spender, value) {
1629
- const {ctx: ctx, ctxArgs: ctxArgs} = await this.logCtx([ context ], this.Approve);
1630
- await this.CheckInitialized(ctx);
1631
- const owner = ctx.identity.getID();
1632
- let allowance = await this._getAllowance(owner, spender, ctx);
1633
- const ownerWallet = await this.walletRepository.read(owner, ...ctxArgs);
1634
- if (ownerWallet.balance < value) {
1635
- throw new BalanceError(`client account ${owner} has insufficient funds.`);
1636
- }
1637
- if (allowance) {
1638
- allowance.value = value;
1639
- await this.allowanceRepository.update(allowance, ...ctxArgs);
1640
- } else {
1641
- allowance = new Allowance({
1642
- owner: owner,
1643
- spender: spender,
1644
- value: value
1645
- });
1646
- await this.allowanceRepository.create(allowance, ...ctxArgs);
1647
- }
1648
- const approvalEvent = {
1649
- owner: owner,
1650
- spender: spender,
1651
- value: value
1652
- };
1653
- this.repo.refresh(ERC20Token, ERC20Events.APPROVAL, "", approvalEvent, ctx);
1654
- return true;
1655
- }
1656
- async Allowance(context, owner, spender) {
1657
- const {ctx: ctx} = await this.logCtx([ context ], this.Allowance);
1658
- await this.CheckInitialized(ctx);
1659
- const allowance = await this._getAllowance(owner, spender, ctx);
1660
- if (!allowance) {
1661
- throw new AllowanceError(`spender ${spender} has no allowance from ${owner}`);
1662
- }
1663
- return allowance.value;
1664
- }
1665
- async _getAllowance(owner, spender, ctx) {
1666
- const allowanceCondition = Condition.and(Condition.attribute("owner").eq(owner), Condition.attribute("spender").eq(spender));
1667
- const allowance = await this.allowanceRepository.select().where(allowanceCondition).execute(ctx);
1668
- return allowance?.[0];
1669
- }
1670
- async Initialize(context, token) {
1671
- const {ctx: ctx} = await this.logCtx([ context ], this.Initialize);
1672
- const tokens = await this.tokenRepository.select().execute(ctx);
1673
- if (tokens.length > 0) {
1674
- throw new AuthorizationError("contract options are already set, client is not authorized to change them");
1675
- }
1676
- token.owner = ctx.identity.getID();
1677
- await this.tokenRepository.create(token, ctx);
1678
- return true;
1679
- }
1680
- async CheckInitialized(context) {
1681
- const {ctx: ctx} = await this.logCtx([ context ], this.CheckInitialized);
1682
- const tokens = await this.tokenRepository.select().execute(ctx);
1683
- if (tokens.length == 0) {
1684
- throw new NotInitializedError("contract options need to be set before calling any function, call Initialize() to initialize contract");
1685
- }
1686
- }
1687
- async Mint(context, amount) {
1688
- const {ctx: ctx} = await this.logCtx([ context ], this.Mint);
1689
- await this.CheckInitialized(ctx);
1690
- const minter = ctx.identity.getID();
1691
- if (amount <= 0) {
1692
- throw new ValidationError("mint amount must be a positive integer");
1693
- }
1694
- let minterWallet;
1695
- try {
1696
- minterWallet = await this.walletRepository.read(minter, ctx);
1697
- const currentBalance = minterWallet.balance;
1698
- const updatedBalance = add(currentBalance, amount);
1699
- const updatedminter = Object.assign({}, minterWallet, {
1700
- balance: updatedBalance
1701
- });
1702
- await this.walletRepository.update(updatedminter, ctx);
1703
- } catch (e) {
1704
- if (e instanceof BaseError) {
1705
- if (e.code === 404) {
1706
- const newWallet = new ERC20Wallet({
1707
- id: minter,
1708
- balance: amount,
1709
- token: await this.TokenName(context)
1710
- });
1711
- await this.walletRepository.create(newWallet, ctx);
1712
- } else {
1713
- throw new InternalError(e.message);
1714
- }
1715
- } else {
1716
- throw new InternalError(e);
1717
- }
1718
- }
1719
- const transferEvent = {
1720
- from: "0x0",
1721
- to: minter,
1722
- value: amount
1723
- };
1724
- const eventHandler = this.repo.ObserverHandler();
1725
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1726
- }
1727
- async Burn(context, amount) {
1728
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.Burn);
1729
- await this.CheckInitialized(ctx);
1730
- const minter = ctx.identity.getID();
1731
- const minterWallet = await this.walletRepository.read(minter, ctx);
1732
- const currentBalance = minterWallet.balance;
1733
- if (currentBalance < amount) {
1734
- throw new BalanceError(`Minter has insufficient funds.`);
1735
- }
1736
- const updatedBalance = sub(currentBalance, amount);
1737
- const updatedminter = Object.assign({}, minterWallet, {
1738
- balance: updatedBalance
1739
- });
1740
- await this.walletRepository.update(updatedminter, ctx);
1741
- log.info(`${amount} tokens were burned`);
1742
- const transferEvent = {
1743
- from: minter,
1744
- to: "0x0",
1745
- value: amount
1746
- };
1747
- const eventHandler = this.repo.ObserverHandler();
1748
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1749
- }
1750
- async BurnFrom(context, account, amount) {
1751
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1752
- await this.CheckInitialized(ctx);
1753
- const accountWallet = await this.walletRepository.read(account, ctx);
1754
- const currentBalance = accountWallet.balance;
1755
- if (currentBalance < amount) {
1756
- throw new BalanceError(`${account} has insufficient funds.`);
1757
- }
1758
- const updatedBalance = sub(currentBalance, amount);
1759
- const updatedaccount = Object.assign({}, accountWallet, {
1760
- balance: updatedBalance
1761
- });
1762
- await this.walletRepository.update(updatedaccount, ctx);
1763
- log.info(`${amount} tokens were burned from ${account}`);
1764
- const transferEvent = {
1765
- from: account,
1766
- to: "0x0",
1767
- value: amount
1768
- };
1769
- const eventHandler = this.repo.ObserverHandler();
1770
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1771
- }
1772
- async ClientAccountBalance(context) {
1773
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1774
- await this.CheckInitialized(ctx);
1775
- const clientAccountID = ctx.identity.getID();
1776
- const clientWallet = await this.walletRepository.read(clientAccountID, ctx);
1777
- if (!clientWallet) {
1778
- throw new BalanceError(`The account ${clientAccountID} does not exist`);
1779
- }
1780
- return clientWallet.balance;
1781
- }
1782
- async ClientAccountID(context) {
1783
- const {ctx: ctx} = await this.logCtx([ context ], this.ClientAccountID);
1784
- await this.CheckInitialized(ctx);
1785
- const clientAccountID = ctx.identity.getID();
1786
- return clientAccountID;
1787
- }
1788
- }
1789
-
1790
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TokenName", null);
1791
-
1792
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Symbol", null);
1793
-
1794
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Decimals", null);
1795
-
1796
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TotalSupply", null);
1797
-
1798
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BalanceOf", null);
1799
-
1800
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Transfer", null);
1801
-
1802
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TransferFrom", null);
1803
-
1804
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Approve", null);
1805
-
1806
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Allowance", null);
1807
-
1808
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, ERC20Token ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Initialize", null);
1809
-
1810
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "CheckInitialized", null);
1811
-
1812
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Mint", null);
1813
-
1814
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Burn", null);
1815
-
1816
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BurnFrom", null);
1817
-
1818
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountBalance", null);
1819
-
1820
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountID", null);
1821
-
1822
- const contracts = [ FabricERC20Contract ];
1823
-
1824
- const VERSION = "0.1.23";
1825
-
1826
- const PACKAGE_NAME = "@decaf-ts/for-fabric";
1827
-
1828
- Metadata.registerLibrary(PACKAGE_NAME, VERSION);
1829
-
1830
- export { ContractLogger, FabricContractAdapter, FabricContractContext, FabricContractRepository, FabricContractRepositoryObservableHandler, FabricCrudContract, FabricStatement, PACKAGE_NAME, SerializedCrudContract, VERSION, contracts, createdByOnFabricCreateUpdate, pkFabricOnCreate };
1831
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWZhYnJpYy5qcyIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnRyYWN0cy9Db250cmFjdENvbnRleHQudHMiLCIuLi9zcmMvc2hhcmVkL2V2ZW50cy50cyIsIi4uL3NyYy9jb250cmFjdHMvRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIudHMiLCIuLi9zcmMvY29udHJhY3RzL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeS50cyIsIi4uL3NyYy9jb250cmFjdHMvRmFicmljQ29udHJhY3RTdGF0ZW1lbnQudHMiLCIuLi9zcmMvc2hhcmVkL2NvbnN0YW50cy50cyIsIi4uL3NyYy9zaGFyZWQvU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIudHMiLCIuLi9zcmMvY29udHJhY3RzL0ZhYnJpY0NvbnN0cnVjdGlvbi50cyIsIi4uL3NyYy9jb250cmFjdHMvbG9nZ2luZy50cyIsIi4uL3NyYy9jb250cmFjdHMvQ29udHJhY3RBZGFwdGVyLnRzIiwiLi4vc3JjL3NoYXJlZC9EZXRlcm1pbmlzdGljU2VyaWFsaXplci50cyIsIi4uL3NyYy9jb250cmFjdHMvY3J1ZC9jcnVkLWNvbnRyYWN0LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9jcnVkL3NlcmlhbGl6ZWQtY3J1ZC1jb250cmFjdC50cyIsIi4uL3NyYy9zaGFyZWQvZXJyb3JzLnRzIiwiLi4vc3JjL3NoYXJlZC9tYXRoLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9lcmMyMC9tb2RlbHMudHMiLCIuLi9zcmMvc2hhcmVkL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvc2hhcmVkL2VyYzIwL2VyYzIwLWNvbnN0YW50cy50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvZXJjMjBjb250cmFjdC50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvaW5kZXgudHMiLCIuLi9zcmMvdmVyc2lvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IENoYWluY29kZVN0dWIsIENsaWVudElkZW50aXR5IH0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb250ZXh0IGNsYXNzIGZvciBGYWJyaWMgY2hhaW5jb2RlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGFjY2VzcyB0byBGYWJyaWMtc3BlY2lmaWMgY29udGV4dCBlbGVtZW50cyBsaWtlIHN0dWIsIGlkZW50aXR5LCBhbmQgbG9nZ2VyIHRvIGJlIHVzZWQgYnkgcmVwb3NpdG9yaWVzIGFuZCBhZGFwdGVycyBkdXJpbmcgY29udHJhY3QgZXhlY3V0aW9uLlxuICogQHRlbXBsYXRlIEYgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHBhcmFtIHtvYmplY3R9IFthcmdzXSAtIE9wdGlvbmFsIGluaXRpYWxpemF0aW9uIGFyZ3VtZW50cyBwYXNzZWQgdG8gdGhlIGJhc2UgQ29udGV4dFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3QgbWV0aG9kXG4gKiBjb25zdCBjb250ZXh0ID0gbmV3IEZhYnJpY0NvbnRyYWN0Q29udGV4dCgpO1xuICogLy8gT3B0aW9uYWxseSBzZXQgdmFsdWVzIHZpYSB0aGUgYmFzZSBDb250ZXh0IEFQSVxuICogY29udGV4dC5zZXQoJ3N0dWInLCBjdHguc3R1Yik7XG4gKiBjb250ZXh0LnNldCgnY2xpZW50SWRlbnRpdHknLCBjdHguY2xpZW50SWRlbnRpdHkpO1xuICogY29udGV4dC5zZXQoJ2xvZ2dlcicsIGNvbnRyYWN0TG9nZ2VyKTtcbiAqXG4gKiAvLyBBY2Nlc3MgY29udGV4dCBwcm9wZXJ0aWVzXG4gKiBjb25zdCB0aW1lc3RhbXAgPSBjb250ZXh0LnRpbWVzdGFtcDtcbiAqIGNvbnN0IGNyZWF0b3IgPSBjb250ZXh0LmlkZW50aXR5LmdldElEKCk7XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgQ29udGV4dFxuICogICBwYXJ0aWNpcGFudCBMZWRnZXJcbiAqICAgQ29udHJhY3QtPj5Db250ZXh0OiBuZXcgRmFicmljQ29udHJhY3RDb250ZXh0KClcbiAqICAgQ29udHJhY3QtPj5Db250ZXh0OiBzZXQoJ3N0dWInfCdjbGllbnRJZGVudGl0eSd8J2xvZ2dlcicsIC4uLilcbiAqICAgQ29udGV4dC0tPj5Db250cmFjdDogdGltZXN0YW1wLCBpZGVudGl0eSwgbG9nZ2VyXG4gKiAgIENvbnRyYWN0LT4+TGVkZ2VyOiBJbnRlcmFjdCB2aWEgc3R1YlxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RDb250ZXh0IGV4dGVuZHMgQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNDb250cmFjdENvbnRleHQgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgdGhlIGNvbnRleHQgd2l0aCBGYWJyaWMtc3BlY2lmaWMgZmxhZ3NcbiAgICovXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIGNoYWluY29kZSBzdHViXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIENoYWluY29kZVN0dWIgaW5zdGFuY2UgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIGxlZGdlclxuICAgKiBAcmV0dXJuIHtDaGFpbmNvZGVTdHVifSBUaGUgY2hhaW5jb2RlIHN0dWJcbiAgICovXG4gIGdldCBzdHViKCk6IENoYWluY29kZVN0dWIge1xuICAgIHJldHVybiB0aGlzLmdldChcInN0dWJcIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRyYW5zYWN0aW9uIHRpbWVzdGFtcFxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgdGltZXN0YW1wIGdldHRlciB0byB1c2UgdGhlIHN0dWIncyB0aW1lc3RhbXBcbiAgICogQHJldHVybiB7RGF0ZX0gVGhlIHRyYW5zYWN0aW9uIHRpbWVzdGFtcFxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IHRpbWVzdGFtcCgpOiBEYXRlIHtcbiAgICByZXR1cm4gdGhpcy5zdHViLmdldERhdGVUaW1lc3RhbXAoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY2xpZW50IGlkZW50aXR5XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIENsaWVudElkZW50aXR5IGluc3RhbmNlIGZvciB0aGUgdHJhbnNhY3Rpb24gc3VibWl0dGVyXG4gICAqIEByZXR1cm4ge0NsaWVudElkZW50aXR5fSBUaGUgY2xpZW50IGlkZW50aXR5XG4gICAqL1xuICBnZXQgaWRlbnRpdHkoKTogQ2xpZW50SWRlbnRpdHkge1xuICAgIHJldHVybiB0aGlzLmdldChcImlkZW50aXR5XCIpO1xuICB9XG5cbiAgb3ZlcnJpZGUgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGBmYWJyaWMgY3R4JHt0aGlzLnN0dWIgPyBcIiB3aXRoIHN0dWJcIiA6IFwid2l0aG91dCBzdHViXCJ9YDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQnVsa0NydWRPcGVyYXRpb25LZXlzLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdlbmVyYXRlcyBhIEZhYnJpYyBldmVudCBuYW1lIGZyb20gY29tcG9uZW50c1xuICogQHN1bW1hcnkgQ3JlYXRlcyBhIHN0YW5kYXJkaXplZCBldmVudCBuYW1lIGJ5IGpvaW5pbmcgdGFibGUsIGV2ZW50LCBhbmQgb3B0aW9uYWwgb3duZXIgd2l0aCB1bmRlcnNjb3Jlc1xuICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlIC0gVGhlIHRhYmxlL2NvbGxlY3Rpb24gbmFtZVxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nfSBldmVudCAtIFRoZSBldmVudCB0eXBlXG4gKiBAcGFyYW0ge3N0cmluZ30gW293bmVyXSAtIE9wdGlvbmFsIG93bmVyIGlkZW50aWZpZXJcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGdlbmVyYXRlZCBldmVudCBuYW1lIGluIGZvcm1hdCBcInRhYmxlX2V2ZW50XCIgb3IgXCJ0YWJsZV9ldmVudF9vd25lclwiXG4gKiBAZnVuY3Rpb24gZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlRmFicmljRXZlbnROYW1lKFxuICB0YWJsZTogc3RyaW5nLFxuICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgb3duZXI/OiBzdHJpbmdcbikge1xuICBjb25zdCBwYXJhbXMgPSBbdGFibGUsIGV2ZW50XTtcbiAgaWYgKG93bmVyKSBwYXJhbXMucHVzaChvd25lcik7XG4gIHJldHVybiBwYXJhbXMuam9pbihcIl9cIik7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhIEZhYnJpYyBldmVudCBuYW1lIGludG8gaXRzIGNvbXBvbmVudHNcbiAqIEBzdW1tYXJ5IFNwbGl0cyBhbiBldmVudCBuYW1lIGJ5IHVuZGVyc2NvcmVzIGFuZCBleHRyYWN0cyB0YWJsZSwgZXZlbnQsIGFuZCBvcHRpb25hbCBvd25lclxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgZXZlbnQgbmFtZSB0byBwYXJzZVxuICogQHJldHVybiB7e3RhYmxlOiBzdHJpbmcsIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nLCBvd25lcjogc3RyaW5nfX0gVGhlIHBhcnNlZCBjb21wb25lbnRzIGFzIGEgc3RydWN0dXJlZCBvYmplY3RcbiAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZSBldmVudCBuYW1lIGZvcm1hdCBpcyBpbnZhbGlkXG4gKiBAZnVuY3Rpb24gcGFyc2VFdmVudE5hbWVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IFBhcnNlciBhcyBwYXJzZUV2ZW50TmFtZVxuICogICBDYWxsZXItPj5QYXJzZXI6IHBhcnNlRXZlbnROYW1lKG5hbWUpXG4gKiAgIFBhcnNlci0+PlBhcnNlcjogc3BsaXQgbmFtZSBieSBcIl9cIlxuICogICBhbHQgcGFydHMgbGVuZ3RoIGludmFsaWRcbiAqICAgICBQYXJzZXItLT4+Q2FsbGVyOiB0aHJvdyBJbnRlcm5hbEVycm9yXG4gKiAgIGVsc2VcbiAqICAgICBQYXJzZXItLT4+Q2FsbGVyOiB7IHRhYmxlLCBldmVudCwgb3duZXI/IH1cbiAqICAgZW5kXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUV2ZW50TmFtZShuYW1lOiBzdHJpbmcpOiB7XG4gIHRhYmxlPzogc3RyaW5nO1xuICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZztcbiAgb3duZXI/OiBzdHJpbmc7XG59IHtcbiAgY29uc3QgcGFydHMgPSBuYW1lLnNwbGl0KFwiX1wiKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA8IDIgfHwgcGFydHMubGVuZ3RoID4gMylcbiAgICByZXR1cm4geyB0YWJsZTogdW5kZWZpbmVkLCBldmVudDogbmFtZSwgb3duZXI6IHVuZGVmaW5lZCB9O1xuICByZXR1cm4ge1xuICAgIHRhYmxlOiBwYXJ0c1swXSxcbiAgICBldmVudDogcGFydHNbMV0sXG4gICAgb3duZXI6IHBhcnRzWzJdLFxuICB9IGFzIHtcbiAgICB0YWJsZTogc3RyaW5nO1xuICAgIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nO1xuICAgIG93bmVyPzogc3RyaW5nO1xuICB9O1xufVxuIiwiaW1wb3J0IHsgQnVsa0NydWRPcGVyYXRpb25LZXlzLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBBZGFwdGVyLFxuICBDb250ZXh0dWFsQXJncyxcbiAgRXZlbnRJZHMsXG4gIE9ic2VydmVySGFuZGxlcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSB9IGZyb20gXCIuLi9zaGFyZWQvZXZlbnRzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE9ic2VydmVyIGhhbmRsZXIgZm9yIEZhYnJpYyBjaGFpbmNvZGUgZXZlbnRzXG4gKiBAc3VtbWFyeSBFbWl0cyBldmVudHMgb24gdGhlIEZhYnJpYyBsZWRnZXIgd2hlbiByZXBvc2l0b3J5IG9wZXJhdGlvbnMgb2NjdXJcbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlclxuICogQGV4dGVuZHMge09ic2VydmVySGFuZGxlcn1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RcbiAqIGltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIC8vIENyZWF0ZSBhIGhhbmRsZXIgd2l0aCBkZWZhdWx0IHN1cHBvcnRlZCBldmVudHNcbiAqIGNvbnN0IGhhbmRsZXIgPSBuZXcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIoKTtcbiAqXG4gKiAvLyBFbWl0IGFuIGV2ZW50XG4gKiBhd2FpdCBoYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAqICAgbG9nZ2VyLFxuICogICAnYXNzZXRzJyxcbiAqICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gKiAgICdhc3NldDEnLFxuICogICBjb250ZXh0XG4gKiApO1xuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgT2JzZXJ2YWJsZUhhbmRsZXJcbiAqICAgcGFydGljaXBhbnQgU3R1YlxuICogICBwYXJ0aWNpcGFudCBMZWRnZXJcbiAqXG4gKiAgIFJlcG9zaXRvcnktPj5PYnNlcnZhYmxlSGFuZGxlcjogdXBkYXRlT2JzZXJ2ZXJzKGxvZywgdGFibGUsIGV2ZW50LCBpZCwgY3R4KVxuICogICBPYnNlcnZhYmxlSGFuZGxlci0+Pk9ic2VydmFibGVIYW5kbGVyOiBDaGVjayBpZiBldmVudCBpcyBzdXBwb3J0ZWRcbiAqICAgT2JzZXJ2YWJsZUhhbmRsZXItPj5PYnNlcnZhYmxlSGFuZGxlcjogZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWUodGFibGUsIGV2ZW50LCBvd25lcilcbiAqICAgT2JzZXJ2YWJsZUhhbmRsZXItPj5TdHViOiBzZXRFdmVudChldmVudE5hbWUsIHBheWxvYWQpXG4gKiAgIFN0dWItPj5MZWRnZXI6IFJlY29yZCBldmVudFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgZXh0ZW5kcyBPYnNlcnZlckhhbmRsZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgdGhlIGhhbmRsZXIgd2l0aCBhIGxpc3Qgb2Ygc3VwcG9ydGVkIGV2ZW50c1xuICAgKiBAcGFyYW0ge0FycmF5PE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc+fSBbc3VwcG9ydGVkRXZlbnRzXSAtIEV2ZW50cyB0aGF0IHdpbGwgdHJpZ2dlciBGYWJyaWMgZXZlbnRzXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHN1cHBvcnRlZEV2ZW50czogKFxuICAgICAgfCBPcGVyYXRpb25LZXlzXG4gICAgICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5c1xuICAgICAgfCBzdHJpbmdcbiAgICApW10gPSBbXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTCxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMLFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEwsXG4gICAgXVxuICApIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG9ic2VydmVycyBieSBlbWl0dGluZyBGYWJyaWMgZXZlbnRzXG4gICAqIEBzdW1tYXJ5IEVtaXRzIGV2ZW50cyBvbiB0aGUgRmFicmljIGxlZGdlciBmb3Igc3VwcG9ydGVkIGV2ZW50IHR5cGVzXG4gICAqIEBwYXJhbSB7TG9nZ2VyfSBsb2cgLSBMb2dnZXIgaW5zdGFuY2UgZm9yIGRlYnVnZ2luZ1xuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUvY29sbGVjdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICAgKiBAcGFyYW0ge0V2ZW50SWRzfSBpZCAtIFRoZSBldmVudCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvd25lcl0gLSBPcHRpb25hbCBvd25lciBpZGVudGlmaWVyIGZvciB0aGUgZXZlbnRcbiAgICogQHBhcmFtIHtvYmplY3QgfCBzdHJpbmcgfCB1bmRlZmluZWR9IFtvd25lcl0gLSBPcHRpb25hbCBwYXlsb2FkIGZvciB0aGUgZXZlbnRcbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZU9ic2VydmVycyhcbiAgICBjbGF6ejogc3RyaW5nIHwgQ29uc3RydWN0b3I8YW55PixcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBBZGFwdGVyLmxvZ0N0eDxGYWJyaWNDb250cmFjdENvbnRleHQ+KFxuICAgICAgYXJncyxcbiAgICAgIHRoaXMudXBkYXRlT2JzZXJ2ZXJzXG4gICAgKTtcbiAgICBjb25zdCB7IHN0dWIgfSA9IGN0eDtcbiAgICBjb25zdCBbb3duZXIsIHBheWxvYWRdID0gYXJncztcbiAgICBjb25zdCB0YWJsZSA9IHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IGNsYXp6IDogY2xhenoubmFtZTtcbiAgICBpZiAodGhpcy5zdXBwb3J0ZWRFdmVudHMuaW5kZXhPZihldmVudCkgIT09IC0xKSB7XG4gICAgICBsb2cuZGVidWcoYEVtaXR0aW5nICR7ZXZlbnR9IGV2ZW50YCk7XG4gICAgICBjb25zdCBldmVudE5hbWUgPSBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSh0YWJsZSwgZXZlbnQsIG93bmVyKTtcbiAgICAgIHN0dWIuc2V0RXZlbnQoZXZlbnROYW1lLCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeSh7IGlkOiBpZCB9KSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHViLnNldEV2ZW50KGV2ZW50LCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShwYXlsb2FkKSkpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgUmVwb3NpdG9yeSxcbiAgT2JzZXJ2ZXJIYW5kbGVyLFxuICBFdmVudElkcyxcbiAgQ29udGV4dHVhbEFyZ3MsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RDb250ZXh0IH0gZnJvbSBcIi4vQ29udHJhY3RDb250ZXh0XCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXJcIjtcbmltcG9ydCB7IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB0eXBlIHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSBcIi4vQ29udHJhY3RBZGFwdGVyXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcG9zaXRvcnkgZm9yIEh5cGVybGVkZ2VyIEZhYnJpYyBjaGFpbmNvZGUgbW9kZWxzXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBDUlVEIG9wZXJhdGlvbnMgZm9yIG1vZGVscyB3aXRoaW4gRmFicmljIGNoYWluY29kZSBjb250cmFjdHNcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBNYW5nb1F1ZXJ5IC0gUXVlcnkgdHlwZSBmb3IgQ291Y2hEQi1saWtlIHF1ZXJpZXNcbiAqIEB0ZW1wbGF0ZSBGYWJyaWNDb250cmFjdEFkYXB0ZXIgLSBBZGFwdGVyIHR5cGUgZm9yIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RGbGFncyAtIEZsYWdzIHNwZWNpZmljIHRvIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RDb250ZXh0IC0gQ29udGV4dCB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICpcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RBZGFwdGVyfSBbYWRhcHRlcl0gLSBUaGUgYWRhcHRlciBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgc3RhdGUgZGF0YWJhc2VcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXk8T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZz59IFt0cmFja2VkRXZlbnRzXSAtIEV2ZW50cyB0byB0cmFjayBmb3Igb2JzZXJ2ZXIgbm90aWZpY2F0aW9uc1xuICpcbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3QgY2xhc3NcbiAqIGltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSwgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIEB0YWJsZSgnYXNzZXRzJylcbiAqIGNsYXNzIEFzc2V0IGV4dGVuZHMgTW9kZWwge1xuICogICBAaWQoKVxuICogICBpZDogc3RyaW5nO1xuICpcbiAqICAgQHByb3BlcnR5KClcbiAqICAgZGF0YTogc3RyaW5nO1xuICogfVxuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBwcml2YXRlIGFkYXB0ZXIgPSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyKCk7XG4gKiAgIHByaXZhdGUgcmVwb3NpdG9yeTogRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PEFzc2V0PjtcbiAqXG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKCdNeUNvbnRyYWN0Jyk7XG4gKiAgICAgdGhpcy5yZXBvc2l0b3J5ID0gbmV3IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxBc3NldD4odGhpcy5hZGFwdGVyLCBBc3NldCk7XG4gKiAgIH1cbiAqXG4gKiAgIEBUcmFuc2FjdGlvbigpXG4gKiAgIGFzeW5jIGNyZWF0ZUFzc2V0KGN0eDogQ29udGV4dCwgaWQ6IHN0cmluZywgZGF0YTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gKiAgICAgY29uc3QgYXNzZXQgPSBuZXcgQXNzZXQoKTtcbiAqICAgICBhc3NldC5pZCA9IGlkO1xuICogICAgIGFzc2V0LmRhdGEgPSBkYXRhO1xuICpcbiAqICAgICBhd2FpdCB0aGlzLnJlcG9zaXRvcnkuY3JlYXRlKGFzc2V0LCB7IHN0dWI6IGN0eC5zdHViIH0pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAqXG4gKiAgIENvbnRyYWN0LT4+UmVwb3NpdG9yeTogY3JlYXRlKG1vZGVsLCBjdHgpXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiBwcmVwYXJlKG1vZGVsLCBwaylcbiAqICAgUmVwb3NpdG9yeS0+PkFkYXB0ZXI6IGNyZWF0ZSh0YWJsZU5hbWUsIGlkLCByZWNvcmQsIHRyYW5zaWVudCwgY3R4KVxuICogICBBZGFwdGVyLT4+U3RhdGVEQjogcHV0U3RhdGUoaWQsIHNlcmlhbGl6ZWREYXRhKVxuICogICBTdGF0ZURCLS0+PkFkYXB0ZXI6IFN1Y2Nlc3NcbiAqICAgQWRhcHRlci0tPj5SZXBvc2l0b3J5OiByZWNvcmRcbiAqICAgUmVwb3NpdG9yeS0+PkFkYXB0ZXI6IHJldmVydChyZWNvcmQsIGNsYXNzLCBwaywgaWQsIHRyYW5zaWVudClcbiAqICAgQWRhcHRlci0tPj5SZXBvc2l0b3J5OiBtb2RlbFxuICogICBSZXBvc2l0b3J5LS0+PkNvbnRyYWN0OiBtb2RlbFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PE0gZXh0ZW5kcyBNb2RlbD4gZXh0ZW5kcyBSZXBvc2l0b3J5PFxuICBNLFxuICBGYWJyaWNDb250cmFjdEFkYXB0ZXJcbj4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyPzogRmFicmljQ29udHJhY3RBZGFwdGVyLFxuICAgIGNsYXp6PzogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvdGVjdGVkIHRyYWNrZWRFdmVudHM/OiAoT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZylbXVxuICApIHtcbiAgICBzdXBlcihhZGFwdGVyLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIG9ic2VydmVyIGhhbmRsZXIgZm9yIHRoaXMgcmVwb3NpdG9yeVxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgaW5zdGFuY2VcbiAgICogQHJldHVybiB7T2JzZXJ2ZXJIYW5kbGVyfSBUaGUgb2JzZXJ2ZXIgaGFuZGxlclxuICAgKi9cbiAgb3ZlcnJpZGUgT2JzZXJ2ZXJIYW5kbGVyKCk6IE9ic2VydmVySGFuZGxlciB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG9ic2VydmVycyBiYXNlZCBvbiB0cmFja2VkIGV2ZW50c1xuICAgKiBAc3VtbWFyeSBGaWx0ZXJzIGV2ZW50cyBiYXNlZCBvbiB0cmFja2VkRXZlbnRzIGFuZCBkZWxlZ2F0ZXMgdG8gdGhlIHBhcmVudCBtZXRob2RcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlIC0gVGhlIHRhYmxlL2NvbGxlY3Rpb24gbmFtZVxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmd9IGV2ZW50IC0gVGhlIGV2ZW50IHR5cGVcbiAgICogQHBhcmFtIHtFdmVudElkc30gaWQgLSBUaGUgZXZlbnQgaWRlbnRpZmllclxuICAgKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY3R4IC0gVGhlIEZhYnJpYyBjb250cmFjdCBjb250ZXh0XG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBvYnNlcnZlcnMgYXJlIHVwZGF0ZWRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZU9ic2VydmVycyhcbiAgICB0YWJsZTogQ29uc3RydWN0b3I8TT4gfCBzdHJpbmcsXG4gICAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcsXG4gICAgaWQ6IEV2ZW50SWRzLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnRyYWNrZWRFdmVudHMgfHwgdGhpcy50cmFja2VkRXZlbnRzLmluZGV4T2YoZXZlbnQpICE9PSAtMSlcbiAgICAgIHJldHVybiBhd2FpdCBzdXBlci51cGRhdGVPYnNlcnZlcnModGFibGUsIGV2ZW50LCBpZCwgLi4uYXJncyk7XG4gIH1cbn1cbiIsImltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHtcbiAgQ291Y2hEQkFkYXB0ZXIsXG4gIENvdWNoREJHcm91cE9wZXJhdG9yLFxuICBDb3VjaERCS2V5cyxcbiAgQ291Y2hEQk9wZXJhdG9yLFxuICBNYW5nb09wZXJhdG9yLFxuICBNYW5nb1F1ZXJ5LFxuICBNYW5nb1NlbGVjdG9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IENvdWNoREJTdGF0ZW1lbnQgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5pbXBvcnQgeyBDb25kaXRpb24sIE9yZGVyRGlyZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN0YXRlbWVudCB3cmFwcGVyIGZvciBleGVjdXRpbmcgTWFuZ28gcXVlcmllcyB3aXRoaW4gRmFicmljIGNvbnRyYWN0c1xuICogQHN1bW1hcnkgQnJpZGdlcyBDb3VjaERCLXN0eWxlIHF1ZXJpZXMgdG8gRmFicmljIHZpYSB0aGUgRmFicmljQ29udHJhY3RBZGFwdGVyLCBoYW5kbGluZyBpZGVudGl0eSBhbmQgcHJpbWFyeSBrZXkgcHJvamVjdGlvbiB3aGVuIG5lZWRlZC5cbiAqIEB0ZW1wbGF0ZSBNIC0gTW9kZWwgdHlwZSB0aGlzIHN0YXRlbWVudCBvcGVyYXRlcyBvblxuICogQHRlbXBsYXRlIFIgLSBSZXN1bHQgdHlwZSByZXR1cm5lZCBieSB0aGUgc3RhdGVtZW50XG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0QWRhcHRlcn0gYWRhcHRlciAtIFRoZSBGYWJyaWMgY29udHJhY3QgYWRhcHRlciB1c2VkIGZvciByYXcgZXhlY3V0aW9uXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY3R4IC0gVGhlIEZhYnJpYyBjb250cmFjdCBjb250ZXh0IGNhcnJ5aW5nIHN0dWIgYW5kIGlkZW50aXR5XG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEZhYnJpY1N0YXRlbWVudFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHN0bXQgPSBuZXcgRmFicmljU3RhdGVtZW50PE15TW9kZWwsIE15TW9kZWxbXT4oYWRhcHRlciwgY3R4KTtcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0bXQucmF3PE15TW9kZWxbXT4oeyBzZWxlY3RvcjogeyB0eXBlOiAnTXlNb2RlbCcgfSB9KTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlbWVudFxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IExlZGdlclxuICogICBBcHAtPj5TdGF0ZW1lbnQ6IHJhdyh7IHNlbGVjdG9yIH0pXG4gKiAgIFN0YXRlbWVudC0+PkFkYXB0ZXI6IGFkYXB0ZXIucmF3KG1hbmdvLCB0cnVlLCBjdHgpXG4gKiAgIEFkYXB0ZXItPj5MZWRnZXI6IEV2YWx1YXRlIHF1ZXJ5XG4gKiAgIEFkYXB0ZXItLT4+U3RhdGVtZW50OiByb3dzXG4gKiAgIFN0YXRlbWVudC0tPj5BcHA6IG1vZGVsc1xuICovXG5leHBvcnQgY2xhc3MgRmFicmljU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBDb3VjaERCU3RhdGVtZW50PFxuICBNLFxuICBDb3VjaERCQWRhcHRlcjxhbnksIHZvaWQsIEZhYnJpY0NvbnRyYWN0Q29udGV4dD4sXG4gIFJcbj4ge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBDb3VjaERCQWRhcHRlcjxhbnksIHZvaWQsIEZhYnJpY0NvbnRyYWN0Q29udGV4dD4pIHtcbiAgICBzdXBlcihhZGFwdGVyKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHJhdzxSPihyYXdJbnB1dDogTWFuZ29RdWVyeSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yYXcpO1xuXG4gICAgY29uc3QgcmVzdWx0czogYW55W10gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KHJhd0lucHV0LCB0cnVlLCBjdHgpO1xuXG4gICAgY29uc3QgcGtBdHRyID0gTW9kZWwucGsodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS5nZXQoXG4gICAgICB0aGlzLmZyb21TZWxlY3RvcixcbiAgICAgIE1ldGFkYXRhLmtleShEQktleXMuSUQsIHBrQXR0ciBhcyBzdHJpbmcpXG4gICAgKT8udHlwZTtcblxuICAgIGlmICghdGhpcy5zZWxlY3RTZWxlY3RvcilcbiAgICAgIHJldHVybiByZXN1bHRzLm1hcCgocikgPT4gdGhpcy5wcm9jZXNzUmVjb3JkKHIsIHBrQXR0ciwgdHlwZSwgY3R4KSkgYXMgUjtcbiAgICByZXR1cm4gcmVzdWx0cyBhcyBSO1xuICB9XG5cbiAgb3ZlcnJpZGUgYnVpbGQoKTogTWFuZ29RdWVyeSB7XG4gICAgY29uc3Qgc2VsZWN0b3JzOiBNYW5nb1NlbGVjdG9yID0ge307XG4gICAgc2VsZWN0b3JzW0NvdWNoREJLZXlzLlRBQkxFXSA9IHt9O1xuICAgIHNlbGVjdG9yc1tDb3VjaERCS2V5cy5UQUJMRV0gPSBNb2RlbC50YWJsZU5hbWUodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IHF1ZXJ5OiBNYW5nb1F1ZXJ5ID0geyBzZWxlY3Rvcjogc2VsZWN0b3JzIH07XG4gICAgaWYgKHRoaXMuc2VsZWN0U2VsZWN0b3IpIHF1ZXJ5LmZpZWxkcyA9IHRoaXMuc2VsZWN0U2VsZWN0b3IgYXMgc3RyaW5nW107XG5cbiAgICBpZiAodGhpcy53aGVyZUNvbmRpdGlvbikge1xuICAgICAgY29uc3QgY29uZGl0aW9uOiBNYW5nb1NlbGVjdG9yID0gdGhpcy5wYXJzZUNvbmRpdGlvbihcbiAgICAgICAgQ29uZGl0aW9uLmFuZChcbiAgICAgICAgICB0aGlzLndoZXJlQ29uZGl0aW9uLFxuICAgICAgICAgIENvbmRpdGlvbi5hdHRyaWJ1dGU8TT4oQ291Y2hEQktleXMuVEFCTEUgYXMga2V5b2YgTSkuZXEoXG4gICAgICAgICAgICBxdWVyeS5zZWxlY3RvcltDb3VjaERCS2V5cy5UQUJMRV1cbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc2VsZWN0b3I7XG4gICAgICBjb25zdCBzZWxlY3RvcktleXMgPSBPYmplY3Qua2V5cyhjb25kaXRpb24pIGFzIE1hbmdvT3BlcmF0b3JbXTtcbiAgICAgIGlmIChcbiAgICAgICAgc2VsZWN0b3JLZXlzLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICBPYmplY3QudmFsdWVzKENvdWNoREJHcm91cE9wZXJhdG9yKS5pbmRleE9mKHNlbGVjdG9yS2V5c1swXSkgIT09IC0xXG4gICAgICApXG4gICAgICAgIHN3aXRjaCAoc2VsZWN0b3JLZXlzWzBdKSB7XG4gICAgICAgICAgY2FzZSBDb3VjaERCR3JvdXBPcGVyYXRvci5BTkQ6XG4gICAgICAgICAgICBjb25kaXRpb25bQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EXSA9IFtcbiAgICAgICAgICAgICAgLi4uT2JqZWN0LnZhbHVlcyhcbiAgICAgICAgICAgICAgICBjb25kaXRpb25bQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EXSBhcyBNYW5nb1NlbGVjdG9yXG4gICAgICAgICAgICAgICkucmVkdWNlKChhY2N1bTogTWFuZ29TZWxlY3RvcltdLCB2YWw6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyh2YWwpO1xuICAgICAgICAgICAgICAgIGlmIChrZXlzLmxlbmd0aCAhPT0gMSlcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJUb28gbWFueSBrZXlzIGluIHF1ZXJ5IHNlbGVjdG9yLiBzaG91bGQgYmUgb25lXCJcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgayA9IGtleXNbMF07XG4gICAgICAgICAgICAgICAgaWYgKGsgPT09IENvdWNoREJHcm91cE9wZXJhdG9yLkFORClcbiAgICAgICAgICAgICAgICAgIGFjY3VtLnB1c2goLi4uKHZhbFtrXSBhcyBhbnlbXSkpO1xuICAgICAgICAgICAgICAgIGVsc2UgYWNjdW0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgICAgICAgfSwgW10pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yID0gY29uZGl0aW9uO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBDb3VjaERCR3JvdXBPcGVyYXRvci5PUjoge1xuICAgICAgICAgICAgY29uc3QgczogUmVjb3JkPGFueSwgYW55PiA9IHt9O1xuICAgICAgICAgICAgc1tDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdID0gW1xuICAgICAgICAgICAgICBjb25kaXRpb24sXG4gICAgICAgICAgICAgIC4uLk9iamVjdC5lbnRyaWVzKHF1ZXJ5LnNlbGVjdG9yKS5tYXAoKFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxhbnksIGFueT4gPSB7fTtcbiAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBxdWVyeS5zZWxlY3RvciA9IHM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgc2hvdWxkIGJlIGltcG9zc2libGVcIik7XG4gICAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBPYmplY3QuZW50cmllcyhjb25kaXRpb24pLmZvckVhY2goKFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgICBpZiAocXVlcnkuc2VsZWN0b3Jba2V5XSlcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgYEEgJHtrZXl9IHF1ZXJ5IHBhcmFtIGlzIGFib3V0IHRvIGJlIG92ZXJyaWRkZW46ICR7cXVlcnkuc2VsZWN0b3Jba2V5XX0gYnkgJHt2YWx9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBxdWVyeS5zZWxlY3RvcltrZXldID0gdmFsO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcmRlckJ5U2VsZWN0b3IpIHtcbiAgICAgIHF1ZXJ5LnNvcnQgPSBxdWVyeS5zb3J0IHx8IFtdO1xuICAgICAgcXVlcnkuc2VsZWN0b3IgPSBxdWVyeS5zZWxlY3RvciB8fCAoe30gYXMgTWFuZ29TZWxlY3Rvcik7XG4gICAgICBjb25zdCBbc2VsZWN0b3IsIHZhbHVlXSA9IHRoaXMub3JkZXJCeVNlbGVjdG9yIGFzIFtcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBPcmRlckRpcmVjdGlvbixcbiAgICAgIF07XG4gICAgICBjb25zdCByZWM6IGFueSA9IHt9O1xuICAgICAgcmVjW3NlbGVjdG9yXSA9IHZhbHVlO1xuICAgICAgKHF1ZXJ5LnNvcnQgYXMgYW55W10pLnB1c2gocmVjIGFzIGFueSk7XG4gICAgICBpZiAoIXF1ZXJ5LnNlbGVjdG9yW3NlbGVjdG9yXSkge1xuICAgICAgICBxdWVyeS5zZWxlY3RvcltzZWxlY3Rvcl0gPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgICAocXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdIGFzIE1hbmdvU2VsZWN0b3IpW0NvdWNoREJPcGVyYXRvci5CSUdHRVJdID1cbiAgICAgICAgICBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmxpbWl0U2VsZWN0b3IpIHF1ZXJ5LmxpbWl0ID0gdGhpcy5saW1pdFNlbGVjdG9yO1xuXG4gICAgaWYgKHRoaXMub2Zmc2V0U2VsZWN0b3IpIHF1ZXJ5LnNraXAgPSB0aGlzLm9mZnNldFNlbGVjdG9yO1xuXG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBLZXlzIHVzZWQgdG8gbWFyayBGYWJyaWMtc3BlY2lmaWMgbW9kZWwgbWV0YWRhdGFcbiAqIEBzdW1tYXJ5IEVudW1lcmF0aW9uIG9mIHNwZWNpYWwga2V5cyB1c2VkIGJ5IHRoZSBzZXJpYWxpemF0aW9uIGxheWVyIHRvIHBlcnNpc3QgRmFicmljLXJlbGF0ZWQgZmxhZ3Mgb24gbW9kZWxzXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBlbnVtIEZhYnJpY01vZGVsS2V5cyB7XG4gIC8qKiBQcml2YXRlIGRhdGEgbWFya2VyIHVzZWQgdG8gdGFnIHByb3BlcnRpZXMgb3IgbW9kZWxzIGZvciBGYWJyaWMgcHJpdmF0ZSBjb2xsZWN0aW9ucyAqL1xuICBQUklWQVRFID0gXCJwcml2YXRlXCIsXG4gIFNIQVJFRCA9IFwic2hhcmVkXCIsXG4gIC8qKiBOYW1lc3BhY2UgcHJlZml4IHVzZWQgZm9yIEZhYnJpYy1zcGVjaWZpYyBtZXRhZGF0YSBrZXlzICovXG4gIEZBQlJJQyA9IFwiZmFicmljLlwiLFxuICBPV05FREJZID0gXCJvd25lZC1ieVwiLFxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3VwcG9ydGVkIGlkZW50aXR5IHR5cGVzIGZvciBGYWJyaWMgY3JlZGVudGlhbHNcbiAqIEBzdW1tYXJ5IEVudW1lcmF0aW9uIG9mIGlkZW50aXR5IGZvcm1hdHMgcmVjb2duaXplZCBieSB0aGlzIGxpYnJhcnlcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGVudW0gSWRlbnRpdHlUeXBlIHtcbiAgLyoqIFN0YW5kYXJkIFguNTA5IGlkZW50aXR5IGZvcm1hdCB1c2VkIGJ5IEh5cGVybGVkZ2VyIEZhYnJpYyAqL1xuICBYNTA5ID0gXCJYLjUwOVwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdHJpbmcgaWRlbnRpZmllciBmb3IgdGhlIEZhYnJpYyBhZGFwdGVyIGZsYXZvdXJcbiAqIEBzdW1tYXJ5IFVzZWQgdG8gdGFnIGFkYXB0ZXJzL3JlcG9zaXRvcmllcyB0aGF0IG9wZXJhdGUgYWdhaW5zdCBIeXBlcmxlZGdlciBGYWJyaWNcbiAqIEBjb25zdCBGYWJyaWNGbGF2b3VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBjb25zdCBGYWJyaWNGbGF2b3VyID0gXCJobGYtZmFicmljXCI7XG4iLCJpbXBvcnQgeyBKU09OU2VyaWFsaXplciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgb3ZlcnJpZGUgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcsIHRhYmxlTmFtZT86IHN0cmluZyk6IE0ge1xuICAgIGNvbnN0IGRlc2VyaWFsaXphdGlvbiA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICAvLyBjb25zdCBjbGFzc05hbWUgPSB0YWJsZU5hbWU7XG4gICAgLy8gaWYgKCFjbGFzc05hbWUpXG4gICAgLy8gICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBjbGFzcyByZWZlcmVuY2UgaW4gc2VyaWFsaXplZCBtb2RlbFwiKTtcblxuICAgIC8vIC8vIHRoaXMgd2lsbCByZXR1cm4gdW5kZWZpbmVkIHZhbHVlc1xuICAgIC8vIGNvbnN0IG1vZGVsOiBNID0gTW9kZWwuYnVpbGQoZGVzZXJpYWxpemF0aW9uLCBjbGFzc05hbWUpIGFzIHVua25vd24gYXMgTTtcblxuICAgIC8vIC8vIFBvcHVsYXRlIE1vZGVsXG4gICAgLy8gY29uc3QgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbiA9IE9iamVjdC5rZXlzKG1vZGVsKS5yZWR1Y2UoXG4gICAgLy8gICAoYWNjdW06IE0sIGtleSkgPT4ge1xuICAgIC8vICAgICAoYWNjdW0gYXMgUmVjb3JkPHN0cmluZywgYW55Pilba2V5XSA9XG4gICAgLy8gICAgICAgZGVzZXJpYWxpemF0aW9uW1JlcG9zaXRvcnkuY29sdW1uKGFjY3VtLCBrZXkpXTtcbiAgICAvLyAgICAgcmV0dXJuIGFjY3VtO1xuICAgIC8vICAgfSxcbiAgICAvLyAgIG1vZGVsXG4gICAgLy8gKTtcblxuICAgIC8vIGNvbnN0IHJlc3VsdCA9IE1vZGVsLmJ1aWxkKFxuICAgIC8vICAgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbixcbiAgICAvLyAgIGNsYXNzTmFtZVxuICAgIC8vICkgYXMgdW5rbm93biBhcyBNO1xuXG4gICAgLy8gcmV0dXJuIHJlc3VsdDtcbiAgICByZXR1cm4gZGVzZXJpYWxpemF0aW9uO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHN0cmluZ2lmeSA9IHJlcXVpcmUoXCJqc29uLXN0cmluZ2lmeS1kZXRlcm1pbmlzdGljXCIpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3Qgc29ydEtleXNSZWN1cnNpdmUgPSByZXF1aXJlKFwic29ydC1rZXlzLXJlY3Vyc2l2ZVwiKTtcbiAgICByZXR1cm4gc3RyaW5naWZ5KHNvcnRLZXlzUmVjdXJzaXZlKHRoaXMucHJlU2VyaWFsaXplKG1vZGVsKSkpO1xuICB9XG5cbiAgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgcmV0dXJuIHRvU2VyaWFsaXplO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBjYWNoZU1vZGVsRm9yUG9wdWxhdGUsXG4gIENhc2NhZGUsXG4gIGNyZWF0ZU9yVXBkYXRlLFxuICBnZXRQb3B1bGF0ZUtleSxcbiAgUmVsYXRpb25zTWV0YWRhdGEsXG4gIFJlcG8sXG4gIFJlcG9zaXRvcnksXG4gIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29udGV4dE9mUmVwb3NpdG9yeSwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCBjcmVhdGlvblxuICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgb25lLXRvLW9uZSByZWxhdGlvbnNoaXAgd2hlbiBjcmVhdGluZyBhIG1vZGVsLCBlaXRoZXIgYnkgcmVmZXJlbmNpbmcgYW4gZXhpc3RpbmcgbW9kZWwgb3IgY3JlYXRpbmcgYSBuZXcgb25lXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBSZXBvPE0sIEYsIEM+XG4gKiBAdGVtcGxhdGUgViAtIFRoZSByZWxhdGlvbnMgbWV0YWRhdGEgdHlwZSBleHRlbmRpbmcgUmVsYXRpb25zTWV0YWRhdGFcbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZVxuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlIGV4dGVuZGluZyBDb250ZXh0PEY+XG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZVxuICogQHBhcmFtIHtDb250ZXh0PEY+fSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSByZWxhdGlvbnMgbWV0YWRhdGFcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IG9mIHRoZSByZWxhdGlvbnNoaXBcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2VcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBjb21wbGV0ZVxuICogQGZ1bmN0aW9uIG9uZVRvT25lT25DcmVhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Y29yZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgb25lVG9PbmVPbkNyZWF0ZVxuICogICBwYXJ0aWNpcGFudCByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCBSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZVxuICpcbiAqICAgQ2FsbGVyLT4+b25lVG9PbmVPbkNyZWF0ZTogdGhpcywgY29udGV4dCwgZGF0YSwga2V5LCBtb2RlbFxuICogICBvbmVUb09uZU9uQ3JlYXRlLT4+b25lVG9PbmVPbkNyZWF0ZTogY2hlY2sgaWYgcHJvcGVydHlWYWx1ZSBleGlzdHNcbiAqXG4gKiAgIGFsdCBwcm9wZXJ0eVZhbHVlIGlzIG5vdCBhbiBvYmplY3RcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+cmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGE6IG1vZGVsLCBrZXlcbiAqICAgICByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YS0tPj5vbmVUb09uZU9uQ3JlYXRlOiBpbm5lclJlcG9cbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+aW5uZXJSZXBvOiByZWFkKHByb3BlcnR5VmFsdWUpXG4gKiAgICAgaW5uZXJSZXBvLS0+Pm9uZVRvT25lT25DcmVhdGU6IHJlYWRcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBwcm9wZXJ0eVZhbHVlLCByZWFkXG4gKiAgICAgb25lVG9PbmVPbkNyZWF0ZS0+Pm9uZVRvT25lT25DcmVhdGU6IHNldCBtb2RlbFtrZXldID0gcHJvcGVydHlWYWx1ZVxuICogICBlbHNlIHByb3BlcnR5VmFsdWUgaXMgYW4gb2JqZWN0XG4gKiAgICAgb25lVG9PbmVPbkNyZWF0ZS0+Pk1vZGVsOiBnZXQoZGF0YS5jbGFzcylcbiAqICAgICBNb2RlbC0tPj5vbmVUb09uZU9uQ3JlYXRlOiBjb25zdHJ1Y3RvclxuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5SZXBvc2l0b3J5OiBmb3JNb2RlbChjb25zdHJ1Y3RvcilcbiAqICAgICBSZXBvc2l0b3J5LS0+Pm9uZVRvT25lT25DcmVhdGU6IHJlcG9cbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+cmVwbzogY3JlYXRlKHByb3BlcnR5VmFsdWUpXG4gKiAgICAgcmVwby0tPj5vbmVUb09uZU9uQ3JlYXRlOiBjcmVhdGVkXG4gKiAgICAgb25lVG9PbmVPbkNyZWF0ZS0+PmZpbmRQcmltYXJ5S2V5OiBjcmVhdGVkXG4gKiAgICAgZmluZFByaW1hcnlLZXktLT4+b25lVG9PbmVPbkNyZWF0ZTogcGtcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBjcmVhdGVkW3BrXSwgY3JlYXRlZFxuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5vbmVUb09uZU9uQ3JlYXRlOiBzZXQgbW9kZWxba2V5XSA9IGNyZWF0ZWRbcGtdXG4gKiAgIGVuZFxuICpcbiAqICAgb25lVG9PbmVPbkNyZWF0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvT25lT25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogRmFicmljQ29udHJhY3RDb250ZXh0LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJvcGVydHlWYWx1ZTogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlKSByZXR1cm47XG5cbiAgaWYgKHR5cGVvZiBwcm9wZXJ0eVZhbHVlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgY29uc3QgaW5uZXJSZXBvID0gcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEoXG4gICAgICBtb2RlbCxcbiAgICAgIGtleSxcbiAgICAgIHRoaXMuYWRhcHRlci5hbGlhc1xuICAgICk7XG4gICAgY29uc3QgcmVhZCA9IGF3YWl0IGlubmVyUmVwby5yZWFkKHByb3BlcnR5VmFsdWUsIGNvbnRleHQpO1xuICAgIGF3YWl0IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZShjb250ZXh0LCBtb2RlbCwga2V5LCBwcm9wZXJ0eVZhbHVlLCByZWFkKTtcbiAgICAobW9kZWwgYXMgYW55KVtrZXldID0gcHJvcGVydHlWYWx1ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBkYXRhLmNsYXNzID1cbiAgICB0eXBlb2YgZGF0YS5jbGFzcyA9PT0gXCJzdHJpbmdcIiA/IGRhdGEuY2xhc3MgOiAoZGF0YS5jbGFzcyBhcyBhbnkpKCkubmFtZTtcblxuICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChkYXRhLmNsYXNzIGFzIHVua25vd24gYXMgc3RyaW5nKTtcbiAgaWYgKCFjb25zdHJ1Y3RvcilcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgQ291bGQgbm90IGZpbmQgbW9kZWwgJHtkYXRhLmNsYXNzfWApO1xuICBjb25zdCByZXBvOiBSZXBvPGFueT4gPSBSZXBvc2l0b3J5LmZvck1vZGVsKGNvbnN0cnVjdG9yLCB0aGlzLmFkYXB0ZXIuYWxpYXMpO1xuICBjb25zdCBjcmVhdGVkID0gYXdhaXQgcmVwby5jcmVhdGUocHJvcGVydHlWYWx1ZSwgY29udGV4dCk7XG4gIGNvbnN0IHBrID0gTW9kZWwucGsoY3JlYXRlZCk7XG4gIGF3YWl0IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZShjb250ZXh0LCBtb2RlbCwga2V5LCBjcmVhdGVkW3BrXSwgY3JlYXRlZCk7XG4gIChtb2RlbCBhcyBhbnkpW2tleV0gPSBjcmVhdGVkW3BrXTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCB1cGRhdGVzXG4gKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCB3aGVuIHVwZGF0aW5nIGEgbW9kZWwsIGVpdGhlciBieSByZWZlcmVuY2luZyBhbiBleGlzdGluZyBtb2RlbCBvciB1cGRhdGluZyB0aGUgcmVsYXRlZCBtb2RlbFxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgUmVwbzxNLCBGLCBDPlxuICogQHRlbXBsYXRlIFYgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhIHR5cGUgZXh0ZW5kaW5nIFJlbGF0aW9uc01ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGVcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtSfSB0aGlzIC0gVGhlIHJlcG9zaXRvcnkgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29udGV4dDxGPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSBvZiB0aGUgcmVsYXRpb25zaGlwXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgY29tcGxldGVcbiAqIEBmdW5jdGlvbiBvbmVUb09uZU9uVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmNvcmVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IG9uZVRvT25lT25VcGRhdGVcbiAqICAgcGFydGljaXBhbnQgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGFcbiAqICAgcGFydGljaXBhbnQgY3JlYXRlT3JVcGRhdGVcbiAqICAgcGFydGljaXBhbnQgZmluZFByaW1hcnlLZXlcbiAqICAgcGFydGljaXBhbnQgY2FjaGVNb2RlbEZvclBvcHVsYXRlXG4gKlxuICogICBDYWxsZXItPj5vbmVUb09uZU9uVXBkYXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvT25lT25VcGRhdGUtPj5vbmVUb09uZU9uVXBkYXRlOiBjaGVjayBpZiBwcm9wZXJ0eVZhbHVlIGV4aXN0c1xuICogICBvbmVUb09uZU9uVXBkYXRlLT4+b25lVG9PbmVPblVwZGF0ZTogY2hlY2sgaWYgY2FzY2FkZS51cGRhdGUgaXMgQ0FTQ0FERVxuICpcbiAqICAgYWx0IHByb3BlcnR5VmFsdWUgaXMgbm90IGFuIG9iamVjdFxuICogICAgIG9uZVRvT25lT25VcGRhdGUtPj5yZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YTogbW9kZWwsIGtleVxuICogICAgIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLS0+Pm9uZVRvT25lT25VcGRhdGU6IGlubmVyUmVwb1xuICogICAgIG9uZVRvT25lT25VcGRhdGUtPj5pbm5lclJlcG86IHJlYWQocHJvcGVydHlWYWx1ZSlcbiAqICAgICBpbm5lclJlcG8tLT4+b25lVG9PbmVPblVwZGF0ZTogcmVhZFxuICogICAgIG9uZVRvT25lT25VcGRhdGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIHByb3BlcnR5VmFsdWUsIHJlYWRcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+b25lVG9PbmVPblVwZGF0ZTogc2V0IG1vZGVsW2tleV0gPSBwcm9wZXJ0eVZhbHVlXG4gKiAgIGVsc2UgcHJvcGVydHlWYWx1ZSBpcyBhbiBvYmplY3RcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+Y3JlYXRlT3JVcGRhdGU6IG1vZGVsW2tleV0sIGNvbnRleHRcbiAqICAgICBjcmVhdGVPclVwZGF0ZS0tPj5vbmVUb09uZU9uVXBkYXRlOiB1cGRhdGVkXG4gKiAgICAgb25lVG9PbmVPblVwZGF0ZS0+PmZpbmRQcmltYXJ5S2V5OiB1cGRhdGVkXG4gKiAgICAgZmluZFByaW1hcnlLZXktLT4+b25lVG9PbmVPblVwZGF0ZTogcGtcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCB1cGRhdGVkW3BrXSwgdXBkYXRlZFxuICogICAgIG9uZVRvT25lT25VcGRhdGUtPj5vbmVUb09uZU9uVXBkYXRlOiBzZXQgbW9kZWxba2V5XSA9IHVwZGF0ZWRbcGtdXG4gKiAgIGVuZFxuICpcbiAqICAgb25lVG9PbmVPblVwZGF0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvT25lT25VcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogRmFicmljQ29udHJhY3RDb250ZXh0LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJvcGVydHlWYWx1ZTogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlKSByZXR1cm47XG4gIGlmIChkYXRhLmNhc2NhZGUudXBkYXRlICE9PSBDYXNjYWRlLkNBU0NBREUpIHJldHVybjtcblxuICBpZiAodHlwZW9mIHByb3BlcnR5VmFsdWUgIT09IFwib2JqZWN0XCIpIHtcbiAgICBjb25zdCBpbm5lclJlcG8gPSByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YShcbiAgICAgIG1vZGVsLFxuICAgICAga2V5LFxuICAgICAgdGhpcy5hZGFwdGVyLmFsaWFzXG4gICAgKTtcbiAgICBjb25zdCByZWFkID0gYXdhaXQgaW5uZXJSZXBvLnJlYWQocHJvcGVydHlWYWx1ZSwgY29udGV4dCk7XG4gICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIHByb3BlcnR5VmFsdWUsIHJlYWQpO1xuICAgIChtb2RlbCBhcyBhbnkpW2tleV0gPSBwcm9wZXJ0eVZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHVwZGF0ZWQ6IGFueSA9IGF3YWl0IGNyZWF0ZU9yVXBkYXRlKFxuICAgIG1vZGVsW2tleV0gYXMgTSxcbiAgICBjb250ZXh0LFxuICAgIHRoaXMuYWRhcHRlci5hbGlhc1xuICApO1xuICBjb25zdCBwayA9IE1vZGVsLnBrKHVwZGF0ZWQpO1xuICBhd2FpdCBjYWNoZU1vZGVsRm9yUG9wdWxhdGUoXG4gICAgY29udGV4dCxcbiAgICBtb2RlbCxcbiAgICBrZXksXG4gICAgdXBkYXRlZFtwa10gYXMgc3RyaW5nLFxuICAgIHVwZGF0ZWRcbiAgKTtcbiAgbW9kZWxba2V5XSA9IHVwZGF0ZWRbcGtdO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIG9uZS10by1vbmUgcmVsYXRpb25zaGlwIGRlbGV0aW9uXG4gKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCB3aGVuIGRlbGV0aW5nIGEgbW9kZWwsIGRlbGV0aW5nIHRoZSByZWxhdGVkIG1vZGVsIGlmIGNhc2NhZGUgaXMgZW5hYmxlZFxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgUmVwbzxNLCBGLCBDPlxuICogQHRlbXBsYXRlIFYgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhIHR5cGUgZXh0ZW5kaW5nIFJlbGF0aW9uc01ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGVcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtSfSB0aGlzIC0gVGhlIHJlcG9zaXRvcnkgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29udGV4dDxGPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSBvZiB0aGUgcmVsYXRpb25zaGlwXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgY29tcGxldGVcbiAqIEBmdW5jdGlvbiBvbmVUb09uZU9uRGVsZXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmNvcmVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IG9uZVRvT25lT25EZWxldGVcbiAqICAgcGFydGljaXBhbnQgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGFcbiAqICAgcGFydGljaXBhbnQgY2FjaGVNb2RlbEZvclBvcHVsYXRlXG4gKlxuICogICBDYWxsZXItPj5vbmVUb09uZU9uRGVsZXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvT25lT25EZWxldGUtPj5vbmVUb09uZU9uRGVsZXRlOiBjaGVjayBpZiBwcm9wZXJ0eVZhbHVlIGV4aXN0c1xuICogICBvbmVUb09uZU9uRGVsZXRlLT4+b25lVG9PbmVPbkRlbGV0ZTogY2hlY2sgaWYgY2FzY2FkZS51cGRhdGUgaXMgQ0FTQ0FERVxuICpcbiAqICAgb25lVG9PbmVPbkRlbGV0ZS0+PnJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhOiBtb2RlbCwga2V5XG4gKiAgIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLS0+Pm9uZVRvT25lT25EZWxldGU6IGlubmVyUmVwb1xuICpcbiAqICAgYWx0IHByb3BlcnR5VmFsdWUgaXMgbm90IGEgTW9kZWwgaW5zdGFuY2VcbiAqICAgICBvbmVUb09uZU9uRGVsZXRlLT4+aW5uZXJSZXBvOiBkZWxldGUobW9kZWxba2V5XSwgY29udGV4dClcbiAqICAgICBpbm5lclJlcG8tLT4+b25lVG9PbmVPbkRlbGV0ZTogZGVsZXRlZFxuICogICBlbHNlIHByb3BlcnR5VmFsdWUgaXMgYSBNb2RlbCBpbnN0YW5jZVxuICogICAgIG9uZVRvT25lT25EZWxldGUtPj5pbm5lclJlcG86IGRlbGV0ZShtb2RlbFtrZXldW2lubmVyUmVwby5wa10sIGNvbnRleHQpXG4gKiAgICAgaW5uZXJSZXBvLS0+Pm9uZVRvT25lT25EZWxldGU6IGRlbGV0ZWRcbiAqICAgZW5kXG4gKlxuICogICBvbmVUb09uZU9uRGVsZXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBkZWxldGVkW2lubmVyUmVwby5wa10sIGRlbGV0ZWRcbiAqICAgb25lVG9PbmVPbkRlbGV0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvT25lT25EZWxldGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogRmFicmljQ29udHJhY3RDb250ZXh0LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJvcGVydHlWYWx1ZTogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlKSByZXR1cm47XG4gIGlmIChkYXRhLmNhc2NhZGUudXBkYXRlICE9PSBDYXNjYWRlLkNBU0NBREUpIHJldHVybjtcbiAgY29uc3QgaW5uZXJSZXBvOiBSZXBvPE0+ID0gcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEoXG4gICAgbW9kZWwsXG4gICAga2V5LFxuICAgIHRoaXMuYWRhcHRlci5hbGlhc1xuICApO1xuICBsZXQgZGVsZXRlZDogTTtcbiAgaWYgKCEocHJvcGVydHlWYWx1ZSBpbnN0YW5jZW9mIE1vZGVsKSlcbiAgICBkZWxldGVkID0gYXdhaXQgaW5uZXJSZXBvLmRlbGV0ZShtb2RlbFtrZXldIGFzIHN0cmluZywgY29udGV4dCk7XG4gIGVsc2VcbiAgICBkZWxldGVkID0gYXdhaXQgaW5uZXJSZXBvLmRlbGV0ZShcbiAgICAgIChtb2RlbFtrZXldIGFzIE0pW01vZGVsLnBrKGlubmVyUmVwby5jbGFzcykgYXMga2V5b2YgTV0gYXMgc3RyaW5nLFxuICAgICAgY29udGV4dFxuICAgICk7XG4gIGF3YWl0IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZShcbiAgICBjb250ZXh0LFxuICAgIG1vZGVsLFxuICAgIGtleSxcbiAgICBkZWxldGVkW01vZGVsLnBrKGlubmVyUmVwby5jbGFzcyldIGFzIHN0cmluZyxcbiAgICBkZWxldGVkXG4gICk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgb25lLXRvLW1hbnkgcmVsYXRpb25zaGlwIGNyZWF0aW9uXG4gKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBvbmUtdG8tbWFueSByZWxhdGlvbnNoaXAgd2hlbiBjcmVhdGluZyBhIG1vZGVsLCBlaXRoZXIgYnkgcmVmZXJlbmNpbmcgZXhpc3RpbmcgbW9kZWxzIG9yIGNyZWF0aW5nIG5ldyBvbmVzXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBSZXBvPE0sIEYsIEM+XG4gKiBAdGVtcGxhdGUgViAtIFRoZSByZWxhdGlvbnMgbWV0YWRhdGEgdHlwZSBleHRlbmRpbmcgUmVsYXRpb25zTWV0YWRhdGFcbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZVxuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlIGV4dGVuZGluZyBDb250ZXh0PEY+XG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZVxuICogQHBhcmFtIHtDb250ZXh0PEY+fSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSByZWxhdGlvbnMgbWV0YWRhdGFcbiAqIEBwYXJhbSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IG9mIHRoZSByZWxhdGlvbnNoaXBcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2VcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBjb21wbGV0ZVxuICogQGZ1bmN0aW9uIG9uZVRvTWFueU9uQ3JlYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmNvcmVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IG9uZVRvTWFueU9uQ3JlYXRlXG4gKiAgIHBhcnRpY2lwYW50IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhXG4gKiAgIHBhcnRpY2lwYW50IGNyZWF0ZU9yVXBkYXRlXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRQcmltYXJ5S2V5XG4gKiAgIHBhcnRpY2lwYW50IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZVxuICpcbiAqICAgQ2FsbGVyLT4+b25lVG9NYW55T25DcmVhdGU6IHRoaXMsIGNvbnRleHQsIGRhdGEsIGtleSwgbW9kZWxcbiAqICAgb25lVG9NYW55T25DcmVhdGUtPj5vbmVUb01hbnlPbkNyZWF0ZTogY2hlY2sgaWYgcHJvcGVydHlWYWx1ZXMgZXhpc3RzIGFuZCBoYXMgbGVuZ3RoXG4gKiAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IGNoZWNrIGlmIGFsbCBlbGVtZW50cyBoYXZlIHNhbWUgdHlwZVxuICogICBvbmVUb01hbnlPbkNyZWF0ZS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBjcmVhdGUgdW5pcXVlVmFsdWVzIHNldFxuICpcbiAqICAgYWx0IGFycmF5VHlwZSBpcyBub3QgXCJvYmplY3RcIlxuICogICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+cmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGE6IG1vZGVsLCBrZXlcbiAqICAgICByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YS0tPj5vbmVUb01hbnlPbkNyZWF0ZTogcmVwb1xuICogICAgIGxvb3AgZm9yIGVhY2ggaWQgaW4gdW5pcXVlVmFsdWVzXG4gKiAgICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+PnJlcG86IHJlYWQoaWQpXG4gKiAgICAgICByZXBvLS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiByZWFkXG4gKiAgICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+PmNhY2hlTW9kZWxGb3JQb3B1bGF0ZTogY29udGV4dCwgbW9kZWwsIGtleSwgaWQsIHJlYWRcbiAqICAgICBlbmRcbiAqICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBzZXQgbW9kZWxba2V5XSA9IFsuLi51bmlxdWVWYWx1ZXNdXG4gKiAgIGVsc2UgYXJyYXlUeXBlIGlzIFwib2JqZWN0XCJcbiAqICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+PmZpbmRQcmltYXJ5S2V5OiBwcm9wZXJ0eVZhbHVlc1swXVxuICogICAgIGZpbmRQcmltYXJ5S2V5LS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBwa05hbWVcbiAqICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBjcmVhdGUgcmVzdWx0IHNldFxuICogICAgIGxvb3AgZm9yIGVhY2ggbSBpbiBwcm9wZXJ0eVZhbHVlc1xuICogICAgICAgb25lVG9NYW55T25DcmVhdGUtPj5jcmVhdGVPclVwZGF0ZTogbSwgY29udGV4dFxuICogICAgICAgY3JlYXRlT3JVcGRhdGUtLT4+b25lVG9NYW55T25DcmVhdGU6IHJlY29yZFxuICogICAgICAgb25lVG9NYW55T25DcmVhdGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIHJlY29yZFtwa05hbWVdLCByZWNvcmRcbiAqICAgICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IGFkZCByZWNvcmRbcGtOYW1lXSB0byByZXN1bHRcbiAqICAgICBlbmRcbiAqICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBzZXQgbW9kZWxba2V5XSA9IFsuLi5yZXN1bHRdXG4gKiAgIGVuZFxuICpcbiAqICAgb25lVG9NYW55T25DcmVhdGUtLT4+Q2FsbGVyOiB2b2lkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvbmVUb01hbnlPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PE0+LFxuICBWIGV4dGVuZHMgUmVsYXRpb25zTWV0YWRhdGEsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwcm9wZXJ0eVZhbHVlczogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlcyB8fCAhcHJvcGVydHlWYWx1ZXMubGVuZ3RoKSByZXR1cm47XG4gIGNvbnN0IGFycmF5VHlwZSA9IHR5cGVvZiBwcm9wZXJ0eVZhbHVlc1swXTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlcy5ldmVyeSgoaXRlbTogYW55KSA9PiB0eXBlb2YgaXRlbSA9PT0gYXJyYXlUeXBlKSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBJbnZhbGlkIG9wZXJhdGlvbi4gQWxsIGVsZW1lbnRzIG9mIHByb3BlcnR5ICR7a2V5IGFzIHN0cmluZ30gbXVzdCBtYXRjaCB0aGUgc2FtZSB0eXBlLmBcbiAgICApO1xuICBjb25zdCB1bmlxdWVWYWx1ZXMgPSBuZXcgU2V0KFsuLi5wcm9wZXJ0eVZhbHVlc10pO1xuICBpZiAoYXJyYXlUeXBlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgY29uc3QgcmVwbyA9IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhKG1vZGVsLCBrZXksIHRoaXMuYWRhcHRlci5hbGlhcyk7XG4gICAgZm9yIChjb25zdCBpZCBvZiB1bmlxdWVWYWx1ZXMpIHtcbiAgICAgIGNvbnN0IHJlYWQgPSBhd2FpdCByZXBvLnJlYWQoaWQsIGNvbnRleHQpO1xuICAgICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIGlkLCByZWFkKTtcbiAgICB9XG4gICAgKG1vZGVsIGFzIGFueSlba2V5XSA9IFsuLi51bmlxdWVWYWx1ZXNdO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHBrTmFtZSA9IE1vZGVsLnBrKHByb3BlcnR5VmFsdWVzWzBdKTtcblxuICBjb25zdCByZXN1bHQ6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG4gIGZvciAoY29uc3QgbSBvZiBwcm9wZXJ0eVZhbHVlcykge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IGNyZWF0ZU9yVXBkYXRlKG0sIGNvbnRleHQsIHRoaXMuYWRhcHRlci5hbGlhcyk7XG4gICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIHJlY29yZFtwa05hbWVdLCByZWNvcmQpO1xuICAgIHJlc3VsdC5hZGQocmVjb3JkW3BrTmFtZV0pO1xuICB9XG5cbiAgKG1vZGVsIGFzIGFueSlba2V5XSA9IFsuLi5yZXN1bHRdO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIG9uZS10by1tYW55IHJlbGF0aW9uc2hpcCBkZWxldGlvblxuICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgb25lLXRvLW1hbnkgcmVsYXRpb25zaGlwIHdoZW4gZGVsZXRpbmcgYSBtb2RlbCwgZGVsZXRpbmcgYWxsIHJlbGF0ZWQgbW9kZWxzIGlmIGNhc2NhZGUgZGVsZXRlIGlzIGVuYWJsZWRcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gb25lVG9NYW55T25EZWxldGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Y29yZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgb25lVG9NYW55T25EZWxldGVcbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YVxuICogICBwYXJ0aWNpcGFudCBjYWNoZU1vZGVsRm9yUG9wdWxhdGVcbiAqXG4gKiAgIENhbGxlci0+Pm9uZVRvTWFueU9uRGVsZXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvTWFueU9uRGVsZXRlLT4+b25lVG9NYW55T25EZWxldGU6IGNoZWNrIGlmIGNhc2NhZGUuZGVsZXRlIGlzIENBU0NBREVcbiAqICAgb25lVG9NYW55T25EZWxldGUtPj5vbmVUb01hbnlPbkRlbGV0ZTogY2hlY2sgaWYgdmFsdWVzIGV4aXN0cyBhbmQgaGFzIGxlbmd0aFxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBjaGVjayBpZiBhbGwgZWxlbWVudHMgaGF2ZSBzYW1lIHR5cGVcbiAqXG4gKiAgIGFsdCBpc0luc3RhbnRpYXRlZCAoYXJyYXlUeXBlIGlzIFwib2JqZWN0XCIpXG4gKiAgICAgb25lVG9NYW55T25EZWxldGUtPj5SZXBvc2l0b3J5OiBmb3JNb2RlbCh2YWx1ZXNbMF0pXG4gKiAgICAgUmVwb3NpdG9yeS0tPj5vbmVUb01hbnlPbkRlbGV0ZTogcmVwb1xuICogICBlbHNlIG5vdCBpbnN0YW50aWF0ZWRcbiAqICAgICBvbmVUb01hbnlPbkRlbGV0ZS0+PnJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhOiBtb2RlbCwga2V5XG4gKiAgICAgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEtLT4+b25lVG9NYW55T25EZWxldGU6IHJlcG9cbiAqICAgZW5kXG4gKlxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBjcmVhdGUgdW5pcXVlVmFsdWVzIHNldFxuICpcbiAqICAgbG9vcCBmb3IgZWFjaCBpZCBpbiB1bmlxdWVWYWx1ZXNcbiAqICAgICBvbmVUb01hbnlPbkRlbGV0ZS0+PnJlcG86IGRlbGV0ZShpZCwgY29udGV4dClcbiAqICAgICByZXBvLS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBkZWxldGVkXG4gKiAgICAgb25lVG9NYW55T25EZWxldGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIGlkLCBkZWxldGVkXG4gKiAgIGVuZFxuICpcbiAqICAgb25lVG9NYW55T25EZWxldGUtPj5vbmVUb01hbnlPbkRlbGV0ZTogc2V0IG1vZGVsW2tleV0gPSBbLi4udW5pcXVlVmFsdWVzXVxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvTWFueU9uRGVsZXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8TT4sXG4gIFYgZXh0ZW5kcyBSZWxhdGlvbnNNZXRhZGF0YSxcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChkYXRhLmNhc2NhZGUuZGVsZXRlICE9PSBDYXNjYWRlLkNBU0NBREUpIHJldHVybjtcbiAgY29uc3QgdmFsdWVzID0gbW9kZWxba2V5XSBhcyBhbnk7XG4gIGlmICghdmFsdWVzIHx8ICF2YWx1ZXMubGVuZ3RoKSByZXR1cm47XG4gIGNvbnN0IGFycmF5VHlwZSA9IHR5cGVvZiB2YWx1ZXNbMF07XG4gIGNvbnN0IGFyZUFsbFNhbWVUeXBlID0gdmFsdWVzLmV2ZXJ5KChpdGVtOiBhbnkpID0+IHR5cGVvZiBpdGVtID09PSBhcnJheVR5cGUpO1xuICBpZiAoIWFyZUFsbFNhbWVUeXBlKVxuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYEludmFsaWQgb3BlcmF0aW9uLiBBbGwgZWxlbWVudHMgb2YgcHJvcGVydHkgJHtrZXkgYXMgc3RyaW5nfSBtdXN0IG1hdGNoIHRoZSBzYW1lIHR5cGUuYFxuICAgICk7XG4gIGNvbnN0IGlzSW5zdGFudGlhdGVkID0gYXJyYXlUeXBlID09PSBcIm9iamVjdFwiO1xuICBjb25zdCByZXBvID0gaXNJbnN0YW50aWF0ZWRcbiAgICA/IFJlcG9zaXRvcnkuZm9yTW9kZWwodmFsdWVzWzBdLCB0aGlzLmFkYXB0ZXIuYWxpYXMpXG4gICAgOiByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YShtb2RlbCwga2V5LCB0aGlzLmFkYXB0ZXIuYWxpYXMpO1xuXG4gIGNvbnN0IHVuaXF1ZVZhbHVlcyA9IG5ldyBTZXQoW1xuICAgIC4uLihpc0luc3RhbnRpYXRlZFxuICAgICAgPyB2YWx1ZXMubWFwKFxuICAgICAgICAgICh2OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB2W01vZGVsLnBrKHRoaXMuY2xhc3MpIGFzIHN0cmluZ11cbiAgICAgICAgKVxuICAgICAgOiB2YWx1ZXMpLFxuICBdKTtcblxuICBmb3IgKGNvbnN0IGlkIG9mIHVuaXF1ZVZhbHVlcy52YWx1ZXMoKSkge1xuICAgIGNvbnN0IGRlbGV0ZWQgPSBhd2FpdCByZXBvLmRlbGV0ZShpZCwgY29udGV4dCk7XG4gICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIGlkLCBkZWxldGVkKTtcbiAgfVxuICAobW9kZWwgYXMgYW55KVtrZXldID0gWy4uLnVuaXF1ZVZhbHVlc107XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBvcHVsYXRlcyBhIG1vZGVsJ3MgcmVsYXRpb25zaGlwXG4gKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYW5kIGF0dGFjaGVzIHJlbGF0ZWQgbW9kZWxzIHRvIGEgbW9kZWwncyByZWxhdGlvbnNoaXAgcHJvcGVydHlcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gcG9wdWxhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Y29yZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcG9wdWxhdGVcbiAqICAgcGFydGljaXBhbnQgZmV0Y2hQb3B1bGF0ZVZhbHVlc1xuICogICBwYXJ0aWNpcGFudCBnZXRQb3B1bGF0ZUtleVxuICogICBwYXJ0aWNpcGFudCBDb250ZXh0XG4gKiAgIHBhcnRpY2lwYW50IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhXG4gKlxuICogICBDYWxsZXItPj5wb3B1bGF0ZTogdGhpcywgY29udGV4dCwgZGF0YSwga2V5LCBtb2RlbFxuICogICBwb3B1bGF0ZS0+PnBvcHVsYXRlOiBjaGVjayBpZiBkYXRhLnBvcHVsYXRlIGlzIHRydWVcbiAqICAgcG9wdWxhdGUtPj5wb3B1bGF0ZTogZ2V0IG5lc3RlZCB2YWx1ZSBhbmQgY2hlY2sgaWYgaXQgZXhpc3RzXG4gKlxuICogICBwb3B1bGF0ZS0+PmZldGNoUG9wdWxhdGVWYWx1ZXM6IGNvbnRleHQsIG1vZGVsLCBrZXksIGlzQXJyID8gbmVzdGVkIDogW25lc3RlZF1cbiAqXG4gKiAgIGZldGNoUG9wdWxhdGVWYWx1ZXMtPj5mZXRjaFBvcHVsYXRlVmFsdWVzOiBpbml0aWFsaXplIHZhcmlhYmxlc1xuICpcbiAqICAgbG9vcCBmb3IgZWFjaCBwcm9LZXlWYWx1ZSBpbiBwcm9wS2V5VmFsdWVzXG4gKiAgICAgZmV0Y2hQb3B1bGF0ZVZhbHVlcy0+PmdldFBvcHVsYXRlS2V5OiBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lLCBwcm9wTmFtZSwgcHJvS2V5VmFsdWVcbiAqICAgICBnZXRQb3B1bGF0ZUtleS0tPj5mZXRjaFBvcHVsYXRlVmFsdWVzOiBjYWNoZUtleVxuICpcbiAqICAgICBhbHQgdHJ5IHRvIGdldCBmcm9tIGNhY2hlXG4gKiAgICAgICBmZXRjaFBvcHVsYXRlVmFsdWVzLT4+Q29udGV4dDogZ2V0KGNhY2hlS2V5KVxuICogICAgICAgQ29udGV4dC0tPj5mZXRjaFBvcHVsYXRlVmFsdWVzOiB2YWxcbiAqICAgICBlbHNlIGNhdGNoIGVycm9yXG4gKiAgICAgICBmZXRjaFBvcHVsYXRlVmFsdWVzLT4+cmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGE6IG1vZGVsLCBwcm9wTmFtZVxuICogICAgICAgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEtLT4+ZmV0Y2hQb3B1bGF0ZVZhbHVlczogcmVwb1xuICogICAgICAgZmV0Y2hQb3B1bGF0ZVZhbHVlcy0+PnJlcG86IHJlYWQocHJvS2V5VmFsdWUpXG4gKiAgICAgICByZXBvLS0+PmZldGNoUG9wdWxhdGVWYWx1ZXM6IHZhbFxuICogICAgIGVuZFxuICpcbiAqICAgICBmZXRjaFBvcHVsYXRlVmFsdWVzLT4+ZmV0Y2hQb3B1bGF0ZVZhbHVlczogYWRkIHZhbCB0byByZXN1bHRzXG4gKiAgIGVuZFxuICpcbiAqICAgZmV0Y2hQb3B1bGF0ZVZhbHVlcy0tPj5wb3B1bGF0ZTogcmVzdWx0c1xuICogICBwb3B1bGF0ZS0+PnBvcHVsYXRlOiBzZXQgbW9kZWxba2V5XSA9IGlzQXJyID8gcmVzIDogcmVzWzBdXG4gKiAgIHBvcHVsYXRlLS0+PkNhbGxlcjogdm9pZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcG9wdWxhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG88TT4sXG4gIFYgZXh0ZW5kcyBSZWxhdGlvbnNNZXRhZGF0YSxcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHRPZlJlcG9zaXRvcnk8Uj4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIWRhdGEucG9wdWxhdGUpIHJldHVybjtcbiAgY29uc3QgbmVzdGVkOiBhbnkgPSBtb2RlbFtrZXldO1xuICBjb25zdCBpc0FyciA9IEFycmF5LmlzQXJyYXkobmVzdGVkKTtcbiAgaWYgKHR5cGVvZiBuZXN0ZWQgPT09IFwidW5kZWZpbmVkXCIgfHwgKGlzQXJyICYmIG5lc3RlZC5sZW5ndGggPT09IDApKSByZXR1cm47XG5cbiAgYXN5bmMgZnVuY3Rpb24gZmV0Y2hQb3B1bGF0ZVZhbHVlcyhcbiAgICBjOiBDb250ZXh0T2ZSZXBvc2l0b3J5PFI+LFxuICAgIG1vZGVsOiBNLFxuICAgIHByb3BOYW1lOiBzdHJpbmcsXG4gICAgcHJvcEtleVZhbHVlczogYW55W10sXG4gICAgYWxpYXM/OiBzdHJpbmdcbiAgKSB7XG4gICAgbGV0IGNhY2hlS2V5OiBzdHJpbmc7XG4gICAgbGV0IHZhbDogYW55O1xuICAgIGNvbnN0IHJlc3VsdHM6IE1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcHJvS2V5VmFsdWUgb2YgcHJvcEtleVZhbHVlcykge1xuICAgICAgY2FjaGVLZXkgPSBnZXRQb3B1bGF0ZUtleShtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lLCBwcm9wTmFtZSwgcHJvS2V5VmFsdWUpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFsID0gYXdhaXQgYy5nZXQoY2FjaGVLZXkgYXMgYW55KTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgIGNvbnN0IHJlcG8gPSByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YShcbiAgICAgICAgICBtb2RlbCxcbiAgICAgICAgICBwcm9wTmFtZSBhcyBrZXlvZiBNLFxuICAgICAgICAgIGFsaWFzXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcmVwbykgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCByZXBvXCIpO1xuICAgICAgICB2YWwgPSBhd2FpdCByZXBvLnJlYWQocHJvS2V5VmFsdWUsIGNvbnRleHQpO1xuICAgICAgfVxuICAgICAgcmVzdWx0cy5wdXNoKHZhbCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG4gIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoUG9wdWxhdGVWYWx1ZXMoXG4gICAgY29udGV4dCxcbiAgICBtb2RlbCxcbiAgICBrZXkgYXMgc3RyaW5nLFxuICAgIGlzQXJyID8gbmVzdGVkIDogW25lc3RlZF0sXG4gICAgdGhpcy5hZGFwdGVyLmFsaWFzXG4gICk7XG4gIChtb2RlbCBhcyBhbnkpW2tleV0gPSBpc0FyciA/IHJlcyA6IHJlc1swXTtcbn1cbiIsImltcG9ydCB7XG4gIExvZ2dlckZhY3RvcnksXG4gIExvZ2dpbmcsXG4gIExvZ2dlcixcbiAgTG9nTGV2ZWwsXG4gIE1pbmlMb2dnZXIsXG4gIE51bWVyaWNMb2dMZXZlbHMsXG4gIFN0cmluZ0xpa2UsXG59IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgTG9nZ2luZ0NvbmZpZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ29udGV4dCBhcyBDdHggfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBMb2dnZXIgaW1wbGVtZW50YXRpb24gZm9yIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RzXG4gKiBAc3VtbWFyeSBBZGFwdHMgdGhlIHN0YW5kYXJkIGxvZ2dpbmcgaW50ZXJmYWNlIHRvIHdvcmsgd2l0aCBGYWJyaWMncyBjaGFpbmNvZGUgY29udGV4dFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZXh0IC0gVGhlIGxvZ2dpbmcgY29udGV4dCBuYW1lXG4gKiBAcGFyYW0ge1BhcnRpYWw8TG9nZ2luZ0NvbmZpZz4gfCB1bmRlZmluZWR9IGNvbmYgLSBPcHRpb25hbCBsb2dnaW5nIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gKlxuICogQGNsYXNzIENvbnRyYWN0TG9nZ2VyXG4gKiBAZXh0ZW5kcyB7TWluaUxvZ2dlcn1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RcbiAqIGltcG9ydCB7IENvbnRyYWN0TG9nZ2VyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBteUZ1bmN0aW9uKGN0eDogQ29udGV4dCk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IGxvZ2dlciA9IG5ldyBDb250cmFjdExvZ2dlcignTXlDb250cmFjdCcsIHsgbGV2ZWw6ICdpbmZvJyB9LCBjdHgpO1xuICpcbiAqICAgICBsb2dnZXIuaW5mbygnUHJvY2Vzc2luZyB0cmFuc2FjdGlvbicpO1xuICogICAgIGxvZ2dlci5kZWJ1ZygnVHJhbnNhY3Rpb24gZGV0YWlsczonLCB7IC4uLiB9KTtcbiAqXG4gKiAgICAgLy8gRG8gc29tZXRoaW5nXG4gKlxuICogICAgIGxvZ2dlci5pbmZvKCdUcmFuc2FjdGlvbiBjb21wbGV0ZScpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRyYWN0TG9nZ2VyIGV4dGVuZHMgTWluaUxvZ2dlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHVuZGVybHlpbmcgRmFicmljIGxvZ2dlciBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGxvZ2dlciE6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBjb250ZXh0OiBzdHJpbmcsXG4gICAgY29uZjogUGFydGlhbDxMb2dnaW5nQ29uZmlnPiB8IHVuZGVmaW5lZCxcbiAgICBjdHg/OiBDdHhcbiAgKSB7XG4gICAgc3VwZXIoY29udGV4dCwgY29uZik7XG5cbiAgICBpZiAoIWN0eCkge1xuICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgTWluaUxvZ2dlcihjb250ZXh0LCBjb25mKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sb2dnZXIgPSBjdHgubG9nZ2luZy5nZXRMb2dnZXIoY29udGV4dCkgYXMgdW5rbm93biBhcyBMb2dnZXI7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIGEgbWVzc2FnZSBhdCB0aGUgc3BlY2lmaWVkIGxldmVsXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSBsb2cgbWV0aG9kIHRvIHVzZSB0aGUgRmFicmljIGNvbnRleHQncyBsb2dnZXJcbiAgICogQHBhcmFtIHtMb2dMZXZlbH0gbGV2ZWwgLSBUaGUgbG9nIGxldmVsXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZSB8IEVycm9yfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBsb2dcbiAgICogQHBhcmFtIHtFcnJvcn0gW3N0YWNrXSAtIE9wdGlvbmFsIHN0YWNrIHRyYWNlIGZvciBlcnJvcnNcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBsb2coXG4gICAgbGV2ZWw6IExvZ0xldmVsLFxuICAgIG1zZzogU3RyaW5nTGlrZSB8IEVycm9yLFxuICAgIHN0YWNrPzogRXJyb3JcbiAgKSB7XG4gICAgaWYgKFxuICAgICAgTnVtZXJpY0xvZ0xldmVsc1t0aGlzLmNvbmZpZyhcImxldmVsXCIpIGFzIExvZ0xldmVsXSA8XG4gICAgICBOdW1lcmljTG9nTGV2ZWxzW2xldmVsXVxuICAgIClcbiAgICAgIHJldHVybjtcblxuICAgIGxldCBtZXRob2Q7XG4gICAgc3dpdGNoIChsZXZlbCkge1xuICAgICAgY2FzZSBMb2dMZXZlbC5pbmZvOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5pbmZvO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTG9nTGV2ZWwudmVyYm9zZTpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIudmVyYm9zZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLmRlYnVnOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5kZWJ1ZztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLmVycm9yOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5lcnJvcjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLnNpbGx5OlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5zaWxseTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkludmFsaWQgbG9nIGxldmVsXCIpO1xuICAgIH1cbiAgICBtZXRob2QuY2FsbCh0aGlzLmxvZ2dlciwgdGhpcy5jcmVhdGVMb2cobGV2ZWwsIG1zZywgc3RhY2spKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IGZ1bmN0aW9uIGZvciBjcmVhdGluZyBDb250cmFjdExvZ2dlciBpbnN0YW5jZXNcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgQ29udHJhY3RMb2dnZXIgd2l0aCB0aGUgZ2l2ZW4gY29udGV4dCwgY29uZmlnLCBhbmQgRmFicmljIGNvbnRleHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBvYmplY3QgLSBUaGUgbG9nZ2luZyBjb250ZXh0IG5hbWVcbiAqIEBwYXJhbSB7UGFydGlhbDxMb2dnaW5nQ29uZmlnPiB8IHVuZGVmaW5lZH0gY29uZmlnIC0gT3B0aW9uYWwgbG9nZ2luZyBjb25maWd1cmF0aW9uXG4gKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICogQHJldHVybiB7Q29udHJhY3RMb2dnZXJ9IEEgbmV3IENvbnRyYWN0TG9nZ2VyIGluc3RhbmNlXG4gKiBAZnVuY3Rpb24gZmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpmYWJyaWMuY29udHJhY3RzXG4gKi9cbmNvbnN0IGZhY3Rvcnk6IExvZ2dlckZhY3RvcnkgPSAoXG4gIG9iamVjdD86IHN0cmluZyxcbiAgY29uZmlnPzogUGFydGlhbDxMb2dnaW5nQ29uZmlnPixcbiAgY3R4PzogQ3R4XG4pID0+IHtcbiAgcmV0dXJuIG5ldyBDb250cmFjdExvZ2dlcihcbiAgICBvYmplY3QgfHwgQ29udHJhY3RMb2dnZXIubmFtZSxcbiAgICBjb25maWcgfHwge30sXG4gICAgY3R4IGFzIEN0eFxuICApO1xufTtcblxuLy8gU2V0IHRoZSBmYWN0b3J5IGFzIHRoZSBkZWZhdWx0IGxvZ2dlciBmYWN0b3J5XG5Mb2dnaW5nLnNldEZhY3RvcnkoZmFjdG9yeSk7XG4iLCJpbXBvcnQgeyBDb3VjaERCQWRhcHRlciwgQ291Y2hEQktleXMsIE1hbmdvUXVlcnkgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5pbXBvcnQgeyBsaXN0LCBNb2RlbCwgcmVxdWlyZWQsIHR5cGUgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHtcbiAgYWZ0ZXJBbnksXG4gIEJhZFJlcXVlc3RFcnJvcixcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBEQktleXMsXG4gIEdyb3VwU29ydCxcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbiAgb25DcmVhdGUsXG4gIG9uQ3JlYXRlVXBkYXRlLFxuICBvbkRlbGV0ZSxcbiAgb25VcGRhdGUsXG4gIE9wZXJhdGlvbktleXMsXG4gIFByaW1hcnlLZXlUeXBlLFxuICByZWFkb25seSxcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7XG4gIENvbnRleHQgYXMgQ3R4LFxuICBPYmplY3QgYXMgRmFicmljT2JqZWN0LFxuICBQcm9wZXJ0eSBhcyBGYWJyaWNQcm9wZXJ0eSxcbn0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHtcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBSZWxhdGlvbnNNZXRhZGF0YSxcbiAgU2VxdWVuY2UsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgQWRhcHRlcixcbiAgQ2FzY2FkZU1ldGFkYXRhLFxuICBKb2luQ29sdW1uT3B0aW9ucyxcbiAgb25lVG9NYW55T25VcGRhdGUsXG4gIEpvaW5UYWJsZU9wdGlvbnMsXG4gIEpvaW5UYWJsZU11bHRpcGxlQ29sdW1uc09wdGlvbnMsXG4gIHJlbGF0aW9uLFxuICBQcmVwYXJlZE1vZGVsLFxuICBSZXBvc2l0b3J5LFxuICBRdWVyeUVycm9yLFxuICBQYWdpbmdFcnJvcixcbiAgTWlncmF0aW9uRXJyb3IsXG4gIE9ic2VydmVyRXJyb3IsXG4gIEF1dGhvcml6YXRpb25FcnJvcixcbiAgRm9yYmlkZGVuRXJyb3IsXG4gIENvbm5lY3Rpb25FcnJvcixcbiAgQ29udGV4dHVhbGl6ZWRBcmdzLFxuICBMb2dnZXJPZixcbiAgQ29udGV4dCxcbiAgUmF3UmVzdWx0LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB0eXBlIHsgQ29udGV4dHVhbEFyZ3MsIE1heWJlQ29udGV4dHVhbEFyZyB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XCI7XG5pbXBvcnQge1xuICBDaGFpbmNvZGVTdHViLFxuICBDbGllbnRJZGVudGl0eSxcbiAgSXRlcmF0b3JzLFxuICBTdGF0ZVF1ZXJ5UmVzcG9uc2UsXG59IGZyb20gXCJmYWJyaWMtc2hpbS1hcGlcIjtcbmltcG9ydCB7IEZhYnJpY1N0YXRlbWVudCB9IGZyb20gXCIuL0ZhYnJpY0NvbnRyYWN0U3RhdGVtZW50XCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyIH0gZnJvbSBcIi4uL3NoYXJlZC9TaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplclwiO1xuaW1wb3J0IHtcbiAgb25lVG9NYW55T25DcmVhdGUsXG4gIG9uZVRvTWFueU9uRGVsZXRlLFxuICBvbmVUb09uZU9uQ3JlYXRlLFxuICBvbmVUb09uZU9uRGVsZXRlLFxuICBvbmVUb09uZU9uVXBkYXRlLFxuICBwb3B1bGF0ZSBhcyBwb3AsXG59IGZyb20gXCIuL0ZhYnJpY0NvbnN0cnVjdGlvblwiO1xuaW1wb3J0IHtcbiAgYXBwbHksXG4gIENvbnN0cnVjdG9yLFxuICBEZWNvcmF0aW9uLFxuICBwcm9wLFxuICBwcm9wTWV0YWRhdGEsXG4gIE1ldGFkYXRhLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IENvbnRyYWN0TG9nZ2VyIH0gZnJvbSBcIi4vbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjcmVhdG9yIG9yIHVwZGF0ZXIgZmllbGQgaW4gYSBtb2RlbCBiYXNlZCBvbiB0aGUgdXNlciBpbiB0aGUgY29udGV4dFxuICogQHN1bW1hcnkgQ2FsbGJhY2sgZnVuY3Rpb24gdXNlZCBpbiBkZWNvcmF0b3JzIHRvIGF1dG9tYXRpY2FsbHkgc2V0IHRoZSBjcmVhdGVkX2J5IG9yIHVwZGF0ZWRfYnkgZmllbGRzXG4gKiB3aXRoIHRoZSB1c2VybmFtZSBmcm9tIHRoZSBjb250ZXh0IHdoZW4gYSBkb2N1bWVudCBpcyBjcmVhdGVkIG9yIHVwZGF0ZWRcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgTmFub1JlcG9zaXRvcnk8TT5cbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgUmVsYXRpb25zTWV0YWRhdGFcbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY29udGV4dCAtIFRoZSBvcGVyYXRpb24gY29udGV4dCBjb250YWluaW5nIHVzZXIgaW5mb3JtYXRpb25cbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSByZWxhdGlvbiBtZXRhZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0IHdpdGggdGhlIHVzZXJuYW1lXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIGJlaW5nIGNyZWF0ZWQgb3IgdXBkYXRlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBGIGFzIGNyZWF0ZWRCeU9uTmFub0NyZWF0ZVVwZGF0ZVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENvbnRleHRcbiAqICAgcGFydGljaXBhbnQgTSBhcyBNb2RlbFxuICogICBGLT4+QzogZ2V0KFwidXNlclwiKVxuICogICBDLS0+PkY6IHVzZXIgb2JqZWN0XG4gKiAgIEYtPj5NOiBzZXQga2V5IHRvIHVzZXIubmFtZVxuICogICBOb3RlIG92ZXIgRjogSWYgbm8gdXNlciBpbiBjb250ZXh0XG4gKiAgIEYtLT4+RjogdGhyb3cgVW5zdXBwb3J0ZWRFcnJvclxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgdXNlciA9IGNvbnRleHQuZ2V0KFwiaWRlbnRpdHlcIikgYXMgQ2xpZW50SWRlbnRpdHk7XG4gICAgbW9kZWxba2V5XSA9IHVzZXIuZ2V0SUQoKSBhcyBNW3R5cGVvZiBrZXldO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJObyBVc2VyIGZvdW5kIGluIGNvbnRleHQuIFBsZWFzZSBwcm92aWRlIGEgdXNlciBpbiB0aGUgY29udGV4dFwiXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmltYXJ5IGtleSBhdXRvLWFzc2lnbm1lbnQgY2FsbGJhY2sgZm9yIEZhYnJpYyBtb2RlbHNcbiAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhbmQgYXNzaWducyBhIHByaW1hcnkga2V5IHZhbHVlIHRvIHRoZSBzcGVjaWZpZWQgbW9kZWwgcHJvcGVydHkgdXNpbmcgYSBGYWJyaWMtYmFja2VkIHNlcXVlbmNlIHdoZW4gdGhlIG1vZGVsIGlzIGNyZWF0ZWQuIElmIHRoZSBzZXF1ZW5jZSBuYW1lIGlzIG5vdCBwcm92aWRlZCBpbiBvcHRpb25zLCBpdCBpcyBkZXJpdmVkIGZyb20gdGhlIG1vZGVsIHZpYSBzZXF1ZW5jZU5hbWVGb3JNb2RlbC4gVGhlIGFzc2lnbmVkIGtleSBpcyBkZWZpbmVkIGFzIG5vbi13cml0YWJsZSBhbmQgZW51bWVyYWJsZS5cbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWwgZm9yIHRoZSB0YXJnZXQgaW5zdGFuY2VcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGZvciByZXBvc2l0b3J5IGNvbnRleHRcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgU2VxdWVuY2VPcHRpb25zIHRvIGNvbmZpZ3VyZSBzZXF1ZW5jZSBiZWhhdmlvclxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBGYWJyaWNDb250cmFjdEZsYWdzIGZvciBjb250ZXh0dWFsIGZsYWdzXG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZSBpbnZva2luZyB0aGUgY2FsbGJhY2tcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjb250ZXh0IC0gRmFicmljIGNvbnRyYWN0IGNvbnRleHQgY29udGFpbmluZyBpbnZvY2F0aW9uIG1ldGFkYXRhXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBTZXF1ZW5jZSBvcHRpb25zIHVzZWQgdG8gY29uZmlndXJlIG9yIGxvY2F0ZSB0aGUgc2VxdWVuY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZSB0byBhc3NpZ24gb24gdGhlIG1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHJlY2VpdmUgdGhlIGdlbmVyYXRlZCBwcmltYXJ5IGtleVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUmVzb2x2ZXMgd2hlbiB0aGUga2V5IGlzIGFzc2lnbmVkIG9yIHdoZW4gbm8gYWN0aW9uIGlzIHJlcXVpcmVkXG4gKiBAZnVuY3Rpb24gcGtGYWJyaWNPbkNyZWF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBSIGFzIFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb250ZXh0PEY+XG4gKiAgIHBhcnRpY2lwYW50IFMgYXMgRmFicmljQ29udHJhY3REQlNlcXVlbmNlXG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgUi0+PlI6IGRlcml2ZSBzZXF1ZW5jZSBuYW1lIGlmIG1pc3NpbmdcbiAqICAgUi0+PlM6IGFkYXB0ZXIuU2VxdWVuY2Uob3B0aW9ucylcbiAqICAgUy0tPj5SOiBzZXF1ZW5jZSBpbnN0YW5jZVxuICogICBSLT4+UzogbmV4dChjb250ZXh0KVxuICogICBTLS0+PlI6IG5leHQgdmFsdWVcbiAqICAgUi0+Pk06IGRlZmluZSBub24td3JpdGFibGUgcHJpbWFyeSBrZXlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBrRmFicmljT25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgZGF0YTogU2VxdWVuY2VPcHRpb25zLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFkYXRhLnR5cGUgfHwgbW9kZWxba2V5XSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldFByaW1hcnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG4gIGlmICghZGF0YS5uYW1lKSBkYXRhLm5hbWUgPSBNb2RlbC5zZXF1ZW5jZU5hbWUobW9kZWwsIFwicGtcIik7XG4gIGxldCBzZXF1ZW5jZTogU2VxdWVuY2U7XG4gIHRyeSB7XG4gICAgc2VxdWVuY2UgPSAoYXdhaXQgdGhpcy5hZGFwdGVyLlNlcXVlbmNlKGRhdGEpKSBhcyBTZXF1ZW5jZTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGluc3RhbnRpYXRlIFNlcXVlbmNlICR7ZGF0YS5uYW1lfTogJHtlfWBcbiAgICApO1xuICB9XG5cbiAgY29uc3QgbmV4dCA9IGF3YWl0IHNlcXVlbmNlLm5leHQoY29udGV4dCBhcyBGYWJyaWNDb250cmFjdENvbnRleHQpO1xuICBzZXRQcmltYXJ5S2V5VmFsdWUobW9kZWwsIGtleSBhcyBzdHJpbmcsIG5leHQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBZGFwdGVyIGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIHN0YXRlIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgQ291Y2hEQi1saWtlIGludGVyZmFjZSBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlIGZyb20gd2l0aGluIGEgY2hhaW5jb2RlIGNvbnRyYWN0XG4gKiBAdGVtcGxhdGUgdm9pZCAtIE5vIGNvbmZpZ3VyYXRpb24gbmVlZGVkIGZvciBjb250cmFjdCBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RGbGFncyAtIEZsYWdzIHNwZWNpZmljIHRvIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RDb250ZXh0IC0gQ29udGV4dCB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdCBjbGFzc1xuICogaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBwcml2YXRlIGFkYXB0ZXIgPSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyKCk7XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IG1vZGVsID0geyBpZCwgZGF0YSwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH07XG4gKiAgICAgYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZSgnYXNzZXRzJywgaWQsIG1vZGVsLCB7fSwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdHViXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAqXG4gKiAgIENvbnRyYWN0LT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgbW9kZWwsIHRyYW5zaWVudCwgY3R4KVxuICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IFNlcmlhbGl6ZSBtb2RlbCB0byBKU09OXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PlN0dWI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3R1Yi0+PlN0YXRlREI6IFdyaXRlIGRhdGFcbiAqICAgU3RhdGVEQi0tPj5TdHViOiBTdWNjZXNzXG4gKiAgIFN0dWItLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlciBleHRlbmRzIENvdWNoREJBZGFwdGVyPFxuICBhbnksXG4gIHZvaWQsXG4gIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBnZXRDbGllbnQoKTogdm9pZCB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXCJDbGllbnQgaXMgbm90IHN1cHBvcnRlZCBpbiBGYWJyaWMgY29udHJhY3RzXCIpO1xuICB9XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGV4dCBkZWNvZGVyIGZvciBjb252ZXJ0aW5nIGJpbmFyeSBkYXRhIHRvIHN0cmluZ3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKFwidXRmOFwiKTtcblxuICBwcm90ZWN0ZWQgc3RhdGljIHJlYWRvbmx5IHNlcmlhbGl6ZXIgPSBuZXcgU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIoKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnRleHQgY29uc3RydWN0b3IgZm9yIHRoaXMgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgQ29udGV4dCBjb25zdHJ1Y3RvciB3aXRoIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHJlYWRvbmx5IENvbnRleHQ6IENvbnN0cnVjdG9yPEZhYnJpY0NvbnRyYWN0Q29udGV4dD4gPVxuICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3IgZm9yIHRoaXMgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIHJlcG9zaXRvcmllc1xuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEByZXR1cm4ge0NvbnN0cnVjdG9yPFJlcG9zaXRvcnk8TSwgTWFuZ29RdWVyeSwgRmFicmljQ29udHJhY3RBZGFwdGVyLCBGYWJyaWNDb250cmFjdEZsYWdzLCBGYWJyaWNDb250cmFjdENvbnRleHQ+Pn0gVGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3JcbiAgICovXG4gIG92ZXJyaWRlIHJlcG9zaXRvcnk8XG4gICAgUiBleHRlbmRzIFJlcG9zaXRvcnk8XG4gICAgICBhbnksXG4gICAgICBBZGFwdGVyPGFueSwgdm9pZCwgTWFuZ29RdWVyeSwgQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgICA+LFxuICA+KCk6IENvbnN0cnVjdG9yPFI+IHtcbiAgICByZXR1cm4gRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8Uj47XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGFuIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3ZvaWR9IHNjb3BlIC0gTm90IHVzZWQgaW4gdGhpcyBhZGFwdGVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWxpYXNdIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyIGluc3RhbmNlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogdm9pZCwgYWxpYXM/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgRmFicmljRmxhdm91ciwgYWxpYXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZm9yKGNvbmZpZzogUGFydGlhbDxhbnk+LCAuLi5hcmdzOiBhbnkpOiB0eXBlb2YgdGhpcyB7XG4gICAgcmV0dXJuIHN1cGVyLmZvcihjb25maWcsIC4uLmFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcmVjb3JkIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWwgYW5kIHN0b3JlcyBpdCBpbiB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgc3R1YiB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5pbmZvKGBpbiBBREFQVEVSIGNyZWF0ZSB3aXRoIGFyZ3MgJHthcmdzfWApO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5pbmZvKGBhZGRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlIHdpdGggcGsgJHtpZH1gKTtcbiAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnB1dFN0YXRlKGNvbXBvc2VkS2V5LCBtb2RlbCwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHJlY29yZCBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYW5kIGRlc2VyaWFsaXplcyBhIHJlY29yZCBmcm9tIHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBpZCAtIFRoZSByZWNvcmQgaWRlbnRpZmllclxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcmV0cmlldmVkIHJlY29yZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgc3R1YiB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkKTtcbiAgICBsb2cuaW5mbyhgaW4gQURBUFRFUiByZWFkIHdpdGggYXJncyAke2FyZ3N9YCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcblxuICAgIGxldCBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29tcG9zZWRLZXkgPSBzdHViLmNyZWF0ZUNvbXBvc2l0ZUtleSh0YWJsZU5hbWUsIFtTdHJpbmcoaWQpXSk7XG4gICAgICBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZFN0YXRlKGNvbXBvc2VkS2V5LCBjdHgpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgYSByZWNvcmQgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFNlcmlhbGl6ZXMgYSBtb2RlbCBhbmQgdXBkYXRlcyBpdCBpbiB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSB1cGRhdGVkIHJlY29yZCBkYXRhXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gdHJhbnNpZW50IC0gVHJhbnNpZW50IGRhdGEgKG5vdCB1c2VkIGluIHRoaXMgaW1wbGVtZW50YXRpb24pXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cywgaW5jbHVkaW5nIHRoZSBjaGFpbmNvZGUgc3R1YiBhbmQgbG9nZ2VyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB1cGRhdGVkIHJlY29yZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NvbnRyYWN0RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGN0eCwgbG9nLCBzdHViIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZSk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcblxuICAgIHRyeSB7XG4gICAgICBsb2cudmVyYm9zZShgdXBkYXRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlIHdpdGggcGsgJHtpZH1gKTtcbiAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnB1dFN0YXRlKGNvbXBvc2VkS2V5LCBtb2RlbCwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVjb3JkIGZyb20gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIHJlY29yZCBhbmQgdGhlbiByZW1vdmVzIGl0IGZyb20gdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGVsZXRlZCByZWNvcmRcbiAgICovXG4gIGFzeW5jIGRlbGV0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgY3R4QXJncywgc3R1YiB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5kZWxldGUpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbGV0IG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb21wb3NlZEtleSA9IHN0dWIuY3JlYXRlQ29tcG9zaXRlS2V5KHRhYmxlTmFtZSwgW1N0cmluZyhpZCldKTtcbiAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5yZWFkKGNsYXp6LCBpZCwgLi4uY3R4QXJncyk7XG4gICAgICBsb2cudmVyYm9zZShgZGVsZXRpbmcgZW50cnkgd2l0aCBwayAke2lkfSBmcm9tICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVTdGF0ZShjb21wb3NlZEtleSwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZVN0YXRlKGlkOiBzdHJpbmcsIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0KSB7XG4gICAgY29uc3QgeyBzdHViIH0gPSB0aGlzLmxvZ0N0eChbY3R4XSwgdGhpcy5kZWxldGVTdGF0ZSk7XG4gICAgYXdhaXQgc3R1Yi5kZWxldGVTdGF0ZShpZCk7XG4gIH1cblxuICBmb3JQcml2YXRlKGNvbGxlY3Rpb246IHN0cmluZyk6IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB7XG4gICAgY29uc3QgdG9PdmVycmlkZSA9IFtcbiAgICAgIHRoaXMucHV0U3RhdGUsXG4gICAgICB0aGlzLnJlYWRTdGF0ZSxcbiAgICAgIHRoaXMuZGVsZXRlU3RhdGUsXG4gICAgICB0aGlzLnF1ZXJ5UmVzdWx0LFxuICAgICAgdGhpcy5xdWVyeVJlc3VsdFBhZ2luYXRlZCxcbiAgICBdLm1hcCgoZm4pID0+IGZuLm5hbWUpO1xuICAgIHJldHVybiBuZXcgUHJveHkodGhpcywge1xuICAgICAgZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICAgICAgaWYgKCF0b092ZXJyaWRlLmluY2x1ZGVzKHByb3AgYXMgc3RyaW5nKSlcbiAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcik7XG4gICAgICAgIHJldHVybiBuZXcgUHJveHkoKHRhcmdldCBhcyBhbnkpW3Byb3BdLCB7XG4gICAgICAgICAgYXN5bmMgYXBwbHkoZm4sIHRoaXNBcmcsIGFyZ3NMaXN0KSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHByb3ApIHtcbiAgICAgICAgICAgICAgY2FzZSBcInB1dFN0YXRlXCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgaWQsIG1vZGVsXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIGF3YWl0IHN0dWIucHV0UHJpdmF0ZURhdGEoY29sbGVjdGlvbiwgaWQudG9TdHJpbmcoKSwgbW9kZWwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlU3RhdGVcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCBpZF0gPSBhcmdzTGlzdDtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHN0dWIgYXMgQ2hhaW5jb2RlU3R1YikuZGVsZXRlUHJpdmF0ZURhdGEoXG4gICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICAgICAgICAgICAgaWRcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNhc2UgXCJyZWFkU3RhdGVcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCBpZF0gPSBhcmdzTGlzdDtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3R1Yi5nZXRQcml2YXRlRGF0YShjb2xsZWN0aW9uLCBpZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2FzZSBcInF1ZXJ5UmVzdWx0XCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgcmF3SW5wdXRdID0gYXJnc0xpc3Q7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0dWIuZ2V0UHJpdmF0ZURhdGFRdWVyeVJlc3VsdChjb2xsZWN0aW9uLCByYXdJbnB1dCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2FzZSBcInF1ZXJ5UmVzdWx0UGFnaW5hdGVkXCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgcmF3SW5wdXQsIGxpbWl0LCBza2lwXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZXJhdG9yID0gYXdhaXQgKFxuICAgICAgICAgICAgICAgICAgc3R1YiBhcyBDaGFpbmNvZGVTdHViXG4gICAgICAgICAgICAgICAgKS5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KGNvbGxlY3Rpb24sIHJhd0lucHV0KTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHRzOiBhbnlbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IHJlYWNoZWRCb29rbWFyayA9IHNraXAgPyBmYWxzZSA6IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3RLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGl0ZXJhdG9yLm5leHQoKTtcblxuICAgICAgICAgICAgICAgICAgaWYgKHJlcy52YWx1ZSAmJiByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWNvcmRLZXkgPSByZXMudmFsdWUua2V5O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWNvcmRWYWx1ZSA9IChyZXMudmFsdWUudmFsdWUgYXMgYW55KS50b1N0cmluZyhcbiAgICAgICAgICAgICAgICAgICAgICBcInV0ZjhcIlxuICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgYSBza2lwLCBza2lwIHVudGlsIHdlIHJlYWNoIGl0XG4gICAgICAgICAgICAgICAgICAgIGlmICghcmVhY2hlZEJvb2ttYXJrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJlY29yZEtleSA9PT0gc2tpcD8udG9TdHJpbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVhY2hlZEJvb2ttYXJrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgIEtleTogcmVjb3JkS2V5LFxuICAgICAgICAgICAgICAgICAgICAgIFJlY29yZDogSlNPTi5wYXJzZShyZWNvcmRWYWx1ZSksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBsYXN0S2V5ID0gcmVjb3JkS2V5O1xuICAgICAgICAgICAgICAgICAgICBjb3VudCsrO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGl0ZXJhdG9yLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yOlxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzIGFzIHVua25vd24gYXMgSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZWRSZWNvcmRzQ291bnQ6IHJlc3VsdHMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBib29rbWFyazogbGFzdEtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBpZiAocmVzLmRvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgaXRlcmF0b3IuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRvcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgYXMgdW5rbm93biBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmZXRjaGVkUmVjb3Jkc0NvdW50OiByZXN1bHRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvb2ttYXJrOiBcIlwiLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICBgVW5zdXBwb3J0ZWQgbWV0aG9kIG92ZXJyaWRlICR7U3RyaW5nKHByb3ApfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBwdXRTdGF0ZShcbiAgICBpZDogc3RyaW5nLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0XG4gICkge1xuICAgIGxldCBkYXRhOiBCdWZmZXI7XG5cbiAgICBjb25zdCB7IHN0dWIsIGxvZyB9ID0gdGhpcy5sb2dDdHgoW2N0eF0sIHRoaXMucHV0U3RhdGUpO1xuICAgIHRyeSB7XG4gICAgICBkYXRhID0gQnVmZmVyLmZyb20oXG4gICAgICAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCBhcyBNb2RlbClcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgcmVjb3JkIHdpdGggaWQgJHtpZH06ICR7ZX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBjdHguZ2V0KFwic2VncmVnYXRlZFwiKTtcbiAgICBpZiAoY29sbGVjdGlvbikgYXdhaXQgc3R1Yi5wdXRQcml2YXRlRGF0YShjb2xsZWN0aW9uLCBpZC50b1N0cmluZygpLCBkYXRhKTtcbiAgICBlbHNlIGF3YWl0IHN0dWIucHV0U3RhdGUoaWQudG9TdHJpbmcoKSwgZGF0YSk7XG5cbiAgICBsb2cuc2lsbHkoXG4gICAgICBgc3RhdGUgc3RvcmVkJHtjb2xsZWN0aW9uID8gYCBpbiAke2NvbGxlY3Rpb259IGNvbGxlY3Rpb25gIDogXCJcIn0gdW5kZXIgaWQgJHtpZH1gXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZFN0YXRlKGlkOiBzdHJpbmcsIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0KSB7XG4gICAgbGV0IHJlc3VsdDogYW55O1xuXG4gICAgY29uc3QgeyBzdHViLCBsb2cgfSA9IHRoaXMubG9nQ3R4KFtjdHhdLCB0aGlzLnJlYWRTdGF0ZSk7XG4gICAgbGV0IHJlczogc3RyaW5nO1xuICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBjdHguZ2V0KFwic2VncmVnYXRlZFwiKTtcbiAgICBpZiAoY29sbGVjdGlvbilcbiAgICAgIHJlcyA9IChhd2FpdCBzdHViLmdldFByaXZhdGVEYXRhKGNvbGxlY3Rpb24sIGlkLnRvU3RyaW5nKCkpKS50b1N0cmluZygpO1xuICAgIGVsc2UgcmVzID0gKGF3YWl0IHN0dWIuZ2V0U3RhdGUoaWQudG9TdHJpbmcoKSkpLnRvU3RyaW5nKCk7XG5cbiAgICBpZiAoIXJlcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgUmVjb3JkIHdpdGggaWQgJHtpZH0ke2NvbGxlY3Rpb24gPyBgIGluICR7Y29sbGVjdGlvbn0gY29sbGVjdGlvbmAgOiBcIlwifSBub3QgZm91bmRgXG4gICAgICApO1xuICAgIGxvZy5zaWxseShcbiAgICAgIGBzdGF0ZSByZXRyaWV2ZWQgZnJvbSR7Y29sbGVjdGlvbiA/IGAgJHtjb2xsZWN0aW9ufSBjb2xsZWN0aW9uYCA6IFwiXCJ9IHVuZGVyIGlkICR7aWR9YFxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IEZhYnJpY0NvbnRyYWN0QWRhcHRlci5zZXJpYWxpemVyLmRlc2VyaWFsaXplKHJlcy50b1N0cmluZygpKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBGYWlsZWQgdG8gcGFyc2UgcmVjb3JkOiAke2V9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBxdWVyeVJlc3VsdChcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViLFxuICAgIHJhd0lucHV0OiBhbnksXG5cbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkU3RhdGUpO1xuICAgIGxldCByZXM6IEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgY29uc3QgY29sbGVjdGlvbiA9IGN0eC5nZXQoXCJzZWdyZWdhdGVkXCIpO1xuICAgIGlmIChjb2xsZWN0aW9uKVxuICAgICAgcmVzID0gYXdhaXQgc3R1Yi5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShyYXdJbnB1dClcbiAgICAgICk7XG4gICAgZWxzZSByZXMgPSBhd2FpdCBzdHViLmdldFF1ZXJ5UmVzdWx0KEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KSk7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgIHN0dWI6IENoYWluY29kZVN0dWIsXG4gICAgcmF3SW5wdXQ6IGFueSxcbiAgICBsaW1pdDogbnVtYmVyID0gMjUwLFxuICAgIHNraXA/OiBudW1iZXIsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxTdGF0ZVF1ZXJ5UmVzcG9uc2U8SXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcj4+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkU3RhdGUpO1xuICAgIGxldCByZXM6IFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPjtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY3R4LmdldChcInNlZ3JlZ2F0ZWRcIik7XG4gICAgaWYgKGNvbGxlY3Rpb24pIHtcbiAgICAgIHJhd0lucHV0LnNlbGVjdG9yID0ge1xuICAgICAgICAuLi5yYXdJbnB1dC5zZWxlY3RvcixcbiAgICAgICAgX2lkOiBza2lwID8geyAkZ3Q6IHNraXAudG9TdHJpbmcoKSB9IDogeyAkZ3RlOiBcIlwiIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgaXQgPSBhd2FpdCBzdHViLmdldFByaXZhdGVEYXRhUXVlcnlSZXN1bHQoXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KVxuICAgICAgKTtcbiAgICAgIHJlcyA9IHtcbiAgICAgICAgaXRlcmF0b3I6IGl0LFxuICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgIGZldGNoZWRSZWNvcmRzQ291bnQ6IGxpbWl0LFxuICAgICAgICAgIGJvb2ttYXJrOiBcIlwiLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9IGVsc2VcbiAgICAgIHJlcyA9IGF3YWl0IHN0dWIuZ2V0UXVlcnlSZXN1bHRXaXRoUGFnaW5hdGlvbihcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocmF3SW5wdXQpLFxuICAgICAgICBsaW1pdCxcbiAgICAgICAgc2tpcD8udG9TdHJpbmcoKVxuICAgICAgKTtcblxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWVyZ2VNb2RlbHMocmVzdWx0czogUmVjb3JkPHN0cmluZywgYW55PltdKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgZXh0cmFjdCA9IChtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PikgPT5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG1vZGVsKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSBcInVuZGVmaW5lZFwiKSBhY2N1bVtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICBsZXQgZmluYWxNb2RlbDogUmVjb3JkPHN0cmluZywgYW55PiA9IHJlc3VsdHMucG9wKCkgYXMgUmVjb3JkPHN0cmluZywgYW55PjtcblxuICAgIGZvciAoY29uc3QgcmVzIG9mIHJlc3VsdHMpIHtcbiAgICAgIGZpbmFsTW9kZWwgPSBPYmplY3QuYXNzaWduKHt9LCBleHRyYWN0KGZpbmFsTW9kZWwpLCBleHRyYWN0KHJlcykpO1xuICAgIH1cblxuICAgIHJldHVybiBmaW5hbE1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNvZGVzIGJpbmFyeSBkYXRhIHRvIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcgdXNpbmcgVVRGLTggZW5jb2RpbmdcbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgLSBUaGUgYmluYXJ5IGRhdGEgdG8gZGVjb2RlXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGRlY29kZWQgc3RyaW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgZGVjb2RlKGJ1ZmZlcjogVWludDhBcnJheSkge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdEFkYXB0ZXIudGV4dERlY29kZXIuZGVjb2RlKGJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgb3BlcmF0aW9uIGZsYWdzIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICAgKiBAc3VtbWFyeSBNZXJnZXMgZGVmYXVsdCBmbGFncyB3aXRoIEZhYnJpYy1zcGVjaWZpYyBjb250ZXh0IGluZm9ybWF0aW9uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz59IGZsYWdzIC0gUGFydGlhbCBmbGFncyB0byBtZXJnZSB3aXRoIGRlZmF1bHRzXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEByZXR1cm4ge0ZhYnJpY0NvbnRyYWN0RmxhZ3N9IFRoZSBtZXJnZWQgZmxhZ3NcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgZmxhZ3M6IFBhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz4sXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxGYWJyaWNDb250cmFjdEZsYWdzPiB7XG4gICAgY29uc3QgYmFzZUZsYWdzID0ge1xuICAgICAgc3R1YjogY3R4LnN0dWIsXG4gICAgICBzZWdyZWdhdGVkOiBmYWxzZSxcbiAgICB9O1xuICAgIGlmIChjdHggaW5zdGFuY2VvZiBGYWJyaWNDb250cmFjdENvbnRleHQpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24oYmFzZUZsYWdzLCB7XG4gICAgICAgIGxvZ2dlcjogY3R4LmxvZ2dlcixcbiAgICAgICAgaWRlbnRpdHk6IGN0eC5pZGVudGl0eSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogY3R4LnN0dWIuZ2V0VHhJRCgpLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIE9iamVjdC5hc3NpZ24oYmFzZUZsYWdzLCB7XG4gICAgICAgIGlkZW50aXR5OiBjdHguY2xpZW50SWRlbnRpdHksXG4gICAgICAgIGxvZ2dlcjogbmV3IENvbnRyYWN0TG9nZ2VyKHRoaXMgYXMgYW55LCB1bmRlZmluZWQsIGN0eCksXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IGN0eC5zdHViLmdldFR4SUQoKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZsYWdzID0gKGF3YWl0IHN1cGVyLmZsYWdzKFxuICAgICAgb3BlcmF0aW9uLFxuICAgICAgbW9kZWwsXG4gICAgICBiYXNlRmxhZ3MgYXMgYW55LFxuICAgICAgLi4uYXJnc1xuICAgICkpIGFzIEZhYnJpY0NvbnRyYWN0RmxhZ3M7XG5cbiAgICByZXR1cm4gZmxhZ3MgYXMgRmFicmljQ29udHJhY3RGbGFncztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhbiBpbmRleCBmb3IgYSBtb2RlbFxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBpcyBub3QgaW1wbGVtZW50ZWQgZm9yIEZhYnJpYyBjb250cmFjdHMgYW5kIHJldHVybnMgYSByZXNvbHZlZCBwcm9taXNlXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWxzIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyBpbW1lZGlhdGVseVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBwcm90ZWN0ZWQgaW5kZXg8TT4obW9kZWxzOiBDb25zdHJ1Y3RvcjxNPik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIHJlc3VsdHMgZnJvbSBhIHN0YXRlIHF1ZXJ5IGl0ZXJhdG9yXG4gICAqIEBzdW1tYXJ5IEl0ZXJhdGVzIHRocm91Z2ggcXVlcnkgcmVzdWx0cyBhbmQgY29udmVydHMgdGhlbSB0byBhIHN0cnVjdHVyZWQgZm9ybWF0XG4gICAqIEBwYXJhbSB7TG9nZ2VyfSBsb2cgLSBMb2dnZXIgaW5zdGFuY2UgZm9yIGRlYnVnZ2luZ1xuICAgKiBAcGFyYW0ge0l0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3J9IGl0ZXJhdG9yIC0gVGhlIHN0YXRlIHF1ZXJ5IGl0ZXJhdG9yXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzSGlzdG9yeT1mYWxzZV0gLSBXaGV0aGVyIHRoaXMgaXMgYSBoaXN0b3J5IHF1ZXJ5XG4gICAqIEByZXR1cm4ge1Byb21pc2U8YW55W10+fSBQcm9taXNlIHJlc29sdmluZyB0byBhbiBhcnJheSBvZiBwcm9jZXNzZWQgcmVzdWx0c1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAgICogICBwYXJ0aWNpcGFudCBSZXN1bHRJdGVyYXRvclxuICAgKiAgIHBhcnRpY2lwYW50IEl0ZXJhdG9yXG4gICAqXG4gICAqICAgQ2FsbGVyLT4+UmVzdWx0SXRlcmF0b3I6IHJlc3VsdEl0ZXJhdG9yKGxvZywgaXRlcmF0b3IsIGlzSGlzdG9yeSlcbiAgICogICBsb29wIFVudGlsIGRvbmVcbiAgICogICAgIFJlc3VsdEl0ZXJhdG9yLT4+SXRlcmF0b3I6IG5leHQoKVxuICAgKiAgICAgSXRlcmF0b3ItLT4+UmVzdWx0SXRlcmF0b3I6IHsgdmFsdWUsIGRvbmUgfVxuICAgKiAgICAgYWx0IEhhcyB2YWx1ZVxuICAgKiAgICAgICBSZXN1bHRJdGVyYXRvci0+PlJlc3VsdEl0ZXJhdG9yOiBQcm9jZXNzIHZhbHVlIGJhc2VkIG9uIGlzSGlzdG9yeVxuICAgKiAgICAgICBSZXN1bHRJdGVyYXRvci0+PlJlc3VsdEl0ZXJhdG9yOiBBZGQgdG8gcmVzdWx0cyBhcnJheVxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqICAgUmVzdWx0SXRlcmF0b3ItPj5JdGVyYXRvcjogY2xvc2UoKVxuICAgKiAgIFJlc3VsdEl0ZXJhdG9yLS0+PkNhbGxlcjogYWxsUmVzdWx0c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlc3VsdEl0ZXJhdG9yKFxuICAgIGxvZzogTG9nZ2VyLFxuICAgIGl0ZXJhdG9yOiBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yLFxuICAgIGlzSGlzdG9yeSA9IGZhbHNlXG4gICkge1xuICAgIGNvbnN0IGFsbFJlc3VsdHMgPSBbXTtcbiAgICBsZXQgcmVzOiB7IHZhbHVlOiBhbnk7IGRvbmU6IGJvb2xlYW4gfSA9IGF3YWl0IGl0ZXJhdG9yLm5leHQoKTtcbiAgICB3aGlsZSAoIXJlcy5kb25lKSB7XG4gICAgICBpZiAocmVzLnZhbHVlICYmIHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZygpKSB7XG4gICAgICAgIGxldCBqc29uUmVzOiBhbnkgPSB7fTtcbiAgICAgICAgbG9nLmRlYnVnKHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgICAgICBpZiAoaXNIaXN0b3J5IC8qICYmIGlzSGlzdG9yeSA9PT0gdHJ1ZSovKSB7XG4gICAgICAgICAganNvblJlcy5UeElkID0gcmVzLnZhbHVlLnR4SWQ7XG4gICAgICAgICAganNvblJlcy5UaW1lc3RhbXAgPSByZXMudmFsdWUudGltZXN0YW1wO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBqc29uUmVzLlZhbHVlID0gSlNPTi5wYXJzZShyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgbG9nLmVycm9yKGVycik7XG4gICAgICAgICAgICBqc29uUmVzLlZhbHVlID0gcmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGpzb25SZXMgPSBKU09OLnBhcnNlKHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICBsb2cuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIGpzb25SZXMgPSByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhbGxSZXN1bHRzLnB1c2goanNvblJlcyk7XG4gICAgICB9XG4gICAgICByZXMgPSBhd2FpdCBpdGVyYXRvci5uZXh0KCk7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgQ2xvc2luZyBpdGVyYXRvciBhZnRlciAke2FsbFJlc3VsdHMubGVuZ3RofSByZXN1bHRzYCk7XG4gICAgaXRlcmF0b3IuY2xvc2UoKTsgLy8gcHVycG9zZWx5IG5vdCBhd2FpdC4gbGV0IGl0ZXJhdG9yIGNsb3NlIG9uIGl0cyBvd25cbiAgICByZXR1cm4gYWxsUmVzdWx0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSByYXcgcXVlcnkgYWdhaW5zdCB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUGVyZm9ybXMgYSByaWNoIHF1ZXJ5IHVzaW5nIENvdWNoREIgc3ludGF4IGFnYWluc3QgdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSByZXR1cm4gdHlwZVxuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHJhd0lucHV0IC0gVGhlIE1hbmdvIFF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHBhcmFtIHtib29sZWFufSBkb2NzT25seSAtIFdoZXRoZXIgdG8gcmV0dXJuIG9ubHkgZG9jdW1lbnRzIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFI+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcXVlcnkgcmVzdWx0c1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAgICogICBwYXJ0aWNpcGFudCBGYWJyaWNDb250cmFjdEFkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBTdHViXG4gICAqICAgcGFydGljaXBhbnQgU3RhdGVEQlxuICAgKlxuICAgKiAgIENhbGxlci0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogcmF3KHJhd0lucHV0LCBkb2NzT25seSwgY3R4KVxuICAgKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogRXh0cmFjdCBsaW1pdCBhbmQgc2tpcFxuICAgKiAgIGFsdCBXaXRoIHBhZ2luYXRpb25cbiAgICogICAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PlN0dWI6IGdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24ocXVlcnksIGxpbWl0LCBza2lwKVxuICAgKiAgIGVsc2UgV2l0aG91dCBwYWdpbmF0aW9uXG4gICAqICAgICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5TdHViOiBnZXRRdWVyeVJlc3VsdChxdWVyeSlcbiAgICogICBlbmRcbiAgICogICBTdHViLT4+U3RhdGVEQjogRXhlY3V0ZSBxdWVyeVxuICAgKiAgIFN0YXRlREItLT4+U3R1YjogSXRlcmF0b3JcbiAgICogICBTdHViLS0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogSXRlcmF0b3JcbiAgICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IHJlc3VsdEl0ZXJhdG9yKGxvZywgaXRlcmF0b3IpXG4gICAqICAgRmFicmljQ29udHJhY3RBZGFwdGVyLS0+PkNhbGxlcjogcmVzdWx0c1xuICAgKi9cbiAgYXN5bmMgcmF3PFIsIEQgZXh0ZW5kcyBib29sZWFuPihcbiAgICByYXdJbnB1dDogTWFuZ29RdWVyeSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZG9jc09ubHk6IEQgPSB0cnVlIGFzIEQsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFJhd1Jlc3VsdDxSLCBEPj4ge1xuICAgIGNvbnN0IHsgbG9nLCBzdHViIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJhdyk7XG5cbiAgICBjb25zdCB7IHNraXAsIGxpbWl0IH0gPSByYXdJbnB1dDtcbiAgICBsZXQgaXRlcmF0b3I6IEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgaWYgKGxpbWl0IHx8IHNraXApIHtcbiAgICAgIGRlbGV0ZSByYXdJbnB1dFtcImxpbWl0XCJdO1xuICAgICAgZGVsZXRlIHJhd0lucHV0W1wic2tpcFwiXTtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFJldHJpZXZpbmcgcGFnaW5hdGVkIGl0ZXJhdG9yOiBsaW1pdDogJHtsaW1pdH0vIHNraXA6ICR7c2tpcH1gXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzcG9uc2U6IFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPiA9XG4gICAgICAgIChhd2FpdCB0aGlzLnF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgICAgICAgIHN0dWIsXG4gICAgICAgICAgcmF3SW5wdXQsXG4gICAgICAgICAgbGltaXQgfHwgMjUwLFxuICAgICAgICAgIChza2lwIGFzIGFueSk/LnRvU3RyaW5nKClcbiAgICAgICAgKSkgYXMgU3RhdGVRdWVyeVJlc3BvbnNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+O1xuICAgICAgaXRlcmF0b3IgPSByZXNwb25zZS5pdGVyYXRvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLmRlYnVnKFwiUmV0cmlldmluZyBpdGVyYXRvclwiKTtcbiAgICAgIGl0ZXJhdG9yID0gKGF3YWl0IHRoaXMucXVlcnlSZXN1bHQoXG4gICAgICAgIHN0dWIsXG4gICAgICAgIHJhd0lucHV0XG4gICAgICApKSBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yO1xuICAgIH1cbiAgICBsb2cuZGVidWcoXCJJdGVyYXRvciBhY3F1aXJlZFwiKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSAoYXdhaXQgdGhpcy5yZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yKSkgYXMgUjtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgcmV0dXJuaW5nICR7QXJyYXkuaXNBcnJheShyZXN1bHRzKSA/IHJlc3VsdHMubGVuZ3RoIDogMX0gcmVzdWx0c2BcbiAgICApO1xuICAgIHJldHVybiByZXN1bHRzIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIFN0YXRlbWVudDxNIGV4dGVuZHMgTW9kZWw+KCk6IEZhYnJpY1N0YXRlbWVudDxNLCBhbnk+IHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY1N0YXRlbWVudCh0aGlzIGFzIGFueSk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGw8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT5bXT4ge1xuICAgIGlmIChpZC5sZW5ndGggIT09IG1vZGVsLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGVBbGwpO1xuICAgIGNvbnN0IHRhYmxlTGFiZWwgPSBNb2RlbC50YWJsZU5hbWUodGFibGVOYW1lKTtcbiAgICBsb2cuZGVidWcoYENyZWF0aW5nICR7aWQubGVuZ3RofSBlbnRyaWVzICR7dGFibGVMYWJlbH0gdGFibGVgKTtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICBpZC5tYXAoKGksIGNvdW50KSA9PiB0aGlzLmNyZWF0ZSh0YWJsZU5hbWUsIGksIG1vZGVsW2NvdW50XSwgLi4uY3R4QXJncykpXG4gICAgKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhYmxlTmFtZTogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKGlkLmxlbmd0aCAhPT0gbW9kZWwubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZUFsbCk7XG4gICAgY29uc3QgdGFibGVMYWJlbCA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIGxvZy5kZWJ1ZyhgVXBkYXRpbmcgJHtpZC5sZW5ndGh9IGVudHJpZXMgJHt0YWJsZUxhYmVsfSB0YWJsZWApO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgIGlkLm1hcCgoaSwgY291bnQpID0+IHRoaXMudXBkYXRlKHRhYmxlTmFtZSwgaSwgbW9kZWxbY291bnRdLCAuLi5jdHhBcmdzKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGtcbiAgICogQHBhcmFtIGFyZ3NcbiAgICovXG4gIG92ZXJyaWRlIHByZXBhcmU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByZXBhcmVkTW9kZWwge1xuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnByZXBhcmUpO1xuXG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIGFueSk7XG4gICAgY29uc3QgcGsgPSBNb2RlbC5wayhtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpO1xuICAgIGNvbnN0IHNwbGl0ID0gTW9kZWwuc2VncmVnYXRlKG1vZGVsKTtcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3QuZW50cmllcyhzcGxpdC5tb2RlbCkucmVkdWNlKFxuICAgICAgKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gYWNjdW07XG4gICAgICAgIGNvbnN0IG1hcHBlZFByb3AgPSBNb2RlbC5jb2x1bW5OYW1lKG1vZGVsLCBrZXkgYXMgYW55KTtcbiAgICAgICAgaWYgKHRoaXMuaXNSZXNlcnZlZChtYXBwZWRQcm9wKSlcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgUHJvcGVydHkgbmFtZSAke21hcHBlZFByb3B9IGlzIHJlc2VydmVkYCk7XG4gICAgICAgIGFjY3VtW21hcHBlZFByb3BdID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LFxuICAgICAge31cbiAgICApO1xuXG4gICAgbG9nLnNpbGx5KFxuICAgICAgYFByZXBhcmluZyByZWNvcmQgZm9yICR7dGFibGVOYW1lfSB0YWJsZSB3aXRoIHBrICR7KG1vZGVsIGFzIGFueSlbcGtdfWBcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlY29yZDogcmVzdWx0LFxuICAgICAgaWQ6IChtb2RlbCBhcyBhbnkpW3BrXSBhcyBzdHJpbmcsXG4gICAgICB0cmFuc2llbnQ6IHNwbGl0LnRyYW5zaWVudCxcbiAgICB9O1xuICB9XG5cbiAgb3ZlcnJpZGUgcmV2ZXJ0PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IE0ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJldmVydCk7XG4gICAgY29uc3Qgb2I6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICBjb25zdCBwayA9IE1vZGVsLnBrKGNsYXp6KTtcbiAgICBvYltwayBhcyBzdHJpbmddID0gaWQ7XG4gICAgY29uc3QgbSA9IChcbiAgICAgIHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IE1vZGVsLmJ1aWxkKG9iLCBjbGF6eikgOiBuZXcgY2xhenoob2IpXG4gICAgKSBhcyBNO1xuICAgIGxvZy5zaWxseShgUmVidWlsZGluZyBtb2RlbCAke20uY29uc3RydWN0b3IubmFtZX0gaWQgJHtpZH1gKTtcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3Qua2V5cyhtKS5yZWR1Y2UoKGFjY3VtOiBNLCBrZXkpID0+IHtcbiAgICAgIChhY2N1bSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtrZXldID1cbiAgICAgICAgb2JqW01vZGVsLmNvbHVtbk5hbWUoYWNjdW0sIGtleSBhcyBhbnkpXTtcbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBtKTtcblxuICAgIGlmICh0cmFuc2llbnQpIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYHJlLWFkZGluZyB0cmFuc2llbnQgcHJvcGVydGllczogJHtPYmplY3Qua2V5cyh0cmFuc2llbnQpLmpvaW4oXCIsIFwiKX1gXG4gICAgICApO1xuICAgICAgT2JqZWN0LmVudHJpZXModHJhbnNpZW50KS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmIChrZXkgaW4gcmVzdWx0ICYmIChyZXN1bHQgYXMgYW55KVtrZXldICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICBgVHJhbnNpZW50IHByb3BlcnR5ICR7a2V5fSBhbHJlYWR5IGV4aXN0cyBvbiBtb2RlbCAke20uY29uc3RydWN0b3IubmFtZX0uIHNob3VsZCBiZSBpbXBvc3NpYmxlYFxuICAgICAgICAgICk7XG4gICAgICAgIHJlc3VsdFtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgb3ZlcnJpZGUgY3JlYXRlUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKSB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZVByZWZpeCk7XG4gICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbCk7XG5cbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uY3R4QXJnc10gYXMgW1xuICAgICAgQ29uc3RydWN0b3I8TT4sXG4gICAgICBQcmltYXJ5S2V5VHlwZSxcbiAgICAgIFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgICAuLi5hbnlbXSxcbiAgICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBdO1xuICB9XG5cbiAgb3ZlcnJpZGUgdXBkYXRlUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogYW55W10ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGVQcmVmaXgpO1xuICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSBNb2RlbC50YWJsZU5hbWUodGFibGVOYW1lKTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuXG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmN0eEFyZ3NdIGFzIFtcbiAgICAgIENvbnN0cnVjdG9yPE0+LFxuICAgICAgUHJpbWFyeUtleVR5cGUsXG4gICAgICBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICAgLi4uYW55W10sXG4gICAgICBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBjcmVhdGVBbGxQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBbLi4uYW55LCBGYWJyaWNDb250cmFjdENvbnRleHRdXG4gICk6IChzdHJpbmcgfCBzdHJpbmdbXSB8IG51bWJlcltdIHwgUmVjb3JkPHN0cmluZywgYW55PltdKVtdIHtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcblxuICAgIGNvbnN0IGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0ID0gYXJncy5wb3AoKTtcblxuICAgIGNvbnN0IHJlY29yZHMgPSBpZHMubWFwKChpZCwgY291bnQpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbHNbY291bnRdKTtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkcywgcmVjb3JkcywgY3R4IGFzIGFueV07XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgdXBkYXRlQWxsUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogWy4uLmFueSwgRmFicmljQ29udHJhY3RDb250ZXh0XVxuICApIHtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcblxuICAgIGNvbnN0IGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0ID0gYXJncy5wb3AoKTtcblxuICAgIGNvbnN0IHJlY29yZHMgPSBpZHMubWFwKChpZCwgY291bnQpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbHNbY291bnRdKTtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkcywgcmVjb3JkcywgY3R4IGFzIGFueV07XG4gIH1cblxuICBvdmVycmlkZSBwYXJzZUVycm9yPEUgZXh0ZW5kcyBCYXNlRXJyb3I+KFxuICAgIGVycjogRXJyb3IgfCBzdHJpbmcsXG4gICAgcmVhc29uPzogc3RyaW5nXG4gICk6IEUge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdEFkYXB0ZXIucGFyc2VFcnJvcihyZWFzb24gfHwgZXJyKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGxvZ0N0eDxBUkdTIGV4dGVuZHMgYW55W10+KFxuICAgIGFyZ3M6IEFSR1MsXG4gICAgbWV0aG9kOiAoKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkpIHwgc3RyaW5nXG4gICk6IENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICB9IHtcbiAgICByZXR1cm4gRmFicmljQ29udHJhY3RBZGFwdGVyLmxvZ0N0eC5jYWxsKHRoaXMsIGFyZ3MsIG1ldGhvZCBhcyBhbnkpIGFzIGFueTtcbiAgfVxuXG4gIHN0YXRpYyBvdmVycmlkZSBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6IHN0cmluZ1xuICApOiBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPiAmIHtcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgfTtcbiAgc3RhdGljIG92ZXJyaWRlIGxvZ0N0eDxBUkdTIGV4dGVuZHMgYW55W10+KFxuICAgIHRoaXM6IGFueSxcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnlcbiAgKTogQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gIH07XG4gIHN0YXRpYyBvdmVycmlkZSBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBzdHJpbmdcbiAgKTogQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gIH0ge1xuICAgIGlmIChhcmdzLmxlbmd0aCA8IDEpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm8gY29udGV4dCBwcm92aWRlZFwiKTtcbiAgICBjb25zdCBjdHggPSBhcmdzLnBvcCgpIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcblxuICAgIGlmICghKGN0eCBpbnN0YW5jZW9mIENvbnRleHQpKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJObyBjb250ZXh0IHByb3ZpZGVkXCIpO1xuICAgIGlmIChhcmdzLmZpbHRlcigoYSkgPT4gYSBpbnN0YW5jZW9mIENvbnRleHQpLmxlbmd0aCA+IDEpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJoZXJlXCIpO1xuICAgIGNvbnN0IGxvZyA9IChcbiAgICAgIHRoaXNcbiAgICAgICAgPyBjdHgubG9nZ2VyLmZvcih0aGlzKS5mb3IobWV0aG9kKVxuICAgICAgICA6IGN0eC5sb2dnZXIuY2xlYXIoKS5mb3IodGhpcykuZm9yKG1ldGhvZClcbiAgICApIGFzIExvZ2dlck9mPEZhYnJpY0NvbnRyYWN0Q29udGV4dD47XG4gICAgcmV0dXJuIHtcbiAgICAgIGN0eDogY3R4LFxuICAgICAgbG9nOiBtZXRob2QgPyAobG9nLmZvcihtZXRob2QpIGFzIExvZ2dlck9mPEZhYnJpY0NvbnRyYWN0Q29udGV4dD4pIDogbG9nLFxuICAgICAgc3R1YjogY3R4LnN0dWIsXG4gICAgICBpZGVudGl0eTogY3R4LmlkZW50aXR5LFxuICAgICAgY3R4QXJnczogWy4uLmFyZ3MsIGN0eF0sXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBvdmVycmlkZSBwYXJzZUVycm9yPEUgZXh0ZW5kcyBCYXNlRXJyb3I+KGVycjogRXJyb3IgfCBzdHJpbmcpOiBFIHtcbiAgICAvLyBpZiAoXG4gICAgLy8gICBNSVNTSU5HX1BSSVZBVEVfREFUQV9SRUdFWC50ZXN0KFxuICAgIC8vICAgICB0eXBlb2YgZXJyID09PSBcInN0cmluZ1wiID8gZXJyIDogZXJyLm1lc3NhZ2VcbiAgICAvLyAgIClcbiAgICAvLyApXG4gICAgLy8gICByZXR1cm4gbmV3IFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzKGVycikgYXMgRTtcbiAgICBjb25zdCBtc2cgPSB0eXBlb2YgZXJyID09PSBcInN0cmluZ1wiID8gZXJyIDogZXJyLm1lc3NhZ2U7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhOb3RGb3VuZEVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE5vdEZvdW5kRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQ29uZmxpY3RFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKEJhZFJlcXVlc3RFcnJvci5uYW1lKSlcbiAgICAgIHJldHVybiBuZXcgQmFkUmVxdWVzdEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKFF1ZXJ5RXJyb3IubmFtZSkpIHJldHVybiBuZXcgUXVlcnlFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhQYWdpbmdFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBQYWdpbmdFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhVbnN1cHBvcnRlZEVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBVbnN1cHBvcnRlZEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKE1pZ3JhdGlvbkVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE1pZ3JhdGlvbkVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKE9ic2VydmVyRXJyb3IubmFtZSkpIHJldHVybiBuZXcgT2JzZXJ2ZXJFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhBdXRob3JpemF0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IEF1dGhvcml6YXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhGb3JiaWRkZW5FcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBGb3JiaWRkZW5FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhDb25uZWN0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhTZXJpYWxpemF0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IFNlcmlhbGl6YXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgcmV0dXJuIG5ldyBJbnRlcm5hbEVycm9yKGVycikgYXMgRTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1ldGhvZCBmb3IgZGVjb3JhdGlvbiBvdmVycmlkZXNcbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzL2V4dGVuZHMgZGVjYWYgZGVjb3JhdGlvbiB3aXRoIEZhYnJpYy1zcGVjaWZpYyBmdW5jdGlvbmFsaXR5XG4gICAqIEBzdGF0aWNcbiAgICogQG92ZXJyaWRlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgZGVjb3JhdGlvbigpOiB2b2lkIHtcbiAgICBzdXBlci5kZWNvcmF0aW9uKCk7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuQ1JFQVRFRF9CWSlcbiAgICAgIC5kZWZpbmUoXG4gICAgICAgIG9uQ3JlYXRlKGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5DUkVBVEVEX0JZLCB7fSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuVVBEQVRFRF9CWSlcbiAgICAgIC5kZWZpbmUoXG4gICAgICAgIG9uQ3JlYXRlVXBkYXRlKGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5VUERBVEVEX0JZLCB7fSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihEQktleXMuSUQpXG4gICAgICAuZGVmaW5lKHtcbiAgICAgICAgZGVjb3JhdG9yOiBmdW5jdGlvbiBwa0RlYyhcbiAgICAgICAgICBvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMsXG4gICAgICAgICAgZ3JvdXBzb3J0PzogR3JvdXBTb3J0XG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBwa0RlYyhvYmo6IGFueSwgYXR0cjogYW55KSB7XG4gICAgICAgICAgICByZXR1cm4gYXBwbHkoXG4gICAgICAgICAgICAgIHJlcXVpcmVkKCksXG4gICAgICAgICAgICAgIHJlYWRvbmx5KCksXG4gICAgICAgICAgICAgIHByb3BNZXRhZGF0YShNZXRhZGF0YS5rZXkoREJLZXlzLklELCBhdHRyKSwgb3B0aW9ucyksXG4gICAgICAgICAgICAgIG9uQ3JlYXRlKHBrRmFicmljT25DcmVhdGUgYXMgYW55LCBvcHRpb25zLCBncm91cHNvcnQpXG4gICAgICAgICAgICApKG9iaiwgYXR0cik7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgIH0gYXMgYW55KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKFBlcnNpc3RlbmNlS2V5cy5DT0xVTU4pXG4gICAgICAuZXh0ZW5kKEZhYnJpY1Byb3BlcnR5KCkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IoUGVyc2lzdGVuY2VLZXlzLlRBQkxFKVxuICAgICAgLmV4dGVuZChmdW5jdGlvbiB0YWJsZShvYmo6IGFueSkge1xuICAgICAgICAvLyBjb25zdCBjaGFpbjogYW55W10gPSBbXTtcblxuICAgICAgICAvLyBsZXQgY3VycmVudCA9IG9iajtcblxuICAgICAgICAvLyBkbyB7XG4gICAgICAgIC8vICAgY2hhaW4ucHVzaChjdXJyZW50KTtcbiAgICAgICAgLy8gICBjb25zb2xlLmxvZyhgRm91bmQgY2xhc3M6ICR7Y3VycmVudH1gKTtcbiAgICAgICAgLy8gfSB3aGlsZSAoY3VycmVudCAmJiBjdXJyZW50ICE9PSBPYmplY3QucHJvdG90eXBlKTtcblxuICAgICAgICAvLyBkbyB7XG4gICAgICAgIC8vICAgY3VycmVudCA9IGNoYWluLnBvcCgpO1xuICAgICAgICAvLyAgIGNvbnNvbGUubG9nKGBBcHBseWluZyBAT2JqZWN0KCkgdG8gY2xhc3M6ICR7Y3VycmVudH1gKTtcbiAgICAgICAgLy8gICAvL1RPRE86IFRISVMgSVMgTk9UIFdPUktJTkcgQU5EIFRIUk9XUyBFUlJPUlxuICAgICAgICAvLyAgIC8vIEZhYnJpY09iamVjdCgpKGN1cnJlbnQpO1xuICAgICAgICAvLyB9IHdoaWxlIChjaGFpbi5sZW5ndGggPiAxKTtcblxuICAgICAgICByZXR1cm4gRmFicmljT2JqZWN0KCkob2JqKTtcbiAgICAgIH0pXG4gICAgICAuYXBwbHkoKTtcblxuICAgIGZ1bmN0aW9uIG9uZVRvT25lRGVjPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4gfCAoKCkgPT4gQ29uc3RydWN0b3I8TT4pLFxuICAgICAgY2FzY2FkZTogQ2FzY2FkZU1ldGFkYXRhLFxuICAgICAgcG9wdWxhdGU6IGJvb2xlYW4sXG4gICAgICBqb2luQ29sdW1uT3B0cz86IEpvaW5Db2x1bW5PcHRpb25zLFxuICAgICAgZms/OiBzdHJpbmdcbiAgICApIHtcbiAgICAgIGNvbnN0IG1ldGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICBjbGFzczogY2xhenosXG4gICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgIHBvcHVsYXRlOiBwb3B1bGF0ZSxcbiAgICAgIH07XG4gICAgICBpZiAoam9pbkNvbHVtbk9wdHMpIG1ldGEuam9pblRhYmxlID0gam9pbkNvbHVtbk9wdHM7XG4gICAgICBpZiAoZmspIG1ldGEubmFtZSA9IGZrO1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICBwcm9wKCksXG4gICAgICAgIHJlbGF0aW9uKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fT05FLCBtZXRhKSxcbiAgICAgICAgdHlwZShbY2xhenosIFN0cmluZywgTnVtYmVyLCBCaWdJbnRdKSxcbiAgICAgICAgb25DcmVhdGUob25lVG9PbmVPbkNyZWF0ZSBhcyBhbnksIG1ldGEpLFxuICAgICAgICBvblVwZGF0ZShvbmVUb09uZU9uVXBkYXRlIGFzIGFueSwgbWV0YSksXG4gICAgICAgIG9uRGVsZXRlKG9uZVRvT25lT25EZWxldGUgYXMgYW55LCBtZXRhKSxcbiAgICAgICAgYWZ0ZXJBbnkocG9wLCBtZXRhKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fT05FLCBtZXRhKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fT05FKVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogb25lVG9PbmVEZWMsXG4gICAgICB9IGFzIGFueSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgZnVuY3Rpb24gb25lVG9NYW55RGVjPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4gfCAoKCkgPT4gQ29uc3RydWN0b3I8TT4pLFxuICAgICAgY2FzY2FkZTogQ2FzY2FkZU1ldGFkYXRhLFxuICAgICAgcG9wdWxhdGU6IGJvb2xlYW4sXG4gICAgICBqb2luVGFibGVPcHRzPzogSm9pblRhYmxlT3B0aW9ucyB8IEpvaW5UYWJsZU11bHRpcGxlQ29sdW1uc09wdGlvbnMsXG4gICAgICBmaz86IHN0cmluZ1xuICAgICkge1xuICAgICAgY29uc3QgbWV0YWRhdGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICBjbGFzczogY2xhenosXG4gICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgIHBvcHVsYXRlOiBwb3B1bGF0ZSxcbiAgICAgIH07XG4gICAgICBpZiAoam9pblRhYmxlT3B0cykgbWV0YWRhdGEuam9pblRhYmxlID0gam9pblRhYmxlT3B0cztcbiAgICAgIGlmIChmaykgbWV0YWRhdGEubmFtZSA9IGZrO1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICBwcm9wKCksXG4gICAgICAgIHJlbGF0aW9uKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fTUFOWSwgbWV0YWRhdGEpLFxuICAgICAgICBsaXN0KFtjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPiwgU3RyaW5nLCBOdW1iZXJdKSxcbiAgICAgICAgb25DcmVhdGUob25lVG9NYW55T25DcmVhdGUgYXMgYW55LCBtZXRhZGF0YSksXG4gICAgICAgIG9uVXBkYXRlKG9uZVRvTWFueU9uVXBkYXRlLCBtZXRhZGF0YSksXG4gICAgICAgIG9uRGVsZXRlKG9uZVRvTWFueU9uRGVsZXRlIGFzIGFueSwgbWV0YWRhdGEpLFxuICAgICAgICBhZnRlckFueShwb3AsIG1ldGFkYXRhKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fTUFOWSwgbWV0YWRhdGEpXG4gICAgICApO1xuICAgIH1cblxuICAgIERlY29yYXRpb24uZm9yKFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fTUFOWSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IG9uZVRvTWFueURlYyxcbiAgICAgIH0gYXMgYW55KVxuICAgICAgLmFwcGx5KCk7XG4gIH1cbn1cblxuRmFicmljQ29udHJhY3RBZGFwdGVyLmRlY29yYXRpb24oKTtcbkFkYXB0ZXIuc2V0Q3VycmVudChGYWJyaWNGbGF2b3VyKTtcbiIsIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cbmltcG9ydCB7IEpTT05TZXJpYWxpemVyLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGV0ZXJtaW5pc3RpYyBKU09OIHNlcmlhbGl6ZXIgZm9yIEZhYnJpYyBtb2RlbHNcbiAqIEBzdW1tYXJ5IEVuc3VyZXMgc3RhYmxlLCBkZXRlcm1pbmlzdGljIEpTT04gb3V0cHV0IGJ5IHNvcnRpbmcgb2JqZWN0IGtleXMgcmVjdXJzaXZlbHkgYmVmb3JlIHN0cmluZ2lmaWNhdGlvbiwgd2hpY2ggaXMgaW1wb3J0YW50IGZvciBGYWJyaWMgZW5kb3JzZW1lbnQgYW5kIGhhc2hpbmcuIEV4dGVuZHMgSlNPTlNlcmlhbGl6ZXIgdG8gcGx1ZyBpbnRvIGV4aXN0aW5nIERlY2FmIG1vZGVsIHNlcmlhbGl6YXRpb24gZmxvdy5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIERlY2FmIE1vZGVsIHN1YnR5cGUgc2VyaWFsaXplZCBieSB0aGlzIGluc3RhbmNlXG4gKiBAcGFyYW0ge3ZvaWR9IFtjb25zdHJ1Y3Rvcl0gTm8gcHVibGljIGNvbnN0cnVjdG9yIGFyZ3VtZW50c1xuICogQGNsYXNzIERldGVybWluaXN0aWNTZXJpYWxpemVyXG4gKiBAZXhhbXBsZVxuICogY29uc3Qgc2VyaWFsaXplciA9IG5ldyBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxNeU1vZGVsPigpO1xuICogY29uc3QganNvbiA9IHNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsKTtcbiAqIGNvbnN0IHJlYnVpbHQgPSBzZXJpYWxpemVyLmRlc2VyaWFsaXplKGpzb24pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgRFMgYXMgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXJcbiAqICAgQ2FsbGVyLT4+RFM6IHNlcmlhbGl6ZShtb2RlbClcbiAqICAgRFMtPj5EUzogcHJlU2VyaWFsaXplKG1vZGVsKVxuICogICBEUy0+PkRTOiBzb3J0LWtleXMtcmVjdXJzaXZlXG4gKiAgIERTLT4+RFM6IGpzb24tc3RyaW5naWZ5LWRldGVybWluaXN0aWNcbiAqICAgRFMtLT4+Q2FsbGVyOiBzdHJpbmdcbiAqICAgQ2FsbGVyLT4+RFM6IGRlc2VyaWFsaXplKHN0cmluZylcbiAqICAgRFMtLT4+Q2FsbGVyOiBtb2RlbFxuICovXG5leHBvcnQgY2xhc3MgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbj4gZXh0ZW5kcyBKU09OU2VyaWFsaXplcjxNPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlc2VyaWFsaXplIGEgSlNPTiBzdHJpbmcgaW50byBhIG1vZGVsIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgYmFzZSBKU09OU2VyaWFsaXplciBpbXBsZW1lbnRhdGlvbiB0byByZWJ1aWxkIHRoZSBtb2RlbFxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gVGhlIEpTT04gc3RyaW5nIHRvIGRlc2VyaWFsaXplXG4gICAqIEByZXR1cm4ge019IFRoZSByZWNvbnN0cnVjdGVkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBvdmVycmlkZSBkZXNlcmlhbGl6ZShzdHI6IHN0cmluZyk6IE0ge1xuICAgIHJldHVybiBzdXBlci5kZXNlcmlhbGl6ZShzdHIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXJpYWxpemUgYSBtb2RlbCBpbnRvIGEgZGV0ZXJtaW5pc3RpYyBKU09OIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBQcmVwYXJlcyB0aGUgbW9kZWwgd2l0aCBwcmVTZXJpYWxpemUsIHNvcnRzIGtleXMgcmVjdXJzaXZlbHksIGFuZCBzdHJpbmdpZmllcyBkZXRlcm1pbmlzdGljYWxseSBmb3Igc3RhYmxlIG9yZGVyaW5nXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gc2VyaWFsaXplXG4gICAqIEByZXR1cm4ge3N0cmluZ30gRGV0ZXJtaW5pc3RpYyBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbFxuICAgKi9cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdHJpbmdpZnkgPSByZXF1aXJlKFwianNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1wiKTtcbiAgICBjb25zdCBzb3J0S2V5c1JlY3Vyc2l2ZSA9IHJlcXVpcmUoXCJzb3J0LWtleXMtcmVjdXJzaXZlXCIpO1xuICAgIHJldHVybiBzdHJpbmdpZnkoc29ydEtleXNSZWN1cnNpdmUodGhpcy5wcmVTZXJpYWxpemUobW9kZWwpKSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuLi9Db250cmFjdEFkYXB0ZXJcIjtcbmltcG9ydCB7IENvbnRyYWN0LCBDb250ZXh0IGFzIEN0eCB9IGZyb20gXCJmYWJyaWMtY29udHJhY3QtYXBpXCI7XG5pbXBvcnQgeyBNb2RlbCwgU2VyaWFsaXplciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIENvbmRpdGlvbixcbiAgQ29udGV4dCxcbiAgQ29udGV4dHVhbGl6ZWRBcmdzLFxuICBMb2dnZXJPZixcbiAgT3JkZXJEaXJlY3Rpb24sXG4gIFJlcG9zaXRvcnksXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL0RldGVybWluaXN0aWNTZXJpYWxpemVyXCI7XG5pbXBvcnQgeyBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgQ2hlY2thYmxlLCBoZWFsdGhjaGVjayB9IGZyb20gXCIuLi8uLi9zaGFyZWQvaW50ZXJmYWNlcy9DaGVja2FibGVcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi4vQ29udHJhY3RDb250ZXh0XCI7XG5pbXBvcnQge1xuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIEludGVybmFsRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG4gIFByaW1hcnlLZXlUeXBlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENoYWluY29kZVN0dWIsIENsaWVudElkZW50aXR5IH0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGNvbnRyYWN0IGNsYXNzIGZvciBDUlVEIG9wZXJhdGlvbnMgaW4gRmFicmljIGNoYWluY29kZVxuICogQHN1bW1hcnkgUHJvdmlkZXMgc3RhbmRhcmQgY3JlYXRlLCByZWFkLCB1cGRhdGUsIGFuZCBkZWxldGUgb3BlcmF0aW9ucyBmb3IgbW9kZWxzIGluIEZhYnJpYyBjaGFpbmNvZGVcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEBjbGFzcyBGYWJyaWNDcnVkQ29udHJhY3RcbiAqIEBleHRlbmRzIHtDb250cmFjdH1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBEZWZpbmUgYSBtb2RlbFxuICogQHRhYmxlKCdhc3NldHMnKVxuICogY2xhc3MgQXNzZXQgZXh0ZW5kcyBNb2RlbCB7XG4gKiAgIEBpZCgpXG4gKiAgIGlkOiBzdHJpbmc7XG4gKlxuICogICBAcHJvcGVydHkoKVxuICogICBkYXRhOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogLy8gQ3JlYXRlIGEgY29udHJhY3QgdGhhdCBleHRlbmRzIEZhYnJpY0NydWRDb250cmFjdFxuICogZXhwb3J0IGNsYXNzIEFzc2V0Q29udHJhY3QgZXh0ZW5kcyBGYWJyaWNDcnVkQ29udHJhY3Q8QXNzZXQ+IHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgc3VwZXIoJ0Fzc2V0Q29udHJhY3QnLCBBc3NldCk7XG4gKiAgIH1cbiAqXG4gKiAgIC8vIEFkZCBjdXN0b20gbWV0aG9kcyBhcyBuZWVkZWRcbiAqICAgYXN5bmMgZ2V0QXNzZXRIaXN0b3J5KGN0eDogQ29udGV4dCwgaWQ6IHN0cmluZyk6IFByb21pc2U8YW55W10+IHtcbiAqICAgICAvLyBDdXN0b20gaW1wbGVtZW50YXRpb25cbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgU3RhdGVEQlxuICpcbiAqICAgQ2xpZW50LT4+Q29udHJhY3Q6IGNyZWF0ZShjdHgsIG1vZGVsKVxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IHJlcG9zaXRvcnkoY3R4KVxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IGNyZWF0ZShtb2RlbCwgY3R4KVxuICogICBSZXBvc2l0b3J5LT4+QWRhcHRlcjogY3JlYXRlKHRhYmxlTmFtZSwgaWQsIHJlY29yZCwgdHJhbnNpZW50LCBjdHgpXG4gKiAgIEFkYXB0ZXItPj5TdGF0ZURCOiBwdXRTdGF0ZShpZCwgc2VyaWFsaXplZERhdGEpXG4gKiAgIFN0YXRlREItLT4+QWRhcHRlcjogU3VjY2Vzc1xuICogICBBZGFwdGVyLS0+PlJlcG9zaXRvcnk6IHJlY29yZFxuICogICBSZXBvc2l0b3J5LS0+PkNvbnRyYWN0OiBtb2RlbFxuICogICBDb250cmFjdC0tPj5DbGllbnQ6IG1vZGVsXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNDcnVkQ29udHJhY3Q8TSBleHRlbmRzIE1vZGVsPlxuICBleHRlbmRzIENvbnRyYWN0XG4gIGltcGxlbWVudHMgQ2hlY2thYmxlXG57XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2hhcmVkIGFkYXB0ZXIgaW5zdGFuY2UgZm9yIGFsbCBjb250cmFjdCBpbnN0YW5jZXNcbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgYWRhcHRlcjogRmFicmljQ29udHJhY3RBZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSByZXBvOiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8TT47XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBzZXJpYWxpemVyID0gbmV3IERldGVybWluaXN0aWNTZXJpYWxpemVyKCk7XG5cbiAgcHJvdGVjdGVkIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IEZhYnJpY0NydWRDb250cmFjdCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIGNvbnRyYWN0IHdpdGggYSBuYW1lIGFuZCBtb2RlbCBjbGFzc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjb250cmFjdFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKi9cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKG5hbWUpO1xuICAgIHRoaXMucmVwbyA9IFJlcG9zaXRvcnkuZm9yTW9kZWwoY2xhenopO1xuICB9XG5cbiAgYXN5bmMgbGlzdEJ5KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleTogc3RyaW5nIHwga2V5b2YgTSxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMubGlzdEJ5KTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmxpc3RCeShcbiAgICAgIGtleSBhcyBrZXlvZiBNLFxuICAgICAgb3JkZXIgYXMgT3JkZXJEaXJlY3Rpb24sXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHBhZ2luYXRlQnkoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5OiBzdHJpbmcgfCBrZXlvZiBNLFxuICAgIG9yZGVyOiBzdHJpbmcsXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMucGFnaW5hdGVCeSk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5wYWdpbmF0ZUJ5KGtleSBhcyBrZXlvZiBNLCBvcmRlciBhcyBhbnksIHNpemUsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgYXN5bmMgZmluZE9uZUJ5KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleTogc3RyaW5nIHwga2V5b2YgTSxcbiAgICB2YWx1ZTogYW55LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuZmluZE9uZUJ5KTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmZpbmRPbmVCeShrZXkgYXMga2V5b2YgTSwgdmFsdWUsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgYXN5bmMgc3RhdGVtZW50KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuc3RhdGVtZW50KTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnN0YXRlbWVudChtZXRob2QsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgc2luZ2xlIG1vZGVsIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyBjcmVhdGUgbWV0aG9kXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCBtb2RlbFxuICAgKi9cbiAgYXN5bmMgY3JlYXRlKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIG1vZGVsOiBzdHJpbmcgfCBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8c3RyaW5nIHwgTT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5pbmZvKGBDT05UUkFDVCBDUkVBVEUsICR7Y3R4QXJnc31gKTtcblxuICAgIGlmICh0eXBlb2YgbW9kZWwgPT09IFwic3RyaW5nXCIpIG1vZGVsID0gdGhpcy5kZXNlcmlhbGl6ZTxNPihtb2RlbCkgYXMgTTtcblxuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBtb2RlbDogJHtKU09OLnN0cmluZ2lmeShtb2RlbCl9YCk7XG5cbiAgICBjb25zdCB0cmFuc2llbnQgPSB0aGlzLmdldFRyYW5zaWVudERhdGEoY3R4KTtcblxuICAgIGxvZy5pbmZvKGBNZXJnaW5nIHRyYW5zaWVudCBkYXRhLi4uYCk7XG4gICAgbW9kZWwgPSBNb2RlbC5tZXJnZShtb2RlbCwgdHJhbnNpZW50LCB0aGlzLmNsYXp6KSBhcyBNO1xuXG4gICAgcmV0dXJuIHRoaXMucmVwby5jcmVhdGUobW9kZWwsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHNpbmdsZSBtb2RlbCBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyByZWFkIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgbW9kZWwgdG8gcmVhZFxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCBtb2RlbFxuICAgKi9cbiAgYXN5bmMgcmVhZChcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXk6IFByaW1hcnlLZXlUeXBlIHwgc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy5yZWFkKTtcblxuICAgIGxvZy5pbmZvKGByZWFkaW5nIGVudHJ5IHdpdGggcGsgJHtrZXl9IGApO1xuXG4gICAgcmV0dXJuIHRoaXMucmVwby5yZWFkKGtleSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VHJhbnNpZW50RGF0YShjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCk6IGFueSB7XG4gICAgY29uc3QgdHJhbnNpZW50TWFwID0gY3R4LnN0dWIuZ2V0VHJhbnNpZW50KCk7XG4gICAgbGV0IHRyYW5zaWVudDogYW55ID0ge307XG5cbiAgICBpZiAodHJhbnNpZW50TWFwLmhhcygodGhpcy5yZXBvIGFzIGFueSkudGFibGVOYW1lKSkge1xuICAgICAgdHJhbnNpZW50ID0gSlNPTi5wYXJzZShcbiAgICAgICAgKHRyYW5zaWVudE1hcC5nZXQoKHRoaXMucmVwbyBhcyBhbnkpLnRhYmxlTmFtZSkgYXMgQnVmZmVyKT8udG9TdHJpbmcoXG4gICAgICAgICAgXCJ1dGY4XCJcbiAgICAgICAgKSBhcyBzdHJpbmdcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zaWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHNpbmdsZSBtb2RlbCBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgdXBkYXRlIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgbW9kZWxcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBtb2RlbDogc3RyaW5nIHwgTSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPHN0cmluZyB8IE0+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMudXBkYXRlKTtcblxuICAgIGlmICh0eXBlb2YgbW9kZWwgPT09IFwic3RyaW5nXCIpIG1vZGVsID0gdGhpcy5kZXNlcmlhbGl6ZTxNPihtb2RlbCkgYXMgTTtcblxuICAgIGxvZy5pbmZvKGBVcGRhdGluZyBtb2RlbDogJHtKU09OLnN0cmluZ2lmeShtb2RlbCl9YCk7XG5cbiAgICBjb25zdCB0cmFuc2llbnQgPSB0aGlzLmdldFRyYW5zaWVudERhdGEoY3R4KTtcblxuICAgIGxvZy5pbmZvKGBNZXJnaW5nIHRyYW5zaWVudCBkYXRhLi4uYCk7XG4gICAgbW9kZWwgPSBNb2RlbC5tZXJnZShtb2RlbCwgdHJhbnNpZW50LCB0aGlzLmNsYXp6KSBhcyBNO1xuICAgIHJldHVybiB0aGlzLnJlcG8udXBkYXRlKG1vZGVsLCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIHNpbmdsZSBtb2RlbCBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyBkZWxldGUgbWV0aG9kXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBrZXkgLSBUaGUga2V5IG9mIHRoZSBtb2RlbCB0byBkZWxldGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIG1vZGVsXG4gICAqL1xuICBhc3luYyBkZWxldGUoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5OiBQcmltYXJ5S2V5VHlwZSB8IHN0cmluZyxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE0gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuZGVsZXRlKTtcbiAgICBsb2cuaW5mbyhgZGVsZXRpbmcgZW50cnkgd2l0aCBwayAke2tleX0gYCk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5kZWxldGUoU3RyaW5nKGtleSksIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIG11bHRpcGxlIG1vZGVscyBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyBkZWxldGVBbGwgbWV0aG9kXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0ga2V5cyAtIFRoZSBrZXlzIG9mIHRoZSBtb2RlbHMgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIG1vZGVsc1xuICAgKi9cbiAgYXN5bmMgZGVsZXRlQWxsKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleXM6IFByaW1hcnlLZXlUeXBlW10gfCBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLnJlYWRBbGwpO1xuICAgIGlmICh0eXBlb2Yga2V5cyA9PT0gXCJzdHJpbmdcIikga2V5cyA9IEpTT04ucGFyc2Uoa2V5cykgYXMgc3RyaW5nW107XG4gICAgcmV0dXJuIHRoaXMucmVwby5kZWxldGVBbGwoa2V5cywgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWRzIG11bHRpcGxlIG1vZGVscyBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyByZWFkQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGtleXMgLSBUaGUga2V5cyBvZiB0aGUgbW9kZWxzIHRvIHJlYWRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCBtb2RlbHNcbiAgICovXG4gIGFzeW5jIHJlYWRBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5czogUHJpbWFyeUtleVR5cGVbXSB8IHN0cmluZyxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE1bXSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMucmVhZEFsbCk7XG4gICAgaWYgKHR5cGVvZiBrZXlzID09PSBcInN0cmluZ1wiKSBrZXlzID0gSlNPTi5wYXJzZShrZXlzKSBhcyBzdHJpbmdbXTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnJlYWRBbGwoa2V5cywgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgbXVsdGlwbGUgbW9kZWxzIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyB1cGRhdGVBbGwgbWV0aG9kXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgbW9kZWxzIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCBtb2RlbHNcbiAgICovXG4gIGFzeW5jIHVwZGF0ZUFsbChcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBtb2RlbHM6IHN0cmluZyB8IE1bXSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPHN0cmluZyB8IE1bXT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy51cGRhdGVBbGwpO1xuICAgIGlmICh0eXBlb2YgbW9kZWxzID09PSBcInN0cmluZ1wiKVxuICAgICAgbW9kZWxzID0gKEpTT04ucGFyc2UobW9kZWxzKSBhcyBbXSlcbiAgICAgICAgLm1hcCgobSkgPT4gdGhpcy5kZXNlcmlhbGl6ZShtKSlcbiAgICAgICAgLm1hcCgobSkgPT4gbmV3IHRoaXMuY2xhenoobSkpIGFzIGFueTtcblxuICAgIGxvZy5pbmZvKGB1cGRhdGluZyAke21vZGVscy5sZW5ndGh9IGVudHJpZXMgdG8gdGhlIHRhYmxlYCk7XG4gICAgcmV0dXJuIHRoaXMucmVwby51cGRhdGVBbGwobW9kZWxzIGFzIHVua25vd24gYXMgTVtdLCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSBxdWVyeSB3aXRoIHRoZSBzcGVjaWZpZWQgY29uZGl0aW9ucyBhbmQgb3B0aW9ucy5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgYSBzaW1wbGlmaWVkIHdheSB0byBxdWVyeSB0aGUgZGF0YWJhc2Ugd2l0aCBjb21tb24gcXVlcnkgcGFyYW1ldGVycy5cbiAgICogQHBhcmFtIHtDb25kaXRpb248TT59IGNvbmRpdGlvbiAtIFRoZSBjb25kaXRpb24gdG8gZmlsdGVyIHJlY29yZHMuXG4gICAqIEBwYXJhbSBvcmRlckJ5IC0gVGhlIGZpZWxkIHRvIG9yZGVyIHJlc3VsdHMgYnkuXG4gICAqIEBwYXJhbSB7T3JkZXJEaXJlY3Rpb259IFtvcmRlcj1PcmRlckRpcmVjdGlvbi5BU0NdIC0gVGhlIHNvcnQgZGlyZWN0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2xpbWl0XSAtIE9wdGlvbmFsIG1heGltdW0gbnVtYmVyIG9mIHJlc3VsdHMgdG8gcmV0dXJuLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW3NraXBdIC0gT3B0aW9uYWwgbnVtYmVyIG9mIHJlc3VsdHMgdG8gc2tpcC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBUaGUgcXVlcnkgcmVzdWx0cyBhcyBtb2RlbCBpbnN0YW5jZXMuXG4gICAqL1xuICBhc3luYyBxdWVyeShcbiAgICBjb250ZXh0OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgY29uZGl0aW9uOiBDb25kaXRpb248TT4gfCBzdHJpbmcsXG4gICAgb3JkZXJCeTogc3RyaW5nIHwga2V5b2YgTSxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24gfCBzdHJpbmcgPSBPcmRlckRpcmVjdGlvbi5BU0MsXG4gICAgbGltaXQ/OiBudW1iZXIsXG4gICAgc2tpcD86IG51bWJlcixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE1bXT4ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGNvbnRleHRdLCB0aGlzLnF1ZXJ5KTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnF1ZXJ5KFxuICAgICAgY29uZGl0aW9uIGFzIENvbmRpdGlvbjxNPixcbiAgICAgIG9yZGVyQnkgYXMga2V5b2YgTSxcbiAgICAgIG9yZGVyIGFzIE9yZGVyRGlyZWN0aW9uLFxuICAgICAgbGltaXQsXG4gICAgICBza2lwLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIHJhdyBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHthbnl9IHJhd0lucHV0IC0gVGhlIHF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHBhcmFtIHtib29sZWFufSBkb2NzT25seSAtIFdoZXRoZXIgdG8gcmV0dXJuIG9ubHkgZG9jdW1lbnRzXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBxdWVyeSByZXN1bHRzXG4gICAqL1xuICBhc3luYyByYXcoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgcmF3SW5wdXQ6IE1hbmdvUXVlcnkgfCBzdHJpbmcsXG4gICAgZG9jc09ubHk6IGJvb2xlYW4sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxhbnkgfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLnJhdyk7XG4gICAgaWYgKHR5cGVvZiByYXdJbnB1dCA9PT0gXCJzdHJpbmdcIilcbiAgICAgIHJhd0lucHV0ID0gSlNPTi5wYXJzZShyYXdJbnB1dCkgYXMgTWFuZ29RdWVyeTtcbiAgICByZXR1cm4gRmFicmljQ3J1ZENvbnRyYWN0LmFkYXB0ZXIucmF3KHJhd0lucHV0LCBkb2NzT25seSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICByZXR1cm4gRmFicmljQ3J1ZENvbnRyYWN0LnNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBkZXNlcmlhbGl6ZTxNIGV4dGVuZHMgTW9kZWw+KHN0cjogc3RyaW5nKTogTSB7XG4gICAgcmV0dXJuIChcbiAgICAgIEZhYnJpY0NydWRDb250cmFjdC5zZXJpYWxpemVyIGFzIHVua25vd24gYXMgU2VyaWFsaXplcjxNPlxuICAgICkuZGVzZXJpYWxpemUoc3RyKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpbml0KGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjdHhdLCB0aGlzLmluaXQpO1xuICAgIGxvZy5pbmZvKGBSdW5uaW5nIGNvbnRyYWN0ICR7dGhpcy5nZXROYW1lKCl9IGluaXRpYWxpemF0aW9uLi4uYCk7XG4gICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgbG9nLmluZm8oYENvbnRyYWN0IGluaXRpYWxpemF0aW9uIGNvbXBsZXRlZC5gKTtcbiAgfVxuXG4gIGFzeW5jIGhlYWx0aGNoZWNrKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICk6IFByb21pc2U8c3RyaW5nIHwgaGVhbHRoY2hlY2s+IHtcbiAgICBjb25zdCB7IGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2N0eF0sIHRoaXMuaGVhbHRoY2hlY2spO1xuICAgIGxvZy5pbmZvKGBSdW5uaW5nIEhlYWx0aGNoZWNrOiAke3RoaXMuaW5pdGlhbGl6ZWR9Li4uYCk7XG4gICAgcmV0dXJuIHsgaGVhbHRoY2hlY2s6IHRoaXMuaW5pdGlhbGl6ZWQgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBtdWx0aXBsZSBtb2RlbHMgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIGNyZWF0ZUFsbCBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBtb2RlbHMgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIG1vZGVsc1xuICAgKi9cbiAgYXN5bmMgY3JlYXRlQWxsKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIG1vZGVsczogc3RyaW5nIHwgTVtdLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8c3RyaW5nIHwgTVtdPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLmNyZWF0ZUFsbCk7XG5cbiAgICBpZiAodHlwZW9mIG1vZGVscyA9PT0gXCJzdHJpbmdcIilcbiAgICAgIG1vZGVscyA9IChKU09OLnBhcnNlKG1vZGVscykgYXMgW10pXG4gICAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKSBhcyBhbnk7XG5cbiAgICBsb2cuaW5mbyhgYWRkaW5nICR7bW9kZWxzLmxlbmd0aH0gZW50cmllcyB0byB0aGUgdGFibGVgKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmNyZWF0ZUFsbChtb2RlbHMgYXMgdW5rbm93biBhcyBNW10sIGN0eCwgLi4uYXJncyk7XG4gIH1cblxuICBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogKCguLi5hcmdzOiBhbnlbXSkgPT4gYW55KSB8IHN0cmluZ1xuICApOiBQcm9taXNlPFxuICAgIENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgICB9XG4gID4ge1xuICAgIHJldHVybiBGYWJyaWNDcnVkQ29udHJhY3QubG9nQ3R4LmJpbmQodGhpcykoYXJncywgbWV0aG9kIGFzIGFueSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGFzeW5jIGxvZ0N0eDxBUkdTIGV4dGVuZHMgYW55W10+KFxuICAgIHRoaXM6IGFueSxcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogc3RyaW5nXG4gICk6IFByb21pc2U8XG4gICAgQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICAgIH1cbiAgPjtcbiAgcHJvdGVjdGVkIHN0YXRpYyBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55XG4gICk6IFByb21pc2U8XG4gICAgQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICAgIH1cbiAgPjtcbiAgcHJvdGVjdGVkIHN0YXRpYyBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBzdHJpbmdcbiAgKTogUHJvbWlzZTxcbiAgICBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPiAmIHtcbiAgICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gICAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gICAgfVxuICA+IHtcbiAgICBpZiAoYXJncy5sZW5ndGggPCAxKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vIGNvbnRleHQgcHJvdmlkZWRcIik7XG4gICAgY29uc3QgY3R4ID0gYXJncy5wb3AoKSBhcyBGYWJyaWNDb250cmFjdENvbnRleHQgfCBDb250ZXh0O1xuICAgIGlmIChjdHggaW5zdGFuY2VvZiBGYWJyaWNDb250cmFjdENvbnRleHQpXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjdHgsXG4gICAgICAgIGxvZzogY3R4LmxvZ2dlci5jbGVhcigpLmZvcih0aGlzKS5mb3IobWV0aG9kKSxcbiAgICAgICAgY3R4QXJnczogWy4uLmFyZ3MsIGN0eF0sXG4gICAgICAgIHN0dWI6IGN0eC5zdHViLFxuICAgICAgICBpZGVudGl0eTogY3R4LmlkZW50aXR5LFxuICAgICAgfTtcblxuICAgIGlmICghKGN0eCBpbnN0YW5jZW9mIEN0eCkpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vIHZhbGlkIGNvbnRleHQgcHJvdmlkZWRcIik7XG5cbiAgICBmdW5jdGlvbiBnZXRPcCgpIHtcbiAgICAgIGlmICh0eXBlb2YgbWV0aG9kID09PSBcInN0cmluZ1wiKSByZXR1cm4gbWV0aG9kO1xuICAgICAgc3dpdGNoIChtZXRob2QubmFtZSkge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuUkVBRDpcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLlVQREFURTpcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLkRFTEVURTpcbiAgICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTDpcbiAgICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTEw6XG4gICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLlVQREFURV9BTEw6XG4gICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEw6XG4gICAgICAgICAgcmV0dXJuIG1ldGhvZC5uYW1lO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBtZXRob2QubmFtZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBvdmVycmlkZXMgPSB7XG4gICAgICBjb3JyZWxhdGlvbklkOiBjdHguc3R1Yi5nZXRUeElEKCksXG4gICAgfTtcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgRmFicmljQ3J1ZENvbnRyYWN0LmFkYXB0ZXIuY29udGV4dChcbiAgICAgIGdldE9wKCksXG4gICAgICBvdmVycmlkZXMgYXMgYW55LFxuICAgICAgdGhpcy5jbGF6eixcbiAgICAgIGN0eFxuICAgICk7XG5cbiAgICBjb25zdCBsb2cgPSAoXG4gICAgICB0aGlzXG4gICAgICAgID8gY29udGV4dC5sb2dnZXIuZm9yKHRoaXMpLmZvcihtZXRob2QpXG4gICAgICAgIDogY29udGV4dC5sb2dnZXIuY2xlYXIoKS5mb3IodGhpcykuZm9yKG1ldGhvZClcbiAgICApIGFzIExvZ2dlck9mPEZhYnJpY0NvbnRyYWN0Q29udGV4dD47XG4gICAgcmV0dXJuIHtcbiAgICAgIGN0eDogY29udGV4dCxcbiAgICAgIGxvZzogbG9nLFxuICAgICAgc3R1YjogY29udGV4dC5zdHViLFxuICAgICAgaWRlbnRpdHk6IGNvbnRleHQuaWRlbnRpdHksXG4gICAgICBjdHhBcmdzOiBbLi4uYXJncywgY29udGV4dF0sXG4gICAgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRmFicmljQ3J1ZENvbnRyYWN0IH0gZnJvbSBcIi4vY3J1ZC1jb250cmFjdFwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgQ29udGV4dCBhcyBDdHgsIFRyYW5zYWN0aW9uIH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBDb25kaXRpb24sIE9yZGVyRGlyZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBTZXJpYWxpemF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ1JVRCBjb250cmFjdCB2YXJpYW50IHRoYXQgc2VyaWFsaXplcy9kZXNlcmlhbGl6ZXMgcGF5bG9hZHNcbiAqIEBzdW1tYXJ5IEV4cG9zZXMgdGhlIHNhbWUgQ1JVRCBvcGVyYXRpb25zIGFzIEZhYnJpY0NydWRDb250cmFjdCBidXQgdGFrZXMgYW5kIHJldHVybnMgSlNPTiBzdHJpbmdzIHRvIGZhY2lsaXRhdGUgc2ltcGxlIGNsaWVudCBpbnRlcmFjdGlvbnMuXG4gKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGUgaGFuZGxlZCBieSB0aGlzIGNvbnRyYWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBjb250cmFjdCBuYW1lXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvciB1c2VkIHRvIGluc3RhbnRpYXRlIG1vZGVscyBmcm9tIEpTT05cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgU2VyaWFsaXplZENydWRDb250cmFjdFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGNvbnRyYWN0ID0gbmV3IFNlcmlhbGl6ZWRDcnVkQ29udHJhY3Q8TXlNb2RlbD4oJ015TW9kZWxDb250cmFjdCcsIE15TW9kZWwpO1xuICogLy8gQ2xpZW50IHN1Ym1pdHMgSlNPTiBzdHJpbmcgcGF5bG9hZHMgYW5kIHJlY2VpdmVzIEpTT04gc3RyaW5nIHJlc3BvbnNlc1xuICovXG5leHBvcnQgY2xhc3MgU2VyaWFsaXplZENydWRDb250cmFjdDxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEZhYnJpY0NydWRDb250cmFjdDxNPiB7XG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgY2xheno6IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgc3VwZXIobmFtZSwgY2xhenopO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKClcbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlKGNvbnRleHQ6IEN0eCwgbW9kZWw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmNyZWF0ZSk7XG4gICAgbG9nLmluZm8oYENyZWF0aW5nIG1vZGVsOiAke21vZGVsfWApO1xuXG4gICAgY29uc3QgbSA9IHRoaXMuZGVzZXJpYWxpemU8TT4obW9kZWwpO1xuXG4gICAgbG9nLmluZm8oYE1vZGVsIGRlc2VyaWFsaXplZDogJHtKU09OLnN0cmluZ2lmeShtKX1gKTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemUoKGF3YWl0IHN1cGVyLmNyZWF0ZShjdHggYXMgYW55LCBtKSkgYXMgTSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQoY29udGV4dDogQ3R4LCBrZXk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJlYWQpO1xuICAgIGxvZy5pbmZvKGBSZWFkaW5nIGlkOiAke2tleX1gKTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemUoKGF3YWl0IHN1cGVyLnJlYWQoY3R4IGFzIGFueSwga2V5KSkgYXMgTSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyB1cGRhdGUoY29udGV4dDogQ3R4LCBtb2RlbDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMudXBkYXRlKTtcbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgbW9kZWw6ICR7bW9kZWx9YCk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplKChhd2FpdCBzdXBlci51cGRhdGUoY3R4IGFzIGFueSwgbW9kZWwpKSBhcyBNKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZShjb250ZXh0OiBDdHgsIGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuZGVsZXRlKTtcbiAgICBsb2cuaW5mbyhgRGVsZXRpbmcgaWQ6ICR7a2V5fWApO1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSgoYXdhaXQgc3VwZXIuZGVsZXRlKGN0eCBhcyBhbnksIGtleSkpIGFzIE0pO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKClcbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlQWxsKGNvbnRleHQ6IEN0eCwga2V5czogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBwYXJzZWRLZXlzOiBzdHJpbmdbXSA9IEpTT04ucGFyc2Uoa2V5cyk7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmRlbGV0ZUFsbCk7XG5cbiAgICBsb2cuaW5mbyhgZGVsZXRpbmcgJHtwYXJzZWRLZXlzLmxlbmd0aH0gZW50cmllcyBmcm9tIHRoZSB0YWJsZWApO1xuXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFxuICAgICAgKChhd2FpdCBzdXBlci5kZWxldGVBbGwoY3R4IGFzIGFueSwgcGFyc2VkS2V5cykpIGFzIE1bXSkubWFwKFxuICAgICAgICAobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZEFsbChjb250ZXh0OiBDdHgsIGtleXM6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcGFyc2VkS2V5czogc3RyaW5nW10gPSBKU09OLnBhcnNlKGtleXMpO1xuXG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJlYWRBbGwpO1xuICAgIGxvZy5pbmZvKGByZWFkaW5nICR7cGFyc2VkS2V5cy5sZW5ndGh9IGVudHJpZXMgZnJvbSB0aGUgdGFibGVgKTtcblxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgICgoYXdhaXQgc3VwZXIucmVhZEFsbChjdHggYXMgYW55LCBwYXJzZWRLZXlzKSkgYXMgTVtdKS5tYXAoKG0pID0+XG4gICAgICAgIHRoaXMuc2VyaWFsaXplKG0pXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbChjb250ZXh0OiBDdHgsIG1vZGVsczogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMudXBkYXRlQWxsKTtcbiAgICBjb25zdCBsaXN0OiBzdHJpbmdbXSA9IEpTT04ucGFyc2UobW9kZWxzKTtcbiAgICBjb25zdCBtb2RlbExpc3Q6IE1bXSA9IGxpc3RcbiAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAubWFwKChtKSA9PiBuZXcgdGhpcy5jbGF6eihtKSk7XG5cbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgJHttb2RlbExpc3QubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgICgoYXdhaXQgc3VwZXIudXBkYXRlQWxsKGN0eCBhcyBhbnksIG1vZGVsTGlzdCkpIGFzIE1bXSkubWFwKFxuICAgICAgICAobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgc3RhdGVtZW50KGNvbnRleHQ6IEN0eCwgbWV0aG9kOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGNvbnRleHRdLCB0aGlzLnN0YXRlbWVudCk7XG4gICAgYXJncyA9IGFyZ3MubWFwKChhKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShhKTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICByZXR1cm4gYTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBsb2cuaW5mbyhgY2FsbGluZyBwcmVwYXJlZCBzdGF0ZW1lbnQgJHttZXRob2R9YCk7XG4gICAgbG9nLmRlYnVnKGB3aXRoIGFyZ3MgJHthcmdzfWApO1xuICAgIHJldHVybiBzdXBlci5zdGF0ZW1lbnQoY3R4LCBtZXRob2QsIC4uLmFyZ3MpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBsaXN0QnkoXG4gICAgY29udGV4dDogQ3R4LFxuICAgIGtleTogc3RyaW5nLFxuICAgIG9yZGVyOiBzdHJpbmcsXG4gICAgLi4uYXJnczogc3RyaW5nW11cbiAgKSB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjb250ZXh0XSwgdGhpcy5saXN0QnkpO1xuICAgIHJldHVybiBzdXBlci5saXN0QnkoY3R4LCBrZXkgYXMga2V5b2YgTSwgb3JkZXIgYXMgT3JkZXJEaXJlY3Rpb24pO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGNvbnRleHQ6IEN0eCxcbiAgICBrZXk6IHN0cmluZyxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIHNpemU6IG51bWJlcixcbiAgICAuLi5hcmdzOiBzdHJpbmdbXVxuICApIHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGNvbnRleHRdLCB0aGlzLnBhZ2luYXRlQnkpO1xuICAgIHJldHVybiBzdXBlci5wYWdpbmF0ZUJ5KGN0eCwga2V5LCBvcmRlciBhcyBhbnksIHNpemUpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBmaW5kT25lQnkoXG4gICAgY29udGV4dDogQ3R4LFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcsXG4gICAgLi4uYXJnczogc3RyaW5nW11cbiAgKSB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjb250ZXh0XSwgdGhpcy5wYWdpbmF0ZUJ5KTtcbiAgICByZXR1cm4gc3VwZXIuZmluZE9uZUJ5KGN0eCwga2V5LCB2YWx1ZSwgLi4uYXJncyk7XG4gIH1cblxuICAvLyBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHF1ZXJ5KFxuICAgIGNvbnRleHQ6IEN0eCxcbiAgICBjb25kaXRpb246IHN0cmluZyxcbiAgICBvcmRlckJ5OiBzdHJpbmcsXG4gICAgb3JkZXI6IHN0cmluZyxcbiAgICBsaW1pdD86IG51bWJlcixcbiAgICBza2lwPzogbnVtYmVyLFxuICAgIC4uLmFyZ3M6IHN0cmluZ1tdXG4gICk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5xdWVyeSk7XG4gICAgbGV0IGNvbmQ6IENvbmRpdGlvbjxhbnk+O1xuICAgIHRyeSB7XG4gICAgICBjb25kID0gQ29uZGl0aW9uLmZyb20oSlNPTi5wYXJzZShjb25kaXRpb24pKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBJbnZhbGlkIGNvbmRpdGlvbjogJHtlfWApO1xuICAgIH1cbiAgICByZXR1cm4gc3VwZXIucXVlcnkoY3R4LCBjb25kLCBvcmRlckJ5LCBvcmRlciBhcyBhbnksIGxpbWl0LCBza2lwLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8vIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgcmF3KFxuICAgIGNvbnRleHQ6IEN0eCxcbiAgICByYXdJbnB1dDogc3RyaW5nLFxuICAgIGRvY3NPbmx5OiBib29sZWFuLFxuICAgIC4uLmFyZ3M6IHN0cmluZ1tdXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5yYXcpO1xuICAgIGNvbnN0IHBhcnNlZElucHV0OiBNYW5nb1F1ZXJ5ID0gSlNPTi5wYXJzZShyYXdJbnB1dCk7XG4gICAgcmV0dXJuIHN1cGVyLnJhdyhjdHgsIHBhcnNlZElucHV0LCBkb2NzT25seSwgLi4uYXJncyk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBpbml0KGN0eDogQ3R4KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgc3VwZXIuaW5pdChjdHgpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBoZWFsdGhjaGVjayhjb250ZXh0OiBDdHgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy51cGRhdGVBbGwpO1xuICAgIGxvZy5kZWJ1ZyhgUnVubmluZyBIZWFsdGhjaGVjazogJHt0aGlzLmluaXRpYWxpemVkfS4uLmApO1xuICAgIC8vVE9ETzogVFJJTSBOT1QgV09SS0lORyBDSEVDSyBMQVRFUlxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhd2FpdCBzdXBlci5oZWFsdGhjaGVjayhjdHggYXMgYW55KSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGwoY29udGV4dDogQ3R4LCBtb2RlbHM6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5jcmVhdGVBbGwpO1xuICAgIGNvbnN0IGxpc3Q6IHN0cmluZ1tdID0gSlNPTi5wYXJzZShtb2RlbHMpO1xuICAgIGNvbnN0IG1vZGVsTGlzdDogTVtdID0gbGlzdFxuICAgICAgLm1hcCgobSkgPT4gdGhpcy5kZXNlcmlhbGl6ZShtKSlcbiAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKTtcblxuICAgIGxvZy5pbmZvKGBBZGRpbmcgJHttb2RlbExpc3QubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgICgoYXdhaXQgc3VwZXIuY3JlYXRlQWxsKGNvbnRleHQsIG1vZGVsTGlzdCkpIGFzIE1bXSkubWFwKFxuICAgICAgICAobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nXG4gICAgICApXG4gICAgKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQmFzZUVycm9yLCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBBdXRob3JpemF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbi8vIGltcG9ydCB7IE1JU1NJTkdfUFJJVkFURV9EQVRBX0VSUk9SX01FU1NBR0UgfSBmcm9tIFwiLi4vY29udHJhY3RzL3ByaXZhdGUtZGF0YVwiO1xuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGFuIG92ZXJmbG93IGVycm9yIGluIGFyaXRobWV0aWMgb3BlcmF0aW9ucyBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIE92ZXJmbG93RXJyb3JcbiAqIEBleHRlbmRzIEludGVybmFsRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBPdmVyZmxvd0Vycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIE92ZXJmbG93RXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiBiYWxhbmNlIHRvIHBlcmZvcm0gYSB0cmFuc2FjdGlvbiBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEJhbGFuY2VFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIEJhbGFuY2VFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBCYWxhbmNlRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiBiYWxhbmNlIHRvIHBlcmZvcm0gYSB0cmFuc2FjdGlvbiBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEJhbGFuY2VFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIEFsbG93YW5jZUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIEFsbG93YW5jZUVycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgcmVnaXN0cmF0aW5nIG5ldyBlbnRpdGllc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgUmVnaXN0cmF0aW9uRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnQgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpc3RyYXRpb25FcnJvciBleHRlbmRzIEF1dGhvcml6YXRpb25FcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIFJlZ2lzdHJhdGlvbkVycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIGFuIHVuc3VwcG9ydGVkIG9wZXJhdGlvbiBpcyBhdHRlbXB0ZWRcbiAqIEBzdW1tYXJ5IFRoaXMgZXJyb3IgaXMgdGhyb3duIHdoZW4gYW4gb3BlcmF0aW9uIGlzIHJlcXVlc3RlZCB0aGF0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIGN1cnJlbnRcbiAqIHBlcnNpc3RlbmNlIGFkYXB0ZXIgb3IgY29uZmlndXJhdGlvbi4gSXQgZXh0ZW5kcyB0aGUgQmFzZUVycm9yIGNsYXNzIGFuZCBzZXRzIGEgNTAwIHN0YXR1cyBjb2RlLlxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIGFuIEVycm9yIG9iamVjdCB0byB3cmFwXG4gKiBAY2xhc3MgVW5zdXBwb3J0ZWRFcnJvclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFRocm93aW5nIGFuIFVuc3VwcG9ydGVkRXJyb3JcbiAqIGlmICghYWRhcHRlci5zdXBwb3J0c1RyYW5zYWN0aW9ucygpKSB7XG4gKiAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKCdUcmFuc2FjdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgYnkgdGhpcyBhZGFwdGVyJyk7XG4gKiB9XG4gKlxuICogLy8gQ2F0Y2hpbmcgYW4gVW5zdXBwb3J0ZWRFcnJvclxuICogdHJ5IHtcbiAqICAgYXdhaXQgYWRhcHRlci5iZWdpblRyYW5zYWN0aW9uKCk7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBVbnN1cHBvcnRlZEVycm9yKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcignT3BlcmF0aW9uIG5vdCBzdXBwb3J0ZWQ6JywgZXJyb3IubWVzc2FnZSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIE1pc3NpbmdDb250ZXh0RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgTWlzc2luZ0NvbnRleHRFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IgPSBcIk1JU1NJTkdfUFJJVkFURV9EQVRBX0VSUk9SX01FU1NBR0VcIikge1xuICAgIHN1cGVyKFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzLm5hbWUsIG1zZywgNDAzKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYW4gZXJyb3IgdGhhdCBvY2N1cnMgd2hlbiBhIHJlcXVpcmVkIGluaXRpYWxpemF0aW9uIHN0ZXAgaXMgbm90IHBlcmZvcm1lZC5cbiAqXG4gKiBAY2xhc3MgTm90SW5pdGlhbGl6ZWRFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nIHwgRXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIGFuIEVycm9yIG9iamVjdCB0byB3cmFwLlxuICpcbiAqIEB0aHJvd3Mge05vdEluaXRpYWxpemVkRXJyb3J9IC0gVGhyb3dzIGFuIGVycm9yIHdoZW4gYSByZXF1aXJlZCBpbml0aWFsaXphdGlvbiBzdGVwIGlzIG5vdCBwZXJmb3JtZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluaXRpYWxpemUgdGhlIGFwcGxpY2F0aW9uXG4gKiBpZiAoIWlzSW5pdGlhbGl6ZWQpIHtcbiAqICAgdGhyb3cgbmV3IE5vdEluaXRpYWxpemVkRXJyb3IoJ0FwcGxpY2F0aW9uIGlzIG5vdCBpbml0aWFsaXplZCcpO1xuICogfVxuICpcbiAqIC8vIENhdGNoaW5nIGFuIE5vdEluaXRpYWxpemVkRXJyb3JcbiAqIHRyeSB7XG4gKiAgIC8vIFBlcmZvcm0gb3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgaW5pdGlhbGl6YXRpb25cbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE5vdEluaXRpYWxpemVkRXJyb3IpIHtcbiAqICAgICBjb25zb2xlLmVycm9yKCdJbml0aWFsaXphdGlvbiBlcnJvcjonLCBlcnJvci5tZXNzYWdlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBOb3RJbml0aWFsaXplZEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKE5vdEluaXRpYWxpemVkRXJyb3IubmFtZSwgbXNnLCA0MDkpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNaXNzaW5nUEtDU1MxMUxpYiBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBNaXNzaW5nUEtDU1MxMUxpYi5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBFbmRvcnNlbWVudEVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgRW5kb3JzZW1lbnRFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG4iLCJpbXBvcnQgeyBzdHJpbmdGb3JtYXQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPdmVyZmxvd0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3ZlcmZsb3ctc2FmZSBhZGRpdGlvbiBvcGVyYXRpb25cbiAqIEBzdW1tYXJ5IEFkZHMgdHdvIG51bWJlcnMgYW5kIHZlcmlmaWVzIG5vIG92ZXJmbG93IGJ5IHJldmVyc2UtY2hlY2tpbmcgdGhlIG9wZXJhbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gYSAtIEZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gU2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIHN1bSBvZiBhIGFuZCBiXG4gKiBAZnVuY3Rpb24gYWRkXG4gKiBAdGhyb3dzIHtPdmVyZmxvd0Vycm9yfSBvbiBhZGRpdGlvbiBvdmVyZmxvd1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYyA9IGEgKyBiO1xuICBpZiAoYSAhPT0gYyAtIGIgfHwgYiAhPT0gYyAtIGEpIHtcbiAgICB0aHJvdyBuZXcgT3ZlcmZsb3dFcnJvcihgQWRkaXRpb24gb3ZlcmZsb3c6ICR7YX0gKyAke2J9YCk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE92ZXJmbG93LXNhZmUgc3VidHJhY3Rpb24gb3BlcmF0aW9uXG4gKiBAc3VtbWFyeSBTdWJ0cmFjdHMgYiBmcm9tIGEgYW5kIHZhbGlkYXRlcyBubyBvdmVyZmxvdyBieSByZXZlcnNlLWNoZWNraW5nIHRoZSBvcGVyYW5kc1xuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBNaW51ZW5kXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFN1YnRyYWhlbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGRpZmZlcmVuY2UgYSAtIGJcbiAqIEBmdW5jdGlvbiBzdWJcbiAqIEB0aHJvd3Mge092ZXJmbG93RXJyb3J9IG9uIHN1YnRhY3Rpb24gb3ZlcmZsb3dcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YihhOiBudW1iZXIsIGI6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGMgPSBhIC0gYjtcbiAgaWYgKGEgIT09IGMgKyBiIHx8IGIgIT09IGEgLSBjKSB7XG4gICAgdGhyb3cgbmV3IE92ZXJmbG93RXJyb3IoYFN1YnRyYWN0aW9uIG92ZXJmbG93OiAke2F9IC0gJHtifWApO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFNhZmUgSW50ZWdlciBQYXJzZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcbiAqXG4gKiBAZnVuY3Rpb24gc2FmZVBhcnNlSW50XG4gKlxuICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBpZiBwYXJzZUludCByZXR1cm5zIE5hTlxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZUludChzdHJpbmc6IHN0cmluZyk6IG51bWJlciB7XG4gIC8vIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBjaGVjayBpZiBzdHJpbmcgb25seSBoYXZlIGRpZ2l0c1xuICBjb25zdCBkaWdpdFJlZ2V4ID0gL15cXGQrJC87XG4gIGlmICghZGlnaXRSZWdleC50ZXN0KHN0cmluZykpIHtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgc3RyaW5nRm9ybWF0KFwiRmFpbGVkIHRvIHBhcnNlOiB7MH1cIiwgXCJzdHJpbmcgY29udGFpbnMgZGlnaXRzXCIpXG4gICAgKTtcbiAgfVxuICBjb25zdCBwYXJzZWRpbnQgPSBwYXJzZUludChzdHJpbmcpO1xuICBpZiAoaXNOYU4ocGFyc2VkaW50KSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBzdHJpbmdGb3JtYXQoXCJGYWlsZWQgdG8gcGFyc2U6IHswfVwiLCBcInN0cmluZyBpcyBub3QgYSBwYXJzYWJsZSBpbnRlZ2VyXCIpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gcGFyc2VkaW50O1xufVxuIiwiaW1wb3J0IHsgQmFzZU1vZGVsLCBjb2x1bW4sIHBrLCB0YWJsZSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgbW9kZWwsIHR5cGUgTW9kZWxBcmcsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCB0b2tlbiBtZXRhZGF0YSBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBFUkMyMCB0b2tlbiBkZWZpbml0aW9uIHdpdGhpbiB0aGUgRmFicmljIEVSQzIwIHNhbXBsZSwgaW5jbHVkaW5nIG5hbWUsIHN5bWJvbCwgZGVjaW1hbHMsIGFuZCB0aGUgb3duaW5nIGlkZW50aXR5LiBVc2VkIHRvIGRlZmluZSB0aGUgdW5pcXVlIHRva2VuIG1hbmFnZWQgYnkgdGhlIGNvbnRyYWN0LlxuICogQHBhcmFtIHtNb2RlbEFyZzxFUkMyMFRva2VuPn0gW21dIC0gT3B0aW9uYWwgcGFydGlhbCBkYXRhIG9yIGFub3RoZXIgaW5zdGFuY2UgdG8gaW5pdGlhbGl6ZSB0aGUgbW9kZWxcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRVJDMjBUb2tlblxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHRva2VuID0gbmV3IEVSQzIwVG9rZW4oeyBuYW1lOiBcIk15VG9rZW5cIiwgc3ltYm9sOiBcIk1US1wiLCBkZWNpbWFsczogMTgsIG93bmVyOiBcIng1MDk6Oi4uLlwiIH0pO1xuICogLy8gUGVyc2lzdCB0aHJvdWdoIGEgcmVwb3NpdG9yeTogYXdhaXQgcmVwby5jcmVhdGUodG9rZW4sIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBBcHAtPj5SZXBvOiBjcmVhdGUobmV3IEVSQzIwVG9rZW4oey4uLn0pLCBjdHgpXG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBjcmVhdGUodGFibGUsIGlkPW5hbWUsIHJlY29yZCwgZmxhZ3MpXG4gKiAgIEFkYXB0ZXItLT4+UmVwbzogc3RvcmVkXG4gKiAgIFJlcG8tLT4+QXBwOiBtb2RlbFxuICovXG5AdGFibGUoXCJlcmMyMF90b2tlbnNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBUb2tlbiBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIEBwayh7IHR5cGU6IFwiU3RyaW5nXCIgfSlcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiB1bmlxdWUgbmFtZVxuICAgKiBAc3VtbWFyeSBTZXJ2ZXMgYXMgdGhlIHByaW1hcnkga2V5IGZvciB0aGUgRVJDMjAgdG9rZW4gZGVmaW5pdGlvbjsgdHlwaWNhbGx5IGEgaHVtYW4tcmVhZGFibGUgaWRlbnRpZmllclxuICAgKi9cbiAgbmFtZSE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBPd25pbmcgaWRlbnRpdHkgb2YgdGhlIHRva2VuXG4gICAqIEBzdW1tYXJ5IFguNTA5IHN1YmplY3Qgb3IgTVNQIGlkZW50aXR5IHN0cmluZyB0aGF0IGRlbm90ZXMgd2hvIG93bnMvY29udHJvbHMgdGhlIHRva2VuIGRlZmluaXRpb25cbiAgICovXG4gIG93bmVyITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiBzeW1ib2xcbiAgICogQHN1bW1hcnkgU2hvcnQgdGlja2VyLWxpa2Ugc3ltYm9sIHVzZWQgdG8gcmVwcmVzZW50IHRoZSB0b2tlbiAoZS5nLiwgTVRLKVxuICAgKi9cbiAgc3ltYm9sITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNpbWFsIHByZWNpc2lvbiBmb3IgdG9rZW4gYW1vdW50c1xuICAgKiBAc3VtbWFyeSBOdW1iZXIgb2YgZGlnaXRzIGFmdGVyIHRoZSBkZWNpbWFsIHNlcGFyYXRvciB1c2VkIHdoZW4gZm9ybWF0dGluZyB0b2tlbiBiYWxhbmNlc1xuICAgKi9cbiAgZGVjaW1hbHMhOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IobT86IE1vZGVsQXJnPEVSQzIwV2FsbGV0Pikge1xuICAgIHN1cGVyKG0pO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVSQzIwIHdhbGxldCBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGhvbGRlciBhY2NvdW50IGZvciBhbiBFUkMyMCB0b2tlbiB3aXRoaW4gdGhlIEZhYnJpYyBuZXR3b3JrLCB0cmFja2luZyBiYWxhbmNlIGFuZCB0b2tlbiBhc3NvY2lhdGlvbi5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8RVJDMjBXYWxsZXQ+fSBbbV0gLSBPcHRpb25hbCBwYXJ0aWFsIGRhdGEgb3IgYW5vdGhlciBpbnN0YW5jZSB0byBpbml0aWFsaXplIHRoZSBtb2RlbFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBFUkMyMFdhbGxldFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHdhbGxldCA9IG5ldyBFUkMyMFdhbGxldCh7IGlkOiBcImFjY3QxXCIsIHRva2VuOiBcIk15VG9rZW5cIiwgYmFsYW5jZTogMTAwMCB9KTtcbiAqIC8vIFVwZGF0ZSBiYWxhbmNlIHZpYSByZXBvc2l0b3J5OiBhd2FpdCByZXBvLnVwZGF0ZSh3YWxsZXQsIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgQXBwLT4+UmVwbzogcmVhZChcImFjY3QxXCIsIGN0eClcbiAqICAgUmVwby0tPj5BcHA6IEVSQzIwV2FsbGV0XG4gKi9cbkB0YWJsZShcImVyYzIwX3dhbGxldHNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBXYWxsZXQgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICBAcGsoeyB0eXBlOiBcIlN0cmluZ1wiIH0pXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2FsbGV0IHVuaXF1ZSBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFByaW1hcnkga2V5IGZvciB0aGUgd2FsbGV0OyBjb21tb25seSByZWZlcmVuY2VzIGFuIGFjY291bnQgb3IgaWRlbnRpdHlcbiAgICovXG4gIGlkITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFzc29jaWF0ZWQgdG9rZW4gbmFtZVxuICAgKiBAc3VtbWFyeSBSZWZlcmVuY2VzIHRoZSBFUkMyMFRva2VuIHRoaXMgd2FsbGV0IGhvbGRzOyBtYWludGFpbmVkIGFzIGEgcmVsYXRpb25zaGlwIGZvciBjYXNjYWRpbmcgdXBkYXRlcy9kZWxldGVzXG4gICAqL1xuICB0b2tlbiE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiBiYWxhbmNlIGZvciB0aGlzIHdhbGxldFxuICAgKiBAc3VtbWFyeSBDdXJyZW50IGFtb3VudCBvZiB0aGUgYXNzb2NpYXRlZCB0b2tlbiBoZWxkIGJ5IHRoaXMgd2FsbGV0XG4gICAqL1xuICBiYWxhbmNlITogbnVtYmVyO1xuXG4gIEBjb2x1bW4oKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENhcHRpdmUgZmxhZyBvciBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IE9wdGlvbmFsIGZpZWxkIHVzZWQgYnkgc29tZSBmbG93cyB0byBtYXJrIG5vbi10cmFuc2ZlcmFibGUgZnVuZHMgb3IgbWFuYWdlZCBjdXN0b2R5XG4gICAqL1xuICBjYXB0aXZlITogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG0/OiBNb2RlbEFyZzxFUkMyMFdhbGxldD4pIHtcbiAgICBzdXBlcihtKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCBhbGxvd2FuY2UgbW9kZWxcbiAqIEBzdW1tYXJ5IENhcHR1cmVzIGFuIGFwcHJvdmFsIHJlbGF0aW9uc2hpcCB3aGVyZSBhbiBvd25lciBhbGxvd3MgYSBzcGVuZGVyIHRvIHRyYW5zZmVyIHVwIHRvIGEgY2VydGFpbiB2YWx1ZSBmcm9tIHRoZSBvd25lcidzIHdhbGxldC5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8QWxsb3dhbmNlPn0gW21dIC0gT3B0aW9uYWwgcGFydGlhbCBkYXRhIG9yIGFub3RoZXIgaW5zdGFuY2UgdG8gaW5pdGlhbGl6ZSB0aGUgbW9kZWxcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgQWxsb3dhbmNlXG4gKiBAZXhhbXBsZVxuICogY29uc3QgYWxsb3dhbmNlID0gbmV3IEFsbG93YW5jZSh7IG93bmVyOiBcImFjY3QxXCIsIHNwZW5kZXI6IFwiYWNjdDJcIiwgdmFsdWU6IDUwIH0pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgQXBwLT4+QXBwOiBuZXcgQWxsb3dhbmNlKHsgb3duZXIsIHNwZW5kZXIsIHZhbHVlIH0pXG4gKi9cbkB0YWJsZShcImVyYzIwX2FsbG93YW5jZXNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgQWxsb3dhbmNlIGV4dGVuZHMgQmFzZU1vZGVsIHtcbiAgQHBrKHsgdHlwZTogXCJTdHJpbmdcIiB9KVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFsbG93YW5jZSB1bmlxdWUgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSBmb3IgdGhlIGFsbG93YW5jZTsgdHlwaWNhbGx5IGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBhcHByb3ZhbCByZWxhdGlvbnNoaXBcbiAgICovXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE93bmVyIHdhbGxldCBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFdhbGxldCB0aGF0IGF1dGhvcml6ZXMgdGhlIGFsbG93YW5jZVxuICAgKi9cbiAgb3duZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3BlbmRlciB3YWxsZXQgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBXYWxsZXQgYWxsb3dlZCB0byBzcGVuZCB1cCB0byB0aGUgYXBwcm92ZWQgdmFsdWUgZnJvbSB0aGUgb3duZXJcbiAgICovXG4gIHNwZW5kZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXBwcm92ZWQgdmFsdWVcbiAgICogQHN1bW1hcnkgTWF4aW11bSB0b2tlbiBhbW91bnQgdGhlIHNwZW5kZXIgbWF5IHRyYW5zZmVyIG9uIGJlaGFsZiBvZiB0aGUgb3duZXJcbiAgICovXG4gIHZhbHVlITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKG0/OiBNb2RlbEFyZzxBbGxvd2FuY2U+KSB7XG4gICAgc3VwZXIobSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEF1dGhvcml6YXRpb25FcnJvcixcbiAgUmVwbyxcbiAgQ29udGV4dCxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgUmVwb3NpdG9yeSxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBvbkNyZWF0ZSxcbiAgb25EZWxldGUsXG4gIG9uUmVhZCxcbiAgb25VcGRhdGUsXG4gIHJlYWRvbmx5LFxuICB0cmFuc2llbnQsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljTW9kZWxLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSExDb250ZXh0IH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IEZhYnJpY0VSQzIwQ29udHJhY3QgfSBmcm9tIFwiLi4vY29udHJhY3RzL2VyYzIwL2VyYzIwY29udHJhY3RcIjtcbmltcG9ydCB7XG4gIGFwcGx5LFxuICBDb25zdHJ1Y3RvcixcbiAgRGVjb3JhdGlvbixcbiAgbWV0YWRhdGEsXG4gIE1ldGFkYXRhLFxuICBwcm9wTWV0YWRhdGEsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIERlY29yYXRvciBmb3IgbWFya2luZyBtZXRob2RzIHRoYXQgcmVxdWlyZSBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqIENoZWNrcyB0aGUgb3duZXIgb2YgdGhlIHRva2VuIGJlZm9yZSBhbGxvd2luZyB0aGUgbWV0aG9kIHRvIGJlIGV4ZWN1dGVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjbGFzcyBUb2tlbkNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBAT3duZXIoKVxuICogICBhc3luYyBNaW50KGN0eDogQ29udGV4dCwgYW1vdW50OiBudW1iZXIpIHtcbiAqICAgICAvLyBNaW50IHRva2VuIGxvZ2ljXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEByZXR1cm5zIHtNZXRob2REZWNvcmF0b3J9IEEgbWV0aG9kIGRlY29yYXRvciB0aGF0IGNoZWNrcyBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE93bmVyKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gICAgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkge1xuICAgIGNvbnN0IG9yaWdpbmFsTWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBhc3luYyBmdW5jdGlvbiAoXG4gICAgICB0aGlzOiBGYWJyaWNFUkMyMENvbnRyYWN0LFxuICAgICAgLi4uYXJnczogYW55W11cbiAgICApIHtcbiAgICAgIGNvbnN0IGN0eDogSExDb250ZXh0ID0gYXJnc1swXTtcbiAgICAgIGNvbnN0IGFjb3VudElkID0gY3R4LmNsaWVudElkZW50aXR5LmdldElEKCk7XG5cbiAgICAgIGNvbnN0IHNlbGVjdCA9IGF3YWl0ICh0aGlzIGFzIEZhYnJpY0VSQzIwQ29udHJhY3QpW1xuICAgICAgICBcInRva2VuUmVwb3NpdG9yeVwiXG4gICAgICBdLnNlbGVjdCgpO1xuXG4gICAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpO1xuXG4gICAgICBpZiAodG9rZW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFwiTm8gdG9rZW5zIGF2YWlhbGJsZVwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vucy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKGBUbyBtYW55IHRva2VuIGF2YWlsYWJsZSA6ICR7dG9rZW5zLmxlbmd0aH1gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vuc1swXS5vd25lciAhPSBhY291bnRJZCkge1xuICAgICAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgICAgIGBVc2VyIG5vdCBhdXRob3JpemVkIHRvIHJ1biAke3Byb3BlcnR5S2V5fSBvbiB0aGUgdG9rZW5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCBvcmlnaW5hbE1ldGhvZC5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvd25lZEJ5T25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbDxib29sZWFuPixcbiAgUiBleHRlbmRzIFJlcG88TT4sXG4gIFYsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PGFueT4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHN0dWIgfSA9IGNvbnRleHQgYXMgYW55O1xuXG4gIGNvbnN0IGNyZWF0b3IgPSBhd2FpdCBzdHViLmdldENyZWF0b3IoKTtcbiAgY29uc3Qgb3duZXIgPSBjcmVhdG9yLm1zcGlkO1xuXG4gIGNvbnN0IHNldE93bmVkQnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG5cbiAgc2V0T3duZWRCeUtleVZhbHVlKG1vZGVsLCBrZXkgYXMgc3RyaW5nLCBvd25lcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBPd25lZEJ5KCkge1xuICBjb25zdCBrZXkgPSBnZXRGYWJyaWNNb2RlbEtleShGYWJyaWNNb2RlbEtleXMuT1dORURCWSk7XG5cbiAgZnVuY3Rpb24gb3duZWRCeSgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG9iajogYW55LCBhdHRyaWJ1dGU/OiBhbnkpIHtcbiAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgb25DcmVhdGUob3duZWRCeU9uQ3JlYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKGdldEZhYnJpY01vZGVsS2V5KEZhYnJpY01vZGVsS2V5cy5PV05FREJZKSwgYXR0cmlidXRlKVxuICAgICAgKShvYmosIGF0dHJpYnV0ZSk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihrZXkpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IG93bmVkQnksXG4gICAgICBhcmdzOiBbXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmFicmljTW9kZWxLZXkoa2V5OiBzdHJpbmcpIHtcbiAgcmV0dXJuIE1ldGFkYXRhLmtleShGYWJyaWNNb2RlbEtleXMuRkFCUklDICsga2V5KTtcbn1cblxuZXhwb3J0IHR5cGUgQ29sbGVjdGlvblJlc29sdmVyID0gPE0gZXh0ZW5kcyBNb2RlbD4obW9kZWw6IE0pID0+IHN0cmluZztcblxuZXhwb3J0IGNvbnN0IEltcGxpY2l0UHJpdmF0ZUNvbGxlY3Rpb246IENvbGxlY3Rpb25SZXNvbHZlciA9IDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTVxuKSA9PiB7XG4gIHJldHVybiBgX18ke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9UHJpdmF0ZUNvbGxlY3Rpb25gO1xufTtcblxuZXhwb3J0IHR5cGUgU2VncmVnYXRlZERhdGFNZXRhZGF0YSA9IHtcbiAgY29sbGVjdGlvbnM6IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcjtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uQ3JlYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IFJlcG9zaXRvcnk8TSwgYW55PixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNGbGFncz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGFbXSxcbiAga2V5czogKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKGtleXMubGVuZ3RoICE9PSBkYXRhLmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBTZWdyZWdhdGVkIGRhdGEga2V5cyBhbmQgbWV0YWRhdGEgbGVuZ3RoIG1pc21hdGNoYFxuICAgICk7XG5cbiAgY29uc3QgY29sbGVjdGlvblJlc29sdmVyID0gZGF0YVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogY29sbGVjdGlvblJlc29sdmVyKG1vZGVsKTtcblxuICBjb25zdCByZWJ1aWx0ID0ga2V5cy5yZWR1Y2UoXG4gICAgKGFjYzogUmVjb3JkPGtleW9mIE0sIGFueT4sIGssIGkpID0+IHtcbiAgICAgIGNvbnN0IGMgPVxuICAgICAgICB0eXBlb2YgZGF0YVtpXS5jb2xsZWN0aW9ucyA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gZGF0YVtpXS5jb2xsZWN0aW9uc1xuICAgICAgICAgIDogZGF0YVtpXS5jb2xsZWN0aW9ucyhtb2RlbCk7XG4gICAgICBpZiAoYyAhPT0gY29sbGVjdGlvbilcbiAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICAgICAgYFNlZ3JlZ2F0ZWQgZGF0YSBjb2xsZWN0aW9uIG1pc21hdGNoOiAke2N9IHZzICR7Y29sbGVjdGlvbn1gXG4gICAgICAgICk7XG4gICAgICBhY2Nba10gPSBtb2RlbFtrXTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSxcbiAgICB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PlxuICApO1xuXG4gIGNvbnN0IHRvQ3JlYXRlID0gbmV3IHRoaXMuY2xhc3MocmVidWlsdCk7XG5cbiAgLy8gY29uc3Qgc2VncmVnYXRlZCA9IE1vZGVsLnNlZ3JlZ2F0ZShtb2RlbCk7XG5cbiAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMub3ZlcnJpZGUoeyBzZWdyZWdhdGVkOiBjb2xsZWN0aW9uIH0gYXMgYW55KS5jcmVhdGUoXG4gICAgdG9DcmVhdGUsXG4gICAgY29udGV4dFxuICApO1xuICBPYmplY3QuYXNzaWduKG1vZGVsLCBjcmVhdGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25SZWFkPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IFJlcG9zaXRvcnk8TSwgYW55PixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNGbGFncz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGFbXSxcbiAga2V5czogKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKGtleXMubGVuZ3RoICE9PSBkYXRhLmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBTZWdyZWdhdGVkIGRhdGEga2V5cyBhbmQgbWV0YWRhdGEgbGVuZ3RoIG1pc21hdGNoYFxuICAgICk7XG5cbiAgY29uc3QgY29sbGVjdGlvblJlc29sdmVyID0gZGF0YVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogY29sbGVjdGlvblJlc29sdmVyKG1vZGVsKTtcblxuICBjb25zdCByZWJ1aWx0ID0ga2V5cy5yZWR1Y2UoXG4gICAgKGFjYzogUmVjb3JkPGtleW9mIE0sIGFueT4sIGssIGkpID0+IHtcbiAgICAgIGNvbnN0IGMgPVxuICAgICAgICB0eXBlb2YgZGF0YVtpXS5jb2xsZWN0aW9ucyA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gZGF0YVtpXS5jb2xsZWN0aW9uc1xuICAgICAgICAgIDogZGF0YVtpXS5jb2xsZWN0aW9ucyhtb2RlbCk7XG4gICAgICBpZiAoYyAhPT0gY29sbGVjdGlvbilcbiAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICAgICAgYFNlZ3JlZ2F0ZWQgZGF0YSBjb2xsZWN0aW9uIG1pc21hdGNoOiAke2N9IHZzICR7Y29sbGVjdGlvbn1gXG4gICAgICAgICk7XG4gICAgICBhY2Nba10gPSBtb2RlbFtrXTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSxcbiAgICB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PlxuICApO1xuXG4gIGNvbnN0IHRvQ3JlYXRlID0gbmV3IHRoaXMuY2xhc3MocmVidWlsdCk7XG5cbiAgLy8gY29uc3Qgc2VncmVnYXRlZCA9IE1vZGVsLnNlZ3JlZ2F0ZShtb2RlbCk7XG5cbiAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMub3ZlcnJpZGUoeyBzZWdyZWdhdGVkOiBjb2xsZWN0aW9uIH0gYXMgYW55KS5jcmVhdGUoXG4gICAgdG9DcmVhdGUsXG4gICAgY29udGV4dFxuICApO1xuICBPYmplY3QuYXNzaWduKG1vZGVsLCBjcmVhdGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25VcGRhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0PEZhYnJpY0ZsYWdzPixcbiAgZGF0YTogU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXk6IGtleW9mIE1bXSxcbiAgbW9kZWw6IE0sXG4gIG9sZE1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHt9XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uRGVsZXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIFYgZXh0ZW5kcyBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNGbGFncz4sXG4gIGRhdGE6IFZbXSxcbiAga2V5OiBrZXlvZiBNW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHt9XG5cbmZ1bmN0aW9uIHNlZ3JlZ2F0ZWQoXG4gIGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcixcbiAgdHlwZTogRmFicmljTW9kZWxLZXlzLlBSSVZBVEUgfCBGYWJyaWNNb2RlbEtleXMuU0hBUkVEXG4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGlubmVyU2VncmVnYXRlZCh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpIHtcbiAgICBmdW5jdGlvbiBzZWdyZWdhdGVkRGVjKHRhcmdldDogb2JqZWN0LCBwcm9wZXJ0eUtleT86IGFueSkge1xuICAgICAgaWYgKCFwcm9wZXJ0eUtleSkge1xuICAgICAgICBjb25zdCBwcm9wcyA9IE1ldGFkYXRhLnByb3BlcnRpZXModGFyZ2V0IGFzIENvbnN0cnVjdG9yKSB8fCBbXTtcbiAgICAgICAgZm9yIChjb25zdCBwcm9wIG9mIHByb3BzKSBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIHR5cGUpKHRhcmdldCwgcHJvcCk7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGtleSA9IE1ldGFkYXRhLmtleSh0eXBlLCBwcm9wZXJ0eUtleSk7XG4gICAgICBjb25zdCBjb25zdHI6IENvbnN0cnVjdG9yID0gdGFyZ2V0LmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yO1xuXG4gICAgICBjb25zdCBtZXRhID0gTWV0YWRhdGEuZ2V0KGNvbnN0ciBhcyBDb25zdHJ1Y3Rvciwga2V5KSB8fCB7fTtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25zID0gbmV3IFNldChtZXRhLmNvbGxlY3Rpb25zIHx8IFtdKTtcbiAgICAgIGNvbGxlY3Rpb25zLmFkZChjb2xsZWN0aW9uKTtcbiAgICAgIG1ldGEuY29sbGVjdGlvbnMgPSBbLi4uY29sbGVjdGlvbnNdO1xuICAgICAgTWV0YWRhdGEuc2V0KGNvbnN0ciBhcyBDb25zdHJ1Y3Rvciwga2V5LCBtZXRhKTtcbiAgICB9XG4gICAgY29uc3QgZGVjczogYW55W10gPSBbXTtcbiAgICBpZiAoIXByb3BlcnR5S2V5KSB7XG4gICAgICAvLyBkZWNvcmF0ZWQgYXQgdGhlIGNsYXNzIGxldmVsXG4gICAgICBNZXRhZGF0YS5wcm9wZXJ0aWVzKHRhcmdldCBhcyBDb25zdHJ1Y3Rvcik/LmZvckVhY2goKHApID0+XG4gICAgICAgIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgdHlwZSkodGFyZ2V0LCBwKVxuICAgICAgKTtcbiAgICAgIHJldHVybiBtZXRhZGF0YSh0eXBlLCB0cnVlKSh0YXJnZXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWNzLnB1c2goXG4gICAgICAgIHRyYW5zaWVudCgpLFxuICAgICAgICBzZWdyZWdhdGVkRGVjLFxuICAgICAgICBvbkNyZWF0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uQ3JlYXRlLFxuICAgICAgICAgIHsgY29sbGVjdGlvbnM6IGNvbGxlY3Rpb24gfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwcmlvcml0eTogOTUsXG4gICAgICAgICAgICBncm91cDpcbiAgICAgICAgICAgICAgdHlwZW9mIGNvbGxlY3Rpb24gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICA6IGNvbGxlY3Rpb24udG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgICksXG4gICAgICAgIG9uUmVhZChcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uUmVhZCBhcyBhbnksXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOlxuICAgICAgICAgICAgICB0eXBlb2YgY29sbGVjdGlvbiA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gY29sbGVjdGlvblxuICAgICAgICAgICAgICAgIDogY29sbGVjdGlvbi50b1N0cmluZygpLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgICAgb25VcGRhdGUoXG4gICAgICAgICAgc2VncmVnYXRlZERhdGFPblVwZGF0ZSBhcyBhbnksXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOlxuICAgICAgICAgICAgICB0eXBlb2YgY29sbGVjdGlvbiA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gY29sbGVjdGlvblxuICAgICAgICAgICAgICAgIDogY29sbGVjdGlvbi50b1N0cmluZygpLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgICAgb25EZWxldGUoXG4gICAgICAgICAgc2VncmVnYXRlZERhdGFPbkRlbGV0ZSBhcyBhbnksXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOlxuICAgICAgICAgICAgICB0eXBlb2YgY29sbGVjdGlvbiA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gY29sbGVjdGlvblxuICAgICAgICAgICAgICAgIDogY29sbGVjdGlvbi50b1N0cmluZygpLFxuICAgICAgICAgIH1cbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGFwcGx5KC4uLmRlY3MpKHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICAgIC8vIHJldHVybiBhcHBseSgpKHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJpdmF0ZURhdGEoXG4gIGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlciA9IEltcGxpY2l0UHJpdmF0ZUNvbGxlY3Rpb25cbikge1xuICBmdW5jdGlvbiBwcml2YXRlRGF0YShjb2xsZWN0aW9uOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIpIHtcbiAgICByZXR1cm4gc2VncmVnYXRlZChjb2xsZWN0aW9uLCBGYWJyaWNNb2RlbEtleXMuUFJJVkFURSk7XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLlBSSVZBVEUpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IHByaXZhdGVEYXRhLFxuICAgICAgYXJnczogW2NvbGxlY3Rpb25dLFxuICAgIH0pXG4gICAgLmFwcGx5KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWREYXRhKGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcikge1xuICBmdW5jdGlvbiBzaGFyZWREYXRhKGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcikge1xuICAgIHJldHVybiBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIEZhYnJpY01vZGVsS2V5cy5TSEFSRUQpO1xuICB9XG5cbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKEZhYnJpY01vZGVsS2V5cy5TSEFSRUQpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IHNoYXJlZERhdGEsXG4gICAgICBhcmdzOiBbY29sbGVjdGlvbl0sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cbi8vXG4vLyBleHBvcnQgZnVuY3Rpb24gcHJpdmF0ZURhdGEoY29sbGVjdGlvbj86IHN0cmluZykge1xuLy8gICBpZiAoIWNvbGxlY3Rpb24pIHtcbi8vICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2xsZWN0aW9uIG5hbWUgaXMgcmVxdWlyZWRcIik7XG4vLyAgIH1cbi8vXG4vLyAgIGNvbnN0IGtleTogc3RyaW5nID0gRmFicmljTW9kZWxLZXlzLlBSSVZBVEU7XG4vL1xuLy8gICByZXR1cm4gZnVuY3Rpb24gcHJpdmF0ZURhdGE8TSBleHRlbmRzIE1vZGVsPihcbi8vICAgICBtb2RlbDogTSB8IENvbnN0cnVjdG9yPE0+LFxuLy8gICAgIGF0dHJpYnV0ZT86IGFueVxuLy8gICApIHtcbi8vICAgICBjb25zdCBjb25zdHIgPVxuLy8gICAgICAgbW9kZWwgaW5zdGFuY2VvZiBNb2RlbCA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcikgOiBtb2RlbDtcbi8vXG4vLyAgICAgY29uc3QgbWV0YURhdGE6IGFueSA9IE1ldGFkYXRhLmdldChjb25zdHIpO1xuLy8gICAgIGNvbnN0IG1vZGVsZGF0YSA9IG1ldGFEYXRhPy5wcml2YXRlPy5jb2xsZWN0aW9ucyB8fCBbXTtcbi8vXG4vLyAgICAgcHJvcE1ldGFkYXRhKGtleSwge1xuLy8gICAgICAgLi4uKCFhdHRyaWJ1dGUgJiYge1xuLy8gICAgICAgICBjb2xsZWN0aW9uczogbW9kZWxkYXRhXG4vLyAgICAgICAgICAgPyBbLi4ubmV3IFNldChbLi4ubW9kZWxkYXRhLCBjb2xsZWN0aW9uXSldXG4vLyAgICAgICAgICAgOiBbY29sbGVjdGlvbl0sXG4vLyAgICAgICB9KSxcbi8vICAgICAgIGlzUHJpdmF0ZTogIWF0dHJpYnV0ZSxcbi8vICAgICB9KShhdHRyaWJ1dGUgPyBjb25zdHIgOiBtb2RlbCk7XG4vL1xuLy8gICAgIGlmIChhdHRyaWJ1dGUpIHtcbi8vICAgICAgIGNvbnN0IGF0dHJpYnV0ZURhdGEgPVxuLy8gICAgICAgICAobWV0YURhdGE/LnByaXZhdGU/LlthdHRyaWJ1dGVdIGFzIGFueSk/LmNvbGxlY3Rpb25zIHx8IFtdO1xuLy8gICAgICAgcHJvcE1ldGFkYXRhKE1ldGFkYXRhLmtleShrZXksIGF0dHJpYnV0ZSksIHtcbi8vICAgICAgICAgY29sbGVjdGlvbnM6IGF0dHJpYnV0ZURhdGFcbi8vICAgICAgICAgICA/IFsuLi5uZXcgU2V0KFsuLi5hdHRyaWJ1dGVEYXRhLCBjb2xsZWN0aW9uXSldXG4vLyAgICAgICAgICAgOiBbY29sbGVjdGlvbl0sXG4vLyAgICAgICB9KShtb2RlbCwgYXR0cmlidXRlKTtcbi8vICAgICAgIHRyYW5zaWVudCgpKG1vZGVsLCBhdHRyaWJ1dGUpO1xuLy8gICAgIH1cbi8vICAgfTtcbi8vIH1cbiIsIi8qKlxuICogRW51bSByZXByZXNlbnRpbmcgdGhlIGV2ZW50cyBlbWl0dGVkIGJ5IGFuIEVSQzIwIGNvbnRyYWN0LlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGVudW0gaXMgdXNlZCB0byBpZGVudGlmeSB0aGUgc3BlY2lmaWMgZXZlbnRzIHRoYXQgY2FuIGJlIGVtaXR0ZWQgYnkgYW4gRVJDMjAgY29udHJhY3QuXG4gKiBUaGUgZXZlbnRzIGFyZSBuYW1lZCBhY2NvcmRpbmcgdG8gdGhlIEVJUC0yMCBzdGFuZGFyZC5cbiAqL1xuZXhwb3J0IGVudW0gRVJDMjBFdmVudHMge1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgYHRyYW5zZmVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgc3VjY2Vzc2Z1bGx5LlxuICAgKlxuICAgKiBAcGFyYW0gZnJvbSAtIFRoZSBhZGRyZXNzIG9mIHRoZSBzZW5kZXIuXG4gICAqIEBwYXJhbSB0byAtIFRoZSBhZGRyZXNzIG9mIHRoZSByZWNpcGllbnQuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhbW91bnQgb2YgdG9rZW5zIHRyYW5zZmVycmVkLlxuICAgKi9cbiAgVFJBTlNGRVIgPSBcIlRyYW5zZmVyXCIsXG5cbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhbiBgYXBwcm92ZWAgZnVuY3Rpb24gaXMgY2FsbGVkIHN1Y2Nlc3NmdWxseS5cbiAgICpcbiAgICogQHBhcmFtIG93bmVyIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHRva2VuIG93bmVyLlxuICAgKiBAcGFyYW0gc3BlbmRlciAtIFRoZSBhZGRyZXNzIG9mIHRoZSBhcHByb3ZlZCBzcGVuZGVyLlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgYW1vdW50IG9mIHRva2VucyBhcHByb3ZlZCBmb3IgdGhlIHNwZW5kZXIuXG4gICAqL1xuICBBUFBST1ZBTCA9IFwiQXBwcm92YWxcIixcbn1cbiIsImltcG9ydCB7IEF1dGhvcml6YXRpb25FcnJvciwgQ29uZGl0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb250ZXh0LCBUcmFuc2FjdGlvbiB9IGZyb20gXCJmYWJyaWMtY29udHJhY3QtYXBpXCI7XG5pbXBvcnQgeyBhZGQsIHN1YiB9IGZyb20gXCIuLi8uLi9zaGFyZWQvbWF0aFwiO1xuaW1wb3J0IHtcbiAgQWxsb3dhbmNlRXJyb3IsXG4gIEJhbGFuY2VFcnJvcixcbiAgTm90SW5pdGlhbGl6ZWRFcnJvcixcbn0gZnJvbSBcIi4uLy4uL3NoYXJlZC9lcnJvcnNcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuLi9Db250cmFjdEFkYXB0ZXJcIjtcbmltcG9ydCB7IEFsbG93YW5jZSwgRVJDMjBUb2tlbiwgRVJDMjBXYWxsZXQgfSBmcm9tIFwiLi9tb2RlbHNcIjtcbmltcG9ydCB7IE93bmVyIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XCI7XG5pbXBvcnQgdHlwZSB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7XG4gIEJhc2VFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbiAgVmFsaWRhdGlvbkVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEZhYnJpY0NydWRDb250cmFjdCB9IGZyb20gXCIuLi9jcnVkL2NydWQtY29udHJhY3RcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIH0gZnJvbSBcIi4uL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyXCI7XG5pbXBvcnQgeyBFUkMyMEV2ZW50cyB9IGZyb20gXCIuLi8uLi9zaGFyZWQvZXJjMjAvZXJjMjAtY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVSQzIwIHRva2VuIGNvbnRyYWN0IGJhc2UgZm9yIEh5cGVybGVkZ2VyIEZhYnJpY1xuICogQHN1bW1hcnkgSW1wbGVtZW50cyBFUkMyMC1saWtlIHRva2VuIGxvZ2ljIHVzaW5nIHJlcG9zaXRvcmllcyBhbmQgYWRhcHRlcnMsIHByb3ZpZGluZyBzdGFuZGFyZCB0b2tlbiBvcGVyYXRpb25zIHN1Y2ggYXMgYmFsYW5jZSBxdWVyaWVzLCB0cmFuc2ZlcnMsIGFwcHJvdmFscywgbWludGluZyBhbmQgYnVybmluZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIGNvbnRyYWN0IG5hbWUgdXNlZCB0byBzY29wZSB0b2tlbiBpZGVudGl0eVxuICogQG5vdGUgaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBTL2VpcC0yMFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBGYWJyaWNFUkMyMENvbnRyYWN0XG4gKiBAZXhhbXBsZVxuICogY2xhc3MgTXlUb2tlbkNvbnRyYWN0IGV4dGVuZHMgRmFicmljRVJDMjBDb250cmFjdCB7XG4gKiAgIGNvbnN0cnVjdG9yKCkgeyBzdXBlcignTXlUb2tlbicpOyB9XG4gKiB9XG4gKiAvLyBUaGUgY29udHJhY3QgZXhwb3NlcyBtZXRob2RzIGxpa2UgVHJhbnNmZXIsIEFwcHJvdmUsIE1pbnQsIEJ1cm4sIGV0Yy5cbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IFdhbGxldFJlcG9cbiAqICAgcGFydGljaXBhbnQgVG9rZW5SZXBvXG4gKiAgIHBhcnRpY2lwYW50IExlZGdlclxuICogICBDbGllbnQtPj5Db250cmFjdDogVHJhbnNmZXIoY3R4LCB0bywgdmFsdWUpXG4gKiAgIENvbnRyYWN0LT4+V2FsbGV0UmVwbzogcmVhZChmcm9tKVxuICogICBDb250cmFjdC0+PldhbGxldFJlcG86IHJlYWQodG8pXG4gKiAgIENvbnRyYWN0LT4+TGVkZ2VyOiBwdXRTdGF0ZSh1cGRhdGVkIGJhbGFuY2VzKVxuICogICBDb250cmFjdC0tPj5DbGllbnQ6IHN1Y2Nlc3NcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEZhYnJpY0VSQzIwQ29udHJhY3QgZXh0ZW5kcyBGYWJyaWNDcnVkQ29udHJhY3Q8RVJDMjBXYWxsZXQ+IHtcbiAgcHJpdmF0ZSB3YWxsZXRSZXBvc2l0b3J5OiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8RVJDMjBXYWxsZXQ+O1xuXG4gIHByaXZhdGUgdG9rZW5SZXBvc2l0b3J5OiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8RVJDMjBUb2tlbj47XG5cbiAgcHJpdmF0ZSBhbGxvd2FuY2VSZXBvc2l0b3J5OiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8QWxsb3dhbmNlPjtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IobmFtZTogc3RyaW5nKSB7XG4gICAgc3VwZXIobmFtZSwgRVJDMjBXYWxsZXQpO1xuXG4gICAgRmFicmljRVJDMjBDb250cmFjdC5hZGFwdGVyID1cbiAgICAgIEZhYnJpY0VSQzIwQ29udHJhY3QuYWRhcHRlciB8fCBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyKCk7XG5cbiAgICB0aGlzLndhbGxldFJlcG9zaXRvcnkgPSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkuZm9yTW9kZWwoXG4gICAgICBFUkMyMFdhbGxldCxcbiAgICAgIEZhYnJpY0VSQzIwQ29udHJhY3QuYWRhcHRlci5hbGlhc1xuICAgICk7XG5cbiAgICB0aGlzLnRva2VuUmVwb3NpdG9yeSA9IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeS5mb3JNb2RlbChcbiAgICAgIEVSQzIwVG9rZW4sXG4gICAgICBGYWJyaWNFUkMyMENvbnRyYWN0LmFkYXB0ZXIuYWxpYXNcbiAgICApO1xuXG4gICAgdGhpcy5hbGxvd2FuY2VSZXBvc2l0b3J5ID0gRmFicmljQ29udHJhY3RSZXBvc2l0b3J5LmZvck1vZGVsKFxuICAgICAgQWxsb3dhbmNlLFxuICAgICAgRmFicmljRVJDMjBDb250cmFjdC5hZGFwdGVyLmFsaWFzXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgVG9rZW5OYW1lKGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IHNlbGVjdCA9IHRoaXMudG9rZW5SZXBvc2l0b3J5LnNlbGVjdCgpO1xuICAgIGNvbnN0IHRva2VuID0gKGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCkpWzBdO1xuXG4gICAgcmV0dXJuIHRva2VuLm5hbWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBzeW1ib2wgb2YgdGhlIHRva2VuLiBFLmcuIOKAnEhJWOKAnS5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEByZXR1cm5zIHtTdHJpbmd9IFJldHVybnMgdGhlIHN5bWJvbCBvZiB0aGUgdG9rZW5cbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgU3ltYm9sKGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IHNlbGVjdCA9IHRoaXMudG9rZW5SZXBvc2l0b3J5LnNlbGVjdCgpO1xuICAgIGNvbnN0IHRva2VuID0gKGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCkpWzBdO1xuXG4gICAgcmV0dXJuIHRva2VuLnN5bWJvbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIG51bWJlciBvZiBkZWNpbWFscyB0aGUgdG9rZW4gdXNlc1xuICAgKiBlLmcuIDgsIG1lYW5zIHRvIGRpdmlkZSB0aGUgdG9rZW4gYW1vdW50IGJ5IDEwMDAwMDAwMCB0byBnZXQgaXRzIHVzZXIgcmVwcmVzZW50YXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGVjaW1hbHNcbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgRGVjaW1hbHMoY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgc2VsZWN0ID0gdGhpcy50b2tlblJlcG9zaXRvcnkuc2VsZWN0KCk7XG4gICAgY29uc3QgdG9rZW4gPSAoYXdhaXQgc2VsZWN0LmV4ZWN1dGUoY3R4KSlbMF07XG5cbiAgICByZXR1cm4gdG9rZW4uZGVjaW1hbHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSB0b3RhbCB0b2tlbiBzdXBwbHkuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIHRoZSB0b3RhbCB0b2tlbiBzdXBwbHlcbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgVG90YWxTdXBwbHkoY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgc2VsZWN0ID0gdGhpcy53YWxsZXRSZXBvc2l0b3J5LnNlbGVjdCgpO1xuICAgIGNvbnN0IHdhbGxldHMgPSBhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpO1xuXG4gICAgaWYgKHdhbGxldHMubGVuZ3RoID09IDApIHtcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKGBUaGUgdG9rZW4gJHt0aGlzLmdldE5hbWUoKX0gZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICBsZXQgdG90YWwgPSAwO1xuXG4gICAgd2FsbGV0cy5mb3JFYWNoKCh3YWxsZXQpID0+IHtcbiAgICAgIHRvdGFsICs9IHdhbGxldC5iYWxhbmNlO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRvdGFsO1xuICB9XG5cbiAgLyoqXG4gICAqIEJhbGFuY2VPZiByZXR1cm5zIHRoZSBiYWxhbmNlIG9mIHRoZSBnaXZlbiBhY2NvdW50LlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGN0eCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gb3duZXIgVGhlIG93bmVyIGZyb20gd2hpY2ggdGhlIGJhbGFuY2Ugd2lsbCBiZSByZXRyaWV2ZWRcbiAgICogQHJldHVybnMge051bWJlcn0gUmV0dXJucyB0aGUgYWNjb3VudCBiYWxhbmNlXG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIEJhbGFuY2VPZihjb250ZXh0OiBDb250ZXh0LCBvd25lcjogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCB3YWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChvd25lciwgY3R4KTtcblxuICAgIHJldHVybiB3YWxsZXQuYmFsYW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBUcmFuc2ZlciB0cmFuc2ZlcnMgdG9rZW5zIGZyb20gY2xpZW50IGFjY291bnQgdG8gcmVjaXBpZW50IGFjY291bnQuXG4gICAqIEBkZXNjcmlwdGlvbiByZWNpcGllbnQgYWNjb3VudCBtdXN0IGJlIGEgdmFsaWQgY2xpZW50SUQgYXMgcmV0dXJuZWQgYnkgdGhlIENsaWVudEFjY291bnRJRCgpIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRvIFRoZSByZWNpcGllbnRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBhbW91bnQgb2YgdG9rZW4gdG8gYmUgdHJhbnNmZXJyZWRcbiAgICpcbiAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybiB3aGV0aGVyIHRoZSB0cmFuc2ZlciB3YXMgc3VjY2Vzc2Z1bCBvciBub3RcbiAgICovXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIFRyYW5zZmVyKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgdG86IHN0cmluZyxcbiAgICB2YWx1ZTogbnVtYmVyXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5UcmFuc2Zlcik7XG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3QgZnJvbSA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgY29uc3QgdHJhbnNmZXJSZXNwID0gYXdhaXQgdGhpcy5fdHJhbnNmZXIoZnJvbSwgdG8sIHZhbHVlLCBjdHgpO1xuICAgIGlmICghdHJhbnNmZXJSZXNwKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkZhaWxlZCB0byB0cmFuc2ZlclwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2ZlciBgdmFsdWVgIGFtb3VudCBvZiB0b2tlbnMgZnJvbSBgZnJvbWAgdG8gYHRvYC5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBmcm9tIFRoZSBzZW5kZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRvIFRoZSByZWNpcGllbnRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBhbW91bnQgb2YgdG9rZW4gdG8gYmUgdHJhbnNmZXJyZWRcbiAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybiB3aGV0aGVyIHRoZSB0cmFuc2ZlciB3YXMgc3VjY2Vzc2Z1bCBvciBub3RcbiAgICovXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIFRyYW5zZmVyRnJvbShcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIGZyb206IHN0cmluZyxcbiAgICB0bzogc3RyaW5nLFxuICAgIHZhbHVlOiBudW1iZXJcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkJ1cm5Gcm9tKTtcbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICAvLyBSZXRyaWV2ZSB0aGUgYWxsb3dhbmNlIG9mIHRoZSBzcGVuZGVyXG5cbiAgICBjb25zdCBzcGVuZGVyID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBjb25zdCBhbGxvd2FuY2UgPSBhd2FpdCB0aGlzLl9nZXRBbGxvd2FuY2UoZnJvbSwgc3BlbmRlciwgY3R4KTtcbiAgICBpZiAoIWFsbG93YW5jZSB8fCBhbGxvd2FuY2UudmFsdWUgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgQWxsb3dhbmNlRXJyb3IoXG4gICAgICAgIGBzcGVuZGVyICR7c3BlbmRlcn0gaGFzIG5vIGFsbG93YW5jZSBmcm9tICR7ZnJvbX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRBbGxvd2FuY2UgPSBhbGxvd2FuY2UudmFsdWU7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdHJhbnNmZXJyZWQgdmFsdWUgaXMgbGVzcyB0aGFuIHRoZSBhbGxvd2FuY2VcbiAgICBpZiAoY3VycmVudEFsbG93YW5jZSA8IHZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKFxuICAgICAgICBcIlRoZSBzcGVuZGVyIGRvZXMgbm90IGhhdmUgZW5vdWdoIGFsbG93YW5jZSB0byBzcGVuZC5cIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBEZWNyZWFzZSB0aGUgYWxsb3dhbmNlXG4gICAgY29uc3QgdXBkYXRlZEFsbG93YW5jZSA9IHN1YihjdXJyZW50QWxsb3dhbmNlLCB2YWx1ZSk7XG4gICAgY29uc3QgbmV3QWxsb3dhbmNlID0gT2JqZWN0LmFzc2lnbih7fSwgYWxsb3dhbmNlLCB7XG4gICAgICB2YWx1ZTogdXBkYXRlZEFsbG93YW5jZSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHRoaXMuYWxsb3dhbmNlUmVwb3NpdG9yeS51cGRhdGUobmV3QWxsb3dhbmNlLCBjdHgpO1xuXG4gICAgLy9SZWFsaXplIHRoZSB0cmFuc2ZlclxuICAgIGNvbnN0IHRyYW5zZmVyUmVzcCA9IGF3YWl0IHRoaXMuX3RyYW5zZmVyKGZyb20sIHRvLCB2YWx1ZSwgY3R4KTtcbiAgICBpZiAoIXRyYW5zZmVyUmVzcCkge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJGYWlsZWQgdG8gdHJhbnNmZXJcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyBfdHJhbnNmZXIoXG4gICAgZnJvbTogc3RyaW5nLFxuICAgIHRvOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlcixcbiAgICBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICApIHtcbiAgICBjb25zdCBsb2cgPSBjdHgubG9nZ2VyO1xuXG4gICAgaWYgKGZyb20gPT09IHRvKSB7XG4gICAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgICBcImNhbm5vdCB0cmFuc2ZlciB0byBhbmQgZnJvbSBzYW1lIGNsaWVudCBhY2NvdW50XCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlIDwgMCkge1xuICAgICAgLy8gdHJhbnNmZXIgb2YgMCBpcyBhbGxvd2VkIGluIEVSQzIwLCBzbyBqdXN0IHZhbGlkYXRlIGFnYWluc3QgbmVnYXRpdmUgYW1vdW50c1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihcInRyYW5zZmVyIGFtb3VudCBjYW5ub3QgYmUgbmVnYXRpdmVcIik7XG4gICAgfVxuXG4gICAgLy8gUmV0cmlldmUgdGhlIGN1cnJlbnQgYmFsYW5jZSBvZiB0aGUgc2VuZGVyXG5cbiAgICBjb25zdCBmcm9tV2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQoZnJvbSwgY3R4KTtcblxuICAgIGNvbnN0IGZyb21CYWxhbmNlID0gZnJvbVdhbGxldC5iYWxhbmNlO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHNlbmRlciBoYXMgZW5vdWdoIHRva2VucyB0byBzcGVuZC5cbiAgICBpZiAoZnJvbUJhbGFuY2UgPCB2YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihgY2xpZW50IGFjY291bnQgJHtmcm9tfSBoYXMgaW5zdWZmaWNpZW50IGZ1bmRzLmApO1xuICAgIH1cblxuICAgIC8vIFJldHJpZXZlIHRoZSBjdXJyZW50IGJhbGFuY2Ugb2YgdGhlIHJlY2VwaWVudFxuXG4gICAgbGV0IHRvV2FsbGV0OiBFUkMyMFdhbGxldDtcbiAgICBsZXQgbmV3VG9XYWxsZXQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgdG9XYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZCh0bywgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIEJhc2VFcnJvcikge1xuICAgICAgICBpZiAoZS5jb2RlID09PSA0MDQpIHtcbiAgICAgICAgICAvLyBDcmVhdGUgYSBuZXcgd2FsbGV0IGZvciB0aGUgbWludGVyXG4gICAgICAgICAgdG9XYWxsZXQgPSBuZXcgRVJDMjBXYWxsZXQoe1xuICAgICAgICAgICAgaWQ6IHRvLFxuICAgICAgICAgICAgYmFsYW5jZTogMCxcbiAgICAgICAgICAgIHRva2VuOiBhd2FpdCB0aGlzLlRva2VuTmFtZShjdHggYXMgYW55KSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBuZXdUb1dhbGxldCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSBhcyBzdHJpbmcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRvQmFsYW5jZSA9IHRvV2FsbGV0LmJhbGFuY2U7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGJhbGFuY2VcbiAgICBjb25zdCBmcm9tVXBkYXRlZEJhbGFuY2UgPSBzdWIoZnJvbUJhbGFuY2UsIHZhbHVlKTtcbiAgICBjb25zdCB0b1VwZGF0ZWRCYWxhbmNlID0gYWRkKHRvQmFsYW5jZSwgdmFsdWUpO1xuXG4gICAgY29uc3QgdXBkYXRlZEZyb21XYWxsZXQgPSBPYmplY3QuYXNzaWduKHt9LCBmcm9tV2FsbGV0LCB7XG4gICAgICBiYWxhbmNlOiBmcm9tVXBkYXRlZEJhbGFuY2UsXG4gICAgfSk7XG5cbiAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkudXBkYXRlKHVwZGF0ZWRGcm9tV2FsbGV0LCBjdHgpO1xuXG4gICAgY29uc3QgdXBkYXRlZFRvV2FsbGV0ID0gT2JqZWN0LmFzc2lnbih7fSwgdG9XYWxsZXQsIHtcbiAgICAgIGJhbGFuY2U6IHRvVXBkYXRlZEJhbGFuY2UsXG4gICAgfSk7XG5cbiAgICBpZiAobmV3VG9XYWxsZXQpIHtcbiAgICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5jcmVhdGUodXBkYXRlZFRvV2FsbGV0LCBjdHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkudXBkYXRlKHVwZGF0ZWRUb1dhbGxldCwgY3R4KTtcbiAgICB9XG5cbiAgICAvLyBFbWl0IHRoZSBUcmFuc2ZlciBldmVudFxuICAgIGNvbnN0IHRyYW5zZmVyRXZlbnQgPSB7IGZyb20sIHRvLCB2YWx1ZTogdmFsdWUgfTtcblxuICAgIHRoaXMucmVwb1xuICAgICAgLnJlZnJlc2goXG4gICAgICAgIEVSQzIwVG9rZW4gYXMgYW55LFxuICAgICAgICBFUkMyMEV2ZW50cy5UUkFOU0ZFUixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdHJhbnNmZXJFdmVudCxcbiAgICAgICAgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICAgICApXG4gICAgICAuY2F0Y2goKGUpID0+IGxvZy5lcnJvcihgRmFpbGVkIHRvIG5vdGlmeSB0cmFuc2ZlcjogJHtlfWApKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyBgc3BlbmRlcmAgdG8gc3BlbmQgYHZhbHVlYCBhbW91bnQgb2YgdG9rZW5zIGZyb20gdGhlIG93bmVyLiBOZXcgQXBwcm92ZSBjYWxscyBvdmVycmlkZSB0aGUgcHJldmlvdXMgYWxsb3dhbmNlLlxuICAgKiBAbm90ZSBodHRwczovL2VpcHMuZXRoZXJldW0ub3JnL0VJUFMvZWlwLTIwXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY3R4IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzcGVuZGVyIFRoZSBzcGVuZGVyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYW1vdW50IG9mIHRva2VucyB0byBiZSBhcHByb3ZlZCBmb3IgdHJhbnNmZXJcbiAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybiB3aGV0aGVyIHRoZSBhcHByb3ZhbCB3YXMgc3VjY2Vzc2Z1bCBvciBub3RcbiAgICovXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIEFwcHJvdmUoXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICBzcGVuZGVyOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlclxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IGN0eCwgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkFwcHJvdmUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgb3duZXIgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGxldCBhbGxvd2FuY2UgPSBhd2FpdCB0aGlzLl9nZXRBbGxvd2FuY2Uob3duZXIsIHNwZW5kZXIsIGN0eCk7XG5cbiAgICBjb25zdCBvd25lcldhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKG93bmVyLCAuLi5jdHhBcmdzKTtcblxuICAgIGlmIChvd25lcldhbGxldC5iYWxhbmNlIDwgdmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoYGNsaWVudCBhY2NvdW50ICR7b3duZXJ9IGhhcyBpbnN1ZmZpY2llbnQgZnVuZHMuYCk7XG4gICAgfVxuXG4gICAgaWYgKGFsbG93YW5jZSkge1xuICAgICAgLy8gT3ZlcndyaXRlIHRoZSBhbGxvd2FuY2VcbiAgICAgIGFsbG93YW5jZS52YWx1ZSA9IHZhbHVlO1xuICAgICAgYXdhaXQgdGhpcy5hbGxvd2FuY2VSZXBvc2l0b3J5LnVwZGF0ZShhbGxvd2FuY2UsIC4uLmN0eEFyZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGxvd2FuY2UgPSBuZXcgQWxsb3dhbmNlKHtcbiAgICAgICAgb3duZXI6IG93bmVyLFxuICAgICAgICBzcGVuZGVyOiBzcGVuZGVyLFxuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdGhpcy5hbGxvd2FuY2VSZXBvc2l0b3J5LmNyZWF0ZShhbGxvd2FuY2UsIC4uLmN0eEFyZ3MpO1xuICAgIH1cblxuICAgIC8vIEVtaXQgdGhlIEFwcHJvdmFsIGV2ZW50XG4gICAgY29uc3QgYXBwcm92YWxFdmVudCA9IHsgb3duZXIsIHNwZW5kZXIsIHZhbHVlOiB2YWx1ZSB9O1xuICAgIHRoaXMucmVwby5yZWZyZXNoKFxuICAgICAgRVJDMjBUb2tlbiBhcyBhbnksXG4gICAgICBFUkMyMEV2ZW50cy5BUFBST1ZBTCxcbiAgICAgIFwiXCIsXG4gICAgICBhcHByb3ZhbEV2ZW50LFxuICAgICAgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICAgKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFtb3VudCBvZiB0b2tlbnMgd2hpY2ggYCBgIGlzIGFsbG93ZWQgdG8gd2l0aGRyYXcgZnJvbSBgb3duZXJgLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGN0eCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gb3duZXIgVGhlIG93bmVyIG9mIHRva2Vuc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gc3BlbmRlciBUaGUgc3BlbmRlciB3aG8gYXJlIGFibGUgdG8gdHJhbnNmZXIgdGhlIHRva2Vuc1xuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm4gdGhlIGFtb3VudCBvZiByZW1haW5pbmcgdG9rZW5zIGFsbG93ZWQgdG8gc3BlbnRcbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgQWxsb3dhbmNlKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgb3duZXI6IHN0cmluZyxcbiAgICBzcGVuZGVyOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkFsbG93YW5jZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBhbGxvd2FuY2UgPSBhd2FpdCB0aGlzLl9nZXRBbGxvd2FuY2Uob3duZXIsIHNwZW5kZXIsIGN0eCk7XG5cbiAgICBpZiAoIWFsbG93YW5jZSkge1xuICAgICAgdGhyb3cgbmV3IEFsbG93YW5jZUVycm9yKFxuICAgICAgICBgc3BlbmRlciAke3NwZW5kZXJ9IGhhcyBubyBhbGxvd2FuY2UgZnJvbSAke293bmVyfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBhbGxvd2FuY2UudmFsdWU7XG4gIH1cblxuICBhc3luYyBfZ2V0QWxsb3dhbmNlKFxuICAgIG93bmVyOiBzdHJpbmcsXG4gICAgc3BlbmRlcjogc3RyaW5nLFxuICAgIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0XG4gICk6IFByb21pc2U8QWxsb3dhbmNlPiB7XG4gICAgY29uc3QgYWxsb3dhbmNlQ29uZGl0aW9uID0gQ29uZGl0aW9uLmFuZChcbiAgICAgIENvbmRpdGlvbi5hdHRyaWJ1dGU8QWxsb3dhbmNlPihcIm93bmVyXCIpLmVxKG93bmVyKSxcbiAgICAgIENvbmRpdGlvbi5hdHRyaWJ1dGU8QWxsb3dhbmNlPihcInNwZW5kZXJcIikuZXEoc3BlbmRlcilcbiAgICApO1xuXG4gICAgY29uc3QgYWxsb3dhbmNlID0gYXdhaXQgdGhpcy5hbGxvd2FuY2VSZXBvc2l0b3J5XG4gICAgICAuc2VsZWN0KClcbiAgICAgIC53aGVyZShhbGxvd2FuY2VDb25kaXRpb24pXG4gICAgICAuZXhlY3V0ZShjdHgpO1xuICAgIHJldHVybiBhbGxvd2FuY2U/LlswXTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PSBFeHRlbmRlZCBGdW5jdGlvbnMgPT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogU2V0IG9wdGlvbmFsIGluZm9tYXRpb24gZm9yIGEgdG9rZW4uXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY3R4IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0b2tlblxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3ltYm9sIFRoZSBzeW1ib2wgb2YgdGhlIHRva2VuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkZWNpbWFscyBUaGUgZGVjaW1hbHMgb2YgdGhlIHRva2VuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0b3RhbFN1cHBseSBUaGUgdG90YWxTdXBwbHkgb2YgdGhlIHRva2VuXG4gICAqL1xuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBJbml0aWFsaXplKGNvbnRleHQ6IENvbnRleHQsIHRva2VuOiBFUkMyMFRva2VuKSB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Jbml0aWFsaXplKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBub3QgYWxyZWFkeSBzZXQsIGNsaWVudCBpcyBub3QgYXV0aG9yaXplZCB0byBjaGFuZ2UgdGhlbSBvbmNlIGludGl0aWFsaXplZFxuICAgIGNvbnN0IHRva2VucyA9IGF3YWl0IHRoaXMudG9rZW5SZXBvc2l0b3J5LnNlbGVjdCgpLmV4ZWN1dGUoY3R4KTtcbiAgICBpZiAodG9rZW5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBBdXRob3JpemF0aW9uRXJyb3IoXG4gICAgICAgIFwiY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQsIGNsaWVudCBpcyBub3QgYXV0aG9yaXplZCB0byBjaGFuZ2UgdGhlbVwiXG4gICAgICApO1xuICAgIH1cblxuICAgIHRva2VuLm93bmVyID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5jcmVhdGUodG9rZW4sIGN0eCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIENoZWNrcyB0aGF0IGNvbnRyYWN0IG9wdGlvbnMgaGF2ZSBiZWVuIGFscmVhZHkgaW5pdGlhbGl6ZWRcbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBDaGVja0luaXRpYWxpemVkKGNvbnRleHQ6IENvbnRleHQpIHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQpO1xuICAgIGNvbnN0IHRva2VucyA9IGF3YWl0IHRoaXMudG9rZW5SZXBvc2l0b3J5LnNlbGVjdCgpLmV4ZWN1dGUoY3R4KTtcbiAgICBpZiAodG9rZW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgTm90SW5pdGlhbGl6ZWRFcnJvcihcbiAgICAgICAgXCJjb250cmFjdCBvcHRpb25zIG5lZWQgdG8gYmUgc2V0IGJlZm9yZSBjYWxsaW5nIGFueSBmdW5jdGlvbiwgY2FsbCBJbml0aWFsaXplKCkgdG8gaW5pdGlhbGl6ZSBjb250cmFjdFwiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNaW50IGNyZWF0ZXMgbmV3IHRva2VucyBhbmQgYWRkcyB0aGVtIHRvIG1pbnRlcidzIGFjY291bnQgYmFsYW5jZVxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBhbW91bnQgb2YgdG9rZW5zIHRvIGJlIG1pbnRlZFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgYmFsYW5jZVxuICAgKi9cbiAgQE93bmVyKClcbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgTWludChjb250ZXh0OiBDb250ZXh0LCBhbW91bnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuTWludCk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICAvLyBHZXQgSUQgb2Ygc3VibWl0dGluZyBjbGllbnQgaWRlbnRpdHlcbiAgICBjb25zdCBtaW50ZXIgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGlmIChhbW91bnQgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcIm1pbnQgYW1vdW50IG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyXCIpO1xuICAgIH1cblxuICAgIGxldCBtaW50ZXJXYWxsZXQ6IEVSQzIwV2FsbGV0O1xuICAgIHRyeSB7XG4gICAgICBtaW50ZXJXYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChtaW50ZXIsIGN0eCk7XG5cbiAgICAgIGNvbnN0IGN1cnJlbnRCYWxhbmNlID0gbWludGVyV2FsbGV0LmJhbGFuY2U7XG5cbiAgICAgIGNvbnN0IHVwZGF0ZWRCYWxhbmNlID0gYWRkKGN1cnJlbnRCYWxhbmNlLCBhbW91bnQpO1xuXG4gICAgICBjb25zdCB1cGRhdGVkbWludGVyID0gT2JqZWN0LmFzc2lnbih7fSwgbWludGVyV2FsbGV0LCB7XG4gICAgICAgIGJhbGFuY2U6IHVwZGF0ZWRCYWxhbmNlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS51cGRhdGUodXBkYXRlZG1pbnRlciwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIEJhc2VFcnJvcikge1xuICAgICAgICBpZiAoZS5jb2RlID09PSA0MDQpIHtcbiAgICAgICAgICAvLyBDcmVhdGUgYSBuZXcgd2FsbGV0IGZvciB0aGUgbWludGVyXG4gICAgICAgICAgY29uc3QgbmV3V2FsbGV0ID0gbmV3IEVSQzIwV2FsbGV0KHtcbiAgICAgICAgICAgIGlkOiBtaW50ZXIsXG4gICAgICAgICAgICBiYWxhbmNlOiBhbW91bnQsXG4gICAgICAgICAgICB0b2tlbjogYXdhaXQgdGhpcy5Ub2tlbk5hbWUoY29udGV4dCksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LmNyZWF0ZShuZXdXYWxsZXQsIGN0eCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSBhcyBzdHJpbmcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEVtaXQgdGhlIFRyYW5zZmVyIGV2ZW50XG4gICAgY29uc3QgdHJhbnNmZXJFdmVudCA9IHsgZnJvbTogXCIweDBcIiwgdG86IG1pbnRlciwgdmFsdWU6IGFtb3VudCB9O1xuICAgIGNvbnN0IGV2ZW50SGFuZGxlciA9XG4gICAgICB0aGlzLnJlcG8uT2JzZXJ2ZXJIYW5kbGVyKCkgYXMgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXI7XG4gICAgZXZlbnRIYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAgICAgIEVSQzIwVG9rZW4sXG4gICAgICBFUkMyMEV2ZW50cy5UUkFOU0ZFUixcbiAgICAgIFwiXCIsXG4gICAgICB0cmFuc2ZlckV2ZW50LFxuICAgICAgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdXJuIHJlZGVlbSB0b2tlbnMgZnJvbSBtaW50ZXIncyBhY2NvdW50IGJhbGFuY2VcbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgYW1vdW50IG9mIHRva2VucyB0byBiZSBidXJuZWRcbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIGJhbGFuY2VcbiAgICovXG4gIEBPd25lcigpXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIEJ1cm4oY29udGV4dDogQ29udGV4dCwgYW1vdW50OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQnVybik7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBtaW50ZXIgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGNvbnN0IG1pbnRlcldhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKG1pbnRlciwgY3R4KTtcblxuICAgIGNvbnN0IGN1cnJlbnRCYWxhbmNlID0gbWludGVyV2FsbGV0LmJhbGFuY2U7XG5cbiAgICBpZiAoY3VycmVudEJhbGFuY2UgPCBhbW91bnQpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoYE1pbnRlciBoYXMgaW5zdWZmaWNpZW50IGZ1bmRzLmApO1xuICAgIH1cblxuICAgIGNvbnN0IHVwZGF0ZWRCYWxhbmNlID0gc3ViKGN1cnJlbnRCYWxhbmNlLCBhbW91bnQpO1xuXG4gICAgY29uc3QgdXBkYXRlZG1pbnRlciA9IE9iamVjdC5hc3NpZ24oe30sIG1pbnRlcldhbGxldCwge1xuICAgICAgYmFsYW5jZTogdXBkYXRlZEJhbGFuY2UsXG4gICAgfSk7XG5cbiAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkudXBkYXRlKHVwZGF0ZWRtaW50ZXIsIGN0eCk7XG5cbiAgICBsb2cuaW5mbyhgJHthbW91bnR9IHRva2VucyB3ZXJlIGJ1cm5lZGApO1xuXG4gICAgLy8gRW1pdCB0aGUgVHJhbnNmZXIgZXZlbnRcbiAgICBjb25zdCB0cmFuc2ZlckV2ZW50ID0geyBmcm9tOiBtaW50ZXIsIHRvOiBcIjB4MFwiLCB2YWx1ZTogYW1vdW50IH07XG4gICAgY29uc3QgZXZlbnRIYW5kbGVyID1cbiAgICAgIHRoaXMucmVwby5PYnNlcnZlckhhbmRsZXIoKSBhcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlcjtcbiAgICBldmVudEhhbmRsZXIudXBkYXRlT2JzZXJ2ZXJzKFxuICAgICAgRVJDMjBUb2tlbixcbiAgICAgIEVSQzIwRXZlbnRzLlRSQU5TRkVSLFxuICAgICAgXCJcIixcbiAgICAgIHRyYW5zZmVyRXZlbnQsXG4gICAgICBjdHggYXMgdW5rbm93biBhcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1cm5Gcm9tIHJlZGVlbSB0b2tlbnMgZnJvbSBhY2NvdW50IGFsbG93ZW5jZSBhbmQgYmFsYW5jZVxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGFjY291bnQgYWNjb3VudCBmcm9tIHdoZXJlIHRva2VucyB3aWxsIGJlIGJ1cm5lZFxuICAgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IGFtb3VudCBvZiB0b2tlbnMgdG8gYmUgYnVybmVkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBiYWxhbmNlXG4gICAqL1xuICBAT3duZXIoKVxuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBCdXJuRnJvbShcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIGFjY291bnQ6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlclxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQnVybkZyb20pO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3QgYWNjb3VudFdhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKGFjY291bnQsIGN0eCk7XG5cbiAgICBjb25zdCBjdXJyZW50QmFsYW5jZSA9IGFjY291bnRXYWxsZXQuYmFsYW5jZTtcblxuICAgIGlmIChjdXJyZW50QmFsYW5jZSA8IGFtb3VudCkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihgJHthY2NvdW50fSBoYXMgaW5zdWZmaWNpZW50IGZ1bmRzLmApO1xuICAgIH1cblxuICAgIGNvbnN0IHVwZGF0ZWRCYWxhbmNlID0gc3ViKGN1cnJlbnRCYWxhbmNlLCBhbW91bnQpO1xuXG4gICAgY29uc3QgdXBkYXRlZGFjY291bnQgPSBPYmplY3QuYXNzaWduKHt9LCBhY2NvdW50V2FsbGV0LCB7XG4gICAgICBiYWxhbmNlOiB1cGRhdGVkQmFsYW5jZSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS51cGRhdGUodXBkYXRlZGFjY291bnQsIGN0eCk7XG5cbiAgICBsb2cuaW5mbyhgJHthbW91bnR9IHRva2VucyB3ZXJlIGJ1cm5lZCBmcm9tICR7YWNjb3VudH1gKTtcblxuICAgIC8vIEVtaXQgdGhlIFRyYW5zZmVyIGV2ZW50XG4gICAgY29uc3QgdHJhbnNmZXJFdmVudCA9IHsgZnJvbTogYWNjb3VudCwgdG86IFwiMHgwXCIsIHZhbHVlOiBhbW91bnQgfTtcbiAgICBjb25zdCBldmVudEhhbmRsZXIgPVxuICAgICAgdGhpcy5yZXBvLk9ic2VydmVySGFuZGxlcigpIGFzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyO1xuICAgIGV2ZW50SGFuZGxlci51cGRhdGVPYnNlcnZlcnMoXG4gICAgICBFUkMyMFRva2VuLFxuICAgICAgRVJDMjBFdmVudHMuVFJBTlNGRVIsXG4gICAgICBcIlwiLFxuICAgICAgdHJhbnNmZXJFdmVudCxcbiAgICAgIGN0eCBhcyB1bmtub3duIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ2xpZW50QWNjb3VudEJhbGFuY2UgcmV0dXJucyB0aGUgYmFsYW5jZSBvZiB0aGUgcmVxdWVzdGluZyBjbGllbnQncyBhY2NvdW50LlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHJldHVybnMge051bWJlcn0gUmV0dXJucyB0aGUgYWNjb3VudCBiYWxhbmNlXG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIENsaWVudEFjY291bnRCYWxhbmNlKGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIC8vIEdldCBJRCBvZiBzdWJtaXR0aW5nIGNsaWVudCBpZGVudGl0eVxuICAgIGNvbnN0IGNsaWVudEFjY291bnRJRCA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgY29uc3QgY2xpZW50V2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQoY2xpZW50QWNjb3VudElELCBjdHgpO1xuXG4gICAgaWYgKCFjbGllbnRXYWxsZXQpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoYFRoZSBhY2NvdW50ICR7Y2xpZW50QWNjb3VudElEfSBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIHJldHVybiBjbGllbnRXYWxsZXQuYmFsYW5jZTtcbiAgfVxuXG4gIC8vIENsaWVudEFjY291bnRJRCByZXR1cm5zIHRoZSBpZCBvZiB0aGUgcmVxdWVzdGluZyBjbGllbnQncyBhY2NvdW50LlxuICAvLyBJbiB0aGlzIGltcGxlbWVudGF0aW9uLCB0aGUgY2xpZW50IGFjY291bnQgSUQgaXMgdGhlIGNsaWVudElkIGl0c2VsZi5cbiAgLy8gVXNlcnMgY2FuIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIGdldCB0aGVpciBvd24gYWNjb3VudCBpZCwgd2hpY2ggdGhleSBjYW4gdGhlbiBnaXZlIHRvIG90aGVycyBhcyB0aGUgcGF5bWVudCBhZGRyZXNzXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgQ2xpZW50QWNjb3VudElEKGNvbnRleHQ6IENvbnRleHQpIHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkNsaWVudEFjY291bnRJRCk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICAvLyBHZXQgSUQgb2Ygc3VibWl0dGluZyBjbGllbnQgaWRlbnRpdHlcbiAgICBjb25zdCBjbGllbnRBY2NvdW50SUQgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcbiAgICByZXR1cm4gY2xpZW50QWNjb3VudElEO1xuICB9XG59XG4iLCJpbXBvcnQgeyBGYWJyaWNFUkMyMENvbnRyYWN0IH0gZnJvbSBcIi4vZXJjMjBjb250cmFjdFwiO1xuXG5leHBvcnQgKiBmcm9tIFwiLi4vRmFicmljQ29udHJhY3RTdGF0ZW1lbnRcIjtcblxuZXhwb3J0IGNvbnN0IGNvbnRyYWN0czogYW55W10gPSBbRmFicmljRVJDMjBDb250cmFjdF07XG4iLCJpbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX05BTUUgPSBcIiMjUEFDS0FHRSMjXCI7XG5cbk1ldGFkYXRhLnJlZ2lzdGVyTGlicmFyeShQQUNLQUdFX05BTUUsIFZFUlNJT04pO1xuIl0sIm5hbWVzIjpbIkZhYnJpY0NvbnRyYWN0Q29udGV4dCIsIkNvbnRleHQiLCJjb25zdHJ1Y3RvciIsInN1cGVyIiwic3R1YiIsInRoaXMiLCJnZXQiLCJ0aW1lc3RhbXAiLCJnZXREYXRlVGltZXN0YW1wIiwiaWRlbnRpdHkiLCJ0b1N0cmluZyIsImdlbmVyYXRlRmFicmljRXZlbnROYW1lIiwidGFibGUiLCJldmVudCIsIm93bmVyIiwicGFyYW1zIiwicHVzaCIsImpvaW4iLCJwYXJzZUV2ZW50TmFtZSIsIm5hbWUiLCJwYXJ0cyIsInNwbGl0IiwibGVuZ3RoIiwidW5kZWZpbmVkIiwiRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIiLCJPYnNlcnZlckhhbmRsZXIiLCJzdXBwb3J0ZWRFdmVudHMiLCJPcGVyYXRpb25LZXlzIiwiQ1JFQVRFIiwiVVBEQVRFIiwiREVMRVRFIiwiQnVsa0NydWRPcGVyYXRpb25LZXlzIiwiQ1JFQVRFX0FMTCIsIlVQREFURV9BTEwiLCJERUxFVEVfQUxMIiwidXBkYXRlT2JzZXJ2ZXJzIiwiY2xhenoiLCJpZCIsImFyZ3MiLCJsb2ciLCJjdHgiLCJBZGFwdGVyIiwibG9nQ3R4IiwicGF5bG9hZCIsImluZGV4T2YiLCJkZWJ1ZyIsImV2ZW50TmFtZSIsInNldEV2ZW50IiwiQnVmZmVyIiwiZnJvbSIsIkpTT04iLCJzdHJpbmdpZnkiLCJGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkiLCJSZXBvc2l0b3J5IiwiYWRhcHRlciIsInRyYWNrZWRFdmVudHMiLCJGYWJyaWNTdGF0ZW1lbnQiLCJDb3VjaERCU3RhdGVtZW50IiwicmF3IiwicmF3SW5wdXQiLCJyZXN1bHRzIiwicGtBdHRyIiwiTW9kZWwiLCJwayIsImZyb21TZWxlY3RvciIsInR5cGUiLCJNZXRhZGF0YSIsImtleSIsIkRCS2V5cyIsIklEIiwic2VsZWN0U2VsZWN0b3IiLCJtYXAiLCJyIiwicHJvY2Vzc1JlY29yZCIsImJ1aWxkIiwic2VsZWN0b3JzIiwiQ291Y2hEQktleXMiLCJUQUJMRSIsInRhYmxlTmFtZSIsInF1ZXJ5Iiwic2VsZWN0b3IiLCJmaWVsZHMiLCJ3aGVyZUNvbmRpdGlvbiIsImNvbmRpdGlvbiIsInBhcnNlQ29uZGl0aW9uIiwiQ29uZGl0aW9uIiwiYW5kIiwiYXR0cmlidXRlIiwiZXEiLCJzZWxlY3RvcktleXMiLCJPYmplY3QiLCJrZXlzIiwidmFsdWVzIiwiQ291Y2hEQkdyb3VwT3BlcmF0b3IiLCJBTkQiLCJyZWR1Y2UiLCJhY2N1bSIsInZhbCIsIkVycm9yIiwiayIsIk9SIiwicyIsImVudHJpZXMiLCJyZXN1bHQiLCJmb3JFYWNoIiwiY29uc29sZSIsIndhcm4iLCJvcmRlckJ5U2VsZWN0b3IiLCJzb3J0IiwidmFsdWUiLCJyZWMiLCJDb3VjaERCT3BlcmF0b3IiLCJCSUdHRVIiLCJsaW1pdFNlbGVjdG9yIiwibGltaXQiLCJvZmZzZXRTZWxlY3RvciIsInNraXAiLCJGYWJyaWNNb2RlbEtleXMiLCJJZGVudGl0eVR5cGUiLCJGYWJyaWNGbGF2b3VyIiwiU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIiLCJKU09OU2VyaWFsaXplciIsImRlc2VyaWFsaXplIiwic3RyIiwiZGVzZXJpYWxpemF0aW9uIiwicGFyc2UiLCJzZXJpYWxpemUiLCJtb2RlbCIsInJlcXVpcmUiLCJzb3J0S2V5c1JlY3Vyc2l2ZSIsInByZVNlcmlhbGl6ZSIsInRvU2VyaWFsaXplIiwiYXNzaWduIiwiYXN5bmMiLCJvbmVUb09uZU9uQ3JlYXRlIiwiY29udGV4dCIsImRhdGEiLCJwcm9wZXJ0eVZhbHVlIiwiaW5uZXJSZXBvIiwicmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEiLCJhbGlhcyIsInJlYWQiLCJjYWNoZU1vZGVsRm9yUG9wdWxhdGUiLCJjbGFzcyIsIkludGVybmFsRXJyb3IiLCJyZXBvIiwiZm9yTW9kZWwiLCJjcmVhdGVkIiwiY3JlYXRlIiwib25lVG9PbmVPblVwZGF0ZSIsImNhc2NhZGUiLCJ1cGRhdGUiLCJDYXNjYWRlIiwiQ0FTQ0FERSIsInVwZGF0ZWQiLCJjcmVhdGVPclVwZGF0ZSIsIm9uZVRvT25lT25EZWxldGUiLCJkZWxldGVkIiwiZGVsZXRlIiwib25lVG9NYW55T25DcmVhdGUiLCJwcm9wZXJ0eVZhbHVlcyIsImFycmF5VHlwZSIsImV2ZXJ5IiwiaXRlbSIsInVuaXF1ZVZhbHVlcyIsIlNldCIsInBrTmFtZSIsIm0iLCJyZWNvcmQiLCJhZGQiLCJvbmVUb01hbnlPbkRlbGV0ZSIsImFyZUFsbFNhbWVUeXBlIiwiaXNJbnN0YW50aWF0ZWQiLCJ2IiwicG9wdWxhdGUiLCJuZXN0ZWQiLCJpc0FyciIsIkFycmF5IiwiaXNBcnJheSIsImZldGNoUG9wdWxhdGVWYWx1ZXMiLCJjIiwicHJvcE5hbWUiLCJwcm9wS2V5VmFsdWVzIiwiY2FjaGVLZXkiLCJwcm9LZXlWYWx1ZSIsImdldFBvcHVsYXRlS2V5IiwiZSIsInJlcyIsIkNvbnRyYWN0TG9nZ2VyIiwiTWluaUxvZ2dlciIsImNvbmYiLCJsb2dnZXIiLCJsb2dnaW5nIiwiZ2V0TG9nZ2VyIiwibGV2ZWwiLCJtc2ciLCJzdGFjayIsIk51bWVyaWNMb2dMZXZlbHMiLCJjb25maWciLCJtZXRob2QiLCJMb2dMZXZlbCIsImluZm8iLCJ2ZXJib3NlIiwiZXJyb3IiLCJzaWxseSIsImNhbGwiLCJjcmVhdGVMb2ciLCJmYWN0b3J5Iiwib2JqZWN0IiwiTG9nZ2luZyIsInNldEZhY3RvcnkiLCJjcmVhdGVkQnlPbkZhYnJpY0NyZWF0ZVVwZGF0ZSIsInVzZXIiLCJnZXRJRCIsIlVuc3VwcG9ydGVkRXJyb3IiLCJwa0ZhYnJpY09uQ3JlYXRlIiwic2V0UHJpbWFyeUtleVZhbHVlIiwidGFyZ2V0IiwicHJvcGVydHlLZXkiLCJkZWZpbmVQcm9wZXJ0eSIsImVudW1lcmFibGUiLCJ3cml0YWJsZSIsImNvbmZpZ3VyYWJsZSIsInNlcXVlbmNlTmFtZSIsInNlcXVlbmNlIiwiU2VxdWVuY2UiLCJuZXh0IiwiRmFicmljQ29udHJhY3RBZGFwdGVyIiwiQ291Y2hEQkFkYXB0ZXIiLCJnZXRDbGllbnQiLCJ0ZXh0RGVjb2RlciIsIlRleHREZWNvZGVyIiwic2VyaWFsaXplciIsInJlcG9zaXRvcnkiLCJzY29wZSIsImZvciIsImNvbXBvc2VkS2V5IiwiY3JlYXRlQ29tcG9zaXRlS2V5IiwiU3RyaW5nIiwicHV0U3RhdGUiLCJwYXJzZUVycm9yIiwicmVhZFN0YXRlIiwiY3R4QXJncyIsImRlbGV0ZVN0YXRlIiwiZm9yUHJpdmF0ZSIsImNvbGxlY3Rpb24iLCJ0b092ZXJyaWRlIiwicXVlcnlSZXN1bHQiLCJxdWVyeVJlc3VsdFBhZ2luYXRlZCIsImZuIiwiUHJveHkiLCJwcm9wIiwicmVjZWl2ZXIiLCJpbmNsdWRlcyIsIlJlZmxlY3QiLCJhcHBseSIsInRoaXNBcmciLCJhcmdzTGlzdCIsInB1dFByaXZhdGVEYXRhIiwiZGVsZXRlUHJpdmF0ZURhdGEiLCJnZXRQcml2YXRlRGF0YSIsImdldFByaXZhdGVEYXRhUXVlcnlSZXN1bHQiLCJpdGVyYXRvciIsImNvdW50IiwicmVhY2hlZEJvb2ttYXJrIiwibGFzdEtleSIsInJlY29yZEtleSIsInJlY29yZFZhbHVlIiwiS2V5IiwiUmVjb3JkIiwiY2xvc2UiLCJtZXRhZGF0YSIsImZldGNoZWRSZWNvcmRzQ291bnQiLCJib29rbWFyayIsImRvbmUiLCJTZXJpYWxpemF0aW9uRXJyb3IiLCJnZXRTdGF0ZSIsIk5vdEZvdW5kRXJyb3IiLCJnZXRRdWVyeVJlc3VsdCIsIl9pZCIsIiRndCIsIiRndGUiLCJpdCIsImdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24iLCJtZXJnZU1vZGVscyIsImV4dHJhY3QiLCJmaW5hbE1vZGVsIiwicG9wIiwiZGVjb2RlIiwiYnVmZmVyIiwiZmxhZ3MiLCJvcGVyYXRpb24iLCJiYXNlRmxhZ3MiLCJzZWdyZWdhdGVkIiwiY29ycmVsYXRpb25JZCIsImdldFR4SUQiLCJjbGllbnRJZGVudGl0eSIsImluZGV4IiwibW9kZWxzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZXN1bHRJdGVyYXRvciIsImlzSGlzdG9yeSIsImFsbFJlc3VsdHMiLCJqc29uUmVzIiwiVHhJZCIsInR4SWQiLCJUaW1lc3RhbXAiLCJWYWx1ZSIsImVyciIsImRvY3NPbmx5IiwicmVzcG9uc2UiLCJTdGF0ZW1lbnQiLCJjcmVhdGVBbGwiLCJ0YWJsZUxhYmVsIiwiYWxsIiwiaSIsInVwZGF0ZUFsbCIsInByZXBhcmUiLCJzZWdyZWdhdGUiLCJtYXBwZWRQcm9wIiwiY29sdW1uTmFtZSIsImlzUmVzZXJ2ZWQiLCJ0cmFuc2llbnQiLCJyZXZlcnQiLCJvYmoiLCJvYiIsImNyZWF0ZVByZWZpeCIsInVwZGF0ZVByZWZpeCIsImNyZWF0ZUFsbFByZWZpeCIsImlkcyIsInJlY29yZHMiLCJ1cGRhdGVBbGxQcmVmaXgiLCJyZWFzb24iLCJmaWx0ZXIiLCJhIiwiY2xlYXIiLCJtZXNzYWdlIiwiQ29uZmxpY3RFcnJvciIsIkJhZFJlcXVlc3RFcnJvciIsIlF1ZXJ5RXJyb3IiLCJQYWdpbmdFcnJvciIsIk1pZ3JhdGlvbkVycm9yIiwiT2JzZXJ2ZXJFcnJvciIsIkF1dGhvcml6YXRpb25FcnJvciIsIkZvcmJpZGRlbkVycm9yIiwiQ29ubmVjdGlvbkVycm9yIiwiZGVjb3JhdGlvbiIsIkRlY29yYXRpb24iLCJmbGF2b3VyZWRBcyIsIlBlcnNpc3RlbmNlS2V5cyIsIkNSRUFURURfQlkiLCJkZWZpbmUiLCJvbkNyZWF0ZSIsInByb3BNZXRhZGF0YSIsIlVQREFURURfQlkiLCJvbkNyZWF0ZVVwZGF0ZSIsImRlY29yYXRvciIsInBrRGVjIiwib3B0aW9ucyIsImdyb3Vwc29ydCIsImF0dHIiLCJyZXF1aXJlZCIsInJlYWRvbmx5IiwiQ09MVU1OIiwiZXh0ZW5kIiwiRmFicmljUHJvcGVydHkiLCJGYWJyaWNPYmplY3QiLCJvbmVUb09uZURlYyIsImpvaW5Db2x1bW5PcHRzIiwiZmsiLCJtZXRhIiwiam9pblRhYmxlIiwicmVsYXRpb24iLCJPTkVfVE9fT05FIiwiTnVtYmVyIiwiQmlnSW50Iiwib25VcGRhdGUiLCJvbkRlbGV0ZSIsImFmdGVyQW55Iiwib25lVG9NYW55RGVjIiwiam9pblRhYmxlT3B0cyIsIk9ORV9UT19NQU5ZIiwibGlzdCIsIm9uZVRvTWFueU9uVXBkYXRlIiwic2V0Q3VycmVudCIsIkRldGVybWluaXN0aWNTZXJpYWxpemVyIiwiRmFicmljQ3J1ZENvbnRyYWN0IiwiQ29udHJhY3QiLCJpbml0aWFsaXplZCIsImxpc3RCeSIsIm9yZGVyIiwicGFnaW5hdGVCeSIsInNpemUiLCJmaW5kT25lQnkiLCJzdGF0ZW1lbnQiLCJnZXRUcmFuc2llbnREYXRhIiwibWVyZ2UiLCJ0cmFuc2llbnRNYXAiLCJnZXRUcmFuc2llbnQiLCJoYXMiLCJkZWxldGVBbGwiLCJyZWFkQWxsIiwib3JkZXJCeSIsIk9yZGVyRGlyZWN0aW9uIiwiQVNDIiwiaW5pdCIsImdldE5hbWUiLCJoZWFsdGhjaGVjayIsImJpbmQiLCJDdHgiLCJnZXRPcCIsIlJFQUQiLCJSRUFEX0FMTCIsIm92ZXJyaWRlcyIsIlNlcmlhbGl6ZWRDcnVkQ29udHJhY3QiLCJwYXJzZWRLZXlzIiwibW9kZWxMaXN0IiwiY29uZCIsInBhcnNlZElucHV0IiwiX19kZWNvcmF0ZSIsIlRyYW5zYWN0aW9uIiwicHJvdG90eXBlIiwiT3ZlcmZsb3dFcnJvciIsIkJhbGFuY2VFcnJvciIsIkFsbG93YW5jZUVycm9yIiwiUmVnaXN0cmF0aW9uRXJyb3IiLCJNaXNzaW5nQ29udGV4dEVycm9yIiwiVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MiLCJCYXNlRXJyb3IiLCJOb3RJbml0aWFsaXplZEVycm9yIiwiTWlzc2luZ1BLQ1NTMTFMaWIiLCJFbmRvcnNlbWVudEVycm9yIiwiYiIsInN1YiIsInNhZmVQYXJzZUludCIsInN0cmluZyIsImRpZ2l0UmVnZXgiLCJ0ZXN0IiwiVmFsaWRhdGlvbkVycm9yIiwic3RyaW5nRm9ybWF0IiwicGFyc2VkaW50IiwicGFyc2VJbnQiLCJpc05hTiIsIkVSQzIwVG9rZW4iLCJCYXNlTW9kZWwiLCJjb2x1bW4iLCJFUkMyMFdhbGxldCIsIkFsbG93YW5jZSIsIk93bmVyIiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsTWV0aG9kIiwiYWNvdW50SWQiLCJzZWxlY3QiLCJ0b2tlbnMiLCJleGVjdXRlIiwib3duZWRCeU9uQ3JlYXRlIiwiY3JlYXRvciIsImdldENyZWF0b3IiLCJtc3BpZCIsInNldE93bmVkQnlLZXlWYWx1ZSIsIk93bmVkQnkiLCJnZXRGYWJyaWNNb2RlbEtleSIsIk9XTkVEQlkiLCJvd25lZEJ5IiwiRkFCUklDIiwiSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvbiIsInNlZ3JlZ2F0ZWREYXRhT25DcmVhdGUiLCJjb2xsZWN0aW9uUmVzb2x2ZXIiLCJjb2xsZWN0aW9ucyIsInJlYnVpbHQiLCJhY2MiLCJ0b0NyZWF0ZSIsIm92ZXJyaWRlIiwic2VncmVnYXRlZERhdGFPblJlYWQiLCJzZWdyZWdhdGVkRGF0YU9uVXBkYXRlIiwib2xkTW9kZWwiLCJzZWdyZWdhdGVkRGF0YU9uRGVsZXRlIiwiaW5uZXJTZWdyZWdhdGVkIiwic2VncmVnYXRlZERlYyIsInByb3BzIiwicHJvcGVydGllcyIsImNvbnN0ciIsInNldCIsImRlY3MiLCJwIiwicHJpb3JpdHkiLCJncm91cCIsIm9uUmVhZCIsInByaXZhdGVEYXRhIiwiUFJJVkFURSIsInNoYXJlZERhdGEiLCJTSEFSRUQiLCJFUkMyMEV2ZW50cyIsIkZhYnJpY0VSQzIwQ29udHJhY3QiLCJ3YWxsZXRSZXBvc2l0b3J5IiwidG9rZW5SZXBvc2l0b3J5IiwiYWxsb3dhbmNlUmVwb3NpdG9yeSIsIlRva2VuTmFtZSIsIkNoZWNrSW5pdGlhbGl6ZWQiLCJ0b2tlbiIsIlN5bWJvbCIsInN5bWJvbCIsIkRlY2ltYWxzIiwiZGVjaW1hbHMiLCJUb3RhbFN1cHBseSIsIndhbGxldHMiLCJ0b3RhbCIsIndhbGxldCIsImJhbGFuY2UiLCJCYWxhbmNlT2YiLCJUcmFuc2ZlciIsInRvIiwidHJhbnNmZXJSZXNwIiwiX3RyYW5zZmVyIiwiVHJhbnNmZXJGcm9tIiwiQnVybkZyb20iLCJzcGVuZGVyIiwiYWxsb3dhbmNlIiwiX2dldEFsbG93YW5jZSIsImN1cnJlbnRBbGxvd2FuY2UiLCJ1cGRhdGVkQWxsb3dhbmNlIiwibmV3QWxsb3dhbmNlIiwiZnJvbVdhbGxldCIsImZyb21CYWxhbmNlIiwidG9XYWxsZXQiLCJuZXdUb1dhbGxldCIsImNvZGUiLCJ0b0JhbGFuY2UiLCJmcm9tVXBkYXRlZEJhbGFuY2UiLCJ0b1VwZGF0ZWRCYWxhbmNlIiwidXBkYXRlZEZyb21XYWxsZXQiLCJ1cGRhdGVkVG9XYWxsZXQiLCJ0cmFuc2ZlckV2ZW50IiwicmVmcmVzaCIsIlRSQU5TRkVSIiwiY2F0Y2giLCJBcHByb3ZlIiwib3duZXJXYWxsZXQiLCJhcHByb3ZhbEV2ZW50IiwiQVBQUk9WQUwiLCJhbGxvd2FuY2VDb25kaXRpb24iLCJ3aGVyZSIsIkluaXRpYWxpemUiLCJNaW50IiwiYW1vdW50IiwibWludGVyIiwibWludGVyV2FsbGV0IiwiY3VycmVudEJhbGFuY2UiLCJ1cGRhdGVkQmFsYW5jZSIsInVwZGF0ZWRtaW50ZXIiLCJuZXdXYWxsZXQiLCJldmVudEhhbmRsZXIiLCJCdXJuIiwiYWNjb3VudCIsImFjY291bnRXYWxsZXQiLCJ1cGRhdGVkYWNjb3VudCIsIkNsaWVudEFjY291bnRCYWxhbmNlIiwiY2xpZW50QWNjb3VudElEIiwiY2xpZW50V2FsbGV0IiwiQ2xpZW50QWNjb3VudElEIiwiX19tZXRhZGF0YSIsImNvbnRyYWN0cyIsIlZFUlNJT04iLCJQQUNLQUdFX05BTUUiLCJyZWdpc3RlckxpYnJhcnkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFrQ00sTUFBT0EsOEJBQThCQztJQUt6QyxXQUFBQztRQUNFQztBQUNEO0lBT0QsUUFBSUM7UUFDRixPQUFPQyxLQUFLQyxJQUFJO0FBQ2pCO0lBT0QsYUFBYUM7UUFDWCxPQUFPRixLQUFLRCxLQUFLSTtBQUNsQjtJQU9ELFlBQUlDO1FBQ0YsT0FBT0osS0FBS0MsSUFBSTtBQUNqQjtJQUVRLFFBQUFJO1FBQ1AsT0FBTyxhQUFhTCxLQUFLRCxPQUFPLGVBQWU7QUFDaEQ7OztTQzVEYU8sd0JBQ2RDLE9BQ0FDLE9BQ0FDO0lBRUEsTUFBTUMsU0FBUyxFQUFDSCxPQUFPQztJQUN2QixJQUFJQyxPQUFPQyxPQUFPQyxLQUFLRjtJQUN2QixPQUFPQyxPQUFPRSxLQUFLO0FBQ3JCOztBQXNCTSxT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
1
+ import{CouchDBStatement as t,CouchDBKeys as e,CouchDBGroupOperator as i,CouchDBOperator as r,CouchDBAdapter as s}from"@decaf-ts/for-couchdb";import{Model as n,JSONSerializer as a,required as o,model as l}from"@decaf-ts/decorator-validation";import{Context as c,ObserverHandler as u,Adapter as d,Repository as g,Condition as p,UnsupportedError as h,QueryError as y,PagingError as w,MigrationError as f,ObserverError as m,AuthorizationError as x,ForbiddenError as b,ConnectionError as S,PersistenceKeys as A,OrderDirection as v,pk as C,column as O,table as k,BaseModel as N}from"@decaf-ts/core";import{OperationKeys as R,BulkCrudOperationKeys as z,DBKeys as E,InternalError as P,SerializationError as T,NotFoundError as $,ConflictError as D,BadRequestError as I,onCreate as B,onCreateUpdate as F,BaseError as j,ValidationError as J}from"@decaf-ts/db-decorators";import{Property as L,Object as q,Contract as _,Context as U,Transaction as M}from"fabric-contract-api";import{Metadata as H,Decoration as Q,propMetadata as V}from"@decaf-ts/decoration";import{Logging as K,MiniLogger as Y,NumericLogLevels as G,LogLevel as W}from"@decaf-ts/logging";import{__decorate as X,__metadata as Z}from"tslib";class tt extends c{constructor(){super()}get stub(){return this.get("stub")}get timestamp(){return this.stub.getDateTimestamp()}get identity(){return this.get("identity")}toString(){return"fabric ctx"+(this.stub?" with stub":"without stub")}}class et extends u{constructor(t=[R.CREATE,R.UPDATE,R.DELETE,z.CREATE_ALL,z.UPDATE_ALL,z.DELETE_ALL]){super(),this.supportedEvents=t}async updateObservers(t,e,i,...r){const{log:s,ctx:n}=d.logCtx(r,this.updateObservers),{stub:a}=n,[o,l]=r,c="string"==typeof t?t:t.name;if(-1!==this.supportedEvents.indexOf(e)){s.debug(`Emitting ${e} event`);const t=((t,e,i)=>{const r=[t,e];return i&&r.push(i),r.join("_")})(c,e,o);a.setEvent(t,Buffer.from(JSON.stringify({id:i})))}else a.setEvent(e,Buffer.from(JSON.stringify(l)))}}class it extends g{constructor(t,e,i){super(t,e),this.trackedEvents=i,this._overrides=Object.assign({},super._overrides,{ignoreValidation:!1,ignoreHandlers:!1,allowRawStatements:!0,forcePrepareSimpleQueries:!1,forcePrepareComplexQueries:!1})}ObserverHandler(){return new et}async updateObservers(t,e,i,...r){if(!this.trackedEvents||-1!==this.trackedEvents.indexOf(e))return await super.updateObservers(t,e,i,...r)}}class rt extends t{constructor(t){super(t)}async raw(t,...e){const{ctx:i}=this.logCtx(e,this.raw),r=await this.adapter.raw(t,!0,i),s=n.pk(this.fromSelector),a=H.get(this.fromSelector,H.key(E.ID,s))?.type;return this.selectSelector?r:r.map(t=>this.processRecord(t,s,a,i))}build(){const t={};t[e.TABLE]={},t[e.TABLE]=n.tableName(this.fromSelector);const s={selector:t};if(this.selectSelector&&(s.fields=this.selectSelector),this.whereCondition){const t=this.parseCondition(p.and(this.whereCondition,p.attribute(e.TABLE).eq(s.selector[e.TABLE]))).selector,r=Object.keys(t);if(1===r.length&&-1!==Object.values(i).indexOf(r[0]))switch(r[0]){case i.AND:t[i.AND]=[...Object.values(t[i.AND]).reduce((t,e)=>{const r=Object.keys(e);if(1!==r.length)throw Error("Too many keys in query selector. should be one");const s=r[0];return s===i.AND?t.push(...e[s]):t.push(e),t},[])],s.selector=t;break;case i.OR:{const e={};e[i.AND]=[t,...Object.entries(s.selector).map(([t,e])=>{const i={};return i[t]=e,i})],s.selector=e;break}default:throw Error("This should be impossible")}else Object.entries(t).forEach(([t,e])=>{s.selector[t],s.selector[t]=e})}if(this.orderBySelector){s.sort=s.sort||[],s.selector=s.selector||{};const[t,e]=this.orderBySelector,i={};i[t]=e,s.sort.push(i),s.selector[t]||(s.selector[t]={},s.selector[t][r.BIGGER]=null)}return this.limitSelector&&(s.limit=this.limitSelector),this.offsetSelector&&(s.skip=this.offsetSelector),s}}var st,nt;(t=>{t.PRIVATE="private",t.SHARED="shared",t.FABRIC="fabric.",t.OWNEDBY="owned-by"})(st||(st={})),(t=>{t.X509="X.509"})(nt||(nt={}));const at="hlf-fabric";class ot extends a{constructor(){super()}deserialize(t,e){return JSON.parse(t)}serialize(t){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t)))}preSerialize(t){return Object.assign({},t)}}class lt extends Y{constructor(t,e,i){super(t,e),this.logger=i?i.logging.getLogger(t):new Y(t,e)}log(t,e,i){if(G[this.config("level")]<G[t])return;let r;switch(t){case W.info:r=this.logger.info;break;case W.verbose:r=this.logger.verbose;break;case W.debug:r=this.logger.debug;break;case W.error:r=this.logger.error;break;case W.silly:r=this.logger.silly;break;default:throw new P("Invalid log level")}r.call(this.logger,this.createLog(t,e,i))}}async function ct(t,e,i,r){try{const e=t.get("identity");r[i]=e.getID()}catch(t){throw new h("No User found in context. Please provide a user in the context")}}async function ut(t,e,i,r){if(!e.type||r[i])return;let s;e.name||(e.name=n.sequenceName(r,"pk"));try{s=await this.adapter.Sequence(e)}catch(t){throw new P(`Failed to instantiate Sequence ${e.name}: ${t}`)}const a=await s.next(t);Object.defineProperty(r,i,{enumerable:!0,writable:!1,configurable:!0,value:a})}K.setFactory((t,e,i)=>new lt(t||lt.name,e||{},i));class dt extends s{getClient(){throw new h("Client is not supported in Fabric contracts")}static{this.textDecoder=new TextDecoder("utf8")}static{this.serializer=new ot}repository(){return it}constructor(t,e){super(t,at,e),this.Context=tt}for(t,...e){return super.for(t,...e)}async create(t,e,i,...r){const{ctx:s,log:a,stub:o}=this.logCtx(r,this.create);a.info("in ADAPTER create with args "+r);const l=n.tableName(t);try{a.info(`adding entry to ${l} table with pk ${e}`);const t=o.createCompositeKey(l,[e+""]);i=await this.putState(t,i,s)}catch(t){throw this.parseError(t)}return i}async read(t,e,...i){const{ctx:r,log:s,stub:a}=this.logCtx(i,this.read);s.info("in ADAPTER read with args "+i);const o=n.tableName(t);let l;try{const t=a.createCompositeKey(o,[e+""]);l=await this.readState(t,r)}catch(t){throw this.parseError(t)}return l}async update(t,e,i,...r){const{ctx:s,log:a,stub:o}=this.logCtx(r,this.update),l=n.tableName(t);try{a.verbose(`updating entry to ${l} table with pk ${e}`);const t=o.createCompositeKey(l,[e+""]);i=await this.putState(t,i,s)}catch(t){throw this.parseError(t)}return i}async delete(t,e,...i){const{ctx:r,log:s,ctxArgs:a,stub:o}=this.logCtx(i,this.delete),l=n.tableName(t);let c;try{const i=o.createCompositeKey(l,[e+""]);c=await this.read(t,e,...a),s.verbose(`deleting entry with pk ${e} from ${l} table`),await this.deleteState(i,r)}catch(t){throw this.parseError(t)}return c}async deleteState(t,e){const{stub:i}=this.logCtx([e],this.deleteState);await i.deleteState(t)}forPrivate(t){const e=[this.putState,this.readState,this.deleteState,this.queryResult,this.queryResultPaginated].map(t=>t.name);return new Proxy(this,{get:(i,r,s)=>e.includes(r)?new Proxy(i[r],{async apply(e,i,s){switch(r){case"putState":{const[e,i,r]=s;return await e.putPrivateData(t,i.toString(),r),r}case"deleteState":{const[e,i]=s;return e.deletePrivateData(t,i)}case"readState":{const[e,i]=s;return e.getPrivateData(t,i)}case"queryResult":{const[e,i]=s;return e.getPrivateDataQueryResult(t,i)}case"queryResultPaginated":{const[e,i,r,n]=s,a=await e.getPrivateDataQueryResult(t,i),o=[];let l=0,c=!n,u=null;for(;;){const t=await a.next();if(t.value&&t.value.value.toString()){const e=t.value.key,i=t.value.value.toString("utf8");if(!c){e===n?.toString()&&(c=!0);continue}if(o.push({Key:e,Record:JSON.parse(i)}),u=e,l++,l>=r)return await a.close(),{iterator:o,metadata:{fetchedRecordsCount:o.length,bookmark:u}}}if(t.done)return await a.close(),{iterator:o,metadata:{fetchedRecordsCount:o.length,bookmark:""}}}}default:throw new P("Unsupported method override "+r)}}}):Reflect.get(i,r,s)})}async putState(t,e,i){let r;const{stub:s,log:n}=this.logCtx([i],this.putState);try{r=Buffer.from(dt.serializer.serialize(e))}catch(e){throw new T(`Failed to serialize record with id ${t}: ${e}`)}const a=i.get("segregated");return a?await s.putPrivateData(a,t.toString(),r):await s.putState(t.toString(),r),n.silly(`state stored${a?` in ${a} collection`:""} under id ${t}`),e}async readState(t,e){let i;const{stub:r,log:s}=this.logCtx([e],this.readState);let n;const a=e.get("segregated");if(n=a?(await r.getPrivateData(a,t.toString())).toString():(await r.getState(t.toString())).toString(),!n)throw new $(`Record with id ${t}${a?` in ${a} collection`:""} not found`);s.silly(`state retrieved from${a?` ${a} collection`:""} under id ${t}`);try{i=dt.serializer.deserialize(n.toString())}catch(t){throw new T("Failed to parse record: "+t)}return i}async queryResult(t,e,...i){const{ctx:r}=this.logCtx(i,this.readState);let s;const n=r.get("segregated");return s=n?await t.getPrivateDataQueryResult(n,JSON.stringify(e)):await t.getQueryResult(JSON.stringify(e)),s}async queryResultPaginated(t,e,i=250,r,...s){const{ctx:n}=this.logCtx(s,this.readState);let a;const o=n.get("segregated");return o?(e.selector={...e.selector,_id:r?{$gt:r.toString()}:{$gte:""}},a={iterator:await t.getPrivateDataQueryResult(o,JSON.stringify(e)),metadata:{fetchedRecordsCount:i,bookmark:""}}):a=await t.getQueryResultWithPagination(JSON.stringify(e),i,r?.toString()),a}mergeModels(t){const e=t=>Object.entries(t).reduce((t,[e,i])=>(void 0!==i&&(t[e]=i),t),{});let i=t.pop();for(const r of t)i=Object.assign({},e(i),e(r));return i}decode(t){return dt.textDecoder.decode(t)}async flags(t,e,i,r,...s){const n={stub:r.stub,segregated:!1};return Object.assign(n,r instanceof tt?{logger:r.logger,identity:r.identity,correlationId:r.stub.getTxID()}:{identity:r.clientIdentity,logger:new lt(this,void 0,r),correlationId:r.stub.getTxID()}),await super.flags(t,e,n,...s)}index(t){return Promise.resolve(void 0)}async resultIterator(t,e,i=!1){const r=[];let s=await e.next();for(;!s.done;){if(s.value&&s.value.value.toString()){let e={};if(t.debug(s.value.value.toString("utf8")),i){e.TxId=s.value.txId,e.Timestamp=s.value.timestamp;try{e.Value=JSON.parse(s.value.value.toString("utf8"))}catch(i){t.error(i),e.Value=s.value.value.toString("utf8")}}else try{e=JSON.parse(s.value.value.toString("utf8"))}catch(i){t.error(i),e=s.value.value.toString("utf8")}r.push(e)}s=await e.next()}return t.debug(`Closing iterator after ${r.length} results`),e.close(),r}async raw(t,e=!0,...i){const{log:r,stub:s}=this.logCtx(i,this.raw),{skip:n,limit:a}=t;let o;a||n?(delete t.limit,delete t.skip,r.debug(`Retrieving paginated iterator: limit: ${a}/ skip: ${n}`),o=(await this.queryResultPaginated(s,t,a||250,n?.toString())).iterator):(r.debug("Retrieving iterator"),o=await this.queryResult(s,t)),r.debug("Iterator acquired");const l=await this.resultIterator(r,o);return r.debug(`returning ${Array.isArray(l)?l.length:1} results`),l}Statement(){return new rt(this)}async createAll(t,e,i,...r){if(e.length!==i.length)throw new P("Ids and models must have the same length");const{log:s,ctxArgs:a}=this.logCtx(r,this.createAll),o=n.tableName(t);return s.debug(`Creating ${e.length} entries ${o} table`),Promise.all(e.map((e,r)=>this.create(t,e,i[r],...a)))}async updateAll(t,e,i,...r){if(e.length!==i.length)throw new P("Ids and models must have the same length");const{log:s,ctxArgs:a}=this.logCtx(r,this.updateAll),o=n.tableName(t);return s.debug(`Updating ${e.length} entries ${o} table`),Promise.all(e.map((e,r)=>this.update(t,e,i[r],...a)))}prepare(t,...e){const{log:i}=this.logCtx(e,this.prepare),r=n.tableName(t.constructor),s=n.pk(t.constructor),a=n.segregate(t),o=Object.entries(a.model).reduce((e,[i,r])=>{if(void 0===r)return e;const s=n.columnName(t,i);if(this.isReserved(s))throw new P(`Property name ${s} is reserved`);return e[s]=r,e},{});return i.silly(`Preparing record for ${r} table with pk ${t[s]}`),{record:o,id:t[s],transient:a.transient}}revert(t,e,i,r,...s){const{log:a}=this.logCtx(s,this.revert),o={};o[n.pk(e)]=i;const l="string"==typeof e?n.build(o,e):new e(o);a.silly(`Rebuilding model ${l.constructor.name} id ${i}`);const c=Object.keys(l).reduce((e,i)=>(e[i]=t[n.columnName(e,i)],e),l);return r&&(a.debug("re-adding transient properties: "+Object.keys(r).join(", ")),Object.entries(r).forEach(([t,e])=>{if(t in c&&void 0!==c[t])throw new P(`Transient property ${t} already exists on model ${l.constructor.name}. should be impossible`);c[t]=e})),c}createPrefix(t,i,r,...s){const{ctxArgs:a}=this.logCtx(s,this.createPrefix),o={};return o[e.TABLE]=n.tableName(t),Object.assign(o,r),[t,i,o,...a]}updatePrefix(t,i,r,...s){const{ctxArgs:a}=this.logCtx(s,this.updatePrefix),o={};return o[e.TABLE]=n.tableName(t),Object.assign(o,r),[t,i,o,...a]}createAllPrefix(t,i,r,...s){if(i.length!==r.length)throw new P("Ids and models must have the same length");const n=s.pop(),a=i.map((i,s)=>{const n={};return n[e.TABLE]=t,Object.assign(n,r[s]),n});return[t,i,a,n]}updateAllPrefix(t,i,r,...s){if(i.length!==r.length)throw new P("Ids and models must have the same length");const n=s.pop(),a=i.map((i,s)=>{const n={};return n[e.TABLE]=t,Object.assign(n,r[s]),n});return[t,i,a,n]}parseError(t,e){return dt.parseError(e||t)}logCtx(t,e){return dt.logCtx.call(this,t,e)}static logCtx(t,e){if(1>t.length)throw new P("No context provided");const i=t.pop();if(!(i instanceof c))throw new P("No context provided");if(t.filter(t=>t instanceof c).length>1)throw Error("here");const r=this?i.logger.for(this).for(e):i.logger.clear().for(this).for(e);return{ctx:i,log:e?r.for(e):r,stub:i.stub,identity:i.identity,ctxArgs:[...t,i]}}static parseError(t){const e="string"==typeof t?t:t.message;return e.includes($.name)?new $(t):e.includes(D.name)?new D(t):e.includes(I.name)?new I(t):e.includes(y.name)?new y(t):e.includes(w.name)?new w(t):e.includes(h.name)?new h(t):e.includes(f.name)?new f(t):e.includes(m.name)?new m(t):e.includes(x.name)?new x(t):e.includes(b.name)?new b(t):e.includes(S.name)?new S(t):e.includes(T.name)?new T(t):new P(t)}static decoration(){super.decoration(),Q.flavouredAs(at).for(A.CREATED_BY).define(B(ct),V(A.CREATED_BY,{})).apply(),Q.flavouredAs(at).for(A.UPDATED_BY).define(F(ct),V(A.UPDATED_BY,{})).apply(),Q.flavouredAs(at).for(A.COLUMN).extend(L()).apply(),Q.flavouredAs(at).for(A.TABLE).extend(t=>q()(t)).apply()}}dt.decoration(),d.setCurrent(at);class gt extends a{constructor(){super()}deserialize(t){return super.deserialize(t)}serialize(t){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t)))}}class pt extends _{static{this.adapter=new dt}static{this.serializer=new gt}constructor(t,e){super(t),this.clazz=e,this.initialized=!1,this.repo=g.forModel(e)}async listBy(t,e,i,...r){const{ctxArgs:s}=await this.logCtx([...r,t],this.listBy);return this.repo.listBy(e,i,...s)}async paginateBy(t,e,i,r,...s){const{ctxArgs:n}=await this.logCtx([...s,t],this.paginateBy);return this.repo.paginateBy(e,i,r,...n)}async findOneBy(t,e,i,...r){const{ctxArgs:s}=await this.logCtx([...r,t],this.findOneBy);return this.repo.findOneBy(e,i,...s)}async statement(t,e,...i){const{ctxArgs:r}=await this.logCtx([...i,t],this.statement);return this.repo.statement(e,...r)}async create(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.create);r.info("CONTRACT CREATE, "+s),"string"==typeof e&&(e=this.deserialize(e)),r.info("Creating model: "+JSON.stringify(e));const a=this.getTransientData(t);return r.info("Merging transient data..."),e=n.merge(e,a,this.clazz),this.repo.create(e,...s)}async read(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.read);return r.info(`reading entry with pk ${e} `),this.repo.read(e,...s)}getTransientData(t){const e=t.stub.getTransient();let i={};return e.has(this.repo.tableName)&&(i=JSON.parse(e.get(this.repo.tableName)?.toString("utf8"))),i}async update(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.update);"string"==typeof e&&(e=this.deserialize(e)),r.info("Updating model: "+JSON.stringify(e));const a=this.getTransientData(t);return r.info("Merging transient data..."),e=n.merge(e,a,this.clazz),this.repo.update(e,...s)}async delete(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.delete);return r.info(`deleting entry with pk ${e} `),this.repo.delete(e+"",...s)}async deleteAll(t,e,...i){const{ctxArgs:r}=await this.logCtx([...i,t],this.readAll);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.deleteAll(e,...r)}async readAll(t,e,...i){const{ctxArgs:r}=await this.logCtx([...i,t],this.readAll);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.readAll(e,...r)}async updateAll(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.updateAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),r.info(`updating ${e.length} entries to the table`),this.repo.updateAll(e,...s)}async query(t,e,i,r=v.ASC,s,n,...a){const{ctxArgs:o}=await this.logCtx([...a,t],this.query);return this.repo.query(e,i,r,s,n,...o)}async raw(t,e,i,...r){const{ctxArgs:s}=await this.logCtx([...r,t],this.raw);return pt.adapter.raw(e,i,...s)}serialize(t){return pt.serializer.serialize(t)}deserialize(t){return pt.serializer.deserialize(t)}async init(t){const{log:e}=await this.logCtx([t],this.init);e.info(`Running contract ${this.getName()} initialization...`),this.initialized=!0,e.info("Contract initialization completed.")}async healthcheck(t){const{log:e}=await this.logCtx([t],this.healthcheck);return e.info(`Running Healthcheck: ${this.initialized}...`),{healthcheck:this.initialized}}async createAll(t,e,...i){const{log:r,ctxArgs:s}=await this.logCtx([...i,t],this.createAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),r.info(`adding ${e.length} entries to the table`),this.repo.createAll(e,...s)}async logCtx(t,e){return pt.logCtx.bind(this)(t,e)}static async logCtx(t,e){if(1>t.length)throw new P("No context provided");const i=t.pop();if(i instanceof tt)return{ctx:i,log:i.logger.clear().for(this).for(e),ctxArgs:[...t,i],stub:i.stub,identity:i.identity};if(!(i instanceof U))throw new P("No valid context provided");const r={correlationId:i.stub.getTxID()},s=await pt.adapter.context((()=>{if("string"==typeof e)return e;switch(e.name){case R.CREATE:case R.READ:case R.UPDATE:case R.DELETE:case z.CREATE_ALL:case z.READ_ALL:case z.UPDATE_ALL:case z.DELETE_ALL:}return e.name})(),r,this.clazz,i),n=this?s.logger.for(this).for(e):s.logger.clear().for(this).for(e);return{ctx:s,log:n,stub:s.stub,identity:s.identity,ctxArgs:[...t,s]}}}class ht extends pt{constructor(t,e){super(t,e)}async create(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.create);i.info("Creating model: "+e);const s=this.deserialize(e);return i.info("Model deserialized: "+JSON.stringify(s)),this.serialize(await super.create(r,s))}async read(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.read);return i.info("Reading id: "+e),this.serialize(await super.read(r,e))}async update(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.update);return i.info("Updating model: "+e),this.serialize(await super.update(r,e))}async delete(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.delete);return i.info("Deleting id: "+e),this.serialize(await super.delete(r,e))}async deleteAll(t,e){const i=JSON.parse(e),{log:r,ctx:s}=await this.logCtx([t],this.deleteAll);return r.info(`deleting ${i.length} entries from the table`),JSON.stringify((await super.deleteAll(s,i)).map(t=>this.serialize(t)))}async readAll(t,e){const i=JSON.parse(e),{log:r,ctx:s}=await this.logCtx([t],this.readAll);return r.info(`reading ${i.length} entries from the table`),JSON.stringify((await super.readAll(s,i)).map(t=>this.serialize(t)))}async updateAll(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.updateAll),s=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t));return i.info(`Updating ${s.length} entries to the table`),JSON.stringify((await super.updateAll(r,s)).map(t=>this.serialize(t)))}async statement(t,e,...i){const{ctx:r,log:s}=await this.logCtx([...i,t],this.statement);return i=i.map(t=>{try{return JSON.parse(t)}catch(e){return t}}),s.info("calling prepared statement "+e),s.debug("with args "+i),JSON.stringify(await super.statement(r,e,...i))}async listBy(t,e,i,...r){const{ctx:s}=await this.logCtx([...r,t],this.listBy);return JSON.stringify(await super.listBy(s,e,i))}async paginateBy(t,e,i,r,...s){const{ctx:n}=await this.logCtx([...s,t],this.paginateBy);return JSON.stringify(await super.paginateBy(n,e,i,r))}async findOneBy(t,e,i,...r){const{ctx:s}=await this.logCtx([...r,t],this.paginateBy);return JSON.stringify(await super.findOneBy(s,e,i,...r))}async query(t,e,i,r,s,n,...a){const{ctx:o}=await this.logCtx([t],this.query);let l;try{l=p.from(JSON.parse(e))}catch(t){throw new T("Invalid condition: "+t)}return JSON.stringify(await super.query(o,l,i,r,s,n,...a))}async init(t){await super.init(t)}async healthcheck(t){const{log:e,ctx:i}=await this.logCtx([t],this.updateAll);return e.debug(`Running Healthcheck: ${this.initialized}...`),JSON.stringify(await super.healthcheck(i))}async createAll(t,e){const{log:i}=await this.logCtx([t],this.createAll),r=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t));return i.info(`Adding ${r.length} entries to the table`),JSON.stringify((await super.createAll(t,r)).map(t=>this.serialize(t)))}}X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"create",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"read",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"update",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"delete",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"deleteAll",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"readAll",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"updateAll",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String,String]),Z("design:returntype",Promise)],ht.prototype,"statement",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String,String,String]),Z("design:returntype",Promise)],ht.prototype,"listBy",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String,String,Number,String]),Z("design:returntype",Promise)],ht.prototype,"paginateBy",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String,String,String]),Z("design:returntype",Promise)],ht.prototype,"findOneBy",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],ht.prototype,"init",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],ht.prototype,"healthcheck",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],ht.prototype,"createAll",null);class yt extends P{constructor(t){super(t,yt.name)}}class wt extends P{constructor(t){super(t,wt.name)}}class ft extends P{constructor(t){super(t,ft.name)}}class mt extends j{constructor(t){super(mt.name,t,409)}}function xt(t,e){const i=t+e;if(t!==i-e||e!==i-t)throw new yt(`Addition overflow: ${t} + ${e}`);return i}function bt(t,e){const i=t-e;if(t!==i+e||e!==t-i)throw new yt(`Subtraction overflow: ${t} - ${e}`);return i}let St=class extends N{constructor(t){super(t)}};X([C({type:"String"}),Z("design:type",String)],St.prototype,"name",void 0),X([O(),o(),Z("design:type",String)],St.prototype,"owner",void 0),X([O(),o(),Z("design:type",String)],St.prototype,"symbol",void 0),X([O(),o(),Z("design:type",Number)],St.prototype,"decimals",void 0),St=X([k("erc20_tokens"),l(),Z("design:paramtypes",[Object])],St);let At=class extends N{constructor(t){super(t)}};X([C({type:"String"}),Z("design:type",String)],At.prototype,"id",void 0),X([O(),o(),Z("design:type",String)],At.prototype,"token",void 0),X([O(),o(),Z("design:type",Number)],At.prototype,"balance",void 0),X([O(),Z("design:type",String)],At.prototype,"captive",void 0),At=X([k("erc20_wallets"),l(),Z("design:paramtypes",[Object])],At);let vt=class extends N{constructor(t){super(t)}};function Ct(){return function(t,e,i){const r=i.value;return i.value=async function(...t){const i=t[0],s=i.clientIdentity.getID(),n=await this.tokenRepository.select(),a=await n.execute(i);if(0==a.length)throw new $("No tokens avaialble");if(a.length>1)throw new $("To many token available : "+a.length);if(a[0].owner!=s)throw new x(`User not authorized to run ${e} on the token`);return await r.apply(this,t)},i}}var Ot;X([C({type:"String"}),O(),o(),Z("design:type",String)],vt.prototype,"owner",void 0),X([O(),o(),Z("design:type",String)],vt.prototype,"spender",void 0),X([O(),o(),Z("design:type",Number)],vt.prototype,"value",void 0),vt=X([k("erc20_allowances"),l(),Z("design:paramtypes",[Object])],vt),(t=>{t.TRANSFER="Transfer",t.APPROVAL="Approval"})(Ot||(Ot={}));class kt extends pt{constructor(t){super(t,At),kt.adapter=kt.adapter||new dt,this.walletRepository=it.forModel(At,kt.adapter.alias),this.tokenRepository=it.forModel(St,kt.adapter.alias),this.allowanceRepository=it.forModel(vt,kt.adapter.alias)}async TokenName(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const i=this.tokenRepository.select();return(await i.execute(e))[0].name}async Symbol(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const i=this.tokenRepository.select();return(await i.execute(e))[0].symbol}async Decimals(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const i=this.tokenRepository.select();return(await i.execute(e))[0].decimals}async TotalSupply(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const i=this.walletRepository.select(),r=await i.execute(e);if(0==r.length)throw new $(`The token ${this.getName()} does not exist`);let s=0;return r.forEach(t=>{s+=t.balance}),s}async BalanceOf(t,e){const{ctx:i}=await this.logCtx([t],this.TokenName);return await this.CheckInitialized(i),(await this.walletRepository.read(e,i)).balance}async Transfer(t,e,i){const{ctx:r}=await this.logCtx([t],this.Transfer);await this.CheckInitialized(r);const s=r.identity.getID();if(!await this._transfer(s,e,i,r))throw new P("Failed to transfer");return!0}async TransferFrom(t,e,i,r){const{ctx:s}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(s);const n=s.identity.getID(),a=await this._getAllowance(e,n,s);if(!a||0>a.value)throw new ft(`spender ${n} has no allowance from ${e}`);const o=a.value;if(r>o)throw new wt("The spender does not have enough allowance to spend.");const l=bt(o,r),c=Object.assign({},a,{value:l});if(await this.allowanceRepository.update(c,s),!await this._transfer(e,i,r,s))throw new P("Failed to transfer");return!0}async _transfer(t,e,i,r){const s=r.logger;if(t===e)throw new x("cannot transfer to and from same client account");if(0>i)throw new wt("transfer amount cannot be negative");const n=await this.walletRepository.read(t,r),a=n.balance;if(i>a)throw new wt(`client account ${t} has insufficient funds.`);let o,l=!1;try{o=await this.walletRepository.read(e,r)}catch(t){if(!(t instanceof j))throw new P(t);if(404!==t.code)throw new P(t.message);o=new At({id:e,balance:0,token:await this.TokenName(r)}),l=!0}const c=o.balance,u=bt(a,i),d=xt(c,i),g=Object.assign({},n,{balance:u});await this.walletRepository.update(g,r);const p=Object.assign({},o,{balance:d});l?await this.walletRepository.create(p,r):await this.walletRepository.update(p,r);const h={from:t,to:e,value:i};return this.repo.refresh(St,Ot.TRANSFER,"",h,r).catch(t=>s.error("Failed to notify transfer: "+t)),!0}async Approve(t,e,i){const{ctx:r,ctxArgs:s}=await this.logCtx([t],this.Approve);await this.CheckInitialized(r);const n=r.identity.getID();let a=await this._getAllowance(n,e,r);if((await this.walletRepository.read(n,...s)).balance<i)throw new wt(`client account ${n} has insufficient funds.`);a?(a.value=i,await this.allowanceRepository.update(a,...s)):(a=new vt({owner:n,spender:e,value:i}),await this.allowanceRepository.create(a,...s));const o={owner:n,spender:e,value:i};return this.repo.refresh(St,Ot.APPROVAL,"",o,r),!0}async Allowance(t,e,i){const{ctx:r}=await this.logCtx([t],this.Allowance);await this.CheckInitialized(r);const s=await this._getAllowance(e,i,r);if(!s)throw new ft(`spender ${i} has no allowance from ${e}`);return s.value}async _getAllowance(t,e,i){const r=p.and(p.attribute("owner").eq(t),p.attribute("spender").eq(e)),s=await this.allowanceRepository.select().where(r).execute(i);return s?.[0]}async Initialize(t,e){const{ctx:i}=await this.logCtx([t],this.Initialize);if((await this.tokenRepository.select().execute(i)).length>0)throw new x("contract options are already set, client is not authorized to change them");return e.owner=i.identity.getID(),await this.tokenRepository.create(e,i),!0}async CheckInitialized(t){const{ctx:e}=await this.logCtx([t],this.CheckInitialized);if(0==(await this.tokenRepository.select().execute(e)).length)throw new mt("contract options need to be set before calling any function, call Initialize() to initialize contract")}async Mint(t,e){const{ctx:i}=await this.logCtx([t],this.Mint);await this.CheckInitialized(i);const r=i.identity.getID();if(0>=e)throw new J("mint amount must be a positive integer");let s;try{s=await this.walletRepository.read(r,i);const t=xt(s.balance,e),n=Object.assign({},s,{balance:t});await this.walletRepository.update(n,i)}catch(s){if(!(s instanceof j))throw new P(s);if(404!==s.code)throw new P(s.message);{const s=new At({id:r,balance:e,token:await this.TokenName(t)});await this.walletRepository.create(s,i)}}const n={from:"0x0",to:r,value:e};this.repo.ObserverHandler().updateObservers(St,Ot.TRANSFER,"",n,i)}async Burn(t,e){const{log:i,ctx:r}=await this.logCtx([t],this.Burn);await this.CheckInitialized(r);const s=r.identity.getID(),n=await this.walletRepository.read(s,r),a=n.balance;if(e>a)throw new wt("Minter has insufficient funds.");const o=bt(a,e),l=Object.assign({},n,{balance:o});await this.walletRepository.update(l,r),i.info(e+" tokens were burned");const c={from:s,to:"0x0",value:e};this.repo.ObserverHandler().updateObservers(St,Ot.TRANSFER,"",c,r)}async BurnFrom(t,e,i){const{log:r,ctx:s}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(s);const n=await this.walletRepository.read(e,s),a=n.balance;if(i>a)throw new wt(e+" has insufficient funds.");const o=bt(a,i),l=Object.assign({},n,{balance:o});await this.walletRepository.update(l,s),r.info(`${i} tokens were burned from ${e}`);const c={from:e,to:"0x0",value:i};this.repo.ObserverHandler().updateObservers(St,Ot.TRANSFER,"",c,s)}async ClientAccountBalance(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const i=e.identity.getID(),r=await this.walletRepository.read(i,e);if(!r)throw new wt(`The account ${i} does not exist`);return r.balance}async ClientAccountID(t){const{ctx:e}=await this.logCtx([t],this.ClientAccountID);return await this.CheckInitialized(e),e.identity.getID()}}X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"TokenName",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"Symbol",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"Decimals",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"TotalSupply",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String]),Z("design:returntype",Promise)],kt.prototype,"BalanceOf",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String,Number]),Z("design:returntype",Promise)],kt.prototype,"Transfer",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String,String,Number]),Z("design:returntype",Promise)],kt.prototype,"TransferFrom",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,String,Number]),Z("design:returntype",Promise)],kt.prototype,"Approve",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U,String,String]),Z("design:returntype",Promise)],kt.prototype,"Allowance",null),X([M(),Z("design:type",Function),Z("design:paramtypes",[U,St]),Z("design:returntype",Promise)],kt.prototype,"Initialize",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"CheckInitialized",null),X([Ct(),M(),Z("design:type",Function),Z("design:paramtypes",[U,Number]),Z("design:returntype",Promise)],kt.prototype,"Mint",null),X([Ct(),M(),Z("design:type",Function),Z("design:paramtypes",[U,Number]),Z("design:returntype",Promise)],kt.prototype,"Burn",null),X([Ct(),M(),Z("design:type",Function),Z("design:paramtypes",[U,String,Number]),Z("design:returntype",Promise)],kt.prototype,"BurnFrom",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"ClientAccountBalance",null),X([M(!1),Z("design:type",Function),Z("design:paramtypes",[U]),Z("design:returntype",Promise)],kt.prototype,"ClientAccountID",null);const Nt=[kt],Rt="##VERSION##",zt="##PACKAGE##";H.registerLibrary(zt,Rt);export{lt as ContractLogger,dt as FabricContractAdapter,tt as FabricContractContext,it as FabricContractRepository,et as FabricContractRepositoryObservableHandler,pt as FabricCrudContract,rt as FabricStatement,zt as PACKAGE_NAME,ht as SerializedCrudContract,Rt as VERSION,Nt as contracts,ct as createdByOnFabricCreateUpdate,ut as pkFabricOnCreate};
2
+ //# sourceMappingURL=for-fabric.js.map