@decaf-ts/for-fabric 0.1.63 → 0.1.65

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 (401) hide show
  1. package/dist/for-fabric.cjs +2 -2744
  2. package/dist/for-fabric.cjs.map +1 -0
  3. package/dist/for-fabric.js +2 -2833
  4. package/dist/for-fabric.js.map +1 -0
  5. package/lib/bin/cli.cjs +1 -2
  6. package/lib/bin/cli.js.map +1 -0
  7. package/lib/cli-module.cjs +1 -1
  8. package/lib/cli-module.js.map +1 -0
  9. package/lib/cli-utils.cjs +1 -1
  10. package/lib/cli-utils.js.map +1 -0
  11. package/lib/client/FabricClientAdapter.cjs +3 -39
  12. package/lib/client/FabricClientAdapter.d.ts +1 -2
  13. package/lib/client/FabricClientAdapter.js.map +1 -0
  14. package/lib/client/FabricClientDispatch.cjs +1 -1
  15. package/lib/client/FabricClientDispatch.js.map +1 -0
  16. package/lib/client/FabricClientPaginator.cjs +1 -1
  17. package/lib/client/FabricClientPaginator.js.map +1 -0
  18. package/lib/client/FabricClientRepository.cjs +1 -1
  19. package/lib/client/FabricClientRepository.js.map +1 -0
  20. package/lib/client/FabricClientStatement.cjs +1 -1
  21. package/lib/client/FabricClientStatement.js.map +1 -0
  22. package/lib/client/collections/generation.cjs +1 -1
  23. package/lib/client/collections/generation.js.map +1 -0
  24. package/lib/client/collections/index.cjs +1 -1
  25. package/lib/client/collections/index.js.map +1 -0
  26. package/lib/client/constants.cjs +2 -3
  27. package/lib/client/constants.js.map +1 -0
  28. package/lib/client/crypto.cjs +1 -1
  29. package/lib/client/crypto.js.map +1 -0
  30. package/lib/client/erc20/FabricERC20ClientRepository.cjs +1 -1
  31. package/lib/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  32. package/lib/client/erc20/index.cjs +1 -1
  33. package/lib/client/erc20/index.js.map +1 -0
  34. package/lib/client/fabric-fs.cjs +1 -1
  35. package/lib/client/fabric-fs.js.map +1 -0
  36. package/lib/client/fabric-hsm.cjs +1 -1
  37. package/lib/client/fabric-hsm.js.map +1 -0
  38. package/lib/client/index.cjs +1 -1
  39. package/lib/client/index.js.map +1 -0
  40. package/lib/client/indexes/generation.cjs +1 -1
  41. package/lib/client/indexes/generation.js.map +1 -0
  42. package/lib/client/indexes/index.cjs +1 -1
  43. package/lib/client/indexes/index.js.map +1 -0
  44. package/lib/client/logging.cjs +1 -1
  45. package/lib/client/logging.js.map +1 -0
  46. package/lib/client/services/FabricEnrollmentService.cjs +1 -1
  47. package/lib/client/services/FabricEnrollmentService.js.map +1 -0
  48. package/lib/client/services/FabricIdentityService.cjs +1 -1
  49. package/lib/client/services/FabricIdentityService.js.map +1 -0
  50. package/lib/client/services/RegistrationRequestBuilder.cjs +1 -1
  51. package/lib/client/services/RegistrationRequestBuilder.js.map +1 -0
  52. package/lib/client/services/constants.cjs +1 -1
  53. package/lib/client/services/constants.js.map +1 -0
  54. package/lib/client/services/index.cjs +1 -1
  55. package/lib/client/services/index.js.map +1 -0
  56. package/lib/client/types.cjs +1 -1
  57. package/lib/client/types.js.map +1 -0
  58. package/lib/client/utils.cjs +1 -1
  59. package/lib/client/utils.js.map +1 -0
  60. package/lib/contract/Address.cjs +1 -1
  61. package/lib/contract/Address.js.map +1 -0
  62. package/lib/contract/AddressContract.cjs +1 -1
  63. package/lib/contract/AddressContract.js.map +1 -0
  64. package/lib/contract/BatchContract.cjs +1 -1
  65. package/lib/contract/BatchContract.js.map +1 -0
  66. package/lib/contract/OtherProductContract.cjs +1 -1
  67. package/lib/contract/OtherProductContract.js.map +1 -0
  68. package/lib/contract/OtherProductSharedContract.cjs +1 -1
  69. package/lib/contract/OtherProductSharedContract.js.map +1 -0
  70. package/lib/contract/Product.cjs +1 -1
  71. package/lib/contract/Product.js.map +1 -0
  72. package/lib/contract/ProductContract.cjs +1 -1
  73. package/lib/contract/ProductContract.js.map +1 -0
  74. package/lib/contract/User.cjs +1 -1
  75. package/lib/contract/User.js.map +1 -0
  76. package/lib/contract/UserContract.cjs +1 -1
  77. package/lib/contract/UserContract.js.map +1 -0
  78. package/lib/contract/index.cjs +1 -1
  79. package/lib/contract/index.js.map +1 -0
  80. package/lib/contract/models/Audit.cjs +1 -1
  81. package/lib/contract/models/Audit.js.map +1 -0
  82. package/lib/contract/models/BaseIdentifiedModel.cjs +1 -1
  83. package/lib/contract/models/BaseIdentifiedModel.js.map +1 -0
  84. package/lib/contract/models/BaseModel.cjs +1 -1
  85. package/lib/contract/models/BaseModel.js.map +1 -0
  86. package/lib/contract/models/Batch.cjs +1 -1
  87. package/lib/contract/models/Batch.js.map +1 -0
  88. package/lib/contract/models/Leaflet.cjs +1 -1
  89. package/lib/contract/models/Leaflet.js.map +1 -0
  90. package/lib/contract/models/LeafletFile.cjs +1 -1
  91. package/lib/contract/models/LeafletFile.js.map +1 -0
  92. package/lib/contract/models/Market.cjs +1 -1
  93. package/lib/contract/models/Market.js.map +1 -0
  94. package/lib/contract/models/OtherProduct.cjs +1 -1
  95. package/lib/contract/models/OtherProduct.js.map +1 -0
  96. package/lib/contract/models/OtherProductShared.cjs +1 -1
  97. package/lib/contract/models/OtherProductShared.js.map +1 -0
  98. package/lib/contract/models/Product.cjs +1 -1
  99. package/lib/contract/models/Product.js.map +1 -0
  100. package/lib/contract/models/ProductStrength.cjs +1 -1
  101. package/lib/contract/models/ProductStrength.js.map +1 -0
  102. package/lib/contract/models/constants.cjs +1 -1
  103. package/lib/contract/models/constants.js.map +1 -0
  104. package/lib/contract/models/decorators.cjs +1 -1
  105. package/lib/contract/models/decorators.js.map +1 -0
  106. package/lib/contract/models/gtin.cjs +1 -1
  107. package/lib/contract/models/gtin.js.map +1 -0
  108. package/lib/contracts/ContractAdapter.cjs +1 -1
  109. package/lib/contracts/ContractAdapter.js.map +1 -0
  110. package/lib/contracts/ContractContext.cjs +1 -1
  111. package/lib/contracts/ContractContext.js.map +1 -0
  112. package/lib/contracts/ContractPrivateDataAdapter.cjs +1 -1
  113. package/lib/contracts/ContractPrivateDataAdapter.js.map +1 -0
  114. package/lib/contracts/FabricConstruction.cjs +1 -1
  115. package/lib/contracts/FabricConstruction.js.map +1 -0
  116. package/lib/contracts/FabricContractPaginator.cjs +1 -1
  117. package/lib/contracts/FabricContractPaginator.js.map +1 -0
  118. package/lib/contracts/FabricContractRepository.cjs +1 -1
  119. package/lib/contracts/FabricContractRepository.js.map +1 -0
  120. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +1 -1
  121. package/lib/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  122. package/lib/contracts/FabricContractSequence.cjs +1 -1
  123. package/lib/contracts/FabricContractSequence.js.map +1 -0
  124. package/lib/contracts/FabricContractStatement.cjs +1 -1
  125. package/lib/contracts/FabricContractStatement.js.map +1 -0
  126. package/lib/contracts/PrivateSequence.cjs +1 -1
  127. package/lib/contracts/PrivateSequence.js.map +1 -0
  128. package/lib/contracts/crud/crud-contract.cjs +1 -1
  129. package/lib/contracts/crud/crud-contract.js.map +1 -0
  130. package/lib/contracts/crud/index.cjs +1 -1
  131. package/lib/contracts/crud/index.js.map +1 -0
  132. package/lib/contracts/crud/serialized-crud-contract.cjs +1 -1
  133. package/lib/contracts/crud/serialized-crud-contract.js.map +1 -0
  134. package/lib/contracts/erc20/erc20contract.cjs +1 -1
  135. package/lib/contracts/erc20/erc20contract.js.map +1 -0
  136. package/lib/contracts/erc20/index.cjs +1 -1
  137. package/lib/contracts/erc20/index.js.map +1 -0
  138. package/lib/contracts/erc20/models.cjs +1 -1
  139. package/lib/contracts/erc20/models.js.map +1 -0
  140. package/lib/contracts/index.cjs +1 -1
  141. package/lib/contracts/index.js.map +1 -0
  142. package/lib/contracts/logging.cjs +1 -1
  143. package/lib/contracts/logging.js.map +1 -0
  144. package/lib/contracts/overrides.cjs +1 -1
  145. package/lib/contracts/overrides.js.map +1 -0
  146. package/lib/contracts/private-data.cjs +1 -1
  147. package/lib/contracts/private-data.js.map +1 -0
  148. package/lib/contracts/types.cjs +1 -1
  149. package/lib/contracts/types.js.map +1 -0
  150. package/lib/contracts/uuid.cjs +1 -1
  151. package/lib/contracts/uuid.js.map +1 -0
  152. package/lib/esm/bin/cli.js +1 -1
  153. package/lib/esm/bin/cli.js.map +1 -0
  154. package/lib/esm/cli-module.js +1 -1
  155. package/lib/esm/cli-module.js.map +1 -0
  156. package/lib/esm/cli-utils.js +1 -1
  157. package/lib/esm/cli-utils.js.map +1 -0
  158. package/lib/esm/client/FabricClientAdapter.d.ts +1 -2
  159. package/lib/esm/client/FabricClientAdapter.js +3 -39
  160. package/lib/esm/client/FabricClientAdapter.js.map +1 -0
  161. package/lib/esm/client/FabricClientDispatch.js +1 -1
  162. package/lib/esm/client/FabricClientDispatch.js.map +1 -0
  163. package/lib/esm/client/FabricClientPaginator.js +1 -1
  164. package/lib/esm/client/FabricClientPaginator.js.map +1 -0
  165. package/lib/esm/client/FabricClientRepository.js +1 -1
  166. package/lib/esm/client/FabricClientRepository.js.map +1 -0
  167. package/lib/esm/client/FabricClientStatement.js +1 -1
  168. package/lib/esm/client/FabricClientStatement.js.map +1 -0
  169. package/lib/esm/client/collections/generation.js +1 -1
  170. package/lib/esm/client/collections/generation.js.map +1 -0
  171. package/lib/esm/client/collections/index.js +1 -1
  172. package/lib/esm/client/collections/index.js.map +1 -0
  173. package/lib/esm/client/constants.js +2 -3
  174. package/lib/esm/client/constants.js.map +1 -0
  175. package/lib/esm/client/crypto.js +1 -1
  176. package/lib/esm/client/crypto.js.map +1 -0
  177. package/lib/esm/client/erc20/FabricERC20ClientRepository.js +1 -1
  178. package/lib/esm/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  179. package/lib/esm/client/erc20/index.js +1 -1
  180. package/lib/esm/client/erc20/index.js.map +1 -0
  181. package/lib/esm/client/fabric-fs.js +1 -1
  182. package/lib/esm/client/fabric-fs.js.map +1 -0
  183. package/lib/esm/client/fabric-hsm.js +1 -1
  184. package/lib/esm/client/fabric-hsm.js.map +1 -0
  185. package/lib/esm/client/index.js +1 -1
  186. package/lib/esm/client/index.js.map +1 -0
  187. package/lib/esm/client/indexes/generation.js +1 -1
  188. package/lib/esm/client/indexes/generation.js.map +1 -0
  189. package/lib/esm/client/indexes/index.js +1 -1
  190. package/lib/esm/client/indexes/index.js.map +1 -0
  191. package/lib/esm/client/logging.js +1 -1
  192. package/lib/esm/client/logging.js.map +1 -0
  193. package/lib/esm/client/services/FabricEnrollmentService.js +1 -1
  194. package/lib/esm/client/services/FabricEnrollmentService.js.map +1 -0
  195. package/lib/esm/client/services/FabricIdentityService.js +1 -1
  196. package/lib/esm/client/services/FabricIdentityService.js.map +1 -0
  197. package/lib/esm/client/services/RegistrationRequestBuilder.js +1 -1
  198. package/lib/esm/client/services/RegistrationRequestBuilder.js.map +1 -0
  199. package/lib/esm/client/services/constants.js +1 -1
  200. package/lib/esm/client/services/constants.js.map +1 -0
  201. package/lib/esm/client/services/index.js +1 -1
  202. package/lib/esm/client/services/index.js.map +1 -0
  203. package/lib/esm/client/types.js +1 -1
  204. package/lib/esm/client/types.js.map +1 -0
  205. package/lib/esm/client/utils.js +1 -1
  206. package/lib/esm/client/utils.js.map +1 -0
  207. package/lib/esm/contract/Address.js +1 -1
  208. package/lib/esm/contract/Address.js.map +1 -0
  209. package/lib/esm/contract/AddressContract.js +1 -1
  210. package/lib/esm/contract/AddressContract.js.map +1 -0
  211. package/lib/esm/contract/BatchContract.js +1 -1
  212. package/lib/esm/contract/BatchContract.js.map +1 -0
  213. package/lib/esm/contract/OtherProductContract.js +1 -1
  214. package/lib/esm/contract/OtherProductContract.js.map +1 -0
  215. package/lib/esm/contract/OtherProductSharedContract.js +1 -1
  216. package/lib/esm/contract/OtherProductSharedContract.js.map +1 -0
  217. package/lib/esm/contract/Product.js +1 -1
  218. package/lib/esm/contract/Product.js.map +1 -0
  219. package/lib/esm/contract/ProductContract.js +1 -1
  220. package/lib/esm/contract/ProductContract.js.map +1 -0
  221. package/lib/esm/contract/User.js +1 -1
  222. package/lib/esm/contract/User.js.map +1 -0
  223. package/lib/esm/contract/UserContract.js +1 -1
  224. package/lib/esm/contract/UserContract.js.map +1 -0
  225. package/lib/esm/contract/index.js +1 -1
  226. package/lib/esm/contract/index.js.map +1 -0
  227. package/lib/esm/contract/models/Audit.js +1 -1
  228. package/lib/esm/contract/models/Audit.js.map +1 -0
  229. package/lib/esm/contract/models/BaseIdentifiedModel.js +1 -1
  230. package/lib/esm/contract/models/BaseIdentifiedModel.js.map +1 -0
  231. package/lib/esm/contract/models/BaseModel.js +1 -1
  232. package/lib/esm/contract/models/BaseModel.js.map +1 -0
  233. package/lib/esm/contract/models/Batch.js +1 -1
  234. package/lib/esm/contract/models/Batch.js.map +1 -0
  235. package/lib/esm/contract/models/Leaflet.js +1 -1
  236. package/lib/esm/contract/models/Leaflet.js.map +1 -0
  237. package/lib/esm/contract/models/LeafletFile.js +1 -1
  238. package/lib/esm/contract/models/LeafletFile.js.map +1 -0
  239. package/lib/esm/contract/models/Market.js +1 -1
  240. package/lib/esm/contract/models/Market.js.map +1 -0
  241. package/lib/esm/contract/models/OtherProduct.js +1 -1
  242. package/lib/esm/contract/models/OtherProduct.js.map +1 -0
  243. package/lib/esm/contract/models/OtherProductShared.js +1 -1
  244. package/lib/esm/contract/models/OtherProductShared.js.map +1 -0
  245. package/lib/esm/contract/models/Product.js +1 -1
  246. package/lib/esm/contract/models/Product.js.map +1 -0
  247. package/lib/esm/contract/models/ProductStrength.js +1 -1
  248. package/lib/esm/contract/models/ProductStrength.js.map +1 -0
  249. package/lib/esm/contract/models/constants.js +1 -1
  250. package/lib/esm/contract/models/constants.js.map +1 -0
  251. package/lib/esm/contract/models/decorators.js +1 -1
  252. package/lib/esm/contract/models/decorators.js.map +1 -0
  253. package/lib/esm/contract/models/gtin.js +1 -1
  254. package/lib/esm/contract/models/gtin.js.map +1 -0
  255. package/lib/esm/contracts/ContractAdapter.js +1 -1
  256. package/lib/esm/contracts/ContractAdapter.js.map +1 -0
  257. package/lib/esm/contracts/ContractContext.js +1 -1
  258. package/lib/esm/contracts/ContractContext.js.map +1 -0
  259. package/lib/esm/contracts/ContractPrivateDataAdapter.js +1 -1
  260. package/lib/esm/contracts/ContractPrivateDataAdapter.js.map +1 -0
  261. package/lib/esm/contracts/FabricConstruction.js +1 -1
  262. package/lib/esm/contracts/FabricConstruction.js.map +1 -0
  263. package/lib/esm/contracts/FabricContractPaginator.js +1 -1
  264. package/lib/esm/contracts/FabricContractPaginator.js.map +1 -0
  265. package/lib/esm/contracts/FabricContractRepository.js +1 -1
  266. package/lib/esm/contracts/FabricContractRepository.js.map +1 -0
  267. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +1 -1
  268. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  269. package/lib/esm/contracts/FabricContractSequence.js +1 -1
  270. package/lib/esm/contracts/FabricContractSequence.js.map +1 -0
  271. package/lib/esm/contracts/FabricContractStatement.js +1 -1
  272. package/lib/esm/contracts/FabricContractStatement.js.map +1 -0
  273. package/lib/esm/contracts/PrivateSequence.js +1 -1
  274. package/lib/esm/contracts/PrivateSequence.js.map +1 -0
  275. package/lib/esm/contracts/crud/crud-contract.js +1 -1
  276. package/lib/esm/contracts/crud/crud-contract.js.map +1 -0
  277. package/lib/esm/contracts/crud/index.js +1 -1
  278. package/lib/esm/contracts/crud/index.js.map +1 -0
  279. package/lib/esm/contracts/crud/serialized-crud-contract.js +1 -1
  280. package/lib/esm/contracts/crud/serialized-crud-contract.js.map +1 -0
  281. package/lib/esm/contracts/erc20/erc20contract.js +1 -1
  282. package/lib/esm/contracts/erc20/erc20contract.js.map +1 -0
  283. package/lib/esm/contracts/erc20/index.js +1 -1
  284. package/lib/esm/contracts/erc20/index.js.map +1 -0
  285. package/lib/esm/contracts/erc20/models.js +1 -1
  286. package/lib/esm/contracts/erc20/models.js.map +1 -0
  287. package/lib/esm/contracts/index.js +1 -1
  288. package/lib/esm/contracts/index.js.map +1 -0
  289. package/lib/esm/contracts/logging.js +1 -1
  290. package/lib/esm/contracts/logging.js.map +1 -0
  291. package/lib/esm/contracts/overrides.js +1 -1
  292. package/lib/esm/contracts/overrides.js.map +1 -0
  293. package/lib/esm/contracts/private-data.js +1 -1
  294. package/lib/esm/contracts/private-data.js.map +1 -0
  295. package/lib/esm/contracts/types.js +1 -1
  296. package/lib/esm/contracts/types.js.map +1 -0
  297. package/lib/esm/contracts/uuid.js +1 -1
  298. package/lib/esm/contracts/uuid.js.map +1 -0
  299. package/lib/esm/index.js +1 -1
  300. package/lib/esm/index.js.map +1 -0
  301. package/lib/esm/shared/ClientSerializer.js +1 -1
  302. package/lib/esm/shared/ClientSerializer.js.map +1 -0
  303. package/lib/esm/shared/DeterministicSerializer.js +1 -1
  304. package/lib/esm/shared/DeterministicSerializer.js.map +1 -0
  305. package/lib/esm/shared/SimpleDeterministicSerializer.js +1 -1
  306. package/lib/esm/shared/SimpleDeterministicSerializer.js.map +1 -0
  307. package/lib/esm/shared/constants.js +1 -1
  308. package/lib/esm/shared/constants.js.map +1 -0
  309. package/lib/esm/shared/decorators.js +1 -1
  310. package/lib/esm/shared/decorators.js.map +1 -0
  311. package/lib/esm/shared/erc20/erc20-constants.js +1 -1
  312. package/lib/esm/shared/erc20/erc20-constants.js.map +1 -0
  313. package/lib/esm/shared/erc20/index.js +1 -1
  314. package/lib/esm/shared/erc20/index.js.map +1 -0
  315. package/lib/esm/shared/errors.js +1 -1
  316. package/lib/esm/shared/errors.js.map +1 -0
  317. package/lib/esm/shared/events.js +1 -1
  318. package/lib/esm/shared/events.js.map +1 -0
  319. package/lib/esm/shared/fabric-types.js +1 -1
  320. package/lib/esm/shared/fabric-types.js.map +1 -0
  321. package/lib/esm/shared/index.js +1 -1
  322. package/lib/esm/shared/index.js.map +1 -0
  323. package/lib/esm/shared/interfaces/Checkable.js +1 -1
  324. package/lib/esm/shared/interfaces/Checkable.js.map +1 -0
  325. package/lib/esm/shared/interfaces/index.js +1 -1
  326. package/lib/esm/shared/interfaces/index.js.map +1 -0
  327. package/lib/esm/shared/math.js +1 -1
  328. package/lib/esm/shared/math.js.map +1 -0
  329. package/lib/esm/shared/model/FabricBaseModel.js +1 -1
  330. package/lib/esm/shared/model/FabricBaseModel.js.map +1 -0
  331. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js +1 -1
  332. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  333. package/lib/esm/shared/model/Identity.js +1 -1
  334. package/lib/esm/shared/model/Identity.js.map +1 -0
  335. package/lib/esm/shared/model/IdentityCredentials.js +1 -1
  336. package/lib/esm/shared/model/IdentityCredentials.js.map +1 -0
  337. package/lib/esm/shared/model/index.js +1 -1
  338. package/lib/esm/shared/model/index.js.map +1 -0
  339. package/lib/esm/shared/overrides/Model.js +1 -1
  340. package/lib/esm/shared/overrides/Model.js.map +1 -0
  341. package/lib/esm/shared/overrides/index.js +1 -1
  342. package/lib/esm/shared/overrides/index.js.map +1 -0
  343. package/lib/esm/shared/overrides/overrides.js +1 -1
  344. package/lib/esm/shared/overrides/overrides.js.map +1 -0
  345. package/lib/esm/shared/types.js +1 -1
  346. package/lib/esm/shared/types.js.map +1 -0
  347. package/lib/esm/version.d.ts +1 -1
  348. package/lib/esm/version.js +2 -2
  349. package/lib/esm/version.js.map +1 -0
  350. package/lib/index.cjs +1 -1
  351. package/lib/index.js.map +1 -0
  352. package/lib/shared/ClientSerializer.cjs +1 -1
  353. package/lib/shared/ClientSerializer.js.map +1 -0
  354. package/lib/shared/DeterministicSerializer.cjs +1 -1
  355. package/lib/shared/DeterministicSerializer.js.map +1 -0
  356. package/lib/shared/SimpleDeterministicSerializer.cjs +1 -1
  357. package/lib/shared/SimpleDeterministicSerializer.js.map +1 -0
  358. package/lib/shared/constants.cjs +1 -1
  359. package/lib/shared/constants.js.map +1 -0
  360. package/lib/shared/decorators.cjs +1 -1
  361. package/lib/shared/decorators.js.map +1 -0
  362. package/lib/shared/erc20/erc20-constants.cjs +1 -1
  363. package/lib/shared/erc20/erc20-constants.js.map +1 -0
  364. package/lib/shared/erc20/index.cjs +1 -1
  365. package/lib/shared/erc20/index.js.map +1 -0
  366. package/lib/shared/errors.cjs +1 -1
  367. package/lib/shared/errors.js.map +1 -0
  368. package/lib/shared/events.cjs +1 -1
  369. package/lib/shared/events.js.map +1 -0
  370. package/lib/shared/fabric-types.cjs +1 -1
  371. package/lib/shared/fabric-types.js.map +1 -0
  372. package/lib/shared/index.cjs +1 -1
  373. package/lib/shared/index.js.map +1 -0
  374. package/lib/shared/interfaces/Checkable.cjs +1 -1
  375. package/lib/shared/interfaces/Checkable.js.map +1 -0
  376. package/lib/shared/interfaces/index.cjs +1 -1
  377. package/lib/shared/interfaces/index.js.map +1 -0
  378. package/lib/shared/math.cjs +1 -1
  379. package/lib/shared/math.js.map +1 -0
  380. package/lib/shared/model/FabricBaseModel.cjs +1 -1
  381. package/lib/shared/model/FabricBaseModel.js.map +1 -0
  382. package/lib/shared/model/FabricIdentifiedBaseModel.cjs +1 -1
  383. package/lib/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  384. package/lib/shared/model/Identity.cjs +1 -1
  385. package/lib/shared/model/Identity.js.map +1 -0
  386. package/lib/shared/model/IdentityCredentials.cjs +1 -1
  387. package/lib/shared/model/IdentityCredentials.js.map +1 -0
  388. package/lib/shared/model/index.cjs +1 -1
  389. package/lib/shared/model/index.js.map +1 -0
  390. package/lib/shared/overrides/Model.cjs +1 -1
  391. package/lib/shared/overrides/Model.js.map +1 -0
  392. package/lib/shared/overrides/index.cjs +1 -1
  393. package/lib/shared/overrides/index.js.map +1 -0
  394. package/lib/shared/overrides/overrides.cjs +1 -1
  395. package/lib/shared/overrides/overrides.js.map +1 -0
  396. package/lib/shared/types.cjs +1 -1
  397. package/lib/shared/types.js.map +1 -0
  398. package/lib/version.cjs +2 -2
  399. package/lib/version.d.ts +1 -1
  400. package/lib/version.js.map +1 -0
  401. package/package.json +1 -1
@@ -1,2833 +1,2 @@
1
- import { Repository, PreparedStatementKeys, PersistenceKeys, Paginator, BaseModel, pk, column, table, Sequence, Context, oneToOne, Cascade, index, normalizeImport, AuthorizationError, createdAt, updatedAt, createdBy, updatedBy, UnsupportedError, ClientBasedService, DefaultAdapterFlags, Statement, QueryClause, Adapter, QueryError, PagingError, MigrationError, ObserverError, ForbiddenError, ConnectionError, Dispatch } from "@decaf-ts/core";
2
-
3
- import { Model, required, model, JSONSerializer, ModelKeys, stringFormat, minlength, min } from "@decaf-ts/decorator-validation";
4
-
5
- import { OperationKeys, enforceDBDecorators, reduceErrorsToPrint, ValidationError, SerializationError, InternalError, BaseError, ConflictError, NotFoundError, version, DBKeys, readonly, onCreate, onUpdate, afterCreate, afterUpdate, afterDelete, transient, onRead, onDelete, BulkCrudOperationKeys, BadRequestError } from "@decaf-ts/db-decorators";
6
-
7
- import { CouchDBKeys } from "@decaf-ts/for-couchdb";
8
-
9
- import { __decorate, __metadata } from "tslib";
10
-
11
- import { Metadata, description, uses, apply, propMetadata, Decoration, metadata, prop } from "@decaf-ts/decoration";
12
-
13
- import FabricCAServices from "fabric-ca-client";
14
-
15
- import { MiniLogger, isBrowser, LoggedClass, Logging, toPascalCase, toCamelCase, debug, final } from "@decaf-ts/logging";
16
-
17
- import { signers, connect } from "@hyperledger/fabric-gateway";
18
-
19
- import { User } from "fabric-common";
20
-
21
- import crypto$1, { X509Certificate } from "crypto";
22
-
23
- import * as x509 from "@peculiar/x509";
24
-
25
- import { Crypto } from "@peculiar/webcrypto";
26
-
27
- import * as grpc from "@grpc/grpc-js";
28
-
29
- import { Client } from "@grpc/grpc-js";
30
-
31
- import pkcs11 from "pkcs11js";
32
-
33
- import fs from "fs";
34
-
35
- import path from "path";
36
-
37
- import { p256 } from "@noble/curves/nist";
38
-
39
- class FabricClientRepository extends Repository {
40
- constructor(adapter, clazz) {
41
- super(adapter, clazz);
42
- this._overrides = Object.assign({}, super["_overrides"], {
43
- ignoreValidation: true,
44
- ignoreHandlers: true,
45
- allowRawStatements: false,
46
- forcePrepareSimpleQueries: true,
47
- forcePrepareComplexQueries: true,
48
- allowGenerationOverride: false
49
- });
50
- }
51
- async paginateBy(key, order, ref = {
52
- offset: 1,
53
- limit: 10
54
- }, ...args) {
55
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, PreparedStatementKeys.PAGE_BY, true)).for(this.paginateBy);
56
- log.verbose(`paginating ${Model.tableName(this.class)} with page size ${ref.limit}`);
57
- return this.statement(this.paginateBy.name, key, order, {
58
- limit: ref.limit,
59
- offset: ref.offset,
60
- bookmark: ref.bookmark
61
- }, ...ctxArgs);
62
- }
63
- async listBy(key, order, ...args) {
64
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, PreparedStatementKeys.LIST_BY, true)).for(this.listBy);
65
- log.verbose(`listing ${Model.tableName(this.class)} by ${key} ${order}`);
66
- return await this.statement(this.listBy.name, key, order, ...ctxArgs);
67
- }
68
- async findBy(key, value, ...args) {
69
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, PreparedStatementKeys.FIND_BY, true)).for(this.findBy);
70
- log.verbose(`finding all ${Model.tableName(this.class)} with ${key} ${value}`);
71
- return await this.statement(this.findBy.name, key, value, ...ctxArgs);
72
- }
73
- async findOneBy(key, value, ...args) {
74
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, PreparedStatementKeys.FIND_ONE_BY, true)).for(this.findOneBy);
75
- log.verbose(`finding One ${Model.tableName(this.class)} with ${key} ${value}`);
76
- return await this.statement(this.findOneBy.name, key, value, ...ctxArgs);
77
- }
78
- async statement(name, ...args) {
79
- const {log: log, ctx: ctx, ctxArgs: ctxArgs} = (await this.logCtx(args, PersistenceKeys.STATEMENT, true)).for(this.statement);
80
- log.verbose(`Executing prepared statement ${name}`);
81
- const callArgs = ctxArgs.slice(0, -1);
82
- const result = JSON.parse(this.adapter.decode(await this.adapter.evaluateTransaction(ctx, PersistenceKeys.STATEMENT, [ name, JSON.stringify(callArgs) ], undefined, undefined, this.class.name)));
83
- if (Array.isArray(result)) {
84
- return result.map(r => r[CouchDBKeys.TABLE] && r[CouchDBKeys.TABLE] === Model.tableName(this.class) ? new this.class(r) : r);
85
- }
86
- return result[CouchDBKeys.TABLE] && result[CouchDBKeys.TABLE] === Model.tableName(this.class) ? new this.class(result) : Paginator.isSerializedPage(result) ? Object.assign(result, {
87
- data: result.data.map(d => new this.class(d))
88
- }) : result;
89
- }
90
- async create(model, ...args) {
91
- const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.create);
92
- log.debug(`Creating new ${this.class.name} in table ${Model.tableName(this.class)}`);
93
- let {record: record, id: id, transient: transient} = this.adapter.prepare(model, ctx);
94
- record = await this.adapter.create(this.class, id, record, transient, ...ctxArgs);
95
- return this.adapter.revert(record, this.class, id, transient, ctx);
96
- }
97
- async update(model, ...args) {
98
- const {ctxArgs: ctxArgs, log: log, ctx: ctx} = this.logCtx(args, this.update);
99
- let {record: record, id: id, transient: transient} = this.adapter.prepare(model, ctx);
100
- log.debug(`updating ${this.class.name} in table ${Model.tableName(this.class)} with id ${id}`);
101
- record = await this.adapter.update(this.class, id, record, transient, ...ctxArgs);
102
- return this.adapter.revert(record, this.class, id, transient, ctx);
103
- }
104
- async createAllPrefix(models, ...args) {
105
- const {ctx: ctx, ctxArgs: ctxArgs} = (await this.logCtx(args, OperationKeys.CREATE, true)).for(this.createAllPrefix);
106
- const ignoreHandlers = ctx.get("ignoreHandlers");
107
- const ignoreValidate = ctx.get("ignoreValidation");
108
- if (!models.length) return [ models, ...ctxArgs ];
109
- models = await Promise.all(models.map(async m => {
110
- m = new this.class(m);
111
- if (!ignoreHandlers) await enforceDBDecorators(this, ctx, m, OperationKeys.CREATE, OperationKeys.ON);
112
- return m;
113
- }));
114
- if (!ignoreValidate) {
115
- const ignoredProps = ctx.get("ignoredValidationProperties") || [];
116
- const errors = await Promise.all(models.map(m => Promise.resolve(m.hasErrors(...ignoredProps))));
117
- const errorMessages = reduceErrorsToPrint(errors);
118
- if (errorMessages) throw new ValidationError(errorMessages);
119
- }
120
- return [ models, ...ctxArgs ];
121
- }
122
- async createAll(models, ...args) {
123
- if (!models.length) return models;
124
- const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.createAll);
125
- log.debug(`Creating ${models.length} new ${this.class.name} in table ${Model.tableName(this.class)}`);
126
- const prepared = models.map(m => this.adapter.prepare(m, ctx));
127
- const ids = prepared.map(p => p.id);
128
- let records = prepared.map(p => p.record);
129
- const transient = prepared.map(p => p.transient);
130
- records = await this.adapter.createAll(this.class, ids, records, transient, ...ctxArgs);
131
- return records.map((r, i) => this.adapter.revert(r, this.class, ids[i], ctx.get("rebuildWithTransient") ? prepared[i].transient : undefined, ctx));
132
- }
133
- async updateAll(models, ...args) {
134
- const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateAll);
135
- log.debug(`Updating ${models.length} new ${this.class.name} in table ${Model.tableName(this.class)}`);
136
- const records = models.map(m => this.adapter.prepare(m, ctx));
137
- const updated = await this.adapter.updateAll(this.class, records.map(r => r.id), records.map(r => r.record), records.map(r => r.transient), ...ctxArgs);
138
- return updated.map((u, i) => this.adapter.revert(u, this.class, records[i].id, ctx.get("rebuildWithTransient") ? records[i].transient : undefined, ctx));
139
- }
140
- }
141
-
142
- let ERC20Token = class ERC20Token extends BaseModel {
143
- constructor(m) {
144
- super(m);
145
- }
146
- };
147
-
148
- __decorate([ pk({
149
- type: String
150
- }), __metadata("design:type", String) ], ERC20Token.prototype, "name", void 0);
151
-
152
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "owner", void 0);
153
-
154
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "symbol", void 0);
155
-
156
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Token.prototype, "decimals", void 0);
157
-
158
- ERC20Token = __decorate([ table("erc20_tokens"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Token);
159
-
160
- let ERC20Wallet = class ERC20Wallet extends BaseModel {
161
- constructor(m) {
162
- super(m);
163
- }
164
- };
165
-
166
- __decorate([ pk({
167
- type: String
168
- }), __metadata("design:type", String) ], ERC20Wallet.prototype, "id", void 0);
169
-
170
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Wallet.prototype, "token", void 0);
171
-
172
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Wallet.prototype, "balance", void 0);
173
-
174
- __decorate([ column(), __metadata("design:type", String) ], ERC20Wallet.prototype, "captive", void 0);
175
-
176
- ERC20Wallet = __decorate([ table("erc20_wallets"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Wallet);
177
-
178
- let Allowance = class Allowance extends BaseModel {
179
- constructor(m) {
180
- super(m);
181
- }
182
- };
183
-
184
- __decorate([ pk({
185
- type: String
186
- }), column(), required(), __metadata("design:type", String) ], Allowance.prototype, "owner", void 0);
187
-
188
- __decorate([ column(), required(), __metadata("design:type", String) ], Allowance.prototype, "spender", void 0);
189
-
190
- __decorate([ column(), required(), __metadata("design:type", Number) ], Allowance.prototype, "value", void 0);
191
-
192
- Allowance = __decorate([ table("erc20_allowances"), model(), __metadata("design:paramtypes", [ Object ]) ], Allowance);
193
-
194
- class ClientSerializer extends JSONSerializer {
195
- constructor() {
196
- super();
197
- }
198
- preSerialize(model, modelName) {
199
- const toSerialize = Object.assign({}, model);
200
- let metadata = Metadata.modelName(model.constructor);
201
- if (!metadata || metadata === "Object") if (modelName) metadata = modelName; else throw new SerializationError(`Could not find metadata for ${model.constructor.name}`);
202
- toSerialize[ModelKeys.ANCHOR] = metadata;
203
- return toSerialize;
204
- }
205
- deserialize(str) {
206
- const deserialization = JSON.parse(str);
207
- const className = deserialization[ModelKeys.ANCHOR];
208
- if (!className) throw new Error("Could not find class reference in serialized model");
209
- const model = Model.build(deserialization, className);
210
- return model;
211
- }
212
- serialize(model, modelName) {
213
- return JSON.stringify(this.preSerialize(model, modelName));
214
- }
215
- }
216
-
217
- class FabricERC20ClientRepository extends FabricClientRepository {
218
- static {
219
- this.serializer = new ClientSerializer;
220
- }
221
- static {
222
- this.decoder = new TextDecoder("utf8");
223
- }
224
- async updateObservers(table, event, id, ...args) {
225
- if (!this.observerHandler) throw new InternalError("ObserverHandler not initialized. Did you register any observables?");
226
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateObservers);
227
- log.verbose(`Updating ${this.observerHandler.count()} observers for ${this}`);
228
- table = typeof table === "string" ? Model.get(table) : table;
229
- let parsedId;
230
- if (id === undefined) {
231
- parsedId = undefined;
232
- } else if (Array.isArray(id)) {
233
- parsedId = id.map(i => Sequence.parseValue(Model.sequenceFor(table).type, i));
234
- } else {
235
- parsedId = Sequence.parseValue(Model.sequenceFor(table).type, id);
236
- }
237
- await this.observerHandler.updateObservers(table, event, parsedId, ...ctxArgs);
238
- }
239
- decode(data) {
240
- return FabricERC20ClientRepository.decoder.decode(data);
241
- }
242
- constructor(adapter) {
243
- super(adapter, ERC20Wallet);
244
- this.serializer = FabricERC20ClientRepository.serializer;
245
- }
246
- async tokenName(...args) {
247
- const {ctx: ctx} = (await this.logCtx(args, "tokenName", true)).for(this.tokenName);
248
- const name = await this.adapter.evaluateTransaction(ctx, "TokenName");
249
- return this.decode(name);
250
- }
251
- async symbol(...args) {
252
- const {ctx: ctx} = (await this.logCtx(args, "symbol", true)).for(this.symbol);
253
- const symbol = await this.adapter.evaluateTransaction(ctx, "Symbol");
254
- return this.decode(symbol);
255
- }
256
- async decimals(...args) {
257
- const {ctx: ctx} = (await this.logCtx(args, "decimals", true)).for(this.decimals);
258
- const decimals = await this.adapter.evaluateTransaction(ctx, "Decimals");
259
- return Number(this.decode(decimals));
260
- }
261
- async totalSupply(...args) {
262
- const {ctx: ctx} = (await this.logCtx(args, "totalSupply", true)).for(this.totalSupply);
263
- const total = await this.adapter.evaluateTransaction(ctx, "TotalSupply");
264
- return Number(this.decode(total));
265
- }
266
- async balanceOf(owner, ...args) {
267
- const {ctx: ctx} = (await this.logCtx(args, "balance", true)).for(this.balanceOf);
268
- const balance = await this.adapter.evaluateTransaction(ctx, "BalanceOf", [ owner ]);
269
- return Number(this.decode(balance));
270
- }
271
- async transfer(to, value, ...args) {
272
- const {ctx: ctx} = (await this.logCtx(args, "transfer", true)).for(this.transfer);
273
- const transferred = await this.adapter.submitTransaction(ctx, "Transfer", [ to, value.toString() ]);
274
- return this.decode(transferred) === "true" ? true : false;
275
- }
276
- async transferFrom(from, to, value) {
277
- const contextArgs = await Context.args("transferFrom", this.class, [], this.adapter, this._overrides || {});
278
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.transferFrom);
279
- const transferred = await this.adapter.submitTransaction(ctx, "TransferFrom", [ from, to, value.toString() ]);
280
- return this.decode(transferred) === "true" ? true : false;
281
- }
282
- async approve(spender, value) {
283
- const contextArgs = await Context.args("approve", this.class, [], this.adapter, this._overrides || {});
284
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.approve);
285
- const approved = await this.adapter.submitTransaction(ctx, "Approve", [ spender, value.toString() ]);
286
- return this.decode(approved) === "true" ? true : false;
287
- }
288
- async allowance(owner, spender) {
289
- const contextArgs = await Context.args("allowance", this.class, [], this.adapter, this._overrides || {});
290
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.allowance);
291
- const allowance = await this.adapter.submitTransaction(ctx, "Allowance", [ owner, spender ]);
292
- return Number(this.decode(allowance));
293
- }
294
- async initialize(token) {
295
- const contextArgs = await Context.args("initialize", this.class, [], this.adapter, this._overrides || {});
296
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.initialize);
297
- const initiliazed = await this.adapter.submitTransaction(ctx, "Initialize", [ FabricERC20ClientRepository.serializer.serialize(token) ]);
298
- return this.decode(initiliazed) === "true" ? true : false;
299
- }
300
- async checkInitialized() {
301
- const contextArgs = await Context.args("checkInitialized", this.class, [], this.adapter, this._overrides || {});
302
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.checkInitialized);
303
- await this.adapter.evaluateTransaction(ctx, "CheckInitialized");
304
- }
305
- async mint(amount) {
306
- const contextArgs = await Context.args("mint", this.class, [], this.adapter, this._overrides || {});
307
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.mint);
308
- await this.adapter.submitTransaction(ctx, "Mint", [ amount.toString() ]);
309
- }
310
- async burn(amount) {
311
- const contextArgs = await Context.args("burn", this.class, [], this.adapter, this._overrides || {});
312
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.burn);
313
- await this.adapter.submitTransaction(ctx, "Burn", [ amount.toString() ]);
314
- }
315
- async burnFrom(account, amount) {
316
- const contextArgs = await Context.args("burnFrom", this.class, [], this.adapter, this._overrides || {});
317
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.burnFrom);
318
- await this.adapter.submitTransaction(ctx, "BurnFrom", [ account, amount.toString() ]);
319
- }
320
- async clientAccountBalance() {
321
- const contextArgs = await Context.args("accountBalance", this.class, [], this.adapter, this._overrides || {});
322
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.clientAccountBalance);
323
- const serializedAccountBalance = await this.adapter.evaluateTransaction(ctx, "ClientAccountBalance");
324
- return Number(this.decode(serializedAccountBalance));
325
- }
326
- async clientAccountID() {
327
- const contextArgs = await Context.args("accountId", this.class, [], this.adapter, this._overrides || {});
328
- const {ctx: ctx} = this.logCtx(contextArgs.args, this.clientAccountID);
329
- const clientAccountID = await this.adapter.evaluateTransaction(ctx, "ClientAccountID");
330
- return this.decode(clientAccountID);
331
- }
332
- }
333
-
334
- function getIndexReference(name, direction, compositions) {
335
- return [ ...name.map(n => n === CouchDBKeys.TABLE ? "table" : n), ...compositions || [], ...direction ? [ direction ] : [], "index" ].join(Metadata.splitter);
336
- }
337
-
338
- function addIndex(accum, fields, direction, compositions) {
339
- const tableField = fields.pop();
340
- if (tableField && tableField !== CouchDBKeys.TABLE) {
341
- fields.push(tableField);
342
- } else if (tableField === CouchDBKeys.TABLE) {
343
- fields.unshift(tableField);
344
- }
345
- const name = getIndexReference(fields, direction, compositions);
346
- let f = [ ...fields, ...compositions || [] ];
347
- if (direction) f = f.reduce((accum, el) => {
348
- const entry = {};
349
- entry[el] = direction;
350
- accum.push(entry);
351
- return accum;
352
- }, []);
353
- const index = {
354
- index: {
355
- fields: f
356
- },
357
- name: name,
358
- ddoc: name,
359
- type: "json"
360
- };
361
- accum[name] = index;
362
- }
363
-
364
- function generateModelIndexes(m, accum) {
365
- const tableName = getIndexReference([ CouchDBKeys.TABLE ]);
366
- const indexes = accum || {};
367
- indexes[tableName] = {
368
- index: {
369
- fields: [ CouchDBKeys.TABLE ]
370
- },
371
- name: tableName,
372
- ddoc: tableName,
373
- type: "json"
374
- };
375
- const result = {};
376
- const modelIndexes = Model.indexes(m);
377
- for (const prop of Object.keys(modelIndexes)) {
378
- for (const [, dec] of Object.entries(modelIndexes[prop])) {
379
- const directions = dec.directions;
380
- const compositions = dec.compositions;
381
- const fields = [ prop, CouchDBKeys.TABLE ];
382
- addIndex(result, fields);
383
- if (compositions && compositions.length) addIndex(result, fields, undefined, compositions);
384
- if (directions && directions.length) {
385
- directions.forEach(d => {
386
- addIndex(result, fields, d);
387
- if (compositions && compositions.length) addIndex(result, fields, d, compositions);
388
- });
389
- }
390
- }
391
- }
392
- Object.entries(result).forEach(([key, value]) => {
393
- indexes[key] = value;
394
- });
395
- return Object.values(result);
396
- }
397
-
398
- function readModelFile(file) {
399
- const path = require("path");
400
- const exports = require(path.join(process.cwd(), file.parentPath, file.name));
401
- const values = Object.values(exports).filter(e => {
402
- try {
403
- const m = new e;
404
- return m instanceof Model;
405
- } catch (e) {
406
- return false;
407
- }
408
- });
409
- return values;
410
- }
411
-
412
- async function readModelFolders(...folders) {
413
- const fs = require("fs");
414
- const result = [];
415
- for (const folder of folders) {
416
- const files = fs.readdirSync(folder, {
417
- withFileTypes: true,
418
- recursive: true
419
- }).filter(f => f.isFile() && f.name.endsWith("js"));
420
- for (const file of files) {
421
- result.push(...readModelFile(file));
422
- }
423
- }
424
- return result;
425
- }
426
-
427
- function writeIndexes(indexes, p = process.cwd(), collection) {
428
- const fs = require("fs");
429
- const path = require("path");
430
- function ensureDirectoryExistence(filePath) {
431
- const dirname = path.dirname(filePath);
432
- if (fs.existsSync(dirname)) {
433
- return true;
434
- }
435
- ensureDirectoryExistence(dirname);
436
- fs.mkdirSync(dirname);
437
- }
438
- indexes.forEach(index => {
439
- const file = path.resolve(path.join(p, `./META-INF/statedb/couchdb/${collection ? `collections/${collection}/` : ""}indexes/${index.name}.json`));
440
- ensureDirectoryExistence(file);
441
- fs.writeFileSync(file, JSON.stringify(index, undefined, 2));
442
- });
443
- }
444
-
445
- let IdentityCredentials = class IdentityCredentials extends BaseModel {
446
- constructor(arg) {
447
- super(arg);
448
- }
449
- };
450
-
451
- __decorate([ description("Unique identifier of the credentials record"), column(), pk(), __metadata("design:type", String) ], IdentityCredentials.prototype, "id", void 0);
452
-
453
- __decorate([ description("PEM-encoded X.509 certificate for the identity"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "certificate", void 0);
454
-
455
- __decorate([ description("PEM-encoded root or intermediate certificate"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "rootCertificate", void 0);
456
-
457
- __decorate([ description("PEM-encoded private key"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "privateKey", void 0);
458
-
459
- IdentityCredentials = __decorate([ model(), __metadata("design:paramtypes", [ Object ]) ], IdentityCredentials);
460
-
461
- var FabricModelKeys;
462
-
463
- (function(FabricModelKeys) {
464
- FabricModelKeys["PRIVATE"] = "private";
465
- FabricModelKeys["SHARED"] = "shared";
466
- FabricModelKeys["FABRIC"] = "fabric";
467
- FabricModelKeys["OWNED_BY"] = "owned-by";
468
- FabricModelKeys["TRANSACTION_ID"] = "transaction-id";
469
- FabricModelKeys["MIRROR"] = "mirror";
470
- })(FabricModelKeys || (FabricModelKeys = {}));
471
-
472
- var IdentityType;
473
-
474
- (function(IdentityType) {
475
- IdentityType["X509"] = "X.509";
476
- })(IdentityType || (IdentityType = {}));
477
-
478
- const FabricFlavour = "hlf-fabric";
479
-
480
- let Identity = class Identity extends BaseModel {
481
- constructor(arg) {
482
- super(arg);
483
- this.type = IdentityType.X509;
484
- }
485
- };
486
-
487
- __decorate([ description("Unique identifier of the identity"), pk(), __metadata("design:type", String) ], Identity.prototype, "id", void 0);
488
-
489
- __decorate([ oneToOne(IdentityCredentials, {
490
- update: Cascade.CASCADE,
491
- delete: Cascade.CASCADE
492
- }), __metadata("design:type", IdentityCredentials) ], Identity.prototype, "credentials", void 0);
493
-
494
- __decorate([ column(), required(), index(), __metadata("design:type", String) ], Identity.prototype, "mspId", void 0);
495
-
496
- __decorate([ column(), required(), __metadata("design:type", String) ], Identity.prototype, "type", void 0);
497
-
498
- Identity = __decorate([ model(), __metadata("design:paramtypes", [ Object ]) ], Identity);
499
-
500
- class CoreUtils {
501
- static {
502
- this.logger = new MiniLogger(CoreUtils.name);
503
- }
504
- constructor() {}
505
- static async contentOfLoadFile(contentOrPath, fileReader) {
506
- if (contentOrPath instanceof Uint8Array) return contentOrPath;
507
- if (contentOrPath.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) return contentOrPath;
508
- return await fileReader(contentOrPath);
509
- }
510
- static async readFile(contentOrPath) {
511
- if (typeof contentOrPath !== "string") return contentOrPath;
512
- const fileReader = async path => {
513
- const {promises: promises} = await normalizeImport(import("fs"));
514
- return await promises.readFile(path);
515
- };
516
- return await fileReader(contentOrPath);
517
- }
518
- static async getCAUser(userName, privateKey, certificate, mspId, options) {
519
- this.logger.debug(stringFormat("Creating CA {0} user {1} with certificate {2}", mspId, userName, certificate));
520
- const user = new User(userName);
521
- const config = options?.hsm ? {
522
- software: false,
523
- lib: options.hsm.library,
524
- slot: options.hsm.slot,
525
- label: options.hsm.tokenLabel,
526
- pin: String(options.hsm.pin)
527
- } : undefined;
528
- const cryptoSuite = this.getCryptoSuite(config);
529
- user.setCryptoSuite(cryptoSuite);
530
- const enrollmentKey = options?.hsm ? await this.getHSMEnrollmentKey(cryptoSuite, certificate, options.hsm) : this.getSoftwareEnrollmentKey(cryptoSuite, privateKey);
531
- await user.setEnrollment(enrollmentKey, certificate, mspId);
532
- return user;
533
- }
534
- static getCryptoSuite(options) {
535
- if (!options) return User.newCryptoSuite();
536
- if (CoreUtils.cryptoSuite) return CoreUtils.cryptoSuite;
537
- CoreUtils.cryptoSuite = User.newCryptoSuite(options);
538
- return CoreUtils.cryptoSuite;
539
- }
540
- static getSoftwareEnrollmentKey(cryptoSuite, privateKey) {
541
- if (!privateKey) {
542
- throw new Error("Private key must be provided when HSM configuration is not supplied");
543
- }
544
- return cryptoSuite.createKeyFromRaw(privateKey);
545
- }
546
- static async getHSMEnrollmentKey(cryptoSuite, certificate, hsm) {
547
- const ski = hsm.keyIdHex && hsm.keyIdHex.trim().length > 0 ? Buffer.from(hsm.keyIdHex, "hex") : await this.getCertificateSKI(certificate);
548
- const key = await cryptoSuite.getKey(ski);
549
- if (!key || typeof key.isPrivate === "function" && !key.isPrivate()) {
550
- throw new Error("Unable to resolve private key from HSM");
551
- }
552
- return key;
553
- }
554
- static async getCertificateSKI(certificate) {
555
- const x509 = new X509Certificate(certificate);
556
- const jwk = x509.publicKey.export({
557
- format: "jwk"
558
- });
559
- const prefix = Buffer.from([ 4 ]);
560
- const x = Buffer.from(jwk.x || "", "base64url");
561
- const y = Buffer.from(jwk.y || "", "base64url");
562
- return crypto$1.createHash("sha256").update(Buffer.concat([ prefix, x, y ])).digest();
563
- }
564
- static async getIdentity(mspId, certDirectoryPath) {
565
- const identityFileReader = async path => {
566
- const {promises: promises} = await normalizeImport(import("fs"));
567
- const certPath = await this.getFirstDirFileName(path);
568
- const credentials = await promises.readFile(certPath);
569
- return credentials;
570
- };
571
- const credentials = await this.contentOfLoadFile(certDirectoryPath, identityFileReader);
572
- return {
573
- mspId: mspId,
574
- credentials: credentials
575
- };
576
- }
577
- static async getFirstDirFileName(dirPath) {
578
- const {promises: promises} = await normalizeImport(import("fs"));
579
- const {join: join} = await normalizeImport(import("path"));
580
- const files = await promises.readdir(dirPath);
581
- return join(dirPath, files[0]);
582
- }
583
- static async getFirstDirFileNameContent(dirPath) {
584
- const {promises: promises} = await normalizeImport(import("fs"));
585
- const {join: join} = await normalizeImport(import("path"));
586
- const files = await promises.readdir(dirPath);
587
- return (await promises.readFile(join(dirPath, files[0]))).toString();
588
- }
589
- static async getFileContent(filePath) {
590
- const {promises: promises} = await normalizeImport(import("fs"));
591
- return (await promises.readFile(filePath)).toString();
592
- }
593
- static async getSigner(keyDirectoryPath) {
594
- const signerFileReader = async path => {
595
- const {promises: promises} = await normalizeImport(import("fs"));
596
- const keyPath = await this.getFirstDirFileName(path);
597
- return await promises.readFile(keyPath);
598
- };
599
- const privateKeyPem = await this.contentOfLoadFile(keyDirectoryPath, signerFileReader);
600
- const privateKey = await this.extractPrivateKey(privateKeyPem);
601
- const keys = Object.getOwnPropertySymbols(privateKey);
602
- const k = privateKey[keys[0]];
603
- return signers.newPrivateKeySigner(k);
604
- }
605
- static async extractPrivateKey(pem) {
606
- const libName = "crypto";
607
- let subtle;
608
- if (globalThis.window && globalThis.window.Crypto) {
609
- subtle = globalThis.Crypto.subtle;
610
- } else {
611
- const lib = await normalizeImport(import(libName));
612
- subtle = lib.subtle || lib.webcrypto.subtle;
613
- }
614
- if (!subtle) throw new Error("Could not load SubtleCrypto module");
615
- function str2ab(str) {
616
- const buf = new ArrayBuffer(str.length);
617
- const bufView = new Uint8Array(buf);
618
- for (let i = 0, strLen = str.length; i < strLen; i++) {
619
- bufView[i] = str.charCodeAt(i);
620
- }
621
- return buf;
622
- }
623
- const str = pem.toString("utf8").replace("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "").replace("-----END PRIVATE KEY-----", "");
624
- const decoded = Buffer.from(str, "base64").toString("binary");
625
- const binaryDer = str2ab(decoded);
626
- const key = await subtle.importKey("pkcs8", binaryDer, {
627
- name: "ECDSA",
628
- namedCurve: "P-256"
629
- }, true, [ "sign" ]);
630
- return key;
631
- }
632
- }
633
-
634
- const crypto = new Crypto;
635
-
636
- x509.cryptoProvider.set(crypto);
637
-
638
- var BASE_ALPHABET;
639
-
640
- (function(BASE_ALPHABET) {
641
- BASE_ALPHABET["BASE2"] = "01";
642
- BASE_ALPHABET["BASE8"] = "01234567";
643
- BASE_ALPHABET["BASE11"] = "0123456789a";
644
- BASE_ALPHABET["BASE16"] = "0123456789abcdef";
645
- BASE_ALPHABET["BASE32"] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
646
- BASE_ALPHABET["BASE32_Z"] = "ybndrfg8ejkmcpqxot1uwisza345h769";
647
- BASE_ALPHABET["BASE36"] = "0123456789abcdefghijklmnopqrstuvwxyz";
648
- BASE_ALPHABET["BASE58"] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
649
- BASE_ALPHABET["BASE62"] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
650
- BASE_ALPHABET["BASE64"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
651
- BASE_ALPHABET["BASE67"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~";
652
- })(BASE_ALPHABET || (BASE_ALPHABET = {}));
653
-
654
- var CRYPTO;
655
-
656
- (function(CRYPTO) {
657
- CRYPTO["HASH"] = "SHA-256";
658
- CRYPTO[CRYPTO["ITERATIONS"] = 1e3] = "ITERATIONS";
659
- CRYPTO[CRYPTO["KEYLENGTH"] = 48] = "KEYLENGTH";
660
- CRYPTO[CRYPTO["DERIVED_IV_LENGTH"] = 16] = "DERIVED_IV_LENGTH";
661
- CRYPTO[CRYPTO["DERIVED_KEY_LENGTH"] = 32] = "DERIVED_KEY_LENGTH";
662
- CRYPTO["ALGORYTHM"] = "AES-GCM";
663
- CRYPTO["KEY_ALGORYTHM"] = "PBKDF2";
664
- })(CRYPTO || (CRYPTO = {}));
665
-
666
- class BaseEncoder {
667
- constructor(alphabet) {
668
- this.alphabet = alphabet;
669
- this.baseMap = new Uint8Array(256);
670
- if (this.alphabet.length >= 255) throw new Error("Alphabet too long");
671
- for (let j = 0; j < this.baseMap.length; j++) this.baseMap[j] = 255;
672
- for (let i = 0; i < alphabet.length; i++) {
673
- const x = alphabet.charAt(i);
674
- const xc = x.charCodeAt(0);
675
- if (this.baseMap[xc] !== 255) throw new Error(x + " is ambiguous");
676
- this.baseMap[xc] = i;
677
- }
678
- this.base = this.alphabet.length;
679
- this.leader = this.alphabet.charAt(0);
680
- this.factor = Math.log(this.base) / Math.log(256);
681
- this.iFactor = Math.log(256) / Math.log(this.base);
682
- }
683
- encode(source) {
684
- if (typeof source === "string") {
685
- source = Buffer.from(source);
686
- } else if (ArrayBuffer.isView(source)) {
687
- source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
688
- } else if (Array.isArray(source)) {
689
- source = Uint8Array.from(source);
690
- }
691
- if (source.length === 0) return "";
692
- let zeroes = 0;
693
- let length = 0;
694
- let pbegin = 0;
695
- const pend = source.length;
696
- while (pbegin !== pend && source[pbegin] === 0) {
697
- pbegin++;
698
- zeroes++;
699
- }
700
- const size = (pend - pbegin) * this.iFactor + 1 >>> 0;
701
- const b58 = new Uint8Array(size);
702
- while (pbegin !== pend) {
703
- let carry = source[pbegin];
704
- let i = 0;
705
- for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
706
- carry += 256 * b58[it1] >>> 0;
707
- b58[it1] = carry % this.base >>> 0;
708
- carry = carry / this.base >>> 0;
709
- }
710
- if (carry !== 0) throw new Error("Non-zero carry");
711
- length = i;
712
- pbegin++;
713
- }
714
- let it2 = size - length;
715
- while (it2 !== size && b58[it2] === 0) it2++;
716
- let str = this.leader.repeat(zeroes);
717
- for (;it2 < size; ++it2) {
718
- str += this.alphabet.charAt(b58[it2]);
719
- }
720
- return str;
721
- }
722
- decodeUnsafe(source) {
723
- if (source.length === 0) return new Uint8Array(0);
724
- let psz = 0;
725
- let zeroes = 0;
726
- let length = 0;
727
- while (source[psz] === this.leader) {
728
- zeroes++;
729
- psz++;
730
- }
731
- const size = (source.length - psz) * this.factor + 1 >>> 0;
732
- const b256 = new Uint8Array(size);
733
- while (source[psz]) {
734
- let carry = this.baseMap[source.charCodeAt(psz)];
735
- if (carry === 255) return;
736
- let i = 0;
737
- for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
738
- carry += this.base * b256[it3] >>> 0;
739
- b256[it3] = carry % 256 >>> 0;
740
- carry = carry / 256 >>> 0;
741
- }
742
- if (carry !== 0) throw new Error("Non-zero carry");
743
- length = i;
744
- psz++;
745
- }
746
- let it4 = size - length;
747
- while (it4 !== size && b256[it4] === 0) it4++;
748
- const vch = new Uint8Array(zeroes + (size - it4));
749
- let j = zeroes;
750
- while (it4 !== size) vch[j++] = b256[it4++];
751
- return vch;
752
- }
753
- decode(source) {
754
- const buffer = this.decodeUnsafe(source);
755
- if (buffer) return buffer;
756
- throw new Error("Non-base" + this.base + " character");
757
- }
758
- }
759
-
760
- class CryptoUtils {
761
- static {
762
- this.b58encoder = new BaseEncoder(BASE_ALPHABET.BASE58);
763
- }
764
- static {
765
- this.logger = new MiniLogger(CryptoUtils.name);
766
- }
767
- constructor() {}
768
- static fabricIdFromCertificate(certificate) {
769
- this.logger.debug(stringFormat("Parsing certificate: {0}", certificate));
770
- const cert = new x509.X509Certificate(certificate);
771
- const {subject: subject, issuer: issuer} = cert;
772
- this.logger.debug(stringFormat("Certificate parsed with subject {0} and issuer {1}", subject, issuer));
773
- return `x509::/${subject.replaceAll(", ", "/")}::/${issuer.replaceAll(", ", "/")}`;
774
- }
775
- static encode(str) {
776
- return this.b58encoder.encode(str);
777
- }
778
- static decode(str) {
779
- const decoded = this.b58encoder.decode(str);
780
- const result = (new TextDecoder).decode(decoded);
781
- return result;
782
- }
783
- static stringToArrayBuffer(str) {
784
- const buf = new ArrayBuffer(str.length);
785
- const bufView = new Uint8Array(buf);
786
- for (let i = 0, strLen = str.length; i < strLen; i++) {
787
- bufView[i] = str.charCodeAt(i);
788
- }
789
- return buf;
790
- }
791
- static async extractKey(type, pem, usages) {
792
- const subtle = crypto.subtle;
793
- const str = pem.toString("utf8").replace(new RegExp(`-----BEGIN (${type.toUpperCase()} KEY|CERTIFICATE)-----`), "").replaceAll("\n", "").replace(new RegExp(`-----END (${type.toUpperCase()} KEY|CERTIFICATE)-----`), "");
794
- const decoded = Buffer.from(str, "base64").toString("binary");
795
- const binaryDer = this.stringToArrayBuffer(decoded);
796
- const key = await subtle.importKey("pkcs8", binaryDer, {
797
- name: "ECDSA",
798
- namedCurve: "P-256"
799
- }, true, usages ? usages : [ "sign" ]);
800
- return key;
801
- }
802
- static async extractPrivateKey(pem, usages) {
803
- return this.extractKey("private", pem, usages);
804
- }
805
- static async extractPublicKey(pem, usages) {
806
- return this.extractKey("public", pem, usages);
807
- }
808
- static async sign(privateKey, data) {
809
- const key = await this.extractPrivateKey(privateKey);
810
- const buff = await crypto.subtle.sign({
811
- name: "ECDSA",
812
- hash: "SHA-256"
813
- }, key, data);
814
- return Array.from(new Uint8Array(buff)).map(b => b.toString(16).padStart(2, "0")).join("");
815
- }
816
- static async verify(certificate, signature, data) {
817
- const cert = new x509.X509Certificate(certificate);
818
- const key = await cert.publicKey.export();
819
- signature = typeof signature === "string" ? Buffer.from(signature, "hex") : signature;
820
- data = typeof data === "string" ? Buffer.from(data) : data;
821
- return crypto.subtle.verify({
822
- name: "ECDSA",
823
- hash: "SHA-256"
824
- }, key, signature, data);
825
- }
826
- static async encrypt(certificate, data) {
827
- const cert = new x509.X509Certificate(certificate);
828
- const key = await cert.publicKey.export();
829
- data = typeof data === "string" ? Buffer.from(data) : data;
830
- const buff = await this.getSubtleCrypto().encrypt({
831
- name: "ECDSA"
832
- }, key, data);
833
- return Array.from(new Uint8Array(buff)).map(b => b.toString(16).padStart(2, "0")).join("");
834
- }
835
- static getSubtleCrypto() {
836
- return isBrowser() ? globalThis.window.crypto.subtle : crypto.subtle;
837
- }
838
- static async decrypt(privateKey, data) {
839
- const key = await this.extractPrivateKey(privateKey);
840
- data = typeof data === "string" ? Buffer.from(data, "hex") : data;
841
- return this.getSubtleCrypto().decrypt({
842
- name: "ECDSA"
843
- }, key, data);
844
- }
845
- static async getMaster(data) {
846
- const textEncoder = new TextEncoder;
847
- if (data === undefined) {
848
- const genGenesis = crypto.randomUUID();
849
- data = textEncoder.encode(genGenesis).buffer;
850
- }
851
- const importedKey = await this.getSubtleCrypto().importKey("raw", data, CRYPTO.KEY_ALGORYTHM, false, [ "deriveBits" ]);
852
- return {
853
- key: importedKey,
854
- iv: data
855
- };
856
- }
857
- static async getDerivationKey(salt, key) {
858
- const textEncoder = new TextEncoder;
859
- const saltBuffer = textEncoder.encode(salt);
860
- const saltHashed = await this.getSubtleCrypto().digest("SHA-256", saltBuffer);
861
- const params = {
862
- name: CRYPTO.KEY_ALGORYTHM,
863
- hash: CRYPTO.HASH,
864
- salt: saltHashed,
865
- iterations: CRYPTO.ITERATIONS
866
- };
867
- const derivation = await this.getSubtleCrypto().deriveBits(params, key, CRYPTO.KEYLENGTH * 8);
868
- return this.getKey(derivation);
869
- }
870
- static async getKey(derivation) {
871
- const ivlen = 16;
872
- const keylen = 32;
873
- const derivedKey = derivation.slice(0, keylen);
874
- const iv = derivation.slice(keylen);
875
- const importedEncryptionKey = await this.getSubtleCrypto().importKey("raw", derivedKey, {
876
- name: CRYPTO.ALGORYTHM
877
- }, false, [ "encrypt", "decrypt" ]);
878
- return {
879
- key: importedEncryptionKey,
880
- iv: iv
881
- };
882
- }
883
- static async encryptPin(text, keyObject) {
884
- const textEncoder = new TextEncoder;
885
- const textBuffer = textEncoder.encode(text);
886
- const encryptedText = await this.getSubtleCrypto().encrypt({
887
- name: CRYPTO.ALGORYTHM,
888
- iv: keyObject.iv
889
- }, keyObject.key, textBuffer);
890
- return encryptedText;
891
- }
892
- static async decryptPin(encryptedText, keyObject) {
893
- const textDecoder = new TextDecoder;
894
- const decryptedText = await this.getSubtleCrypto().decrypt({
895
- name: CRYPTO.ALGORYTHM,
896
- iv: keyObject.iv
897
- }, keyObject.key, encryptedText);
898
- return textDecoder.decode(decryptedText);
899
- }
900
- }
901
-
902
- class OverflowError extends InternalError {
903
- constructor(msg) {
904
- super(msg, OverflowError.name);
905
- }
906
- }
907
-
908
- class BalanceError extends InternalError {
909
- constructor(msg) {
910
- super(msg, BalanceError.name);
911
- }
912
- }
913
-
914
- class AllowanceError extends InternalError {
915
- constructor(msg) {
916
- super(msg, AllowanceError.name);
917
- }
918
- }
919
-
920
- class RegistrationError extends AuthorizationError {
921
- constructor(msg) {
922
- super(msg, RegistrationError.name);
923
- }
924
- }
925
-
926
- class MissingContextError extends InternalError {
927
- constructor(msg) {
928
- super(msg, MissingContextError.name, 500);
929
- }
930
- }
931
-
932
- class UnauthorizedPrivateDataAccess extends BaseError {
933
- constructor(msg = "MISSING_PRIVATE_DATA_ERROR_MESSAGE") {
934
- super(UnauthorizedPrivateDataAccess.name, msg, 403);
935
- }
936
- }
937
-
938
- class NotInitializedError extends BaseError {
939
- constructor(msg) {
940
- super(NotInitializedError.name, msg, 409);
941
- }
942
- }
943
-
944
- class MissingPKCSS11Lib extends InternalError {
945
- constructor(msg) {
946
- super(msg, MissingPKCSS11Lib.name, 500);
947
- }
948
- }
949
-
950
- class EndorsementError extends InternalError {
951
- constructor(message) {
952
- super(message, EndorsementError.name, 500);
953
- }
954
- }
955
-
956
- class MvccReadConflictError extends InternalError {
957
- constructor(message) {
958
- super(message, MvccReadConflictError.name, 500);
959
- }
960
- }
961
-
962
- class PhantomReadConflictError extends InternalError {
963
- constructor(message) {
964
- super(message, PhantomReadConflictError.name, 500);
965
- }
966
- }
967
-
968
- class EndorsementPolicyError extends InternalError {
969
- constructor(message) {
970
- super(message, EndorsementPolicyError.name, 500);
971
- }
972
- }
973
-
974
- var HFCAIdentityType;
975
-
976
- (function(HFCAIdentityType) {
977
- HFCAIdentityType["PEER"] = "peer";
978
- HFCAIdentityType["ORDERER"] = "orderer";
979
- HFCAIdentityType["CLIENT"] = "client";
980
- HFCAIdentityType["USER"] = "user";
981
- HFCAIdentityType["ADMIN"] = "admin";
982
- })(HFCAIdentityType || (HFCAIdentityType = {}));
983
-
984
- var HFCAIdentityAttributes;
985
-
986
- (function(HFCAIdentityAttributes) {
987
- HFCAIdentityAttributes["HFREGISTRARROLES"] = "hf.Registrar.Roles";
988
- HFCAIdentityAttributes["HFREGISTRARDELEGATEROLES"] = "hf.Registrar.DelegateRoles";
989
- HFCAIdentityAttributes["HFREGISTRARATTRIBUTES"] = "hf.Registrar.Attributes";
990
- HFCAIdentityAttributes["HFINTERMEDIATECA"] = "hf.IntermediateCA";
991
- HFCAIdentityAttributes["HFREVOKER"] = "hf.Revoker";
992
- HFCAIdentityAttributes["HFAFFILIATIONMGR"] = "hf.AffiliationMgr";
993
- HFCAIdentityAttributes["HFGENCRL"] = "hf.GenCRL";
994
- })(HFCAIdentityAttributes || (HFCAIdentityAttributes = {}));
995
-
996
- class FabricEnrollmentService extends LoggedClass {
997
- constructor(caConfig) {
998
- CoreUtils.getCryptoSuite(caConfig.hsm ? {
999
- software: false,
1000
- lib: caConfig.hsm.library,
1001
- slot: caConfig.hsm.slot,
1002
- label: caConfig.hsm.tokenLabel,
1003
- pin: String(caConfig.hsm.pin)
1004
- } : undefined);
1005
- super();
1006
- this.caConfig = caConfig;
1007
- }
1008
- async User() {
1009
- if (this.user) return this.user;
1010
- const {caName: caName, caCert: caCert, caKey: caKey, url: url, hsm: hsm} = this.caConfig;
1011
- const log = this.log.for(this.User);
1012
- log.debug(`Creating CA user for ${caName} at ${url}`);
1013
- log.debug(`Retrieving CA certificate from ${caCert}`);
1014
- const certificate = await CoreUtils.getFirstDirFileNameContent(caCert);
1015
- let key;
1016
- if (!hsm) {
1017
- if (!caKey) {
1018
- throw new InternalError(`Missing caKey configuration for CA ${caName}. Provide a key directory or configure HSM support.`);
1019
- }
1020
- log.debug(`Retrieving CA key from ${caKey}`);
1021
- key = await CoreUtils.getFirstDirFileNameContent(caKey);
1022
- } else {
1023
- log.debug(`Using HSM configuration for CA ${caName} with library ${hsm.library}`);
1024
- }
1025
- log.debug(`Loading Admin user for ca ${caName}`);
1026
- this.user = await CoreUtils.getCAUser("admin", key, certificate, caName, {
1027
- hsm: hsm
1028
- });
1029
- return this.user;
1030
- }
1031
- async CA() {
1032
- if (this.ca) return this.ca;
1033
- const log = this.log.for(this.CA);
1034
- const {url: url, tls: tls, caName: caName} = this.caConfig;
1035
- let {trustedRoots: trustedRoots, verify: verify} = tls;
1036
- const root = trustedRoots[0];
1037
- log.debug(`Retrieving CA certificate from ${root}. cwd: ${process.cwd()}`);
1038
- const certificate = await CoreUtils.getFileContent(root);
1039
- log.debug(`Creating CA Client for CA ${caName} under ${url}`);
1040
- this.ca = new FabricCAServices(url, {
1041
- trustedRoots: Buffer.from(certificate),
1042
- verify: verify
1043
- }, caName);
1044
- return this.ca;
1045
- }
1046
- async Client() {
1047
- if (this.client) return this.client;
1048
- const ca = await this.CA();
1049
- this.client = ca["_FabricCAServices"];
1050
- return this.client;
1051
- }
1052
- async Certificate() {
1053
- if (!this.certificateService) this.certificateService = (await this.Client()).newCertificateService();
1054
- return this.certificateService;
1055
- }
1056
- async Affiliations() {
1057
- if (!this.affiliationService) this.affiliationService = (await this.CA()).newAffiliationService();
1058
- return this.affiliationService;
1059
- }
1060
- async Identities() {
1061
- if (!this.identityService) this.identityService = (await this.CA()).newIdentityService();
1062
- return this.identityService;
1063
- }
1064
- async getCertificates(request, doMap = true) {
1065
- const certificateService = await this.Certificate();
1066
- const user = await this.User();
1067
- const log = this.log.for(this.getCertificates);
1068
- log.debug(`Retrieving certificates${request ? ` for ${request.id}` : ""} for CA ${this.caConfig.caName}`);
1069
- const response = (await certificateService.getCertificates(request || {}, user)).result;
1070
- log.debug(`Found ${response.certs.length} certificates: ${JSON.stringify(response)}`);
1071
- return doMap ? response.certs.map(c => c.PEM) : response;
1072
- }
1073
- async getIdentities() {
1074
- const identitiesService = await this.Identities();
1075
- const log = this.log.for(this.getIdentities);
1076
- log.debug(`Retrieving Identities under CA ${this.caConfig.caName}`);
1077
- const response = (await identitiesService.getAll(await this.User())).result;
1078
- log.debug(`Found ${response.identities.length} Identities: ${JSON.stringify(response)}`);
1079
- return response.identities;
1080
- }
1081
- parseError(e) {
1082
- const regexp = /.*code:\s(\d+).*?message:\s["'](.+)["']/gs;
1083
- const match = regexp.exec(e.message);
1084
- if (!match) return new RegistrationError(e);
1085
- const [, code, message] = match;
1086
- switch (code) {
1087
- case "74":
1088
- case "71":
1089
- return new ConflictError(message);
1090
-
1091
- case "20":
1092
- return new AuthorizationError(message);
1093
-
1094
- default:
1095
- return new RegistrationError(message);
1096
- }
1097
- }
1098
- async getAffiliations() {
1099
- const affiliationService = await this.Affiliations();
1100
- const log = this.log.for(this.getAffiliations);
1101
- log.debug(`Retrieving Affiliations under CA ${this.caConfig.caName}`);
1102
- const response = (await affiliationService.getAll(await this.User())).result;
1103
- log.debug(`Found ${response.a.length} Affiliations: ${JSON.stringify(response)}`);
1104
- return response;
1105
- }
1106
- async read(enrollmentId) {
1107
- const ca = await this.CA();
1108
- const user = await this.User();
1109
- let result;
1110
- try {
1111
- result = await ca.newIdentityService().getOne(enrollmentId, user);
1112
- } catch (e) {
1113
- throw new NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${e}`);
1114
- }
1115
- if (!result.success) throw new NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1116
- return result.result;
1117
- }
1118
- async register(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments) {
1119
- let registration;
1120
- const log = this.log.for(this.register);
1121
- try {
1122
- const {userName: userName, password: password} = model;
1123
- const ca = await this.CA();
1124
- const user = await this.User();
1125
- const props = {
1126
- enrollmentID: userName,
1127
- enrollmentSecret: password,
1128
- affiliation: affiliation,
1129
- userRole: userRole,
1130
- attrs: attrs,
1131
- maxEnrollments: maxEnrollments
1132
- };
1133
- registration = await ca.register(props, user);
1134
- log.info(`Registration for ${userName} created with user type ${userRole ?? "Undefined Role"} ${isSuperUser ? "as super user" : ""}`);
1135
- } catch (e) {
1136
- throw this.parseError(e);
1137
- }
1138
- return registration;
1139
- }
1140
- static identityFromEnrollment(enrollment, mspId) {
1141
- const {certificate: certificate, key: key, rootCertificate: rootCertificate} = enrollment;
1142
- const log = Logging.for(FabricEnrollmentService, {}).for(this.identityFromEnrollment);
1143
- log.debug(`Generating Identity from certificate ${certificate} in msp ${mspId}`);
1144
- const clientId = CryptoUtils.fabricIdFromCertificate(certificate);
1145
- const id = CryptoUtils.encode(clientId);
1146
- log.debug(`Identity ${clientId} and encodedId ${id}`);
1147
- const now = new Date;
1148
- return new Identity({
1149
- id: id,
1150
- credentials: {
1151
- id: id,
1152
- certificate: certificate,
1153
- privateKey: key.toBytes(),
1154
- rootCertificate: rootCertificate,
1155
- createdOn: now,
1156
- updatedOn: now
1157
- },
1158
- mspId: mspId,
1159
- createdOn: now,
1160
- updatedOn: now
1161
- });
1162
- }
1163
- async enroll(enrollmentId, registration) {
1164
- let identity;
1165
- const log = this.log.for(this.enroll);
1166
- try {
1167
- const ca = await this.CA();
1168
- log.debug(`Enrolling ${enrollmentId}`);
1169
- const enrollment = await ca.enroll({
1170
- enrollmentID: enrollmentId,
1171
- enrollmentSecret: registration
1172
- });
1173
- identity = FabricEnrollmentService.identityFromEnrollment(enrollment, this.caConfig.caName);
1174
- log.info(`Successfully enrolled ${enrollmentId} under ${this.caConfig.caName} as ${identity.id}`);
1175
- } catch (e) {
1176
- throw this.parseError(e);
1177
- }
1178
- return identity;
1179
- }
1180
- async registerAndEnroll(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments) {
1181
- const registration = await this.register(model, isSuperUser, affiliation, userRole, attrs, maxEnrollments);
1182
- const {userName: userName} = model;
1183
- return this.enroll(userName, registration);
1184
- }
1185
- async revoke(enrollmentId) {
1186
- const ca = await this.CA();
1187
- const user = await this.User();
1188
- const identity = await this.read(enrollmentId);
1189
- if (!identity) throw new NotFoundError(`Could not find enrollment with id ${enrollmentId}`);
1190
- let result;
1191
- try {
1192
- result = await ca.revoke({
1193
- enrollmentID: identity.id,
1194
- reason: "User Deletation"
1195
- }, user);
1196
- } catch (e) {
1197
- throw new InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${e}`);
1198
- }
1199
- if (!result.success) throw new InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1200
- return result;
1201
- }
1202
- }
1203
-
1204
- class RegistrationRequestBuilder extends Model {
1205
- constructor() {
1206
- super(...arguments);
1207
- this.affiliation = "";
1208
- }
1209
- build() {
1210
- const errs = this.hasErrors();
1211
- if (errs) throw new ValidationError(errs.toString());
1212
- const response = {
1213
- enrollmentID: this.enrollmentID,
1214
- enrollmentSecret: this.enrollmentSecret,
1215
- role: this.role,
1216
- affiliation: this.affiliation
1217
- };
1218
- if (typeof this.maxEnrollments !== "undefined") response.maxEnrollments = this.maxEnrollments;
1219
- if (this.attrs) response.attrs = this.attrs;
1220
- return response;
1221
- }
1222
- setAffiliation(value) {
1223
- this.affiliation = value;
1224
- return this;
1225
- }
1226
- addAttr(attr) {
1227
- this.attrs = this.attrs || [];
1228
- this.attrs.push(attr);
1229
- return this;
1230
- }
1231
- setAttrs(value) {
1232
- this.attrs = value;
1233
- return this;
1234
- }
1235
- setEnrollmentID(value) {
1236
- this.enrollmentID = value;
1237
- return this;
1238
- }
1239
- setEnrollmentSecret(value) {
1240
- this.enrollmentSecret = value;
1241
- return this;
1242
- }
1243
- setMaxEnrollments(value) {
1244
- this.maxEnrollments = value;
1245
- return this;
1246
- }
1247
- setRole(value) {
1248
- this.role = value;
1249
- return this;
1250
- }
1251
- }
1252
-
1253
- __decorate([ required(), __metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "affiliation", void 0);
1254
-
1255
- __decorate([ minlength(1), __metadata("design:type", Array) ], RegistrationRequestBuilder.prototype, "attrs", void 0);
1256
-
1257
- __decorate([ required(), __metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "enrollmentID", void 0);
1258
-
1259
- __decorate([ required(), __metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "enrollmentSecret", void 0);
1260
-
1261
- __decorate([ min(0), __metadata("design:type", Number) ], RegistrationRequestBuilder.prototype, "maxEnrollments", void 0);
1262
-
1263
- __decorate([ required(), __metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "role", void 0);
1264
-
1265
- var ERC20Events;
1266
-
1267
- (function(ERC20Events) {
1268
- ERC20Events["TRANSFER"] = "Transfer";
1269
- ERC20Events["APPROVAL"] = "Approval";
1270
- })(ERC20Events || (ERC20Events = {}));
1271
-
1272
- let FabricBaseModel = class FabricBaseModel extends Model {
1273
- constructor(arg) {
1274
- super(arg);
1275
- }
1276
- };
1277
-
1278
- __decorate([ description("Stores the original timestamp of creation"), column(), createdAt(), __metadata("design:type", Date) ], FabricBaseModel.prototype, "createdAt", void 0);
1279
-
1280
- __decorate([ description("Stores the timestamp of the last update"), column(), updatedAt(), __metadata("design:type", Date) ], FabricBaseModel.prototype, "updatedAt", void 0);
1281
-
1282
- __decorate([ description("Stores the version of the model"), column(), version(), __metadata("design:type", Number) ], FabricBaseModel.prototype, "version", void 0);
1283
-
1284
- FabricBaseModel = __decorate([ uses(FabricFlavour), __metadata("design:paramtypes", [ Object ]) ], FabricBaseModel);
1285
-
1286
- let FabricIdentifiedBaseModel = class FabricIdentifiedBaseModel extends FabricBaseModel {
1287
- constructor(arg) {
1288
- super(arg);
1289
- }
1290
- };
1291
-
1292
- __decorate([ description("Stores the creator"), column(), createdBy(), __metadata("design:type", String) ], FabricIdentifiedBaseModel.prototype, "createdBy", void 0);
1293
-
1294
- __decorate([ description("Stores the user that last updated the model"), column(), updatedBy(), __metadata("design:type", String) ], FabricIdentifiedBaseModel.prototype, "updatedBy", void 0);
1295
-
1296
- FabricIdentifiedBaseModel = __decorate([ uses(FabricFlavour), __metadata("design:paramtypes", [ Object ]) ], FabricIdentifiedBaseModel);
1297
-
1298
- Model.prototype.isShared = function isShared() {
1299
- return Model.isShared(this.constructor);
1300
- };
1301
-
1302
- Model.prototype.isPrivate = function isPrivate() {
1303
- return Model.isPrivate(this.constructor);
1304
- };
1305
-
1306
- Model.prototype.segregate = function segregate() {
1307
- return Model.segregate(this);
1308
- };
1309
-
1310
- Model.segregate = function segregate(model) {
1311
- if (!Model.isTransient(model)) return {
1312
- model: model
1313
- };
1314
- const decoratedProperties = Metadata.validatableProperties(model.constructor);
1315
- const transientProps = Metadata.get(model.constructor, DBKeys.TRANSIENT);
1316
- const privateProperties = Metadata.get(model.constructor, FabricModelKeys.PRIVATE);
1317
- const sharedProperties = Metadata.get(model.constructor, FabricModelKeys.PRIVATE);
1318
- const result = {
1319
- model: {},
1320
- transient: {},
1321
- private: {},
1322
- shared: {}
1323
- };
1324
- const transientKeys = Object.keys(transientProps);
1325
- const privateKeys = Object.keys(privateProperties);
1326
- const sharedKeys = Object.keys(sharedProperties);
1327
- for (const key of decoratedProperties) {
1328
- const isTransient = transientKeys.includes(key);
1329
- const isPrivate = privateKeys.includes(key);
1330
- const isShared = sharedKeys.includes(key);
1331
- if (isTransient) {
1332
- result.transient = result.transient || {};
1333
- result.transient[key] = model[key];
1334
- if (isPrivate) {
1335
- result.private = result.private || {};
1336
- result.private[key] = model[key];
1337
- }
1338
- if (isShared) {
1339
- result.shared = result.shared || {};
1340
- result.shared[key] = model[key];
1341
- }
1342
- } else {
1343
- result.model = result.model || {};
1344
- result.model[key] = model[key];
1345
- }
1346
- }
1347
- result.model = Model.build(result.model, model.constructor.name);
1348
- return result;
1349
- }.bind(Model);
1350
-
1351
- Model.isPrivate = function isPrivate(model) {
1352
- return !!Metadata.get(typeof model !== "function" ? model.constructor : model, FabricModelKeys.PRIVATE);
1353
- }.bind(Model);
1354
-
1355
- Model.isShared = function isShared(model) {
1356
- return !!Metadata.get(typeof model !== "function" ? model.constructor : model, FabricModelKeys.SHARED);
1357
- }.bind(Model);
1358
-
1359
- Model.mirrored = function mirrored(model) {
1360
- return Metadata.get(typeof model !== "function" ? model.constructor : model, Metadata.key(FabricModelKeys.FABRIC, FabricModelKeys.MIRROR));
1361
- }.bind(Model);
1362
-
1363
- Model.ownerOf = function ownerOf(model) {
1364
- const meta = Metadata.get(model.constructor, Metadata.key(FabricModelKeys.FABRIC, FabricModelKeys.OWNED_BY));
1365
- if (!meta) return undefined;
1366
- return model[meta];
1367
- }.bind(Model);
1368
-
1369
- Model.mirroredAt = function mirroredAt(model) {
1370
- model = typeof model !== "function" ? model.constructor : model;
1371
- return Metadata.get(model, Metadata.key(FabricModelKeys.FABRIC, FabricModelKeys.MIRROR));
1372
- }.bind(Model);
1373
-
1374
- Model.collectionsFor = function collectionsFor(model) {
1375
- const privateKeys = [ FabricModelKeys.PRIVATE ];
1376
- const sharedKeys = [ FabricModelKeys.SHARED ];
1377
- const privateKey = Metadata.key(...privateKeys);
1378
- const sharedKey = Metadata.key(...sharedKeys);
1379
- const constr = typeof model === "function" ? model : model.constructor;
1380
- const privateMeta = Metadata.get(constr, privateKey);
1381
- const sharedMeta = Metadata.get(constr, sharedKey);
1382
- return {
1383
- privateCols: privateMeta?.collections || [],
1384
- sharedCols: sharedMeta?.collections || []
1385
- };
1386
- }.bind(Model);
1387
-
1388
- function Owner() {
1389
- return function(target, propertyKey, descriptor) {
1390
- const originalMethod = descriptor.value;
1391
- descriptor.value = async function(...args) {
1392
- const ctx = args[0];
1393
- const acountId = ctx.clientIdentity.getID();
1394
- const select = await this["tokenRepository"].select();
1395
- const tokens = await select.execute(ctx);
1396
- if (tokens.length == 0) {
1397
- throw new NotFoundError("No tokens avaialble");
1398
- }
1399
- if (tokens.length > 1) {
1400
- throw new NotFoundError(`To many token available : ${tokens.length}`);
1401
- }
1402
- if (tokens[0].owner != acountId) {
1403
- throw new AuthorizationError(`User not authorized to run ${propertyKey} on the token`);
1404
- }
1405
- return await originalMethod.apply(this, args);
1406
- };
1407
- return descriptor;
1408
- };
1409
- }
1410
-
1411
- async function ownedByOnCreate(context, data, key, model) {
1412
- const {stub: stub} = context;
1413
- const creator = await stub.getCreator();
1414
- const owner = creator.mspid;
1415
- const setOwnedByKeyValue = function(target, propertyKey, value) {
1416
- Object.defineProperty(target, propertyKey, {
1417
- enumerable: true,
1418
- writable: false,
1419
- configurable: true,
1420
- value: value
1421
- });
1422
- };
1423
- setOwnedByKeyValue(model, key, owner);
1424
- }
1425
-
1426
- function ownedBy() {
1427
- function ownedBy() {
1428
- return function(obj, attribute) {
1429
- return apply(required(), readonly(), onCreate(ownedByOnCreate), propMetadata(Metadata.key(FabricModelKeys.FABRIC, FabricModelKeys.OWNED_BY), attribute))(obj, attribute);
1430
- };
1431
- }
1432
- return Decoration.for(FabricModelKeys.OWNED_BY).define({
1433
- decorator: ownedBy,
1434
- args: []
1435
- }).apply();
1436
- }
1437
-
1438
- async function transactionIdOnCreate(context, data, key, model) {
1439
- const {stub: stub} = context;
1440
- model[key] = stub.getTxID();
1441
- }
1442
-
1443
- function transactionId() {
1444
- function transactionId() {
1445
- return function(obj, attribute) {
1446
- return apply(required(), readonly(), onCreate(transactionIdOnCreate), onUpdate(transactionIdOnCreate), propMetadata(Metadata.key(FabricModelKeys.FABRIC, attribute, FabricModelKeys.TRANSACTION_ID), attribute))(obj, attribute);
1447
- };
1448
- }
1449
- return Decoration.for(FabricModelKeys.TRANSACTION_ID).define({
1450
- decorator: transactionId,
1451
- args: []
1452
- }).apply();
1453
- }
1454
-
1455
- async function evalMirrorMetadata(model, resolver, ctx) {
1456
- let collection = resolver;
1457
- if (typeof collection !== "string") {
1458
- try {
1459
- const owner = Model.ownerOf(model) || ctx.get("stub").getCreator().toString();
1460
- if (resolver && typeof resolver === "function") collection = await resolver(model, owner, ctx);
1461
- } catch (e) {
1462
- throw new InternalError(`Failed to resolve collection mirror name: ${e}`);
1463
- }
1464
- }
1465
- if (!collection || typeof collection !== "string") throw new InternalError(`No collection found model ${model.constructor.name}`);
1466
- return collection;
1467
- }
1468
-
1469
- async function createMirrorHandler(context, data, key, model) {
1470
- const collection = await evalMirrorMetadata(model, data.resolver, context);
1471
- const repo = this.override(Object.assign({}, this._overrides, {
1472
- segregate: collection,
1473
- ignoreValidation: true,
1474
- ignoreHandlers: true
1475
- }));
1476
- const mirror = await repo.create(model, context);
1477
- context.logger.info(`Mirror for ${Model.tableName(this.class)} created with ${Model.pk(model)}: ${mirror[Model.pk(model)]}`);
1478
- }
1479
-
1480
- async function updateMirrorHandler(context, data, key, model) {
1481
- const collection = await evalMirrorMetadata(model, data.resolver, context);
1482
- const repo = this.override(Object.assign({}, this._overrides, {
1483
- segregate: collection,
1484
- ignoreValidation: true,
1485
- ignoreHandlers: true
1486
- }));
1487
- const mirror = await repo.update(model, context);
1488
- context.logger.info(`Mirror for ${Model.tableName(this.class)} updated with ${Model.pk(model)}: ${mirror[Model.pk(model)]}`);
1489
- }
1490
-
1491
- async function deleteMirrorHandler(context, data, key, model) {
1492
- const collection = await evalMirrorMetadata(model, data.resolver, context);
1493
- const repo = this.override(Object.assign({}, this._overrides, {
1494
- segregate: collection,
1495
- ignoreValidation: true,
1496
- ignoreHandlers: true
1497
- }));
1498
- const mirror = await repo.delete(Model.pk(model), context);
1499
- context.logger.info(`Mirror for ${Model.tableName(this.class)} deleted with ${Model.pk(model)}: ${mirror[Model.pk(model)]}`);
1500
- }
1501
-
1502
- function mirror(collection, condition) {
1503
- function mirror(resolver, condition) {
1504
- const meta = {
1505
- condition: condition,
1506
- resolver: resolver
1507
- };
1508
- return apply(metadata(Metadata.key(FabricModelKeys.FABRIC, FabricModelKeys.MIRROR), meta), privateData(collection), afterCreate(createMirrorHandler, meta, {
1509
- priority: 95
1510
- }), afterUpdate(updateMirrorHandler, meta, {
1511
- priority: 95
1512
- }), afterDelete(deleteMirrorHandler, meta, {
1513
- priority: 95
1514
- }));
1515
- }
1516
- return Decoration.for(FabricModelKeys.MIRROR).define({
1517
- decorator: mirror,
1518
- args: [ collection, condition ]
1519
- }).apply();
1520
- }
1521
-
1522
- const ModelCollection = (model, mspId) => {
1523
- const orgName = mspId || (typeof model !== "function" ? Model.ownerOf(model) : undefined);
1524
- const constr = typeof model === "function" ? model : model.constructor;
1525
- if (!orgName) throw new InternalError(`Model ${constr.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);
1526
- return `${toPascalCase(constr.name)}${mspId ? toPascalCase(mspId) : ""}`;
1527
- };
1528
-
1529
- const ImplicitPrivateCollection = (model, mspId) => {
1530
- const orgName = mspId || (typeof model !== "function" ? Model.ownerOf(model) : undefined);
1531
- if (!orgName) throw new InternalError(`Model ${model.constructor.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);
1532
- return `__${toPascalCase(orgName)}PrivateCollection`;
1533
- };
1534
-
1535
- async function segregatedDataOnCreate(context, data, keys, model) {
1536
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1537
- const msp = Model.ownerOf(model);
1538
- if (!msp) throw new ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1539
- const collectionResolver = data[0].collections;
1540
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model, msp, context);
1541
- const rebuilt = keys.reduce((acc, k, i) => {
1542
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model, msp, context);
1543
- if (c !== collection) throw new UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1544
- acc[k] = model[k];
1545
- return acc;
1546
- }, {});
1547
- const toCreate = new this.class(rebuilt);
1548
- const created = await this.override({
1549
- segregated: collection,
1550
- mergeModel: false,
1551
- ignoreHandlers: true,
1552
- ignoreValidation: true
1553
- }).create(toCreate, context);
1554
- Object.assign(model, created);
1555
- }
1556
-
1557
- async function segregatedDataOnRead(context, data, keys, model) {
1558
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1559
- const msp = Model.ownerOf(model);
1560
- if (!msp) throw new ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1561
- const collectionResolver = data[0].collections;
1562
- const collection = typeof collectionResolver === "string" ? collectionResolver : await collectionResolver(model, msp, context);
1563
- const rebuilt = keys.reduce((acc, k, i) => {
1564
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model, msp, context);
1565
- if (c !== collection) return acc;
1566
- acc[k] = model[k];
1567
- return acc;
1568
- }, {});
1569
- }
1570
-
1571
- async function segregatedDataOnUpdate(context, data, key, model, oldModel) {}
1572
-
1573
- async function segregatedDataOnDelete(context, data, key, model) {}
1574
-
1575
- function segregated(collection, type, filter) {
1576
- return function innerSegregated(target, propertyKey) {
1577
- function segregatedDec(target, propertyKey) {
1578
- const key = Metadata.key(type, propertyKey);
1579
- const constr = target.constructor;
1580
- const meta = Metadata.get(constr, key) || {};
1581
- const collections = new Set(meta.collections || []);
1582
- collections.add(collection);
1583
- meta.collections = [ ...collections ];
1584
- Metadata.set(constr, key, meta);
1585
- const constrMeta = Metadata.get(constr, type) || {};
1586
- const constrCollections = new Set(constrMeta.collections || []);
1587
- constrCollections.add(collection);
1588
- meta.collections = [ ...collections ];
1589
- Metadata.set(constr, type, meta);
1590
- }
1591
- const decs = [];
1592
- if (!propertyKey) {
1593
- Metadata.properties(target)?.forEach(p => {
1594
- if (!filter || filter(p)) {
1595
- segregated(collection, type)(target.prototype, p);
1596
- }
1597
- });
1598
- } else {
1599
- decs.push(prop(), transient(), segregatedDec, onCreate(segregatedDataOnCreate, {
1600
- collections: collection
1601
- }, {
1602
- priority: 95,
1603
- group: typeof collection === "string" ? collection : collection.toString()
1604
- }), onRead(segregatedDataOnRead, {
1605
- collections: collection
1606
- }, {
1607
- priority: 95,
1608
- group: typeof collection === "string" ? collection : collection.toString()
1609
- }), onUpdate(segregatedDataOnUpdate, {
1610
- collections: collection
1611
- }, {
1612
- priority: 95,
1613
- group: typeof collection === "string" ? collection : collection.toString()
1614
- }), onDelete(segregatedDataOnDelete, {
1615
- collections: collection
1616
- }, {
1617
- priority: 95,
1618
- group: typeof collection === "string" ? collection : collection.toString()
1619
- }));
1620
- }
1621
- return apply(...decs)(target, propertyKey);
1622
- };
1623
- }
1624
-
1625
- function privateData(collection = ImplicitPrivateCollection) {
1626
- function privateData(collection) {
1627
- return segregated(collection, FabricModelKeys.PRIVATE);
1628
- }
1629
- return Decoration.for(FabricModelKeys.PRIVATE).define({
1630
- decorator: privateData,
1631
- args: [ collection ]
1632
- }).apply();
1633
- }
1634
-
1635
- function sharedData(collection) {
1636
- function sharedData(collection) {
1637
- return segregated(collection, FabricModelKeys.SHARED);
1638
- }
1639
- return Decoration.for(FabricModelKeys.SHARED).define({
1640
- decorator: sharedData,
1641
- args: [ collection ]
1642
- }).apply();
1643
- }
1644
-
1645
- class DeterministicSerializer extends JSONSerializer {
1646
- constructor() {
1647
- super();
1648
- }
1649
- preSerialize(model) {
1650
- const toSerialize = Object.assign({}, model);
1651
- let metadata;
1652
- try {
1653
- metadata = Metadata.modelName(model.constructor);
1654
- } catch (error) {
1655
- metadata = undefined;
1656
- }
1657
- toSerialize[ModelKeys.ANCHOR] = metadata || model.constructor.name;
1658
- const preSerialize = function preSerialize(obj) {
1659
- const self = this;
1660
- if (typeof obj !== "object") return obj;
1661
- if (Array.isArray(obj)) return obj.map(o => preSerialize.call(self, o));
1662
- return this.preSerialize.call(this, obj);
1663
- }.bind(this);
1664
- Model.relations(model).forEach(r => {
1665
- toSerialize[r] = preSerialize(toSerialize[r]);
1666
- });
1667
- return toSerialize;
1668
- }
1669
- deserialize(str) {
1670
- const deserialization = JSON.parse(str);
1671
- const className = deserialization[ModelKeys.ANCHOR];
1672
- if (!className) throw new Error("Could not find class reference in serialized model");
1673
- const model = Model.build(deserialization, className);
1674
- return model;
1675
- }
1676
- serialize(model) {
1677
- const stringify = require("json-stringify-deterministic");
1678
- const sortKeysRecursive = require("sort-keys-recursive");
1679
- return stringify(sortKeysRecursive(this.preSerialize(model)));
1680
- }
1681
- }
1682
-
1683
- function generateFabricEventName(table, event, owner) {
1684
- const params = [ table, event ];
1685
- if (owner) params.push(owner);
1686
- return params.join("_");
1687
- }
1688
-
1689
- function parseEventName(name) {
1690
- const parts = name.split("_");
1691
- if (parts.length < 2 || parts.length > 3) return {
1692
- table: undefined,
1693
- event: name,
1694
- owner: undefined
1695
- };
1696
- return {
1697
- table: parts[0],
1698
- event: parts[1],
1699
- owner: parts[2]
1700
- };
1701
- }
1702
-
1703
- function add(a, b) {
1704
- const c = a + b;
1705
- if (a !== c - b || b !== c - a) {
1706
- throw new OverflowError(`Addition overflow: ${a} + ${b}`);
1707
- }
1708
- return c;
1709
- }
1710
-
1711
- function sub(a, b) {
1712
- const c = a - b;
1713
- if (a !== c + b || b !== a - c) {
1714
- throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
1715
- }
1716
- return c;
1717
- }
1718
-
1719
- function safeParseInt(string) {
1720
- const digitRegex = /^\d+$/;
1721
- if (!digitRegex.test(string)) {
1722
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string contains digits"));
1723
- }
1724
- const parsedint = parseInt(string);
1725
- if (isNaN(parsedint)) {
1726
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string is not a parsable integer"));
1727
- }
1728
- return parsedint;
1729
- }
1730
-
1731
- class SimpleDeterministicSerializer extends JSONSerializer {
1732
- constructor() {
1733
- super();
1734
- }
1735
- deserialize(str, tableName) {
1736
- const deserialization = JSON.parse(str);
1737
- return deserialization;
1738
- }
1739
- serialize(model, putAnchor = true) {
1740
- const stringify = require("json-stringify-deterministic");
1741
- const sortKeysRecursive = require("sort-keys-recursive");
1742
- const preSerialization = this.preSerialize(model, putAnchor);
1743
- return stringify(sortKeysRecursive(preSerialization));
1744
- }
1745
- preSerialize(model, putAnchor = true) {
1746
- const toSerialize = Object.assign({}, model);
1747
- let metadata;
1748
- try {
1749
- metadata = Metadata.modelName(model.constructor);
1750
- } catch (error) {
1751
- metadata = undefined;
1752
- }
1753
- if (putAnchor) toSerialize[ModelKeys.ANCHOR] = metadata || model.constructor.name;
1754
- function preSerialize(obj) {
1755
- if (typeof obj !== "object") return obj;
1756
- if (Array.isArray(obj)) return obj.map(preSerialize);
1757
- return this.preSerialize(obj);
1758
- }
1759
- Model.relations(model).forEach(r => {
1760
- toSerialize[r] = preSerialize.call(this, toSerialize[r]);
1761
- });
1762
- return toSerialize;
1763
- }
1764
- }
1765
-
1766
- class FabricIdentityService extends ClientBasedService {
1767
- constructor() {
1768
- super();
1769
- }
1770
- get rootClient() {
1771
- return this.client["_FabricCaServices"];
1772
- }
1773
- get user() {
1774
- if (!this._user) throw new InternalError("Fabric identity service not properly setup: missing user");
1775
- return this._user;
1776
- }
1777
- get certificates() {
1778
- return this.rootClient.newCertificateService();
1779
- }
1780
- get affiliations() {
1781
- return this.client.newAffiliationService();
1782
- }
1783
- get identities() {
1784
- return this.client.newIdentityService();
1785
- }
1786
- async getUser(cfg, ctx) {
1787
- const log = ctx.logger.for(this.getUser);
1788
- const {caName: caName, caCert: caCert, caKey: caKey, url: url, hsm: hsm} = cfg;
1789
- log.info(`Creating CA user for ${caName} at ${url}`);
1790
- log.verbose(`Retrieving CA certificate from ${caCert}`);
1791
- const certificate = await CoreUtils.getFirstDirFileNameContent(caCert);
1792
- let key;
1793
- if (!hsm) {
1794
- if (!caKey) {
1795
- throw new InternalError(`Missing caKey configuration for CA ${caName}. Provide a key directory or configure HSM support.`);
1796
- }
1797
- log.debug(`Retrieving CA key from ${caKey}`);
1798
- key = await CoreUtils.getFirstDirFileNameContent(caKey);
1799
- } else {
1800
- log.debug(`Using HSM configuration for CA ${caName} with library ${hsm.library}`);
1801
- }
1802
- log.debug(`Loading Admin user for ca ${caName}`);
1803
- this._user = await CoreUtils.getCAUser("admin", key, certificate, caName, {
1804
- hsm: hsm
1805
- });
1806
- return this._user;
1807
- }
1808
- async initialize(...args) {
1809
- const {log: log, ctx: ctx} = await this.logCtx(args, this.initialize, true);
1810
- const [config] = args;
1811
- if (!config) throw new InternalError("Missing Fabric CA configuration");
1812
- const {url: url, tls: tls, caName: caName} = config;
1813
- log.info(`Initializing CA Client for CA ${config.caName} at ${config.url}`);
1814
- const {trustedRoots: trustedRoots, verify: verify} = tls;
1815
- const root = trustedRoots[0];
1816
- log.debug(`Retrieving CA certificate from ${root}. cwd: ${process.cwd()}`);
1817
- const certificate = await CoreUtils.getFileContent(root);
1818
- log.debug(`CA Certificate: ${certificate.toString()}`);
1819
- const client = new FabricCAServices(url, {
1820
- trustedRoots: Buffer.from(certificate),
1821
- verify: verify
1822
- }, caName);
1823
- const user = await this.getUser(config, ctx);
1824
- log.debug(`CA user loaded: ${user.getName()}`);
1825
- return {
1826
- config: config,
1827
- client: client
1828
- };
1829
- }
1830
- async getCertificates(request, doMap = true, ...args) {
1831
- if (request instanceof Context) {
1832
- args = [ request ];
1833
- doMap = true;
1834
- request = undefined;
1835
- } else if (typeof request === "boolean") {
1836
- doMap = request;
1837
- request = undefined;
1838
- } else if (typeof doMap !== "boolean") {
1839
- args = [ doMap, ...args ];
1840
- doMap = true;
1841
- }
1842
- const {log: log} = await this.logCtx(args, this.getCertificates, true);
1843
- log.debug(`Retrieving certificates${request ? ` for ${request.id}` : ""} for CA ${this.config.caName}`);
1844
- const response = (await this.certificates.getCertificates(request || {}, this.user)).result;
1845
- log.verbose(`Found ${response.certs.length} certificates`);
1846
- log.debug(response.certs);
1847
- return doMap ? response.certs.map(c => c.PEM) : response;
1848
- }
1849
- async getIdentities(ctx) {
1850
- const log = ctx.logger.for(this.getIdentities);
1851
- log.verbose(`Retrieving Identities under CA ${this.config.caName}`);
1852
- const response = (await this.identities.getAll(this.user)).result;
1853
- log.verbose(`Found ${response.identities.length} Identities`);
1854
- log.debug(response.identities);
1855
- return response.identities;
1856
- }
1857
- async getAffiliations(ctx) {
1858
- const log = ctx.logger.for(this.getAffiliations);
1859
- log.verbose(`Retrieving Affiliations under CA ${this.config.caName}`);
1860
- const response = (await this.affiliations.getAll(this.user)).result;
1861
- log.verbose(`Found ${response.a.length} Affiliations`);
1862
- log.debug(JSON.stringify(response));
1863
- return response;
1864
- }
1865
- parseError(e) {
1866
- const regexp = /.*code:\s(\d+).*?message:\s["'](.+)["']/gs;
1867
- const match = regexp.exec(e.message);
1868
- if (!match) return new RegistrationError(e);
1869
- const [, code, message] = match;
1870
- switch (code) {
1871
- case "74":
1872
- case "71":
1873
- return new ConflictError(message);
1874
-
1875
- case "20":
1876
- return new AuthorizationError(message);
1877
-
1878
- default:
1879
- return new RegistrationError(message);
1880
- }
1881
- }
1882
- async read(enrollmentId, ...args) {
1883
- const {log: log} = await this.logCtx(args, this.read, true);
1884
- log.verbose(`Retrieving identity with enrollment ID ${enrollmentId}`);
1885
- let result;
1886
- try {
1887
- result = await this.identities.getOne(enrollmentId, this.user);
1888
- } catch (e) {
1889
- throw new NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${e}`);
1890
- }
1891
- if (!result.success) throw new NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1892
- return result.result;
1893
- }
1894
- async register(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments, ...args) {
1895
- const {log: log} = await this.logCtx(args, this.register, true);
1896
- let registration;
1897
- try {
1898
- const {userName: userName, password: password} = model;
1899
- const props = {
1900
- enrollmentID: userName,
1901
- enrollmentSecret: password,
1902
- affiliation: affiliation,
1903
- userRole: userRole,
1904
- attrs: attrs,
1905
- maxEnrollments: maxEnrollments
1906
- };
1907
- registration = await this.client.register(props, this.user);
1908
- log.info(`Registration for ${userName} created with user type ${userRole ?? "Undefined Role"} ${isSuperUser ? "as super user" : ""}`);
1909
- } catch (e) {
1910
- throw this.parseError(e);
1911
- }
1912
- return registration;
1913
- }
1914
- static identityFromEnrollment(enrollment, mspId, ctx) {
1915
- const log = ctx.logger.for(this.identityFromEnrollment);
1916
- const {certificate: certificate, key: key, rootCertificate: rootCertificate} = enrollment;
1917
- log.verbose(`Generating Identity from certificate ${certificate} in msp ${mspId}`);
1918
- const clientId = CryptoUtils.fabricIdFromCertificate(certificate);
1919
- const id = CryptoUtils.encode(clientId);
1920
- log.debug(`Identity ${clientId} and encodedId ${id}`);
1921
- return new Identity({
1922
- id: id,
1923
- credentials: {
1924
- id: id,
1925
- certificate: certificate,
1926
- privateKey: key.toBytes(),
1927
- rootCertificate: rootCertificate
1928
- },
1929
- mspId: mspId
1930
- });
1931
- }
1932
- async enroll(enrollmentId, registration, ...args) {
1933
- const {log: log, ctx: ctx} = await this.logCtx(args, this.enroll, true);
1934
- let identity;
1935
- try {
1936
- log.debug(`Enrolling ${enrollmentId}`);
1937
- const enrollment = await this.client.enroll({
1938
- enrollmentID: enrollmentId,
1939
- enrollmentSecret: registration
1940
- });
1941
- identity = FabricIdentityService.identityFromEnrollment(enrollment, this.config.caName, ctx);
1942
- log.info(`Successfully enrolled ${enrollmentId} under ${this.config.caName} as ${identity.id}`);
1943
- } catch (e) {
1944
- throw this.parseError(e);
1945
- }
1946
- return identity;
1947
- }
1948
- async registerAndEnroll(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments, ...args) {
1949
- const {ctx: ctx} = await this.logCtx(args, this.registerAndEnroll, true);
1950
- const registration = await this.register(model, isSuperUser, affiliation, userRole, attrs, maxEnrollments, ctx);
1951
- const {userName: userName} = model;
1952
- return this.enroll(userName, registration, ctx);
1953
- }
1954
- async revoke(enrollmentId, ...args) {
1955
- const {log: log} = await this.logCtx(args, this.revoke, true);
1956
- log.verbose(`Revoking identity with enrollment ID ${enrollmentId}`);
1957
- const identity = await this.read(enrollmentId);
1958
- if (!identity) throw new NotFoundError(`Could not find enrollment with id ${enrollmentId}`);
1959
- let result;
1960
- try {
1961
- result = await this.client.revoke({
1962
- enrollmentID: identity.id,
1963
- reason: "User Deletion"
1964
- }, this.user);
1965
- } catch (e) {
1966
- throw new InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${e}`);
1967
- }
1968
- if (!result.success) throw new InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1969
- return result;
1970
- }
1971
- }
1972
-
1973
- const DefaultFabricClientFlags = Object.assign({
1974
- evaluateTimeout: 5,
1975
- endorseTimeout: 15,
1976
- submitTimeout: 5,
1977
- commitTimeout: 60
1978
- }, DefaultAdapterFlags);
1979
-
1980
- const log = new MiniLogger("fabric-fs");
1981
-
1982
- async function contentOfLoadFile(contentOrPath, fileReader) {
1983
- if (contentOrPath instanceof Uint8Array) return contentOrPath;
1984
- if (contentOrPath.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) return contentOrPath;
1985
- return await fileReader(contentOrPath);
1986
- }
1987
-
1988
- async function readFile(contentOrPath) {
1989
- if (typeof contentOrPath !== "string") return contentOrPath;
1990
- const fileReader = async path => {
1991
- const {promises: promises} = await normalizeImport(import("fs"));
1992
- return await promises.readFile(path);
1993
- };
1994
- return await fileReader(contentOrPath);
1995
- }
1996
-
1997
- async function getCAUser(userName, privateKey, certificate, mspId) {
1998
- log.debug(`Creating a CA ${mspId} user ${userName} with certificate ${certificate}`);
1999
- const user = new User(userName);
2000
- const cryptoSuite = User.newCryptoSuite();
2001
- user.setCryptoSuite(cryptoSuite);
2002
- const importedKey = cryptoSuite.createKeyFromRaw(privateKey);
2003
- await user.setEnrollment(importedKey, certificate, mspId);
2004
- return user;
2005
- }
2006
-
2007
- async function getIdentity(mspId, certDirectoryPath) {
2008
- const identityFileReader = async path => {
2009
- const {promises: promises} = await normalizeImport(import("fs"));
2010
- const certPath = await getFirstDirFileName(path);
2011
- const credentials = await promises.readFile(certPath);
2012
- return credentials;
2013
- };
2014
- const credentials = await contentOfLoadFile(certDirectoryPath, identityFileReader);
2015
- return {
2016
- mspId: mspId,
2017
- credentials: credentials
2018
- };
2019
- }
2020
-
2021
- async function getFirstDirFileName(dirPath) {
2022
- const {promises: promises} = await normalizeImport(import("fs"));
2023
- const {join: join} = await normalizeImport(import("path"));
2024
- const files = await promises.readdir(dirPath);
2025
- return join(dirPath, files[0]);
2026
- }
2027
-
2028
- async function getFirstDirFileNameContent(dirPath) {
2029
- const {promises: promises} = await normalizeImport(import("fs"));
2030
- const {join: join} = await normalizeImport(import("path"));
2031
- const files = await promises.readdir(dirPath);
2032
- return (await promises.readFile(join(dirPath, files[0]))).toString();
2033
- }
2034
-
2035
- async function getSigner(keyDirectoryPath) {
2036
- const signerFileReader = async path => {
2037
- const {promises: promises} = await normalizeImport(import("fs"));
2038
- const keyPath = await getFirstDirFileName(path);
2039
- return await promises.readFile(keyPath);
2040
- };
2041
- const privateKeyPem = await contentOfLoadFile(keyDirectoryPath, signerFileReader);
2042
- const privateKey = await extractPrivateKey(privateKeyPem);
2043
- const keys = Object.getOwnPropertySymbols(privateKey);
2044
- const k = privateKey[keys[0]];
2045
- return signers.newPrivateKeySigner(k);
2046
- }
2047
-
2048
- async function extractPrivateKey(pem) {
2049
- const libName = "crypto";
2050
- let subtle;
2051
- if (isBrowser()) {
2052
- subtle = globalThis.crypto.subtle;
2053
- } else {
2054
- const lib = await normalizeImport(import(libName));
2055
- subtle = lib.subtle || lib.webcrypto.subtle;
2056
- }
2057
- if (!subtle) throw new Error("Could not load SubtleCrypto module");
2058
- function str2ab(str) {
2059
- const buf = new ArrayBuffer(str.length);
2060
- const bufView = new Uint8Array(buf);
2061
- for (let i = 0, strLen = str.length; i < strLen; i++) {
2062
- bufView[i] = str.charCodeAt(i);
2063
- }
2064
- return buf;
2065
- }
2066
- const str = pem.toString("utf8").replace("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "").replace("-----END PRIVATE KEY-----", "");
2067
- const decoded = Buffer.from(str, "base64").toString("binary");
2068
- const binaryDer = str2ab(decoded);
2069
- try {
2070
- const key = await subtle.importKey("pkcs8", binaryDer, {
2071
- name: "ECDSA",
2072
- namedCurve: "P-256"
2073
- }, true, [ "sign" ]);
2074
- return key;
2075
- } catch (e) {
2076
- throw new InternalError(e);
2077
- }
2078
- }
2079
-
2080
- class HSMSignerFactoryCustom {
2081
- static #pkcs11=null;
2082
- static #initialized=false;
2083
- constructor(library) {
2084
- if (!HSMSignerFactoryCustom.#pkcs11) {
2085
- HSMSignerFactoryCustom.#pkcs11 = new pkcs11.PKCS11;
2086
- HSMSignerFactoryCustom.#pkcs11.load(this.findHSMPKCS11Lib(library));
2087
- }
2088
- if (!HSMSignerFactoryCustom.#initialized) {
2089
- try {
2090
- HSMSignerFactoryCustom.#pkcs11.C_Initialize();
2091
- } catch (e) {
2092
- if (e.code !== pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED) {
2093
- throw e;
2094
- }
2095
- }
2096
- HSMSignerFactoryCustom.#initialized = true;
2097
- }
2098
- }
2099
- findHSMPKCS11Lib(lib) {
2100
- const commonSoftHSMPathNames = [ "/usr/lib/softhsm/libsofthsm2.so", "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", "/usr/local/lib/softhsm/libsofthsm2.so", "/usr/lib/libacsp-pkcs11.so", "/opt/homebrew/lib/softhsm/libsofthsm2.so" ];
2101
- if (lib) commonSoftHSMPathNames.push(lib);
2102
- for (const pathnameToTry of commonSoftHSMPathNames) {
2103
- if (fs.existsSync(pathnameToTry)) {
2104
- return pathnameToTry;
2105
- }
2106
- }
2107
- throw new MissingPKCSS11Lib("Unable to find PKCS11 library");
2108
- }
2109
- dispose() {
2110
- HSMSignerFactoryCustom.#pkcs11.C_Finalize();
2111
- }
2112
- sanitizeOptions(hsmSignerOptions) {
2113
- const options = Object.assign({
2114
- userType: pkcs11.CKU_USER
2115
- }, hsmSignerOptions);
2116
- this.assertNotEmpty(options.label, "label");
2117
- this.assertNotEmpty(options.pin, "pin");
2118
- this.assertNotEmpty(options.identifier, "identifier");
2119
- return options;
2120
- }
2121
- assertNotEmpty(property, name) {
2122
- if (!property || property.toString().trim().length === 0) {
2123
- throw new Error(`${name} property must be provided`);
2124
- }
2125
- }
2126
- findSlotForLabel(pkcs11Label) {
2127
- const slots = HSMSignerFactoryCustom.#pkcs11.C_GetSlotList(true);
2128
- if (slots.length === 0) {
2129
- throw new Error("No pkcs11 slots can be found");
2130
- }
2131
- const slot = slots.find(slotToCheck => {
2132
- const tokenInfo = HSMSignerFactoryCustom.#pkcs11.C_GetTokenInfo(slotToCheck);
2133
- return tokenInfo.label.trim() === pkcs11Label;
2134
- });
2135
- if (!slot) {
2136
- throw new Error(`label ${pkcs11Label} cannot be found in the pkcs11 slot list`);
2137
- }
2138
- return slot;
2139
- }
2140
- login(session, userType, pin) {
2141
- try {
2142
- HSMSignerFactoryCustom.#pkcs11.C_Login(session, userType, pin);
2143
- } catch (err) {
2144
- const pkcs11err = err;
2145
- if (pkcs11err.code !== pkcs11.CKR_USER_ALREADY_LOGGED_IN) {
2146
- throw err;
2147
- }
2148
- }
2149
- }
2150
- findObjectInHSM(session, keytype, identifier) {
2151
- const pkcs11Template = [ {
2152
- type: pkcs11.CKA_ID,
2153
- value: identifier
2154
- }, {
2155
- type: pkcs11.CKA_CLASS,
2156
- value: keytype
2157
- }, {
2158
- type: pkcs11.CKA_KEY_TYPE,
2159
- value: pkcs11.CKK_EC
2160
- } ];
2161
- HSMSignerFactoryCustom.#pkcs11.C_FindObjectsInit(session, pkcs11Template);
2162
- const hsmObject = HSMSignerFactoryCustom.#pkcs11.C_FindObjects(session, 1)[0];
2163
- if (!hsmObject) {
2164
- HSMSignerFactoryCustom.#pkcs11.C_FindObjectsFinal(session);
2165
- throw new Error(`Unable to find object in HSM with ID ${identifier.toString()}`);
2166
- }
2167
- HSMSignerFactoryCustom.#pkcs11.C_FindObjectsFinal(session);
2168
- return hsmObject;
2169
- }
2170
- newSigner(hsmSignerOptions) {
2171
- const options = this.sanitizeOptions(hsmSignerOptions);
2172
- const pkcs = HSMSignerFactoryCustom.#pkcs11;
2173
- const slot = this.findSlotForLabel(options.label);
2174
- const session = pkcs.C_OpenSession(slot, pkcs11.CKF_SERIAL_SESSION);
2175
- let privateKeyHandle;
2176
- try {
2177
- this.login(session, options.userType, options.pin);
2178
- privateKeyHandle = this.findObjectInHSM(session, pkcs11.CKO_PRIVATE_KEY, options.identifier);
2179
- } catch (err) {
2180
- HSMSignerFactoryCustom.#pkcs11.C_CloseSession(session);
2181
- throw err;
2182
- }
2183
- return {
2184
- signer: async digest => {
2185
- HSMSignerFactoryCustom.#pkcs11.C_SignInit(session, {
2186
- mechanism: pkcs11.CKM_ECDSA
2187
- }, privateKeyHandle);
2188
- const compactSignature = await HSMSignerFactoryCustom.#pkcs11.C_SignAsync(session, Buffer.from(digest), Buffer.alloc(p256.Point.Fn.BYTES * 2));
2189
- return p256.Signature.fromBytes(compactSignature, "compact").normalizeS().toBytes("der");
2190
- },
2191
- close: () => {
2192
- HSMSignerFactoryCustom.#pkcs11.C_CloseSession(session);
2193
- }
2194
- };
2195
- }
2196
- assertDefined(value) {
2197
- if (value === undefined) {
2198
- throw new Error("required value was undefined");
2199
- }
2200
- return value;
2201
- }
2202
- getUncompressedPointOnCurve(key) {
2203
- const jwk = key.export({
2204
- format: "jwk"
2205
- });
2206
- const x = Buffer.from(this.assertDefined(jwk.x), "base64url");
2207
- const y = Buffer.from(this.assertDefined(jwk.y), "base64url");
2208
- const prefix = Buffer.from("04", "hex");
2209
- return Buffer.concat([ prefix, x, y ]);
2210
- }
2211
- getSKIFromCertificatePath(certPath) {
2212
- const p = certPath.endsWith(".pem") ? certPath : path.join(certPath, "cert.pem");
2213
- const credentials = fs.readFileSync(p);
2214
- return this.getSKIFromCertificate(credentials);
2215
- }
2216
- getSKIFromCertificate(cert) {
2217
- const certificate = new crypto$1.X509Certificate(cert);
2218
- const uncompressedPoint = this.getUncompressedPointOnCurve(certificate.publicKey);
2219
- return crypto$1.createHash("sha256").update(uncompressedPoint).digest();
2220
- }
2221
- }
2222
-
2223
- class FabricClientStatement extends Statement {
2224
- constructor(adapter, overrides) {
2225
- super(adapter, overrides);
2226
- }
2227
- squash(ctx) {
2228
- const squashed = super.squash(ctx);
2229
- if (!squashed) return squashed;
2230
- const {method: method, params: params, args: args} = squashed;
2231
- const {direction: direction, limit: limit} = params;
2232
- switch (method) {
2233
- case PreparedStatementKeys.FIND_BY:
2234
- break;
2235
-
2236
- case PreparedStatementKeys.LIST_BY:
2237
- args.push(direction);
2238
- break;
2239
-
2240
- case PreparedStatementKeys.PAGE_BY:
2241
- args.push(direction, limit);
2242
- break;
2243
-
2244
- case PreparedStatementKeys.FIND_ONE_BY:
2245
- break;
2246
-
2247
- default:
2248
- throw new InternalError(`Unsupported method ${method}`);
2249
- }
2250
- return squashed;
2251
- }
2252
- async executePrepared(...argz) {
2253
- const repo = Repository.forModel(this.fromSelector, this.adapter.alias);
2254
- const {method: method, args: args} = this.prepared;
2255
- return repo.statement(method, ...args, ...argz);
2256
- }
2257
- async prepare(ctx) {
2258
- ctx = ctx || await this.adapter.context(PersistenceKeys.QUERY, this.overrides || {}, this.fromSelector);
2259
- if (this.isSimpleQuery() && ctx.get("forcePrepareSimpleQueries")) {
2260
- const squashed = this.squash(ctx);
2261
- if (squashed) {
2262
- this.prepared = squashed;
2263
- return this;
2264
- }
2265
- }
2266
- const args = [];
2267
- const params = {};
2268
- const prepared = {
2269
- class: this.fromSelector,
2270
- args: args,
2271
- params: params
2272
- };
2273
- const method = [ QueryClause.FIND_BY ];
2274
- if (this.whereCondition) {
2275
- const parsed = this.prepareCondition(this.whereCondition, ctx);
2276
- method.push(parsed.method);
2277
- if (parsed.args && parsed.args.length) args.push(...parsed.args);
2278
- }
2279
- if (this.selectSelector) method.push(QueryClause.SELECT, this.selectSelector.join(` ${QueryClause.AND.toLowerCase()} `));
2280
- if (this.orderBySelector) {
2281
- method.push(QueryClause.ORDER_BY, this.orderBySelector[0]);
2282
- args.push(this.orderBySelector[1]);
2283
- }
2284
- prepared.method = toCamelCase(method.join(" "));
2285
- prepared.params = params;
2286
- this.prepared = prepared;
2287
- return this;
2288
- }
2289
- build() {
2290
- throw new UnsupportedError(`This method is only called is prepared statements are not used. If so, a dedicated implementation for the native queries used is required`);
2291
- }
2292
- parseCondition(condition, ...args) {
2293
- throw new UnsupportedError(`This method is only called is prepared statements are not used. Is so, a dedicated implementation for the native queries used is required`);
2294
- }
2295
- }
2296
-
2297
- class FabricClientPaginator extends Paginator {
2298
- constructor(adapter, query, size, clazz) {
2299
- super(adapter, query, size, clazz);
2300
- }
2301
- prepare(rawStatement) {
2302
- throw new UnsupportedError(`Raw query access must be implemented by a subclass. only prepared statements are natively available`);
2303
- }
2304
- page(page = 1, ...args) {
2305
- return super.page(page, ...args);
2306
- }
2307
- }
2308
-
2309
- var _a;
2310
-
2311
- class FabricClientAdapter extends Adapter {
2312
- static {
2313
- this.decoder = new TextDecoder("utf8");
2314
- }
2315
- static {
2316
- this.serializer = new ClientSerializer;
2317
- }
2318
- static {
2319
- this.log = Logging.for(FabricClientAdapter);
2320
- }
2321
- constructor(config, alias) {
2322
- super(config, FabricFlavour, alias);
2323
- this.serializer = FabricClientAdapter.serializer;
2324
- }
2325
- Statement(overrides) {
2326
- return new FabricClientStatement(this, overrides);
2327
- }
2328
- Paginator(query, size, clazz) {
2329
- return new FabricClientPaginator(this, query, size, clazz);
2330
- }
2331
- flags(operation, model, flags, ...args) {
2332
- return super.flags(operation, model, flags, ...args);
2333
- }
2334
- async context(operation, overrides, model, ...args) {
2335
- const log = this.log.for(this.context);
2336
- log.silly(`creating new context for ${operation} operation on ${model ? Array.isArray(model) ? model.map(m => Model.tableName(m)) : Model.tableName(model) : "no"} table ${overrides && Object.keys(overrides) ? Object.keys(overrides).length : "no"} with flag overrides`);
2337
- let ctx = args.pop();
2338
- if (typeof ctx !== "undefined" && !(ctx instanceof Context)) {
2339
- args.push(ctx);
2340
- ctx = undefined;
2341
- }
2342
- overrides = ctx ? Object.assign({}, overrides, ctx.toOverrides()) : overrides;
2343
- const flags = await this.flags(typeof operation === "string" ? operation : operation.name, model, overrides, ...args, ctx);
2344
- if (ctx) {
2345
- if (!(ctx instanceof this.Context)) {
2346
- return (new this.Context).accumulate({
2347
- ...ctx["cache"],
2348
- ...flags,
2349
- parentContext: ctx
2350
- });
2351
- }
2352
- const currentOp = ctx.get("operation");
2353
- const currentModel = ctx.get("affectedTables");
2354
- if (currentOp !== operation || model !== currentModel) return (new this.Context).accumulate({
2355
- ...ctx["cache"],
2356
- ...flags,
2357
- parentContext: ctx
2358
- });
2359
- return ctx.accumulate(flags);
2360
- }
2361
- return (new this.Context).accumulate({
2362
- ...DefaultFabricClientFlags,
2363
- ...flags
2364
- });
2365
- }
2366
- decode(data) {
2367
- return FabricClientAdapter.decoder.decode(data);
2368
- }
2369
- repository() {
2370
- return FabricClientRepository;
2371
- }
2372
- createPrefix(clazz, id, model, ...args) {
2373
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.createPrefix);
2374
- const tableName = Model.tableName(clazz);
2375
- const record = {};
2376
- record[CouchDBKeys.TABLE] = tableName;
2377
- Object.assign(record, model);
2378
- return [ clazz, id, record, ...ctxArgs ];
2379
- }
2380
- createAllPrefix(clazz, ids, models, ...args) {
2381
- const tableName = Model.tableName(clazz);
2382
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
2383
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.createAllPrefix);
2384
- const records = ids.map((id, count) => {
2385
- const record = {};
2386
- record[CouchDBKeys.TABLE] = tableName;
2387
- Object.assign(record, models[count]);
2388
- return record;
2389
- });
2390
- return [ clazz, ids, records, ...ctxArgs ];
2391
- }
2392
- updateAllPrefix(clazz, ids, models, ...args) {
2393
- const tableName = Model.tableName(clazz);
2394
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
2395
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.updateAllPrefix);
2396
- const records = ids.map(() => {
2397
- const record = {};
2398
- record[CouchDBKeys.TABLE] = tableName;
2399
- return record;
2400
- });
2401
- return [ clazz, ids, records, ...ctxArgs ];
2402
- }
2403
- async createAll(clazz, ids, models, ...args) {
2404
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
2405
- const ctxArgs = [ ...args ];
2406
- const transient = ctxArgs.shift();
2407
- const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.createAll);
2408
- const tableName = Model.tableName(clazz);
2409
- log.info(`adding ${ids.length} entries to ${tableName} table`);
2410
- log.verbose(`pks: ${ids}`);
2411
- const result = await this.submitTransaction(ctx, BulkCrudOperationKeys.CREATE_ALL, [ JSON.stringify(models.map(m => this.serializer.serialize(m, clazz.name))) ], transient, undefined, clazz.name);
2412
- try {
2413
- return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2414
- } catch (e) {
2415
- throw new SerializationError(e);
2416
- }
2417
- }
2418
- async readAll(clazz, ids, ...args) {
2419
- const {log: log, ctx: ctx} = this.logCtx(args, this.readAll);
2420
- const tableName = Model.tableName(clazz);
2421
- log.info(`reading ${ids.length} entries to ${tableName} table`);
2422
- log.verbose(`pks: ${ids}`);
2423
- const result = await this.evaluateTransaction(ctx, BulkCrudOperationKeys.READ_ALL, [ JSON.stringify(ids) ], undefined, undefined, clazz.name);
2424
- try {
2425
- return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2426
- } catch (e) {
2427
- throw new SerializationError(e);
2428
- }
2429
- }
2430
- async updateAll(clazz, ids, models, ...args) {
2431
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
2432
- const ctxArgs = [ ...args ];
2433
- const transient = ctxArgs.shift();
2434
- const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.updateAll);
2435
- const tableName = Model.tableName(clazz);
2436
- log.info(`updating ${ids.length} entries to ${tableName} table`);
2437
- log.verbose(`pks: ${ids}`);
2438
- const result = await this.submitTransaction(ctx, BulkCrudOperationKeys.UPDATE_ALL, [ JSON.stringify(models.map(m => this.serializer.serialize(m, clazz.name))) ], transient, undefined, clazz.name);
2439
- try {
2440
- return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2441
- } catch (e) {
2442
- throw new SerializationError(e);
2443
- }
2444
- }
2445
- async deleteAll(clazz, ids, ...args) {
2446
- const {log: log, ctx: ctx} = this.logCtx(args, this.deleteAll);
2447
- const tableName = Model.tableName(clazz);
2448
- log.info(`deleting ${ids.length} entries to ${tableName} table`);
2449
- log.verbose(`pks: ${ids}`);
2450
- const result = await this.submitTransaction(ctx, BulkCrudOperationKeys.DELETE_ALL, [ JSON.stringify(ids) ], undefined, undefined, clazz.name);
2451
- try {
2452
- return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2453
- } catch (e) {
2454
- throw new SerializationError(e);
2455
- }
2456
- }
2457
- prepare(model, ...args) {
2458
- const {log: log} = this.logCtx(args, this.prepare);
2459
- const split = Model.segregate(model);
2460
- if (model[PersistenceKeys.METADATA]) {
2461
- log.silly(`Passing along persistence metadata for ${model[PersistenceKeys.METADATA]}`);
2462
- Object.defineProperty(split.model, PersistenceKeys.METADATA, {
2463
- enumerable: false,
2464
- writable: false,
2465
- configurable: true,
2466
- value: model[PersistenceKeys.METADATA]
2467
- });
2468
- }
2469
- return {
2470
- record: split.model,
2471
- model: split.model,
2472
- id: model[Model.pk(model.constructor)],
2473
- transient: split.transient,
2474
- private: split.private,
2475
- shared: split.shared
2476
- };
2477
- }
2478
- revert(obj, clazz, id, transient, ...args) {
2479
- const {log: log} = this.logCtx(args, this.revert);
2480
- if (transient) {
2481
- log.verbose(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
2482
- Object.entries(transient).forEach(([key, val]) => {
2483
- if (key in obj) throw new InternalError(`Transient property ${key} already exists on model ${typeof clazz === "string" ? clazz : clazz.name}. should be impossible`);
2484
- obj[key] = val;
2485
- });
2486
- }
2487
- return new clazz(obj);
2488
- }
2489
- async create(clazz, id, model, transient = {}, ...args) {
2490
- const ctxArgs = [ ...args ];
2491
- const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.create);
2492
- const tableName = Model.tableName(clazz);
2493
- log.verbose(`adding entry to ${tableName} table`);
2494
- log.debug(`pk: ${id}`);
2495
- const result = await this.submitTransaction(ctx, OperationKeys.CREATE, [ this.serializer.serialize(model, clazz.name) ], transient, undefined, clazz.name);
2496
- return this.serializer.deserialize(this.decode(result));
2497
- }
2498
- async read(clazz, id, ...args) {
2499
- const {log: log, ctx: ctx} = this.logCtx(args, this.readAll);
2500
- const tableName = Model.tableName(clazz);
2501
- log.verbose(`reading entry from ${tableName} table`);
2502
- log.debug(`pk: ${id}`);
2503
- const result = await this.evaluateTransaction(ctx, OperationKeys.READ, [ id.toString() ], undefined, undefined, clazz.name);
2504
- return this.serializer.deserialize(this.decode(result));
2505
- }
2506
- updatePrefix(clazz, id, model, ...args) {
2507
- const tableName = Model.tableName(clazz);
2508
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.updatePrefix);
2509
- const record = {};
2510
- record[CouchDBKeys.TABLE] = tableName;
2511
- Object.assign(record, model);
2512
- return [ clazz, id, record, ...ctxArgs ];
2513
- }
2514
- async update(clazz, id, model, transient = {}, ...args) {
2515
- const ctxArgs = [ ...args ];
2516
- const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.updateAll);
2517
- log.info(`CLIENT UPDATE class : ${typeof clazz}`);
2518
- const tableName = Model.tableName(clazz);
2519
- log.verbose(`updating entry to ${tableName} table`);
2520
- log.debug(`pk: ${id}`);
2521
- const result = await this.submitTransaction(ctx, OperationKeys.UPDATE, [ this.serializer.serialize(model, clazz.name || clazz) ], transient, undefined, clazz.name);
2522
- return this.serializer.deserialize(this.decode(result));
2523
- }
2524
- async delete(clazz, id, ...args) {
2525
- const {log: log, ctx: ctx} = this.logCtx(args, this.delete);
2526
- const tableName = Model.tableName(clazz);
2527
- log.verbose(`deleting entry from ${tableName} table`);
2528
- log.debug(`pk: ${id}`);
2529
- const result = await this.submitTransaction(ctx, OperationKeys.DELETE, [ id.toString() ], undefined, undefined, clazz.name);
2530
- return this.serializer.deserialize(this.decode(result));
2531
- }
2532
- async raw(rawInput, docsOnly = true, clazz, ...args) {
2533
- const {log: log, ctx: ctx} = this.logCtx(args, this.raw);
2534
- const tableName = clazz.name;
2535
- log.info(`Performing raw statement on table ${Model.tableName(clazz)}`);
2536
- let transactionResult;
2537
- try {
2538
- transactionResult = await this.evaluateTransaction(ctx, "raw", [ JSON.stringify(rawInput), docsOnly ], undefined, undefined, tableName);
2539
- } catch (e) {
2540
- throw this.parseError(e);
2541
- }
2542
- let result;
2543
- try {
2544
- result = JSON.parse(this.decode(transactionResult));
2545
- } catch (e) {
2546
- throw new SerializationError(`Failed to process result: ${e}`);
2547
- }
2548
- const parseRecord = record => {
2549
- if (Model.isModel(record)) return Model.build(record);
2550
- return record;
2551
- };
2552
- if (Array.isArray(result)) {
2553
- if (!result.length) return result;
2554
- const el = result[0];
2555
- if (Model.isModel(el)) return result.map(el => Model.build(el));
2556
- return result;
2557
- }
2558
- return parseRecord(result);
2559
- }
2560
- getClient() {
2561
- if (!this._client) this._client = FabricClientAdapter.getClient(this.config);
2562
- return this._client;
2563
- }
2564
- async Gateway(ctx) {
2565
- return FabricClientAdapter.getGateway(ctx, this.config, this.client);
2566
- }
2567
- getContractName(className) {
2568
- if (!className) return undefined;
2569
- return `${className}Contract`;
2570
- }
2571
- async Contract(ctx, contractName) {
2572
- return FabricClientAdapter.getContract(await this.Gateway(ctx), this.config, contractName);
2573
- }
2574
- async transaction(ctx, api, submit = true, args, transientData, endorsingOrganizations, className) {
2575
- const log = this.log.for(this.transaction);
2576
- const gateway = await this.Gateway(ctx);
2577
- try {
2578
- const contract = await this.Contract(ctx, this.getContractName(className));
2579
- log.verbose(`${submit ? "Submit" : "Evaluate"}ting transaction ${this.getContractName(className) || this.config.contractName}.${api}`);
2580
- log.debug(`args: ${args?.map(a => a.toString()).join("\n") || "none"}`);
2581
- const method = submit ? contract.submit : contract.evaluate;
2582
- endorsingOrganizations = endorsingOrganizations?.length ? endorsingOrganizations : undefined;
2583
- const proposalOptions = {
2584
- arguments: args || [],
2585
- transientData: transientData
2586
- };
2587
- return await method.call(contract, api, proposalOptions);
2588
- } catch (e) {
2589
- if (e.code === 10) {
2590
- throw new Error(`${e.details[0].message}`);
2591
- }
2592
- throw this.parseError(e);
2593
- } finally {
2594
- this.log.debug(`Closing ${this.config.mspId} gateway connection`);
2595
- gateway.close();
2596
- }
2597
- }
2598
- parseError(err) {
2599
- return FabricClientAdapter.parseError(err);
2600
- }
2601
- async submitTransaction(ctx, api, args, transientData, endorsingOrganizations, className) {
2602
- return this.transaction(ctx, api, true, args, transientData, endorsingOrganizations, className);
2603
- }
2604
- async evaluateTransaction(ctx, api, args, transientData, endorsingOrganizations, className) {
2605
- return this.transaction(ctx, api, false, args, transientData, endorsingOrganizations, className);
2606
- }
2607
- async close() {
2608
- if (this.client) {
2609
- this.log.verbose(`Closing ${this.config.mspId} gateway client`);
2610
- this.client.close();
2611
- }
2612
- }
2613
- static getContract(gateway, config, contractName) {
2614
- const log = this.log.for(this.getContract);
2615
- const network = this.getNetwork(gateway, config.channel);
2616
- let contract;
2617
- try {
2618
- log.debug(`Retrieving chaincode ${config.chaincodeName} contract ${contractName || config.contractName} from network ${config.channel}`);
2619
- contractName = contractName ? contractName : config.contractName;
2620
- contract = network.getContract(config.chaincodeName, contractName);
2621
- } catch (e) {
2622
- throw this.parseError(e);
2623
- }
2624
- return contract;
2625
- }
2626
- static getNetwork(gateway, channelName) {
2627
- const log = Logging.for(this.getNetwork);
2628
- let network;
2629
- try {
2630
- log.debug(`Connecting to channel ${channelName}`);
2631
- network = gateway.getNetwork(channelName);
2632
- } catch (e) {
2633
- throw this.parseError(e);
2634
- }
2635
- return network;
2636
- }
2637
- static async getGateway(ctx, config, client) {
2638
- return await this.getConnection(client || await this.getClient(config), config, ctx);
2639
- }
2640
- static getClient(config) {
2641
- const log = this.log.for(this.getClient);
2642
- log.debug(`generating TLS credentials for msp ${config.mspId}`);
2643
- let pathOrCert = config.tlsCert;
2644
- if (typeof pathOrCert === "string") {
2645
- if (pathOrCert.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) {
2646
- pathOrCert = Buffer.from(pathOrCert, "utf8");
2647
- } else {
2648
- try {
2649
- pathOrCert = Buffer.from(fs.readFileSync(pathOrCert, "utf8"));
2650
- } catch (e) {
2651
- throw new InternalError(`Failed to read the tls certificate from ${pathOrCert}: ${e}`);
2652
- }
2653
- }
2654
- }
2655
- const tlsCredentials = grpc.credentials.createSsl(pathOrCert);
2656
- log.debug(`generating Gateway Client for url ${config.peerEndpoint}`);
2657
- return new Client(config.peerEndpoint, tlsCredentials, {
2658
- "grpc.max_receive_message_length": (config.sizeLimit || 15) * 1024 * 1024,
2659
- "grpc.max_send_message_length": (config.sizeLimit || 15) * 1024 * 1024
2660
- });
2661
- }
2662
- static async getConnection(client, config, ctx) {
2663
- const log = Logging.for(this.getConnection);
2664
- log.debug(`Retrieving Peer Identity for ${config.mspId} under ${config.certCertOrDirectoryPath}`);
2665
- const identity = await getIdentity(config.mspId, config.certCertOrDirectoryPath);
2666
- log.debug(`Retrieving signer key from ${config.keyCertOrDirectoryPath}`);
2667
- let signer, close = () => {};
2668
- if (!config.hsm) {
2669
- signer = await getSigner(config.keyCertOrDirectoryPath);
2670
- } else {
2671
- const hsm = new HSMSignerFactoryCustom(config.hsm.library);
2672
- const identifier = hsm.getSKIFromCertificatePath(config.certCertOrDirectoryPath);
2673
- const pkcs11Signer = hsm.newSigner({
2674
- label: config.hsm.tokenLabel,
2675
- pin: String(config.hsm.pin),
2676
- identifier: identifier
2677
- });
2678
- signer = pkcs11Signer.signer;
2679
- close = pkcs11Signer.close;
2680
- }
2681
- const options = {
2682
- client: client,
2683
- identity: identity,
2684
- signer: signer,
2685
- evaluateOptions: () => ({
2686
- deadline: Date.now() + 1e3 * ctx.get("evaluateTimeout")
2687
- }),
2688
- endorseOptions: () => ({
2689
- deadline: Date.now() + 1e3 * ctx.get("endorseTimeout")
2690
- }),
2691
- submitOptions: () => ({
2692
- deadline: Date.now() + 1e3 * ctx.get("submitTimeout")
2693
- }),
2694
- commitStatusOptions: () => ({
2695
- deadline: Date.now() + 1e3 * ctx.get("commitTimeout")
2696
- })
2697
- };
2698
- log.debug(`Connecting to ${config.mspId}`);
2699
- const gateway = connect(options);
2700
- if (config.hsm) {
2701
- gateway.close = new Proxy(gateway.close, {
2702
- apply(target, thisArg, argArray) {
2703
- Reflect.apply(target, thisArg, argArray);
2704
- close();
2705
- }
2706
- });
2707
- }
2708
- return gateway;
2709
- }
2710
- Dispatch() {
2711
- return new FabricClientAdapter["_baseDispatch"];
2712
- }
2713
- static parseError(err) {
2714
- const msg = typeof err === "string" ? err : err.message;
2715
- if (msg.includes("MVCC_READ_CONFLICT")) return new MvccReadConflictError(err);
2716
- if (msg.includes("ENDORSEMENT_POLICY_FAILURE")) return new EndorsementPolicyError(err);
2717
- if (msg.includes("PHANTOM_READ_CONFLICT")) return new PhantomReadConflictError(err);
2718
- if (err instanceof Error && err.code) {
2719
- switch (err.code) {
2720
- case 9:
2721
- return new EndorsementError(err);
2722
- }
2723
- }
2724
- if (msg.includes(NotFoundError.name)) return new NotFoundError(err);
2725
- if (msg.includes(ConflictError.name)) return new ConflictError(err);
2726
- if (msg.includes(BadRequestError.name)) return new BadRequestError(err);
2727
- if (msg.includes(QueryError.name)) return new QueryError(err);
2728
- if (msg.includes(PagingError.name)) return new PagingError(err);
2729
- if (msg.includes(UnsupportedError.name)) return new UnsupportedError(err);
2730
- if (msg.includes(MigrationError.name)) return new MigrationError(err);
2731
- if (msg.includes(ObserverError.name)) return new ObserverError(err);
2732
- if (msg.includes(AuthorizationError.name)) return new AuthorizationError(err);
2733
- if (msg.includes(ForbiddenError.name)) return new ForbiddenError(err);
2734
- if (msg.includes(ConnectionError.name)) return new ConnectionError(err);
2735
- if (msg.includes(SerializationError.name)) return new SerializationError(err);
2736
- return new InternalError(err);
2737
- }
2738
- }
2739
-
2740
- __decorate([ debug(), final(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Object, Object, Object, Object, Context ]), __metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "create", null);
2741
-
2742
- __decorate([ debug(), final(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Object, Object, Context ]), __metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "read", null);
2743
-
2744
- __decorate([ debug(), final(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Object, Object, Object, Object, Context ]), __metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "update", null);
2745
-
2746
- __decorate([ debug(), final(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Object, Object, Context ]), __metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "delete", null);
2747
-
2748
- __decorate([ debug(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Object, typeof (_a = typeof D !== "undefined" && D) === "function" ? _a : Object, Object, Context ]), __metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "raw", null);
2749
-
2750
- FabricClientAdapter.decoration();
2751
-
2752
- Adapter.setCurrent(FabricFlavour);
2753
-
2754
- class FabricClientDispatch extends Dispatch {
2755
- constructor(client) {
2756
- super();
2757
- this.client = client;
2758
- this.decoder = new TextDecoder("utf8");
2759
- }
2760
- async close() {
2761
- if (this.listeningStack) this.listeningStack.close();
2762
- }
2763
- parsePayload(jsonBytes) {
2764
- const json = this.decoder.decode(jsonBytes);
2765
- return JSON.parse(json);
2766
- }
2767
- observe(observer) {
2768
- if (!(observer instanceof FabricClientAdapter)) throw new UnsupportedError("Only FabricClientAdapter can be observed by dispatch");
2769
- super.observe(observer);
2770
- return () => this.unObserve(observer);
2771
- }
2772
- async updateObservers(model, event, id, ...args) {
2773
- const {log: log, ctxArgs: ctxArgs} = Adapter.logCtx(this.updateObservers, event, false, ...args);
2774
- if (!this.adapter) {
2775
- log.verbose(`No adapter observed for dispatch; skipping observer update for ${typeof model === "string" ? model : Model.tableName(model)}:${event}`);
2776
- return;
2777
- }
2778
- try {
2779
- await this.adapter.refresh(model, event, id, ...ctxArgs);
2780
- } catch (e) {
2781
- throw new InternalError(`Failed to refresh dispatch: ${e}`);
2782
- }
2783
- }
2784
- async handleEvents(ctxArg) {
2785
- if (!this.listeningStack) throw new InternalError(`Event stack not initialized. Ensure that "startListening" is called before attempting this operation.`);
2786
- if (!this.adapter || !this.adapter.config) throw new InternalError(`No adapter found. should be impossible`);
2787
- const ctx = ctxArg || await this.adapter.context(OperationKeys.READ, {
2788
- correlationId: this.adapter.config.chaincodeName
2789
- }, this.models && this.models[0] || Model);
2790
- const log = this.log.for(this.handleEvents);
2791
- log.info(`Listening for incoming events on chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}"...`);
2792
- try {
2793
- for await (const evt of this.listeningStack) {
2794
- const {table: table, event: event, owner: owner} = parseEventName(evt.eventName);
2795
- if (owner && owner !== this.adapter.config?.mspId) continue;
2796
- const payload = this.parsePayload(evt.payload);
2797
- try {
2798
- const targetModel = table ? Model.get(table) : Model.get(this.models[0].name);
2799
- const modelRef = targetModel ?? (table || this.models[0]?.name);
2800
- await this.updateObservers(modelRef, event, payload.id, ctx);
2801
- } catch (e) {
2802
- log.error(`Failed update observables for table ${table} event ${event} id: ${payload.id}: ${e}`);
2803
- }
2804
- }
2805
- } catch (e) {
2806
- log.error(`Failed to read event for chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}": ${e}`);
2807
- await this.close();
2808
- }
2809
- }
2810
- async initialize() {
2811
- if (!this.adapter) throw new InternalError(`No adapter or config observed for dispatch`);
2812
- const context = await this.adapter.context("dispatch", {
2813
- correlationId: this.adapter.config.chaincodeName
2814
- }, Model);
2815
- const {ctx: ctx} = this.logCtx([ context ], this.initialize);
2816
- const gateway = await FabricClientAdapter.getGateway(ctx, this.adapter.config, this.client);
2817
- const network = gateway.getNetwork(this.adapter.config.channel);
2818
- if (!this.adapter) throw new InternalError(`No adapter observed for dispatch`);
2819
- this.listeningStack = await network.getChaincodeEvents(this.adapter.config.chaincodeName);
2820
- this.handleEvents(ctx);
2821
- }
2822
- }
2823
-
2824
- if (FabricClientAdapter) FabricClientAdapter["_baseDispatch"] = FabricClientDispatch;
2825
-
2826
- const VERSION = "0.1.62";
2827
-
2828
- const PACKAGE_NAME = "@decaf-ts/for-fabric";
2829
-
2830
- Metadata.registerLibrary(PACKAGE_NAME, VERSION);
2831
-
2832
- export { AllowanceError, BASE_ALPHABET, BalanceError, BaseEncoder, CRYPTO, ClientSerializer, CoreUtils, CryptoUtils, DefaultFabricClientFlags, DeterministicSerializer, ERC20Events, EndorsementError, EndorsementPolicyError, FabricBaseModel, FabricClientAdapter, FabricClientDispatch, FabricClientRepository, FabricERC20ClientRepository, FabricEnrollmentService, FabricFlavour, FabricIdentifiedBaseModel, FabricIdentityService, FabricModelKeys, HFCAIdentityAttributes, HFCAIdentityType, Identity, IdentityCredentials, IdentityType, ImplicitPrivateCollection, MissingContextError, MissingPKCSS11Lib, ModelCollection, MvccReadConflictError, NotInitializedError, OverflowError, Owner, PACKAGE_NAME, PhantomReadConflictError, RegistrationError, RegistrationRequestBuilder, SimpleDeterministicSerializer, UnauthorizedPrivateDataAccess, VERSION, add, contentOfLoadFile, createMirrorHandler, deleteMirrorHandler, evalMirrorMetadata, extractPrivateKey, generateFabricEventName, generateModelIndexes, getCAUser, getFirstDirFileName, getFirstDirFileNameContent, getIdentity, getSigner, mirror, ownedBy, ownedByOnCreate, parseEventName, privateData, readFile, readModelFile, readModelFolders, safeParseInt, segregatedDataOnCreate, segregatedDataOnDelete, segregatedDataOnRead, segregatedDataOnUpdate, sharedData, sub, transactionId, transactionIdOnCreate, updateMirrorHandler, writeIndexes };
2833
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWZhYnJpYy5qcyIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaWVudC9GYWJyaWNDbGllbnRSZXBvc2l0b3J5LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9lcmMyMC9tb2RlbHMudHMiLCIuLi9zcmMvc2hhcmVkL0NsaWVudFNlcmlhbGl6ZXIudHMiLCIuLi9zcmMvY2xpZW50L2VyYzIwL0ZhYnJpY0VSQzIwQ2xpZW50UmVwb3NpdG9yeS50cyIsIi4uL3NyYy9jbGllbnQvaW5kZXhlcy9nZW5lcmF0aW9uLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9JZGVudGl0eUNyZWRlbnRpYWxzLnRzIiwiLi4vc3JjL3NoYXJlZC9jb25zdGFudHMudHMiLCIuLi9zcmMvc2hhcmVkL21vZGVsL0lkZW50aXR5LnRzIiwiLi4vc3JjL2NsaWVudC91dGlscy50cyIsIi4uL3NyYy9jbGllbnQvY3J5cHRvLnRzIiwiLi4vc3JjL3NoYXJlZC9lcnJvcnMudHMiLCIuLi9zcmMvY2xpZW50L3NlcnZpY2VzL0ZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlLnRzIiwiLi4vc3JjL2NsaWVudC9zZXJ2aWNlcy9SZWdpc3RyYXRpb25SZXF1ZXN0QnVpbGRlci50cyIsIi4uL3NyYy9zaGFyZWQvZXJjMjAvZXJjMjAtY29uc3RhbnRzLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9GYWJyaWNCYXNlTW9kZWwudHMiLCIuLi9zcmMvc2hhcmVkL21vZGVsL0ZhYnJpY0lkZW50aWZpZWRCYXNlTW9kZWwudHMiLCIuLi9zcmMvc2hhcmVkL292ZXJyaWRlcy9vdmVycmlkZXMudHMiLCIuLi9zcmMvc2hhcmVkL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvc2hhcmVkL0RldGVybWluaXN0aWNTZXJpYWxpemVyLnRzIiwiLi4vc3JjL3NoYXJlZC9ldmVudHMudHMiLCIuLi9zcmMvc2hhcmVkL21hdGgudHMiLCIuLi9zcmMvc2hhcmVkL1NpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2NsaWVudC9zZXJ2aWNlcy9GYWJyaWNJZGVudGl0eVNlcnZpY2UudHMiLCIuLi9zcmMvY2xpZW50L2NvbnN0YW50cy50cyIsIi4uL3NyYy9jbGllbnQvZmFicmljLWZzLnRzIiwiLi4vc3JjL2NsaWVudC9mYWJyaWMtaHNtLnRzIiwiLi4vc3JjL2NsaWVudC9GYWJyaWNDbGllbnRTdGF0ZW1lbnQudHMiLCIuLi9zcmMvY2xpZW50L0ZhYnJpY0NsaWVudFBhZ2luYXRvci50cyIsIi4uL3NyYy9jbGllbnQvRmFicmljQ2xpZW50QWRhcHRlci50cyIsIi4uL3NyYy9jbGllbnQvRmFicmljQ2xpZW50RGlzcGF0Y2gudHMiLCIuLi9zcmMvdmVyc2lvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBPcmRlckRpcmVjdGlvbixcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBSZXBvc2l0b3J5LFxuICBDb250ZXh0T2YsXG4gIFByZXBhcmVkU3RhdGVtZW50S2V5cyxcbiAgU2VyaWFsaXplZFBhZ2UsXG4gIERpcmVjdGlvbkxpbWl0T2Zmc2V0LFxuICBQYWdpbmF0b3IsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBNYXliZUNvbnRleHR1YWxBcmcgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IHR5cGUgRmFicmljQ2xpZW50QWRhcHRlciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7XG4gIE9wZXJhdGlvbktleXMsXG4gIFByaW1hcnlLZXlUeXBlLFxuICBWYWxpZGF0aW9uRXJyb3IsXG4gIHJlZHVjZUVycm9yc1RvUHJpbnQsXG4gIGVuZm9yY2VEQkRlY29yYXRvcnMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ291Y2hEQktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcG9zaXRvcnkgaW1wbGVtZW50YXRpb24gZm9yIEZhYnJpYyBjbGllbnQgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRXh0ZW5kcyB0aGUgZ2VuZXJpYyBSZXBvc2l0b3J5IHRvIHByZXBhcmUgY29udGV4dCBhbmQgYXJndW1lbnRzIGZvciBDUlVEIG9wZXJhdGlvbnMgZXhlY3V0ZWQgdmlhIGEgRmFicmljIGNsaWVudCBBZGFwdGVyLCB3aXJpbmcgUmVwb3NpdG9yeUZsYWdzIGFuZCBGYWJyaWMtc3BlY2lmaWMgb3ZlcnJpZGVzLlxuICogQHRlbXBsYXRlIE0gZXh0ZW5kcyBNb2RlbCAtIFRoZSBtb2RlbCB0eXBlIGhhbmRsZWQgYnkgdGhpcyByZXBvc2l0b3J5XG4gKiBAcGFyYW0ge0FkYXB0ZXI8YW55LCBNYW5nb1F1ZXJ5LCBGYWJyaWNGbGFncywgQ29udGV4dDxGYWJyaWNGbGFncz4+fSBbYWRhcHRlcl0gLSBPcHRpb25hbCBhZGFwdGVyIGluc3RhbmNlIHVzZWQgdG8gZXhlY3V0ZSBvcGVyYXRpb25zXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbY2xhenpdIC0gT3B0aW9uYWwgbW9kZWwgY29uc3RydWN0b3IgdXNlZCBieSB0aGUgcmVwb3NpdG9yeVxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBGYWJyaWNDbGllbnRSZXBvc2l0b3J5XG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgUmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuICogaW1wb3J0IHsgRmFicmljQ2xpZW50UmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWZhYnJpY1wiO1xuICpcbiAqIGNsYXNzIFVzZXIgZXh0ZW5kcyBNb2RlbCB7IGlkITogc3RyaW5nOyBuYW1lITogc3RyaW5nOyB9XG4gKiBjb25zdCByZXBvID0gbmV3IEZhYnJpY0NsaWVudFJlcG9zaXRvcnk8VXNlcj4oKTtcbiAqIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCByZXBvLmNyZWF0ZShuZXcgVXNlcih7IGlkOiBcIjFcIiwgbmFtZTogXCJBbGljZVwiIH0pKTtcbiAqIGNvbnN0IGxvYWRlZCA9IGF3YWl0IHJlcG8ucmVhZChcIjFcIik7XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgUmVwbyBhcyBGYWJyaWNDbGllbnRSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgQXBwLT4+UmVwbzogY3JlYXRlKG1vZGVsKVxuICogICBSZXBvLT4+UmVwbzogY3JlYXRlUHJlZml4KG1vZGVsLCAuLi5hcmdzKVxuICogICBSZXBvLT4+QWRhcHRlcjogY3JlYXRlKHRhYmxlLCBpZCwgbW9kZWwsIGZsYWdzKVxuICogICBBZGFwdGVyLS0+PlJlcG86IHJlc3VsdFxuICogICBSZXBvLS0+PkFwcDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NsaWVudFJlcG9zaXRvcnk8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgQSBleHRlbmRzIEZhYnJpY0NsaWVudEFkYXB0ZXIgPSBGYWJyaWNDbGllbnRBZGFwdGVyLFxuPiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgQT4ge1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgX292ZXJyaWRlcyA9IE9iamVjdC5hc3NpZ24oe30sIHN1cGVyW1wiX292ZXJyaWRlc1wiXSwge1xuICAgIGlnbm9yZVZhbGlkYXRpb246IHRydWUsXG4gICAgaWdub3JlSGFuZGxlcnM6IHRydWUsXG4gICAgYWxsb3dSYXdTdGF0ZW1lbnRzOiBmYWxzZSxcbiAgICBmb3JjZVByZXBhcmVTaW1wbGVRdWVyaWVzOiB0cnVlLFxuICAgIGZvcmNlUHJlcGFyZUNvbXBsZXhRdWVyaWVzOiB0cnVlLFxuICAgIGFsbG93R2VuZXJhdGlvbk92ZXJyaWRlOiBmYWxzZSxcbiAgfSk7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlcj86IEEsIGNsYXp6PzogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBzdXBlcihhZGFwdGVyLCBjbGF6eik7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGtleToga2V5b2YgTSxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24sXG4gICAgcmVmOiBPbWl0PERpcmVjdGlvbkxpbWl0T2Zmc2V0LCBcImRpcmVjdGlvblwiPiA9IHtcbiAgICAgIG9mZnNldDogMSxcbiAgICAgIGxpbWl0OiAxMCxcbiAgICB9LFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8U2VyaWFsaXplZFBhZ2U8TT4+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLlBBR0VfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5wYWdpbmF0ZUJ5KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBwYWdpbmF0aW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB3aXRoIHBhZ2Ugc2l6ZSAke3JlZi5saW1pdH1gXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnQoXG4gICAgICB0aGlzLnBhZ2luYXRlQnkubmFtZSxcbiAgICAgIGtleSxcbiAgICAgIG9yZGVyLFxuICAgICAgeyBsaW1pdDogcmVmLmxpbWl0LCBvZmZzZXQ6IHJlZi5vZmZzZXQsIGJvb2ttYXJrOiByZWYuYm9va21hcmsgfSxcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgbGlzdEJ5KFxuICAgIGtleToga2V5b2YgTSxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKSB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFByZXBhcmVkU3RhdGVtZW50S2V5cy5MSVNUX0JZLCB0cnVlKVxuICAgICkuZm9yKHRoaXMubGlzdEJ5KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBsaXN0aW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSBieSAke2tleSBhcyBzdHJpbmd9ICR7b3JkZXJ9YFxuICAgICk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnN0YXRlbWVudChcbiAgICAgIHRoaXMubGlzdEJ5Lm5hbWUsXG4gICAgICBrZXksXG4gICAgICBvcmRlcixcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApKSBhcyBhbnk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBmaW5kQnkoXG4gICAga2V5OiBrZXlvZiBNLFxuICAgIHZhbHVlOiBhbnksXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkZJTkRfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5maW5kQnkpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYGZpbmRpbmcgYWxsICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB3aXRoICR7a2V5IGFzIHN0cmluZ30gJHt2YWx1ZX1gXG4gICAgKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuc3RhdGVtZW50KFxuICAgICAgdGhpcy5maW5kQnkubmFtZSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICkpIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGZpbmRPbmVCeShcbiAgICBrZXk6IGtleW9mIE0sXG4gICAgdmFsdWU6IGFueSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPE0+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkZJTkRfT05FX0JZLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuZmluZE9uZUJ5KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBmaW5kaW5nIE9uZSAke01vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKX0gd2l0aCAke2tleSBhcyBzdHJpbmd9ICR7dmFsdWV9YFxuICAgICk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnN0YXRlbWVudChcbiAgICAgIHRoaXMuZmluZE9uZUJ5Lm5hbWUsXG4gICAgICBrZXksXG4gICAgICB2YWx1ZSxcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApKSBhcyBhbnk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBzdGF0ZW1lbnQoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCwgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUGVyc2lzdGVuY2VLZXlzLlNUQVRFTUVOVCwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLnN0YXRlbWVudCk7XG4gICAgbG9nLnZlcmJvc2UoYEV4ZWN1dGluZyBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfWApO1xuICAgIGNvbnN0IGNhbGxBcmdzID0gY3R4QXJncy5zbGljZSgwLCAtMSk7XG4gICAgY29uc3QgcmVzdWx0ID0gSlNPTi5wYXJzZShcbiAgICAgIHRoaXMuYWRhcHRlci5kZWNvZGUoXG4gICAgICAgIGF3YWl0IHRoaXMuYWRhcHRlci5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgICAgIGN0eCxcbiAgICAgICAgICBQZXJzaXN0ZW5jZUtleXMuU1RBVEVNRU5ULFxuICAgICAgICAgIFtuYW1lLCBKU09OLnN0cmluZ2lmeShjYWxsQXJncyldLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdGhpcy5jbGFzcy5uYW1lXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIHJlc3VsdC5tYXAoKHI6IGFueSkgPT5cbiAgICAgICAgKHIgYXMgYW55KVtDb3VjaERCS2V5cy5UQUJMRV0gJiZcbiAgICAgICAgKHIgYXMgYW55KVtDb3VjaERCS2V5cy5UQUJMRV0gPT09IE1vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKVxuICAgICAgICAgID8gbmV3IHRoaXMuY2xhc3MocilcbiAgICAgICAgICA6IHJcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiAocmVzdWx0IGFzIGFueSlbQ291Y2hEQktleXMuVEFCTEVdICYmXG4gICAgICAocmVzdWx0IGFzIGFueSlbQ291Y2hEQktleXMuVEFCTEVdID09PSBNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcylcbiAgICAgID8gbmV3IHRoaXMuY2xhc3MocmVzdWx0KVxuICAgICAgOiBQYWdpbmF0b3IuaXNTZXJpYWxpemVkUGFnZShyZXN1bHQpXG4gICAgICAgID8gT2JqZWN0LmFzc2lnbihyZXN1bHQsIHtcbiAgICAgICAgICAgIGRhdGE6IHJlc3VsdC5kYXRhLm1hcCgoZDogYW55KSA9PiBuZXcgdGhpcy5jbGFzcyhkKSksXG4gICAgICAgICAgfSlcbiAgICAgICAgOiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGUoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBDcmVhdGluZyBuZXcgJHt0aGlzLmNsYXNzLm5hbWV9IGluIHRhYmxlICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfWBcbiAgICApO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCBjdHgpO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGUoXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgaWQsXG4gICAgICByZWNvcmQsXG4gICAgICB0cmFuc2llbnQsXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydDxNPihyZWNvcmQsIHRoaXMuY2xhc3MsIGlkLCB0cmFuc2llbnQsIGN0eCk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyB1cGRhdGUoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGUpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCBjdHgpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGB1cGRhdGluZyAke3RoaXMuY2xhc3MubmFtZX0gaW4gdGFibGUgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IHdpdGggaWQgJHtpZH1gXG4gICAgKTtcbiAgICByZWNvcmQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIudXBkYXRlKFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGlkLFxuICAgICAgcmVjb3JkLFxuICAgICAgdHJhbnNpZW50LFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQ8TT4ocmVjb3JkLCB0aGlzLmNsYXNzLCBpZCwgdHJhbnNpZW50LCBjdHgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChcbiAgICBtb2RlbHM6IE1bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPFtNW10sIC4uLmFueVtdLCBDb250ZXh0T2Y8QT5dPiB7XG4gICAgY29uc3QgeyBjdHgsIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIE9wZXJhdGlvbktleXMuQ1JFQVRFLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuY3JlYXRlQWxsUHJlZml4KTtcbiAgICBjb25zdCBpZ25vcmVIYW5kbGVycyA9IGN0eC5nZXQoXCJpZ25vcmVIYW5kbGVyc1wiKTtcbiAgICBjb25zdCBpZ25vcmVWYWxpZGF0ZSA9IGN0eC5nZXQoXCJpZ25vcmVWYWxpZGF0aW9uXCIpO1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIFttb2RlbHMsIC4uLmN0eEFyZ3NdIGFzIGFueTtcblxuICAgIG1vZGVscyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICBtID0gbmV3IHRoaXMuY2xhc3MobSk7XG4gICAgICAgIGlmICghaWdub3JlSGFuZGxlcnMpXG4gICAgICAgICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCBSZXBvc2l0b3J5PE0sIEE+LCBhbnk+KFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgIGN0eCxcbiAgICAgICAgICAgIG0sXG4gICAgICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgICApO1xuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGlmICghaWdub3JlVmFsaWRhdGUpIHtcbiAgICAgIGNvbnN0IGlnbm9yZWRQcm9wcyA9IGN0eC5nZXQoXCJpZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXNcIikgfHwgW107XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBtb2RlbHMubWFwKChtKSA9PiBQcm9taXNlLnJlc29sdmUobS5oYXNFcnJvcnMoLi4uaWdub3JlZFByb3BzKSkpXG4gICAgICApO1xuXG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2VzID0gcmVkdWNlRXJyb3JzVG9QcmludChlcnJvcnMpO1xuXG4gICAgICBpZiAoZXJyb3JNZXNzYWdlcykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJvck1lc3NhZ2VzKTtcbiAgICB9XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmN0eEFyZ3NdIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbChcbiAgICBtb2RlbHM6IE1bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPE1bXT4ge1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIG1vZGVscztcbiAgICBjb25zdCB7IGN0eCwgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZUFsbCk7XG4gICAgbG9nLmRlYnVnKFxuICAgICAgYENyZWF0aW5nICR7bW9kZWxzLmxlbmd0aH0gbmV3ICR7dGhpcy5jbGFzcy5uYW1lfSBpbiB0YWJsZSAke01vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKX1gXG4gICAgKTtcblxuICAgIGNvbnN0IHByZXBhcmVkID0gbW9kZWxzLm1hcCgobSkgPT4gdGhpcy5hZGFwdGVyLnByZXBhcmUobSwgY3R4KSk7XG4gICAgY29uc3QgaWRzID0gcHJlcGFyZWQubWFwKChwKSA9PiBwLmlkKTtcbiAgICBsZXQgcmVjb3JkcyA9IHByZXBhcmVkLm1hcCgocCkgPT4gcC5yZWNvcmQpO1xuICAgIGNvbnN0IHRyYW5zaWVudCA9IHByZXBhcmVkLm1hcCgocCkgPT4gcC50cmFuc2llbnQpO1xuICAgIHJlY29yZHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuY3JlYXRlQWxsKFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGlkcyBhcyBQcmltYXJ5S2V5VHlwZVtdLFxuICAgICAgcmVjb3JkcyxcbiAgICAgIHRyYW5zaWVudCxcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApO1xuICAgIHJldHVybiByZWNvcmRzLm1hcCgociwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQoXG4gICAgICAgIHIsXG4gICAgICAgIHRoaXMuY2xhc3MsXG4gICAgICAgIGlkc1tpXSxcbiAgICAgICAgY3R4LmdldChcInJlYnVpbGRXaXRoVHJhbnNpZW50XCIpID8gcHJlcGFyZWRbaV0udHJhbnNpZW50IDogdW5kZWZpbmVkLFxuICAgICAgICBjdHhcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlQWxsKFxuICAgIG1vZGVsczogTVtdLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGVBbGwpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBVcGRhdGluZyAke21vZGVscy5sZW5ndGh9IG5ldyAke3RoaXMuY2xhc3MubmFtZX0gaW4gdGFibGUgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9YFxuICAgICk7XG5cbiAgICBjb25zdCByZWNvcmRzID0gbW9kZWxzLm1hcCgobSkgPT4gdGhpcy5hZGFwdGVyLnByZXBhcmUobSwgY3R4KSk7XG4gICAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IHRoaXMuYWRhcHRlci51cGRhdGVBbGwoXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIuaWQpLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIucmVjb3JkKSxcbiAgICAgIHJlY29yZHMubWFwKChyKSA9PiByLnRyYW5zaWVudCksXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgICByZXR1cm4gdXBkYXRlZC5tYXAoKHUsIGkpID0+XG4gICAgICB0aGlzLmFkYXB0ZXIucmV2ZXJ0KFxuICAgICAgICB1LFxuICAgICAgICB0aGlzLmNsYXNzLFxuICAgICAgICByZWNvcmRzW2ldLmlkLFxuICAgICAgICBjdHguZ2V0KFwicmVidWlsZFdpdGhUcmFuc2llbnRcIikgPyByZWNvcmRzW2ldLnRyYW5zaWVudCA6IHVuZGVmaW5lZCxcbiAgICAgICAgY3R4XG4gICAgICApXG4gICAgKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQmFzZU1vZGVsLCBjb2x1bW4sIHBrLCB0YWJsZSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgbW9kZWwsIHR5cGUgTW9kZWxBcmcsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCB0b2tlbiBtZXRhZGF0YSBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBFUkMyMCB0b2tlbiBkZWZpbml0aW9uIHdpdGhpbiB0aGUgRmFicmljIEVSQzIwIHNhbXBsZSwgaW5jbHVkaW5nIG5hbWUsIHN5bWJvbCwgZGVjaW1hbHMsIGFuZCB0aGUgb3duaW5nIGlkZW50aXR5LiBVc2VkIHRvIGRlZmluZSB0aGUgdW5pcXVlIHRva2VuIG1hbmFnZWQgYnkgdGhlIGNvbnRyYWN0LlxuICogQHBhcmFtIHtNb2RlbEFyZzxFUkMyMFRva2VuPn0gW21dIC0gT3B0aW9uYWwgcGFydGlhbCBkYXRhIG9yIGFub3RoZXIgaW5zdGFuY2UgdG8gaW5pdGlhbGl6ZSB0aGUgbW9kZWxcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRVJDMjBUb2tlblxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHRva2VuID0gbmV3IEVSQzIwVG9rZW4oeyBuYW1lOiBcIk15VG9rZW5cIiwgc3ltYm9sOiBcIk1US1wiLCBkZWNpbWFsczogMTgsIG93bmVyOiBcIng1MDk6Oi4uLlwiIH0pO1xuICogLy8gUGVyc2lzdCB0aHJvdWdoIGEgcmVwb3NpdG9yeTogYXdhaXQgcmVwby5jcmVhdGUodG9rZW4sIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBBcHAtPj5SZXBvOiBjcmVhdGUobmV3IEVSQzIwVG9rZW4oey4uLn0pLCBjdHgpXG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBjcmVhdGUodGFibGUsIGlkPW5hbWUsIHJlY29yZCwgZmxhZ3MpXG4gKiAgIEFkYXB0ZXItLT4+UmVwbzogc3RvcmVkXG4gKiAgIFJlcG8tLT4+QXBwOiBtb2RlbFxuICovXG5AdGFibGUoXCJlcmMyMF90b2tlbnNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBUb2tlbiBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIEBwayh7IHR5cGU6IFN0cmluZyB9KVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRva2VuIHVuaXF1ZSBuYW1lXG4gICAqIEBzdW1tYXJ5IFNlcnZlcyBhcyB0aGUgcHJpbWFyeSBrZXkgZm9yIHRoZSBFUkMyMCB0b2tlbiBkZWZpbml0aW9uOyB0eXBpY2FsbHkgYSBodW1hbi1yZWFkYWJsZSBpZGVudGlmaWVyXG4gICAqL1xuICBuYW1lITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE93bmluZyBpZGVudGl0eSBvZiB0aGUgdG9rZW5cbiAgICogQHN1bW1hcnkgWC41MDkgc3ViamVjdCBvciBNU1AgaWRlbnRpdHkgc3RyaW5nIHRoYXQgZGVub3RlcyB3aG8gb3ducy9jb250cm9scyB0aGUgdG9rZW4gZGVmaW5pdGlvblxuICAgKi9cbiAgb3duZXIhOiBzdHJpbmc7XG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRva2VuIHN5bWJvbFxuICAgKiBAc3VtbWFyeSBTaG9ydCB0aWNrZXItbGlrZSBzeW1ib2wgdXNlZCB0byByZXByZXNlbnQgdGhlIHRva2VuIChlLmcuLCBNVEspXG4gICAqL1xuICBzeW1ib2whOiBzdHJpbmc7XG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlY2ltYWwgcHJlY2lzaW9uIGZvciB0b2tlbiBhbW91bnRzXG4gICAqIEBzdW1tYXJ5IE51bWJlciBvZiBkaWdpdHMgYWZ0ZXIgdGhlIGRlY2ltYWwgc2VwYXJhdG9yIHVzZWQgd2hlbiBmb3JtYXR0aW5nIHRva2VuIGJhbGFuY2VzXG4gICAqL1xuICBkZWNpbWFscyE6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihtPzogTW9kZWxBcmc8RVJDMjBXYWxsZXQ+KSB7XG4gICAgc3VwZXIobSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRVJDMjAgd2FsbGV0IG1vZGVsXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgaG9sZGVyIGFjY291bnQgZm9yIGFuIEVSQzIwIHRva2VuIHdpdGhpbiB0aGUgRmFicmljIG5ldHdvcmssIHRyYWNraW5nIGJhbGFuY2UgYW5kIHRva2VuIGFzc29jaWF0aW9uLlxuICogQHBhcmFtIHtNb2RlbEFyZzxFUkMyMFdhbGxldD59IFttXSAtIE9wdGlvbmFsIHBhcnRpYWwgZGF0YSBvciBhbm90aGVyIGluc3RhbmNlIHRvIGluaXRpYWxpemUgdGhlIG1vZGVsXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEVSQzIwV2FsbGV0XG4gKiBAZXhhbXBsZVxuICogY29uc3Qgd2FsbGV0ID0gbmV3IEVSQzIwV2FsbGV0KHsgaWQ6IFwiYWNjdDFcIiwgdG9rZW46IFwiTXlUb2tlblwiLCBiYWxhbmNlOiAxMDAwIH0pO1xuICogLy8gVXBkYXRlIGJhbGFuY2UgdmlhIHJlcG9zaXRvcnk6IGF3YWl0IHJlcG8udXBkYXRlKHdhbGxldCwgY3R4KVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgUmVwb1xuICogICBBcHAtPj5SZXBvOiByZWFkKFwiYWNjdDFcIiwgY3R4KVxuICogICBSZXBvLS0+PkFwcDogRVJDMjBXYWxsZXRcbiAqL1xuQHRhYmxlKFwiZXJjMjBfd2FsbGV0c1wiKVxuQG1vZGVsKClcbmV4cG9ydCBjbGFzcyBFUkMyMFdhbGxldCBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIEBwayh7IHR5cGU6IFN0cmluZyB9KVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdhbGxldCB1bmlxdWUgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSBmb3IgdGhlIHdhbGxldDsgY29tbW9ubHkgcmVmZXJlbmNlcyBhbiBhY2NvdW50IG9yIGlkZW50aXR5XG4gICAqL1xuICBpZCE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc3NvY2lhdGVkIHRva2VuIG5hbWVcbiAgICogQHN1bW1hcnkgUmVmZXJlbmNlcyB0aGUgRVJDMjBUb2tlbiB0aGlzIHdhbGxldCBob2xkczsgbWFpbnRhaW5lZCBhcyBhIHJlbGF0aW9uc2hpcCBmb3IgY2FzY2FkaW5nIHVwZGF0ZXMvZGVsZXRlc1xuICAgKi9cbiAgdG9rZW4hOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVG9rZW4gYmFsYW5jZSBmb3IgdGhpcyB3YWxsZXRcbiAgICogQHN1bW1hcnkgQ3VycmVudCBhbW91bnQgb2YgdGhlIGFzc29jaWF0ZWQgdG9rZW4gaGVsZCBieSB0aGlzIHdhbGxldFxuICAgKi9cbiAgYmFsYW5jZSE6IG51bWJlcjtcblxuICBAY29sdW1uKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDYXB0aXZlIGZsYWcgb3IgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBPcHRpb25hbCBmaWVsZCB1c2VkIGJ5IHNvbWUgZmxvd3MgdG8gbWFyayBub24tdHJhbnNmZXJhYmxlIGZ1bmRzIG9yIG1hbmFnZWQgY3VzdG9keVxuICAgKi9cbiAgY2FwdGl2ZSE6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihtPzogTW9kZWxBcmc8RVJDMjBXYWxsZXQ+KSB7XG4gICAgc3VwZXIobSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRVJDMjAgYWxsb3dhbmNlIG1vZGVsXG4gKiBAc3VtbWFyeSBDYXB0dXJlcyBhbiBhcHByb3ZhbCByZWxhdGlvbnNoaXAgd2hlcmUgYW4gb3duZXIgYWxsb3dzIGEgc3BlbmRlciB0byB0cmFuc2ZlciB1cCB0byBhIGNlcnRhaW4gdmFsdWUgZnJvbSB0aGUgb3duZXIncyB3YWxsZXQuXG4gKiBAcGFyYW0ge01vZGVsQXJnPEFsbG93YW5jZT59IFttXSAtIE9wdGlvbmFsIHBhcnRpYWwgZGF0YSBvciBhbm90aGVyIGluc3RhbmNlIHRvIGluaXRpYWxpemUgdGhlIG1vZGVsXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEFsbG93YW5jZVxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGFsbG93YW5jZSA9IG5ldyBBbGxvd2FuY2UoeyBvd25lcjogXCJhY2N0MVwiLCBzcGVuZGVyOiBcImFjY3QyXCIsIHZhbHVlOiA1MCB9KTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIEFwcC0+PkFwcDogbmV3IEFsbG93YW5jZSh7IG93bmVyLCBzcGVuZGVyLCB2YWx1ZSB9KVxuICovXG5AdGFibGUoXCJlcmMyMF9hbGxvd2FuY2VzXCIpXG5AbW9kZWwoKVxuZXhwb3J0IGNsYXNzIEFsbG93YW5jZSBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIEBwayh7IHR5cGU6IFN0cmluZyB9KVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFsbG93YW5jZSB1bmlxdWUgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSBmb3IgdGhlIGFsbG93YW5jZTsgdHlwaWNhbGx5IGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBhcHByb3ZhbCByZWxhdGlvbnNoaXBcbiAgICovXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE93bmVyIHdhbGxldCBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFdhbGxldCB0aGF0IGF1dGhvcml6ZXMgdGhlIGFsbG93YW5jZVxuICAgKi9cbiAgb3duZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3BlbmRlciB3YWxsZXQgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBXYWxsZXQgYWxsb3dlZCB0byBzcGVuZCB1cCB0byB0aGUgYXBwcm92ZWQgdmFsdWUgZnJvbSB0aGUgb3duZXJcbiAgICovXG4gIHNwZW5kZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXBwcm92ZWQgdmFsdWVcbiAgICogQHN1bW1hcnkgTWF4aW11bSB0b2tlbiBhbW91bnQgdGhlIHNwZW5kZXIgbWF5IHRyYW5zZmVyIG9uIGJlaGFsZiBvZiB0aGUgb3duZXJcbiAgICovXG4gIHZhbHVlITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKG0/OiBNb2RlbEFyZzxBbGxvd2FuY2U+KSB7XG4gICAgc3VwZXIobSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEpTT05TZXJpYWxpemVyLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBTZXJpYWxpemF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDbGllbnQtc2lkZSBKU09OIHNlcmlhbGl6ZXIgZm9yIERlY2FmIG1vZGVscyB0YXJnZXRpbmcgSHlwZXJsZWRnZXIgRmFicmljXG4gKiBAc3VtbWFyeSBFeHRlbmRzIHRoZSBiYXNlIEpTT05TZXJpYWxpemVyIHRvIGVtYmVkIG1vZGVsIG1ldGFkYXRhIChhbmNob3IpIHJlcXVpcmVkIHRvIHJlY29uc3RydWN0IGluc3RhbmNlcyBvbiB0aGUgY2xpZW50LCBhbmQgdG8gc2FmZWx5IHNlcmlhbGl6ZS9kZXNlcmlhbGl6ZSBGYWJyaWMtYm91bmQgbW9kZWxzLlxuICogQHRlbXBsYXRlIE0gZXh0ZW5kcyBNb2RlbCAtIFRoZSBEZWNhZiBtb2RlbCB0eXBlIGhhbmRsZWQgYnkgdGhpcyBzZXJpYWxpemVyXG4gKiBAcGFyYW0ge3ZvaWR9IFtjb25zdHJ1Y3Rvcl0gTm8gcHVibGljIGNvbnN0cnVjdG9yIGFyZ3VtZW50czsgcHJvdmlkZWQgZm9yIGRvY3VtZW50YXRpb24gY29tcGxldGVuZXNzXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIENsaWVudFNlcmlhbGl6ZXJcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBzZXJpYWxpemVyID0gbmV3IENsaWVudFNlcmlhbGl6ZXI8VXNlcj4oKTtcbiAqIGNvbnN0IGpzb24gPSBzZXJpYWxpemVyLnNlcmlhbGl6ZShuZXcgVXNlcih7IGlkOiBcIjFcIiwgbmFtZTogXCJBbGljZVwiIH0pKTtcbiAqIGNvbnN0IHVzZXIgPSBzZXJpYWxpemVyLmRlc2VyaWFsaXplKGpzb24pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgU2VyaWFsaXplciBhcyBDbGllbnRTZXJpYWxpemVyXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIEFwcC0+PlNlcmlhbGl6ZXI6IHNlcmlhbGl6ZShtb2RlbClcbiAqICAgU2VyaWFsaXplci0+PlNlcmlhbGl6ZXI6IHByZVNlcmlhbGl6ZShtb2RlbClcbiAqICAgU2VyaWFsaXplci0tPj5BcHA6IEpTT04gc3RyaW5nXG4gKiAgIEFwcC0+PlNlcmlhbGl6ZXI6IGRlc2VyaWFsaXplKGpzb24pXG4gKiAgIFNlcmlhbGl6ZXItPj5TZXJpYWxpemVyOiBKU09OLnBhcnNlKGpzb24pXG4gKiAgIFNlcmlhbGl6ZXItPj5Nb2RlbDogTW9kZWwuYnVpbGQocGFyc2VkLCBhbmNob3IpXG4gKiAgIE1vZGVsLS0+PkFwcDogaW5zdGFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIENsaWVudFNlcmlhbGl6ZXI8TSBleHRlbmRzIE1vZGVsPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmUgYSBtb2RlbCBmb3IgSlNPTiBzZXJpYWxpemF0aW9uIGVtYmVkZGluZyBjbGFzcyBhbmNob3JcbiAgICogQHN1bW1hcnkgQ2xvbmVzIHRoZSBtb2RlbCBhbmQgaW5qZWN0cyB0aGUgY2xhc3MgbWV0YWRhdGEgYW5jaG9yIHNvIGl0IGNhbiBiZSByZWNvbnN0cnVjdGVkIGR1cmluZyBkZXNlcmlhbGl6YXRpb24uIEZhbGxzIGJhY2sgdG8gcHJvdmlkZWQgdGFibGUgbmFtZSBpZiBtZXRhZGF0YSBpcyBub3QgYXZhaWxhYmxlLlxuICAgKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGUgaGFuZGxlZCBieSB0aGlzIHNlcmlhbGl6ZXJcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBzZXJpYWxpemVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFttb2RlbE5hbWVdIC0gT3B0aW9uYWwgdGFibGUgbmFtZSB0byB1c2Ugd2hlbiBtZXRhZGF0YSBjYW5ub3QgYmUgZGVyaXZlZFxuICAgKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBBIHBsYWluIG9iamVjdCByZWFkeSB0byBiZSBKU09OLnN0cmluZ2lmeSdkXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNLCBtb2RlbE5hbWU/OiBzdHJpbmcpIHtcbiAgICAvLyBUT0RPOiBuZXN0ZWQgcHJlc2VyaWFsaXphdGlvbiAoc28gaW5jcmVhc2UgcGVyZm9ybWFuY2Ugd2hlbiBkZXNlcmlhbGl6aW5nKVxuICAgIGNvbnN0IHRvU2VyaWFsaXplOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gT2JqZWN0LmFzc2lnbih7fSwgbW9kZWwpO1xuICAgIGxldCBtZXRhZGF0YSA9IE1ldGFkYXRhLm1vZGVsTmFtZShtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPik7XG5cbiAgICBpZiAoIW1ldGFkYXRhIHx8IG1ldGFkYXRhID09PSBcIk9iamVjdFwiKVxuICAgICAgaWYgKG1vZGVsTmFtZSkgbWV0YWRhdGEgPSBtb2RlbE5hbWU7XG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgYENvdWxkIG5vdCBmaW5kIG1ldGFkYXRhIGZvciAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICAgICApO1xuICAgIHRvU2VyaWFsaXplW01vZGVsS2V5cy5BTkNIT1JdID0gbWV0YWRhdGE7XG4gICAgcmV0dXJuIHRvU2VyaWFsaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWJ1aWxkcyBhIG1vZGVsIGZyb20gaXRzIEpTT04gc2VyaWFsaXphdGlvblxuICAgKiBAc3VtbWFyeSBQYXJzZXMgdGhlIEpTT04gc3RyaW5nLCByZXRyaWV2ZXMgdGhlIGVtYmVkZGVkIG1vZGVsIGFuY2hvciwgYW5kIHVzZXMgTW9kZWwuYnVpbGQgdG8gcmVjb25zdHJ1Y3QgdGhlIG9yaWdpbmFsIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBUaGUgSlNPTiBzdHJpbmcgcHJldmlvdXNseSBwcm9kdWNlZCBieSBzZXJpYWxpemVcbiAgICogQHJldHVybiB7TX0gVGhlIHJlY29uc3RydWN0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIG92ZXJyaWRlIGRlc2VyaWFsaXplKHN0cjogc3RyaW5nKTogTSB7XG4gICAgY29uc3QgZGVzZXJpYWxpemF0aW9uID0gSlNPTi5wYXJzZShzdHIpO1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGRlc2VyaWFsaXphdGlvbltNb2RlbEtleXMuQU5DSE9SXTtcbiAgICBpZiAoIWNsYXNzTmFtZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBmaW5kIGNsYXNzIHJlZmVyZW5jZSBpbiBzZXJpYWxpemVkIG1vZGVsXCIpO1xuICAgIGNvbnN0IG1vZGVsOiBNID0gTW9kZWwuYnVpbGQoZGVzZXJpYWxpemF0aW9uLCBjbGFzc05hbWUpIGFzIHVua25vd24gYXMgTTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNlcmlhbGl6ZXMgYSBtb2RlbCB0byBhIEpTT04gc3RyaW5nXG4gICAqIEBzdW1tYXJ5IFByZXBhcmVzIHRoZSBtb2RlbCB2aWEgcHJlU2VyaWFsaXplLCBlbWJlZGRpbmcgbWV0YWRhdGEgbmVlZGVkIGZvciByZWNvbnN0cnVjdGlvbiwgYW5kIHJldHVybnMgYSBKU09OIHN0cmluZyByZXByZXNlbnRhdGlvblxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHNlcmlhbGl6ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3RhYmxlXSAtIE9wdGlvbmFsIHRhYmxlIG5hbWUgdG8gaW5jbHVkZSBhcyBhbmNob3Igd2hlbiBtZXRhZGF0YSBpcyB1bmF2YWlsYWJsZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEEgSlNPTiBzdHJpbmcgY29udGFpbmluZyB0aGUgc2VyaWFsaXplZCBtb2RlbCB3aXRoIGFuY2hvciBtZXRhZGF0YVxuICAgKi9cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNLCBtb2RlbE5hbWU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLnByZVNlcmlhbGl6ZShtb2RlbCwgbW9kZWxOYW1lKSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEZhYnJpY0NsaWVudFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vRmFicmljQ2xpZW50UmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgRVJDMjBUb2tlbiwgRVJDMjBXYWxsZXQgfSBmcm9tIFwiLi4vLi4vY29udHJhY3RzL2VyYzIwL21vZGVsc1wiO1xuaW1wb3J0IHsgTW9kZWwsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRBZGFwdGVyIH0gZnJvbSBcIi4uL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7IENsaWVudFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL0NsaWVudFNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIENvbnRleHQsXG4gIENvbnRleHRPZixcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIEV2ZW50SWRzLFxuICBNYXliZUNvbnRleHR1YWxBcmcsXG4gIFNlcXVlbmNlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7XG4gIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyxcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuLyoqXG4gKiBSZXBvc2l0b3J5IGZvciBpbnRlcmFjdGluZyB3aXRoIEVSQzIwIGNvbnRyYWN0cyBvbiBhIEh5cGVybGVkZ2VyIEZhYnJpYyBuZXR3b3JrLlxuICogRXh0ZW5kcyB0aGUgYmFzZSBGYWJyaWNDbGllbnRSZXBvc2l0b3J5IGNsYXNzIGFuZCB1dGlsaXplcyB0aGUgQ2xpZW50U2VyaWFsaXplciBmb3IgZGF0YSBzZXJpYWxpemF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgRmFicmljRVJDMjBDbGllbnRSZXBvc2l0b3J5PFxuICBBIGV4dGVuZHMgRmFicmljQ2xpZW50QWRhcHRlcixcbj4gZXh0ZW5kcyBGYWJyaWNDbGllbnRSZXBvc2l0b3J5PEVSQzIwV2FsbGV0LCBBPiB7XG4gIHByaXZhdGUgc3RhdGljIHNlcmlhbGl6ZXIgPSBuZXcgQ2xpZW50U2VyaWFsaXplcigpO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBzZXJpYWxpemVyOiBTZXJpYWxpemVyPGFueT4gPVxuICAgIEZhYnJpY0VSQzIwQ2xpZW50UmVwb3NpdG9yeS5zZXJpYWxpemVyO1xuXG4gIHByaXZhdGUgc3RhdGljIGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGY4XCIpO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTm90aWZpZXMgYWxsIG9ic2VydmVycyBvZiBhbiBldmVudC5cbiAgICogQHN1bW1hcnkgVXBkYXRlcyBhbGwgcmVnaXN0ZXJlZCBvYnNlcnZlcnMgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBhIGRhdGFiYXNlIGV2ZW50LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUgbmFtZSB3aGVyZSB0aGUgZXZlbnQgb2NjdXJyZWQuXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c3xCdWxrQ3J1ZE9wZXJhdGlvbktleXN8c3RyaW5nfSBldmVudCAtIFRoZSB0eXBlIG9mIGV2ZW50IHRoYXQgb2NjdXJyZWQuXG4gICAqIEBwYXJhbSB7RXZlbnRJZHN9IGlkIC0gVGhlIElEIG9yIElEcyBvZiB0aGUgYWZmZWN0ZWQgcmVjb3Jkcy5cbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBvYnNlcnZlcnMgaGF2ZSBiZWVuIG5vdGlmaWVkLlxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgb2JzZXJ2ZXIgaGFuZGxlciBpcyBub3QgaW5pdGlhbGl6ZWQuXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGVPYnNlcnZlcnM8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZTogQ29uc3RydWN0b3I8TT4gfCBzdHJpbmcsXG4gICAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcsXG4gICAgaWQ6IEV2ZW50SWRzLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLm9ic2VydmVySGFuZGxlcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBcIk9ic2VydmVySGFuZGxlciBub3QgaW5pdGlhbGl6ZWQuIERpZCB5b3UgcmVnaXN0ZXIgYW55IG9ic2VydmFibGVzP1wiXG4gICAgICApO1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZU9ic2VydmVycyk7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgVXBkYXRpbmcgJHt0aGlzLm9ic2VydmVySGFuZGxlci5jb3VudCgpfSBvYnNlcnZlcnMgZm9yICR7dGhpc31gXG4gICAgKTtcblxuICAgIHRhYmxlID0gKFxuICAgICAgdHlwZW9mIHRhYmxlID09PSBcInN0cmluZ1wiID8gTW9kZWwuZ2V0KHRhYmxlKSA6IHRhYmxlXG4gICAgKSBhcyBDb25zdHJ1Y3RvcjxNPjtcbiAgICBsZXQgcGFyc2VkSWQ6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcnNlZElkID0gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpZCkpIHtcbiAgICAgIHBhcnNlZElkID0gaWQubWFwKFxuICAgICAgICAoaSkgPT4gU2VxdWVuY2UucGFyc2VWYWx1ZShNb2RlbC5zZXF1ZW5jZUZvcih0YWJsZSkudHlwZSwgaSkgYXMgc3RyaW5nXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXJzZWRJZCA9IFNlcXVlbmNlLnBhcnNlVmFsdWUoXG4gICAgICAgIE1vZGVsLnNlcXVlbmNlRm9yKHRhYmxlKS50eXBlLFxuICAgICAgICBpZFxuICAgICAgKSBhcyBzdHJpbmc7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMub2JzZXJ2ZXJIYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAgICAgIHRhYmxlLFxuICAgICAgZXZlbnQsXG4gICAgICBwYXJzZWRJZCEsXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGVzIGEgVWludDhBcnJheSBpbnRvIGEgc3RyaW5nIHVzaW5nIHRoZSBUZXh0RGVjb2Rlci5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgVWludDhBcnJheSB0byBkZWNvZGUuXG4gICAqIEByZXR1cm5zIFRoZSBkZWNvZGVkIHN0cmluZy5cbiAgICovXG4gIGRlY29kZShkYXRhOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgICByZXR1cm4gRmFicmljRVJDMjBDbGllbnRSZXBvc2l0b3J5LmRlY29kZXIuZGVjb2RlKGRhdGEpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlcj86IEEpIHtcbiAgICBzdXBlcihhZGFwdGVyLCBFUkMyMFdhbGxldCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBuYW1lIG9mIHRoZSBFUkMyMCB0b2tlbi5cbiAgICpcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBmZXRjaCB0aGUgbmFtZSBvZiB0aGUgRVJDMjAgdG9rZW4uXG4gICAqIEl0IGNhbGxzIHRoZSBcIlRva2VuTmFtZVwiIHRyYW5zYWN0aW9uIG9uIHRoZSBzbWFydCBjb250cmFjdCBhbmQgZGVjb2RlcyB0aGUgcmV0dXJuZWQgZGF0YS5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbmFtZSBvZiB0aGUgRVJDMjAgdG9rZW4uXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMgb3IgdGhlIGRlY29kaW5nIHByb2Nlc3MgZmFpbHMuXG4gICAqL1xuICBhc3luYyB0b2tlbk5hbWUoLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj4pOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSAoYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgXCJ0b2tlbk5hbWVcIiwgdHJ1ZSkpLmZvcihcbiAgICAgIHRoaXMudG9rZW5OYW1lXG4gICAgKTtcbiAgICBjb25zdCBuYW1lID0gYXdhaXQgdGhpcy5hZGFwdGVyLmV2YWx1YXRlVHJhbnNhY3Rpb24oY3R4LCBcIlRva2VuTmFtZVwiKTtcbiAgICByZXR1cm4gdGhpcy5kZWNvZGUobmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzeW1ib2wgb2YgdGhlIEVSQzIwIHRva2VuLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGludGVyYWN0cyB3aXRoIHRoZSBibG9ja2NoYWluIG5ldHdvcmsgdG8gZmV0Y2ggdGhlIHN5bWJvbCBvZiB0aGUgRVJDMjAgdG9rZW4uXG4gICAqIEl0IGNhbGxzIHRoZSBcIlN5bWJvbFwiIHRyYW5zYWN0aW9uIG9uIHRoZSBzbWFydCBjb250cmFjdCBhbmQgZGVjb2RlcyB0aGUgcmV0dXJuZWQgZGF0YS5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgc3ltYm9sIG9mIHRoZSBFUkMyMCB0b2tlbi5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBmYWlscyBvciB0aGUgZGVjb2RpbmcgcHJvY2VzcyBmYWlscy5cbiAgICovXG4gIGFzeW5jIHN5bWJvbCguLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+Pik6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBcInN5bWJvbFwiLCB0cnVlKSkuZm9yKHRoaXMuc3ltYm9sKTtcbiAgICBjb25zdCBzeW1ib2wgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuZXZhbHVhdGVUcmFuc2FjdGlvbihjdHgsIFwiU3ltYm9sXCIpO1xuICAgIHJldHVybiB0aGlzLmRlY29kZShzeW1ib2wpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgRVJDMjAgdG9rZW4uXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBmZXRjaCB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgRVJDMjAgdG9rZW4uXG4gICAqIEl0IGNhbGxzIHRoZSBcIkRlY2ltYWxzXCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0IGFuZCBkZWNvZGVzIHRoZSByZXR1cm5lZCBkYXRhLlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXI+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIHRoZSBFUkMyMCB0b2tlbi5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBmYWlscyBvciB0aGUgZGVjb2RpbmcgcHJvY2VzcyBmYWlscy5cbiAgICovXG4gIGFzeW5jIGRlY2ltYWxzKC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gKGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFwiZGVjaW1hbHNcIiwgdHJ1ZSkpLmZvcihcbiAgICAgIHRoaXMuZGVjaW1hbHNcbiAgICApO1xuICAgIGNvbnN0IGRlY2ltYWxzID0gYXdhaXQgdGhpcy5hZGFwdGVyLmV2YWx1YXRlVHJhbnNhY3Rpb24oY3R4LCBcIkRlY2ltYWxzXCIpO1xuICAgIHJldHVybiBOdW1iZXIodGhpcy5kZWNvZGUoZGVjaW1hbHMpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHRvdGFsIHN1cHBseSBvZiB0aGUgRVJDMjAgdG9rZW4uXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBmZXRjaCB0aGUgdG90YWwgc3VwcGx5IG9mIHRoZSBFUkMyMCB0b2tlbi5cbiAgICogSXQgY2FsbHMgdGhlIFwiVG90YWxTdXBwbHlcIiB0cmFuc2FjdGlvbiBvbiB0aGUgc21hcnQgY29udHJhY3QgYW5kIGRlY29kZXMgdGhlIHJldHVybmVkIGRhdGEuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRvdGFsIHN1cHBseSBvZiB0aGUgRVJDMjAgdG9rZW4uXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMgb3IgdGhlIGRlY29kaW5nIHByb2Nlc3MgZmFpbHMuXG4gICAqL1xuICBhc3luYyB0b3RhbFN1cHBseShcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSAoYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgXCJ0b3RhbFN1cHBseVwiLCB0cnVlKSkuZm9yKFxuICAgICAgdGhpcy50b3RhbFN1cHBseVxuICAgICk7XG4gICAgY29uc3QgdG90YWwgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuZXZhbHVhdGVUcmFuc2FjdGlvbihjdHgsIFwiVG90YWxTdXBwbHlcIik7XG4gICAgcmV0dXJuIE51bWJlcih0aGlzLmRlY29kZSh0b3RhbCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgYmFsYW5jZSBvZiB0aGUgRVJDMjAgdG9rZW4gZm9yIGEgc3BlY2lmaWVkIG93bmVyLlxuICAgKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIGZldGNoIHRoZSBiYWxhbmNlIG9mIHRoZSBFUkMyMCB0b2tlbiBmb3IgYSBnaXZlbiBvd25lci5cbiAgICogSXQgY2FsbHMgdGhlIFwiQmFsYW5jZU9mXCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0IHdpdGggdGhlIHByb3ZpZGVkIG93bmVyJ3MgYWRkcmVzcyBhcyBhIHBhcmFtZXRlci5cbiAgICogVGhlIHJldHVybmVkIGRhdGEgaXMgdGhlbiBkZWNvZGVkIGFuZCBjb252ZXJ0ZWQgdG8gYSBudW1iZXIuXG4gICAqXG4gICAqIEBwYXJhbSBvd25lciAtIFRoZSBhZGRyZXNzIG9mIHRoZSBFUkMyMCB0b2tlbiBvd25lci5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgYmFsYW5jZSBvZiB0aGUgRVJDMjAgdG9rZW4gZm9yIHRoZSBzcGVjaWZpZWQgb3duZXIuXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMgb3IgdGhlIGRlY29kaW5nIHByb2Nlc3MgZmFpbHMuXG4gICAqL1xuICBhc3luYyBiYWxhbmNlT2YoXG4gICAgb3duZXI6IHN0cmluZyxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSAoYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgXCJiYWxhbmNlXCIsIHRydWUpKS5mb3IoXG4gICAgICB0aGlzLmJhbGFuY2VPZlxuICAgICk7XG4gICAgY29uc3QgYmFsYW5jZSA9IGF3YWl0IHRoaXMuYWRhcHRlci5ldmFsdWF0ZVRyYW5zYWN0aW9uKGN0eCwgXCJCYWxhbmNlT2ZcIiwgW1xuICAgICAgb3duZXIsXG4gICAgXSk7XG4gICAgcmV0dXJuIE51bWJlcih0aGlzLmRlY29kZShiYWxhbmNlKSk7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmZXJzIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgdG8gYSByZWNpcGllbnQuXG4gICAqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBUaGlzIGZ1bmN0aW9uIGludGVyYWN0cyB3aXRoIHRoZSBibG9ja2NoYWluIG5ldHdvcmsgdG8gdHJhbnNmZXIgYSBzcGVjaWZpZWQgYW1vdW50IG9mIEVSQzIwIHRva2VucyB0byBhIHJlY2lwaWVudC5cbiAgICogSXQgY2FsbHMgdGhlIFwiVHJhbnNmZXJcIiB0cmFuc2FjdGlvbiBvbiB0aGUgc21hcnQgY29udHJhY3Qgd2l0aCB0aGUgcmVjaXBpZW50J3MgYWRkcmVzcyBhbmQgdGhlIHRyYW5zZmVyIGFtb3VudCBhcyBwYXJhbWV0ZXJzLlxuICAgKiBUaGUgcmV0dXJuZWQgZGF0YSBpcyB0aGVuIGRlY29kZWQgYW5kIGNoZWNrZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSB0cmFuc2ZlciB3YXMgc3VjY2Vzc2Z1bC5cbiAgICpcbiAgICogQHBhcmFtIHRvIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHJlY2lwaWVudC5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgdG8gdHJhbnNmZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGB0cnVlYCBpZiB0aGUgdHJhbnNmZXIgd2FzIHN1Y2Nlc3NmdWwsIGFuZCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBmYWlscyBvciB0aGUgZGVjb2RpbmcgcHJvY2VzcyBmYWlscy5cbiAgICovXG4gIGFzeW5jIHRyYW5zZmVyKFxuICAgIHRvOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlcixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gKGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFwidHJhbnNmZXJcIiwgdHJ1ZSkpLmZvcihcbiAgICAgIHRoaXMudHJhbnNmZXJcbiAgICApO1xuICAgIGNvbnN0IHRyYW5zZmVycmVkID0gYXdhaXQgdGhpcy5hZGFwdGVyLnN1Ym1pdFRyYW5zYWN0aW9uKGN0eCwgXCJUcmFuc2ZlclwiLCBbXG4gICAgICB0byxcbiAgICAgIHZhbHVlLnRvU3RyaW5nKCksXG4gICAgXSk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb2RlKHRyYW5zZmVycmVkKSA9PT0gXCJ0cnVlXCIgPyB0cnVlIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmZXJzIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgZnJvbSBvbmUgYWNjb3VudCB0byBhbm90aGVyLlxuICAgKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIHRyYW5zZmVyIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgZnJvbSBvbmUgYWNjb3VudCB0byBhbm90aGVyLlxuICAgKiBGb3IgdGhpcyB0cmFuc2ZlciB0byB3b3JrIHRoZSBzcGVuZGVyICggYWNjb3VudCB0aGF0IHdpbGwgdHJpZ2dlciB0aGlzIGZ1bmN0aW9uICkgbmVlZCB0byBoYXZlIHRoZSB2YWx1ZSBhcHByb3ZlZCBhcyBhbiBhbGxvd2FuY2UgYnkgdGhlIHNlbmRlci5cbiAgICogSXQgY2FsbHMgdGhlIFwiVHJhbnNmZXJGcm9tXCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0IHdpdGggdGhlIHNlbmRlcidzIGFkZHJlc3MsIHJlY2lwaWVudCdzIGFkZHJlc3MsIGFuZCB0aGUgdHJhbnNmZXIgYW1vdW50IGFzIHBhcmFtZXRlcnMuXG4gICAqIFRoZSByZXR1cm5lZCBkYXRhIGlzIHRoZW4gZGVjb2RlZCBhbmQgY2hlY2tlZCB0byBkZXRlcm1pbmUgaWYgdGhlIHRyYW5zZmVyIHdhcyBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gZnJvbSAtIFRoZSBhZGRyZXNzIG9mIHRoZSBzZW5kZXIuXG4gICAqIEBwYXJhbSB0byAtIFRoZSBhZGRyZXNzIG9mIHRoZSByZWNpcGllbnQuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhbW91bnQgb2YgRVJDMjAgdG9rZW5zIHRvIHRyYW5zZmVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBgdHJ1ZWAgaWYgdGhlIHRyYW5zZmVyIHdhcyBzdWNjZXNzZnVsLCBhbmQgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMgb3IgdGhlIGRlY29kaW5nIHByb2Nlc3MgZmFpbHMuXG4gICAqL1xuICBhc3luYyB0cmFuc2ZlckZyb20oXG4gICAgZnJvbTogc3RyaW5nLFxuICAgIHRvOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlclxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFwidHJhbnNmZXJGcm9tXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLnRyYW5zZmVyRnJvbSk7XG4gICAgY29uc3QgdHJhbnNmZXJyZWQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuc3VibWl0VHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBcIlRyYW5zZmVyRnJvbVwiLFxuICAgICAgW2Zyb20sIHRvLCB2YWx1ZS50b1N0cmluZygpXVxuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy5kZWNvZGUodHJhbnNmZXJyZWQpID09PSBcInRydWVcIiA/IHRydWUgOiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHByb3ZlcyBhIHNwZWNpZmllZCBhbW91bnQgb2YgRVJDMjAgdG9rZW5zIHRvIGJlIHNwZW50IGJ5IGEgc3BlY2lmaWVkIHNwZW5kZXIuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBhcHByb3ZlIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgdG8gYmUgc3BlbnQgYnkgYSBzcGVjaWZpZWQgc3BlbmRlci5cbiAgICogSXQgY2FsbHMgdGhlIFwiQXBwcm92ZVwiIHRyYW5zYWN0aW9uIG9uIHRoZSBzbWFydCBjb250cmFjdCB3aXRoIHRoZSBzcGVuZGVyJ3MgYWRkcmVzcyBhbmQgdGhlIGFwcHJvdmFsIGFtb3VudCBhcyBwYXJhbWV0ZXJzLlxuICAgKiBUaGUgcmV0dXJuZWQgZGF0YSBpcyB0aGVuIGRlY29kZWQgYW5kIGNoZWNrZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSBhcHByb3ZhbCB3YXMgc3VjY2Vzc2Z1bC5cbiAgICpcbiAgICogQHBhcmFtIHNwZW5kZXIgLSBUaGUgYWRkcmVzcyBvZiB0aGUgc3BlbmRlci5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgdG8gYXBwcm92ZSBmb3IgdGhlIHNwZW5kZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGB0cnVlYCBpZiB0aGUgYXBwcm92YWwgd2FzIHN1Y2Nlc3NmdWwsIGFuZCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBmYWlscyBvciB0aGUgZGVjb2RpbmcgcHJvY2VzcyBmYWlscy5cbiAgICovXG4gIGFzeW5jIGFwcHJvdmUoc3BlbmRlcjogc3RyaW5nLCB2YWx1ZTogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBcImFwcHJvdmVcIixcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBbXSxcbiAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgIHRoaXMuX292ZXJyaWRlcyB8fCB7fVxuICAgICk7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXMubG9nQ3R4KGNvbnRleHRBcmdzLmFyZ3MsIHRoaXMuYXBwcm92ZSk7XG4gICAgY29uc3QgYXBwcm92ZWQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuc3VibWl0VHJhbnNhY3Rpb24oY3R4LCBcIkFwcHJvdmVcIiwgW1xuICAgICAgc3BlbmRlcixcbiAgICAgIHZhbHVlLnRvU3RyaW5nKCksXG4gICAgXSk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb2RlKGFwcHJvdmVkKSA9PT0gXCJ0cnVlXCIgPyB0cnVlIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBhbGxvd2FuY2Ugb2YgRVJDMjAgdG9rZW5zIHRoYXQgdGhlIHNwZWNpZmllZCBvd25lciBoYXMgYXBwcm92ZWQgZm9yIGEgc3BlbmRlci5cbiAgICpcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBmZXRjaCB0aGUgYWxsb3dhbmNlIG9mIEVSQzIwIHRva2VucyB0aGF0IHRoZSBzcGVjaWZpZWQgb3duZXIgaGFzIGFwcHJvdmVkIGZvciBhIHNwZW5kZXIuXG4gICAqIEl0IGNhbGxzIHRoZSBcIkFsbG93YW5jZVwiIHRyYW5zYWN0aW9uIG9uIHRoZSBzbWFydCBjb250cmFjdCB3aXRoIHRoZSBvd25lcidzIGFkZHJlc3MgYW5kIHRoZSBzcGVuZGVyJ3MgYWRkcmVzcyBhcyBwYXJhbWV0ZXJzLlxuICAgKiBUaGUgcmV0dXJuZWQgZGF0YSBpcyB0aGVuIGRlY29kZWQgYW5kIGNvbnZlcnRlZCB0byBhIG51bWJlci5cbiAgICpcbiAgICogQHBhcmFtIG93bmVyIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIEVSQzIwIHRva2VuIG93bmVyLlxuICAgKiBAcGFyYW0gc3BlbmRlciAtIFRoZSBhZGRyZXNzIG9mIHRoZSBzcGVuZGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXI+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBhbGxvd2FuY2Ugb2YgRVJDMjAgdG9rZW5zIHRoYXQgdGhlIHNwZWNpZmllZCBvd25lciBoYXMgYXBwcm92ZWQgZm9yIHRoZSBzcGVuZGVyLlxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHRyYW5zYWN0aW9uIGZhaWxzIG9yIHRoZSBkZWNvZGluZyBwcm9jZXNzIGZhaWxzLlxuICAgKi9cbiAgYXN5bmMgYWxsb3dhbmNlKG93bmVyOiBzdHJpbmcsIHNwZW5kZXI6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBcImFsbG93YW5jZVwiLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIFtdLFxuICAgICAgdGhpcy5hZGFwdGVyLFxuICAgICAgdGhpcy5fb3ZlcnJpZGVzIHx8IHt9XG4gICAgKTtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoY29udGV4dEFyZ3MuYXJncywgdGhpcy5hbGxvd2FuY2UpO1xuICAgIGNvbnN0IGFsbG93YW5jZSA9IGF3YWl0IHRoaXMuYWRhcHRlci5zdWJtaXRUcmFuc2FjdGlvbihjdHgsIFwiQWxsb3dhbmNlXCIsIFtcbiAgICAgIG93bmVyLFxuICAgICAgc3BlbmRlcixcbiAgICBdKTtcbiAgICByZXR1cm4gTnVtYmVyKHRoaXMuZGVjb2RlKGFsbG93YW5jZSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBFUkMyMCBjb250cmFjdCB3aXRoIHRoZSBwcm92aWRlZCB0b2tlbiBpbmZvcm1hdGlvbi5cbiAgICpcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRoaXMgZnVuY3Rpb24gaW50ZXJhY3RzIHdpdGggdGhlIGJsb2NrY2hhaW4gbmV0d29yayB0byBpbml0aWFsaXplIHRoZSBFUkMyMCBjb250cmFjdCB3aXRoIHRoZSBnaXZlbiB0b2tlbiBpbmZvcm1hdGlvbi5cbiAgICogSXQgY2FsbHMgdGhlIFwiSW5pdGlhbGl6ZVwiIHRyYW5zYWN0aW9uIG9uIHRoZSBzbWFydCBjb250cmFjdCB3aXRoIHRoZSBzZXJpYWxpemVkIHRva2VuIGRhdGEgYXMgYSBwYXJhbWV0ZXIuXG4gICAqIFRoZSByZXR1cm5lZCBkYXRhIGlzIHRoZW4gZGVjb2RlZCBhbmQgY2hlY2tlZCB0byBkZXRlcm1pbmUgaWYgdGhlIGluaXRpYWxpemF0aW9uIHdhcyBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgRVJDMjAgdG9rZW4gaW5mb3JtYXRpb24gdG8gaW5pdGlhbGl6ZSB0aGUgY29udHJhY3Qgd2l0aC5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYHRydWVgIGlmIHRoZSBpbml0aWFsaXphdGlvbiB3YXMgc3VjY2Vzc2Z1bCwgYW5kIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHRyYW5zYWN0aW9uIGZhaWxzIG9yIHRoZSBkZWNvZGluZyBwcm9jZXNzIGZhaWxzLlxuICAgKi9cbiAgYXN5bmMgaW5pdGlhbGl6ZSh0b2tlbjogRVJDMjBUb2tlbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgXCJpbml0aWFsaXplXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmluaXRpYWxpemUpO1xuICAgIGNvbnN0IGluaXRpbGlhemVkID0gYXdhaXQgdGhpcy5hZGFwdGVyLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgXCJJbml0aWFsaXplXCIsXG4gICAgICBbRmFicmljRVJDMjBDbGllbnRSZXBvc2l0b3J5LnNlcmlhbGl6ZXIuc2VyaWFsaXplKHRva2VuKV1cbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMuZGVjb2RlKGluaXRpbGlhemVkKSA9PT0gXCJ0cnVlXCIgPyB0cnVlIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBFUkMyMCBjb250cmFjdCBoYXMgYmVlbiBpbml0aWFsaXplZC5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIHZlcmlmeSBpZiB0aGUgRVJDMjAgY29udHJhY3QgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAqIEl0IGNhbGxzIHRoZSBcIkNoZWNrSW5pdGlhbGl6ZWRcIiB0cmFuc2FjdGlvbiBvbiB0aGUgc21hcnQgY29udHJhY3QsIHdoaWNoIGRvZXMgbm90IHJlcXVpcmUgYW55IHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBpbml0aWFsaXphdGlvbiBjaGVjayBpcyBjb21wbGV0ZWQuXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMuXG4gICAqL1xuICBhc3luYyBjaGVja0luaXRpYWxpemVkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgXCJjaGVja0luaXRpYWxpemVkXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmNoZWNrSW5pdGlhbGl6ZWQpO1xuICAgIGF3YWl0IHRoaXMuYWRhcHRlci5ldmFsdWF0ZVRyYW5zYWN0aW9uKGN0eCwgXCJDaGVja0luaXRpYWxpemVkXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1pbnRzIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMuXG4gICAqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBUaGlzIGZ1bmN0aW9uIGludGVyYWN0cyB3aXRoIHRoZSBibG9ja2NoYWluIG5ldHdvcmsgdG8gbWludCBhIHNwZWNpZmllZCBhbW91bnQgb2YgRVJDMjAgdG9rZW5zLlxuICAgKiBJdCBjYWxscyB0aGUgXCJNaW50XCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0IHdpdGggdGhlIG1pbnRpbmcgYW1vdW50IGFzIGEgcGFyYW1ldGVyLlxuICAgKiBUaGUgZnVuY3Rpb24gZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZSwgYnV0IGl0IHVwZGF0ZXMgdGhlIG1pbnRlcidzIG51bWJlciBvZiB0b2tlbnMuXG4gICAqXG4gICAqIEBwYXJhbSBhbW91bnQgLSBUaGUgYW1vdW50IG9mIEVSQzIwIHRva2VucyB0byBtaW50LlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbWludGluZyBwcm9jZXNzIGlzIGNvbXBsZXRlZC5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBmYWlscy5cbiAgICovXG4gIGFzeW5jIG1pbnQoYW1vdW50OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFwibWludFwiLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIFtdLFxuICAgICAgdGhpcy5hZGFwdGVyLFxuICAgICAgdGhpcy5fb3ZlcnJpZGVzIHx8IHt9XG4gICAgKTtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoY29udGV4dEFyZ3MuYXJncywgdGhpcy5taW50KTtcbiAgICBhd2FpdCB0aGlzLmFkYXB0ZXIuc3VibWl0VHJhbnNhY3Rpb24oY3R4LCBcIk1pbnRcIiwgW2Ftb3VudC50b1N0cmluZygpXSk7XG4gIH1cblxuICAvKipcbiAgICogQnVybnMgYSBzcGVjaWZpZWQgYW1vdW50IG9mIEVSQzIwIHRva2VucyBmcm9tIHRoZSBtaW50ZXIncyBhY2NvdW50LlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGludGVyYWN0cyB3aXRoIHRoZSBibG9ja2NoYWluIG5ldHdvcmsgdG8gYnVybiBhIHNwZWNpZmllZCBhbW91bnQgb2YgRVJDMjAgdG9rZW5zLlxuICAgKiBJdCBjYWxscyB0aGUgXCJCdXJuXCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0IHdpdGggdGhlIGJ1cm5pbmcgYW1vdW50IGFzIGEgcGFyYW1ldGVyLlxuICAgKiBUaGUgZnVuY3Rpb24gZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZSwgYnV0IGl0IGRlY3JlYXNlcyB0aGUgbWludGVyJ3MgbnVtYmVyIG9mIHRva2Vucy5cbiAgICpcbiAgICogQHBhcmFtIGFtb3VudCAtIFRoZSBhbW91bnQgb2YgRVJDMjAgdG9rZW5zIHRvIGJ1cm4uXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBidXJuaW5nIHByb2Nlc3MgaXMgY29tcGxldGVkLlxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHRyYW5zYWN0aW9uIGZhaWxzLlxuICAgKi9cbiAgYXN5bmMgYnVybihhbW91bnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgXCJidXJuXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmJ1cm4pO1xuICAgIGF3YWl0IHRoaXMuYWRhcHRlci5zdWJtaXRUcmFuc2FjdGlvbihjdHgsIFwiQnVyblwiLCBbYW1vdW50LnRvU3RyaW5nKCldKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdXJucyBhIHNwZWNpZmllZCBhbW91bnQgb2YgRVJDMjAgdG9rZW5zIGZyb20gYSBzcGVjaWZpZWQgYWNjb3VudC5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIGJ1cm4gYSBzcGVjaWZpZWQgYW1vdW50IG9mIEVSQzIwIHRva2VucyBmcm9tIGEgZ2l2ZW4gYWNjb3VudC5cbiAgICogSXQgY2FsbHMgdGhlIFwiQnVybkZyb21cIiB0cmFuc2FjdGlvbiBvbiB0aGUgc21hcnQgY29udHJhY3Qgd2l0aCB0aGUgYWNjb3VudCdzIGFkZHJlc3MgYW5kIHRoZSBidXJuaW5nIGFtb3VudCBhcyBwYXJhbWV0ZXJzLlxuICAgKiBUaGUgZnVuY3Rpb24gZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZSwgYnV0IGl0IGRlY3JlYXNlcyB0aGUgc3BlY2lmaWVkIGFjY291bnQncyBudW1iZXIgb2YgdG9rZW5zLlxuICAgKlxuICAgKiBAcGFyYW0gYWNjb3VudCAtIFRoZSBhZGRyZXNzIG9mIHRoZSBhY2NvdW50IGZyb20gd2hpY2ggdG8gYnVybiB0aGUgRVJDMjAgdG9rZW5zLlxuICAgKiBAcGFyYW0gYW1vdW50IC0gVGhlIGFtb3VudCBvZiBFUkMyMCB0b2tlbnMgdG8gYnVybi5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGJ1cm5pbmcgcHJvY2VzcyBpcyBjb21wbGV0ZWQuXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMuXG4gICAqL1xuICBhc3luYyBidXJuRnJvbShhY2NvdW50OiBzdHJpbmcsIGFtb3VudDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBcImJ1cm5Gcm9tXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmJ1cm5Gcm9tKTtcbiAgICBhd2FpdCB0aGlzLmFkYXB0ZXIuc3VibWl0VHJhbnNhY3Rpb24oY3R4LCBcIkJ1cm5Gcm9tXCIsIFtcbiAgICAgIGFjY291bnQsXG4gICAgICBhbW91bnQudG9TdHJpbmcoKSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIGJhbGFuY2Ugb2YgRVJDMjAgdG9rZW5zIGFzc29jaWF0ZWQgd2l0aCB0aGUgY2xpZW50J3MgYWNjb3VudC5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIGZldGNoIHRoZSBiYWxhbmNlIG9mIEVSQzIwIHRva2VucyBhc3NvY2lhdGVkIHdpdGggdGhlIGNsaWVudCdzIGFjY291bnQuXG4gICAqIEl0IGNhbGxzIHRoZSBcIkNsaWVudEFjY291bnRCYWxhbmNlXCIgdHJhbnNhY3Rpb24gb24gdGhlIHNtYXJ0IGNvbnRyYWN0LCB3aGljaCBkb2VzIG5vdCByZXF1aXJlIGFueSBwYXJhbWV0ZXJzLlxuICAgKiBUaGUgcmV0dXJuZWQgZGF0YSBpcyB0aGVuIGRlY29kZWQgYW5kIGNvbnZlcnRlZCB0byBhIG51bWJlci5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgYmFsYW5jZSBvZiBFUkMyMCB0b2tlbnMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjbGllbnQncyBhY2NvdW50LlxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHRyYW5zYWN0aW9uIGZhaWxzIG9yIHRoZSBkZWNvZGluZyBwcm9jZXNzIGZhaWxzLlxuICAgKi9cbiAgYXN5bmMgY2xpZW50QWNjb3VudEJhbGFuY2UoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFwiYWNjb3VudEJhbGFuY2VcIixcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBbXSxcbiAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgIHRoaXMuX292ZXJyaWRlcyB8fCB7fVxuICAgICk7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXMubG9nQ3R4KGNvbnRleHRBcmdzLmFyZ3MsIHRoaXMuY2xpZW50QWNjb3VudEJhbGFuY2UpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRBY2NvdW50QmFsYW5jZSA9IGF3YWl0IHRoaXMuYWRhcHRlci5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgXCJDbGllbnRBY2NvdW50QmFsYW5jZVwiXG4gICAgKTtcblxuICAgIHJldHVybiBOdW1iZXIodGhpcy5kZWNvZGUoc2VyaWFsaXplZEFjY291bnRCYWxhbmNlKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBjbGllbnQncyBhY2NvdW50IElEIGZyb20gdGhlIGJsb2NrY2hhaW4gbmV0d29yay5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBpbnRlcmFjdHMgd2l0aCB0aGUgYmxvY2tjaGFpbiBuZXR3b3JrIHRvIGZldGNoIHRoZSBjbGllbnQncyBhY2NvdW50IElELlxuICAgKiBJdCBjYWxscyB0aGUgXCJDbGllbnRBY2NvdW50SURcIiB0cmFuc2FjdGlvbiBvbiB0aGUgc21hcnQgY29udHJhY3QsIHdoaWNoIGRvZXMgbm90IHJlcXVpcmUgYW55IHBhcmFtZXRlcnMuXG4gICAqIFRoZSByZXR1cm5lZCBkYXRhIGlzIHRoZW4gZGVjb2RlZCBhbmQgcmV0dXJuZWQgYXMgYSBzdHJpbmcuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNsaWVudCdzIGFjY291bnQgSUQuXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdHJhbnNhY3Rpb24gZmFpbHMgb3IgdGhlIGRlY29kaW5nIHByb2Nlc3MgZmFpbHMuXG4gICAqL1xuICBhc3luYyBjbGllbnRBY2NvdW50SUQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFwiYWNjb3VudElkXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmNsaWVudEFjY291bnRJRCk7XG4gICAgY29uc3QgY2xpZW50QWNjb3VudElEID0gYXdhaXQgdGhpcy5hZGFwdGVyLmV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBcIkNsaWVudEFjY291bnRJRFwiXG4gICAgKTtcblxuICAgIHJldHVybiB0aGlzLmRlY29kZShjbGllbnRBY2NvdW50SUQpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBJbmRleE1ldGFkYXRhLCBPcmRlckRpcmVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IE1vZGVsLCBNb2RlbENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG5leHBvcnQgdHlwZSBJbmRleCA9IHtcbiAgaW5kZXg6IHtcbiAgICBmaWVsZHM6IHN0cmluZ1tdIHwgeyBbazogc3RyaW5nXTogT3JkZXJEaXJlY3Rpb24gfTtcbiAgfTtcbiAgZGRvYz86IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICB0eXBlOiBcImpzb25cIjtcbn07XG5cbmZ1bmN0aW9uIGdldEluZGV4UmVmZXJlbmNlKFxuICBuYW1lOiBzdHJpbmdbXSxcbiAgZGlyZWN0aW9uPzogT3JkZXJEaXJlY3Rpb24sXG4gIGNvbXBvc2l0aW9ucz86IHN0cmluZ1tdXG4pIHtcbiAgcmV0dXJuIFtcbiAgICAuLi5uYW1lLm1hcCgobikgPT4gKG4gPT09IENvdWNoREJLZXlzLlRBQkxFID8gXCJ0YWJsZVwiIDogbikpLFxuICAgIC4uLihjb21wb3NpdGlvbnMgfHwgW10pLFxuICAgIC4uLihkaXJlY3Rpb24gPyBbZGlyZWN0aW9uXSA6IFtdKSxcbiAgICBcImluZGV4XCIsXG4gIF0uam9pbihNZXRhZGF0YS5zcGxpdHRlcik7XG59XG5cbmZ1bmN0aW9uIGFkZEluZGV4KFxuICBhY2N1bTogUmVjb3JkPHN0cmluZywgYW55PixcbiAgZmllbGRzOiBzdHJpbmdbXSxcbiAgZGlyZWN0aW9uPzogT3JkZXJEaXJlY3Rpb24sXG4gIGNvbXBvc2l0aW9ucz86IHN0cmluZ1tdXG4pIHtcbiAgY29uc3QgdGFibGVGaWVsZCA9IGZpZWxkcy5wb3AoKTtcbiAgaWYgKHRhYmxlRmllbGQgJiYgdGFibGVGaWVsZCAhPT0gQ291Y2hEQktleXMuVEFCTEUpIHtcbiAgICBmaWVsZHMucHVzaCh0YWJsZUZpZWxkKTtcbiAgfSBlbHNlIGlmICh0YWJsZUZpZWxkID09PSBDb3VjaERCS2V5cy5UQUJMRSkge1xuICAgIGZpZWxkcy51bnNoaWZ0KHRhYmxlRmllbGQpO1xuICB9XG5cbiAgY29uc3QgbmFtZSA9IGdldEluZGV4UmVmZXJlbmNlKGZpZWxkcywgZGlyZWN0aW9uLCBjb21wb3NpdGlvbnMpO1xuXG4gIGxldCBmOiBzdHJpbmdbXSB8IHsgW2s6IHN0cmluZ106IE9yZGVyRGlyZWN0aW9uIH1bXSA9IFtcbiAgICAuLi5maWVsZHMsXG4gICAgLi4uKGNvbXBvc2l0aW9ucyB8fCBbXSksXG4gIF07XG5cbiAgaWYgKGRpcmVjdGlvbilcbiAgICBmID0gZi5yZWR1Y2UoKGFjY3VtOiB7IFtrOiBzdHJpbmddOiBPcmRlckRpcmVjdGlvbiB9W10sIGVsOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGVudHJ5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICBlbnRyeVtlbF0gPSBkaXJlY3Rpb247XG4gICAgICBhY2N1bS5wdXNoKGVudHJ5KTtcbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBbXSk7XG5cbiAgY29uc3QgaW5kZXg6IEluZGV4ID0ge1xuICAgIGluZGV4OiB7XG4gICAgICBmaWVsZHM6IGYsXG4gICAgfSxcbiAgICBuYW1lOiBuYW1lLFxuICAgIGRkb2M6IG5hbWUsXG4gICAgdHlwZTogXCJqc29uXCIsXG4gIH0gYXMgSW5kZXg7XG5cbiAgYWNjdW1bbmFtZV0gPSBpbmRleDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlTW9kZWxJbmRleGVzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG06IENvbnN0cnVjdG9yPE0+LFxuICBhY2N1bT86IFJlY29yZDxzdHJpbmcsIGFueT5cbik6IEluZGV4W10ge1xuICBjb25zdCB0YWJsZU5hbWUgPSBnZXRJbmRleFJlZmVyZW5jZShbQ291Y2hEQktleXMuVEFCTEVdKTtcbiAgY29uc3QgaW5kZXhlczogUmVjb3JkPHN0cmluZywgSW5kZXg+ID0gYWNjdW0gfHwge307XG4gIGluZGV4ZXNbdGFibGVOYW1lXSA9IHtcbiAgICBpbmRleDoge1xuICAgICAgZmllbGRzOiBbQ291Y2hEQktleXMuVEFCTEVdLFxuICAgIH0sXG4gICAgbmFtZTogdGFibGVOYW1lLFxuICAgIGRkb2M6IHRhYmxlTmFtZSxcbiAgICB0eXBlOiBcImpzb25cIixcbiAgfTtcblxuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcblxuICBjb25zdCBtb2RlbEluZGV4ZXMgPSBNb2RlbC5pbmRleGVzKG0pO1xuICBmb3IgKGNvbnN0IHByb3Agb2YgT2JqZWN0LmtleXMobW9kZWxJbmRleGVzKSkge1xuICAgIGZvciAoY29uc3QgWywgZGVjXSBvZiBPYmplY3QuZW50cmllcyhtb2RlbEluZGV4ZXNbcHJvcF0pKSB7XG4gICAgICBjb25zdCBkaXJlY3Rpb25zID0gKGRlYyBhcyBJbmRleE1ldGFkYXRhKVxuICAgICAgICAuZGlyZWN0aW9ucyBhcyB1bmtub3duIGFzIE9yZGVyRGlyZWN0aW9uW107XG4gICAgICBjb25zdCBjb21wb3NpdGlvbnMgPSAoZGVjIGFzIEluZGV4TWV0YWRhdGEpLmNvbXBvc2l0aW9ucztcbiAgICAgIGNvbnN0IGZpZWxkcyA9IFtwcm9wLCBDb3VjaERCS2V5cy5UQUJMRV07XG5cbiAgICAgIGFkZEluZGV4KHJlc3VsdCwgZmllbGRzKTtcbiAgICAgIGlmIChjb21wb3NpdGlvbnMgJiYgY29tcG9zaXRpb25zLmxlbmd0aClcbiAgICAgICAgYWRkSW5kZXgocmVzdWx0LCBmaWVsZHMsIHVuZGVmaW5lZCwgY29tcG9zaXRpb25zKTtcbiAgICAgIGlmIChkaXJlY3Rpb25zICYmIGRpcmVjdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGRpcmVjdGlvbnMuZm9yRWFjaCgoZCkgPT4ge1xuICAgICAgICAgIGFkZEluZGV4KHJlc3VsdCwgZmllbGRzLCBkKTtcbiAgICAgICAgICBpZiAoY29tcG9zaXRpb25zICYmIGNvbXBvc2l0aW9ucy5sZW5ndGgpXG4gICAgICAgICAgICBhZGRJbmRleChyZXN1bHQsIGZpZWxkcywgZCwgY29tcG9zaXRpb25zKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgT2JqZWN0LmVudHJpZXMocmVzdWx0KS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICBpbmRleGVzW2tleV0gPSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiBPYmplY3QudmFsdWVzKHJlc3VsdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkTW9kZWxGaWxlKGZpbGU6IGFueSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICBjb25zdCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gIGNvbnN0IGV4cG9ydHMgPSByZXF1aXJlKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBmaWxlLnBhcmVudFBhdGgsIGZpbGUubmFtZSkpO1xuXG4gIGNvbnN0IHZhbHVlcyA9IE9iamVjdC52YWx1ZXMoZXhwb3J0cykuZmlsdGVyKChlKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG0gPSBuZXcgKGUgYXMgQ29uc3RydWN0b3IpKCk7XG4gICAgICByZXR1cm4gbSBpbnN0YW5jZW9mIE1vZGVsO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH0pIGFzIE1vZGVsQ29uc3RydWN0b3I8YW55PltdO1xuICByZXR1cm4gdmFsdWVzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE1vZGVsRm9sZGVycyhcbiAgLi4uZm9sZGVyczogc3RyaW5nW11cbik6IFByb21pc2U8TW9kZWxDb25zdHJ1Y3Rvcjxhbnk+W10+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgZnMgPSByZXF1aXJlKFwiZnNcIik7XG5cbiAgY29uc3QgcmVzdWx0OiBNb2RlbENvbnN0cnVjdG9yPGFueT5bXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZm9sZGVyIG9mIGZvbGRlcnMpIHtcbiAgICBjb25zdCBmaWxlcyA9IGZzXG4gICAgICAucmVhZGRpclN5bmMoZm9sZGVyLCB7XG4gICAgICAgIHdpdGhGaWxlVHlwZXM6IHRydWUsXG4gICAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChmOiBhbnkpID0+IGYuaXNGaWxlKCkgJiYgZi5uYW1lLmVuZHNXaXRoKFwianNcIikpO1xuICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgcmVzdWx0LnB1c2goLi4ucmVhZE1vZGVsRmlsZShmaWxlKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUluZGV4ZXMoXG4gIGluZGV4ZXM6IEluZGV4W10sXG4gIHA6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCksXG4gIGNvbGxlY3Rpb24/OiBzdHJpbmdcbikge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICBjb25zdCBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgcGF0aCA9IHJlcXVpcmUoXCJwYXRoXCIpO1xuXG4gIGZ1bmN0aW9uIGVuc3VyZURpcmVjdG9yeUV4aXN0ZW5jZShmaWxlUGF0aDogc3RyaW5nKSB7XG4gICAgY29uc3QgZGlybmFtZTogc3RyaW5nID0gcGF0aC5kaXJuYW1lKGZpbGVQYXRoKSBhcyBzdHJpbmc7XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoZGlybmFtZSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBlbnN1cmVEaXJlY3RvcnlFeGlzdGVuY2UoZGlybmFtZSk7XG4gICAgZnMubWtkaXJTeW5jKGRpcm5hbWUpO1xuICB9XG5cbiAgaW5kZXhlcy5mb3JFYWNoKChpbmRleCkgPT4ge1xuICAgIGNvbnN0IGZpbGUgPSBwYXRoLnJlc29sdmUoXG4gICAgICBwYXRoLmpvaW4oXG4gICAgICAgIHAsXG4gICAgICAgIGAuL01FVEEtSU5GL3N0YXRlZGIvY291Y2hkYi8ke2NvbGxlY3Rpb24gPyBgY29sbGVjdGlvbnMvJHtjb2xsZWN0aW9ufS9gIDogXCJcIn1pbmRleGVzLyR7aW5kZXgubmFtZX0uanNvbmBcbiAgICAgIClcbiAgICApO1xuICAgIGVuc3VyZURpcmVjdG9yeUV4aXN0ZW5jZShmaWxlKTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGUsIEpTT04uc3RyaW5naWZ5KGluZGV4LCB1bmRlZmluZWQsIDIpKTtcbiAgfSk7XG59XG4iLCJpbXBvcnQgeyBCYXNlTW9kZWwsIGNvbHVtbiwgcGsgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IG1vZGVsLCB0eXBlIE1vZGVsQXJnLCByZXF1aXJlZCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGRlc2NyaXB0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIElkZW50aXR5IGNyZWRlbnRpYWwgbW9kZWwgc3RvcmluZyBjcnlwdG9ncmFwaGljIG1hdGVyaWFsc1xuICogQHN1bW1hcnkgSG9sZHMgY2VydGlmaWNhdGUgY2hhaW4gYW5kIHByaXZhdGUga2V5IGluZm9ybWF0aW9uIGZvciBhIEZhYnJpYyBpZGVudGl0eSwgbWFuYWdlZCBhcyBhIHNlcGFyYXRlIGVudGl0eSBsaW5rZWQgZnJvbSBJZGVudGl0eVxuICogQHBhcmFtIHtNb2RlbEFyZzxJZGVudGl0eUNyZWRlbnRpYWxzPn0gW2FyZ10gLSBPcHRpb25hbCBpbml0aWFsaXphdGlvbiBvYmplY3QgdXNlZCB0byBwb3B1bGF0ZSBtb2RlbCBmaWVsZHNcbiAqIEBjbGFzcyBJZGVudGl0eUNyZWRlbnRpYWxzXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGNyZWRlbnRpYWxzIGVudHJ5XG4gKiBjb25zdCBjcmVkcyA9IG5ldyBJZGVudGl0eUNyZWRlbnRpYWxzKHsgaWQ6IFwiY3JlZHMxXCIsIGNlcnRpZmljYXRlOiBcIi4uLlwiLCByb290Q2VydGlmaWNhdGU6IFwiLi4uXCIsIHByaXZhdGVLZXk6IFwiLi4uXCIgfSk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBNb2RlbCBhcyBJZGVudGl0eUNyZWRlbnRpYWxzXG4gKiAgIEFwcC0+Pk1vZGVsOiBuZXcgSWRlbnRpdHlDcmVkZW50aWFscyh7IGlkLCBjZXJ0aWZpY2F0ZSwgcm9vdENlcnRpZmljYXRlLCBwcml2YXRlS2V5IH0pXG4gKiAgIE1vZGVsLS0+PkFwcDogaW5zdGFuY2VcbiAqIEBzZWUgbW9kZWxcbiAqL1xuQG1vZGVsKClcbmV4cG9ydCBjbGFzcyBJZGVudGl0eUNyZWRlbnRpYWxzIGV4dGVuZHMgQmFzZU1vZGVsIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY3JlZGVudGlhbHMgcmVjb3JkXG4gICAqIEBzdW1tYXJ5IFByaW1hcnkga2V5IGZvciByZWZlcmVuY2luZyB0aGlzIGNyZWRlbnRpYWxzIGVudHJ5XG4gICAqL1xuICBAZGVzY3JpcHRpb24oXCJVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY3JlZGVudGlhbHMgcmVjb3JkXCIpXG4gIEBjb2x1bW4oKVxuICBAcGsoKVxuICBpZCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBFTS1lbmNvZGVkIFguNTA5IGNlcnRpZmljYXRlIGZvciB0aGUgaWRlbnRpdHlcbiAgICogQHN1bW1hcnkgTGVhZiBjZXJ0aWZpY2F0ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGlkZW50aXR5XG4gICAqL1xuICBAZGVzY3JpcHRpb24oXCJQRU0tZW5jb2RlZCBYLjUwOSBjZXJ0aWZpY2F0ZSBmb3IgdGhlIGlkZW50aXR5XCIpXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICBjZXJ0aWZpY2F0ZSE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBFTS1lbmNvZGVkIHJvb3Qgb3IgaW50ZXJtZWRpYXRlIGNlcnRpZmljYXRlXG4gICAqIEBzdW1tYXJ5IFJvb3Qgb2YgdHJ1c3QgdXNlZCB0byB2YWxpZGF0ZSB0aGUgbGVhZiBjZXJ0aWZpY2F0ZVxuICAgKi9cbiAgQGRlc2NyaXB0aW9uKFwiUEVNLWVuY29kZWQgcm9vdCBvciBpbnRlcm1lZGlhdGUgY2VydGlmaWNhdGVcIilcbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIHJvb3RDZXJ0aWZpY2F0ZSE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBFTS1lbmNvZGVkIHByaXZhdGUga2V5IG1hdGVyaWFsXG4gICAqIEBzdW1tYXJ5IFByaXZhdGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGlkZW50aXR5IGNlcnRpZmljYXRlXG4gICAqL1xuICBAZGVzY3JpcHRpb24oXCJQRU0tZW5jb2RlZCBwcml2YXRlIGtleVwiKVxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgcHJpdmF0ZUtleSE6IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihhcmc/OiBNb2RlbEFyZzxJZGVudGl0eUNyZWRlbnRpYWxzPikge1xuICAgIHN1cGVyKGFyZyk7XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIEtleXMgdXNlZCB0byBtYXJrIEZhYnJpYy1zcGVjaWZpYyBtb2RlbCBtZXRhZGF0YVxuICogQHN1bW1hcnkgRW51bWVyYXRpb24gb2Ygc3BlY2lhbCBrZXlzIHVzZWQgYnkgdGhlIHNlcmlhbGl6YXRpb24gbGF5ZXIgdG8gcGVyc2lzdCBGYWJyaWMtcmVsYXRlZCBmbGFncyBvbiBtb2RlbHNcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGVudW0gRmFicmljTW9kZWxLZXlzIHtcbiAgLyoqIFByaXZhdGUgZGF0YSBtYXJrZXIgdXNlZCB0byB0YWcgcHJvcGVydGllcyBvciBtb2RlbHMgZm9yIEZhYnJpYyBwcml2YXRlIGNvbGxlY3Rpb25zICovXG4gIFBSSVZBVEUgPSBcInByaXZhdGVcIixcbiAgU0hBUkVEID0gXCJzaGFyZWRcIixcbiAgLyoqIE5hbWVzcGFjZSBwcmVmaXggdXNlZCBmb3IgRmFicmljLXNwZWNpZmljIG1ldGFkYXRhIGtleXMgKi9cbiAgRkFCUklDID0gXCJmYWJyaWNcIixcbiAgT1dORURfQlkgPSBcIm93bmVkLWJ5XCIsXG4gIFRSQU5TQUNUSU9OX0lEID0gXCJ0cmFuc2FjdGlvbi1pZFwiLFxuICBNSVJST1IgPSBcIm1pcnJvclwiLFxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3VwcG9ydGVkIGlkZW50aXR5IHR5cGVzIGZvciBGYWJyaWMgY3JlZGVudGlhbHNcbiAqIEBzdW1tYXJ5IEVudW1lcmF0aW9uIG9mIGlkZW50aXR5IGZvcm1hdHMgcmVjb2duaXplZCBieSB0aGlzIGxpYnJhcnlcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGVudW0gSWRlbnRpdHlUeXBlIHtcbiAgLyoqIFN0YW5kYXJkIFguNTA5IGlkZW50aXR5IGZvcm1hdCB1c2VkIGJ5IEh5cGVybGVkZ2VyIEZhYnJpYyAqL1xuICBYNTA5ID0gXCJYLjUwOVwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdHJpbmcgaWRlbnRpZmllciBmb3IgdGhlIEZhYnJpYyBhZGFwdGVyIGZsYXZvdXJcbiAqIEBzdW1tYXJ5IFVzZWQgdG8gdGFnIGFkYXB0ZXJzL3JlcG9zaXRvcmllcyB0aGF0IG9wZXJhdGUgYWdhaW5zdCBIeXBlcmxlZGdlciBGYWJyaWNcbiAqIEBjb25zdCBGYWJyaWNGbGF2b3VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBjb25zdCBGYWJyaWNGbGF2b3VyID0gXCJobGYtZmFicmljXCI7XG4iLCJpbXBvcnQge1xuICBCYXNlTW9kZWwsXG4gIENhc2NhZGUsXG4gIGNvbHVtbixcbiAgaW5kZXgsXG4gIG9uZVRvT25lLFxuICBwayxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBtb2RlbCwgdHlwZSBNb2RlbEFyZywgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBJZGVudGl0eUNyZWRlbnRpYWxzIH0gZnJvbSBcIi4vSWRlbnRpdHlDcmVkZW50aWFsc1wiO1xuaW1wb3J0IHsgSWRlbnRpdHlUeXBlIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSWRlbnRpdHkgbW9kZWwgcmVwcmVzZW50aW5nIGEgRmFicmljIHdhbGxldCBlbnRyeVxuICogQHN1bW1hcnkgRW5jYXBzdWxhdGVzIGFuIGlkZW50aXR5IHN0b3JlZCBpbiBhIEZhYnJpYyB3YWxsZXQsIGluY2x1ZGluZyBpdHMgTVNQIGlkZW50aWZpZXIsIGNyZWRlbnRpYWwgbGlua2FnZSwgYW5kIHR5cGUgaW5mb3JtYXRpb24uIEJ1aWx0IG9uIEJhc2VNb2RlbCBmb3IgaW50ZWdyYXRpb24gd2l0aCBEZWNhZiB2YWxpZGF0aW9uIGFuZCBwZXJzaXN0ZW5jZS5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8SWRlbnRpdHk+fSBbYXJnXSAtIE9wdGlvbmFsIGluaXRpYWxpemF0aW9uIG9iamVjdCB1c2VkIHRvIHBvcHVsYXRlIG1vZGVsIGZpZWxkc1xuICogQGNsYXNzIElkZW50aXR5XG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgbmV3IGlkZW50aXR5IHJlZmVyZW5jaW5nIGV4aXN0aW5nIGNyZWRlbnRpYWxzXG4gKiBjb25zdCBpZCA9IG5ldyBJZGVudGl0eSh7IGlkOiBcInVzZXIxXCIsIG1zcElkOiBcIk9yZzFNU1BcIiwgdHlwZTogSWRlbnRpdHlUeXBlLlg1MDkgfSk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBNb2RlbCBhcyBJZGVudGl0eVxuICogICBBcHAtPj5Nb2RlbDogbmV3IElkZW50aXR5KHsgaWQsIG1zcElkLCB0eXBlIH0pXG4gKiAgIE1vZGVsLS0+PkFwcDogaW5zdGFuY2VcbiAqL1xuQG1vZGVsKClcbmV4cG9ydCBjbGFzcyBJZGVudGl0eSBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGlkZW50aXR5IGluIHRoZSB3YWxsZXRcbiAgICogQHN1bW1hcnkgUHJpbWFyeSBrZXkgdXNlZCB0byByZWZlcmVuY2UgdGhpcyBpZGVudGl0eSByZWNvcmRcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBpZGVudGl0eVwiKVxuICBAcGsoKVxuICBpZCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpbmsgdG8gdGhlIGlkZW50aXR5IGNyZWRlbnRpYWxzIHN0b3JlZCBzZXBhcmF0ZWx5XG4gICAqIEBzdW1tYXJ5IE9uZS10by1vbmUgcmVsYXRpb25zaGlwIHRvIHRoZSBjcmVkZW50aWFscyBlbnRpdHk7IGNhc2NhZGVzIG9uIHVwZGF0ZSBhbmQgZGVsZXRlXG4gICAqL1xuICBAb25lVG9PbmUoSWRlbnRpdHlDcmVkZW50aWFscywge1xuICAgIHVwZGF0ZTogQ2FzY2FkZS5DQVNDQURFLFxuICAgIGRlbGV0ZTogQ2FzY2FkZS5DQVNDQURFLFxuICB9KVxuICBjcmVkZW50aWFscyE6IElkZW50aXR5Q3JlZGVudGlhbHM7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBUaGUgTVNQIElEIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG9yZ2FuaXphdGlvbiB0aGF0IGlzc3VlZCB0aGlzIGlkZW50aXR5XG4gICAqL1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgQGluZGV4KClcbiAgbXNwSWQhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUeXBlIG9mIGlkZW50aXR5XG4gICAqIEBzdW1tYXJ5IEluZGljYXRlcyB0aGUgaWRlbnRpdHkgZW5jb2RpbmcvZm9ybWF0OyBkZWZhdWx0cyB0byBYLjUwOVxuICAgKi9cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIHR5cGU6IElkZW50aXR5VHlwZSA9IElkZW50aXR5VHlwZS5YNTA5O1xuXG4gIGNvbnN0cnVjdG9yKGFyZzogTW9kZWxBcmc8SWRlbnRpdHk+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgc3RyaW5nRm9ybWF0IH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgTG9nZ2VyLCBNaW5pTG9nZ2VyIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBJZGVudGl0eSwgU2lnbmVyLCBzaWduZXJzIH0gZnJvbSBcIkBoeXBlcmxlZGdlci9mYWJyaWMtZ2F0ZXdheVwiO1xuaW1wb3J0IHsgQ3J5cHRvU2V0dGluZywgSUNyeXB0b1N1aXRlLCBVc2VyIH0gZnJvbSBcImZhYnJpYy1jb21tb25cIjtcbmltcG9ydCB7IEhTTU9wdGlvbnMgfSBmcm9tIFwiLi4vc2hhcmVkL3R5cGVzXCI7XG5pbXBvcnQgeyBub3JtYWxpemVJbXBvcnQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCBjcnlwdG8sIHsgWDUwOUNlcnRpZmljYXRlIH0gZnJvbSBcImNyeXB0b1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb3JlIHV0aWxpdGllcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBmaWxlcywgY3J5cHRvIGlkZW50aXRpZXMsIGFuZCBGYWJyaWMgU0RLIGhlbHBlcnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHN0YXRpYyBoZWxwZXIgbWV0aG9kcyB0byByZWFkIGNyZWRlbnRpYWxzIGFuZCBrZXlzIGZyb20gZGlzayBvciByYXcgY29udGVudCwgY29uc3RydWN0IEZhYnJpYyBnYXRld2F5IElkZW50aXRpZXMgYW5kIFNpZ25lcnMsIGFuZCBwZXJmb3JtIGNvbW1vbiBmaWxlc3lzdGVtIG9wZXJhdGlvbnMgdXNlZCBieSB0aGUgRmFicmljIGNsaWVudCB0b29saW5nLlxuICogQGNsYXNzIENvcmVVdGlsc1xuICogQGV4YW1wbGVcbiAqIC8vIFJlYWQgYW4gaWRlbnRpdHkgYW5kIHNpZ25lciBmcm9tIGRpcmVjdG9yaWVzXG4gKiBjb25zdCBpZGVudGl0eSA9IGF3YWl0IENvcmVVdGlscy5nZXRJZGVudGl0eSgnT3JnMU1TUCcsICcvbXNwL3NpZ25jZXJ0cycpO1xuICogY29uc3Qgc2lnbmVyID0gYXdhaXQgQ29yZVV0aWxzLmdldFNpZ25lcignL21zcC9rZXlzdG9yZScpO1xuICogLy8gQnVpbGQgYSBDQSB1c2VyXG4gKiBjb25zdCB1c2VyID0gYXdhaXQgQ29yZVV0aWxzLmdldENBVXNlcignYXBwVXNlcicsIHBlbUtleSwgcGVtQ2VydCwgJ09yZzFNU1AnKTtcbiAqL1xuZXhwb3J0IGNsYXNzIENvcmVVdGlscyB7XG4gIHByaXZhdGUgc3RhdGljIGxvZ2dlcjogTG9nZ2VyID0gbmV3IE1pbmlMb2dnZXIoQ29yZVV0aWxzLm5hbWUpO1xuXG4gIHByaXZhdGUgc3RhdGljIGNyeXB0b1N1aXRlOiBJQ3J5cHRvU3VpdGU7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlIGZpbGUgY29udGVudCBmcm9tIGEgcGF0aCBvciByZXR1cm4gcHJvdmlkZWQgcmF3IGNvbnRlbnRcbiAgICogQHN1bW1hcnkgSWYgdGhlIGlucHV0IGlzIGEgVWludDhBcnJheSBvciBQRU0gY29udGVudCwgcmV0dXJucyBpdCBhcy1pczsgb3RoZXJ3aXNlIHVzZXMgYSBwcm92aWRlZCBhc3luYyBmaWxlUmVhZGVyIHRvIGxvYWQgdGhlIGNvbnRlbnQgZnJvbSBkaXNrLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xVaW50OEFycmF5fSBjb250ZW50T3JQYXRoIC0gRWl0aGVyIGEgcmF3IGNvbnRlbnQgYnVmZmVyL3N0cmluZyBvciBhIGZpbGVzeXN0ZW0gcGF0aFxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHN0cmluZyk6IFByb21pc2U8c3RyaW5nfFVpbnQ4QXJyYXl8QnVmZmVyPn0gZmlsZVJlYWRlciAtIEFzeW5jIGZ1bmN0aW9uIHRvIHJlYWQgZmlsZSBjb250ZW50IHdoZW4gYSBwYXRoIGlzIHByb3ZpZGVkXG4gICAqIEByZXR1cm4ge1Byb21pc2U8c3RyaW5nfFVpbnQ4QXJyYXl8QnVmZmVyPn0gVGhlIGNvbnRlbnQgdG8gYmUgdXNlZCBkb3duc3RyZWFtXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBhc3luYyBjb250ZW50T2ZMb2FkRmlsZShcbiAgICBjb250ZW50T3JQYXRoOiBzdHJpbmcgfCBVaW50OEFycmF5LFxuICAgIGZpbGVSZWFkZXI6IChwYXRoOiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nIHwgVWludDhBcnJheSB8IEJ1ZmZlcj5cbiAgKSB7XG4gICAgaWYgKGNvbnRlbnRPclBhdGggaW5zdGFuY2VvZiBVaW50OEFycmF5KSByZXR1cm4gY29udGVudE9yUGF0aDtcbiAgICBpZiAoXG4gICAgICBjb250ZW50T3JQYXRoLm1hdGNoKFxuICAgICAgICAvLS0tLS1CRUdJTiAoQ0VSVElGSUNBVEV8S0VZfFBSSVZBVEUgS0VZKS0tLS0tLis/LS0tLS1FTkQgXFwxLS0tLS0kL2dtc1xuICAgICAgKVxuICAgIClcbiAgICAgIHJldHVybiBjb250ZW50T3JQYXRoO1xuICAgIHJldHVybiBhd2FpdCBmaWxlUmVhZGVyKGNvbnRlbnRPclBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkIGZpbGUgY29udGVudCBmcm9tIGEgcGF0aCBvciByZXR1cm4gcHJvdmlkZWQgQnVmZmVyXG4gICAqIEBzdW1tYXJ5IENvbnZlbmllbmNlIHdyYXBwZXIgdGhhdCBsb2FkcyBhIGZpbGUgdXNpbmcgZnMucHJvbWlzZXMgd2hlbiBhIHBhdGggc3RyaW5nIGlzIHByb3ZpZGVkOyBvdGhlcndpc2UgcmV0dXJucyB0aGUgZ2l2ZW4gQnVmZmVyIGRpcmVjdGx5LlxuICAgKiBAcGFyYW0ge3N0cmluZ3xCdWZmZXJ9IGNvbnRlbnRPclBhdGggLSBQYXRoIHRvIGEgZmlsZSBvbiBkaXNrIG9yIGFuIGFscmVhZHktbG9hZGVkIEJ1ZmZlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHN0cmluZ3xVaW50OEFycmF5fEJ1ZmZlcj59IFRoZSBmaWxlIGNvbnRlbnQgYXMgYSBCdWZmZXIvc3RyaW5nIGRlcGVuZGluZyBvbiByZWFkZXJcbiAgICovXG4gIHN0YXRpYyBhc3luYyByZWFkRmlsZShjb250ZW50T3JQYXRoOiBzdHJpbmcgfCBCdWZmZXIpIHtcbiAgICBpZiAodHlwZW9mIGNvbnRlbnRPclBhdGggIT09IFwic3RyaW5nXCIpIHJldHVybiBjb250ZW50T3JQYXRoO1xuXG4gICAgY29uc3QgZmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgICByZXR1cm4gYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUocGF0aCk7XG4gICAgfTtcblxuICAgIHJldHVybiBhd2FpdCBmaWxlUmVhZGVyKGNvbnRlbnRPclBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGUgYSBGYWJyaWMgQ0EgVXNlciBvYmplY3Qgd2l0aCBlbnJvbGxtZW50XG4gICAqIEBzdW1tYXJ5IENvbnN0cnVjdHMgYSBmYWJyaWMtY29tbW9uIFVzZXIsIHNldHMgYSBjcnlwdG8gc3VpdGUsIGltcG9ydHMgdGhlIHByb3ZpZGVkIHByaXZhdGUga2V5LCBhbmQgc2V0cyBlbnJvbGxtZW50IHdpdGggY2VydGlmaWNhdGUgYW5kIE1TUCBJRC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIC0gVGhlIHVzZXIgbmFtZSBmb3IgdGhlIENBIHVzZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHByaXZhdGVLZXkgLSBQRU0tZW5jb2RlZCBwcml2YXRlIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2VydGlmaWNhdGUgLSBQRU0tZW5jb2RlZCBYLjUwOSBjZXJ0aWZpY2F0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbXNwSWQgLSBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgaWRlbnRpZmllclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFVzZXI+fSBUaGUgZW5yb2xsZWQgRmFicmljIFVzZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRDQVVzZXIoXG4gICAgdXNlck5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgY2VydGlmaWNhdGU6IHN0cmluZyxcbiAgICBtc3BJZDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiB7IGhzbT86IEhTTU9wdGlvbnMgfVxuICApOiBQcm9taXNlPFVzZXI+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgIHN0cmluZ0Zvcm1hdChcbiAgICAgICAgXCJDcmVhdGluZyBDQSB7MH0gdXNlciB7MX0gd2l0aCBjZXJ0aWZpY2F0ZSB7Mn1cIixcbiAgICAgICAgbXNwSWQsXG4gICAgICAgIHVzZXJOYW1lLFxuICAgICAgICBjZXJ0aWZpY2F0ZVxuICAgICAgKVxuICAgICk7XG4gICAgY29uc3QgdXNlciA9IG5ldyBVc2VyKHVzZXJOYW1lKTtcbiAgICBjb25zdCBjb25maWcgPSBvcHRpb25zPy5oc21cbiAgICAgID8ge1xuICAgICAgICAgIHNvZnR3YXJlOiBmYWxzZSxcbiAgICAgICAgICBsaWI6IG9wdGlvbnMuaHNtLmxpYnJhcnksXG4gICAgICAgICAgc2xvdDogb3B0aW9ucy5oc20uc2xvdCxcbiAgICAgICAgICBsYWJlbDogb3B0aW9ucy5oc20udG9rZW5MYWJlbCxcbiAgICAgICAgICBwaW46IFN0cmluZyhvcHRpb25zLmhzbS5waW4pLFxuICAgICAgICB9XG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBjcnlwdG9TdWl0ZSA9IHRoaXMuZ2V0Q3J5cHRvU3VpdGUoY29uZmlnKTtcblxuICAgIHVzZXIuc2V0Q3J5cHRvU3VpdGUoY3J5cHRvU3VpdGUpO1xuICAgIGNvbnN0IGVucm9sbG1lbnRLZXkgPSBvcHRpb25zPy5oc21cbiAgICAgID8gYXdhaXQgdGhpcy5nZXRIU01FbnJvbGxtZW50S2V5KGNyeXB0b1N1aXRlLCBjZXJ0aWZpY2F0ZSwgb3B0aW9ucy5oc20pXG4gICAgICA6IHRoaXMuZ2V0U29mdHdhcmVFbnJvbGxtZW50S2V5KGNyeXB0b1N1aXRlLCBwcml2YXRlS2V5KTtcbiAgICBhd2FpdCB1c2VyLnNldEVucm9sbG1lbnQoZW5yb2xsbWVudEtleSwgY2VydGlmaWNhdGUsIG1zcElkKTtcbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXRDcnlwdG9TdWl0ZShvcHRpb25zPzogQ3J5cHRvU2V0dGluZyk6IElDcnlwdG9TdWl0ZSB7XG4gICAgaWYgKCFvcHRpb25zKSByZXR1cm4gVXNlci5uZXdDcnlwdG9TdWl0ZSgpO1xuICAgIGlmIChDb3JlVXRpbHMuY3J5cHRvU3VpdGUpIHJldHVybiBDb3JlVXRpbHMuY3J5cHRvU3VpdGU7XG5cbiAgICBDb3JlVXRpbHMuY3J5cHRvU3VpdGUgPSBVc2VyLm5ld0NyeXB0b1N1aXRlKG9wdGlvbnMpO1xuICAgIHJldHVybiBDb3JlVXRpbHMuY3J5cHRvU3VpdGU7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRTb2Z0d2FyZUVucm9sbG1lbnRLZXkoXG4gICAgY3J5cHRvU3VpdGU6IGFueSxcbiAgICBwcml2YXRlS2V5Pzogc3RyaW5nXG4gICkge1xuICAgIGlmICghcHJpdmF0ZUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlByaXZhdGUga2V5IG11c3QgYmUgcHJvdmlkZWQgd2hlbiBIU00gY29uZmlndXJhdGlvbiBpcyBub3Qgc3VwcGxpZWRcIlxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNyeXB0b1N1aXRlLmNyZWF0ZUtleUZyb21SYXcocHJpdmF0ZUtleSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBhc3luYyBnZXRIU01FbnJvbGxtZW50S2V5KFxuICAgIGNyeXB0b1N1aXRlOiBhbnksXG4gICAgY2VydGlmaWNhdGU6IHN0cmluZyxcbiAgICBoc206IEhTTU9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3Qgc2tpID1cbiAgICAgIGhzbS5rZXlJZEhleCAmJiBoc20ua2V5SWRIZXgudHJpbSgpLmxlbmd0aCA+IDBcbiAgICAgICAgPyBCdWZmZXIuZnJvbShoc20ua2V5SWRIZXgsIFwiaGV4XCIpXG4gICAgICAgIDogYXdhaXQgdGhpcy5nZXRDZXJ0aWZpY2F0ZVNLSShjZXJ0aWZpY2F0ZSk7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgY3J5cHRvU3VpdGUuZ2V0S2V5KHNraSk7XG4gICAgaWYgKCFrZXkgfHwgKHR5cGVvZiBrZXkuaXNQcml2YXRlID09PSBcImZ1bmN0aW9uXCIgJiYgIWtleS5pc1ByaXZhdGUoKSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXNvbHZlIHByaXZhdGUga2V5IGZyb20gSFNNXCIpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5O1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGdldENlcnRpZmljYXRlU0tJKGNlcnRpZmljYXRlOiBzdHJpbmcpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICAgIGNvbnN0IHg1MDkgPSBuZXcgWDUwOUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBqd2sgPSB4NTA5LnB1YmxpY0tleS5leHBvcnQoeyBmb3JtYXQ6IFwiandrXCIgfSk7XG4gICAgY29uc3QgcHJlZml4ID0gQnVmZmVyLmZyb20oWzB4MDRdKTtcbiAgICBjb25zdCB4ID0gQnVmZmVyLmZyb20oandrLnggfHwgXCJcIiwgXCJiYXNlNjR1cmxcIik7XG4gICAgY29uc3QgeSA9IEJ1ZmZlci5mcm9tKGp3ay55IHx8IFwiXCIsIFwiYmFzZTY0dXJsXCIpO1xuICAgIHJldHVybiBjcnlwdG9cbiAgICAgIC5jcmVhdGVIYXNoKFwic2hhMjU2XCIpXG4gICAgICAudXBkYXRlKEJ1ZmZlci5jb25jYXQoW3ByZWZpeCwgeCwgeV0pKVxuICAgICAgLmRpZ2VzdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCdWlsZCBhIEZhYnJpYyBHYXRld2F5IElkZW50aXR5IGZyb20gYW4gTVNQIElEIGFuZCBjZXJ0aWZpY2F0ZVxuICAgKiBAc3VtbWFyeSBSZWFkcyBhIGNlcnRpZmljYXRlIGZyb20gYSBkaXJlY3RvcnkgcGF0aCBvciBhY2NlcHRzIHJhdyBjb250ZW50IGFuZCByZXR1cm5zIGFuIElkZW50aXR5IG9iamVjdCBzdWl0YWJsZSBmb3IgdGhlIEZhYnJpYyBHYXRld2F5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbXNwSWQgLSBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgSURcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNlcnREaXJlY3RvcnlQYXRoIC0gUGF0aCB0byBhIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBjZXJ0aWZpY2F0ZSBmaWxlLCBvciBQRU0gY29udGVudFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gVGhlIGlkZW50aXR5IGNvbnRhaW5pbmcgbXNwSWQgYW5kIGNlcnRpZmljYXRlIGNyZWRlbnRpYWxzXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2V0SWRlbnRpdHkoXG4gICAgbXNwSWQ6IHN0cmluZyxcbiAgICBjZXJ0RGlyZWN0b3J5UGF0aDogc3RyaW5nXG4gICk6IFByb21pc2U8SWRlbnRpdHk+IHtcbiAgICBjb25zdCBpZGVudGl0eUZpbGVSZWFkZXIgPSBhc3luYyAocGF0aDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgICAgY29uc3QgY2VydFBhdGggPSBhd2FpdCB0aGlzLmdldEZpcnN0RGlyRmlsZU5hbWUocGF0aCk7XG4gICAgICBjb25zdCBjcmVkZW50aWFscyA9IGF3YWl0IHByb21pc2VzLnJlYWRGaWxlKGNlcnRQYXRoKTtcbiAgICAgIHJldHVybiBjcmVkZW50aWFscztcbiAgICB9O1xuXG4gICAgY29uc3QgY3JlZGVudGlhbHM6IFVpbnQ4QXJyYXkgPSAoYXdhaXQgdGhpcy5jb250ZW50T2ZMb2FkRmlsZShcbiAgICAgIGNlcnREaXJlY3RvcnlQYXRoLFxuICAgICAgaWRlbnRpdHlGaWxlUmVhZGVyXG4gICAgKSkgYXMgVWludDhBcnJheTtcblxuICAgIHJldHVybiB7IG1zcElkLCBjcmVkZW50aWFscyB9O1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGdldEZpcnN0RGlyRmlsZU5hbWUoZGlyUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIGNvbnN0IHsgam9pbiB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcInBhdGhcIikpO1xuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcHJvbWlzZXMucmVhZGRpcihkaXJQYXRoKTtcbiAgICByZXR1cm4gam9pbihkaXJQYXRoLCBmaWxlc1swXSk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoZGlyUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIGNvbnN0IHsgam9pbiB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcInBhdGhcIikpO1xuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcHJvbWlzZXMucmVhZGRpcihkaXJQYXRoKTtcbiAgICByZXR1cm4gKGF3YWl0IHByb21pc2VzLnJlYWRGaWxlKGpvaW4oZGlyUGF0aCwgZmlsZXNbMF0pKSkudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBnZXRGaWxlQ29udGVudChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIHJldHVybiAoYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUoZmlsZVBhdGgpKS50b1N0cmluZygpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGdldFNpZ25lcihrZXlEaXJlY3RvcnlQYXRoOiBzdHJpbmcpOiBQcm9taXNlPFNpZ25lcj4ge1xuICAgIGNvbnN0IHNpZ25lckZpbGVSZWFkZXIgPSBhc3luYyAocGF0aDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgICAgY29uc3Qga2V5UGF0aCA9IGF3YWl0IHRoaXMuZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICAgIHJldHVybiBhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShrZXlQYXRoKTtcbiAgICB9O1xuXG4gICAgY29uc3QgcHJpdmF0ZUtleVBlbSA9IChhd2FpdCB0aGlzLmNvbnRlbnRPZkxvYWRGaWxlKFxuICAgICAga2V5RGlyZWN0b3J5UGF0aCxcbiAgICAgIHNpZ25lckZpbGVSZWFkZXJcbiAgICApKSBhcyBCdWZmZXI7XG4gICAgY29uc3QgcHJpdmF0ZUtleSA9IGF3YWl0IHRoaXMuZXh0cmFjdFByaXZhdGVLZXkocHJpdmF0ZUtleVBlbSk7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocHJpdmF0ZUtleSk7XG4gICAgY29uc3QgayA9IChwcml2YXRlS2V5IGFzIGFueSlba2V5c1swXV07XG4gICAgLy8gLS1cblxuICAgIHJldHVybiBzaWduZXJzLm5ld1ByaXZhdGVLZXlTaWduZXIoayBhcyBhbnkpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgZXh0cmFjdFByaXZhdGVLZXkocGVtOiBCdWZmZXIpIHtcbiAgICBjb25zdCBsaWJOYW1lID0gXCJjcnlwdG9cIjtcbiAgICBsZXQgc3VidGxlOiBhbnk7XG4gICAgaWYgKFxuICAgICAgKGdsb2JhbFRoaXMgYXMgYW55KS53aW5kb3cgJiZcbiAgICAgICgoZ2xvYmFsVGhpcyBhcyBhbnkpLndpbmRvdyBhcyB7IENyeXB0bzogYW55IH0pLkNyeXB0b1xuICAgICkge1xuICAgICAgc3VidGxlID0gKChnbG9iYWxUaGlzIGFzIGFueSkuQ3J5cHRvIGFzIGFueSkuc3VidGxlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsaWIgPSAoYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChsaWJOYW1lKSkpIGFzIGFueTtcbiAgICAgIHN1YnRsZSA9IGxpYi5zdWJ0bGUgfHwgbGliLndlYmNyeXB0by5zdWJ0bGU7XG4gICAgfVxuXG4gICAgaWYgKCFzdWJ0bGUpIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBsb2FkIFN1YnRsZUNyeXB0byBtb2R1bGVcIik7XG5cbiAgICBmdW5jdGlvbiBzdHIyYWIoc3RyOiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihzdHIubGVuZ3RoKTtcbiAgICAgIGNvbnN0IGJ1ZlZpZXcgPSBuZXcgVWludDhBcnJheShidWYpO1xuICAgICAgZm9yIChsZXQgaSA9IDAsIHN0ckxlbiA9IHN0ci5sZW5ndGg7IGkgPCBzdHJMZW47IGkrKykge1xuICAgICAgICBidWZWaWV3W2ldID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVmO1xuICAgIH1cblxuICAgIGNvbnN0IHN0ciA9IHBlbVxuICAgICAgLnRvU3RyaW5nKFwidXRmOFwiKVxuICAgICAgLnJlcGxhY2UoXCItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cIiwgXCJcIilcbiAgICAgIC5yZXBsYWNlQWxsKFwiXFxuXCIsIFwiXCIpXG4gICAgICAucmVwbGFjZShcIi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cIiwgXCJcIik7XG4gICAgY29uc3QgZGVjb2RlZCA9IEJ1ZmZlci5mcm9tKHN0ciwgXCJiYXNlNjRcIikudG9TdHJpbmcoXCJiaW5hcnlcIik7XG4gICAgY29uc3QgYmluYXJ5RGVyID0gc3RyMmFiKGRlY29kZWQpO1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHN1YnRsZS5pbXBvcnRLZXkoXG4gICAgICBcInBrY3M4XCIsXG4gICAgICBiaW5hcnlEZXIsXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgICAgbmFtZWRDdXJ2ZTogXCJQLTI1NlwiLFxuICAgICAgfSxcbiAgICAgIHRydWUsXG4gICAgICBbXCJzaWduXCJdXG4gICAgKTtcblxuICAgIHJldHVybiBrZXk7XG4gIH1cbn1cbiIsImltcG9ydCAqIGFzIHg1MDkgZnJvbSBcIkBwZWN1bGlhci94NTA5XCI7XG5pbXBvcnQgeyBDcnlwdG8sIENyeXB0b0tleSB9IGZyb20gXCJAcGVjdWxpYXIvd2ViY3J5cHRvXCI7XG5pbXBvcnQgeyBzdHJpbmdGb3JtYXQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBpc0Jyb3dzZXIsIE1pbmlMb2dnZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuY29uc3QgY3J5cHRvID0gbmV3IENyeXB0bygpO1xueDUwOS5jcnlwdG9Qcm92aWRlci5zZXQoY3J5cHRvKTtcblxuZXhwb3J0IGVudW0gQkFTRV9BTFBIQUJFVCB7XG4gIEJBU0UyID0gXCIwMVwiLFxuICBCQVNFOCA9IFwiMDEyMzQ1NjdcIixcbiAgQkFTRTExID0gXCIwMTIzNDU2Nzg5YVwiLFxuICBCQVNFMTYgPSBcIjAxMjM0NTY3ODlhYmNkZWZcIixcbiAgQkFTRTMyID0gXCIwMTIzNDU2Nzg5QUJDREVGR0hKS01OUFFSU1RWV1hZWlwiLFxuICBCQVNFMzJfWiA9IFwieWJuZHJmZzhlamttY3BxeG90MXV3aXN6YTM0NWg3NjlcIixcbiAgQkFTRTM2ID0gXCIwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcIixcbiAgQkFTRTU4ID0gXCIxMjM0NTY3ODlBQkNERUZHSEpLTE1OUFFSU1RVVldYWVphYmNkZWZnaGlqa21ub3BxcnN0dXZ3eHl6XCIsXG4gIEJBU0U2MiA9IFwiMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpcIixcbiAgQkFTRTY0ID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvXCIsXG4gIEJBU0U2NyA9IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODktXy4hflwiLFxufVxuXG5leHBvcnQgdHlwZSBrZXlPYmplY3QgPSB7XG4gIGl2OiBBcnJheUJ1ZmZlcjtcbiAga2V5OiBDcnlwdG9LZXk7XG59O1xuXG5leHBvcnQgZW51bSBDUllQVE8ge1xuICBIQVNIID0gXCJTSEEtMjU2XCIsXG4gIElURVJBVElPTlMgPSAxMDAwLFxuICBLRVlMRU5HVEggPSA0OCxcbiAgREVSSVZFRF9JVl9MRU5HVEggPSAxNixcbiAgREVSSVZFRF9LRVlfTEVOR1RIID0gMzIsIC8vIEJlY2F1c2UgU0hBLTI1NiB1c2VkIGhhcyBhIG5hdGl2ZSBzaXplIG9mIDMyIGJ5dGVzXG4gIEFMR09SWVRITSA9IFwiQUVTLUdDTVwiLFxuICBLRVlfQUxHT1JZVEhNID0gXCJQQktERjJcIixcbn1cblxuZXhwb3J0IGNsYXNzIEJhc2VFbmNvZGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYXNlTWFwOiBVaW50OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoMjU2KTtcbiAgcHJpdmF0ZSByZWFkb25seSBiYXNlOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbGVhZGVyOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZmFjdG9yOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgaUZhY3RvcjogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYWxwaGFiZXQ6IEJBU0VfQUxQSEFCRVQpIHtcbiAgICBpZiAodGhpcy5hbHBoYWJldC5sZW5ndGggPj0gMjU1KSB0aHJvdyBuZXcgRXJyb3IoXCJBbHBoYWJldCB0b28gbG9uZ1wiKTtcblxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5iYXNlTWFwLmxlbmd0aDsgaisrKSB0aGlzLmJhc2VNYXBbal0gPSAyNTU7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFscGhhYmV0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB4ID0gYWxwaGFiZXQuY2hhckF0KGkpO1xuICAgICAgY29uc3QgeGMgPSB4LmNoYXJDb2RlQXQoMCk7XG4gICAgICBpZiAodGhpcy5iYXNlTWFwW3hjXSAhPT0gMjU1KSB0aHJvdyBuZXcgRXJyb3IoeCArIFwiIGlzIGFtYmlndW91c1wiKTtcblxuICAgICAgdGhpcy5iYXNlTWFwW3hjXSA9IGk7XG4gICAgfVxuXG4gICAgdGhpcy5iYXNlID0gdGhpcy5hbHBoYWJldC5sZW5ndGg7XG4gICAgdGhpcy5sZWFkZXIgPSB0aGlzLmFscGhhYmV0LmNoYXJBdCgwKTtcbiAgICB0aGlzLmZhY3RvciA9IE1hdGgubG9nKHRoaXMuYmFzZSkgLyBNYXRoLmxvZygyNTYpOyAvLyBsb2coQkFTRSkgLyBsb2coMjU2KSwgcm91bmRlZCB1cFxuICAgIHRoaXMuaUZhY3RvciA9IE1hdGgubG9nKDI1NikgLyBNYXRoLmxvZyh0aGlzLmJhc2UpOyAvLyBsb2coMjU2KSAvIGxvZyhCQVNFKSwgcm91bmRlZCB1cFxuICB9XG5cbiAgZW5jb2RlKHNvdXJjZTogVWludDhBcnJheSB8IERhdGFWaWV3IHwgYW55W10gfCBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgc291cmNlID0gQnVmZmVyLmZyb20oc291cmNlKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhzb3VyY2UpKSB7XG4gICAgICBzb3VyY2UgPSBuZXcgVWludDhBcnJheShcbiAgICAgICAgc291cmNlLmJ1ZmZlcixcbiAgICAgICAgc291cmNlLmJ5dGVPZmZzZXQsXG4gICAgICAgIHNvdXJjZS5ieXRlTGVuZ3RoXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShzb3VyY2UpKSB7XG4gICAgICBzb3VyY2UgPSBVaW50OEFycmF5LmZyb20oc291cmNlKTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFwiXCI7XG5cbiAgICAvLyBTa2lwICYgY291bnQgbGVhZGluZyB6ZXJvZXMuXG4gICAgbGV0IHplcm9lcyA9IDA7XG4gICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgbGV0IHBiZWdpbiA9IDA7XG4gICAgY29uc3QgcGVuZCA9IHNvdXJjZS5sZW5ndGg7XG4gICAgd2hpbGUgKHBiZWdpbiAhPT0gcGVuZCAmJiBzb3VyY2VbcGJlZ2luXSA9PT0gMCkge1xuICAgICAgcGJlZ2luKys7XG4gICAgICB6ZXJvZXMrKztcbiAgICB9XG4gICAgLy8gQWxsb2NhdGUgZW5vdWdoIHNwYWNlIGluIGJpZy1lbmRpYW4gYmFzZTU4IHJlcHJlc2VudGF0aW9uLlxuICAgIGNvbnN0IHNpemUgPSAoKHBlbmQgLSBwYmVnaW4pICogdGhpcy5pRmFjdG9yICsgMSkgPj4+IDA7XG4gICAgY29uc3QgYjU4ID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gICAgLy8gUHJvY2VzcyB0aGUgYnl0ZXMuXG4gICAgd2hpbGUgKHBiZWdpbiAhPT0gcGVuZCkge1xuICAgICAgbGV0IGNhcnJ5ID0gc291cmNlW3BiZWdpbl07XG4gICAgICAvLyBBcHBseSBcImI1OCA9IGI1OCAqIDI1NiArIGNoXCIuXG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBmb3IgKFxuICAgICAgICBsZXQgaXQxID0gc2l6ZSAtIDE7XG4gICAgICAgIChjYXJyeSAhPT0gMCB8fCBpIDwgbGVuZ3RoKSAmJiBpdDEgIT09IC0xO1xuICAgICAgICBpdDEtLSwgaSsrXG4gICAgICApIHtcbiAgICAgICAgY2FycnkgKz0gKDI1NiAqIGI1OFtpdDFdKSA+Pj4gMDtcbiAgICAgICAgYjU4W2l0MV0gPSBjYXJyeSAlIHRoaXMuYmFzZSA+Pj4gMDtcbiAgICAgICAgY2FycnkgPSAoY2FycnkgLyB0aGlzLmJhc2UpID4+PiAwO1xuICAgICAgfVxuICAgICAgaWYgKGNhcnJ5ICE9PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOb24temVybyBjYXJyeVwiKTtcblxuICAgICAgbGVuZ3RoID0gaTtcbiAgICAgIHBiZWdpbisrO1xuICAgIH1cbiAgICAvLyBTa2lwIGxlYWRpbmcgemVyb2VzIGluIGJhc2U1OCByZXN1bHQuXG4gICAgbGV0IGl0MiA9IHNpemUgLSBsZW5ndGg7XG4gICAgd2hpbGUgKGl0MiAhPT0gc2l6ZSAmJiBiNThbaXQyXSA9PT0gMCkgaXQyKys7XG5cbiAgICAvLyBUcmFuc2xhdGUgdGhlIHJlc3VsdCBpbnRvIGEgc3RyaW5nLlxuICAgIGxldCBzdHIgPSB0aGlzLmxlYWRlci5yZXBlYXQoemVyb2VzKTtcbiAgICBmb3IgKDsgaXQyIDwgc2l6ZTsgKytpdDIpIHtcbiAgICAgIHN0ciArPSB0aGlzLmFscGhhYmV0LmNoYXJBdChiNThbaXQyXSk7XG4gICAgfVxuICAgIHJldHVybiBzdHI7XG4gIH1cblxuICBwcml2YXRlIGRlY29kZVVuc2FmZShzb3VyY2U6IHN0cmluZyk6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQge1xuICAgIGlmIChzb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7XG5cbiAgICBsZXQgcHN6ID0gMDtcbiAgICAvLyBTa2lwIGFuZCBjb3VudCBsZWFkaW5nICcxJ3MuXG4gICAgbGV0IHplcm9lcyA9IDA7XG4gICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgd2hpbGUgKHNvdXJjZVtwc3pdID09PSB0aGlzLmxlYWRlcikge1xuICAgICAgemVyb2VzKys7XG4gICAgICBwc3orKztcbiAgICB9XG4gICAgLy8gQWxsb2NhdGUgZW5vdWdoIHNwYWNlIGluIGJpZy1lbmRpYW4gYmFzZTI1NiByZXByZXNlbnRhdGlvbi5cbiAgICBjb25zdCBzaXplID0gKChzb3VyY2UubGVuZ3RoIC0gcHN6KSAqIHRoaXMuZmFjdG9yICsgMSkgPj4+IDA7IC8vIGxvZyg1OCkgLyBsb2coMjU2KSwgcm91bmRlZCB1cC5cbiAgICBjb25zdCBiMjU2ID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gICAgLy8gUHJvY2VzcyB0aGUgY2hhcmFjdGVycy5cbiAgICB3aGlsZSAoc291cmNlW3Bzel0pIHtcbiAgICAgIC8vIERlY29kZSBjaGFyYWN0ZXJcbiAgICAgIGxldCBjYXJyeSA9IHRoaXMuYmFzZU1hcFtzb3VyY2UuY2hhckNvZGVBdChwc3opXTtcbiAgICAgIC8vIEludmFsaWQgY2hhcmFjdGVyXG4gICAgICBpZiAoY2FycnkgPT09IDI1NSkgcmV0dXJuO1xuXG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBmb3IgKFxuICAgICAgICBsZXQgaXQzID0gc2l6ZSAtIDE7XG4gICAgICAgIChjYXJyeSAhPT0gMCB8fCBpIDwgbGVuZ3RoKSAmJiBpdDMgIT09IC0xO1xuICAgICAgICBpdDMtLSwgaSsrXG4gICAgICApIHtcbiAgICAgICAgY2FycnkgKz0gKHRoaXMuYmFzZSAqIGIyNTZbaXQzXSkgPj4+IDA7XG4gICAgICAgIGIyNTZbaXQzXSA9IGNhcnJ5ICUgMjU2ID4+PiAwO1xuICAgICAgICBjYXJyeSA9IChjYXJyeSAvIDI1NikgPj4+IDA7XG4gICAgICB9XG4gICAgICBpZiAoY2FycnkgIT09IDApIHRocm93IG5ldyBFcnJvcihcIk5vbi16ZXJvIGNhcnJ5XCIpO1xuXG4gICAgICBsZW5ndGggPSBpO1xuICAgICAgcHN6Kys7XG4gICAgfVxuICAgIC8vIFNraXAgbGVhZGluZyB6ZXJvZXMgaW4gYjI1Ni5cbiAgICBsZXQgaXQ0ID0gc2l6ZSAtIGxlbmd0aDtcbiAgICB3aGlsZSAoaXQ0ICE9PSBzaXplICYmIGIyNTZbaXQ0XSA9PT0gMCkgaXQ0Kys7XG5cbiAgICBjb25zdCB2Y2ggPSBuZXcgVWludDhBcnJheSh6ZXJvZXMgKyAoc2l6ZSAtIGl0NCkpO1xuICAgIGxldCBqID0gemVyb2VzO1xuICAgIHdoaWxlIChpdDQgIT09IHNpemUpIHZjaFtqKytdID0gYjI1NltpdDQrK107XG5cbiAgICByZXR1cm4gdmNoO1xuICB9XG5cbiAgZGVjb2RlKHNvdXJjZTogc3RyaW5nKSB7XG4gICAgY29uc3QgYnVmZmVyID0gdGhpcy5kZWNvZGVVbnNhZmUoc291cmNlKTtcbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gYnVmZmVyO1xuICAgIHRocm93IG5ldyBFcnJvcihcIk5vbi1iYXNlXCIgKyB0aGlzLmJhc2UgKyBcIiBjaGFyYWN0ZXJcIik7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENyeXB0b1V0aWxzIHtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgYjU4ZW5jb2RlciA9IG5ldyBCYXNlRW5jb2RlcihCQVNFX0FMUEhBQkVULkJBU0U1OCk7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IGxvZ2dlciA9IG5ldyBNaW5pTG9nZ2VyKENyeXB0b1V0aWxzLm5hbWUpO1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICBzdGF0aWMgZmFicmljSWRGcm9tQ2VydGlmaWNhdGUoY2VydGlmaWNhdGU6IHN0cmluZykge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKHN0cmluZ0Zvcm1hdChcIlBhcnNpbmcgY2VydGlmaWNhdGU6IHswfVwiLCBjZXJ0aWZpY2F0ZSkpO1xuICAgIGNvbnN0IGNlcnQgPSBuZXcgeDUwOS5YNTA5Q2VydGlmaWNhdGUoY2VydGlmaWNhdGUpO1xuICAgIGNvbnN0IHsgc3ViamVjdCwgaXNzdWVyIH0gPSBjZXJ0O1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgc3RyaW5nRm9ybWF0KFxuICAgICAgICBcIkNlcnRpZmljYXRlIHBhcnNlZCB3aXRoIHN1YmplY3QgezB9IGFuZCBpc3N1ZXIgezF9XCIsXG4gICAgICAgIHN1YmplY3QsXG4gICAgICAgIGlzc3VlclxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIGB4NTA5OjovJHtzdWJqZWN0LnJlcGxhY2VBbGwoXCIsIFwiLCBcIi9cIil9OjovJHtpc3N1ZXIucmVwbGFjZUFsbChcIiwgXCIsIFwiL1wiKX1gO1xuICB9XG5cbiAgc3RhdGljIGVuY29kZShzdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYjU4ZW5jb2Rlci5lbmNvZGUoc3RyKTtcbiAgfVxuICBzdGF0aWMgZGVjb2RlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBkZWNvZGVkID0gdGhpcy5iNThlbmNvZGVyLmRlY29kZShzdHIpO1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkZWNvZGVkKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc3RhdGljIHN0cmluZ1RvQXJyYXlCdWZmZXIoc3RyOiBzdHJpbmcpIHtcbiAgICBjb25zdCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoc3RyLmxlbmd0aCk7XG4gICAgY29uc3QgYnVmVmlldyA9IG5ldyBVaW50OEFycmF5KGJ1Zik7XG4gICAgZm9yIChsZXQgaSA9IDAsIHN0ckxlbiA9IHN0ci5sZW5ndGg7IGkgPCBzdHJMZW47IGkrKykge1xuICAgICAgYnVmVmlld1tpXSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgIH1cbiAgICByZXR1cm4gYnVmO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgZXh0cmFjdEtleShcbiAgICB0eXBlOiBcInByaXZhdGVcIiB8IFwicHVibGljXCIsXG4gICAgcGVtOiBCdWZmZXIgfCBzdHJpbmcsXG4gICAgdXNhZ2VzPzogYW55W11cbiAgKSB7XG4gICAgY29uc3Qgc3VidGxlID0gY3J5cHRvLnN1YnRsZTtcblxuICAgIGNvbnN0IHN0ciA9IHBlbVxuICAgICAgLnRvU3RyaW5nKFwidXRmOFwiKVxuICAgICAgLnJlcGxhY2UoXG4gICAgICAgIG5ldyBSZWdFeHAoYC0tLS0tQkVHSU4gKCR7dHlwZS50b1VwcGVyQ2FzZSgpfSBLRVl8Q0VSVElGSUNBVEUpLS0tLS1gKSxcbiAgICAgICAgXCJcIlxuICAgICAgKVxuICAgICAgLnJlcGxhY2VBbGwoXCJcXG5cIiwgXCJcIilcbiAgICAgIC5yZXBsYWNlKFxuICAgICAgICBuZXcgUmVnRXhwKGAtLS0tLUVORCAoJHt0eXBlLnRvVXBwZXJDYXNlKCl9IEtFWXxDRVJUSUZJQ0FURSktLS0tLWApLFxuICAgICAgICBcIlwiXG4gICAgICApO1xuICAgIGNvbnN0IGRlY29kZWQgPSBCdWZmZXIuZnJvbShzdHIsIFwiYmFzZTY0XCIpLnRvU3RyaW5nKFwiYmluYXJ5XCIpO1xuICAgIGNvbnN0IGJpbmFyeURlciA9IHRoaXMuc3RyaW5nVG9BcnJheUJ1ZmZlcihkZWNvZGVkKTtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCBzdWJ0bGUuaW1wb3J0S2V5KFxuICAgICAgXCJwa2NzOFwiLFxuICAgICAgYmluYXJ5RGVyLFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIkVDRFNBXCIsXG4gICAgICAgIG5hbWVkQ3VydmU6IFwiUC0yNTZcIixcbiAgICAgIH0sXG4gICAgICB0cnVlLFxuICAgICAgdXNhZ2VzID8gdXNhZ2VzIDogW1wic2lnblwiXVxuICAgICk7XG5cbiAgICByZXR1cm4ga2V5O1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGV4dHJhY3RQcml2YXRlS2V5KHBlbTogQnVmZmVyIHwgc3RyaW5nLCB1c2FnZXM/OiBhbnlbXSkge1xuICAgIHJldHVybiB0aGlzLmV4dHJhY3RLZXkoXCJwcml2YXRlXCIsIHBlbSwgdXNhZ2VzKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBleHRyYWN0UHVibGljS2V5KHBlbTogQnVmZmVyIHwgc3RyaW5nLCB1c2FnZXM/OiBhbnlbXSkge1xuICAgIHJldHVybiB0aGlzLmV4dHJhY3RLZXkoXCJwdWJsaWNcIiwgcGVtLCB1c2FnZXMpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIHNpZ24ocHJpdmF0ZUtleTogc3RyaW5nLCBkYXRhOiBCdWZmZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHRoaXMuZXh0cmFjdFByaXZhdGVLZXkocHJpdmF0ZUtleSk7XG4gICAgY29uc3QgYnVmZiA9IChhd2FpdCBjcnlwdG8uc3VidGxlLnNpZ24oXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgICAgaGFzaDogXCJTSEEtMjU2XCIsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgZGF0YVxuICAgICkpIGFzIEFycmF5QnVmZmVyO1xuXG4gICAgcmV0dXJuIEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoYnVmZikpXG4gICAgICAubWFwKChiKSA9PiBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCBcIjBcIikpXG4gICAgICAuam9pbihcIlwiKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyB2ZXJpZnkoXG4gICAgY2VydGlmaWNhdGU6IHN0cmluZyxcbiAgICBzaWduYXR1cmU6IEJ1ZmZlciB8IHN0cmluZyxcbiAgICBkYXRhOiBCdWZmZXIgfCBzdHJpbmdcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgY2VydCA9IG5ldyB4NTA5Llg1MDlDZXJ0aWZpY2F0ZShjZXJ0aWZpY2F0ZSk7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgY2VydC5wdWJsaWNLZXkuZXhwb3J0KCk7XG4gICAgc2lnbmF0dXJlID0gKFxuICAgICAgdHlwZW9mIHNpZ25hdHVyZSA9PT0gXCJzdHJpbmdcIiA/IEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSwgXCJoZXhcIikgOiBzaWduYXR1cmVcbiAgICApIGFzIEJ1ZmZlcjtcbiAgICBkYXRhID0gKHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiID8gQnVmZmVyLmZyb20oZGF0YSkgOiBkYXRhKSBhcyBCdWZmZXI7XG4gICAgcmV0dXJuIGNyeXB0by5zdWJ0bGUudmVyaWZ5KFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIkVDRFNBXCIsXG4gICAgICAgIGhhc2g6IFwiU0hBLTI1NlwiLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHNpZ25hdHVyZSxcbiAgICAgIGRhdGFcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGVuY3J5cHQoY2VydGlmaWNhdGU6IHN0cmluZywgZGF0YTogc3RyaW5nIHwgQnVmZmVyKSB7XG4gICAgY29uc3QgY2VydCA9IG5ldyB4NTA5Llg1MDlDZXJ0aWZpY2F0ZShjZXJ0aWZpY2F0ZSk7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgY2VydC5wdWJsaWNLZXkuZXhwb3J0KCk7XG4gICAgZGF0YSA9ICh0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiA/IEJ1ZmZlci5mcm9tKGRhdGEpIDogZGF0YSkgYXMgQnVmZmVyO1xuICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCB0aGlzLmdldFN1YnRsZUNyeXB0bygpLmVuY3J5cHQoXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICBkYXRhXG4gICAgKTtcblxuICAgIHJldHVybiBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGJ1ZmYpKVxuICAgICAgLm1hcCgoYikgPT4gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgXCIwXCIpKVxuICAgICAgLmpvaW4oXCJcIik7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRTdWJ0bGVDcnlwdG8oKSB7XG4gICAgcmV0dXJuIGlzQnJvd3NlcigpXG4gICAgICA/IChnbG9iYWxUaGlzIGFzIGFueSkud2luZG93LmNyeXB0by5zdWJ0bGVcbiAgICAgIDogY3J5cHRvLnN1YnRsZTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBkZWNyeXB0KHByaXZhdGVLZXk6IHN0cmluZywgZGF0YTogc3RyaW5nIHwgQnVmZmVyKSB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5leHRyYWN0UHJpdmF0ZUtleShwcml2YXRlS2V5KTtcbiAgICBkYXRhID0gKFxuICAgICAgdHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIgPyBCdWZmZXIuZnJvbShkYXRhLCBcImhleFwiKSA6IGRhdGFcbiAgICApIGFzIEJ1ZmZlcjtcbiAgICByZXR1cm4gdGhpcy5nZXRTdWJ0bGVDcnlwdG8oKS5kZWNyeXB0KFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIkVDRFNBXCIsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgZGF0YVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBnZXQgYSByYW5kb20gbWFzdGVyIGtleVxuICAgKlxuICAgKiBAZGVzY3JpcHRpb24gSWYgZGF0YSBpcyBub3QgcGFzc2VkLCBhIHJhbmRvbSBBcnJheUJ1ZmZlciB3aWxsIGJlIGdlbmVyYXRlZFxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBkYXRhIGVuY3J5dGlvbiBkYXRhXG4gICAqXG4gICAqIEBmdW5jdGlvbiBnZXRNYXN0ZXJcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRNYXN0ZXIoZGF0YT86IEFycmF5QnVmZmVyKTogUHJvbWlzZTxrZXlPYmplY3Q+IHtcbiAgICBjb25zdCB0ZXh0RW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpO1xuICAgIGlmIChkYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGdlbkdlbmVzaXMgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgICAgZGF0YSA9IHRleHRFbmNvZGVyLmVuY29kZShnZW5HZW5lc2lzKS5idWZmZXI7XG4gICAgfVxuXG4gICAgY29uc3QgaW1wb3J0ZWRLZXkgPSBhd2FpdCB0aGlzLmdldFN1YnRsZUNyeXB0bygpLmltcG9ydEtleShcbiAgICAgIFwicmF3XCIsXG4gICAgICBkYXRhLFxuICAgICAgQ1JZUFRPLktFWV9BTEdPUllUSE0gYXMgc3RyaW5nLFxuICAgICAgZmFsc2UsXG4gICAgICBbXCJkZXJpdmVCaXRzXCJdXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBrZXk6IGltcG9ydGVkS2V5LFxuICAgICAgaXY6IGRhdGEhLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBkZXJpdmUgYSBrZXkgZnJvbSBhbm90aGVyIGtleVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2FsdFxuICAgKiBAcGFyYW0ge0NyeXB0b0tleX0ga2V5IE9yaWdpbmFsIGtleVxuICAgKlxuICAgKiBAZnVuY3Rpb24gZ2V0RGVyaXZhdGlvbktleVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGdldERlcml2YXRpb25LZXkoc2FsdDogc3RyaW5nLCBrZXk6IENyeXB0b0tleSkge1xuICAgIGNvbnN0IHRleHRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG4gICAgY29uc3Qgc2FsdEJ1ZmZlciA9IHRleHRFbmNvZGVyLmVuY29kZShzYWx0KTtcbiAgICBjb25zdCBzYWx0SGFzaGVkID0gYXdhaXQgdGhpcy5nZXRTdWJ0bGVDcnlwdG8oKS5kaWdlc3QoXG4gICAgICBcIlNIQS0yNTZcIixcbiAgICAgIHNhbHRCdWZmZXJcbiAgICApO1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIG5hbWU6IENSWVBUTy5LRVlfQUxHT1JZVEhNIGFzIHN0cmluZyxcbiAgICAgIGhhc2g6IENSWVBUTy5IQVNILFxuICAgICAgc2FsdDogc2FsdEhhc2hlZCxcbiAgICAgIGl0ZXJhdGlvbnM6IENSWVBUTy5JVEVSQVRJT05TLFxuICAgIH07XG4gICAgY29uc3QgZGVyaXZhdGlvbiA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuZGVyaXZlQml0cyhcbiAgICAgIHBhcmFtcyxcbiAgICAgIGtleSxcbiAgICAgIENSWVBUTy5LRVlMRU5HVEggKiA4XG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5nZXRLZXkoZGVyaXZhdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBnZXQgdGhlIGtleSBhbmQgSVYgZnJvbSB0aGUgQ3J5dG9LZXkgYXJyYXlcbiAgICpcbiAgICogQHBhcmFtIHtBcnJheUJ1ZmZlcn0gZGVyaXZhdGlvblxuICAgKlxuICAgKiBAZnVuY3Rpb24gZ2V0S2V5XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2V0S2V5KGRlcml2YXRpb246IEFycmF5QnVmZmVyKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGNvbnN0IGl2bGVuID0gMTY7XG4gICAgY29uc3Qga2V5bGVuID0gMzI7XG4gICAgY29uc3QgZGVyaXZlZEtleSA9IGRlcml2YXRpb24uc2xpY2UoMCwga2V5bGVuKTtcbiAgICBjb25zdCBpdiA9IGRlcml2YXRpb24uc2xpY2Uoa2V5bGVuKTtcbiAgICBjb25zdCBpbXBvcnRlZEVuY3J5cHRpb25LZXkgPSBhd2FpdCB0aGlzLmdldFN1YnRsZUNyeXB0bygpLmltcG9ydEtleShcbiAgICAgIFwicmF3XCIsXG4gICAgICBkZXJpdmVkS2V5LFxuICAgICAgeyBuYW1lOiBDUllQVE8uQUxHT1JZVEhNIGFzIHN0cmluZyB9LFxuICAgICAgZmFsc2UsXG4gICAgICBbXCJlbmNyeXB0XCIsIFwiZGVjcnlwdFwiXVxuICAgICk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGtleTogaW1wb3J0ZWRFbmNyeXB0aW9uS2V5LFxuICAgICAgaXY6IGl2LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBkZWNyeXB0IGRhdGFcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICogQHBhcmFtIHtrZXlPYmplY3R9IGtleU9iamVjdFxuICAgKlxuICAgKiBAZnVuY3Rpb24gZW5jcnlwdFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGVuY3J5cHRQaW4oXG4gICAgdGV4dDogc3RyaW5nLFxuICAgIGtleU9iamVjdDoga2V5T2JqZWN0XG4gICk6IFByb21pc2U8QXJyYXlCdWZmZXI+IHtcbiAgICBjb25zdCB0ZXh0RW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpO1xuICAgIGNvbnN0IHRleHRCdWZmZXIgPSB0ZXh0RW5jb2Rlci5lbmNvZGUodGV4dCk7XG4gICAgY29uc3QgZW5jcnlwdGVkVGV4dCA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuZW5jcnlwdChcbiAgICAgIHsgbmFtZTogQ1JZUFRPLkFMR09SWVRITSBhcyBzdHJpbmcsIGl2OiBrZXlPYmplY3QuaXYgfSxcbiAgICAgIGtleU9iamVjdC5rZXksXG4gICAgICB0ZXh0QnVmZmVyXG4gICAgKTtcbiAgICByZXR1cm4gZW5jcnlwdGVkVGV4dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIGRlY3J5cHQgZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge0J1ZmZlclNvdXJjZX0gZW5jcnlwdGVkVGV4dFxuICAgKiBAcGFyYW0ge2tleU9iamVjdH0ga2V5T2JqZWN0XG4gICAqXG4gICAqIEBmdW5jdGlvbiBkZWNyeXB0XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZGVjcnlwdFBpbihcbiAgICBlbmNyeXB0ZWRUZXh0OiBBcnJheUJ1ZmZlcixcbiAgICBrZXlPYmplY3Q6IGtleU9iamVjdFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCk7XG4gICAgY29uc3QgZGVjcnlwdGVkVGV4dCA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuZGVjcnlwdChcbiAgICAgIHsgbmFtZTogQ1JZUFRPLkFMR09SWVRITSBhcyBzdHJpbmcsIGl2OiBrZXlPYmplY3QuaXYgfSxcbiAgICAgIGtleU9iamVjdC5rZXksXG4gICAgICBlbmNyeXB0ZWRUZXh0XG4gICAgKTtcbiAgICByZXR1cm4gdGV4dERlY29kZXIuZGVjb2RlKGRlY3J5cHRlZFRleHQpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBCYXNlRXJyb3IsIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEF1dGhvcml6YXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuLy8gaW1wb3J0IHsgTUlTU0lOR19QUklWQVRFX0RBVEFfRVJST1JfTUVTU0FHRSB9IGZyb20gXCIuLi9jb250cmFjdHMvcHJpdmF0ZS1kYXRhXCI7XG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gb3ZlcmZsb3cgZXJyb3IgaW4gYXJpdGhtZXRpYyBvcGVyYXRpb25zIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgT3ZlcmZsb3dFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIE92ZXJmbG93RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgT3ZlcmZsb3dFcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGJhbGFuY2UgdG8gcGVyZm9ybSBhIHRyYW5zYWN0aW9uIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgQmFsYW5jZUVycm9yXG4gKiBAZXh0ZW5kcyBJbnRlcm5hbEVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgQmFsYW5jZUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIEJhbGFuY2VFcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGJhbGFuY2UgdG8gcGVyZm9ybSBhIHRyYW5zYWN0aW9uIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgQmFsYW5jZUVycm9yXG4gKiBAZXh0ZW5kcyBJbnRlcm5hbEVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgQWxsb3dhbmNlRXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgQWxsb3dhbmNlRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSByZWdpc3RyYXRpbmcgbmV3IGVudGl0aWVzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBSZWdpc3RyYXRpb25FcnJvclxuICpcbiAqIEBjYXRlZ29ydCBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lzdHJhdGlvbkVycm9yIGV4dGVuZHMgQXV0aG9yaXphdGlvbkVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgUmVnaXN0cmF0aW9uRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXJyb3IgdGhyb3duIHdoZW4gYW4gdW5zdXBwb3J0ZWQgb3BlcmF0aW9uIGlzIGF0dGVtcHRlZFxuICogQHN1bW1hcnkgVGhpcyBlcnJvciBpcyB0aHJvd24gd2hlbiBhbiBvcGVyYXRpb24gaXMgcmVxdWVzdGVkIHRoYXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY3VycmVudFxuICogcGVyc2lzdGVuY2UgYWRhcHRlciBvciBjb25maWd1cmF0aW9uLiBJdCBleHRlbmRzIHRoZSBCYXNlRXJyb3IgY2xhc3MgYW5kIHNldHMgYSA1MDAgc3RhdHVzIGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgYW4gRXJyb3Igb2JqZWN0IHRvIHdyYXBcbiAqIEBjbGFzcyBVbnN1cHBvcnRlZEVycm9yXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gVGhyb3dpbmcgYW4gVW5zdXBwb3J0ZWRFcnJvclxuICogaWYgKCFhZGFwdGVyLnN1cHBvcnRzVHJhbnNhY3Rpb25zKCkpIHtcbiAqICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoJ1RyYW5zYWN0aW9ucyBhcmUgbm90IHN1cHBvcnRlZCBieSB0aGlzIGFkYXB0ZXInKTtcbiAqIH1cbiAqXG4gKiAvLyBDYXRjaGluZyBhbiBVbnN1cHBvcnRlZEVycm9yXG4gKiB0cnkge1xuICogICBhd2FpdCBhZGFwdGVyLmJlZ2luVHJhbnNhY3Rpb24oKTtcbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFVuc3VwcG9ydGVkRXJyb3IpIHtcbiAqICAgICBjb25zb2xlLmVycm9yKCdPcGVyYXRpb24gbm90IHN1cHBvcnRlZDonLCBlcnJvci5tZXNzYWdlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgTWlzc2luZ0NvbnRleHRFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBNaXNzaW5nQ29udGV4dEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvciA9IFwiTUlTU0lOR19QUklWQVRFX0RBVEFfRVJST1JfTUVTU0FHRVwiKSB7XG4gICAgc3VwZXIoVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MubmFtZSwgbXNnLCA0MDMpO1xuICB9XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBlcnJvciB0aGF0IG9jY3VycyB3aGVuIGEgcmVxdWlyZWQgaW5pdGlhbGl6YXRpb24gc3RlcCBpcyBub3QgcGVyZm9ybWVkLlxuICpcbiAqIEBjbGFzcyBOb3RJbml0aWFsaXplZEVycm9yXG4gKiBAZXh0ZW5kcyBCYXNlRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKlxuICogQHBhcmFtIHtzdHJpbmcgfCBFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgYW4gRXJyb3Igb2JqZWN0IHRvIHdyYXAuXG4gKlxuICogQHRocm93cyB7Tm90SW5pdGlhbGl6ZWRFcnJvcn0gLSBUaHJvd3MgYW4gZXJyb3Igd2hlbiBhIHJlcXVpcmVkIGluaXRpYWxpemF0aW9uIHN0ZXAgaXMgbm90IHBlcmZvcm1lZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb25cbiAqIGlmICghaXNJbml0aWFsaXplZCkge1xuICogICB0aHJvdyBuZXcgTm90SW5pdGlhbGl6ZWRFcnJvcignQXBwbGljYXRpb24gaXMgbm90IGluaXRpYWxpemVkJyk7XG4gKiB9XG4gKlxuICogLy8gQ2F0Y2hpbmcgYW4gTm90SW5pdGlhbGl6ZWRFcnJvclxuICogdHJ5IHtcbiAqICAgLy8gUGVyZm9ybSBvcGVyYXRpb25zIHRoYXQgcmVxdWlyZSBpbml0aWFsaXphdGlvblxuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgaWYgKGVycm9yIGluc3RhbmNlb2YgTm90SW5pdGlhbGl6ZWRFcnJvcikge1xuICogICAgIGNvbnNvbGUuZXJyb3IoJ0luaXRpYWxpemF0aW9uIGVycm9yOicsIGVycm9yLm1lc3NhZ2UpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIE5vdEluaXRpYWxpemVkRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoTm90SW5pdGlhbGl6ZWRFcnJvci5uYW1lLCBtc2csIDQwOSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1pc3NpbmdQS0NTUzExTGliIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIE1pc3NpbmdQS0NTUzExTGliLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEVuZG9yc2VtZW50RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBFbmRvcnNlbWVudEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE12Y2NSZWFkQ29uZmxpY3RFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIE12Y2NSZWFkQ29uZmxpY3RFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRW5kb3JzZW1lbnRQb2xpY3lFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIEVuZG9yc2VtZW50UG9saWN5RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuIiwiaW1wb3J0IEZhYnJpY0NBU2VydmljZXMgZnJvbSBcImZhYnJpYy1jYS1jbGllbnRcIjtcbmltcG9ydCB7XG4gIEFmZmlsaWF0aW9uU2VydmljZSxcbiAgSWRlbnRpdHlTZXJ2aWNlLFxuICBJRW5yb2xsUmVzcG9uc2UsXG4gIElSZWdpc3RlclJlcXVlc3QsXG4gIElTZXJ2aWNlUmVzcG9uc2UsXG4gIFRMU09wdGlvbnMsXG59IGZyb20gXCJmYWJyaWMtY2EtY2xpZW50XCI7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSBcImZhYnJpYy1jb21tb25cIjtcbmltcG9ydCB7IENBQ29uZmlnLCBDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi9zaGFyZWQvdHlwZXNcIjtcbmltcG9ydCB7IElkZW50aXR5IH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9tb2RlbC9JZGVudGl0eVwiO1xuaW1wb3J0IHsgQXV0aG9yaXphdGlvbkVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBDb25mbGljdEVycm9yLFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENvcmVVdGlscyB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgQ0FfUk9MRSB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ3J5cHRvVXRpbHMgfSBmcm9tIFwiLi4vY3J5cHRvXCI7XG5pbXBvcnQge1xuICBDZXJ0aWZpY2F0ZVJlc3BvbnNlLFxuICBGYWJyaWNJZGVudGl0eSxcbiAgR2V0Q2VydGlmaWNhdGVzUmVxdWVzdCxcbiAgSWRlbnRpdHlSZXNwb25zZSxcbn0gZnJvbSBcIi4uLy4uL3NoYXJlZC9mYWJyaWMtdHlwZXNcIjtcbmltcG9ydCB7IFJlZ2lzdHJhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9lcnJvcnNcIjtcbmltcG9ydCB7IExvZ2dlZENsYXNzLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEh5cGVybGVkZ2VyIEZhYnJpYyBDQSBpZGVudGl0eSB0eXBlcy5cbiAqIEBzdW1tYXJ5IEVudW1lcmF0ZXMgdGhlIHN1cHBvcnRlZCBpZGVudGl0eSB0eXBlcyByZWNvZ25pemVkIGJ5IEZhYnJpYyBDQSBmb3IgcmVnaXN0cmF0aW9uIGFuZCBpZGVudGl0eSBtYW5hZ2VtZW50LlxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgZW51bSBIRkNBSWRlbnRpdHlUeXBlIHtcbiAgUEVFUiA9IFwicGVlclwiLFxuICBPUkRFUkVSID0gXCJvcmRlcmVyXCIsXG4gIENMSUVOVCA9IFwiY2xpZW50XCIsXG4gIFVTRVIgPSBcInVzZXJcIixcbiAgQURNSU4gPSBcImFkbWluXCIsXG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBLZXkvdmFsdWUgYXR0cmlidXRlIHVzZWQgZHVyaW5nIENBIHJlZ2lzdHJhdGlvbi5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gYXR0cmlidXRlIGVudHJ5IHRoYXQgY2FuIGJlIGF0dGFjaGVkIHRvIGEgRmFicmljIENBIGlkZW50aXR5IGR1cmluZyByZWdpc3RyYXRpb24sIG9wdGlvbmFsbHkgbWFya2luZyBpdCBmb3IgaW5jbHVzaW9uIGluIGVjZXJ0LlxuICogQGludGVyZmFjZSBJS2V5VmFsdWVBdHRyaWJ1dGVcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIEF0dHJpYnV0ZSBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gQXR0cmlidXRlIHZhbHVlLlxuICogQHBhcmFtIHtib29sZWFufSBbZWNlcnRdIC0gV2hldGhlciB0aGUgYXR0cmlidXRlIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgZW5yb2xsbWVudCBjZXJ0aWZpY2F0ZSAoRUNlcnQpLlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgaW50ZXJmYWNlIElLZXlWYWx1ZUF0dHJpYnV0ZSB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsdWU6IHN0cmluZztcbiAgZWNlcnQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdGFuZGFyZCBGYWJyaWMgQ0EgaWRlbnRpdHkgYXR0cmlidXRlIGtleXMuXG4gKiBAc3VtbWFyeSBFbnVtZXJhdGVzIHdlbGwta25vd24gRmFicmljIENBIGF0dHJpYnV0ZSBrZXlzIHRoYXQgY2FuIGJlIGFzc2lnbmVkIHRvIGlkZW50aXRpZXMgZm9yIGRlbGVnYXRpb25zIGFuZCBwZXJtaXNzaW9ucy5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGVudW0gSEZDQUlkZW50aXR5QXR0cmlidXRlcyB7XG4gIEhGUkVHSVNUUkFSUk9MRVMgPSBcImhmLlJlZ2lzdHJhci5Sb2xlc1wiLFxuICBIRlJFR0lTVFJBUkRFTEVHQVRFUk9MRVMgPSBcImhmLlJlZ2lzdHJhci5EZWxlZ2F0ZVJvbGVzXCIsXG4gIEhGUkVHSVNUUkFSQVRUUklCVVRFUyA9IFwiaGYuUmVnaXN0cmFyLkF0dHJpYnV0ZXNcIixcbiAgSEZJTlRFUk1FRElBVEVDQSA9IFwiaGYuSW50ZXJtZWRpYXRlQ0FcIixcbiAgSEZSRVZPS0VSID0gXCJoZi5SZXZva2VyXCIsXG4gIEhGQUZGSUxJQVRJT05NR1IgPSBcImhmLkFmZmlsaWF0aW9uTWdyXCIsXG4gIEhGR0VOQ1JMID0gXCJoZi5HZW5DUkxcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2VydmljZSB3cmFwcGVyIGZvciBpbnRlcmFjdGluZyB3aXRoIGEgRmFicmljIENBLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgaGlnaC1sZXZlbCBvcGVyYXRpb25zIGZvciBtYW5hZ2luZyBpZGVudGl0aWVzIGFnYWluc3QgYSBIeXBlcmxlZGdlciBGYWJyaWMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5LCBpbmNsdWRpbmcgcmVnaXN0cmF0aW9uLCBlbnJvbGxtZW50LCByZXZvY2F0aW9uLCBhbmQgYWRtaW5pc3RyYXRpdmUgcXVlcmllcy4gRW5jYXBzdWxhdGVzIGxvd2VyLWxldmVsIEZhYnJpYyBDQSBjbGllbnQgY2FsbHMgd2l0aCBjb25zaXN0ZW50IGxvZ2dpbmcgYW5kIGVycm9yIG1hcHBpbmcuXG4gKiBAcGFyYW0ge0NBQ29uZmlnfSBjYUNvbmZpZyAtIENvbm5lY3Rpb24gYW5kIFRMUyBjb25maWd1cmF0aW9uIGZvciB0aGUgdGFyZ2V0IENBLlxuICogQGNsYXNzIEZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlXG4gKiBAZXhhbXBsZVxuICogLy8gUmVnaXN0ZXIgYW5kIGVucm9sbCBhIG5ldyB1c2VyXG4gKiBjb25zdCBzdmMgPSBuZXcgRmFicmljRW5yb2xsbWVudFNlcnZpY2Uoe1xuICogICB1cmw6ICdodHRwczovL2xvY2FsaG9zdDo3MDU0JyxcbiAqICAgY2FOYW1lOiAnT3JnMUNBJyxcbiAqICAgdGxzOiB7IHRydXN0ZWRSb290czogWycvcGF0aC90by9jYS5wZW0nXSwgdmVyaWZ5OiBmYWxzZSB9LFxuICogICBjYUNlcnQ6ICcvcGF0aC90by9hZG1pbi9jZXJ0RGlyJyxcbiAqICAgY2FLZXk6ICcvcGF0aC90by9hZG1pbi9rZXlEaXInXG4gKiB9KTtcbiAqIGF3YWl0IHN2Yy5yZWdpc3Rlcih7IHVzZXJOYW1lOiAnYWxpY2UnLCBwYXNzd29yZDogJ3MzY3IzdCcgfSwgZmFsc2UsICdvcmcxLmRlcGFydG1lbnQxJywgQ0FfUk9MRS5VU0VSKTtcbiAqIGNvbnN0IGlkID0gYXdhaXQgc3ZjLmVucm9sbCgnYWxpY2UnLCAnczNjcjN0Jyk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIGF1dG9udW1iZXJcbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFN2YyBhcyBGYWJyaWNFbnJvbGxtZW50U2VydmljZVxuICogICBwYXJ0aWNpcGFudCBDQSBhcyBGYWJyaWMgQ0FcbiAqICAgQXBwLT4+U3ZjOiByZWdpc3RlcihjcmVkZW50aWFscywgLi4uKVxuICogICBTdmMtPj5DQTogcmVnaXN0ZXIocmVxdWVzdCwgYWRtaW5Vc2VyKVxuICogICBDQS0tPj5TdmM6IGVucm9sbG1lbnRTZWNyZXRcbiAqICAgU3ZjLS0+PkFwcDogc2VjcmV0XG4gKiAgIEFwcC0+PlN2YzogZW5yb2xsKGVucm9sbG1lbnRJZCwgc2VjcmV0KVxuICogICBTdmMtPj5DQTogZW5yb2xsKHtlbnJvbGxtZW50SUQsIHNlY3JldH0pXG4gKiAgIENBLS0+PlN2YzogY2VydGlmaWNhdGVzXG4gKiAgIFN2Yy0tPj5BcHA6IElkZW50aXR5XG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNFbnJvbGxtZW50U2VydmljZSBleHRlbmRzIExvZ2dlZENsYXNzIHtcbiAgcHJpdmF0ZSBjYT86IEZhYnJpY0NBU2VydmljZXM7XG5cbiAgcHJpdmF0ZSBjZXJ0aWZpY2F0ZVNlcnZpY2U/OiBhbnk7XG5cbiAgcHJpdmF0ZSBhZmZpbGlhdGlvblNlcnZpY2U/OiBBZmZpbGlhdGlvblNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBpZGVudGl0eVNlcnZpY2U/OiBJZGVudGl0eVNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBjbGllbnQ/OiBhbnk7XG5cbiAgcHJpdmF0ZSB1c2VyPzogVXNlcjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNhQ29uZmlnOiBDQUNvbmZpZykge1xuICAgIENvcmVVdGlscy5nZXRDcnlwdG9TdWl0ZShcbiAgICAgIGNhQ29uZmlnLmhzbVxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHNvZnR3YXJlOiBmYWxzZSxcbiAgICAgICAgICAgIGxpYjogY2FDb25maWcuaHNtLmxpYnJhcnksXG4gICAgICAgICAgICBzbG90OiBjYUNvbmZpZy5oc20uc2xvdCxcbiAgICAgICAgICAgIGxhYmVsOiBjYUNvbmZpZy5oc20udG9rZW5MYWJlbCxcbiAgICAgICAgICAgIHBpbjogU3RyaW5nKGNhQ29uZmlnLmhzbS5waW4pLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWRcbiAgICApO1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgVXNlcigpOiBQcm9taXNlPFVzZXI+IHtcbiAgICBpZiAodGhpcy51c2VyKSByZXR1cm4gdGhpcy51c2VyO1xuICAgIGNvbnN0IHsgY2FOYW1lLCBjYUNlcnQsIGNhS2V5LCB1cmwsIGhzbSB9ID0gdGhpcy5jYUNvbmZpZztcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5Vc2VyKTtcbiAgICBsb2cuZGVidWcoYENyZWF0aW5nIENBIHVzZXIgZm9yICR7Y2FOYW1lfSBhdCAke3VybH1gKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0EgY2VydGlmaWNhdGUgZnJvbSAke2NhQ2VydH1gKTtcbiAgICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGF3YWl0IENvcmVVdGlscy5nZXRGaXJzdERpckZpbGVOYW1lQ29udGVudChjYUNlcnQpO1xuICAgIGxldCBrZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIWhzbSkge1xuICAgICAgaWYgKCFjYUtleSkge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgTWlzc2luZyBjYUtleSBjb25maWd1cmF0aW9uIGZvciBDQSAke2NhTmFtZX0uIFByb3ZpZGUgYSBrZXkgZGlyZWN0b3J5IG9yIGNvbmZpZ3VyZSBIU00gc3VwcG9ydC5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0Ega2V5IGZyb20gJHtjYUtleX1gKTtcbiAgICAgIGtleSA9IGF3YWl0IENvcmVVdGlscy5nZXRGaXJzdERpckZpbGVOYW1lQ29udGVudChjYUtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFVzaW5nIEhTTSBjb25maWd1cmF0aW9uIGZvciBDQSAke2NhTmFtZX0gd2l0aCBsaWJyYXJ5ICR7aHNtLmxpYnJhcnl9YFxuICAgICAgKTtcbiAgICB9XG4gICAgbG9nLmRlYnVnKGBMb2FkaW5nIEFkbWluIHVzZXIgZm9yIGNhICR7Y2FOYW1lfWApO1xuICAgIHRoaXMudXNlciA9IGF3YWl0IENvcmVVdGlscy5nZXRDQVVzZXIoXCJhZG1pblwiLCBrZXksIGNlcnRpZmljYXRlLCBjYU5hbWUsIHtcbiAgICAgIGhzbSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy51c2VyO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIENBKCk6IFByb21pc2U8RmFicmljQ0FTZXJ2aWNlcz4ge1xuICAgIGlmICh0aGlzLmNhKSByZXR1cm4gdGhpcy5jYTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5DQSk7XG4gICAgY29uc3QgeyB1cmwsIHRscywgY2FOYW1lIH0gPSB0aGlzLmNhQ29uZmlnO1xuXG4gICAgLy8gRk9SIFNvbWUgUmVhc29uIHRoZSB2ZXJpZmljYXRpb24gZmFpbHMgbmVlZCB0byBpbnZlc3RpZ2F0ZSB0aGlzIHdvcmtzIGZvciBub3dcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgdHJ1c3RlZFJvb3RzLCB2ZXJpZnkgfSA9IHRscyBhcyBUTFNPcHRpb25zO1xuXG4gICAgY29uc3Qgcm9vdCA9ICh0cnVzdGVkUm9vdHMgYXMgc3RyaW5nW10pWzBdIGFzIHN0cmluZztcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0EgY2VydGlmaWNhdGUgZnJvbSAke3Jvb3R9LiBjd2Q6ICR7cHJvY2Vzcy5jd2QoKX1gKTtcblxuICAgIGNvbnN0IGNlcnRpZmljYXRlID0gYXdhaXQgQ29yZVV0aWxzLmdldEZpbGVDb250ZW50KHJvb3QpO1xuICAgIGxvZy5kZWJ1ZyhgQ3JlYXRpbmcgQ0EgQ2xpZW50IGZvciBDQSAke2NhTmFtZX0gdW5kZXIgJHt1cmx9YCk7XG4gICAgdGhpcy5jYSA9IG5ldyBGYWJyaWNDQVNlcnZpY2VzKFxuICAgICAgdXJsLFxuICAgICAge1xuICAgICAgICB0cnVzdGVkUm9vdHM6IEJ1ZmZlci5mcm9tKGNlcnRpZmljYXRlKSxcbiAgICAgICAgdmVyaWZ5LFxuICAgICAgfSBhcyBUTFNPcHRpb25zLFxuICAgICAgY2FOYW1lXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5jYTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBDbGllbnQoKTogUHJvbWlzZTx7IG5ld0NlcnRpZmljYXRlU2VydmljZTogYW55IH0+IHtcbiAgICBpZiAodGhpcy5jbGllbnQpIHJldHVybiB0aGlzLmNsaWVudDtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICB0aGlzLmNsaWVudCA9IChjYSBhcyBhbnkpW1wiX0ZhYnJpY0NBU2VydmljZXNcIl07XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIENlcnRpZmljYXRlKCkge1xuICAgIGlmICghdGhpcy5jZXJ0aWZpY2F0ZVNlcnZpY2UpXG4gICAgICB0aGlzLmNlcnRpZmljYXRlU2VydmljZSA9IChhd2FpdCB0aGlzLkNsaWVudCgpKS5uZXdDZXJ0aWZpY2F0ZVNlcnZpY2UoKTtcbiAgICByZXR1cm4gdGhpcy5jZXJ0aWZpY2F0ZVNlcnZpY2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgQWZmaWxpYXRpb25zKCkge1xuICAgIGlmICghdGhpcy5hZmZpbGlhdGlvblNlcnZpY2UpXG4gICAgICB0aGlzLmFmZmlsaWF0aW9uU2VydmljZSA9IChhd2FpdCB0aGlzLkNBKCkpLm5ld0FmZmlsaWF0aW9uU2VydmljZSgpO1xuICAgIHJldHVybiB0aGlzLmFmZmlsaWF0aW9uU2VydmljZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBJZGVudGl0aWVzKCkge1xuICAgIGlmICghdGhpcy5pZGVudGl0eVNlcnZpY2UpXG4gICAgICB0aGlzLmlkZW50aXR5U2VydmljZSA9IChhd2FpdCB0aGlzLkNBKCkpLm5ld0lkZW50aXR5U2VydmljZSgpO1xuICAgIHJldHVybiB0aGlzLmlkZW50aXR5U2VydmljZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmUgY2VydGlmaWNhdGVzIGZyb20gdGhlIENBLlxuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgQ0EgY2VydGlmaWNhdGUgc2VydmljZSB0byBsaXN0IGNlcnRpZmljYXRlcywgb3B0aW9uYWxseSBtYXBwaW5nIHRvIFBFTSBzdHJpbmdzIG9ubHkuXG4gICAqIEBwYXJhbSB7R2V0Q2VydGlmaWNhdGVzUmVxdWVzdH0gW3JlcXVlc3RdIC0gT3B0aW9uYWwgZmlsdGVyIHJlcXVlc3QgZm9yIGNlcnRpZmljYXRlIGxvb2t1cC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZG9NYXA9dHJ1ZV0gLSBXaGVuIHRydWUsIHJldHVybnMgYXJyYXkgb2YgUEVNIHN0cmluZ3M7IG90aGVyd2lzZSByZXR1cm5zIGZ1bGwgcmVzcG9uc2Ugb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHN0cmluZ1tdIHwgQ2VydGlmaWNhdGVSZXNwb25zZT59IEFycmF5IG9mIFBFTSBzdHJpbmdzIG9yIHRoZSBmdWxsIGNlcnRpZmljYXRlIHJlc3BvbnNlLlxuICAgKi9cbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzKFxuICAgIHJlcXVlc3Q/OiBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0LFxuICAgIGRvTWFwID0gdHJ1ZVxuICApOiBQcm9taXNlPHN0cmluZ1tdIHwgQ2VydGlmaWNhdGVSZXNwb25zZT4ge1xuICAgIGNvbnN0IGNlcnRpZmljYXRlU2VydmljZSA9IGF3YWl0IHRoaXMuQ2VydGlmaWNhdGUoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0Q2VydGlmaWNhdGVzKTtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgUmV0cmlldmluZyBjZXJ0aWZpY2F0ZXMke3JlcXVlc3QgPyBgIGZvciAke3JlcXVlc3QuaWR9YCA6IFwiXCJ9IGZvciBDQSAke3RoaXMuY2FDb25maWcuY2FOYW1lfWBcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBDZXJ0aWZpY2F0ZVJlc3BvbnNlID0gKFxuICAgICAgYXdhaXQgY2VydGlmaWNhdGVTZXJ2aWNlLmdldENlcnRpZmljYXRlcyhyZXF1ZXN0IHx8IHt9LCB1c2VyKVxuICAgICkucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmNlcnRzLmxlbmd0aH0gY2VydGlmaWNhdGVzOiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gXG4gICAgKTtcbiAgICByZXR1cm4gZG9NYXAgPyByZXNwb25zZS5jZXJ0cy5tYXAoKGMpID0+IGMuUEVNKSA6IHJlc3BvbnNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaXN0IGlkZW50aXRpZXMgcmVnaXN0ZXJlZCBpbiB0aGUgQ0EuXG4gICAqIEBzdW1tYXJ5IFF1ZXJpZXMgdGhlIENBIGlkZW50aXR5IHNlcnZpY2UgdG8gZmV0Y2ggYWxsIGlkZW50aXRpZXMgYW5kIHJldHVybnMgdGhlIGxpc3QgYXMgRmFicmljSWRlbnRpdHkgb2JqZWN0cy5cbiAgICogQHJldHVybiB7UHJvbWlzZTxGYWJyaWNJZGVudGl0eVtdPn0gVGhlIGxpc3Qgb2YgaWRlbnRpdGllcyByZWdpc3RlcmVkIGluIHRoZSBDQS5cbiAgICovXG4gIGFzeW5jIGdldElkZW50aXRpZXMoKTogUHJvbWlzZTxGYWJyaWNJZGVudGl0eVtdPiB7XG4gICAgY29uc3QgaWRlbnRpdGllc1NlcnZpY2UgPSBhd2FpdCB0aGlzLklkZW50aXRpZXMoKTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5nZXRJZGVudGl0aWVzKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgSWRlbnRpdGllcyB1bmRlciBDQSAke3RoaXMuY2FDb25maWcuY2FOYW1lfWApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBJZGVudGl0eVJlc3BvbnNlID0gKFxuICAgICAgYXdhaXQgaWRlbnRpdGllc1NlcnZpY2UuZ2V0QWxsKGF3YWl0IHRoaXMuVXNlcigpKVxuICAgICkucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmlkZW50aXRpZXMubGVuZ3RofSBJZGVudGl0aWVzOiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gXG4gICAgKTtcbiAgICByZXR1cm4gcmVzcG9uc2UuaWRlbnRpdGllcztcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUVycm9yKGU6IEVycm9yKSB7XG4gICAgY29uc3QgcmVnZXhwID0gLy4qY29kZTpcXHMoXFxkKykuKj9tZXNzYWdlOlxcc1tcIiddKC4rKVtcIiddL2dzO1xuICAgIGNvbnN0IG1hdGNoID0gcmVnZXhwLmV4ZWMoZS5tZXNzYWdlKTtcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKGUpO1xuICAgIGNvbnN0IFssIGNvZGUsIG1lc3NhZ2VdID0gbWF0Y2g7XG4gICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICBjYXNlIFwiNzRcIjpcbiAgICAgIGNhc2UgXCI3MVwiOlxuICAgICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IobWVzc2FnZSk7XG4gICAgICBjYXNlIFwiMjBcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IobWVzc2FnZSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmUgYWZmaWxpYXRpb25zIGZyb20gdGhlIENBLlxuICAgKiBAc3VtbWFyeSBRdWVyaWVzIHRoZSBDQSBmb3IgdGhlIGxpc3Qgb2YgYWZmaWxpYXRpb25zIGF2YWlsYWJsZSB1bmRlciB0aGUgY29uZmlndXJlZCBDQS5cbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgYWZmaWxpYXRpb25zIHJlc3VsdCBwYXlsb2FkLlxuICAgKi9cbiAgYXN5bmMgZ2V0QWZmaWxpYXRpb25zKCkge1xuICAgIGNvbnN0IGFmZmlsaWF0aW9uU2VydmljZSA9IGF3YWl0IHRoaXMuQWZmaWxpYXRpb25zKCk7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0QWZmaWxpYXRpb25zKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQWZmaWxpYXRpb25zIHVuZGVyIENBICR7dGhpcy5jYUNvbmZpZy5jYU5hbWV9YCk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgYWZmaWxpYXRpb25TZXJ2aWNlLmdldEFsbChhd2FpdCB0aGlzLlVzZXIoKSkpXG4gICAgICAucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmEubGVuZ3RofSBBZmZpbGlhdGlvbnM6ICR7SlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpfWBcbiAgICApO1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZCBpZGVudGl0eSBkZXRhaWxzIGZyb20gdGhlIENBIGJ5IGVucm9sbG1lbnQgSUQuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhbmQgdmFsaWRhdGVzIGEgc2luZ2xlIGlkZW50aXR5LCB0aHJvd2luZyBOb3RGb3VuZEVycm9yIHdoZW4gbWlzc2luZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGVucm9sbG1lbnRJZCAtIEVucm9sbG1lbnQgSUQgdG8gbG9va3VwLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEZhYnJpY0lkZW50aXR5Pn0gVGhlIGlkZW50aXR5IGRldGFpbHMgc3RvcmVkIGluIHRoZSBDQS5cbiAgICovXG4gIGFzeW5jIHJlYWQoZW5yb2xsbWVudElkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgbGV0IHJlc3VsdDogSVNlcnZpY2VSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgY2EubmV3SWRlbnRpdHlTZXJ2aWNlKCkuZ2V0T25lKGVucm9sbG1lbnRJZCwgdXNlcik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYENvdWxkbid0IGZpbmQgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgQ291bGRuJ3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke3Jlc3VsdC5lcnJvcnMuam9pbihcIlxcblwiKX1gXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQgYXMgRmFicmljSWRlbnRpdHk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVyIGEgbmV3IGlkZW50aXR5IHdpdGggdGhlIENBLlxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgcmVnaXN0cmF0aW9uIHJlcXVlc3QgZm9yIGEgbmV3IGVucm9sbG1lbnQgSUQsIHJldHVybmluZyB0aGUgZW5yb2xsbWVudCBzZWNyZXQgdXBvbiBzdWNjZXNzLlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkIGZvciB0aGUgbmV3IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSByZWdpc3RlcmVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXIoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbGV0IHJlZ2lzdHJhdGlvbjogc3RyaW5nO1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJlZ2lzdGVyKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyB1c2VyTmFtZSwgcGFzc3dvcmQgfSA9IG1vZGVsO1xuICAgICAgY29uc3QgY2EgPSBhd2FpdCB0aGlzLkNBKCk7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgICBjb25zdCBwcm9wcyA9IHtcbiAgICAgICAgZW5yb2xsbWVudElEOiB1c2VyTmFtZSBhcyBzdHJpbmcsXG4gICAgICAgIGVucm9sbG1lbnRTZWNyZXQ6IHBhc3N3b3JkLFxuICAgICAgICBhZmZpbGlhdGlvbjogYWZmaWxpYXRpb24sXG4gICAgICAgIHVzZXJSb2xlOiB1c2VyUm9sZSxcbiAgICAgICAgYXR0cnM6IGF0dHJzLFxuICAgICAgICBtYXhFbnJvbGxtZW50czogbWF4RW5yb2xsbWVudHMsXG4gICAgICB9IGFzIElSZWdpc3RlclJlcXVlc3Q7XG4gICAgICByZWdpc3RyYXRpb24gPSBhd2FpdCBjYS5yZWdpc3Rlcihwcm9wcywgdXNlcik7XG4gICAgICBsb2cuaW5mbyhcbiAgICAgICAgYFJlZ2lzdHJhdGlvbiBmb3IgJHt1c2VyTmFtZX0gY3JlYXRlZCB3aXRoIHVzZXIgdHlwZSAke3VzZXJSb2xlID8/IFwiVW5kZWZpbmVkIFJvbGVcIn0gJHtpc1N1cGVyVXNlciA/IFwiYXMgc3VwZXIgdXNlclwiIDogXCJcIn1gXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVnaXN0cmF0aW9uO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyBpZGVudGl0eUZyb21FbnJvbGxtZW50KFxuICAgIGVucm9sbG1lbnQ6IElFbnJvbGxSZXNwb25zZSxcbiAgICBtc3BJZDogc3RyaW5nXG4gICk6IElkZW50aXR5IHtcbiAgICBjb25zdCB7IGNlcnRpZmljYXRlLCBrZXksIHJvb3RDZXJ0aWZpY2F0ZSB9ID0gZW5yb2xsbWVudDtcbiAgICBjb25zdCBsb2cgPSBMb2dnaW5nLmZvcihGYWJyaWNFbnJvbGxtZW50U2VydmljZSwge30pLmZvcihcbiAgICAgIHRoaXMuaWRlbnRpdHlGcm9tRW5yb2xsbWVudFxuICAgICk7XG4gICAgbG9nLmRlYnVnKFxuICAgICAgYEdlbmVyYXRpbmcgSWRlbnRpdHkgZnJvbSBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlfSBpbiBtc3AgJHttc3BJZH1gXG4gICAgKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IENyeXB0b1V0aWxzLmZhYnJpY0lkRnJvbUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBpZCA9IENyeXB0b1V0aWxzLmVuY29kZShjbGllbnRJZCk7XG4gICAgbG9nLmRlYnVnKGBJZGVudGl0eSAke2NsaWVudElkfSBhbmQgZW5jb2RlZElkICR7aWR9YCk7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IElkZW50aXR5KHtcbiAgICAgIGlkOiBpZCxcbiAgICAgIGNyZWRlbnRpYWxzOiB7XG4gICAgICAgIGlkOiBpZCxcbiAgICAgICAgY2VydGlmaWNhdGU6IGNlcnRpZmljYXRlLFxuICAgICAgICBwcml2YXRlS2V5OiBrZXkudG9CeXRlcygpLFxuICAgICAgICByb290Q2VydGlmaWNhdGU6IHJvb3RDZXJ0aWZpY2F0ZSxcbiAgICAgICAgY3JlYXRlZE9uOiBub3csXG4gICAgICAgIHVwZGF0ZWRPbjogbm93LFxuICAgICAgfSxcbiAgICAgIG1zcElkOiBtc3BJZCxcbiAgICAgIGNyZWF0ZWRPbjogbm93LFxuICAgICAgdXBkYXRlZE9uOiBub3csXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVucm9sbCBhbiBpZGVudGl0eSB3aXRoIHRoZSBDQSB1c2luZyBhIHJlZ2lzdHJhdGlvbiBzZWNyZXQuXG4gICAqIEBzdW1tYXJ5IEV4Y2hhbmdlcyB0aGUgZW5yb2xsbWVudCBJRCBhbmQgc2VjcmV0IGZvciBjZXJ0aWZpY2F0ZXMsIHJldHVybmluZyBhIGNvbnN0cnVjdGVkIElkZW50aXR5IG1vZGVsLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZW5yb2xsbWVudElkIC0gRW5yb2xsbWVudCBJRCB0byBlbnJvbGwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWdpc3RyYXRpb24gLSBFbnJvbGxtZW50IHNlY3JldCByZXR1cm5lZCBhdCByZWdpc3RyYXRpb24gdGltZS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxJZGVudGl0eT59IFRoZSBlbnJvbGxlZCBpZGVudGl0eSBvYmplY3Qgd2l0aCBjcmVkZW50aWFscy5cbiAgICovXG4gIGFzeW5jIGVucm9sbChlbnJvbGxtZW50SWQ6IHN0cmluZywgcmVnaXN0cmF0aW9uOiBzdHJpbmcpIHtcbiAgICBsZXQgaWRlbnRpdHk6IElkZW50aXR5O1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmVucm9sbCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNhID0gYXdhaXQgdGhpcy5DQSgpO1xuICAgICAgbG9nLmRlYnVnKGBFbnJvbGxpbmcgJHtlbnJvbGxtZW50SWR9YCk7XG4gICAgICBjb25zdCBlbnJvbGxtZW50OiBJRW5yb2xsUmVzcG9uc2UgPSBhd2FpdCBjYS5lbnJvbGwoe1xuICAgICAgICBlbnJvbGxtZW50SUQ6IGVucm9sbG1lbnRJZCxcbiAgICAgICAgZW5yb2xsbWVudFNlY3JldDogcmVnaXN0cmF0aW9uLFxuICAgICAgfSk7XG4gICAgICBpZGVudGl0eSA9IEZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlLmlkZW50aXR5RnJvbUVucm9sbG1lbnQoXG4gICAgICAgIGVucm9sbG1lbnQsXG4gICAgICAgIHRoaXMuY2FDb25maWcuY2FOYW1lXG4gICAgICApO1xuICAgICAgbG9nLmluZm8oXG4gICAgICAgIGBTdWNjZXNzZnVsbHkgZW5yb2xsZWQgJHtlbnJvbGxtZW50SWR9IHVuZGVyICR7dGhpcy5jYUNvbmZpZy5jYU5hbWV9IGFzICR7aWRlbnRpdHkuaWR9YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlKTtcbiAgICB9XG4gICAgcmV0dXJuIGlkZW50aXR5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlciBhbmQgZW5yb2xsIGEgbmV3IGlkZW50aXR5IGluIG9uZSBzdGVwLlxuICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgYSBuZXcgZW5yb2xsbWVudCBJRCB3aXRoIHRoZSBDQSBhbmQgaW1tZWRpYXRlbHkgZXhjaGFuZ2VzIHRoZSBzZWNyZXQgdG8gZW5yb2xsLCByZXR1cm5pbmcgdGhlIGNyZWF0ZWQgSWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7Q3JlZGVudGlhbHN9IG1vZGVsIC0gQ3JlZGVudGlhbHMgZm9yIHRoZSBuZXcgaWRlbnRpdHkgY29udGFpbmluZyB1c2VyTmFtZSBhbmQgcGFzc3dvcmQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzU3VwZXJVc2VyPWZhbHNlXSAtIFdoZXRoZXIgdG8gcmVnaXN0ZXIgdGhlIGlkZW50aXR5IGFzIGEgc3VwZXIgdXNlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFthZmZpbGlhdGlvbj1cIlwiXSAtIEFmZmlsaWF0aW9uIHN0cmluZyAoZS5nLiwgb3JnMS5kZXBhcnRtZW50MSkuXG4gICAqIEBwYXJhbSB7Q0FfUk9MRSB8IHN0cmluZ30gW3VzZXJSb2xlXSAtIFJvbGUgdG8gYXNzaWduIHRvIHRoZSBpZGVudGl0eS5cbiAgICogQHBhcmFtIHtJS2V5VmFsdWVBdHRyaWJ1dGV9IFthdHRyc10gLSBPcHRpb25hbCBhdHRyaWJ1dGVzIHRvIGF0dGFjaCB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4RW5yb2xsbWVudHNdIC0gTWF4aW11bSBudW1iZXIgb2YgZW5yb2xsbWVudHMgYWxsb3dlZCBmb3IgdGhlIGlkZW50aXR5LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gVGhlIGVucm9sbGVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXJBbmRFbnJvbGwoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyXG4gICk6IFByb21pc2U8SWRlbnRpdHk+IHtcbiAgICBjb25zdCByZWdpc3RyYXRpb24gPSBhd2FpdCB0aGlzLnJlZ2lzdGVyKFxuICAgICAgbW9kZWwsXG4gICAgICBpc1N1cGVyVXNlcixcbiAgICAgIGFmZmlsaWF0aW9uLFxuICAgICAgdXNlclJvbGUsXG4gICAgICBhdHRycyxcbiAgICAgIG1heEVucm9sbG1lbnRzXG4gICAgKTtcbiAgICBjb25zdCB7IHVzZXJOYW1lIH0gPSBtb2RlbDtcbiAgICByZXR1cm4gdGhpcy5lbnJvbGwodXNlck5hbWUgYXMgc3RyaW5nLCByZWdpc3RyYXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldm9rZXMgdGhlIGVucm9sbG1lbnQgb2YgYW4gaWRlbnRpdHkgd2l0aCB0aGUgc3BlY2lmaWVkIGVucm9sbG1lbnQgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBlbnJvbGxtZW50SWQgLSBUaGUgZW5yb2xsbWVudCBJRCBvZiB0aGUgaWRlbnRpdHkgdG8gYmUgcmV2b2tlZC5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlc3VsdCBvZiB0aGUgcmV2b2NhdGlvbiBvcGVyYXRpb24uXG4gICAqXG4gICAqIEB0aHJvd3Mge05vdEZvdW5kRXJyb3J9IElmIHRoZSBlbnJvbGxtZW50IHdpdGggdGhlIHNwZWNpZmllZCBJRCBkb2VzIG5vdCBleGlzdC5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlcmUgaXMgYW4gZXJyb3IgZHVyaW5nIHRoZSByZXZvY2F0aW9uIHByb2Nlc3MuXG4gICAqL1xuICBhc3luYyByZXZva2UoZW5yb2xsbWVudElkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgY29uc3QgaWRlbnRpdHkgPSBhd2FpdCB0aGlzLnJlYWQoZW5yb2xsbWVudElkKTtcbiAgICBpZiAoIWlkZW50aXR5KVxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9YFxuICAgICAgKTtcbiAgICBsZXQgcmVzdWx0OiBJU2VydmljZVJlc3BvbnNlO1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBjYS5yZXZva2UoXG4gICAgICAgIHsgZW5yb2xsbWVudElEOiBpZGVudGl0eS5pZCwgcmVhc29uOiBcIlVzZXIgRGVsZXRhdGlvblwiIH0sXG4gICAgICAgIHVzZXJcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgcmV2b2tlIGVucm9sbG1lbnQgd2l0aCBpZCAke2Vucm9sbG1lbnRJZH06ICR7ZX1gXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgcmV2b2tlIGVucm9sbG1lbnQgd2l0aCBpZCAke2Vucm9sbG1lbnRJZH06ICR7cmVzdWx0LmVycm9ycy5qb2luKFwiXFxuXCIpfWBcbiAgICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSVJlZ2lzdGVyUmVxdWVzdCwgSUtleVZhbHVlQXR0cmlidXRlIH0gZnJvbSBcImZhYnJpYy1jYS1jbGllbnRcIjtcbmltcG9ydCB7IENBX1JPTEUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIG1pbixcbiAgbWlubGVuZ3RoLFxuICBNb2RlbCxcbiAgcmVxdWlyZWQsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uUmVxdWVzdEJ1aWxkZXIgZXh0ZW5kcyBNb2RlbCB7XG4gIEByZXF1aXJlZCgpXG4gIGFmZmlsaWF0aW9uOiBzdHJpbmcgPSBcIlwiO1xuICBAbWlubGVuZ3RoKDEpXG4gIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlW107XG4gIEByZXF1aXJlZCgpXG4gIGVucm9sbG1lbnRJRCE6IHN0cmluZztcbiAgQHJlcXVpcmVkKClcbiAgZW5yb2xsbWVudFNlY3JldCE6IHN0cmluZztcbiAgQG1pbigwKVxuICBtYXhFbnJvbGxtZW50cz86IG51bWJlcjtcbiAgQHJlcXVpcmVkKClcbiAgcm9sZSE6IHN0cmluZztcblxuICBidWlsZCgpOiBJUmVnaXN0ZXJSZXF1ZXN0IHtcbiAgICBjb25zdCBlcnJzID0gdGhpcy5oYXNFcnJvcnMoKTtcbiAgICBpZiAoZXJycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJzLnRvU3RyaW5nKCkpO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBJUmVnaXN0ZXJSZXF1ZXN0ID0ge1xuICAgICAgZW5yb2xsbWVudElEOiB0aGlzLmVucm9sbG1lbnRJRCxcbiAgICAgIGVucm9sbG1lbnRTZWNyZXQ6IHRoaXMuZW5yb2xsbWVudFNlY3JldCxcbiAgICAgIHJvbGU6IHRoaXMucm9sZSxcbiAgICAgIGFmZmlsaWF0aW9uOiB0aGlzLmFmZmlsaWF0aW9uLFxuICAgIH07XG4gICAgaWYgKHR5cGVvZiB0aGlzLm1heEVucm9sbG1lbnRzICE9PSBcInVuZGVmaW5lZFwiKVxuICAgICAgcmVzcG9uc2UubWF4RW5yb2xsbWVudHMgPSB0aGlzLm1heEVucm9sbG1lbnRzO1xuICAgIGlmICh0aGlzLmF0dHJzKSByZXNwb25zZS5hdHRycyA9IHRoaXMuYXR0cnM7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgc2V0QWZmaWxpYXRpb24odmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuYWZmaWxpYXRpb24gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGFkZEF0dHIoYXR0cjogSUtleVZhbHVlQXR0cmlidXRlKSB7XG4gICAgdGhpcy5hdHRycyA9IHRoaXMuYXR0cnMgfHwgW107XG4gICAgdGhpcy5hdHRycy5wdXNoKGF0dHIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0QXR0cnModmFsdWU6IElLZXlWYWx1ZUF0dHJpYnV0ZVtdKSB7XG4gICAgdGhpcy5hdHRycyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0RW5yb2xsbWVudElEKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmVucm9sbG1lbnRJRCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0RW5yb2xsbWVudFNlY3JldCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5lbnJvbGxtZW50U2VjcmV0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRNYXhFbnJvbGxtZW50cyh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5tYXhFbnJvbGxtZW50cyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Um9sZSh2YWx1ZTogQ0FfUk9MRSB8IHN0cmluZykge1xuICAgIHRoaXMucm9sZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59XG4iLCIvKipcbiAqIEVudW0gcmVwcmVzZW50aW5nIHRoZSBldmVudHMgZW1pdHRlZCBieSBhbiBFUkMyMCBjb250cmFjdC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhpcyBlbnVtIGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHNwZWNpZmljIGV2ZW50cyB0aGF0IGNhbiBiZSBlbWl0dGVkIGJ5IGFuIEVSQzIwIGNvbnRyYWN0LlxuICogVGhlIGV2ZW50cyBhcmUgbmFtZWQgYWNjb3JkaW5nIHRvIHRoZSBFSVAtMjAgc3RhbmRhcmQuXG4gKi9cbmV4cG9ydCBlbnVtIEVSQzIwRXZlbnRzIHtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGB0cmFuc2ZlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIHN1Y2Nlc3NmdWxseS5cbiAgICpcbiAgICogQHBhcmFtIGZyb20gLSBUaGUgYWRkcmVzcyBvZiB0aGUgc2VuZGVyLlxuICAgKiBAcGFyYW0gdG8gLSBUaGUgYWRkcmVzcyBvZiB0aGUgcmVjaXBpZW50LlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgYW1vdW50IG9mIHRva2VucyB0cmFuc2ZlcnJlZC5cbiAgICovXG4gIFRSQU5TRkVSID0gXCJUcmFuc2ZlclwiLFxuXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYW4gYGFwcHJvdmVgIGZ1bmN0aW9uIGlzIGNhbGxlZCBzdWNjZXNzZnVsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBvd25lciAtIFRoZSBhZGRyZXNzIG9mIHRoZSB0b2tlbiBvd25lci5cbiAgICogQHBhcmFtIHNwZW5kZXIgLSBUaGUgYWRkcmVzcyBvZiB0aGUgYXBwcm92ZWQgc3BlbmRlci5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiB0b2tlbnMgYXBwcm92ZWQgZm9yIHRoZSBzcGVuZGVyLlxuICAgKi9cbiAgQVBQUk9WQUwgPSBcIkFwcHJvdmFsXCIsXG59XG4iLCJpbXBvcnQgeyBNb2RlbCwgdHlwZSBNb2RlbEFyZyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGNvbHVtbiwgY3JlYXRlZEF0LCB1cGRhdGVkQXQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IGRlc2NyaXB0aW9uLCB1c2VzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUHJvcGVydHkgfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuXG5AdXNlcyhGYWJyaWNGbGF2b3VyKVxuZXhwb3J0IGNsYXNzIEZhYnJpY0Jhc2VNb2RlbCBleHRlbmRzIE1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBvcmlnaW5hbCB0aW1lc3RhbXAgb2YgY3JlYXRpb25cIilcbiAgQGNvbHVtbigpXG4gIEBjcmVhdGVkQXQoKVxuICBjcmVhdGVkQXQhOiBEYXRlO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdGltZXN0YW1wIG9mIHRoZSBsYXN0IHVwZGF0ZVwiKVxuICBAY29sdW1uKClcbiAgQHVwZGF0ZWRBdCgpXG4gIHVwZGF0ZWRBdCE6IERhdGU7XG5cbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2RlbFwiKVxuICBAY29sdW1uKClcbiAgQHZlcnNpb24oKVxuICB2ZXJzaW9uITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0Jhc2VNb2RlbD4pIHtcbiAgICBzdXBlcihhcmcpO1xuICB9XG59XG4iLCJpbXBvcnQgeyB0eXBlIE1vZGVsQXJnIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgY29sdW1uLCBjcmVhdGVkQnksIHVwZGF0ZWRCeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24sIHVzZXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0ZsYXZvdXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBGYWJyaWNCYXNlTW9kZWwgfSBmcm9tIFwiLi9GYWJyaWNCYXNlTW9kZWxcIjtcblxuQHVzZXMoRmFicmljRmxhdm91cilcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNJZGVudGlmaWVkQmFzZU1vZGVsIGV4dGVuZHMgRmFicmljQmFzZU1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBjcmVhdG9yXCIpXG4gIEBjb2x1bW4oKVxuICBAY3JlYXRlZEJ5KClcbiAgY3JlYXRlZEJ5ITogc3RyaW5nO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdXNlciB0aGF0IGxhc3QgdXBkYXRlZCB0aGUgbW9kZWxcIilcbiAgQGNvbHVtbigpXG4gIEB1cGRhdGVkQnkoKVxuICB1cGRhdGVkQnkhOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0lkZW50aWZpZWRCYXNlTW9kZWw+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY01vZGVsS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFNlZ3JlZ2F0ZWRNb2RlbCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgREJLZXlzLCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb2xsZWN0aW9uUmVzb2x2ZXIsIE1pcnJvck1ldGFkYXRhIH0gZnJvbSBcIi4uL2RlY29yYXRvcnNcIjtcblxuTW9kZWwucHJvdG90eXBlLmlzU2hhcmVkID0gZnVuY3Rpb24gaXNTaGFyZWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogTVxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBNb2RlbC5pc1NoYXJlZCh0aGlzLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yPE0+KTtcbn07XG5cbk1vZGVsLnByb3RvdHlwZS5pc1ByaXZhdGUgPSBmdW5jdGlvbiBpc1ByaXZhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogTVxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBNb2RlbC5pc1ByaXZhdGUodGhpcy5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPik7XG59O1xuXG5Nb2RlbC5wcm90b3R5cGUuc2VncmVnYXRlID0gZnVuY3Rpb24gc2VncmVnYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IE1cbik6IFNlZ3JlZ2F0ZWRNb2RlbDxNPiB7XG4gIHJldHVybiBNb2RlbC5zZWdyZWdhdGUodGhpcyk7XG59O1xuXG4oTW9kZWwgYXMgYW55KS5zZWdyZWdhdGUgPSBmdW5jdGlvbiBzZWdyZWdhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbik6IFNlZ3JlZ2F0ZWRNb2RlbDxNPiB7XG4gIGlmICghTW9kZWwuaXNUcmFuc2llbnQobW9kZWwpKSByZXR1cm4geyBtb2RlbDogbW9kZWwgfTtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllcyA9IE1ldGFkYXRhLnZhbGlkYXRhYmxlUHJvcGVydGllcyhcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnlcbiAgKTtcblxuICBjb25zdCB0cmFuc2llbnRQcm9wcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgREJLZXlzLlRSQU5TSUVOVFxuICApO1xuICBjb25zdCBwcml2YXRlUHJvcGVydGllcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgRmFicmljTW9kZWxLZXlzLlBSSVZBVEVcbiAgKTtcbiAgY29uc3Qgc2hhcmVkUHJvcGVydGllcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgRmFicmljTW9kZWxLZXlzLlBSSVZBVEVcbiAgKTtcblxuICBjb25zdCByZXN1bHQ6IFNlZ3JlZ2F0ZWRNb2RlbDxNPiA9IHtcbiAgICBtb2RlbDoge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT4sXG4gICAgdHJhbnNpZW50OiB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PixcbiAgICBwcml2YXRlOiB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PixcbiAgICBzaGFyZWQ6IHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+LFxuICB9O1xuXG4gIGNvbnN0IHRyYW5zaWVudEtleXMgPSBPYmplY3Qua2V5cyh0cmFuc2llbnRQcm9wcyk7XG4gIGNvbnN0IHByaXZhdGVLZXlzID0gT2JqZWN0LmtleXMocHJpdmF0ZVByb3BlcnRpZXMpO1xuICBjb25zdCBzaGFyZWRLZXlzID0gT2JqZWN0LmtleXMoc2hhcmVkUHJvcGVydGllcyk7XG5cbiAgZm9yIChjb25zdCBrZXkgb2YgZGVjb3JhdGVkUHJvcGVydGllcykge1xuICAgIGNvbnN0IGlzVHJhbnNpZW50ID0gdHJhbnNpZW50S2V5cy5pbmNsdWRlcyhrZXkpO1xuICAgIGNvbnN0IGlzUHJpdmF0ZSA9IHByaXZhdGVLZXlzLmluY2x1ZGVzKGtleSk7XG4gICAgY29uc3QgaXNTaGFyZWQgPSBzaGFyZWRLZXlzLmluY2x1ZGVzKGtleSk7XG4gICAgaWYgKGlzVHJhbnNpZW50KSB7XG4gICAgICByZXN1bHQudHJhbnNpZW50ID0gcmVzdWx0LnRyYW5zaWVudCB8fCAoe30gYXMgYW55KTtcbiAgICAgIChyZXN1bHQudHJhbnNpZW50IGFzIGFueSlba2V5XSA9IG1vZGVsW2tleSBhcyBrZXlvZiBNXTtcbiAgICAgIGlmIChpc1ByaXZhdGUpIHtcbiAgICAgICAgcmVzdWx0LnByaXZhdGUgPSByZXN1bHQucHJpdmF0ZSB8fCAoe30gYXMgYW55KTtcbiAgICAgICAgKHJlc3VsdC5wcml2YXRlIGFzIGFueSlba2V5XSA9IG1vZGVsW2tleSBhcyBrZXlvZiBNXTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1NoYXJlZCkge1xuICAgICAgICByZXN1bHQuc2hhcmVkID0gcmVzdWx0LnNoYXJlZCB8fCAoe30gYXMgYW55KTtcbiAgICAgICAgKHJlc3VsdC5zaGFyZWQgYXMgYW55KVtrZXldID0gbW9kZWxba2V5IGFzIGtleW9mIE1dO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQubW9kZWwgPSByZXN1bHQubW9kZWwgfHwge307XG4gICAgICAocmVzdWx0Lm1vZGVsIGFzIGFueSlba2V5XSA9IChtb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJlc3VsdC5tb2RlbCA9IE1vZGVsLmJ1aWxkKHJlc3VsdC5tb2RlbCwgbW9kZWwuY29uc3RydWN0b3IubmFtZSk7XG4gIHJldHVybiByZXN1bHQgYXMgU2VncmVnYXRlZE1vZGVsPE0+O1xufS5iaW5kKE1vZGVsKTtcblxuKE1vZGVsIGFzIGFueSkuaXNQcml2YXRlID0gZnVuY3Rpb24gaXNQcml2YXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT5cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gISFNZXRhZGF0YS5nZXQoXG4gICAgdHlwZW9mIG1vZGVsICE9PSBcImZ1bmN0aW9uXCIgPyAobW9kZWwuY29uc3RydWN0b3IgYXMgYW55KSA6IG1vZGVsLFxuICAgIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFXG4gICk7XG59LmJpbmQoTW9kZWwpO1xuXG4oTW9kZWwgYXMgYW55KS5pc1NoYXJlZCA9IGZ1bmN0aW9uIGlzU2hhcmVkPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT5cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gISFNZXRhZGF0YS5nZXQoXG4gICAgdHlwZW9mIG1vZGVsICE9PSBcImZ1bmN0aW9uXCIgPyAobW9kZWwuY29uc3RydWN0b3IgYXMgYW55KSA6IG1vZGVsLFxuICAgIEZhYnJpY01vZGVsS2V5cy5TSEFSRURcbiAgKTtcbn0uYmluZChNb2RlbCk7XG5cbihNb2RlbCBhcyBhbnkpLm1pcnJvcmVkID0gZnVuY3Rpb24gbWlycm9yZWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBNZXRhZGF0YS5nZXQoXG4gICAgdHlwZW9mIG1vZGVsICE9PSBcImZ1bmN0aW9uXCIgPyAobW9kZWwuY29uc3RydWN0b3IgYXMgYW55KSA6IG1vZGVsLFxuICAgIE1ldGFkYXRhLmtleShGYWJyaWNNb2RlbEtleXMuRkFCUklDLCBGYWJyaWNNb2RlbEtleXMuTUlSUk9SKVxuICApO1xufS5iaW5kKE1vZGVsKTtcblxuKE1vZGVsIGFzIGFueSkub3duZXJPZiA9IGZ1bmN0aW9uIG93bmVyT2Y8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG1ldGEgPSBNZXRhZGF0YS5nZXQoXG4gICAgbW9kZWwuY29uc3RydWN0b3IgYXMgYW55LFxuICAgIE1ldGFkYXRhLmtleShGYWJyaWNNb2RlbEtleXMuRkFCUklDLCBGYWJyaWNNb2RlbEtleXMuT1dORURfQlkpXG4gICk7XG4gIGlmICghbWV0YSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIG1vZGVsW21ldGEgYXMga2V5b2YgTV0gYXMgc3RyaW5nO1xufS5iaW5kKE1vZGVsKTtcblxuKE1vZGVsIGFzIGFueSkubWlycm9yZWRBdCA9IGZ1bmN0aW9uIG1pcnJvcmVkQXQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogTWlycm9yTWV0YWRhdGEgfCB1bmRlZmluZWQge1xuICBtb2RlbCA9IHR5cGVvZiBtb2RlbCAhPT0gXCJmdW5jdGlvblwiID8gKG1vZGVsLmNvbnN0cnVjdG9yIGFzIGFueSkgOiBtb2RlbDtcbiAgcmV0dXJuIE1ldGFkYXRhLmdldChcbiAgICBtb2RlbCBhcyBhbnksXG4gICAgTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsIEZhYnJpY01vZGVsS2V5cy5NSVJST1IpXG4gICk7XG59LmJpbmQoTW9kZWwpO1xuXG4oTW9kZWwgYXMgYW55KS5jb2xsZWN0aW9uc0ZvciA9IGZ1bmN0aW9uIGNvbGxlY3Rpb25zRm9yPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT5cbik6IHtcbiAgcHJpdmF0ZUNvbHM6IChzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIpW107XG4gIHNoYXJlZENvbHM6IChzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIpW107XG59IHtcbiAgY29uc3QgcHJpdmF0ZUtleXM6IHN0cmluZ1tdID0gW0ZhYnJpY01vZGVsS2V5cy5QUklWQVRFXSBhcyBzdHJpbmdbXTtcbiAgY29uc3Qgc2hhcmVkS2V5czogc3RyaW5nW10gPSBbRmFicmljTW9kZWxLZXlzLlNIQVJFRF0gYXMgc3RyaW5nW107XG5cbiAgY29uc3QgcHJpdmF0ZUtleSA9IE1ldGFkYXRhLmtleSguLi5wcml2YXRlS2V5cyk7XG4gIGNvbnN0IHNoYXJlZEtleSA9IE1ldGFkYXRhLmtleSguLi5zaGFyZWRLZXlzKTtcblxuICBjb25zdCBjb25zdHIgPSB0eXBlb2YgbW9kZWwgPT09IFwiZnVuY3Rpb25cIiA/IG1vZGVsIDogbW9kZWwuY29uc3RydWN0b3I7XG5cbiAgY29uc3QgcHJpdmF0ZU1ldGE6IHsgY29sbGVjdGlvbnM6IHN0cmluZ1tdIH0gPSBNZXRhZGF0YS5nZXQoXG4gICAgY29uc3RyIGFzIGFueSxcbiAgICBwcml2YXRlS2V5XG4gICk7XG4gIGNvbnN0IHNoYXJlZE1ldGE6IHsgY29sbGVjdGlvbnM6IHN0cmluZ1tdIH0gPSBNZXRhZGF0YS5nZXQoXG4gICAgY29uc3RyIGFzIGFueSxcbiAgICBzaGFyZWRLZXlcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHByaXZhdGVDb2xzOiBwcml2YXRlTWV0YT8uY29sbGVjdGlvbnMgfHwgW10sXG4gICAgc2hhcmVkQ29sczogc2hhcmVkTWV0YT8uY29sbGVjdGlvbnMgfHwgW10sXG4gIH07XG59LmJpbmQoTW9kZWwpO1xuIiwiaW1wb3J0IHtcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBSZXBvLFxuICBDb250ZXh0LFxuICBVbnN1cHBvcnRlZEVycm9yLFxuICBSZXBvc2l0b3J5LFxuICBDb250ZXh0T2YsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHtcbiAgYWZ0ZXJDcmVhdGUsXG4gIGFmdGVyRGVsZXRlLFxuICBhZnRlclVwZGF0ZSxcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbiAgb25DcmVhdGUsXG4gIG9uRGVsZXRlLFxuICBvblJlYWQsXG4gIG9uVXBkYXRlLFxuICByZWFkb25seSxcbiAgdHJhbnNpZW50LFxuICBWYWxpZGF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljTW9kZWxLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSExDb250ZXh0IH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IEZhYnJpY0VSQzIwQ29udHJhY3QgfSBmcm9tIFwiLi4vY29udHJhY3RzL2VyYzIwL2VyYzIwY29udHJhY3RcIjtcbmltcG9ydCB7XG4gIGFwcGx5LFxuICBDb25zdHJ1Y3RvcixcbiAgRGVjb3JhdGlvbixcbiAgbWV0YWRhdGEsXG4gIE1ldGFkYXRhLFxuICBwcm9wLFxuICBwcm9wTWV0YWRhdGEsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgdG9QYXNjYWxDYXNlIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEZsYWdzIH0gZnJvbSBcIi4uL2NvbnRyYWN0cy90eXBlc1wiO1xuaW1wb3J0IFwiLi4vc2hhcmVkL292ZXJyaWRlc1wiO1xuXG4vKipcbiAqIERlY29yYXRvciBmb3IgbWFya2luZyBtZXRob2RzIHRoYXQgcmVxdWlyZSBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqIENoZWNrcyB0aGUgb3duZXIgb2YgdGhlIHRva2VuIGJlZm9yZSBhbGxvd2luZyB0aGUgbWV0aG9kIHRvIGJlIGV4ZWN1dGVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjbGFzcyBUb2tlbkNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBAT3duZXIoKVxuICogICBhc3luYyBNaW50KGN0eDogQ29udGV4dCwgYW1vdW50OiBudW1iZXIpIHtcbiAqICAgICAvLyBNaW50IHRva2VuIGxvZ2ljXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEByZXR1cm5zIHtNZXRob2REZWNvcmF0b3J9IEEgbWV0aG9kIGRlY29yYXRvciB0aGF0IGNoZWNrcyBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE93bmVyKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gICAgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkge1xuICAgIGNvbnN0IG9yaWdpbmFsTWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBhc3luYyBmdW5jdGlvbiAoXG4gICAgICB0aGlzOiBGYWJyaWNFUkMyMENvbnRyYWN0LFxuICAgICAgLi4uYXJnczogYW55W11cbiAgICApIHtcbiAgICAgIGNvbnN0IGN0eDogSExDb250ZXh0ID0gYXJnc1swXTtcbiAgICAgIGNvbnN0IGFjb3VudElkID0gY3R4LmNsaWVudElkZW50aXR5LmdldElEKCk7XG5cbiAgICAgIGNvbnN0IHNlbGVjdCA9IGF3YWl0ICh0aGlzIGFzIEZhYnJpY0VSQzIwQ29udHJhY3QpW1xuICAgICAgICBcInRva2VuUmVwb3NpdG9yeVwiXG4gICAgICBdLnNlbGVjdCgpO1xuXG4gICAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpO1xuXG4gICAgICBpZiAodG9rZW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFwiTm8gdG9rZW5zIGF2YWlhbGJsZVwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vucy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKGBUbyBtYW55IHRva2VuIGF2YWlsYWJsZSA6ICR7dG9rZW5zLmxlbmd0aH1gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vuc1swXS5vd25lciAhPSBhY291bnRJZCkge1xuICAgICAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgICAgIGBVc2VyIG5vdCBhdXRob3JpemVkIHRvIHJ1biAke3Byb3BlcnR5S2V5fSBvbiB0aGUgdG9rZW5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCBvcmlnaW5hbE1ldGhvZC5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvd25lZEJ5T25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbDxib29sZWFuPixcbiAgUiBleHRlbmRzIFJlcG88TT4sXG4gIFYsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0T2Y8Uj4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHN0dWIgfSA9IGNvbnRleHQgYXMgYW55O1xuXG4gIGNvbnN0IGNyZWF0b3IgPSBhd2FpdCBzdHViLmdldENyZWF0b3IoKTtcbiAgY29uc3Qgb3duZXIgPSBjcmVhdG9yLm1zcGlkO1xuXG4gIGNvbnN0IHNldE93bmVkQnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG5cbiAgc2V0T3duZWRCeUtleVZhbHVlKG1vZGVsLCBrZXkgYXMgc3RyaW5nLCBvd25lcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvd25lZEJ5KCkge1xuICBmdW5jdGlvbiBvd25lZEJ5KCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAob2JqOiBhbnksIGF0dHJpYnV0ZT86IGFueSkge1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICByZXF1aXJlZCgpLFxuICAgICAgICByZWFkb25seSgpLFxuICAgICAgICBvbkNyZWF0ZShvd25lZEJ5T25DcmVhdGUpLFxuICAgICAgICBwcm9wTWV0YWRhdGEoXG4gICAgICAgICAgTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsIEZhYnJpY01vZGVsS2V5cy5PV05FRF9CWSksXG4gICAgICAgICAgYXR0cmlidXRlXG4gICAgICAgIClcbiAgICAgICkob2JqLCBhdHRyaWJ1dGUpO1xuICAgIH07XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLk9XTkVEX0JZKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiBvd25lZEJ5LFxuICAgICAgYXJnczogW10sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWRPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsPGJvb2xlYW4+LFxuICBSIGV4dGVuZHMgUmVwbzxNPixcbiAgVixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHRPZjxSPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc3R1YiB9ID0gY29udGV4dCBhcyBhbnk7XG4gIG1vZGVsW2tleV0gPSBzdHViLmdldFR4SUQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWQoKSB7XG4gIGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWQoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChvYmo6IGFueSwgYXR0cmlidXRlPzogYW55KSB7XG4gICAgICByZXR1cm4gYXBwbHkoXG4gICAgICAgIHJlcXVpcmVkKCksXG4gICAgICAgIHJlYWRvbmx5KCksXG4gICAgICAgIG9uQ3JlYXRlKHRyYW5zYWN0aW9uSWRPbkNyZWF0ZSksXG4gICAgICAgIG9uVXBkYXRlKHRyYW5zYWN0aW9uSWRPbkNyZWF0ZSksXG4gICAgICAgIHByb3BNZXRhZGF0YShcbiAgICAgICAgICBNZXRhZGF0YS5rZXkoXG4gICAgICAgICAgICBGYWJyaWNNb2RlbEtleXMuRkFCUklDLFxuICAgICAgICAgICAgYXR0cmlidXRlLFxuICAgICAgICAgICAgRmFicmljTW9kZWxLZXlzLlRSQU5TQUNUSU9OX0lEXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhdHRyaWJ1dGVcbiAgICAgICAgKVxuICAgICAgKShvYmosIGF0dHJpYnV0ZSk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuVFJBTlNBQ1RJT05fSUQpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IHRyYW5zYWN0aW9uSWQsXG4gICAgICBhcmdzOiBbXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgdHlwZSBNaXJyb3JDb25kaXRpb24gPSAobXNwOiBzdHJpbmcpID0+IGJvb2xlYW47XG5cbmV4cG9ydCB0eXBlIE1pcnJvck1ldGFkYXRhID0ge1xuICBjb25kaXRpb246IE1pcnJvckNvbmRpdGlvbjtcbiAgcmVzb2x2ZXI6IENvbGxlY3Rpb25SZXNvbHZlciB8IHN0cmluZztcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBldmFsTWlycm9yTWV0YWRhdGE8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHJlc29sdmVyOiB1bmRlZmluZWQgfCBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIsXG4gIGN0eDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPlxuKSB7XG4gIGxldCBjb2xsZWN0aW9uOiBDb2xsZWN0aW9uUmVzb2x2ZXIgfCBzdHJpbmcgfCB1bmRlZmluZWQgPSByZXNvbHZlcjtcbiAgaWYgKHR5cGVvZiBjb2xsZWN0aW9uICE9PSBcInN0cmluZ1wiKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG93bmVyID1cbiAgICAgICAgTW9kZWwub3duZXJPZihtb2RlbCkgfHwgY3R4LmdldChcInN0dWJcIikuZ2V0Q3JlYXRvcigpLnRvU3RyaW5nKCk7XG4gICAgICBpZiAocmVzb2x2ZXIgJiYgdHlwZW9mIHJlc29sdmVyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIGNvbGxlY3Rpb24gPSBhd2FpdCByZXNvbHZlcihtb2RlbCwgb3duZXIsIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEZhaWxlZCB0byByZXNvbHZlIGNvbGxlY3Rpb24gbWlycm9yIG5hbWU6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIWNvbGxlY3Rpb24gfHwgdHlwZW9mIGNvbGxlY3Rpb24gIT09IFwic3RyaW5nXCIpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTm8gY29sbGVjdGlvbiBmb3VuZCBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICk7XG4gIHJldHVybiBjb2xsZWN0aW9uO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlTWlycm9ySGFuZGxlcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwb3NpdG9yeTxNLCBhbnk+LFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPixcbiAgZGF0YTogTWlycm9yTWV0YWRhdGEsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjb2xsZWN0aW9uID0gYXdhaXQgZXZhbE1pcnJvck1ldGFkYXRhKG1vZGVsLCBkYXRhLnJlc29sdmVyLCBjb250ZXh0KTtcblxuICBjb25zdCByZXBvID0gdGhpcy5vdmVycmlkZShcbiAgICBPYmplY3QuYXNzaWduKHt9LCB0aGlzLl9vdmVycmlkZXMsIHtcbiAgICAgIHNlZ3JlZ2F0ZTogY29sbGVjdGlvbixcbiAgICAgIGlnbm9yZVZhbGlkYXRpb246IHRydWUsXG4gICAgICBpZ25vcmVIYW5kbGVyczogdHJ1ZSxcbiAgICB9IGFzIGFueSlcbiAgKTtcblxuICBjb25zdCBtaXJyb3IgPSBhd2FpdCByZXBvLmNyZWF0ZShtb2RlbCwgY29udGV4dCk7XG4gIGNvbnRleHQubG9nZ2VyLmluZm8oXG4gICAgYE1pcnJvciBmb3IgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IGNyZWF0ZWQgd2l0aCAke01vZGVsLnBrKG1vZGVsKSBhcyBzdHJpbmd9OiAke21pcnJvcltNb2RlbC5wayhtb2RlbCldfWBcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZU1pcnJvckhhbmRsZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55Pixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IE1pcnJvck1ldGFkYXRhLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29sbGVjdGlvbiA9IGF3YWl0IGV2YWxNaXJyb3JNZXRhZGF0YShtb2RlbCwgZGF0YS5yZXNvbHZlciwgY29udGV4dCk7XG5cbiAgY29uc3QgcmVwbyA9IHRoaXMub3ZlcnJpZGUoXG4gICAgT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5fb3ZlcnJpZGVzLCB7XG4gICAgICBzZWdyZWdhdGU6IGNvbGxlY3Rpb24sXG4gICAgICBpZ25vcmVWYWxpZGF0aW9uOiB0cnVlLFxuICAgICAgaWdub3JlSGFuZGxlcnM6IHRydWUsXG4gICAgfSBhcyBhbnkpXG4gICk7XG5cbiAgY29uc3QgbWlycm9yID0gYXdhaXQgcmVwby51cGRhdGUobW9kZWwsIGNvbnRleHQpO1xuICBjb250ZXh0LmxvZ2dlci5pbmZvKFxuICAgIGBNaXJyb3IgZm9yICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB1cGRhdGVkIHdpdGggJHtNb2RlbC5wayhtb2RlbCkgYXMgc3RyaW5nfTogJHttaXJyb3JbTW9kZWwucGsobW9kZWwpXX1gXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVNaXJyb3JIYW5kbGVyPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvc2l0b3J5PE0sIGFueT4sXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PEZhYnJpY0NvbnRyYWN0RmxhZ3M+LFxuICBkYXRhOiBNaXJyb3JNZXRhZGF0YSxcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNvbGxlY3Rpb24gPSBhd2FpdCBldmFsTWlycm9yTWV0YWRhdGEobW9kZWwsIGRhdGEucmVzb2x2ZXIsIGNvbnRleHQpO1xuXG4gIGNvbnN0IHJlcG8gPSB0aGlzLm92ZXJyaWRlKFxuICAgIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX292ZXJyaWRlcywge1xuICAgICAgc2VncmVnYXRlOiBjb2xsZWN0aW9uLFxuICAgICAgaWdub3JlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICAgIGlnbm9yZUhhbmRsZXJzOiB0cnVlLFxuICAgIH0gYXMgYW55KVxuICApO1xuXG4gIGNvbnN0IG1pcnJvciA9IGF3YWl0IHJlcG8uZGVsZXRlKE1vZGVsLnBrKG1vZGVsKSBhcyBzdHJpbmcsIGNvbnRleHQpO1xuICBjb250ZXh0LmxvZ2dlci5pbmZvKFxuICAgIGBNaXJyb3IgZm9yICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSBkZWxldGVkIHdpdGggJHtNb2RlbC5wayhtb2RlbCkgYXMgc3RyaW5nfTogJHttaXJyb3JbTW9kZWwucGsobW9kZWwpXX1gXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtaXJyb3IoXG4gIGNvbGxlY3Rpb246IENvbGxlY3Rpb25SZXNvbHZlciB8IHN0cmluZyxcbiAgY29uZGl0aW9uPzogTWlycm9yQ29uZGl0aW9uXG4pIHtcbiAgZnVuY3Rpb24gbWlycm9yKFxuICAgIHJlc29sdmVyOiBDb2xsZWN0aW9uUmVzb2x2ZXIgfCBzdHJpbmcsXG4gICAgY29uZGl0aW9uOiBNaXJyb3JDb25kaXRpb25cbiAgKSB7XG4gICAgY29uc3QgbWV0YTogTWlycm9yTWV0YWRhdGEgPSB7XG4gICAgICBjb25kaXRpb246IGNvbmRpdGlvbixcbiAgICAgIHJlc29sdmVyOiByZXNvbHZlcixcbiAgICB9O1xuICAgIHJldHVybiBhcHBseShcbiAgICAgIG1ldGFkYXRhKFxuICAgICAgICBNZXRhZGF0YS5rZXkoRmFicmljTW9kZWxLZXlzLkZBQlJJQywgRmFicmljTW9kZWxLZXlzLk1JUlJPUiksXG4gICAgICAgIG1ldGFcbiAgICAgICksXG4gICAgICBwcml2YXRlRGF0YShjb2xsZWN0aW9uKSxcbiAgICAgIGFmdGVyQ3JlYXRlKGNyZWF0ZU1pcnJvckhhbmRsZXIgYXMgYW55LCBtZXRhLCB7IHByaW9yaXR5OiA5NSB9KSxcbiAgICAgIGFmdGVyVXBkYXRlKHVwZGF0ZU1pcnJvckhhbmRsZXIgYXMgYW55LCBtZXRhLCB7IHByaW9yaXR5OiA5NSB9KSxcbiAgICAgIGFmdGVyRGVsZXRlKGRlbGV0ZU1pcnJvckhhbmRsZXIgYXMgYW55LCBtZXRhLCB7IHByaW9yaXR5OiA5NSB9KVxuICAgICk7XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLk1JUlJPUilcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogbWlycm9yLFxuICAgICAgYXJnczogW2NvbGxlY3Rpb24sIGNvbmRpdGlvbl0sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IHR5cGUgQ29sbGVjdGlvblJlc29sdmVyID0gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT4sXG4gIG1zcD86IHN0cmluZyxcbiAgLi4uYXJnczogYW55W11cbikgPT4gc3RyaW5nO1xuXG5leHBvcnQgY29uc3QgTW9kZWxDb2xsZWN0aW9uOiBDb2xsZWN0aW9uUmVzb2x2ZXIgPSA8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPixcbiAgbXNwSWQ/OiBzdHJpbmdcbikgPT4ge1xuICBjb25zdCBvcmdOYW1lID1cbiAgICBtc3BJZCB8fCAodHlwZW9mIG1vZGVsICE9PSBcImZ1bmN0aW9uXCIgPyBNb2RlbC5vd25lck9mKG1vZGVsKSA6IHVuZGVmaW5lZCk7XG4gIGNvbnN0IGNvbnN0ciA9IHR5cGVvZiBtb2RlbCA9PT0gXCJmdW5jdGlvblwiID8gbW9kZWwgOiBtb2RlbC5jb25zdHJ1Y3RvcjtcbiAgaWYgKCFvcmdOYW1lKVxuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYE1vZGVsICR7Y29uc3RyLm5hbWV9IGlzIG5vdCBvd25lZCBieSBhbnkgb3JnYW5pemF0aW9uLiBkaWQgeW91IHVzZSBAb3duZWRCeSgpIChvciBwcm92aWRlIHRoZSBuYW1lKT9gXG4gICAgKTtcbiAgcmV0dXJuIGAke3RvUGFzY2FsQ2FzZShjb25zdHIubmFtZSl9JHttc3BJZCA/IHRvUGFzY2FsQ2FzZShtc3BJZCkgOiBcIlwifWA7XG59O1xuXG5leHBvcnQgY29uc3QgSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvbjogQ29sbGVjdGlvblJlc29sdmVyID0gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT4sXG4gIG1zcElkPzogc3RyaW5nXG4pID0+IHtcbiAgY29uc3Qgb3JnTmFtZSA9XG4gICAgbXNwSWQgfHwgKHR5cGVvZiBtb2RlbCAhPT0gXCJmdW5jdGlvblwiID8gTW9kZWwub3duZXJPZihtb2RlbCkgOiB1bmRlZmluZWQpO1xuICBpZiAoIW9yZ05hbWUpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBpcyBub3Qgb3duZWQgYnkgYW55IG9yZ2FuaXphdGlvbi4gZGlkIHlvdSB1c2UgQG93bmVkQnkoKSAob3IgcHJvdmlkZSB0aGUgbmFtZSk/YFxuICAgICk7XG4gIHJldHVybiBgX18ke3RvUGFzY2FsQ2FzZShvcmdOYW1lKX1Qcml2YXRlQ29sbGVjdGlvbmA7XG59O1xuXG5leHBvcnQgdHlwZSBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhID0ge1xuICBjb2xsZWN0aW9uczogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0T2Y8dHlwZW9mIHRoaXM+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW10sXG4gIGtleXM6IChrZXlvZiBNKVtdLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChrZXlzLmxlbmd0aCAhPT0gZGF0YS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IG1zcCA9IE1vZGVsLm93bmVyT2YobW9kZWwpO1xuICBpZiAoIW1zcClcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgYFRoZXJlJ3Mgbm8gYXNzaWduZWQgb3JnYW5pemF0aW9uIGZvciBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICk7XG5cbiAgY29uc3QgY29sbGVjdGlvblJlc29sdmVyID0gZGF0YVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogY29sbGVjdGlvblJlc29sdmVyKG1vZGVsLCBtc3AsIGNvbnRleHQpO1xuXG4gIGNvbnN0IHJlYnVpbHQgPSBrZXlzLnJlZHVjZShcbiAgICAoYWNjOiBSZWNvcmQ8a2V5b2YgTSwgYW55PiwgaywgaSkgPT4ge1xuICAgICAgY29uc3QgYyA9XG4gICAgICAgIHR5cGVvZiBkYXRhW2ldLmNvbGxlY3Rpb25zID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBkYXRhW2ldLmNvbGxlY3Rpb25zXG4gICAgICAgICAgOiBkYXRhW2ldLmNvbGxlY3Rpb25zKG1vZGVsLCBtc3AsIGNvbnRleHQpO1xuICAgICAgaWYgKGMgIT09IGNvbGxlY3Rpb24pXG4gICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICAgIGBTZWdyZWdhdGVkIGRhdGEgY29sbGVjdGlvbiBtaXNtYXRjaDogJHtjfSB2cyAke2NvbGxlY3Rpb259YFxuICAgICAgICApO1xuICAgICAgYWNjW2tdID0gbW9kZWxba107XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT5cbiAgKTtcblxuICBjb25zdCB0b0NyZWF0ZSA9IG5ldyB0aGlzLmNsYXNzKHJlYnVpbHQpO1xuXG4gIC8vIGNvbnN0IHNlZ3JlZ2F0ZWQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuXG4gIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB0aGlzLm92ZXJyaWRlKHtcbiAgICBzZWdyZWdhdGVkOiBjb2xsZWN0aW9uLFxuICAgIG1lcmdlTW9kZWw6IGZhbHNlLFxuICAgIGlnbm9yZUhhbmRsZXJzOiB0cnVlLFxuICAgIGlnbm9yZVZhbGlkYXRpb246IHRydWUsXG4gIH0gYXMgYW55KS5jcmVhdGUodG9DcmVhdGUsIGNvbnRleHQpO1xuICBPYmplY3QuYXNzaWduKG1vZGVsLCBjcmVhdGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25SZWFkPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IFJlcG9zaXRvcnk8TSwgYW55PixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNGbGFncz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGFbXSxcbiAga2V5czogKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKGtleXMubGVuZ3RoICE9PSBkYXRhLmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBTZWdyZWdhdGVkIGRhdGEga2V5cyBhbmQgbWV0YWRhdGEgbGVuZ3RoIG1pc21hdGNoYFxuICAgICk7XG5cbiAgY29uc3QgbXNwID0gTW9kZWwub3duZXJPZihtb2RlbCk7XG4gIGlmICghbXNwKVxuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBgVGhlcmUncyBubyBhc3NpZ25lZCBvcmdhbml6YXRpb24gZm9yIG1vZGVsICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX1gXG4gICAgKTtcblxuICBjb25zdCBjb2xsZWN0aW9uUmVzb2x2ZXIgPSBkYXRhWzBdLmNvbGxlY3Rpb25zO1xuICBjb25zdCBjb2xsZWN0aW9uID1cbiAgICB0eXBlb2YgY29sbGVjdGlvblJlc29sdmVyID09PSBcInN0cmluZ1wiXG4gICAgICA/IGNvbGxlY3Rpb25SZXNvbHZlclxuICAgICAgOiBhd2FpdCBjb2xsZWN0aW9uUmVzb2x2ZXIobW9kZWwsIG1zcCwgY29udGV4dCk7XG5cbiAgY29uc3QgcmVidWlsdCA9IGtleXMucmVkdWNlKFxuICAgIChhY2M6IFJlY29yZDxrZXlvZiBNLCBhbnk+LCBrLCBpKSA9PiB7XG4gICAgICBjb25zdCBjID1cbiAgICAgICAgdHlwZW9mIGRhdGFbaV0uY29sbGVjdGlvbnMgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IGRhdGFbaV0uY29sbGVjdGlvbnNcbiAgICAgICAgICA6IGRhdGFbaV0uY29sbGVjdGlvbnMobW9kZWwsIG1zcCwgY29udGV4dCk7XG4gICAgICBpZiAoYyAhPT0gY29sbGVjdGlvbikgcmV0dXJuIGFjYztcbiAgICAgIGFjY1trXSA9IG1vZGVsW2tdO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LFxuICAgIHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+XG4gICk7XG5cbiAgLy8gY29uc3Qgc2VncmVnYXRlZCA9IE1vZGVsLnNlZ3JlZ2F0ZShtb2RlbCk7XG4gIC8vXG4gIC8vIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB0aGlzLm92ZXJyaWRlKHsgc2VncmVnYXRlZDogY29sbGVjdGlvbiB9IGFzIGFueSkucmVhZEFsbChcbiAgLy8gICB0b0NyZWF0ZSxcbiAgLy8gICBjb250ZXh0XG4gIC8vICk7XG4gIC8vIE9iamVjdC5hc3NpZ24obW9kZWwsIGNyZWF0ZWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPblVwZGF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHRPZjx0eXBlb2YgdGhpcz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGFbXSxcbiAga2V5OiBrZXlvZiBNW10sXG4gIG1vZGVsOiBNLFxuICBvbGRNb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7fVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPbkRlbGV0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBWIGV4dGVuZHMgU2VncmVnYXRlZERhdGFNZXRhZGF0YSxcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHRPZjxSPixcbiAgZGF0YTogVltdLFxuICBrZXk6IGtleW9mIE1bXSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge31cblxuZnVuY3Rpb24gc2VncmVnYXRlZChcbiAgY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyLFxuICB0eXBlOiBGYWJyaWNNb2RlbEtleXMuUFJJVkFURSB8IEZhYnJpY01vZGVsS2V5cy5TSEFSRUQsXG4gIGZpbHRlcj86IChwcm9wTmFtZTogc3RyaW5nKSA9PiBib29sZWFuXG4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGlubmVyU2VncmVnYXRlZCh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpIHtcbiAgICBmdW5jdGlvbiBzZWdyZWdhdGVkRGVjKHRhcmdldDogb2JqZWN0LCBwcm9wZXJ0eUtleT86IGFueSkge1xuICAgICAgY29uc3Qga2V5ID0gTWV0YWRhdGEua2V5KHR5cGUsIHByb3BlcnR5S2V5KTtcbiAgICAgIGNvbnN0IGNvbnN0cjogQ29uc3RydWN0b3IgPSB0YXJnZXQuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3I7XG5cbiAgICAgIGNvbnN0IG1ldGEgPSBNZXRhZGF0YS5nZXQoY29uc3RyIGFzIENvbnN0cnVjdG9yLCBrZXkpIHx8IHt9O1xuICAgICAgY29uc3QgY29sbGVjdGlvbnMgPSBuZXcgU2V0KG1ldGEuY29sbGVjdGlvbnMgfHwgW10pO1xuICAgICAgY29sbGVjdGlvbnMuYWRkKGNvbGxlY3Rpb24pO1xuICAgICAgbWV0YS5jb2xsZWN0aW9ucyA9IFsuLi5jb2xsZWN0aW9uc107XG4gICAgICBNZXRhZGF0YS5zZXQoY29uc3RyIGFzIENvbnN0cnVjdG9yLCBrZXksIG1ldGEpO1xuXG4gICAgICBjb25zdCBjb25zdHJNZXRhID0gTWV0YWRhdGEuZ2V0KGNvbnN0ciBhcyBDb25zdHJ1Y3RvciwgdHlwZSkgfHwge307XG4gICAgICBjb25zdCBjb25zdHJDb2xsZWN0aW9ucyA9IG5ldyBTZXQoY29uc3RyTWV0YS5jb2xsZWN0aW9ucyB8fCBbXSk7XG4gICAgICBjb25zdHJDb2xsZWN0aW9ucy5hZGQoY29sbGVjdGlvbik7XG4gICAgICBtZXRhLmNvbGxlY3Rpb25zID0gWy4uLmNvbGxlY3Rpb25zXTtcbiAgICAgIE1ldGFkYXRhLnNldChjb25zdHIgYXMgQ29uc3RydWN0b3IsIHR5cGUsIG1ldGEpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlY3M6IGFueVtdID0gW107XG4gICAgaWYgKCFwcm9wZXJ0eUtleSkge1xuICAgICAgLy8gZGVjb3JhdGVkIGF0IHRoZSBjbGFzcyBsZXZlbFxuICAgICAgTWV0YWRhdGEucHJvcGVydGllcyh0YXJnZXQgYXMgQ29uc3RydWN0b3IpPy5mb3JFYWNoKChwKSA9PiB7XG4gICAgICAgIGlmICghZmlsdGVyIHx8IGZpbHRlcihwKSkge1xuICAgICAgICAgIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgdHlwZSkoKHRhcmdldCBhcyBhbnkpLnByb3RvdHlwZSwgcCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWNzLnB1c2goXG4gICAgICAgIHByb3AoKSxcbiAgICAgICAgdHJhbnNpZW50KCksXG4gICAgICAgIHNlZ3JlZ2F0ZWREZWMsXG4gICAgICAgIG9uQ3JlYXRlKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGUsXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOlxuICAgICAgICAgICAgICB0eXBlb2YgY29sbGVjdGlvbiA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gY29sbGVjdGlvblxuICAgICAgICAgICAgICAgIDogY29sbGVjdGlvbi50b1N0cmluZygpLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgICAgb25SZWFkKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25SZWFkIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvblVwZGF0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uVXBkYXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvbkRlbGV0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uRGVsZXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYXBwbHkoLi4uZGVjcykodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcml2YXRlRGF0YShcbiAgY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyID0gSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvblxuKSB7XG4gIGZ1bmN0aW9uIHByaXZhdGVEYXRhKGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcikge1xuICAgIHJldHVybiBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFKTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuUFJJVkFURSlcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogcHJpdmF0ZURhdGEsXG4gICAgICBhcmdzOiBbY29sbGVjdGlvbl0sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gIGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gICAgcmV0dXJuIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgRmFicmljTW9kZWxLZXlzLlNIQVJFRCk7XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLlNIQVJFRClcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogc2hhcmVkRGF0YSxcbiAgICAgIGFyZ3M6IFtjb2xsZWN0aW9uXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQge1xuICBKU09OU2VyaWFsaXplcixcbiAgTW9kZWwsXG4gIE1vZGVsS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZXRlcm1pbmlzdGljIEpTT04gc2VyaWFsaXplciBmb3IgRmFicmljIG1vZGVsc1xuICogQHN1bW1hcnkgRW5zdXJlcyBzdGFibGUsIGRldGVybWluaXN0aWMgSlNPTiBvdXRwdXQgYnkgc29ydGluZyBvYmplY3Qga2V5cyByZWN1cnNpdmVseSBiZWZvcmUgc3RyaW5naWZpY2F0aW9uLCB3aGljaCBpcyBpbXBvcnRhbnQgZm9yIEZhYnJpYyBlbmRvcnNlbWVudCBhbmQgaGFzaGluZy4gRXh0ZW5kcyBKU09OU2VyaWFsaXplciB0byBwbHVnIGludG8gZXhpc3RpbmcgRGVjYWYgbW9kZWwgc2VyaWFsaXphdGlvbiBmbG93LlxuICogQHRlbXBsYXRlIE0gLSBUaGUgRGVjYWYgTW9kZWwgc3VidHlwZSBzZXJpYWxpemVkIGJ5IHRoaXMgaW5zdGFuY2VcbiAqIEBwYXJhbSB7dm9pZH0gW2NvbnN0cnVjdG9yXSBObyBwdWJsaWMgY29uc3RydWN0b3IgYXJndW1lbnRzXG4gKiBAY2xhc3MgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXJcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBzZXJpYWxpemVyID0gbmV3IERldGVybWluaXN0aWNTZXJpYWxpemVyPE15TW9kZWw+KCk7XG4gKiBjb25zdCBqc29uID0gc2VyaWFsaXplci5zZXJpYWxpemUobW9kZWwpO1xuICogY29uc3QgcmVidWlsdCA9IHNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoanNvbik7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBEUyBhcyBEZXRlcm1pbmlzdGljU2VyaWFsaXplclxuICogICBDYWxsZXItPj5EUzogc2VyaWFsaXplKG1vZGVsKVxuICogICBEUy0+PkRTOiBwcmVTZXJpYWxpemUobW9kZWwpXG4gKiAgIERTLT4+RFM6IHNvcnQta2V5cy1yZWN1cnNpdmVcbiAqICAgRFMtPj5EUzoganNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1xuICogICBEUy0tPj5DYWxsZXI6IHN0cmluZ1xuICogICBDYWxsZXItPj5EUzogZGVzZXJpYWxpemUoc3RyaW5nKVxuICogICBEUy0tPj5DYWxsZXI6IG1vZGVsXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNKSB7XG4gICAgLy8gVE9ETzogbmVzdGVkIHByZXNlcmlhbGl6YXRpb24gKHNvIGluY3JlYXNlIHBlcmZvcm1hbmNlIHdoZW4gZGVzZXJpYWxpemluZylcbiAgICAvLyBUT0RPOiBWZXJpZnkgd2h5IHRoZXJlIGlzIG5vIG1ldGFkYXRhXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgbGV0IG1ldGFkYXRhO1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IE1ldGFkYXRhLm1vZGVsTmFtZShtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3Rvcik7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIG1ldGFkYXRhID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0b1NlcmlhbGl6ZVtNb2RlbEtleXMuQU5DSE9SXSA9IG1ldGFkYXRhIHx8IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG5cbiAgICBjb25zdCBwcmVTZXJpYWxpemUgPSBmdW5jdGlvbiBwcmVTZXJpYWxpemUoXG4gICAgICB0aGlzOiBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxhbnk+LFxuICAgICAgb2JqOiBhbnlcbiAgICApOiBhbnkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSByZXR1cm4gb2JqO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAoKG8pID0+IHByZVNlcmlhbGl6ZS5jYWxsKHNlbGYsIG8pKTtcbiAgICAgIHJldHVybiB0aGlzLnByZVNlcmlhbGl6ZS5jYWxsKHRoaXMsIG9iaik7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgTW9kZWwucmVsYXRpb25zKG1vZGVsKS5mb3JFYWNoKChyKSA9PiB7XG4gICAgICB0b1NlcmlhbGl6ZVtyXSA9IHByZVNlcmlhbGl6ZSh0b1NlcmlhbGl6ZVtyXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRvU2VyaWFsaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJlYnVpbGRzIGEgbW9kZWwgZnJvbSBhIHNlcmlhbGl6YXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQgZmFpbHMgdG8gcGFyc2UgdGhlIHN0cmluZywgb3IgdG8gYnVpbGQgdGhlIG1vZGVsXG4gICAqL1xuICBvdmVycmlkZSBkZXNlcmlhbGl6ZShzdHI6IHN0cmluZyk6IE0ge1xuICAgIGNvbnN0IGRlc2VyaWFsaXphdGlvbiA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBkZXNlcmlhbGl6YXRpb25bTW9kZWxLZXlzLkFOQ0hPUl07XG4gICAgaWYgKCFjbGFzc05hbWUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBjbGFzcyByZWZlcmVuY2UgaW4gc2VyaWFsaXplZCBtb2RlbFwiKTtcbiAgICBjb25zdCBtb2RlbDogTSA9IE1vZGVsLmJ1aWxkKGRlc2VyaWFsaXphdGlvbiwgY2xhc3NOYW1lKSBhcyB1bmtub3duIGFzIE07XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXJpYWxpemUgYSBtb2RlbCBpbnRvIGEgZGV0ZXJtaW5pc3RpYyBKU09OIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBQcmVwYXJlcyB0aGUgbW9kZWwgd2l0aCBwcmVTZXJpYWxpemUsIHNvcnRzIGtleXMgcmVjdXJzaXZlbHksIGFuZCBzdHJpbmdpZmllcyBkZXRlcm1pbmlzdGljYWxseSBmb3Igc3RhYmxlIG9yZGVyaW5nXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gc2VyaWFsaXplXG4gICAqIEByZXR1cm4ge3N0cmluZ30gRGV0ZXJtaW5pc3RpYyBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbFxuICAgKi9cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdHJpbmdpZnkgPSByZXF1aXJlKFwianNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1wiKTtcbiAgICBjb25zdCBzb3J0S2V5c1JlY3Vyc2l2ZSA9IHJlcXVpcmUoXCJzb3J0LWtleXMtcmVjdXJzaXZlXCIpO1xuICAgIHJldHVybiBzdHJpbmdpZnkoc29ydEtleXNSZWN1cnNpdmUodGhpcy5wcmVTZXJpYWxpemUobW9kZWwpKSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBGYWJyaWMgZXZlbnQgbmFtZSBmcm9tIGNvbXBvbmVudHNcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBzdGFuZGFyZGl6ZWQgZXZlbnQgbmFtZSBieSBqb2luaW5nIHRhYmxlLCBldmVudCwgYW5kIG9wdGlvbmFsIG93bmVyIHdpdGggdW5kZXJzY29yZXNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSAtIFRoZSB0YWJsZS9jb2xsZWN0aW9uIG5hbWVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IFtvd25lcl0gLSBPcHRpb25hbCBvd25lciBpZGVudGlmaWVyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgZXZlbnQgbmFtZSBpbiBmb3JtYXQgXCJ0YWJsZV9ldmVudFwiIG9yIFwidGFibGVfZXZlbnRfb3duZXJcIlxuICogQGZ1bmN0aW9uIGdlbmVyYXRlRmFicmljRXZlbnROYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZShcbiAgdGFibGU6IHN0cmluZyxcbiAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcsXG4gIG93bmVyPzogc3RyaW5nXG4pIHtcbiAgY29uc3QgcGFyYW1zID0gW3RhYmxlLCBldmVudF07XG4gIGlmIChvd25lcikgcGFyYW1zLnB1c2gob3duZXIpO1xuICByZXR1cm4gcGFyYW1zLmpvaW4oXCJfXCIpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYSBGYWJyaWMgZXZlbnQgbmFtZSBpbnRvIGl0cyBjb21wb25lbnRzXG4gKiBAc3VtbWFyeSBTcGxpdHMgYW4gZXZlbnQgbmFtZSBieSB1bmRlcnNjb3JlcyBhbmQgZXh0cmFjdHMgdGFibGUsIGV2ZW50LCBhbmQgb3B0aW9uYWwgb3duZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIGV2ZW50IG5hbWUgdG8gcGFyc2VcbiAqIEByZXR1cm4ge3t0YWJsZTogc3RyaW5nLCBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZywgb3duZXI6IHN0cmluZ319IFRoZSBwYXJzZWQgY29tcG9uZW50cyBhcyBhIHN0cnVjdHVyZWQgb2JqZWN0XG4gKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgZXZlbnQgbmFtZSBmb3JtYXQgaXMgaW52YWxpZFxuICogQGZ1bmN0aW9uIHBhcnNlRXZlbnROYW1lXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBQYXJzZXIgYXMgcGFyc2VFdmVudE5hbWVcbiAqICAgQ2FsbGVyLT4+UGFyc2VyOiBwYXJzZUV2ZW50TmFtZShuYW1lKVxuICogICBQYXJzZXItPj5QYXJzZXI6IHNwbGl0IG5hbWUgYnkgXCJfXCJcbiAqICAgYWx0IHBhcnRzIGxlbmd0aCBpbnZhbGlkXG4gKiAgICAgUGFyc2VyLS0+PkNhbGxlcjogdGhyb3cgSW50ZXJuYWxFcnJvclxuICogICBlbHNlXG4gKiAgICAgUGFyc2VyLS0+PkNhbGxlcjogeyB0YWJsZSwgZXZlbnQsIG93bmVyPyB9XG4gKiAgIGVuZFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VFdmVudE5hbWUobmFtZTogc3RyaW5nKToge1xuICB0YWJsZT86IHN0cmluZztcbiAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc7XG4gIG93bmVyPzogc3RyaW5nO1xufSB7XG4gIGNvbnN0IHBhcnRzID0gbmFtZS5zcGxpdChcIl9cIik7XG4gIGlmIChwYXJ0cy5sZW5ndGggPCAyIHx8IHBhcnRzLmxlbmd0aCA+IDMpXG4gICAgcmV0dXJuIHsgdGFibGU6IHVuZGVmaW5lZCwgZXZlbnQ6IG5hbWUsIG93bmVyOiB1bmRlZmluZWQgfTtcbiAgcmV0dXJuIHtcbiAgICB0YWJsZTogcGFydHNbMF0sXG4gICAgZXZlbnQ6IHBhcnRzWzFdLFxuICAgIG93bmVyOiBwYXJ0c1syXSxcbiAgfSBhcyB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZztcbiAgICBvd25lcj86IHN0cmluZztcbiAgfTtcbn1cbiIsImltcG9ydCB7IHN0cmluZ0Zvcm1hdCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IE92ZXJmbG93RXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBPdmVyZmxvdy1zYWZlIGFkZGl0aW9uIG9wZXJhdGlvblxuICogQHN1bW1hcnkgQWRkcyB0d28gbnVtYmVycyBhbmQgdmVyaWZpZXMgbm8gb3ZlcmZsb3cgYnkgcmV2ZXJzZS1jaGVja2luZyB0aGUgb3BlcmFuZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gRmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtudW1iZXJ9IGIgLSBTZWNvbmQgb3BlcmFuZFxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgc3VtIG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvbiBhZGRcbiAqIEB0aHJvd3Mge092ZXJmbG93RXJyb3J9IG9uIGFkZGl0aW9uIG92ZXJmbG93XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGQoYTogbnVtYmVyLCBiOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBjID0gYSArIGI7XG4gIGlmIChhICE9PSBjIC0gYiB8fCBiICE9PSBjIC0gYSkge1xuICAgIHRocm93IG5ldyBPdmVyZmxvd0Vycm9yKGBBZGRpdGlvbiBvdmVyZmxvdzogJHthfSArICR7Yn1gKTtcbiAgfVxuICByZXR1cm4gYztcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3ZlcmZsb3ctc2FmZSBzdWJ0cmFjdGlvbiBvcGVyYXRpb25cbiAqIEBzdW1tYXJ5IFN1YnRyYWN0cyBiIGZyb20gYSBhbmQgdmFsaWRhdGVzIG5vIG92ZXJmbG93IGJ5IHJldmVyc2UtY2hlY2tpbmcgdGhlIG9wZXJhbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gYSAtIE1pbnVlbmRcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gU3VidHJhaGVuZFxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgZGlmZmVyZW5jZSBhIC0gYlxuICogQGZ1bmN0aW9uIHN1YlxuICogQHRocm93cyB7T3ZlcmZsb3dFcnJvcn0gb24gc3VidGFjdGlvbiBvdmVyZmxvd1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ViKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYyA9IGEgLSBiO1xuICBpZiAoYSAhPT0gYyArIGIgfHwgYiAhPT0gYSAtIGMpIHtcbiAgICB0aHJvdyBuZXcgT3ZlcmZsb3dFcnJvcihgU3VidHJhY3Rpb24gb3ZlcmZsb3c6ICR7YX0gLSAke2J9YCk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgU2FmZSBJbnRlZ2VyIFBhcnNlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZ1xuICpcbiAqIEBmdW5jdGlvbiBzYWZlUGFyc2VJbnRcbiAqXG4gKiBAdGhyb3dzIHtWYWxpZGF0aW9uRXJyb3J9IGlmIHBhcnNlSW50IHJldHVybnMgTmFOXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlSW50KHN0cmluZzogc3RyaW5nKTogbnVtYmVyIHtcbiAgLy8gUmVndWxhciBleHByZXNzaW9uIHRvIGNoZWNrIGlmIHN0cmluZyBvbmx5IGhhdmUgZGlnaXRzXG4gIGNvbnN0IGRpZ2l0UmVnZXggPSAvXlxcZCskLztcbiAgaWYgKCFkaWdpdFJlZ2V4LnRlc3Qoc3RyaW5nKSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBzdHJpbmdGb3JtYXQoXCJGYWlsZWQgdG8gcGFyc2U6IHswfVwiLCBcInN0cmluZyBjb250YWlucyBkaWdpdHNcIilcbiAgICApO1xuICB9XG4gIGNvbnN0IHBhcnNlZGludCA9IHBhcnNlSW50KHN0cmluZyk7XG4gIGlmIChpc05hTihwYXJzZWRpbnQpKSB7XG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHN0cmluZ0Zvcm1hdChcIkZhaWxlZCB0byBwYXJzZTogezB9XCIsIFwic3RyaW5nIGlzIG5vdCBhIHBhcnNhYmxlIGludGVnZXJcIilcbiAgICApO1xuICB9XG4gIHJldHVybiBwYXJzZWRpbnQ7XG59XG4iLCJpbXBvcnQge1xuICBKU09OU2VyaWFsaXplcixcbiAgTW9kZWwsXG4gIE1vZGVsS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgb3ZlcnJpZGUgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcsIHRhYmxlTmFtZT86IHN0cmluZyk6IE0ge1xuICAgIGNvbnN0IGRlc2VyaWFsaXphdGlvbiA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICAvLyBjb25zdCBjbGFzc05hbWUgPSB0YWJsZU5hbWU7XG4gICAgLy8gaWYgKCFjbGFzc05hbWUpXG4gICAgLy8gICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBjbGFzcyByZWZlcmVuY2UgaW4gc2VyaWFsaXplZCBtb2RlbFwiKTtcblxuICAgIC8vIC8vIHRoaXMgd2lsbCByZXR1cm4gdW5kZWZpbmVkIHZhbHVlc1xuICAgIC8vIGNvbnN0IG1vZGVsOiBNID0gTW9kZWwuYnVpbGQoZGVzZXJpYWxpemF0aW9uLCBjbGFzc05hbWUpIGFzIHVua25vd24gYXMgTTtcblxuICAgIC8vIC8vIFBvcHVsYXRlIE1vZGVsXG4gICAgLy8gY29uc3QgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbiA9IE9iamVjdC5rZXlzKG1vZGVsKS5yZWR1Y2UoXG4gICAgLy8gICAoYWNjdW06IE0sIGtleSkgPT4ge1xuICAgIC8vICAgICAoYWNjdW0gYXMgUmVjb3JkPHN0cmluZywgYW55Pilba2V5XSA9XG4gICAgLy8gICAgICAgZGVzZXJpYWxpemF0aW9uW1JlcG9zaXRvcnkuY29sdW1uKGFjY3VtLCBrZXkpXTtcbiAgICAvLyAgICAgcmV0dXJuIGFjY3VtO1xuICAgIC8vICAgfSxcbiAgICAvLyAgIG1vZGVsXG4gICAgLy8gKTtcblxuICAgIC8vIGNvbnN0IHJlc3VsdCA9IE1vZGVsLmJ1aWxkKFxuICAgIC8vICAgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbixcbiAgICAvLyAgIGNsYXNzTmFtZVxuICAgIC8vICkgYXMgdW5rbm93biBhcyBNO1xuXG4gICAgLy8gcmV0dXJuIHJlc3VsdDtcbiAgICByZXR1cm4gZGVzZXJpYWxpemF0aW9uO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNLCBwdXRBbmNob3IgPSB0cnVlKTogc3RyaW5nIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHN0cmluZ2lmeSA9IHJlcXVpcmUoXCJqc29uLXN0cmluZ2lmeS1kZXRlcm1pbmlzdGljXCIpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3Qgc29ydEtleXNSZWN1cnNpdmUgPSByZXF1aXJlKFwic29ydC1rZXlzLXJlY3Vyc2l2ZVwiKTtcbiAgICBjb25zdCBwcmVTZXJpYWxpemF0aW9uID0gdGhpcy5wcmVTZXJpYWxpemUobW9kZWwsIHB1dEFuY2hvcik7XG4gICAgcmV0dXJuIHN0cmluZ2lmeShzb3J0S2V5c1JlY3Vyc2l2ZShwcmVTZXJpYWxpemF0aW9uKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNLCBwdXRBbmNob3I6IGJvb2xlYW4gPSB0cnVlKSB7XG4gICAgLy8gVE9ETzogbmVzdGVkIHByZXNlcmlhbGl6YXRpb24gKHNvIGluY3JlYXNlIHBlcmZvcm1hbmNlIHdoZW4gZGVzZXJpYWxpemluZylcbiAgICAvLyBUT0RPOiBWZXJpZnkgd2h5IHRoZXJlIGlzIG5vIG1ldGFkYXRhXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgbGV0IG1ldGFkYXRhO1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IE1ldGFkYXRhLm1vZGVsTmFtZShtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3Rvcik7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIG1ldGFkYXRhID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAocHV0QW5jaG9yKVxuICAgICAgdG9TZXJpYWxpemVbTW9kZWxLZXlzLkFOQ0hPUl0gPSBtZXRhZGF0YSB8fCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuXG4gICAgZnVuY3Rpb24gcHJlU2VyaWFsaXplKFxuICAgICAgdGhpczogU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8YW55PixcbiAgICAgIG9iajogYW55XG4gICAgKTogYW55IHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSByZXR1cm4gb2JqO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAocHJlU2VyaWFsaXplKTtcbiAgICAgIHJldHVybiB0aGlzLnByZVNlcmlhbGl6ZShvYmopO1xuICAgIH1cbiAgICBNb2RlbC5yZWxhdGlvbnMobW9kZWwpLmZvckVhY2goKHIpID0+IHtcbiAgICAgIHRvU2VyaWFsaXplW3JdID0gcHJlU2VyaWFsaXplLmNhbGwodGhpcywgdG9TZXJpYWxpemVbcl0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0b1NlcmlhbGl6ZTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBDbGllbnRCYXNlZFNlcnZpY2UsXG4gIENvbnRleHQsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgRmFicmljQ0FTZXJ2aWNlcywge1xuICBBZmZpbGlhdGlvblNlcnZpY2UsXG4gIElkZW50aXR5U2VydmljZSxcbiAgSUVucm9sbFJlc3BvbnNlLFxuICBJUmVnaXN0ZXJSZXF1ZXN0LFxuICBJU2VydmljZVJlc3BvbnNlLFxuICBUTFNPcHRpb25zLFxufSBmcm9tIFwiZmFicmljLWNhLWNsaWVudFwiO1xuaW1wb3J0IHsgQ0FDb25maWcsIENyZWRlbnRpYWxzIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgQ29uZmxpY3RFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb3JlVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7XG4gIENlcnRpZmljYXRlUmVzcG9uc2UsXG4gIEZhYnJpY0lkZW50aXR5LFxuICBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0LFxuICBJZGVudGl0eVJlc3BvbnNlLFxufSBmcm9tIFwiLi4vLi4vc2hhcmVkL2ZhYnJpYy10eXBlc1wiO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gXCJmYWJyaWMtY29tbW9uXCI7XG5pbXBvcnQgeyBSZWdpc3RyYXRpb25FcnJvciB9IGZyb20gXCIuLi8uLi9zaGFyZWQvZXJyb3JzXCI7XG5pbXBvcnQgeyBDQV9ST0xFIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJS2V5VmFsdWVBdHRyaWJ1dGUgfSBmcm9tIFwiLi9GYWJyaWNFbnJvbGxtZW50U2VydmljZVwiO1xuaW1wb3J0IHsgSWRlbnRpdHkgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL2luZGV4XCI7XG5pbXBvcnQgeyBDcnlwdG9VdGlscyB9IGZyb20gXCIuLi9jcnlwdG9cIjtcblxuZXhwb3J0IGNsYXNzIEZhYnJpY0lkZW50aXR5U2VydmljZSBleHRlbmRzIENsaWVudEJhc2VkU2VydmljZTxcbiAgRmFicmljQ0FTZXJ2aWNlcyxcbiAgQ0FDb25maWdcbj4ge1xuICBwcm90ZWN0ZWQgX3VzZXIhOiBVc2VyO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHJvb3RDbGllbnQoKTogeyBuZXdDZXJ0aWZpY2F0ZVNlcnZpY2U6IGFueSB9IHtcbiAgICByZXR1cm4gKHRoaXMuY2xpZW50IGFzIGFueSlbXCJfRmFicmljQ2FTZXJ2aWNlc1wiXSBhcyBhbnk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHVzZXIoKTogVXNlciB7XG4gICAgaWYgKCF0aGlzLl91c2VyKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIFwiRmFicmljIGlkZW50aXR5IHNlcnZpY2Ugbm90IHByb3Blcmx5IHNldHVwOiBtaXNzaW5nIHVzZXJcIlxuICAgICAgKTtcbiAgICByZXR1cm4gdGhpcy5fdXNlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgY2VydGlmaWNhdGVzKCkge1xuICAgIHJldHVybiB0aGlzLnJvb3RDbGllbnQubmV3Q2VydGlmaWNhdGVTZXJ2aWNlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGFmZmlsaWF0aW9ucygpOiBBZmZpbGlhdGlvblNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5uZXdBZmZpbGlhdGlvblNlcnZpY2UoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgaWRlbnRpdGllcygpOiBJZGVudGl0eVNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5uZXdJZGVudGl0eVNlcnZpY2UoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRVc2VyKGNmZzogQ0FDb25maWcsIGN0eDogQ29udGV4dCkge1xuICAgIGNvbnN0IGxvZyA9IGN0eC5sb2dnZXIuZm9yKHRoaXMuZ2V0VXNlcik7XG4gICAgY29uc3QgeyBjYU5hbWUsIGNhQ2VydCwgY2FLZXksIHVybCwgaHNtIH0gPSBjZmc7XG5cbiAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgQ0EgdXNlciBmb3IgJHtjYU5hbWV9IGF0ICR7dXJsfWApO1xuICAgIGxvZy52ZXJib3NlKGBSZXRyaWV2aW5nIENBIGNlcnRpZmljYXRlIGZyb20gJHtjYUNlcnR9YCk7XG4gICAgY29uc3QgY2VydGlmaWNhdGUgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoY2FDZXJ0KTtcbiAgICBsZXQga2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKCFoc20pIHtcbiAgICAgIGlmICghY2FLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYE1pc3NpbmcgY2FLZXkgY29uZmlndXJhdGlvbiBmb3IgQ0EgJHtjYU5hbWV9LiBQcm92aWRlIGEga2V5IGRpcmVjdG9yeSBvciBjb25maWd1cmUgSFNNIHN1cHBvcnQuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbG9nLmRlYnVnKGBSZXRyaWV2aW5nIENBIGtleSBmcm9tICR7Y2FLZXl9YCk7XG4gICAgICBrZXkgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoY2FLZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2cuZGVidWcoXG4gICAgICAgIGBVc2luZyBIU00gY29uZmlndXJhdGlvbiBmb3IgQ0EgJHtjYU5hbWV9IHdpdGggbGlicmFyeSAke2hzbS5saWJyYXJ5fWBcbiAgICAgICk7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgTG9hZGluZyBBZG1pbiB1c2VyIGZvciBjYSAke2NhTmFtZX1gKTtcbiAgICB0aGlzLl91c2VyID0gYXdhaXQgQ29yZVV0aWxzLmdldENBVXNlcihcImFkbWluXCIsIGtleSwgY2VydGlmaWNhdGUsIGNhTmFtZSwge1xuICAgICAgaHNtLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLl91c2VyO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdGlhbGl6ZShcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPHsgY29uZmlnOiBDQUNvbmZpZzsgY2xpZW50OiBGYWJyaWNDQVNlcnZpY2VzIH0+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmluaXRpYWxpemUsIHRydWUpO1xuICAgIGNvbnN0IFtjb25maWddID0gYXJncztcbiAgICBpZiAoIWNvbmZpZykgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJNaXNzaW5nIEZhYnJpYyBDQSBjb25maWd1cmF0aW9uXCIpO1xuXG4gICAgY29uc3QgeyB1cmwsIHRscywgY2FOYW1lIH0gPSBjb25maWc7XG4gICAgbG9nLmluZm8oYEluaXRpYWxpemluZyBDQSBDbGllbnQgZm9yIENBICR7Y29uZmlnLmNhTmFtZX0gYXQgJHtjb25maWcudXJsfWApO1xuICAgIGNvbnN0IHsgdHJ1c3RlZFJvb3RzLCB2ZXJpZnkgfSA9IHRscyBhcyBUTFNPcHRpb25zO1xuXG4gICAgY29uc3Qgcm9vdCA9ICh0cnVzdGVkUm9vdHMgYXMgc3RyaW5nW10pWzBdIGFzIHN0cmluZztcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0EgY2VydGlmaWNhdGUgZnJvbSAke3Jvb3R9LiBjd2Q6ICR7cHJvY2Vzcy5jd2QoKX1gKTtcblxuICAgIGNvbnN0IGNlcnRpZmljYXRlID0gYXdhaXQgQ29yZVV0aWxzLmdldEZpbGVDb250ZW50KHJvb3QpO1xuXG4gICAgbG9nLmRlYnVnKGBDQSBDZXJ0aWZpY2F0ZTogJHtjZXJ0aWZpY2F0ZS50b1N0cmluZygpfWApO1xuXG4gICAgY29uc3QgY2xpZW50ID0gbmV3IEZhYnJpY0NBU2VydmljZXMoXG4gICAgICB1cmwsXG4gICAgICB7XG4gICAgICAgIHRydXN0ZWRSb290czogQnVmZmVyLmZyb20oY2VydGlmaWNhdGUpLFxuICAgICAgICB2ZXJpZnksXG4gICAgICB9IGFzIFRMU09wdGlvbnMsXG4gICAgICBjYU5hbWVcbiAgICApO1xuXG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZ2V0VXNlcihjb25maWcsIGN0eCk7XG4gICAgbG9nLmRlYnVnKGBDQSB1c2VyIGxvYWRlZDogJHt1c2VyLmdldE5hbWUoKX1gKTtcbiAgICByZXR1cm4ge1xuICAgICAgY29uZmlnLFxuICAgICAgY2xpZW50LFxuICAgIH07XG4gIH1cblxuICBhc3luYyBnZXRDZXJ0aWZpY2F0ZXMoLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT4pOiBQcm9taXNlPHN0cmluZ1tdPjtcbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzKFxuICAgIHJlcXVlc3Q6IEdldENlcnRpZmljYXRlc1JlcXVlc3QsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxzdHJpbmdbXT47XG4gIGFzeW5jIGdldENlcnRpZmljYXRlczxNQVAgZXh0ZW5kcyBib29sZWFuPihcbiAgICBkb01hcDogTUFQLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TUFQIGV4dGVuZHMgZmFsc2UgPyBDZXJ0aWZpY2F0ZVJlc3BvbnNlIDogc3RyaW5nW10+O1xuICBhc3luYyBnZXRDZXJ0aWZpY2F0ZXM8TUFQIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgcmVxdWVzdDogR2V0Q2VydGlmaWNhdGVzUmVxdWVzdCxcbiAgICBkb01hcDogTUFQLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TUFQIGV4dGVuZHMgZmFsc2UgPyBDZXJ0aWZpY2F0ZVJlc3BvbnNlIDogc3RyaW5nW10+O1xuICBhc3luYyBnZXRDZXJ0aWZpY2F0ZXM8TUFQIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgcmVxdWVzdD86IEdldENlcnRpZmljYXRlc1JlcXVlc3QgfCBNQVAsXG4gICAgZG9NYXA6IE1BUCA9IHRydWUgYXMgTUFQLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TUFQIGV4dGVuZHMgZmFsc2UgPyBDZXJ0aWZpY2F0ZVJlc3BvbnNlIDogc3RyaW5nW10+IHtcbiAgICBpZiAocmVxdWVzdCBpbnN0YW5jZW9mIENvbnRleHQpIHtcbiAgICAgIGFyZ3MgPSBbcmVxdWVzdF07XG4gICAgICBkb01hcCA9IHRydWUgYXMgTUFQO1xuICAgICAgcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiByZXF1ZXN0ID09PSBcImJvb2xlYW5cIikge1xuICAgICAgZG9NYXAgPSByZXF1ZXN0O1xuICAgICAgcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkb01hcCAhPT0gXCJib29sZWFuXCIpIHtcbiAgICAgIGFyZ3MgPSBbZG9NYXAgYXMgTWF5YmVDb250ZXh0dWFsQXJnPGFueT4sIC4uLmFyZ3NdO1xuICAgICAgZG9NYXAgPSB0cnVlIGFzIE1BUDtcbiAgICB9XG5cbiAgICBjb25zdCB7IGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgdGhpcy5nZXRDZXJ0aWZpY2F0ZXMsIHRydWUpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBSZXRyaWV2aW5nIGNlcnRpZmljYXRlcyR7cmVxdWVzdCA/IGAgZm9yICR7cmVxdWVzdC5pZH1gIDogXCJcIn0gZm9yIENBICR7dGhpcy5jb25maWcuY2FOYW1lfWBcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBDZXJ0aWZpY2F0ZVJlc3BvbnNlID0gKFxuICAgICAgYXdhaXQgdGhpcy5jZXJ0aWZpY2F0ZXMuZ2V0Q2VydGlmaWNhdGVzKHJlcXVlc3QgfHwge30sIHRoaXMudXNlcilcbiAgICApLnJlc3VsdDtcbiAgICBsb2cudmVyYm9zZShgRm91bmQgJHtyZXNwb25zZS5jZXJ0cy5sZW5ndGh9IGNlcnRpZmljYXRlc2ApO1xuICAgIGxvZy5kZWJ1ZyhyZXNwb25zZS5jZXJ0cyk7XG4gICAgcmV0dXJuIChcbiAgICAgIGRvTWFwID8gcmVzcG9uc2UuY2VydHMubWFwKChjKSA9PiBjLlBFTSkgOiByZXNwb25zZVxuICAgICkgYXMgTUFQIGV4dGVuZHMgZmFsc2UgPyBDZXJ0aWZpY2F0ZVJlc3BvbnNlIDogc3RyaW5nW107XG4gIH1cblxuICBhc3luYyBnZXRJZGVudGl0aWVzKGN0eDogQ29udGV4dCk6IFByb21pc2U8RmFicmljSWRlbnRpdHlbXT4ge1xuICAgIGNvbnN0IGxvZyA9IGN0eC5sb2dnZXIuZm9yKHRoaXMuZ2V0SWRlbnRpdGllcyk7XG4gICAgbG9nLnZlcmJvc2UoYFJldHJpZXZpbmcgSWRlbnRpdGllcyB1bmRlciBDQSAke3RoaXMuY29uZmlnLmNhTmFtZX1gKTtcbiAgICBjb25zdCByZXNwb25zZTogSWRlbnRpdHlSZXNwb25zZSA9IChhd2FpdCB0aGlzLmlkZW50aXRpZXMuZ2V0QWxsKHRoaXMudXNlcikpXG4gICAgICAucmVzdWx0O1xuICAgIGxvZy52ZXJib3NlKGBGb3VuZCAke3Jlc3BvbnNlLmlkZW50aXRpZXMubGVuZ3RofSBJZGVudGl0aWVzYCk7XG4gICAgbG9nLmRlYnVnKHJlc3BvbnNlLmlkZW50aXRpZXMpO1xuICAgIHJldHVybiByZXNwb25zZS5pZGVudGl0aWVzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZSBhZmZpbGlhdGlvbnMgZnJvbSB0aGUgQ0EuXG4gICAqIEBzdW1tYXJ5IFF1ZXJpZXMgdGhlIENBIGZvciB0aGUgbGlzdCBvZiBhZmZpbGlhdGlvbnMgYXZhaWxhYmxlIHVuZGVyIHRoZSBjb25maWd1cmVkIENBLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBhZmZpbGlhdGlvbnMgcmVzdWx0IHBheWxvYWQuXG4gICAqL1xuICBhc3luYyBnZXRBZmZpbGlhdGlvbnMoY3R4OiBDb250ZXh0KSB7XG4gICAgY29uc3QgbG9nID0gY3R4LmxvZ2dlci5mb3IodGhpcy5nZXRBZmZpbGlhdGlvbnMpO1xuICAgIGxvZy52ZXJib3NlKGBSZXRyaWV2aW5nIEFmZmlsaWF0aW9ucyB1bmRlciBDQSAke3RoaXMuY29uZmlnLmNhTmFtZX1gKTtcbiAgICBjb25zdCByZXNwb25zZSA9IChhd2FpdCB0aGlzLmFmZmlsaWF0aW9ucy5nZXRBbGwodGhpcy51c2VyKSkucmVzdWx0O1xuICAgIGxvZy52ZXJib3NlKGBGb3VuZCAke3Jlc3BvbnNlLmEubGVuZ3RofSBBZmZpbGlhdGlvbnNgKTtcbiAgICBsb2cuZGVidWcoSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VFcnJvcihlOiBFcnJvcikge1xuICAgIGNvbnN0IHJlZ2V4cCA9IC8uKmNvZGU6XFxzKFxcZCspLio/bWVzc2FnZTpcXHNbXCInXSguKylbXCInXS9ncztcbiAgICBjb25zdCBtYXRjaCA9IHJlZ2V4cC5leGVjKGUubWVzc2FnZSk7XG4gICAgaWYgKCFtYXRjaCkgcmV0dXJuIG5ldyBSZWdpc3RyYXRpb25FcnJvcihlKTtcbiAgICBjb25zdCBbLCBjb2RlLCBtZXNzYWdlXSA9IG1hdGNoO1xuICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgY2FzZSBcIjc0XCI6XG4gICAgICBjYXNlIFwiNzFcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKG1lc3NhZ2UpO1xuICAgICAgY2FzZSBcIjIwXCI6XG4gICAgICAgIHJldHVybiBuZXcgQXV0aG9yaXphdGlvbkVycm9yKG1lc3NhZ2UpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG5ldyBSZWdpc3RyYXRpb25FcnJvcihtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWQgaWRlbnRpdHkgZGV0YWlscyBmcm9tIHRoZSBDQSBieSBlbnJvbGxtZW50IElELlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYW5kIHZhbGlkYXRlcyBhIHNpbmdsZSBpZGVudGl0eSwgdGhyb3dpbmcgTm90Rm91bmRFcnJvciB3aGVuIG1pc3NpbmcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBlbnJvbGxtZW50SWQgLSBFbnJvbGxtZW50IElEIHRvIGxvb2t1cC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxGYWJyaWNJZGVudGl0eT59IFRoZSBpZGVudGl0eSBkZXRhaWxzIHN0b3JlZCBpbiB0aGUgQ0EuXG4gICAqL1xuICBhc3luYyByZWFkKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8RmFicmljSWRlbnRpdHk+IHtcbiAgICBjb25zdCB7IGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkLCB0cnVlKTtcbiAgICBsb2cudmVyYm9zZShgUmV0cmlldmluZyBpZGVudGl0eSB3aXRoIGVucm9sbG1lbnQgSUQgJHtlbnJvbGxtZW50SWR9YCk7XG4gICAgbGV0IHJlc3VsdDogSVNlcnZpY2VSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5pZGVudGl0aWVzLmdldE9uZShlbnJvbGxtZW50SWQsIHRoaXMudXNlcik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYENvdWxkbid0IGZpbmQgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgQ291bGRuJ3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke3Jlc3VsdC5lcnJvcnMuam9pbihcIlxcblwiKX1gXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQgYXMgRmFicmljSWRlbnRpdHk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVyIGEgbmV3IGlkZW50aXR5IHdpdGggdGhlIENBLlxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgcmVnaXN0cmF0aW9uIHJlcXVlc3QgZm9yIGEgbmV3IGVucm9sbG1lbnQgSUQsIHJldHVybmluZyB0aGUgZW5yb2xsbWVudCBzZWNyZXQgdXBvbiBzdWNjZXNzLlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkIGZvciB0aGUgbmV3IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSByZWdpc3RlcmVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXIoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmVnaXN0ZXIsIHRydWUpO1xuXG4gICAgbGV0IHJlZ2lzdHJhdGlvbjogc3RyaW5nO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IHVzZXJOYW1lLCBwYXNzd29yZCB9ID0gbW9kZWw7XG4gICAgICBjb25zdCBwcm9wcyA9IHtcbiAgICAgICAgZW5yb2xsbWVudElEOiB1c2VyTmFtZSBhcyBzdHJpbmcsXG4gICAgICAgIGVucm9sbG1lbnRTZWNyZXQ6IHBhc3N3b3JkLFxuICAgICAgICBhZmZpbGlhdGlvbjogYWZmaWxpYXRpb24sXG4gICAgICAgIHVzZXJSb2xlOiB1c2VyUm9sZSxcbiAgICAgICAgYXR0cnM6IGF0dHJzLFxuICAgICAgICBtYXhFbnJvbGxtZW50czogbWF4RW5yb2xsbWVudHMsXG4gICAgICB9IGFzIElSZWdpc3RlclJlcXVlc3Q7XG4gICAgICByZWdpc3RyYXRpb24gPSBhd2FpdCB0aGlzLmNsaWVudC5yZWdpc3Rlcihwcm9wcywgdGhpcy51c2VyKTtcbiAgICAgIGxvZy5pbmZvKFxuICAgICAgICBgUmVnaXN0cmF0aW9uIGZvciAke3VzZXJOYW1lfSBjcmVhdGVkIHdpdGggdXNlciB0eXBlICR7dXNlclJvbGUgPz8gXCJVbmRlZmluZWQgUm9sZVwifSAke2lzU3VwZXJVc2VyID8gXCJhcyBzdXBlciB1c2VyXCIgOiBcIlwifWBcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICAgIHJldHVybiByZWdpc3RyYXRpb247XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGlkZW50aXR5RnJvbUVucm9sbG1lbnQoXG4gICAgZW5yb2xsbWVudDogSUVucm9sbFJlc3BvbnNlLFxuICAgIG1zcElkOiBzdHJpbmcsXG4gICAgY3R4OiBDb250ZXh0XG4gICk6IElkZW50aXR5IHtcbiAgICBjb25zdCBsb2cgPSBjdHgubG9nZ2VyLmZvcih0aGlzLmlkZW50aXR5RnJvbUVucm9sbG1lbnQpO1xuICAgIGNvbnN0IHsgY2VydGlmaWNhdGUsIGtleSwgcm9vdENlcnRpZmljYXRlIH0gPSBlbnJvbGxtZW50O1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEdlbmVyYXRpbmcgSWRlbnRpdHkgZnJvbSBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlfSBpbiBtc3AgJHttc3BJZH1gXG4gICAgKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IENyeXB0b1V0aWxzLmZhYnJpY0lkRnJvbUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBpZCA9IENyeXB0b1V0aWxzLmVuY29kZShjbGllbnRJZCk7XG4gICAgbG9nLmRlYnVnKGBJZGVudGl0eSAke2NsaWVudElkfSBhbmQgZW5jb2RlZElkICR7aWR9YCk7XG4gICAgcmV0dXJuIG5ldyBJZGVudGl0eSh7XG4gICAgICBpZDogaWQsXG4gICAgICBjcmVkZW50aWFsczoge1xuICAgICAgICBpZDogaWQsXG4gICAgICAgIGNlcnRpZmljYXRlOiBjZXJ0aWZpY2F0ZSxcbiAgICAgICAgcHJpdmF0ZUtleToga2V5LnRvQnl0ZXMoKSxcbiAgICAgICAgcm9vdENlcnRpZmljYXRlOiByb290Q2VydGlmaWNhdGUsXG4gICAgICB9LFxuICAgICAgbXNwSWQ6IG1zcElkLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFbnJvbGwgYW4gaWRlbnRpdHkgd2l0aCB0aGUgQ0EgdXNpbmcgYSByZWdpc3RyYXRpb24gc2VjcmV0LlxuICAgKiBAc3VtbWFyeSBFeGNoYW5nZXMgdGhlIGVucm9sbG1lbnQgSUQgYW5kIHNlY3JldCBmb3IgY2VydGlmaWNhdGVzLCByZXR1cm5pbmcgYSBjb25zdHJ1Y3RlZCBJZGVudGl0eSBtb2RlbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGVucm9sbG1lbnRJZCAtIEVucm9sbG1lbnQgSUQgdG8gZW5yb2xsLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmVnaXN0cmF0aW9uIC0gRW5yb2xsbWVudCBzZWNyZXQgcmV0dXJuZWQgYXQgcmVnaXN0cmF0aW9uIHRpbWUuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8SWRlbnRpdHk+fSBUaGUgZW5yb2xsZWQgaWRlbnRpdHkgb2JqZWN0IHdpdGggY3JlZGVudGlhbHMuXG4gICAqL1xuICBhc3luYyBlbnJvbGwoXG4gICAgZW5yb2xsbWVudElkOiBzdHJpbmcsXG4gICAgcmVnaXN0cmF0aW9uOiBzdHJpbmcsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxJZGVudGl0eT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMuZW5yb2xsLCB0cnVlKTtcbiAgICBsZXQgaWRlbnRpdHk6IElkZW50aXR5O1xuICAgIHRyeSB7XG4gICAgICBsb2cuZGVidWcoYEVucm9sbGluZyAke2Vucm9sbG1lbnRJZH1gKTtcbiAgICAgIGNvbnN0IGVucm9sbG1lbnQ6IElFbnJvbGxSZXNwb25zZSA9IGF3YWl0IHRoaXMuY2xpZW50LmVucm9sbCh7XG4gICAgICAgIGVucm9sbG1lbnRJRDogZW5yb2xsbWVudElkLFxuICAgICAgICBlbnJvbGxtZW50U2VjcmV0OiByZWdpc3RyYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGlkZW50aXR5ID0gRmFicmljSWRlbnRpdHlTZXJ2aWNlLmlkZW50aXR5RnJvbUVucm9sbG1lbnQoXG4gICAgICAgIGVucm9sbG1lbnQsXG4gICAgICAgIHRoaXMuY29uZmlnLmNhTmFtZSxcbiAgICAgICAgY3R4XG4gICAgICApO1xuICAgICAgbG9nLmluZm8oXG4gICAgICAgIGBTdWNjZXNzZnVsbHkgZW5yb2xsZWQgJHtlbnJvbGxtZW50SWR9IHVuZGVyICR7dGhpcy5jb25maWcuY2FOYW1lfSBhcyAke2lkZW50aXR5LmlkfWBcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICAgIHJldHVybiBpZGVudGl0eTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXIgYW5kIGVucm9sbCBhIG5ldyBpZGVudGl0eSBpbiBvbmUgc3RlcC5cbiAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIGEgbmV3IGVucm9sbG1lbnQgSUQgd2l0aCB0aGUgQ0EgYW5kIGltbWVkaWF0ZWx5IGV4Y2hhbmdlcyB0aGUgc2VjcmV0IHRvIGVucm9sbCwgcmV0dXJuaW5nIHRoZSBjcmVhdGVkIElkZW50aXR5LlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGZvciB0aGUgbmV3IGlkZW50aXR5IGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxJZGVudGl0eT59IFRoZSBlbnJvbGxlZCBpZGVudGl0eS5cbiAgICovXG4gIGFzeW5jIHJlZ2lzdGVyQW5kRW5yb2xsKFxuICAgIG1vZGVsOiBDcmVkZW50aWFscyxcbiAgICBpc1N1cGVyVXNlcjogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGFmZmlsaWF0aW9uOiBzdHJpbmcgPSBcIlwiLFxuICAgIHVzZXJSb2xlPzogQ0FfUk9MRSB8IHN0cmluZyxcbiAgICBhdHRycz86IElLZXlWYWx1ZUF0dHJpYnV0ZSxcbiAgICBtYXhFbnJvbGxtZW50cz86IG51bWJlcixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPElkZW50aXR5PiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmVnaXN0ZXJBbmRFbnJvbGwsIHRydWUpO1xuICAgIGNvbnN0IHJlZ2lzdHJhdGlvbiA9IGF3YWl0IHRoaXMucmVnaXN0ZXIoXG4gICAgICBtb2RlbCxcbiAgICAgIGlzU3VwZXJVc2VyLFxuICAgICAgYWZmaWxpYXRpb24sXG4gICAgICB1c2VyUm9sZSxcbiAgICAgIGF0dHJzLFxuICAgICAgbWF4RW5yb2xsbWVudHMsXG4gICAgICBjdHhcbiAgICApO1xuICAgIGNvbnN0IHsgdXNlck5hbWUgfSA9IG1vZGVsO1xuICAgIHJldHVybiB0aGlzLmVucm9sbCh1c2VyTmFtZSBhcyBzdHJpbmcsIHJlZ2lzdHJhdGlvbiwgY3R4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXZva2VzIHRoZSBlbnJvbGxtZW50IG9mIGFuIGlkZW50aXR5IHdpdGggdGhlIHNwZWNpZmllZCBlbnJvbGxtZW50IElELlxuICAgKlxuICAgKiBAcGFyYW0gZW5yb2xsbWVudElkIC0gVGhlIGVucm9sbG1lbnQgSUQgb2YgdGhlIGlkZW50aXR5IHRvIGJlIHJldm9rZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSByZXN1bHQgb2YgdGhlIHJldm9jYXRpb24gb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAdGhyb3dzIHtOb3RGb3VuZEVycm9yfSBJZiB0aGUgZW5yb2xsbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgSUQgZG9lcyBub3QgZXhpc3QuXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZXJlIGlzIGFuIGVycm9yIGR1cmluZyB0aGUgcmV2b2NhdGlvbiBwcm9jZXNzLlxuICAgKi9cbiAgYXN5bmMgcmV2b2tlKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8SVNlcnZpY2VSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJldm9rZSwgdHJ1ZSk7XG4gICAgbG9nLnZlcmJvc2UoYFJldm9raW5nIGlkZW50aXR5IHdpdGggZW5yb2xsbWVudCBJRCAke2Vucm9sbG1lbnRJZH1gKTtcbiAgICBjb25zdCBpZGVudGl0eSA9IGF3YWl0IHRoaXMucmVhZChlbnJvbGxtZW50SWQpO1xuICAgIGlmICghaWRlbnRpdHkpXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYENvdWxkIG5vdCBmaW5kIGVucm9sbG1lbnQgd2l0aCBpZCAke2Vucm9sbG1lbnRJZH1gXG4gICAgICApO1xuICAgIGxldCByZXN1bHQ6IElTZXJ2aWNlUmVzcG9uc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHRoaXMuY2xpZW50LnJldm9rZShcbiAgICAgICAgeyBlbnJvbGxtZW50SUQ6IGlkZW50aXR5LmlkLCByZWFzb246IFwiVXNlciBEZWxldGlvblwiIH0sXG4gICAgICAgIHRoaXMudXNlclxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYENvdWxkIG5vdCByZXZva2UgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghcmVzdWx0LnN1Y2Nlc3MpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYENvdWxkIG5vdCByZXZva2UgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtyZXN1bHQuZXJyb3JzLmpvaW4oXCJcXG5cIil9YFxuICAgICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iLCJpbXBvcnQgeyBGYWJyaWNDbGllbnRGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWZhdWx0QWRhcHRlckZsYWdzIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5cbmV4cG9ydCBjb25zdCBEZWZhdWx0RmFicmljQ2xpZW50RmxhZ3M6IEZhYnJpY0NsaWVudEZsYWdzID0gT2JqZWN0LmFzc2lnbihcbiAge1xuICAgIGV2YWx1YXRlVGltZW91dDogNSxcbiAgICBlbmRvcnNlVGltZW91dDogMTUsXG4gICAgc3VibWl0VGltZW91dDogNSxcbiAgICBjb21taXRUaW1lb3V0OiA2MCxcbiAgfSxcbiAgRGVmYXVsdEFkYXB0ZXJGbGFnc1xuKSBhcyBhbnk7XG4iLCJpbXBvcnQgeyBpc0Jyb3dzZXIsIE1pbmlMb2dnZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IFVzZXIgfSBmcm9tIFwiZmFicmljLWNvbW1vblwiO1xuaW1wb3J0IHsgSWRlbnRpdHksIFNpZ25lciwgc2lnbmVycyB9IGZyb20gXCJAaHlwZXJsZWRnZXIvZmFicmljLWdhdGV3YXlcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZUltcG9ydCB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuXG5jb25zdCBsb2cgPSBuZXcgTWluaUxvZ2dlcihcImZhYnJpYy1mc1wiKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTG9hZHMgY29udGVudCBmcm9tIGEgZmlsZSBvciByZXR1cm5zIHRoZSBjb250ZW50IGlmIGFscmVhZHkgbG9hZGVkXG4gKiBAc3VtbWFyeSBEZXRlcm1pbmVzIGlmIHRoZSBpbnB1dCBpcyBhbHJlYWR5IGNvbnRlbnQgb3IgYSBwYXRoIHRvIGEgZmlsZSwgYW5kIGxvYWRzIHRoZSBmaWxlIGlmIG5lZWRlZFxuICogQHBhcmFtIHtzdHJpbmcgfCBVaW50OEFycmF5fSBjb250ZW50T3JQYXRoIC0gVGhlIGNvbnRlbnQgb3IgcGF0aCB0byBsb2FkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaWxlUmVhZGVyIC0gRnVuY3Rpb24gdG8gcmVhZCB0aGUgZmlsZSBpZiBjb250ZW50T3JQYXRoIGlzIGEgcGF0aFxuICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmcgfCBVaW50OEFycmF5IHwgQnVmZmVyPn0gVGhlIGNvbnRlbnRcbiAqIEBmdW5jdGlvbiBjb250ZW50T2ZMb2FkRmlsZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29udGVudE9mTG9hZEZpbGUoXG4gIGNvbnRlbnRPclBhdGg6IHN0cmluZyB8IFVpbnQ4QXJyYXksXG4gIGZpbGVSZWFkZXI6IChwYXRoOiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nIHwgVWludDhBcnJheSB8IEJ1ZmZlcj5cbikge1xuICBpZiAoY29udGVudE9yUGF0aCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHJldHVybiBjb250ZW50T3JQYXRoO1xuICBpZiAoXG4gICAgY29udGVudE9yUGF0aC5tYXRjaChcbiAgICAgIC8tLS0tLUJFR0lOIChDRVJUSUZJQ0FURXxLRVl8UFJJVkFURSBLRVkpLS0tLS0uKz8tLS0tLUVORCBcXDEtLS0tLSQvZ21zXG4gICAgKVxuICApXG4gICAgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG4gIHJldHVybiBhd2FpdCBmaWxlUmVhZGVyKGNvbnRlbnRPclBhdGgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIGZpbGUgZnJvbSB0aGUgZmlsZSBzeXN0ZW1cbiAqIEBzdW1tYXJ5IExvYWRzIGEgZmlsZSB1c2luZyB0aGUgTm9kZS5qcyBmaWxlIHN5c3RlbSBtb2R1bGVcbiAqIEBwYXJhbSB7c3RyaW5nIHwgQnVmZmVyfSBjb250ZW50T3JQYXRoIC0gVGhlIGNvbnRlbnQgb3IgcGF0aCB0byBsb2FkXG4gKiBAcmV0dXJuIHtQcm9taXNlPEJ1ZmZlcj59IFRoZSBmaWxlIGNvbnRlbnQgYXMgYSBCdWZmZXJcbiAqIEBmdW5jdGlvbiByZWFkRmlsZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEZpbGUoY29udGVudE9yUGF0aDogc3RyaW5nIHwgQnVmZmVyKSB7XG4gIGlmICh0eXBlb2YgY29udGVudE9yUGF0aCAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG5cbiAgY29uc3QgZmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIHJldHVybiBhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShwYXRoKTtcbiAgfTtcblxuICByZXR1cm4gYXdhaXQgZmlsZVJlYWRlcihjb250ZW50T3JQYXRoKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIENlcnRpZmljYXRlIEF1dGhvcml0eSB1c2VyXG4gKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHVzZXIgd2l0aCB0aGUgZ2l2ZW4gY3JlZGVudGlhbHMgZm9yIGludGVyYWN0aW5nIHdpdGggYSBGYWJyaWMgQ0FcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyTmFtZSAtIFRoZSB1c2VyIG5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcml2YXRlS2V5IC0gVGhlIHByaXZhdGUga2V5IGFzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gY2VydGlmaWNhdGUgLSBUaGUgY2VydGlmaWNhdGUgYXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc3BJZCAtIFRoZSBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgSURcbiAqIEByZXR1cm4ge1Byb21pc2U8VXNlcj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHVzZXJcbiAqIEBmdW5jdGlvbiBnZXRDQVVzZXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldENBVXNlcihcbiAgdXNlck5hbWU6IHN0cmluZyxcbiAgcHJpdmF0ZUtleTogc3RyaW5nLFxuICBjZXJ0aWZpY2F0ZTogc3RyaW5nLFxuICBtc3BJZDogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXI+IHtcbiAgbG9nLmRlYnVnKFxuICAgIGBDcmVhdGluZyBhIENBICR7bXNwSWR9IHVzZXIgJHt1c2VyTmFtZX0gd2l0aCBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlfWBcbiAgKTtcbiAgY29uc3QgdXNlciA9IG5ldyBVc2VyKHVzZXJOYW1lKTtcbiAgY29uc3QgY3J5cHRvU3VpdGUgPSBVc2VyLm5ld0NyeXB0b1N1aXRlKCk7XG4gIHVzZXIuc2V0Q3J5cHRvU3VpdGUoY3J5cHRvU3VpdGUpO1xuICBjb25zdCBpbXBvcnRlZEtleSA9IGNyeXB0b1N1aXRlLmNyZWF0ZUtleUZyb21SYXcocHJpdmF0ZUtleSk7XG4gIGF3YWl0IHVzZXIuc2V0RW5yb2xsbWVudChpbXBvcnRlZEtleSwgY2VydGlmaWNhdGUsIG1zcElkKTtcbiAgcmV0dXJuIHVzZXI7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgYW4gaWRlbnRpdHkgZnJvbSBhIGNlcnRpZmljYXRlIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgTG9hZHMgYSBjZXJ0aWZpY2F0ZSBmcm9tIGEgZGlyZWN0b3J5IGFuZCBjcmVhdGVzIGFuIElkZW50aXR5IG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IG1zcElkIC0gVGhlIE1lbWJlcnNoaXAgU2VydmljZSBQcm92aWRlciBJRFxuICogQHBhcmFtIHtzdHJpbmd9IGNlcnREaXJlY3RvcnlQYXRoIC0gUGF0aCB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGlkZW50aXR5XG4gKiBAZnVuY3Rpb24gZ2V0SWRlbnRpdHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldElkZW50aXR5KFxuICBtc3BJZDogc3RyaW5nLFxuICBjZXJ0RGlyZWN0b3J5UGF0aDogc3RyaW5nXG4pOiBQcm9taXNlPElkZW50aXR5PiB7XG4gIGNvbnN0IGlkZW50aXR5RmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIGNvbnN0IGNlcnRQYXRoID0gYXdhaXQgZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICBjb25zdCBjcmVkZW50aWFscyA9IGF3YWl0IHByb21pc2VzLnJlYWRGaWxlKGNlcnRQYXRoKTtcbiAgICByZXR1cm4gY3JlZGVudGlhbHM7XG4gIH07XG5cbiAgY29uc3QgY3JlZGVudGlhbHM6IFVpbnQ4QXJyYXkgPSAoYXdhaXQgY29udGVudE9mTG9hZEZpbGUoXG4gICAgY2VydERpcmVjdG9yeVBhdGgsXG4gICAgaWRlbnRpdHlGaWxlUmVhZGVyXG4gICkpIGFzIFVpbnQ4QXJyYXk7XG5cbiAgcmV0dXJuIHsgbXNwSWQsIGNyZWRlbnRpYWxzIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIGZ1bGwgcGF0aCBvZiB0aGUgZmlyc3QgZmlsZSBpbiBhIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgUmVhZHMgYSBkaXJlY3RvcnkgYW5kIHJldHVybnMgdGhlIHBhdGggdG8gdGhlIGZpcnN0IGZpbGUgZm91bmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBkaXJQYXRoIC0gUGF0aCB0byB0aGUgZGlyZWN0b3J5XG4gKiBAcmV0dXJuIHtQcm9taXNlPHN0cmluZz59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBmdWxsIHBhdGggb2YgdGhlIGZpcnN0IGZpbGVcbiAqIEBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuY2xpZW50XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lKGRpclBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gIGNvbnN0IHsgam9pbiB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcInBhdGhcIikpO1xuICBjb25zdCBmaWxlcyA9IGF3YWl0IHByb21pc2VzLnJlYWRkaXIoZGlyUGF0aCk7XG4gIHJldHVybiBqb2luKGRpclBhdGgsIGZpbGVzWzBdKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY29udGVudCBvZiB0aGUgZmlyc3QgZmlsZSBpbiBhIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgUmVhZHMgYSBkaXJlY3RvcnksIGZpbmRzIHRoZSBmaXJzdCBmaWxlLCBhbmQgcmV0dXJucyBpdHMgY29udGVudCBhcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IGRpclBhdGggLSBQYXRoIHRvIHRoZSBkaXJlY3RvcnlcbiAqIEByZXR1cm4ge1Byb21pc2U8c3RyaW5nPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNvbnRlbnQgb2YgdGhlIGZpcnN0IGZpbGVcbiAqIEBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lQ29udGVudFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoXG4gIGRpclBhdGg6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgeyBwcm9taXNlcyB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcImZzXCIpKTtcbiAgY29uc3QgeyBqb2luIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwicGF0aFwiKSk7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgcHJvbWlzZXMucmVhZGRpcihkaXJQYXRoKTtcbiAgcmV0dXJuIChhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShqb2luKGRpclBhdGgsIGZpbGVzWzBdKSkpLnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgYSBzaWduZXIgZnJvbSBhIGtleSBkaXJlY3RvcnlcbiAqIEBzdW1tYXJ5IExvYWRzIGEgcHJpdmF0ZSBrZXkgZnJvbSBhIGRpcmVjdG9yeSBhbmQgY3JlYXRlcyBhIFNpZ25lciBmb3IgRmFicmljIHRyYW5zYWN0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IGtleURpcmVjdG9yeVBhdGggLSBQYXRoIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgcHJpdmF0ZSBrZXlcbiAqIEByZXR1cm4ge1Byb21pc2U8U2lnbmVyPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHNpZ25lclxuICogQGZ1bmN0aW9uIGdldFNpZ25lclxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0U2lnbmVyKGtleURpcmVjdG9yeVBhdGg6IHN0cmluZyk6IFByb21pc2U8U2lnbmVyPiB7XG4gIGNvbnN0IHNpZ25lckZpbGVSZWFkZXIgPSBhc3luYyAocGF0aDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgeyBwcm9taXNlcyB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcImZzXCIpKTtcbiAgICBjb25zdCBrZXlQYXRoID0gYXdhaXQgZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICByZXR1cm4gYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUoa2V5UGF0aCk7XG4gIH07XG5cbiAgY29uc3QgcHJpdmF0ZUtleVBlbSA9IChhd2FpdCBjb250ZW50T2ZMb2FkRmlsZShcbiAgICBrZXlEaXJlY3RvcnlQYXRoLFxuICAgIHNpZ25lckZpbGVSZWFkZXJcbiAgKSkgYXMgQnVmZmVyO1xuICAvLyBOb2RlIGJhc2VkIGltcGxlbWVudGF0aW9uXG4gIC8vIHByaXZhdGVLZXkgPSBjcmVhdGVQcml2YXRlS2V5KHByaXZhdGVLZXlQZW0pO1xuICAvLyAtLVxuXG4gIC8vIHdlYiBiYXNlZCBpbXBsZW1lbnRhdGlvblxuICBjb25zdCBwcml2YXRlS2V5ID0gYXdhaXQgZXh0cmFjdFByaXZhdGVLZXkocHJpdmF0ZUtleVBlbSk7XG4gIGNvbnN0IGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHByaXZhdGVLZXkpO1xuICBjb25zdCBrID0gKHByaXZhdGVLZXkgYXMgYW55KVtrZXlzWzBdXTtcbiAgLy8gLS1cblxuICByZXR1cm4gc2lnbmVycy5uZXdQcml2YXRlS2V5U2lnbmVyKGsgYXMgYW55KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXh0cmFjdHMgYSBwcml2YXRlIGtleSBmcm9tIGEgUEVNIGJ1ZmZlclxuICogQHN1bW1hcnkgQ29udmVydHMgYSBQRU0tZW5jb2RlZCBwcml2YXRlIGtleSB0byBhIENyeXB0b0tleSBvYmplY3RcbiAqIEBwYXJhbSB7QnVmZmVyfSBwZW0gLSBUaGUgUEVNLWVuY29kZWQgcHJpdmF0ZSBrZXlcbiAqIEByZXR1cm4ge1Byb21pc2U8Q3J5cHRvS2V5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIENyeXB0b0tleVxuICogQGZ1bmN0aW9uIGV4dHJhY3RQcml2YXRlS2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuY2xpZW50XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBFeHRyYWN0UHJpdmF0ZUtleVxuICogICBwYXJ0aWNpcGFudCBTdWJ0bGVDcnlwdG9cbiAqXG4gKiAgIENhbGxlci0+PkV4dHJhY3RQcml2YXRlS2V5OiBleHRyYWN0UHJpdmF0ZUtleShwZW0pXG4gKiAgIEV4dHJhY3RQcml2YXRlS2V5LT4+RXh0cmFjdFByaXZhdGVLZXk6IEdldCBTdWJ0bGVDcnlwdG8gaW1wbGVtZW50YXRpb25cbiAqICAgRXh0cmFjdFByaXZhdGVLZXktPj5FeHRyYWN0UHJpdmF0ZUtleTogUGFyc2UgUEVNIGZvcm1hdFxuICogICBFeHRyYWN0UHJpdmF0ZUtleS0+PkV4dHJhY3RQcml2YXRlS2V5OiBDb252ZXJ0IHRvIGJpbmFyeSBERVJcbiAqICAgRXh0cmFjdFByaXZhdGVLZXktPj5TdWJ0bGVDcnlwdG86IGltcG9ydEtleShwa2NzOCwgYmluYXJ5RGVyLCBvcHRpb25zKVxuICogICBTdWJ0bGVDcnlwdG8tLT4+RXh0cmFjdFByaXZhdGVLZXk6IENyeXB0b0tleVxuICogICBFeHRyYWN0UHJpdmF0ZUtleS0tPj5DYWxsZXI6IENyeXB0b0tleVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXh0cmFjdFByaXZhdGVLZXkocGVtOiBCdWZmZXIpIHtcbiAgY29uc3QgbGliTmFtZSA9IFwiY3J5cHRvXCI7XG4gIGxldCBzdWJ0bGU7XG4gIGlmIChpc0Jyb3dzZXIoKSkge1xuICAgIHN1YnRsZSA9IChnbG9iYWxUaGlzIGFzIGFueSkuY3J5cHRvLnN1YnRsZTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBsaWIgPSAoYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChsaWJOYW1lKSkpIGFzIGFueTtcbiAgICBzdWJ0bGUgPSBsaWIuc3VidGxlIHx8IGxpYi53ZWJjcnlwdG8uc3VidGxlO1xuICB9XG5cbiAgaWYgKCFzdWJ0bGUpIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBsb2FkIFN1YnRsZUNyeXB0byBtb2R1bGVcIik7XG5cbiAgZnVuY3Rpb24gc3RyMmFiKHN0cjogc3RyaW5nKSB7XG4gICAgY29uc3QgYnVmID0gbmV3IEFycmF5QnVmZmVyKHN0ci5sZW5ndGgpO1xuICAgIGNvbnN0IGJ1ZlZpZXcgPSBuZXcgVWludDhBcnJheShidWYpO1xuICAgIGZvciAobGV0IGkgPSAwLCBzdHJMZW4gPSBzdHIubGVuZ3RoOyBpIDwgc3RyTGVuOyBpKyspIHtcbiAgICAgIGJ1ZlZpZXdbaV0gPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZjtcbiAgfVxuXG4gIGNvbnN0IHN0ciA9IHBlbVxuICAgIC50b1N0cmluZyhcInV0ZjhcIilcbiAgICAucmVwbGFjZShcIi0tLS0tQkVHSU4gUFJJVkFURSBLRVktLS0tLVwiLCBcIlwiKVxuICAgIC5yZXBsYWNlQWxsKFwiXFxuXCIsIFwiXCIpXG4gICAgLnJlcGxhY2UoXCItLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tXCIsIFwiXCIpO1xuICBjb25zdCBkZWNvZGVkID0gQnVmZmVyLmZyb20oc3RyLCBcImJhc2U2NFwiKS50b1N0cmluZyhcImJpbmFyeVwiKTtcbiAgY29uc3QgYmluYXJ5RGVyID0gc3RyMmFiKGRlY29kZWQpO1xuXG4gIHRyeSB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgc3VidGxlLmltcG9ydEtleShcbiAgICAgIFwicGtjczhcIixcbiAgICAgIGJpbmFyeURlcixcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJFQ0RTQVwiLFxuICAgICAgICBuYW1lZEN1cnZlOiBcIlAtMjU2XCIsXG4gICAgICB9LFxuICAgICAgdHJ1ZSxcbiAgICAgIFtcInNpZ25cIl1cbiAgICApO1xuXG4gICAgcmV0dXJuIGtleTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSk7XG4gIH1cbn1cbiIsImltcG9ydCBwa2NzMTEgZnJvbSBcInBrY3MxMWpzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgTWlzc2luZ1BLQ1NTMTFMaWIgfSBmcm9tIFwiLi4vc2hhcmVkL2Vycm9yc1wiO1xuaW1wb3J0IGNyeXB0byBmcm9tIFwiY3J5cHRvXCI7XG5pbXBvcnQgeyBwMjU2IH0gZnJvbSBcIkBub2JsZS9jdXJ2ZXMvbmlzdFwiO1xuXG5leHBvcnQgY2xhc3MgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbSB7XG4gIHN0YXRpYyAjcGtjczExOiBwa2NzMTEuUEtDUzExIHwgbnVsbCA9IG51bGw7XG4gIHN0YXRpYyAjaW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihsaWJyYXJ5OiBzdHJpbmcpIHtcbiAgICBpZiAoIUhTTVNpZ25lckZhY3RvcnlDdXN0b20uI3BrY3MxMSkge1xuICAgICAgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExID0gbmV3IHBrY3MxMS5QS0NTMTEoKTtcbiAgICAgIEhTTVNpZ25lckZhY3RvcnlDdXN0b20uI3BrY3MxMS5sb2FkKHRoaXMuZmluZEhTTVBLQ1MxMUxpYihsaWJyYXJ5KSk7XG4gICAgfVxuXG4gICAgaWYgKCFIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNpbml0aWFsaXplZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExLkNfSW5pdGlhbGl6ZSgpO1xuICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAvLyBpZ25vcmUgXCJhbHJlYWR5IGluaXRpYWxpemVkXCIgaWYgdGVzdHMgLyBob3QgcmVsb2FkcyBjYXVzZSByZXVzZVxuICAgICAgICBpZiAoKGUgYXMgYW55KS5jb2RlICE9PSBwa2NzMTEuQ0tSX0NSWVBUT0tJX0FMUkVBRFlfSU5JVElBTElaRUQpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNpbml0aWFsaXplZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmaW5kSFNNUEtDUzExTGliKGxpYj86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgY29tbW9uU29mdEhTTVBhdGhOYW1lcyA9IFtcbiAgICAgIFwiL3Vzci9saWIvc29mdGhzbS9saWJzb2Z0aHNtMi5zb1wiLFxuICAgICAgXCIvdXNyL2xpYi94ODZfNjQtbGludXgtZ251L3NvZnRoc20vbGlic29mdGhzbTIuc29cIixcbiAgICAgIFwiL3Vzci9sb2NhbC9saWIvc29mdGhzbS9saWJzb2Z0aHNtMi5zb1wiLFxuICAgICAgXCIvdXNyL2xpYi9saWJhY3NwLXBrY3MxMS5zb1wiLFxuICAgICAgXCIvb3B0L2hvbWVicmV3L2xpYi9zb2Z0aHNtL2xpYnNvZnRoc20yLnNvXCIsXG4gICAgXTtcblxuICAgIGlmIChsaWIpIGNvbW1vblNvZnRIU01QYXRoTmFtZXMucHVzaChsaWIpO1xuXG4gICAgZm9yIChjb25zdCBwYXRobmFtZVRvVHJ5IG9mIGNvbW1vblNvZnRIU01QYXRoTmFtZXMpIHtcbiAgICAgIGlmIChmcy5leGlzdHNTeW5jKHBhdGhuYW1lVG9UcnkpKSB7XG4gICAgICAgIHJldHVybiBwYXRobmFtZVRvVHJ5O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNaXNzaW5nUEtDU1MxMUxpYihcIlVuYWJsZSB0byBmaW5kIFBLQ1MxMSBsaWJyYXJ5XCIpO1xuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNwa2NzMTEhLkNfRmluYWxpemUoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2FuaXRpemVPcHRpb25zKGhzbVNpZ25lck9wdGlvbnM6IEhTTUNvbmZpZykge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKFxuICAgICAge1xuICAgICAgICB1c2VyVHlwZTogcGtjczExLkNLVV9VU0VSLFxuICAgICAgfSxcbiAgICAgIGhzbVNpZ25lck9wdGlvbnNcbiAgICApO1xuICAgIHRoaXMuYXNzZXJ0Tm90RW1wdHkob3B0aW9ucy5sYWJlbCwgXCJsYWJlbFwiKTtcbiAgICB0aGlzLmFzc2VydE5vdEVtcHR5KG9wdGlvbnMucGluLCBcInBpblwiKTtcbiAgICB0aGlzLmFzc2VydE5vdEVtcHR5KG9wdGlvbnMuaWRlbnRpZmllciBhcyB1bmtub3duIGFzIHN0cmluZywgXCJpZGVudGlmaWVyXCIpO1xuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnROb3RFbXB0eShwcm9wZXJ0eTogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIXByb3BlcnR5IHx8IHByb3BlcnR5LnRvU3RyaW5nKCkudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke25hbWV9IHByb3BlcnR5IG11c3QgYmUgcHJvdmlkZWRgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRTbG90Rm9yTGFiZWwocGtjczExTGFiZWw6IHN0cmluZykge1xuICAgIGNvbnN0IHNsb3RzID0gKFxuICAgICAgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTFcbiAgICApLkNfR2V0U2xvdExpc3QodHJ1ZSk7XG4gICAgaWYgKHNsb3RzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gcGtjczExIHNsb3RzIGNhbiBiZSBmb3VuZFwiKTtcbiAgICB9XG4gICAgY29uc3Qgc2xvdCA9IHNsb3RzLmZpbmQoKHNsb3RUb0NoZWNrKSA9PiB7XG4gICAgICBjb25zdCB0b2tlbkluZm8gPSAoXG4gICAgICAgIEhTTVNpZ25lckZhY3RvcnlDdXN0b20uI3BrY3MxMSBhcyBwa2NzMTEuUEtDUzExXG4gICAgICApLkNfR2V0VG9rZW5JbmZvKHNsb3RUb0NoZWNrKTtcbiAgICAgIHJldHVybiB0b2tlbkluZm8ubGFiZWwudHJpbSgpID09PSBwa2NzMTFMYWJlbDtcbiAgICB9KTtcbiAgICBpZiAoIXNsb3QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGxhYmVsICR7cGtjczExTGFiZWx9IGNhbm5vdCBiZSBmb3VuZCBpbiB0aGUgcGtjczExIHNsb3QgbGlzdGBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBzbG90O1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dpbihzZXNzaW9uOiBwa2NzMTEuSGFuZGxlLCB1c2VyVHlwZTogbnVtYmVyLCBwaW46IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAoSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTEpLkNfTG9naW4oXG4gICAgICAgIHNlc3Npb24sXG4gICAgICAgIHVzZXJUeXBlLFxuICAgICAgICBwaW5cbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICBjb25zdCBwa2NzMTFlcnIgPSBlcnIgYXMgeyBjb2RlOiBudW1iZXIgfTtcbiAgICAgIGlmIChwa2NzMTFlcnIuY29kZSAhPT0gcGtjczExLkNLUl9VU0VSX0FMUkVBRFlfTE9HR0VEX0lOKSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRPYmplY3RJbkhTTShcbiAgICBzZXNzaW9uOiBwa2NzMTEuSGFuZGxlLFxuICAgIGtleXR5cGU6IG51bWJlcixcbiAgICBpZGVudGlmaWVyOiBhbnlcbiAgKSB7XG4gICAgY29uc3QgcGtjczExVGVtcGxhdGUgPSBbXG4gICAgICB7IHR5cGU6IHBrY3MxMS5DS0FfSUQsIHZhbHVlOiBpZGVudGlmaWVyIH0sXG4gICAgICB7IHR5cGU6IHBrY3MxMS5DS0FfQ0xBU1MsIHZhbHVlOiBrZXl0eXBlIH0sXG4gICAgICB7IHR5cGU6IHBrY3MxMS5DS0FfS0VZX1RZUEUsIHZhbHVlOiBwa2NzMTEuQ0tLX0VDIH0sXG4gICAgXTtcblxuICAgIChIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNwa2NzMTEgYXMgcGtjczExLlBLQ1MxMSkuQ19GaW5kT2JqZWN0c0luaXQoXG4gICAgICBzZXNzaW9uLFxuICAgICAgcGtjczExVGVtcGxhdGVcbiAgICApO1xuICAgIGNvbnN0IGhzbU9iamVjdCA9IChcbiAgICAgIEhTTVNpZ25lckZhY3RvcnlDdXN0b20uI3BrY3MxMSBhcyBwa2NzMTEuUEtDUzExXG4gICAgKS5DX0ZpbmRPYmplY3RzKHNlc3Npb24sIDEpWzBdO1xuICAgIGlmICghaHNtT2JqZWN0KSB7XG4gICAgICAoSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTEpLkNfRmluZE9iamVjdHNGaW5hbChcbiAgICAgICAgc2Vzc2lvblxuICAgICAgKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFVuYWJsZSB0byBmaW5kIG9iamVjdCBpbiBIU00gd2l0aCBJRCAke2lkZW50aWZpZXIudG9TdHJpbmcoKX1gXG4gICAgICApO1xuICAgIH1cbiAgICAoSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTEpLkNfRmluZE9iamVjdHNGaW5hbChcbiAgICAgIHNlc3Npb25cbiAgICApO1xuICAgIHJldHVybiBoc21PYmplY3Q7XG4gIH1cblxuICBuZXdTaWduZXIoaHNtU2lnbmVyT3B0aW9uczogSFNNQ29uZmlnKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuc2FuaXRpemVPcHRpb25zKGhzbVNpZ25lck9wdGlvbnMpO1xuICAgIGNvbnN0IHBrY3MgPSBIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNwa2NzMTEgYXMgcGtjczExLlBLQ1MxMTtcbiAgICBjb25zdCBzbG90ID0gdGhpcy5maW5kU2xvdEZvckxhYmVsKG9wdGlvbnMubGFiZWwpO1xuICAgIGNvbnN0IHNlc3Npb24gPSBwa2NzLkNfT3BlblNlc3Npb24oc2xvdCwgcGtjczExLkNLRl9TRVJJQUxfU0VTU0lPTik7XG4gICAgbGV0IHByaXZhdGVLZXlIYW5kbGU7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMubG9naW4oc2Vzc2lvbiwgb3B0aW9ucy51c2VyVHlwZSwgb3B0aW9ucy5waW4pO1xuICAgICAgcHJpdmF0ZUtleUhhbmRsZSA9IHRoaXMuZmluZE9iamVjdEluSFNNKFxuICAgICAgICBzZXNzaW9uLFxuICAgICAgICBwa2NzMTEuQ0tPX1BSSVZBVEVfS0VZLFxuICAgICAgICBvcHRpb25zLmlkZW50aWZpZXJcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAoSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTEpLkNfQ2xvc2VTZXNzaW9uKHNlc3Npb24pO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgc2lnbmVyOiBhc3luYyAoZGlnZXN0OiBhbnkpID0+IHtcbiAgICAgICAgKEhTTVNpZ25lckZhY3RvcnlDdXN0b20uI3BrY3MxMSBhcyBwa2NzMTEuUEtDUzExKS5DX1NpZ25Jbml0KFxuICAgICAgICAgIHNlc3Npb24sXG4gICAgICAgICAgeyBtZWNoYW5pc206IHBrY3MxMS5DS01fRUNEU0EgfSxcbiAgICAgICAgICBwcml2YXRlS2V5SGFuZGxlXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGNvbXBhY3RTaWduYXR1cmUgPSBhd2FpdCAoXG4gICAgICAgICAgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbS4jcGtjczExIGFzIHBrY3MxMS5QS0NTMTFcbiAgICAgICAgKS5DX1NpZ25Bc3luYyhcbiAgICAgICAgICBzZXNzaW9uLFxuICAgICAgICAgIEJ1ZmZlci5mcm9tKGRpZ2VzdCksXG4gICAgICAgICAgLy8gRUMgc2lnbmF0dXJlcyBoYXZlIGxlbmd0aCBvZiAybiBhY2NvcmRpbmcgdG8gdGhlIFBLQ1MxMSBzcGVjOlxuICAgICAgICAgIC8vIGh0dHBzOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy9wa2NzMTEvcGtjczExLXNwZWMvdjMuMS9wa2NzMTEtc3BlYy12My4xLmh0bWxcbiAgICAgICAgICBCdWZmZXIuYWxsb2MocDI1Ni5Qb2ludC5Gbi5CWVRFUyAqIDIpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBwMjU2LlNpZ25hdHVyZS5mcm9tQnl0ZXMoY29tcGFjdFNpZ25hdHVyZSwgXCJjb21wYWN0XCIpXG4gICAgICAgICAgLm5vcm1hbGl6ZVMoKVxuICAgICAgICAgIC50b0J5dGVzKFwiZGVyXCIpO1xuICAgICAgfSxcbiAgICAgIGNsb3NlOiAoKSA9PiB7XG4gICAgICAgIChIU01TaWduZXJGYWN0b3J5Q3VzdG9tLiNwa2NzMTEgYXMgcGtjczExLlBLQ1MxMSkuQ19DbG9zZVNlc3Npb24oXG4gICAgICAgICAgc2Vzc2lvblxuICAgICAgICApO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnREZWZpbmVkPFQ+KHZhbHVlOiBUIHwgdW5kZWZpbmVkKTogVCB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInJlcXVpcmVkIHZhbHVlIHdhcyB1bmRlZmluZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRVbmNvbXByZXNzZWRQb2ludE9uQ3VydmUoa2V5OiBjcnlwdG8uS2V5T2JqZWN0KTogQnVmZmVyIHtcbiAgICBjb25zdCBqd2sgPSBrZXkuZXhwb3J0KHsgZm9ybWF0OiBcImp3a1wiIH0pO1xuICAgIGNvbnN0IHggPSBCdWZmZXIuZnJvbSh0aGlzLmFzc2VydERlZmluZWQoandrLngpLCBcImJhc2U2NHVybFwiKTtcbiAgICBjb25zdCB5ID0gQnVmZmVyLmZyb20odGhpcy5hc3NlcnREZWZpbmVkKGp3ay55KSwgXCJiYXNlNjR1cmxcIik7XG4gICAgY29uc3QgcHJlZml4ID0gQnVmZmVyLmZyb20oXCIwNFwiLCBcImhleFwiKTtcbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChbcHJlZml4LCB4LCB5XSk7XG4gIH1cblxuICBnZXRTS0lGcm9tQ2VydGlmaWNhdGVQYXRoKGNlcnRQYXRoOiBzdHJpbmcpIHtcbiAgICBjb25zdCBwID0gY2VydFBhdGguZW5kc1dpdGgoXCIucGVtXCIpXG4gICAgICA/IGNlcnRQYXRoXG4gICAgICA6IHBhdGguam9pbihjZXJ0UGF0aCwgXCJjZXJ0LnBlbVwiKTtcbiAgICBjb25zdCBjcmVkZW50aWFscyA9IGZzLnJlYWRGaWxlU3luYyhwKTtcblxuICAgIHJldHVybiB0aGlzLmdldFNLSUZyb21DZXJ0aWZpY2F0ZShjcmVkZW50aWFscyk7XG4gIH1cblxuICBnZXRTS0lGcm9tQ2VydGlmaWNhdGUoY2VydDogc3RyaW5nIHwgTm9uU2hhcmVkQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBjZXJ0aWZpY2F0ZSA9IG5ldyBjcnlwdG8uWDUwOUNlcnRpZmljYXRlKGNlcnQpO1xuICAgIGNvbnN0IHVuY29tcHJlc3NlZFBvaW50ID0gdGhpcy5nZXRVbmNvbXByZXNzZWRQb2ludE9uQ3VydmUoXG4gICAgICBjZXJ0aWZpY2F0ZS5wdWJsaWNLZXlcbiAgICApO1xuXG4gICAgcmV0dXJuIGNyeXB0by5jcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZSh1bmNvbXByZXNzZWRQb2ludCkuZGlnZXN0KCk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBIU01Db25maWcge1xuICBsYWJlbDogc3RyaW5nO1xuICBpZGVudGlmaWVyOiBCdWZmZXI8QXJyYXlCdWZmZXJMaWtlPjtcbiAgcGluOiBzdHJpbmc7XG59XG4iLCJpbXBvcnQge1xuICBBZGFwdGVyRmxhZ3MsXG4gIENvbmRpdGlvbixcbiAgQ29udGV4dCxcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBQZXJzaXN0ZW5jZUtleXMsXG4gIFByZXBhcmVkU3RhdGVtZW50LFxuICBQcmVwYXJlZFN0YXRlbWVudEtleXMsXG4gIFF1ZXJ5Q2xhdXNlLFxuICBSZXBvc2l0b3J5LFxuICBTdGF0ZW1lbnQsXG4gIFN0YXRlbWVudEV4ZWN1dG9yLFxuICBVbnN1cHBvcnRlZEVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50QWRhcHRlciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7IE1hbmdvUXVlcnkgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyB0b0NhbWVsQ2FzZSB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG5leHBvcnQgY2xhc3MgRmFicmljQ2xpZW50U3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBTdGF0ZW1lbnQ8XG4gIE0sXG4gIEZhYnJpY0NsaWVudEFkYXB0ZXIsXG4gIFIsXG4gIE1hbmdvUXVlcnlcbj4ge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBGYWJyaWNDbGllbnRBZGFwdGVyLCBvdmVycmlkZXM/OiBQYXJ0aWFsPEFkYXB0ZXJGbGFncz4pIHtcbiAgICBzdXBlcihhZGFwdGVyLCBvdmVycmlkZXMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHNxdWFzaChcbiAgICBjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+XG4gICk6IFByZXBhcmVkU3RhdGVtZW50PGFueT4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHNxdWFzaGVkOiBQcmVwYXJlZFN0YXRlbWVudDxNPiB8IHVuZGVmaW5lZCA9IHN1cGVyLnNxdWFzaChcbiAgICAgIGN0eCBhcyBuZXZlclxuICAgICk7XG4gICAgaWYgKCFzcXVhc2hlZCkgcmV0dXJuIHNxdWFzaGVkO1xuXG4gICAgY29uc3QgeyBtZXRob2QsIHBhcmFtcywgYXJncyB9ID0gc3F1YXNoZWQ7XG4gICAgY29uc3QgeyBkaXJlY3Rpb24sIGxpbWl0IH0gPSBwYXJhbXM7XG4gICAgc3dpdGNoIChtZXRob2QpIHtcbiAgICAgIGNhc2UgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkZJTkRfQlk6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmVwYXJlZFN0YXRlbWVudEtleXMuTElTVF9CWTpcbiAgICAgICAgYXJncy5wdXNoKGRpcmVjdGlvbik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmVwYXJlZFN0YXRlbWVudEtleXMuUEFHRV9CWTpcbiAgICAgICAgYXJncy5wdXNoKGRpcmVjdGlvbiwgbGltaXQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkZJTkRfT05FX0JZOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBVbnN1cHBvcnRlZCBtZXRob2QgJHttZXRob2R9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNxdWFzaGVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGV4ZWN1dGVQcmVwYXJlZChcbiAgICAuLi5hcmd6OiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IHJlcG8gPSBSZXBvc2l0b3J5LmZvck1vZGVsKHRoaXMuZnJvbVNlbGVjdG9yLCB0aGlzLmFkYXB0ZXIuYWxpYXMpO1xuICAgIGNvbnN0IHsgbWV0aG9kLCBhcmdzIH0gPSB0aGlzLnByZXBhcmVkIGFzIFByZXBhcmVkU3RhdGVtZW50PGFueT47XG4gICAgcmV0dXJuIHJlcG8uc3RhdGVtZW50KG1ldGhvZCwgLi4uYXJncywgLi4uYXJneik7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBwcmVwYXJlKFxuICAgIGN0eD86IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+XG4gICk6IFByb21pc2U8U3RhdGVtZW50RXhlY3V0b3I8TSwgUj4+IHtcbiAgICBjdHggPVxuICAgICAgY3R4IHx8XG4gICAgICAoYXdhaXQgdGhpcy5hZGFwdGVyLmNvbnRleHQoXG4gICAgICAgIFBlcnNpc3RlbmNlS2V5cy5RVUVSWSxcbiAgICAgICAgdGhpcy5vdmVycmlkZXMgfHwge30sXG4gICAgICAgIHRoaXMuZnJvbVNlbGVjdG9yXG4gICAgICApKTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMuaXNTaW1wbGVRdWVyeSgpICYmXG4gICAgICAoY3R4IGFzIENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+KS5nZXQoXCJmb3JjZVByZXBhcmVTaW1wbGVRdWVyaWVzXCIpXG4gICAgKSB7XG4gICAgICBjb25zdCBzcXVhc2hlZCA9IHRoaXMuc3F1YXNoKGN0eCBhcyBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPik7XG4gICAgICBpZiAoc3F1YXNoZWQpIHtcbiAgICAgICAgdGhpcy5wcmVwYXJlZCA9IHNxdWFzaGVkO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgYXJnczogKHN0cmluZyB8IG51bWJlcilbXSA9IFtdO1xuICAgIGNvbnN0IHBhcmFtczogYW55ID0ge30gYXMgYW55O1xuXG4gICAgY29uc3QgcHJlcGFyZWQ6IFByZXBhcmVkU3RhdGVtZW50PGFueT4gPSB7XG4gICAgICBjbGFzczogdGhpcy5mcm9tU2VsZWN0b3IsXG4gICAgICBhcmdzLFxuICAgICAgcGFyYW1zLFxuICAgIH0gYXMgYW55O1xuXG4gICAgY29uc3QgbWV0aG9kOiBzdHJpbmdbXSA9IFtRdWVyeUNsYXVzZS5GSU5EX0JZXTtcblxuICAgIGlmICh0aGlzLndoZXJlQ29uZGl0aW9uKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLnByZXBhcmVDb25kaXRpb24odGhpcy53aGVyZUNvbmRpdGlvbiwgY3R4IGFzIG5ldmVyKTtcbiAgICAgIG1ldGhvZC5wdXNoKHBhcnNlZC5tZXRob2QpO1xuICAgICAgaWYgKHBhcnNlZC5hcmdzICYmIHBhcnNlZC5hcmdzLmxlbmd0aClcbiAgICAgICAgYXJncy5wdXNoKC4uLihwYXJzZWQuYXJncyBhcyAoc3RyaW5nIHwgbnVtYmVyKVtdKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnNlbGVjdFNlbGVjdG9yKVxuICAgICAgbWV0aG9kLnB1c2goXG4gICAgICAgIFF1ZXJ5Q2xhdXNlLlNFTEVDVCxcbiAgICAgICAgdGhpcy5zZWxlY3RTZWxlY3Rvci5qb2luKGAgJHtRdWVyeUNsYXVzZS5BTkQudG9Mb3dlckNhc2UoKX0gYClcbiAgICAgICk7XG4gICAgaWYgKHRoaXMub3JkZXJCeVNlbGVjdG9yKSB7XG4gICAgICBtZXRob2QucHVzaChRdWVyeUNsYXVzZS5PUkRFUl9CWSwgdGhpcy5vcmRlckJ5U2VsZWN0b3JbMF0gYXMgc3RyaW5nKTtcbiAgICAgIGFyZ3MucHVzaCh0aGlzLm9yZGVyQnlTZWxlY3RvclsxXSk7XG4gICAgfVxuICAgIC8vIGlmICh0aGlzLmdyb3VwQnlTZWxlY3RvcilcbiAgICAvLyAgIG1ldGhvZC5wdXNoKFF1ZXJ5Q2xhdXNlLkdST1VQX0JZLCB0aGlzLmdyb3VwQnlTZWxlY3RvciBhcyBzdHJpbmcpO1xuICAgIC8vIGlmICh0aGlzLmxpbWl0U2VsZWN0b3IpIHBhcmFtcy5saW1pdCA9IHRoaXMubGltaXRTZWxlY3RvcjtcbiAgICAvLyBpZiAodGhpcy5vZmZzZXRTZWxlY3Rvcikge1xuICAgIC8vICAgcGFyYW1zLnNraXAgPSB0aGlzLm9mZnNldFNlbGVjdG9yO1xuICAgIC8vIH1cbiAgICBwcmVwYXJlZC5tZXRob2QgPSB0b0NhbWVsQ2FzZShtZXRob2Quam9pbihcIiBcIikpO1xuICAgIHByZXBhcmVkLnBhcmFtcyA9IHBhcmFtcztcbiAgICB0aGlzLnByZXBhcmVkID0gcHJlcGFyZWQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYnVpbGQoKTogTWFuZ29RdWVyeSB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICBgVGhpcyBtZXRob2QgaXMgb25seSBjYWxsZWQgaXMgcHJlcGFyZWQgc3RhdGVtZW50cyBhcmUgbm90IHVzZWQuIElmIHNvLCBhIGRlZGljYXRlZCBpbXBsZW1lbnRhdGlvbiBmb3IgdGhlIG5hdGl2ZSBxdWVyaWVzIHVzZWQgaXMgcmVxdWlyZWRgXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBwYXJzZUNvbmRpdGlvbihcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgY29uZGl0aW9uOiBDb25kaXRpb248TT4sXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IE1hbmdvUXVlcnkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgYFRoaXMgbWV0aG9kIGlzIG9ubHkgY2FsbGVkIGlzIHByZXBhcmVkIHN0YXRlbWVudHMgYXJlIG5vdCB1c2VkLiBJcyBzbywgYSBkZWRpY2F0ZWQgaW1wbGVtZW50YXRpb24gZm9yIHRoZSBuYXRpdmUgcXVlcmllcyB1c2VkIGlzIHJlcXVpcmVkYFxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgUGFnaW5hdG9yLFxuICBQcmVwYXJlZFN0YXRlbWVudCxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRBZGFwdGVyIH0gZnJvbSBcIi4vRmFicmljQ2xpZW50QWRhcHRlclwiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcblxuZXhwb3J0IGNsYXNzIEZhYnJpY0NsaWVudFBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgUGFnaW5hdG9yPFxuICBNLFxuICBNW10sXG4gIE1hbmdvUXVlcnlcbj4ge1xuICBib29rbWFyaz86IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyOiBGYWJyaWNDbGllbnRBZGFwdGVyLFxuICAgIHF1ZXJ5OiBNYW5nb1F1ZXJ5IHwgUHJlcGFyZWRTdGF0ZW1lbnQ8YW55PixcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHByb3RlY3RlZCBwcmVwYXJlKHJhd1N0YXRlbWVudDogTWFuZ29RdWVyeSk6IE1hbmdvUXVlcnkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgYFJhdyBxdWVyeSBhY2Nlc3MgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBhIHN1YmNsYXNzLiBvbmx5IHByZXBhcmVkIHN0YXRlbWVudHMgYXJlIG5hdGl2ZWx5IGF2YWlsYWJsZWBcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgcGFnZShcbiAgICBwYWdlOiBudW1iZXIgPSAxLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIHN1cGVyLnBhZ2UocGFnZSwgLi4uYXJncyk7IC8vIHRoaXMgd2lsbCBmYWlsIGZvciBub24tcHJlcGFyZWQgc3RhdGVtZW50c1xuICB9XG59XG4iLCJpbXBvcnQgXCIuLi9zaGFyZWQvb3ZlcnJpZGVzXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cywgdHlwZSBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgQ2xpZW50IH0gZnJvbSBcIkBncnBjL2dycGMtanNcIjtcbmltcG9ydCAqIGFzIGdycGMgZnJvbSBcIkBncnBjL2dycGMtanNcIjtcbmltcG9ydCB7XG4gIE1vZGVsLFxuICB0eXBlIE1vZGVsQ29uc3RydWN0b3IsXG4gIHR5cGUgU2VyaWFsaXplcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgZGVidWcsIGZpbmFsLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyB0eXBlIFBlZXJDb25maWcsIHR5cGUgU2VncmVnYXRlZE1vZGVsIH0gZnJvbSBcIi4uL3NoYXJlZC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgY29ubmVjdCxcbiAgdHlwZSBDb25uZWN0T3B0aW9ucyxcbiAgR2F0ZXdheSxcbiAgTmV0d29yayxcbiAgUHJvcG9zYWxPcHRpb25zLFxuICBDb250cmFjdCBhcyBDb250cmFrdCxcbiAgdHlwZSBTaWduZXIsXG59IGZyb20gXCJAaHlwZXJsZWRnZXIvZmFicmljLWdhdGV3YXlcIjtcbmltcG9ydCB7IGdldElkZW50aXR5LCBnZXRTaWduZXIgfSBmcm9tIFwiLi9mYWJyaWMtZnNcIjtcbmltcG9ydCB7XG4gIEJhc2VFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIENvbmZsaWN0RXJyb3IsXG4gIEJhZFJlcXVlc3RFcnJvcixcbiAgdHlwZSBQcmltYXJ5S2V5VHlwZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDb250ZXh0LFxuICBBZGFwdGVyLFxuICB0eXBlIEFkYXB0ZXJGbGFncyxcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIEZvcmJpZGRlbkVycm9yLFxuICBNaWdyYXRpb25FcnJvcixcbiAgT2JzZXJ2ZXJFcnJvcixcbiAgUGFnaW5nRXJyb3IsXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUXVlcnlFcnJvcixcbiAgUmVwb3NpdG9yeSxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgU3RhdGVtZW50LFxuICB0eXBlIFByZXBhcmVkU3RhdGVtZW50LFxuICBQYWdpbmF0b3IsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIHR5cGUgUHJlcGFyZWRNb2RlbCxcbiAgQWxsT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IENsaWVudFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vc2hhcmVkL0NsaWVudFNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudERpc3BhdGNoIH0gZnJvbSBcIi4vRmFicmljQ2xpZW50RGlzcGF0Y2hcIjtcbmltcG9ydCB7IEhTTVNpZ25lckZhY3RvcnlDdXN0b20gfSBmcm9tIFwiLi9mYWJyaWMtaHNtXCI7XG5pbXBvcnQgeyB0eXBlIENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRTdGF0ZW1lbnQgfSBmcm9tIFwiLi9GYWJyaWNDbGllbnRTdGF0ZW1lbnRcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudFBhZ2luYXRvciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudFBhZ2luYXRvclwiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50UmVwb3NpdG9yeSB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudFJlcG9zaXRvcnlcIjtcbmltcG9ydCB7XG4gIEVuZG9yc2VtZW50RXJyb3IsXG4gIEVuZG9yc2VtZW50UG9saWN5RXJyb3IsXG4gIE12Y2NSZWFkQ29uZmxpY3RFcnJvcixcbiAgUGhhbnRvbVJlYWRDb25mbGljdEVycm9yLFxufSBmcm9tIFwiLi4vc2hhcmVkL2Vycm9yc1wiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVmYXVsdEZhYnJpY0NsaWVudEZsYWdzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggSHlwZXJsZWRnZXIgRmFicmljIG5ldHdvcmtzXG4gKiBAc3VtbWFyeSBUaGUgRmFicmljQWRhcHRlciBleHRlbmRzIENvdWNoREJBZGFwdGVyIHRvIHByb3ZpZGUgYSBzZWFtbGVzcyBpbnRlcmZhY2UgZm9yIGludGVyYWN0aW5nIHdpdGggSHlwZXJsZWRnZXIgRmFicmljIG5ldHdvcmtzLlxuICogSXQgaGFuZGxlcyBjb25uZWN0aW9uIG1hbmFnZW1lbnQsIHRyYW5zYWN0aW9uIHN1Ym1pc3Npb24sIGFuZCBDUlVEIG9wZXJhdGlvbnMgYWdhaW5zdCBGYWJyaWMgY2hhaW5jb2RlLlxuICogQHRlbXBsYXRlIFBlZXJDb25maWcgLSBDb25maWd1cmF0aW9uIHR5cGUgZm9yIGNvbm5lY3RpbmcgdG8gYSBGYWJyaWMgcGVlclxuICogQHRlbXBsYXRlIEZhYnJpY0ZsYWdzIC0gRmxhZ3Mgc3BlY2lmaWMgdG8gRmFicmljIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBDb250ZXh0PEZhYnJpY0ZsYWdzPiAtIENvbnRleHQgdHlwZSBjb250YWluaW5nIEZhYnJpYy1zcGVjaWZpYyBmbGFnc1xuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gZm9yIGNvbm5lY3RpbmcgdG8gYSBGYWJyaWMgcGVlclxuICogQHBhcmFtIGFsaWFzIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyIGluc3RhbmNlXG4gKiBAY2xhc3MgRmFicmljQ2xpZW50QWRhcHRlclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0ZSBhIG5ldyBGYWJyaWNBZGFwdGVyIGluc3RhbmNlXG4gKiBjb25zdCBjb25maWc6IFBlZXJDb25maWcgPSB7XG4gKiAgIG1zcElkOiAnT3JnMU1TUCcsXG4gKiAgIHBlZXJFbmRwb2ludDogJ2xvY2FsaG9zdDo3MDUxJyxcbiAqICAgY2hhbm5lbE5hbWU6ICdteWNoYW5uZWwnLFxuICogICBjaGFpbmNvZGVOYW1lOiAnbXljYycsXG4gKiAgIGNvbnRyYWN0TmFtZTogJ215Y29udHJhY3QnLFxuICogICB0bHNDZXJ0UGF0aDogJy9wYXRoL3RvL3Rscy9jZXJ0JyxcbiAqICAgY2VydERpcmVjdG9yeVBhdGg6ICcvcGF0aC90by9jZXJ0L2RpcicsXG4gKiAgIGtleURpcmVjdG9yeVBhdGg6ICcvcGF0aC90by9rZXkvZGlyJ1xuICogfTtcbiAqXG4gKiBjb25zdCBhZGFwdGVyID0gbmV3IEZhYnJpY0FkYXB0ZXIoY29uZmlnLCAnb3JnMS1hZGFwdGVyJyk7XG4gKlxuICogLy8gVXNlIHRoZSBhZGFwdGVyIHRvIGludGVyYWN0IHdpdGggdGhlIEZhYnJpYyBuZXR3b3JrXG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBhZGFwdGVyLnJlYWQoJ3VzZXJzJywgJ3VzZXIxJywgbXlTZXJpYWxpemVyKTtcbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRmFicmljQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBHYXRld2F5XG4gKiAgIHBhcnRpY2lwYW50IE5ldHdvcmtcbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgQ2hhaW5jb2RlXG4gKlxuICogICBDbGllbnQtPj5GYWJyaWNBZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgbW9kZWwsIHRyYW5zaWVudCwgc2VyaWFsaXplcilcbiAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IHN1Ym1pdFRyYW5zYWN0aW9uKE9wZXJhdGlvbktleXMuQ1JFQVRFLCBbc2VyaWFsaXplZE1vZGVsXSwgdHJhbnNpZW50KVxuICogICBGYWJyaWNBZGFwdGVyLT4+R2F0ZXdheTogY29ubmVjdCgpXG4gKiAgIEdhdGV3YXktPj5OZXR3b3JrOiBnZXROZXR3b3JrKGNoYW5uZWxOYW1lKVxuICogICBOZXR3b3JrLT4+Q29udHJhY3Q6IGdldENvbnRyYWN0KGNoYWluY29kZU5hbWUsIGNvbnRyYWN0TmFtZSlcbiAqICAgRmFicmljQWRhcHRlci0+PkNvbnRyYWN0OiBzdWJtaXQoYXBpLCBwcm9wb3NhbE9wdGlvbnMpXG4gKiAgIENvbnRyYWN0LT4+Q2hhaW5jb2RlOiBpbnZva2VcbiAqICAgQ2hhaW5jb2RlLS0+PkNvbnRyYWN0OiByZXNwb25zZVxuICogICBDb250cmFjdC0tPj5GYWJyaWNBZGFwdGVyOiByZXN1bHRcbiAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IGRlY29kZShyZXN1bHQpXG4gKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBzZXJpYWxpemVyLmRlc2VyaWFsaXplKGRlY29kZWRSZXN1bHQpXG4gKiAgIEZhYnJpY0FkYXB0ZXItLT4+Q2xpZW50OiBkZXNlcmlhbGl6ZWRSZXN1bHRcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NsaWVudEFkYXB0ZXIgZXh0ZW5kcyBBZGFwdGVyPFxuICBQZWVyQ29uZmlnLFxuICBDbGllbnQsXG4gIE1hbmdvUXVlcnksXG4gIENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+XG4+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGF0aWMgdGV4dCBkZWNvZGVyIGZvciBjb252ZXJ0aW5nIFVpbnQ4QXJyYXkgdG8gc3RyaW5nXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBkZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKFwidXRmOFwiKTtcblxuICBwcml2YXRlIHN0YXRpYyBzZXJpYWxpemVyID0gbmV3IENsaWVudFNlcmlhbGl6ZXIoKTtcblxuICBwcm90ZWN0ZWQgc3RhdGljIGxvZyA9IExvZ2dpbmcuZm9yKEZhYnJpY0NsaWVudEFkYXB0ZXIpO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBzZXJpYWxpemVyOiBTZXJpYWxpemVyPGFueT4gPVxuICAgIEZhYnJpY0NsaWVudEFkYXB0ZXIuc2VyaWFsaXplcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQWRhcHRlciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIG5ldyBhZGFwdGVyIGZvciBpbnRlcmFjdGluZyB3aXRoIGEgSHlwZXJsZWRnZXIgRmFicmljIG5ldHdvcmtcbiAgICogQHBhcmFtIHtQZWVyQ29uZmlnfSBjb25maWcgLSBDb25maWd1cmF0aW9uIGZvciBjb25uZWN0aW5nIHRvIGEgRmFicmljIHBlZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IFthbGlhc10gLSBPcHRpb25hbCBhbGlhcyBmb3IgdGhlIGFkYXB0ZXIgaW5zdGFuY2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogUGVlckNvbmZpZywgYWxpYXM/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihjb25maWcsIEZhYnJpY0ZsYXZvdXIsIGFsaWFzKTtcbiAgfVxuXG4gIG92ZXJyaWRlIFN0YXRlbWVudDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8QWRhcHRlckZsYWdzPlxuICApOiBTdGF0ZW1lbnQ8TSwgRmFicmljQ2xpZW50QWRhcHRlciwgYW55LCBNYW5nb1F1ZXJ5PiB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDbGllbnRTdGF0ZW1lbnQodGhpcywgb3ZlcnJpZGVzKTtcbiAgfVxuXG4gIFBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHF1ZXJ5OiBQcmVwYXJlZFN0YXRlbWVudDxhbnk+IHwgTWFuZ29RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICk6IFBhZ2luYXRvcjxNLCBhbnksIE1hbmdvUXVlcnk+IHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NsaWVudFBhZ2luYXRvcih0aGlzLCBxdWVyeSwgc2l6ZSwgY2xhenopO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGZsYWdzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzIHwgc3RyaW5nLFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiB8IENvbnN0cnVjdG9yPE0+W10gfCB1bmRlZmluZWQsXG4gICAgZmxhZ3M6IFBhcnRpYWw8RmFicmljQ2xpZW50RmxhZ3M+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8RmFicmljQ2xpZW50RmxhZ3M+IHtcbiAgICByZXR1cm4gc3VwZXIuZmxhZ3Mob3BlcmF0aW9uLCBtb2RlbCwgZmxhZ3MsIC4uLmFyZ3MpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgY29udGV4dDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogKCguLi5hcmdzOiBhbnlbXSkgPT4gYW55KSB8IEFsbE9wZXJhdGlvbktleXMsXG4gICAgb3ZlcnJpZGVzOiBQYXJ0aWFsPEZhYnJpY0NsaWVudEZsYWdzPixcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4gfCBDb25zdHJ1Y3RvcjxNPltdLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0PGFueT4+XG4gICk6IFByb21pc2U8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5jb250ZXh0KTtcbiAgICBsb2cuc2lsbHkoXG4gICAgICBgY3JlYXRpbmcgbmV3IGNvbnRleHQgZm9yICR7b3BlcmF0aW9ufSBvcGVyYXRpb24gb24gJHttb2RlbCA/IChBcnJheS5pc0FycmF5KG1vZGVsKSA/IG1vZGVsLm1hcCgobSkgPT4gTW9kZWwudGFibGVOYW1lKG0pKSA6IE1vZGVsLnRhYmxlTmFtZShtb2RlbCkpIDogXCJub1wifSB0YWJsZSAke292ZXJyaWRlcyAmJiBPYmplY3Qua2V5cyhvdmVycmlkZXMpID8gT2JqZWN0LmtleXMob3ZlcnJpZGVzKS5sZW5ndGggOiBcIm5vXCJ9IHdpdGggZmxhZyBvdmVycmlkZXNgXG4gICAgKTtcbiAgICBsZXQgY3R4ID0gYXJncy5wb3AoKTtcbiAgICBpZiAodHlwZW9mIGN0eCAhPT0gXCJ1bmRlZmluZWRcIiAmJiAhKGN0eCBpbnN0YW5jZW9mIENvbnRleHQpKSB7XG4gICAgICBhcmdzLnB1c2goY3R4KTtcbiAgICAgIGN0eCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBvdmVycmlkZXMgPSBjdHhcbiAgICAgID8gT2JqZWN0LmFzc2lnbih7fSwgb3ZlcnJpZGVzLCBjdHgudG9PdmVycmlkZXMoKSlcbiAgICAgIDogb3ZlcnJpZGVzO1xuICAgIGNvbnN0IGZsYWdzID0gYXdhaXQgdGhpcy5mbGFncyhcbiAgICAgIHR5cGVvZiBvcGVyYXRpb24gPT09IFwic3RyaW5nXCIgPyBvcGVyYXRpb24gOiBvcGVyYXRpb24ubmFtZSxcbiAgICAgIG1vZGVsLFxuICAgICAgb3ZlcnJpZGVzIGFzIFBhcnRpYWw8RmFicmljQ2xpZW50RmxhZ3M+LFxuICAgICAgLi4uYXJncyxcbiAgICAgIGN0eFxuICAgICk7XG5cbiAgICBpZiAoY3R4KSB7XG4gICAgICBpZiAoIShjdHggaW5zdGFuY2VvZiB0aGlzLkNvbnRleHQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgdGhpcy5Db250ZXh0KCkuYWNjdW11bGF0ZSh7XG4gICAgICAgICAgLi4uY3R4W1wiY2FjaGVcIl0sXG4gICAgICAgICAgLi4uZmxhZ3MsXG4gICAgICAgICAgcGFyZW50Q29udGV4dDogY3R4LFxuICAgICAgICB9KSBhcyBhbnk7XG4gICAgICB9XG4gICAgICBjb25zdCBjdXJyZW50T3AgPSBjdHguZ2V0KFwib3BlcmF0aW9uXCIpO1xuICAgICAgY29uc3QgY3VycmVudE1vZGVsID0gY3R4LmdldChcImFmZmVjdGVkVGFibGVzXCIpO1xuICAgICAgaWYgKGN1cnJlbnRPcCAhPT0gb3BlcmF0aW9uIHx8IG1vZGVsICE9PSBjdXJyZW50TW9kZWwpXG4gICAgICAgIHJldHVybiBuZXcgdGhpcy5Db250ZXh0KCkuYWNjdW11bGF0ZSh7XG4gICAgICAgICAgLi4uY3R4W1wiY2FjaGVcIl0sXG4gICAgICAgICAgLi4uZmxhZ3MsXG4gICAgICAgICAgcGFyZW50Q29udGV4dDogY3R4LFxuICAgICAgICB9KSBhcyBhbnk7XG4gICAgICByZXR1cm4gY3R4LmFjY3VtdWxhdGUoZmxhZ3MpIGFzIGFueTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IHRoaXMuQ29udGV4dCgpLmFjY3VtdWxhdGUoe1xuICAgICAgLi4uRGVmYXVsdEZhYnJpY0NsaWVudEZsYWdzLFxuICAgICAgLi4uZmxhZ3MsXG4gICAgfSkgYXMgYW55O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNvZGVzIGEgVWludDhBcnJheSB0byBhIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBiaW5hcnkgZGF0YSByZWNlaXZlZCBmcm9tIEZhYnJpYyB0byBhIHN0cmluZyB1c2luZyBVVEYtOCBlbmNvZGluZ1xuICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGEgLSBUaGUgYmluYXJ5IGRhdGEgdG8gZGVjb2RlXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGRlY29kZWQgc3RyaW5nXG4gICAqL1xuICBkZWNvZGUoZGF0YTogVWludDhBcnJheSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIEZhYnJpY0NsaWVudEFkYXB0ZXIuZGVjb2Rlci5kZWNvZGUoZGF0YSk7XG4gIH1cblxuICBvdmVycmlkZSByZXBvc2l0b3J5PFxuICAgIFIgZXh0ZW5kcyBSZXBvc2l0b3J5PFxuICAgICAgYW55LFxuICAgICAgQWRhcHRlcjxQZWVyQ29uZmlnLCBDbGllbnQsIE1hbmdvUXVlcnksIENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICAgID4sXG4gID4oKTogQ29uc3RydWN0b3I8Uj4ge1xuICAgIHJldHVybiBGYWJyaWNDbGllbnRSZXBvc2l0b3J5IGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8Uj47XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFtDb25zdHJ1Y3RvcjxNPiwgUHJpbWFyeUtleVR5cGUsIFJlY29yZDxzdHJpbmcsIGFueT4sIC4uLmFueVtdLCBDb250ZXh0XSB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZVByZWZpeCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbCk7XG4gICAgcmV0dXJuIFtjbGF6eiwgaWQsIHJlY29yZCwgLi4uY3R4QXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIG11bHRpcGxlIHJlY29yZHMgZm9yIGNyZWF0aW9uXG4gICAqIEBzdW1tYXJ5IEFkZHMgbmVjZXNzYXJ5IENvdWNoREIgZmllbGRzIHRvIG11bHRpcGxlIHJlY29yZHMgYmVmb3JlIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAgICogQHBhcmFtIHtzdHJpbmdbXXxudW1iZXJbXX0gaWRzIC0gVGhlIElEcyBvZiB0aGUgcmVjb3Jkc1xuICAgKiBAcGFyYW0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byBwcmVwYXJlXG4gICAqIEByZXR1cm4gQSB0dXBsZSBjb250YWluaW5nIHRoZSB0YWJsZU5hbWUsIGlkcywgYW5kIHByZXBhcmVkIHJlY29yZHNcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgaWRzIGFuZCBtb2RlbHMgYXJyYXlzIGhhdmUgZGlmZmVyZW50IGxlbmd0aHNcbiAgICovXG4gIHByb3RlY3RlZCBjcmVhdGVBbGxQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWRzOiBzdHJpbmdbXSB8IG51bWJlcltdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKSB7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMuY3JlYXRlQWxsUHJlZml4KTtcbiAgICBjb25zdCByZWNvcmRzID0gaWRzLm1hcCgoaWQsIGNvdW50KSA9PiB7XG4gICAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWxzW2NvdW50XSk7XG4gICAgICByZXR1cm4gcmVjb3JkO1xuICAgIH0pO1xuICAgIHJldHVybiBbY2xhenosIGlkcywgcmVjb3JkcywgLi4uY3R4QXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlQWxsUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICkge1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZUFsbFByZWZpeCk7XG4gICAgY29uc3QgcmVjb3JkcyA9IGlkcy5tYXAoKCkgPT4ge1xuICAgICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW2NsYXp6LCBpZHMsIHJlY29yZHMsIC4uLmN0eEFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG11bHRpcGxlIHJlY29yZHMgaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb25cbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIGNyZWF0ZSBtdWx0aXBsZSByZWNvcmRzIGluIHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGlkcyAtIEFycmF5IG9mIHJlY29yZCBpZGVudGlmaWVyc1xuICAgKiBAcGFyYW0ge0FycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+fSBtb2RlbHMgLSBBcnJheSBvZiByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHJlY29yZHNcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG4gICAgLy9IRVJFIVxuICAgIGNvbnN0IGN0eEFyZ3MgPSBbLi4uKGFyZ3MgYXMgdW5rbm93biBhcyBhbnlbXSldO1xuICAgIGNvbnN0IHRyYW5zaWVudCA9IGN0eEFyZ3Muc2hpZnQoKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IHRoaXMubG9nQ3R4KFxuICAgICAgY3R4QXJncyBhcyBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj4sXG4gICAgICB0aGlzLmNyZWF0ZUFsbFxuICAgICk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcblxuICAgIGxvZy5pbmZvKGBhZGRpbmcgJHtpZHMubGVuZ3RofSBlbnRyaWVzIHRvICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgIGxvZy52ZXJib3NlKGBwa3M6ICR7aWRzfWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc3VibWl0VHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTCxcbiAgICAgIFtcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgbW9kZWxzLm1hcCgobSkgPT4gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShtLCBjbGF6ei5uYW1lKSlcbiAgICAgICAgKSxcbiAgICAgIF0sXG4gICAgICB0cmFuc2llbnQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5kZWNvZGUocmVzdWx0KSkubWFwKChyOiBhbnkpID0+IEpTT04ucGFyc2UocikpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBtdWx0aXBsZSByZWNvcmRzIGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uXG4gICAqIEBzdW1tYXJ5IFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byByZWFkIG11bHRpcGxlIHJlY29yZHMgZnJvbSB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBpZHMgLSBBcnJheSBvZiByZWNvcmQgaWRlbnRpZmllcnMgdG8gcmVhZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCByZWNvcmRzXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyByZWFkQWxsPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJlYWRBbGwpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbG9nLmluZm8oYHJlYWRpbmcgJHtpZHMubGVuZ3RofSBlbnRyaWVzIHRvICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgIGxvZy52ZXJib3NlKGBwa3M6ICR7aWRzfWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXZhbHVhdGVUcmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5SRUFEX0FMTCxcbiAgICAgIFtKU09OLnN0cmluZ2lmeShpZHMpXSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLmRlY29kZShyZXN1bHQpKS5tYXAoKHI6IGFueSkgPT4gSlNPTi5wYXJzZShyKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgbXVsdGlwbGUgcmVjb3JkcyBpbiBhIHNpbmdsZSB0cmFuc2FjdGlvblxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gdXBkYXRlIG11bHRpcGxlIHJlY29yZHMgaW4gdGhlIEZhYnJpYyBsZWRnZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0gaWRzIC0gQXJyYXkgb2YgcmVjb3JkIGlkZW50aWZpZXJzXG4gICAqIEBwYXJhbSB7QXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj59IG1vZGVscyAtIEFycmF5IG9mIHVwZGF0ZWQgcmVjb3JkIGRhdGFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0cmFuc2llbnQgLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8QXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCByZWNvcmRzXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGw8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWRzOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT5bXT4ge1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIGNvbnN0IGN0eEFyZ3MgPSBbLi4uKGFyZ3MgYXMgdW5rbm93biBhcyBhbnlbXSldO1xuICAgIGNvbnN0IHRyYW5zaWVudCA9IGN0eEFyZ3Muc2hpZnQoKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IHRoaXMubG9nQ3R4KFxuICAgICAgY3R4QXJncyBhcyBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj4sXG4gICAgICB0aGlzLnVwZGF0ZUFsbFxuICAgICk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBsb2cuaW5mbyhgdXBkYXRpbmcgJHtpZHMubGVuZ3RofSBlbnRyaWVzIHRvICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgIGxvZy52ZXJib3NlKGBwa3M6ICR7aWRzfWApO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5zdWJtaXRUcmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMLFxuICAgICAgW1xuICAgICAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICBtb2RlbHMubWFwKChtKSA9PiB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG0sIGNsYXp6Lm5hbWUpKVxuICAgICAgICApLFxuICAgICAgXSxcbiAgICAgIHRyYW5zaWVudCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLmRlY29kZShyZXN1bHQpKS5tYXAoKHI6IGFueSkgPT4gSlNPTi5wYXJzZShyKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgcmVjb3JkcyBpbiBhIHNpbmdsZSB0cmFuc2FjdGlvblxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gZGVsZXRlIG11bHRpcGxlIHJlY29yZHMgZnJvbSB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+fSBpZHMgLSBBcnJheSBvZiByZWNvcmQgaWRlbnRpZmllcnMgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7U2VyaWFsaXplcjxhbnk+fSBzZXJpYWxpemVyIC0gU2VyaWFsaXplciBmb3IgdGhlIG1vZGVsIGRhdGFcbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIHJlY29yZHNcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5kZWxldGVBbGwpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbG9nLmluZm8oYGRlbGV0aW5nICR7aWRzLmxlbmd0aH0gZW50cmllcyB0byAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cudmVyYm9zZShgcGtzOiAke2lkc31gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEwsXG4gICAgICBbSlNPTi5zdHJpbmdpZnkoaWRzKV0sXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5kZWNvZGUocmVzdWx0KSkubWFwKChyOiBhbnkpID0+IEpTT04ucGFyc2UocikpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIG1vZGVsIGZvciBwZXJzaXN0ZW5jZVxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIG1vZGVsIGluc3RhbmNlIGludG8gYSBmb3JtYXQgc3VpdGFibGUgZm9yIGRhdGFiYXNlIHN0b3JhZ2UsXG4gICAqIGhhbmRsaW5nIGNvbHVtbiBtYXBwaW5nIGFuZCBzZXBhcmF0aW5nIHRyYW5zaWVudCBwcm9wZXJ0aWVzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcmVwYXJlXG4gICAqIEBwYXJhbSBwayAtIFRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0eSBuYW1lXG4gICAqIEByZXR1cm4gVGhlIHByZXBhcmVkIGRhdGFcbiAgICovXG4gIG92ZXJyaWRlIHByZXBhcmU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogU2VncmVnYXRlZE1vZGVsPE0+ICYgUHJlcGFyZWRNb2RlbCB7XG4gICAgY29uc3QgeyBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucHJlcGFyZSk7XG4gICAgY29uc3Qgc3BsaXQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuICAgIGlmICgobW9kZWwgYXMgYW55KVtQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEFdKSB7XG4gICAgICBsb2cuc2lsbHkoXG4gICAgICAgIGBQYXNzaW5nIGFsb25nIHBlcnNpc3RlbmNlIG1ldGFkYXRhIGZvciAkeyhtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV19YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzcGxpdC5tb2RlbCwgUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBLCB7XG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IChtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVjb3JkOiBzcGxpdC5tb2RlbCxcbiAgICAgIG1vZGVsOiBzcGxpdC5tb2RlbCxcbiAgICAgIGlkOiBtb2RlbFtNb2RlbC5wayhtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPildIGFzIHN0cmluZyxcbiAgICAgIHRyYW5zaWVudDogc3BsaXQudHJhbnNpZW50LFxuICAgICAgcHJpdmF0ZTogc3BsaXQucHJpdmF0ZSxcbiAgICAgIHNoYXJlZDogc3BsaXQuc2hhcmVkLFxuICAgIH07XG4gIH1cblxuICBvdmVycmlkZSByZXZlcnQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBNIHtcbiAgICBjb25zdCB7IGxvZyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZXZlcnQpO1xuICAgIGlmICh0cmFuc2llbnQpIHtcbiAgICAgIGxvZy52ZXJib3NlKFxuICAgICAgICBgcmUtYWRkaW5nIHRyYW5zaWVudCBwcm9wZXJ0aWVzOiAke09iamVjdC5rZXlzKHRyYW5zaWVudCkuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBPYmplY3QuZW50cmllcyh0cmFuc2llbnQgYXMgUmVjb3JkPHN0cmluZywgYW55PikuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAoa2V5IGluIG9iailcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBUcmFuc2llbnQgcHJvcGVydHkgJHtrZXl9IGFscmVhZHkgZXhpc3RzIG9uIG1vZGVsICR7dHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gY2xhenogOiBjbGF6ei5uYW1lfS4gc2hvdWxkIGJlIGltcG9zc2libGVgXG4gICAgICAgICAgKTtcbiAgICAgICAgKG9iaiBhcyBNKVtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IChjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPikob2JqKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHNpbmdsZSByZWNvcmRcbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIGNyZWF0ZSBhIHJlY29yZCBpbiB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgcmVjb3JkIGRhdGFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0cmFuc2llbnQgLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHJlY29yZFxuICAgKi9cbiAgQGRlYnVnKClcbiAgQGZpbmFsKClcbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICB0cmFuc2llbnQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgY3R4QXJncyA9IFsuLi4oYXJncyBhcyB1bmtub3duIGFzIGFueVtdKV07XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoXG4gICAgICBjdHhBcmdzIGFzIENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PixcbiAgICAgIHRoaXMuY3JlYXRlXG4gICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGxvZy52ZXJib3NlKGBhZGRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLmRlYnVnKGBwazogJHtpZH1gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBbdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCwgY2xhenoubmFtZSldLFxuICAgICAgdHJhbnNpZW50LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY2xhenoubmFtZVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZSh0aGlzLmRlY29kZShyZXN1bHQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgYSBzaW5nbGUgcmVjb3JkXG4gICAqIEBzdW1tYXJ5IEV2YWx1YXRlcyBhIHRyYW5zYWN0aW9uIHRvIHJlYWQgYSByZWNvcmQgZnJvbSB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXRyaWV2ZWQgcmVjb3JkXG4gICAqL1xuICBAZGVidWcoKVxuICBAZmluYWwoKVxuICBhc3luYyByZWFkPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkQWxsKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuXG4gICAgbG9nLnZlcmJvc2UoYHJlYWRpbmcgZW50cnkgZnJvbSAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cuZGVidWcoYHBrOiAke2lkfWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXZhbHVhdGVUcmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIFtpZC50b1N0cmluZygpXSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUodGhpcy5kZWNvZGUocmVzdWx0KSk7XG4gIH1cblxuICB1cGRhdGVQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKSB7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMudXBkYXRlUHJlZml4KTtcbiAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgIC8vIHJlY29yZFtDb3VjaERCS2V5cy5JRF0gPSB0aGlzLmdlbmVyYXRlSWQodGFibGVOYW1lLCBpZCk7XG4gICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsKTtcbiAgICByZXR1cm4gW2NsYXp6LCBpZCwgcmVjb3JkLCAuLi5jdHhBcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHNpbmdsZSByZWNvcmRcbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIHVwZGF0ZSBhIHJlY29yZCBpbiB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgdXBkYXRlZCByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgcmVjb3JkXG4gICAqL1xuICBAZGVidWcoKVxuICBAZmluYWwoKVxuICBhc3luYyB1cGRhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIHRyYW5zaWVudDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCBjdHhBcmdzID0gWy4uLihhcmdzIGFzIHVua25vd24gYXMgYW55W10pXTtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChcbiAgICAgIGN0eEFyZ3MgYXMgQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+LFxuICAgICAgdGhpcy51cGRhdGVBbGxcbiAgICApO1xuICAgIGxvZy5pbmZvKGBDTElFTlQgVVBEQVRFIGNsYXNzIDogJHt0eXBlb2YgY2xhenp9YCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBsb2cudmVyYm9zZShgdXBkYXRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLmRlYnVnKGBwazogJHtpZH1gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBbdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCwgY2xhenoubmFtZSB8fCBjbGF6eildLCAvLyBUT0RPIHNob3VsZCBiZSByZWNldmluZyBjbGFzcyBidXQgaXMgcmVjZWl2aW5nIHN0cmluZ1xuICAgICAgdHJhbnNpZW50LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY2xhenoubmFtZVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZSh0aGlzLmRlY29kZShyZXN1bHQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIHNpbmdsZSByZWNvcmRcbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIGRlbGV0ZSBhIHJlY29yZCBmcm9tIHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXIgdG8gZGVsZXRlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIHJlY29yZFxuICAgKi9cbiAgQGRlYnVnKClcbiAgQGZpbmFsKClcbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5kZWxldGUpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbG9nLnZlcmJvc2UoYGRlbGV0aW5nIGVudHJ5IGZyb20gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLmRlYnVnKGBwazogJHtpZH1gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBbaWQudG9TdHJpbmcoKV0sXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKHRoaXMuZGVjb2RlKHJlc3VsdCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHJhdyBxdWVyeSBhZ2FpbnN0IHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBzdW1tYXJ5IEV2YWx1YXRlcyBhIHRyYW5zYWN0aW9uIHRvIHBlcmZvcm0gYSBxdWVyeSB1c2luZyBNYW5nbyBRdWVyeSBzeW50YXhcbiAgICogQHRlbXBsYXRlIFYgLSBUaGUgcmV0dXJuIHR5cGVcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdJbnB1dCAtIFRoZSBNYW5nbyBRdWVyeSB0byBleGVjdXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gcHJvY2VzcyAtIFdoZXRoZXIgdG8gcHJvY2VzcyB0aGUgcmVzdWx0XG4gICAqIEByZXR1cm4ge1Byb21pc2U8Vj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBxdWVyeSByZXN1bHRcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gICAqICAgcGFydGljaXBhbnQgRmFicmljQWRhcHRlclxuICAgKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gICAqICAgcGFydGljaXBhbnQgQ2hhaW5jb2RlXG4gICAqXG4gICAqICAgQ2xpZW50LT4+RmFicmljQWRhcHRlcjogcmF3KHJhd0lucHV0LCBwcm9jZXNzKVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBKU09OLnN0cmluZ2lmeShyYXdJbnB1dClcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+RmFicmljQWRhcHRlcjogZXZhbHVhdGVUcmFuc2FjdGlvbihcInF1ZXJ5XCIsIFtpbnB1dF0pXG4gICAqICAgRmFicmljQWRhcHRlci0+PkNvbnRyYWN0OiBldmFsdWF0ZShcInF1ZXJ5XCIsIHByb3Bvc2FsT3B0aW9ucylcbiAgICogICBDb250cmFjdC0+PkNoYWluY29kZTogaW52b2tlXG4gICAqICAgQ2hhaW5jb2RlLS0+PkNvbnRyYWN0OiByZXNwb25zZVxuICAgKiAgIENvbnRyYWN0LS0+PkZhYnJpY0FkYXB0ZXI6IHJlc3VsdFxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBKU09OLnBhcnNlKGRlY29kZShyZXN1bHQpKVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBQcm9jZXNzIHJlc3VsdCBiYXNlZCBvbiB0eXBlXG4gICAqICAgRmFicmljQWRhcHRlci0tPj5DbGllbnQ6IHByb2Nlc3NlZCByZXN1bHRcbiAgICovXG4gIEBkZWJ1ZygpXG4gIGFzeW5jIHJhdzxWLCBEIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgcmF3SW5wdXQ6IE1hbmdvUXVlcnksXG4gICAgZG9jc09ubHk6IEQgPSB0cnVlIGFzIEQsXG4gICAgY2xheno6IE1vZGVsQ29uc3RydWN0b3I8YW55PixcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxWPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yYXcpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IGNsYXp6Lm5hbWU7XG4gICAgbG9nLmluZm8oYFBlcmZvcm1pbmcgcmF3IHN0YXRlbWVudCBvbiB0YWJsZSAke01vZGVsLnRhYmxlTmFtZShjbGF6eil9YCk7XG4gICAgbGV0IHRyYW5zYWN0aW9uUmVzdWx0OiBhbnk7XG4gICAgdHJ5IHtcbiAgICAgIHRyYW5zYWN0aW9uUmVzdWx0ID0gYXdhaXQgdGhpcy5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgICBjdHgsXG4gICAgICAgIFwicmF3XCIsXG4gICAgICAgIFtKU09OLnN0cmluZ2lmeShyYXdJbnB1dCksIGRvY3NPbmx5XSxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIHRhYmxlTmFtZVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICAgIGxldCByZXN1bHQ6IGFueTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gSlNPTi5wYXJzZSh0aGlzLmRlY29kZSh0cmFuc2FjdGlvblJlc3VsdCkpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihgRmFpbGVkIHRvIHByb2Nlc3MgcmVzdWx0OiAke2V9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VSZWNvcmQgPSAocmVjb3JkOiBSZWNvcmQ8YW55LCBhbnk+KSA9PiB7XG4gICAgICBpZiAoTW9kZWwuaXNNb2RlbChyZWNvcmQpKSByZXR1cm4gTW9kZWwuYnVpbGQocmVjb3JkKTtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkpIHtcbiAgICAgIGlmICghcmVzdWx0Lmxlbmd0aCkgcmV0dXJuIHJlc3VsdCBhcyBWO1xuICAgICAgY29uc3QgZWwgPSByZXN1bHRbMF07XG4gICAgICBpZiAoTW9kZWwuaXNNb2RlbChlbCkpXG4gICAgICAgIC8vIGlmIHRoZSBmaXJzdCBvbmUgaXMgYSBtb2RlbCwgYWxsIGFyZSBtb2RlbHNcbiAgICAgICAgcmV0dXJuIHJlc3VsdC5tYXAoKGVsKSA9PiBNb2RlbC5idWlsZChlbCkpIGFzIFY7XG4gICAgICByZXR1cm4gcmVzdWx0IGFzIFY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcnNlUmVjb3JkKHJlc3VsdCBhcyBhbnkpIGFzIFY7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgb3IgY3JlYXRlcyBhIGdSUEMgY2xpZW50IGZvciB0aGUgRmFicmljIHBlZXJcbiAgICogQHN1bW1hcnkgUmV0dXJucyBhIGNhY2hlZCBjbGllbnQgb3IgY3JlYXRlcyBhIG5ldyBvbmUgaWYgbm9uZSBleGlzdHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxDbGllbnQ+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZ1JQQyBjbGllbnRcbiAgICovXG4gIG92ZXJyaWRlIGdldENsaWVudCgpOiBDbGllbnQge1xuICAgIGlmICghdGhpcy5fY2xpZW50KVxuICAgICAgdGhpcy5fY2xpZW50ID0gRmFicmljQ2xpZW50QWRhcHRlci5nZXRDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgYSBHYXRld2F5IGluc3RhbmNlIGZvciB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIG5ldyBHYXRld2F5IGluc3RhbmNlIHVzaW5nIHRoZSBjdXJyZW50IGNsaWVudFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEdhdGV3YXk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgR2F0ZXdheSBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIEdhdGV3YXkoY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPik6IFByb21pc2U8R2F0ZXdheT4ge1xuICAgIHJldHVybiBGYWJyaWNDbGllbnRBZGFwdGVyLmdldEdhdGV3YXkoY3R4LCB0aGlzLmNvbmZpZywgdGhpcy5jbGllbnQpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250cmFjdE5hbWUoY2xhc3NOYW1lPzogc3RyaW5nKSB7XG4gICAgaWYgKCFjbGFzc05hbWUpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIGAke2NsYXNzTmFtZX1Db250cmFjdGA7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgYSBDb250cmFjdCBpbnN0YW5jZSBmb3IgdGhlIEZhYnJpYyBjaGFpbmNvZGVcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIG5ldyBDb250cmFjdCBpbnN0YW5jZSB1c2luZyB0aGUgY3VycmVudCBHYXRld2F5XG4gICAqIEByZXR1cm4ge1Byb21pc2U8Q29udHJha3Q+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgQ29udHJhY3QgaW5zdGFuY2VcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBDb250cmFjdChcbiAgICBjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+LFxuICAgIGNvbnRyYWN0TmFtZT86IHN0cmluZ1xuICApOiBQcm9taXNlPENvbnRyYWt0PiB7XG4gICAgcmV0dXJuIEZhYnJpY0NsaWVudEFkYXB0ZXIuZ2V0Q29udHJhY3QoXG4gICAgICBhd2FpdCB0aGlzLkdhdGV3YXkoY3R4KSxcbiAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgY29udHJhY3ROYW1lXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSB0cmFuc2FjdGlvbiBvbiB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgU3VibWl0cyBvciBldmFsdWF0ZXMgYSB0cmFuc2FjdGlvbiBvbiB0aGUgRmFicmljIGNoYWluY29kZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXBpIC0gVGhlIGNoYWluY29kZSBmdW5jdGlvbiB0byBjYWxsXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc3VibWl0IC0gV2hldGhlciB0byBzdWJtaXQgKHRydWUpIG9yIGV2YWx1YXRlIChmYWxzZSkgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7YW55W119IFthcmdzXSAtIEFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBjaGFpbmNvZGUgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fSBbdHJhbnNpZW50RGF0YV0gLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPn0gW2VuZG9yc2luZ09yZ2FuaXphdGlvbnNdIC0gT3JnYW5pemF0aW9ucyB0aGF0IG11c3QgZW5kb3JzZSB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxVaW50OEFycmF5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHRyYW5zYWN0aW9uIHJlc3VsdFxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBGYWJyaWNBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgR2F0ZXdheVxuICAgKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gICAqICAgcGFydGljaXBhbnQgQ2hhaW5jb2RlXG4gICAqXG4gICAqICAgRmFicmljQWRhcHRlci0+PkdhdGV3YXk6IGNvbm5lY3QoKVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5Db250cmFjdDogZ2V0Q29udHJhY3QoKVxuICAgKiAgIGFsdCBzdWJtaXQgdHJhbnNhY3Rpb25cbiAgICogICAgIEZhYnJpY0FkYXB0ZXItPj5Db250cmFjdDogc3VibWl0KGFwaSwgcHJvcG9zYWxPcHRpb25zKVxuICAgKiAgIGVsc2UgZXZhbHVhdGUgdHJhbnNhY3Rpb25cbiAgICogICAgIEZhYnJpY0FkYXB0ZXItPj5Db250cmFjdDogZXZhbHVhdGUoYXBpLCBwcm9wb3NhbE9wdGlvbnMpXG4gICAqICAgZW5kXG4gICAqICAgQ29udHJhY3QtPj5DaGFpbmNvZGU6IGludm9rZVxuICAgKiAgIENoYWluY29kZS0tPj5Db250cmFjdDogcmVzcG9uc2VcbiAgICogICBDb250cmFjdC0tPj5GYWJyaWNBZGFwdGVyOiByZXN1bHRcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+R2F0ZXdheTogY2xvc2UoKVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHRyYW5zYWN0aW9uKFxuICAgIGN0eDogQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgYXBpOiBzdHJpbmcsXG4gICAgc3VibWl0ID0gdHJ1ZSxcbiAgICBhcmdzPzogYW55W10sXG4gICAgdHJhbnNpZW50RGF0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICAgZW5kb3JzaW5nT3JnYW5pemF0aW9ucz86IEFycmF5PHN0cmluZz4sXG4gICAgY2xhc3NOYW1lPzogc3RyaW5nXG4gICk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnRyYW5zYWN0aW9uKTtcbiAgICBjb25zdCBnYXRld2F5ID0gYXdhaXQgdGhpcy5HYXRld2F5KGN0eCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbnRyYWN0ID0gYXdhaXQgdGhpcy5Db250cmFjdChcbiAgICAgICAgY3R4LFxuICAgICAgICB0aGlzLmdldENvbnRyYWN0TmFtZShjbGFzc05hbWUpXG4gICAgICApO1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGAke3N1Ym1pdCA/IFwiU3VibWl0XCIgOiBcIkV2YWx1YXRlXCJ9dGluZyB0cmFuc2FjdGlvbiAke3RoaXMuZ2V0Q29udHJhY3ROYW1lKGNsYXNzTmFtZSkgfHwgdGhpcy5jb25maWcuY29udHJhY3ROYW1lfS4ke2FwaX1gXG4gICAgICApO1xuICAgICAgbG9nLmRlYnVnKGBhcmdzOiAke2FyZ3M/Lm1hcCgoYSkgPT4gYS50b1N0cmluZygpKS5qb2luKFwiXFxuXCIpIHx8IFwibm9uZVwifWApO1xuICAgICAgY29uc3QgbWV0aG9kID0gc3VibWl0ID8gY29udHJhY3Quc3VibWl0IDogY29udHJhY3QuZXZhbHVhdGU7XG5cbiAgICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnMgPSBlbmRvcnNpbmdPcmdhbml6YXRpb25zPy5sZW5ndGhcbiAgICAgICAgPyBlbmRvcnNpbmdPcmdhbml6YXRpb25zXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcHJvcG9zYWxPcHRpb25zOiBQcm9wb3NhbE9wdGlvbnMgPSB7XG4gICAgICAgIGFyZ3VtZW50czogYXJncyB8fCBbXSxcbiAgICAgICAgdHJhbnNpZW50RGF0YTogdHJhbnNpZW50RGF0YSxcbiAgICAgICAgLy8gLi4uKGVuZG9yc2luZ09yZ2FuaXphdGlvbnMgJiYgeyBlbmRvcnNpbmdPcmdhbml6YXRpb25zIH0pIC8vIG1zcElkIGxpc3RcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBhd2FpdCBtZXRob2QuY2FsbChjb250cmFjdCwgYXBpLCBwcm9wb3NhbE9wdGlvbnMpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gMTApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2UuZGV0YWlsc1swXS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgQ2xvc2luZyAke3RoaXMuY29uZmlnLm1zcElkfSBnYXRld2F5IGNvbm5lY3Rpb25gKTtcbiAgICAgIGdhdGV3YXkuY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhbiBlcnJvciBpbnRvIGEgQmFzZUVycm9yXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGFueSBlcnJvciBpbnRvIGEgc3RhbmRhcmRpemVkIEJhc2VFcnJvclxuICAgKiBAcGFyYW0ge0Vycm9yIHwgc3RyaW5nfSBlcnIgLSBUaGUgZXJyb3IgdG8gcGFyc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gT3B0aW9uYWwgcmVhc29uIGZvciB0aGUgZXJyb3JcbiAgICogQHJldHVybiB7QmFzZUVycm9yfSBUaGUgcGFyc2VkIGVycm9yXG4gICAqL1xuICBvdmVycmlkZSBwYXJzZUVycm9yPEUgZXh0ZW5kcyBCYXNlRXJyb3I+KGVycjogRXJyb3IgfCBzdHJpbmcpOiBFIHtcbiAgICByZXR1cm4gRmFicmljQ2xpZW50QWRhcHRlci5wYXJzZUVycm9yPEU+KGVycik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgYSB0cmFuc2FjdGlvbiB0aGF0IG1vZGlmaWVzIHRoZSBsZWRnZXIgc3RhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFwaSAtIFRoZSBjaGFpbmNvZGUgZnVuY3Rpb24gdG8gY2FsbFxuICAgKiBAcGFyYW0ge2FueVtdfSBbYXJnc10gLSBBcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgY2hhaW5jb2RlIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn0gW3RyYW5zaWVudERhdGFdIC0gVHJhbnNpZW50IGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IFtlbmRvcnNpbmdPcmdhbml6YXRpb25zXSAtIE9yZ2FuaXphdGlvbnMgdGhhdCBtdXN0IGVuZG9yc2UgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8VWludDhBcnJheT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB0cmFuc2FjdGlvbiByZXN1bHRcbiAgICovXG4gIGFzeW5jIHN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgIGN0eDogQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgYXBpOiBzdHJpbmcsXG4gICAgYXJncz86IGFueVtdLFxuICAgIHRyYW5zaWVudERhdGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnM/OiBBcnJheTxzdHJpbmc+LFxuICAgIGNsYXNzTmFtZT86IHN0cmluZ1xuICApOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIGFwaSxcbiAgICAgIHRydWUsXG4gICAgICBhcmdzLFxuICAgICAgdHJhbnNpZW50RGF0YSxcbiAgICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnMsXG4gICAgICBjbGFzc05hbWVcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFdmFsdWF0ZXMgYSB0cmFuc2FjdGlvbiBvbiB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgYSB0cmFuc2FjdGlvbiB0aGF0IGRvZXMgbm90IG1vZGlmeSB0aGUgbGVkZ2VyIHN0YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcGkgLSBUaGUgY2hhaW5jb2RlIGZ1bmN0aW9uIHRvIGNhbGxcbiAgICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIC0gQXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGNoYWluY29kZSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHN0cmluZz59IFt0cmFuc2llbnREYXRhXSAtIFRyYW5zaWVudCBkYXRhIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBbZW5kb3JzaW5nT3JnYW5pemF0aW9uc10gLSBPcmdhbml6YXRpb25zIHRoYXQgbXVzdCBlbmRvcnNlIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFVpbnQ4QXJyYXk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdHJhbnNhY3Rpb24gcmVzdWx0XG4gICAqL1xuICBhc3luYyBldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgIGN0eDogQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgYXBpOiBzdHJpbmcsXG4gICAgYXJncz86IGFueVtdLFxuICAgIHRyYW5zaWVudERhdGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnM/OiBBcnJheTxzdHJpbmc+LFxuICAgIGNsYXNzTmFtZT86IHN0cmluZ1xuICApOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIGFwaSxcbiAgICAgIGZhbHNlLFxuICAgICAgYXJncyxcbiAgICAgIHRyYW5zaWVudERhdGEsXG4gICAgICBlbmRvcnNpbmdPcmdhbml6YXRpb25zLFxuICAgICAgY2xhc3NOYW1lXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBDbG9zZXMgdGhlIGdSUEMgY2xpZW50IGlmIGl0IGV4aXN0c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgY2xpZW50IGlzIGNsb3NlZFxuICAgKi9cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xpZW50KSB7XG4gICAgICB0aGlzLmxvZy52ZXJib3NlKGBDbG9zaW5nICR7dGhpcy5jb25maWcubXNwSWR9IGdhdGV3YXkgY2xpZW50YCk7XG4gICAgICB0aGlzLmNsaWVudC5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIENvbnRyYWN0IGluc3RhbmNlIGZyb20gYSBHYXRld2F5XG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIGNoYWluY29kZSBjb250cmFjdCBmcm9tIHRoZSBzcGVjaWZpZWQgbmV0d29ya1xuICAgKiBAcGFyYW0ge0dhdGV3YXl9IGdhdGV3YXkgLSBUaGUgR2F0ZXdheSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge1BlZXJDb25maWd9IGNvbmZpZyAtIFRoZSBwZWVyIGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybiB7Q29udHJha3R9IFRoZSBDb250cmFjdCBpbnN0YW5jZVxuICAgKi9cbiAgc3RhdGljIGdldENvbnRyYWN0KFxuICAgIGdhdGV3YXk6IEdhdGV3YXksXG4gICAgY29uZmlnOiBQZWVyQ29uZmlnLFxuICAgIGNvbnRyYWN0TmFtZT86IHN0cmluZ1xuICApOiBDb250cmFrdCB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0Q29udHJhY3QpO1xuICAgIGNvbnN0IG5ldHdvcmsgPSB0aGlzLmdldE5ldHdvcmsoZ2F0ZXdheSwgY29uZmlnLmNoYW5uZWwpO1xuICAgIGxldCBjb250cmFjdDogQ29udHJha3Q7XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFJldHJpZXZpbmcgY2hhaW5jb2RlICR7Y29uZmlnLmNoYWluY29kZU5hbWV9IGNvbnRyYWN0ICR7Y29udHJhY3ROYW1lIHx8IGNvbmZpZy5jb250cmFjdE5hbWV9IGZyb20gbmV0d29yayAke2NvbmZpZy5jaGFubmVsfWBcbiAgICAgICk7XG4gICAgICBjb250cmFjdE5hbWUgPSBjb250cmFjdE5hbWUgPyBjb250cmFjdE5hbWUgOiBjb25maWcuY29udHJhY3ROYW1lO1xuICAgICAgY29udHJhY3QgPSBuZXR3b3JrLmdldENvbnRyYWN0KGNvbmZpZy5jaGFpbmNvZGVOYW1lLCBjb250cmFjdE5hbWUpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgICByZXR1cm4gY29udHJhY3Q7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgYSBOZXR3b3JrIGluc3RhbmNlIGZyb20gYSBHYXRld2F5XG4gICAqIEBzdW1tYXJ5IENvbm5lY3RzIHRvIGEgc3BlY2lmaWMgY2hhbm5lbCBvbiB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHBhcmFtIHtHYXRld2F5fSBnYXRld2F5IC0gVGhlIEdhdGV3YXkgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWxOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGNoYW5uZWwgdG8gY29ubmVjdCB0b1xuICAgKiBAcmV0dXJuIHtOZXR3b3JrfSBUaGUgTmV0d29yayBpbnN0YW5jZVxuICAgKi9cbiAgc3RhdGljIGdldE5ldHdvcmsoZ2F0ZXdheTogR2F0ZXdheSwgY2hhbm5lbE5hbWU6IHN0cmluZyk6IE5ldHdvcmsge1xuICAgIGNvbnN0IGxvZyA9IExvZ2dpbmcuZm9yKHRoaXMuZ2V0TmV0d29yayk7XG4gICAgbGV0IG5ldHdvcms6IE5ldHdvcms7XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5kZWJ1ZyhgQ29ubmVjdGluZyB0byBjaGFubmVsICR7Y2hhbm5lbE5hbWV9YCk7XG4gICAgICBuZXR3b3JrID0gZ2F0ZXdheS5nZXROZXR3b3JrKGNoYW5uZWxOYW1lKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV0d29yaztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIEdhdGV3YXkgaW5zdGFuY2UgZm9yIGNvbm5lY3RpbmcgdG8gdGhlIEZhYnJpYyBuZXR3b3JrXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBHYXRld2F5IHVzaW5nIHRoZSBwcm92aWRlZCBjb25maWd1cmF0aW9uIGFuZCBjbGllbnRcbiAgICogQHBhcmFtIHtQZWVyQ29uZmlnfSBjb25maWcgLSBUaGUgcGVlciBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSB7Q2xpZW50fSBbY2xpZW50XSAtIE9wdGlvbmFsIGdSUEMgY2xpZW50LCB3aWxsIGJlIGNyZWF0ZWQgaWYgbm90IHByb3ZpZGVkXG4gICAqIEByZXR1cm4ge1Byb21pc2U8R2F0ZXdheT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBHYXRld2F5IGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2V0R2F0ZXdheShcbiAgICBjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+LFxuICAgIGNvbmZpZzogUGVlckNvbmZpZyxcbiAgICBjbGllbnQ/OiBDbGllbnRcbiAgKSB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmdldENvbm5lY3Rpb24oXG4gICAgICBjbGllbnQgfHwgKGF3YWl0IHRoaXMuZ2V0Q2xpZW50KGNvbmZpZykpLFxuICAgICAgY29uZmlnLFxuICAgICAgY3R4XG4gICAgKSkgYXMgR2F0ZXdheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGdSUEMgY2xpZW50IGZvciBjb25uZWN0aW5nIHRvIGEgRmFicmljIHBlZXJcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBjbGllbnQgd2l0aCBUTFMgY3JlZGVudGlhbHMgZm9yIHNlY3VyZSBjb21tdW5pY2F0aW9uXG4gICAqIEBwYXJhbSB7UGVlckNvbmZpZ30gY29uZmlnIC0gVGhlIHBlZXIgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJuIHtDbGllbnR9IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBnUlBDIGNsaWVudFxuICAgKi9cbiAgc3RhdGljIGdldENsaWVudChjb25maWc6IFBlZXJDb25maWcpOiBDbGllbnQge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmdldENsaWVudCk7XG4gICAgbG9nLmRlYnVnKGBnZW5lcmF0aW5nIFRMUyBjcmVkZW50aWFscyBmb3IgbXNwICR7Y29uZmlnLm1zcElkfWApO1xuICAgIGxldCBwYXRoT3JDZXJ0OiBzdHJpbmcgfCBCdWZmZXIgPSBjb25maWcudGxzQ2VydCBhcyBzdHJpbmcgfCBCdWZmZXI7XG5cbiAgICBpZiAodHlwZW9mIHBhdGhPckNlcnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGlmIChcbiAgICAgICAgcGF0aE9yQ2VydC5tYXRjaChcbiAgICAgICAgICAvLS0tLS1CRUdJTiAoQ0VSVElGSUNBVEV8S0VZfFBSSVZBVEUgS0VZKS0tLS0tLis/LS0tLS1FTkQgXFwxLS0tLS0kL2dtc1xuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgcGF0aE9yQ2VydCA9IEJ1ZmZlci5mcm9tKHBhdGhPckNlcnQsIFwidXRmOFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcGF0aE9yQ2VydCA9IEJ1ZmZlci5mcm9tKGZzLnJlYWRGaWxlU3luYyhwYXRoT3JDZXJ0LCBcInV0ZjhcIikpO1xuICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICBgRmFpbGVkIHRvIHJlYWQgdGhlIHRscyBjZXJ0aWZpY2F0ZSBmcm9tICR7cGF0aE9yQ2VydH06ICR7ZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRsc0NyZWRlbnRpYWxzID0gZ3JwYy5jcmVkZW50aWFscy5jcmVhdGVTc2wocGF0aE9yQ2VydCk7XG4gICAgbG9nLmRlYnVnKGBnZW5lcmF0aW5nIEdhdGV3YXkgQ2xpZW50IGZvciB1cmwgJHtjb25maWcucGVlckVuZHBvaW50fWApO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KGNvbmZpZy5wZWVyRW5kcG9pbnQsIHRsc0NyZWRlbnRpYWxzLCB7XG4gICAgICBcImdycGMubWF4X3JlY2VpdmVfbWVzc2FnZV9sZW5ndGhcIjogKGNvbmZpZy5zaXplTGltaXQgfHwgMTUpICogMTAyNCAqIDEwMjQsXG4gICAgICBcImdycGMubWF4X3NlbmRfbWVzc2FnZV9sZW5ndGhcIjogKGNvbmZpZy5zaXplTGltaXQgfHwgMTUpICogMTAyNCAqIDEwMjQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVzdGFibGlzaGVzIGEgY29ubmVjdGlvbiB0byB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIEdhdGV3YXkgY29ubmVjdGlvbiB3aXRoIGlkZW50aXR5IGFuZCBzaWduZXJcbiAgICogQHBhcmFtIHtDbGllbnR9IGNsaWVudCAtIFRoZSBnUlBDIGNsaWVudFxuICAgKiBAcGFyYW0ge1BlZXJDb25maWd9IGNvbmZpZyAtIFRoZSBwZWVyIGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxHYXRld2F5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNvbm5lY3RlZCBHYXRld2F5XG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICAgKiAgIHBhcnRpY2lwYW50IEZhYnJpY0FkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBJZGVudGl0eVxuICAgKiAgIHBhcnRpY2lwYW50IFNpZ25lclxuICAgKiAgIHBhcnRpY2lwYW50IEdhdGV3YXlcbiAgICpcbiAgICogICBDYWxsZXItPj5GYWJyaWNBZGFwdGVyOiBnZXRDb25uZWN0aW9uKGNsaWVudCwgY29uZmlnKVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5JZGVudGl0eTogZ2V0SWRlbnRpdHkobXNwSWQsIGNlcnREaXJlY3RvcnlQYXRoKVxuICAgKiAgIElkZW50aXR5LS0+PkZhYnJpY0FkYXB0ZXI6IGlkZW50aXR5XG4gICAqICAgRmFicmljQWRhcHRlci0+PlNpZ25lcjogZ2V0U2lnbmVyKGtleURpcmVjdG9yeVBhdGgpXG4gICAqICAgU2lnbmVyLS0+PkZhYnJpY0FkYXB0ZXI6IHNpZ25lclxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBDcmVhdGUgQ29ubmVjdE9wdGlvbnNcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+R2F0ZXdheTogY29ubmVjdChvcHRpb25zKVxuICAgKiAgIEdhdGV3YXktLT4+RmFicmljQWRhcHRlcjogZ2F0ZXdheVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItLT4+Q2FsbGVyOiBnYXRld2F5XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2V0Q29ubmVjdGlvbihcbiAgICBjbGllbnQ6IENsaWVudCxcbiAgICBjb25maWc6IFBlZXJDb25maWcsXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApIHtcbiAgICBjb25zdCBsb2cgPSBMb2dnaW5nLmZvcih0aGlzLmdldENvbm5lY3Rpb24pO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBSZXRyaWV2aW5nIFBlZXIgSWRlbnRpdHkgZm9yICR7Y29uZmlnLm1zcElkfSB1bmRlciAke2NvbmZpZy5jZXJ0Q2VydE9yRGlyZWN0b3J5UGF0aH1gXG4gICAgKTtcbiAgICBjb25zdCBpZGVudGl0eSA9IGF3YWl0IGdldElkZW50aXR5KFxuICAgICAgY29uZmlnLm1zcElkLFxuICAgICAgY29uZmlnLmNlcnRDZXJ0T3JEaXJlY3RvcnlQYXRoIGFzIGFueVxuICAgICk7XG4gICAgbG9nLmRlYnVnKGBSZXRyaWV2aW5nIHNpZ25lciBrZXkgZnJvbSAke2NvbmZpZy5rZXlDZXJ0T3JEaXJlY3RvcnlQYXRofWApO1xuXG4gICAgbGV0IHNpZ25lcjogU2lnbmVyLFxuICAgICAgY2xvc2UgPSAoKSA9PiB7fTtcbiAgICBpZiAoIWNvbmZpZy5oc20pIHtcbiAgICAgIHNpZ25lciA9IGF3YWl0IGdldFNpZ25lcihjb25maWcua2V5Q2VydE9yRGlyZWN0b3J5UGF0aCBhcyBhbnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBoc20gPSBuZXcgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbShjb25maWcuaHNtLmxpYnJhcnkpO1xuICAgICAgY29uc3QgaWRlbnRpZmllciA9IGhzbS5nZXRTS0lGcm9tQ2VydGlmaWNhdGVQYXRoKFxuICAgICAgICBjb25maWcuY2VydENlcnRPckRpcmVjdG9yeVBhdGggYXMgYW55XG4gICAgICApO1xuICAgICAgY29uc3QgcGtjczExU2lnbmVyID0gaHNtLm5ld1NpZ25lcih7XG4gICAgICAgIGxhYmVsOiBjb25maWcuaHNtLnRva2VuTGFiZWwgYXMgc3RyaW5nLFxuICAgICAgICBwaW46IFN0cmluZyhjb25maWcuaHNtLnBpbikgYXMgc3RyaW5nLFxuICAgICAgICBpZGVudGlmaWVyOiBpZGVudGlmaWVyLFxuICAgICAgICAvLyB1c2VyVHlwZTogMSAvKkNLVV9VU0VSICovLFxuICAgICAgfSk7XG4gICAgICBzaWduZXIgPSBwa2NzMTFTaWduZXIuc2lnbmVyO1xuXG4gICAgICBjbG9zZSA9IHBrY3MxMVNpZ25lci5jbG9zZTtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgY2xpZW50LFxuICAgICAgaWRlbnRpdHk6IGlkZW50aXR5LFxuICAgICAgc2lnbmVyOiBzaWduZXIsXG4gICAgICAvLyBEZWZhdWx0IHRpbWVvdXRzIGZvciBkaWZmZXJlbnQgZ1JQQyBjYWxsc1xuICAgICAgZXZhbHVhdGVPcHRpb25zOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IGRlYWRsaW5lOiBEYXRlLm5vdygpICsgMTAwMCAqIGN0eC5nZXQoXCJldmFsdWF0ZVRpbWVvdXRcIikgfTsgLy8gZGVmYXVsdHMgdG8gNSBzZWNvbmRzXG4gICAgICB9LFxuICAgICAgZW5kb3JzZU9wdGlvbnM6ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHsgZGVhZGxpbmU6IERhdGUubm93KCkgKyAxMDAwICogY3R4LmdldChcImVuZG9yc2VUaW1lb3V0XCIpIH07IC8vIGRlZmF1bHRzIHRvIDE1IHNlY29uZHNcbiAgICAgIH0sXG4gICAgICBzdWJtaXRPcHRpb25zOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IGRlYWRsaW5lOiBEYXRlLm5vdygpICsgMTAwMCAqIGN0eC5nZXQoXCJzdWJtaXRUaW1lb3V0XCIpIH07IC8vIGRlZmF1bHRzIHRvIDUgc2Vjb25kc1xuICAgICAgfSxcbiAgICAgIGNvbW1pdFN0YXR1c09wdGlvbnM6ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHsgZGVhZGxpbmU6IERhdGUubm93KCkgKyAxMDAwICogY3R4LmdldChcImNvbW1pdFRpbWVvdXRcIikgfTsgLy8gZGVmYXVsdHMgdG8gMSBtaW51dGVcbiAgICAgIH0sXG4gICAgfSBhcyBDb25uZWN0T3B0aW9ucztcblxuICAgIGxvZy5kZWJ1ZyhgQ29ubmVjdGluZyB0byAke2NvbmZpZy5tc3BJZH1gKTtcbiAgICBjb25zdCBnYXRld2F5ID0gY29ubmVjdChvcHRpb25zKTtcblxuICAgIC8vIFRPRE86IHJlcGxhY2U/XG4gICAgaWYgKGNvbmZpZy5oc20pIHtcbiAgICAgIGdhdGV3YXkuY2xvc2UgPSBuZXcgUHJveHkoZ2F0ZXdheS5jbG9zZSwge1xuICAgICAgICBhcHBseSh0YXJnZXQ6ICgpID0+IHZvaWQsIHRoaXNBcmc6IGFueSwgYXJnQXJyYXk6IGFueVtdKTogYW55IHtcbiAgICAgICAgICBSZWZsZWN0LmFwcGx5KHRhcmdldCwgdGhpc0FyZywgYXJnQXJyYXkpO1xuICAgICAgICAgIGNsb3NlKCk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2F0ZXdheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBEaXNwYXRjaCBpbnN0YW5jZSBmb3IgdGhlIEZhYnJpYyBjbGllbnQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gaXMgcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIGEgbmV3IEZhYnJpY0NsaWVudERpc3BhdGNoIGluc3RhbmNlIHRoYXQgY2FuIGJlIHVzZWQgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgRmFicmljIG5ldHdvcmsuXG4gICAqIEByZXR1cm5zIHtEaXNwYXRjaH0gQSBuZXcgRGlzcGF0Y2ggaW5zdGFuY2UgY29uZmlndXJlZCBmb3IgdGhlIEZhYnJpYyBjbGllbnQuXG4gICAqIEByZW1hcmtzIFRoZSBEaXNwYXRjaCBpbnN0YW5jZSBpcyB1c2VkIHRvIGVuY2Fwc3VsYXRlIHRoZSBsb2dpYyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgRmFicmljIG5ldHdvcmssIHN1Y2ggYXMgc3VibWl0dGluZyB0cmFuc2FjdGlvbnMgb3IgcXVlcnlpbmcgZGF0YS5cbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgZmFicmljRGlzcGF0Y2ggPSBmYWJyaWNDbGllbnRBZGFwdGVyLkRpc3BhdGNoKCk7XG4gICAqIGZhYnJpY0Rpc3BhdGNoLnN1Ym1pdFRyYW5zYWN0aW9uKCdjcmVhdGVQcm9kdWN0JywgeyBuYW1lOiAnUHJvZHVjdCBBJywgcHJpY2U6IDEwMCB9KTtcbiAgICovXG4gIG92ZXJyaWRlIERpc3BhdGNoKCk6IEZhYnJpY0NsaWVudERpc3BhdGNoIHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NsaWVudEFkYXB0ZXJbXCJfYmFzZURpc3BhdGNoXCJdKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhbiBlcnJvciBpbnRvIGEgQmFzZUVycm9yXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGFueSBlcnJvciBpbnRvIGEgc3RhbmRhcmRpemVkIEJhc2VFcnJvciB1c2luZyB0aGUgcGFyZW50IGNsYXNzIGltcGxlbWVudGF0aW9uXG4gICAqIEBwYXJhbSB7RXJyb3IgfCBzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3JcbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgcGFyc2VFcnJvcjxFIGV4dGVuZHMgQmFzZUVycm9yPihlcnI6IEVycm9yIHwgc3RyaW5nKTogRSB7XG4gICAgLy8gaWYgKFxuICAgIC8vICAgTUlTU0lOR19QUklWQVRFX0RBVEFfUkVHRVgudGVzdChcbiAgICAvLyAgICAgdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlXG4gICAgLy8gICApXG4gICAgLy8gKVxuICAgIC8vICAgcmV0dXJuIG5ldyBVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyhlcnIpIGFzIEU7XG4gICAgY29uc3QgbXNnID0gdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlO1xuXG4gICAgaWYgKG1zZy5pbmNsdWRlcyhcIk1WQ0NfUkVBRF9DT05GTElDVFwiKSlcbiAgICAgIHJldHVybiBuZXcgTXZjY1JlYWRDb25mbGljdEVycm9yKGVycikgYXMgRTtcblxuICAgIGlmIChtc2cuaW5jbHVkZXMoXCJFTkRPUlNFTUVOVF9QT0xJQ1lfRkFJTFVSRVwiKSlcbiAgICAgIHJldHVybiBuZXcgRW5kb3JzZW1lbnRQb2xpY3lFcnJvcihlcnIpIGFzIEU7XG5cbiAgICBpZiAobXNnLmluY2x1ZGVzKFwiUEhBTlRPTV9SRUFEX0NPTkZMSUNUXCIpKVxuICAgICAgcmV0dXJuIG5ldyBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IoZXJyKSBhcyBFO1xuXG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIChlcnIgYXMgYW55KS5jb2RlKSB7XG4gICAgICBzd2l0Y2ggKChlcnIgYXMgYW55KS5jb2RlKSB7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICByZXR1cm4gbmV3IEVuZG9yc2VtZW50RXJyb3IoZXJyKSBhcyBFO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtc2cuaW5jbHVkZXMoTm90Rm91bmRFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKENvbmZsaWN0RXJyb3IubmFtZSkpIHJldHVybiBuZXcgQ29uZmxpY3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhCYWRSZXF1ZXN0RXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IEJhZFJlcXVlc3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhRdWVyeUVycm9yLm5hbWUpKSByZXR1cm4gbmV3IFF1ZXJ5RXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoUGFnaW5nRXJyb3IubmFtZSkpIHJldHVybiBuZXcgUGFnaW5nRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoVW5zdXBwb3J0ZWRFcnJvci5uYW1lKSlcbiAgICAgIHJldHVybiBuZXcgVW5zdXBwb3J0ZWRFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhNaWdyYXRpb25FcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBNaWdyYXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhPYnNlcnZlckVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE9ic2VydmVyRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQXV0aG9yaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoRm9yYmlkZGVuRXJyb3IubmFtZSkpIHJldHVybiBuZXcgRm9yYmlkZGVuRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQ29ubmVjdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBDb25uZWN0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoU2VyaWFsaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpIGFzIEU7XG4gIH1cbn1cblxuRmFicmljQ2xpZW50QWRhcHRlci5kZWNvcmF0aW9uKCk7XG5BZGFwdGVyLnNldEN1cnJlbnQoRmFicmljRmxhdm91cik7XG4iLCJpbXBvcnQge1xuICBBZGFwdGVyLFxuICBDb250ZXh0dWFsQXJncyxcbiAgRGlzcGF0Y2gsXG4gIEV2ZW50SWRzLFxuICBVbnN1cHBvcnRlZEVycm9yLFxuICBDb250ZXh0LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFBlZXJDb25maWcgfSBmcm9tIFwiLi4vc2hhcmVkL3R5cGVzXCI7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tIFwiQGdycGMvZ3JwYy1qc1wiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50QWRhcHRlciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7XG4gIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyxcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDaGFpbmNvZGVFdmVudCxcbiAgQ2xvc2VhYmxlQXN5bmNJdGVyYWJsZSxcbn0gZnJvbSBcIkBoeXBlcmxlZGdlci9mYWJyaWMtZ2F0ZXdheVwiO1xuaW1wb3J0IHsgcGFyc2VFdmVudE5hbWUgfSBmcm9tIFwiLi4vc2hhcmVkL2V2ZW50c1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFdmVudCBkaXNwYXRjaGVyIGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIGV2ZW50c1xuICogQHN1bW1hcnkgTGlzdGVucyBmb3IgYW5kIHByb2Nlc3NlcyBldmVudHMgZW1pdHRlZCBieSBGYWJyaWMgY2hhaW5jb2RlLCBkaXNwYXRjaGluZyB0aGVtIHRvIHJlZ2lzdGVyZWQgb2JzZXJ2ZXJzXG4gKiBAdGVtcGxhdGUgUGVlckNvbmZpZyAtIENvbmZpZ3VyYXRpb24gdHlwZSBmb3IgY29ubmVjdGluZyB0byBhIEZhYnJpYyBwZWVyXG4gKiBAcGFyYW0gY2xpZW50IC0gZ1JQQyBjbGllbnQgZm9yIGNvbm5lY3RpbmcgdG8gdGhlIEZhYnJpYyBuZXR3b3JrXG4gKiBAY2xhc3MgRmFicmljQ2xpZW50RGlzcGF0Y2hcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBuZXcgRmFicmljRGlzcGF0Y2ggaW5zdGFuY2VcbiAqIGNvbnN0IGNsaWVudCA9IGF3YWl0IEZhYnJpY0FkYXB0ZXIuZ2V0Q2xpZW50KHBlZXJDb25maWcpO1xuICogY29uc3QgZGlzcGF0Y2ggPSBuZXcgRmFicmljRGlzcGF0Y2goY2xpZW50KTtcbiAqXG4gKiAvLyBDb25maWd1cmUgdGhlIGRpc3BhdGNoIHdpdGggcGVlciBjb25maWd1cmF0aW9uXG4gKiBkaXNwYXRjaC5jb25maWd1cmUocGVlckNvbmZpZyk7XG4gKlxuICogLy8gUmVnaXN0ZXIgYW4gb2JzZXJ2ZXIgZm9yIGEgc3BlY2lmaWMgdGFibGUgYW5kIGV2ZW50XG4gKiBkaXNwYXRjaC5vYnNlcnZlKCd1c2VycycsICdjcmVhdGUnLCAoaWQpID0+IHtcbiAqICAgY29uc29sZS5sb2coYFVzZXIgY3JlYXRlZDogJHtpZH1gKTtcbiAqIH0pO1xuICpcbiAqIC8vIFN0YXJ0IGxpc3RlbmluZyBmb3IgZXZlbnRzXG4gKiBhd2FpdCBkaXNwYXRjaC5zdGFydCgpO1xuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBGYWJyaWNEaXNwYXRjaFxuICogICBwYXJ0aWNpcGFudCBHYXRld2F5XG4gKiAgIHBhcnRpY2lwYW50IE5ldHdvcmtcbiAqICAgcGFydGljaXBhbnQgQ2hhaW5jb2RlXG4gKlxuICogICBDbGllbnQtPj5GYWJyaWNEaXNwYXRjaDogbmV3IEZhYnJpY0Rpc3BhdGNoKGNsaWVudClcbiAqICAgQ2xpZW50LT4+RmFicmljRGlzcGF0Y2g6IGNvbmZpZ3VyZShwZWVyQ29uZmlnKVxuICogICBDbGllbnQtPj5GYWJyaWNEaXNwYXRjaDogb2JzZXJ2ZSh0YWJsZSwgZXZlbnQsIGNhbGxiYWNrKVxuICogICBDbGllbnQtPj5GYWJyaWNEaXNwYXRjaDogc3RhcnQoKVxuICogICBGYWJyaWNEaXNwYXRjaC0+PkZhYnJpY0Rpc3BhdGNoOiBpbml0aWFsaXplKClcbiAqICAgRmFicmljRGlzcGF0Y2gtPj5HYXRld2F5OiBnZXRHYXRld2F5KGNvbmZpZywgY2xpZW50KVxuICogICBHYXRld2F5LT4+TmV0d29yazogZ2V0TmV0d29yayhjaGFubmVsKVxuICogICBOZXR3b3JrLT4+TmV0d29yazogZ2V0Q2hhaW5jb2RlRXZlbnRzKGNoYWluY29kZU5hbWUpXG4gKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IGhhbmRsZUV2ZW50cygpXG4gKiAgIGxvb3AgRm9yIGVhY2ggZXZlbnRcbiAqICAgICBDaGFpbmNvZGUtLT4+RmFicmljRGlzcGF0Y2g6IENoYWluY29kZUV2ZW50XG4gKiAgICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogcGFyc2VFdmVudE5hbWUoZXZlbnROYW1lKVxuICogICAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IHBhcnNlUGF5bG9hZChwYXlsb2FkKVxuICogICAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IHVwZGF0ZU9ic2VydmVycyh0YWJsZSwgZXZlbnQsIGlkKVxuICogICAgIEZhYnJpY0Rpc3BhdGNoLS0+PkNsaWVudDogY2FsbGJhY2soaWQpXG4gKiAgIGVuZFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ2xpZW50RGlzcGF0Y2ggZXh0ZW5kcyBEaXNwYXRjaDxGYWJyaWNDbGllbnRBZGFwdGVyPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXZlbnQgbGlzdGVuaW5nIHN0YWNrIGZvciBjaGFpbmNvZGUgZXZlbnRzXG4gICAqL1xuICBwcml2YXRlIGxpc3RlbmluZ1N0YWNrPzogQ2xvc2VhYmxlQXN5bmNJdGVyYWJsZTxDaGFpbmNvZGVFdmVudD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXh0IGRlY29kZXIgZm9yIGNvbnZlcnRpbmcgZXZlbnQgcGF5bG9hZHMgZnJvbSBieXRlcyB0byBzdHJpbmdzXG4gICAqL1xuICBwcml2YXRlIGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGY4XCIpO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNEaXNwYXRjaCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIGRpc3BhdGNoZXIgZm9yIEZhYnJpYyBjaGFpbmNvZGUgZXZlbnRzXG4gICAqIEBwYXJhbSB7Q2xpZW50fSBjbGllbnQgLSBnUlBDIGNsaWVudCBmb3IgY29ubmVjdGluZyB0byB0aGUgRmFicmljIG5ldHdvcmtcbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBjbGllbnQ6IENsaWVudCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgZXZlbnQgbGlzdGVuaW5nIGNvbm5lY3Rpb25cbiAgICogQHN1bW1hcnkgU3RvcHMgbGlzdGVuaW5nIGZvciBjaGFpbmNvZGUgZXZlbnRzIGFuZCByZWxlYXNlcyByZXNvdXJjZXNcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgY2xvc2VkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5saXN0ZW5pbmdTdGFjaykgdGhpcy5saXN0ZW5pbmdTdGFjay5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgZXZlbnQgcGF5bG9hZCBmcm9tIGJpbmFyeSBmb3JtYXRcbiAgICogQHN1bW1hcnkgQ29udmVydHMgYSBVaW50OEFycmF5IGNvbnRhaW5pbmcgSlNPTiB0byBhbiBvYmplY3Qgd2l0aCBhbiBpZCBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGpzb25CeXRlcyAtIFRoZSBiaW5hcnkgcGF5bG9hZCBmcm9tIHRoZSBjaGFpbmNvZGUgZXZlbnRcbiAgICogQHJldHVybiB7eyBpZDogc3RyaW5nIH19IFRoZSBwYXJzZWQgcGF5bG9hZCBjb250YWluaW5nIHRoZSByZWNvcmQgSURcbiAgICovXG4gIHByaXZhdGUgcGFyc2VQYXlsb2FkKGpzb25CeXRlczogVWludDhBcnJheSk6IHsgaWQ6IHN0cmluZyB9IHtcbiAgICBjb25zdCBqc29uID0gdGhpcy5kZWNvZGVyLmRlY29kZShqc29uQnl0ZXMpO1xuICAgIHJldHVybiBKU09OLnBhcnNlKGpzb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGFydHMgb2JzZXJ2aW5nIGFuIGFkYXB0ZXJcbiAgICogQHN1bW1hcnkgQ29ubmVjdHMgdGhpcyBkaXNwYXRjaCB0byBhbiBhZGFwdGVyIHRvIG1vbml0b3IgaXRzIG9wZXJhdGlvbnNcbiAgICogQHBhcmFtIHtBZGFwdGVyPGFueSwgYW55LCBhbnksIGFueT59IG9ic2VydmVyIC0gVGhlIGFkYXB0ZXIgdG8gb2JzZXJ2ZVxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgb3ZlcnJpZGUgb2JzZXJ2ZShvYnNlcnZlcjogQWRhcHRlcjxhbnksIGFueSwgYW55LCBhbnk+KTogKCkgPT4gdm9pZCB7XG4gICAgaWYgKCEob2JzZXJ2ZXIgaW5zdGFuY2VvZiBGYWJyaWNDbGllbnRBZGFwdGVyKSlcbiAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICBcIk9ubHkgRmFicmljQ2xpZW50QWRhcHRlciBjYW4gYmUgb2JzZXJ2ZWQgYnkgZGlzcGF0Y2hcIlxuICAgICAgKTtcbiAgICBzdXBlci5vYnNlcnZlKG9ic2VydmVyIGFzIEZhYnJpY0NsaWVudEFkYXB0ZXIpO1xuICAgIHJldHVybiAoKSA9PiB0aGlzLnVuT2JzZXJ2ZShvYnNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgb2JzZXJ2ZXJzIGFib3V0IGEgZGF0YWJhc2UgZXZlbnRcbiAgICogQHN1bW1hcnkgTm90aWZpZXMgb2JzZXJ2ZXJzIGFib3V0IGEgY2hhbmdlIGluIHRoZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgd2hlcmUgdGhlIGNoYW5nZSBvY2N1cnJlZFxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXN8QnVsa0NydWRPcGVyYXRpb25LZXlzfHN0cmluZ30gZXZlbnQgLSBUaGUgdHlwZSBvZiBvcGVyYXRpb24gdGhhdCBvY2N1cnJlZFxuICAgKiBAcGFyYW0ge2FueX0gcGF5bG9hZCAtIFRoZSBldmVudCBwYXlsb2FkXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIG9ic2VydmVycyBoYXZlIGJlZW4gbm90aWZpZWRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZU9ic2VydmVycyhcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8YW55PiB8IHN0cmluZyxcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSBBZGFwdGVyLmxvZ0N0eDxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj4oXG4gICAgICB0aGlzLnVwZGF0ZU9ic2VydmVycyxcbiAgICAgIGV2ZW50LFxuICAgICAgZmFsc2UsXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgICBpZiAoIXRoaXMuYWRhcHRlcikge1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGBObyBhZGFwdGVyIG9ic2VydmVkIGZvciBkaXNwYXRjaDsgc2tpcHBpbmcgb2JzZXJ2ZXIgdXBkYXRlIGZvciAke3R5cGVvZiBtb2RlbCA9PT0gXCJzdHJpbmdcIiA/IG1vZGVsIDogTW9kZWwudGFibGVOYW1lKG1vZGVsKX06JHtldmVudH1gXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5hZGFwdGVyLnJlZnJlc2gobW9kZWwsIGV2ZW50LCBpZCwgLi4uY3R4QXJncyk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEZhaWxlZCB0byByZWZyZXNoIGRpc3BhdGNoOiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgaW5jb21pbmcgY2hhaW5jb2RlIGV2ZW50c1xuICAgKiBAc3VtbWFyeSBMaXN0ZW5zIGZvciBldmVudHMgZnJvbSB0aGUgY2hhaW5jb2RlIGFuZCBkaXNwYXRjaGVzIHRoZW0gdG8gcmVnaXN0ZXJlZCBvYnNlcnZlcnNcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gZXZlbnQgaGFuZGxpbmcgc3RvcHNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgRmFicmljRGlzcGF0Y2hcbiAgICogICBwYXJ0aWNpcGFudCBFdmVudFN0YWNrXG4gICAqICAgcGFydGljaXBhbnQgRXZlbnRQYXJzZXJcbiAgICogICBwYXJ0aWNpcGFudCBPYnNlcnZlcnNcbiAgICpcbiAgICogICBGYWJyaWNEaXNwYXRjaC0+PkZhYnJpY0Rpc3BhdGNoOiBoYW5kbGVFdmVudHMoKVxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RXZlbnRTdGFjazogZm9yIGF3YWl0IChjb25zdCBldnQgb2YgbGlzdGVuaW5nU3RhY2spXG4gICAqICAgRXZlbnRTdGFjay0tPj5GYWJyaWNEaXNwYXRjaDogQ2hhaW5jb2RlRXZlbnRcbiAgICogICBGYWJyaWNEaXNwYXRjaC0+PkV2ZW50UGFyc2VyOiBwYXJzZUV2ZW50TmFtZShldnQuZXZlbnROYW1lKVxuICAgKiAgIEV2ZW50UGFyc2VyLS0+PkZhYnJpY0Rpc3BhdGNoOiB7IHRhYmxlLCBldmVudCwgb3duZXIgfVxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IENoZWNrIGlmIGV2ZW50IGlzIGZvciB0aGlzIE1TUFxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IHBhcnNlUGF5bG9hZChldnQucGF5bG9hZClcbiAgICogICBGYWJyaWNEaXNwYXRjaC0+Pk9ic2VydmVyczogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBldmVudCwgcGF5bG9hZC5pZClcbiAgICogICBPYnNlcnZlcnMtLT4+RmFicmljRGlzcGF0Y2g6IENhbGxiYWNrcyBleGVjdXRlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGhhbmRsZUV2ZW50cyhcbiAgICBjdHhBcmc/OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMubGlzdGVuaW5nU3RhY2spXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYEV2ZW50IHN0YWNrIG5vdCBpbml0aWFsaXplZC4gRW5zdXJlIHRoYXQgXCJzdGFydExpc3RlbmluZ1wiIGlzIGNhbGxlZCBiZWZvcmUgYXR0ZW1wdGluZyB0aGlzIG9wZXJhdGlvbi5gXG4gICAgICApO1xuXG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIgfHwgIXRoaXMuYWRhcHRlci5jb25maWcpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlciBmb3VuZC4gc2hvdWxkIGJlIGltcG9zc2libGVgKTtcblxuICAgIGNvbnN0IGN0eCA9XG4gICAgICBjdHhBcmcgfHxcbiAgICAgIChhd2FpdCB0aGlzLmFkYXB0ZXIuY29udGV4dChcbiAgICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgICB7XG4gICAgICAgICAgY29ycmVsYXRpb25JZDogdGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFpbmNvZGVOYW1lLFxuICAgICAgICB9LFxuICAgICAgICAodGhpcy5tb2RlbHMgJiYgdGhpcy5tb2RlbHNbMF0pIHx8IChNb2RlbCBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yKVxuICAgICAgKSk7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuaGFuZGxlRXZlbnRzKTtcblxuICAgIGxvZy5pbmZvKFxuICAgICAgYExpc3RlbmluZyBmb3IgaW5jb21pbmcgZXZlbnRzIG9uIGNoYWluY29kZSBcIiR7dGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFpbmNvZGVOYW1lfVwiIG9uIGNoYW5uZWwgXCIke3RoaXMuYWRhcHRlci5jb25maWcuY2hhbm5lbH1cIi4uLmBcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIGZvciBhd2FpdCAoY29uc3QgZXZ0IG9mIHRoaXMubGlzdGVuaW5nU3RhY2spIHtcbiAgICAgICAgY29uc3QgeyB0YWJsZSwgZXZlbnQsIG93bmVyIH0gPSBwYXJzZUV2ZW50TmFtZShldnQuZXZlbnROYW1lKTtcbiAgICAgICAgaWYgKG93bmVyICYmIG93bmVyICE9PSB0aGlzLmFkYXB0ZXIuY29uZmlnPy5tc3BJZCkgY29udGludWU7XG4gICAgICAgIGNvbnN0IHBheWxvYWQ6IHsgaWQ6IHN0cmluZyB9ID0gdGhpcy5wYXJzZVBheWxvYWQoZXZ0LnBheWxvYWQpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHRhcmdldE1vZGVsID0gdGFibGVcbiAgICAgICAgICAgID8gTW9kZWwuZ2V0KHRhYmxlKVxuICAgICAgICAgICAgOiBNb2RlbC5nZXQodGhpcy5tb2RlbHNbMF0ubmFtZSk7XG4gICAgICAgICAgY29uc3QgbW9kZWxSZWYgPSB0YXJnZXRNb2RlbCA/PyAodGFibGUgfHwgdGhpcy5tb2RlbHNbMF0/Lm5hbWUpO1xuICAgICAgICAgIGF3YWl0IHRoaXMudXBkYXRlT2JzZXJ2ZXJzKFxuICAgICAgICAgICAgbW9kZWxSZWYgYXMgQ29uc3RydWN0b3IgfCBzdHJpbmcsXG4gICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgIHBheWxvYWQuaWQgYXMgc3RyaW5nLFxuICAgICAgICAgICAgY3R4XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIGxvZy5lcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdXBkYXRlIG9ic2VydmFibGVzIGZvciB0YWJsZSAke3RhYmxlfSBldmVudCAke2V2ZW50fSBpZDogJHtwYXlsb2FkLmlkfTogJHtlfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBsb2cuZXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmVhZCBldmVudCBmb3IgY2hhaW5jb2RlIFwiJHt0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYWluY29kZU5hbWV9XCIgb24gY2hhbm5lbCBcIiR7dGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFubmVsfVwiOiAke2V9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBldmVudCBsaXN0ZW5lclxuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBGYWJyaWMgbmV0d29yayBhbmQgc3RhcnRzIGxpc3RlbmluZyBmb3IgY2hhaW5jb2RlIGV2ZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlciBvciBjb25maWcgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jb250ZXh0KFxuICAgICAgXCJkaXNwYXRjaFwiLFxuICAgICAge1xuICAgICAgICBjb3JyZWxhdGlvbklkOiB0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYWluY29kZU5hbWUsXG4gICAgICB9LFxuICAgICAgTW9kZWwgYXMgYW55XG4gICAgKTtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmluaXRpYWxpemUpO1xuICAgIGNvbnN0IGdhdGV3YXkgPSBhd2FpdCBGYWJyaWNDbGllbnRBZGFwdGVyLmdldEdhdGV3YXkoXG4gICAgICBjdHgsXG4gICAgICB0aGlzLmFkYXB0ZXIuY29uZmlnIGFzIFBlZXJDb25maWcsXG4gICAgICB0aGlzLmNsaWVudFxuICAgICk7XG4gICAgY29uc3QgbmV0d29yayA9IGdhdGV3YXkuZ2V0TmV0d29yayh0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYW5uZWwpO1xuICAgIGlmICghdGhpcy5hZGFwdGVyKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE5vIGFkYXB0ZXIgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgdGhpcy5saXN0ZW5pbmdTdGFjayA9IGF3YWl0IG5ldHdvcmsuZ2V0Q2hhaW5jb2RlRXZlbnRzKFxuICAgICAgdGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFpbmNvZGVOYW1lXG4gICAgKTtcbiAgICB0aGlzLmhhbmRsZUV2ZW50cyhjdHgpO1xuICB9XG59XG5cbmlmIChGYWJyaWNDbGllbnRBZGFwdGVyKVxuICBGYWJyaWNDbGllbnRBZGFwdGVyW1wiX2Jhc2VEaXNwYXRjaFwiXSA9IEZhYnJpY0NsaWVudERpc3BhdGNoO1xuIiwiaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9OQU1FID0gXCIjI1BBQ0tBR0UjI1wiO1xuXG5NZXRhZGF0YS5yZWdpc3RlckxpYnJhcnkoUEFDS0FHRV9OQU1FLCBWRVJTSU9OKTtcbiJdLCJuYW1lcyI6WyJGYWJyaWNDbGllbnRSZXBvc2l0b3J5IiwiUmVwb3NpdG9yeSIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImNsYXp6Iiwic3VwZXIiLCJ0aGlzIiwiX292ZXJyaWRlcyIsIk9iamVjdCIsImFzc2lnbiIsImlnbm9yZVZhbGlkYXRpb24iLCJpZ25vcmVIYW5kbGVycyIsImFsbG93UmF3U3RhdGVtZW50cyIsImZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXMiLCJmb3JjZVByZXBhcmVDb21wbGV4UXVlcmllcyIsImFsbG93R2VuZXJhdGlvbk92ZXJyaWRlIiwicGFnaW5hdGVCeSIsImtleSIsIm9yZGVyIiwicmVmIiwib2Zmc2V0IiwibGltaXQiLCJhcmdzIiwibG9nIiwiY3R4QXJncyIsImxvZ0N0eCIsIlByZXBhcmVkU3RhdGVtZW50S2V5cyIsIlBBR0VfQlkiLCJmb3IiLCJ2ZXJib3NlIiwiTW9kZWwiLCJ0YWJsZU5hbWUiLCJjbGFzcyIsInN0YXRlbWVudCIsIm5hbWUiLCJib29rbWFyayIsImxpc3RCeSIsIkxJU1RfQlkiLCJmaW5kQnkiLCJ2YWx1ZSIsIkZJTkRfQlkiLCJmaW5kT25lQnkiLCJGSU5EX09ORV9CWSIsImN0eCIsIlBlcnNpc3RlbmNlS2V5cyIsIlNUQVRFTUVOVCIsImNhbGxBcmdzIiwic2xpY2UiLCJyZXN1bHQiLCJKU09OIiwicGFyc2UiLCJkZWNvZGUiLCJldmFsdWF0ZVRyYW5zYWN0aW9uIiwic3RyaW5naWZ5IiwidW5kZWZpbmVkIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwiciIsIkNvdWNoREJLZXlzIiwiVEFCTEUiLCJQYWdpbmF0b3IiLCJpc1NlcmlhbGl6ZWRQYWdlIiwiZGF0YSIsImQiLCJjcmVhdGUiLCJtb2RlbCIsImRlYnVnIiwicmVjb3JkIiwiaWQiLCJ0cmFuc2llbnQiLCJwcmVwYXJlIiwicmV2ZXJ0IiwidXBkYXRlIiwiY3JlYXRlQWxsUHJlZml4IiwibW9kZWxzIiwiT3BlcmF0aW9uS2V5cyIsIkNSRUFURSIsImdldCIsImlnbm9yZVZhbGlkYXRlIiwibGVuZ3RoIiwiUHJvbWlzZSIsImFsbCIsImFzeW5jIiwibSIsImVuZm9yY2VEQkRlY29yYXRvcnMiLCJPTiIsImlnbm9yZWRQcm9wcyIsImVycm9ycyIsInJlc29sdmUiLCJoYXNFcnJvcnMiLCJlcnJvck1lc3NhZ2VzIiwicmVkdWNlRXJyb3JzVG9QcmludCIsIlZhbGlkYXRpb25FcnJvciIsImNyZWF0ZUFsbCIsInByZXBhcmVkIiwiaWRzIiwicCIsInJlY29yZHMiLCJpIiwidXBkYXRlQWxsIiwidXBkYXRlZCIsInUiLCJFUkMyMFRva2VuIiwiQmFzZU1vZGVsIiwiX19kZWNvcmF0ZSIsInBrIiwidHlwZSIsIlN0cmluZyIsInByb3RvdHlwZSIsImNvbHVtbiIsInJlcXVpcmVkIiwidGFibGUiLCJFUkMyMFdhbGxldCIsIkFsbG93YW5jZSIsIkNsaWVudFNlcmlhbGl6ZXIiLCJKU09OU2VyaWFsaXplciIsInByZVNlcmlhbGl6ZSIsIm1vZGVsTmFtZSIsInRvU2VyaWFsaXplIiwibWV0YWRhdGEiLCJNZXRhZGF0YSIsIlNlcmlhbGl6YXRpb25FcnJvciIsIk1vZGVsS2V5cyIsIkFOQ0hPUiIsImRlc2VyaWFsaXplIiwic3RyIiwiZGVzZXJpYWxpemF0aW9uIiwiY2xhc3NOYW1lIiwiRXJyb3IiLCJidWlsZCIsInNlcmlhbGl6ZSIsIkZhYnJpY0VSQzIwQ2xpZW50UmVwb3NpdG9yeSIsInNlcmlhbGl6ZXIiLCJkZWNvZGVyIiwiVGV4dERlY29kZXIiLCJ1cGRhdGVPYnNlcnZlcnMiLCJldmVudCIsIm9ic2VydmVySGFuZGxlciIsIkludGVybmFsRXJyb3IiLCJjb3VudCIsInBhcnNlZElkIiwiU2VxdWVuY2UiLCJwYXJzZVZhbHVlIiwic2VxdWVuY2VGb3IiLCJ0b2tlbk5hbWUiLCJzeW1ib2wiLCJkZWNpbWFscyIsIk51bWJlciIsInRvdGFsU3VwcGx5IiwidG90YWwiLCJiYWxhbmNlT2YiLCJvd25lciIsImJhbGFuY2UiLCJ0cmFuc2ZlciIsInRvIiwidHJhbnNmZXJyZWQiLCJzdWJtaXRUcmFuc2FjdGlvbiIsInRvU3RyaW5nIiwidHJhbnNmZXJGcm9tIiwiZnJvbSIsImNvbnRleHRBcmdzIiwiQ29udGV4dCIsImFwcHJvdmUiLCJzcGVuZGVyIiwiYXBwcm92ZWQiLCJhbGxvd2FuY2UiLCJpbml0aWFsaXplIiwidG9rZW4iLCJpbml0aWxpYXplZCIsImNoZWNrSW5pdGlhbGl6ZWQiLCJtaW50IiwiYW1vdW50IiwiYnVybiIsImJ1cm5Gcm9tIiwiYWNjb3VudCIsImNsaWVudEFjY291bnRCYWxhbmNlIiwic2VyaWFsaXplZEFjY291bnRCYWxhbmNlIiwiY2xpZW50QWNjb3VudElEIiwiZ2V0SW5kZXhSZWZlcmVuY2UiLCJkaXJlY3Rpb24iLCJjb21wb3NpdGlvbnMiLCJuIiwiam9pbiIsInNwbGl0dGVyIiwiYWRkSW5kZXgiLCJhY2N1bSIsImZpZWxkcyIsInRhYmxlRmllbGQiLCJwb3AiLCJwdXNoIiwidW5zaGlmdCIsImYiLCJyZWR1Y2UiLCJlbCIsImVudHJ5IiwiaW5kZXgiLCJkZG9jIiwiZ2VuZXJhdGVNb2RlbEluZGV4ZXMiLCJpbmRleGVzIiwibW9kZWxJbmRleGVzIiwicHJvcCIsImtleXMiLCJkZWMiLCJlbnRyaWVzIiwiZGlyZWN0aW9ucyIsImZvckVhY2giLCJ2YWx1ZXMiLCJyZWFkTW9kZWxGaWxlIiwiZmlsZSIsInBhdGgiLCJyZXF1aXJlIiwiZXhwb3J0cyIsInByb2Nlc3MiLCJjd2QiLCJwYXJlbnRQYXRoIiwiZmlsdGVyIiwiZSIsInJlYWRNb2RlbEZvbGRlcnMiLCJmb2xkZXJzIiwiZnMiLCJmb2xkZXIiLCJmaWxlcyIsInJlYWRkaXJTeW5jIiwid2l0aEZpbGVUeXBlcyIsInJlY3Vyc2l2ZSIsImlzRmlsZSIsImVuZHNXaXRoIiwid3JpdGVJbmRleGVzIiwiY29sbGVjdGlvbiIsImVuc3VyZURpcmVjdG9yeUV4aXN0ZW5jZSIsImZpbGVQYXRoIiwiZGlybmFtZSIsImV4aXN0c1N5bmMiLCJta2RpclN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwiSWRlbnRpdHlDcmVkZW50aWFscyIsImFyZyIsImRlc2NyaXB0aW9uIiwiRmFicmljTW9kZWxLZXlzIiwiSWRlbnRpdHlUeXBlIiwiRmFicmljRmxhdm91ciIsIklkZW50aXR5IiwiWDUwOSIsIm9uZVRvT25lIiwiQ2FzY2FkZSIsIkNBU0NBREUiLCJkZWxldGUiLCJDb3JlVXRpbHMiLCJsb2dnZXIiLCJNaW5pTG9nZ2VyIiwiY29udGVudE9mTG9hZEZpbGUiLCJjb250ZW50T3JQYXRoIiwiZmlsZVJlYWRlciIsIlVpbnQ4QXJyYXkiLCJtYXRjaCIsInJlYWRGaWxlIiwicHJvbWlzZXMiLCJub3JtYWxpemVJbXBvcnQiLCJpbXBvcnQiLCJnZXRDQVVzZXIiLCJ1c2VyTmFtZSIsInByaXZhdGVLZXkiLCJjZXJ0aWZpY2F0ZSIsIm1zcElkIiwib3B0aW9ucyIsInN0cmluZ0Zvcm1hdCIsInVzZXIiLCJVc2VyIiwiY29uZmlnIiwiaHNtIiwic29mdHdhcmUiLCJsaWIiLCJsaWJyYXJ5Iiwic2xvdCIsImxhYmVsIiwidG9rZW5MYWJlbCIsInBpbiIsImNyeXB0b1N1aXRlIiwiZ2V0Q3J5cHRvU3VpdGUiLCJzZXRDcnlwdG9TdWl0ZSIsImVucm9sbG1lbnRLZXkiLCJnZXRIU01FbnJvbGxtZW50S2V5IiwiZ2V0U29mdHdhcmVFbnJvbGxtZW50S2V5Iiwic2V0RW5yb2xsbWVudCIsIm5ld0NyeXB0b1N1aXRlIiwiY3JlYXRlS2V5RnJvbVJhdyIsInNraSIsImtleUlkSGV4IiwidHJpbSIsIkJ1ZmZlciIsImdldENlcnRpZmljYXRlU0tJIiwiZ2V0S2V5IiwiaXNQcml2YXRlIiwieDUwOSIsIlg1MDlDZXJ0aWZpY2F0ZSIsImp3ayIsInB1YmxpY0tleSIsImV4cG9ydCIsImZvcm1hdCIsInByZWZpeCIsIngiLCJ5IiwiY3J5cHRvIiwiY3JlYXRlSGFzaCIsImNvbmNhdCIsImRpZ2VzdCIsImdldElkZW50aXR5IiwiY2VydERpcmVjdG9yeVBhdGgiLCJpZGVudGl0eUZpbGVSZWFkZXIiLCJjZXJ0UGF0aCIsImdldEZpcnN0RGlyRmlsZU5hbWUiLCJjcmVkZW50aWFscyIsImRpclBhdGgiLCJyZWFkZGlyIiwiZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQiLCJnZXRGaWxlQ29udGVudCIsImdldFNpZ25lciIsImtleURpcmVjdG9yeVBhdGgiLCJzaWduZXJGaWxlUmVhZGVyIiwia2V5UGF0aCIsInByaXZhdGVLZXlQZW0iLCJleHRyYWN0UHJpdmF0ZUtleSIsImdldE93blByb3BlcnR5U3ltYm9scyIsImsiLCJzaWduZXJzIiwibmV3UHJpdmF0ZUtleVNpZ25lciIsInBlbSIsImxpYk5hbWUiLCJzdWJ0bGUiLCJnbG9iYWxUaGlzIiwid2luZG93IiwiQ3J5cHRvIiwid2ViY3J5cHRvIiwic3RyMmFiIiwiYnVmIiwiQXJyYXlCdWZmZXIiLCJidWZWaWV3Iiwic3RyTGVuIiwiY2hhckNvZGVBdCIsInJlcGxhY2UiLCJyZXBsYWNlQWxsIiwiZGVjb2RlZCIsImJpbmFyeURlciIsImltcG9ydEtleSIsIm5hbWVkQ3VydmUiLCJjcnlwdG9Qcm92aWRlciIsInNldCIsIkJBU0VfQUxQSEFCRVQiLCJDUllQVE8iLCJCYXNlRW5jb2RlciIsImFscGhhYmV0IiwiYmFzZU1hcCIsImoiLCJjaGFyQXQiLCJ4YyIsImJhc2UiLCJsZWFkZXIiLCJmYWN0b3IiLCJNYXRoIiwiaUZhY3RvciIsImVuY29kZSIsInNvdXJjZSIsImlzVmlldyIsImJ1ZmZlciIsImJ5dGVPZmZzZXQiLCJieXRlTGVuZ3RoIiwiemVyb2VzIiwicGJlZ2luIiwicGVuZCIsInNpemUiLCJiNTgiLCJjYXJyeSIsIml0MSIsIml0MiIsInJlcGVhdCIsImRlY29kZVVuc2FmZSIsInBzeiIsImIyNTYiLCJpdDMiLCJpdDQiLCJ2Y2giLCJDcnlwdG9VdGlscyIsImI1OGVuY29kZXIiLCJCQVNFNTgiLCJmYWJyaWNJZEZyb21DZXJ0aWZpY2F0ZSIsImNlcnQiLCJzdWJqZWN0IiwiaXNzdWVyIiwic3RyaW5nVG9BcnJheUJ1ZmZlciIsImV4dHJhY3RLZXkiLCJ1c2FnZXMiLCJSZWdFeHAiLCJ0b1VwcGVyQ2FzZSIsImV4dHJhY3RQdWJsaWNLZXkiLCJzaWduIiwiYnVmZiIsImhhc2giLCJiIiwicGFkU3RhcnQiLCJ2ZXJpZnkiLCJzaWduYXR1cmUiLCJlbmNyeXB0IiwiZ2V0U3VidGxlQ3J5cHRvIiwiaXNCcm93c2VyIiwiZGVjcnlwdCIsImdldE1hc3RlciIsInRleHRFbmNvZGVyIiwiVGV4dEVuY29kZXIiLCJnZW5HZW5lc2lzIiwicmFuZG9tVVVJRCIsImltcG9ydGVkS2V5IiwiS0VZX0FMR09SWVRITSIsIml2IiwiZ2V0RGVyaXZhdGlvbktleSIsInNhbHQiLCJzYWx0QnVmZmVyIiwic2FsdEhhc2hlZCIsInBhcmFtcyIsIkhBU0giLCJpdGVyYXRpb25zIiwiSVRFUkFUSU9OUyIsImRlcml2YXRpb24iLCJkZXJpdmVCaXRzIiwiS0VZTEVOR1RIIiwiaXZsZW4iLCJrZXlsZW4iLCJkZXJpdmVkS2V5IiwiaW1wb3J0ZWRFbmNyeXB0aW9uS2V5IiwiQUxHT1JZVEhNIiwiZW5jcnlwdFBpbiIsInRleHQiLCJrZXlPYmplY3QiLCJ0ZXh0QnVmZmVyIiwiZW5jcnlwdGVkVGV4dCIsImRlY3J5cHRQaW4iLCJ0ZXh0RGVjb2RlciIsImRlY3J5cHRlZFRleHQiLCJPdmVyZmxvd0Vycm9yIiwibXNnIiwiQmFsYW5jZUVycm9yIiwiQWxsb3dhbmNlRXJyb3IiLCJSZWdpc3RyYXRpb25FcnJvciIsIkF1dGhvcml6YXRpb25FcnJvciIsIk1pc3NpbmdDb250ZXh0RXJyb3IiLCJVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyIsIkJhc2VFcnJvciIsIk5vdEluaXRpYWxpemVkRXJyb3IiLCJNaXNzaW5nUEtDU1MxMUxpYiIsIkVuZG9yc2VtZW50RXJyb3IiLCJtZXNzYWdlIiwiTXZjY1JlYWRDb25mbGljdEVycm9yIiwiUGhhbnRvbVJlYWRDb25mbGljdEVycm9yIiwiRW5kb3JzZW1lbnRQb2xpY3lFcnJvciIsIkhGQ0FJZGVudGl0eVR5cGUiLCJIRkNBSWRlbnRpdHlBdHRyaWJ1dGVzIiwiRmFicmljRW5yb2xsbWVudFNlcnZpY2UiLCJMb2dnZWRDbGFzcyIsImNhQ29uZmlnIiwiY2FOYW1lIiwiY2FDZXJ0IiwiY2FLZXkiLCJ1cmwiLCJDQSIsImNhIiwidGxzIiwidHJ1c3RlZFJvb3RzIiwicm9vdCIsIkZhYnJpY0NBU2VydmljZXMiLCJDbGllbnQiLCJjbGllbnQiLCJDZXJ0aWZpY2F0ZSIsImNlcnRpZmljYXRlU2VydmljZSIsIm5ld0NlcnRpZmljYXRlU2VydmljZSIsIkFmZmlsaWF0aW9ucyIsImFmZmlsaWF0aW9uU2VydmljZSIsIm5ld0FmZmlsaWF0aW9uU2VydmljZSIsIklkZW50aXRpZXMiLCJpZGVudGl0eVNlcnZpY2UiLCJuZXdJZGVudGl0eVNlcnZpY2UiLCJnZXRDZXJ0aWZpY2F0ZXMiLCJyZXF1ZXN0IiwiZG9NYXAiLCJyZXNwb25zZSIsImNlcnRzIiwiYyIsIlBFTSIsImdldElkZW50aXRpZXMiLCJpZGVudGl0aWVzU2VydmljZSIsImdldEFsbCIsImlkZW50aXRpZXMiLCJwYXJzZUVycm9yIiwicmVnZXhwIiwiZXhlYyIsImNvZGUiLCJDb25mbGljdEVycm9yIiwiZ2V0QWZmaWxpYXRpb25zIiwiYSIsInJlYWQiLCJlbnJvbGxtZW50SWQiLCJnZXRPbmUiLCJOb3RGb3VuZEVycm9yIiwic3VjY2VzcyIsInJlZ2lzdGVyIiwiaXNTdXBlclVzZXIiLCJhZmZpbGlhdGlvbiIsInVzZXJSb2xlIiwiYXR0cnMiLCJtYXhFbnJvbGxtZW50cyIsInJlZ2lzdHJhdGlvbiIsInBhc3N3b3JkIiwicHJvcHMiLCJlbnJvbGxtZW50SUQiLCJlbnJvbGxtZW50U2VjcmV0IiwiaW5mbyIsImlkZW50aXR5RnJvbUVucm9sbG1lbnQiLCJlbnJvbGxtZW50Iiwicm9vdENlcnRpZmljYXRlIiwiTG9nZ2luZyIsImNsaWVudElkIiwibm93IiwiRGF0ZSIsInRvQnl0ZXMiLCJjcmVhdGVkT24iLCJ1cGRhdGVkT24iLCJlbnJvbGwiLCJpZGVudGl0eSIsInJlZ2lzdGVyQW5kRW5yb2xsIiwicmV2b2tlIiwicmVhc29uIiwiUmVnaXN0cmF0aW9uUmVxdWVzdEJ1aWxkZXIiLCJlcnJzIiwicm9sZSIsInNldEFmZmlsaWF0aW9uIiwiYWRkQXR0ciIsImF0dHIiLCJzZXRBdHRycyIsInNldEVucm9sbG1lbnRJRCIsInNldEVucm9sbG1lbnRTZWNyZXQiLCJzZXRNYXhFbnJvbGxtZW50cyIsInNldFJvbGUiLCJtaW5sZW5ndGgiLCJtaW4iLCJFUkMyMEV2ZW50cyIsIkZhYnJpY0Jhc2VNb2RlbCIsImNyZWF0ZWRBdCIsInVwZGF0ZWRBdCIsInZlcnNpb24iLCJ1c2VzIiwiRmFicmljSWRlbnRpZmllZEJhc2VNb2RlbCIsImNyZWF0ZWRCeSIsInVwZGF0ZWRCeSIsImlzU2hhcmVkIiwic2VncmVnYXRlIiwiaXNUcmFuc2llbnQiLCJkZWNvcmF0ZWRQcm9wZXJ0aWVzIiwidmFsaWRhdGFibGVQcm9wZXJ0aWVzIiwidHJhbnNpZW50UHJvcHMiLCJEQktleXMiLCJUUkFOU0lFTlQiLCJwcml2YXRlUHJvcGVydGllcyIsIlBSSVZBVEUiLCJzaGFyZWRQcm9wZXJ0aWVzIiwicHJpdmF0ZSIsInNoYXJlZCIsInRyYW5zaWVudEtleXMiLCJwcml2YXRlS2V5cyIsInNoYXJlZEtleXMiLCJpbmNsdWRlcyIsImJpbmQiLCJTSEFSRUQiLCJtaXJyb3JlZCIsIkZBQlJJQyIsIk1JUlJPUiIsIm93bmVyT2YiLCJtZXRhIiwiT1dORURfQlkiLCJtaXJyb3JlZEF0IiwiY29sbGVjdGlvbnNGb3IiLCJzaGFyZWRLZXkiLCJjb25zdHIiLCJwcml2YXRlTWV0YSIsInNoYXJlZE1ldGEiLCJwcml2YXRlQ29scyIsImNvbGxlY3Rpb25zIiwic2hhcmVkQ29scyIsIk93bmVyIiwidGFyZ2V0IiwicHJvcGVydHlLZXkiLCJkZXNjcmlwdG9yIiwib3JpZ2luYWxNZXRob2QiLCJhY291bnRJZCIsImNsaWVudElkZW50aXR5IiwiZ2V0SUQiLCJzZWxlY3QiLCJ0b2tlbnMiLCJleGVjdXRlIiwiYXBwbHkiLCJvd25lZEJ5T25DcmVhdGUiLCJjb250ZXh0Iiwic3R1YiIsImNyZWF0b3IiLCJnZXRDcmVhdG9yIiwibXNwaWQiLCJzZXRPd25lZEJ5S2V5VmFsdWUiLCJkZWZpbmVQcm9wZXJ0eSIsImVudW1lcmFibGUiLCJ3cml0YWJsZSIsImNvbmZpZ3VyYWJsZSIsIm93bmVkQnkiLCJvYmoiLCJhdHRyaWJ1dGUiLCJyZWFkb25seSIsIm9uQ3JlYXRlIiwicHJvcE1ldGFkYXRhIiwiRGVjb3JhdGlvbiIsImRlZmluZSIsImRlY29yYXRvciIsInRyYW5zYWN0aW9uSWRPbkNyZWF0ZSIsImdldFR4SUQiLCJ0cmFuc2FjdGlvbklkIiwib25VcGRhdGUiLCJUUkFOU0FDVElPTl9JRCIsImV2YWxNaXJyb3JNZXRhZGF0YSIsInJlc29sdmVyIiwiY3JlYXRlTWlycm9ySGFuZGxlciIsInJlcG8iLCJvdmVycmlkZSIsIm1pcnJvciIsInVwZGF0ZU1pcnJvckhhbmRsZXIiLCJkZWxldGVNaXJyb3JIYW5kbGVyIiwiY29uZGl0aW9uIiwicHJpdmF0ZURhdGEiLCJhZnRlckNyZWF0ZSIsInByaW9yaXR5IiwiYWZ0ZXJVcGRhdGUiLCJhZnRlckRlbGV0ZSIsIk1vZGVsQ29sbGVjdGlvbiIsIm9yZ05hbWUiLCJ0b1Bhc2NhbENhc2UiLCJJbXBsaWNpdFByaXZhdGVDb2xsZWN0aW9uIiwic2VncmVnYXRlZERhdGFPbkNyZWF0ZSIsIm1zcCIsImNvbGxlY3Rpb25SZXNvbHZlciIsInJlYnVpbHQiLCJhY2MiLCJVbnN1cHBvcnRlZEVycm9yIiwidG9DcmVhdGUiLCJjcmVhdGVkIiwic2VncmVnYXRlZCIsIm1lcmdlTW9kZWwiLCJzZWdyZWdhdGVkRGF0YU9uUmVhZCIsInNlZ3JlZ2F0ZWREYXRhT25VcGRhdGUiLCJvbGRNb2RlbCIsInNlZ3JlZ2F0ZWREYXRhT25EZWxldGUiLCJpbm5lclNlZ3JlZ2F0ZWQiLCJzZWdyZWdhdGVkRGVjIiwiU2V0IiwiYWRkIiwiY29uc3RyTWV0YSIsImNvbnN0ckNvbGxlY3Rpb25zIiwiZGVjcyIsInByb3BlcnRpZXMiLCJncm91cCIsIm9uUmVhZCIsIm9uRGVsZXRlIiwic2hhcmVkRGF0YSIsIkRldGVybWluaXN0aWNTZXJpYWxpemVyIiwiZXJyb3IiLCJzZWxmIiwibyIsImNhbGwiLCJyZWxhdGlvbnMiLCJzb3J0S2V5c1JlY3Vyc2l2ZSIsImdlbmVyYXRlRmFicmljRXZlbnROYW1lIiwicGFyc2VFdmVudE5hbWUiLCJwYXJ0cyIsInNwbGl0Iiwic3ViIiwic2FmZVBhcnNlSW50Iiwic3RyaW5nIiwiZGlnaXRSZWdleCIsInRlc3QiLCJwYXJzZWRpbnQiLCJwYXJzZUludCIsImlzTmFOIiwiU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIiLCJwdXRBbmNob3IiLCJwcmVTZXJpYWxpemF0aW9uIiwiRmFicmljSWRlbnRpdHlTZXJ2aWNlIiwiQ2xpZW50QmFzZWRTZXJ2aWNlIiwicm9vdENsaWVudCIsIl91c2VyIiwiY2VydGlmaWNhdGVzIiwiYWZmaWxpYXRpb25zIiwiZ2V0VXNlciIsImNmZyIsImdldE5hbWUiLCJEZWZhdWx0RmFicmljQ2xpZW50RmxhZ3MiLCJldmFsdWF0ZVRpbWVvdXQiLCJlbmRvcnNlVGltZW91dCIsInN1Ym1pdFRpbWVvdXQiLCJjb21taXRUaW1lb3V0IiwiRGVmYXVsdEFkYXB0ZXJGbGFncyIsIkhTTVNpZ25lckZhY3RvcnlDdXN0b20iLCJzdGF0aWMiLCJwa2NzMTEiLCJQS0NTMTEiLCJsb2FkIiwiZmluZEhTTVBLQ1MxMUxpYiIsImluaXRpYWxpemVkIiwiQ19Jbml0aWFsaXplIiwiQ0tSX0NSWVBUT0tJX0FMUkVBRFlfSU5JVElBTElaRUQiLCJjb21tb25Tb2Z0SFNNUGF0aE5hbWVzIiwicGF0aG5hbWVUb1RyeSIsImRpc3Bvc2UiLCJDX0ZpbmFsaXplIiwic2FuaXRpemVPcHRpb25zIiwiaHNtU2lnbmVyT3B0aW9ucyIsInVzZXJUeXBlIiwiQ0tVX1VTRVIiLCJhc3NlcnROb3RFbXB0eSIsImlkZW50aWZpZXIiLCJwcm9wZXJ0eSIsImZpbmRTbG90Rm9yTGFiZWwiLCJwa2NzMTFMYWJlbCIsInNsb3RzIiwiQ19HZXRTbG90TGlzdCIsImZpbmQiLCJzbG90VG9DaGVjayIsInRva2VuSW5mbyIsIkNfR2V0VG9rZW5JbmZvIiwibG9naW4iLCJzZXNzaW9uIiwiQ19Mb2dpbiIsImVyciIsInBrY3MxMWVyciIsIkNLUl9VU0VSX0FMUkVBRFlfTE9HR0VEX0lOIiwiZmluZE9iamVjdEluSFNNIiwia2V5dHlwZSIsInBrY3MxMVRlbXBsYXRlIiwiQ0tBX0lEIiwiQ0tBX0NMQVNTIiwiQ0tBX0tFWV9UWVBFIiwiQ0tLX0VDIiwiQ19GaW5kT2JqZWN0c0luaXQiLCJoc21PYmplY3QiLCJDX0ZpbmRPYmplY3RzIiwiQ19GaW5kT2JqZWN0c0ZpbmFsIiwibmV3U2lnbmVyIiwicGtjcyIsIkNfT3BlblNlc3Npb24iLCJDS0ZfU0VSSUFMX1NFU1NJT04iLCJwcml2YXRlS2V5SGFuZGxlIiwiQ0tPX1BSSVZBVEVfS0VZIiwiQ19DbG9zZVNlc3Npb24iLCJzaWduZXIiLCJDX1NpZ25Jbml0IiwibWVjaGFuaXNtIiwiQ0tNX0VDRFNBIiwiY29tcGFjdFNpZ25hdHVyZSIsIkNfU2lnbkFzeW5jIiwiYWxsb2MiLCJwMjU2IiwiUG9pbnQiLCJGbiIsIkJZVEVTIiwiU2lnbmF0dXJlIiwiZnJvbUJ5dGVzIiwibm9ybWFsaXplUyIsImNsb3NlIiwiYXNzZXJ0RGVmaW5lZCIsImdldFVuY29tcHJlc3NlZFBvaW50T25DdXJ2ZSIsImdldFNLSUZyb21DZXJ0aWZpY2F0ZVBhdGgiLCJyZWFkRmlsZVN5bmMiLCJnZXRTS0lGcm9tQ2VydGlmaWNhdGUiLCJ1bmNvbXByZXNzZWRQb2ludCIsIkZhYnJpY0NsaWVudFN0YXRlbWVudCIsIlN0YXRlbWVudCIsIm92ZXJyaWRlcyIsInNxdWFzaCIsInNxdWFzaGVkIiwibWV0aG9kIiwiZXhlY3V0ZVByZXBhcmVkIiwiYXJneiIsImZvck1vZGVsIiwiZnJvbVNlbGVjdG9yIiwiYWxpYXMiLCJRVUVSWSIsImlzU2ltcGxlUXVlcnkiLCJRdWVyeUNsYXVzZSIsIndoZXJlQ29uZGl0aW9uIiwicGFyc2VkIiwicHJlcGFyZUNvbmRpdGlvbiIsInNlbGVjdFNlbGVjdG9yIiwiU0VMRUNUIiwiQU5EIiwidG9Mb3dlckNhc2UiLCJvcmRlckJ5U2VsZWN0b3IiLCJPUkRFUl9CWSIsInRvQ2FtZWxDYXNlIiwicGFyc2VDb25kaXRpb24iLCJGYWJyaWNDbGllbnRQYWdpbmF0b3IiLCJxdWVyeSIsInJhd1N0YXRlbWVudCIsInBhZ2UiLCJGYWJyaWNDbGllbnRBZGFwdGVyIiwiQWRhcHRlciIsImZsYWdzIiwib3BlcmF0aW9uIiwic2lsbHkiLCJ0b092ZXJyaWRlcyIsImFjY3VtdWxhdGUiLCJwYXJlbnRDb250ZXh0IiwiY3VycmVudE9wIiwiY3VycmVudE1vZGVsIiwicmVwb3NpdG9yeSIsImNyZWF0ZVByZWZpeCIsInVwZGF0ZUFsbFByZWZpeCIsInNoaWZ0IiwiQnVsa0NydWRPcGVyYXRpb25LZXlzIiwiQ1JFQVRFX0FMTCIsInJlYWRBbGwiLCJSRUFEX0FMTCIsIlVQREFURV9BTEwiLCJkZWxldGVBbGwiLCJERUxFVEVfQUxMIiwiTUVUQURBVEEiLCJ2YWwiLCJSRUFEIiwidXBkYXRlUHJlZml4IiwiVVBEQVRFIiwiREVMRVRFIiwicmF3IiwicmF3SW5wdXQiLCJkb2NzT25seSIsInRyYW5zYWN0aW9uUmVzdWx0IiwicGFyc2VSZWNvcmQiLCJpc01vZGVsIiwiZ2V0Q2xpZW50IiwiX2NsaWVudCIsIkdhdGV3YXkiLCJnZXRHYXRld2F5IiwiZ2V0Q29udHJhY3ROYW1lIiwiQ29udHJhY3QiLCJjb250cmFjdE5hbWUiLCJnZXRDb250cmFjdCIsInRyYW5zYWN0aW9uIiwiYXBpIiwic3VibWl0IiwidHJhbnNpZW50RGF0YSIsImVuZG9yc2luZ09yZ2FuaXphdGlvbnMiLCJnYXRld2F5IiwiY29udHJhY3QiLCJldmFsdWF0ZSIsInByb3Bvc2FsT3B0aW9ucyIsImFyZ3VtZW50cyIsImRldGFpbHMiLCJuZXR3b3JrIiwiZ2V0TmV0d29yayIsImNoYW5uZWwiLCJjaGFpbmNvZGVOYW1lIiwiY2hhbm5lbE5hbWUiLCJnZXRDb25uZWN0aW9uIiwicGF0aE9yQ2VydCIsInRsc0NlcnQiLCJ0bHNDcmVkZW50aWFscyIsImdycGMiLCJjcmVhdGVTc2wiLCJwZWVyRW5kcG9pbnQiLCJzaXplTGltaXQiLCJjZXJ0Q2VydE9yRGlyZWN0b3J5UGF0aCIsImtleUNlcnRPckRpcmVjdG9yeVBhdGgiLCJwa2NzMTFTaWduZXIiLCJldmFsdWF0ZU9wdGlvbnMiLCJkZWFkbGluZSIsImVuZG9yc2VPcHRpb25zIiwic3VibWl0T3B0aW9ucyIsImNvbW1pdFN0YXR1c09wdGlvbnMiLCJjb25uZWN0IiwiUHJveHkiLCJ0aGlzQXJnIiwiYXJnQXJyYXkiLCJSZWZsZWN0IiwiRGlzcGF0Y2giLCJCYWRSZXF1ZXN0RXJyb3IiLCJRdWVyeUVycm9yIiwiUGFnaW5nRXJyb3IiLCJNaWdyYXRpb25FcnJvciIsIk9ic2VydmVyRXJyb3IiLCJGb3JiaWRkZW5FcnJvciIsIkNvbm5lY3Rpb25FcnJvciIsImZpbmFsIiwiRCIsIl9hIiwiZGVjb3JhdGlvbiIsInNldEN1cnJlbnQiLCJGYWJyaWNDbGllbnREaXNwYXRjaCIsImxpc3RlbmluZ1N0YWNrIiwicGFyc2VQYXlsb2FkIiwianNvbkJ5dGVzIiwianNvbiIsIm9ic2VydmUiLCJvYnNlcnZlciIsInVuT2JzZXJ2ZSIsInJlZnJlc2giLCJoYW5kbGVFdmVudHMiLCJjdHhBcmciLCJjb3JyZWxhdGlvbklkIiwiZXZ0IiwiZXZlbnROYW1lIiwicGF5bG9hZCIsInRhcmdldE1vZGVsIiwibW9kZWxSZWYiLCJnZXRDaGFpbmNvZGVFdmVudHMiLCJWRVJTSU9OIiwiUEFDS0FHRV9OQU1FIiwicmVnaXN0ZXJMaWJyYXJ5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW1ETSxNQUFPQSwrQkFHSEM7SUFVUixXQUFBQyxDQUFZQyxTQUFhQztRQUN2QkMsTUFBTUYsU0FBU0M7UUFWRUUsS0FBVUMsYUFBR0MsT0FBT0MsT0FBTyxDQUFBLEdBQUlKLE1BQU0sZUFBZTtZQUNyRUssa0JBQWtCO1lBQ2xCQyxnQkFBZ0I7WUFDaEJDLG9CQUFvQjtZQUNwQkMsMkJB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
1
+ import{Repository as t,PreparedStatementKeys as e,PersistenceKeys as r,Paginator as i,pk as s,column as n,table as a,BaseModel as o,Sequence as c,Context as l,oneToOne as d,Cascade as h,index as u,normalizeImport as p,AuthorizationError as g,createdAt as f,updatedAt as m,createdBy as y,updatedBy as w,UnsupportedError as b,ClientBasedService as C,Statement as A,QueryClause as v,Adapter as S,QueryError as E,PagingError as x,MigrationError as N,ObserverError as T,ForbiddenError as I,ConnectionError as O,Dispatch as R}from"@decaf-ts/core";import{Model as $,required as k,model as F,JSONSerializer as B,ModelKeys as _,stringFormat as P,minlength as j,min as K}from"@decaf-ts/decorator-validation";import{OperationKeys as L,enforceDBDecorators as z,reduceErrorsToPrint as M,ValidationError as H,SerializationError as U,InternalError as Y,BaseError as G,ConflictError as V,NotFoundError as J,version as q,DBKeys as W,readonly as X,onCreate as Q,onUpdate as Z,afterCreate as tt,afterUpdate as et,afterDelete as rt,transient as it,onRead as st,onDelete as nt,BulkCrudOperationKeys as at,BadRequestError as ot}from"@decaf-ts/db-decorators";import{CouchDBKeys as ct}from"@decaf-ts/for-couchdb";import{__decorate as lt,__metadata as dt}from"tslib";import{Metadata as ht,description as ut,uses as pt,Decoration as gt,apply as ft,propMetadata as mt,metadata as yt,prop as wt}from"@decaf-ts/decoration";import bt from"fabric-ca-client";import{MiniLogger as Ct,isBrowser as At,LoggedClass as vt,Logging as St,toPascalCase as Et,toCamelCase as xt,debug as Nt,final as Tt}from"@decaf-ts/logging";import{signers as It,connect as Ot}from"@hyperledger/fabric-gateway";import{User as Rt}from"fabric-common";import $t,{X509Certificate as kt}from"crypto";import*as Ft from"@peculiar/x509";import{Crypto as Dt}from"@peculiar/webcrypto";import*as Bt from"@grpc/grpc-js";import{Client as _t}from"@grpc/grpc-js";import Pt from"pkcs11js";import jt from"fs";import Kt from"path";import{p256 as Lt}from"@noble/curves/nist";class zt extends t{constructor(t,e){super(t,e),this._overrides=Object.assign({},super._overrides,{ignoreValidation:!0,ignoreHandlers:!0,allowRawStatements:!1,forcePrepareSimpleQueries:!0,forcePrepareComplexQueries:!0,allowGenerationOverride:!1})}async paginateBy(t,r,i={offset:1,limit:10},...s){const{log:n,ctxArgs:a}=(await this.logCtx(s,e.PAGE_BY,!0)).for(this.paginateBy);return n.verbose(`paginating ${$.tableName(this.class)} with page size ${i.limit}`),this.statement(this.paginateBy.name,t,r,{limit:i.limit,offset:i.offset,bookmark:i.bookmark},...a)}async listBy(t,r,...i){const{log:s,ctxArgs:n}=(await this.logCtx(i,e.LIST_BY,!0)).for(this.listBy);return s.verbose(`listing ${$.tableName(this.class)} by ${t} ${r}`),await this.statement(this.listBy.name,t,r,...n)}async findBy(t,r,...i){const{log:s,ctxArgs:n}=(await this.logCtx(i,e.FIND_BY,!0)).for(this.findBy);return s.verbose(`finding all ${$.tableName(this.class)} with ${t} ${r}`),await this.statement(this.findBy.name,t,r,...n)}async findOneBy(t,r,...i){const{log:s,ctxArgs:n}=(await this.logCtx(i,e.FIND_ONE_BY,!0)).for(this.findOneBy);return s.verbose(`finding One ${$.tableName(this.class)} with ${t} ${r}`),await this.statement(this.findOneBy.name,t,r,...n)}async statement(t,...e){const{log:s,ctx:n,ctxArgs:a}=(await this.logCtx(e,r.STATEMENT,!0)).for(this.statement);s.verbose("Executing prepared statement "+t);const o=a.slice(0,-1),c=JSON.parse(this.adapter.decode(await this.adapter.evaluateTransaction(n,r.STATEMENT,[t,JSON.stringify(o)],void 0,void 0,this.class.name)));return Array.isArray(c)?c.map(t=>t[ct.TABLE]&&t[ct.TABLE]===$.tableName(this.class)?new this.class(t):t):c[ct.TABLE]&&c[ct.TABLE]===$.tableName(this.class)?new this.class(c):i.isSerializedPage(c)?Object.assign(c,{data:c.data.map(t=>new this.class(t))}):c}async create(t,...e){const{ctx:r,log:i,ctxArgs:s}=this.logCtx(e,this.create);i.debug(`Creating new ${this.class.name} in table ${$.tableName(this.class)}`);let{record:n,id:a,transient:o}=this.adapter.prepare(t,r);return n=await this.adapter.create(this.class,a,n,o,...s),this.adapter.revert(n,this.class,a,o,r)}async update(t,...e){const{ctxArgs:r,log:i,ctx:s}=this.logCtx(e,this.update);let{record:n,id:a,transient:o}=this.adapter.prepare(t,s);return i.debug(`updating ${this.class.name} in table ${$.tableName(this.class)} with id ${a}`),n=await this.adapter.update(this.class,a,n,o,...r),this.adapter.revert(n,this.class,a,o,s)}async createAllPrefix(t,...e){const{ctx:r,ctxArgs:i}=(await this.logCtx(e,L.CREATE,!0)).for(this.createAllPrefix),s=r.get("ignoreHandlers"),n=r.get("ignoreValidation");if(!t.length)return[t,...i];if(t=await Promise.all(t.map(async t=>(t=new this.class(t),s||await z(this,r,t,L.CREATE,L.ON),t))),!n){const e=r.get("ignoredValidationProperties")||[],i=await Promise.all(t.map(t=>Promise.resolve(t.hasErrors(...e)))),s=M(i);if(s)throw new H(s)}return[t,...i]}async createAll(t,...e){if(!t.length)return t;const{ctx:r,log:i,ctxArgs:s}=this.logCtx(e,this.createAll);i.debug(`Creating ${t.length} new ${this.class.name} in table ${$.tableName(this.class)}`);const n=t.map(t=>this.adapter.prepare(t,r)),a=n.map(t=>t.id);let o=n.map(t=>t.record);const c=n.map(t=>t.transient);return o=await this.adapter.createAll(this.class,a,o,c,...s),o.map((t,e)=>this.adapter.revert(t,this.class,a[e],r.get("rebuildWithTransient")?n[e].transient:void 0,r))}async updateAll(t,...e){const{ctx:r,log:i,ctxArgs:s}=this.logCtx(e,this.updateAll);i.debug(`Updating ${t.length} new ${this.class.name} in table ${$.tableName(this.class)}`);const n=t.map(t=>this.adapter.prepare(t,r));return(await this.adapter.updateAll(this.class,n.map(t=>t.id),n.map(t=>t.record),n.map(t=>t.transient),...s)).map((t,e)=>this.adapter.revert(t,this.class,n[e].id,r.get("rebuildWithTransient")?n[e].transient:void 0,r))}}let Mt=class extends o{constructor(t){super(t)}};lt([s({type:String}),dt("design:type",String)],Mt.prototype,"name",void 0),lt([n(),k(),dt("design:type",String)],Mt.prototype,"owner",void 0),lt([n(),k(),dt("design:type",String)],Mt.prototype,"symbol",void 0),lt([n(),k(),dt("design:type",Number)],Mt.prototype,"decimals",void 0),Mt=lt([a("erc20_tokens"),F(),dt("design:paramtypes",[Object])],Mt);let Ht=class extends o{constructor(t){super(t)}};lt([s({type:String}),dt("design:type",String)],Ht.prototype,"id",void 0),lt([n(),k(),dt("design:type",String)],Ht.prototype,"token",void 0),lt([n(),k(),dt("design:type",Number)],Ht.prototype,"balance",void 0),lt([n(),dt("design:type",String)],Ht.prototype,"captive",void 0),Ht=lt([a("erc20_wallets"),F(),dt("design:paramtypes",[Object])],Ht);let Ut=class extends o{constructor(t){super(t)}};lt([s({type:String}),n(),k(),dt("design:type",String)],Ut.prototype,"owner",void 0),lt([n(),k(),dt("design:type",String)],Ut.prototype,"spender",void 0),lt([n(),k(),dt("design:type",Number)],Ut.prototype,"value",void 0),Ut=lt([a("erc20_allowances"),F(),dt("design:paramtypes",[Object])],Ut);class Yt extends B{constructor(){super()}preSerialize(t,e){const r=Object.assign({},t);let i=ht.modelName(t.constructor);if(!i||"Object"===i){if(!e)throw new U("Could not find metadata for "+t.constructor.name);i=e}return r[_.ANCHOR]=i,r}deserialize(t){const e=JSON.parse(t),r=e[_.ANCHOR];if(!r)throw Error("Could not find class reference in serialized model");return $.build(e,r)}serialize(t,e){return JSON.stringify(this.preSerialize(t,e))}}class Gt extends zt{static{this.serializer=new Yt}static{this.decoder=new TextDecoder("utf8")}async updateObservers(t,e,r,...i){if(!this.observerHandler)throw new Y("ObserverHandler not initialized. Did you register any observables?");const{log:s,ctxArgs:n}=this.logCtx(i,this.updateObservers);let a;s.verbose(`Updating ${this.observerHandler.count()} observers for ${this}`),t="string"==typeof t?$.get(t):t,a=void 0===r?void 0:Array.isArray(r)?r.map(e=>c.parseValue($.sequenceFor(t).type,e)):c.parseValue($.sequenceFor(t).type,r),await this.observerHandler.updateObservers(t,e,a,...n)}decode(t){return Gt.decoder.decode(t)}constructor(t){super(t,Ht),this.serializer=Gt.serializer}async tokenName(...t){const{ctx:e}=(await this.logCtx(t,"tokenName",!0)).for(this.tokenName),r=await this.adapter.evaluateTransaction(e,"TokenName");return this.decode(r)}async symbol(...t){const{ctx:e}=(await this.logCtx(t,"symbol",!0)).for(this.symbol),r=await this.adapter.evaluateTransaction(e,"Symbol");return this.decode(r)}async decimals(...t){const{ctx:e}=(await this.logCtx(t,"decimals",!0)).for(this.decimals),r=await this.adapter.evaluateTransaction(e,"Decimals");return Number(this.decode(r))}async totalSupply(...t){const{ctx:e}=(await this.logCtx(t,"totalSupply",!0)).for(this.totalSupply),r=await this.adapter.evaluateTransaction(e,"TotalSupply");return Number(this.decode(r))}async balanceOf(t,...e){const{ctx:r}=(await this.logCtx(e,"balance",!0)).for(this.balanceOf),i=await this.adapter.evaluateTransaction(r,"BalanceOf",[t]);return Number(this.decode(i))}async transfer(t,e,...r){const{ctx:i}=(await this.logCtx(r,"transfer",!0)).for(this.transfer),s=await this.adapter.submitTransaction(i,"Transfer",[t,e.toString()]);return"true"===this.decode(s)}async transferFrom(t,e,r){const i=await l.args("transferFrom",this.class,[],this.adapter,this._overrides||{}),{ctx:s}=this.logCtx(i.args,this.transferFrom),n=await this.adapter.submitTransaction(s,"TransferFrom",[t,e,r.toString()]);return"true"===this.decode(n)}async approve(t,e){const r=await l.args("approve",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.approve),s=await this.adapter.submitTransaction(i,"Approve",[t,e.toString()]);return"true"===this.decode(s)}async allowance(t,e){const r=await l.args("allowance",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.allowance),s=await this.adapter.submitTransaction(i,"Allowance",[t,e]);return Number(this.decode(s))}async initialize(t){const e=await l.args("initialize",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.initialize),i=await this.adapter.submitTransaction(r,"Initialize",[Gt.serializer.serialize(t)]);return"true"===this.decode(i)}async checkInitialized(){const t=await l.args("checkInitialized",this.class,[],this.adapter,this._overrides||{}),{ctx:e}=this.logCtx(t.args,this.checkInitialized);await this.adapter.evaluateTransaction(e,"CheckInitialized")}async mint(t){const e=await l.args("mint",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.mint);await this.adapter.submitTransaction(r,"Mint",[t.toString()])}async burn(t){const e=await l.args("burn",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.burn);await this.adapter.submitTransaction(r,"Burn",[t.toString()])}async burnFrom(t,e){const r=await l.args("burnFrom",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.burnFrom);await this.adapter.submitTransaction(i,"BurnFrom",[t,e.toString()])}async clientAccountBalance(){const t=await l.args("accountBalance",this.class,[],this.adapter,this._overrides||{}),{ctx:e}=this.logCtx(t.args,this.clientAccountBalance),r=await this.adapter.evaluateTransaction(e,"ClientAccountBalance");return Number(this.decode(r))}async clientAccountID(){const t=await l.args("accountId",this.class,[],this.adapter,this._overrides||{}),{ctx:e}=this.logCtx(t.args,this.clientAccountID),r=await this.adapter.evaluateTransaction(e,"ClientAccountID");return this.decode(r)}}function Vt(t,e,r){return[...t.map(t=>t===ct.TABLE?"table":t),...r||[],...e?[e]:[],"index"].join(ht.splitter)}function Jt(t,e,r,i){const s=e.pop();s&&s!==ct.TABLE?e.push(s):s===ct.TABLE&&e.unshift(s);const n=Vt(e,r,i);let a=[...e,...i||[]];r&&(a=a.reduce((t,e)=>{const i={};return i[e]=r,t.push(i),t},[]));const o={index:{fields:a},name:n,ddoc:n,type:"json"};t[n]=o}function qt(t,e){const r=Vt([ct.TABLE]),i=e||{};i[r]={index:{fields:[ct.TABLE]},name:r,ddoc:r,type:"json"};const s={},n=$.indexes(t);for(const t of Object.keys(n))for(const[,e]of Object.entries(n[t])){const r=e.directions,i=e.compositions,n=[t,ct.TABLE];Jt(s,n),i&&i.length&&Jt(s,n,void 0,i),r&&r.length&&r.forEach(t=>{Jt(s,n,t),i&&i.length&&Jt(s,n,t,i)})}return Object.entries(s).forEach(([t,e])=>{i[t]=e}),Object.values(s)}function Wt(t){const e=require("path"),r=require(e.join(process.cwd(),t.parentPath,t.name));return Object.values(r).filter(t=>{try{return new t instanceof $}catch(t){return!1}})}async function Xt(...t){const e=require("fs"),r=[];for(const i of t){const t=e.readdirSync(i,{withFileTypes:!0,recursive:!0}).filter(t=>t.isFile()&&t.name.endsWith("js"));for(const e of t)r.push(...Wt(e))}return r}function Qt(t,e=process.cwd(),r){const i=require("fs"),s=require("path");function n(t){const e=s.dirname(t);if(i.existsSync(e))return!0;n(e),i.mkdirSync(e)}t.forEach(t=>{const a=s.resolve(s.join(e,`./META-INF/statedb/couchdb/${r?`collections/${r}/`:""}indexes/${t.name}.json`));n(a),i.writeFileSync(a,JSON.stringify(t,void 0,2))})}let Zt=class extends o{constructor(t){super(t)}};var te,ee;lt([ut("Unique identifier of the credentials record"),n(),s(),dt("design:type",String)],Zt.prototype,"id",void 0),lt([ut("PEM-encoded X.509 certificate for the identity"),n(),k(),dt("design:type",String)],Zt.prototype,"certificate",void 0),lt([ut("PEM-encoded root or intermediate certificate"),n(),k(),dt("design:type",String)],Zt.prototype,"rootCertificate",void 0),lt([ut("PEM-encoded private key"),n(),k(),dt("design:type",String)],Zt.prototype,"privateKey",void 0),Zt=lt([F(),dt("design:paramtypes",[Object])],Zt),(t=>{t.PRIVATE="private",t.SHARED="shared",t.FABRIC="fabric",t.OWNED_BY="owned-by",t.TRANSACTION_ID="transaction-id",t.MIRROR="mirror"})(te||(te={})),(t=>{t.X509="X.509"})(ee||(ee={}));const re="hlf-fabric";let ie=class extends o{constructor(t){super(t),this.type=ee.X509}};lt([ut("Unique identifier of the identity"),s(),dt("design:type",String)],ie.prototype,"id",void 0),lt([d(Zt,{update:h.CASCADE,delete:h.CASCADE}),dt("design:type",Zt)],ie.prototype,"credentials",void 0),lt([n(),k(),u(),dt("design:type",String)],ie.prototype,"mspId",void 0),lt([n(),k(),dt("design:type",String)],ie.prototype,"type",void 0),ie=lt([F(),dt("design:paramtypes",[Object])],ie);class se{static{this.logger=new Ct(se.name)}constructor(){}static async contentOfLoadFile(t,e){return t instanceof Uint8Array||t.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)?t:await e(t)}static async readFile(t){return"string"!=typeof t?t:await(async t=>{const{promises:e}=await p(import("fs"));return await e.readFile(t)})(t)}static async getCAUser(t,e,r,i,s){this.logger.debug(P("Creating CA {0} user {1} with certificate {2}",i,t,r));const n=new Rt(t),a=s?.hsm?{software:!1,lib:s.hsm.library,slot:s.hsm.slot,label:s.hsm.tokenLabel,pin:s.hsm.pin+""}:void 0,o=this.getCryptoSuite(a);n.setCryptoSuite(o);const c=s?.hsm?await this.getHSMEnrollmentKey(o,r,s.hsm):this.getSoftwareEnrollmentKey(o,e);return await n.setEnrollment(c,r,i),n}static getCryptoSuite(t){return t?(se.cryptoSuite||(se.cryptoSuite=Rt.newCryptoSuite(t)),se.cryptoSuite):Rt.newCryptoSuite()}static getSoftwareEnrollmentKey(t,e){if(!e)throw Error("Private key must be provided when HSM configuration is not supplied");return t.createKeyFromRaw(e)}static async getHSMEnrollmentKey(t,e,r){const i=r.keyIdHex&&r.keyIdHex.trim().length>0?Buffer.from(r.keyIdHex,"hex"):await this.getCertificateSKI(e),s=await t.getKey(i);if(!s||"function"==typeof s.isPrivate&&!s.isPrivate())throw Error("Unable to resolve private key from HSM");return s}static async getCertificateSKI(t){const e=new kt(t).publicKey.export({format:"jwk"}),r=Buffer.from([4]),i=Buffer.from(e.x||"","base64url"),s=Buffer.from(e.y||"","base64url");return $t.createHash("sha256").update(Buffer.concat([r,i,s])).digest()}static async getIdentity(t,e){const r=await this.contentOfLoadFile(e,async t=>{const{promises:e}=await p(import("fs")),r=await this.getFirstDirFileName(t);return await e.readFile(r)});return{mspId:t,credentials:r}}static async getFirstDirFileName(t){const{promises:e}=await p(import("fs")),{join:r}=await p(import("path"));return r(t,(await e.readdir(t))[0])}static async getFirstDirFileNameContent(t){const{promises:e}=await p(import("fs")),{join:r}=await p(import("path")),i=await e.readdir(t);return(await e.readFile(r(t,i[0]))).toString()}static async getFileContent(t){const{promises:e}=await p(import("fs"));return(await e.readFile(t)).toString()}static async getSigner(t){const e=await this.contentOfLoadFile(t,async t=>{const{promises:e}=await p(import("fs")),r=await this.getFirstDirFileName(t);return await e.readFile(r)}),r=await this.extractPrivateKey(e),i=r[Object.getOwnPropertySymbols(r)[0]];return It.newPrivateKeySigner(i)}static async extractPrivateKey(t){let e;if(globalThis.window&&globalThis.window.Crypto)e=globalThis.Crypto.subtle;else{const t=await p(import("crypto"));e=t.subtle||t.webcrypto.subtle}if(!e)throw Error("Could not load SubtleCrypto module");const r=t.toString("utf8").replace("-----BEGIN PRIVATE KEY-----","").replaceAll("\n","").replace("-----END PRIVATE KEY-----",""),i=(t=>{const e=new ArrayBuffer(t.length),r=new Uint8Array(e);for(let e=0,i=t.length;i>e;e++)r[e]=t.charCodeAt(e);return e})(Buffer.from(r,"base64").toString("binary"));return await e.importKey("pkcs8",i,{name:"ECDSA",namedCurve:"P-256"},!0,["sign"])}}const ne=new Dt;var ae,oe,ce,le,de;Ft.cryptoProvider.set(ne),(t=>{t.BASE2="01",t.BASE8="01234567",t.BASE11="0123456789a",t.BASE16="0123456789abcdef",t.BASE32="0123456789ABCDEFGHJKMNPQRSTVWXYZ",t.BASE32_Z="ybndrfg8ejkmcpqxot1uwisza345h769",t.BASE36="0123456789abcdefghijklmnopqrstuvwxyz",t.BASE58="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",t.BASE62="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",t.BASE64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t.BASE67="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~"})(ae||(ae={})),(t=>{t.HASH="SHA-256",t[t.ITERATIONS=1e3]="ITERATIONS",t[t.KEYLENGTH=48]="KEYLENGTH",t[t.DERIVED_IV_LENGTH=16]="DERIVED_IV_LENGTH",t[t.DERIVED_KEY_LENGTH=32]="DERIVED_KEY_LENGTH",t.ALGORYTHM="AES-GCM",t.KEY_ALGORYTHM="PBKDF2"})(oe||(oe={}));class he{constructor(t){if(this.alphabet=t,this.baseMap=new Uint8Array(256),this.alphabet.length>=255)throw Error("Alphabet too long");for(let t=0;t<this.baseMap.length;t++)this.baseMap[t]=255;for(let e=0;e<t.length;e++){const r=t.charAt(e),i=r.charCodeAt(0);if(255!==this.baseMap[i])throw Error(r+" is ambiguous");this.baseMap[i]=e}this.base=this.alphabet.length,this.leader=this.alphabet.charAt(0),this.factor=Math.log(this.base)/Math.log(256),this.iFactor=Math.log(256)/Math.log(this.base)}encode(t){if("string"==typeof t?t=Buffer.from(t):ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t)),0===t.length)return"";let e=0,r=0,i=0;const s=t.length;for(;i!==s&&0===t[i];)i++,e++;const n=(s-i)*this.iFactor+1>>>0,a=new Uint8Array(n);for(;i!==s;){let e=t[i],s=0;for(let t=n-1;(0!==e||r>s)&&-1!==t;t--,s++)e+=256*a[t]>>>0,a[t]=e%this.base>>>0,e=e/this.base>>>0;if(0!==e)throw Error("Non-zero carry");r=s,i++}let o=n-r;for(;o!==n&&0===a[o];)o++;let c=this.leader.repeat(e);for(;n>o;++o)c+=this.alphabet.charAt(a[o]);return c}decodeUnsafe(t){if(0===t.length)return new Uint8Array(0);let e=0,r=0,i=0;for(;t[e]===this.leader;)r++,e++;const s=(t.length-e)*this.factor+1>>>0,n=new Uint8Array(s);for(;t[e];){let r=this.baseMap[t.charCodeAt(e)];if(255===r)return;let a=0;for(let t=s-1;(0!==r||i>a)&&-1!==t;t--,a++)r+=this.base*n[t]>>>0,n[t]=r%256>>>0,r=r/256>>>0;if(0!==r)throw Error("Non-zero carry");i=a,e++}let a=s-i;for(;a!==s&&0===n[a];)a++;const o=new Uint8Array(r+(s-a));let c=r;for(;a!==s;)o[c++]=n[a++];return o}decode(t){const e=this.decodeUnsafe(t);if(e)return e;throw Error("Non-base"+this.base+" character")}}class ue{static{this.b58encoder=new he(ae.BASE58)}static{this.logger=new Ct(ue.name)}constructor(){}static fabricIdFromCertificate(t){this.logger.debug(P("Parsing certificate: {0}",t));const e=new Ft.X509Certificate(t),{subject:r,issuer:i}=e;return this.logger.debug(P("Certificate parsed with subject {0} and issuer {1}",r,i)),`x509::/${r.replaceAll(", ","/")}::/${i.replaceAll(", ","/")}`}static encode(t){return this.b58encoder.encode(t)}static decode(t){const e=this.b58encoder.decode(t);return(new TextDecoder).decode(e)}static stringToArrayBuffer(t){const e=new ArrayBuffer(t.length),r=new Uint8Array(e);for(let e=0,i=t.length;i>e;e++)r[e]=t.charCodeAt(e);return e}static async extractKey(t,e,r){const i=ne.subtle,s=e.toString("utf8").replace(RegExp(`-----BEGIN (${t.toUpperCase()} KEY|CERTIFICATE)-----`),"").replaceAll("\n","").replace(RegExp(`-----END (${t.toUpperCase()} KEY|CERTIFICATE)-----`),""),n=Buffer.from(s,"base64").toString("binary"),a=this.stringToArrayBuffer(n);return await i.importKey("pkcs8",a,{name:"ECDSA",namedCurve:"P-256"},!0,r||["sign"])}static async extractPrivateKey(t,e){return this.extractKey("private",t,e)}static async extractPublicKey(t,e){return this.extractKey("public",t,e)}static async sign(t,e){const r=await this.extractPrivateKey(t),i=await ne.subtle.sign({name:"ECDSA",hash:"SHA-256"},r,e);return Array.from(new Uint8Array(i)).map(t=>t.toString(16).padStart(2,"0")).join("")}static async verify(t,e,r){const i=new Ft.X509Certificate(t),s=await i.publicKey.export();return e="string"==typeof e?Buffer.from(e,"hex"):e,r="string"==typeof r?Buffer.from(r):r,ne.subtle.verify({name:"ECDSA",hash:"SHA-256"},s,e,r)}static async encrypt(t,e){const r=new Ft.X509Certificate(t),i=await r.publicKey.export();e="string"==typeof e?Buffer.from(e):e;const s=await this.getSubtleCrypto().encrypt({name:"ECDSA"},i,e);return Array.from(new Uint8Array(s)).map(t=>t.toString(16).padStart(2,"0")).join("")}static getSubtleCrypto(){return At()?globalThis.window.crypto.subtle:ne.subtle}static async decrypt(t,e){const r=await this.extractPrivateKey(t);return e="string"==typeof e?Buffer.from(e,"hex"):e,this.getSubtleCrypto().decrypt({name:"ECDSA"},r,e)}static async getMaster(t){const e=new TextEncoder;if(void 0===t){const r=ne.randomUUID();t=e.encode(r).buffer}return{key:await this.getSubtleCrypto().importKey("raw",t,oe.KEY_ALGORYTHM,!1,["deriveBits"]),iv:t}}static async getDerivationKey(t,e){const r=(new TextEncoder).encode(t),i=await this.getSubtleCrypto().digest("SHA-256",r),s={name:oe.KEY_ALGORYTHM,hash:oe.HASH,salt:i,iterations:oe.ITERATIONS},n=await this.getSubtleCrypto().deriveBits(s,e,8*oe.KEYLENGTH);return this.getKey(n)}static async getKey(t){const e=t.slice(0,32),r=t.slice(32);return{key:await this.getSubtleCrypto().importKey("raw",e,{name:oe.ALGORYTHM},!1,["encrypt","decrypt"]),iv:r}}static async encryptPin(t,e){const r=(new TextEncoder).encode(t);return await this.getSubtleCrypto().encrypt({name:oe.ALGORYTHM,iv:e.iv},e.key,r)}static async decryptPin(t,e){const r=new TextDecoder,i=await this.getSubtleCrypto().decrypt({name:oe.ALGORYTHM,iv:e.iv},e.key,t);return r.decode(i)}}class pe extends Y{constructor(t){super(t,pe.name)}}class ge extends Y{constructor(t){super(t,ge.name)}}class fe extends Y{constructor(t){super(t,fe.name)}}class me extends g{constructor(t){super(t,me.name)}}class ye extends Y{constructor(t){super(t,ye.name,500)}}class we extends G{constructor(t="MISSING_PRIVATE_DATA_ERROR_MESSAGE"){super(we.name,t,403)}}class be extends G{constructor(t){super(be.name,t,409)}}class Ce extends Y{constructor(t){super(t,Ce.name,500)}}class Ae extends Y{constructor(t){super(t,Ae.name,500)}}class ve extends Y{constructor(t){super(t,ve.name,500)}}class Se extends Y{constructor(t){super(t,Se.name,500)}}class Ee extends Y{constructor(t){super(t,Ee.name,500)}}(t=>{t.PEER="peer",t.ORDERER="orderer",t.CLIENT="client",t.USER="user",t.ADMIN="admin"})(ce||(ce={})),(t=>{t.HFREGISTRARROLES="hf.Registrar.Roles",t.HFREGISTRARDELEGATEROLES="hf.Registrar.DelegateRoles",t.HFREGISTRARATTRIBUTES="hf.Registrar.Attributes",t.HFINTERMEDIATECA="hf.IntermediateCA",t.HFREVOKER="hf.Revoker",t.HFAFFILIATIONMGR="hf.AffiliationMgr",t.HFGENCRL="hf.GenCRL"})(le||(le={}));class xe extends vt{constructor(t){se.getCryptoSuite(t.hsm?{software:!1,lib:t.hsm.library,slot:t.hsm.slot,label:t.hsm.tokenLabel,pin:t.hsm.pin+""}:void 0),super(),this.caConfig=t}async User(){if(this.user)return this.user;const{caName:t,caCert:e,caKey:r,url:i,hsm:s}=this.caConfig,n=this.log.for(this.User);n.debug(`Creating CA user for ${t} at ${i}`),n.debug("Retrieving CA certificate from "+e);const a=await se.getFirstDirFileNameContent(e);let o;if(s)n.debug(`Using HSM configuration for CA ${t} with library ${s.library}`);else{if(!r)throw new Y(`Missing caKey configuration for CA ${t}. Provide a key directory or configure HSM support.`);n.debug("Retrieving CA key from "+r),o=await se.getFirstDirFileNameContent(r)}return n.debug("Loading Admin user for ca "+t),this.user=await se.getCAUser("admin",o,a,t,{hsm:s}),this.user}async CA(){if(this.ca)return this.ca;const t=this.log.for(this.CA),{url:e,tls:r,caName:i}=this.caConfig;let{trustedRoots:s,verify:n}=r;const a=s[0];t.debug(`Retrieving CA certificate from ${a}. cwd: ${process.cwd()}`);const o=await se.getFileContent(a);return t.debug(`Creating CA Client for CA ${i} under ${e}`),this.ca=new bt(e,{trustedRoots:Buffer.from(o),verify:n},i),this.ca}async Client(){if(this.client)return this.client;const t=await this.CA();return this.client=t._FabricCAServices,this.client}async Certificate(){return this.certificateService||(this.certificateService=(await this.Client()).newCertificateService()),this.certificateService}async Affiliations(){return this.affiliationService||(this.affiliationService=(await this.CA()).newAffiliationService()),this.affiliationService}async Identities(){return this.identityService||(this.identityService=(await this.CA()).newIdentityService()),this.identityService}async getCertificates(t,e=!0){const r=await this.Certificate(),i=await this.User(),s=this.log.for(this.getCertificates);s.debug(`Retrieving certificates${t?" for "+t.id:""} for CA ${this.caConfig.caName}`);const n=(await r.getCertificates(t||{},i)).result;return s.debug(`Found ${n.certs.length} certificates: ${JSON.stringify(n)}`),e?n.certs.map(t=>t.PEM):n}async getIdentities(){const t=await this.Identities(),e=this.log.for(this.getIdentities);e.debug("Retrieving Identities under CA "+this.caConfig.caName);const r=(await t.getAll(await this.User())).result;return e.debug(`Found ${r.identities.length} Identities: ${JSON.stringify(r)}`),r.identities}parseError(t){const e=/.*code:\s(\d+).*?message:\s["'](.+)["']/gs.exec(t.message);if(!e)return new me(t);const[,r,i]=e;switch(r){case"74":case"71":return new V(i);case"20":return new g(i);default:return new me(i)}}async getAffiliations(){const t=await this.Affiliations(),e=this.log.for(this.getAffiliations);e.debug("Retrieving Affiliations under CA "+this.caConfig.caName);const r=(await t.getAll(await this.User())).result;return e.debug(`Found ${r.a.length} Affiliations: ${JSON.stringify(r)}`),r}async read(t){const e=await this.CA(),r=await this.User();let i;try{i=await e.newIdentityService().getOne(t,r)}catch(e){throw new J(`Couldn't find enrollment with id ${t}: ${e}`)}if(!i.success)throw new J(`Couldn't find enrollment with id ${t}: ${i.errors.join("\n")}`);return i.result}async register(t,e=!1,r="",i,s,n){let a;const o=this.log.for(this.register);try{const{userName:c,password:l}=t,d=await this.CA(),h=await this.User(),u={enrollmentID:c,enrollmentSecret:l,affiliation:r,userRole:i,attrs:s,maxEnrollments:n};a=await d.register(u,h),o.info(`Registration for ${c} created with user type ${i??"Undefined Role"} ${e?"as super user":""}`)}catch(t){throw this.parseError(t)}return a}static identityFromEnrollment(t,e){const{certificate:r,key:i,rootCertificate:s}=t,n=St.for(xe,{}).for(this.identityFromEnrollment);n.debug(`Generating Identity from certificate ${r} in msp ${e}`);const a=ue.fabricIdFromCertificate(r),o=ue.encode(a);n.debug(`Identity ${a} and encodedId ${o}`);const c=new Date;return new ie({id:o,credentials:{id:o,certificate:r,privateKey:i.toBytes(),rootCertificate:s,createdOn:c,updatedOn:c},mspId:e,createdOn:c,updatedOn:c})}async enroll(t,e){let r;const i=this.log.for(this.enroll);try{const s=await this.CA();i.debug("Enrolling "+t);const n=await s.enroll({enrollmentID:t,enrollmentSecret:e});r=xe.identityFromEnrollment(n,this.caConfig.caName),i.info(`Successfully enrolled ${t} under ${this.caConfig.caName} as ${r.id}`)}catch(t){throw this.parseError(t)}return r}async registerAndEnroll(t,e=!1,r="",i,s,n){const a=await this.register(t,e,r,i,s,n),{userName:o}=t;return this.enroll(o,a)}async revoke(t){const e=await this.CA(),r=await this.User(),i=await this.read(t);if(!i)throw new J("Could not find enrollment with id "+t);let s;try{s=await e.revoke({enrollmentID:i.id,reason:"User Deletation"},r)}catch(e){throw new Y(`Could not revoke enrollment with id ${t}: ${e}`)}if(!s.success)throw new Y(`Could not revoke enrollment with id ${t}: ${s.errors.join("\n")}`);return s}}class Ne extends ${constructor(){super(...arguments),this.affiliation=""}build(){const t=this.hasErrors();if(t)throw new H(t.toString());const e={enrollmentID:this.enrollmentID,enrollmentSecret:this.enrollmentSecret,role:this.role,affiliation:this.affiliation};return void 0!==this.maxEnrollments&&(e.maxEnrollments=this.maxEnrollments),this.attrs&&(e.attrs=this.attrs),e}setAffiliation(t){return this.affiliation=t,this}addAttr(t){return this.attrs=this.attrs||[],this.attrs.push(t),this}setAttrs(t){return this.attrs=t,this}setEnrollmentID(t){return this.enrollmentID=t,this}setEnrollmentSecret(t){return this.enrollmentSecret=t,this}setMaxEnrollments(t){return this.maxEnrollments=t,this}setRole(t){return this.role=t,this}}lt([k(),dt("design:type",String)],Ne.prototype,"affiliation",void 0),lt([j(1),dt("design:type",Array)],Ne.prototype,"attrs",void 0),lt([k(),dt("design:type",String)],Ne.prototype,"enrollmentID",void 0),lt([k(),dt("design:type",String)],Ne.prototype,"enrollmentSecret",void 0),lt([K(0),dt("design:type",Number)],Ne.prototype,"maxEnrollments",void 0),lt([k(),dt("design:type",String)],Ne.prototype,"role",void 0),(t=>{t.TRANSFER="Transfer",t.APPROVAL="Approval"})(de||(de={}));let Te=class extends ${constructor(t){super(t)}};lt([ut("Stores the original timestamp of creation"),n(),f(),dt("design:type",Date)],Te.prototype,"createdAt",void 0),lt([ut("Stores the timestamp of the last update"),n(),m(),dt("design:type",Date)],Te.prototype,"updatedAt",void 0),lt([ut("Stores the version of the model"),n(),q(),dt("design:type",Number)],Te.prototype,"version",void 0),Te=lt([pt(re),dt("design:paramtypes",[Object])],Te);let Ie=class extends Te{constructor(t){super(t)}};function Oe(){return function(t,e,r){const i=r.value;return r.value=async function(...t){const r=t[0],s=r.clientIdentity.getID(),n=await this.tokenRepository.select(),a=await n.execute(r);if(0==a.length)throw new J("No tokens avaialble");if(a.length>1)throw new J("To many token available : "+a.length);if(a[0].owner!=s)throw new g(`User not authorized to run ${e} on the token`);return await i.apply(this,t)},r}}async function Re(t,e,r,i){const{stub:s}=t,n=(await s.getCreator()).mspid;Object.defineProperty(i,r,{enumerable:!0,writable:!1,configurable:!0,value:n})}function $e(){return gt.for(te.OWNED_BY).define({decorator:()=>(t,e)=>ft(k(),X(),Q(Re),mt(ht.key(te.FABRIC,te.OWNED_BY),e))(t,e),args:[]}).apply()}async function ke(t,e,r,i){const{stub:s}=t;i[r]=s.getTxID()}function Fe(){return gt.for(te.TRANSACTION_ID).define({decorator:()=>(t,e)=>ft(k(),X(),Q(ke),Z(ke),mt(ht.key(te.FABRIC,e,te.TRANSACTION_ID),e))(t,e),args:[]}).apply()}async function De(t,e,r){let i=e;if("string"!=typeof i)try{const s=$.ownerOf(t)||r.get("stub").getCreator().toString();e&&"function"==typeof e&&(i=await e(t,s,r))}catch(t){throw new Y("Failed to resolve collection mirror name: "+t)}if(!i||"string"!=typeof i)throw new Y("No collection found model "+t.constructor.name);return i}async function Be(t,e,r,i){const s=await De(i,e.resolver,t),n=this.override(Object.assign({},this._overrides,{segregate:s,ignoreValidation:!0,ignoreHandlers:!0})),a=await n.create(i,t);t.logger.info(`Mirror for ${$.tableName(this.class)} created with ${$.pk(i)}: ${a[$.pk(i)]}`)}async function _e(t,e,r,i){const s=await De(i,e.resolver,t),n=this.override(Object.assign({},this._overrides,{segregate:s,ignoreValidation:!0,ignoreHandlers:!0})),a=await n.update(i,t);t.logger.info(`Mirror for ${$.tableName(this.class)} updated with ${$.pk(i)}: ${a[$.pk(i)]}`)}async function Pe(t,e,r,i){const s=await De(i,e.resolver,t),n=this.override(Object.assign({},this._overrides,{segregate:s,ignoreValidation:!0,ignoreHandlers:!0})),a=await n.delete($.pk(i),t);t.logger.info(`Mirror for ${$.tableName(this.class)} deleted with ${$.pk(i)}: ${a[$.pk(i)]}`)}function je(t,e){return gt.for(te.MIRROR).define({decorator:(e,r)=>{const i={condition:r,resolver:e};return ft(yt(ht.key(te.FABRIC,te.MIRROR),i),Ge(t),tt(Be,i,{priority:95}),et(_e,i,{priority:95}),rt(Pe,i,{priority:95}))},args:[t,e]}).apply()}lt([ut("Stores the creator"),n(),y(),dt("design:type",String)],Ie.prototype,"createdBy",void 0),lt([ut("Stores the user that last updated the model"),n(),w(),dt("design:type",String)],Ie.prototype,"updatedBy",void 0),Ie=lt([pt(re),dt("design:paramtypes",[Object])],Ie),$.prototype.isShared=function(){return $.isShared(this.constructor)},$.prototype.isPrivate=function(){return $.isPrivate(this.constructor)},$.prototype.segregate=function(){return $.segregate(this)},$.segregate=(t=>{if(!$.isTransient(t))return{model:t};const e=ht.validatableProperties(t.constructor),r=ht.get(t.constructor,W.TRANSIENT),i=ht.get(t.constructor,te.PRIVATE),s=ht.get(t.constructor,te.PRIVATE),n={model:{},transient:{},private:{},shared:{}},a=Object.keys(r),o=Object.keys(i),c=Object.keys(s);for(const r of e){const e=a.includes(r),i=o.includes(r),s=c.includes(r);e?(n.transient=n.transient||{},n.transient[r]=t[r],i&&(n.private=n.private||{},n.private[r]=t[r]),s&&(n.shared=n.shared||{},n.shared[r]=t[r])):(n.model=n.model||{},n.model[r]=t[r])}return n.model=$.build(n.model,t.constructor.name),n}).bind($),$.isPrivate=(t=>!!ht.get("function"!=typeof t?t.constructor:t,te.PRIVATE)).bind($),$.isShared=(t=>!!ht.get("function"!=typeof t?t.constructor:t,te.SHARED)).bind($),$.mirrored=(t=>ht.get("function"!=typeof t?t.constructor:t,ht.key(te.FABRIC,te.MIRROR))).bind($),$.ownerOf=(t=>{const e=ht.get(t.constructor,ht.key(te.FABRIC,te.OWNED_BY));if(e)return t[e]}).bind($),$.mirroredAt=(t=>(t="function"!=typeof t?t.constructor:t,ht.get(t,ht.key(te.FABRIC,te.MIRROR)))).bind($),$.collectionsFor=(t=>{const e=[te.PRIVATE],r=[te.SHARED],i=ht.key(...e),s=ht.key(...r),n="function"==typeof t?t:t.constructor,a=ht.get(n,i),o=ht.get(n,s);return{privateCols:a?.collections||[],sharedCols:o?.collections||[]}}).bind($);const Ke=(t,e)=>{const r=e||("function"!=typeof t?$.ownerOf(t):void 0),i="function"==typeof t?t:t.constructor;if(!r)throw new Y(`Model ${i.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);return`${Et(i.name)}${e?Et(e):""}`},Le=(t,e)=>{const r=e||("function"!=typeof t?$.ownerOf(t):void 0);if(!r)throw new Y(`Model ${t.constructor.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);return`__${Et(r)}PrivateCollection`};async function ze(t,e,r,i){if(r.length!==e.length)throw new Y("Segregated data keys and metadata length mismatch");const s=$.ownerOf(i);if(!s)throw new H("There's no assigned organization for model "+i.constructor.name);const n=e[0].collections,a="string"==typeof n?n:n(i,s,t),o=r.reduce((r,n,o)=>{const c="string"==typeof e[o].collections?e[o].collections:e[o].collections(i,s,t);if(c!==a)throw new b(`Segregated data collection mismatch: ${c} vs ${a}`);return r[n]=i[n],r},{}),c=new this.class(o),l=await this.override({segregated:a,mergeModel:!1,ignoreHandlers:!0,ignoreValidation:!0}).create(c,t);Object.assign(i,l)}async function Me(t,e,r,i){if(r.length!==e.length)throw new Y("Segregated data keys and metadata length mismatch");const s=$.ownerOf(i);if(!s)throw new H("There's no assigned organization for model "+i.constructor.name);const n=e[0].collections,a="string"==typeof n?n:await n(i,s,t);r.reduce((r,n,o)=>(("string"==typeof e[o].collections?e[o].collections:e[o].collections(i,s,t))!==a||(r[n]=i[n]),r),{})}async function He(t,e,r,i,s){}async function Ue(t,e,r,i){}function Ye(t,e,r){return(i,s)=>{const n=[];return s?n.push(wt(),it(),(r,i)=>{const s=ht.key(e,i),n=r.constructor,a=ht.get(n,s)||{},o=new Set(a.collections||[]);o.add(t),a.collections=[...o],ht.set(n,s,a);const c=ht.get(n,e)||{};new Set(c.collections||[]).add(t),a.collections=[...o],ht.set(n,e,a)},Q(ze,{collections:t},{priority:95,group:"string"==typeof t?t:t.toString()}),st(Me,{collections:t},{priority:95,group:"string"==typeof t?t:t.toString()}),Z(He,{collections:t},{priority:95,group:"string"==typeof t?t:t.toString()}),nt(Ue,{collections:t},{priority:95,group:"string"==typeof t?t:t.toString()})):ht.properties(i)?.forEach(s=>{r&&!r(s)||Ye(t,e)(i.prototype,s)}),ft(...n)(i,s)}}function Ge(t=Le){return gt.for(te.PRIVATE).define({decorator:t=>Ye(t,te.PRIVATE),args:[t]}).apply()}function Ve(t){return gt.for(te.SHARED).define({decorator:t=>Ye(t,te.SHARED),args:[t]}).apply()}class Je extends B{constructor(){super()}preSerialize(t){const e=Object.assign({},t);let r;try{r=ht.modelName(t.constructor)}catch(t){r=void 0}e[_.ANCHOR]=r||t.constructor.name;const i=function t(e){const r=this;return"object"!=typeof e?e:Array.isArray(e)?e.map(e=>t.call(r,e)):this.preSerialize.call(this,e)}.bind(this);return $.relations(t).forEach(t=>{e[t]=i(e[t])}),e}deserialize(t){const e=JSON.parse(t),r=e[_.ANCHOR];if(!r)throw Error("Could not find class reference in serialized model");return $.build(e,r)}serialize(t){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t)))}}function qe(t,e,r){const i=[t,e];return r&&i.push(r),i.join("_")}function We(t){const e=t.split("_");return 2>e.length||e.length>3?{table:void 0,event:t,owner:void 0}:{table:e[0],event:e[1],owner:e[2]}}function Xe(t,e){const r=t+e;if(t!==r-e||e!==r-t)throw new pe(`Addition overflow: ${t} + ${e}`);return r}function Qe(t,e){const r=t-e;if(t!==r+e||e!==t-r)throw new pe(`Subtraction overflow: ${t} - ${e}`);return r}function Ze(t){if(!/^\d+$/.test(t))throw new H(P("Failed to parse: {0}","string contains digits"));const e=parseInt(t);if(isNaN(e))throw new H(P("Failed to parse: {0}","string is not a parsable integer"));return e}class tr extends B{constructor(){super()}deserialize(t,e){return JSON.parse(t)}serialize(t,e=!0){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t,e)))}preSerialize(t,e=!0){const r=Object.assign({},t);let i;try{i=ht.modelName(t.constructor)}catch(t){i=void 0}function s(t){return"object"!=typeof t?t:Array.isArray(t)?t.map(s):this.preSerialize(t)}return e&&(r[_.ANCHOR]=i||t.constructor.name),$.relations(t).forEach(t=>{r[t]=s.call(this,r[t])}),r}}class er extends C{constructor(){super()}get rootClient(){return this.client._FabricCaServices}get user(){if(!this._user)throw new Y("Fabric identity service not properly setup: missing user");return this._user}get certificates(){return this.rootClient.newCertificateService()}get affiliations(){return this.client.newAffiliationService()}get identities(){return this.client.newIdentityService()}async getUser(t,e){const r=e.logger.for(this.getUser),{caName:i,caCert:s,caKey:n,url:a,hsm:o}=t;r.info(`Creating CA user for ${i} at ${a}`),r.verbose("Retrieving CA certificate from "+s);const c=await se.getFirstDirFileNameContent(s);let l;if(o)r.debug(`Using HSM configuration for CA ${i} with library ${o.library}`);else{if(!n)throw new Y(`Missing caKey configuration for CA ${i}. Provide a key directory or configure HSM support.`);r.debug("Retrieving CA key from "+n),l=await se.getFirstDirFileNameContent(n)}return r.debug("Loading Admin user for ca "+i),this._user=await se.getCAUser("admin",l,c,i,{hsm:o}),this._user}async initialize(...t){const{log:e,ctx:r}=await this.logCtx(t,this.initialize,!0),[i]=t;if(!i)throw new Y("Missing Fabric CA configuration");const{url:s,tls:n,caName:a}=i;e.info(`Initializing CA Client for CA ${i.caName} at ${i.url}`);const{trustedRoots:o,verify:c}=n,l=o[0];e.debug(`Retrieving CA certificate from ${l}. cwd: ${process.cwd()}`);const d=await se.getFileContent(l);e.debug("CA Certificate: "+d.toString());const h=new bt(s,{trustedRoots:Buffer.from(d),verify:c},a),u=await this.getUser(i,r);return e.debug("CA user loaded: "+u.getName()),{config:i,client:h}}async getCertificates(t,e=!0,...r){t instanceof l?(r=[t],e=!0,t=void 0):"boolean"==typeof t?(e=t,t=void 0):"boolean"!=typeof e&&(r=[e,...r],e=!0);const{log:i}=await this.logCtx(r,this.getCertificates,!0);i.debug(`Retrieving certificates${t?" for "+t.id:""} for CA ${this.config.caName}`);const s=(await this.certificates.getCertificates(t||{},this.user)).result;return i.verbose(`Found ${s.certs.length} certificates`),i.debug(s.certs),e?s.certs.map(t=>t.PEM):s}async getIdentities(t){const e=t.logger.for(this.getIdentities);e.verbose("Retrieving Identities under CA "+this.config.caName);const r=(await this.identities.getAll(this.user)).result;return e.verbose(`Found ${r.identities.length} Identities`),e.debug(r.identities),r.identities}async getAffiliations(t){const e=t.logger.for(this.getAffiliations);e.verbose("Retrieving Affiliations under CA "+this.config.caName);const r=(await this.affiliations.getAll(this.user)).result;return e.verbose(`Found ${r.a.length} Affiliations`),e.debug(JSON.stringify(r)),r}parseError(t){const e=/.*code:\s(\d+).*?message:\s["'](.+)["']/gs.exec(t.message);if(!e)return new me(t);const[,r,i]=e;switch(r){case"74":case"71":return new V(i);case"20":return new g(i);default:return new me(i)}}async read(t,...e){const{log:r}=await this.logCtx(e,this.read,!0);let i;r.verbose("Retrieving identity with enrollment ID "+t);try{i=await this.identities.getOne(t,this.user)}catch(e){throw new J(`Couldn't find enrollment with id ${t}: ${e}`)}if(!i.success)throw new J(`Couldn't find enrollment with id ${t}: ${i.errors.join("\n")}`);return i.result}async register(t,e=!1,r="",i,s,n,...a){const{log:o}=await this.logCtx(a,this.register,!0);let c;try{const{userName:a,password:l}=t,d={enrollmentID:a,enrollmentSecret:l,affiliation:r,userRole:i,attrs:s,maxEnrollments:n};c=await this.client.register(d,this.user),o.info(`Registration for ${a} created with user type ${i??"Undefined Role"} ${e?"as super user":""}`)}catch(t){throw this.parseError(t)}return c}static identityFromEnrollment(t,e,r){const i=r.logger.for(this.identityFromEnrollment),{certificate:s,key:n,rootCertificate:a}=t;i.verbose(`Generating Identity from certificate ${s} in msp ${e}`);const o=ue.fabricIdFromCertificate(s),c=ue.encode(o);return i.debug(`Identity ${o} and encodedId ${c}`),new ie({id:c,credentials:{id:c,certificate:s,privateKey:n.toBytes(),rootCertificate:a},mspId:e})}async enroll(t,e,...r){const{log:i,ctx:s}=await this.logCtx(r,this.enroll,!0);let n;try{i.debug("Enrolling "+t);const r=await this.client.enroll({enrollmentID:t,enrollmentSecret:e});n=er.identityFromEnrollment(r,this.config.caName,s),i.info(`Successfully enrolled ${t} under ${this.config.caName} as ${n.id}`)}catch(t){throw this.parseError(t)}return n}async registerAndEnroll(t,e=!1,r="",i,s,n,...a){const{ctx:o}=await this.logCtx(a,this.registerAndEnroll,!0),c=await this.register(t,e,r,i,s,n,o),{userName:l}=t;return this.enroll(l,c,o)}async revoke(t,...e){const{log:r}=await this.logCtx(e,this.revoke,!0);r.verbose("Revoking identity with enrollment ID "+t);const i=await this.read(t);if(!i)throw new J("Could not find enrollment with id "+t);let s;try{s=await this.client.revoke({enrollmentID:i.id,reason:"User Deletion"},this.user)}catch(e){throw new Y(`Could not revoke enrollment with id ${t}: ${e}`)}if(!s.success)throw new Y(`Could not revoke enrollment with id ${t}: ${s.errors.join("\n")}`);return s}}const rr=Object.assign({evaluateTimeout:5,endorseTimeout:15,submitTimeout:5,commitTimeout:60}),ir=new Ct("fabric-fs");async function sr(t,e){return t instanceof Uint8Array||t.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)?t:await e(t)}async function nr(t){return"string"!=typeof t?t:await(async t=>{const{promises:e}=await p(import("fs"));return await e.readFile(t)})(t)}async function ar(t,e,r,i){ir.debug(`Creating a CA ${i} user ${t} with certificate ${r}`);const s=new Rt(t),n=Rt.newCryptoSuite();s.setCryptoSuite(n);const a=n.createKeyFromRaw(e);return await s.setEnrollment(a,r,i),s}async function or(t,e){const r=await sr(e,async t=>{const{promises:e}=await p(import("fs")),r=await cr(t);return await e.readFile(r)});return{mspId:t,credentials:r}}async function cr(t){const{promises:e}=await p(import("fs")),{join:r}=await p(import("path"));return r(t,(await e.readdir(t))[0])}async function lr(t){const{promises:e}=await p(import("fs")),{join:r}=await p(import("path")),i=await e.readdir(t);return(await e.readFile(r(t,i[0]))).toString()}async function dr(t){const e=await sr(t,async t=>{const{promises:e}=await p(import("fs")),r=await cr(t);return await e.readFile(r)}),r=await hr(e),i=r[Object.getOwnPropertySymbols(r)[0]];return It.newPrivateKeySigner(i)}async function hr(t){let e;if(At())e=globalThis.crypto.subtle;else{const t=await p(import("crypto"));e=t.subtle||t.webcrypto.subtle}if(!e)throw Error("Could not load SubtleCrypto module");const r=t.toString("utf8").replace("-----BEGIN PRIVATE KEY-----","").replaceAll("\n","").replace("-----END PRIVATE KEY-----",""),i=(t=>{const e=new ArrayBuffer(t.length),r=new Uint8Array(e);for(let e=0,i=t.length;i>e;e++)r[e]=t.charCodeAt(e);return e})(Buffer.from(r,"base64").toString("binary"));try{return await e.importKey("pkcs8",i,{name:"ECDSA",namedCurve:"P-256"},!0,["sign"])}catch(t){throw new Y(t)}}class ur{static#t=null;static#e=!1;constructor(t){if(ur.#t||(ur.#t=new Pt.PKCS11,ur.#t.load(this.findHSMPKCS11Lib(t))),!ur.#e){try{ur.#t.C_Initialize()}catch(t){if(t.code!==Pt.CKR_CRYPTOKI_ALREADY_INITIALIZED)throw t}ur.#e=!0}}findHSMPKCS11Lib(t){const e=["/usr/lib/softhsm/libsofthsm2.so","/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so","/usr/local/lib/softhsm/libsofthsm2.so","/usr/lib/libacsp-pkcs11.so","/opt/homebrew/lib/softhsm/libsofthsm2.so"];t&&e.push(t);for(const t of e)if(jt.existsSync(t))return t;throw new Ce("Unable to find PKCS11 library")}dispose(){ur.#t.C_Finalize()}sanitizeOptions(t){const e=Object.assign({userType:Pt.CKU_USER},t);return this.assertNotEmpty(e.label,"label"),this.assertNotEmpty(e.pin,"pin"),this.assertNotEmpty(e.identifier,"identifier"),e}assertNotEmpty(t,e){if(!t||0===t.toString().trim().length)throw Error(e+" property must be provided")}findSlotForLabel(t){const e=ur.#t.C_GetSlotList(!0);if(0===e.length)throw Error("No pkcs11 slots can be found");const r=e.find(e=>ur.#t.C_GetTokenInfo(e).label.trim()===t);if(!r)throw Error(`label ${t} cannot be found in the pkcs11 slot list`);return r}login(t,e,r){try{ur.#t.C_Login(t,e,r)}catch(t){if(t.code!==Pt.CKR_USER_ALREADY_LOGGED_IN)throw t}}findObjectInHSM(t,e,r){const i=[{type:Pt.CKA_ID,value:r},{type:Pt.CKA_CLASS,value:e},{type:Pt.CKA_KEY_TYPE,value:Pt.CKK_EC}];ur.#t.C_FindObjectsInit(t,i);const s=ur.#t.C_FindObjects(t,1)[0];if(!s)throw ur.#t.C_FindObjectsFinal(t),Error("Unable to find object in HSM with ID "+r.toString());return ur.#t.C_FindObjectsFinal(t),s}newSigner(t){const e=this.sanitizeOptions(t),r=ur.#t,i=this.findSlotForLabel(e.label),s=r.C_OpenSession(i,Pt.CKF_SERIAL_SESSION);let n;try{this.login(s,e.userType,e.pin),n=this.findObjectInHSM(s,Pt.CKO_PRIVATE_KEY,e.identifier)}catch(t){throw ur.#t.C_CloseSession(s),t}return{signer:async t=>{ur.#t.C_SignInit(s,{mechanism:Pt.CKM_ECDSA},n);const e=await ur.#t.C_SignAsync(s,Buffer.from(t),Buffer.alloc(2*Lt.Point.Fn.BYTES));return Lt.Signature.fromBytes(e,"compact").normalizeS().toBytes("der")},close:()=>{ur.#t.C_CloseSession(s)}}}assertDefined(t){if(void 0===t)throw Error("required value was undefined");return t}getUncompressedPointOnCurve(t){const e=t.export({format:"jwk"}),r=Buffer.from(this.assertDefined(e.x),"base64url"),i=Buffer.from(this.assertDefined(e.y),"base64url"),s=Buffer.from("04","hex");return Buffer.concat([s,r,i])}getSKIFromCertificatePath(t){const e=t.endsWith(".pem")?t:Kt.join(t,"cert.pem"),r=jt.readFileSync(e);return this.getSKIFromCertificate(r)}getSKIFromCertificate(t){const e=new $t.X509Certificate(t),r=this.getUncompressedPointOnCurve(e.publicKey);return $t.createHash("sha256").update(r).digest()}}class pr extends A{constructor(t,e){super(t,e)}squash(t){const r=super.squash(t);if(!r)return r;const{method:i,params:s,args:n}=r,{direction:a,limit:o}=s;switch(i){case e.FIND_BY:break;case e.LIST_BY:n.push(a);break;case e.PAGE_BY:n.push(a,o);break;case e.FIND_ONE_BY:break;default:throw new Y("Unsupported method "+i)}return r}async executePrepared(...e){const r=t.forModel(this.fromSelector,this.adapter.alias),{method:i,args:s}=this.prepared;return r.statement(i,...s,...e)}async prepare(t){if(t=t||await this.adapter.context(r.QUERY,this.overrides||{},this.fromSelector),this.isSimpleQuery()&&t.get("forcePrepareSimpleQueries")){const e=this.squash(t);if(e)return this.prepared=e,this}const e=[],i={},s={class:this.fromSelector,args:e,params:i},n=[v.FIND_BY];if(this.whereCondition){const r=this.prepareCondition(this.whereCondition,t);n.push(r.method),r.args&&r.args.length&&e.push(...r.args)}return this.selectSelector&&n.push(v.SELECT,this.selectSelector.join(` ${v.AND.toLowerCase()} `)),this.orderBySelector&&(n.push(v.ORDER_BY,this.orderBySelector[0]),e.push(this.orderBySelector[1])),s.method=xt(n.join(" ")),s.params=i,this.prepared=s,this}build(){throw new b("This method is only called is prepared statements are not used. If so, a dedicated implementation for the native queries used is required")}parseCondition(t,...e){throw new b("This method is only called is prepared statements are not used. Is so, a dedicated implementation for the native queries used is required")}}class gr extends i{constructor(t,e,r,i){super(t,e,r,i)}prepare(t){throw new b("Raw query access must be implemented by a subclass. only prepared statements are natively available")}page(t=1,...e){return super.page(t,...e)}}var fr;class mr extends S{static{this.decoder=new TextDecoder("utf8")}static{this.serializer=new Yt}static{this.log=St.for(mr)}constructor(t,e){super(t,re,e),this.serializer=mr.serializer}Statement(t){return new pr(this,t)}Paginator(t,e,r){return new gr(this,t,e,r)}async flags(t,e,r,...i){return Object.assign(await super.flags(t,e,Object.assign({},this.config,r),...i))}decode(t){return mr.decoder.decode(t)}repository(){return zt}createPrefix(t,e,r,...i){const{ctxArgs:s}=this.logCtx(i,this.createPrefix),n=$.tableName(t),a={};return a[ct.TABLE]=n,Object.assign(a,r),[t,e,a,...s]}createAllPrefix(t,e,r,...i){const s=$.tableName(t);if(e.length!==r.length)throw new Y("Ids and models must have the same length");const{ctxArgs:n}=this.logCtx(i,this.createAllPrefix),a=e.map((t,e)=>{const i={};return i[ct.TABLE]=s,Object.assign(i,r[e]),i});return[t,e,a,...n]}updateAllPrefix(t,e,r,...i){const s=$.tableName(t);if(e.length!==r.length)throw new Y("Ids and models must have the same length");const{ctxArgs:n}=this.logCtx(i,this.updateAllPrefix),a=e.map(()=>{const t={};return t[ct.TABLE]=s,t});return[t,e,a,...n]}async createAll(t,e,r,...i){if(e.length!==r.length)throw new Y("Ids and models must have the same length");const s=[...i],n=s.shift(),{log:a,ctx:o}=this.logCtx(s,this.createAll),c=$.tableName(t);a.info(`adding ${e.length} entries to ${c} table`),a.verbose("pks: "+e);const l=await this.submitTransaction(o,at.CREATE_ALL,[JSON.stringify(r.map(e=>this.serializer.serialize(e,t.name)))],n,void 0,t.name);try{return JSON.parse(this.decode(l)).map(t=>JSON.parse(t))}catch(t){throw new U(t)}}async readAll(t,e,...r){const{log:i,ctx:s}=this.logCtx(r,this.readAll),n=$.tableName(t);i.info(`reading ${e.length} entries to ${n} table`),i.verbose("pks: "+e);const a=await this.evaluateTransaction(s,at.READ_ALL,[JSON.stringify(e)],void 0,void 0,t.name);try{return JSON.parse(this.decode(a)).map(t=>JSON.parse(t))}catch(t){throw new U(t)}}async updateAll(t,e,r,...i){if(e.length!==r.length)throw new Y("Ids and models must have the same length");const s=[...i],n=s.shift(),{log:a,ctx:o}=this.logCtx(s,this.updateAll),c=$.tableName(t);a.info(`updating ${e.length} entries to ${c} table`),a.verbose("pks: "+e);const l=await this.submitTransaction(o,at.UPDATE_ALL,[JSON.stringify(r.map(e=>this.serializer.serialize(e,t.name)))],n,void 0,t.name);try{return JSON.parse(this.decode(l)).map(t=>JSON.parse(t))}catch(t){throw new U(t)}}async deleteAll(t,e,...r){const{log:i,ctx:s}=this.logCtx(r,this.deleteAll),n=$.tableName(t);i.info(`deleting ${e.length} entries to ${n} table`),i.verbose("pks: "+e);const a=await this.submitTransaction(s,at.DELETE_ALL,[JSON.stringify(e)],void 0,void 0,t.name);try{return JSON.parse(this.decode(a)).map(t=>JSON.parse(t))}catch(t){throw new U(t)}}prepare(t,...e){const{log:i}=this.logCtx(e,this.prepare),s=$.segregate(t);return t[r.METADATA]&&(i.silly("Passing along persistence metadata for "+t[r.METADATA]),Object.defineProperty(s.model,r.METADATA,{enumerable:!1,writable:!1,configurable:!0,value:t[r.METADATA]})),{record:s.model,model:s.model,id:t[$.pk(t.constructor)],transient:s.transient,private:s.private,shared:s.shared}}revert(t,e,r,i,...s){const{log:n}=this.logCtx(s,this.revert);return i&&(n.verbose("re-adding transient properties: "+Object.keys(i).join(", ")),Object.entries(i).forEach(([r,i])=>{if(r in t)throw new Y(`Transient property ${r} already exists on model ${"string"==typeof e?e:e.name}. should be impossible`);t[r]=i})),new e(t)}async create(t,e,r,i={},...s){const n=[...s],{log:a,ctx:o}=this.logCtx(n,this.create),c=$.tableName(t);a.verbose(`adding entry to ${c} table`),a.debug("pk: "+e);const l=await this.submitTransaction(o,L.CREATE,[this.serializer.serialize(r,t.name)],i,void 0,t.name);return this.serializer.deserialize(this.decode(l))}async read(t,e,...r){const{log:i,ctx:s}=this.logCtx(r,this.readAll),n=$.tableName(t);i.verbose(`reading entry from ${n} table`),i.debug("pk: "+e);const a=await this.evaluateTransaction(s,L.READ,[e.toString()],void 0,void 0,t.name);return this.serializer.deserialize(this.decode(a))}updatePrefix(t,e,r,...i){const s=$.tableName(t),{ctxArgs:n}=this.logCtx(i,this.updatePrefix),a={};return a[ct.TABLE]=s,Object.assign(a,r),[t,e,a,...n]}async update(t,e,r,i={},...s){const n=[...s],{log:a,ctx:o}=this.logCtx(n,this.updateAll);a.info("CLIENT UPDATE class : "+typeof t);const c=$.tableName(t);a.verbose(`updating entry to ${c} table`),a.debug("pk: "+e);const l=await this.submitTransaction(o,L.UPDATE,[this.serializer.serialize(r,t.name||t)],i,void 0,t.name);return this.serializer.deserialize(this.decode(l))}async delete(t,e,...r){const{log:i,ctx:s}=this.logCtx(r,this.delete),n=$.tableName(t);i.verbose(`deleting entry from ${n} table`),i.debug("pk: "+e);const a=await this.submitTransaction(s,L.DELETE,[e.toString()],void 0,void 0,t.name);return this.serializer.deserialize(this.decode(a))}async raw(t,e=!0,r,...i){const{log:s,ctx:n}=this.logCtx(i,this.raw),a=r.name;let o,c;s.info("Performing raw statement on table "+$.tableName(r));try{o=await this.evaluateTransaction(n,"raw",[JSON.stringify(t),e],void 0,void 0,a)}catch(t){throw this.parseError(t)}try{c=JSON.parse(this.decode(o))}catch(t){throw new U("Failed to process result: "+t)}if(Array.isArray(c)){if(!c.length)return c;const t=c[0];return $.isModel(t)?c.map(t=>$.build(t)):c}return l=c,$.isModel(l)?$.build(l):l;var l}getClient(){return this._client||(this._client=mr.getClient(this.config)),this._client}async Gateway(t){return mr.getGateway(t,this.config,this.client)}getContractName(t){if(t)return t+"Contract"}async Contract(t,e){return mr.getContract(await this.Gateway(t),this.config,e)}async transaction(t,e,r=!0,i,s,n,a){const o=this.log.for(this.transaction),c=await this.Gateway(t);try{const c=await this.Contract(t,this.getContractName(a));o.verbose(`${r?"Submit":"Evaluate"}ting transaction ${this.getContractName(a)||this.config.contractName}.${e}`),o.debug("args: "+(i?.map(t=>t.toString()).join("\n")||"none"));const l=r?c.submit:c.evaluate;n=n?.length?n:void 0;const d={arguments:i||[],transientData:s};return await l.call(c,e,d)}catch(t){if(10===t.code)throw Error(""+t.details[0].message);throw this.parseError(t)}finally{this.log.debug(`Closing ${this.config.mspId} gateway connection`),c.close()}}parseError(t){return mr.parseError(t)}async submitTransaction(t,e,r,i,s,n){return this.transaction(t,e,!0,r,i,s,n)}async evaluateTransaction(t,e,r,i,s,n){return this.transaction(t,e,!1,r,i,s,n)}async close(){this.client&&(this.log.verbose(`Closing ${this.config.mspId} gateway client`),this.client.close())}static getContract(t,e,r){const i=this.log.for(this.getContract),s=this.getNetwork(t,e.channel);let n;try{i.debug(`Retrieving chaincode ${e.chaincodeName} contract ${r||e.contractName} from network ${e.channel}`),r=r||e.contractName,n=s.getContract(e.chaincodeName,r)}catch(t){throw this.parseError(t)}return n}static getNetwork(t,e){const r=St.for(this.getNetwork);let i;try{r.debug("Connecting to channel "+e),i=t.getNetwork(e)}catch(t){throw this.parseError(t)}return i}static async getGateway(t,e,r){return await this.getConnection(r||await this.getClient(e),e,t)}static getClient(t){const e=this.log.for(this.getClient);e.debug("generating TLS credentials for msp "+t.mspId);let r=t.tlsCert;if("string"==typeof r)if(r.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms))r=Buffer.from(r,"utf8");else try{r=Buffer.from(jt.readFileSync(r,"utf8"))}catch(t){throw new Y(`Failed to read the tls certificate from ${r}: ${t}`)}const i=Bt.credentials.createSsl(r);return e.debug("generating Gateway Client for url "+t.peerEndpoint),new _t(t.peerEndpoint,i,{"grpc.max_receive_message_length":1024*(t.sizeLimit||15)*1024,"grpc.max_send_message_length":1024*(t.sizeLimit||15)*1024})}static async getConnection(t,e,r){const i=St.for(this.getConnection);i.debug(`Retrieving Peer Identity for ${e.mspId} under ${e.certCertOrDirectoryPath}`);const s=await or(e.mspId,e.certCertOrDirectoryPath);i.debug("Retrieving signer key from "+e.keyCertOrDirectoryPath);let n,a=()=>{};if(e.hsm){const t=new ur(e.hsm.library),r=t.getSKIFromCertificatePath(e.certCertOrDirectoryPath),i=t.newSigner({label:e.hsm.tokenLabel,pin:e.hsm.pin+"",identifier:r});n=i.signer,a=i.close}else n=await dr(e.keyCertOrDirectoryPath);const o={client:t,identity:s,signer:n,evaluateOptions:()=>({deadline:Date.now()+1e3*r.get("evaluateTimeout")}),endorseOptions:()=>({deadline:Date.now()+1e3*r.get("endorseTimeout")}),submitOptions:()=>({deadline:Date.now()+1e3*r.get("submitTimeout")}),commitStatusOptions:()=>({deadline:Date.now()+1e3*r.get("commitTimeout")})};i.debug("Connecting to "+e.mspId);const c=Ot(o);return e.hsm&&(c.close=new Proxy(c.close,{apply(t,e,r){Reflect.apply(t,e,r),a()}})),c}Dispatch(){return new mr._baseDispatch}static parseError(t){const e="string"==typeof t?t:t.message;return e.includes("MVCC_READ_CONFLICT")?new ve(t):e.includes("ENDORSEMENT_POLICY_FAILURE")?new Ee(t):e.includes("PHANTOM_READ_CONFLICT")?new Se(t):t instanceof Error&&t.code&&9===t.code?new Ae(t):e.includes(J.name)?new J(t):e.includes(V.name)?new V(t):e.includes(ot.name)?new ot(t):e.includes(E.name)?new E(t):e.includes(x.name)?new x(t):e.includes(b.name)?new b(t):e.includes(N.name)?new N(t):e.includes(T.name)?new T(t):e.includes(g.name)?new g(t):e.includes(I.name)?new I(t):e.includes(O.name)?new O(t):e.includes(U.name)?new U(t):new Y(t)}}lt([Nt(),Tt(),dt("design:type",Function),dt("design:paramtypes",[Object,Object,Object,Object,l]),dt("design:returntype",Promise)],mr.prototype,"create",null),lt([Nt(),Tt(),dt("design:type",Function),dt("design:paramtypes",[Object,Object,l]),dt("design:returntype",Promise)],mr.prototype,"read",null),lt([Nt(),Tt(),dt("design:type",Function),dt("design:paramtypes",[Object,Object,Object,Object,l]),dt("design:returntype",Promise)],mr.prototype,"update",null),lt([Nt(),Tt(),dt("design:type",Function),dt("design:paramtypes",[Object,Object,l]),dt("design:returntype",Promise)],mr.prototype,"delete",null),lt([Nt(),dt("design:type",Function),dt("design:paramtypes",[Object,"function"==typeof(fr="undefined"!=typeof D&&D)?fr:Object,Object,l]),dt("design:returntype",Promise)],mr.prototype,"raw",null),mr.decoration(),S.setCurrent(re);class yr extends R{constructor(t){super(),this.client=t,this.decoder=new TextDecoder("utf8")}async close(){this.listeningStack&&this.listeningStack.close()}parsePayload(t){const e=this.decoder.decode(t);return JSON.parse(e)}observe(t){if(!(t instanceof mr))throw new b("Only FabricClientAdapter can be observed by dispatch");return super.observe(t),()=>this.unObserve(t)}async updateObservers(t,e,r,...i){const{log:s,ctxArgs:n}=S.logCtx(this.updateObservers,e,!1,...i);if(this.adapter)try{await this.adapter.refresh(t,e,r,...n)}catch(t){throw new Y("Failed to refresh dispatch: "+t)}else s.verbose(`No adapter observed for dispatch; skipping observer update for ${"string"==typeof t?t:$.tableName(t)}:${e}`)}async handleEvents(t){if(!this.listeningStack)throw new Y('Event stack not initialized. Ensure that "startListening" is called before attempting this operation.');if(!this.adapter||!this.adapter.config)throw new Y("No adapter found. should be impossible");const e=t||await this.adapter.context(L.READ,{correlationId:this.adapter.config.chaincodeName},this.models&&this.models[0]||$),r=this.log.for(this.handleEvents);r.info(`Listening for incoming events on chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}"...`);try{for await(const t of this.listeningStack){const{table:i,event:s,owner:n}=We(t.eventName);if(n&&n!==this.adapter.config?.mspId)continue;const a=this.parsePayload(t.payload);try{const t=(i?$.get(i):$.get(this.models[0].name))??(i||this.models[0]?.name);await this.updateObservers(t,s,a.id,e)}catch(t){r.error(`Failed update observables for table ${i} event ${s} id: ${a.id}: ${t}`)}}}catch(t){r.error(`Failed to read event for chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}": ${t}`),await this.close()}}async initialize(){if(!this.adapter)throw new Y("No adapter or config observed for dispatch");const t=await this.adapter.context("dispatch",{correlationId:this.adapter.config.chaincodeName},$),{ctx:e}=this.logCtx([t],this.initialize),r=(await mr.getGateway(e,this.adapter.config,this.client)).getNetwork(this.adapter.config.channel);if(!this.adapter)throw new Y("No adapter observed for dispatch");this.listeningStack=await r.getChaincodeEvents(this.adapter.config.chaincodeName),this.handleEvents(e)}}mr&&(mr._baseDispatch=yr);const wr="##VERSION##",br="##PACKAGE##";ht.registerLibrary(br,wr);export{fe as AllowanceError,ae as BASE_ALPHABET,ge as BalanceError,he as BaseEncoder,oe as CRYPTO,Yt as ClientSerializer,se as CoreUtils,ue as CryptoUtils,rr as DefaultFabricClientFlags,Je as DeterministicSerializer,de as ERC20Events,Ae as EndorsementError,Ee as EndorsementPolicyError,Te as FabricBaseModel,mr as FabricClientAdapter,yr as FabricClientDispatch,zt as FabricClientRepository,Gt as FabricERC20ClientRepository,xe as FabricEnrollmentService,re as FabricFlavour,Ie as FabricIdentifiedBaseModel,er as FabricIdentityService,te as FabricModelKeys,le as HFCAIdentityAttributes,ce as HFCAIdentityType,ie as Identity,Zt as IdentityCredentials,ee as IdentityType,Le as ImplicitPrivateCollection,ye as MissingContextError,Ce as MissingPKCSS11Lib,Ke as ModelCollection,ve as MvccReadConflictError,be as NotInitializedError,pe as OverflowError,Oe as Owner,br as PACKAGE_NAME,Se as PhantomReadConflictError,me as RegistrationError,Ne as RegistrationRequestBuilder,tr as SimpleDeterministicSerializer,we as UnauthorizedPrivateDataAccess,wr as VERSION,Xe as add,sr as contentOfLoadFile,Be as createMirrorHandler,Pe as deleteMirrorHandler,De as evalMirrorMetadata,hr as extractPrivateKey,qe as generateFabricEventName,qt as generateModelIndexes,ar as getCAUser,cr as getFirstDirFileName,lr as getFirstDirFileNameContent,or as getIdentity,dr as getSigner,je as mirror,$e as ownedBy,Re as ownedByOnCreate,We as parseEventName,Ge as privateData,nr as readFile,Wt as readModelFile,Xt as readModelFolders,Ze as safeParseInt,ze as segregatedDataOnCreate,Ue as segregatedDataOnDelete,Me as segregatedDataOnRead,He as segregatedDataOnUpdate,Ve as sharedData,Qe as sub,Fe as transactionId,ke as transactionIdOnCreate,_e as updateMirrorHandler,Qt as writeIndexes};
2
+ //# sourceMappingURL=for-fabric.js.map