@decaf-ts/for-fabric 0.1.104 → 0.1.106

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 (433) hide show
  1. package/dist/for-fabric.cjs +3117 -2
  2. package/dist/for-fabric.js +3218 -2
  3. package/lib/bin/cli.cjs +2 -1
  4. package/lib/cli-module.cjs +1 -1
  5. package/lib/cli-utils.cjs +1 -1
  6. package/lib/client/FabricClientAdapter.cjs +16 -2
  7. package/lib/client/FabricClientAdapter.d.ts +1 -0
  8. package/lib/client/FabricClientDispatch.cjs +1 -1
  9. package/lib/client/FabricClientPaginator.cjs +1 -1
  10. package/lib/client/FabricClientRepository.cjs +6 -1
  11. package/lib/client/FabricClientRepository.d.ts +1 -0
  12. package/lib/client/FabricClientStatement.cjs +1 -1
  13. package/lib/client/collections/generation.cjs +1 -1
  14. package/lib/client/collections/index.cjs +1 -1
  15. package/lib/client/constants.cjs +1 -1
  16. package/lib/client/crypto.cjs +1 -1
  17. package/lib/client/erc20/FabricERC20ClientRepository.cjs +1 -1
  18. package/lib/client/erc20/index.cjs +1 -1
  19. package/lib/client/fabric-fs.cjs +1 -1
  20. package/lib/client/fabric-hsm.cjs +1 -1
  21. package/lib/client/index.cjs +1 -1
  22. package/lib/client/indexes/generation.cjs +1 -1
  23. package/lib/client/indexes/index.cjs +1 -1
  24. package/lib/client/logging.cjs +1 -1
  25. package/lib/client/services/FabricEnrollmentService.cjs +1 -1
  26. package/lib/client/services/FabricIdentityService.cjs +1 -1
  27. package/lib/client/services/RegistrationRequestBuilder.cjs +1 -1
  28. package/lib/client/services/constants.cjs +1 -1
  29. package/lib/client/services/index.cjs +1 -1
  30. package/lib/client/types.cjs +1 -1
  31. package/lib/client/utils.cjs +1 -1
  32. package/lib/contract/Address.cjs +1 -1
  33. package/lib/contract/AddressContract.cjs +1 -1
  34. package/lib/contract/BatchContract.cjs +1 -1
  35. package/lib/contract/MarketContract.cjs +1 -1
  36. package/lib/contract/OtherProductContract.cjs +1 -1
  37. package/lib/contract/OtherProductSharedContract.cjs +1 -1
  38. package/lib/contract/Product.cjs +1 -1
  39. package/lib/contract/ProductContract.cjs +1 -1
  40. package/lib/contract/ProductStrengthContract.cjs +1 -1
  41. package/lib/contract/SegregatedPrivateDocumentContract.cjs +1 -1
  42. package/lib/contract/SegregatedSharedDocumentContract.cjs +1 -1
  43. package/lib/contract/User.cjs +1 -1
  44. package/lib/contract/UserContract.cjs +1 -1
  45. package/lib/contract/index.cjs +1 -1
  46. package/lib/contract/models/Audit.cjs +1 -1
  47. package/lib/contract/models/BaseIdentifiedModel.cjs +1 -1
  48. package/lib/contract/models/BaseModel.cjs +1 -1
  49. package/lib/contract/models/Batch.cjs +1 -1
  50. package/lib/contract/models/Leaflet.cjs +1 -1
  51. package/lib/contract/models/LeafletFile.cjs +1 -1
  52. package/lib/contract/models/Market.cjs +1 -1
  53. package/lib/contract/models/OtherProduct.cjs +1 -1
  54. package/lib/contract/models/OtherProductShared.cjs +1 -1
  55. package/lib/contract/models/Product.cjs +1 -1
  56. package/lib/contract/models/ProductStrength.cjs +1 -1
  57. package/lib/contract/models/SegregatedDocument.cjs +1 -1
  58. package/lib/contract/models/constants.cjs +1 -1
  59. package/lib/contract/models/decorators.cjs +1 -1
  60. package/lib/contract/models/gtin.cjs +1 -1
  61. package/lib/contracts/ContractAdapter.cjs +1 -1
  62. package/lib/contracts/ContractContext.cjs +1 -1
  63. package/lib/contracts/ContractPrivateDataAdapter.cjs +1 -1
  64. package/lib/contracts/FabricConstruction.cjs +1 -1
  65. package/lib/contracts/FabricContractPaginator.cjs +1 -1
  66. package/lib/contracts/FabricContractRepository.cjs +1 -1
  67. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +1 -1
  68. package/lib/contracts/FabricContractSequence.cjs +1 -1
  69. package/lib/contracts/FabricContractStatement.cjs +1 -1
  70. package/lib/contracts/PrivateSequence.cjs +1 -1
  71. package/lib/contracts/auth/decorators.cjs +1 -1
  72. package/lib/contracts/auth/index.cjs +1 -1
  73. package/lib/contracts/crud/crud-contract.cjs +9 -2
  74. package/lib/contracts/crud/index.cjs +1 -1
  75. package/lib/contracts/crud/serialized-crud-contract.cjs +1 -1
  76. package/lib/contracts/erc20/erc20contract.cjs +1 -1
  77. package/lib/contracts/erc20/index.cjs +1 -1
  78. package/lib/contracts/erc20/models.cjs +1 -1
  79. package/lib/contracts/index.cjs +1 -1
  80. package/lib/contracts/logging.cjs +1 -1
  81. package/lib/contracts/overrides.cjs +1 -1
  82. package/lib/contracts/private-data.cjs +1 -1
  83. package/lib/contracts/types.cjs +1 -1
  84. package/lib/contracts/uuid.cjs +1 -1
  85. package/lib/esm/bin/cli.js +1 -1
  86. package/lib/esm/cli-module.js +1 -1
  87. package/lib/esm/cli-utils.js +1 -1
  88. package/lib/esm/client/FabricClientAdapter.d.ts +1 -0
  89. package/lib/esm/client/FabricClientAdapter.js +16 -2
  90. package/lib/esm/client/FabricClientDispatch.js +1 -1
  91. package/lib/esm/client/FabricClientPaginator.js +1 -1
  92. package/lib/esm/client/FabricClientRepository.d.ts +1 -0
  93. package/lib/esm/client/FabricClientRepository.js +6 -1
  94. package/lib/esm/client/FabricClientStatement.js +1 -1
  95. package/lib/esm/client/collections/generation.js +1 -1
  96. package/lib/esm/client/collections/index.js +1 -1
  97. package/lib/esm/client/constants.js +1 -1
  98. package/lib/esm/client/crypto.js +1 -1
  99. package/lib/esm/client/erc20/FabricERC20ClientRepository.js +1 -1
  100. package/lib/esm/client/erc20/index.js +1 -1
  101. package/lib/esm/client/fabric-fs.js +1 -1
  102. package/lib/esm/client/fabric-hsm.js +1 -1
  103. package/lib/esm/client/index.js +1 -1
  104. package/lib/esm/client/indexes/generation.js +1 -1
  105. package/lib/esm/client/indexes/index.js +1 -1
  106. package/lib/esm/client/logging.js +1 -1
  107. package/lib/esm/client/services/FabricEnrollmentService.js +1 -1
  108. package/lib/esm/client/services/FabricIdentityService.js +1 -1
  109. package/lib/esm/client/services/RegistrationRequestBuilder.js +1 -1
  110. package/lib/esm/client/services/constants.js +1 -1
  111. package/lib/esm/client/services/index.js +1 -1
  112. package/lib/esm/client/types.js +1 -1
  113. package/lib/esm/client/utils.js +1 -1
  114. package/lib/esm/contract/Address.js +1 -1
  115. package/lib/esm/contract/AddressContract.js +1 -1
  116. package/lib/esm/contract/BatchContract.js +1 -1
  117. package/lib/esm/contract/MarketContract.js +1 -1
  118. package/lib/esm/contract/OtherProductContract.js +1 -1
  119. package/lib/esm/contract/OtherProductSharedContract.js +1 -1
  120. package/lib/esm/contract/Product.js +1 -1
  121. package/lib/esm/contract/ProductContract.js +1 -1
  122. package/lib/esm/contract/ProductStrengthContract.js +1 -1
  123. package/lib/esm/contract/SegregatedPrivateDocumentContract.js +1 -1
  124. package/lib/esm/contract/SegregatedSharedDocumentContract.js +1 -1
  125. package/lib/esm/contract/User.js +1 -1
  126. package/lib/esm/contract/UserContract.js +1 -1
  127. package/lib/esm/contract/index.js +1 -1
  128. package/lib/esm/contract/models/Audit.js +1 -1
  129. package/lib/esm/contract/models/BaseIdentifiedModel.js +1 -1
  130. package/lib/esm/contract/models/BaseModel.js +1 -1
  131. package/lib/esm/contract/models/Batch.js +1 -1
  132. package/lib/esm/contract/models/Leaflet.js +1 -1
  133. package/lib/esm/contract/models/LeafletFile.js +1 -1
  134. package/lib/esm/contract/models/Market.js +1 -1
  135. package/lib/esm/contract/models/OtherProduct.js +1 -1
  136. package/lib/esm/contract/models/OtherProductShared.js +1 -1
  137. package/lib/esm/contract/models/Product.js +1 -1
  138. package/lib/esm/contract/models/ProductStrength.js +1 -1
  139. package/lib/esm/contract/models/SegregatedDocument.js +1 -1
  140. package/lib/esm/contract/models/constants.js +1 -1
  141. package/lib/esm/contract/models/decorators.js +1 -1
  142. package/lib/esm/contract/models/gtin.js +1 -1
  143. package/lib/esm/contracts/ContractAdapter.js +1 -1
  144. package/lib/esm/contracts/ContractContext.js +1 -1
  145. package/lib/esm/contracts/ContractPrivateDataAdapter.js +1 -1
  146. package/lib/esm/contracts/FabricConstruction.js +1 -1
  147. package/lib/esm/contracts/FabricContractPaginator.js +1 -1
  148. package/lib/esm/contracts/FabricContractRepository.js +1 -1
  149. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +1 -1
  150. package/lib/esm/contracts/FabricContractSequence.js +1 -1
  151. package/lib/esm/contracts/FabricContractStatement.js +1 -1
  152. package/lib/esm/contracts/PrivateSequence.js +1 -1
  153. package/lib/esm/contracts/auth/decorators.js +1 -1
  154. package/lib/esm/contracts/auth/index.js +1 -1
  155. package/lib/esm/contracts/crud/crud-contract.js +9 -2
  156. package/lib/esm/contracts/crud/index.js +1 -1
  157. package/lib/esm/contracts/crud/serialized-crud-contract.js +1 -1
  158. package/lib/esm/contracts/erc20/erc20contract.js +1 -1
  159. package/lib/esm/contracts/erc20/index.js +1 -1
  160. package/lib/esm/contracts/erc20/models.js +1 -1
  161. package/lib/esm/contracts/index.js +1 -1
  162. package/lib/esm/contracts/logging.js +1 -1
  163. package/lib/esm/contracts/overrides.js +1 -1
  164. package/lib/esm/contracts/private-data.js +1 -1
  165. package/lib/esm/contracts/types.js +1 -1
  166. package/lib/esm/contracts/uuid.js +1 -1
  167. package/lib/esm/index.js +1 -1
  168. package/lib/esm/shared/ClientSerializer.js +1 -1
  169. package/lib/esm/shared/DeterministicSerializer.js +1 -1
  170. package/lib/esm/shared/SimpleDeterministicSerializer.js +1 -1
  171. package/lib/esm/shared/constants.js +1 -1
  172. package/lib/esm/shared/decorators.js +1 -1
  173. package/lib/esm/shared/erc20/erc20-constants.js +1 -1
  174. package/lib/esm/shared/erc20/index.js +1 -1
  175. package/lib/esm/shared/errors.js +1 -1
  176. package/lib/esm/shared/events.js +1 -1
  177. package/lib/esm/shared/fabric-types.js +1 -1
  178. package/lib/esm/shared/index.js +1 -1
  179. package/lib/esm/shared/interfaces/Checkable.d.ts +2 -0
  180. package/lib/esm/shared/interfaces/Checkable.js +1 -1
  181. package/lib/esm/shared/interfaces/index.js +1 -1
  182. package/lib/esm/shared/math.js +1 -1
  183. package/lib/esm/shared/model/FabricBaseModel.js +1 -1
  184. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js +1 -1
  185. package/lib/esm/shared/model/Identity.js +1 -1
  186. package/lib/esm/shared/model/IdentityCredentials.js +1 -1
  187. package/lib/esm/shared/model/index.js +1 -1
  188. package/lib/esm/shared/overrides/Model.js +1 -1
  189. package/lib/esm/shared/overrides/index.js +1 -1
  190. package/lib/esm/shared/overrides/overrides.js +1 -1
  191. package/lib/esm/shared/types.js +1 -1
  192. package/lib/esm/version.d.ts +1 -1
  193. package/lib/esm/version.js +2 -2
  194. package/lib/index.cjs +1 -1
  195. package/lib/shared/ClientSerializer.cjs +1 -1
  196. package/lib/shared/DeterministicSerializer.cjs +1 -1
  197. package/lib/shared/SimpleDeterministicSerializer.cjs +1 -1
  198. package/lib/shared/constants.cjs +1 -1
  199. package/lib/shared/decorators.cjs +1 -1
  200. package/lib/shared/erc20/erc20-constants.cjs +1 -1
  201. package/lib/shared/erc20/index.cjs +1 -1
  202. package/lib/shared/errors.cjs +1 -1
  203. package/lib/shared/events.cjs +1 -1
  204. package/lib/shared/fabric-types.cjs +1 -1
  205. package/lib/shared/index.cjs +1 -1
  206. package/lib/shared/interfaces/Checkable.cjs +1 -1
  207. package/lib/shared/interfaces/Checkable.d.ts +2 -0
  208. package/lib/shared/interfaces/index.cjs +1 -1
  209. package/lib/shared/math.cjs +1 -1
  210. package/lib/shared/model/FabricBaseModel.cjs +1 -1
  211. package/lib/shared/model/FabricIdentifiedBaseModel.cjs +1 -1
  212. package/lib/shared/model/Identity.cjs +1 -1
  213. package/lib/shared/model/IdentityCredentials.cjs +1 -1
  214. package/lib/shared/model/index.cjs +1 -1
  215. package/lib/shared/overrides/Model.cjs +1 -1
  216. package/lib/shared/overrides/index.cjs +1 -1
  217. package/lib/shared/overrides/overrides.cjs +1 -1
  218. package/lib/shared/types.cjs +1 -1
  219. package/lib/version.cjs +2 -2
  220. package/lib/version.d.ts +1 -1
  221. package/package.json +1 -1
  222. package/dist/for-fabric.cjs.map +0 -1
  223. package/dist/for-fabric.js.map +0 -1
  224. package/lib/bin/cli.js.map +0 -1
  225. package/lib/cli-module.js.map +0 -1
  226. package/lib/cli-utils.js.map +0 -1
  227. package/lib/client/FabricClientAdapter.js.map +0 -1
  228. package/lib/client/FabricClientDispatch.js.map +0 -1
  229. package/lib/client/FabricClientPaginator.js.map +0 -1
  230. package/lib/client/FabricClientRepository.js.map +0 -1
  231. package/lib/client/FabricClientStatement.js.map +0 -1
  232. package/lib/client/collections/generation.js.map +0 -1
  233. package/lib/client/collections/index.js.map +0 -1
  234. package/lib/client/constants.js.map +0 -1
  235. package/lib/client/crypto.js.map +0 -1
  236. package/lib/client/erc20/FabricERC20ClientRepository.js.map +0 -1
  237. package/lib/client/erc20/index.js.map +0 -1
  238. package/lib/client/fabric-fs.js.map +0 -1
  239. package/lib/client/fabric-hsm.js.map +0 -1
  240. package/lib/client/index.js.map +0 -1
  241. package/lib/client/indexes/generation.js.map +0 -1
  242. package/lib/client/indexes/index.js.map +0 -1
  243. package/lib/client/logging.js.map +0 -1
  244. package/lib/client/services/FabricEnrollmentService.js.map +0 -1
  245. package/lib/client/services/FabricIdentityService.js.map +0 -1
  246. package/lib/client/services/RegistrationRequestBuilder.js.map +0 -1
  247. package/lib/client/services/constants.js.map +0 -1
  248. package/lib/client/services/index.js.map +0 -1
  249. package/lib/client/types.js.map +0 -1
  250. package/lib/client/utils.js.map +0 -1
  251. package/lib/contract/Address.js.map +0 -1
  252. package/lib/contract/AddressContract.js.map +0 -1
  253. package/lib/contract/BatchContract.js.map +0 -1
  254. package/lib/contract/MarketContract.js.map +0 -1
  255. package/lib/contract/OtherProductContract.js.map +0 -1
  256. package/lib/contract/OtherProductSharedContract.js.map +0 -1
  257. package/lib/contract/Product.js.map +0 -1
  258. package/lib/contract/ProductContract.js.map +0 -1
  259. package/lib/contract/ProductStrengthContract.js.map +0 -1
  260. package/lib/contract/SegregatedPrivateDocumentContract.js.map +0 -1
  261. package/lib/contract/SegregatedSharedDocumentContract.js.map +0 -1
  262. package/lib/contract/User.js.map +0 -1
  263. package/lib/contract/UserContract.js.map +0 -1
  264. package/lib/contract/index.js.map +0 -1
  265. package/lib/contract/models/Audit.js.map +0 -1
  266. package/lib/contract/models/BaseIdentifiedModel.js.map +0 -1
  267. package/lib/contract/models/BaseModel.js.map +0 -1
  268. package/lib/contract/models/Batch.js.map +0 -1
  269. package/lib/contract/models/Leaflet.js.map +0 -1
  270. package/lib/contract/models/LeafletFile.js.map +0 -1
  271. package/lib/contract/models/Market.js.map +0 -1
  272. package/lib/contract/models/OtherProduct.js.map +0 -1
  273. package/lib/contract/models/OtherProductShared.js.map +0 -1
  274. package/lib/contract/models/Product.js.map +0 -1
  275. package/lib/contract/models/ProductStrength.js.map +0 -1
  276. package/lib/contract/models/SegregatedDocument.js.map +0 -1
  277. package/lib/contract/models/constants.js.map +0 -1
  278. package/lib/contract/models/decorators.js.map +0 -1
  279. package/lib/contract/models/gtin.js.map +0 -1
  280. package/lib/contracts/ContractAdapter.js.map +0 -1
  281. package/lib/contracts/ContractContext.js.map +0 -1
  282. package/lib/contracts/ContractPrivateDataAdapter.js.map +0 -1
  283. package/lib/contracts/FabricConstruction.js.map +0 -1
  284. package/lib/contracts/FabricContractPaginator.js.map +0 -1
  285. package/lib/contracts/FabricContractRepository.js.map +0 -1
  286. package/lib/contracts/FabricContractRepositoryObservableHandler.js.map +0 -1
  287. package/lib/contracts/FabricContractSequence.js.map +0 -1
  288. package/lib/contracts/FabricContractStatement.js.map +0 -1
  289. package/lib/contracts/PrivateSequence.js.map +0 -1
  290. package/lib/contracts/auth/decorators.js.map +0 -1
  291. package/lib/contracts/auth/index.js.map +0 -1
  292. package/lib/contracts/crud/crud-contract.js.map +0 -1
  293. package/lib/contracts/crud/index.js.map +0 -1
  294. package/lib/contracts/crud/serialized-crud-contract.js.map +0 -1
  295. package/lib/contracts/erc20/erc20contract.js.map +0 -1
  296. package/lib/contracts/erc20/index.js.map +0 -1
  297. package/lib/contracts/erc20/models.js.map +0 -1
  298. package/lib/contracts/index.js.map +0 -1
  299. package/lib/contracts/logging.js.map +0 -1
  300. package/lib/contracts/overrides.js.map +0 -1
  301. package/lib/contracts/private-data.js.map +0 -1
  302. package/lib/contracts/types.js.map +0 -1
  303. package/lib/contracts/uuid.js.map +0 -1
  304. package/lib/esm/bin/cli.js.map +0 -1
  305. package/lib/esm/cli-module.js.map +0 -1
  306. package/lib/esm/cli-utils.js.map +0 -1
  307. package/lib/esm/client/FabricClientAdapter.js.map +0 -1
  308. package/lib/esm/client/FabricClientDispatch.js.map +0 -1
  309. package/lib/esm/client/FabricClientPaginator.js.map +0 -1
  310. package/lib/esm/client/FabricClientRepository.js.map +0 -1
  311. package/lib/esm/client/FabricClientStatement.js.map +0 -1
  312. package/lib/esm/client/collections/generation.js.map +0 -1
  313. package/lib/esm/client/collections/index.js.map +0 -1
  314. package/lib/esm/client/constants.js.map +0 -1
  315. package/lib/esm/client/crypto.js.map +0 -1
  316. package/lib/esm/client/erc20/FabricERC20ClientRepository.js.map +0 -1
  317. package/lib/esm/client/erc20/index.js.map +0 -1
  318. package/lib/esm/client/fabric-fs.js.map +0 -1
  319. package/lib/esm/client/fabric-hsm.js.map +0 -1
  320. package/lib/esm/client/index.js.map +0 -1
  321. package/lib/esm/client/indexes/generation.js.map +0 -1
  322. package/lib/esm/client/indexes/index.js.map +0 -1
  323. package/lib/esm/client/logging.js.map +0 -1
  324. package/lib/esm/client/services/FabricEnrollmentService.js.map +0 -1
  325. package/lib/esm/client/services/FabricIdentityService.js.map +0 -1
  326. package/lib/esm/client/services/RegistrationRequestBuilder.js.map +0 -1
  327. package/lib/esm/client/services/constants.js.map +0 -1
  328. package/lib/esm/client/services/index.js.map +0 -1
  329. package/lib/esm/client/types.js.map +0 -1
  330. package/lib/esm/client/utils.js.map +0 -1
  331. package/lib/esm/contract/Address.js.map +0 -1
  332. package/lib/esm/contract/AddressContract.js.map +0 -1
  333. package/lib/esm/contract/BatchContract.js.map +0 -1
  334. package/lib/esm/contract/MarketContract.js.map +0 -1
  335. package/lib/esm/contract/OtherProductContract.js.map +0 -1
  336. package/lib/esm/contract/OtherProductSharedContract.js.map +0 -1
  337. package/lib/esm/contract/Product.js.map +0 -1
  338. package/lib/esm/contract/ProductContract.js.map +0 -1
  339. package/lib/esm/contract/ProductStrengthContract.js.map +0 -1
  340. package/lib/esm/contract/SegregatedPrivateDocumentContract.js.map +0 -1
  341. package/lib/esm/contract/SegregatedSharedDocumentContract.js.map +0 -1
  342. package/lib/esm/contract/User.js.map +0 -1
  343. package/lib/esm/contract/UserContract.js.map +0 -1
  344. package/lib/esm/contract/index.js.map +0 -1
  345. package/lib/esm/contract/models/Audit.js.map +0 -1
  346. package/lib/esm/contract/models/BaseIdentifiedModel.js.map +0 -1
  347. package/lib/esm/contract/models/BaseModel.js.map +0 -1
  348. package/lib/esm/contract/models/Batch.js.map +0 -1
  349. package/lib/esm/contract/models/Leaflet.js.map +0 -1
  350. package/lib/esm/contract/models/LeafletFile.js.map +0 -1
  351. package/lib/esm/contract/models/Market.js.map +0 -1
  352. package/lib/esm/contract/models/OtherProduct.js.map +0 -1
  353. package/lib/esm/contract/models/OtherProductShared.js.map +0 -1
  354. package/lib/esm/contract/models/Product.js.map +0 -1
  355. package/lib/esm/contract/models/ProductStrength.js.map +0 -1
  356. package/lib/esm/contract/models/SegregatedDocument.js.map +0 -1
  357. package/lib/esm/contract/models/constants.js.map +0 -1
  358. package/lib/esm/contract/models/decorators.js.map +0 -1
  359. package/lib/esm/contract/models/gtin.js.map +0 -1
  360. package/lib/esm/contracts/ContractAdapter.js.map +0 -1
  361. package/lib/esm/contracts/ContractContext.js.map +0 -1
  362. package/lib/esm/contracts/ContractPrivateDataAdapter.js.map +0 -1
  363. package/lib/esm/contracts/FabricConstruction.js.map +0 -1
  364. package/lib/esm/contracts/FabricContractPaginator.js.map +0 -1
  365. package/lib/esm/contracts/FabricContractRepository.js.map +0 -1
  366. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js.map +0 -1
  367. package/lib/esm/contracts/FabricContractSequence.js.map +0 -1
  368. package/lib/esm/contracts/FabricContractStatement.js.map +0 -1
  369. package/lib/esm/contracts/PrivateSequence.js.map +0 -1
  370. package/lib/esm/contracts/auth/decorators.js.map +0 -1
  371. package/lib/esm/contracts/auth/index.js.map +0 -1
  372. package/lib/esm/contracts/crud/crud-contract.js.map +0 -1
  373. package/lib/esm/contracts/crud/index.js.map +0 -1
  374. package/lib/esm/contracts/crud/serialized-crud-contract.js.map +0 -1
  375. package/lib/esm/contracts/erc20/erc20contract.js.map +0 -1
  376. package/lib/esm/contracts/erc20/index.js.map +0 -1
  377. package/lib/esm/contracts/erc20/models.js.map +0 -1
  378. package/lib/esm/contracts/index.js.map +0 -1
  379. package/lib/esm/contracts/logging.js.map +0 -1
  380. package/lib/esm/contracts/overrides.js.map +0 -1
  381. package/lib/esm/contracts/private-data.js.map +0 -1
  382. package/lib/esm/contracts/types.js.map +0 -1
  383. package/lib/esm/contracts/uuid.js.map +0 -1
  384. package/lib/esm/index.js.map +0 -1
  385. package/lib/esm/shared/ClientSerializer.js.map +0 -1
  386. package/lib/esm/shared/DeterministicSerializer.js.map +0 -1
  387. package/lib/esm/shared/SimpleDeterministicSerializer.js.map +0 -1
  388. package/lib/esm/shared/constants.js.map +0 -1
  389. package/lib/esm/shared/decorators.js.map +0 -1
  390. package/lib/esm/shared/erc20/erc20-constants.js.map +0 -1
  391. package/lib/esm/shared/erc20/index.js.map +0 -1
  392. package/lib/esm/shared/errors.js.map +0 -1
  393. package/lib/esm/shared/events.js.map +0 -1
  394. package/lib/esm/shared/fabric-types.js.map +0 -1
  395. package/lib/esm/shared/index.js.map +0 -1
  396. package/lib/esm/shared/interfaces/Checkable.js.map +0 -1
  397. package/lib/esm/shared/interfaces/index.js.map +0 -1
  398. package/lib/esm/shared/math.js.map +0 -1
  399. package/lib/esm/shared/model/FabricBaseModel.js.map +0 -1
  400. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js.map +0 -1
  401. package/lib/esm/shared/model/Identity.js.map +0 -1
  402. package/lib/esm/shared/model/IdentityCredentials.js.map +0 -1
  403. package/lib/esm/shared/model/index.js.map +0 -1
  404. package/lib/esm/shared/overrides/Model.js.map +0 -1
  405. package/lib/esm/shared/overrides/index.js.map +0 -1
  406. package/lib/esm/shared/overrides/overrides.js.map +0 -1
  407. package/lib/esm/shared/types.js.map +0 -1
  408. package/lib/esm/version.js.map +0 -1
  409. package/lib/index.js.map +0 -1
  410. package/lib/shared/ClientSerializer.js.map +0 -1
  411. package/lib/shared/DeterministicSerializer.js.map +0 -1
  412. package/lib/shared/SimpleDeterministicSerializer.js.map +0 -1
  413. package/lib/shared/constants.js.map +0 -1
  414. package/lib/shared/decorators.js.map +0 -1
  415. package/lib/shared/erc20/erc20-constants.js.map +0 -1
  416. package/lib/shared/erc20/index.js.map +0 -1
  417. package/lib/shared/errors.js.map +0 -1
  418. package/lib/shared/events.js.map +0 -1
  419. package/lib/shared/fabric-types.js.map +0 -1
  420. package/lib/shared/index.js.map +0 -1
  421. package/lib/shared/interfaces/Checkable.js.map +0 -1
  422. package/lib/shared/interfaces/index.js.map +0 -1
  423. package/lib/shared/math.js.map +0 -1
  424. package/lib/shared/model/FabricBaseModel.js.map +0 -1
  425. package/lib/shared/model/FabricIdentifiedBaseModel.js.map +0 -1
  426. package/lib/shared/model/Identity.js.map +0 -1
  427. package/lib/shared/model/IdentityCredentials.js.map +0 -1
  428. package/lib/shared/model/index.js.map +0 -1
  429. package/lib/shared/overrides/Model.js.map +0 -1
  430. package/lib/shared/overrides/index.js.map +0 -1
  431. package/lib/shared/overrides/overrides.js.map +0 -1
  432. package/lib/shared/types.js.map +0 -1
  433. package/lib/version.js.map +0 -1
@@ -1,2 +1,3117 @@
1
- var e,t;e=this,t=function(e,t,r,i,a,o,s,n,c,l,d,u,h,g,p,f){"use strict";function y(e){var t=Object.create(null);return e&&Object.keys(e).forEach(r=>{if("default"!==r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i.get?i:{enumerable:!0,get:()=>e[r]})}}),t.default=e,Object.freeze(t)}var m=y(h),w=y(p);class b extends t.Repository{constructor(e,t){super(e,t),this._overrides=Object.assign({},super._overrides,{ignoreValidation:!0,ignoreHandlers:!0,allowRawStatements:!1,forcePrepareSimpleQueries:!0,forcePrepareComplexQueries:!0,allowGenerationOverride:!1})}override(e){return super.override(Object.assign({},e,this._overrides)).for(e)}ObserverHandler(){return super.ObserverHandler()}async paginateBy(e,i,a={offset:1,limit:10},...o){const{log:s,ctxArgs:n}=(await this.logCtx(o,t.PreparedStatementKeys.PAGE_BY,!0)).for(this.paginateBy);return s.verbose(`paginating ${r.Model.tableName(this.class)} with page size ${a.limit}`),this.statement(this.paginateBy.name,e,i,{limit:a.limit,offset:a.offset,bookmark:a.bookmark},...n)}async listBy(e,i,...a){const{log:o,ctxArgs:s}=(await this.logCtx(a,t.PreparedStatementKeys.LIST_BY,!0)).for(this.listBy);return o.verbose(`listing ${r.Model.tableName(this.class)} by ${e} ${i}`),await this.statement(this.listBy.name,e,i,...s)}async findBy(e,i,...a){const{log:o,ctxArgs:s}=(await this.logCtx(a,t.PreparedStatementKeys.FIND_BY,!0)).for(this.findBy);return o.verbose(`finding all ${r.Model.tableName(this.class)} with ${e} ${i}`),await this.statement(this.findBy.name,e,i,...s)}async findOneBy(e,i,...a){const{log:o,ctxArgs:s}=(await this.logCtx(a,t.PreparedStatementKeys.FIND_ONE_BY,!0)).for(this.findOneBy);return o.verbose(`finding One ${r.Model.tableName(this.class)} with ${e} ${i}`),await this.statement(this.findOneBy.name,e,i,...s)}async find(e,i=t.OrderDirection.ASC,...a){const{log:o,ctxArgs:s}=(await this.logCtx(a,t.PreparedStatementKeys.FIND,!0)).for(this.find);return o.verbose(`finding ${r.Model.tableName(this.class)} by default query attributes`),await this.statement(this.find.name,e,i,...s)}async page(e,i=t.OrderDirection.ASC,a={offset:1,limit:10},...o){const{log:s,ctxArgs:n}=(await this.logCtx(o,t.PreparedStatementKeys.PAGE,!0)).for(this.page);return s.verbose(`paging ${r.Model.tableName(this.class)} by default query attributes`),await this.statement(this.page.name,e,i,a,...n)}async statement(e,...i){const{log:o,ctx:s,ctxArgs:n}=(await this.logCtx(i,t.PersistenceKeys.STATEMENT,!0)).for(this.statement);o.verbose("Executing prepared statement "+e);const c=n.slice(0,-1),l=JSON.parse(this.adapter.decode(await this.adapter.evaluateTransaction(s,t.PersistenceKeys.STATEMENT,[e,JSON.stringify(c)],void 0,void 0,this.class.name)));return Array.isArray(l)?l.map(e=>e[a.CouchDBKeys.TABLE]&&e[a.CouchDBKeys.TABLE]===r.Model.tableName(this.class)?new this.class(e):e):l[a.CouchDBKeys.TABLE]&&l[a.CouchDBKeys.TABLE]===r.Model.tableName(this.class)?new this.class(l):t.Paginator.isSerializedPage(l)?Object.assign(l,{data:l.data.map(e=>new this.class(e))}):l}async countOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.COUNT_OF,!0)).for(this.countOf);a.verbose(`counting ${r.Model.tableName(this.class)}${e?" by "+e:""}`);const s=e?[e,...o]:o;return this.statement(t.PreparedStatementKeys.COUNT_OF,...s)}async maxOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.MAX_OF,!0)).for(this.maxOf);return a.verbose(`finding max of ${e} in ${r.Model.tableName(this.class)}`),this.statement(t.PreparedStatementKeys.MAX_OF,e,...o)}async minOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.MIN_OF,!0)).for(this.minOf);return a.verbose(`finding min of ${e} in ${r.Model.tableName(this.class)}`),this.statement(t.PreparedStatementKeys.MIN_OF,e,...o)}async avgOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.AVG_OF,!0)).for(this.avgOf);return a.verbose(`calculating avg of ${e} in ${r.Model.tableName(this.class)}`),this.statement(t.PreparedStatementKeys.AVG_OF,e,...o)}async sumOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.SUM_OF,!0)).for(this.sumOf);return a.verbose(`calculating sum of ${e} in ${r.Model.tableName(this.class)}`),this.statement(t.PreparedStatementKeys.SUM_OF,e,...o)}async distinctOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.DISTINCT_OF,!0)).for(this.distinctOf);return a.verbose(`finding distinct values of ${e} in ${r.Model.tableName(this.class)}`),this.statement(t.PreparedStatementKeys.DISTINCT_OF,e,...o)}async groupOf(e,...i){const{log:a,ctxArgs:o}=(await this.logCtx(i,t.PreparedStatementKeys.GROUP_OF,!0)).for(this.groupOf);return a.verbose(`grouping ${r.Model.tableName(this.class)} by ${e}`),this.statement(t.PreparedStatementKeys.GROUP_OF,e,...o)}async create(e,...t){const{ctx:i,log:a,ctxArgs:o}=this.logCtx(t,this.create);a.debug(`Creating new ${this.class.name} in table ${r.Model.tableName(this.class)}`);let{record:s,id:n,transient:c}=this.adapter.prepare(e,i);return s=await this.adapter.create(this.class,n,s,c,...o),this.adapter.revert(s,this.class,n,c,i)}async update(e,...t){const{ctxArgs:i,log:a,ctx:o}=this.logCtx(t,this.update);let{record:s,id:n,transient:c}=this.adapter.prepare(e,o);return a.debug(`updating ${this.class.name} in table ${r.Model.tableName(this.class)} with id ${n}`),s=await this.adapter.update(this.class,n,s,c,...i),this.adapter.revert(s,this.class,n,c,o)}async createAllPrefix(e,...t){const{ctx:r,ctxArgs:a}=(await this.logCtx(t,i.OperationKeys.CREATE,!0)).for(this.createAllPrefix),o=r.get("ignoreHandlers"),s=r.get("ignoreValidation");if(!e.length)return[e,...a];if(e=await Promise.all(e.map(async e=>(e=new this.class(e),o||await i.enforceDBDecorators(this,r,e,i.OperationKeys.CREATE,i.OperationKeys.ON),e))),!s){const t=r.get("ignoredValidationProperties")||[],a=await Promise.all(e.map(e=>Promise.resolve(e.hasErrors(...t)))),o=i.reduceErrorsToPrint(a);if(o)throw new i.ValidationError(o)}return[e,...a]}async createAll(e,...t){if(!e.length)return e;const{ctx:i,log:a,ctxArgs:o}=this.logCtx(t,this.createAll);a.debug(`Creating ${e.length} new ${this.class.name} in table ${r.Model.tableName(this.class)}`);const s=e.map(e=>this.adapter.prepare(e,i)),n=s.map(e=>e.id);let c=s.map(e=>e.record);const l=s.map(e=>e.transient);return c=await this.adapter.createAll(this.class,n,c,l,...o),c.map((e,t)=>this.adapter.revert(e,this.class,n[t],i.get("rebuildWithTransient")?s[t].transient:void 0,i))}async updateAll(e,...t){const{ctx:i,log:a,ctxArgs:o}=this.logCtx(t,this.updateAll);a.debug(`Updating ${e.length} new ${this.class.name} in table ${r.Model.tableName(this.class)}`);const s=e.map(e=>this.adapter.prepare(e,i));return(await this.adapter.updateAll(this.class,s.map(e=>e.id),s.map(e=>e.record),s.map(e=>e.transient),...o)).map((e,t)=>this.adapter.revert(e,this.class,s[t].id,i.get("rebuildWithTransient")?s[t].transient:void 0,i))}}let E=class extends t.BaseModel{constructor(e){super(e)}};o.__decorate([t.pk({type:String}),o.__metadata("design:type",String)],E.prototype,"name",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",String)],E.prototype,"owner",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",String)],E.prototype,"symbol",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",Number)],E.prototype,"decimals",void 0),E=o.__decorate([t.table("erc20_tokens"),r.model(),o.__metadata("design:paramtypes",[Object])],E);let C=class extends t.BaseModel{constructor(e){super(e)}};o.__decorate([t.pk({type:String}),o.__metadata("design:type",String)],C.prototype,"id",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",String)],C.prototype,"token",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",Number)],C.prototype,"balance",void 0),o.__decorate([t.column(),o.__metadata("design:type",String)],C.prototype,"captive",void 0),C=o.__decorate([t.table("erc20_wallets"),r.model(),o.__metadata("design:paramtypes",[Object])],C);let A=class extends t.BaseModel{constructor(e){super(e)}};o.__decorate([t.pk({type:String}),t.column(),r.required(),o.__metadata("design:type",String)],A.prototype,"owner",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",String)],A.prototype,"spender",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",Number)],A.prototype,"value",void 0),A=o.__decorate([t.table("erc20_allowances"),r.model(),o.__metadata("design:paramtypes",[Object])],A);class v extends r.JSONSerializer{constructor(){super()}preSerialize(e,t){const a=Object.assign({},e);let o=s.Metadata.modelName(e.constructor);if(!o||"Object"===o){if(!t)throw new i.SerializationError("Could not find metadata for "+e.constructor.name);o=t}return a[r.ModelKeys.ANCHOR]=o,a}deserialize(e){const t=JSON.parse(e),i=t[r.ModelKeys.ANCHOR];if(!i)throw Error("Could not find class reference in serialized model");return r.Model.build(t,i)}serialize(e,t){return JSON.stringify(this.preSerialize(e,t))}}class S extends b{static{this.serializer=new v}static{this.decoder=new TextDecoder("utf8")}async updateObservers(e,a,o,...s){if(!this.observerHandler)throw new i.InternalError("ObserverHandler not initialized. Did you register any observables?");const{log:n,ctxArgs:c}=this.logCtx(s,this.updateObservers);let l;n.verbose(`Updating ${this.observerHandler.count()} observers for ${this}`),e="string"==typeof e?r.Model.get(e):e,l=void 0===o?void 0:Array.isArray(o)?o.map(i=>t.Sequence.parseValue(r.Model.sequenceFor(e).type,i)):t.Sequence.parseValue(r.Model.sequenceFor(e).type,o),await this.observerHandler.updateObservers(e,a,l,...c)}decode(e){return S.decoder.decode(e)}constructor(e){super(e,C),this.serializer=S.serializer}async tokenName(...e){const{ctx:t}=(await this.logCtx(e,"tokenName",!0)).for(this.tokenName),r=await this.adapter.evaluateTransaction(t,"TokenName");return this.decode(r)}async symbol(...e){const{ctx:t}=(await this.logCtx(e,"symbol",!0)).for(this.symbol),r=await this.adapter.evaluateTransaction(t,"Symbol");return this.decode(r)}async decimals(...e){const{ctx:t}=(await this.logCtx(e,"decimals",!0)).for(this.decimals),r=await this.adapter.evaluateTransaction(t,"Decimals");return Number(this.decode(r))}async totalSupply(...e){const{ctx:t}=(await this.logCtx(e,"totalSupply",!0)).for(this.totalSupply),r=await this.adapter.evaluateTransaction(t,"TotalSupply");return Number(this.decode(r))}async balanceOf(e,...t){const{ctx:r}=(await this.logCtx(t,"balance",!0)).for(this.balanceOf),i=await this.adapter.evaluateTransaction(r,"BalanceOf",[e]);return Number(this.decode(i))}async transfer(e,t,...r){const{ctx:i}=(await this.logCtx(r,"transfer",!0)).for(this.transfer),a=await this.adapter.submitTransaction(i,"Transfer",[e,t.toString()]);return"true"===this.decode(a)}async transferFrom(e,r,i){const a=await t.Context.args("transferFrom",this.class,[],this.adapter,this._overrides||{}),{ctx:o}=this.logCtx(a.args,this.transferFrom),s=await this.adapter.submitTransaction(o,"TransferFrom",[e,r,i.toString()]);return"true"===this.decode(s)}async approve(e,r){const i=await t.Context.args("approve",this.class,[],this.adapter,this._overrides||{}),{ctx:a}=this.logCtx(i.args,this.approve),o=await this.adapter.submitTransaction(a,"Approve",[e,r.toString()]);return"true"===this.decode(o)}async allowance(e,r){const i=await t.Context.args("allowance",this.class,[],this.adapter,this._overrides||{}),{ctx:a}=this.logCtx(i.args,this.allowance),o=await this.adapter.submitTransaction(a,"Allowance",[e,r]);return Number(this.decode(o))}async initialize(e){const r=await t.Context.args("initialize",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.initialize),a=await this.adapter.submitTransaction(i,"Initialize",[S.serializer.serialize(e)]);return"true"===this.decode(a)}async checkInitialized(){const e=await t.Context.args("checkInitialized",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.checkInitialized);await this.adapter.evaluateTransaction(r,"CheckInitialized")}async mint(e){const r=await t.Context.args("mint",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.mint);await this.adapter.submitTransaction(i,"Mint",[e.toString()])}async burn(e){const r=await t.Context.args("burn",this.class,[],this.adapter,this._overrides||{}),{ctx:i}=this.logCtx(r.args,this.burn);await this.adapter.submitTransaction(i,"Burn",[e.toString()])}async burnFrom(e,r){const i=await t.Context.args("burnFrom",this.class,[],this.adapter,this._overrides||{}),{ctx:a}=this.logCtx(i.args,this.burnFrom);await this.adapter.submitTransaction(a,"BurnFrom",[e,r.toString()])}async clientAccountBalance(){const e=await t.Context.args("accountBalance",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.clientAccountBalance),i=await this.adapter.evaluateTransaction(r,"ClientAccountBalance");return Number(this.decode(i))}async clientAccountID(){const e=await t.Context.args("accountId",this.class,[],this.adapter,this._overrides||{}),{ctx:r}=this.logCtx(e.args,this.clientAccountID),i=await this.adapter.evaluateTransaction(r,"ClientAccountID");return this.decode(i)}}function O(e){const t=require("fs"),r=require("path").dirname(e);if(t.existsSync(r))return!0;O(r),t.mkdirSync(r)}function _(e){const t=require("path"),i=require(t.join(process.cwd(),e.parentPath,e.name));return Object.values(i).filter(e=>{try{return new e instanceof r.Model}catch(e){return!1}})}var I;e.IdentityCredentials=class extends t.BaseModel{constructor(e){super(e)}},o.__decorate([s.description("Unique identifier of the credentials record"),t.column(),t.pk(),o.__metadata("design:type",String)],e.IdentityCredentials.prototype,"id",void 0),o.__decorate([s.description("PEM-encoded X.509 certificate for the identity"),t.column(),r.required(),o.__metadata("design:type",String)],e.IdentityCredentials.prototype,"certificate",void 0),o.__decorate([s.description("PEM-encoded root or intermediate certificate"),t.column(),r.required(),o.__metadata("design:type",String)],e.IdentityCredentials.prototype,"rootCertificate",void 0),o.__decorate([s.description("PEM-encoded private key"),t.column(),r.required(),o.__metadata("design:type",String)],e.IdentityCredentials.prototype,"privateKey",void 0),e.IdentityCredentials=o.__decorate([r.model(),o.__metadata("design:paramtypes",[Object])],e.IdentityCredentials),e.FabricModelKeys=void 0,(I=e.FabricModelKeys||(e.FabricModelKeys={})).PRIVATE="private",I.SHARED="shared",I.FABRIC="fabric",I.OWNED_BY="owned-by",I.TRANSACTION_ID="transaction-id",I.MIRROR="mirror",e.IdentityType=void 0,(e.IdentityType||(e.IdentityType={})).X509="X.509";const M="hlf-fabric";e.Identity=class extends t.BaseModel{constructor(t){super(t),this.type=e.IdentityType.X509}},o.__decorate([s.description("Unique identifier of the identity"),t.pk(),o.__metadata("design:type",String)],e.Identity.prototype,"id",void 0),o.__decorate([t.oneToOne(e.IdentityCredentials,{update:t.Cascade.CASCADE,delete:t.Cascade.CASCADE}),o.__metadata("design:type",e.IdentityCredentials)],e.Identity.prototype,"credentials",void 0),o.__decorate([t.column(),r.required(),t.index(),o.__metadata("design:type",String)],e.Identity.prototype,"mspId",void 0),o.__decorate([t.column(),r.required(),o.__metadata("design:type",String)],e.Identity.prototype,"type",void 0),e.Identity=o.__decorate([r.model(),o.__metadata("design:paramtypes",[Object])],e.Identity);class x{static{this.logger=new c.MiniLogger(x.name)}constructor(){}static async contentOfLoadFile(e,t){return e instanceof Uint8Array||e.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)?e:await t(e)}static async readFile(e){return"string"!=typeof e?e:await(async e=>{const{promises:r}=await t.normalizeImport(import("fs"));return await r.readFile(e)})(e)}static async getCAUser(e,t,i,a,o){this.logger.debug(r.stringFormat("Creating CA {0} user {1} with certificate {2}",a,e,i));const s=new d.User(e),n=o?.hsm?{software:!1,lib:o.hsm.library,slot:o.hsm.slot,label:o.hsm.tokenLabel,pin:o.hsm.pin+""}:void 0,c=this.getCryptoSuite(n);s.setCryptoSuite(c);const l=o?.hsm?await this.getHSMEnrollmentKey(c,i,o.hsm):this.getSoftwareEnrollmentKey(c,t);return await s.setEnrollment(l,i,a),s}static getCryptoSuite(e){return e?(x.cryptoSuite||(x.cryptoSuite=d.User.newCryptoSuite(e)),x.cryptoSuite):d.User.newCryptoSuite()}static getSoftwareEnrollmentKey(e,t){if(!t)throw Error("Private key must be provided when HSM configuration is not supplied");return e.createKeyFromRaw(t)}static async getHSMEnrollmentKey(e,t,r){const i=r.keyIdHex&&r.keyIdHex.trim().length>0?Buffer.from(r.keyIdHex,"hex"):await this.getCertificateSKI(t),a=await e.getKey(i);if(!a||"function"==typeof a.isPrivate&&!a.isPrivate())throw Error("Unable to resolve private key from HSM");return a}static async getCertificateSKI(e){const t=new u.X509Certificate(e).publicKey.export({format:"jwk"}),r=Buffer.from([4]),i=Buffer.from(t.x||"","base64url"),a=Buffer.from(t.y||"","base64url");return u.createHash("sha256").update(Buffer.concat([r,i,a])).digest()}static async getIdentity(e,r){return{mspId:e,credentials:await this.contentOfLoadFile(r,async e=>{const{promises:r}=await t.normalizeImport(import("fs")),i=await this.getFirstDirFileName(e);return await r.readFile(i)})}}static async getFirstDirFileName(e){const{promises:r}=await t.normalizeImport(import("fs")),{join:i}=await t.normalizeImport(import("path"));return i(e,(await r.readdir(e))[0])}static async getFirstDirFileNameContent(e){const{promises:r}=await t.normalizeImport(import("fs")),{join:i}=await t.normalizeImport(import("path")),a=await r.readdir(e);return(await r.readFile(i(e,a[0]))).toString()}static async getFileContent(e){const{promises:r}=await t.normalizeImport(import("fs"));return(await r.readFile(e)).toString()}static async getSigner(e){const r=await this.contentOfLoadFile(e,async e=>{const{promises:r}=await t.normalizeImport(import("fs")),i=await this.getFirstDirFileName(e);return await r.readFile(i)}),i=await this.extractPrivateKey(r),a=i[Object.getOwnPropertySymbols(i)[0]];return l.signers.newPrivateKeySigner(a)}static async extractPrivateKey(e){let r;if(globalThis.window&&globalThis.window.Crypto)r=globalThis.Crypto.subtle;else{const e=await t.normalizeImport(import("crypto"));r=e.subtle||e.webcrypto.subtle}if(!r)throw Error("Could not load SubtleCrypto module");const i=e.toString("utf8").replace("-----BEGIN PRIVATE KEY-----","").replaceAll("\n","").replace("-----END PRIVATE KEY-----",""),a=(e=>{const t=new ArrayBuffer(e.length),r=new Uint8Array(t);for(let t=0,i=e.length;i>t;t++)r[t]=e.charCodeAt(t);return t})(Buffer.from(i,"base64").toString("binary"));return await r.importKey("pkcs8",a,{name:"ECDSA",namedCurve:"P-256"},!0,["sign"])}}const N=new g.Crypto;var T,F,R,$,B;m.cryptoProvider.set(N),e.BASE_ALPHABET=void 0,(T=e.BASE_ALPHABET||(e.BASE_ALPHABET={})).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-_.!~",e.CRYPTO=void 0,(F=e.CRYPTO||(e.CRYPTO={})).HASH="SHA-256",F[F.ITERATIONS=1e3]="ITERATIONS",F[F.KEYLENGTH=48]="KEYLENGTH",F[F.DERIVED_IV_LENGTH=16]="DERIVED_IV_LENGTH",F[F.DERIVED_KEY_LENGTH=32]="DERIVED_KEY_LENGTH",F.ALGORYTHM="AES-GCM",F.KEY_ALGORYTHM="PBKDF2";class P{constructor(e){if(this.alphabet=e,this.baseMap=new Uint8Array(256),this.alphabet.length>=255)throw Error("Alphabet too long");for(let e=0;e<this.baseMap.length;e++)this.baseMap[e]=255;for(let t=0;t<e.length;t++){const r=e.charAt(t),i=r.charCodeAt(0);if(255!==this.baseMap[i])throw Error(r+" is ambiguous");this.baseMap[i]=t}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(e){if("string"==typeof e?e=Buffer.from(e):ArrayBuffer.isView(e)?e=new Uint8Array(e.buffer,e.byteOffset,e.byteLength):Array.isArray(e)&&(e=Uint8Array.from(e)),0===e.length)return"";let t=0,r=0,i=0;const a=e.length;for(;i!==a&&0===e[i];)i++,t++;const o=(a-i)*this.iFactor+1>>>0,s=new Uint8Array(o);for(;i!==a;){let t=e[i],a=0;for(let e=o-1;(0!==t||r>a)&&-1!==e;e--,a++)t+=256*s[e]>>>0,s[e]=t%this.base>>>0,t=t/this.base>>>0;if(0!==t)throw Error("Non-zero carry");r=a,i++}let n=o-r;for(;n!==o&&0===s[n];)n++;let c=this.leader.repeat(t);for(;o>n;++n)c+=this.alphabet.charAt(s[n]);return c}decodeUnsafe(e){if(0===e.length)return new Uint8Array(0);let t=0,r=0,i=0;for(;e[t]===this.leader;)r++,t++;const a=(e.length-t)*this.factor+1>>>0,o=new Uint8Array(a);for(;e[t];){let r=this.baseMap[e.charCodeAt(t)];if(255===r)return;let s=0;for(let e=a-1;(0!==r||i>s)&&-1!==e;e--,s++)r+=this.base*o[e]>>>0,o[e]=r%256>>>0,r=r/256>>>0;if(0!==r)throw Error("Non-zero carry");i=s,t++}let s=a-i;for(;s!==a&&0===o[s];)s++;const n=new Uint8Array(r+(a-s));let c=r;for(;s!==a;)n[c++]=o[s++];return n}decode(e){const t=this.decodeUnsafe(e);if(t)return t;throw Error("Non-base"+this.base+" character")}}class K{static{this.b58encoder=new P(e.BASE_ALPHABET.BASE58)}static{this.logger=new c.MiniLogger(K.name)}constructor(){}static fabricIdFromCertificate(e){this.logger.debug(r.stringFormat("Parsing certificate: {0}",e));const t=new m.X509Certificate(e),{subject:i,issuer:a}=t;return this.logger.debug(r.stringFormat("Certificate parsed with subject {0} and issuer {1}",i,a)),`x509::/${i.replaceAll(", ","/")}::/${a.replaceAll(", ","/")}`}static encode(e){return this.b58encoder.encode(e)}static decode(e){const t=this.b58encoder.decode(e);return(new TextDecoder).decode(t)}static stringToArrayBuffer(e){const t=new ArrayBuffer(e.length),r=new Uint8Array(t);for(let t=0,i=e.length;i>t;t++)r[t]=e.charCodeAt(t);return t}static async extractKey(e,t,r){const i=N.subtle,a=t.toString("utf8").replace(RegExp(`-----BEGIN (${e.toUpperCase()} KEY|CERTIFICATE)-----`),"").replaceAll("\n","").replace(RegExp(`-----END (${e.toUpperCase()} KEY|CERTIFICATE)-----`),""),o=Buffer.from(a,"base64").toString("binary"),s=this.stringToArrayBuffer(o);return await i.importKey("pkcs8",s,{name:"ECDSA",namedCurve:"P-256"},!0,r||["sign"])}static async extractPrivateKey(e,t){return this.extractKey("private",e,t)}static async extractPublicKey(e,t){return this.extractKey("public",e,t)}static async sign(e,t){const r=await this.extractPrivateKey(e),i=await N.subtle.sign({name:"ECDSA",hash:"SHA-256"},r,t);return Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,"0")).join("")}static async verify(e,t,r){const i=new m.X509Certificate(e),a=await i.publicKey.export();return t="string"==typeof t?Buffer.from(t,"hex"):t,r="string"==typeof r?Buffer.from(r):r,N.subtle.verify({name:"ECDSA",hash:"SHA-256"},a,t,r)}static async encrypt(e,t){const r=new m.X509Certificate(e),i=await r.publicKey.export();t="string"==typeof t?Buffer.from(t):t;const a=await this.getSubtleCrypto().encrypt({name:"ECDSA"},i,t);return Array.from(new Uint8Array(a)).map(e=>e.toString(16).padStart(2,"0")).join("")}static getSubtleCrypto(){return c.isBrowser()?globalThis.window.crypto.subtle:N.subtle}static async decrypt(e,t){const r=await this.extractPrivateKey(e);return t="string"==typeof t?Buffer.from(t,"hex"):t,this.getSubtleCrypto().decrypt({name:"ECDSA"},r,t)}static async getMaster(t){const r=new TextEncoder;if(void 0===t){const e=N.randomUUID();t=r.encode(e).buffer}return{key:await this.getSubtleCrypto().importKey("raw",t,e.CRYPTO.KEY_ALGORYTHM,!1,["deriveBits"]),iv:t}}static async getDerivationKey(t,r){const i=(new TextEncoder).encode(t),a=await this.getSubtleCrypto().digest("SHA-256",i),o={name:e.CRYPTO.KEY_ALGORYTHM,hash:e.CRYPTO.HASH,salt:a,iterations:e.CRYPTO.ITERATIONS},s=await this.getSubtleCrypto().deriveBits(o,r,8*e.CRYPTO.KEYLENGTH);return this.getKey(s)}static async getKey(t){const r=t.slice(0,32),i=t.slice(32);return{key:await this.getSubtleCrypto().importKey("raw",r,{name:e.CRYPTO.ALGORYTHM},!1,["encrypt","decrypt"]),iv:i}}static async encryptPin(t,r){const i=(new TextEncoder).encode(t);return await this.getSubtleCrypto().encrypt({name:e.CRYPTO.ALGORYTHM,iv:r.iv},r.key,i)}static async decryptPin(t,r){const i=new TextDecoder,a=await this.getSubtleCrypto().decrypt({name:e.CRYPTO.ALGORYTHM,iv:r.iv},r.key,t);return i.decode(a)}}class k extends i.InternalError{constructor(e){super(e,k.name)}}class z extends i.InternalError{constructor(e){super(e,z.name)}}class j extends i.InternalError{constructor(e){super(e,j.name)}}class L extends t.AuthorizationError{constructor(e){super(e,L.name)}}class U extends i.InternalError{constructor(e){super(e,U.name,500)}}class H extends i.BaseError{constructor(e="MISSING_PRIVATE_DATA_ERROR_MESSAGE"){super(H.name,e,403)}}class q extends i.BaseError{constructor(e){super(q.name,e,409)}}class G extends i.InternalError{constructor(e){super(e,G.name,500)}}class Y extends i.InternalError{constructor(e){super(e,Y.name,500)}}class V extends i.InternalError{constructor(e){super(e,V.name,500)}}class J extends i.InternalError{constructor(e){super(e,J.name,500)}}class Q extends i.InternalError{constructor(e){super(e,Q.name,500)}}class W extends i.InternalError{constructor(e,t=W.name,r=590){super(e,t,r)}}class X extends i.InternalError{constructor(e){super(e,X.name,591)}}class Z extends i.InternalError{constructor(e){super(e,Z.name,592)}}e.HFCAIdentityType=void 0,(R=e.HFCAIdentityType||(e.HFCAIdentityType={})).PEER="peer",R.ORDERER="orderer",R.CLIENT="client",R.USER="user",R.ADMIN="admin",e.HFCAIdentityAttributes=void 0,($=e.HFCAIdentityAttributes||(e.HFCAIdentityAttributes={})).HFREGISTRARROLES="hf.Registrar.Roles",$.HFREGISTRARDELEGATEROLES="hf.Registrar.DelegateRoles",$.HFREGISTRARATTRIBUTES="hf.Registrar.Attributes",$.HFINTERMEDIATECA="hf.IntermediateCA",$.HFREVOKER="hf.Revoker",$.HFAFFILIATIONMGR="hf.AffiliationMgr",$.HFGENCRL="hf.GenCRL";class ee extends c.LoggedClass{constructor(e){x.getCryptoSuite(e.hsm?{software:!1,lib:e.hsm.library,slot:e.hsm.slot,label:e.hsm.tokenLabel,pin:e.hsm.pin+""}:void 0),super(),this.caConfig=e}async User(){if(this.user)return this.user;const{caName:e,caCert:t,caKey:r,url:a,hsm:o}=this.caConfig,s=this.log.for(this.User);s.debug(`Creating CA user for ${e} at ${a}`),s.debug("Retrieving CA certificate from "+t);const n=await x.getFirstDirFileNameContent(t);let c;if(o)s.debug(`Using HSM configuration for CA ${e} with library ${o.library}`);else{if(!r)throw new i.InternalError(`Missing caKey configuration for CA ${e}. Provide a key directory or configure HSM support.`);s.debug("Retrieving CA key from "+r),c=await x.getFirstDirFileNameContent(r)}return s.debug("Loading Admin user for ca "+e),this.user=await x.getCAUser("admin",c,n,e,{hsm:o}),this.user}async CA(){if(this.ca)return this.ca;const e=this.log.for(this.CA),{url:t,tls:r,caName:i}=this.caConfig;let{trustedRoots:a,verify:o}=r;const s=a[0];e.debug(`Retrieving CA certificate from ${s}. cwd: ${process.cwd()}`);const c=await x.getFileContent(s);return e.debug(`Creating CA Client for CA ${i} under ${t}`),this.ca=new n(t,{trustedRoots:Buffer.from(c),verify:o},i),this.ca}async Client(){if(this.client)return this.client;const e=await this.CA();return this.client=e._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(e,t=!0){const r=await this.Certificate(),i=await this.User(),a=this.log.for(this.getCertificates);a.debug(`Retrieving certificates${e?" for "+e.id:""} for CA ${this.caConfig.caName}`);const o=(await r.getCertificates(e||{},i)).result;return a.debug(`Found ${o.certs.length} certificates: ${JSON.stringify(o)}`),t?o.certs.map(e=>e.PEM):o}async getIdentities(){const e=await this.Identities(),t=this.log.for(this.getIdentities);t.debug("Retrieving Identities under CA "+this.caConfig.caName);const r=(await e.getAll(await this.User())).result;return t.debug(`Found ${r.identities.length} Identities: ${JSON.stringify(r)}`),r.identities}parseError(e){const r=/.*code:\s(\d+).*?message:\s["'](.+)["']/gs.exec(e.message);if(!r)return new L(e);const[,a,o]=r;switch(a){case"74":case"71":return new i.ConflictError(o);case"20":return new t.AuthorizationError(o);default:return new L(o)}}async getAffiliations(){const e=await this.Affiliations(),t=this.log.for(this.getAffiliations);t.debug("Retrieving Affiliations under CA "+this.caConfig.caName);const r=(await e.getAll(await this.User())).result;return t.debug(`Found ${r.a.length} Affiliations: ${JSON.stringify(r)}`),r}async read(e){const t=await this.CA(),r=await this.User();let a;try{a=await t.newIdentityService().getOne(e,r)}catch(t){throw new i.NotFoundError(`Couldn't find enrollment with id ${e}: ${t}`)}if(!a.success)throw new i.NotFoundError(`Couldn't find enrollment with id ${e}: ${a.errors.join("\n")}`);return a.result}async register(e,t=!1,r="",i,a,o){let s;const n=this.log.for(this.register);try{const{userName:c,password:l}=e,d=await this.CA(),u=await this.User(),h={enrollmentID:c,enrollmentSecret:l,affiliation:r,userRole:i,attrs:a,maxEnrollments:o};s=await d.register(h,u),n.info(`Registration for ${c} created with user type ${i??"Undefined Role"} ${t?"as super user":""}`)}catch(e){throw this.parseError(e)}return s}static identityFromEnrollment(t,r){const{certificate:i,key:a,rootCertificate:o}=t,s=c.Logging.for(ee,{}).for(this.identityFromEnrollment);s.debug(`Generating Identity from certificate ${i} in msp ${r}`);const n=K.fabricIdFromCertificate(i),l=K.encode(n);s.debug(`Identity ${n} and encodedId ${l}`);const d=new Date;return new e.Identity({id:l,credentials:{id:l,certificate:i,privateKey:a.toBytes(),rootCertificate:o,createdOn:d,updatedOn:d},mspId:r,createdOn:d,updatedOn:d})}async enroll(e,t){let r;const i=this.log.for(this.enroll);try{const a=await this.CA();i.debug("Enrolling "+e);const o=await a.enroll({enrollmentID:e,enrollmentSecret:t});r=ee.identityFromEnrollment(o,this.caConfig.caName),i.info(`Successfully enrolled ${e} under ${this.caConfig.caName} as ${r.id}`)}catch(e){throw this.parseError(e)}return r}async registerAndEnroll(e,t=!1,r="",i,a,o){const s=await this.register(e,t,r,i,a,o),{userName:n}=e;return this.enroll(n,s)}async revoke(e){const t=await this.CA(),r=await this.User(),a=await this.read(e);if(!a)throw new i.NotFoundError("Could not find enrollment with id "+e);let o;try{o=await t.revoke({enrollmentID:a.id,reason:"User Deletation"},r)}catch(t){throw new i.InternalError(`Could not revoke enrollment with id ${e}: ${t}`)}if(!o.success)throw new i.InternalError(`Could not revoke enrollment with id ${e}: ${o.errors.join("\n")}`);return o}}class te extends r.Model{constructor(){super(...arguments),this.affiliation=""}build(){const e=this.hasErrors();if(e)throw new i.ValidationError(e.toString());const t={enrollmentID:this.enrollmentID,enrollmentSecret:this.enrollmentSecret,role:this.role,affiliation:this.affiliation};return void 0!==this.maxEnrollments&&(t.maxEnrollments=this.maxEnrollments),this.attrs&&(t.attrs=this.attrs),t}setAffiliation(e){return this.affiliation=e,this}addAttr(e){return this.attrs=this.attrs||[],this.attrs.push(e),this}setAttrs(e){return this.attrs=e,this}setEnrollmentID(e){return this.enrollmentID=e,this}setEnrollmentSecret(e){return this.enrollmentSecret=e,this}setMaxEnrollments(e){return this.maxEnrollments=e,this}setRole(e){return this.role=e,this}}o.__decorate([r.required(),o.__metadata("design:type",String)],te.prototype,"affiliation",void 0),o.__decorate([r.minlength(1),o.__metadata("design:type",Array)],te.prototype,"attrs",void 0),o.__decorate([r.required(),o.__metadata("design:type",String)],te.prototype,"enrollmentID",void 0),o.__decorate([r.required(),o.__metadata("design:type",String)],te.prototype,"enrollmentSecret",void 0),o.__decorate([r.min(0),o.__metadata("design:type",Number)],te.prototype,"maxEnrollments",void 0),o.__decorate([r.required(),o.__metadata("design:type",String)],te.prototype,"role",void 0),e.ERC20Events=void 0,(B=e.ERC20Events||(e.ERC20Events={})).TRANSFER="Transfer",B.APPROVAL="Approval",e.FabricBaseModel=class extends r.Model{constructor(e){super(e)}},o.__decorate([s.description("Stores the original timestamp of creation"),t.column(),t.createdAt(),o.__metadata("design:type",Date)],e.FabricBaseModel.prototype,"createdAt",void 0),o.__decorate([s.description("Stores the timestamp of the last update"),t.column(),t.updatedAt(),o.__metadata("design:type",Date)],e.FabricBaseModel.prototype,"updatedAt",void 0),o.__decorate([s.description("Stores the version of the model"),t.column(),i.version(),o.__metadata("design:type",Number)],e.FabricBaseModel.prototype,"version",void 0),e.FabricBaseModel=o.__decorate([s.uses(M),o.__metadata("design:paramtypes",[Object])],e.FabricBaseModel),e.FabricIdentifiedBaseModel=class extends e.FabricBaseModel{constructor(e){super(e)}},o.__decorate([s.description("Stores the creator"),t.column(),t.createdBy(),o.__metadata("design:type",String)],e.FabricIdentifiedBaseModel.prototype,"createdBy",void 0),o.__decorate([s.description("Stores the user that last updated the model"),t.column(),t.updatedBy(),o.__metadata("design:type",String)],e.FabricIdentifiedBaseModel.prototype,"updatedBy",void 0),e.FabricIdentifiedBaseModel=o.__decorate([s.uses(M),o.__metadata("design:paramtypes",[Object])],e.FabricIdentifiedBaseModel),r.Model.prototype.isShared=function(){return r.Model.isShared(this.constructor)},r.Model.prototype.isPrivate=function(){return r.Model.isPrivate(this.constructor)},r.Model.prototype.segregate=function(){return r.Model.segregate(this)},r.Model.segregate=(t=>{if(!r.Model.isTransient(t))return{model:t};const a=s.Metadata.validatableProperties(t.constructor),o=s.Metadata.get(t.constructor,i.DBKeys.TRANSIENT),n=s.Metadata.get(t.constructor,e.FabricModelKeys.PRIVATE),c=s.Metadata.get(t.constructor,e.FabricModelKeys.SHARED),l={model:{},transient:{},privates:{},shared:{}},d=Object.keys(o||{}),u=Object.keys(n||{}),h=Object.keys(c||{});for(const e of a){const r=t[e],i=d.includes(e),a=u.includes(e),o=h.includes(e);(i||a||o)&&(l.transient=l.transient||{},l.transient[e]=r),a&&(l.privates=l.privates||{},l.privates[e]=r),o&&(l.shared=l.shared||{},l.shared[e]=r),!i&&!a&&!o&&(l.model=l.model||{},l.model[e]=r)}return l.model=r.Model.build(l.model,t.constructor.name),l}).bind(r.Model),r.Model.isPrivate=(t=>!!s.Metadata.get("function"!=typeof t?t.constructor:t,e.FabricModelKeys.PRIVATE)).bind(r.Model),r.Model.isShared=(t=>!!s.Metadata.get("function"!=typeof t?t.constructor:t,e.FabricModelKeys.SHARED)).bind(r.Model),r.Model.mirrored=(t=>s.Metadata.get("function"!=typeof t?t.constructor:t,s.Metadata.key(e.FabricModelKeys.FABRIC,e.FabricModelKeys.MIRROR))).bind(r.Model),r.Model.ownerOf=(t=>{const r=s.Metadata.get(t.constructor,s.Metadata.key(e.FabricModelKeys.FABRIC,e.FabricModelKeys.OWNED_BY));if(r)return t[r]}).bind(r.Model),r.Model.mirroredAt=(t=>(t="function"!=typeof t?t.constructor:t,s.Metadata.get(t,s.Metadata.key(e.FabricModelKeys.FABRIC,e.FabricModelKeys.MIRROR)))).bind(r.Model),r.Model.collectionsFor=(t=>{const r=[e.FabricModelKeys.PRIVATE],i=[e.FabricModelKeys.SHARED],a=s.Metadata.key(...r),o=s.Metadata.key(...i),n="function"==typeof t?t:t.constructor,c=s.Metadata.get(n,a),l=s.Metadata.get(n,o);return{privateCols:c?.collections||[],sharedCols:l?.collections||[]}}).bind(r.Model);const re="mirror:skip:";function ie(e){if(e)return"string"==typeof e?e:e.getMSPID()}async function ae(e,t,r,i){const{stub:a}=e,o=(await a.getCreator()).mspid;Object.defineProperty(i,r,{enumerable:!0,writable:!1,configurable:!0,value:o})}async function oe(e,t,r,i){const{stub:a}=e;i[r]=a.getTxID()}async function se(e,t,a){let o=t;if("string"!=typeof o)try{const i=r.Model.ownerOf(e)||a.get("stub").getCreator().toString();t&&"function"==typeof t&&(o=await t(e,i,a))}catch(e){throw new i.InternalError("Failed to resolve collection mirror name: "+e)}if(!o||"string"!=typeof o)throw new i.InternalError("No collection found model "+e.constructor.name);return o}async function ne(e,t,i,a){const o=await se(a,t.resolver,e),s=this.override(Object.assign({},this._overrides,{segregated:o,mirror:!0,ignoreValidation:!0,ignoreHandlers:!0})),n=await s.create(a,e);e.logger.info(`Mirror for ${r.Model.tableName(this.class)} created with ${r.Model.pk(a)}: ${n[r.Model.pk(a)]}`)}async function ce(e,t,i,a){const o=await se(a,t.resolver,e),s=this.override(Object.assign({},this._overrides,{segregated:o,mirror:!0,ignoreValidation:!0,ignoreHandlers:!0,applyUpdateValidation:!1,mergeForUpdate:!1}));await s.update(a,e),e.logger.info(`Mirror for ${r.Model.tableName(this.class)} updated: ${a[r.Model.pk(a)]}`)}async function le(e,t,i,a){const o=await se(a,t.resolver,e),s=a[r.Model.pk(a)],n=this.override(Object.assign({},this._overrides,{segregated:o,mirror:!0,ignoreValidation:!0,ignoreHandlers:!0}));try{await n.delete(s,e)}catch{}e.logger.info(`Mirror for ${r.Model.tableName(this.class)} deleted: ${s+""}`)}async function de(e,r,i,a){const o=ie(e.get("identity"));if(o&&r.condition(o))throw new t.AuthorizationError(`Organization ${o} is not authorized to modify mirrored data`)}async function ue(e,t,r,i){const a=ie(e.get("identity"));if(!a)return void e.logger.debug("Mirror read: No MSP ID available, using default read behavior");const o=await se(i,t.resolver,e),s=`${re}${o}`,n=e;t.condition(a)?(e.logger.info(`Mirror read: MSP ${a} matches condition, routing ALL reads exclusively to collection ${o}`),n.put("segregated",o),n.readFrom(o),n.put(s,!1)):n.put(s,!0)}const he=(e,t)=>{const a=t||("function"!=typeof e?r.Model.ownerOf(e):void 0);if(!a)throw new i.InternalError(`Model ${e.constructor.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);return`__${c.toPascalCase(a)}PrivateCollection`};async function ge(e,t,i,a){const o=Array.isArray(t)?t:[t],s=r.Model.ownerOf(a)||ie(e.get("identity"));if(!s)return;const n=[];for(const t of o){const r=t.collections,i="string"==typeof r?r:r(a,s,e);i&&!n.includes(i)&&n.push(i)}n.length>0&&e.readFrom(n);const c=e;if(!c.isFullySegregated){const e=r.Model.pk(a),t=r.Model.segregate(a);0===Object.keys(t.model).filter(r=>r!==e&&void 0!==t.model[r]).length&&c.markFullySegregated()}const l=this.adapter,d=r.Model.tableName(a.constructor)+"_pk";l.setSequenceSegregation(d,c.isFullySegregated,n)}async function pe(e,a,o,s){const n=Array.isArray(a)?a:[a],c=Array.isArray(o)?o:[o];if(c.length!==n.length)throw new i.InternalError("Segregated data keys and metadata length mismatch");const l=r.Model.ownerOf(s)||ie(e.get("identity"));if(!l)throw new i.ValidationError("There's no assigned organization for model "+s.constructor.name);const d=n[0].collections,u="string"==typeof d?d:d(s,l,e);c.forEach((r,i)=>{const a="string"==typeof n[i].collections?n[i].collections:n[i].collections(s,l,e);if(a!==u)throw new t.UnsupportedError(`Segregated data collection mismatch: ${a} vs ${u}`)}),e.writeTo(u,s)}async function fe(e,t,a,o){const s=Array.isArray(t)?t:[t];if((Array.isArray(a)?a:[a]).length!==s.length)throw new i.InternalError("Segregated data keys and metadata length mismatch");const n=r.Model.ownerOf(o)||ie(e.get("identity"));if(!n)throw new i.ValidationError("There's no assigned organization for model "+o.constructor.name);const c=s[0].collections,l="string"==typeof c?c:await c(o,n,e),d=`${re}${l}`;e.getOrUndefined(d)||e.readFrom(l)}async function ye(e,a,o,s,n){const c=Array.isArray(a)?a:[a],l=Array.isArray(o)?o:[o];if(l.length!==c.length)throw new i.InternalError("Segregated data keys and metadata length mismatch");const d=r.Model.ownerOf(s)||ie(e.get("identity"));if(!d)throw new i.ValidationError("There's no assigned organization for model "+s.constructor.name);const u=c[0].collections,h="string"==typeof u?u:u(s,d,e);l.forEach((r,i)=>{const a="string"==typeof c[i].collections?c[i].collections:c[i].collections(s,d,e);if(a!==h)throw new t.UnsupportedError(`Segregated data collection mismatch: ${a} vs ${h}`)}),e.writeTo(h,s)}async function me(e,t,a,o){const s=Array.isArray(t)?t:[t];if((Array.isArray(a)?a:[a]).length!==s.length)throw new i.InternalError("Segregated data keys and metadata length mismatch");const n=r.Model.ownerOf(o)||ie(e.get("identity"));if(!n)throw new i.ValidationError("There's no assigned organization for model "+o.constructor.name);const c=s[0].collections,l="string"==typeof c?c:c(o,n,e);e.readFrom(l)}function we(e,t,r){return(r,a)=>{const o=[];if(!a){const i=s.Metadata.validatableProperties(r);return i?.forEach(i=>{we(e,t)(r.prototype,i)}),r}{const r="string"==typeof e?e:e.toString(),a=r+":data",n={collections:e},c={priority:35,group:r+":extract"};o.push(s.prop(),i.transient(),(r,a)=>{const o=s.Metadata.key(t,a),n=r.constructor,c=s.Metadata.get(n,o)||{},l=new Set(c.collections||[]);l.add(e),c.collections=[...l],s.Metadata.set(n,o,c);const d=s.Metadata.get(n,t)||{},u=new Set(d.collections||[]);u.add(e),d.collections=[...u],s.Metadata.set(n,t,d);const h={...s.Metadata.get(n,i.DBKeys.TRANSIENT)||{},[a]:{}};s.Metadata.set(n,i.DBKeys.TRANSIENT,h)},i.on(i.DBOperations.ALL,ge,n,c),i.onCreate(pe,{collections:e},{priority:95,group:a}),i.onRead(fe,{collections:e},{priority:95,group:a}),i.onUpdate(ye,{collections:e},{priority:95,group:a}),i.onDelete(me,{collections:e},{priority:95,group:a}))}return s.apply(...o)(r,a)}}function be(t=he){return s.Decoration.for(e.FabricModelKeys.PRIVATE).define({decorator:t=>we(t,e.FabricModelKeys.PRIVATE),args:[t]}).apply()}class Ee extends r.JSONSerializer{constructor(){super()}preSerialize(e){const t=Object.assign({},e);let i;try{i=s.Metadata.modelName(e.constructor)}catch(e){i=void 0}t[r.ModelKeys.ANCHOR]=i||e.constructor.name;const a=function e(t){const r=this;return"object"!=typeof t?t:Array.isArray(t)?t.map(t=>e.call(r,t)):this.preSerialize.call(this,t)}.bind(this);return r.Model.relations(e).forEach(e=>{t[e]=a(t[e])}),t}deserialize(e){const t=JSON.parse(e),i=t[r.ModelKeys.ANCHOR];if(!i)throw Error("Could not find class reference in serialized model");return r.Model.build(t,i)}serialize(e){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(e)))}}function Ce(e){const t=e.split("_");return 2>t.length||t.length>3?{table:void 0,event:e,owner:void 0}:{table:t[0],event:t[1],owner:t[2]}}class Ae extends r.JSONSerializer{constructor(){super()}deserialize(e,t){return JSON.parse(e)}serialize(e,t=!0){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(e,t)))}preSerialize(e,t=!0){const i=Object.assign({},e);let a;try{a=s.Metadata.modelName(e.constructor)}catch(e){a=void 0}function o(e){return"object"!=typeof e?e:Array.isArray(e)?e.map(o):this.preSerialize(e)}return t&&(i[r.ModelKeys.ANCHOR]=a||e.constructor.name),r.Model.relations(e).forEach(e=>{i[e]=o.call(this,i[e])}),i}}class ve extends t.ClientBasedService{constructor(){super()}get rootClient(){return this.client._FabricCaServices}get user(){if(!this._user)throw new i.InternalError("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(e,t){const r=t.logger.for(this.getUser),{caName:a,caCert:o,caKey:s,url:n,hsm:c}=e;r.info(`Creating CA user for ${a} at ${n}`),r.verbose("Retrieving CA certificate from "+o);const l=await x.getFirstDirFileNameContent(o);let d;if(c)r.debug(`Using HSM configuration for CA ${a} with library ${c.library}`);else{if(!s)throw new i.InternalError(`Missing caKey configuration for CA ${a}. Provide a key directory or configure HSM support.`);r.debug("Retrieving CA key from "+s),d=await x.getFirstDirFileNameContent(s)}return r.debug("Loading Admin user for ca "+a),this._user=await x.getCAUser("admin",d,l,a,{hsm:c}),this._user}async initialize(...e){const{log:r,ctx:a}=(await this.logCtx(e,t.PersistenceKeys.INITIALIZATION,!0)).for(this.initialize),[o]=e;if(!o)throw new i.InternalError("Missing Fabric CA configuration");const{url:s,tls:c,caName:l}=o;r.info(`Initializing CA Client for CA ${o.caName} at ${o.url}`);const{trustedRoots:d,verify:u}=c,h=d[0];r.debug(`Retrieving CA certificate from ${h}. cwd: ${process.cwd()}`);const g=await x.getFileContent(h);r.debug("CA Certificate: "+g.toString());const p=new n(s,{trustedRoots:Buffer.from(g),verify:u},l),f=await this.getUser(o,a);return r.debug("CA user loaded: "+f.getName()),{config:o,client:p}}async getCertificates(e,r=!0,...a){e instanceof t.Context?(a=[e],r=!0,e=void 0):"boolean"==typeof e?(r=e,e=void 0):"boolean"!=typeof r&&(a=[r,...a],r=!0);const{log:o}=(await this.logCtx(a,i.OperationKeys.READ,!0)).for(this.getCertificates);o.debug(`Retrieving certificates${e?" for "+e.id:""} for CA ${this.config.caName}`);const s=(await this.certificates.getCertificates(e||{},this.user)).result;return o.verbose(`Found ${s.certs.length} certificates`),o.debug(s.certs),r?s.certs.map(e=>e.PEM):s}async getIdentities(e){const t=e.logger.for(this.getIdentities);t.verbose("Retrieving Identities under CA "+this.config.caName);const r=(await this.identities.getAll(this.user)).result;return t.verbose(`Found ${r.identities.length} Identities`),t.debug(r.identities),r.identities}async getAffiliations(e){const t=e.logger.for(this.getAffiliations);t.verbose("Retrieving Affiliations under CA "+this.config.caName);const r=(await this.affiliations.getAll(this.user)).result;return t.verbose(`Found ${r.a.length} Affiliations`),t.debug(JSON.stringify(r)),r}parseError(e){const r=/.*code:\s(\d+).*?message:\s["'](.+)["']/gs.exec(e.message);if(!r)return new L(e);const[,a,o]=r;switch(a){case"74":case"71":return new i.ConflictError(o);case"20":return new t.AuthorizationError(o);default:return new L(o)}}async read(e,...t){const{log:r}=(await this.logCtx(t,i.OperationKeys.READ,!0)).for(this.read);let a;r.verbose("Retrieving identity with enrollment ID "+e);try{a=await this.identities.getOne(e,this.user)}catch(t){throw new i.NotFoundError(`Couldn't find enrollment with id ${e}: ${t}`)}if(!a.success)throw new i.NotFoundError(`Couldn't find enrollment with id ${e}: ${a.errors.join("\n")}`);return a.result}async register(e,t=!1,r="",i,a,o,...s){const{log:n}=(await this.logCtx(s,"register",!0)).for(this.register);let c;try{const{userName:s,password:l}=e,d={enrollmentID:s,enrollmentSecret:l,affiliation:r,userRole:i,attrs:a,maxEnrollments:o};c=await this.client.register(d,this.user),n.info(`Registration for ${s} created with user type ${i??"Undefined Role"} ${t?"as super user":""}`)}catch(e){throw this.parseError(e)}return c}static identityFromEnrollment(t,r,i){const a=i.logger.for(this.identityFromEnrollment),{certificate:o,key:s,rootCertificate:n}=t;a.verbose(`Generating Identity from certificate ${o} in msp ${r}`);const c=K.fabricIdFromCertificate(o),l=K.encode(c);return a.debug(`Identity ${c} and encodedId ${l}`),new e.Identity({id:l,credentials:{id:l,certificate:o,privateKey:s.toBytes(),rootCertificate:n},mspId:r})}async enroll(e,t,...r){const{log:i,ctx:a}=(await this.logCtx(r,"enroll",!0)).for(this.enroll);let o;try{i.debug("Enrolling "+e);const r=await this.client.enroll({enrollmentID:e,enrollmentSecret:t});o=ve.identityFromEnrollment(r,this.config.caName,a),i.info(`Successfully enrolled ${e} under ${this.config.caName} as ${o.id}`)}catch(e){throw this.parseError(e)}return o}async registerAndEnroll(e,t=!1,r="",i,a,o,...s){const{ctx:n}=(await this.logCtx(s,"register-enroll",!0)).for(this.registerAndEnroll),c=await this.register(e,t,r,i,a,o,n),{userName:l}=e;return this.enroll(l,c,n)}async reenroll(e,t,r=[],...i){const{log:a,ctx:o}=(await this.logCtx(i,"reenroll",!0)).for(this.reenroll);try{a.debug("Re-enrolling "+e);const{mspId:i,credentials:s}=t,n=d.User.createUser(e,"",i||this.user.getMspid(),s.certificate,s.privateKey);n.setCryptoSuite(this.user.getCryptoSuite());const c=await this.client.reenroll(n,r),l=ve.identityFromEnrollment(c,this.config.caName,o);return a.info(`Successfully re-enrolled ${e} under ${this.config.caName} as ${l.id}`),l}catch(e){throw this.parseError(e)}}async revoke(e,...t){const{log:r}=(await this.logCtx(t,"revoke",!0)).for(this.revoke);r.verbose("Revoking identity with enrollment ID "+e);const a=await this.read(e);if(!a)throw new i.NotFoundError("Could not find enrollment with id "+e);let o;try{o=await this.client.revoke({enrollmentID:a.id,reason:"User Deletion"},this.user)}catch(t){throw new i.InternalError(`Could not revoke enrollment with id ${e}: ${t}`)}if(!o.success)throw new i.InternalError(`Could not revoke enrollment with id ${e}: ${o.errors.join("\n")}`);return o}}var Se;e.CA_ROLE=void 0,(Se=e.CA_ROLE||(e.CA_ROLE={})).ADMIN="admin",Se.USER="user",Se.CLIENT="client";const Oe=Object.assign({evaluateTimeout:5,endorseTimeout:15,submitTimeout:5,commitTimeout:60}),_e=new c.MiniLogger("fabric-fs");async function Ie(e,t){return e instanceof Uint8Array||e.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)?e:await t(e)}async function Me(e,r){return{mspId:e,credentials:await Ie(r,async e=>{const{promises:r}=await t.normalizeImport(import("fs")),i=await xe(e);return await r.readFile(i)})}}async function xe(e){const{promises:r}=await t.normalizeImport(import("fs")),{join:i}=await t.normalizeImport(import("path"));return i(e,(await r.readdir(e))[0])}async function Ne(e){const r=await Ie(e,async e=>{const{promises:r}=await t.normalizeImport(import("fs")),i=await xe(e);return await r.readFile(i)}),i=await Te(r),a=i[Object.getOwnPropertySymbols(i)[0]];return l.signers.newPrivateKeySigner(a)}async function Te(e){let r;if(c.isBrowser())r=globalThis.crypto.subtle;else{const e=await t.normalizeImport(import("crypto"));r=e.subtle||e.webcrypto.subtle}if(!r)throw Error("Could not load SubtleCrypto module");const a=e.toString("utf8").replace("-----BEGIN PRIVATE KEY-----","").replaceAll("\n","").replace("-----END PRIVATE KEY-----",""),o=(e=>{const t=new ArrayBuffer(e.length),r=new Uint8Array(t);for(let t=0,i=e.length;i>t;t++)r[t]=e.charCodeAt(t);return t})(Buffer.from(a,"base64").toString("binary"));try{return await r.importKey("pkcs8",o,{name:"ECDSA",namedCurve:"P-256"},!0,["sign"])}catch(e){throw new i.InternalError(e)}}function De(e){if(!e)return"\0";const t=Array.from(e);for(let e=t.length-1;e>=0;e-=1){const r=t[e].codePointAt(0);if(void 0!==r&&1114111>r)return t[e]=String.fromCodePoint(r+1),t.slice(0,e+1).join("")}return e+"\0"}class Fe extends t.Statement{constructor(e,t){super(e,t)}squash(e){const r=super.squash(e);if(!r)return r;const{method:a,params:o,args:s}=r,{direction:n,limit:c}=o;switch(a){case t.PreparedStatementKeys.FIND:break;case t.PreparedStatementKeys.PAGE:s.push(n,c);break;case t.PreparedStatementKeys.FIND_BY:break;case t.PreparedStatementKeys.LIST_BY:s.push(n);break;case t.PreparedStatementKeys.PAGE_BY:s.push(n,c);break;case t.PreparedStatementKeys.FIND_ONE_BY:break;default:throw new i.InternalError("Unsupported method "+a)}return r}async executePrepared(...e){const r=t.Repository.forModel(this.fromSelector,this.adapter.alias),{method:i,args:a}=this.prepared;return r.statement(i,...a,...e)}async prepare(e){if(e=e||await this.adapter.context(t.PersistenceKeys.QUERY,this.overrides||{},this.fromSelector),this.isSimpleQuery()&&e.get("forcePrepareSimpleQueries")){const t=this.squash(e);if(t)return this.prepared=t,this}const r=[],i={},a={class:this.fromSelector,args:r,params:i},o=[t.QueryClause.FIND_BY];if(this.whereCondition){const t=this.prepareCondition(this.whereCondition,e);o.push(t.method),t.args&&t.args.length&&r.push(...t.args)}return this.selectSelector&&o.push(t.QueryClause.SELECT,this.selectSelector.join(` ${t.QueryClause.AND.toLowerCase()} `)),this.orderBySelectors?.length&&(o.push(t.QueryClause.ORDER_BY,this.orderBySelectors[0][0]),r.push(this.orderBySelectors[0][1])),a.method=c.toCamelCase(o.join(" ")),a.params=i,this.prepared=a,this}processRecord(e,r,i,o){if(e[a.CouchDBKeys.ID]){const[,...r]=e[a.CouchDBKeys.ID].split(a.CouchDBKeys.SEPARATOR),s=r.join("_");return this.adapter.revert(e,this.fromSelector,t.Sequence.parseValue(i,s),void 0,o)}return e}async raw(e,...t){const{ctx:a}=this.logCtx(t,this.raw),o=e?.aggregateInfo;if(e?.aggregate&&o)return this.executeAggregate(o,a);const n=await this.adapter.raw(e,!0,this.fromSelector,a),c=r.Model.pk(this.fromSelector),l=s.Metadata.get(this.fromSelector,s.Metadata.key(i.DBKeys.ID,c))?.type;return this.selectSelector?n:n.map(e=>this.processRecord(e,c,l,a))}build(){const e=this.log.for(this.build),i=this.buildAggregateQuery();if(i)return i;const o={};o[a.CouchDBKeys.TABLE]={},o[a.CouchDBKeys.TABLE]=r.Model.tableName(this.fromSelector);const s={selector:o};if(this.selectSelector&&(s.fields=this.selectSelector),this.whereCondition){const r=this.parseCondition(t.Condition.and(this.whereCondition,t.Condition.attribute(a.CouchDBKeys.TABLE).eq(s.selector[a.CouchDBKeys.TABLE]))).selector,i=Object.keys(r);if(1===i.length&&-1!==Object.values(a.CouchDBGroupOperator).indexOf(i[0]))switch(i[0]){case a.CouchDBGroupOperator.AND:r[a.CouchDBGroupOperator.AND]=[...Object.values(r[a.CouchDBGroupOperator.AND]).reduce((e,t)=>{const r=Object.keys(t);if(1!==r.length)throw Error("Too many keys in query selector. should be one");const i=r[0];return i===a.CouchDBGroupOperator.AND?e.push(...t[i]):e.push(t),e},[])],s.selector=r;break;case a.CouchDBGroupOperator.OR:{const e={};e[a.CouchDBGroupOperator.AND]=[r,...Object.entries(s.selector).map(([e,t])=>{const r={};return r[e]=t,r})],s.selector=e;break}default:throw Error("This should be impossible")}else Object.entries(r).forEach(([t,r])=>{s.selector[t]&&e.warn(`A ${t} query param is about to be overridden: ${s.selector[t]} by ${r}`),s.selector[t]=r})}if(this.orderBySelectors?.length){s.sort=s.sort||[],s.selector=s.selector||{};for(const[e,t]of this.orderBySelectors){const r=e,i={};i[r]=t,s.sort.push(i),s.selector[r]||(s.selector[r]={},s.selector[r][a.CouchDBOperator.BIGGER]=null)}}return this.limitSelector?s.limit=this.limitSelector:(e.warn("No limit selector defined. Using default couchdb limit of "+a.CouchDBQueryLimit),s.limit=a.CouchDBQueryLimit),this.offsetSelector&&(s.skip=this.offsetSelector),s}parseCondition(e){const{attr1:r,operator:i,comparison:o}=e;if(i===t.Operator.STARTS_WITH){if("string"!=typeof r)throw new t.QueryError("STARTS_WITH requires an attribute name");if("string"!=typeof o)throw new t.QueryError("STARTS_WITH requires a string comparison");const e={start:s=o,end:De(s)},i={};return i[r]={},i[r][a.CouchDBOperator.BIGGER_EQ]=e.start,i[r][a.CouchDBOperator.SMALLER]=e.end,{selector:i}}var s,n;if(i===t.Operator.ENDS_WITH){if("string"!=typeof r)throw new t.QueryError("ENDS_WITH requires an attribute name");if("string"!=typeof o)throw new t.QueryError("ENDS_WITH requires a string comparison");const e={};return e[r]={[a.CouchDBOperator.REGEXP]:(n=o,n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"$")},{selector:e}}if(i===t.Operator.BETWEEN){const e=r;if(!Array.isArray(o)||2!==o.length)throw new t.QueryError("BETWEEN operator requires [min, max] comparison");const[i,s]=o,n={};return n[e]={},n[e][a.translateOperators(t.Operator.BIGGER_EQ)]=i,n[e][a.translateOperators(t.Operator.SMALLER_EQ)]=s,{selector:n}}let c={};if(-1===[t.GroupOperator.AND,t.GroupOperator.OR,t.Operator.NOT].indexOf(i))c[r]={},c[r][a.translateOperators(i)]=o;else if(i===t.Operator.NOT)c=this.parseCondition(r).selector,c[a.translateOperators(t.Operator.NOT)]={},c[a.translateOperators(t.Operator.NOT)][r.attr1]=o;else{const e=this.parseCondition(r).selector,t=this.parseCondition(o).selector;c=((e,t,r)=>{const i={selector:{}};return i.selector[e]=[t,r],i})(a.translateOperators(i),e,t).selector}return{selector:c}}buildAggregateQuery(){if(!this.fromSelector)return;if(this.avgSelector){const e=this.avgSelector+"",r=this.createAggregateDescriptor("sum",e),i=this.createAggregateDescriptor("count",e);if(!r||!i)throw new t.QueryError("Avg operation requires sum and count views for attribute "+e);return this.createAggregateQuery({kind:"avg",attribute:e,sumDescriptor:r.descriptor,countDescriptor:i.descriptor})}if(void 0!==this.countDistinctSelector){const e=null==this.countDistinctSelector?void 0:this.countDistinctSelector+"",t=this.createAggregateDescriptor("distinct",e);if(t)return t.countDistinct=!0,this.createAggregateQuery(t)}const e=!!(void 0!==this.countSelector||void 0!==this.countDistinctSelector||this.minSelector||this.maxSelector||this.sumSelector||this.distinctSelector),i=[["count",this.countSelector??void 0],["max",this.maxSelector],["min",this.minSelector],["sum",this.sumSelector],["distinct",this.distinctSelector]];for(const[e,t]of i){const r=t?t+"":void 0,i=this.createAggregateDescriptor(e,r);if(i)return this.createAggregateQuery(i)}if(e)throw new t.QueryError(`No CouchDB view metadata found for table ${r.Model.tableName(this.fromSelector)} aggregator`)}createAggregateDescriptor(e,t){if(!this.fromSelector)return;const i=a.findViewMetadata(this.fromSelector,e,t);if(!i.length)return;const o=i[0],s=r.Model.tableName(this.fromSelector),n=a.generateViewName(s,o.attribute,e,o),c=o.ddoc||a.generateDesignDocName(s,n),l={reduce:void 0!==o.reduce||!o.returnDocs};return"distinct"!==e&&"groupBy"!==e||(l.group=!0),{kind:e,meta:o,descriptor:{ddoc:c,view:n,options:l}}}createAggregateQuery(e){return{selector:{},aggregate:!0,aggregateInfo:e}}getFabricAdapter(){return this.adapter}async executeAggregate(e,t){if(!this.isViewAggregate(e))return this.handleAverage(e,t);const r=this.getFabricAdapter(),i=e,a=await r.view(i.descriptor.ddoc,i.descriptor.view,i.descriptor.options,t);return this.processViewResponse(e,a)}async handleAverage(e,r){if("avg"!==e.kind)throw new t.QueryError("Average descriptor is not valid");const i=this.getFabricAdapter(),[a,o]=[e.sumDescriptor,e.countDescriptor],[s,n]=await Promise.all([i.view(a.ddoc,a.view,a.options,r),i.view(o.ddoc,o.view,o.options,r)]),c=s.rows?.[0]?.value??0,l=n.rows?.[0]?.value??0;return l?c/l:0}processViewResponse(e,r){if("avg"===e.kind)throw new t.QueryError("Average results should be handled before processing rows");const i=r.rows||[],a=e,o=a.meta;return a.countDistinct?i.length||0:"distinct"===a.kind||"groupBy"===a.kind?i.map(e=>e.key??e.value):o.returnDocs?i.map(e=>e.value??e.doc??e):i.length?i[0].value??i[0].key??null:"count"===a.kind?0:null}isViewAggregate(e){return"avg"!==e.kind}}class Re extends t.Paginator{constructor(e,t,r,i){super(e,t,r,i)}prepare(e){throw new t.UnsupportedError("Raw query access must be implemented by a subclass. only prepared statements are natively available")}page(e=1,...t){return super.page(e,...t)}}var $e;class Be extends t.Adapter{static{this.decoder=new TextDecoder("utf8")}static{this.serializer=new v}static{this.log=c.Logging.for(Be)}constructor(e,t){super(Object.assign({},Oe,e),M,t),this.serializer=Be.serializer}Statement(e){return new Fe(this,e)}Paginator(e,t,r){return new Re(this,e,t,r)}async flags(e,t,r,...i){return Object.assign(await super.flags(e,t,Object.assign({},this.config,r),...i))}async context(e,i,a,...o){this.log.for(this.context).silly(`creating new context for ${e} operation on ${a?Array.isArray(a)?a.map(e=>r.Model.tableName(e)):r.Model.tableName(a):"no"} table ${i&&Object.keys(i)?Object.keys(i).length:"no"} with flag overrides`);let s=o.pop();void 0===s||s instanceof t.Context||(o.push(s),s=void 0),i=s?Object.assign({},s.toOverrides(),i):i;const n=await this.flags("string"==typeof e?e:e.name,a,i,...[...o,s].filter(Boolean));if(s){if(!(s instanceof this.Context)){const e=(new this.Context).accumulate({...s.cache,...n,parentContext:s});return s.accumulate({childContexts:[...s.getOrUndefined("childContexts")||[],e]}),e}const t=s.getOrUndefined("operation"),r=s.getOrUndefined("affectedTables");if(!t||t!==e||a&&a!==r){const e=(new this.Context).accumulate({...s.cache,...n,parentContext:s});return s.accumulate({childContexts:[...s.getOrUndefined("childContexts")||[],e]}),e}return s.accumulate(n)}return(new this.Context).accumulate({...n})}decode(e){return Be.decoder.decode(e)}repository(){return b}createPrefix(e,t,i,...o){const{ctxArgs:s}=this.logCtx(o,this.createPrefix),n=r.Model.tableName(e),c={};return c[a.CouchDBKeys.TABLE]=n,Object.assign(c,i),[e,t,c,...s]}createAllPrefix(e,t,o,...s){const n=r.Model.tableName(e);if(t.length!==o.length)throw new i.InternalError("Ids and models must have the same length");const{ctxArgs:c}=this.logCtx(s,this.createAllPrefix),l=t.map((e,t)=>{const r={};return r[a.CouchDBKeys.TABLE]=n,Object.assign(r,o[t]),r});return[e,t,l,...c]}updateAllPrefix(e,t,o,...s){const n=r.Model.tableName(e);if(t.length!==o.length)throw new i.InternalError("Ids and models must have the same length");const{ctxArgs:c}=this.logCtx(s,this.updateAllPrefix),l=t.map(()=>{const e={};return e[a.CouchDBKeys.TABLE]=n,e});return[e,t,l,...c]}async createAll(e,t,a,...o){if(t.length!==a.length)throw new i.InternalError("Ids and models must have the same length");const s=[...o];let n=s.shift();const{log:c,ctx:l}=this.logCtx(s,this.createAll),d=r.Model.tableName(e);c.info(`adding ${t.length} entries to ${d} table`),c.verbose("pks: "+t),n=n&&(Array.isArray(n)?n:Object.keys(n)).length?{[d]:n}:{};const u=await this.submitTransaction(l,i.BulkCrudOperationKeys.CREATE_ALL,[JSON.stringify(a.map(t=>this.serializer.serialize(t,e.name)))],n,void 0,e.name);try{return JSON.parse(this.decode(u)).map(e=>JSON.parse(e))}catch(e){throw new i.SerializationError(e)}}async readAll(e,t,...a){const{log:o,ctx:s}=this.logCtx(a,this.readAll),n=r.Model.tableName(e);o.info(`reading ${t.length} entries to ${n} table`),o.verbose("pks: "+t);const c=await this.evaluateTransaction(s,i.BulkCrudOperationKeys.READ_ALL,[JSON.stringify(t)],void 0,void 0,e.name);try{return JSON.parse(this.decode(c)).map(e=>JSON.parse(e))}catch(e){throw new i.SerializationError(e)}}async updateAll(e,t,a,...o){if(t.length!==a.length)throw new i.InternalError("Ids and models must have the same length");const s=[...o];let n=s.shift();const{log:c,ctx:l}=this.logCtx(s,this.updateAll),d=r.Model.tableName(e);c.info(`updating ${t.length} entries to ${d} table`),c.verbose("pks: "+t),n=n&&(Array.isArray(n)?n:Object.keys(n)).length?{[d]:n}:{};const u=await this.submitTransaction(l,i.BulkCrudOperationKeys.UPDATE_ALL,[JSON.stringify(a.map(t=>this.serializer.serialize(t,e.name)))],n,void 0,e.name);try{return JSON.parse(this.decode(u)).map(e=>JSON.parse(e))}catch(e){throw new i.SerializationError(e)}}async deleteAll(e,t,...a){const{log:o,ctx:s}=this.logCtx(a,this.deleteAll),n=r.Model.tableName(e);o.info(`deleting ${t.length} entries to ${n} table`),o.verbose("pks: "+t);const c=await this.submitTransaction(s,i.BulkCrudOperationKeys.DELETE_ALL,[JSON.stringify(t)],void 0,void 0,e.name);try{return JSON.parse(this.decode(c)).map(e=>JSON.parse(e))}catch(e){throw new i.SerializationError(e)}}prepare(e,...i){const{log:a}=this.logCtx(i,this.prepare),o=r.Model.segregate(e);return e[t.PersistenceKeys.METADATA]&&(a.silly("Passing along persistence metadata for "+e[t.PersistenceKeys.METADATA]),Object.defineProperty(o.model,t.PersistenceKeys.METADATA,{enumerable:!1,writable:!1,configurable:!0,value:e[t.PersistenceKeys.METADATA]})),{record:o.model,model:o.model,id:e[r.Model.pk(e.constructor)],transient:o.transient,privates:o.privates,shared:o.shared}}revert(e,t,r,a,...o){const{log:s}=this.logCtx(o,this.revert);return a&&(s.verbose("re-adding transient properties: "+Object.keys(a).join(", ")),Object.entries(a).forEach(([r,a])=>{if(r in e&&void 0!==e[r])throw new i.InternalError(`Transient property ${r} already exists on model ${"string"==typeof t?t:t.name}. should be impossible`);e[r]=a})),new t(e)}async create(e,t,a,o={},...s){const n=[...s],{log:c,ctx:l}=this.logCtx(n,this.create),d=r.Model.tableName(e);c.verbose(`adding entry to ${d} table`),c.debug("pk: "+t),o=o&&Object.keys(o).length?{[d]:o}:{};const u=await this.submitTransaction(l,i.OperationKeys.CREATE,[this.serializer.serialize(a,e.name)],o,void 0,e.name);return this.serializer.deserialize(this.decode(u))}async read(e,t,...a){const{log:o,ctx:s}=this.logCtx(a,this.readAll),n=r.Model.tableName(e);o.verbose(`reading entry from ${n} table`),o.debug("pk: "+t);const c=await this.evaluateTransaction(s,i.OperationKeys.READ,[t.toString()],void 0,void 0,e.name);return this.serializer.deserialize(this.decode(c))}updatePrefix(e,t,i,...o){const s=r.Model.tableName(e),{ctxArgs:n}=this.logCtx(o,this.updatePrefix),c={};return c[a.CouchDBKeys.TABLE]=s,Object.assign(c,i),[e,t,c,...n]}async update(e,t,a,o={},...s){const n=[...s],{log:c,ctx:l}=this.logCtx(n,this.updateAll);c.info("CLIENT UPDATE class : "+typeof e);const d=r.Model.tableName(e);c.verbose(`updating entry to ${d} table`),c.debug("pk: "+t),o=o&&Object.keys(o).length?{[d]:o}:{};const u=await this.submitTransaction(l,i.OperationKeys.UPDATE,[this.serializer.serialize(a,e.name||e)],o,void 0,e.name);return this.serializer.deserialize(this.decode(u))}async delete(e,t,...a){const{log:o,ctx:s}=this.logCtx(a,this.delete),n=r.Model.tableName(e);o.verbose(`deleting entry from ${n} table`),o.debug("pk: "+t);const c=await this.submitTransaction(s,i.OperationKeys.DELETE,[t.toString()],void 0,void 0,e.name);return this.serializer.deserialize(this.decode(c))}async raw(e,t=!0,a,...o){const{log:s,ctx:n}=this.logCtx(o,this.raw),c=a.name;let l,d;s.info("Performing raw statement on table "+r.Model.tableName(a));try{l=await this.evaluateTransaction(n,"raw",[JSON.stringify(e),t],void 0,void 0,c)}catch(e){throw this.parseError(e)}try{d=JSON.parse(this.decode(l))}catch(e){throw new i.SerializationError("Failed to process result: "+e)}if(Array.isArray(d)){if(!d.length)return d;const e=d[0];return r.Model.isModel(e)?d.map(e=>r.Model.build(e)):d}return u=d,r.Model.isModel(u)?r.Model.build(u):u;var u}async view(e,t,r,...a){const{log:o,ctx:s}=this.logCtx(a,this.view);let n,c;o.info(`Querying view ${e}/${t}`);try{n=await this.evaluateTransaction(s,"view",[e,t,JSON.stringify(r)],void 0,void 0,void 0)}catch(e){throw this.parseError(e)}try{c=JSON.parse(this.decode(n))}catch(e){throw new i.SerializationError("Failed to process view result: "+e)}return c}getClient(){return this._client||(this._client=Be.getClient(this.config)),this._client}async Gateway(e){return Be.getGateway(e,this.config,this.client)}getContractName(e){if(e)return e+"Contract"}async Contract(e,t){return Be.getContract(await this.Gateway(e),this.config,t)}async transaction(e,t,r=!0,i,a={},o,s){const n=this.log.for(this.transaction),c=await this.Gateway(e);try{const c=await this.Contract(e,this.getContractName(s));n.verbose(`${r?"Submit":"Evaluate"}ting transaction ${this.getContractName(s)||this.config.contractName}.${t}`),n.debug("args: "+(i?.map(e=>e.toString()).join("\n")||"none"));const l=r?c.submit:c.evaluate;o=o?.length?o:void 0;const d={arguments:i||[],transientData:Object.entries(a).reduce((e,[t,r])=>(e[t]=JSON.stringify(r),e),{})};return await l.call(c,t,d)}catch(e){if(10===e.code)throw Error(""+e.details[0].message);throw this.parseError(e)}finally{this.log.debug(`Closing ${this.config.mspId} gateway connection`),c.close()}}parseError(e){return Be.parseError(e)}async submitTransaction(e,t,r,i,a,o){return this.transaction(e,t,!0,r,i,a,o)}async evaluateTransaction(e,t,r,i,a,o){return this.transaction(e,t,!1,r,i,a,o)}async close(){this.client&&(this.log.verbose(`Closing ${this.config.mspId} gateway client`),this.client.close())}static getContract(e,t,r){const i=this.log.for(this.getContract),a=this.getNetwork(e,t.channel);let o;try{i.debug(`Retrieving chaincode ${t.chaincodeName} contract ${r||t.contractName} from network ${t.channel}`),r=r||t.contractName,o=a.getContract(t.chaincodeName,r)}catch(e){throw this.parseError(e)}return o}static getNetwork(e,t){const r=c.Logging.for(this.getNetwork);let i;try{r.debug("Connecting to channel "+t),i=e.getNetwork(t)}catch(e){throw this.parseError(e)}return i}static async getGateway(e,t,r){return await this.getConnection(r||await this.getClient(t),t,e)}static getClient(e){const t=this.log.for(this.getClient);t.debug("generating TLS credentials for msp "+e.mspId);let r=e.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(f.readFileSync(r,"utf8"))}catch(e){throw new i.InternalError(`Failed to read the tls certificate from ${r}: ${e}`)}const a=w.credentials.createSsl(r);return t.debug("generating Gateway Client for url "+e.peerEndpoint),new p.Client(e.peerEndpoint,a,{"grpc.max_receive_message_length":1024*(e.sizeLimit||15)*1024,"grpc.max_send_message_length":1024*(e.sizeLimit||15)*1024})}static async getConnection(e,r,i){const a=c.Logging.for(this.getConnection);a.debug(`Retrieving Peer Identity for ${r.mspId} under ${r.certCertOrDirectoryPath}`);const o=await Me(r.mspId,r.certCertOrDirectoryPath);try{a.debug("preparing transaction signer for "+K.fabricIdFromCertificate(o.credentials.toString()))}catch(e){a.error("Failed to extract Fabric ID from certificate",e)}let s;if(r.hsm)throw new t.UnsupportedError("HSM NOT IMPLEMENTED");s=await Ne(r.keyCertOrDirectoryPath);const n={client:e,identity:o,signer:s,evaluateOptions:()=>({deadline:Date.now()+1e3*i.get("evaluateTimeout")}),endorseOptions:()=>({deadline:Date.now()+1e3*i.get("endorseTimeout")}),submitOptions:()=>({deadline:Date.now()+1e3*i.get("submitTimeout")}),commitStatusOptions:()=>({deadline:Date.now()+1e3*i.get("commitTimeout")})};a.debug("Connecting to "+r.mspId);const d=l.connect(n);return r.hsm&&(d.close=new Proxy(d.close,{apply(e,t,r){Reflect.apply(e,t,r)}})),d}Dispatch(){return new Be._baseDispatch}static parseError(e){const r="string"==typeof e?e:e.message;return r.includes("MVCC_READ_CONFLICT")?new V(e):r.includes("DEADLINE_EXCEEDED")?new X(e):r.includes("ENDORSEMENT_POLICY_FAILURE")?new Q(e):r.includes("PHANTOM_READ_CONFLICT")?new J(e):e instanceof Error&&e.code&&9===e.code?new Y(e):r.includes(i.NotFoundError.name)?new i.NotFoundError(e):r.includes(i.ConflictError.name)?new i.ConflictError(e):r.includes(i.BadRequestError.name)?new i.BadRequestError(e):r.includes(t.QueryError.name)?new t.QueryError(e):r.includes(t.PagingError.name)?new t.PagingError(e):r.includes(t.UnsupportedError.name)?new t.UnsupportedError(e):r.includes(t.MigrationError.name)?new t.MigrationError(e):r.includes(t.ObserverError.name)?new t.ObserverError(e):r.includes(t.AuthorizationError.name)?new t.AuthorizationError(e):r.includes(t.ForbiddenError.name)?new t.ForbiddenError(e):r.includes(t.ConnectionError.name)?new t.ConnectionError(e):r.includes(i.SerializationError.name)?new i.SerializationError(e):new i.InternalError(e)}}o.__decorate([c.debug(),c.final(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[Object,Object,Object,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"create",null),o.__decorate([c.debug(),c.final(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[Object,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"read",null),o.__decorate([c.debug(),c.final(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[Object,Object,Object,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"update",null),o.__decorate([c.debug(),c.final(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[Object,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"delete",null),o.__decorate([c.debug(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[Object,"function"==typeof($e="undefined"!=typeof D&&D)?$e:Object,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"raw",null),o.__decorate([c.debug(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[String,String,Object,t.Context]),o.__metadata("design:returntype",Promise)],Be.prototype,"view",null),Be.decoration(),t.Adapter.setCurrent(M);class Pe extends t.Dispatch{constructor(e){super(),this.client=e,this.decoder=new TextDecoder("utf8")}async close(){this.listeningStack&&this.listeningStack.close()}parsePayload(e){const t=this.decoder.decode(e);return JSON.parse(t)}observe(e){if(!(e instanceof Be))throw new t.UnsupportedError("Only FabricClientAdapter can be observed by dispatch");return super.observe(e),()=>this.unObserve(e)}async updateObservers(e,a,o,...s){const{log:n,ctxArgs:c}=t.Adapter.logCtx(this.updateObservers,a,!1,...s);if(this.adapter)try{await this.adapter.refresh(e,a,o,...c)}catch(e){throw new i.InternalError("Failed to refresh dispatch: "+e)}else n.verbose(`No adapter observed for dispatch; skipping observer update for ${"string"==typeof e?e:r.Model.tableName(e)}:${a}`)}async handleEvents(e){if(!this.listeningStack)throw new i.InternalError('Event stack not initialized. Ensure that "startListening" is called before attempting this operation.');if(!this.adapter||!this.adapter.config)throw new i.InternalError("No adapter found. should be impossible");const t=e||await this.adapter.context(i.OperationKeys.READ,{correlationId:this.adapter.config.chaincodeName},this.models&&this.models[0]||r.Model),a=this.log.for(this.handleEvents);a.info(`Listening for incoming events on chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}"...`);try{for await(const e of this.listeningStack){const{table:i,event:o,owner:s}=Ce(e.eventName);if(s&&s!==this.adapter.config?.mspId)continue;const n=this.parsePayload(e.payload);try{const e=(i?r.Model.get(i):r.Model.get(this.models[0].name))??(i||this.models[0]?.name);await this.updateObservers(e,o,n.id,t)}catch(e){a.error(`Failed update observables for table ${i} event ${o} id: ${n.id}: ${e}`)}}}catch(e){a.error(`Failed to read event for chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}": ${e}`),await this.close()}}async initialize(){if(!this.adapter)throw new i.InternalError("No adapter or config observed for dispatch");const e=await this.adapter.context("dispatch",{correlationId:this.adapter.config.chaincodeName},r.Model),{ctx:t}=this.logCtx([e],this.initialize),a=(await Be.getGateway(t,this.adapter.config,this.client)).getNetwork(this.adapter.config.channel);if(!this.adapter)throw new i.InternalError("No adapter observed for dispatch");this.listeningStack=await a.getChaincodeEvents(this.adapter.config.chaincodeName),this.handleEvents(t)}}Be&&(Be._baseDispatch=Pe);const Ke="##VERSION##",ke="##PACKAGE##";s.Metadata.registerLibrary(ke,Ke),e.AllowanceError=j,e.BalanceError=z,e.BaseEncoder=P,e.ClientSerializer=v,e.CoreUtils=x,e.CryptoUtils=K,e.DefaultFabricClientFlags=Oe,e.DeterministicSerializer=Ee,e.EndorsementError=Y,e.EndorsementPolicyError=Q,e.FabricClientAdapter=Be,e.FabricClientDispatch=Pe,e.FabricClientRepository=b,e.FabricERC20ClientRepository=S,e.FabricEnrollmentService=ee,e.FabricFlavour=M,e.FabricIdentityService=ve,e.ImplicitPrivateCollection=he,e.MissingContextError=U,e.MissingPKCSS11Lib=G,e.ModelCollection=(e,t)=>{const a=t||("function"!=typeof e?r.Model.ownerOf(e):void 0),o="function"==typeof e?e:e.constructor;if(!a)throw new i.InternalError(`Model ${o.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);return`${c.toPascalCase(o.name)}${a?c.toPascalCase(a):""}`},e.MvccReadConflictError=V,e.NamespaceCollection=e=>(t,a)=>{const o=a||("function"!=typeof t?r.Model.ownerOf(t):void 0),s="function"==typeof t?t:t.constructor;if(!o)throw new i.InternalError(`Model ${s.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);return`${e}${o?c.toPascalCase(o):""}`},e.NotInitializedError=q,e.OverflowError=k,e.Owner=function(){return function(e,r,a){const o=a.value;return a.value=async function(...e){const a=e[0],s=a.clientIdentity.getID(),n=await this.tokenRepository.select(),c=await n.execute(a);if(0==c.length)throw new i.NotFoundError("No tokens avaialble");if(c.length>1)throw new i.NotFoundError("To many token available : "+c.length);if(c[0].owner!=s)throw new t.AuthorizationError(`User not authorized to run ${r} on the token`);return await o.apply(this,e)},a}},e.PACKAGE_NAME=ke,e.PhantomReadConflictError=J,e.RegistrationError=L,e.RegistrationRequestBuilder=te,e.SEGREGATED_COLLECTION_EXTRACTION_PRIORITY=35,e.SimpleDeterministicSerializer=Ae,e.TransactionBufferSizeError=Z,e.TransactionLimitsError=W,e.TransactionTimeoutError=X,e.UnauthorizedPrivateDataAccess=H,e.VERSION=Ke,e.add=(e,t)=>{const r=e+t;if(e!==r-t||t!==r-e)throw new k(`Addition overflow: ${e} + ${t}`);return r},e.contentOfLoadFile=Ie,e.createMirrorHandler=ne,e.deleteMirrorHandler=le,e.evalMirrorMetadata=se,e.extractPrivateKey=Te,e.extractSegregatedCollections=ge,e.generateFabricEventName=(e,t,r)=>{const i=[e,t];return r&&i.push(r),i.join("_")},e.generateModelDesignDocs=(e,t)=>{const r=a.generateViews([e]),i=t||{};return r.forEach(e=>{i[e._id]=e}),r},e.generateModelIndexes=e=>a.generateIndexes([e]),e.getCAUser=async(e,t,r,i)=>{_e.debug(`Creating a CA ${i} user ${e} with certificate ${r}`);const a=new d.User(e),o=d.User.newCryptoSuite();a.setCryptoSuite(o);const s=o.createKeyFromRaw(t);return await a.setEnrollment(s,r,i),a},e.getFirstDirFileName=xe,e.getFirstDirFileNameContent=async e=>{const{promises:r}=await t.normalizeImport(import("fs")),{join:i}=await t.normalizeImport(import("path")),a=await r.readdir(e);return(await r.readFile(i(e,a[0]))).toString()},e.getIdentity=Me,e.getSigner=Ne,e.mirror=(t,r)=>s.Decoration.for(e.FabricModelKeys.MIRROR).define({decorator:(r,a)=>{const o={condition:a,resolver:r};return s.apply(s.metadata(s.Metadata.key(e.FabricModelKeys.FABRIC,e.FabricModelKeys.MIRROR),o),be(t),i.onRead(ue,o,{priority:30}),i.onCreate(de,o,{priority:20}),i.onUpdate(de,o,{priority:20}),i.onDelete(de,o,{priority:20}),i.afterCreate(ne,o,{priority:95}),i.afterUpdate(ce,o,{priority:95}),i.afterDelete(le,o,{priority:95}))},args:[t,r]}).apply(),e.mirrorWriteGuard=de,e.ownedBy=()=>s.Decoration.for(e.FabricModelKeys.OWNED_BY).define({decorator:()=>(t,a)=>s.apply(r.required(),i.generated(),i.readonly(),i.onCreate(ae),s.propMetadata(s.Metadata.key(e.FabricModelKeys.FABRIC,e.FabricModelKeys.OWNED_BY),a))(t,a),args:[]}).apply(),e.ownedByOnCreate=ae,e.parseEventName=Ce,e.privateData=be,e.readFile=async e=>"string"!=typeof e?e:await(async e=>{const{promises:r}=await t.normalizeImport(import("fs"));return await r.readFile(e)})(e),e.readMirrorHandler=ue,e.readModelFile=_,e.readModelFolders=async(...e)=>{const t=require("fs"),r=[];for(const i of e){const e=t.readdirSync(i,{withFileTypes:!0,recursive:!0}).filter(e=>e.isFile()&&e.name.endsWith("js"));for(const t of e)r.push(..._(t))}return r},e.safeParseInt=e=>{if(!/^\d+$/.test(e))throw new i.ValidationError(r.stringFormat("Failed to parse: {0}","string contains digits"));const t=parseInt(e);if(isNaN(t))throw new i.ValidationError(r.stringFormat("Failed to parse: {0}","string is not a parsable integer"));return t},e.segregatedDataOnCreate=pe,e.segregatedDataOnDelete=me,e.segregatedDataOnRead=fe,e.segregatedDataOnUpdate=ye,e.sharedData=t=>s.Decoration.for(e.FabricModelKeys.SHARED).define({decorator:t=>we(t,e.FabricModelKeys.SHARED),args:[t]}).apply(),e.sub=(e,t)=>{const r=e-t;if(e!==r+t||t!==e-r)throw new k(`Subtraction overflow: ${e} - ${t}`);return r},e.transactionId=()=>s.Decoration.for(e.FabricModelKeys.TRANSACTION_ID).define({decorator:()=>(t,a)=>s.apply(r.required(),i.readonly(),i.onCreate(oe),i.onUpdate(oe),s.propMetadata(s.Metadata.key(e.FabricModelKeys.FABRIC,a,e.FabricModelKeys.TRANSACTION_ID),a))(t,a),args:[]}).apply(),e.transactionIdOnCreate=oe,e.updateMirrorHandler=ce,e.writeDesignDocs=(e,t=process.cwd(),r)=>{if(!e.length)return;const i=require("fs"),a=require("path");e.forEach(e=>{const o=e._id.replace(/^_design\//,""),s=a.resolve(a.join(t,`./META-INF/statedb/couchdb/${r?`collections/${r}/`:""}design_docs/${o}.json`));O(s);const n={...e};delete n._rev,i.writeFileSync(s,JSON.stringify(n,void 0,2))})},e.writeIndexes=(e,t=process.cwd(),r)=>{const i=require("fs"),a=require("path");e.forEach(e=>{const o=a.resolve(a.join(t,`./META-INF/statedb/couchdb/${r?`collections/${r}/`:""}indexes/${e.name}.json`));O(o),i.writeFileSync(o,JSON.stringify(e,void 0,2))})}},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@decaf-ts/core"),require("@decaf-ts/decorator-validation"),require("@decaf-ts/db-decorators"),require("@decaf-ts/for-couchdb"),require("tslib"),require("@decaf-ts/decoration"),require("fabric-ca-client"),require("@decaf-ts/logging"),require("@hyperledger/fabric-gateway"),require("fabric-common"),require("crypto"),require("@peculiar/x509"),require("@peculiar/webcrypto"),require("@grpc/grpc-js"),require("fs")):"function"==typeof define&&define.amd?define(["exports","@decaf-ts/core","@decaf-ts/decorator-validation","@decaf-ts/db-decorators","@decaf-ts/for-couchdb","tslib","@decaf-ts/decoration","fabric-ca-client","@decaf-ts/logging","@hyperledger/fabric-gateway","fabric-common","crypto","@peculiar/x509","@peculiar/webcrypto","@grpc/grpc-js","fs"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["for-fabric"]={},e.decafTsCore,e.decafTsDecoratorValidation,e.decafTsDbDecorators,e.decafTsForCouchdb,e.tslib,e.decafTsDecoration,e.fabricCaClient,e.decafTsLogging,e.hyperledgerFabricGateway,e.fabricCommon,e.crypto,e.peculiarX509,e.peculiarWebcrypto,e.grpcGrpcJs,e.fs);
2
- //# sourceMappingURL=for-fabric.cjs.map
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@decaf-ts/core"), require("@decaf-ts/decorator-validation"), require("@decaf-ts/db-decorators"), require("@decaf-ts/for-couchdb"), require("tslib"), require("@decaf-ts/decoration"), require("fabric-ca-client"), require("@decaf-ts/logging"), require("@hyperledger/fabric-gateway"), require("fabric-common"), require("crypto"), require("@peculiar/x509"), require("@peculiar/webcrypto"), require("@grpc/grpc-js"), require("fs")) : typeof define === "function" && define.amd ? define([ "exports", "@decaf-ts/core", "@decaf-ts/decorator-validation", "@decaf-ts/db-decorators", "@decaf-ts/for-couchdb", "tslib", "@decaf-ts/decoration", "fabric-ca-client", "@decaf-ts/logging", "@hyperledger/fabric-gateway", "fabric-common", "crypto", "@peculiar/x509", "@peculiar/webcrypto", "@grpc/grpc-js", "fs" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
3
+ factory(global["for-fabric"] = {}, global.decafTsCore, global.decafTsDecoratorValidation, global.decafTsDbDecorators, global.decafTsForCouchdb, global.tslib, global.decafTsDecoration, global.fabricCaClient, global.decafTsLogging, global.hyperledgerFabricGateway, global.fabricCommon, global.crypto, global.peculiarX509, global.peculiarWebcrypto, global.grpcGrpcJs, global.fs));
4
+ })(this, function(exports, core, decoratorValidation, dbDecorators, forCouchdb, tslib, decoration, FabricCAServices, logging, fabricGateway, fabricCommon, crypto$1, x509, webcrypto, grpc, fs) {
5
+ "use strict";
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function(k) {
10
+ if (k !== "default") {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function() {
15
+ return e[k];
16
+ }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+ var x509__namespace = _interopNamespaceDefault(x509);
25
+ var grpc__namespace = _interopNamespaceDefault(grpc);
26
+ class FabricClientRepository extends core.Repository {
27
+ constructor(adapter, clazz) {
28
+ super(adapter, clazz);
29
+ this._overrides = Object.assign({}, super["_overrides"], {
30
+ ignoreValidation: true,
31
+ ignoreHandlers: true,
32
+ allowRawStatements: false,
33
+ forcePrepareSimpleQueries: true,
34
+ forcePrepareComplexQueries: true,
35
+ allowGenerationOverride: false
36
+ });
37
+ }
38
+ override(flags) {
39
+ return super.override(Object.assign({}, flags, this._overrides)).for(flags);
40
+ }
41
+ ObserverHandler() {
42
+ return super.ObserverHandler();
43
+ }
44
+ async paginateBy(key, order, ref = {
45
+ offset: 1,
46
+ limit: 10
47
+ }, ...args) {
48
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.PAGE_BY, true)).for(this.paginateBy);
49
+ log.verbose(`paginating ${decoratorValidation.Model.tableName(this.class)} with page size ${ref.limit}`);
50
+ return this.statement(this.paginateBy.name, key, order, {
51
+ limit: ref.limit,
52
+ offset: ref.offset,
53
+ bookmark: ref.bookmark
54
+ }, ...ctxArgs);
55
+ }
56
+ async listBy(key, order, ...args) {
57
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.LIST_BY, true)).for(this.listBy);
58
+ log.verbose(`listing ${decoratorValidation.Model.tableName(this.class)} by ${key} ${order}`);
59
+ return await this.statement(this.listBy.name, key, order, ...ctxArgs);
60
+ }
61
+ async findBy(key, value, ...args) {
62
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.FIND_BY, true)).for(this.findBy);
63
+ log.verbose(`finding all ${decoratorValidation.Model.tableName(this.class)} with ${key} ${value}`);
64
+ return await this.statement(this.findBy.name, key, value, ...ctxArgs);
65
+ }
66
+ async findOneBy(key, value, ...args) {
67
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.FIND_ONE_BY, true)).for(this.findOneBy);
68
+ log.verbose(`finding One ${decoratorValidation.Model.tableName(this.class)} with ${key} ${value}`);
69
+ return await this.statement(this.findOneBy.name, key, value, ...ctxArgs);
70
+ }
71
+ async find(value, order = core.OrderDirection.ASC, ...args) {
72
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.FIND, true)).for(this.find);
73
+ log.verbose(`finding ${decoratorValidation.Model.tableName(this.class)} by default query attributes`);
74
+ return await this.statement(this.find.name, value, order, ...ctxArgs);
75
+ }
76
+ async page(value, direction = core.OrderDirection.ASC, ref = {
77
+ offset: 1,
78
+ limit: 10
79
+ }, ...args) {
80
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.PAGE, true)).for(this.page);
81
+ log.verbose(`paging ${decoratorValidation.Model.tableName(this.class)} by default query attributes`);
82
+ return await this.statement(this.page.name, value, direction, ref, ...ctxArgs);
83
+ }
84
+ async statement(name, ...args) {
85
+ const {log: log, ctx: ctx, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PersistenceKeys.STATEMENT, true)).for(this.statement);
86
+ log.verbose(`Executing prepared statement ${name}`);
87
+ const callArgs = ctxArgs.slice(0, -1);
88
+ const result = JSON.parse(this.adapter.decode(await this.adapter.evaluateTransaction(ctx, core.PersistenceKeys.STATEMENT, [ name, JSON.stringify(callArgs) ], undefined, undefined, this.class.name)));
89
+ if (Array.isArray(result)) {
90
+ return result.map(r => r[forCouchdb.CouchDBKeys.TABLE] && r[forCouchdb.CouchDBKeys.TABLE] === decoratorValidation.Model.tableName(this.class) ? new this.class(r) : r);
91
+ }
92
+ return result[forCouchdb.CouchDBKeys.TABLE] && result[forCouchdb.CouchDBKeys.TABLE] === decoratorValidation.Model.tableName(this.class) ? new this.class(result) : core.Paginator.isSerializedPage(result) ? Object.assign(result, {
93
+ data: result.data.map(d => new this.class(d))
94
+ }) : result;
95
+ }
96
+ async countOf(key, ...args) {
97
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.COUNT_OF, true)).for(this.countOf);
98
+ log.verbose(`counting ${decoratorValidation.Model.tableName(this.class)}${key ? ` by ${key}` : ""}`);
99
+ const stmtArgs = key ? [ key, ...ctxArgs ] : ctxArgs;
100
+ return this.statement(core.PreparedStatementKeys.COUNT_OF, ...stmtArgs);
101
+ }
102
+ async maxOf(key, ...args) {
103
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.MAX_OF, true)).for(this.maxOf);
104
+ log.verbose(`finding max of ${key} in ${decoratorValidation.Model.tableName(this.class)}`);
105
+ return this.statement(core.PreparedStatementKeys.MAX_OF, key, ...ctxArgs);
106
+ }
107
+ async minOf(key, ...args) {
108
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.MIN_OF, true)).for(this.minOf);
109
+ log.verbose(`finding min of ${key} in ${decoratorValidation.Model.tableName(this.class)}`);
110
+ return this.statement(core.PreparedStatementKeys.MIN_OF, key, ...ctxArgs);
111
+ }
112
+ async avgOf(key, ...args) {
113
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.AVG_OF, true)).for(this.avgOf);
114
+ log.verbose(`calculating avg of ${key} in ${decoratorValidation.Model.tableName(this.class)}`);
115
+ return this.statement(core.PreparedStatementKeys.AVG_OF, key, ...ctxArgs);
116
+ }
117
+ async sumOf(key, ...args) {
118
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.SUM_OF, true)).for(this.sumOf);
119
+ log.verbose(`calculating sum of ${key} in ${decoratorValidation.Model.tableName(this.class)}`);
120
+ return this.statement(core.PreparedStatementKeys.SUM_OF, key, ...ctxArgs);
121
+ }
122
+ async distinctOf(key, ...args) {
123
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.DISTINCT_OF, true)).for(this.distinctOf);
124
+ log.verbose(`finding distinct values of ${key} in ${decoratorValidation.Model.tableName(this.class)}`);
125
+ return this.statement(core.PreparedStatementKeys.DISTINCT_OF, key, ...ctxArgs);
126
+ }
127
+ async groupOf(key, ...args) {
128
+ const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, core.PreparedStatementKeys.GROUP_OF, true)).for(this.groupOf);
129
+ log.verbose(`grouping ${decoratorValidation.Model.tableName(this.class)} by ${key}`);
130
+ return this.statement(core.PreparedStatementKeys.GROUP_OF, key, ...ctxArgs);
131
+ }
132
+ async healthcheck(...args) {
133
+ const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.healthcheck);
134
+ const result = await this.adapter.healthcheck(this.class, ...ctxArgs);
135
+ return result;
136
+ }
137
+ async create(model, ...args) {
138
+ const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.create);
139
+ log.debug(`Creating new ${this.class.name} in table ${decoratorValidation.Model.tableName(this.class)}`);
140
+ let {record: record, id: id, transient: transient} = this.adapter.prepare(model, ctx);
141
+ record = await this.adapter.create(this.class, id, record, transient, ...ctxArgs);
142
+ return this.adapter.revert(record, this.class, id, transient, ctx);
143
+ }
144
+ async update(model, ...args) {
145
+ const {ctxArgs: ctxArgs, log: log, ctx: ctx} = this.logCtx(args, this.update);
146
+ let {record: record, id: id, transient: transient} = this.adapter.prepare(model, ctx);
147
+ log.debug(`updating ${this.class.name} in table ${decoratorValidation.Model.tableName(this.class)} with id ${id}`);
148
+ record = await this.adapter.update(this.class, id, record, transient, ...ctxArgs);
149
+ return this.adapter.revert(record, this.class, id, transient, ctx);
150
+ }
151
+ async createAllPrefix(models, ...args) {
152
+ const {ctx: ctx, ctxArgs: ctxArgs} = (await this.logCtx(args, dbDecorators.OperationKeys.CREATE, true)).for(this.createAllPrefix);
153
+ const ignoreHandlers = ctx.get("ignoreHandlers");
154
+ const ignoreValidate = ctx.get("ignoreValidation");
155
+ if (!models.length) return [ models, ...ctxArgs ];
156
+ models = await Promise.all(models.map(async m => {
157
+ m = new this.class(m);
158
+ if (!ignoreHandlers) await dbDecorators.enforceDBDecorators(this, ctx, m, dbDecorators.OperationKeys.CREATE, dbDecorators.OperationKeys.ON);
159
+ return m;
160
+ }));
161
+ if (!ignoreValidate) {
162
+ const ignoredProps = ctx.get("ignoredValidationProperties") || [];
163
+ const errors = await Promise.all(models.map(m => Promise.resolve(m.hasErrors(...ignoredProps))));
164
+ const errorMessages = dbDecorators.reduceErrorsToPrint(errors);
165
+ if (errorMessages) throw new dbDecorators.ValidationError(errorMessages);
166
+ }
167
+ return [ models, ...ctxArgs ];
168
+ }
169
+ async createAll(models, ...args) {
170
+ if (!models.length) return models;
171
+ const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.createAll);
172
+ log.debug(`Creating ${models.length} new ${this.class.name} in table ${decoratorValidation.Model.tableName(this.class)}`);
173
+ const prepared = models.map(m => this.adapter.prepare(m, ctx));
174
+ const ids = prepared.map(p => p.id);
175
+ let records = prepared.map(p => p.record);
176
+ const transient = prepared.map(p => p.transient);
177
+ records = await this.adapter.createAll(this.class, ids, records, transient, ...ctxArgs);
178
+ return records.map((r, i) => this.adapter.revert(r, this.class, ids[i], ctx.get("rebuildWithTransient") ? prepared[i].transient : undefined, ctx));
179
+ }
180
+ async updateAll(models, ...args) {
181
+ const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateAll);
182
+ log.debug(`Updating ${models.length} new ${this.class.name} in table ${decoratorValidation.Model.tableName(this.class)}`);
183
+ const records = models.map(m => this.adapter.prepare(m, ctx));
184
+ const updated = await this.adapter.updateAll(this.class, records.map(r => r.id), records.map(r => r.record), records.map(r => r.transient), ...ctxArgs);
185
+ return updated.map((u, i) => this.adapter.revert(u, this.class, records[i].id, ctx.get("rebuildWithTransient") ? records[i].transient : undefined, ctx));
186
+ }
187
+ }
188
+ let ERC20Token = class ERC20Token extends core.BaseModel {
189
+ constructor(m) {
190
+ super(m);
191
+ }
192
+ };
193
+ tslib.__decorate([ core.pk({
194
+ type: String
195
+ }), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "name", void 0);
196
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "owner", void 0);
197
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "symbol", void 0);
198
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], ERC20Token.prototype, "decimals", void 0);
199
+ ERC20Token = tslib.__decorate([ core.table("erc20_tokens"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], ERC20Token);
200
+ let ERC20Wallet = class ERC20Wallet extends core.BaseModel {
201
+ constructor(m) {
202
+ super(m);
203
+ }
204
+ };
205
+ tslib.__decorate([ core.pk({
206
+ type: String
207
+ }), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "id", void 0);
208
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "token", void 0);
209
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], ERC20Wallet.prototype, "balance", void 0);
210
+ tslib.__decorate([ core.column(), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "captive", void 0);
211
+ ERC20Wallet = tslib.__decorate([ core.table("erc20_wallets"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], ERC20Wallet);
212
+ let Allowance = class Allowance extends core.BaseModel {
213
+ constructor(m) {
214
+ super(m);
215
+ }
216
+ };
217
+ tslib.__decorate([ core.pk({
218
+ type: String
219
+ }), core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], Allowance.prototype, "owner", void 0);
220
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], Allowance.prototype, "spender", void 0);
221
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], Allowance.prototype, "value", void 0);
222
+ Allowance = tslib.__decorate([ core.table("erc20_allowances"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], Allowance);
223
+ class ClientSerializer extends decoratorValidation.JSONSerializer {
224
+ constructor() {
225
+ super();
226
+ }
227
+ preSerialize(model, modelName) {
228
+ const toSerialize = Object.assign({}, model);
229
+ let metadata = decoration.Metadata.modelName(model.constructor);
230
+ if (!metadata || metadata === "Object") if (modelName) metadata = modelName; else throw new dbDecorators.SerializationError(`Could not find metadata for ${model.constructor.name}`);
231
+ toSerialize[decoratorValidation.ModelKeys.ANCHOR] = metadata;
232
+ return toSerialize;
233
+ }
234
+ deserialize(str) {
235
+ const deserialization = JSON.parse(str);
236
+ const className = deserialization[decoratorValidation.ModelKeys.ANCHOR];
237
+ if (!className) throw new Error("Could not find class reference in serialized model");
238
+ const model = decoratorValidation.Model.build(deserialization, className);
239
+ return model;
240
+ }
241
+ serialize(model, modelName) {
242
+ return JSON.stringify(this.preSerialize(model, modelName));
243
+ }
244
+ }
245
+ class FabricERC20ClientRepository extends FabricClientRepository {
246
+ static {
247
+ this.serializer = new ClientSerializer;
248
+ }
249
+ static {
250
+ this.decoder = new TextDecoder("utf8");
251
+ }
252
+ async updateObservers(table, event, id, ...args) {
253
+ if (!this.observerHandler) throw new dbDecorators.InternalError("ObserverHandler not initialized. Did you register any observables?");
254
+ const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateObservers);
255
+ log.verbose(`Updating ${this.observerHandler.count()} observers for ${this}`);
256
+ table = typeof table === "string" ? decoratorValidation.Model.get(table) : table;
257
+ let parsedId;
258
+ if (id === undefined) {
259
+ parsedId = undefined;
260
+ } else if (Array.isArray(id)) {
261
+ parsedId = id.map(i => core.Sequence.parseValue(decoratorValidation.Model.sequenceFor(table).type, i));
262
+ } else {
263
+ parsedId = core.Sequence.parseValue(decoratorValidation.Model.sequenceFor(table).type, id);
264
+ }
265
+ await this.observerHandler.updateObservers(table, event, parsedId, ...ctxArgs);
266
+ }
267
+ decode(data) {
268
+ return FabricERC20ClientRepository.decoder.decode(data);
269
+ }
270
+ constructor(adapter) {
271
+ super(adapter, ERC20Wallet);
272
+ this.serializer = FabricERC20ClientRepository.serializer;
273
+ }
274
+ async tokenName(...args) {
275
+ const {ctx: ctx} = (await this.logCtx(args, "tokenName", true)).for(this.tokenName);
276
+ const name = await this.adapter.evaluateTransaction(ctx, "TokenName");
277
+ return this.decode(name);
278
+ }
279
+ async symbol(...args) {
280
+ const {ctx: ctx} = (await this.logCtx(args, "symbol", true)).for(this.symbol);
281
+ const symbol = await this.adapter.evaluateTransaction(ctx, "Symbol");
282
+ return this.decode(symbol);
283
+ }
284
+ async decimals(...args) {
285
+ const {ctx: ctx} = (await this.logCtx(args, "decimals", true)).for(this.decimals);
286
+ const decimals = await this.adapter.evaluateTransaction(ctx, "Decimals");
287
+ return Number(this.decode(decimals));
288
+ }
289
+ async totalSupply(...args) {
290
+ const {ctx: ctx} = (await this.logCtx(args, "totalSupply", true)).for(this.totalSupply);
291
+ const total = await this.adapter.evaluateTransaction(ctx, "TotalSupply");
292
+ return Number(this.decode(total));
293
+ }
294
+ async balanceOf(owner, ...args) {
295
+ const {ctx: ctx} = (await this.logCtx(args, "balance", true)).for(this.balanceOf);
296
+ const balance = await this.adapter.evaluateTransaction(ctx, "BalanceOf", [ owner ]);
297
+ return Number(this.decode(balance));
298
+ }
299
+ async transfer(to, value, ...args) {
300
+ const {ctx: ctx} = (await this.logCtx(args, "transfer", true)).for(this.transfer);
301
+ const transferred = await this.adapter.submitTransaction(ctx, "Transfer", [ to, value.toString() ]);
302
+ return this.decode(transferred) === "true" ? true : false;
303
+ }
304
+ async transferFrom(from, to, value) {
305
+ const contextArgs = await core.Context.args("transferFrom", this.class, [], this.adapter, this._overrides || {});
306
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.transferFrom);
307
+ const transferred = await this.adapter.submitTransaction(ctx, "TransferFrom", [ from, to, value.toString() ]);
308
+ return this.decode(transferred) === "true" ? true : false;
309
+ }
310
+ async approve(spender, value) {
311
+ const contextArgs = await core.Context.args("approve", this.class, [], this.adapter, this._overrides || {});
312
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.approve);
313
+ const approved = await this.adapter.submitTransaction(ctx, "Approve", [ spender, value.toString() ]);
314
+ return this.decode(approved) === "true" ? true : false;
315
+ }
316
+ async allowance(owner, spender) {
317
+ const contextArgs = await core.Context.args("allowance", this.class, [], this.adapter, this._overrides || {});
318
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.allowance);
319
+ const allowance = await this.adapter.submitTransaction(ctx, "Allowance", [ owner, spender ]);
320
+ return Number(this.decode(allowance));
321
+ }
322
+ async initialize(token) {
323
+ const contextArgs = await core.Context.args("initialize", this.class, [], this.adapter, this._overrides || {});
324
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.initialize);
325
+ const initiliazed = await this.adapter.submitTransaction(ctx, "Initialize", [ FabricERC20ClientRepository.serializer.serialize(token) ]);
326
+ return this.decode(initiliazed) === "true" ? true : false;
327
+ }
328
+ async checkInitialized() {
329
+ const contextArgs = await core.Context.args("checkInitialized", this.class, [], this.adapter, this._overrides || {});
330
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.checkInitialized);
331
+ await this.adapter.evaluateTransaction(ctx, "CheckInitialized");
332
+ }
333
+ async mint(amount) {
334
+ const contextArgs = await core.Context.args("mint", this.class, [], this.adapter, this._overrides || {});
335
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.mint);
336
+ await this.adapter.submitTransaction(ctx, "Mint", [ amount.toString() ]);
337
+ }
338
+ async burn(amount) {
339
+ const contextArgs = await core.Context.args("burn", this.class, [], this.adapter, this._overrides || {});
340
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.burn);
341
+ await this.adapter.submitTransaction(ctx, "Burn", [ amount.toString() ]);
342
+ }
343
+ async burnFrom(account, amount) {
344
+ const contextArgs = await core.Context.args("burnFrom", this.class, [], this.adapter, this._overrides || {});
345
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.burnFrom);
346
+ await this.adapter.submitTransaction(ctx, "BurnFrom", [ account, amount.toString() ]);
347
+ }
348
+ async clientAccountBalance() {
349
+ const contextArgs = await core.Context.args("accountBalance", this.class, [], this.adapter, this._overrides || {});
350
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.clientAccountBalance);
351
+ const serializedAccountBalance = await this.adapter.evaluateTransaction(ctx, "ClientAccountBalance");
352
+ return Number(this.decode(serializedAccountBalance));
353
+ }
354
+ async clientAccountID() {
355
+ const contextArgs = await core.Context.args("accountId", this.class, [], this.adapter, this._overrides || {});
356
+ const {ctx: ctx} = this.logCtx(contextArgs.args, this.clientAccountID);
357
+ const clientAccountID = await this.adapter.evaluateTransaction(ctx, "ClientAccountID");
358
+ return this.decode(clientAccountID);
359
+ }
360
+ }
361
+ function ensureDirectoryExistence(filePath) {
362
+ const fs = require("fs");
363
+ const path = require("path");
364
+ const dirname = path.dirname(filePath);
365
+ if (fs.existsSync(dirname)) {
366
+ return true;
367
+ }
368
+ ensureDirectoryExistence(dirname);
369
+ fs.mkdirSync(dirname);
370
+ }
371
+ function generateModelIndexes(m) {
372
+ return forCouchdb.generateIndexes([ m ]);
373
+ }
374
+ function generateModelDesignDocs(m, accum) {
375
+ const views = forCouchdb.generateViews([ m ]);
376
+ const storage = accum || {};
377
+ views.forEach(doc => {
378
+ storage[doc._id] = doc;
379
+ });
380
+ return views;
381
+ }
382
+ function readModelFile(file) {
383
+ const path = require("path");
384
+ const exports = require(path.join(process.cwd(), file.parentPath, file.name));
385
+ const values = Object.values(exports).filter(e => {
386
+ try {
387
+ const m = new e;
388
+ return m instanceof decoratorValidation.Model;
389
+ } catch (e) {
390
+ return false;
391
+ }
392
+ });
393
+ return values;
394
+ }
395
+ async function readModelFolders(...folders) {
396
+ const fs = require("fs");
397
+ const result = [];
398
+ for (const folder of folders) {
399
+ const files = fs.readdirSync(folder, {
400
+ withFileTypes: true,
401
+ recursive: true
402
+ }).filter(f => f.isFile() && f.name.endsWith("js"));
403
+ for (const file of files) {
404
+ result.push(...readModelFile(file));
405
+ }
406
+ }
407
+ return result;
408
+ }
409
+ function writeIndexes(indexes, p = process.cwd(), collection) {
410
+ const fs = require("fs");
411
+ const path = require("path");
412
+ indexes.forEach(index => {
413
+ const file = path.resolve(path.join(p, `./META-INF/statedb/couchdb/${collection ? `collections/${collection}/` : ""}indexes/${index.name}.json`));
414
+ ensureDirectoryExistence(file);
415
+ fs.writeFileSync(file, JSON.stringify(index, undefined, 2));
416
+ });
417
+ }
418
+ function writeDesignDocs(designDocs, p = process.cwd(), collection) {
419
+ if (!designDocs.length) return;
420
+ const fs = require("fs");
421
+ const path = require("path");
422
+ designDocs.forEach(doc => {
423
+ const docId = doc._id.replace(/^_design\//, "");
424
+ const file = path.resolve(path.join(p, `./META-INF/statedb/couchdb/${collection ? `collections/${collection}/` : ""}design_docs/${docId}.json`));
425
+ ensureDirectoryExistence(file);
426
+ const payload = {
427
+ ...doc
428
+ };
429
+ delete payload._rev;
430
+ fs.writeFileSync(file, JSON.stringify(payload, undefined, 2));
431
+ });
432
+ }
433
+ exports.IdentityCredentials = class IdentityCredentials extends core.BaseModel {
434
+ constructor(arg) {
435
+ super(arg);
436
+ }
437
+ };
438
+ tslib.__decorate([ decoration.description("Unique identifier of the credentials record"), core.column(), core.pk(), tslib.__metadata("design:type", String) ], exports.IdentityCredentials.prototype, "id", void 0);
439
+ tslib.__decorate([ decoration.description("PEM-encoded X.509 certificate for the identity"), core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], exports.IdentityCredentials.prototype, "certificate", void 0);
440
+ tslib.__decorate([ decoration.description("PEM-encoded root or intermediate certificate"), core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], exports.IdentityCredentials.prototype, "rootCertificate", void 0);
441
+ tslib.__decorate([ decoration.description("PEM-encoded private key"), core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], exports.IdentityCredentials.prototype, "privateKey", void 0);
442
+ exports.IdentityCredentials = tslib.__decorate([ decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], exports.IdentityCredentials);
443
+ exports.FabricModelKeys = void 0;
444
+ (function(FabricModelKeys) {
445
+ FabricModelKeys["PRIVATE"] = "private";
446
+ FabricModelKeys["SHARED"] = "shared";
447
+ FabricModelKeys["FABRIC"] = "fabric";
448
+ FabricModelKeys["OWNED_BY"] = "owned-by";
449
+ FabricModelKeys["TRANSACTION_ID"] = "transaction-id";
450
+ FabricModelKeys["MIRROR"] = "mirror";
451
+ })(exports.FabricModelKeys || (exports.FabricModelKeys = {}));
452
+ exports.IdentityType = void 0;
453
+ (function(IdentityType) {
454
+ IdentityType["X509"] = "X.509";
455
+ })(exports.IdentityType || (exports.IdentityType = {}));
456
+ const FabricFlavour = "hlf-fabric";
457
+ exports.Identity = class Identity extends core.BaseModel {
458
+ constructor(arg) {
459
+ super(arg);
460
+ this.type = exports.IdentityType.X509;
461
+ }
462
+ };
463
+ tslib.__decorate([ decoration.description("Unique identifier of the identity"), core.pk(), tslib.__metadata("design:type", String) ], exports.Identity.prototype, "id", void 0);
464
+ tslib.__decorate([ core.oneToOne(exports.IdentityCredentials, {
465
+ update: core.Cascade.CASCADE,
466
+ delete: core.Cascade.CASCADE
467
+ }), tslib.__metadata("design:type", exports.IdentityCredentials) ], exports.Identity.prototype, "credentials", void 0);
468
+ tslib.__decorate([ core.column(), decoratorValidation.required(), core.index(), tslib.__metadata("design:type", String) ], exports.Identity.prototype, "mspId", void 0);
469
+ tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], exports.Identity.prototype, "type", void 0);
470
+ exports.Identity = tslib.__decorate([ decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], exports.Identity);
471
+ class CoreUtils {
472
+ static {
473
+ this.logger = new logging.MiniLogger(CoreUtils.name);
474
+ }
475
+ constructor() {}
476
+ static async contentOfLoadFile(contentOrPath, fileReader) {
477
+ if (contentOrPath instanceof Uint8Array) return contentOrPath;
478
+ if (contentOrPath.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) return contentOrPath;
479
+ return await fileReader(contentOrPath);
480
+ }
481
+ static async readFile(contentOrPath) {
482
+ if (typeof contentOrPath !== "string") return contentOrPath;
483
+ const fileReader = async path => {
484
+ const {promises: promises} = await core.normalizeImport(import("fs"));
485
+ return await promises.readFile(path);
486
+ };
487
+ return await fileReader(contentOrPath);
488
+ }
489
+ static async getCAUser(userName, privateKey, certificate, mspId, options) {
490
+ this.logger.debug(decoratorValidation.stringFormat("Creating CA {0} user {1} with certificate {2}", mspId, userName, certificate));
491
+ const user = new fabricCommon.User(userName);
492
+ const config = options?.hsm ? {
493
+ software: false,
494
+ lib: options.hsm.library,
495
+ slot: options.hsm.slot,
496
+ label: options.hsm.tokenLabel,
497
+ pin: String(options.hsm.pin)
498
+ } : undefined;
499
+ const cryptoSuite = this.getCryptoSuite(config);
500
+ user.setCryptoSuite(cryptoSuite);
501
+ const enrollmentKey = options?.hsm ? await this.getHSMEnrollmentKey(cryptoSuite, certificate, options.hsm) : this.getSoftwareEnrollmentKey(cryptoSuite, privateKey);
502
+ await user.setEnrollment(enrollmentKey, certificate, mspId);
503
+ return user;
504
+ }
505
+ static getCryptoSuite(options) {
506
+ if (!options) return fabricCommon.User.newCryptoSuite();
507
+ if (CoreUtils.cryptoSuite) return CoreUtils.cryptoSuite;
508
+ CoreUtils.cryptoSuite = fabricCommon.User.newCryptoSuite(options);
509
+ return CoreUtils.cryptoSuite;
510
+ }
511
+ static getSoftwareEnrollmentKey(cryptoSuite, privateKey) {
512
+ if (!privateKey) {
513
+ throw new Error("Private key must be provided when HSM configuration is not supplied");
514
+ }
515
+ return cryptoSuite.createKeyFromRaw(privateKey);
516
+ }
517
+ static async getHSMEnrollmentKey(cryptoSuite, certificate, hsm) {
518
+ const ski = hsm.keyIdHex && hsm.keyIdHex.trim().length > 0 ? Buffer.from(hsm.keyIdHex, "hex") : await this.getCertificateSKI(certificate);
519
+ const key = await cryptoSuite.getKey(ski);
520
+ if (!key || typeof key.isPrivate === "function" && !key.isPrivate()) {
521
+ throw new Error("Unable to resolve private key from HSM");
522
+ }
523
+ return key;
524
+ }
525
+ static async getCertificateSKI(certificate) {
526
+ const x509 = new crypto$1.X509Certificate(certificate);
527
+ const jwk = x509.publicKey.export({
528
+ format: "jwk"
529
+ });
530
+ const prefix = Buffer.from([ 4 ]);
531
+ const x = Buffer.from(jwk.x || "", "base64url");
532
+ const y = Buffer.from(jwk.y || "", "base64url");
533
+ return crypto$1.createHash("sha256").update(Buffer.concat([ prefix, x, y ])).digest();
534
+ }
535
+ static async getIdentity(mspId, certDirectoryPath) {
536
+ const identityFileReader = async path => {
537
+ const {promises: promises} = await core.normalizeImport(import("fs"));
538
+ const certPath = await this.getFirstDirFileName(path);
539
+ const credentials = await promises.readFile(certPath);
540
+ return credentials;
541
+ };
542
+ const credentials = await this.contentOfLoadFile(certDirectoryPath, identityFileReader);
543
+ return {
544
+ mspId: mspId,
545
+ credentials: credentials
546
+ };
547
+ }
548
+ static async getFirstDirFileName(dirPath) {
549
+ const {promises: promises} = await core.normalizeImport(import("fs"));
550
+ const {join: join} = await core.normalizeImport(import("path"));
551
+ const files = await promises.readdir(dirPath);
552
+ return join(dirPath, files[0]);
553
+ }
554
+ static async getFirstDirFileNameContent(dirPath) {
555
+ const {promises: promises} = await core.normalizeImport(import("fs"));
556
+ const {join: join} = await core.normalizeImport(import("path"));
557
+ const files = await promises.readdir(dirPath);
558
+ return (await promises.readFile(join(dirPath, files[0]))).toString();
559
+ }
560
+ static async getFileContent(filePath) {
561
+ const {promises: promises} = await core.normalizeImport(import("fs"));
562
+ return (await promises.readFile(filePath)).toString();
563
+ }
564
+ static async getSigner(keyDirectoryPath) {
565
+ const signerFileReader = async path => {
566
+ const {promises: promises} = await core.normalizeImport(import("fs"));
567
+ const keyPath = await this.getFirstDirFileName(path);
568
+ return await promises.readFile(keyPath);
569
+ };
570
+ const privateKeyPem = await this.contentOfLoadFile(keyDirectoryPath, signerFileReader);
571
+ const privateKey = await this.extractPrivateKey(privateKeyPem);
572
+ const keys = Object.getOwnPropertySymbols(privateKey);
573
+ const k = privateKey[keys[0]];
574
+ return fabricGateway.signers.newPrivateKeySigner(k);
575
+ }
576
+ static async extractPrivateKey(pem) {
577
+ const libName = "crypto";
578
+ let subtle;
579
+ if (globalThis.window && globalThis.window.Crypto) {
580
+ subtle = globalThis.Crypto.subtle;
581
+ } else {
582
+ const lib = await core.normalizeImport(import(libName));
583
+ subtle = lib.subtle || lib.webcrypto.subtle;
584
+ }
585
+ if (!subtle) throw new Error("Could not load SubtleCrypto module");
586
+ function str2ab(str) {
587
+ const buf = new ArrayBuffer(str.length);
588
+ const bufView = new Uint8Array(buf);
589
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
590
+ bufView[i] = str.charCodeAt(i);
591
+ }
592
+ return buf;
593
+ }
594
+ const str = pem.toString("utf8").replace("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "").replace("-----END PRIVATE KEY-----", "");
595
+ const decoded = Buffer.from(str, "base64").toString("binary");
596
+ const binaryDer = str2ab(decoded);
597
+ const key = await subtle.importKey("pkcs8", binaryDer, {
598
+ name: "ECDSA",
599
+ namedCurve: "P-256"
600
+ }, true, [ "sign" ]);
601
+ return key;
602
+ }
603
+ }
604
+ const crypto = new webcrypto.Crypto;
605
+ x509__namespace.cryptoProvider.set(crypto);
606
+ exports.BASE_ALPHABET = void 0;
607
+ (function(BASE_ALPHABET) {
608
+ BASE_ALPHABET["BASE2"] = "01";
609
+ BASE_ALPHABET["BASE8"] = "01234567";
610
+ BASE_ALPHABET["BASE11"] = "0123456789a";
611
+ BASE_ALPHABET["BASE16"] = "0123456789abcdef";
612
+ BASE_ALPHABET["BASE32"] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
613
+ BASE_ALPHABET["BASE32_Z"] = "ybndrfg8ejkmcpqxot1uwisza345h769";
614
+ BASE_ALPHABET["BASE36"] = "0123456789abcdefghijklmnopqrstuvwxyz";
615
+ BASE_ALPHABET["BASE58"] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
616
+ BASE_ALPHABET["BASE62"] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
617
+ BASE_ALPHABET["BASE64"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
618
+ BASE_ALPHABET["BASE67"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~";
619
+ })(exports.BASE_ALPHABET || (exports.BASE_ALPHABET = {}));
620
+ exports.CRYPTO = void 0;
621
+ (function(CRYPTO) {
622
+ CRYPTO["HASH"] = "SHA-256";
623
+ CRYPTO[CRYPTO["ITERATIONS"] = 1e3] = "ITERATIONS";
624
+ CRYPTO[CRYPTO["KEYLENGTH"] = 48] = "KEYLENGTH";
625
+ CRYPTO[CRYPTO["DERIVED_IV_LENGTH"] = 16] = "DERIVED_IV_LENGTH";
626
+ CRYPTO[CRYPTO["DERIVED_KEY_LENGTH"] = 32] = "DERIVED_KEY_LENGTH";
627
+ CRYPTO["ALGORYTHM"] = "AES-GCM";
628
+ CRYPTO["KEY_ALGORYTHM"] = "PBKDF2";
629
+ })(exports.CRYPTO || (exports.CRYPTO = {}));
630
+ class BaseEncoder {
631
+ constructor(alphabet) {
632
+ this.alphabet = alphabet;
633
+ this.baseMap = new Uint8Array(256);
634
+ if (this.alphabet.length >= 255) throw new Error("Alphabet too long");
635
+ for (let j = 0; j < this.baseMap.length; j++) this.baseMap[j] = 255;
636
+ for (let i = 0; i < alphabet.length; i++) {
637
+ const x = alphabet.charAt(i);
638
+ const xc = x.charCodeAt(0);
639
+ if (this.baseMap[xc] !== 255) throw new Error(x + " is ambiguous");
640
+ this.baseMap[xc] = i;
641
+ }
642
+ this.base = this.alphabet.length;
643
+ this.leader = this.alphabet.charAt(0);
644
+ this.factor = Math.log(this.base) / Math.log(256);
645
+ this.iFactor = Math.log(256) / Math.log(this.base);
646
+ }
647
+ encode(source) {
648
+ if (typeof source === "string") {
649
+ source = Buffer.from(source);
650
+ } else if (ArrayBuffer.isView(source)) {
651
+ source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
652
+ } else if (Array.isArray(source)) {
653
+ source = Uint8Array.from(source);
654
+ }
655
+ if (source.length === 0) return "";
656
+ let zeroes = 0;
657
+ let length = 0;
658
+ let pbegin = 0;
659
+ const pend = source.length;
660
+ while (pbegin !== pend && source[pbegin] === 0) {
661
+ pbegin++;
662
+ zeroes++;
663
+ }
664
+ const size = (pend - pbegin) * this.iFactor + 1 >>> 0;
665
+ const b58 = new Uint8Array(size);
666
+ while (pbegin !== pend) {
667
+ let carry = source[pbegin];
668
+ let i = 0;
669
+ for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
670
+ carry += 256 * b58[it1] >>> 0;
671
+ b58[it1] = carry % this.base >>> 0;
672
+ carry = carry / this.base >>> 0;
673
+ }
674
+ if (carry !== 0) throw new Error("Non-zero carry");
675
+ length = i;
676
+ pbegin++;
677
+ }
678
+ let it2 = size - length;
679
+ while (it2 !== size && b58[it2] === 0) it2++;
680
+ let str = this.leader.repeat(zeroes);
681
+ for (;it2 < size; ++it2) {
682
+ str += this.alphabet.charAt(b58[it2]);
683
+ }
684
+ return str;
685
+ }
686
+ decodeUnsafe(source) {
687
+ if (source.length === 0) return new Uint8Array(0);
688
+ let psz = 0;
689
+ let zeroes = 0;
690
+ let length = 0;
691
+ while (source[psz] === this.leader) {
692
+ zeroes++;
693
+ psz++;
694
+ }
695
+ const size = (source.length - psz) * this.factor + 1 >>> 0;
696
+ const b256 = new Uint8Array(size);
697
+ while (source[psz]) {
698
+ let carry = this.baseMap[source.charCodeAt(psz)];
699
+ if (carry === 255) return;
700
+ let i = 0;
701
+ for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
702
+ carry += this.base * b256[it3] >>> 0;
703
+ b256[it3] = carry % 256 >>> 0;
704
+ carry = carry / 256 >>> 0;
705
+ }
706
+ if (carry !== 0) throw new Error("Non-zero carry");
707
+ length = i;
708
+ psz++;
709
+ }
710
+ let it4 = size - length;
711
+ while (it4 !== size && b256[it4] === 0) it4++;
712
+ const vch = new Uint8Array(zeroes + (size - it4));
713
+ let j = zeroes;
714
+ while (it4 !== size) vch[j++] = b256[it4++];
715
+ return vch;
716
+ }
717
+ decode(source) {
718
+ const buffer = this.decodeUnsafe(source);
719
+ if (buffer) return buffer;
720
+ throw new Error("Non-base" + this.base + " character");
721
+ }
722
+ }
723
+ class CryptoUtils {
724
+ static {
725
+ this.b58encoder = new BaseEncoder(exports.BASE_ALPHABET.BASE58);
726
+ }
727
+ static {
728
+ this.logger = new logging.MiniLogger(CryptoUtils.name);
729
+ }
730
+ constructor() {}
731
+ static fabricIdFromCertificate(certificate) {
732
+ this.logger.debug(decoratorValidation.stringFormat("Parsing certificate: {0}", certificate));
733
+ const cert = new x509__namespace.X509Certificate(certificate);
734
+ const {subject: subject, issuer: issuer} = cert;
735
+ this.logger.debug(decoratorValidation.stringFormat("Certificate parsed with subject {0} and issuer {1}", subject, issuer));
736
+ return `x509::/${subject.replaceAll(", ", "/")}::/${issuer.replaceAll(", ", "/")}`;
737
+ }
738
+ static encode(str) {
739
+ return this.b58encoder.encode(str);
740
+ }
741
+ static decode(str) {
742
+ const decoded = this.b58encoder.decode(str);
743
+ const result = (new TextDecoder).decode(decoded);
744
+ return result;
745
+ }
746
+ static stringToArrayBuffer(str) {
747
+ const buf = new ArrayBuffer(str.length);
748
+ const bufView = new Uint8Array(buf);
749
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
750
+ bufView[i] = str.charCodeAt(i);
751
+ }
752
+ return buf;
753
+ }
754
+ static async extractKey(type, pem, usages) {
755
+ const subtle = crypto.subtle;
756
+ const str = pem.toString("utf8").replace(new RegExp(`-----BEGIN (${type.toUpperCase()} KEY|CERTIFICATE)-----`), "").replaceAll("\n", "").replace(new RegExp(`-----END (${type.toUpperCase()} KEY|CERTIFICATE)-----`), "");
757
+ const decoded = Buffer.from(str, "base64").toString("binary");
758
+ const binaryDer = this.stringToArrayBuffer(decoded);
759
+ const key = await subtle.importKey("pkcs8", binaryDer, {
760
+ name: "ECDSA",
761
+ namedCurve: "P-256"
762
+ }, true, usages ? usages : [ "sign" ]);
763
+ return key;
764
+ }
765
+ static async extractPrivateKey(pem, usages) {
766
+ return this.extractKey("private", pem, usages);
767
+ }
768
+ static async extractPublicKey(pem, usages) {
769
+ return this.extractKey("public", pem, usages);
770
+ }
771
+ static async sign(privateKey, data) {
772
+ const key = await this.extractPrivateKey(privateKey);
773
+ const buff = await crypto.subtle.sign({
774
+ name: "ECDSA",
775
+ hash: "SHA-256"
776
+ }, key, data);
777
+ return Array.from(new Uint8Array(buff)).map(b => b.toString(16).padStart(2, "0")).join("");
778
+ }
779
+ static async verify(certificate, signature, data) {
780
+ const cert = new x509__namespace.X509Certificate(certificate);
781
+ const key = await cert.publicKey.export();
782
+ signature = typeof signature === "string" ? Buffer.from(signature, "hex") : signature;
783
+ data = typeof data === "string" ? Buffer.from(data) : data;
784
+ return crypto.subtle.verify({
785
+ name: "ECDSA",
786
+ hash: "SHA-256"
787
+ }, key, signature, data);
788
+ }
789
+ static async encrypt(certificate, data) {
790
+ const cert = new x509__namespace.X509Certificate(certificate);
791
+ const key = await cert.publicKey.export();
792
+ data = typeof data === "string" ? Buffer.from(data) : data;
793
+ const buff = await this.getSubtleCrypto().encrypt({
794
+ name: "ECDSA"
795
+ }, key, data);
796
+ return Array.from(new Uint8Array(buff)).map(b => b.toString(16).padStart(2, "0")).join("");
797
+ }
798
+ static getSubtleCrypto() {
799
+ return logging.isBrowser() ? globalThis.window.crypto.subtle : crypto.subtle;
800
+ }
801
+ static async decrypt(privateKey, data) {
802
+ const key = await this.extractPrivateKey(privateKey);
803
+ data = typeof data === "string" ? Buffer.from(data, "hex") : data;
804
+ return this.getSubtleCrypto().decrypt({
805
+ name: "ECDSA"
806
+ }, key, data);
807
+ }
808
+ static async getMaster(data) {
809
+ const textEncoder = new TextEncoder;
810
+ if (data === undefined) {
811
+ const genGenesis = crypto.randomUUID();
812
+ data = textEncoder.encode(genGenesis).buffer;
813
+ }
814
+ const importedKey = await this.getSubtleCrypto().importKey("raw", data, exports.CRYPTO.KEY_ALGORYTHM, false, [ "deriveBits" ]);
815
+ return {
816
+ key: importedKey,
817
+ iv: data
818
+ };
819
+ }
820
+ static async getDerivationKey(salt, key) {
821
+ const textEncoder = new TextEncoder;
822
+ const saltBuffer = textEncoder.encode(salt);
823
+ const saltHashed = await this.getSubtleCrypto().digest("SHA-256", saltBuffer);
824
+ const params = {
825
+ name: exports.CRYPTO.KEY_ALGORYTHM,
826
+ hash: exports.CRYPTO.HASH,
827
+ salt: saltHashed,
828
+ iterations: exports.CRYPTO.ITERATIONS
829
+ };
830
+ const derivation = await this.getSubtleCrypto().deriveBits(params, key, exports.CRYPTO.KEYLENGTH * 8);
831
+ return this.getKey(derivation);
832
+ }
833
+ static async getKey(derivation) {
834
+ const ivlen = 16;
835
+ const keylen = 32;
836
+ const derivedKey = derivation.slice(0, keylen);
837
+ const iv = derivation.slice(keylen);
838
+ const importedEncryptionKey = await this.getSubtleCrypto().importKey("raw", derivedKey, {
839
+ name: exports.CRYPTO.ALGORYTHM
840
+ }, false, [ "encrypt", "decrypt" ]);
841
+ return {
842
+ key: importedEncryptionKey,
843
+ iv: iv
844
+ };
845
+ }
846
+ static async encryptPin(text, keyObject) {
847
+ const textEncoder = new TextEncoder;
848
+ const textBuffer = textEncoder.encode(text);
849
+ const encryptedText = await this.getSubtleCrypto().encrypt({
850
+ name: exports.CRYPTO.ALGORYTHM,
851
+ iv: keyObject.iv
852
+ }, keyObject.key, textBuffer);
853
+ return encryptedText;
854
+ }
855
+ static async decryptPin(encryptedText, keyObject) {
856
+ const textDecoder = new TextDecoder;
857
+ const decryptedText = await this.getSubtleCrypto().decrypt({
858
+ name: exports.CRYPTO.ALGORYTHM,
859
+ iv: keyObject.iv
860
+ }, keyObject.key, encryptedText);
861
+ return textDecoder.decode(decryptedText);
862
+ }
863
+ }
864
+ class OverflowError extends dbDecorators.InternalError {
865
+ constructor(msg) {
866
+ super(msg, OverflowError.name);
867
+ }
868
+ }
869
+ class BalanceError extends dbDecorators.InternalError {
870
+ constructor(msg) {
871
+ super(msg, BalanceError.name);
872
+ }
873
+ }
874
+ class AllowanceError extends dbDecorators.InternalError {
875
+ constructor(msg) {
876
+ super(msg, AllowanceError.name);
877
+ }
878
+ }
879
+ class RegistrationError extends core.AuthorizationError {
880
+ constructor(msg) {
881
+ super(msg, RegistrationError.name);
882
+ }
883
+ }
884
+ class MissingContextError extends dbDecorators.InternalError {
885
+ constructor(msg) {
886
+ super(msg, MissingContextError.name, 500);
887
+ }
888
+ }
889
+ class UnauthorizedPrivateDataAccess extends dbDecorators.BaseError {
890
+ constructor(msg = "MISSING_PRIVATE_DATA_ERROR_MESSAGE") {
891
+ super(UnauthorizedPrivateDataAccess.name, msg, 403);
892
+ }
893
+ }
894
+ class NotInitializedError extends dbDecorators.BaseError {
895
+ constructor(msg) {
896
+ super(NotInitializedError.name, msg, 409);
897
+ }
898
+ }
899
+ class MissingPKCSS11Lib extends dbDecorators.InternalError {
900
+ constructor(msg) {
901
+ super(msg, MissingPKCSS11Lib.name, 500);
902
+ }
903
+ }
904
+ class EndorsementError extends dbDecorators.InternalError {
905
+ constructor(message) {
906
+ super(message, EndorsementError.name, 500);
907
+ }
908
+ }
909
+ class MvccReadConflictError extends dbDecorators.InternalError {
910
+ constructor(message) {
911
+ super(message, MvccReadConflictError.name, 500);
912
+ }
913
+ }
914
+ class PhantomReadConflictError extends dbDecorators.InternalError {
915
+ constructor(message) {
916
+ super(message, PhantomReadConflictError.name, 500);
917
+ }
918
+ }
919
+ class EndorsementPolicyError extends dbDecorators.InternalError {
920
+ constructor(message) {
921
+ super(message, EndorsementPolicyError.name, 500);
922
+ }
923
+ }
924
+ class TransactionLimitsError extends dbDecorators.InternalError {
925
+ constructor(message, name = TransactionLimitsError.name, code = 590) {
926
+ super(message, name, code);
927
+ }
928
+ }
929
+ class TransactionTimeoutError extends dbDecorators.InternalError {
930
+ constructor(message) {
931
+ super(message, TransactionTimeoutError.name, 591);
932
+ }
933
+ }
934
+ class TransactionBufferSizeError extends dbDecorators.InternalError {
935
+ constructor(message) {
936
+ super(message, TransactionBufferSizeError.name, 592);
937
+ }
938
+ }
939
+ exports.HFCAIdentityType = void 0;
940
+ (function(HFCAIdentityType) {
941
+ HFCAIdentityType["PEER"] = "peer";
942
+ HFCAIdentityType["ORDERER"] = "orderer";
943
+ HFCAIdentityType["CLIENT"] = "client";
944
+ HFCAIdentityType["USER"] = "user";
945
+ HFCAIdentityType["ADMIN"] = "admin";
946
+ })(exports.HFCAIdentityType || (exports.HFCAIdentityType = {}));
947
+ exports.HFCAIdentityAttributes = void 0;
948
+ (function(HFCAIdentityAttributes) {
949
+ HFCAIdentityAttributes["HFREGISTRARROLES"] = "hf.Registrar.Roles";
950
+ HFCAIdentityAttributes["HFREGISTRARDELEGATEROLES"] = "hf.Registrar.DelegateRoles";
951
+ HFCAIdentityAttributes["HFREGISTRARATTRIBUTES"] = "hf.Registrar.Attributes";
952
+ HFCAIdentityAttributes["HFINTERMEDIATECA"] = "hf.IntermediateCA";
953
+ HFCAIdentityAttributes["HFREVOKER"] = "hf.Revoker";
954
+ HFCAIdentityAttributes["HFAFFILIATIONMGR"] = "hf.AffiliationMgr";
955
+ HFCAIdentityAttributes["HFGENCRL"] = "hf.GenCRL";
956
+ })(exports.HFCAIdentityAttributes || (exports.HFCAIdentityAttributes = {}));
957
+ class FabricEnrollmentService extends logging.LoggedClass {
958
+ constructor(caConfig) {
959
+ CoreUtils.getCryptoSuite(caConfig.hsm ? {
960
+ software: false,
961
+ lib: caConfig.hsm.library,
962
+ slot: caConfig.hsm.slot,
963
+ label: caConfig.hsm.tokenLabel,
964
+ pin: String(caConfig.hsm.pin)
965
+ } : undefined);
966
+ super();
967
+ this.caConfig = caConfig;
968
+ }
969
+ async User() {
970
+ if (this.user) return this.user;
971
+ const {caName: caName, caCert: caCert, caKey: caKey, url: url, hsm: hsm} = this.caConfig;
972
+ const log = this.log.for(this.User);
973
+ log.debug(`Creating CA user for ${caName} at ${url}`);
974
+ log.debug(`Retrieving CA certificate from ${caCert}`);
975
+ const certificate = await CoreUtils.getFirstDirFileNameContent(caCert);
976
+ let key;
977
+ if (!hsm) {
978
+ if (!caKey) {
979
+ throw new dbDecorators.InternalError(`Missing caKey configuration for CA ${caName}. Provide a key directory or configure HSM support.`);
980
+ }
981
+ log.debug(`Retrieving CA key from ${caKey}`);
982
+ key = await CoreUtils.getFirstDirFileNameContent(caKey);
983
+ } else {
984
+ log.debug(`Using HSM configuration for CA ${caName} with library ${hsm.library}`);
985
+ }
986
+ log.debug(`Loading Admin user for ca ${caName}`);
987
+ this.user = await CoreUtils.getCAUser("admin", key, certificate, caName, {
988
+ hsm: hsm
989
+ });
990
+ return this.user;
991
+ }
992
+ async CA() {
993
+ if (this.ca) return this.ca;
994
+ const log = this.log.for(this.CA);
995
+ const {url: url, tls: tls, caName: caName} = this.caConfig;
996
+ let {trustedRoots: trustedRoots, verify: verify} = tls;
997
+ const root = trustedRoots[0];
998
+ log.debug(`Retrieving CA certificate from ${root}. cwd: ${process.cwd()}`);
999
+ const certificate = await CoreUtils.getFileContent(root);
1000
+ log.debug(`Creating CA Client for CA ${caName} under ${url}`);
1001
+ this.ca = new FabricCAServices(url, {
1002
+ trustedRoots: Buffer.from(certificate),
1003
+ verify: verify
1004
+ }, caName);
1005
+ return this.ca;
1006
+ }
1007
+ async Client() {
1008
+ if (this.client) return this.client;
1009
+ const ca = await this.CA();
1010
+ this.client = ca["_FabricCAServices"];
1011
+ return this.client;
1012
+ }
1013
+ async Certificate() {
1014
+ if (!this.certificateService) this.certificateService = (await this.Client()).newCertificateService();
1015
+ return this.certificateService;
1016
+ }
1017
+ async Affiliations() {
1018
+ if (!this.affiliationService) this.affiliationService = (await this.CA()).newAffiliationService();
1019
+ return this.affiliationService;
1020
+ }
1021
+ async Identities() {
1022
+ if (!this.identityService) this.identityService = (await this.CA()).newIdentityService();
1023
+ return this.identityService;
1024
+ }
1025
+ async getCertificates(request, doMap = true) {
1026
+ const certificateService = await this.Certificate();
1027
+ const user = await this.User();
1028
+ const log = this.log.for(this.getCertificates);
1029
+ log.debug(`Retrieving certificates${request ? ` for ${request.id}` : ""} for CA ${this.caConfig.caName}`);
1030
+ const response = (await certificateService.getCertificates(request || {}, user)).result;
1031
+ log.debug(`Found ${response.certs.length} certificates: ${JSON.stringify(response)}`);
1032
+ return doMap ? response.certs.map(c => c.PEM) : response;
1033
+ }
1034
+ async getIdentities() {
1035
+ const identitiesService = await this.Identities();
1036
+ const log = this.log.for(this.getIdentities);
1037
+ log.debug(`Retrieving Identities under CA ${this.caConfig.caName}`);
1038
+ const response = (await identitiesService.getAll(await this.User())).result;
1039
+ log.debug(`Found ${response.identities.length} Identities: ${JSON.stringify(response)}`);
1040
+ return response.identities;
1041
+ }
1042
+ parseError(e) {
1043
+ const regexp = /.*code:\s(\d+).*?message:\s["'](.+)["']/gs;
1044
+ const match = regexp.exec(e.message);
1045
+ if (!match) return new RegistrationError(e);
1046
+ const [, code, message] = match;
1047
+ switch (code) {
1048
+ case "74":
1049
+ case "71":
1050
+ return new dbDecorators.ConflictError(message);
1051
+
1052
+ case "20":
1053
+ return new core.AuthorizationError(message);
1054
+
1055
+ default:
1056
+ return new RegistrationError(message);
1057
+ }
1058
+ }
1059
+ async getAffiliations() {
1060
+ const affiliationService = await this.Affiliations();
1061
+ const log = this.log.for(this.getAffiliations);
1062
+ log.debug(`Retrieving Affiliations under CA ${this.caConfig.caName}`);
1063
+ const response = (await affiliationService.getAll(await this.User())).result;
1064
+ log.debug(`Found ${response.a.length} Affiliations: ${JSON.stringify(response)}`);
1065
+ return response;
1066
+ }
1067
+ async read(enrollmentId) {
1068
+ const ca = await this.CA();
1069
+ const user = await this.User();
1070
+ let result;
1071
+ try {
1072
+ result = await ca.newIdentityService().getOne(enrollmentId, user);
1073
+ } catch (e) {
1074
+ throw new dbDecorators.NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${e}`);
1075
+ }
1076
+ if (!result.success) throw new dbDecorators.NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1077
+ return result.result;
1078
+ }
1079
+ async register(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments) {
1080
+ let registration;
1081
+ const log = this.log.for(this.register);
1082
+ try {
1083
+ const {userName: userName, password: password} = model;
1084
+ const ca = await this.CA();
1085
+ const user = await this.User();
1086
+ const props = {
1087
+ enrollmentID: userName,
1088
+ enrollmentSecret: password,
1089
+ affiliation: affiliation,
1090
+ userRole: userRole,
1091
+ attrs: attrs,
1092
+ maxEnrollments: maxEnrollments
1093
+ };
1094
+ registration = await ca.register(props, user);
1095
+ log.info(`Registration for ${userName} created with user type ${userRole ?? "Undefined Role"} ${isSuperUser ? "as super user" : ""}`);
1096
+ } catch (e) {
1097
+ throw this.parseError(e);
1098
+ }
1099
+ return registration;
1100
+ }
1101
+ static identityFromEnrollment(enrollment, mspId) {
1102
+ const {certificate: certificate, key: key, rootCertificate: rootCertificate} = enrollment;
1103
+ const log = logging.Logging.for(FabricEnrollmentService, {}).for(this.identityFromEnrollment);
1104
+ log.debug(`Generating Identity from certificate ${certificate} in msp ${mspId}`);
1105
+ const clientId = CryptoUtils.fabricIdFromCertificate(certificate);
1106
+ const id = CryptoUtils.encode(clientId);
1107
+ log.debug(`Identity ${clientId} and encodedId ${id}`);
1108
+ const now = new Date;
1109
+ return new exports.Identity({
1110
+ id: id,
1111
+ credentials: {
1112
+ id: id,
1113
+ certificate: certificate,
1114
+ privateKey: key.toBytes(),
1115
+ rootCertificate: rootCertificate,
1116
+ createdOn: now,
1117
+ updatedOn: now
1118
+ },
1119
+ mspId: mspId,
1120
+ createdOn: now,
1121
+ updatedOn: now
1122
+ });
1123
+ }
1124
+ async enroll(enrollmentId, registration) {
1125
+ let identity;
1126
+ const log = this.log.for(this.enroll);
1127
+ try {
1128
+ const ca = await this.CA();
1129
+ log.debug(`Enrolling ${enrollmentId}`);
1130
+ const enrollment = await ca.enroll({
1131
+ enrollmentID: enrollmentId,
1132
+ enrollmentSecret: registration
1133
+ });
1134
+ identity = FabricEnrollmentService.identityFromEnrollment(enrollment, this.caConfig.caName);
1135
+ log.info(`Successfully enrolled ${enrollmentId} under ${this.caConfig.caName} as ${identity.id}`);
1136
+ } catch (e) {
1137
+ throw this.parseError(e);
1138
+ }
1139
+ return identity;
1140
+ }
1141
+ async registerAndEnroll(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments) {
1142
+ const registration = await this.register(model, isSuperUser, affiliation, userRole, attrs, maxEnrollments);
1143
+ const {userName: userName} = model;
1144
+ return this.enroll(userName, registration);
1145
+ }
1146
+ async revoke(enrollmentId) {
1147
+ const ca = await this.CA();
1148
+ const user = await this.User();
1149
+ const identity = await this.read(enrollmentId);
1150
+ if (!identity) throw new dbDecorators.NotFoundError(`Could not find enrollment with id ${enrollmentId}`);
1151
+ let result;
1152
+ try {
1153
+ result = await ca.revoke({
1154
+ enrollmentID: identity.id,
1155
+ reason: "User Deletation"
1156
+ }, user);
1157
+ } catch (e) {
1158
+ throw new dbDecorators.InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${e}`);
1159
+ }
1160
+ if (!result.success) throw new dbDecorators.InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1161
+ return result;
1162
+ }
1163
+ }
1164
+ class RegistrationRequestBuilder extends decoratorValidation.Model {
1165
+ constructor() {
1166
+ super(...arguments);
1167
+ this.affiliation = "";
1168
+ }
1169
+ build() {
1170
+ const errs = this.hasErrors();
1171
+ if (errs) throw new dbDecorators.ValidationError(errs.toString());
1172
+ const response = {
1173
+ enrollmentID: this.enrollmentID,
1174
+ enrollmentSecret: this.enrollmentSecret,
1175
+ role: this.role,
1176
+ affiliation: this.affiliation
1177
+ };
1178
+ if (typeof this.maxEnrollments !== "undefined") response.maxEnrollments = this.maxEnrollments;
1179
+ if (this.attrs) response.attrs = this.attrs;
1180
+ return response;
1181
+ }
1182
+ setAffiliation(value) {
1183
+ this.affiliation = value;
1184
+ return this;
1185
+ }
1186
+ addAttr(attr) {
1187
+ this.attrs = this.attrs || [];
1188
+ this.attrs.push(attr);
1189
+ return this;
1190
+ }
1191
+ setAttrs(value) {
1192
+ this.attrs = value;
1193
+ return this;
1194
+ }
1195
+ setEnrollmentID(value) {
1196
+ this.enrollmentID = value;
1197
+ return this;
1198
+ }
1199
+ setEnrollmentSecret(value) {
1200
+ this.enrollmentSecret = value;
1201
+ return this;
1202
+ }
1203
+ setMaxEnrollments(value) {
1204
+ this.maxEnrollments = value;
1205
+ return this;
1206
+ }
1207
+ setRole(value) {
1208
+ this.role = value;
1209
+ return this;
1210
+ }
1211
+ }
1212
+ tslib.__decorate([ decoratorValidation.required(), tslib.__metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "affiliation", void 0);
1213
+ tslib.__decorate([ decoratorValidation.minlength(1), tslib.__metadata("design:type", Array) ], RegistrationRequestBuilder.prototype, "attrs", void 0);
1214
+ tslib.__decorate([ decoratorValidation.required(), tslib.__metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "enrollmentID", void 0);
1215
+ tslib.__decorate([ decoratorValidation.required(), tslib.__metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "enrollmentSecret", void 0);
1216
+ tslib.__decorate([ decoratorValidation.min(0), tslib.__metadata("design:type", Number) ], RegistrationRequestBuilder.prototype, "maxEnrollments", void 0);
1217
+ tslib.__decorate([ decoratorValidation.required(), tslib.__metadata("design:type", String) ], RegistrationRequestBuilder.prototype, "role", void 0);
1218
+ exports.ERC20Events = void 0;
1219
+ (function(ERC20Events) {
1220
+ ERC20Events["TRANSFER"] = "Transfer";
1221
+ ERC20Events["APPROVAL"] = "Approval";
1222
+ })(exports.ERC20Events || (exports.ERC20Events = {}));
1223
+ exports.FabricBaseModel = class FabricBaseModel extends decoratorValidation.Model {
1224
+ constructor(arg) {
1225
+ super(arg);
1226
+ }
1227
+ };
1228
+ tslib.__decorate([ decoration.description("Stores the original timestamp of creation"), core.column(), core.createdAt(), tslib.__metadata("design:type", Date) ], exports.FabricBaseModel.prototype, "createdAt", void 0);
1229
+ tslib.__decorate([ decoration.description("Stores the timestamp of the last update"), core.column(), core.updatedAt(), tslib.__metadata("design:type", Date) ], exports.FabricBaseModel.prototype, "updatedAt", void 0);
1230
+ tslib.__decorate([ decoration.description("Stores the version of the model"), core.column(), dbDecorators.version(), tslib.__metadata("design:type", Number) ], exports.FabricBaseModel.prototype, "version", void 0);
1231
+ exports.FabricBaseModel = tslib.__decorate([ decoration.uses(FabricFlavour), tslib.__metadata("design:paramtypes", [ Object ]) ], exports.FabricBaseModel);
1232
+ exports.FabricIdentifiedBaseModel = class FabricIdentifiedBaseModel extends exports.FabricBaseModel {
1233
+ constructor(arg) {
1234
+ super(arg);
1235
+ }
1236
+ };
1237
+ tslib.__decorate([ decoration.description("Stores the creator"), core.column(), core.createdBy(), tslib.__metadata("design:type", String) ], exports.FabricIdentifiedBaseModel.prototype, "createdBy", void 0);
1238
+ tslib.__decorate([ decoration.description("Stores the user that last updated the model"), core.column(), core.updatedBy(), tslib.__metadata("design:type", String) ], exports.FabricIdentifiedBaseModel.prototype, "updatedBy", void 0);
1239
+ exports.FabricIdentifiedBaseModel = tslib.__decorate([ decoration.uses(FabricFlavour), tslib.__metadata("design:paramtypes", [ Object ]) ], exports.FabricIdentifiedBaseModel);
1240
+ decoratorValidation.Model.prototype.isShared = function isShared() {
1241
+ return decoratorValidation.Model.isShared(this.constructor);
1242
+ };
1243
+ decoratorValidation.Model.prototype.isPrivate = function isPrivate() {
1244
+ return decoratorValidation.Model.isPrivate(this.constructor);
1245
+ };
1246
+ decoratorValidation.Model.prototype.segregate = function segregate() {
1247
+ return decoratorValidation.Model.segregate(this);
1248
+ };
1249
+ decoratorValidation.Model.segregate = function segregate(model) {
1250
+ if (!decoratorValidation.Model.isTransient(model)) return {
1251
+ model: model
1252
+ };
1253
+ const decoratedProperties = decoration.Metadata.validatableProperties(model.constructor);
1254
+ const transientProps = decoration.Metadata.get(model.constructor, dbDecorators.DBKeys.TRANSIENT);
1255
+ const privateProperties = decoration.Metadata.get(model.constructor, exports.FabricModelKeys.PRIVATE);
1256
+ const sharedProperties = decoration.Metadata.get(model.constructor, exports.FabricModelKeys.SHARED);
1257
+ const result = {
1258
+ model: {},
1259
+ transient: {},
1260
+ privates: {},
1261
+ shared: {}
1262
+ };
1263
+ const transientKeys = Object.keys(transientProps || {});
1264
+ const privateKeys = Object.keys(privateProperties || {});
1265
+ const sharedKeys = Object.keys(sharedProperties || {});
1266
+ for (const key of decoratedProperties) {
1267
+ const value = model[key];
1268
+ const isTransient = transientKeys.includes(key);
1269
+ const isPrivate = privateKeys.includes(key);
1270
+ const isShared = sharedKeys.includes(key);
1271
+ if (isTransient || isPrivate || isShared) {
1272
+ result.transient = result.transient || {};
1273
+ result.transient[key] = value;
1274
+ }
1275
+ if (isPrivate) {
1276
+ result.privates = result.privates || {};
1277
+ result.privates[key] = value;
1278
+ }
1279
+ if (isShared) {
1280
+ result.shared = result.shared || {};
1281
+ result.shared[key] = value;
1282
+ }
1283
+ const shouldIncludeInModel = !isTransient && !isPrivate && !isShared;
1284
+ if (shouldIncludeInModel) {
1285
+ result.model = result.model || {};
1286
+ result.model[key] = value;
1287
+ }
1288
+ }
1289
+ result.model = decoratorValidation.Model.build(result.model, model.constructor.name);
1290
+ return result;
1291
+ }.bind(decoratorValidation.Model);
1292
+ decoratorValidation.Model.isPrivate = function isPrivate(model) {
1293
+ return !!decoration.Metadata.get(typeof model !== "function" ? model.constructor : model, exports.FabricModelKeys.PRIVATE);
1294
+ }.bind(decoratorValidation.Model);
1295
+ decoratorValidation.Model.isShared = function isShared(model) {
1296
+ return !!decoration.Metadata.get(typeof model !== "function" ? model.constructor : model, exports.FabricModelKeys.SHARED);
1297
+ }.bind(decoratorValidation.Model);
1298
+ decoratorValidation.Model.mirrored = function mirrored(model) {
1299
+ return decoration.Metadata.get(typeof model !== "function" ? model.constructor : model, decoration.Metadata.key(exports.FabricModelKeys.FABRIC, exports.FabricModelKeys.MIRROR));
1300
+ }.bind(decoratorValidation.Model);
1301
+ decoratorValidation.Model.ownerOf = function ownerOf(model) {
1302
+ const meta = decoration.Metadata.get(model.constructor, decoration.Metadata.key(exports.FabricModelKeys.FABRIC, exports.FabricModelKeys.OWNED_BY));
1303
+ if (!meta) return undefined;
1304
+ return model[meta];
1305
+ }.bind(decoratorValidation.Model);
1306
+ decoratorValidation.Model.mirroredAt = function mirroredAt(model) {
1307
+ model = typeof model !== "function" ? model.constructor : model;
1308
+ return decoration.Metadata.get(model, decoration.Metadata.key(exports.FabricModelKeys.FABRIC, exports.FabricModelKeys.MIRROR));
1309
+ }.bind(decoratorValidation.Model);
1310
+ decoratorValidation.Model.collectionsFor = function collectionsFor(model) {
1311
+ const privateKeys = [ exports.FabricModelKeys.PRIVATE ];
1312
+ const sharedKeys = [ exports.FabricModelKeys.SHARED ];
1313
+ const privateKey = decoration.Metadata.key(...privateKeys);
1314
+ const sharedKey = decoration.Metadata.key(...sharedKeys);
1315
+ const constr = typeof model === "function" ? model : model.constructor;
1316
+ const privateMeta = decoration.Metadata.get(constr, privateKey);
1317
+ const sharedMeta = decoration.Metadata.get(constr, sharedKey);
1318
+ return {
1319
+ privateCols: privateMeta?.collections || [],
1320
+ sharedCols: sharedMeta?.collections || []
1321
+ };
1322
+ }.bind(decoratorValidation.Model);
1323
+ const MIRROR_SKIP_FLAG_PREFIX = "mirror:skip:";
1324
+ function extractMspId(identity) {
1325
+ if (!identity) return undefined;
1326
+ if (typeof identity === "string") return identity;
1327
+ return identity.getMSPID();
1328
+ }
1329
+ function Owner() {
1330
+ return function(target, propertyKey, descriptor) {
1331
+ const originalMethod = descriptor.value;
1332
+ descriptor.value = async function(...args) {
1333
+ const ctx = args[0];
1334
+ const acountId = ctx.clientIdentity.getID();
1335
+ const select = await this["tokenRepository"].select();
1336
+ const tokens = await select.execute(ctx);
1337
+ if (tokens.length == 0) {
1338
+ throw new dbDecorators.NotFoundError("No tokens avaialble");
1339
+ }
1340
+ if (tokens.length > 1) {
1341
+ throw new dbDecorators.NotFoundError(`To many token available : ${tokens.length}`);
1342
+ }
1343
+ if (tokens[0].owner != acountId) {
1344
+ throw new core.AuthorizationError(`User not authorized to run ${propertyKey} on the token`);
1345
+ }
1346
+ return await originalMethod.apply(this, args);
1347
+ };
1348
+ return descriptor;
1349
+ };
1350
+ }
1351
+ async function ownedByOnCreate(context, data, key, model) {
1352
+ const {stub: stub} = context;
1353
+ const creator = await stub.getCreator();
1354
+ const owner = creator.mspid;
1355
+ const setOwnedByKeyValue = function(target, propertyKey, value) {
1356
+ Object.defineProperty(target, propertyKey, {
1357
+ enumerable: true,
1358
+ writable: false,
1359
+ configurable: true,
1360
+ value: value
1361
+ });
1362
+ };
1363
+ setOwnedByKeyValue(model, key, owner);
1364
+ }
1365
+ function ownedBy() {
1366
+ function ownedBy() {
1367
+ return function(obj, attribute) {
1368
+ return decoration.apply(decoratorValidation.required(), dbDecorators.generated(), dbDecorators.readonly(), dbDecorators.onCreate(ownedByOnCreate), decoration.propMetadata(decoration.Metadata.key(exports.FabricModelKeys.FABRIC, exports.FabricModelKeys.OWNED_BY), attribute))(obj, attribute);
1369
+ };
1370
+ }
1371
+ return decoration.Decoration.for(exports.FabricModelKeys.OWNED_BY).define({
1372
+ decorator: ownedBy,
1373
+ args: []
1374
+ }).apply();
1375
+ }
1376
+ async function transactionIdOnCreate(context, data, key, model) {
1377
+ const {stub: stub} = context;
1378
+ model[key] = stub.getTxID();
1379
+ }
1380
+ function transactionId() {
1381
+ function transactionId() {
1382
+ return function(obj, attribute) {
1383
+ return decoration.apply(decoratorValidation.required(), dbDecorators.readonly(), dbDecorators.onCreate(transactionIdOnCreate), dbDecorators.onUpdate(transactionIdOnCreate), decoration.propMetadata(decoration.Metadata.key(exports.FabricModelKeys.FABRIC, attribute, exports.FabricModelKeys.TRANSACTION_ID), attribute))(obj, attribute);
1384
+ };
1385
+ }
1386
+ return decoration.Decoration.for(exports.FabricModelKeys.TRANSACTION_ID).define({
1387
+ decorator: transactionId,
1388
+ args: []
1389
+ }).apply();
1390
+ }
1391
+ async function evalMirrorMetadata(model, resolver, ctx) {
1392
+ let collection = resolver;
1393
+ if (typeof collection !== "string") {
1394
+ try {
1395
+ const owner = decoratorValidation.Model.ownerOf(model) || ctx.get("stub").getCreator().toString();
1396
+ if (resolver && typeof resolver === "function") collection = await resolver(model, owner, ctx);
1397
+ } catch (e) {
1398
+ throw new dbDecorators.InternalError(`Failed to resolve collection mirror name: ${e}`);
1399
+ }
1400
+ }
1401
+ if (!collection || typeof collection !== "string") throw new dbDecorators.InternalError(`No collection found model ${model.constructor.name}`);
1402
+ return collection;
1403
+ }
1404
+ async function createMirrorHandler(context, data, key, model) {
1405
+ const collection = await evalMirrorMetadata(model, data.resolver, context);
1406
+ const repo = this.override(Object.assign({}, this._overrides, {
1407
+ segregated: collection,
1408
+ mirror: true,
1409
+ ignoreValidation: true,
1410
+ ignoreHandlers: true
1411
+ }));
1412
+ const mirror = await repo.create(model, context);
1413
+ context.logger.info(`Mirror for ${decoratorValidation.Model.tableName(this.class)} created with ${decoratorValidation.Model.pk(model)}: ${mirror[decoratorValidation.Model.pk(model)]}`);
1414
+ }
1415
+ async function updateMirrorHandler(context, data, key, model) {
1416
+ const collection = await evalMirrorMetadata(model, data.resolver, context);
1417
+ const repo = this.override(Object.assign({}, this._overrides, {
1418
+ segregated: collection,
1419
+ mirror: true,
1420
+ ignoreValidation: true,
1421
+ ignoreHandlers: true,
1422
+ applyUpdateValidation: false,
1423
+ mergeForUpdate: false
1424
+ }));
1425
+ await repo.update(model, context);
1426
+ context.logger.info(`Mirror for ${decoratorValidation.Model.tableName(this.class)} updated: ${model[decoratorValidation.Model.pk(model)]}`);
1427
+ }
1428
+ async function deleteMirrorHandler(context, data, key, model) {
1429
+ const collection = await evalMirrorMetadata(model, data.resolver, context);
1430
+ const pkProp = decoratorValidation.Model.pk(model);
1431
+ const id = model[pkProp];
1432
+ const repo = this.override(Object.assign({}, this._overrides, {
1433
+ segregated: collection,
1434
+ mirror: true,
1435
+ ignoreValidation: true,
1436
+ ignoreHandlers: true
1437
+ }));
1438
+ try {
1439
+ await repo.delete(id, context);
1440
+ } catch {}
1441
+ context.logger.info(`Mirror for ${decoratorValidation.Model.tableName(this.class)} deleted: ${String(id)}`);
1442
+ }
1443
+ async function mirrorWriteGuard(context, data, key, model) {
1444
+ const msp = extractMspId(context.get("identity"));
1445
+ if (!msp) return;
1446
+ if (data.condition(msp)) {
1447
+ throw new core.AuthorizationError(`Organization ${msp} is not authorized to modify mirrored data`);
1448
+ }
1449
+ }
1450
+ async function readMirrorHandler(context, data, key, model) {
1451
+ const msp = extractMspId(context.get("identity"));
1452
+ if (!msp) {
1453
+ context.logger.debug(`Mirror read: No MSP ID available, using default read behavior`);
1454
+ return;
1455
+ }
1456
+ const collection = await evalMirrorMetadata(model, data.resolver, context);
1457
+ const skipFlagKey = `${MIRROR_SKIP_FLAG_PREFIX}${collection}`;
1458
+ const fabricCtx = context;
1459
+ const matches = data.condition(msp);
1460
+ if (matches) {
1461
+ context.logger.info(`Mirror read: MSP ${msp} matches condition, routing ALL reads exclusively to collection ${collection}`);
1462
+ fabricCtx.put("segregated", collection);
1463
+ fabricCtx.readFrom(collection);
1464
+ fabricCtx.put(skipFlagKey, false);
1465
+ } else {
1466
+ fabricCtx.put(skipFlagKey, true);
1467
+ }
1468
+ }
1469
+ function mirror(collection, condition) {
1470
+ function mirror(resolver, condition) {
1471
+ const meta = {
1472
+ condition: condition,
1473
+ resolver: resolver
1474
+ };
1475
+ return decoration.apply(decoration.metadata(decoration.Metadata.key(exports.FabricModelKeys.FABRIC, exports.FabricModelKeys.MIRROR), meta), privateData(collection), dbDecorators.onRead(readMirrorHandler, meta, {
1476
+ priority: 30
1477
+ }), dbDecorators.onCreate(mirrorWriteGuard, meta, {
1478
+ priority: 20
1479
+ }), dbDecorators.onUpdate(mirrorWriteGuard, meta, {
1480
+ priority: 20
1481
+ }), dbDecorators.onDelete(mirrorWriteGuard, meta, {
1482
+ priority: 20
1483
+ }), dbDecorators.afterCreate(createMirrorHandler, meta, {
1484
+ priority: 95
1485
+ }), dbDecorators.afterUpdate(updateMirrorHandler, meta, {
1486
+ priority: 95
1487
+ }), dbDecorators.afterDelete(deleteMirrorHandler, meta, {
1488
+ priority: 95
1489
+ }));
1490
+ }
1491
+ return decoration.Decoration.for(exports.FabricModelKeys.MIRROR).define({
1492
+ decorator: mirror,
1493
+ args: [ collection, condition ]
1494
+ }).apply();
1495
+ }
1496
+ const ModelCollection = (model, mspId) => {
1497
+ const orgName = mspId || (typeof model !== "function" ? decoratorValidation.Model.ownerOf(model) : undefined);
1498
+ const constr = typeof model === "function" ? model : model.constructor;
1499
+ if (!orgName) throw new dbDecorators.InternalError(`Model ${constr.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);
1500
+ return `${logging.toPascalCase(constr.name)}${orgName ? logging.toPascalCase(orgName) : ""}`;
1501
+ };
1502
+ function NamespaceCollection(namespace) {
1503
+ return (model, mspId) => {
1504
+ const orgName = mspId || (typeof model !== "function" ? decoratorValidation.Model.ownerOf(model) : undefined);
1505
+ const constr = typeof model === "function" ? model : model.constructor;
1506
+ if (!orgName) throw new dbDecorators.InternalError(`Model ${constr.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);
1507
+ return `${namespace}${orgName ? logging.toPascalCase(orgName) : ""}`;
1508
+ };
1509
+ }
1510
+ const ImplicitPrivateCollection = (model, mspId) => {
1511
+ const orgName = mspId || (typeof model !== "function" ? decoratorValidation.Model.ownerOf(model) : undefined);
1512
+ if (!orgName) throw new dbDecorators.InternalError(`Model ${model.constructor.name} is not owned by any organization. did you use @ownedBy() (or provide the name)?`);
1513
+ return `__${logging.toPascalCase(orgName)}PrivateCollection`;
1514
+ };
1515
+ const SEGREGATED_COLLECTION_EXTRACTION_PRIORITY = 35;
1516
+ async function extractSegregatedCollections(context, data, keys, model) {
1517
+ const dataArray = Array.isArray(data) ? data : [ data ];
1518
+ const msp = decoratorValidation.Model.ownerOf(model) || extractMspId(context.get("identity"));
1519
+ if (!msp) {
1520
+ return;
1521
+ }
1522
+ const collections = [];
1523
+ for (const metadata of dataArray) {
1524
+ const collectionResolver = metadata.collections;
1525
+ const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model, msp, context);
1526
+ if (collection && !collections.includes(collection)) {
1527
+ collections.push(collection);
1528
+ }
1529
+ }
1530
+ if (collections.length > 0) {
1531
+ context.readFrom(collections);
1532
+ }
1533
+ const fabricCtx = context;
1534
+ if (!fabricCtx.isFullySegregated) {
1535
+ const pkProp = decoratorValidation.Model.pk(model);
1536
+ const segregated = decoratorValidation.Model.segregate(model);
1537
+ const publicKeys = Object.keys(segregated.model).filter(k => k !== pkProp && segregated.model[k] !== undefined);
1538
+ if (publicKeys.length === 0) {
1539
+ fabricCtx.markFullySegregated();
1540
+ }
1541
+ }
1542
+ const adapter = this.adapter;
1543
+ const tableName = decoratorValidation.Model.tableName(model.constructor);
1544
+ const seqName = `${tableName}_pk`;
1545
+ adapter.setSequenceSegregation(seqName, fabricCtx.isFullySegregated, collections);
1546
+ }
1547
+ async function segregatedDataOnCreate(context, data, keys, model) {
1548
+ const dataArray = Array.isArray(data) ? data : [ data ];
1549
+ const keyArray = Array.isArray(keys) ? keys : [ keys ];
1550
+ if (keyArray.length !== dataArray.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1551
+ const msp = decoratorValidation.Model.ownerOf(model) || extractMspId(context.get("identity"));
1552
+ if (!msp) throw new dbDecorators.ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1553
+ const collectionResolver = dataArray[0].collections;
1554
+ const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model, msp, context);
1555
+ keyArray.forEach((_k, i) => {
1556
+ const c = typeof dataArray[i].collections === "string" ? dataArray[i].collections : dataArray[i].collections(model, msp, context);
1557
+ if (c !== collection) throw new core.UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1558
+ });
1559
+ context.writeTo(collection, model);
1560
+ }
1561
+ async function segregatedDataOnRead(context, data, keys, model) {
1562
+ const dataArray = Array.isArray(data) ? data : [ data ];
1563
+ const keyArray = Array.isArray(keys) ? keys : [ keys ];
1564
+ if (keyArray.length !== dataArray.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1565
+ const msp = decoratorValidation.Model.ownerOf(model) || extractMspId(context.get("identity"));
1566
+ if (!msp) throw new dbDecorators.ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1567
+ const collectionResolver = dataArray[0].collections;
1568
+ const collection = typeof collectionResolver === "string" ? collectionResolver : await collectionResolver(model, msp, context);
1569
+ const skipFlagKey = `${MIRROR_SKIP_FLAG_PREFIX}${collection}`;
1570
+ const fabricCtx = context;
1571
+ if (fabricCtx.getOrUndefined(skipFlagKey)) return;
1572
+ context.readFrom(collection);
1573
+ }
1574
+ async function segregatedDataOnUpdate(context, data, key, model, oldModel) {
1575
+ const dataArray = Array.isArray(data) ? data : [ data ];
1576
+ const keyArray = Array.isArray(key) ? key : [ key ];
1577
+ if (keyArray.length !== dataArray.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1578
+ const msp = decoratorValidation.Model.ownerOf(model) || extractMspId(context.get("identity"));
1579
+ if (!msp) throw new dbDecorators.ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1580
+ const collectionResolver = dataArray[0].collections;
1581
+ const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model, msp, context);
1582
+ keyArray.forEach((k, i) => {
1583
+ const c = typeof dataArray[i].collections === "string" ? dataArray[i].collections : dataArray[i].collections(model, msp, context);
1584
+ if (c !== collection) throw new core.UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1585
+ });
1586
+ context.writeTo(collection, model);
1587
+ }
1588
+ async function segregatedDataOnDelete(context, data, key, model) {
1589
+ const dataArray = Array.isArray(data) ? data : [ data ];
1590
+ const keyArray = Array.isArray(key) ? key : [ key ];
1591
+ if (keyArray.length !== dataArray.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1592
+ const msp = decoratorValidation.Model.ownerOf(model) || extractMspId(context.get("identity"));
1593
+ if (!msp) throw new dbDecorators.ValidationError(`There's no assigned organization for model ${model.constructor.name}`);
1594
+ const collectionResolver = dataArray[0].collections;
1595
+ const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model, msp, context);
1596
+ context.readFrom(collection);
1597
+ }
1598
+ function segregated(collection, type, filter) {
1599
+ return function innerSegregated(target, propertyKey) {
1600
+ function segregatedDec(target, propertyKey) {
1601
+ const key = decoration.Metadata.key(type, propertyKey);
1602
+ const constr = target.constructor;
1603
+ const meta = decoration.Metadata.get(constr, key) || {};
1604
+ const collections = new Set(meta.collections || []);
1605
+ collections.add(collection);
1606
+ meta.collections = [ ...collections ];
1607
+ decoration.Metadata.set(constr, key, meta);
1608
+ const constrMeta = decoration.Metadata.get(constr, type) || {};
1609
+ const constrCollections = new Set(constrMeta.collections || []);
1610
+ constrCollections.add(collection);
1611
+ constrMeta.collections = [ ...constrCollections ];
1612
+ decoration.Metadata.set(constr, type, constrMeta);
1613
+ const transientMeta = decoration.Metadata.get(constr, dbDecorators.DBKeys.TRANSIENT) || {};
1614
+ const updatedTransientMeta = {
1615
+ ...transientMeta,
1616
+ [propertyKey]: {}
1617
+ };
1618
+ decoration.Metadata.set(constr, dbDecorators.DBKeys.TRANSIENT, updatedTransientMeta);
1619
+ }
1620
+ const decs = [];
1621
+ if (!propertyKey) {
1622
+ const properties = decoration.Metadata.validatableProperties(target);
1623
+ properties?.forEach(p => {
1624
+ if (!filter || filter(p)) {
1625
+ segregated(collection, type)(target.prototype, p);
1626
+ }
1627
+ });
1628
+ return target;
1629
+ } else {
1630
+ const groupName = typeof collection === "string" ? collection : collection.toString();
1631
+ const extractGroupName = `${groupName}:extract`;
1632
+ const dataGroupName = `${groupName}:data`;
1633
+ const earlyExtractionMeta = {
1634
+ collections: collection
1635
+ };
1636
+ const earlyExtractionGroupSort = {
1637
+ priority: SEGREGATED_COLLECTION_EXTRACTION_PRIORITY,
1638
+ group: extractGroupName
1639
+ };
1640
+ decs.push(decoration.prop(), dbDecorators.transient(), segregatedDec, dbDecorators.on(dbDecorators.DBOperations.ALL, extractSegregatedCollections, earlyExtractionMeta, earlyExtractionGroupSort), dbDecorators.onCreate(segregatedDataOnCreate, {
1641
+ collections: collection
1642
+ }, {
1643
+ priority: 95,
1644
+ group: dataGroupName
1645
+ }), dbDecorators.onRead(segregatedDataOnRead, {
1646
+ collections: collection
1647
+ }, {
1648
+ priority: 95,
1649
+ group: dataGroupName
1650
+ }), dbDecorators.onUpdate(segregatedDataOnUpdate, {
1651
+ collections: collection
1652
+ }, {
1653
+ priority: 95,
1654
+ group: dataGroupName
1655
+ }), dbDecorators.onDelete(segregatedDataOnDelete, {
1656
+ collections: collection
1657
+ }, {
1658
+ priority: 95,
1659
+ group: dataGroupName
1660
+ }));
1661
+ }
1662
+ return decoration.apply(...decs)(target, propertyKey);
1663
+ };
1664
+ }
1665
+ function privateData(collection = ImplicitPrivateCollection) {
1666
+ function privateData(collection) {
1667
+ return segregated(collection, exports.FabricModelKeys.PRIVATE);
1668
+ }
1669
+ return decoration.Decoration.for(exports.FabricModelKeys.PRIVATE).define({
1670
+ decorator: privateData,
1671
+ args: [ collection ]
1672
+ }).apply();
1673
+ }
1674
+ function sharedData(collection) {
1675
+ function sharedData(collection) {
1676
+ return segregated(collection, exports.FabricModelKeys.SHARED);
1677
+ }
1678
+ return decoration.Decoration.for(exports.FabricModelKeys.SHARED).define({
1679
+ decorator: sharedData,
1680
+ args: [ collection ]
1681
+ }).apply();
1682
+ }
1683
+ class DeterministicSerializer extends decoratorValidation.JSONSerializer {
1684
+ constructor() {
1685
+ super();
1686
+ }
1687
+ preSerialize(model) {
1688
+ const toSerialize = Object.assign({}, model);
1689
+ let metadata;
1690
+ try {
1691
+ metadata = decoration.Metadata.modelName(model.constructor);
1692
+ } catch (error) {
1693
+ metadata = undefined;
1694
+ }
1695
+ toSerialize[decoratorValidation.ModelKeys.ANCHOR] = metadata || model.constructor.name;
1696
+ const preSerialize = function preSerialize(obj) {
1697
+ const self = this;
1698
+ if (typeof obj !== "object") return obj;
1699
+ if (Array.isArray(obj)) return obj.map(o => preSerialize.call(self, o));
1700
+ return this.preSerialize.call(this, obj);
1701
+ }.bind(this);
1702
+ decoratorValidation.Model.relations(model).forEach(r => {
1703
+ toSerialize[r] = preSerialize(toSerialize[r]);
1704
+ });
1705
+ return toSerialize;
1706
+ }
1707
+ deserialize(str) {
1708
+ const deserialization = JSON.parse(str);
1709
+ const className = deserialization[decoratorValidation.ModelKeys.ANCHOR];
1710
+ if (!className) throw new Error("Could not find class reference in serialized model");
1711
+ const model = decoratorValidation.Model.build(deserialization, className);
1712
+ return model;
1713
+ }
1714
+ serialize(model) {
1715
+ const stringify = require("json-stringify-deterministic");
1716
+ const sortKeysRecursive = require("sort-keys-recursive");
1717
+ return stringify(sortKeysRecursive(this.preSerialize(model)));
1718
+ }
1719
+ }
1720
+ function generateFabricEventName(table, event, owner) {
1721
+ const params = [ table, event ];
1722
+ if (owner) params.push(owner);
1723
+ return params.join("_");
1724
+ }
1725
+ function parseEventName(name) {
1726
+ const parts = name.split("_");
1727
+ if (parts.length < 2 || parts.length > 3) return {
1728
+ table: undefined,
1729
+ event: name,
1730
+ owner: undefined
1731
+ };
1732
+ return {
1733
+ table: parts[0],
1734
+ event: parts[1],
1735
+ owner: parts[2]
1736
+ };
1737
+ }
1738
+ function add(a, b) {
1739
+ const c = a + b;
1740
+ if (a !== c - b || b !== c - a) {
1741
+ throw new OverflowError(`Addition overflow: ${a} + ${b}`);
1742
+ }
1743
+ return c;
1744
+ }
1745
+ function sub(a, b) {
1746
+ const c = a - b;
1747
+ if (a !== c + b || b !== a - c) {
1748
+ throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
1749
+ }
1750
+ return c;
1751
+ }
1752
+ function safeParseInt(string) {
1753
+ const digitRegex = /^\d+$/;
1754
+ if (!digitRegex.test(string)) {
1755
+ throw new dbDecorators.ValidationError(decoratorValidation.stringFormat("Failed to parse: {0}", "string contains digits"));
1756
+ }
1757
+ const parsedint = parseInt(string);
1758
+ if (isNaN(parsedint)) {
1759
+ throw new dbDecorators.ValidationError(decoratorValidation.stringFormat("Failed to parse: {0}", "string is not a parsable integer"));
1760
+ }
1761
+ return parsedint;
1762
+ }
1763
+ class SimpleDeterministicSerializer extends decoratorValidation.JSONSerializer {
1764
+ constructor() {
1765
+ super();
1766
+ }
1767
+ deserialize(str, tableName) {
1768
+ const deserialization = JSON.parse(str);
1769
+ return deserialization;
1770
+ }
1771
+ serialize(model, putAnchor = true) {
1772
+ const stringify = require("json-stringify-deterministic");
1773
+ const sortKeysRecursive = require("sort-keys-recursive");
1774
+ const preSerialization = this.preSerialize(model, putAnchor);
1775
+ return stringify(sortKeysRecursive(preSerialization));
1776
+ }
1777
+ preSerialize(model, putAnchor = true) {
1778
+ const toSerialize = Object.assign({}, model);
1779
+ let metadata;
1780
+ try {
1781
+ metadata = decoration.Metadata.modelName(model.constructor);
1782
+ } catch (error) {
1783
+ metadata = undefined;
1784
+ }
1785
+ if (putAnchor) toSerialize[decoratorValidation.ModelKeys.ANCHOR] = metadata || model.constructor.name;
1786
+ function preSerialize(obj) {
1787
+ if (typeof obj !== "object") return obj;
1788
+ if (Array.isArray(obj)) return obj.map(preSerialize);
1789
+ return this.preSerialize(obj);
1790
+ }
1791
+ decoratorValidation.Model.relations(model).forEach(r => {
1792
+ toSerialize[r] = preSerialize.call(this, toSerialize[r]);
1793
+ });
1794
+ return toSerialize;
1795
+ }
1796
+ }
1797
+ class FabricIdentityService extends core.ClientBasedService {
1798
+ constructor() {
1799
+ super();
1800
+ }
1801
+ get rootClient() {
1802
+ return this.client["_FabricCaServices"];
1803
+ }
1804
+ get user() {
1805
+ if (!this._user) throw new dbDecorators.InternalError("Fabric identity service not properly setup: missing user");
1806
+ return this._user;
1807
+ }
1808
+ get certificates() {
1809
+ return this.rootClient.newCertificateService();
1810
+ }
1811
+ get affiliations() {
1812
+ return this.client.newAffiliationService();
1813
+ }
1814
+ get identities() {
1815
+ return this.client.newIdentityService();
1816
+ }
1817
+ async getUser(cfg, ctx) {
1818
+ const log = ctx.logger.for(this.getUser);
1819
+ const {caName: caName, caCert: caCert, caKey: caKey, url: url, hsm: hsm} = cfg;
1820
+ log.info(`Creating CA user for ${caName} at ${url}`);
1821
+ log.verbose(`Retrieving CA certificate from ${caCert}`);
1822
+ const certificate = await CoreUtils.getFirstDirFileNameContent(caCert);
1823
+ let key;
1824
+ if (!hsm) {
1825
+ if (!caKey) {
1826
+ throw new dbDecorators.InternalError(`Missing caKey configuration for CA ${caName}. Provide a key directory or configure HSM support.`);
1827
+ }
1828
+ log.debug(`Retrieving CA key from ${caKey}`);
1829
+ key = await CoreUtils.getFirstDirFileNameContent(caKey);
1830
+ } else {
1831
+ log.debug(`Using HSM configuration for CA ${caName} with library ${hsm.library}`);
1832
+ }
1833
+ log.debug(`Loading Admin user for ca ${caName}`);
1834
+ this._user = await CoreUtils.getCAUser("admin", key, certificate, caName, {
1835
+ hsm: hsm
1836
+ });
1837
+ return this._user;
1838
+ }
1839
+ async initialize(...args) {
1840
+ const {log: log, ctx: ctx} = (await this.logCtx(args, core.PersistenceKeys.INITIALIZATION, true)).for(this.initialize);
1841
+ const [config] = args;
1842
+ if (!config) throw new dbDecorators.InternalError("Missing Fabric CA configuration");
1843
+ const {url: url, tls: tls, caName: caName} = config;
1844
+ log.info(`Initializing CA Client for CA ${config.caName} at ${config.url}`);
1845
+ const {trustedRoots: trustedRoots, verify: verify} = tls;
1846
+ const root = trustedRoots[0];
1847
+ log.debug(`Retrieving CA certificate from ${root}. cwd: ${process.cwd()}`);
1848
+ const certificate = await CoreUtils.getFileContent(root);
1849
+ log.debug(`CA Certificate: ${certificate.toString()}`);
1850
+ const client = new FabricCAServices(url, {
1851
+ trustedRoots: Buffer.from(certificate),
1852
+ verify: verify
1853
+ }, caName);
1854
+ const user = await this.getUser(config, ctx);
1855
+ log.debug(`CA user loaded: ${user.getName()}`);
1856
+ return {
1857
+ config: config,
1858
+ client: client
1859
+ };
1860
+ }
1861
+ async getCertificates(request, doMap = true, ...args) {
1862
+ if (request instanceof core.Context) {
1863
+ args = [ request ];
1864
+ doMap = true;
1865
+ request = undefined;
1866
+ } else if (typeof request === "boolean") {
1867
+ doMap = request;
1868
+ request = undefined;
1869
+ } else if (typeof doMap !== "boolean") {
1870
+ args = [ doMap, ...args ];
1871
+ doMap = true;
1872
+ }
1873
+ const {log: log} = (await this.logCtx(args, dbDecorators.OperationKeys.READ, true)).for(this.getCertificates);
1874
+ log.debug(`Retrieving certificates${request ? ` for ${request.id}` : ""} for CA ${this.config.caName}`);
1875
+ const response = (await this.certificates.getCertificates(request || {}, this.user)).result;
1876
+ log.verbose(`Found ${response.certs.length} certificates`);
1877
+ log.debug(response.certs);
1878
+ return doMap ? response.certs.map(c => c.PEM) : response;
1879
+ }
1880
+ async getIdentities(ctx) {
1881
+ const log = ctx.logger.for(this.getIdentities);
1882
+ log.verbose(`Retrieving Identities under CA ${this.config.caName}`);
1883
+ const response = (await this.identities.getAll(this.user)).result;
1884
+ log.verbose(`Found ${response.identities.length} Identities`);
1885
+ log.debug(response.identities);
1886
+ return response.identities;
1887
+ }
1888
+ async getAffiliations(ctx) {
1889
+ const log = ctx.logger.for(this.getAffiliations);
1890
+ log.verbose(`Retrieving Affiliations under CA ${this.config.caName}`);
1891
+ const response = (await this.affiliations.getAll(this.user)).result;
1892
+ log.verbose(`Found ${response.a.length} Affiliations`);
1893
+ log.debug(JSON.stringify(response));
1894
+ return response;
1895
+ }
1896
+ parseError(e) {
1897
+ const regexp = /.*code:\s(\d+).*?message:\s["'](.+)["']/gs;
1898
+ const match = regexp.exec(e.message);
1899
+ if (!match) return new RegistrationError(e);
1900
+ const [, code, message] = match;
1901
+ switch (code) {
1902
+ case "74":
1903
+ case "71":
1904
+ return new dbDecorators.ConflictError(message);
1905
+
1906
+ case "20":
1907
+ return new core.AuthorizationError(message);
1908
+
1909
+ default:
1910
+ return new RegistrationError(message);
1911
+ }
1912
+ }
1913
+ async read(enrollmentId, ...args) {
1914
+ const {log: log} = (await this.logCtx(args, dbDecorators.OperationKeys.READ, true)).for(this.read);
1915
+ log.verbose(`Retrieving identity with enrollment ID ${enrollmentId}`);
1916
+ let result;
1917
+ try {
1918
+ result = await this.identities.getOne(enrollmentId, this.user);
1919
+ } catch (e) {
1920
+ throw new dbDecorators.NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${e}`);
1921
+ }
1922
+ if (!result.success) throw new dbDecorators.NotFoundError(`Couldn't find enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
1923
+ return result.result;
1924
+ }
1925
+ async register(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments, ...args) {
1926
+ const {log: log} = (await this.logCtx(args, "register", true)).for(this.register);
1927
+ let registration;
1928
+ try {
1929
+ const {userName: userName, password: password} = model;
1930
+ const props = {
1931
+ enrollmentID: userName,
1932
+ enrollmentSecret: password,
1933
+ affiliation: affiliation,
1934
+ userRole: userRole,
1935
+ attrs: attrs,
1936
+ maxEnrollments: maxEnrollments
1937
+ };
1938
+ registration = await this.client.register(props, this.user);
1939
+ log.info(`Registration for ${userName} created with user type ${userRole ?? "Undefined Role"} ${isSuperUser ? "as super user" : ""}`);
1940
+ } catch (e) {
1941
+ throw this.parseError(e);
1942
+ }
1943
+ return registration;
1944
+ }
1945
+ static identityFromEnrollment(enrollment, mspId, ctx) {
1946
+ const log = ctx.logger.for(this.identityFromEnrollment);
1947
+ const {certificate: certificate, key: key, rootCertificate: rootCertificate} = enrollment;
1948
+ log.verbose(`Generating Identity from certificate ${certificate} in msp ${mspId}`);
1949
+ const clientId = CryptoUtils.fabricIdFromCertificate(certificate);
1950
+ const id = CryptoUtils.encode(clientId);
1951
+ log.debug(`Identity ${clientId} and encodedId ${id}`);
1952
+ return new exports.Identity({
1953
+ id: id,
1954
+ credentials: {
1955
+ id: id,
1956
+ certificate: certificate,
1957
+ privateKey: key.toBytes(),
1958
+ rootCertificate: rootCertificate
1959
+ },
1960
+ mspId: mspId
1961
+ });
1962
+ }
1963
+ async enroll(enrollmentId, registration, ...args) {
1964
+ const {log: log, ctx: ctx} = (await this.logCtx(args, "enroll", true)).for(this.enroll);
1965
+ let identity;
1966
+ try {
1967
+ log.debug(`Enrolling ${enrollmentId}`);
1968
+ const enrollment = await this.client.enroll({
1969
+ enrollmentID: enrollmentId,
1970
+ enrollmentSecret: registration
1971
+ });
1972
+ identity = FabricIdentityService.identityFromEnrollment(enrollment, this.config.caName, ctx);
1973
+ log.info(`Successfully enrolled ${enrollmentId} under ${this.config.caName} as ${identity.id}`);
1974
+ } catch (e) {
1975
+ throw this.parseError(e);
1976
+ }
1977
+ return identity;
1978
+ }
1979
+ async registerAndEnroll(model, isSuperUser = false, affiliation = "", userRole, attrs, maxEnrollments, ...args) {
1980
+ const {ctx: ctx} = (await this.logCtx(args, "register-enroll", true)).for(this.registerAndEnroll);
1981
+ const registration = await this.register(model, isSuperUser, affiliation, userRole, attrs, maxEnrollments, ctx);
1982
+ const {userName: userName} = model;
1983
+ return this.enroll(userName, registration, ctx);
1984
+ }
1985
+ async reenroll(enrollmentId, identity, attrReqs = [], ...args) {
1986
+ const {log: log, ctx: ctx} = (await this.logCtx(args, "reenroll", true)).for(this.reenroll);
1987
+ try {
1988
+ log.debug(`Re-enrolling ${enrollmentId}`);
1989
+ const {mspId: mspId, credentials: credentials} = identity;
1990
+ const user = fabricCommon.User.createUser(enrollmentId, "", mspId || this.user.getMspid(), credentials.certificate, credentials.privateKey);
1991
+ user.setCryptoSuite(this.user.getCryptoSuite());
1992
+ const enrollment = await this.client.reenroll(user, attrReqs);
1993
+ const newIdentity = FabricIdentityService.identityFromEnrollment(enrollment, this.config.caName, ctx);
1994
+ log.info(`Successfully re-enrolled ${enrollmentId} under ${this.config.caName} as ${newIdentity.id}`);
1995
+ return newIdentity;
1996
+ } catch (e) {
1997
+ throw this.parseError(e);
1998
+ }
1999
+ }
2000
+ async revoke(enrollmentId, ...args) {
2001
+ const {log: log} = (await this.logCtx(args, "revoke", true)).for(this.revoke);
2002
+ log.verbose(`Revoking identity with enrollment ID ${enrollmentId}`);
2003
+ const identity = await this.read(enrollmentId);
2004
+ if (!identity) throw new dbDecorators.NotFoundError(`Could not find enrollment with id ${enrollmentId}`);
2005
+ let result;
2006
+ try {
2007
+ result = await this.client.revoke({
2008
+ enrollmentID: identity.id,
2009
+ reason: "User Deletion"
2010
+ }, this.user);
2011
+ } catch (e) {
2012
+ throw new dbDecorators.InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${e}`);
2013
+ }
2014
+ if (!result.success) throw new dbDecorators.InternalError(`Could not revoke enrollment with id ${enrollmentId}: ${result.errors.join("\n")}`);
2015
+ return result;
2016
+ }
2017
+ }
2018
+ exports.CA_ROLE = void 0;
2019
+ (function(CA_ROLE) {
2020
+ CA_ROLE["ADMIN"] = "admin";
2021
+ CA_ROLE["USER"] = "user";
2022
+ CA_ROLE["CLIENT"] = "client";
2023
+ })(exports.CA_ROLE || (exports.CA_ROLE = {}));
2024
+ const DefaultFabricClientFlags = Object.assign({
2025
+ evaluateTimeout: 5,
2026
+ endorseTimeout: 15,
2027
+ submitTimeout: 5,
2028
+ commitTimeout: 60
2029
+ });
2030
+ const log = new logging.MiniLogger("fabric-fs");
2031
+ async function contentOfLoadFile(contentOrPath, fileReader) {
2032
+ if (contentOrPath instanceof Uint8Array) return contentOrPath;
2033
+ if (contentOrPath.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) return contentOrPath;
2034
+ return await fileReader(contentOrPath);
2035
+ }
2036
+ async function readFile(contentOrPath) {
2037
+ if (typeof contentOrPath !== "string") return contentOrPath;
2038
+ const fileReader = async path => {
2039
+ const {promises: promises} = await core.normalizeImport(import("fs"));
2040
+ return await promises.readFile(path);
2041
+ };
2042
+ return await fileReader(contentOrPath);
2043
+ }
2044
+ async function getCAUser(userName, privateKey, certificate, mspId) {
2045
+ log.debug(`Creating a CA ${mspId} user ${userName} with certificate ${certificate}`);
2046
+ const user = new fabricCommon.User(userName);
2047
+ const cryptoSuite = fabricCommon.User.newCryptoSuite();
2048
+ user.setCryptoSuite(cryptoSuite);
2049
+ const importedKey = cryptoSuite.createKeyFromRaw(privateKey);
2050
+ await user.setEnrollment(importedKey, certificate, mspId);
2051
+ return user;
2052
+ }
2053
+ async function getIdentity(mspId, certDirectoryPath) {
2054
+ const identityFileReader = async path => {
2055
+ const {promises: promises} = await core.normalizeImport(import("fs"));
2056
+ const certPath = await getFirstDirFileName(path);
2057
+ const credentials = await promises.readFile(certPath);
2058
+ return credentials;
2059
+ };
2060
+ const credentials = await contentOfLoadFile(certDirectoryPath, identityFileReader);
2061
+ return {
2062
+ mspId: mspId,
2063
+ credentials: credentials
2064
+ };
2065
+ }
2066
+ async function getFirstDirFileName(dirPath) {
2067
+ const {promises: promises} = await core.normalizeImport(import("fs"));
2068
+ const {join: join} = await core.normalizeImport(import("path"));
2069
+ const files = await promises.readdir(dirPath);
2070
+ return join(dirPath, files[0]);
2071
+ }
2072
+ async function getFirstDirFileNameContent(dirPath) {
2073
+ const {promises: promises} = await core.normalizeImport(import("fs"));
2074
+ const {join: join} = await core.normalizeImport(import("path"));
2075
+ const files = await promises.readdir(dirPath);
2076
+ return (await promises.readFile(join(dirPath, files[0]))).toString();
2077
+ }
2078
+ async function getSigner(keyDirectoryPath) {
2079
+ const signerFileReader = async path => {
2080
+ const {promises: promises} = await core.normalizeImport(import("fs"));
2081
+ const keyPath = await getFirstDirFileName(path);
2082
+ return await promises.readFile(keyPath);
2083
+ };
2084
+ const privateKeyPem = await contentOfLoadFile(keyDirectoryPath, signerFileReader);
2085
+ const privateKey = await extractPrivateKey(privateKeyPem);
2086
+ const keys = Object.getOwnPropertySymbols(privateKey);
2087
+ const k = privateKey[keys[0]];
2088
+ return fabricGateway.signers.newPrivateKeySigner(k);
2089
+ }
2090
+ async function extractPrivateKey(pem) {
2091
+ const libName = "crypto";
2092
+ let subtle;
2093
+ if (logging.isBrowser()) {
2094
+ subtle = globalThis.crypto.subtle;
2095
+ } else {
2096
+ const lib = await core.normalizeImport(import(libName));
2097
+ subtle = lib.subtle || lib.webcrypto.subtle;
2098
+ }
2099
+ if (!subtle) throw new Error("Could not load SubtleCrypto module");
2100
+ function str2ab(str) {
2101
+ const buf = new ArrayBuffer(str.length);
2102
+ const bufView = new Uint8Array(buf);
2103
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
2104
+ bufView[i] = str.charCodeAt(i);
2105
+ }
2106
+ return buf;
2107
+ }
2108
+ const str = pem.toString("utf8").replace("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "").replace("-----END PRIVATE KEY-----", "");
2109
+ const decoded = Buffer.from(str, "base64").toString("binary");
2110
+ const binaryDer = str2ab(decoded);
2111
+ try {
2112
+ const key = await subtle.importKey("pkcs8", binaryDer, {
2113
+ name: "ECDSA",
2114
+ namedCurve: "P-256"
2115
+ }, true, [ "sign" ]);
2116
+ return key;
2117
+ } catch (e) {
2118
+ throw new dbDecorators.InternalError(e);
2119
+ }
2120
+ }
2121
+ const escapeRegExp = value => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2122
+ function nextLexicographicString(value) {
2123
+ if (!value) return "\0";
2124
+ const chars = Array.from(value);
2125
+ for (let i = chars.length - 1; i >= 0; i -= 1) {
2126
+ const code = chars[i].codePointAt(0);
2127
+ if (code === undefined) continue;
2128
+ if (code < 1114111) {
2129
+ chars[i] = String.fromCodePoint(code + 1);
2130
+ return chars.slice(0, i + 1).join("");
2131
+ }
2132
+ }
2133
+ return `${value}\0`;
2134
+ }
2135
+ function prefixRange(prefix) {
2136
+ return {
2137
+ start: prefix,
2138
+ end: nextLexicographicString(prefix)
2139
+ };
2140
+ }
2141
+ class FabricClientStatement extends core.Statement {
2142
+ constructor(adapter, overrides) {
2143
+ super(adapter, overrides);
2144
+ }
2145
+ squash(ctx) {
2146
+ const squashed = super.squash(ctx);
2147
+ if (!squashed) return squashed;
2148
+ const {method: method, params: params, args: args} = squashed;
2149
+ const {direction: direction, limit: limit} = params;
2150
+ switch (method) {
2151
+ case core.PreparedStatementKeys.FIND:
2152
+ break;
2153
+
2154
+ case core.PreparedStatementKeys.PAGE:
2155
+ args.push(direction, limit);
2156
+ break;
2157
+
2158
+ case core.PreparedStatementKeys.FIND_BY:
2159
+ break;
2160
+
2161
+ case core.PreparedStatementKeys.LIST_BY:
2162
+ args.push(direction);
2163
+ break;
2164
+
2165
+ case core.PreparedStatementKeys.PAGE_BY:
2166
+ args.push(direction, limit);
2167
+ break;
2168
+
2169
+ case core.PreparedStatementKeys.FIND_ONE_BY:
2170
+ break;
2171
+
2172
+ default:
2173
+ throw new dbDecorators.InternalError(`Unsupported method ${method}`);
2174
+ }
2175
+ return squashed;
2176
+ }
2177
+ async executePrepared(...argz) {
2178
+ const repo = core.Repository.forModel(this.fromSelector, this.adapter.alias);
2179
+ const {method: method, args: args} = this.prepared;
2180
+ return repo.statement(method, ...args, ...argz);
2181
+ }
2182
+ async prepare(ctx) {
2183
+ ctx = ctx || await this.adapter.context(core.PersistenceKeys.QUERY, this.overrides || {}, this.fromSelector);
2184
+ if (this.isSimpleQuery() && ctx.get("forcePrepareSimpleQueries")) {
2185
+ const squashed = this.squash(ctx);
2186
+ if (squashed) {
2187
+ this.prepared = squashed;
2188
+ return this;
2189
+ }
2190
+ }
2191
+ const args = [];
2192
+ const params = {};
2193
+ const prepared = {
2194
+ class: this.fromSelector,
2195
+ args: args,
2196
+ params: params
2197
+ };
2198
+ const method = [ core.QueryClause.FIND_BY ];
2199
+ if (this.whereCondition) {
2200
+ const parsed = this.prepareCondition(this.whereCondition, ctx);
2201
+ method.push(parsed.method);
2202
+ if (parsed.args && parsed.args.length) args.push(...parsed.args);
2203
+ }
2204
+ if (this.selectSelector) method.push(core.QueryClause.SELECT, this.selectSelector.join(` ${core.QueryClause.AND.toLowerCase()} `));
2205
+ if (this.orderBySelectors?.length) {
2206
+ method.push(core.QueryClause.ORDER_BY, this.orderBySelectors[0][0]);
2207
+ args.push(this.orderBySelectors[0][1]);
2208
+ }
2209
+ prepared.method = logging.toCamelCase(method.join(" "));
2210
+ prepared.params = params;
2211
+ this.prepared = prepared;
2212
+ return this;
2213
+ }
2214
+ processRecord(r, pkAttr, sequenceType, ctx) {
2215
+ if (r[forCouchdb.CouchDBKeys.ID]) {
2216
+ const [, ...keyArgs] = r[forCouchdb.CouchDBKeys.ID].split(forCouchdb.CouchDBKeys.SEPARATOR);
2217
+ const id = keyArgs.join("_");
2218
+ return this.adapter.revert(r, this.fromSelector, core.Sequence.parseValue(sequenceType, id), undefined, ctx);
2219
+ }
2220
+ return r;
2221
+ }
2222
+ async raw(rawInput, ...args) {
2223
+ const {ctx: ctx} = this.logCtx(args, this.raw);
2224
+ const aggregator = rawInput?.aggregateInfo;
2225
+ if (rawInput?.aggregate && aggregator) {
2226
+ return this.executeAggregate(aggregator, ctx);
2227
+ }
2228
+ const results = await this.adapter.raw(rawInput, true, this.fromSelector, ctx);
2229
+ const pkAttr = decoratorValidation.Model.pk(this.fromSelector);
2230
+ const type = decoration.Metadata.get(this.fromSelector, decoration.Metadata.key(dbDecorators.DBKeys.ID, pkAttr))?.type;
2231
+ if (!this.selectSelector) return results.map(r => this.processRecord(r, pkAttr, type, ctx));
2232
+ return results;
2233
+ }
2234
+ build() {
2235
+ const log = this.log.for(this.build);
2236
+ const aggregateQuery = this.buildAggregateQuery();
2237
+ if (aggregateQuery) return aggregateQuery;
2238
+ const selectors = {};
2239
+ selectors[forCouchdb.CouchDBKeys.TABLE] = {};
2240
+ selectors[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(this.fromSelector);
2241
+ const query = {
2242
+ selector: selectors
2243
+ };
2244
+ if (this.selectSelector) query.fields = this.selectSelector;
2245
+ if (this.whereCondition) {
2246
+ const condition = this.parseCondition(core.Condition.and(this.whereCondition, core.Condition.attribute(forCouchdb.CouchDBKeys.TABLE).eq(query.selector[forCouchdb.CouchDBKeys.TABLE]))).selector;
2247
+ const selectorKeys = Object.keys(condition);
2248
+ if (selectorKeys.length === 1 && Object.values(forCouchdb.CouchDBGroupOperator).indexOf(selectorKeys[0]) !== -1) switch (selectorKeys[0]) {
2249
+ case forCouchdb.CouchDBGroupOperator.AND:
2250
+ condition[forCouchdb.CouchDBGroupOperator.AND] = [ ...Object.values(condition[forCouchdb.CouchDBGroupOperator.AND]).reduce((accum, val) => {
2251
+ const keys = Object.keys(val);
2252
+ if (keys.length !== 1) throw new Error("Too many keys in query selector. should be one");
2253
+ const k = keys[0];
2254
+ if (k === forCouchdb.CouchDBGroupOperator.AND) accum.push(...val[k]); else accum.push(val);
2255
+ return accum;
2256
+ }, []) ];
2257
+ query.selector = condition;
2258
+ break;
2259
+
2260
+ case forCouchdb.CouchDBGroupOperator.OR:
2261
+ {
2262
+ const s = {};
2263
+ s[forCouchdb.CouchDBGroupOperator.AND] = [ condition, ...Object.entries(query.selector).map(([key, val]) => {
2264
+ const result = {};
2265
+ result[key] = val;
2266
+ return result;
2267
+ }) ];
2268
+ query.selector = s;
2269
+ break;
2270
+ }
2271
+
2272
+ default:
2273
+ throw new Error("This should be impossible");
2274
+ } else {
2275
+ Object.entries(condition).forEach(([key, val]) => {
2276
+ if (query.selector[key]) log.warn(`A ${key} query param is about to be overridden: ${query.selector[key]} by ${val}`);
2277
+ query.selector[key] = val;
2278
+ });
2279
+ }
2280
+ }
2281
+ if (this.orderBySelectors?.length) {
2282
+ query.sort = query.sort || [];
2283
+ query.selector = query.selector || {};
2284
+ for (const [selectorKey, direction] of this.orderBySelectors) {
2285
+ const selector = selectorKey;
2286
+ const rec = {};
2287
+ rec[selector] = direction;
2288
+ query.sort.push(rec);
2289
+ if (!query.selector[selector]) {
2290
+ query.selector[selector] = {};
2291
+ query.selector[selector][forCouchdb.CouchDBOperator.BIGGER] = null;
2292
+ }
2293
+ }
2294
+ }
2295
+ if (this.limitSelector) {
2296
+ query.limit = this.limitSelector;
2297
+ } else {
2298
+ log.warn(`No limit selector defined. Using default couchdb limit of ${forCouchdb.CouchDBQueryLimit}`);
2299
+ query.limit = forCouchdb.CouchDBQueryLimit;
2300
+ }
2301
+ if (this.offsetSelector) query.skip = this.offsetSelector;
2302
+ return query;
2303
+ }
2304
+ parseCondition(condition) {
2305
+ function merge(op, obj1, obj2) {
2306
+ const result = {
2307
+ selector: {}
2308
+ };
2309
+ result.selector[op] = [ obj1, obj2 ];
2310
+ return result;
2311
+ }
2312
+ const {attr1: attr1, operator: operator, comparison: comparison} = condition;
2313
+ if (operator === core.Operator.STARTS_WITH) {
2314
+ if (typeof attr1 !== "string") throw new core.QueryError("STARTS_WITH requires an attribute name");
2315
+ if (typeof comparison !== "string") throw new core.QueryError("STARTS_WITH requires a string comparison");
2316
+ const range = prefixRange(comparison);
2317
+ const selector = {};
2318
+ selector[attr1] = {};
2319
+ selector[attr1][forCouchdb.CouchDBOperator.BIGGER_EQ] = range.start;
2320
+ selector[attr1][forCouchdb.CouchDBOperator.SMALLER] = range.end;
2321
+ return {
2322
+ selector: selector
2323
+ };
2324
+ }
2325
+ if (operator === core.Operator.ENDS_WITH) {
2326
+ if (typeof attr1 !== "string") throw new core.QueryError("ENDS_WITH requires an attribute name");
2327
+ if (typeof comparison !== "string") throw new core.QueryError("ENDS_WITH requires a string comparison");
2328
+ const selector = {};
2329
+ selector[attr1] = {
2330
+ [forCouchdb.CouchDBOperator.REGEXP]: `${escapeRegExp(comparison)}$`
2331
+ };
2332
+ return {
2333
+ selector: selector
2334
+ };
2335
+ }
2336
+ if (operator === core.Operator.BETWEEN) {
2337
+ const attr = attr1;
2338
+ if (!Array.isArray(comparison) || comparison.length !== 2) throw new core.QueryError("BETWEEN operator requires [min, max] comparison");
2339
+ const [min, max] = comparison;
2340
+ const opBetween = {};
2341
+ opBetween[attr] = {};
2342
+ opBetween[attr][forCouchdb.translateOperators(core.Operator.BIGGER_EQ)] = min;
2343
+ opBetween[attr][forCouchdb.translateOperators(core.Operator.SMALLER_EQ)] = max;
2344
+ return {
2345
+ selector: opBetween
2346
+ };
2347
+ }
2348
+ let op = {};
2349
+ if ([ core.GroupOperator.AND, core.GroupOperator.OR, core.Operator.NOT ].indexOf(operator) === -1) {
2350
+ op[attr1] = {};
2351
+ op[attr1][forCouchdb.translateOperators(operator)] = comparison;
2352
+ } else if (operator === core.Operator.NOT) {
2353
+ op = this.parseCondition(attr1).selector;
2354
+ op[forCouchdb.translateOperators(core.Operator.NOT)] = {};
2355
+ op[forCouchdb.translateOperators(core.Operator.NOT)][attr1.attr1] = comparison;
2356
+ } else {
2357
+ const op1 = this.parseCondition(attr1).selector;
2358
+ const op2 = this.parseCondition(comparison).selector;
2359
+ op = merge(forCouchdb.translateOperators(operator), op1, op2).selector;
2360
+ }
2361
+ return {
2362
+ selector: op
2363
+ };
2364
+ }
2365
+ buildAggregateQuery() {
2366
+ if (!this.fromSelector) return undefined;
2367
+ if (this.avgSelector) {
2368
+ const attribute = String(this.avgSelector);
2369
+ const sumInfo = this.createAggregateDescriptor("sum", attribute);
2370
+ const countInfo = this.createAggregateDescriptor("count", attribute);
2371
+ if (!sumInfo || !countInfo) throw new core.QueryError(`Avg operation requires sum and count views for attribute ${attribute}`);
2372
+ return this.createAggregateQuery({
2373
+ kind: "avg",
2374
+ attribute: attribute,
2375
+ sumDescriptor: sumInfo.descriptor,
2376
+ countDescriptor: countInfo.descriptor
2377
+ });
2378
+ }
2379
+ if (typeof this.countDistinctSelector !== "undefined") {
2380
+ const attribute = this.countDistinctSelector == null ? undefined : String(this.countDistinctSelector);
2381
+ const info = this.createAggregateDescriptor("distinct", attribute);
2382
+ if (info) {
2383
+ info.countDistinct = true;
2384
+ return this.createAggregateQuery(info);
2385
+ }
2386
+ }
2387
+ const aggregatorUsed = typeof this.countSelector !== "undefined" || typeof this.countDistinctSelector !== "undefined" || !!this.minSelector || !!this.maxSelector || !!this.sumSelector || !!this.distinctSelector;
2388
+ const aggregatorChecks = [ [ "count", this.countSelector ?? undefined ], [ "max", this.maxSelector ], [ "min", this.minSelector ], [ "sum", this.sumSelector ], [ "distinct", this.distinctSelector ] ];
2389
+ for (const [kind, selector] of aggregatorChecks) {
2390
+ const attribute = selector ? String(selector) : undefined;
2391
+ const info = this.createAggregateDescriptor(kind, attribute);
2392
+ if (info) return this.createAggregateQuery(info);
2393
+ }
2394
+ if (aggregatorUsed) {
2395
+ throw new core.QueryError(`No CouchDB view metadata found for table ${decoratorValidation.Model.tableName(this.fromSelector)} aggregator`);
2396
+ }
2397
+ return undefined;
2398
+ }
2399
+ createAggregateDescriptor(kind, attribute) {
2400
+ if (!this.fromSelector) return undefined;
2401
+ const metas = forCouchdb.findViewMetadata(this.fromSelector, kind, attribute);
2402
+ if (!metas.length) return undefined;
2403
+ const meta = metas[0];
2404
+ const tableName = decoratorValidation.Model.tableName(this.fromSelector);
2405
+ const viewName = forCouchdb.generateViewName(tableName, meta.attribute, kind, meta);
2406
+ const ddoc = meta.ddoc || forCouchdb.generateDesignDocName(tableName, viewName);
2407
+ const options = {
2408
+ reduce: meta.reduce !== undefined ? true : !meta.returnDocs
2409
+ };
2410
+ if (kind === "distinct" || kind === "groupBy") options.group = true;
2411
+ return {
2412
+ kind: kind,
2413
+ meta: meta,
2414
+ descriptor: {
2415
+ ddoc: ddoc,
2416
+ view: viewName,
2417
+ options: options
2418
+ }
2419
+ };
2420
+ }
2421
+ createAggregateQuery(info) {
2422
+ return {
2423
+ selector: {},
2424
+ aggregate: true,
2425
+ aggregateInfo: info
2426
+ };
2427
+ }
2428
+ getFabricAdapter() {
2429
+ return this.adapter;
2430
+ }
2431
+ async executeAggregate(info, ctx) {
2432
+ if (!this.isViewAggregate(info)) {
2433
+ return this.handleAverage(info, ctx);
2434
+ }
2435
+ const fabricAdapter = this.getFabricAdapter();
2436
+ const viewInfo = info;
2437
+ const response = await fabricAdapter.view(viewInfo.descriptor.ddoc, viewInfo.descriptor.view, viewInfo.descriptor.options, ctx);
2438
+ return this.processViewResponse(info, response);
2439
+ }
2440
+ async handleAverage(info, ctx) {
2441
+ if (info.kind !== "avg") throw new core.QueryError("Average descriptor is not valid");
2442
+ const fabricAdapter = this.getFabricAdapter();
2443
+ const [sumDesc, countDesc] = [ info.sumDescriptor, info.countDescriptor ];
2444
+ const [sumResponse, countResponse] = await Promise.all([ fabricAdapter.view(sumDesc.ddoc, sumDesc.view, sumDesc.options, ctx), fabricAdapter.view(countDesc.ddoc, countDesc.view, countDesc.options, ctx) ]);
2445
+ const sum = sumResponse.rows?.[0]?.value ?? 0;
2446
+ const count = countResponse.rows?.[0]?.value ?? 0;
2447
+ if (!count) return 0;
2448
+ return sum / count;
2449
+ }
2450
+ processViewResponse(info, response) {
2451
+ if (info.kind === "avg") throw new core.QueryError("Average results should be handled before processing rows");
2452
+ const rows = response.rows || [];
2453
+ const viewInfo = info;
2454
+ const meta = viewInfo.meta;
2455
+ if (viewInfo.countDistinct) {
2456
+ return rows.length || 0;
2457
+ }
2458
+ if (viewInfo.kind === "distinct" || viewInfo.kind === "groupBy") {
2459
+ return rows.map(row => row.key ?? row.value);
2460
+ }
2461
+ if (meta.returnDocs) {
2462
+ return rows.map(row => row.value ?? row.doc ?? row);
2463
+ }
2464
+ if (!rows.length) {
2465
+ return viewInfo.kind === "count" ? 0 : null;
2466
+ }
2467
+ return rows[0].value ?? rows[0].key ?? null;
2468
+ }
2469
+ isViewAggregate(info) {
2470
+ return info.kind !== "avg";
2471
+ }
2472
+ }
2473
+ class FabricClientPaginator extends core.Paginator {
2474
+ constructor(adapter, query, size, clazz) {
2475
+ super(adapter, query, size, clazz);
2476
+ }
2477
+ prepare(rawStatement) {
2478
+ throw new core.UnsupportedError(`Raw query access must be implemented by a subclass. only prepared statements are natively available`);
2479
+ }
2480
+ page(page = 1, ...args) {
2481
+ return super.page(page, ...args);
2482
+ }
2483
+ }
2484
+ var _a;
2485
+ class FabricClientAdapter extends core.Adapter {
2486
+ static {
2487
+ this.decoder = new TextDecoder("utf8");
2488
+ }
2489
+ static {
2490
+ this.serializer = new ClientSerializer;
2491
+ }
2492
+ static {
2493
+ this.log = logging.Logging.for(FabricClientAdapter);
2494
+ }
2495
+ constructor(config, alias) {
2496
+ super(Object.assign({}, DefaultFabricClientFlags, config), FabricFlavour, alias);
2497
+ this.serializer = FabricClientAdapter.serializer;
2498
+ }
2499
+ Statement(overrides) {
2500
+ return new FabricClientStatement(this, overrides);
2501
+ }
2502
+ Paginator(query, size, clazz) {
2503
+ return new FabricClientPaginator(this, query, size, clazz);
2504
+ }
2505
+ async flags(operation, model, flags, ...args) {
2506
+ const f = Object.assign(await super.flags(operation, model, Object.assign({}, this.config, flags), ...args));
2507
+ return f;
2508
+ }
2509
+ async context(operation, overrides, model, ...args) {
2510
+ const log = this.log.for(this.context);
2511
+ log.silly(`creating new context for ${operation} operation on ${model ? Array.isArray(model) ? model.map(m => decoratorValidation.Model.tableName(m)) : decoratorValidation.Model.tableName(model) : "no"} table ${overrides && Object.keys(overrides) ? Object.keys(overrides).length : "no"} with flag overrides`);
2512
+ let ctx = args.pop();
2513
+ if (typeof ctx !== "undefined" && !(ctx instanceof core.Context)) {
2514
+ args.push(ctx);
2515
+ ctx = undefined;
2516
+ }
2517
+ overrides = ctx ? Object.assign({}, ctx.toOverrides(), overrides) : overrides;
2518
+ const flags = await this.flags(typeof operation === "string" ? operation : operation.name, model, overrides, ...[ ...args, ctx ].filter(Boolean));
2519
+ if (ctx) {
2520
+ if (!(ctx instanceof this.Context)) {
2521
+ const newCtx = (new this.Context).accumulate({
2522
+ ...ctx["cache"],
2523
+ ...flags,
2524
+ parentContext: ctx
2525
+ });
2526
+ ctx.accumulate({
2527
+ childContexts: [ ...ctx.getOrUndefined("childContexts") || [], newCtx ]
2528
+ });
2529
+ return newCtx;
2530
+ }
2531
+ const currentOp = ctx.getOrUndefined("operation");
2532
+ const currentModel = ctx.getOrUndefined("affectedTables");
2533
+ if (!currentOp || currentOp !== operation || model && model !== currentModel) {
2534
+ const newCtx = (new this.Context).accumulate({
2535
+ ...ctx["cache"],
2536
+ ...flags,
2537
+ parentContext: ctx
2538
+ });
2539
+ ctx.accumulate({
2540
+ childContexts: [ ...ctx.getOrUndefined("childContexts") || [], newCtx ]
2541
+ });
2542
+ return newCtx;
2543
+ }
2544
+ return ctx.accumulate(flags);
2545
+ }
2546
+ return (new this.Context).accumulate({
2547
+ ...flags
2548
+ });
2549
+ }
2550
+ decode(data) {
2551
+ return FabricClientAdapter.decoder.decode(data);
2552
+ }
2553
+ repository() {
2554
+ return FabricClientRepository;
2555
+ }
2556
+ createPrefix(clazz, id, model, ...args) {
2557
+ const {ctxArgs: ctxArgs} = this.logCtx(args, this.createPrefix);
2558
+ const tableName = decoratorValidation.Model.tableName(clazz);
2559
+ const record = {};
2560
+ record[forCouchdb.CouchDBKeys.TABLE] = tableName;
2561
+ Object.assign(record, model);
2562
+ return [ clazz, id, record, ...ctxArgs ];
2563
+ }
2564
+ createAllPrefix(clazz, ids, models, ...args) {
2565
+ const tableName = decoratorValidation.Model.tableName(clazz);
2566
+ if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
2567
+ const {ctxArgs: ctxArgs} = this.logCtx(args, this.createAllPrefix);
2568
+ const records = ids.map((id, count) => {
2569
+ const record = {};
2570
+ record[forCouchdb.CouchDBKeys.TABLE] = tableName;
2571
+ Object.assign(record, models[count]);
2572
+ return record;
2573
+ });
2574
+ return [ clazz, ids, records, ...ctxArgs ];
2575
+ }
2576
+ updateAllPrefix(clazz, ids, models, ...args) {
2577
+ const tableName = decoratorValidation.Model.tableName(clazz);
2578
+ if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
2579
+ const {ctxArgs: ctxArgs} = this.logCtx(args, this.updateAllPrefix);
2580
+ const records = ids.map(() => {
2581
+ const record = {};
2582
+ record[forCouchdb.CouchDBKeys.TABLE] = tableName;
2583
+ return record;
2584
+ });
2585
+ return [ clazz, ids, records, ...ctxArgs ];
2586
+ }
2587
+ async createAll(clazz, ids, models, ...args) {
2588
+ if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
2589
+ const ctxArgs = [ ...args ];
2590
+ let transient = ctxArgs.shift();
2591
+ const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.createAll);
2592
+ const tableName = decoratorValidation.Model.tableName(clazz);
2593
+ log.info(`adding ${ids.length} entries to ${tableName} table`);
2594
+ log.verbose(`pks: ${ids}`);
2595
+ transient = transient && (Array.isArray(transient) ? transient : Object.keys(transient)).length ? {
2596
+ [tableName]: transient
2597
+ } : {};
2598
+ const result = await this.submitTransaction(ctx, dbDecorators.BulkCrudOperationKeys.CREATE_ALL, [ JSON.stringify(models.map(m => this.serializer.serialize(m, clazz.name))) ], transient, undefined, clazz.name);
2599
+ try {
2600
+ return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2601
+ } catch (e) {
2602
+ throw new dbDecorators.SerializationError(e);
2603
+ }
2604
+ }
2605
+ async readAll(clazz, ids, ...args) {
2606
+ const {log: log, ctx: ctx} = this.logCtx(args, this.readAll);
2607
+ const tableName = decoratorValidation.Model.tableName(clazz);
2608
+ log.info(`reading ${ids.length} entries to ${tableName} table`);
2609
+ log.verbose(`pks: ${ids}`);
2610
+ const result = await this.evaluateTransaction(ctx, dbDecorators.BulkCrudOperationKeys.READ_ALL, [ JSON.stringify(ids) ], undefined, undefined, clazz.name);
2611
+ try {
2612
+ return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2613
+ } catch (e) {
2614
+ throw new dbDecorators.SerializationError(e);
2615
+ }
2616
+ }
2617
+ async updateAll(clazz, ids, models, ...args) {
2618
+ if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
2619
+ const ctxArgs = [ ...args ];
2620
+ let transient = ctxArgs.shift();
2621
+ const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.updateAll);
2622
+ const tableName = decoratorValidation.Model.tableName(clazz);
2623
+ log.info(`updating ${ids.length} entries to ${tableName} table`);
2624
+ log.verbose(`pks: ${ids}`);
2625
+ transient = transient && (Array.isArray(transient) ? transient : Object.keys(transient)).length ? {
2626
+ [tableName]: transient
2627
+ } : {};
2628
+ const result = await this.submitTransaction(ctx, dbDecorators.BulkCrudOperationKeys.UPDATE_ALL, [ JSON.stringify(models.map(m => this.serializer.serialize(m, clazz.name))) ], transient, undefined, clazz.name);
2629
+ try {
2630
+ return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2631
+ } catch (e) {
2632
+ throw new dbDecorators.SerializationError(e);
2633
+ }
2634
+ }
2635
+ async deleteAll(clazz, ids, ...args) {
2636
+ const {log: log, ctx: ctx} = this.logCtx(args, this.deleteAll);
2637
+ const tableName = decoratorValidation.Model.tableName(clazz);
2638
+ log.info(`deleting ${ids.length} entries to ${tableName} table`);
2639
+ log.verbose(`pks: ${ids}`);
2640
+ const result = await this.submitTransaction(ctx, dbDecorators.BulkCrudOperationKeys.DELETE_ALL, [ JSON.stringify(ids) ], undefined, undefined, clazz.name);
2641
+ try {
2642
+ return JSON.parse(this.decode(result)).map(r => JSON.parse(r));
2643
+ } catch (e) {
2644
+ throw new dbDecorators.SerializationError(e);
2645
+ }
2646
+ }
2647
+ prepare(model, ...args) {
2648
+ const {log: log} = this.logCtx(args, this.prepare);
2649
+ const split = decoratorValidation.Model.segregate(model);
2650
+ if (model[core.PersistenceKeys.METADATA]) {
2651
+ log.silly(`Passing along persistence metadata for ${model[core.PersistenceKeys.METADATA]}`);
2652
+ Object.defineProperty(split.model, core.PersistenceKeys.METADATA, {
2653
+ enumerable: false,
2654
+ writable: false,
2655
+ configurable: true,
2656
+ value: model[core.PersistenceKeys.METADATA]
2657
+ });
2658
+ }
2659
+ return {
2660
+ record: split.model,
2661
+ model: split.model,
2662
+ id: model[decoratorValidation.Model.pk(model.constructor)],
2663
+ transient: split.transient,
2664
+ privates: split.privates,
2665
+ shared: split.shared
2666
+ };
2667
+ }
2668
+ revert(obj, clazz, id, transient, ...args) {
2669
+ const {log: log} = this.logCtx(args, this.revert);
2670
+ if (transient) {
2671
+ log.verbose(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
2672
+ Object.entries(transient).forEach(([key, val]) => {
2673
+ if (key in obj && typeof obj[key] !== "undefined") throw new dbDecorators.InternalError(`Transient property ${key} already exists on model ${typeof clazz === "string" ? clazz : clazz.name}. should be impossible`);
2674
+ obj[key] = val;
2675
+ });
2676
+ }
2677
+ return new clazz(obj);
2678
+ }
2679
+ async create(clazz, id, model, transient = {}, ...args) {
2680
+ const ctxArgs = [ ...args ];
2681
+ const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.create);
2682
+ const tableName = decoratorValidation.Model.tableName(clazz);
2683
+ log.verbose(`adding entry to ${tableName} table`);
2684
+ log.debug(`pk: ${id}`);
2685
+ transient = transient && Object.keys(transient).length ? {
2686
+ [tableName]: transient
2687
+ } : {};
2688
+ const result = await this.submitTransaction(ctx, dbDecorators.OperationKeys.CREATE, [ this.serializer.serialize(model, clazz.name) ], transient, undefined, clazz.name);
2689
+ return this.serializer.deserialize(this.decode(result));
2690
+ }
2691
+ async healthcheck(clazz, ...args) {
2692
+ const {log: log, ctx: ctx} = this.logCtx(args, this.healthcheck);
2693
+ const tableName = decoratorValidation.Model.tableName(clazz);
2694
+ log.verbose(`reading entry from ${tableName} table`);
2695
+ const result = await this.evaluateTransaction(ctx, dbDecorators.OperationKeys.READ, [], undefined, undefined, clazz.name);
2696
+ return JSON.parse(this.decode(result));
2697
+ }
2698
+ async read(clazz, id, ...args) {
2699
+ const {log: log, ctx: ctx} = this.logCtx(args, this.read);
2700
+ const tableName = decoratorValidation.Model.tableName(clazz);
2701
+ log.verbose(`reading entry from ${tableName} table`);
2702
+ log.debug(`pk: ${id}`);
2703
+ const result = await this.evaluateTransaction(ctx, dbDecorators.OperationKeys.READ, [ id.toString() ], undefined, undefined, clazz.name);
2704
+ return this.serializer.deserialize(this.decode(result));
2705
+ }
2706
+ updatePrefix(clazz, id, model, ...args) {
2707
+ const tableName = decoratorValidation.Model.tableName(clazz);
2708
+ const {ctxArgs: ctxArgs} = this.logCtx(args, this.updatePrefix);
2709
+ const record = {};
2710
+ record[forCouchdb.CouchDBKeys.TABLE] = tableName;
2711
+ Object.assign(record, model);
2712
+ return [ clazz, id, record, ...ctxArgs ];
2713
+ }
2714
+ async update(clazz, id, model, transient = {}, ...args) {
2715
+ const ctxArgs = [ ...args ];
2716
+ const {log: log, ctx: ctx} = this.logCtx(ctxArgs, this.updateAll);
2717
+ log.info(`CLIENT UPDATE class : ${typeof clazz}`);
2718
+ const tableName = decoratorValidation.Model.tableName(clazz);
2719
+ log.verbose(`updating entry to ${tableName} table`);
2720
+ log.debug(`pk: ${id}`);
2721
+ transient = transient && Object.keys(transient).length ? {
2722
+ [tableName]: transient
2723
+ } : {};
2724
+ const result = await this.submitTransaction(ctx, dbDecorators.OperationKeys.UPDATE, [ this.serializer.serialize(model, clazz.name || clazz) ], transient, undefined, clazz.name);
2725
+ return this.serializer.deserialize(this.decode(result));
2726
+ }
2727
+ async delete(clazz, id, ...args) {
2728
+ const {log: log, ctx: ctx} = this.logCtx(args, this.delete);
2729
+ const tableName = decoratorValidation.Model.tableName(clazz);
2730
+ log.verbose(`deleting entry from ${tableName} table`);
2731
+ log.debug(`pk: ${id}`);
2732
+ const result = await this.submitTransaction(ctx, dbDecorators.OperationKeys.DELETE, [ id.toString() ], undefined, undefined, clazz.name);
2733
+ return this.serializer.deserialize(this.decode(result));
2734
+ }
2735
+ async raw(rawInput, docsOnly = true, clazz, ...args) {
2736
+ const {log: log, ctx: ctx} = this.logCtx(args, this.raw);
2737
+ const tableName = clazz.name;
2738
+ log.info(`Performing raw statement on table ${decoratorValidation.Model.tableName(clazz)}`);
2739
+ let transactionResult;
2740
+ try {
2741
+ transactionResult = await this.evaluateTransaction(ctx, "raw", [ JSON.stringify(rawInput), docsOnly ], undefined, undefined, tableName);
2742
+ } catch (e) {
2743
+ throw this.parseError(e);
2744
+ }
2745
+ let result;
2746
+ try {
2747
+ result = JSON.parse(this.decode(transactionResult));
2748
+ } catch (e) {
2749
+ throw new dbDecorators.SerializationError(`Failed to process result: ${e}`);
2750
+ }
2751
+ const parseRecord = record => {
2752
+ if (decoratorValidation.Model.isModel(record)) return decoratorValidation.Model.build(record);
2753
+ return record;
2754
+ };
2755
+ if (Array.isArray(result)) {
2756
+ if (!result.length) return result;
2757
+ const el = result[0];
2758
+ if (decoratorValidation.Model.isModel(el)) return result.map(el => decoratorValidation.Model.build(el));
2759
+ return result;
2760
+ }
2761
+ return parseRecord(result);
2762
+ }
2763
+ async view(ddoc, viewName, options, ...args) {
2764
+ const {log: log, ctx: ctx} = this.logCtx(args, this.view);
2765
+ log.info(`Querying view ${ddoc}/${viewName}`);
2766
+ let transactionResult;
2767
+ try {
2768
+ transactionResult = await this.evaluateTransaction(ctx, "view", [ ddoc, viewName, JSON.stringify(options) ], undefined, undefined, undefined);
2769
+ } catch (e) {
2770
+ throw this.parseError(e);
2771
+ }
2772
+ let result;
2773
+ try {
2774
+ result = JSON.parse(this.decode(transactionResult));
2775
+ } catch (e) {
2776
+ throw new dbDecorators.SerializationError(`Failed to process view result: ${e}`);
2777
+ }
2778
+ return result;
2779
+ }
2780
+ getClient() {
2781
+ if (!this._client) this._client = FabricClientAdapter.getClient(this.config);
2782
+ return this._client;
2783
+ }
2784
+ async Gateway(ctx) {
2785
+ return FabricClientAdapter.getGateway(ctx, this.config, this.client);
2786
+ }
2787
+ getContractName(className) {
2788
+ if (!className) return undefined;
2789
+ return `${className}Contract`;
2790
+ }
2791
+ async Contract(ctx, contractName) {
2792
+ return FabricClientAdapter.getContract(await this.Gateway(ctx), this.config, contractName);
2793
+ }
2794
+ async transaction(ctx, api, submit = true, args, transientData = {}, endorsingOrganizations, className) {
2795
+ const log = this.log.for(this.transaction);
2796
+ const gateway = await this.Gateway(ctx);
2797
+ try {
2798
+ const contract = await this.Contract(ctx, this.getContractName(className));
2799
+ log.verbose(`${submit ? "Submit" : "Evaluate"}ting transaction ${this.getContractName(className) || this.config.contractName}.${api}`);
2800
+ log.debug(`args: ${args?.map(a => a.toString()).join("\n") || "none"}`);
2801
+ const method = submit ? contract.submit : contract.evaluate;
2802
+ endorsingOrganizations = endorsingOrganizations?.length ? endorsingOrganizations : undefined;
2803
+ const proposalOptions = {
2804
+ arguments: args || [],
2805
+ transientData: Object.entries(transientData).reduce((acc, [key, val]) => {
2806
+ acc[key] = JSON.stringify(val);
2807
+ return acc;
2808
+ }, {})
2809
+ };
2810
+ return await method.call(contract, api, proposalOptions);
2811
+ } catch (e) {
2812
+ if (e.code === 10) {
2813
+ throw new Error(`${e.details[0].message}`);
2814
+ }
2815
+ throw this.parseError(e);
2816
+ } finally {
2817
+ this.log.debug(`Closing ${this.config.mspId} gateway connection`);
2818
+ gateway.close();
2819
+ }
2820
+ }
2821
+ parseError(err) {
2822
+ return FabricClientAdapter.parseError(err);
2823
+ }
2824
+ async submitTransaction(ctx, api, args, transientData, endorsingOrganizations, className) {
2825
+ return this.transaction(ctx, api, true, args, transientData, endorsingOrganizations, className);
2826
+ }
2827
+ async evaluateTransaction(ctx, api, args, transientData, endorsingOrganizations, className) {
2828
+ return this.transaction(ctx, api, false, args, transientData, endorsingOrganizations, className);
2829
+ }
2830
+ async close() {
2831
+ if (this.client) {
2832
+ this.log.verbose(`Closing ${this.config.mspId} gateway client`);
2833
+ this.client.close();
2834
+ }
2835
+ }
2836
+ static getContract(gateway, config, contractName) {
2837
+ const log = this.log.for(this.getContract);
2838
+ const network = this.getNetwork(gateway, config.channel);
2839
+ let contract;
2840
+ try {
2841
+ log.debug(`Retrieving chaincode ${config.chaincodeName} contract ${contractName || config.contractName} from network ${config.channel}`);
2842
+ contractName = contractName ? contractName : config.contractName;
2843
+ contract = network.getContract(config.chaincodeName, contractName);
2844
+ } catch (e) {
2845
+ throw this.parseError(e);
2846
+ }
2847
+ return contract;
2848
+ }
2849
+ static getNetwork(gateway, channelName) {
2850
+ const log = logging.Logging.for(this.getNetwork);
2851
+ let network;
2852
+ try {
2853
+ log.debug(`Connecting to channel ${channelName}`);
2854
+ network = gateway.getNetwork(channelName);
2855
+ } catch (e) {
2856
+ throw this.parseError(e);
2857
+ }
2858
+ return network;
2859
+ }
2860
+ static async getGateway(ctx, config, client) {
2861
+ return await this.getConnection(client || await this.getClient(config), config, ctx);
2862
+ }
2863
+ static getClient(config) {
2864
+ const log = this.log.for(this.getClient);
2865
+ log.debug(`generating TLS credentials for msp ${config.mspId}`);
2866
+ let pathOrCert = config.tlsCert;
2867
+ if (typeof pathOrCert === "string") {
2868
+ if (pathOrCert.match(/-----BEGIN (CERTIFICATE|KEY|PRIVATE KEY)-----.+?-----END \1-----$/gms)) {
2869
+ pathOrCert = Buffer.from(pathOrCert, "utf8");
2870
+ } else {
2871
+ try {
2872
+ pathOrCert = Buffer.from(fs.readFileSync(pathOrCert, "utf8"));
2873
+ } catch (e) {
2874
+ throw new dbDecorators.InternalError(`Failed to read the tls certificate from ${pathOrCert}: ${e}`);
2875
+ }
2876
+ }
2877
+ }
2878
+ const tlsCredentials = grpc__namespace.credentials.createSsl(pathOrCert);
2879
+ log.debug(`generating Gateway Client for url ${config.peerEndpoint}`);
2880
+ return new grpc.Client(config.peerEndpoint, tlsCredentials, {
2881
+ "grpc.max_receive_message_length": (config.sizeLimit || 15) * 1024 * 1024,
2882
+ "grpc.max_send_message_length": (config.sizeLimit || 15) * 1024 * 1024
2883
+ });
2884
+ }
2885
+ static async getConnection(client, config, ctx) {
2886
+ const log = logging.Logging.for(this.getConnection);
2887
+ log.debug(`Retrieving Peer Identity for ${config.mspId} under ${config.certCertOrDirectoryPath}`);
2888
+ const identity = await getIdentity(config.mspId, config.certCertOrDirectoryPath);
2889
+ try {
2890
+ log.debug(`preparing transaction signer for ${CryptoUtils.fabricIdFromCertificate(identity.credentials.toString())}`);
2891
+ } catch (e) {
2892
+ log.error(`Failed to extract Fabric ID from certificate`, e);
2893
+ }
2894
+ let signer;
2895
+ const close = () => {};
2896
+ if (!config.hsm) {
2897
+ signer = await getSigner(config.keyCertOrDirectoryPath);
2898
+ } else {
2899
+ throw new core.UnsupportedError("HSM NOT IMPLEMENTED");
2900
+ }
2901
+ const options = {
2902
+ client: client,
2903
+ identity: identity,
2904
+ signer: signer,
2905
+ evaluateOptions: () => ({
2906
+ deadline: Date.now() + 1e3 * ctx.get("evaluateTimeout")
2907
+ }),
2908
+ endorseOptions: () => ({
2909
+ deadline: Date.now() + 1e3 * ctx.get("endorseTimeout")
2910
+ }),
2911
+ submitOptions: () => ({
2912
+ deadline: Date.now() + 1e3 * ctx.get("submitTimeout")
2913
+ }),
2914
+ commitStatusOptions: () => ({
2915
+ deadline: Date.now() + 1e3 * ctx.get("commitTimeout")
2916
+ })
2917
+ };
2918
+ log.debug(`Connecting to ${config.mspId}`);
2919
+ const gateway = fabricGateway.connect(options);
2920
+ if (config.hsm) {
2921
+ gateway.close = new Proxy(gateway.close, {
2922
+ apply(target, thisArg, argArray) {
2923
+ Reflect.apply(target, thisArg, argArray);
2924
+ close();
2925
+ }
2926
+ });
2927
+ }
2928
+ return gateway;
2929
+ }
2930
+ Dispatch() {
2931
+ return new FabricClientAdapter["_baseDispatch"];
2932
+ }
2933
+ static parseError(err) {
2934
+ const msg = typeof err === "string" ? err : err.message;
2935
+ if (msg.includes("MVCC_READ_CONFLICT")) return new MvccReadConflictError(err);
2936
+ if (msg.includes("DEADLINE_EXCEEDED")) return new TransactionTimeoutError(err);
2937
+ if (msg.includes("ENDORSEMENT_POLICY_FAILURE")) return new EndorsementPolicyError(err);
2938
+ if (msg.includes("PHANTOM_READ_CONFLICT")) return new PhantomReadConflictError(err);
2939
+ if (err instanceof Error && err.code) {
2940
+ switch (err.code) {
2941
+ case 9:
2942
+ return new EndorsementError(err);
2943
+ }
2944
+ }
2945
+ if (msg.includes(dbDecorators.NotFoundError.name)) return new dbDecorators.NotFoundError(err);
2946
+ if (msg.includes(dbDecorators.ConflictError.name)) return new dbDecorators.ConflictError(err);
2947
+ if (msg.includes(dbDecorators.BadRequestError.name)) return new dbDecorators.BadRequestError(err);
2948
+ if (msg.includes(core.QueryError.name)) return new core.QueryError(err);
2949
+ if (msg.includes(core.PagingError.name)) return new core.PagingError(err);
2950
+ if (msg.includes(core.UnsupportedError.name)) return new core.UnsupportedError(err);
2951
+ if (msg.includes(core.MigrationError.name)) return new core.MigrationError(err);
2952
+ if (msg.includes(core.ObserverError.name)) return new core.ObserverError(err);
2953
+ if (msg.includes(core.AuthorizationError.name)) return new core.AuthorizationError(err);
2954
+ if (msg.includes(core.ForbiddenError.name)) return new core.ForbiddenError(err);
2955
+ if (msg.includes(core.ConnectionError.name)) return new core.ConnectionError(err);
2956
+ if (msg.includes(dbDecorators.SerializationError.name)) return new dbDecorators.SerializationError(err);
2957
+ return new dbDecorators.InternalError(err);
2958
+ }
2959
+ }
2960
+ tslib.__decorate([ logging.debug(), logging.final(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, Object, Object, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "create", null);
2961
+ tslib.__decorate([ logging.debug(), logging.final(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "healthcheck", null);
2962
+ tslib.__decorate([ logging.debug(), logging.final(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "read", null);
2963
+ tslib.__decorate([ logging.debug(), logging.final(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, Object, Object, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "update", null);
2964
+ tslib.__decorate([ logging.debug(), logging.final(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "delete", null);
2965
+ tslib.__decorate([ logging.debug(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ Object, typeof (_a = typeof D !== "undefined" && D) === "function" ? _a : Object, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "raw", null);
2966
+ tslib.__decorate([ logging.debug(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ String, String, Object, core.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricClientAdapter.prototype, "view", null);
2967
+ FabricClientAdapter.decoration();
2968
+ core.Adapter.setCurrent(FabricFlavour);
2969
+ class FabricClientDispatch extends core.Dispatch {
2970
+ constructor(client) {
2971
+ super();
2972
+ this.client = client;
2973
+ this.decoder = new TextDecoder("utf8");
2974
+ }
2975
+ async close() {
2976
+ if (this.listeningStack) this.listeningStack.close();
2977
+ }
2978
+ parsePayload(jsonBytes) {
2979
+ const json = this.decoder.decode(jsonBytes);
2980
+ return JSON.parse(json);
2981
+ }
2982
+ observe(observer) {
2983
+ if (!(observer instanceof FabricClientAdapter)) throw new core.UnsupportedError("Only FabricClientAdapter can be observed by dispatch");
2984
+ super.observe(observer);
2985
+ return () => this.unObserve(observer);
2986
+ }
2987
+ async updateObservers(model, event, id, ...args) {
2988
+ const {log: log, ctxArgs: ctxArgs} = core.Adapter.logCtx(this.updateObservers, event, false, ...args);
2989
+ if (!this.adapter) {
2990
+ log.verbose(`No adapter observed for dispatch; skipping observer update for ${typeof model === "string" ? model : decoratorValidation.Model.tableName(model)}:${event}`);
2991
+ return;
2992
+ }
2993
+ try {
2994
+ await this.adapter.refresh(model, event, id, ...ctxArgs);
2995
+ } catch (e) {
2996
+ throw new dbDecorators.InternalError(`Failed to refresh dispatch: ${e}`);
2997
+ }
2998
+ }
2999
+ async handleEvents(ctxArg) {
3000
+ if (!this.listeningStack) throw new dbDecorators.InternalError(`Event stack not initialized. Ensure that "startListening" is called before attempting this operation.`);
3001
+ if (!this.adapter || !this.adapter.config) throw new dbDecorators.InternalError(`No adapter found. should be impossible`);
3002
+ const ctx = ctxArg || await this.adapter.context(dbDecorators.OperationKeys.READ, {
3003
+ correlationId: this.adapter.config.chaincodeName
3004
+ }, this.models && this.models[0] || decoratorValidation.Model);
3005
+ const log = this.log.for(this.handleEvents);
3006
+ log.info(`Listening for incoming events on chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}"...`);
3007
+ try {
3008
+ for await (const evt of this.listeningStack) {
3009
+ const {table: table, event: event, owner: owner} = parseEventName(evt.eventName);
3010
+ if (owner && owner !== this.adapter.config?.mspId) continue;
3011
+ const payload = this.parsePayload(evt.payload);
3012
+ try {
3013
+ const targetModel = table ? decoratorValidation.Model.get(table) : decoratorValidation.Model.get(this.models[0].name);
3014
+ const modelRef = targetModel ?? (table || this.models[0]?.name);
3015
+ await this.updateObservers(modelRef, event, payload.id, ctx);
3016
+ } catch (e) {
3017
+ log.error(`Failed update observables for table ${table} event ${event} id: ${payload.id}: ${e}`);
3018
+ }
3019
+ }
3020
+ } catch (e) {
3021
+ log.error(`Failed to read event for chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}": ${e}`);
3022
+ await this.close();
3023
+ }
3024
+ }
3025
+ async initialize() {
3026
+ if (!this.adapter) throw new dbDecorators.InternalError(`No adapter or config observed for dispatch`);
3027
+ const context = await this.adapter.context("dispatch", {
3028
+ correlationId: this.adapter.config.chaincodeName
3029
+ }, decoratorValidation.Model);
3030
+ const {ctx: ctx} = this.logCtx([ context ], this.initialize);
3031
+ const gateway = await FabricClientAdapter.getGateway(ctx, this.adapter.config, this.client);
3032
+ const network = gateway.getNetwork(this.adapter.config.channel);
3033
+ if (!this.adapter) throw new dbDecorators.InternalError(`No adapter observed for dispatch`);
3034
+ this.listeningStack = await network.getChaincodeEvents(this.adapter.config.chaincodeName);
3035
+ this.handleEvents(ctx);
3036
+ }
3037
+ }
3038
+ if (FabricClientAdapter) FabricClientAdapter["_baseDispatch"] = FabricClientDispatch;
3039
+ const VERSION = "0.1.106";
3040
+ const PACKAGE_NAME = "@decaf-ts/for-fabric";
3041
+ decoration.Metadata.registerLibrary(PACKAGE_NAME, VERSION);
3042
+ exports.AllowanceError = AllowanceError;
3043
+ exports.BalanceError = BalanceError;
3044
+ exports.BaseEncoder = BaseEncoder;
3045
+ exports.ClientSerializer = ClientSerializer;
3046
+ exports.CoreUtils = CoreUtils;
3047
+ exports.CryptoUtils = CryptoUtils;
3048
+ exports.DefaultFabricClientFlags = DefaultFabricClientFlags;
3049
+ exports.DeterministicSerializer = DeterministicSerializer;
3050
+ exports.EndorsementError = EndorsementError;
3051
+ exports.EndorsementPolicyError = EndorsementPolicyError;
3052
+ exports.FabricClientAdapter = FabricClientAdapter;
3053
+ exports.FabricClientDispatch = FabricClientDispatch;
3054
+ exports.FabricClientRepository = FabricClientRepository;
3055
+ exports.FabricERC20ClientRepository = FabricERC20ClientRepository;
3056
+ exports.FabricEnrollmentService = FabricEnrollmentService;
3057
+ exports.FabricFlavour = FabricFlavour;
3058
+ exports.FabricIdentityService = FabricIdentityService;
3059
+ exports.ImplicitPrivateCollection = ImplicitPrivateCollection;
3060
+ exports.MissingContextError = MissingContextError;
3061
+ exports.MissingPKCSS11Lib = MissingPKCSS11Lib;
3062
+ exports.ModelCollection = ModelCollection;
3063
+ exports.MvccReadConflictError = MvccReadConflictError;
3064
+ exports.NamespaceCollection = NamespaceCollection;
3065
+ exports.NotInitializedError = NotInitializedError;
3066
+ exports.OverflowError = OverflowError;
3067
+ exports.Owner = Owner;
3068
+ exports.PACKAGE_NAME = PACKAGE_NAME;
3069
+ exports.PhantomReadConflictError = PhantomReadConflictError;
3070
+ exports.RegistrationError = RegistrationError;
3071
+ exports.RegistrationRequestBuilder = RegistrationRequestBuilder;
3072
+ exports.SEGREGATED_COLLECTION_EXTRACTION_PRIORITY = SEGREGATED_COLLECTION_EXTRACTION_PRIORITY;
3073
+ exports.SimpleDeterministicSerializer = SimpleDeterministicSerializer;
3074
+ exports.TransactionBufferSizeError = TransactionBufferSizeError;
3075
+ exports.TransactionLimitsError = TransactionLimitsError;
3076
+ exports.TransactionTimeoutError = TransactionTimeoutError;
3077
+ exports.UnauthorizedPrivateDataAccess = UnauthorizedPrivateDataAccess;
3078
+ exports.VERSION = VERSION;
3079
+ exports.add = add;
3080
+ exports.contentOfLoadFile = contentOfLoadFile;
3081
+ exports.createMirrorHandler = createMirrorHandler;
3082
+ exports.deleteMirrorHandler = deleteMirrorHandler;
3083
+ exports.evalMirrorMetadata = evalMirrorMetadata;
3084
+ exports.extractPrivateKey = extractPrivateKey;
3085
+ exports.extractSegregatedCollections = extractSegregatedCollections;
3086
+ exports.generateFabricEventName = generateFabricEventName;
3087
+ exports.generateModelDesignDocs = generateModelDesignDocs;
3088
+ exports.generateModelIndexes = generateModelIndexes;
3089
+ exports.getCAUser = getCAUser;
3090
+ exports.getFirstDirFileName = getFirstDirFileName;
3091
+ exports.getFirstDirFileNameContent = getFirstDirFileNameContent;
3092
+ exports.getIdentity = getIdentity;
3093
+ exports.getSigner = getSigner;
3094
+ exports.mirror = mirror;
3095
+ exports.mirrorWriteGuard = mirrorWriteGuard;
3096
+ exports.ownedBy = ownedBy;
3097
+ exports.ownedByOnCreate = ownedByOnCreate;
3098
+ exports.parseEventName = parseEventName;
3099
+ exports.privateData = privateData;
3100
+ exports.readFile = readFile;
3101
+ exports.readMirrorHandler = readMirrorHandler;
3102
+ exports.readModelFile = readModelFile;
3103
+ exports.readModelFolders = readModelFolders;
3104
+ exports.safeParseInt = safeParseInt;
3105
+ exports.segregatedDataOnCreate = segregatedDataOnCreate;
3106
+ exports.segregatedDataOnDelete = segregatedDataOnDelete;
3107
+ exports.segregatedDataOnRead = segregatedDataOnRead;
3108
+ exports.segregatedDataOnUpdate = segregatedDataOnUpdate;
3109
+ exports.sharedData = sharedData;
3110
+ exports.sub = sub;
3111
+ exports.transactionId = transactionId;
3112
+ exports.transactionIdOnCreate = transactionIdOnCreate;
3113
+ exports.updateMirrorHandler = updateMirrorHandler;
3114
+ exports.writeDesignDocs = writeDesignDocs;
3115
+ exports.writeIndexes = writeIndexes;
3116
+ });
3117
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWZhYnJpYy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jbGllbnQvRmFicmljQ2xpZW50UmVwb3NpdG9yeS50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvbW9kZWxzLnRzIiwiLi4vc3JjL3NoYXJlZC9DbGllbnRTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2NsaWVudC9lcmMyMC9GYWJyaWNFUkMyMENsaWVudFJlcG9zaXRvcnkudHMiLCIuLi9zcmMvY2xpZW50L2luZGV4ZXMvZ2VuZXJhdGlvbi50cyIsIi4uL3NyYy9zaGFyZWQvbW9kZWwvSWRlbnRpdHlDcmVkZW50aWFscy50cyIsIi4uL3NyYy9zaGFyZWQvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9JZGVudGl0eS50cyIsIi4uL3NyYy9jbGllbnQvdXRpbHMudHMiLCIuLi9zcmMvY2xpZW50L2NyeXB0by50cyIsIi4uL3NyYy9zaGFyZWQvZXJyb3JzLnRzIiwiLi4vc3JjL2NsaWVudC9zZXJ2aWNlcy9GYWJyaWNFbnJvbGxtZW50U2VydmljZS50cyIsIi4uL3NyYy9jbGllbnQvc2VydmljZXMvUmVnaXN0cmF0aW9uUmVxdWVzdEJ1aWxkZXIudHMiLCIuLi9zcmMvc2hhcmVkL2VyYzIwL2VyYzIwLWNvbnN0YW50cy50cyIsIi4uL3NyYy9zaGFyZWQvbW9kZWwvRmFicmljQmFzZU1vZGVsLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9GYWJyaWNJZGVudGlmaWVkQmFzZU1vZGVsLnRzIiwiLi4vc3JjL3NoYXJlZC9vdmVycmlkZXMvb3ZlcnJpZGVzLnRzIiwiLi4vc3JjL3NoYXJlZC9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL3NoYXJlZC9EZXRlcm1pbmlzdGljU2VyaWFsaXplci50cyIsIi4uL3NyYy9zaGFyZWQvZXZlbnRzLnRzIiwiLi4vc3JjL3NoYXJlZC9tYXRoLnRzIiwiLi4vc3JjL3NoYXJlZC9TaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplci50cyIsIi4uL3NyYy9jbGllbnQvc2VydmljZXMvRmFicmljSWRlbnRpdHlTZXJ2aWNlLnRzIiwiLi4vc3JjL2NsaWVudC9zZXJ2aWNlcy9jb25zdGFudHMudHMiLCIuLi9zcmMvY2xpZW50L2NvbnN0YW50cy50cyIsIi4uL3NyYy9jbGllbnQvZmFicmljLWZzLnRzIiwiLi4vc3JjL2NsaWVudC9GYWJyaWNDbGllbnRTdGF0ZW1lbnQudHMiLCIuLi9zcmMvY2xpZW50L0ZhYnJpY0NsaWVudFBhZ2luYXRvci50cyIsIi4uL3NyYy9jbGllbnQvRmFicmljQ2xpZW50QWRhcHRlci50cyIsIi4uL3NyYy9jbGllbnQvRmFicmljQ2xpZW50RGlzcGF0Y2gudHMiLCIuLi9zcmMvdmVyc2lvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBPcmRlckRpcmVjdGlvbixcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBSZXBvc2l0b3J5LFxuICBDb250ZXh0T2YsXG4gIFByZXBhcmVkU3RhdGVtZW50S2V5cyxcbiAgU2VyaWFsaXplZFBhZ2UsXG4gIERpcmVjdGlvbkxpbWl0T2Zmc2V0LFxuICBQYWdpbmF0b3IsXG4gIEZsYWdzT2YsXG4gIE9ic2VydmVySGFuZGxlcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IE1heWJlQ29udGV4dHVhbEFyZyB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgdHlwZSBGYWJyaWNDbGllbnRBZGFwdGVyIH0gZnJvbSBcIi4vRmFicmljQ2xpZW50QWRhcHRlclwiO1xuaW1wb3J0IHtcbiAgT3BlcmF0aW9uS2V5cyxcbiAgUHJpbWFyeUtleVR5cGUsXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgcmVkdWNlRXJyb3JzVG9QcmludCxcbiAgZW5mb3JjZURCRGVjb3JhdG9ycyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwb3NpdG9yeSBpbXBsZW1lbnRhdGlvbiBmb3IgRmFicmljIGNsaWVudCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBFeHRlbmRzIHRoZSBnZW5lcmljIFJlcG9zaXRvcnkgdG8gcHJlcGFyZSBjb250ZXh0IGFuZCBhcmd1bWVudHMgZm9yIENSVUQgb3BlcmF0aW9ucyBleGVjdXRlZCB2aWEgYSBGYWJyaWMgY2xpZW50IEFkYXB0ZXIsIHdpcmluZyBSZXBvc2l0b3J5RmxhZ3MgYW5kIEZhYnJpYy1zcGVjaWZpYyBvdmVycmlkZXMuXG4gKiBAdGVtcGxhdGUgTSBleHRlbmRzIE1vZGVsIC0gVGhlIG1vZGVsIHR5cGUgaGFuZGxlZCBieSB0aGlzIHJlcG9zaXRvcnlcbiAqIEBwYXJhbSB7QWRhcHRlcjxhbnksIE1hbmdvUXVlcnksIEZhYnJpY0ZsYWdzLCBDb250ZXh0PEZhYnJpY0ZsYWdzPj59IFthZGFwdGVyXSAtIE9wdGlvbmFsIGFkYXB0ZXIgaW5zdGFuY2UgdXNlZCB0byBleGVjdXRlIG9wZXJhdGlvbnNcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBPcHRpb25hbCBtb2RlbCBjb25zdHJ1Y3RvciB1c2VkIGJ5IHRoZSByZXBvc2l0b3J5XG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEZhYnJpY0NsaWVudFJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG4gKiBpbXBvcnQgeyBGYWJyaWNDbGllbnRSZXBvc2l0b3J5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItZmFicmljXCI7XG4gKlxuICogY2xhc3MgVXNlciBleHRlbmRzIE1vZGVsIHsgaWQhOiBzdHJpbmc7IG5hbWUhOiBzdHJpbmc7IH1cbiAqIGNvbnN0IHJlcG8gPSBuZXcgRmFicmljQ2xpZW50UmVwb3NpdG9yeTxVc2VyPigpO1xuICogY29uc3QgY3JlYXRlZCA9IGF3YWl0IHJlcG8uY3JlYXRlKG5ldyBVc2VyKHsgaWQ6IFwiMVwiLCBuYW1lOiBcIkFsaWNlXCIgfSkpO1xuICogY29uc3QgbG9hZGVkID0gYXdhaXQgcmVwby5yZWFkKFwiMVwiKTtcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBSZXBvIGFzIEZhYnJpY0NsaWVudFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBBcHAtPj5SZXBvOiBjcmVhdGUobW9kZWwpXG4gKiAgIFJlcG8tPj5SZXBvOiBjcmVhdGVQcmVmaXgobW9kZWwsIC4uLmFyZ3MpXG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBjcmVhdGUodGFibGUsIGlkLCBtb2RlbCwgZmxhZ3MpXG4gKiAgIEFkYXB0ZXItLT4+UmVwbzogcmVzdWx0XG4gKiAgIFJlcG8tLT4+QXBwOiBtb2RlbFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ2xpZW50UmVwb3NpdG9yeTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBBIGV4dGVuZHMgRmFicmljQ2xpZW50QWRhcHRlciA9IEZhYnJpY0NsaWVudEFkYXB0ZXIsXG4+IGV4dGVuZHMgUmVwb3NpdG9yeTxNLCBBPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBfb3ZlcnJpZGVzID0gT2JqZWN0LmFzc2lnbih7fSwgc3VwZXJbXCJfb3ZlcnJpZGVzXCJdLCB7XG4gICAgaWdub3JlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICBpZ25vcmVIYW5kbGVyczogdHJ1ZSxcbiAgICBhbGxvd1Jhd1N0YXRlbWVudHM6IGZhbHNlLFxuICAgIGZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXM6IHRydWUsXG4gICAgZm9yY2VQcmVwYXJlQ29tcGxleFF1ZXJpZXM6IHRydWUsXG4gICAgYWxsb3dHZW5lcmF0aW9uT3ZlcnJpZGU6IGZhbHNlLFxuICB9KTtcblxuICBjb25zdHJ1Y3RvcihhZGFwdGVyPzogQSwgY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGNsYXp6KTtcbiAgfVxuXG4gIG92ZXJyaWRlIG92ZXJyaWRlKGZsYWdzOiBQYXJ0aWFsPEZsYWdzT2Y8Q29udGV4dE9mPEE+Pj4pOiB0aGlzIHtcbiAgICByZXR1cm4gc3VwZXJcbiAgICAgIC5vdmVycmlkZShPYmplY3QuYXNzaWduKHt9LCBmbGFncywgdGhpcy5fb3ZlcnJpZGVzKSlcbiAgICAgIC5mb3IoZmxhZ3MgYXMgYW55KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBPYnNlcnZlckhhbmRsZXIoKTogT2JzZXJ2ZXJIYW5kbGVyIHtcbiAgICByZXR1cm4gc3VwZXIuT2JzZXJ2ZXJIYW5kbGVyKCk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGtleToga2V5b2YgTSxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24sXG4gICAgcmVmOiBPbWl0PERpcmVjdGlvbkxpbWl0T2Zmc2V0LCBcImRpcmVjdGlvblwiPiA9IHtcbiAgICAgIG9mZnNldDogMSxcbiAgICAgIGxpbWl0OiAxMCxcbiAgICB9LFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8U2VyaWFsaXplZFBhZ2U8TT4+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLlBBR0VfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5wYWdpbmF0ZUJ5KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBwYWdpbmF0aW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB3aXRoIHBhZ2Ugc2l6ZSAke3JlZi5saW1pdH1gXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnQoXG4gICAgICB0aGlzLnBhZ2luYXRlQnkubmFtZSxcbiAgICAgIGtleSxcbiAgICAgIG9yZGVyLFxuICAgICAgeyBsaW1pdDogcmVmLmxpbWl0LCBvZmZzZXQ6IHJlZi5vZmZzZXQsIGJvb2ttYXJrOiByZWYuYm9va21hcmsgfSxcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgbGlzdEJ5KFxuICAgIGtleToga2V5b2YgTSxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkxJU1RfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5saXN0QnkpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYGxpc3RpbmcgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IGJ5ICR7a2V5IGFzIHN0cmluZ30gJHtvcmRlcn1gXG4gICAgKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuc3RhdGVtZW50KFxuICAgICAgdGhpcy5saXN0QnkubmFtZSxcbiAgICAgIGtleSxcbiAgICAgIG9yZGVyLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICkpIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGZpbmRCeShcbiAgICBrZXk6IGtleW9mIE0sXG4gICAgdmFsdWU6IGFueSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPE1bXT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuRklORF9CWSwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLmZpbmRCeSk7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgZmluZGluZyBhbGwgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IHdpdGggJHtrZXkgYXMgc3RyaW5nfSAke3ZhbHVlfWBcbiAgICApO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5zdGF0ZW1lbnQoXG4gICAgICB0aGlzLmZpbmRCeS5uYW1lLFxuICAgICAga2V5LFxuICAgICAgdmFsdWUsXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKSkgYXMgYW55O1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgZmluZE9uZUJ5KFxuICAgIGtleToga2V5b2YgTSxcbiAgICB2YWx1ZTogYW55LFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8TT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuRklORF9PTkVfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5maW5kT25lQnkpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYGZpbmRpbmcgT25lICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB3aXRoICR7a2V5IGFzIHN0cmluZ30gJHt2YWx1ZX1gXG4gICAgKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuc3RhdGVtZW50KFxuICAgICAgdGhpcy5maW5kT25lQnkubmFtZSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICkpIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGZpbmQoXG4gICAgdmFsdWU6IHN0cmluZyxcbiAgICBvcmRlcjogT3JkZXJEaXJlY3Rpb24gPSBPcmRlckRpcmVjdGlvbi5BU0MsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkZJTkQsIHRydWUpXG4gICAgKS5mb3IodGhpcy5maW5kKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBmaW5kaW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSBieSBkZWZhdWx0IHF1ZXJ5IGF0dHJpYnV0ZXNgXG4gICAgKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuc3RhdGVtZW50KFxuICAgICAgdGhpcy5maW5kLm5hbWUsXG4gICAgICB2YWx1ZSxcbiAgICAgIG9yZGVyLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICkpIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHBhZ2UoXG4gICAgdmFsdWU6IHN0cmluZyxcbiAgICBkaXJlY3Rpb246IE9yZGVyRGlyZWN0aW9uID0gT3JkZXJEaXJlY3Rpb24uQVNDLFxuICAgIHJlZjogT21pdDxEaXJlY3Rpb25MaW1pdE9mZnNldCwgXCJkaXJlY3Rpb25cIj4gPSB7XG4gICAgICBvZmZzZXQ6IDEsXG4gICAgICBsaW1pdDogMTAsXG4gICAgfSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+PlxuICApOiBQcm9taXNlPFNlcmlhbGl6ZWRQYWdlPE0+PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFByZXBhcmVkU3RhdGVtZW50S2V5cy5QQUdFLCB0cnVlKVxuICAgICkuZm9yKHRoaXMucGFnZSk7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgcGFnaW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSBieSBkZWZhdWx0IHF1ZXJ5IGF0dHJpYnV0ZXNgXG4gICAgKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuc3RhdGVtZW50KFxuICAgICAgdGhpcy5wYWdlLm5hbWUsXG4gICAgICB2YWx1ZSxcbiAgICAgIGRpcmVjdGlvbixcbiAgICAgIHJlZixcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApKSBhcyBhbnk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBzdGF0ZW1lbnQoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCwgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUGVyc2lzdGVuY2VLZXlzLlNUQVRFTUVOVCwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLnN0YXRlbWVudCk7XG4gICAgbG9nLnZlcmJvc2UoYEV4ZWN1dGluZyBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfWApO1xuICAgIGNvbnN0IGNhbGxBcmdzID0gY3R4QXJncy5zbGljZSgwLCAtMSk7XG4gICAgY29uc3QgcmVzdWx0ID0gSlNPTi5wYXJzZShcbiAgICAgIHRoaXMuYWRhcHRlci5kZWNvZGUoXG4gICAgICAgIGF3YWl0IHRoaXMuYWRhcHRlci5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgICAgIGN0eCxcbiAgICAgICAgICBQZXJzaXN0ZW5jZUtleXMuU1RBVEVNRU5ULFxuICAgICAgICAgIFtuYW1lLCBKU09OLnN0cmluZ2lmeShjYWxsQXJncyldLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdGhpcy5jbGFzcy5uYW1lXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIHJlc3VsdC5tYXAoKHI6IGFueSkgPT5cbiAgICAgICAgKHIgYXMgYW55KVtDb3VjaERCS2V5cy5UQUJMRV0gJiZcbiAgICAgICAgKHIgYXMgYW55KVtDb3VjaERCS2V5cy5UQUJMRV0gPT09IE1vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKVxuICAgICAgICAgID8gbmV3IHRoaXMuY2xhc3MocilcbiAgICAgICAgICA6IHJcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiAocmVzdWx0IGFzIGFueSlbQ291Y2hEQktleXMuVEFCTEVdICYmXG4gICAgICAocmVzdWx0IGFzIGFueSlbQ291Y2hEQktleXMuVEFCTEVdID09PSBNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcylcbiAgICAgID8gbmV3IHRoaXMuY2xhc3MocmVzdWx0KVxuICAgICAgOiBQYWdpbmF0b3IuaXNTZXJpYWxpemVkUGFnZShyZXN1bHQpXG4gICAgICAgID8gT2JqZWN0LmFzc2lnbihyZXN1bHQsIHtcbiAgICAgICAgICAgIGRhdGE6IHJlc3VsdC5kYXRhLm1hcCgoZDogYW55KSA9PiBuZXcgdGhpcy5jbGFzcyhkKSksXG4gICAgICAgICAgfSlcbiAgICAgICAgOiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjb3VudE9mKFxuICAgIGtleT86IGtleW9mIE0sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkNPVU5UX09GLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuY291bnRPZik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgY291bnRpbmcgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9JHtrZXkgPyBgIGJ5ICR7a2V5IGFzIHN0cmluZ31gIDogXCJcIn1gXG4gICAgKTtcbiAgICBjb25zdCBzdG10QXJncyA9IGtleSA/IFtrZXksIC4uLmN0eEFyZ3NdIDogY3R4QXJncztcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnQoUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkNPVU5UX09GLCAuLi5zdG10QXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBtYXhPZjxLIGV4dGVuZHMga2V5b2YgTT4oXG4gICAga2V5OiBLLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8TVtLXT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuTUFYX09GLCB0cnVlKVxuICAgICkuZm9yKHRoaXMubWF4T2YpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYGZpbmRpbmcgbWF4IG9mICR7a2V5IGFzIHN0cmluZ30gaW4gJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50KFByZXBhcmVkU3RhdGVtZW50S2V5cy5NQVhfT0YsIGtleSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBtaW5PZjxLIGV4dGVuZHMga2V5b2YgTT4oXG4gICAga2V5OiBLLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8TVtLXT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuTUlOX09GLCB0cnVlKVxuICAgICkuZm9yKHRoaXMubWluT2YpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYGZpbmRpbmcgbWluIG9mICR7a2V5IGFzIHN0cmluZ30gaW4gJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50KFByZXBhcmVkU3RhdGVtZW50S2V5cy5NSU5fT0YsIGtleSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBhdmdPZjxLIGV4dGVuZHMga2V5b2YgTT4oXG4gICAga2V5OiBLLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFByZXBhcmVkU3RhdGVtZW50S2V5cy5BVkdfT0YsIHRydWUpXG4gICAgKS5mb3IodGhpcy5hdmdPZik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgY2FsY3VsYXRpbmcgYXZnIG9mICR7a2V5IGFzIHN0cmluZ30gaW4gJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50KFByZXBhcmVkU3RhdGVtZW50S2V5cy5BVkdfT0YsIGtleSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBzdW1PZjxLIGV4dGVuZHMga2V5b2YgTT4oXG4gICAga2V5OiBLLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIFByZXBhcmVkU3RhdGVtZW50S2V5cy5TVU1fT0YsIHRydWUpXG4gICAgKS5mb3IodGhpcy5zdW1PZik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgY2FsY3VsYXRpbmcgc3VtIG9mICR7a2V5IGFzIHN0cmluZ30gaW4gJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50KFByZXBhcmVkU3RhdGVtZW50S2V5cy5TVU1fT0YsIGtleSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBkaXN0aW5jdE9mPEsgZXh0ZW5kcyBrZXlvZiBNPihcbiAgICBrZXk6IEssXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNW0tdW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkRJU1RJTkNUX09GLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuZGlzdGluY3RPZik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgZmluZGluZyBkaXN0aW5jdCB2YWx1ZXMgb2YgJHtrZXkgYXMgc3RyaW5nfSBpbiAke01vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKX1gXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnQoUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkRJU1RJTkNUX09GLCBrZXksIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgZ3JvdXBPZjxLIGV4dGVuZHMga2V5b2YgTT4oXG4gICAga2V5OiBLLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxDb250ZXh0T2Y8QT4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgTVtdPj4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuR1JPVVBfT0YsIHRydWUpXG4gICAgKS5mb3IodGhpcy5ncm91cE9mKTtcbiAgICBsb2cudmVyYm9zZShgZ3JvdXBpbmcgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IGJ5ICR7a2V5IGFzIHN0cmluZ31gKTtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnQoUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkdST1VQX09GLCBrZXksIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgYXN5bmMgaGVhbHRoY2hlY2soLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj4pIHtcbiAgICBjb25zdCB7IGN0eCwgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmhlYWx0aGNoZWNrKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYWRhcHRlci5oZWFsdGhjaGVjayh0aGlzLmNsYXNzLCAuLi5jdHhBcmdzKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGUoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBDcmVhdGluZyBuZXcgJHt0aGlzLmNsYXNzLm5hbWV9IGluIHRhYmxlICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfWBcbiAgICApO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCBjdHgpO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGUoXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgaWQsXG4gICAgICByZWNvcmQsXG4gICAgICB0cmFuc2llbnQsXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydDxNPihyZWNvcmQsIHRoaXMuY2xhc3MsIGlkLCB0cmFuc2llbnQsIGN0eCk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyB1cGRhdGUoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHRPZjxBPj5cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGUpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCBjdHgpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGB1cGRhdGluZyAke3RoaXMuY2xhc3MubmFtZX0gaW4gdGFibGUgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IHdpdGggaWQgJHtpZH1gXG4gICAgKTtcbiAgICByZWNvcmQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIudXBkYXRlKFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGlkLFxuICAgICAgcmVjb3JkLFxuICAgICAgdHJhbnNpZW50LFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQ8TT4ocmVjb3JkLCB0aGlzLmNsYXNzLCBpZCwgdHJhbnNpZW50LCBjdHgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChcbiAgICBtb2RlbHM6IE1bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dE9mPEE+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+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFwiYWNjb3VudElkXCIsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgW10sXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLmNsaWVudEFjY291bnRJRCk7XG4gICAgY29uc3QgY2xpZW50QWNjb3VudElEID0gYXdhaXQgdGhpcy5hZGFwdGVyLmV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBcIkNsaWVudEFjY291bnRJRFwiXG4gICAgKTtcblxuICAgIHJldHVybiB0aGlzLmRlY29kZShjbGllbnRBY2NvdW50SUQpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHtcbiAgQ3JlYXRlSW5kZXhSZXF1ZXN0LFxuICBDb3VjaERCRGVzaWduRG9jLFxuICBnZW5lcmF0ZUluZGV4ZXMsXG4gIGdlbmVyYXRlVmlld3MsXG59IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IE1vZGVsLCBNb2RlbENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG5leHBvcnQgdHlwZSBJbmRleCA9IENyZWF0ZUluZGV4UmVxdWVzdDtcblxuZnVuY3Rpb24gZW5zdXJlRGlyZWN0b3J5RXhpc3RlbmNlKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgZnMgPSByZXF1aXJlKFwiZnNcIik7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gIGNvbnN0IHBhdGggPSByZXF1aXJlKFwicGF0aFwiKTtcbiAgY29uc3QgZGlybmFtZTogc3RyaW5nID0gcGF0aC5kaXJuYW1lKGZpbGVQYXRoKTtcbiAgaWYgKGZzLmV4aXN0c1N5bmMoZGlybmFtZSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBlbnN1cmVEaXJlY3RvcnlFeGlzdGVuY2UoZGlybmFtZSk7XG4gIGZzLm1rZGlyU3luYyhkaXJuYW1lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlTW9kZWxJbmRleGVzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG06IENvbnN0cnVjdG9yPE0+XG4pOiBJbmRleFtdIHtcbiAgcmV0dXJuIGdlbmVyYXRlSW5kZXhlcyhbbV0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVNb2RlbERlc2lnbkRvY3M8TSBleHRlbmRzIE1vZGVsPihcbiAgbTogQ29uc3RydWN0b3I8TT4sXG4gIGFjY3VtPzogUmVjb3JkPHN0cmluZywgQ291Y2hEQkRlc2lnbkRvYz5cbik6IENvdWNoREJEZXNpZ25Eb2NbXSB7XG4gIGNvbnN0IHZpZXdzID0gZ2VuZXJhdGVWaWV3cyhbbV0pO1xuICBjb25zdCBzdG9yYWdlOiBSZWNvcmQ8c3RyaW5nLCBDb3VjaERCRGVzaWduRG9jPiA9IGFjY3VtIHx8IHt9O1xuICB2aWV3cy5mb3JFYWNoKChkb2MpID0+IHtcbiAgICBzdG9yYWdlW2RvYy5faWRdID0gZG9jO1xuICB9KTtcbiAgcmV0dXJuIHZpZXdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZE1vZGVsRmlsZShmaWxlOiBhbnkpIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgcGF0aCA9IHJlcXVpcmUoXCJwYXRoXCIpO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICBjb25zdCBleHBvcnRzID0gcmVxdWlyZShwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgZmlsZS5wYXJlbnRQYXRoLCBmaWxlLm5hbWUpKTtcblxuICBjb25zdCB2YWx1ZXMgPSBPYmplY3QudmFsdWVzKGV4cG9ydHMpLmZpbHRlcigoZSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBtID0gbmV3IChlIGFzIENvbnN0cnVjdG9yKSgpO1xuICAgICAgcmV0dXJuIG0gaW5zdGFuY2VvZiBNb2RlbDtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9KSBhcyBNb2RlbENvbnN0cnVjdG9yPGFueT5bXTtcbiAgcmV0dXJuIHZhbHVlcztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRNb2RlbEZvbGRlcnMoXG4gIC4uLmZvbGRlcnM6IHN0cmluZ1tdXG4pOiBQcm9taXNlPE1vZGVsQ29uc3RydWN0b3I8YW55PltdPiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gIGNvbnN0IGZzID0gcmVxdWlyZShcImZzXCIpO1xuXG4gIGNvbnN0IHJlc3VsdDogTW9kZWxDb25zdHJ1Y3Rvcjxhbnk+W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGZvbGRlciBvZiBmb2xkZXJzKSB7XG4gICAgY29uc3QgZmlsZXMgPSBmc1xuICAgICAgLnJlYWRkaXJTeW5jKGZvbGRlciwge1xuICAgICAgICB3aXRoRmlsZVR5cGVzOiB0cnVlLFxuICAgICAgICByZWN1cnNpdmU6IHRydWUsXG4gICAgICB9KVxuICAgICAgLmZpbHRlcigoZjogYW55KSA9PiBmLmlzRmlsZSgpICYmIGYubmFtZS5lbmRzV2l0aChcImpzXCIpKTtcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIHJlc3VsdC5wdXNoKC4uLnJlYWRNb2RlbEZpbGUoZmlsZSkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVJbmRleGVzKFxuICBpbmRleGVzOiBJbmRleFtdLFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpLFxuICBjb2xsZWN0aW9uPzogc3RyaW5nXG4pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgZnMgPSByZXF1aXJlKFwiZnNcIik7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gIGNvbnN0IHBhdGggPSByZXF1aXJlKFwicGF0aFwiKTtcblxuICBpbmRleGVzLmZvckVhY2goKGluZGV4KSA9PiB7XG4gICAgY29uc3QgZmlsZSA9IHBhdGgucmVzb2x2ZShcbiAgICAgIHBhdGguam9pbihcbiAgICAgICAgcCxcbiAgICAgICAgYC4vTUVUQS1JTkYvc3RhdGVkYi9jb3VjaGRiLyR7Y29sbGVjdGlvbiA/IGBjb2xsZWN0aW9ucy8ke2NvbGxlY3Rpb259L2AgOiBcIlwifWluZGV4ZXMvJHtpbmRleC5uYW1lfS5qc29uYFxuICAgICAgKVxuICAgICk7XG4gICAgZW5zdXJlRGlyZWN0b3J5RXhpc3RlbmNlKGZpbGUpO1xuICAgIGZzLndyaXRlRmlsZVN5bmMoZmlsZSwgSlNPTi5zdHJpbmdpZnkoaW5kZXgsIHVuZGVmaW5lZCwgMikpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlRGVzaWduRG9jcyhcbiAgZGVzaWduRG9jczogQ291Y2hEQkRlc2lnbkRvY1tdLFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpLFxuICBjb2xsZWN0aW9uPzogc3RyaW5nXG4pIHtcbiAgaWYgKCFkZXNpZ25Eb2NzLmxlbmd0aCkgcmV0dXJuO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICBjb25zdCBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgY29uc3QgcGF0aCA9IHJlcXVpcmUoXCJwYXRoXCIpO1xuXG4gIGRlc2lnbkRvY3MuZm9yRWFjaCgoZG9jKSA9PiB7XG4gICAgY29uc3QgZG9jSWQgPSBkb2MuX2lkLnJlcGxhY2UoL15fZGVzaWduXFwvLywgXCJcIik7XG4gICAgY29uc3QgZmlsZSA9IHBhdGgucmVzb2x2ZShcbiAgICAgIHBhdGguam9pbihcbiAgICAgICAgcCxcbiAgICAgICAgYC4vTUVUQS1JTkYvc3RhdGVkYi9jb3VjaGRiLyR7Y29sbGVjdGlvbiA/IGBjb2xsZWN0aW9ucy8ke2NvbGxlY3Rpb259L2AgOiBcIlwifWRlc2lnbl9kb2NzLyR7ZG9jSWR9Lmpzb25gXG4gICAgICApXG4gICAgKTtcbiAgICBlbnN1cmVEaXJlY3RvcnlFeGlzdGVuY2UoZmlsZSk7XG4gICAgY29uc3QgcGF5bG9hZCA9IHsgLi4uZG9jIH07XG4gICAgZGVsZXRlIHBheWxvYWQuX3JldjtcbiAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGUsIEpTT04uc3RyaW5naWZ5KHBheWxvYWQsIHVuZGVmaW5lZCwgMikpO1xuICB9KTtcbn1cbiIsImltcG9ydCB7IEJhc2VNb2RlbCwgY29sdW1uLCBwayB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgbW9kZWwsIHR5cGUgTW9kZWxBcmcsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSWRlbnRpdHkgY3JlZGVudGlhbCBtb2RlbCBzdG9yaW5nIGNyeXB0b2dyYXBoaWMgbWF0ZXJpYWxzXG4gKiBAc3VtbWFyeSBIb2xkcyBjZXJ0aWZpY2F0ZSBjaGFpbiBhbmQgcHJpdmF0ZSBrZXkgaW5mb3JtYXRpb24gZm9yIGEgRmFicmljIGlkZW50aXR5LCBtYW5hZ2VkIGFzIGEgc2VwYXJhdGUgZW50aXR5IGxpbmtlZCBmcm9tIElkZW50aXR5XG4gKiBAcGFyYW0ge01vZGVsQXJnPElkZW50aXR5Q3JlZGVudGlhbHM+fSBbYXJnXSAtIE9wdGlvbmFsIGluaXRpYWxpemF0aW9uIG9iamVjdCB1c2VkIHRvIHBvcHVsYXRlIG1vZGVsIGZpZWxkc1xuICogQGNsYXNzIElkZW50aXR5Q3JlZGVudGlhbHNcbiAqIEBleGFtcGxlXG4gKiAvLyBDcmVhdGUgY3JlZGVudGlhbHMgZW50cnlcbiAqIGNvbnN0IGNyZWRzID0gbmV3IElkZW50aXR5Q3JlZGVudGlhbHMoeyBpZDogXCJjcmVkczFcIiwgY2VydGlmaWNhdGU6IFwiLi4uXCIsIHJvb3RDZXJ0aWZpY2F0ZTogXCIuLi5cIiwgcHJpdmF0ZUtleTogXCIuLi5cIiB9KTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsIGFzIElkZW50aXR5Q3JlZGVudGlhbHNcbiAqICAgQXBwLT4+TW9kZWw6IG5ldyBJZGVudGl0eUNyZWRlbnRpYWxzKHsgaWQsIGNlcnRpZmljYXRlLCByb290Q2VydGlmaWNhdGUsIHByaXZhdGVLZXkgfSlcbiAqICAgTW9kZWwtLT4+QXBwOiBpbnN0YW5jZVxuICogQHNlZSBtb2RlbFxuICovXG5AbW9kZWwoKVxuZXhwb3J0IGNsYXNzIElkZW50aXR5Q3JlZGVudGlhbHMgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjcmVkZW50aWFscyByZWNvcmRcbiAgICogQHN1bW1hcnkgUHJpbWFyeSBrZXkgZm9yIHJlZmVyZW5jaW5nIHRoaXMgY3JlZGVudGlhbHMgZW50cnlcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjcmVkZW50aWFscyByZWNvcmRcIilcbiAgQGNvbHVtbigpXG4gIEBwaygpXG4gIGlkITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUEVNLWVuY29kZWQgWC41MDkgY2VydGlmaWNhdGUgZm9yIHRoZSBpZGVudGl0eVxuICAgKiBAc3VtbWFyeSBMZWFmIGNlcnRpZmljYXRlIGFzc29jaWF0ZWQgd2l0aCB0aGUgaWRlbnRpdHlcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlBFTS1lbmNvZGVkIFguNTA5IGNlcnRpZmljYXRlIGZvciB0aGUgaWRlbnRpdHlcIilcbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIGNlcnRpZmljYXRlITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUEVNLWVuY29kZWQgcm9vdCBvciBpbnRlcm1lZGlhdGUgY2VydGlmaWNhdGVcbiAgICogQHN1bW1hcnkgUm9vdCBvZiB0cnVzdCB1c2VkIHRvIHZhbGlkYXRlIHRoZSBsZWFmIGNlcnRpZmljYXRlXG4gICAqL1xuICBAZGVzY3JpcHRpb24oXCJQRU0tZW5jb2RlZCByb290IG9yIGludGVybWVkaWF0ZSBjZXJ0aWZpY2F0ZVwiKVxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgcm9vdENlcnRpZmljYXRlITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUEVNLWVuY29kZWQgcHJpdmF0ZSBrZXkgbWF0ZXJpYWxcbiAgICogQHN1bW1hcnkgUHJpdmF0ZSBrZXkgY29ycmVzcG9uZGluZyB0byB0aGUgaWRlbnRpdHkgY2VydGlmaWNhdGVcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlBFTS1lbmNvZGVkIHByaXZhdGUga2V5XCIpXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICBwcml2YXRlS2V5ITogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPElkZW50aXR5Q3JlZGVudGlhbHM+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gS2V5cyB1c2VkIHRvIG1hcmsgRmFicmljLXNwZWNpZmljIG1vZGVsIG1ldGFkYXRhXG4gKiBAc3VtbWFyeSBFbnVtZXJhdGlvbiBvZiBzcGVjaWFsIGtleXMgdXNlZCBieSB0aGUgc2VyaWFsaXphdGlvbiBsYXllciB0byBwZXJzaXN0IEZhYnJpYy1yZWxhdGVkIGZsYWdzIG9uIG1vZGVsc1xuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZW51bSBGYWJyaWNNb2RlbEtleXMge1xuICAvKiogUHJpdmF0ZSBkYXRhIG1hcmtlciB1c2VkIHRvIHRhZyBwcm9wZXJ0aWVzIG9yIG1vZGVscyBmb3IgRmFicmljIHByaXZhdGUgY29sbGVjdGlvbnMgKi9cbiAgUFJJVkFURSA9IFwicHJpdmF0ZVwiLFxuICBTSEFSRUQgPSBcInNoYXJlZFwiLFxuICAvKiogTmFtZXNwYWNlIHByZWZpeCB1c2VkIGZvciBGYWJyaWMtc3BlY2lmaWMgbWV0YWRhdGEga2V5cyAqL1xuICBGQUJSSUMgPSBcImZhYnJpY1wiLFxuICBPV05FRF9CWSA9IFwib3duZWQtYnlcIixcbiAgVFJBTlNBQ1RJT05fSUQgPSBcInRyYW5zYWN0aW9uLWlkXCIsXG4gIE1JUlJPUiA9IFwibWlycm9yXCIsXG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdXBwb3J0ZWQgaWRlbnRpdHkgdHlwZXMgZm9yIEZhYnJpYyBjcmVkZW50aWFsc1xuICogQHN1bW1hcnkgRW51bWVyYXRpb24gb2YgaWRlbnRpdHkgZm9ybWF0cyByZWNvZ25pemVkIGJ5IHRoaXMgbGlicmFyeVxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZW51bSBJZGVudGl0eVR5cGUge1xuICAvKiogU3RhbmRhcmQgWC41MDkgaWRlbnRpdHkgZm9ybWF0IHVzZWQgYnkgSHlwZXJsZWRnZXIgRmFicmljICovXG4gIFg1MDkgPSBcIlguNTA5XCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN0cmluZyBpZGVudGlmaWVyIGZvciB0aGUgRmFicmljIGFkYXB0ZXIgZmxhdm91clxuICogQHN1bW1hcnkgVXNlZCB0byB0YWcgYWRhcHRlcnMvcmVwb3NpdG9yaWVzIHRoYXQgb3BlcmF0ZSBhZ2FpbnN0IEh5cGVybGVkZ2VyIEZhYnJpY1xuICogQGNvbnN0IEZhYnJpY0ZsYXZvdXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEZhYnJpY0ZsYXZvdXIgPSBcImhsZi1mYWJyaWNcIjtcbiIsImltcG9ydCB7XG4gIEJhc2VNb2RlbCxcbiAgQ2FzY2FkZSxcbiAgY29sdW1uLFxuICBpbmRleCxcbiAgb25lVG9PbmUsXG4gIHBrLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IG1vZGVsLCB0eXBlIE1vZGVsQXJnLCByZXF1aXJlZCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IElkZW50aXR5Q3JlZGVudGlhbHMgfSBmcm9tIFwiLi9JZGVudGl0eUNyZWRlbnRpYWxzXCI7XG5pbXBvcnQgeyBJZGVudGl0eVR5cGUgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBkZXNjcmlwdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBJZGVudGl0eSBtb2RlbCByZXByZXNlbnRpbmcgYSBGYWJyaWMgd2FsbGV0IGVudHJ5XG4gKiBAc3VtbWFyeSBFbmNhcHN1bGF0ZXMgYW4gaWRlbnRpdHkgc3RvcmVkIGluIGEgRmFicmljIHdhbGxldCwgaW5jbHVkaW5nIGl0cyBNU1AgaWRlbnRpZmllciwgY3JlZGVudGlhbCBsaW5rYWdlLCBhbmQgdHlwZSBpbmZvcm1hdGlvbi4gQnVpbHQgb24gQmFzZU1vZGVsIGZvciBpbnRlZ3JhdGlvbiB3aXRoIERlY2FmIHZhbGlkYXRpb24gYW5kIHBlcnNpc3RlbmNlLlxuICogQHBhcmFtIHtNb2RlbEFyZzxJZGVudGl0eT59IFthcmddIC0gT3B0aW9uYWwgaW5pdGlhbGl6YXRpb24gb2JqZWN0IHVzZWQgdG8gcG9wdWxhdGUgbW9kZWwgZmllbGRzXG4gKiBAY2xhc3MgSWRlbnRpdHlcbiAqIEBleGFtcGxlXG4gKiAvLyBDcmVhdGUgYSBuZXcgaWRlbnRpdHkgcmVmZXJlbmNpbmcgZXhpc3RpbmcgY3JlZGVudGlhbHNcbiAqIGNvbnN0IGlkID0gbmV3IElkZW50aXR5KHsgaWQ6IFwidXNlcjFcIiwgbXNwSWQ6IFwiT3JnMU1TUFwiLCB0eXBlOiBJZGVudGl0eVR5cGUuWDUwOSB9KTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsIGFzIElkZW50aXR5XG4gKiAgIEFwcC0+Pk1vZGVsOiBuZXcgSWRlbnRpdHkoeyBpZCwgbXNwSWQsIHR5cGUgfSlcbiAqICAgTW9kZWwtLT4+QXBwOiBpbnN0YW5jZVxuICovXG5AbW9kZWwoKVxuZXhwb3J0IGNsYXNzIElkZW50aXR5IGV4dGVuZHMgQmFzZU1vZGVsIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgaWRlbnRpdHkgaW4gdGhlIHdhbGxldFxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSB1c2VkIHRvIHJlZmVyZW5jZSB0aGlzIGlkZW50aXR5IHJlY29yZFxuICAgKi9cbiAgQGRlc2NyaXB0aW9uKFwiVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGlkZW50aXR5XCIpXG4gIEBwaygpXG4gIGlkITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGluayB0byB0aGUgaWRlbnRpdHkgY3JlZGVudGlhbHMgc3RvcmVkIHNlcGFyYXRlbHlcbiAgICogQHN1bW1hcnkgT25lLXRvLW9uZSByZWxhdGlvbnNoaXAgdG8gdGhlIGNyZWRlbnRpYWxzIGVudGl0eTsgY2FzY2FkZXMgb24gdXBkYXRlIGFuZCBkZWxldGVcbiAgICovXG4gIEBvbmVUb09uZShJZGVudGl0eUNyZWRlbnRpYWxzLCB7XG4gICAgdXBkYXRlOiBDYXNjYWRlLkNBU0NBREUsXG4gICAgZGVsZXRlOiBDYXNjYWRlLkNBU0NBREUsXG4gIH0pXG4gIGNyZWRlbnRpYWxzITogSWRlbnRpdHlDcmVkZW50aWFscztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1lbWJlcnNoaXAgU2VydmljZSBQcm92aWRlciBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFRoZSBNU1AgSUQgY29ycmVzcG9uZGluZyB0byB0aGUgb3JnYW5pemF0aW9uIHRoYXQgaXNzdWVkIHRoaXMgaWRlbnRpdHlcbiAgICovXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICBAaW5kZXgoKVxuICBtc3BJZCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFR5cGUgb2YgaWRlbnRpdHlcbiAgICogQHN1bW1hcnkgSW5kaWNhdGVzIHRoZSBpZGVudGl0eSBlbmNvZGluZy9mb3JtYXQ7IGRlZmF1bHRzIHRvIFguNTA5XG4gICAqL1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgdHlwZTogSWRlbnRpdHlUeXBlID0gSWRlbnRpdHlUeXBlLlg1MDk7XG5cbiAgY29uc3RydWN0b3IoYXJnOiBNb2RlbEFyZzxJZGVudGl0eT4pIHtcbiAgICBzdXBlcihhcmcpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBzdHJpbmdGb3JtYXQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBMb2dnZXIsIE1pbmlMb2dnZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IElkZW50aXR5LCBTaWduZXIsIHNpZ25lcnMgfSBmcm9tIFwiQGh5cGVybGVkZ2VyL2ZhYnJpYy1nYXRld2F5XCI7XG5pbXBvcnQgeyBDcnlwdG9TZXR0aW5nLCBJQ3J5cHRvU3VpdGUsIFVzZXIgfSBmcm9tIFwiZmFicmljLWNvbW1vblwiO1xuaW1wb3J0IHsgSFNNT3B0aW9ucyB9IGZyb20gXCIuLi9zaGFyZWQvdHlwZXNcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZUltcG9ydCB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IGNyeXB0bywgeyBYNTA5Q2VydGlmaWNhdGUgfSBmcm9tIFwiY3J5cHRvXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvcmUgdXRpbGl0aWVzIGZvciBpbnRlcmFjdGluZyB3aXRoIGZpbGVzLCBjcnlwdG8gaWRlbnRpdGllcywgYW5kIEZhYnJpYyBTREsgaGVscGVyc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgc3RhdGljIGhlbHBlciBtZXRob2RzIHRvIHJlYWQgY3JlZGVudGlhbHMgYW5kIGtleXMgZnJvbSBkaXNrIG9yIHJhdyBjb250ZW50LCBjb25zdHJ1Y3QgRmFicmljIGdhdGV3YXkgSWRlbnRpdGllcyBhbmQgU2lnbmVycywgYW5kIHBlcmZvcm0gY29tbW9uIGZpbGVzeXN0ZW0gb3BlcmF0aW9ucyB1c2VkIGJ5IHRoZSBGYWJyaWMgY2xpZW50IHRvb2xpbmcuXG4gKiBAY2xhc3MgQ29yZVV0aWxzXG4gKiBAZXhhbXBsZVxuICogLy8gUmVhZCBhbiBpZGVudGl0eSBhbmQgc2lnbmVyIGZyb20gZGlyZWN0b3JpZXNcbiAqIGNvbnN0IGlkZW50aXR5ID0gYXdhaXQgQ29yZVV0aWxzLmdldElkZW50aXR5KCdPcmcxTVNQJywgJy9tc3Avc2lnbmNlcnRzJyk7XG4gKiBjb25zdCBzaWduZXIgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0U2lnbmVyKCcvbXNwL2tleXN0b3JlJyk7XG4gKiAvLyBCdWlsZCBhIENBIHVzZXJcbiAqIGNvbnN0IHVzZXIgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0Q0FVc2VyKCdhcHBVc2VyJywgcGVtS2V5LCBwZW1DZXJ0LCAnT3JnMU1TUCcpO1xuICovXG5leHBvcnQgY2xhc3MgQ29yZVV0aWxzIHtcbiAgcHJpdmF0ZSBzdGF0aWMgbG9nZ2VyOiBMb2dnZXIgPSBuZXcgTWluaUxvZ2dlcihDb3JlVXRpbHMubmFtZSk7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY3J5cHRvU3VpdGU6IElDcnlwdG9TdWl0ZTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlc29sdmUgZmlsZSBjb250ZW50IGZyb20gYSBwYXRoIG9yIHJldHVybiBwcm92aWRlZCByYXcgY29udGVudFxuICAgKiBAc3VtbWFyeSBJZiB0aGUgaW5wdXQgaXMgYSBVaW50OEFycmF5IG9yIFBFTSBjb250ZW50LCByZXR1cm5zIGl0IGFzLWlzOyBvdGhlcndpc2UgdXNlcyBhIHByb3ZpZGVkIGFzeW5jIGZpbGVSZWFkZXIgdG8gbG9hZCB0aGUgY29udGVudCBmcm9tIGRpc2suXG4gICAqIEBwYXJhbSB7c3RyaW5nfFVpbnQ4QXJyYXl9IGNvbnRlbnRPclBhdGggLSBFaXRoZXIgYSByYXcgY29udGVudCBidWZmZXIvc3RyaW5nIG9yIGEgZmlsZXN5c3RlbSBwYXRoXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oc3RyaW5nKTogUHJvbWlzZTxzdHJpbmd8VWludDhBcnJheXxCdWZmZXI+fSBmaWxlUmVhZGVyIC0gQXN5bmMgZnVuY3Rpb24gdG8gcmVhZCBmaWxlIGNvbnRlbnQgd2hlbiBhIHBhdGggaXMgcHJvdmlkZWRcbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmd8VWludDhBcnJheXxCdWZmZXI+fSBUaGUgY29udGVudCB0byBiZSB1c2VkIGRvd25zdHJlYW1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGFzeW5jIGNvbnRlbnRPZkxvYWRGaWxlKFxuICAgIGNvbnRlbnRPclBhdGg6IHN0cmluZyB8IFVpbnQ4QXJyYXksXG4gICAgZmlsZVJlYWRlcjogKHBhdGg6IHN0cmluZykgPT4gUHJvbWlzZTxzdHJpbmcgfCBVaW50OEFycmF5IHwgQnVmZmVyPlxuICApIHtcbiAgICBpZiAoY29udGVudE9yUGF0aCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHJldHVybiBjb250ZW50T3JQYXRoO1xuICAgIGlmIChcbiAgICAgIGNvbnRlbnRPclBhdGgubWF0Y2goXG4gICAgICAgIC8tLS0tLUJFR0lOIChDRVJUSUZJQ0FURXxLRVl8UFJJVkFURSBLRVkpLS0tLS0uKz8tLS0tLUVORCBcXDEtLS0tLSQvZ21zXG4gICAgICApXG4gICAgKVxuICAgICAgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG4gICAgcmV0dXJuIGF3YWl0IGZpbGVSZWFkZXIoY29udGVudE9yUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWQgZmlsZSBjb250ZW50IGZyb20gYSBwYXRoIG9yIHJldHVybiBwcm92aWRlZCBCdWZmZXJcbiAgICogQHN1bW1hcnkgQ29udmVuaWVuY2Ugd3JhcHBlciB0aGF0IGxvYWRzIGEgZmlsZSB1c2luZyBmcy5wcm9taXNlcyB3aGVuIGEgcGF0aCBzdHJpbmcgaXMgcHJvdmlkZWQ7IG90aGVyd2lzZSByZXR1cm5zIHRoZSBnaXZlbiBCdWZmZXIgZGlyZWN0bHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfEJ1ZmZlcn0gY29udGVudE9yUGF0aCAtIFBhdGggdG8gYSBmaWxlIG9uIGRpc2sgb3IgYW4gYWxyZWFkeS1sb2FkZWQgQnVmZmVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8c3RyaW5nfFVpbnQ4QXJyYXl8QnVmZmVyPn0gVGhlIGZpbGUgY29udGVudCBhcyBhIEJ1ZmZlci9zdHJpbmcgZGVwZW5kaW5nIG9uIHJlYWRlclxuICAgKi9cbiAgc3RhdGljIGFzeW5jIHJlYWRGaWxlKGNvbnRlbnRPclBhdGg6IHN0cmluZyB8IEJ1ZmZlcikge1xuICAgIGlmICh0eXBlb2YgY29udGVudE9yUGF0aCAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG5cbiAgICBjb25zdCBmaWxlUmVhZGVyID0gYXN5bmMgKHBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgeyBwcm9taXNlcyB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcImZzXCIpKTtcbiAgICAgIHJldHVybiBhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShwYXRoKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGF3YWl0IGZpbGVSZWFkZXIoY29udGVudE9yUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZSBhIEZhYnJpYyBDQSBVc2VyIG9iamVjdCB3aXRoIGVucm9sbG1lbnRcbiAgICogQHN1bW1hcnkgQ29uc3RydWN0cyBhIGZhYnJpYy1jb21tb24gVXNlciwgc2V0cyBhIGNyeXB0byBzdWl0ZSwgaW1wb3J0cyB0aGUgcHJvdmlkZWQgcHJpdmF0ZSBrZXksIGFuZCBzZXRzIGVucm9sbG1lbnQgd2l0aCBjZXJ0aWZpY2F0ZSBhbmQgTVNQIElELlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXNlck5hbWUgLSBUaGUgdXNlciBuYW1lIGZvciB0aGUgQ0EgdXNlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJpdmF0ZUtleSAtIFBFTS1lbmNvZGVkIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjZXJ0aWZpY2F0ZSAtIFBFTS1lbmNvZGVkIFguNTA5IGNlcnRpZmljYXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtc3BJZCAtIE1lbWJlcnNoaXAgU2VydmljZSBQcm92aWRlciBpZGVudGlmaWVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8VXNlcj59IFRoZSBlbnJvbGxlZCBGYWJyaWMgVXNlciBpbnN0YW5jZVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGdldENBVXNlcihcbiAgICB1c2VyTmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGVLZXk6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBjZXJ0aWZpY2F0ZTogc3RyaW5nLFxuICAgIG1zcElkOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHsgaHNtPzogSFNNT3B0aW9ucyB9XG4gICk6IFByb21pc2U8VXNlcj4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgc3RyaW5nRm9ybWF0KFxuICAgICAgICBcIkNyZWF0aW5nIENBIHswfSB1c2VyIHsxfSB3aXRoIGNlcnRpZmljYXRlIHsyfVwiLFxuICAgICAgICBtc3BJZCxcbiAgICAgICAgdXNlck5hbWUsXG4gICAgICAgIGNlcnRpZmljYXRlXG4gICAgICApXG4gICAgKTtcbiAgICBjb25zdCB1c2VyID0gbmV3IFVzZXIodXNlck5hbWUpO1xuICAgIGNvbnN0IGNvbmZpZyA9IG9wdGlvbnM/LmhzbVxuICAgICAgPyB7XG4gICAgICAgICAgc29mdHdhcmU6IGZhbHNlLFxuICAgICAgICAgIGxpYjogb3B0aW9ucy5oc20ubGlicmFyeSxcbiAgICAgICAgICBzbG90OiBvcHRpb25zLmhzbS5zbG90LFxuICAgICAgICAgIGxhYmVsOiBvcHRpb25zLmhzbS50b2tlbkxhYmVsLFxuICAgICAgICAgIHBpbjogU3RyaW5nKG9wdGlvbnMuaHNtLnBpbiksXG4gICAgICAgIH1cbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGNyeXB0b1N1aXRlID0gdGhpcy5nZXRDcnlwdG9TdWl0ZShjb25maWcpO1xuXG4gICAgdXNlci5zZXRDcnlwdG9TdWl0ZShjcnlwdG9TdWl0ZSk7XG4gICAgY29uc3QgZW5yb2xsbWVudEtleSA9IG9wdGlvbnM/LmhzbVxuICAgICAgPyBhd2FpdCB0aGlzLmdldEhTTUVucm9sbG1lbnRLZXkoY3J5cHRvU3VpdGUsIGNlcnRpZmljYXRlLCBvcHRpb25zLmhzbSlcbiAgICAgIDogdGhpcy5nZXRTb2Z0d2FyZUVucm9sbG1lbnRLZXkoY3J5cHRvU3VpdGUsIHByaXZhdGVLZXkpO1xuICAgIGF3YWl0IHVzZXIuc2V0RW5yb2xsbWVudChlbnJvbGxtZW50S2V5LCBjZXJ0aWZpY2F0ZSwgbXNwSWQpO1xuICAgIHJldHVybiB1c2VyO1xuICB9XG5cbiAgc3RhdGljIGdldENyeXB0b1N1aXRlKG9wdGlvbnM/OiBDcnlwdG9TZXR0aW5nKTogSUNyeXB0b1N1aXRlIHtcbiAgICBpZiAoIW9wdGlvbnMpIHJldHVybiBVc2VyLm5ld0NyeXB0b1N1aXRlKCk7XG4gICAgaWYgKENvcmVVdGlscy5jcnlwdG9TdWl0ZSkgcmV0dXJuIENvcmVVdGlscy5jcnlwdG9TdWl0ZTtcblxuICAgIENvcmVVdGlscy5jcnlwdG9TdWl0ZSA9IFVzZXIubmV3Q3J5cHRvU3VpdGUob3B0aW9ucyk7XG4gICAgcmV0dXJuIENvcmVVdGlscy5jcnlwdG9TdWl0ZTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFNvZnR3YXJlRW5yb2xsbWVudEtleShcbiAgICBjcnlwdG9TdWl0ZTogYW55LFxuICAgIHByaXZhdGVLZXk/OiBzdHJpbmdcbiAgKSB7XG4gICAgaWYgKCFwcml2YXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiUHJpdmF0ZSBrZXkgbXVzdCBiZSBwcm92aWRlZCB3aGVuIEhTTSBjb25maWd1cmF0aW9uIGlzIG5vdCBzdXBwbGllZFwiXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY3J5cHRvU3VpdGUuY3JlYXRlS2V5RnJvbVJhdyhwcml2YXRlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGFzeW5jIGdldEhTTUVucm9sbG1lbnRLZXkoXG4gICAgY3J5cHRvU3VpdGU6IGFueSxcbiAgICBjZXJ0aWZpY2F0ZTogc3RyaW5nLFxuICAgIGhzbTogSFNNT3B0aW9uc1xuICApIHtcbiAgICBjb25zdCBza2kgPVxuICAgICAgaHNtLmtleUlkSGV4ICYmIGhzbS5rZXlJZEhleC50cmltKCkubGVuZ3RoID4gMFxuICAgICAgICA/IEJ1ZmZlci5mcm9tKGhzbS5rZXlJZEhleCwgXCJoZXhcIilcbiAgICAgICAgOiBhd2FpdCB0aGlzLmdldENlcnRpZmljYXRlU0tJKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCBjcnlwdG9TdWl0ZS5nZXRLZXkoc2tpKTtcbiAgICBpZiAoIWtleSB8fCAodHlwZW9mIGtleS5pc1ByaXZhdGUgPT09IFwiZnVuY3Rpb25cIiAmJiAha2V5LmlzUHJpdmF0ZSgpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIHJlc29sdmUgcHJpdmF0ZSBrZXkgZnJvbSBIU01cIik7XG4gICAgfVxuICAgIHJldHVybiBrZXk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0Q2VydGlmaWNhdGVTS0koY2VydGlmaWNhdGU6IHN0cmluZyk6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgY29uc3QgeDUwOSA9IG5ldyBYNTA5Q2VydGlmaWNhdGUoY2VydGlmaWNhdGUpO1xuICAgIGNvbnN0IGp3ayA9IHg1MDkucHVibGljS2V5LmV4cG9ydCh7IGZvcm1hdDogXCJqd2tcIiB9KTtcbiAgICBjb25zdCBwcmVmaXggPSBCdWZmZXIuZnJvbShbMHgwNF0pO1xuICAgIGNvbnN0IHggPSBCdWZmZXIuZnJvbShqd2sueCB8fCBcIlwiLCBcImJhc2U2NHVybFwiKTtcbiAgICBjb25zdCB5ID0gQnVmZmVyLmZyb20oandrLnkgfHwgXCJcIiwgXCJiYXNlNjR1cmxcIik7XG4gICAgcmV0dXJuIGNyeXB0b1xuICAgICAgLmNyZWF0ZUhhc2goXCJzaGEyNTZcIilcbiAgICAgIC51cGRhdGUoQnVmZmVyLmNvbmNhdChbcHJlZml4LCB4LCB5XSkpXG4gICAgICAuZGlnZXN0KCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1aWxkIGEgRmFicmljIEdhdGV3YXkgSWRlbnRpdHkgZnJvbSBhbiBNU1AgSUQgYW5kIGNlcnRpZmljYXRlXG4gICAqIEBzdW1tYXJ5IFJlYWRzIGEgY2VydGlmaWNhdGUgZnJvbSBhIGRpcmVjdG9yeSBwYXRoIG9yIGFjY2VwdHMgcmF3IGNvbnRlbnQgYW5kIHJldHVybnMgYW4gSWRlbnRpdHkgb2JqZWN0IHN1aXRhYmxlIGZvciB0aGUgRmFicmljIEdhdGV3YXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtc3BJZCAtIE1lbWJlcnNoaXAgU2VydmljZSBQcm92aWRlciBJRFxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2VydERpcmVjdG9yeVBhdGggLSBQYXRoIHRvIGEgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGNlcnRpZmljYXRlIGZpbGUsIG9yIFBFTSBjb250ZW50XG4gICAqIEByZXR1cm4ge1Byb21pc2U8SWRlbnRpdHk+fSBUaGUgaWRlbnRpdHkgY29udGFpbmluZyBtc3BJZCBhbmQgY2VydGlmaWNhdGUgY3JlZGVudGlhbHNcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRJZGVudGl0eShcbiAgICBtc3BJZDogc3RyaW5nLFxuICAgIGNlcnREaXJlY3RvcnlQYXRoOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZGVudGl0eT4ge1xuICAgIGNvbnN0IGlkZW50aXR5RmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgICBjb25zdCBjZXJ0UGF0aCA9IGF3YWl0IHRoaXMuZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxzID0gYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUoY2VydFBhdGgpO1xuICAgICAgcmV0dXJuIGNyZWRlbnRpYWxzO1xuICAgIH07XG5cbiAgICBjb25zdCBjcmVkZW50aWFsczogVWludDhBcnJheSA9IChhd2FpdCB0aGlzLmNvbnRlbnRPZkxvYWRGaWxlKFxuICAgICAgY2VydERpcmVjdG9yeVBhdGgsXG4gICAgICBpZGVudGl0eUZpbGVSZWFkZXJcbiAgICApKSBhcyBVaW50OEFycmF5O1xuXG4gICAgcmV0dXJuIHsgbXNwSWQsIGNyZWRlbnRpYWxzIH07XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0Rmlyc3REaXJGaWxlTmFtZShkaXJQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgY29uc3QgeyBqb2luIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwicGF0aFwiKSk7XG4gICAgY29uc3QgZmlsZXMgPSBhd2FpdCBwcm9taXNlcy5yZWFkZGlyKGRpclBhdGgpO1xuICAgIHJldHVybiBqb2luKGRpclBhdGgsIGZpbGVzWzBdKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBnZXRGaXJzdERpckZpbGVOYW1lQ29udGVudChkaXJQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgY29uc3QgeyBqb2luIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwicGF0aFwiKSk7XG4gICAgY29uc3QgZmlsZXMgPSBhd2FpdCBwcm9taXNlcy5yZWFkZGlyKGRpclBhdGgpO1xuICAgIHJldHVybiAoYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUoam9pbihkaXJQYXRoLCBmaWxlc1swXSkpKS50b1N0cmluZygpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGdldEZpbGVDb250ZW50KGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgcmV0dXJuIChhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShmaWxlUGF0aCkpLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0U2lnbmVyKGtleURpcmVjdG9yeVBhdGg6IHN0cmluZyk6IFByb21pc2U8U2lnbmVyPiB7XG4gICAgY29uc3Qgc2lnbmVyRmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gICAgICBjb25zdCBrZXlQYXRoID0gYXdhaXQgdGhpcy5nZXRGaXJzdERpckZpbGVOYW1lKHBhdGgpO1xuICAgICAgcmV0dXJuIGF3YWl0IHByb21pc2VzLnJlYWRGaWxlKGtleVBhdGgpO1xuICAgIH07XG5cbiAgICBjb25zdCBwcml2YXRlS2V5UGVtID0gKGF3YWl0IHRoaXMuY29udGVudE9mTG9hZEZpbGUoXG4gICAgICBrZXlEaXJlY3RvcnlQYXRoLFxuICAgICAgc2lnbmVyRmlsZVJlYWRlclxuICAgICkpIGFzIEJ1ZmZlcjtcbiAgICBjb25zdCBwcml2YXRlS2V5ID0gYXdhaXQgdGhpcy5leHRyYWN0UHJpdmF0ZUtleShwcml2YXRlS2V5UGVtKTtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwcml2YXRlS2V5KTtcbiAgICBjb25zdCBrID0gKHByaXZhdGVLZXkgYXMgYW55KVtrZXlzWzBdXTtcbiAgICAvLyAtLVxuXG4gICAgcmV0dXJuIHNpZ25lcnMubmV3UHJpdmF0ZUtleVNpZ25lcihrIGFzIGFueSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBhc3luYyBleHRyYWN0UHJpdmF0ZUtleShwZW06IEJ1ZmZlcikge1xuICAgIGNvbnN0IGxpYk5hbWUgPSBcImNyeXB0b1wiO1xuICAgIGxldCBzdWJ0bGU6IGFueTtcbiAgICBpZiAoXG4gICAgICAoZ2xvYmFsVGhpcyBhcyBhbnkpLndpbmRvdyAmJlxuICAgICAgKChnbG9iYWxUaGlzIGFzIGFueSkud2luZG93IGFzIHsgQ3J5cHRvOiBhbnkgfSkuQ3J5cHRvXG4gICAgKSB7XG4gICAgICBzdWJ0bGUgPSAoKGdsb2JhbFRoaXMgYXMgYW55KS5DcnlwdG8gYXMgYW55KS5zdWJ0bGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGxpYiA9IChhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KGxpYk5hbWUpKSkgYXMgYW55O1xuICAgICAgc3VidGxlID0gbGliLnN1YnRsZSB8fCBsaWIud2ViY3J5cHRvLnN1YnRsZTtcbiAgICB9XG5cbiAgICBpZiAoIXN1YnRsZSkgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGxvYWQgU3VidGxlQ3J5cHRvIG1vZHVsZVwiKTtcblxuICAgIGZ1bmN0aW9uIHN0cjJhYihzdHI6IHN0cmluZykge1xuICAgICAgY29uc3QgYnVmID0gbmV3IEFycmF5QnVmZmVyKHN0ci5sZW5ndGgpO1xuICAgICAgY29uc3QgYnVmVmlldyA9IG5ldyBVaW50OEFycmF5KGJ1Zik7XG4gICAgICBmb3IgKGxldCBpID0gMCwgc3RyTGVuID0gc3RyLmxlbmd0aDsgaSA8IHN0ckxlbjsgaSsrKSB7XG4gICAgICAgIGJ1ZlZpZXdbaV0gPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWY7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyID0gcGVtXG4gICAgICAudG9TdHJpbmcoXCJ1dGY4XCIpXG4gICAgICAucmVwbGFjZShcIi0tLS0tQkVHSU4gUFJJVkFURSBLRVktLS0tLVwiLCBcIlwiKVxuICAgICAgLnJlcGxhY2VBbGwoXCJcXG5cIiwgXCJcIilcbiAgICAgIC5yZXBsYWNlKFwiLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVwiLCBcIlwiKTtcbiAgICBjb25zdCBkZWNvZGVkID0gQnVmZmVyLmZyb20oc3RyLCBcImJhc2U2NFwiKS50b1N0cmluZyhcImJpbmFyeVwiKTtcbiAgICBjb25zdCBiaW5hcnlEZXIgPSBzdHIyYWIoZGVjb2RlZCk7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgc3VidGxlLmltcG9ydEtleShcbiAgICAgIFwicGtjczhcIixcbiAgICAgIGJpbmFyeURlcixcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJFQ0RTQVwiLFxuICAgICAgICBuYW1lZEN1cnZlOiBcIlAtMjU2XCIsXG4gICAgICB9LFxuICAgICAgdHJ1ZSxcbiAgICAgIFtcInNpZ25cIl1cbiAgICApO1xuXG4gICAgcmV0dXJuIGtleTtcbiAgfVxufVxuIiwiaW1wb3J0ICogYXMgeDUwOSBmcm9tIFwiQHBlY3VsaWFyL3g1MDlcIjtcbmltcG9ydCB7IENyeXB0bywgQ3J5cHRvS2V5IH0gZnJvbSBcIkBwZWN1bGlhci93ZWJjcnlwdG9cIjtcbmltcG9ydCB7IHN0cmluZ0Zvcm1hdCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGlzQnJvd3NlciwgTWluaUxvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG5jb25zdCBjcnlwdG8gPSBuZXcgQ3J5cHRvKCk7XG54NTA5LmNyeXB0b1Byb3ZpZGVyLnNldChjcnlwdG8pO1xuXG5leHBvcnQgZW51bSBCQVNFX0FMUEhBQkVUIHtcbiAgQkFTRTIgPSBcIjAxXCIsXG4gIEJBU0U4ID0gXCIwMTIzNDU2N1wiLFxuICBCQVNFMTEgPSBcIjAxMjM0NTY3ODlhXCIsXG4gIEJBU0UxNiA9IFwiMDEyMzQ1Njc4OWFiY2RlZlwiLFxuICBCQVNFMzIgPSBcIjAxMjM0NTY3ODlBQkNERUZHSEpLTU5QUVJTVFZXWFlaXCIsXG4gIEJBU0UzMl9aID0gXCJ5Ym5kcmZnOGVqa21jcHF4b3QxdXdpc3phMzQ1aDc2OVwiLFxuICBCQVNFMzYgPSBcIjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwiLFxuICBCQVNFNTggPSBcIjEyMzQ1Njc4OUFCQ0RFRkdISktMTU5QUVJTVFVWV1hZWmFiY2RlZmdoaWprbW5vcHFyc3R1dnd4eXpcIixcbiAgQkFTRTYyID0gXCIwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWlwiLFxuICBCQVNFNjQgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky9cIixcbiAgQkFTRTY3ID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fLiF+XCIsXG59XG5cbmV4cG9ydCB0eXBlIGtleU9iamVjdCA9IHtcbiAgaXY6IEFycmF5QnVmZmVyO1xuICBrZXk6IENyeXB0b0tleTtcbn07XG5cbmV4cG9ydCBlbnVtIENSWVBUTyB7XG4gIEhBU0ggPSBcIlNIQS0yNTZcIixcbiAgSVRFUkFUSU9OUyA9IDEwMDAsXG4gIEtFWUxFTkdUSCA9IDQ4LFxuICBERVJJVkVEX0lWX0xFTkdUSCA9IDE2LFxuICBERVJJVkVEX0tFWV9MRU5HVEggPSAzMiwgLy8gQmVjYXVzZSBTSEEtMjU2IHVzZWQgaGFzIGEgbmF0aXZlIHNpemUgb2YgMzIgYnl0ZXNcbiAgQUxHT1JZVEhNID0gXCJBRVMtR0NNXCIsXG4gIEtFWV9BTEdPUllUSE0gPSBcIlBCS0RGMlwiLFxufVxuXG5leHBvcnQgY2xhc3MgQmFzZUVuY29kZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGJhc2VNYXA6IFVpbnQ4QXJyYXkgPSBuZXcgVWludDhBcnJheSgyNTYpO1xuICBwcml2YXRlIHJlYWRvbmx5IGJhc2U6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBsZWFkZXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBmYWN0b3I6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBpRmFjdG9yOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBhbHBoYWJldDogQkFTRV9BTFBIQUJFVCkge1xuICAgIGlmICh0aGlzLmFscGhhYmV0Lmxlbmd0aCA+PSAyNTUpIHRocm93IG5ldyBFcnJvcihcIkFscGhhYmV0IHRvbyBsb25nXCIpO1xuXG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmJhc2VNYXAubGVuZ3RoOyBqKyspIHRoaXMuYmFzZU1hcFtqXSA9IDI1NTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxwaGFiZXQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHggPSBhbHBoYWJldC5jaGFyQXQoaSk7XG4gICAgICBjb25zdCB4YyA9IHguY2hhckNvZGVBdCgwKTtcbiAgICAgIGlmICh0aGlzLmJhc2VNYXBbeGNdICE9PSAyNTUpIHRocm93IG5ldyBFcnJvcih4ICsgXCIgaXMgYW1iaWd1b3VzXCIpO1xuXG4gICAgICB0aGlzLmJhc2VNYXBbeGNdID0gaTtcbiAgICB9XG5cbiAgICB0aGlzLmJhc2UgPSB0aGlzLmFscGhhYmV0Lmxlbmd0aDtcbiAgICB0aGlzLmxlYWRlciA9IHRoaXMuYWxwaGFiZXQuY2hhckF0KDApO1xuICAgIHRoaXMuZmFjdG9yID0gTWF0aC5sb2codGhpcy5iYXNlKSAvIE1hdGgubG9nKDI1Nik7IC8vIGxvZyhCQVNFKSAvIGxvZygyNTYpLCByb3VuZGVkIHVwXG4gICAgdGhpcy5pRmFjdG9yID0gTWF0aC5sb2coMjU2KSAvIE1hdGgubG9nKHRoaXMuYmFzZSk7IC8vIGxvZygyNTYpIC8gbG9nKEJBU0UpLCByb3VuZGVkIHVwXG4gIH1cblxuICBlbmNvZGUoc291cmNlOiBVaW50OEFycmF5IHwgRGF0YVZpZXcgfCBhbnlbXSB8IHN0cmluZykge1xuICAgIGlmICh0eXBlb2Ygc291cmNlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBzb3VyY2UgPSBCdWZmZXIuZnJvbShzb3VyY2UpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KHNvdXJjZSkpIHtcbiAgICAgIHNvdXJjZSA9IG5ldyBVaW50OEFycmF5KFxuICAgICAgICBzb3VyY2UuYnVmZmVyLFxuICAgICAgICBzb3VyY2UuYnl0ZU9mZnNldCxcbiAgICAgICAgc291cmNlLmJ5dGVMZW5ndGhcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgIHNvdXJjZSA9IFVpbnQ4QXJyYXkuZnJvbShzb3VyY2UpO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm4gXCJcIjtcblxuICAgIC8vIFNraXAgJiBjb3VudCBsZWFkaW5nIHplcm9lcy5cbiAgICBsZXQgemVyb2VzID0gMDtcbiAgICBsZXQgbGVuZ3RoID0gMDtcbiAgICBsZXQgcGJlZ2luID0gMDtcbiAgICBjb25zdCBwZW5kID0gc291cmNlLmxlbmd0aDtcbiAgICB3aGlsZSAocGJlZ2luICE9PSBwZW5kICYmIHNvdXJjZVtwYmVnaW5dID09PSAwKSB7XG4gICAgICBwYmVnaW4rKztcbiAgICAgIHplcm9lcysrO1xuICAgIH1cbiAgICAvLyBBbGxvY2F0ZSBlbm91Z2ggc3BhY2UgaW4gYmlnLWVuZGlhbiBiYXNlNTggcmVwcmVzZW50YXRpb24uXG4gICAgY29uc3Qgc2l6ZSA9ICgocGVuZCAtIHBiZWdpbikgKiB0aGlzLmlGYWN0b3IgKyAxKSA+Pj4gMDtcbiAgICBjb25zdCBiNTggPSBuZXcgVWludDhBcnJheShzaXplKTtcbiAgICAvLyBQcm9jZXNzIHRoZSBieXRlcy5cbiAgICB3aGlsZSAocGJlZ2luICE9PSBwZW5kKSB7XG4gICAgICBsZXQgY2FycnkgPSBzb3VyY2VbcGJlZ2luXTtcbiAgICAgIC8vIEFwcGx5IFwiYjU4ID0gYjU4ICogMjU2ICsgY2hcIi5cbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGZvciAoXG4gICAgICAgIGxldCBpdDEgPSBzaXplIC0gMTtcbiAgICAgICAgKGNhcnJ5ICE9PSAwIHx8IGkgPCBsZW5ndGgpICYmIGl0MSAhPT0gLTE7XG4gICAgICAgIGl0MS0tLCBpKytcbiAgICAgICkge1xuICAgICAgICBjYXJyeSArPSAoMjU2ICogYjU4W2l0MV0pID4+PiAwO1xuICAgICAgICBiNThbaXQxXSA9IGNhcnJ5ICUgdGhpcy5iYXNlID4+PiAwO1xuICAgICAgICBjYXJyeSA9IChjYXJyeSAvIHRoaXMuYmFzZSkgPj4+IDA7XG4gICAgICB9XG4gICAgICBpZiAoY2FycnkgIT09IDApIHRocm93IG5ldyBFcnJvcihcIk5vbi16ZXJvIGNhcnJ5XCIpO1xuXG4gICAgICBsZW5ndGggPSBpO1xuICAgICAgcGJlZ2luKys7XG4gICAgfVxuICAgIC8vIFNraXAgbGVhZGluZyB6ZXJvZXMgaW4gYmFzZTU4IHJlc3VsdC5cbiAgICBsZXQgaXQyID0gc2l6ZSAtIGxlbmd0aDtcbiAgICB3aGlsZSAoaXQyICE9PSBzaXplICYmIGI1OFtpdDJdID09PSAwKSBpdDIrKztcblxuICAgIC8vIFRyYW5zbGF0ZSB0aGUgcmVzdWx0IGludG8gYSBzdHJpbmcuXG4gICAgbGV0IHN0ciA9IHRoaXMubGVhZGVyLnJlcGVhdCh6ZXJvZXMpO1xuICAgIGZvciAoOyBpdDIgPCBzaXplOyArK2l0Mikge1xuICAgICAgc3RyICs9IHRoaXMuYWxwaGFiZXQuY2hhckF0KGI1OFtpdDJdKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxuXG4gIHByaXZhdGUgZGVjb2RlVW5zYWZlKHNvdXJjZTogc3RyaW5nKTogVWludDhBcnJheSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHNvdXJjZS5sZW5ndGggPT09IDApIHJldHVybiBuZXcgVWludDhBcnJheSgwKTtcblxuICAgIGxldCBwc3ogPSAwO1xuICAgIC8vIFNraXAgYW5kIGNvdW50IGxlYWRpbmcgJzEncy5cbiAgICBsZXQgemVyb2VzID0gMDtcbiAgICBsZXQgbGVuZ3RoID0gMDtcbiAgICB3aGlsZSAoc291cmNlW3Bzel0gPT09IHRoaXMubGVhZGVyKSB7XG4gICAgICB6ZXJvZXMrKztcbiAgICAgIHBzeisrO1xuICAgIH1cbiAgICAvLyBBbGxvY2F0ZSBlbm91Z2ggc3BhY2UgaW4gYmlnLWVuZGlhbiBiYXNlMjU2IHJlcHJlc2VudGF0aW9uLlxuICAgIGNvbnN0IHNpemUgPSAoKHNvdXJjZS5sZW5ndGggLSBwc3opICogdGhpcy5mYWN0b3IgKyAxKSA+Pj4gMDsgLy8gbG9nKDU4KSAvIGxvZygyNTYpLCByb3VuZGVkIHVwLlxuICAgIGNvbnN0IGIyNTYgPSBuZXcgVWludDhBcnJheShzaXplKTtcbiAgICAvLyBQcm9jZXNzIHRoZSBjaGFyYWN0ZXJzLlxuICAgIHdoaWxlIChzb3VyY2VbcHN6XSkge1xuICAgICAgLy8gRGVjb2RlIGNoYXJhY3RlclxuICAgICAgbGV0IGNhcnJ5ID0gdGhpcy5iYXNlTWFwW3NvdXJjZS5jaGFyQ29kZUF0KHBzeildO1xuICAgICAgLy8gSW52YWxpZCBjaGFyYWN0ZXJcbiAgICAgIGlmIChjYXJyeSA9PT0gMjU1KSByZXR1cm47XG5cbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGZvciAoXG4gICAgICAgIGxldCBpdDMgPSBzaXplIC0gMTtcbiAgICAgICAgKGNhcnJ5ICE9PSAwIHx8IGkgPCBsZW5ndGgpICYmIGl0MyAhPT0gLTE7XG4gICAgICAgIGl0My0tLCBpKytcbiAgICAgICkge1xuICAgICAgICBjYXJyeSArPSAodGhpcy5iYXNlICogYjI1NltpdDNdKSA+Pj4gMDtcbiAgICAgICAgYjI1NltpdDNdID0gY2FycnkgJSAyNTYgPj4+IDA7XG4gICAgICAgIGNhcnJ5ID0gKGNhcnJ5IC8gMjU2KSA+Pj4gMDtcbiAgICAgIH1cbiAgICAgIGlmIChjYXJyeSAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKFwiTm9uLXplcm8gY2FycnlcIik7XG5cbiAgICAgIGxlbmd0aCA9IGk7XG4gICAgICBwc3orKztcbiAgICB9XG4gICAgLy8gU2tpcCBsZWFkaW5nIHplcm9lcyBpbiBiMjU2LlxuICAgIGxldCBpdDQgPSBzaXplIC0gbGVuZ3RoO1xuICAgIHdoaWxlIChpdDQgIT09IHNpemUgJiYgYjI1NltpdDRdID09PSAwKSBpdDQrKztcblxuICAgIGNvbnN0IHZjaCA9IG5ldyBVaW50OEFycmF5KHplcm9lcyArIChzaXplIC0gaXQ0KSk7XG4gICAgbGV0IGogPSB6ZXJvZXM7XG4gICAgd2hpbGUgKGl0NCAhPT0gc2l6ZSkgdmNoW2orK10gPSBiMjU2W2l0NCsrXTtcblxuICAgIHJldHVybiB2Y2g7XG4gIH1cblxuICBkZWNvZGUoc291cmNlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmRlY29kZVVuc2FmZShzb3VyY2UpO1xuICAgIGlmIChidWZmZXIpIHJldHVybiBidWZmZXI7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTm9uLWJhc2VcIiArIHRoaXMuYmFzZSArIFwiIGNoYXJhY3RlclwiKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ3J5cHRvVXRpbHMge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBiNThlbmNvZGVyID0gbmV3IEJhc2VFbmNvZGVyKEJBU0VfQUxQSEFCRVQuQkFTRTU4KTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IE1pbmlMb2dnZXIoQ3J5cHRvVXRpbHMubmFtZSk7XG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIHN0YXRpYyBmYWJyaWNJZEZyb21DZXJ0aWZpY2F0ZShjZXJ0aWZpY2F0ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoc3RyaW5nRm9ybWF0KFwiUGFyc2luZyBjZXJ0aWZpY2F0ZTogezB9XCIsIGNlcnRpZmljYXRlKSk7XG4gICAgY29uc3QgY2VydCA9IG5ldyB4NTA5Llg1MDlDZXJ0aWZpY2F0ZShjZXJ0aWZpY2F0ZSk7XG4gICAgY29uc3QgeyBzdWJqZWN0LCBpc3N1ZXIgfSA9IGNlcnQ7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICBzdHJpbmdGb3JtYXQoXG4gICAgICAgIFwiQ2VydGlmaWNhdGUgcGFyc2VkIHdpdGggc3ViamVjdCB7MH0gYW5kIGlzc3VlciB7MX1cIixcbiAgICAgICAgc3ViamVjdCxcbiAgICAgICAgaXNzdWVyXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gYHg1MDk6Oi8ke3N1YmplY3QucmVwbGFjZUFsbChcIiwgXCIsIFwiL1wiKX06Oi8ke2lzc3Vlci5yZXBsYWNlQWxsKFwiLCBcIiwgXCIvXCIpfWA7XG4gIH1cblxuICBzdGF0aWMgZW5jb2RlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5iNThlbmNvZGVyLmVuY29kZShzdHIpO1xuICB9XG4gIHN0YXRpYyBkZWNvZGUoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGRlY29kZWQgPSB0aGlzLmI1OGVuY29kZXIuZGVjb2RlKHN0cik7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRlY29kZWQpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBzdGF0aWMgc3RyaW5nVG9BcnJheUJ1ZmZlcihzdHI6IHN0cmluZykge1xuICAgIGNvbnN0IGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihzdHIubGVuZ3RoKTtcbiAgICBjb25zdCBidWZWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmKTtcbiAgICBmb3IgKGxldCBpID0gMCwgc3RyTGVuID0gc3RyLmxlbmd0aDsgaSA8IHN0ckxlbjsgaSsrKSB7XG4gICAgICBidWZWaWV3W2ldID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgfVxuICAgIHJldHVybiBidWY7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBhc3luYyBleHRyYWN0S2V5KFxuICAgIHR5cGU6IFwicHJpdmF0ZVwiIHwgXCJwdWJsaWNcIixcbiAgICBwZW06IEJ1ZmZlciB8IHN0cmluZyxcbiAgICB1c2FnZXM/OiBhbnlbXVxuICApIHtcbiAgICBjb25zdCBzdWJ0bGUgPSBjcnlwdG8uc3VidGxlO1xuXG4gICAgY29uc3Qgc3RyID0gcGVtXG4gICAgICAudG9TdHJpbmcoXCJ1dGY4XCIpXG4gICAgICAucmVwbGFjZShcbiAgICAgICAgbmV3IFJlZ0V4cChgLS0tLS1CRUdJTiAoJHt0eXBlLnRvVXBwZXJDYXNlKCl9IEtFWXxDRVJUSUZJQ0FURSktLS0tLWApLFxuICAgICAgICBcIlwiXG4gICAgICApXG4gICAgICAucmVwbGFjZUFsbChcIlxcblwiLCBcIlwiKVxuICAgICAgLnJlcGxhY2UoXG4gICAgICAgIG5ldyBSZWdFeHAoYC0tLS0tRU5EICgke3R5cGUudG9VcHBlckNhc2UoKX0gS0VZfENFUlRJRklDQVRFKS0tLS0tYCksXG4gICAgICAgIFwiXCJcbiAgICAgICk7XG4gICAgY29uc3QgZGVjb2RlZCA9IEJ1ZmZlci5mcm9tKHN0ciwgXCJiYXNlNjRcIikudG9TdHJpbmcoXCJiaW5hcnlcIik7XG4gICAgY29uc3QgYmluYXJ5RGVyID0gdGhpcy5zdHJpbmdUb0FycmF5QnVmZmVyKGRlY29kZWQpO1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHN1YnRsZS5pbXBvcnRLZXkoXG4gICAgICBcInBrY3M4XCIsXG4gICAgICBiaW5hcnlEZXIsXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgICAgbmFtZWRDdXJ2ZTogXCJQLTI1NlwiLFxuICAgICAgfSxcbiAgICAgIHRydWUsXG4gICAgICB1c2FnZXMgPyB1c2FnZXMgOiBbXCJzaWduXCJdXG4gICAgKTtcblxuICAgIHJldHVybiBrZXk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZXh0cmFjdFByaXZhdGVLZXkocGVtOiBCdWZmZXIgfCBzdHJpbmcsIHVzYWdlcz86IGFueVtdKSB7XG4gICAgcmV0dXJuIHRoaXMuZXh0cmFjdEtleShcInByaXZhdGVcIiwgcGVtLCB1c2FnZXMpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGV4dHJhY3RQdWJsaWNLZXkocGVtOiBCdWZmZXIgfCBzdHJpbmcsIHVzYWdlcz86IGFueVtdKSB7XG4gICAgcmV0dXJuIHRoaXMuZXh0cmFjdEtleShcInB1YmxpY1wiLCBwZW0sIHVzYWdlcyk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgc2lnbihwcml2YXRlS2V5OiBzdHJpbmcsIGRhdGE6IEJ1ZmZlcik6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5leHRyYWN0UHJpdmF0ZUtleShwcml2YXRlS2V5KTtcbiAgICBjb25zdCBidWZmID0gKGF3YWl0IGNyeXB0by5zdWJ0bGUuc2lnbihcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJFQ0RTQVwiLFxuICAgICAgICBoYXNoOiBcIlNIQS0yNTZcIixcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICBkYXRhXG4gICAgKSkgYXMgQXJyYXlCdWZmZXI7XG5cbiAgICByZXR1cm4gQXJyYXkuZnJvbShuZXcgVWludDhBcnJheShidWZmKSlcbiAgICAgIC5tYXAoKGIpID0+IGIudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsIFwiMFwiKSlcbiAgICAgIC5qb2luKFwiXCIpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIHZlcmlmeShcbiAgICBjZXJ0aWZpY2F0ZTogc3RyaW5nLFxuICAgIHNpZ25hdHVyZTogQnVmZmVyIHwgc3RyaW5nLFxuICAgIGRhdGE6IEJ1ZmZlciB8IHN0cmluZ1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBjZXJ0ID0gbmV3IHg1MDkuWDUwOUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCBjZXJ0LnB1YmxpY0tleS5leHBvcnQoKTtcbiAgICBzaWduYXR1cmUgPSAoXG4gICAgICB0eXBlb2Ygc2lnbmF0dXJlID09PSBcInN0cmluZ1wiID8gQnVmZmVyLmZyb20oc2lnbmF0dXJlLCBcImhleFwiKSA6IHNpZ25hdHVyZVxuICAgICkgYXMgQnVmZmVyO1xuICAgIGRhdGEgPSAodHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIgPyBCdWZmZXIuZnJvbShkYXRhKSA6IGRhdGEpIGFzIEJ1ZmZlcjtcbiAgICByZXR1cm4gY3J5cHRvLnN1YnRsZS52ZXJpZnkoXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgICAgaGFzaDogXCJTSEEtMjU2XCIsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgc2lnbmF0dXJlLFxuICAgICAgZGF0YVxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZW5jcnlwdChjZXJ0aWZpY2F0ZTogc3RyaW5nLCBkYXRhOiBzdHJpbmcgfCBCdWZmZXIpIHtcbiAgICBjb25zdCBjZXJ0ID0gbmV3IHg1MDkuWDUwOUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCBjZXJ0LnB1YmxpY0tleS5leHBvcnQoKTtcbiAgICBkYXRhID0gKHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiID8gQnVmZmVyLmZyb20oZGF0YSkgOiBkYXRhKSBhcyBCdWZmZXI7XG4gICAgY29uc3QgYnVmZiA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuZW5jcnlwdChcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJFQ0RTQVwiLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIGRhdGFcbiAgICApO1xuXG4gICAgcmV0dXJuIEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoYnVmZikpXG4gICAgICAubWFwKChiKSA9PiBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCBcIjBcIikpXG4gICAgICAuam9pbihcIlwiKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFN1YnRsZUNyeXB0bygpIHtcbiAgICByZXR1cm4gaXNCcm93c2VyKClcbiAgICAgID8gKGdsb2JhbFRoaXMgYXMgYW55KS53aW5kb3cuY3J5cHRvLnN1YnRsZVxuICAgICAgOiBjcnlwdG8uc3VidGxlO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGRlY3J5cHQocHJpdmF0ZUtleTogc3RyaW5nLCBkYXRhOiBzdHJpbmcgfCBCdWZmZXIpIHtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCB0aGlzLmV4dHJhY3RQcml2YXRlS2V5KHByaXZhdGVLZXkpO1xuICAgIGRhdGEgPSAoXG4gICAgICB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiA/IEJ1ZmZlci5mcm9tKGRhdGEsIFwiaGV4XCIpIDogZGF0YVxuICAgICkgYXMgQnVmZmVyO1xuICAgIHJldHVybiB0aGlzLmdldFN1YnRsZUNyeXB0bygpLmRlY3J5cHQoXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwiRUNEU0FcIixcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICBkYXRhXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIGdldCBhIHJhbmRvbSBtYXN0ZXIga2V5XG4gICAqXG4gICAqIEBkZXNjcmlwdGlvbiBJZiBkYXRhIGlzIG5vdCBwYXNzZWQsIGEgcmFuZG9tIEFycmF5QnVmZmVyIHdpbGwgYmUgZ2VuZXJhdGVkXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGRhdGEgZW5jcnl0aW9uIGRhdGFcbiAgICpcbiAgICogQGZ1bmN0aW9uIGdldE1hc3RlclxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGdldE1hc3RlcihkYXRhPzogQXJyYXlCdWZmZXIpOiBQcm9taXNlPGtleU9iamVjdD4ge1xuICAgIGNvbnN0IHRleHRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG4gICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgZ2VuR2VuZXNpcyA9IGNyeXB0by5yYW5kb21VVUlEKCk7XG4gICAgICBkYXRhID0gdGV4dEVuY29kZXIuZW5jb2RlKGdlbkdlbmVzaXMpLmJ1ZmZlcjtcbiAgICB9XG5cbiAgICBjb25zdCBpbXBvcnRlZEtleSA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuaW1wb3J0S2V5KFxuICAgICAgXCJyYXdcIixcbiAgICAgIGRhdGEsXG4gICAgICBDUllQVE8uS0VZX0FMR09SWVRITSBhcyBzdHJpbmcsXG4gICAgICBmYWxzZSxcbiAgICAgIFtcImRlcml2ZUJpdHNcIl1cbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGtleTogaW1wb3J0ZWRLZXksXG4gICAgICBpdjogZGF0YSEsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIGRlcml2ZSBhIGtleSBmcm9tIGFub3RoZXIga2V5XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzYWx0XG4gICAqIEBwYXJhbSB7Q3J5cHRvS2V5fSBrZXkgT3JpZ2luYWwga2V5XG4gICAqXG4gICAqIEBmdW5jdGlvbiBnZXREZXJpdmF0aW9uS2V5XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2V0RGVyaXZhdGlvbktleShzYWx0OiBzdHJpbmcsIGtleTogQ3J5cHRvS2V5KSB7XG4gICAgY29uc3QgdGV4dEVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICBjb25zdCBzYWx0QnVmZmVyID0gdGV4dEVuY29kZXIuZW5jb2RlKHNhbHQpO1xuICAgIGNvbnN0IHNhbHRIYXNoZWQgPSBhd2FpdCB0aGlzLmdldFN1YnRsZUNyeXB0bygpLmRpZ2VzdChcbiAgICAgIFwiU0hBLTI1NlwiLFxuICAgICAgc2FsdEJ1ZmZlclxuICAgICk7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgbmFtZTogQ1JZUFRPLktFWV9BTEdPUllUSE0gYXMgc3RyaW5nLFxuICAgICAgaGFzaDogQ1JZUFRPLkhBU0gsXG4gICAgICBzYWx0OiBzYWx0SGFzaGVkLFxuICAgICAgaXRlcmF0aW9uczogQ1JZUFRPLklURVJBVElPTlMsXG4gICAgfTtcbiAgICBjb25zdCBkZXJpdmF0aW9uID0gYXdhaXQgdGhpcy5nZXRTdWJ0bGVDcnlwdG8oKS5kZXJpdmVCaXRzKFxuICAgICAgcGFyYW1zLFxuICAgICAga2V5LFxuICAgICAgQ1JZUFRPLktFWUxFTkdUSCAqIDhcbiAgICApO1xuICAgIHJldHVybiB0aGlzLmdldEtleShkZXJpdmF0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5IGFuZCBJViBmcm9tIHRoZSBDcnl0b0tleSBhcnJheVxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBkZXJpdmF0aW9uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBnZXRLZXlcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRLZXkoZGVyaXZhdGlvbjogQXJyYXlCdWZmZXIpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgY29uc3QgaXZsZW4gPSAxNjtcbiAgICBjb25zdCBrZXlsZW4gPSAzMjtcbiAgICBjb25zdCBkZXJpdmVkS2V5ID0gZGVyaXZhdGlvbi5zbGljZSgwLCBrZXlsZW4pO1xuICAgIGNvbnN0IGl2ID0gZGVyaXZhdGlvbi5zbGljZShrZXlsZW4pO1xuICAgIGNvbnN0IGltcG9ydGVkRW5jcnlwdGlvbktleSA9IGF3YWl0IHRoaXMuZ2V0U3VidGxlQ3J5cHRvKCkuaW1wb3J0S2V5KFxuICAgICAgXCJyYXdcIixcbiAgICAgIGRlcml2ZWRLZXksXG4gICAgICB7IG5hbWU6IENSWVBUTy5BTEdPUllUSE0gYXMgc3RyaW5nIH0sXG4gICAgICBmYWxzZSxcbiAgICAgIFtcImVuY3J5cHRcIiwgXCJkZWNyeXB0XCJdXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAga2V5OiBpbXBvcnRlZEVuY3J5cHRpb25LZXksXG4gICAgICBpdjogaXYsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIGRlY3J5cHQgZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgKiBAcGFyYW0ge2tleU9iamVjdH0ga2V5T2JqZWN0XG4gICAqXG4gICAqIEBmdW5jdGlvbiBlbmNyeXB0XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZW5jcnlwdFBpbihcbiAgICB0ZXh0OiBzdHJpbmcsXG4gICAga2V5T2JqZWN0OiBrZXlPYmplY3RcbiAgKTogUHJvbWlzZTxBcnJheUJ1ZmZlcj4ge1xuICAgIGNvbnN0IHRleHRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG4gICAgY29uc3QgdGV4dEJ1ZmZlciA9IHRleHRFbmNvZGVyLmVuY29kZSh0ZXh0KTtcbiAgICBjb25zdCBlbmNyeXB0ZWRUZXh0ID0gYXdhaXQgdGhpcy5nZXRTdWJ0bGVDcnlwdG8oKS5lbmNyeXB0KFxuICAgICAgeyBuYW1lOiBDUllQVE8uQUxHT1JZVEhNIGFzIHN0cmluZywgaXY6IGtleU9iamVjdC5pdiB9LFxuICAgICAga2V5T2JqZWN0LmtleSxcbiAgICAgIHRleHRCdWZmZXJcbiAgICApO1xuICAgIHJldHVybiBlbmNyeXB0ZWRUZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFV0aWwgZnVuY3Rpb24gdG8gZGVjcnlwdCBkYXRhXG4gICAqXG4gICAqIEBwYXJhbSB7QnVmZmVyU291cmNlfSBlbmNyeXB0ZWRUZXh0XG4gICAqIEBwYXJhbSB7a2V5T2JqZWN0fSBrZXlPYmplY3RcbiAgICpcbiAgICogQGZ1bmN0aW9uIGRlY3J5cHRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBkZWNyeXB0UGluKFxuICAgIGVuY3J5cHRlZFRleHQ6IEFycmF5QnVmZmVyLFxuICAgIGtleU9iamVjdDoga2V5T2JqZWN0XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgdGV4dERlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcbiAgICBjb25zdCBkZWNyeXB0ZWRUZXh0ID0gYXdhaXQgdGhpcy5nZXRTdWJ0bGVDcnlwdG8oKS5kZWNyeXB0KFxuICAgICAgeyBuYW1lOiBDUllQVE8uQUxHT1JZVEhNIGFzIHN0cmluZywgaXY6IGtleU9iamVjdC5pdiB9LFxuICAgICAga2V5T2JqZWN0LmtleSxcbiAgICAgIGVuY3J5cHRlZFRleHRcbiAgICApO1xuICAgIHJldHVybiB0ZXh0RGVjb2Rlci5kZWNvZGUoZGVjcnlwdGVkVGV4dCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEJhc2VFcnJvciwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQXV0aG9yaXphdGlvbkVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG4vLyBpbXBvcnQgeyBNSVNTSU5HX1BSSVZBVEVfREFUQV9FUlJPUl9NRVNTQUdFIH0gZnJvbSBcIi4uL2NvbnRyYWN0cy9wcml2YXRlLWRhdGFcIjtcbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBvdmVyZmxvdyBlcnJvciBpbiBhcml0aG1ldGljIG9wZXJhdGlvbnMgaW4gU21hcnQgQ29udHJhY3RzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBPdmVyZmxvd0Vycm9yXG4gKiBAZXh0ZW5kcyBJbnRlcm5hbEVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgT3ZlcmZsb3dFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBPdmVyZmxvd0Vycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgaW4gYmFsYW5jZSB0byBwZXJmb3JtIGEgdHJhbnNhY3Rpb24gaW4gU21hcnQgQ29udHJhY3RzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBCYWxhbmNlRXJyb3JcbiAqIEBleHRlbmRzIEludGVybmFsRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBCYWxhbmNlRXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgQmFsYW5jZUVycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgaW4gYmFsYW5jZSB0byBwZXJmb3JtIGEgdHJhbnNhY3Rpb24gaW4gU21hcnQgQ29udHJhY3RzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBCYWxhbmNlRXJyb3JcbiAqIEBleHRlbmRzIEludGVybmFsRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBBbGxvd2FuY2VFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBBbGxvd2FuY2VFcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIHJlZ2lzdHJhdGluZyBuZXcgZW50aXRpZXNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIFJlZ2lzdHJhdGlvbkVycm9yXG4gKlxuICogQGNhdGVnb3J0IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uRXJyb3IgZXh0ZW5kcyBBdXRob3JpemF0aW9uRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBSZWdpc3RyYXRpb25FcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gd2hlbiBhbiB1bnN1cHBvcnRlZCBvcGVyYXRpb24gaXMgYXR0ZW1wdGVkXG4gKiBAc3VtbWFyeSBUaGlzIGVycm9yIGlzIHRocm93biB3aGVuIGFuIG9wZXJhdGlvbiBpcyByZXF1ZXN0ZWQgdGhhdCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBjdXJyZW50XG4gKiBwZXJzaXN0ZW5jZSBhZGFwdGVyIG9yIGNvbmZpZ3VyYXRpb24uIEl0IGV4dGVuZHMgdGhlIEJhc2VFcnJvciBjbGFzcyBhbmQgc2V0cyBhIDUwMCBzdGF0dXMgY29kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBhbiBFcnJvciBvYmplY3QgdG8gd3JhcFxuICogQGNsYXNzIFVuc3VwcG9ydGVkRXJyb3JcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBUaHJvd2luZyBhbiBVbnN1cHBvcnRlZEVycm9yXG4gKiBpZiAoIWFkYXB0ZXIuc3VwcG9ydHNUcmFuc2FjdGlvbnMoKSkge1xuICogICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcignVHJhbnNhY3Rpb25zIGFyZSBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgYWRhcHRlcicpO1xuICogfVxuICpcbiAqIC8vIENhdGNoaW5nIGFuIFVuc3VwcG9ydGVkRXJyb3JcbiAqIHRyeSB7XG4gKiAgIGF3YWl0IGFkYXB0ZXIuYmVnaW5UcmFuc2FjdGlvbigpO1xuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgaWYgKGVycm9yIGluc3RhbmNlb2YgVW5zdXBwb3J0ZWRFcnJvcikge1xuICogICAgIGNvbnNvbGUuZXJyb3IoJ09wZXJhdGlvbiBub3Qgc3VwcG9ydGVkOicsIGVycm9yLm1lc3NhZ2UpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBNaXNzaW5nQ29udGV4dEVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIE1pc3NpbmdDb250ZXh0RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yID0gXCJNSVNTSU5HX1BSSVZBVEVfREFUQV9FUlJPUl9NRVNTQUdFXCIpIHtcbiAgICBzdXBlcihVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2Vzcy5uYW1lLCBtc2csIDQwMyk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGVycm9yIHRoYXQgb2NjdXJzIHdoZW4gYSByZXF1aXJlZCBpbml0aWFsaXphdGlvbiBzdGVwIGlzIG5vdCBwZXJmb3JtZWQuXG4gKlxuICogQGNsYXNzIE5vdEluaXRpYWxpemVkRXJyb3JcbiAqIEBleHRlbmRzIEJhc2VFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyB8IEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBhbiBFcnJvciBvYmplY3QgdG8gd3JhcC5cbiAqXG4gKiBAdGhyb3dzIHtOb3RJbml0aWFsaXplZEVycm9yfSAtIFRocm93cyBhbiBlcnJvciB3aGVuIGEgcmVxdWlyZWQgaW5pdGlhbGl6YXRpb24gc3RlcCBpcyBub3QgcGVyZm9ybWVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbml0aWFsaXplIHRoZSBhcHBsaWNhdGlvblxuICogaWYgKCFpc0luaXRpYWxpemVkKSB7XG4gKiAgIHRocm93IG5ldyBOb3RJbml0aWFsaXplZEVycm9yKCdBcHBsaWNhdGlvbiBpcyBub3QgaW5pdGlhbGl6ZWQnKTtcbiAqIH1cbiAqXG4gKiAvLyBDYXRjaGluZyBhbiBOb3RJbml0aWFsaXplZEVycm9yXG4gKiB0cnkge1xuICogICAvLyBQZXJmb3JtIG9wZXJhdGlvbnMgdGhhdCByZXF1aXJlIGluaXRpYWxpemF0aW9uXG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBOb3RJbml0aWFsaXplZEVycm9yKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcignSW5pdGlhbGl6YXRpb24gZXJyb3I6JywgZXJyb3IubWVzc2FnZSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgTm90SW5pdGlhbGl6ZWRFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihOb3RJbml0aWFsaXplZEVycm9yLm5hbWUsIG1zZywgNDA5KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTWlzc2luZ1BLQ1NTMTFMaWIgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgTWlzc2luZ1BLQ1NTMTFMaWIubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRW5kb3JzZW1lbnRFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIEVuZG9yc2VtZW50RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTXZjY1JlYWRDb25mbGljdEVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgTXZjY1JlYWRDb25mbGljdEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBoYW50b21SZWFkQ29uZmxpY3RFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIFBoYW50b21SZWFkQ29uZmxpY3RFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBFbmRvcnNlbWVudFBvbGljeUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgRW5kb3JzZW1lbnRQb2xpY3lFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUcmFuc2FjdGlvbkxpbWl0c0Vycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yLFxuICAgIG5hbWU6IHN0cmluZyA9IFRyYW5zYWN0aW9uTGltaXRzRXJyb3IubmFtZSxcbiAgICBjb2RlID0gNTkwXG4gICkge1xuICAgIHN1cGVyKG1lc3NhZ2UsIG5hbWUsIGNvZGUpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUcmFuc2FjdGlvblRpbWVvdXRFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIFRyYW5zYWN0aW9uVGltZW91dEVycm9yLm5hbWUsIDU5MSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRyYW5zYWN0aW9uQnVmZmVyU2l6ZUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgVHJhbnNhY3Rpb25CdWZmZXJTaXplRXJyb3IubmFtZSwgNTkyKTtcbiAgfVxufVxuIiwiaW1wb3J0IEZhYnJpY0NBU2VydmljZXMgZnJvbSBcImZhYnJpYy1jYS1jbGllbnRcIjtcbmltcG9ydCB7XG4gIEFmZmlsaWF0aW9uU2VydmljZSxcbiAgSWRlbnRpdHlTZXJ2aWNlLFxuICBJRW5yb2xsUmVzcG9uc2UsXG4gIElSZWdpc3RlclJlcXVlc3QsXG4gIElTZXJ2aWNlUmVzcG9uc2UsXG4gIFRMU09wdGlvbnMsXG59IGZyb20gXCJmYWJyaWMtY2EtY2xpZW50XCI7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSBcImZhYnJpYy1jb21tb25cIjtcbmltcG9ydCB7IENBQ29uZmlnLCBDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi9zaGFyZWQvdHlwZXNcIjtcbmltcG9ydCB7IElkZW50aXR5IH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9tb2RlbC9JZGVudGl0eVwiO1xuaW1wb3J0IHsgQXV0aG9yaXphdGlvbkVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBDb25mbGljdEVycm9yLFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENvcmVVdGlscyB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgQ0FfUk9MRSB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ3J5cHRvVXRpbHMgfSBmcm9tIFwiLi4vY3J5cHRvXCI7XG5pbXBvcnQge1xuICBDZXJ0aWZpY2F0ZVJlc3BvbnNlLFxuICBGYWJyaWNJZGVudGl0eSxcbiAgR2V0Q2VydGlmaWNhdGVzUmVxdWVzdCxcbiAgSWRlbnRpdHlSZXNwb25zZSxcbn0gZnJvbSBcIi4uLy4uL3NoYXJlZC9mYWJyaWMtdHlwZXNcIjtcbmltcG9ydCB7IFJlZ2lzdHJhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9lcnJvcnNcIjtcbmltcG9ydCB7IExvZ2dlZENsYXNzLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEh5cGVybGVkZ2VyIEZhYnJpYyBDQSBpZGVudGl0eSB0eXBlcy5cbiAqIEBzdW1tYXJ5IEVudW1lcmF0ZXMgdGhlIHN1cHBvcnRlZCBpZGVudGl0eSB0eXBlcyByZWNvZ25pemVkIGJ5IEZhYnJpYyBDQSBmb3IgcmVnaXN0cmF0aW9uIGFuZCBpZGVudGl0eSBtYW5hZ2VtZW50LlxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgZW51bSBIRkNBSWRlbnRpdHlUeXBlIHtcbiAgUEVFUiA9IFwicGVlclwiLFxuICBPUkRFUkVSID0gXCJvcmRlcmVyXCIsXG4gIENMSUVOVCA9IFwiY2xpZW50XCIsXG4gIFVTRVIgPSBcInVzZXJcIixcbiAgQURNSU4gPSBcImFkbWluXCIsXG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBLZXkvdmFsdWUgYXR0cmlidXRlIHVzZWQgZHVyaW5nIENBIHJlZ2lzdHJhdGlvbi5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gYXR0cmlidXRlIGVudHJ5IHRoYXQgY2FuIGJlIGF0dGFjaGVkIHRvIGEgRmFicmljIENBIGlkZW50aXR5IGR1cmluZyByZWdpc3RyYXRpb24sIG9wdGlvbmFsbHkgbWFya2luZyBpdCBmb3IgaW5jbHVzaW9uIGluIGVjZXJ0LlxuICogQGludGVyZmFjZSBJS2V5VmFsdWVBdHRyaWJ1dGVcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIEF0dHJpYnV0ZSBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gQXR0cmlidXRlIHZhbHVlLlxuICogQHBhcmFtIHtib29sZWFufSBbZWNlcnRdIC0gV2hldGhlciB0aGUgYXR0cmlidXRlIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgZW5yb2xsbWVudCBjZXJ0aWZpY2F0ZSAoRUNlcnQpLlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgaW50ZXJmYWNlIElLZXlWYWx1ZUF0dHJpYnV0ZSB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsdWU6IHN0cmluZztcbiAgZWNlcnQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdGFuZGFyZCBGYWJyaWMgQ0EgaWRlbnRpdHkgYXR0cmlidXRlIGtleXMuXG4gKiBAc3VtbWFyeSBFbnVtZXJhdGVzIHdlbGwta25vd24gRmFicmljIENBIGF0dHJpYnV0ZSBrZXlzIHRoYXQgY2FuIGJlIGFzc2lnbmVkIHRvIGlkZW50aXRpZXMgZm9yIGRlbGVnYXRpb25zIGFuZCBwZXJtaXNzaW9ucy5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGVudW0gSEZDQUlkZW50aXR5QXR0cmlidXRlcyB7XG4gIEhGUkVHSVNUUkFSUk9MRVMgPSBcImhmLlJlZ2lzdHJhci5Sb2xlc1wiLFxuICBIRlJFR0lTVFJBUkRFTEVHQVRFUk9MRVMgPSBcImhmLlJlZ2lzdHJhci5EZWxlZ2F0ZVJvbGVzXCIsXG4gIEhGUkVHSVNUUkFSQVRUUklCVVRFUyA9IFwiaGYuUmVnaXN0cmFyLkF0dHJpYnV0ZXNcIixcbiAgSEZJTlRFUk1FRElBVEVDQSA9IFwiaGYuSW50ZXJtZWRpYXRlQ0FcIixcbiAgSEZSRVZPS0VSID0gXCJoZi5SZXZva2VyXCIsXG4gIEhGQUZGSUxJQVRJT05NR1IgPSBcImhmLkFmZmlsaWF0aW9uTWdyXCIsXG4gIEhGR0VOQ1JMID0gXCJoZi5HZW5DUkxcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2VydmljZSB3cmFwcGVyIGZvciBpbnRlcmFjdGluZyB3aXRoIGEgRmFicmljIENBLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgaGlnaC1sZXZlbCBvcGVyYXRpb25zIGZvciBtYW5hZ2luZyBpZGVudGl0aWVzIGFnYWluc3QgYSBIeXBlcmxlZGdlciBGYWJyaWMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5LCBpbmNsdWRpbmcgcmVnaXN0cmF0aW9uLCBlbnJvbGxtZW50LCByZXZvY2F0aW9uLCBhbmQgYWRtaW5pc3RyYXRpdmUgcXVlcmllcy4gRW5jYXBzdWxhdGVzIGxvd2VyLWxldmVsIEZhYnJpYyBDQSBjbGllbnQgY2FsbHMgd2l0aCBjb25zaXN0ZW50IGxvZ2dpbmcgYW5kIGVycm9yIG1hcHBpbmcuXG4gKiBAcGFyYW0ge0NBQ29uZmlnfSBjYUNvbmZpZyAtIENvbm5lY3Rpb24gYW5kIFRMUyBjb25maWd1cmF0aW9uIGZvciB0aGUgdGFyZ2V0IENBLlxuICogQGNsYXNzIEZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlXG4gKiBAZXhhbXBsZVxuICogLy8gUmVnaXN0ZXIgYW5kIGVucm9sbCBhIG5ldyB1c2VyXG4gKiBjb25zdCBzdmMgPSBuZXcgRmFicmljRW5yb2xsbWVudFNlcnZpY2Uoe1xuICogICB1cmw6ICdodHRwczovL2xvY2FsaG9zdDo3MDU0JyxcbiAqICAgY2FOYW1lOiAnT3JnMUNBJyxcbiAqICAgdGxzOiB7IHRydXN0ZWRSb290czogWycvcGF0aC90by9jYS5wZW0nXSwgdmVyaWZ5OiBmYWxzZSB9LFxuICogICBjYUNlcnQ6ICcvcGF0aC90by9hZG1pbi9jZXJ0RGlyJyxcbiAqICAgY2FLZXk6ICcvcGF0aC90by9hZG1pbi9rZXlEaXInXG4gKiB9KTtcbiAqIGF3YWl0IHN2Yy5yZWdpc3Rlcih7IHVzZXJOYW1lOiAnYWxpY2UnLCBwYXNzd29yZDogJ3MzY3IzdCcgfSwgZmFsc2UsICdvcmcxLmRlcGFydG1lbnQxJywgQ0FfUk9MRS5VU0VSKTtcbiAqIGNvbnN0IGlkID0gYXdhaXQgc3ZjLmVucm9sbCgnYWxpY2UnLCAnczNjcjN0Jyk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIGF1dG9udW1iZXJcbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFN2YyBhcyBGYWJyaWNFbnJvbGxtZW50U2VydmljZVxuICogICBwYXJ0aWNpcGFudCBDQSBhcyBGYWJyaWMgQ0FcbiAqICAgQXBwLT4+U3ZjOiByZWdpc3RlcihjcmVkZW50aWFscywgLi4uKVxuICogICBTdmMtPj5DQTogcmVnaXN0ZXIocmVxdWVzdCwgYWRtaW5Vc2VyKVxuICogICBDQS0tPj5TdmM6IGVucm9sbG1lbnRTZWNyZXRcbiAqICAgU3ZjLS0+PkFwcDogc2VjcmV0XG4gKiAgIEFwcC0+PlN2YzogZW5yb2xsKGVucm9sbG1lbnRJZCwgc2VjcmV0KVxuICogICBTdmMtPj5DQTogZW5yb2xsKHtlbnJvbGxtZW50SUQsIHNlY3JldH0pXG4gKiAgIENBLS0+PlN2YzogY2VydGlmaWNhdGVzXG4gKiAgIFN2Yy0tPj5BcHA6IElkZW50aXR5XG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNFbnJvbGxtZW50U2VydmljZSBleHRlbmRzIExvZ2dlZENsYXNzIHtcbiAgcHJpdmF0ZSBjYT86IEZhYnJpY0NBU2VydmljZXM7XG5cbiAgcHJpdmF0ZSBjZXJ0aWZpY2F0ZVNlcnZpY2U/OiBhbnk7XG5cbiAgcHJpdmF0ZSBhZmZpbGlhdGlvblNlcnZpY2U/OiBBZmZpbGlhdGlvblNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBpZGVudGl0eVNlcnZpY2U/OiBJZGVudGl0eVNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBjbGllbnQ/OiBhbnk7XG5cbiAgcHJpdmF0ZSB1c2VyPzogVXNlcjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNhQ29uZmlnOiBDQUNvbmZpZykge1xuICAgIENvcmVVdGlscy5nZXRDcnlwdG9TdWl0ZShcbiAgICAgIGNhQ29uZmlnLmhzbVxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHNvZnR3YXJlOiBmYWxzZSxcbiAgICAgICAgICAgIGxpYjogY2FDb25maWcuaHNtLmxpYnJhcnksXG4gICAgICAgICAgICBzbG90OiBjYUNvbmZpZy5oc20uc2xvdCxcbiAgICAgICAgICAgIGxhYmVsOiBjYUNvbmZpZy5oc20udG9rZW5MYWJlbCxcbiAgICAgICAgICAgIHBpbjogU3RyaW5nKGNhQ29uZmlnLmhzbS5waW4pLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWRcbiAgICApO1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgVXNlcigpOiBQcm9taXNlPFVzZXI+IHtcbiAgICBpZiAodGhpcy51c2VyKSByZXR1cm4gdGhpcy51c2VyO1xuICAgIGNvbnN0IHsgY2FOYW1lLCBjYUNlcnQsIGNhS2V5LCB1cmwsIGhzbSB9ID0gdGhpcy5jYUNvbmZpZztcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5Vc2VyKTtcbiAgICBsb2cuZGVidWcoYENyZWF0aW5nIENBIHVzZXIgZm9yICR7Y2FOYW1lfSBhdCAke3VybH1gKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0EgY2VydGlmaWNhdGUgZnJvbSAke2NhQ2VydH1gKTtcbiAgICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGF3YWl0IENvcmVVdGlscy5nZXRGaXJzdERpckZpbGVOYW1lQ29udGVudChjYUNlcnQpO1xuICAgIGxldCBrZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIWhzbSkge1xuICAgICAgaWYgKCFjYUtleSkge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgTWlzc2luZyBjYUtleSBjb25maWd1cmF0aW9uIGZvciBDQSAke2NhTmFtZX0uIFByb3ZpZGUgYSBrZXkgZGlyZWN0b3J5IG9yIGNvbmZpZ3VyZSBIU00gc3VwcG9ydC5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0Ega2V5IGZyb20gJHtjYUtleX1gKTtcbiAgICAgIGtleSA9IGF3YWl0IENvcmVVdGlscy5nZXRGaXJzdERpckZpbGVOYW1lQ29udGVudChjYUtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFVzaW5nIEhTTSBjb25maWd1cmF0aW9uIGZvciBDQSAke2NhTmFtZX0gd2l0aCBsaWJyYXJ5ICR7aHNtLmxpYnJhcnl9YFxuICAgICAgKTtcbiAgICB9XG4gICAgbG9nLmRlYnVnKGBMb2FkaW5nIEFkbWluIHVzZXIgZm9yIGNhICR7Y2FOYW1lfWApO1xuICAgIHRoaXMudXNlciA9IGF3YWl0IENvcmVVdGlscy5nZXRDQVVzZXIoXCJhZG1pblwiLCBrZXksIGNlcnRpZmljYXRlLCBjYU5hbWUsIHtcbiAgICAgIGhzbSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy51c2VyO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIENBKCk6IFByb21pc2U8RmFicmljQ0FTZXJ2aWNlcz4ge1xuICAgIGlmICh0aGlzLmNhKSByZXR1cm4gdGhpcy5jYTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5DQSk7XG4gICAgY29uc3QgeyB1cmwsIHRscywgY2FOYW1lIH0gPSB0aGlzLmNhQ29uZmlnO1xuXG4gICAgLy8gRk9SIFNvbWUgUmVhc29uIHRoZSB2ZXJpZmljYXRpb24gZmFpbHMgbmVlZCB0byBpbnZlc3RpZ2F0ZSB0aGlzIHdvcmtzIGZvciBub3dcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgdHJ1c3RlZFJvb3RzLCB2ZXJpZnkgfSA9IHRscyBhcyBUTFNPcHRpb25zO1xuXG4gICAgY29uc3Qgcm9vdCA9ICh0cnVzdGVkUm9vdHMgYXMgc3RyaW5nW10pWzBdIGFzIHN0cmluZztcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQ0EgY2VydGlmaWNhdGUgZnJvbSAke3Jvb3R9LiBjd2Q6ICR7cHJvY2Vzcy5jd2QoKX1gKTtcblxuICAgIGNvbnN0IGNlcnRpZmljYXRlID0gYXdhaXQgQ29yZVV0aWxzLmdldEZpbGVDb250ZW50KHJvb3QpO1xuICAgIGxvZy5kZWJ1ZyhgQ3JlYXRpbmcgQ0EgQ2xpZW50IGZvciBDQSAke2NhTmFtZX0gdW5kZXIgJHt1cmx9YCk7XG4gICAgdGhpcy5jYSA9IG5ldyBGYWJyaWNDQVNlcnZpY2VzKFxuICAgICAgdXJsLFxuICAgICAge1xuICAgICAgICB0cnVzdGVkUm9vdHM6IEJ1ZmZlci5mcm9tKGNlcnRpZmljYXRlKSxcbiAgICAgICAgdmVyaWZ5LFxuICAgICAgfSBhcyBUTFNPcHRpb25zLFxuICAgICAgY2FOYW1lXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5jYTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBDbGllbnQoKTogUHJvbWlzZTx7IG5ld0NlcnRpZmljYXRlU2VydmljZTogYW55IH0+IHtcbiAgICBpZiAodGhpcy5jbGllbnQpIHJldHVybiB0aGlzLmNsaWVudDtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICB0aGlzLmNsaWVudCA9IChjYSBhcyBhbnkpW1wiX0ZhYnJpY0NBU2VydmljZXNcIl07XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIENlcnRpZmljYXRlKCkge1xuICAgIGlmICghdGhpcy5jZXJ0aWZpY2F0ZVNlcnZpY2UpXG4gICAgICB0aGlzLmNlcnRpZmljYXRlU2VydmljZSA9IChhd2FpdCB0aGlzLkNsaWVudCgpKS5uZXdDZXJ0aWZpY2F0ZVNlcnZpY2UoKTtcbiAgICByZXR1cm4gdGhpcy5jZXJ0aWZpY2F0ZVNlcnZpY2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgQWZmaWxpYXRpb25zKCkge1xuICAgIGlmICghdGhpcy5hZmZpbGlhdGlvblNlcnZpY2UpXG4gICAgICB0aGlzLmFmZmlsaWF0aW9uU2VydmljZSA9IChhd2FpdCB0aGlzLkNBKCkpLm5ld0FmZmlsaWF0aW9uU2VydmljZSgpO1xuICAgIHJldHVybiB0aGlzLmFmZmlsaWF0aW9uU2VydmljZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBJZGVudGl0aWVzKCkge1xuICAgIGlmICghdGhpcy5pZGVudGl0eVNlcnZpY2UpXG4gICAgICB0aGlzLmlkZW50aXR5U2VydmljZSA9IChhd2FpdCB0aGlzLkNBKCkpLm5ld0lkZW50aXR5U2VydmljZSgpO1xuICAgIHJldHVybiB0aGlzLmlkZW50aXR5U2VydmljZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmUgY2VydGlmaWNhdGVzIGZyb20gdGhlIENBLlxuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgQ0EgY2VydGlmaWNhdGUgc2VydmljZSB0byBsaXN0IGNlcnRpZmljYXRlcywgb3B0aW9uYWxseSBtYXBwaW5nIHRvIFBFTSBzdHJpbmdzIG9ubHkuXG4gICAqIEBwYXJhbSB7R2V0Q2VydGlmaWNhdGVzUmVxdWVzdH0gW3JlcXVlc3RdIC0gT3B0aW9uYWwgZmlsdGVyIHJlcXVlc3QgZm9yIGNlcnRpZmljYXRlIGxvb2t1cC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZG9NYXA9dHJ1ZV0gLSBXaGVuIHRydWUsIHJldHVybnMgYXJyYXkgb2YgUEVNIHN0cmluZ3M7IG90aGVyd2lzZSByZXR1cm5zIGZ1bGwgcmVzcG9uc2Ugb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHN0cmluZ1tdIHwgQ2VydGlmaWNhdGVSZXNwb25zZT59IEFycmF5IG9mIFBFTSBzdHJpbmdzIG9yIHRoZSBmdWxsIGNlcnRpZmljYXRlIHJlc3BvbnNlLlxuICAgKi9cbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzKFxuICAgIHJlcXVlc3Q/OiBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0LFxuICAgIGRvTWFwID0gdHJ1ZVxuICApOiBQcm9taXNlPHN0cmluZ1tdIHwgQ2VydGlmaWNhdGVSZXNwb25zZT4ge1xuICAgIGNvbnN0IGNlcnRpZmljYXRlU2VydmljZSA9IGF3YWl0IHRoaXMuQ2VydGlmaWNhdGUoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0Q2VydGlmaWNhdGVzKTtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgUmV0cmlldmluZyBjZXJ0aWZpY2F0ZXMke3JlcXVlc3QgPyBgIGZvciAke3JlcXVlc3QuaWR9YCA6IFwiXCJ9IGZvciBDQSAke3RoaXMuY2FDb25maWcuY2FOYW1lfWBcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBDZXJ0aWZpY2F0ZVJlc3BvbnNlID0gKFxuICAgICAgYXdhaXQgY2VydGlmaWNhdGVTZXJ2aWNlLmdldENlcnRpZmljYXRlcyhyZXF1ZXN0IHx8IHt9LCB1c2VyKVxuICAgICkucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmNlcnRzLmxlbmd0aH0gY2VydGlmaWNhdGVzOiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gXG4gICAgKTtcbiAgICByZXR1cm4gZG9NYXAgPyByZXNwb25zZS5jZXJ0cy5tYXAoKGMpID0+IGMuUEVNKSA6IHJlc3BvbnNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaXN0IGlkZW50aXRpZXMgcmVnaXN0ZXJlZCBpbiB0aGUgQ0EuXG4gICAqIEBzdW1tYXJ5IFF1ZXJpZXMgdGhlIENBIGlkZW50aXR5IHNlcnZpY2UgdG8gZmV0Y2ggYWxsIGlkZW50aXRpZXMgYW5kIHJldHVybnMgdGhlIGxpc3QgYXMgRmFicmljSWRlbnRpdHkgb2JqZWN0cy5cbiAgICogQHJldHVybiB7UHJvbWlzZTxGYWJyaWNJZGVudGl0eVtdPn0gVGhlIGxpc3Qgb2YgaWRlbnRpdGllcyByZWdpc3RlcmVkIGluIHRoZSBDQS5cbiAgICovXG4gIGFzeW5jIGdldElkZW50aXRpZXMoKTogUHJvbWlzZTxGYWJyaWNJZGVudGl0eVtdPiB7XG4gICAgY29uc3QgaWRlbnRpdGllc1NlcnZpY2UgPSBhd2FpdCB0aGlzLklkZW50aXRpZXMoKTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5nZXRJZGVudGl0aWVzKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgSWRlbnRpdGllcyB1bmRlciBDQSAke3RoaXMuY2FDb25maWcuY2FOYW1lfWApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBJZGVudGl0eVJlc3BvbnNlID0gKFxuICAgICAgYXdhaXQgaWRlbnRpdGllc1NlcnZpY2UuZ2V0QWxsKGF3YWl0IHRoaXMuVXNlcigpKVxuICAgICkucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmlkZW50aXRpZXMubGVuZ3RofSBJZGVudGl0aWVzOiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gXG4gICAgKTtcbiAgICByZXR1cm4gcmVzcG9uc2UuaWRlbnRpdGllcztcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUVycm9yKGU6IEVycm9yKSB7XG4gICAgY29uc3QgcmVnZXhwID0gLy4qY29kZTpcXHMoXFxkKykuKj9tZXNzYWdlOlxcc1tcIiddKC4rKVtcIiddL2dzO1xuICAgIGNvbnN0IG1hdGNoID0gcmVnZXhwLmV4ZWMoZS5tZXNzYWdlKTtcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKGUpO1xuICAgIGNvbnN0IFssIGNvZGUsIG1lc3NhZ2VdID0gbWF0Y2g7XG4gICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICBjYXNlIFwiNzRcIjpcbiAgICAgIGNhc2UgXCI3MVwiOlxuICAgICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IobWVzc2FnZSk7XG4gICAgICBjYXNlIFwiMjBcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IobWVzc2FnZSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmUgYWZmaWxpYXRpb25zIGZyb20gdGhlIENBLlxuICAgKiBAc3VtbWFyeSBRdWVyaWVzIHRoZSBDQSBmb3IgdGhlIGxpc3Qgb2YgYWZmaWxpYXRpb25zIGF2YWlsYWJsZSB1bmRlciB0aGUgY29uZmlndXJlZCBDQS5cbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgYWZmaWxpYXRpb25zIHJlc3VsdCBwYXlsb2FkLlxuICAgKi9cbiAgYXN5bmMgZ2V0QWZmaWxpYXRpb25zKCkge1xuICAgIGNvbnN0IGFmZmlsaWF0aW9uU2VydmljZSA9IGF3YWl0IHRoaXMuQWZmaWxpYXRpb25zKCk7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0QWZmaWxpYXRpb25zKTtcbiAgICBsb2cuZGVidWcoYFJldHJpZXZpbmcgQWZmaWxpYXRpb25zIHVuZGVyIENBICR7dGhpcy5jYUNvbmZpZy5jYU5hbWV9YCk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgYWZmaWxpYXRpb25TZXJ2aWNlLmdldEFsbChhd2FpdCB0aGlzLlVzZXIoKSkpXG4gICAgICAucmVzdWx0O1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBGb3VuZCAke3Jlc3BvbnNlLmEubGVuZ3RofSBBZmZpbGlhdGlvbnM6ICR7SlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpfWBcbiAgICApO1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZCBpZGVudGl0eSBkZXRhaWxzIGZyb20gdGhlIENBIGJ5IGVucm9sbG1lbnQgSUQuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhbmQgdmFsaWRhdGVzIGEgc2luZ2xlIGlkZW50aXR5LCB0aHJvd2luZyBOb3RGb3VuZEVycm9yIHdoZW4gbWlzc2luZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGVucm9sbG1lbnRJZCAtIEVucm9sbG1lbnQgSUQgdG8gbG9va3VwLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEZhYnJpY0lkZW50aXR5Pn0gVGhlIGlkZW50aXR5IGRldGFpbHMgc3RvcmVkIGluIHRoZSBDQS5cbiAgICovXG4gIGFzeW5jIHJlYWQoZW5yb2xsbWVudElkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgbGV0IHJlc3VsdDogSVNlcnZpY2VSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgY2EubmV3SWRlbnRpdHlTZXJ2aWNlKCkuZ2V0T25lKGVucm9sbG1lbnRJZCwgdXNlcik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYENvdWxkbid0IGZpbmQgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgQ291bGRuJ3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke3Jlc3VsdC5lcnJvcnMuam9pbihcIlxcblwiKX1gXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQgYXMgRmFicmljSWRlbnRpdHk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVyIGEgbmV3IGlkZW50aXR5IHdpdGggdGhlIENBLlxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgcmVnaXN0cmF0aW9uIHJlcXVlc3QgZm9yIGEgbmV3IGVucm9sbG1lbnQgSUQsIHJldHVybmluZyB0aGUgZW5yb2xsbWVudCBzZWNyZXQgdXBvbiBzdWNjZXNzLlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkIGZvciB0aGUgbmV3IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSByZWdpc3RlcmVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXIoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbGV0IHJlZ2lzdHJhdGlvbjogc3RyaW5nO1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJlZ2lzdGVyKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyB1c2VyTmFtZSwgcGFzc3dvcmQgfSA9IG1vZGVsO1xuICAgICAgY29uc3QgY2EgPSBhd2FpdCB0aGlzLkNBKCk7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgICBjb25zdCBwcm9wcyA9IHtcbiAgICAgICAgZW5yb2xsbWVudElEOiB1c2VyTmFtZSBhcyBzdHJpbmcsXG4gICAgICAgIGVucm9sbG1lbnRTZWNyZXQ6IHBhc3N3b3JkLFxuICAgICAgICBhZmZpbGlhdGlvbjogYWZmaWxpYXRpb24sXG4gICAgICAgIHVzZXJSb2xlOiB1c2VyUm9sZSxcbiAgICAgICAgYXR0cnM6IGF0dHJzLFxuICAgICAgICBtYXhFbnJvbGxtZW50czogbWF4RW5yb2xsbWVudHMsXG4gICAgICB9IGFzIElSZWdpc3RlclJlcXVlc3Q7XG4gICAgICByZWdpc3RyYXRpb24gPSBhd2FpdCBjYS5yZWdpc3Rlcihwcm9wcywgdXNlcik7XG4gICAgICBsb2cuaW5mbyhcbiAgICAgICAgYFJlZ2lzdHJhdGlvbiBmb3IgJHt1c2VyTmFtZX0gY3JlYXRlZCB3aXRoIHVzZXIgdHlwZSAke3VzZXJSb2xlID8/IFwiVW5kZWZpbmVkIFJvbGVcIn0gJHtpc1N1cGVyVXNlciA/IFwiYXMgc3VwZXIgdXNlclwiIDogXCJcIn1gXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVnaXN0cmF0aW9uO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyBpZGVudGl0eUZyb21FbnJvbGxtZW50KFxuICAgIGVucm9sbG1lbnQ6IElFbnJvbGxSZXNwb25zZSxcbiAgICBtc3BJZDogc3RyaW5nXG4gICk6IElkZW50aXR5IHtcbiAgICBjb25zdCB7IGNlcnRpZmljYXRlLCBrZXksIHJvb3RDZXJ0aWZpY2F0ZSB9ID0gZW5yb2xsbWVudDtcbiAgICBjb25zdCBsb2cgPSBMb2dnaW5nLmZvcihGYWJyaWNFbnJvbGxtZW50U2VydmljZSwge30pLmZvcihcbiAgICAgIHRoaXMuaWRlbnRpdHlGcm9tRW5yb2xsbWVudFxuICAgICk7XG4gICAgbG9nLmRlYnVnKFxuICAgICAgYEdlbmVyYXRpbmcgSWRlbnRpdHkgZnJvbSBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlfSBpbiBtc3AgJHttc3BJZH1gXG4gICAgKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IENyeXB0b1V0aWxzLmZhYnJpY0lkRnJvbUNlcnRpZmljYXRlKGNlcnRpZmljYXRlKTtcbiAgICBjb25zdCBpZCA9IENyeXB0b1V0aWxzLmVuY29kZShjbGllbnRJZCk7XG4gICAgbG9nLmRlYnVnKGBJZGVudGl0eSAke2NsaWVudElkfSBhbmQgZW5jb2RlZElkICR7aWR9YCk7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IElkZW50aXR5KHtcbiAgICAgIGlkOiBpZCxcbiAgICAgIGNyZWRlbnRpYWxzOiB7XG4gICAgICAgIGlkOiBpZCxcbiAgICAgICAgY2VydGlmaWNhdGU6IGNlcnRpZmljYXRlLFxuICAgICAgICBwcml2YXRlS2V5OiBrZXkudG9CeXRlcygpLFxuICAgICAgICByb290Q2VydGlmaWNhdGU6IHJvb3RDZXJ0aWZpY2F0ZSxcbiAgICAgICAgY3JlYXRlZE9uOiBub3csXG4gICAgICAgIHVwZGF0ZWRPbjogbm93LFxuICAgICAgfSxcbiAgICAgIG1zcElkOiBtc3BJZCxcbiAgICAgIGNyZWF0ZWRPbjogbm93LFxuICAgICAgdXBkYXRlZE9uOiBub3csXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVucm9sbCBhbiBpZGVudGl0eSB3aXRoIHRoZSBDQSB1c2luZyBhIHJlZ2lzdHJhdGlvbiBzZWNyZXQuXG4gICAqIEBzdW1tYXJ5IEV4Y2hhbmdlcyB0aGUgZW5yb2xsbWVudCBJRCBhbmQgc2VjcmV0IGZvciBjZXJ0aWZpY2F0ZXMsIHJldHVybmluZyBhIGNvbnN0cnVjdGVkIElkZW50aXR5IG1vZGVsLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZW5yb2xsbWVudElkIC0gRW5yb2xsbWVudCBJRCB0byBlbnJvbGwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWdpc3RyYXRpb24gLSBFbnJvbGxtZW50IHNlY3JldCByZXR1cm5lZCBhdCByZWdpc3RyYXRpb24gdGltZS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxJZGVudGl0eT59IFRoZSBlbnJvbGxlZCBpZGVudGl0eSBvYmplY3Qgd2l0aCBjcmVkZW50aWFscy5cbiAgICovXG4gIGFzeW5jIGVucm9sbChlbnJvbGxtZW50SWQ6IHN0cmluZywgcmVnaXN0cmF0aW9uOiBzdHJpbmcpIHtcbiAgICBsZXQgaWRlbnRpdHk6IElkZW50aXR5O1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmVucm9sbCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNhID0gYXdhaXQgdGhpcy5DQSgpO1xuICAgICAgbG9nLmRlYnVnKGBFbnJvbGxpbmcgJHtlbnJvbGxtZW50SWR9YCk7XG4gICAgICBjb25zdCBlbnJvbGxtZW50OiBJRW5yb2xsUmVzcG9uc2UgPSBhd2FpdCBjYS5lbnJvbGwoe1xuICAgICAgICBlbnJvbGxtZW50SUQ6IGVucm9sbG1lbnRJZCxcbiAgICAgICAgZW5yb2xsbWVudFNlY3JldDogcmVnaXN0cmF0aW9uLFxuICAgICAgfSk7XG4gICAgICBpZGVudGl0eSA9IEZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlLmlkZW50aXR5RnJvbUVucm9sbG1lbnQoXG4gICAgICAgIGVucm9sbG1lbnQsXG4gICAgICAgIHRoaXMuY2FDb25maWcuY2FOYW1lXG4gICAgICApO1xuICAgICAgbG9nLmluZm8oXG4gICAgICAgIGBTdWNjZXNzZnVsbHkgZW5yb2xsZWQgJHtlbnJvbGxtZW50SWR9IHVuZGVyICR7dGhpcy5jYUNvbmZpZy5jYU5hbWV9IGFzICR7aWRlbnRpdHkuaWR9YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlKTtcbiAgICB9XG4gICAgcmV0dXJuIGlkZW50aXR5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlciBhbmQgZW5yb2xsIGEgbmV3IGlkZW50aXR5IGluIG9uZSBzdGVwLlxuICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgYSBuZXcgZW5yb2xsbWVudCBJRCB3aXRoIHRoZSBDQSBhbmQgaW1tZWRpYXRlbHkgZXhjaGFuZ2VzIHRoZSBzZWNyZXQgdG8gZW5yb2xsLCByZXR1cm5pbmcgdGhlIGNyZWF0ZWQgSWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7Q3JlZGVudGlhbHN9IG1vZGVsIC0gQ3JlZGVudGlhbHMgZm9yIHRoZSBuZXcgaWRlbnRpdHkgY29udGFpbmluZyB1c2VyTmFtZSBhbmQgcGFzc3dvcmQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzU3VwZXJVc2VyPWZhbHNlXSAtIFdoZXRoZXIgdG8gcmVnaXN0ZXIgdGhlIGlkZW50aXR5IGFzIGEgc3VwZXIgdXNlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFthZmZpbGlhdGlvbj1cIlwiXSAtIEFmZmlsaWF0aW9uIHN0cmluZyAoZS5nLiwgb3JnMS5kZXBhcnRtZW50MSkuXG4gICAqIEBwYXJhbSB7Q0FfUk9MRSB8IHN0cmluZ30gW3VzZXJSb2xlXSAtIFJvbGUgdG8gYXNzaWduIHRvIHRoZSBpZGVudGl0eS5cbiAgICogQHBhcmFtIHtJS2V5VmFsdWVBdHRyaWJ1dGV9IFthdHRyc10gLSBPcHRpb25hbCBhdHRyaWJ1dGVzIHRvIGF0dGFjaCB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4RW5yb2xsbWVudHNdIC0gTWF4aW11bSBudW1iZXIgb2YgZW5yb2xsbWVudHMgYWxsb3dlZCBmb3IgdGhlIGlkZW50aXR5LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gVGhlIGVucm9sbGVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXJBbmRFbnJvbGwoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyXG4gICk6IFByb21pc2U8SWRlbnRpdHk+IHtcbiAgICBjb25zdCByZWdpc3RyYXRpb24gPSBhd2FpdCB0aGlzLnJlZ2lzdGVyKFxuICAgICAgbW9kZWwsXG4gICAgICBpc1N1cGVyVXNlcixcbiAgICAgIGFmZmlsaWF0aW9uLFxuICAgICAgdXNlclJvbGUsXG4gICAgICBhdHRycyxcbiAgICAgIG1heEVucm9sbG1lbnRzXG4gICAgKTtcbiAgICBjb25zdCB7IHVzZXJOYW1lIH0gPSBtb2RlbDtcbiAgICByZXR1cm4gdGhpcy5lbnJvbGwodXNlck5hbWUgYXMgc3RyaW5nLCByZWdpc3RyYXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldm9rZXMgdGhlIGVucm9sbG1lbnQgb2YgYW4gaWRlbnRpdHkgd2l0aCB0aGUgc3BlY2lmaWVkIGVucm9sbG1lbnQgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBlbnJvbGxtZW50SWQgLSBUaGUgZW5yb2xsbWVudCBJRCBvZiB0aGUgaWRlbnRpdHkgdG8gYmUgcmV2b2tlZC5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlc3VsdCBvZiB0aGUgcmV2b2NhdGlvbiBvcGVyYXRpb24uXG4gICAqXG4gICAqIEB0aHJvd3Mge05vdEZvdW5kRXJyb3J9IElmIHRoZSBlbnJvbGxtZW50IHdpdGggdGhlIHNwZWNpZmllZCBJRCBkb2VzIG5vdCBleGlzdC5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlcmUgaXMgYW4gZXJyb3IgZHVyaW5nIHRoZSByZXZvY2F0aW9uIHByb2Nlc3MuXG4gICAqL1xuICBhc3luYyByZXZva2UoZW5yb2xsbWVudElkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjYSA9IGF3YWl0IHRoaXMuQ0EoKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5Vc2VyKCk7XG4gICAgY29uc3QgaWRlbnRpdHkgPSBhd2FpdCB0aGlzLnJlYWQoZW5yb2xsbWVudElkKTtcbiAgICBpZiAoIWlkZW50aXR5KVxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9YFxuICAgICAgKTtcbiAgICBsZXQgcmVzdWx0OiBJU2VydmljZVJlc3BvbnNlO1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBjYS5yZXZva2UoXG4gICAgICAgIHsgZW5yb2xsbWVudElEOiBpZGVudGl0eS5pZCwgcmVhc29uOiBcIlVzZXIgRGVsZXRhdGlvblwiIH0sXG4gICAgICAgIHVzZXJcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgcmV2b2tlIGVucm9sbG1lbnQgd2l0aCBpZCAke2Vucm9sbG1lbnRJZH06ICR7ZX1gXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBDb3VsZCBub3QgcmV2b2tlIGVucm9sbG1lbnQgd2l0aCBpZCAke2Vucm9sbG1lbnRJZH06ICR7cmVzdWx0LmVycm9ycy5qb2luKFwiXFxuXCIpfWBcbiAgICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSVJlZ2lzdGVyUmVxdWVzdCwgSUtleVZhbHVlQXR0cmlidXRlIH0gZnJvbSBcImZhYnJpYy1jYS1jbGllbnRcIjtcbmltcG9ydCB7IENBX1JPTEUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIG1pbixcbiAgbWlubGVuZ3RoLFxuICBNb2RlbCxcbiAgcmVxdWlyZWQsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uUmVxdWVzdEJ1aWxkZXIgZXh0ZW5kcyBNb2RlbCB7XG4gIEByZXF1aXJlZCgpXG4gIGFmZmlsaWF0aW9uOiBzdHJpbmcgPSBcIlwiO1xuICBAbWlubGVuZ3RoKDEpXG4gIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlW107XG4gIEByZXF1aXJlZCgpXG4gIGVucm9sbG1lbnRJRCE6IHN0cmluZztcbiAgQHJlcXVpcmVkKClcbiAgZW5yb2xsbWVudFNlY3JldCE6IHN0cmluZztcbiAgQG1pbigwKVxuICBtYXhFbnJvbGxtZW50cz86IG51bWJlcjtcbiAgQHJlcXVpcmVkKClcbiAgcm9sZSE6IHN0cmluZztcblxuICBidWlsZCgpOiBJUmVnaXN0ZXJSZXF1ZXN0IHtcbiAgICBjb25zdCBlcnJzID0gdGhpcy5oYXNFcnJvcnMoKTtcbiAgICBpZiAoZXJycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJzLnRvU3RyaW5nKCkpO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBJUmVnaXN0ZXJSZXF1ZXN0ID0ge1xuICAgICAgZW5yb2xsbWVudElEOiB0aGlzLmVucm9sbG1lbnRJRCxcbiAgICAgIGVucm9sbG1lbnRTZWNyZXQ6IHRoaXMuZW5yb2xsbWVudFNlY3JldCxcbiAgICAgIHJvbGU6IHRoaXMucm9sZSxcbiAgICAgIGFmZmlsaWF0aW9uOiB0aGlzLmFmZmlsaWF0aW9uLFxuICAgIH07XG4gICAgaWYgKHR5cGVvZiB0aGlzLm1heEVucm9sbG1lbnRzICE9PSBcInVuZGVmaW5lZFwiKVxuICAgICAgcmVzcG9uc2UubWF4RW5yb2xsbWVudHMgPSB0aGlzLm1heEVucm9sbG1lbnRzO1xuICAgIGlmICh0aGlzLmF0dHJzKSByZXNwb25zZS5hdHRycyA9IHRoaXMuYXR0cnM7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgc2V0QWZmaWxpYXRpb24odmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuYWZmaWxpYXRpb24gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGFkZEF0dHIoYXR0cjogSUtleVZhbHVlQXR0cmlidXRlKSB7XG4gICAgdGhpcy5hdHRycyA9IHRoaXMuYXR0cnMgfHwgW107XG4gICAgdGhpcy5hdHRycy5wdXNoKGF0dHIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0QXR0cnModmFsdWU6IElLZXlWYWx1ZUF0dHJpYnV0ZVtdKSB7XG4gICAgdGhpcy5hdHRycyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0RW5yb2xsbWVudElEKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmVucm9sbG1lbnRJRCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0RW5yb2xsbWVudFNlY3JldCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5lbnJvbGxtZW50U2VjcmV0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRNYXhFbnJvbGxtZW50cyh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5tYXhFbnJvbGxtZW50cyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Um9sZSh2YWx1ZTogQ0FfUk9MRSB8IHN0cmluZykge1xuICAgIHRoaXMucm9sZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59XG4iLCIvKipcbiAqIEVudW0gcmVwcmVzZW50aW5nIHRoZSBldmVudHMgZW1pdHRlZCBieSBhbiBFUkMyMCBjb250cmFjdC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhpcyBlbnVtIGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHNwZWNpZmljIGV2ZW50cyB0aGF0IGNhbiBiZSBlbWl0dGVkIGJ5IGFuIEVSQzIwIGNvbnRyYWN0LlxuICogVGhlIGV2ZW50cyBhcmUgbmFtZWQgYWNjb3JkaW5nIHRvIHRoZSBFSVAtMjAgc3RhbmRhcmQuXG4gKi9cbmV4cG9ydCBlbnVtIEVSQzIwRXZlbnRzIHtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGB0cmFuc2ZlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIHN1Y2Nlc3NmdWxseS5cbiAgICpcbiAgICogQHBhcmFtIGZyb20gLSBUaGUgYWRkcmVzcyBvZiB0aGUgc2VuZGVyLlxuICAgKiBAcGFyYW0gdG8gLSBUaGUgYWRkcmVzcyBvZiB0aGUgcmVjaXBpZW50LlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgYW1vdW50IG9mIHRva2VucyB0cmFuc2ZlcnJlZC5cbiAgICovXG4gIFRSQU5TRkVSID0gXCJUcmFuc2ZlclwiLFxuXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYW4gYGFwcHJvdmVgIGZ1bmN0aW9uIGlzIGNhbGxlZCBzdWNjZXNzZnVsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBvd25lciAtIFRoZSBhZGRyZXNzIG9mIHRoZSB0b2tlbiBvd25lci5cbiAgICogQHBhcmFtIHNwZW5kZXIgLSBUaGUgYWRkcmVzcyBvZiB0aGUgYXBwcm92ZWQgc3BlbmRlci5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiB0b2tlbnMgYXBwcm92ZWQgZm9yIHRoZSBzcGVuZGVyLlxuICAgKi9cbiAgQVBQUk9WQUwgPSBcIkFwcHJvdmFsXCIsXG59XG4iLCJpbXBvcnQgeyBNb2RlbCwgdHlwZSBNb2RlbEFyZyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGNvbHVtbiwgY3JlYXRlZEF0LCB1cGRhdGVkQXQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IGRlc2NyaXB0aW9uLCB1c2VzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUHJvcGVydHkgfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuXG5AdXNlcyhGYWJyaWNGbGF2b3VyKVxuZXhwb3J0IGNsYXNzIEZhYnJpY0Jhc2VNb2RlbCBleHRlbmRzIE1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBvcmlnaW5hbCB0aW1lc3RhbXAgb2YgY3JlYXRpb25cIilcbiAgQGNvbHVtbigpXG4gIEBjcmVhdGVkQXQoKVxuICBjcmVhdGVkQXQhOiBEYXRlO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdGltZXN0YW1wIG9mIHRoZSBsYXN0IHVwZGF0ZVwiKVxuICBAY29sdW1uKClcbiAgQHVwZGF0ZWRBdCgpXG4gIHVwZGF0ZWRBdCE6IERhdGU7XG5cbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2RlbFwiKVxuICBAY29sdW1uKClcbiAgQHZlcnNpb24oKVxuICB2ZXJzaW9uITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0Jhc2VNb2RlbD4pIHtcbiAgICBzdXBlcihhcmcpO1xuICB9XG59XG4iLCJpbXBvcnQgeyB0eXBlIE1vZGVsQXJnIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgY29sdW1uLCBjcmVhdGVkQnksIHVwZGF0ZWRCeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24sIHVzZXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0ZsYXZvdXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBGYWJyaWNCYXNlTW9kZWwgfSBmcm9tIFwiLi9GYWJyaWNCYXNlTW9kZWxcIjtcblxuQHVzZXMoRmFicmljRmxhdm91cilcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNJZGVudGlmaWVkQmFzZU1vZGVsIGV4dGVuZHMgRmFicmljQmFzZU1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBjcmVhdG9yXCIpXG4gIEBjb2x1bW4oKVxuICBAY3JlYXRlZEJ5KClcbiAgY3JlYXRlZEJ5ITogc3RyaW5nO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdXNlciB0aGF0IGxhc3QgdXBkYXRlZCB0aGUgbW9kZWxcIilcbiAgQGNvbHVtbigpXG4gIEB1cGRhdGVkQnkoKVxuICB1cGRhdGVkQnkhOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0lkZW50aWZpZWRCYXNlTW9kZWw+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY01vZGVsS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFNlZ3JlZ2F0ZWRNb2RlbCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb2xsZWN0aW9uUmVzb2x2ZXIsIE1pcnJvck1ldGFkYXRhIH0gZnJvbSBcIi4uL2RlY29yYXRvcnNcIjtcblxuTW9kZWwucHJvdG90eXBlLmlzU2hhcmVkID0gZnVuY3Rpb24gaXNTaGFyZWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogTVxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBNb2RlbC5pc1NoYXJlZCh0aGlzLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yPE0+KTtcbn07XG5cbk1vZGVsLnByb3RvdHlwZS5pc1ByaXZhdGUgPSBmdW5jdGlvbiBpc1ByaXZhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogTVxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBNb2RlbC5pc1ByaXZhdGUodGhpcy5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPik7XG59O1xuXG5Nb2RlbC5wcm90b3R5cGUuc2VncmVnYXRlID0gZnVuY3Rpb24gc2VncmVnYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IE1cbik6IFNlZ3JlZ2F0ZWRNb2RlbDxNPiB7XG4gIHJldHVybiBNb2RlbC5zZWdyZWdhdGUodGhpcyk7XG59O1xuXG4oTW9kZWwgYXMgYW55KS5zZWdyZWdhdGUgPSBmdW5jdGlvbiBzZWdyZWdhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbik6IFNlZ3JlZ2F0ZWRNb2RlbDxNPiB7XG4gIGlmICghTW9kZWwuaXNUcmFuc2llbnQobW9kZWwpKSByZXR1cm4geyBtb2RlbDogbW9kZWwgfTtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllcyA9IE1ldGFkYXRhLnZhbGlkYXRhYmxlUHJvcGVydGllcyhcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnlcbiAgKTtcblxuICBjb25zdCB0cmFuc2llbnRQcm9wcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgREJLZXlzLlRSQU5TSUVOVFxuICApO1xuICBjb25zdCBwcml2YXRlUHJvcGVydGllcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgRmFicmljTW9kZWxLZXlzLlBSSVZBVEVcbiAgKTtcbiAgY29uc3Qgc2hhcmVkUHJvcGVydGllcyA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgRmFicmljTW9kZWxLZXlzLlNIQVJFRFxuICApO1xuXG4gIGNvbnN0IHJlc3VsdDogU2VncmVnYXRlZE1vZGVsPE0+ID0ge1xuICAgIG1vZGVsOiB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PixcbiAgICB0cmFuc2llbnQ6IHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+LFxuICAgIHByaXZhdGVzOiB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PixcbiAgICBzaGFyZWQ6IHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+LFxuICB9O1xuXG4gIGNvbnN0IHRyYW5zaWVudEtleXMgPSBPYmplY3Qua2V5cyh0cmFuc2llbnRQcm9wcyB8fCB7fSk7XG4gIGNvbnN0IHByaXZhdGVLZXlzID0gT2JqZWN0LmtleXMocHJpdmF0ZVByb3BlcnRpZXMgfHwge30pO1xuICBjb25zdCBzaGFyZWRLZXlzID0gT2JqZWN0LmtleXMoc2hhcmVkUHJvcGVydGllcyB8fCB7fSk7XG5cbiAgLy8gY29uc3QgcGtLZXkgPSBNb2RlbC5wayhtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpO1xuICBmb3IgKGNvbnN0IGtleSBvZiBkZWNvcmF0ZWRQcm9wZXJ0aWVzKSB7XG4gICAgY29uc3QgdmFsdWUgPSBtb2RlbFtrZXkgYXMga2V5b2YgTV07XG4gICAgY29uc3QgaXNUcmFuc2llbnQgPSB0cmFuc2llbnRLZXlzLmluY2x1ZGVzKGtleSk7XG4gICAgY29uc3QgaXNQcml2YXRlID0gcHJpdmF0ZUtleXMuaW5jbHVkZXMoa2V5KTtcbiAgICBjb25zdCBpc1NoYXJlZCA9IHNoYXJlZEtleXMuaW5jbHVkZXMoa2V5KTtcbiAgICAvLyBjb25zdCBpc1ByaW1hcnlLZXkgPSBrZXkgPT09IHBrS2V5O1xuXG4gICAgaWYgKGlzVHJhbnNpZW50IHx8IGlzUHJpdmF0ZSB8fCBpc1NoYXJlZCkge1xuICAgICAgcmVzdWx0LnRyYW5zaWVudCA9IHJlc3VsdC50cmFuc2llbnQgfHwgKHt9IGFzIGFueSk7XG4gICAgICAocmVzdWx0LnRyYW5zaWVudCBhcyBhbnkpW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKGlzUHJpdmF0ZSkge1xuICAgICAgcmVzdWx0LnByaXZhdGVzID0gcmVzdWx0LnByaXZhdGVzIHx8ICh7fSBhcyBhbnkpO1xuICAgICAgKHJlc3VsdC5wcml2YXRlcyBhcyBhbnkpW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKGlzU2hhcmVkKSB7XG4gICAgICByZXN1bHQuc2hhcmVkID0gcmVzdWx0LnNoYXJlZCB8fCAoe30gYXMgYW55KTtcbiAgICAgIChyZXN1bHQuc2hhcmVkIGFzIGFueSlba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgICBjb25zdCBzaG91bGRJbmNsdWRlSW5Nb2RlbCA9ICFpc1RyYW5zaWVudCAmJiAhaXNQcml2YXRlICYmICFpc1NoYXJlZDtcbiAgICBpZiAoc2hvdWxkSW5jbHVkZUluTW9kZWwpIHtcbiAgICAgIHJlc3VsdC5tb2RlbCA9IHJlc3VsdC5tb2RlbCB8fCB7fTtcbiAgICAgIChyZXN1bHQubW9kZWwgYXMgYW55KVtrZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmVzdWx0Lm1vZGVsID0gTW9kZWwuYnVpbGQocmVzdWx0Lm1vZGVsLCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgcmV0dXJuIHJlc3VsdCBhcyBTZWdyZWdhdGVkTW9kZWw8TT47XG59LmJpbmQoTW9kZWwpO1xuXG4oTW9kZWwgYXMgYW55KS5pc1ByaXZhdGUgPSBmdW5jdGlvbiBpc1ByaXZhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIU1ldGFkYXRhLmdldChcbiAgICB0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpIDogbW9kZWwsXG4gICAgRmFicmljTW9kZWxLZXlzLlBSSVZBVEVcbiAgKTtcbn0uYmluZChNb2RlbCk7XG5cbihNb2RlbCBhcyBhbnkpLmlzU2hhcmVkID0gZnVuY3Rpb24gaXNTaGFyZWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIU1ldGFkYXRhLmdldChcbiAgICB0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpIDogbW9kZWwsXG4gICAgRmFicmljTW9kZWxLZXlzLlNIQVJFRFxuICApO1xufS5iaW5kKE1vZGVsKTtcblxuKE1vZGVsIGFzIGFueSkubWlycm9yZWQgPSBmdW5jdGlvbiBtaXJyb3JlZDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTSB8IENvbnN0cnVjdG9yPE0+XG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIE1ldGFkYXRhLmdldChcbiAgICB0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpIDogbW9kZWwsXG4gICAgTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsIEZhYnJpY01vZGVsS2V5cy5NSVJST1IpXG4gICk7XG59LmJpbmQoTW9kZWwpO1xuXG4oTW9kZWwgYXMgYW55KS5vd25lck9mID0gZnVuY3Rpb24gb3duZXJPZjxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTVxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbWV0YSA9IE1ldGFkYXRhLmdldChcbiAgICBtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnksXG4gICAgTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsIEZhYnJpY01vZGVsS2V5cy5PV05FRF9CWSlcbiAgKTtcbiAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4gbW9kZWxbbWV0YSBhcyBrZXlvZiBNXSBhcyBzdHJpbmc7XG59LmJpbmQoTW9kZWwpO1xuXG4oTW9kZWwgYXMgYW55KS5taXJyb3JlZEF0ID0gZnVuY3Rpb24gbWlycm9yZWRBdDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTSB8IENvbnN0cnVjdG9yPE0+XG4pOiBNaXJyb3JNZXRhZGF0YSB8IHVuZGVmaW5lZCB7XG4gIG1vZGVsID0gdHlwZW9mIG1vZGVsICE9PSBcImZ1bmN0aW9uXCIgPyAobW9kZWwuY29uc3RydWN0b3IgYXMgYW55KSA6IG1vZGVsO1xuICByZXR1cm4gTWV0YWRhdGEuZ2V0KFxuICAgIG1vZGVsIGFzIGFueSxcbiAgICBNZXRhZGF0YS5rZXkoRmFicmljTW9kZWxLZXlzLkZBQlJJQywgRmFicmljTW9kZWxLZXlzLk1JUlJPUilcbiAgKTtcbn0uYmluZChNb2RlbCk7XG5cbihNb2RlbCBhcyBhbnkpLmNvbGxlY3Rpb25zRm9yID0gZnVuY3Rpb24gY29sbGVjdGlvbnNGb3I8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKToge1xuICBwcml2YXRlQ29sczogKHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcilbXTtcbiAgc2hhcmVkQ29sczogKHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcilbXTtcbn0ge1xuICBjb25zdCBwcml2YXRlS2V5czogc3RyaW5nW10gPSBbRmFicmljTW9kZWxLZXlzLlBSSVZBVEVdIGFzIHN0cmluZ1tdO1xuICBjb25zdCBzaGFyZWRLZXlzOiBzdHJpbmdbXSA9IFtGYWJyaWNNb2RlbEtleXMuU0hBUkVEXSBhcyBzdHJpbmdbXTtcblxuICBjb25zdCBwcml2YXRlS2V5ID0gTWV0YWRhdGEua2V5KC4uLnByaXZhdGVLZXlzKTtcbiAgY29uc3Qgc2hhcmVkS2V5ID0gTWV0YWRhdGEua2V5KC4uLnNoYXJlZEtleXMpO1xuXG4gIGNvbnN0IGNvbnN0ciA9IHR5cGVvZiBtb2RlbCA9PT0gXCJmdW5jdGlvblwiID8gbW9kZWwgOiBtb2RlbC5jb25zdHJ1Y3RvcjtcblxuICBjb25zdCBwcml2YXRlTWV0YTogeyBjb2xsZWN0aW9uczogc3RyaW5nW10gfSA9IE1ldGFkYXRhLmdldChcbiAgICBjb25zdHIgYXMgYW55LFxuICAgIHByaXZhdGVLZXlcbiAgKTtcbiAgY29uc3Qgc2hhcmVkTWV0YTogeyBjb2xsZWN0aW9uczogc3RyaW5nW10gfSA9IE1ldGFkYXRhLmdldChcbiAgICBjb25zdHIgYXMgYW55LFxuICAgIHNoYXJlZEtleVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgcHJpdmF0ZUNvbHM6IHByaXZhdGVNZXRhPy5jb2xsZWN0aW9ucyB8fCBbXSxcbiAgICBzaGFyZWRDb2xzOiBzaGFyZWRNZXRhPy5jb2xsZWN0aW9ucyB8fCBbXSxcbiAgfTtcbn0uYmluZChNb2RlbCk7XG4iLCJpbXBvcnQge1xuICBBdXRob3JpemF0aW9uRXJyb3IsXG4gIFJlcG8sXG4gIENvbnRleHQsXG4gIFVuc3VwcG9ydGVkRXJyb3IsXG4gIFJlcG9zaXRvcnksXG4gIENvbnRleHRPZixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBhZnRlckNyZWF0ZSxcbiAgYWZ0ZXJEZWxldGUsXG4gIGFmdGVyVXBkYXRlLFxuICBnZW5lcmF0ZWQsXG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIG9uQ3JlYXRlLFxuICBvbkRlbGV0ZSxcbiAgb25SZWFkLFxuICBvblVwZGF0ZSxcbiAgcmVhZG9ubHksXG4gIHRyYW5zaWVudCxcbiAgVmFsaWRhdGlvbkVycm9yLFxuICBEQktleXMsXG4gIERCT3BlcmF0aW9ucyxcbiAgb24sXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljTW9kZWxLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSExDb250ZXh0IH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IENsaWVudElkZW50aXR5IH0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuaW1wb3J0IHsgRmFicmljRVJDMjBDb250cmFjdCB9IGZyb20gXCIuLi9jb250cmFjdHMvZXJjMjAvZXJjMjBjb250cmFjdFwiO1xuaW1wb3J0IHtcbiAgYXBwbHksXG4gIENvbnN0cnVjdG9yLFxuICBEZWNvcmF0aW9uLFxuICBtZXRhZGF0YSxcbiAgTWV0YWRhdGEsXG4gIHByb3AsXG4gIHByb3BNZXRhZGF0YSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyB0b1Bhc2NhbENhc2UgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0RmxhZ3MgfSBmcm9tIFwiLi4vY29udHJhY3RzL3R5cGVzXCI7XG5pbXBvcnQgXCIuLi9zaGFyZWQvb3ZlcnJpZGVzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi4vY29udHJhY3RzL2luZGV4XCI7XG5cbmNvbnN0IE1JUlJPUl9TS0lQX0ZMQUdfUFJFRklYID0gXCJtaXJyb3I6c2tpcDpcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXh0cmFjdHMgdGhlIE1TUCBJRCBmcm9tIGVpdGhlciBhIHN0cmluZyBvciBDbGllbnRJZGVudGl0eSBvYmplY3RcbiAqIEBwYXJhbSBpZGVudGl0eSAtIFRoZSBpZGVudGl0eSB2YWx1ZSB3aGljaCBjYW4gYmUgYSBzdHJpbmcgTVNQIElEIG9yIENsaWVudElkZW50aXR5IG9iamVjdFxuICogQHJldHVybnMgVGhlIE1TUCBJRCBhcyBhIHN0cmluZywgb3IgdW5kZWZpbmVkIGlmIG5vdCBhdmFpbGFibGVcbiAqL1xuZnVuY3Rpb24gZXh0cmFjdE1zcElkKFxuICBpZGVudGl0eTogc3RyaW5nIHwgQ2xpZW50SWRlbnRpdHkgfCB1bmRlZmluZWRcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghaWRlbnRpdHkpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmICh0eXBlb2YgaWRlbnRpdHkgPT09IFwic3RyaW5nXCIpIHJldHVybiBpZGVudGl0eTtcbiAgcmV0dXJuIGlkZW50aXR5LmdldE1TUElEKCk7XG59XG5cbi8qKlxuICogRGVjb3JhdG9yIGZvciBtYXJraW5nIG1ldGhvZHMgdGhhdCByZXF1aXJlIG93bmVyc2hpcCBhdXRob3JpemF0aW9uLlxuICogQ2hlY2tzIHRoZSBvd25lciBvZiB0aGUgdG9rZW4gYmVmb3JlIGFsbG93aW5nIHRoZSBtZXRob2QgdG8gYmUgZXhlY3V0ZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNsYXNzIFRva2VuQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7XG4gKiAgIEBPd25lcigpXG4gKiAgIGFzeW5jIE1pbnQoY3R4OiBDb250ZXh0LCBhbW91bnQ6IG51bWJlcikge1xuICogICAgIC8vIE1pbnQgdG9rZW4gbG9naWNcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQHJldHVybnMge01ldGhvZERlY29yYXRvcn0gQSBtZXRob2QgZGVjb3JhdG9yIHRoYXQgY2hlY2tzIG93bmVyc2hpcCBhdXRob3JpemF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT3duZXIoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoXG4gICAgdGFyZ2V0OiBhbnksXG4gICAgcHJvcGVydHlLZXk6IHN0cmluZyxcbiAgICBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3JcbiAgKSB7XG4gICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgZGVzY3JpcHRvci52YWx1ZSA9IGFzeW5jIGZ1bmN0aW9uIChcbiAgICAgIHRoaXM6IEZhYnJpY0VSQzIwQ29udHJhY3QsXG4gICAgICAuLi5hcmdzOiBhbnlbXVxuICAgICkge1xuICAgICAgY29uc3QgY3R4OiBITENvbnRleHQgPSBhcmdzWzBdO1xuICAgICAgY29uc3QgYWNvdW50SWQgPSBjdHguY2xpZW50SWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgICAgY29uc3Qgc2VsZWN0ID0gYXdhaXQgKHRoaXMgYXMgRmFicmljRVJDMjBDb250cmFjdClbXG4gICAgICAgIFwidG9rZW5SZXBvc2l0b3J5XCJcbiAgICAgIF0uc2VsZWN0KCk7XG5cbiAgICAgIGNvbnN0IHRva2VucyA9IGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCk7XG5cbiAgICAgIGlmICh0b2tlbnMubGVuZ3RoID09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXCJObyB0b2tlbnMgYXZhaWFsYmxlXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAodG9rZW5zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoYFRvIG1hbnkgdG9rZW4gYXZhaWxhYmxlIDogJHt0b2tlbnMubGVuZ3RofWApO1xuICAgICAgfVxuXG4gICAgICBpZiAodG9rZW5zWzBdLm93bmVyICE9IGFjb3VudElkKSB7XG4gICAgICAgIHRocm93IG5ldyBBdXRob3JpemF0aW9uRXJyb3IoXG4gICAgICAgICAgYFVzZXIgbm90IGF1dGhvcml6ZWQgdG8gcnVuICR7cHJvcGVydHlLZXl9IG9uIHRoZSB0b2tlbmBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF3YWl0IG9yaWdpbmFsTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH07XG5cbiAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG93bmVkQnlPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsPGJvb2xlYW4+LFxuICBSIGV4dGVuZHMgUmVwbzxNPixcbiAgVixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHRPZjxSPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc3R1YiB9ID0gY29udGV4dCBhcyBhbnk7XG5cbiAgY29uc3QgY3JlYXRvciA9IGF3YWl0IHN0dWIuZ2V0Q3JlYXRvcigpO1xuICBjb25zdCBvd25lciA9IGNyZWF0b3IubXNwaWQ7XG5cbiAgY29uc3Qgc2V0T3duZWRCeUtleVZhbHVlID0gZnVuY3Rpb24gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFyZ2V0OiBNLFxuICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludFxuICApIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBwcm9wZXJ0eUtleSwge1xuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICB9KTtcbiAgfTtcblxuICBzZXRPd25lZEJ5S2V5VmFsdWUobW9kZWwsIGtleSBhcyBzdHJpbmcsIG93bmVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG93bmVkQnkoKSB7XG4gIGZ1bmN0aW9uIG93bmVkQnkoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChvYmo6IGFueSwgYXR0cmlidXRlPzogYW55KSB7XG4gICAgICByZXR1cm4gYXBwbHkoXG4gICAgICAgIHJlcXVpcmVkKCksXG4gICAgICAgIGdlbmVyYXRlZCgpLFxuICAgICAgICByZWFkb25seSgpLFxuICAgICAgICBvbkNyZWF0ZShvd25lZEJ5T25DcmVhdGUpLFxuICAgICAgICBwcm9wTWV0YWRhdGEoXG4gICAgICAgICAgTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsIEZhYnJpY01vZGVsS2V5cy5PV05FRF9CWSksXG4gICAgICAgICAgYXR0cmlidXRlXG4gICAgICAgIClcbiAgICAgICkob2JqLCBhdHRyaWJ1dGUpO1xuICAgIH07XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLk9XTkVEX0JZKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiBvd25lZEJ5LFxuICAgICAgYXJnczogW10sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWRPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsPGJvb2xlYW4+LFxuICBSIGV4dGVuZHMgUmVwbzxNPixcbiAgVixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHRPZjxSPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc3R1YiB9ID0gY29udGV4dCBhcyBhbnk7XG4gIG1vZGVsW2tleV0gPSBzdHViLmdldFR4SUQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWQoKSB7XG4gIGZ1bmN0aW9uIHRyYW5zYWN0aW9uSWQoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChvYmo6IGFueSwgYXR0cmlidXRlPzogYW55KSB7XG4gICAgICByZXR1cm4gYXBwbHkoXG4gICAgICAgIHJlcXVpcmVkKCksXG4gICAgICAgIHJlYWRvbmx5KCksXG4gICAgICAgIG9uQ3JlYXRlKHRyYW5zYWN0aW9uSWRPbkNyZWF0ZSksXG4gICAgICAgIG9uVXBkYXRlKHRyYW5zYWN0aW9uSWRPbkNyZWF0ZSksXG4gICAgICAgIHByb3BNZXRhZGF0YShcbiAgICAgICAgICBNZXRhZGF0YS5rZXkoXG4gICAgICAgICAgICBGYWJyaWNNb2RlbEtleXMuRkFCUklDLFxuICAgICAgICAgICAgYXR0cmlidXRlLFxuICAgICAgICAgICAgRmFicmljTW9kZWxLZXlzLlRSQU5TQUNUSU9OX0lEXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhdHRyaWJ1dGVcbiAgICAgICAgKVxuICAgICAgKShvYmosIGF0dHJpYnV0ZSk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuVFJBTlNBQ1RJT05fSUQpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IHRyYW5zYWN0aW9uSWQsXG4gICAgICBhcmdzOiBbXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgdHlwZSBNaXJyb3JDb25kaXRpb24gPSAobXNwOiBzdHJpbmcpID0+IGJvb2xlYW47XG5cbmV4cG9ydCB0eXBlIE1pcnJvck1ldGFkYXRhID0ge1xuICBjb25kaXRpb246IE1pcnJvckNvbmRpdGlvbjtcbiAgcmVzb2x2ZXI6IENvbGxlY3Rpb25SZXNvbHZlciB8IHN0cmluZztcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBldmFsTWlycm9yTWV0YWRhdGE8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHJlc29sdmVyOiB1bmRlZmluZWQgfCBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIsXG4gIGN0eDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPlxuKSB7XG4gIGxldCBjb2xsZWN0aW9uOiBDb2xsZWN0aW9uUmVzb2x2ZXIgfCBzdHJpbmcgfCB1bmRlZmluZWQgPSByZXNvbHZlcjtcbiAgaWYgKHR5cGVvZiBjb2xsZWN0aW9uICE9PSBcInN0cmluZ1wiKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG93bmVyID1cbiAgICAgICAgTW9kZWwub3duZXJPZihtb2RlbCkgfHwgY3R4LmdldChcInN0dWJcIikuZ2V0Q3JlYXRvcigpLnRvU3RyaW5nKCk7XG4gICAgICBpZiAocmVzb2x2ZXIgJiYgdHlwZW9mIHJlc29sdmVyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIGNvbGxlY3Rpb24gPSBhd2FpdCByZXNvbHZlcihtb2RlbCwgb3duZXIsIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEZhaWxlZCB0byByZXNvbHZlIGNvbGxlY3Rpb24gbWlycm9yIG5hbWU6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIWNvbGxlY3Rpb24gfHwgdHlwZW9mIGNvbGxlY3Rpb24gIT09IFwic3RyaW5nXCIpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTm8gY29sbGVjdGlvbiBmb3VuZCBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICk7XG4gIHJldHVybiBjb2xsZWN0aW9uO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlTWlycm9ySGFuZGxlcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwb3NpdG9yeTxNLCBhbnk+LFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPixcbiAgZGF0YTogTWlycm9yTWV0YWRhdGEsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjb2xsZWN0aW9uID0gYXdhaXQgZXZhbE1pcnJvck1ldGFkYXRhKG1vZGVsLCBkYXRhLnJlc29sdmVyLCBjb250ZXh0KTtcbiAgY29uc3QgcmVwbyA9IHRoaXMub3ZlcnJpZGUoXG4gICAgT2JqZWN0LmFzc2lnbih7fSwgKHRoaXMgYXMgYW55KS5fb3ZlcnJpZGVzLCB7XG4gICAgICBzZWdyZWdhdGVkOiBjb2xsZWN0aW9uLFxuICAgICAgbWlycm9yOiB0cnVlLFxuICAgICAgaWdub3JlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICAgIGlnbm9yZUhhbmRsZXJzOiB0cnVlLFxuICAgIH0gYXMgYW55KVxuICApO1xuICBjb25zdCBtaXJyb3IgPSBhd2FpdCByZXBvLmNyZWF0ZShtb2RlbCwgY29udGV4dCk7XG4gIGNvbnRleHQubG9nZ2VyLmluZm8oXG4gICAgYE1pcnJvciBmb3IgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IGNyZWF0ZWQgd2l0aCAke01vZGVsLnBrKG1vZGVsKSBhcyBzdHJpbmd9OiAke21pcnJvcltNb2RlbC5wayhtb2RlbCldfWBcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZU1pcnJvckhhbmRsZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55Pixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IE1pcnJvck1ldGFkYXRhLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29sbGVjdGlvbiA9IGF3YWl0IGV2YWxNaXJyb3JNZXRhZGF0YShtb2RlbCwgZGF0YS5yZXNvbHZlciwgY29udGV4dCk7XG4gIGNvbnN0IHJlcG8gPSB0aGlzLm92ZXJyaWRlKFxuICAgIE9iamVjdC5hc3NpZ24oe30sICh0aGlzIGFzIGFueSkuX292ZXJyaWRlcywge1xuICAgICAgc2VncmVnYXRlZDogY29sbGVjdGlvbixcbiAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgIGlnbm9yZVZhbGlkYXRpb246IHRydWUsXG4gICAgICBpZ25vcmVIYW5kbGVyczogdHJ1ZSxcbiAgICAgIGFwcGx5VXBkYXRlVmFsaWRhdGlvbjogZmFsc2UsXG4gICAgICBtZXJnZUZvclVwZGF0ZTogZmFsc2UsXG4gICAgfSBhcyBhbnkpXG4gICk7XG4gIGF3YWl0IHJlcG8udXBkYXRlKG1vZGVsLCBjb250ZXh0KTtcbiAgY29udGV4dC5sb2dnZXIuaW5mbyhcbiAgICBgTWlycm9yIGZvciAke01vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKX0gdXBkYXRlZDogJHsobW9kZWwgYXMgYW55KVtNb2RlbC5wayhtb2RlbCldfWBcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZU1pcnJvckhhbmRsZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55Pixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IE1pcnJvck1ldGFkYXRhLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29sbGVjdGlvbiA9IGF3YWl0IGV2YWxNaXJyb3JNZXRhZGF0YShtb2RlbCwgZGF0YS5yZXNvbHZlciwgY29udGV4dCk7XG4gIGNvbnN0IHBrUHJvcCA9IE1vZGVsLnBrKG1vZGVsKSBhcyBrZXlvZiBNO1xuICBjb25zdCBpZCA9IG1vZGVsW3BrUHJvcF07XG4gIGNvbnN0IHJlcG8gPSB0aGlzLm92ZXJyaWRlKFxuICAgIE9iamVjdC5hc3NpZ24oe30sICh0aGlzIGFzIGFueSkuX292ZXJyaWRlcywge1xuICAgICAgc2VncmVnYXRlZDogY29sbGVjdGlvbixcbiAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgIGlnbm9yZVZhbGlkYXRpb246IHRydWUsXG4gICAgICBpZ25vcmVIYW5kbGVyczogdHJ1ZSxcbiAgICB9IGFzIGFueSlcbiAgKTtcbiAgdHJ5IHtcbiAgICBhd2FpdCByZXBvLmRlbGV0ZShpZCBhcyBhbnksIGNvbnRleHQpO1xuICB9IGNhdGNoIHtcbiAgICAvLyBNYXkgYWxyZWFkeSBiZSBkZWxldGVkIGJ5IGFkYXB0ZXIuZGVsZXRlU2VncmVnYXRlZENvbGxlY3Rpb25zXG4gIH1cbiAgY29udGV4dC5sb2dnZXIuaW5mbyhcbiAgICBgTWlycm9yIGZvciAke01vZGVsLnRhYmxlTmFtZSh0aGlzLmNsYXNzKX0gZGVsZXRlZDogJHtTdHJpbmcoaWQpfWBcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1pcnJvcldyaXRlR3VhcmQ8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55Pixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IE1pcnJvck1ldGFkYXRhLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgbXNwID0gZXh0cmFjdE1zcElkKFxuICAgIGNvbnRleHQuZ2V0KFwiaWRlbnRpdHlcIikgYXMgc3RyaW5nIHwgQ2xpZW50SWRlbnRpdHkgfCB1bmRlZmluZWRcbiAgKTtcbiAgaWYgKCFtc3ApIHJldHVybjtcbiAgaWYgKGRhdGEuY29uZGl0aW9uKG1zcCkpIHtcbiAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgYE9yZ2FuaXphdGlvbiAke21zcH0gaXMgbm90IGF1dGhvcml6ZWQgdG8gbW9kaWZ5IG1pcnJvcmVkIGRhdGFgXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE1pcnJvckhhbmRsZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55Pixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IE1pcnJvck1ldGFkYXRhLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gR2V0IHRoZSBjdXJyZW50IE1TUCBJRCBmcm9tIHRoZSBjb250ZXh0XG4gIGNvbnN0IG1zcCA9IGV4dHJhY3RNc3BJZChcbiAgICBjb250ZXh0LmdldChcImlkZW50aXR5XCIpIGFzIHN0cmluZyB8IENsaWVudElkZW50aXR5IHwgdW5kZWZpbmVkXG4gICk7XG5cbiAgaWYgKCFtc3ApIHtcbiAgICBjb250ZXh0LmxvZ2dlci5kZWJ1ZyhcbiAgICAgIGBNaXJyb3IgcmVhZDogTm8gTVNQIElEIGF2YWlsYWJsZSwgdXNpbmcgZGVmYXVsdCByZWFkIGJlaGF2aW9yYFxuICAgICk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gRXZhbHVhdGUgdGhlIG1pcnJvciBjb25kaXRpb25cbiAgY29uc3QgY29sbGVjdGlvbiA9IGF3YWl0IGV2YWxNaXJyb3JNZXRhZGF0YShtb2RlbCwgZGF0YS5yZXNvbHZlciwgY29udGV4dCk7XG4gIGNvbnN0IHNraXBGbGFnS2V5ID0gYCR7TUlSUk9SX1NLSVBfRkxBR19QUkVGSVh9JHtjb2xsZWN0aW9ufWA7XG4gIGNvbnN0IGZhYnJpY0N0eCA9IGNvbnRleHQgYXMgRmFicmljQ29udHJhY3RDb250ZXh0O1xuICBjb25zdCBtYXRjaGVzID0gZGF0YS5jb25kaXRpb24obXNwKTtcblxuICBpZiAobWF0Y2hlcykge1xuICAgIGNvbnRleHQubG9nZ2VyLmluZm8oXG4gICAgICBgTWlycm9yIHJlYWQ6IE1TUCAke21zcH0gbWF0Y2hlcyBjb25kaXRpb24sIHJvdXRpbmcgQUxMIHJlYWRzIGV4Y2x1c2l2ZWx5IHRvIGNvbGxlY3Rpb24gJHtjb2xsZWN0aW9ufWBcbiAgICApO1xuXG4gICAgLy8gU2V0IHRoZSBzZWdyZWdhdGVkIGZsYWcgaW4gY29udGV4dCB0byByb3V0ZSBBTEwgcmVhZHMgdG8gdGhlIG1pcnJvciBjb2xsZWN0aW9uXG4gICAgLy8gVGhpcyBlbnN1cmVzIG5vIHJlYWRzIGdvIHRvIHdvcmxkIHN0YXRlIG9yIG90aGVyIGNvbGxlY3Rpb25zXG4gICAgZmFicmljQ3R4LnB1dChcInNlZ3JlZ2F0ZWRcIiwgY29sbGVjdGlvbik7XG4gICAgZmFicmljQ3R4LnJlYWRGcm9tKGNvbGxlY3Rpb24pO1xuICAgIGZhYnJpY0N0eC5wdXQoc2tpcEZsYWdLZXksIGZhbHNlKTtcbiAgfSBlbHNlIHtcbiAgICBmYWJyaWNDdHgucHV0KHNraXBGbGFnS2V5LCB0cnVlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWlycm9yKFxuICBjb2xsZWN0aW9uOiBDb2xsZWN0aW9uUmVzb2x2ZXIgfCBzdHJpbmcsXG4gIGNvbmRpdGlvbjogTWlycm9yQ29uZGl0aW9uXG4pIHtcbiAgZnVuY3Rpb24gbWlycm9yKFxuICAgIHJlc29sdmVyOiBDb2xsZWN0aW9uUmVzb2x2ZXIgfCBzdHJpbmcsXG4gICAgY29uZGl0aW9uOiBNaXJyb3JDb25kaXRpb25cbiAgKSB7XG4gICAgY29uc3QgbWV0YTogTWlycm9yTWV0YWRhdGEgPSB7XG4gICAgICBjb25kaXRpb246IGNvbmRpdGlvbixcbiAgICAgIHJlc29sdmVyOiByZXNvbHZlcixcbiAgICB9O1xuICAgIHJldHVybiBhcHBseShcbiAgICAgIG1ldGFkYXRhKFxuICAgICAgICBNZXRhZGF0YS5rZXkoRmFicmljTW9kZWxLZXlzLkZBQlJJQywgRmFicmljTW9kZWxLZXlzLk1JUlJPUiksXG4gICAgICAgIG1ldGFcbiAgICAgICksXG4gICAgICBwcml2YXRlRGF0YShjb2xsZWN0aW9uKSxcbiAgICAgIC8vIFJlYWQgaGFuZGxlciBydW5zIGVhcmx5IChwcmlvcml0eSAzMCkgdG8gc2V0IHVwIGNvbnRleHQgYmVmb3JlIGFueSByZWFkc1xuICAgICAgb25SZWFkKHJlYWRNaXJyb3JIYW5kbGVyIGFzIGFueSwgbWV0YSwgeyBwcmlvcml0eTogMzAgfSksXG4gICAgICAvLyBXcml0ZSBndWFyZHMg4oCUIHJlamVjdCBtYXRjaGluZyBNU1BzIGJlZm9yZSBhbnkgcHJvY2Vzc2luZ1xuICAgICAgb25DcmVhdGUobWlycm9yV3JpdGVHdWFyZCBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDIwIH0pLFxuICAgICAgb25VcGRhdGUobWlycm9yV3JpdGVHdWFyZCBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDIwIH0pLFxuICAgICAgb25EZWxldGUobWlycm9yV3JpdGVHdWFyZCBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDIwIH0pLFxuICAgICAgLy8gTWlycm9yIHN5bmMgaGFuZGxlcnMg4oCUIHdyaXRlIGZ1bGwgbW9kZWwgQUZURVIgb3BlcmF0aW9uIGNvbXBsZXRlc1xuICAgICAgYWZ0ZXJDcmVhdGUoY3JlYXRlTWlycm9ySGFuZGxlciBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDk1IH0pLFxuICAgICAgYWZ0ZXJVcGRhdGUodXBkYXRlTWlycm9ySGFuZGxlciBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDk1IH0pLFxuICAgICAgYWZ0ZXJEZWxldGUoZGVsZXRlTWlycm9ySGFuZGxlciBhcyBhbnksIG1ldGEsIHsgcHJpb3JpdHk6IDk1IH0pXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuTUlSUk9SKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiBtaXJyb3IsXG4gICAgICBhcmdzOiBbY29sbGVjdGlvbiwgY29uZGl0aW9uXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgdHlwZSBDb2xsZWN0aW9uUmVzb2x2ZXIgPSA8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPixcbiAgbXNwPzogc3RyaW5nLFxuICAuLi5hcmdzOiBhbnlbXVxuKSA9PiBzdHJpbmc7XG5cbmV4cG9ydCBjb25zdCBNb2RlbENvbGxlY3Rpb246IENvbGxlY3Rpb25SZXNvbHZlciA9IDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTSB8IENvbnN0cnVjdG9yPE0+LFxuICBtc3BJZD86IHN0cmluZ1xuKSA9PiB7XG4gIGNvbnN0IG9yZ05hbWUgPVxuICAgIG1zcElkIHx8ICh0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IE1vZGVsLm93bmVyT2YobW9kZWwpIDogdW5kZWZpbmVkKTtcbiAgY29uc3QgY29uc3RyID0gdHlwZW9mIG1vZGVsID09PSBcImZ1bmN0aW9uXCIgPyBtb2RlbCA6IG1vZGVsLmNvbnN0cnVjdG9yO1xuICBpZiAoIW9yZ05hbWUpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTW9kZWwgJHtjb25zdHIubmFtZX0gaXMgbm90IG93bmVkIGJ5IGFueSBvcmdhbml6YXRpb24uIGRpZCB5b3UgdXNlIEBvd25lZEJ5KCkgKG9yIHByb3ZpZGUgdGhlIG5hbWUpP2BcbiAgICApO1xuICByZXR1cm4gYCR7dG9QYXNjYWxDYXNlKGNvbnN0ci5uYW1lKX0ke29yZ05hbWUgPyB0b1Bhc2NhbENhc2Uob3JnTmFtZSkgOiBcIlwifWA7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gTmFtZXNwYWNlQ29sbGVjdGlvbihuYW1lc3BhY2U6IHN0cmluZyk6IENvbGxlY3Rpb25SZXNvbHZlciB7XG4gIHJldHVybiA8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSB8IENvbnN0cnVjdG9yPE0+LCBtc3BJZD86IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IG9yZ05hbWUgPVxuICAgICAgbXNwSWQgfHwgKHR5cGVvZiBtb2RlbCAhPT0gXCJmdW5jdGlvblwiID8gTW9kZWwub3duZXJPZihtb2RlbCkgOiB1bmRlZmluZWQpO1xuICAgIGNvbnN0IGNvbnN0ciA9IHR5cGVvZiBtb2RlbCA9PT0gXCJmdW5jdGlvblwiID8gbW9kZWwgOiBtb2RlbC5jb25zdHJ1Y3RvcjtcbiAgICBpZiAoIW9yZ05hbWUpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYE1vZGVsICR7Y29uc3RyLm5hbWV9IGlzIG5vdCBvd25lZCBieSBhbnkgb3JnYW5pemF0aW9uLiBkaWQgeW91IHVzZSBAb3duZWRCeSgpIChvciBwcm92aWRlIHRoZSBuYW1lKT9gXG4gICAgICApO1xuICAgIHJldHVybiBgJHtuYW1lc3BhY2V9JHtvcmdOYW1lID8gdG9QYXNjYWxDYXNlKG9yZ05hbWUpIDogXCJcIn1gO1xuICB9O1xufVxuXG5leHBvcnQgY29uc3QgSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvbjogQ29sbGVjdGlvblJlc29sdmVyID0gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT4sXG4gIG1zcElkPzogc3RyaW5nXG4pID0+IHtcbiAgY29uc3Qgb3JnTmFtZSA9XG4gICAgbXNwSWQgfHwgKHR5cGVvZiBtb2RlbCAhPT0gXCJmdW5jdGlvblwiID8gTW9kZWwub3duZXJPZihtb2RlbCkgOiB1bmRlZmluZWQpO1xuICBpZiAoIW9yZ05hbWUpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBpcyBub3Qgb3duZWQgYnkgYW55IG9yZ2FuaXphdGlvbi4gZGlkIHlvdSB1c2UgQG93bmVkQnkoKSAob3IgcHJvdmlkZSB0aGUgbmFtZSk/YFxuICAgICk7XG4gIHJldHVybiBgX18ke3RvUGFzY2FsQ2FzZShvcmdOYW1lKX1Qcml2YXRlQ29sbGVjdGlvbmA7XG59O1xuXG5leHBvcnQgdHlwZSBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhID0ge1xuICBjb2xsZWN0aW9uczogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUHJpb3JpdHkgZm9yIGVhcmx5IGNvbGxlY3Rpb24gZXh0cmFjdGlvbiAoYmVmb3JlIHBrIGdlbmVyYXRpb24gYXQgcHJpb3JpdHkgNjApXG4gKiBAc3VtbWFyeSBUaGlzIHByaW9yaXR5IGVuc3VyZXMgY29sbGVjdGlvbnMgYXJlIHJlZ2lzdGVyZWQgaW4gY29udGV4dCBiZWZvcmUgYW55IHNlcXVlbmNlXG4gKiBvcGVyYXRpb25zIG9jY3VyLCBhbGxvd2luZyBzZXF1ZW5jZXMgdG8gYmUgcmVwbGljYXRlZCB0byBwcml2YXRlL3NoYXJlZCBjb2xsZWN0aW9ucy5cbiAqL1xuZXhwb3J0IGNvbnN0IFNFR1JFR0FURURfQ09MTEVDVElPTl9FWFRSQUNUSU9OX1BSSU9SSVRZID0gMzU7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVhcmx5IGhhbmRsZXIgdG8gZXh0cmFjdCBhbmQgcmVnaXN0ZXIgY29sbGVjdGlvbnMgaW4gY29udGV4dFxuICogQHN1bW1hcnkgUnVucyB3aXRoIHByaW9yaXR5IDwgNDAgdG8gZXh0cmFjdCBjb2xsZWN0aW9uIG5hbWVzIGJlZm9yZSBwayBnZW5lcmF0aW9uIChwcmlvcml0eSA2MCkuXG4gKiBUaGlzIGFsbG93cyBGYWJyaWNDb250cmFjdFNlcXVlbmNlIHRvIGtub3cgd2hpY2ggY29sbGVjdGlvbnMgdG8gcmVwbGljYXRlIHRvLlxuICogQHRlbXBsYXRlIE0gLSBUeXBlIHRoYXQgZXh0ZW5kcyBNb2RlbFxuICogQHBhcmFtIHtDb250ZXh0T2Y8UmVwb3NpdG9yeTxNLCBhbnk+Pn0gY29udGV4dCAtIFRoZSBleGVjdXRpb24gY29udGV4dFxuICogQHBhcmFtIHtTZWdyZWdhdGVkRGF0YU1ldGFkYXRhIHwgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdfSBkYXRhIC0gVGhlIHNlZ3JlZ2F0ZWQgZGF0YSBtZXRhZGF0YVxuICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0ga2V5cyAtIFRoZSBwcm9wZXJ0eSBrZXkocykgYmVpbmcgc2VncmVnYXRlZFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4dHJhY3RTZWdyZWdhdGVkQ29sbGVjdGlvbnM8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0T2Y8dHlwZW9mIHRoaXM+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhIHwgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXlzOiBrZXlvZiBNIHwgKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZGF0YUFycmF5ID0gKFxuICAgIEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogW2RhdGFdXG4gICkgYXMgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdO1xuXG4gIGNvbnN0IG1zcCA9XG4gICAgTW9kZWwub3duZXJPZihtb2RlbCkgfHxcbiAgICBleHRyYWN0TXNwSWQoXG4gICAgICBjb250ZXh0LmdldChcImlkZW50aXR5XCIpIGFzIHN0cmluZyB8IENsaWVudElkZW50aXR5IHwgdW5kZWZpbmVkXG4gICAgKTtcbiAgaWYgKCFtc3ApIHtcbiAgICAvLyBDYW4ndCBleHRyYWN0IGNvbGxlY3Rpb25zIHdpdGhvdXQgTVNQLCB3aWxsIGJlIGNhdWdodCBieSBsYXRlciBoYW5kbGVyc1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGNvbGxlY3Rpb25zOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IG1ldGFkYXRhIG9mIGRhdGFBcnJheSkge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IG1ldGFkYXRhLmNvbGxlY3Rpb25zO1xuICAgIGNvbnN0IGNvbGxlY3Rpb24gPVxuICAgICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IGNvbGxlY3Rpb25SZXNvbHZlclxuICAgICAgICA6IGNvbGxlY3Rpb25SZXNvbHZlcihtb2RlbCwgbXNwLCBjb250ZXh0KTtcbiAgICBpZiAoY29sbGVjdGlvbiAmJiAhY29sbGVjdGlvbnMuaW5jbHVkZXMoY29sbGVjdGlvbikpIHtcbiAgICAgIGNvbGxlY3Rpb25zLnB1c2goY29sbGVjdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVnaXN0ZXIgY29sbGVjdGlvbnMgZWFybHkgdXNpbmcgcmVhZEZyb20gLSB0aGlzIGFsbG93cyBzZXF1ZW5jZSBjb2RlXG4gIC8vIHRvIGtub3cgd2hpY2ggY29sbGVjdGlvbnMgdG8gcmVwbGljYXRlIHRvIGR1cmluZyBwayBnZW5lcmF0aW9uXG4gIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgKGNvbnRleHQgYXMgRmFicmljQ29udHJhY3RDb250ZXh0KS5yZWFkRnJvbShjb2xsZWN0aW9ucyk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBtb2RlbCBpcyBmdWxseSBzZWdyZWdhdGVkIChhbGwgbm9uLXBrIHByb3BlcnRpZXMgYXJlIHByaXZhdGUvc2hhcmVkL3RyYW5zaWVudCkuXG4gIC8vIFVzZSBNb2RlbC5zZWdyZWdhdGUoKSB3aGljaCBpcyB0aGUgY2Fub25pY2FsIHdheSB0byBkZXRlcm1pbmUgd2hhdCdzIHRyYW5zaWVudCxcbiAgLy8gcmF0aGVyIHRoYW4gcmVhZGluZyBEQktleXMuVFJBTlNJRU5UIG1ldGFkYXRhIHdoaWNoIG1heSBub3QgYWNjdW11bGF0ZSBjb3JyZWN0bHlcbiAgLy8gd2hlbiBjbGFzcy1sZXZlbCBAcHJpdmF0ZURhdGEgYXBwbGllcyBkZWNvcmF0b3JzIGl0ZXJhdGl2ZWx5LlxuICBjb25zdCBmYWJyaWNDdHggPSBjb250ZXh0IGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcbiAgaWYgKCFmYWJyaWNDdHguaXNGdWxseVNlZ3JlZ2F0ZWQpIHtcbiAgICBjb25zdCBwa1Byb3AgPSBNb2RlbC5wayhtb2RlbCkgYXMgc3RyaW5nO1xuICAgIGNvbnN0IHNlZ3JlZ2F0ZWQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuICAgIGNvbnN0IHB1YmxpY0tleXMgPSBPYmplY3Qua2V5cyhzZWdyZWdhdGVkLm1vZGVsKS5maWx0ZXIoXG4gICAgICAoaykgPT4gayAhPT0gcGtQcm9wICYmIChzZWdyZWdhdGVkLm1vZGVsIGFzIGFueSlba10gIT09IHVuZGVmaW5lZFxuICAgICk7XG4gICAgaWYgKHB1YmxpY0tleXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBmYWJyaWNDdHgubWFya0Z1bGx5U2VncmVnYXRlZCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFN0b3JlIHNlZ3JlZ2F0aW9uIG1ldGFkYXRhIG9uIHRoZSBhZGFwdGVyIChwZXJzaXN0cyBhY3Jvc3MgY29udGV4dCBjaGFpbnMpLlxuICAvLyBUaGUgU2VxdWVuY2UgY3JlYXRlcyBpdHMgb3duIGNvbnRleHQgdmlhIGxvZ0N0eCwgbG9zaW5nIGNvbnRleHQtc3RvcmVkIGZsYWdzLlxuICBjb25zdCBhZGFwdGVyID0gKHRoaXMgYXMgYW55KS5hZGFwdGVyIGFzIGFueTtcbiAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yPE0+KTtcbiAgY29uc3Qgc2VxTmFtZSA9IGAke3RhYmxlTmFtZX1fcGtgO1xuICBhZGFwdGVyLnNldFNlcXVlbmNlU2VncmVnYXRpb24oXG4gICAgc2VxTmFtZSxcbiAgICBmYWJyaWNDdHguaXNGdWxseVNlZ3JlZ2F0ZWQsXG4gICAgY29sbGVjdGlvbnNcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0T2Y8dHlwZW9mIHRoaXM+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhIHwgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXlzOiBrZXlvZiBNIHwgKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZGF0YUFycmF5ID0gKFxuICAgIEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogW2RhdGFdXG4gICkgYXMgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdO1xuICBjb25zdCBrZXlBcnJheSA9IChBcnJheS5pc0FycmF5KGtleXMpID8ga2V5cyA6IFtrZXlzXSkgYXMgKGtleW9mIE0pW107XG4gIGlmIChrZXlBcnJheS5sZW5ndGggIT09IGRhdGFBcnJheS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IG1zcCA9XG4gICAgTW9kZWwub3duZXJPZihtb2RlbCkgfHxcbiAgICBleHRyYWN0TXNwSWQoXG4gICAgICBjb250ZXh0LmdldChcImlkZW50aXR5XCIpIGFzIHN0cmluZyB8IENsaWVudElkZW50aXR5IHwgdW5kZWZpbmVkXG4gICAgKTtcbiAgaWYgKCFtc3ApXG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIGBUaGVyZSdzIG5vIGFzc2lnbmVkIG9yZ2FuaXphdGlvbiBmb3IgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICApO1xuXG4gIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IGRhdGFBcnJheVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogY29sbGVjdGlvblJlc29sdmVyKG1vZGVsLCBtc3AsIGNvbnRleHQpO1xuXG4gIC8vIFZhbGlkYXRlIGFsbCBrZXlzIHJlc29sdmUgdG8gdGhlIHNhbWUgY29sbGVjdGlvblxuICBrZXlBcnJheS5mb3JFYWNoKChfaywgaSkgPT4ge1xuICAgIGNvbnN0IGMgPVxuICAgICAgdHlwZW9mIGRhdGFBcnJheVtpXS5jb2xsZWN0aW9ucyA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IGRhdGFBcnJheVtpXS5jb2xsZWN0aW9uc1xuICAgICAgICA6IGRhdGFBcnJheVtpXS5jb2xsZWN0aW9ucyhtb2RlbCwgbXNwLCBjb250ZXh0KTtcbiAgICBpZiAoYyAhPT0gY29sbGVjdGlvbilcbiAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICBgU2VncmVnYXRlZCBkYXRhIGNvbGxlY3Rpb24gbWlzbWF0Y2g6ICR7Y30gdnMgJHtjb2xsZWN0aW9ufWBcbiAgICAgICk7XG4gIH0pO1xuXG4gIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBtb2RlbCDigJQgcHJlcGFyZSgpIHdpbGwgZmlsdGVyIHRvIGNvbGxlY3Rpb24tc3BlY2lmaWMgZmllbGRzXG4gIChjb250ZXh0IGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dCkud3JpdGVUbyhjb2xsZWN0aW9uLCBtb2RlbCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uUmVhZDxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljRmxhZ3M+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhIHwgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXlzOiBrZXlvZiBNIHwgKGtleW9mIE0pW10sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZGF0YUFycmF5ID0gKFxuICAgIEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogW2RhdGFdXG4gICkgYXMgU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdO1xuICBjb25zdCBrZXlBcnJheSA9IChBcnJheS5pc0FycmF5KGtleXMpID8ga2V5cyA6IFtrZXlzXSkgYXMgKGtleW9mIE0pW107XG4gIGlmIChrZXlBcnJheS5sZW5ndGggIT09IGRhdGFBcnJheS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IG1zcCA9IE1vZGVsLm93bmVyT2YobW9kZWwpIHx8IGV4dHJhY3RNc3BJZChjb250ZXh0LmdldChcImlkZW50aXR5XCIpKTtcbiAgaWYgKCFtc3ApXG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIGBUaGVyZSdzIG5vIGFzc2lnbmVkIG9yZ2FuaXphdGlvbiBmb3IgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICApO1xuXG4gIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IGRhdGFBcnJheVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogYXdhaXQgY29sbGVjdGlvblJlc29sdmVyKG1vZGVsLCBtc3AsIGNvbnRleHQpO1xuXG4gIGNvbnN0IHNraXBGbGFnS2V5ID0gYCR7TUlSUk9SX1NLSVBfRkxBR19QUkVGSVh9JHtjb2xsZWN0aW9ufWA7XG4gIGNvbnN0IGZhYnJpY0N0eCA9IGNvbnRleHQgYXMgRmFicmljQ29udHJhY3RDb250ZXh0O1xuICBpZiAoZmFicmljQ3R4LmdldE9yVW5kZWZpbmVkKHNraXBGbGFnS2V5IGFzIGFueSkpIHJldHVybjtcblxuICAoY29udGV4dCBhcyBGYWJyaWNDb250cmFjdENvbnRleHQpLnJlYWRGcm9tKGNvbGxlY3Rpb24pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPblVwZGF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHRPZjx0eXBlb2YgdGhpcz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGEgfCBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW10sXG4gIGtleToga2V5b2YgTSB8IChrZXlvZiBNKVtdLFxuICBtb2RlbDogTSxcbiAgb2xkTW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBkYXRhQXJyYXkgPSAoXG4gICAgQXJyYXkuaXNBcnJheShkYXRhKSA/IGRhdGEgOiBbZGF0YV1cbiAgKSBhcyBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW107XG4gIGNvbnN0IGtleUFycmF5ID0gKEFycmF5LmlzQXJyYXkoa2V5KSA/IGtleSA6IFtrZXldKSBhcyAoa2V5b2YgTSlbXTtcbiAgaWYgKGtleUFycmF5Lmxlbmd0aCAhPT0gZGF0YUFycmF5Lmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBTZWdyZWdhdGVkIGRhdGEga2V5cyBhbmQgbWV0YWRhdGEgbGVuZ3RoIG1pc21hdGNoYFxuICAgICk7XG5cbiAgY29uc3QgbXNwID1cbiAgICBNb2RlbC5vd25lck9mKG1vZGVsKSB8fFxuICAgIGV4dHJhY3RNc3BJZChcbiAgICAgIGNvbnRleHQuZ2V0KFwiaWRlbnRpdHlcIikgYXMgc3RyaW5nIHwgQ2xpZW50SWRlbnRpdHkgfCB1bmRlZmluZWRcbiAgICApO1xuICBpZiAoIW1zcClcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgYFRoZXJlJ3Mgbm8gYXNzaWduZWQgb3JnYW5pemF0aW9uIGZvciBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICk7XG5cbiAgY29uc3QgY29sbGVjdGlvblJlc29sdmVyID0gZGF0YUFycmF5WzBdLmNvbGxlY3Rpb25zO1xuICBjb25zdCBjb2xsZWN0aW9uID1cbiAgICB0eXBlb2YgY29sbGVjdGlvblJlc29sdmVyID09PSBcInN0cmluZ1wiXG4gICAgICA/IGNvbGxlY3Rpb25SZXNvbHZlclxuICAgICAgOiBjb2xsZWN0aW9uUmVzb2x2ZXIobW9kZWwsIG1zcCwgY29udGV4dCk7XG5cbiAga2V5QXJyYXkuZm9yRWFjaCgoaywgaSkgPT4ge1xuICAgIGNvbnN0IGMgPVxuICAgICAgdHlwZW9mIGRhdGFBcnJheVtpXS5jb2xsZWN0aW9ucyA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IGRhdGFBcnJheVtpXS5jb2xsZWN0aW9uc1xuICAgICAgICA6IGRhdGFBcnJheVtpXS5jb2xsZWN0aW9ucyhtb2RlbCwgbXNwLCBjb250ZXh0KTtcbiAgICBpZiAoYyAhPT0gY29sbGVjdGlvbilcbiAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICBgU2VncmVnYXRlZCBkYXRhIGNvbGxlY3Rpb24gbWlzbWF0Y2g6ICR7Y30gdnMgJHtjb2xsZWN0aW9ufWBcbiAgICAgICk7XG4gIH0pO1xuXG4gIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBtb2RlbCDigJQgcHJlcGFyZSgpIHdpbGwgZmlsdGVyIHRvIGNvbGxlY3Rpb24tc3BlY2lmaWMgZmllbGRzXG4gIChjb250ZXh0IGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dCkud3JpdGVUbyhjb2xsZWN0aW9uLCBtb2RlbCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uRGVsZXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIFYgZXh0ZW5kcyBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dE9mPFI+LFxuICBkYXRhOiBWIHwgVltdLFxuICBrZXk6IChrZXlvZiBNKVtdLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGRhdGFBcnJheSA9IChBcnJheS5pc0FycmF5KGRhdGEpID8gZGF0YSA6IFtkYXRhXSkgYXMgVltdO1xuICBjb25zdCBrZXlBcnJheSA9IChBcnJheS5pc0FycmF5KGtleSkgPyBrZXkgOiBba2V5XSkgYXMgKGtleW9mIE0pW107XG4gIGlmIChrZXlBcnJheS5sZW5ndGggIT09IGRhdGFBcnJheS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IG1zcCA9XG4gICAgTW9kZWwub3duZXJPZihtb2RlbCkgfHxcbiAgICBleHRyYWN0TXNwSWQoXG4gICAgICBjb250ZXh0LmdldChcImlkZW50aXR5XCIpIGFzIHN0cmluZyB8IENsaWVudElkZW50aXR5IHwgdW5kZWZpbmVkXG4gICAgKTtcbiAgaWYgKCFtc3ApXG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIGBUaGVyZSdzIG5vIGFzc2lnbmVkIG9yZ2FuaXphdGlvbiBmb3IgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICApO1xuXG4gIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IGRhdGFBcnJheVswXS5jb2xsZWN0aW9ucztcbiAgY29uc3QgY29sbGVjdGlvbiA9XG4gICAgdHlwZW9mIGNvbGxlY3Rpb25SZXNvbHZlciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBjb2xsZWN0aW9uUmVzb2x2ZXJcbiAgICAgIDogY29sbGVjdGlvblJlc29sdmVyKG1vZGVsLCBtc3AsIGNvbnRleHQpO1xuXG4gIChjb250ZXh0IGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dCkucmVhZEZyb20oY29sbGVjdGlvbik7XG59XG5cbmZ1bmN0aW9uIHNlZ3JlZ2F0ZWQoXG4gIGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcixcbiAgdHlwZTogRmFicmljTW9kZWxLZXlzLlBSSVZBVEUgfCBGYWJyaWNNb2RlbEtleXMuU0hBUkVELFxuICBmaWx0ZXI/OiAocHJvcE5hbWU6IHN0cmluZykgPT4gYm9vbGVhblxuKSB7XG4gIHJldHVybiBmdW5jdGlvbiBpbm5lclNlZ3JlZ2F0ZWQodGFyZ2V0OiBvYmplY3QsIHByb3BlcnR5S2V5PzogYW55KSB7XG4gICAgZnVuY3Rpb24gc2VncmVnYXRlZERlYyh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpIHtcbiAgICAgIGNvbnN0IGtleSA9IE1ldGFkYXRhLmtleSh0eXBlLCBwcm9wZXJ0eUtleSk7XG4gICAgICBjb25zdCBjb25zdHI6IENvbnN0cnVjdG9yID0gdGFyZ2V0LmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yO1xuXG4gICAgICBjb25zdCBtZXRhID0gTWV0YWRhdGEuZ2V0KGNvbnN0ciBhcyBDb25zdHJ1Y3Rvciwga2V5KSB8fCB7fTtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25zID0gbmV3IFNldChtZXRhLmNvbGxlY3Rpb25zIHx8IFtdKTtcbiAgICAgIGNvbGxlY3Rpb25zLmFkZChjb2xsZWN0aW9uKTtcbiAgICAgIG1ldGEuY29sbGVjdGlvbnMgPSBbLi4uY29sbGVjdGlvbnNdO1xuICAgICAgTWV0YWRhdGEuc2V0KGNvbnN0ciBhcyBDb25zdHJ1Y3Rvciwga2V5LCBtZXRhKTtcblxuICAgICAgY29uc3QgY29uc3RyTWV0YSA9IE1ldGFkYXRhLmdldChjb25zdHIgYXMgQ29uc3RydWN0b3IsIHR5cGUpIHx8IHt9O1xuICAgICAgY29uc3QgY29uc3RyQ29sbGVjdGlvbnMgPSBuZXcgU2V0KGNvbnN0ck1ldGEuY29sbGVjdGlvbnMgfHwgW10pO1xuICAgICAgY29uc3RyQ29sbGVjdGlvbnMuYWRkKGNvbGxlY3Rpb24pO1xuICAgICAgY29uc3RyTWV0YS5jb2xsZWN0aW9ucyA9IFsuLi5jb25zdHJDb2xsZWN0aW9uc107XG4gICAgICBNZXRhZGF0YS5zZXQoY29uc3RyIGFzIENvbnN0cnVjdG9yLCB0eXBlLCBjb25zdHJNZXRhKTtcblxuICAgICAgY29uc3QgdHJhbnNpZW50TWV0YSA9XG4gICAgICAgIE1ldGFkYXRhLmdldChjb25zdHIgYXMgQ29uc3RydWN0b3IsIERCS2V5cy5UUkFOU0lFTlQpIHx8IHt9O1xuICAgICAgY29uc3QgdXBkYXRlZFRyYW5zaWVudE1ldGEgPSB7XG4gICAgICAgIC4uLnRyYW5zaWVudE1ldGEsXG4gICAgICAgIFtwcm9wZXJ0eUtleSBhcyBhbnldOiB7fSxcbiAgICAgIH07XG4gICAgICBNZXRhZGF0YS5zZXQoXG4gICAgICAgIGNvbnN0ciBhcyBDb25zdHJ1Y3RvcixcbiAgICAgICAgREJLZXlzLlRSQU5TSUVOVCxcbiAgICAgICAgdXBkYXRlZFRyYW5zaWVudE1ldGFcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVjczogYW55W10gPSBbXTtcbiAgICBpZiAoIXByb3BlcnR5S2V5KSB7XG4gICAgICAvLyBkZWNvcmF0ZWQgYXQgdGhlIGNsYXNzIGxldmVsXG4gICAgICBjb25zdCBwcm9wZXJ0aWVzID0gTWV0YWRhdGEudmFsaWRhdGFibGVQcm9wZXJ0aWVzKHRhcmdldCBhcyBDb25zdHJ1Y3Rvcik7XG4gICAgICBwcm9wZXJ0aWVzPy5mb3JFYWNoKChwKSA9PiB7XG4gICAgICAgIGlmICghZmlsdGVyIHx8IGZpbHRlcihwKSkge1xuICAgICAgICAgIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgdHlwZSkoKHRhcmdldCBhcyBhbnkpLnByb3RvdHlwZSwgcCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZ3JvdXBOYW1lID1cbiAgICAgICAgdHlwZW9mIGNvbGxlY3Rpb24gPT09IFwic3RyaW5nXCIgPyBjb2xsZWN0aW9uIDogY29sbGVjdGlvbi50b1N0cmluZygpO1xuICAgICAgLy8gVXNlIGRpZmZlcmVudCBncm91cCBuYW1lcyBmb3IgZXh0cmFjdGlvbiB2cyBkYXRhIGhhbmRsZXJzIHRvIHByZXZlbnQgbWVyZ2luZ1xuICAgICAgY29uc3QgZXh0cmFjdEdyb3VwTmFtZSA9IGAke2dyb3VwTmFtZX06ZXh0cmFjdGA7XG4gICAgICBjb25zdCBkYXRhR3JvdXBOYW1lID0gYCR7Z3JvdXBOYW1lfTpkYXRhYDtcbiAgICAgIGNvbnN0IGVhcmx5RXh0cmFjdGlvbk1ldGEgPSB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH07XG4gICAgICBjb25zdCBlYXJseUV4dHJhY3Rpb25Hcm91cFNvcnQgPSB7XG4gICAgICAgIHByaW9yaXR5OiBTRUdSRUdBVEVEX0NPTExFQ1RJT05fRVhUUkFDVElPTl9QUklPUklUWSxcbiAgICAgICAgZ3JvdXA6IGV4dHJhY3RHcm91cE5hbWUsXG4gICAgICB9O1xuICAgICAgZGVjcy5wdXNoKFxuICAgICAgICBwcm9wKCksXG4gICAgICAgIHRyYW5zaWVudCgpLFxuICAgICAgICBzZWdyZWdhdGVkRGVjLFxuICAgICAgICAvLyBFYXJseSBleHRyYWN0aW9uIGhhbmRsZXJzIC0gcnVuIEJFRk9SRSBwayBnZW5lcmF0aW9uIChwcmlvcml0eSA2MClcbiAgICAgICAgLy8gVGhpcyBlbnN1cmVzIGNvbGxlY3Rpb25zIGFyZSByZWdpc3RlcmVkIGluIGNvbnRleHQgZm9yIHNlcXVlbmNlIHJlcGxpY2F0aW9uXG4gICAgICAgIC8vIFdlIHJlZ2lzdGVyIGZvciBlYWNoIG9wZXJhdGlvbiBleHBsaWNpdGx5IHRvIGVuc3VyZSBwcm9wZXIgaGFuZGxlciBsb29rdXBcbiAgICAgICAgb24oXG4gICAgICAgICAgREJPcGVyYXRpb25zLkFMTCxcbiAgICAgICAgICBleHRyYWN0U2VncmVnYXRlZENvbGxlY3Rpb25zIGFzIGFueSxcbiAgICAgICAgICBlYXJseUV4dHJhY3Rpb25NZXRhLFxuICAgICAgICAgIGVhcmx5RXh0cmFjdGlvbkdyb3VwU29ydFxuICAgICAgICApLFxuICAgICAgICAvLyBNYWluIGhhbmRsZXJzIGZvciBzZWdyZWdhdGVkIGRhdGEgb3BlcmF0aW9ucyAocHJpb3JpdHkgOTUpXG4gICAgICAgIG9uQ3JlYXRlKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGUsXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOiBkYXRhR3JvdXBOYW1lLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgICAgb25SZWFkKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25SZWFkIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6IGRhdGFHcm91cE5hbWUsXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvblVwZGF0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uVXBkYXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6IGRhdGFHcm91cE5hbWUsXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvbkRlbGV0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uRGVsZXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6IGRhdGFHcm91cE5hbWUsXG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYXBwbHkoLi4uZGVjcykodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcml2YXRlRGF0YShcbiAgY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyID0gSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvblxuKSB7XG4gIGZ1bmN0aW9uIHByaXZhdGVEYXRhKGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcikge1xuICAgIHJldHVybiBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFKTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuUFJJVkFURSlcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogcHJpdmF0ZURhdGEsXG4gICAgICBhcmdzOiBbY29sbGVjdGlvbl0sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gIGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gICAgcmV0dXJuIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgRmFicmljTW9kZWxLZXlzLlNIQVJFRCk7XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLlNIQVJFRClcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogc2hhcmVkRGF0YSxcbiAgICAgIGFyZ3M6IFtjb2xsZWN0aW9uXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQge1xuICBKU09OU2VyaWFsaXplcixcbiAgTW9kZWwsXG4gIE1vZGVsS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZXRlcm1pbmlzdGljIEpTT04gc2VyaWFsaXplciBmb3IgRmFicmljIG1vZGVsc1xuICogQHN1bW1hcnkgRW5zdXJlcyBzdGFibGUsIGRldGVybWluaXN0aWMgSlNPTiBvdXRwdXQgYnkgc29ydGluZyBvYmplY3Qga2V5cyByZWN1cnNpdmVseSBiZWZvcmUgc3RyaW5naWZpY2F0aW9uLCB3aGljaCBpcyBpbXBvcnRhbnQgZm9yIEZhYnJpYyBlbmRvcnNlbWVudCBhbmQgaGFzaGluZy4gRXh0ZW5kcyBKU09OU2VyaWFsaXplciB0byBwbHVnIGludG8gZXhpc3RpbmcgRGVjYWYgbW9kZWwgc2VyaWFsaXphdGlvbiBmbG93LlxuICogQHRlbXBsYXRlIE0gLSBUaGUgRGVjYWYgTW9kZWwgc3VidHlwZSBzZXJpYWxpemVkIGJ5IHRoaXMgaW5zdGFuY2VcbiAqIEBwYXJhbSB7dm9pZH0gW2NvbnN0cnVjdG9yXSBObyBwdWJsaWMgY29uc3RydWN0b3IgYXJndW1lbnRzXG4gKiBAY2xhc3MgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXJcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBzZXJpYWxpemVyID0gbmV3IERldGVybWluaXN0aWNTZXJpYWxpemVyPE15TW9kZWw+KCk7XG4gKiBjb25zdCBqc29uID0gc2VyaWFsaXplci5zZXJpYWxpemUobW9kZWwpO1xuICogY29uc3QgcmVidWlsdCA9IHNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoanNvbik7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBEUyBhcyBEZXRlcm1pbmlzdGljU2VyaWFsaXplclxuICogICBDYWxsZXItPj5EUzogc2VyaWFsaXplKG1vZGVsKVxuICogICBEUy0+PkRTOiBwcmVTZXJpYWxpemUobW9kZWwpXG4gKiAgIERTLT4+RFM6IHNvcnQta2V5cy1yZWN1cnNpdmVcbiAqICAgRFMtPj5EUzoganNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1xuICogICBEUy0tPj5DYWxsZXI6IHN0cmluZ1xuICogICBDYWxsZXItPj5EUzogZGVzZXJpYWxpemUoc3RyaW5nKVxuICogICBEUy0tPj5DYWxsZXI6IG1vZGVsXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNKSB7XG4gICAgLy8gVE9ETzogbmVzdGVkIHByZXNlcmlhbGl6YXRpb24gKHNvIGluY3JlYXNlIHBlcmZvcm1hbmNlIHdoZW4gZGVzZXJpYWxpemluZylcbiAgICAvLyBUT0RPOiBWZXJpZnkgd2h5IHRoZXJlIGlzIG5vIG1ldGFkYXRhXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgbGV0IG1ldGFkYXRhO1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IE1ldGFkYXRhLm1vZGVsTmFtZShtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3Rvcik7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIG1ldGFkYXRhID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0b1NlcmlhbGl6ZVtNb2RlbEtleXMuQU5DSE9SXSA9IG1ldGFkYXRhIHx8IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG5cbiAgICBjb25zdCBwcmVTZXJpYWxpemUgPSBmdW5jdGlvbiBwcmVTZXJpYWxpemUoXG4gICAgICB0aGlzOiBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxhbnk+LFxuICAgICAgb2JqOiBhbnlcbiAgICApOiBhbnkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSByZXR1cm4gb2JqO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAoKG8pID0+IHByZVNlcmlhbGl6ZS5jYWxsKHNlbGYsIG8pKTtcbiAgICAgIHJldHVybiB0aGlzLnByZVNlcmlhbGl6ZS5jYWxsKHRoaXMsIG9iaik7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgTW9kZWwucmVsYXRpb25zKG1vZGVsKS5mb3JFYWNoKChyKSA9PiB7XG4gICAgICB0b1NlcmlhbGl6ZVtyXSA9IHByZVNlcmlhbGl6ZSh0b1NlcmlhbGl6ZVtyXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRvU2VyaWFsaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJlYnVpbGRzIGEgbW9kZWwgZnJvbSBhIHNlcmlhbGl6YXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQgZmFpbHMgdG8gcGFyc2UgdGhlIHN0cmluZywgb3IgdG8gYnVpbGQgdGhlIG1vZGVsXG4gICAqL1xuICBvdmVycmlkZSBkZXNlcmlhbGl6ZShzdHI6IHN0cmluZyk6IE0ge1xuICAgIGNvbnN0IGRlc2VyaWFsaXphdGlvbiA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBkZXNlcmlhbGl6YXRpb25bTW9kZWxLZXlzLkFOQ0hPUl07XG4gICAgaWYgKCFjbGFzc05hbWUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBjbGFzcyByZWZlcmVuY2UgaW4gc2VyaWFsaXplZCBtb2RlbFwiKTtcbiAgICBjb25zdCBtb2RlbDogTSA9IE1vZGVsLmJ1aWxkKGRlc2VyaWFsaXphdGlvbiwgY2xhc3NOYW1lKSBhcyB1bmtub3duIGFzIE07XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXJpYWxpemUgYSBtb2RlbCBpbnRvIGEgZGV0ZXJtaW5pc3RpYyBKU09OIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBQcmVwYXJlcyB0aGUgbW9kZWwgd2l0aCBwcmVTZXJpYWxpemUsIHNvcnRzIGtleXMgcmVjdXJzaXZlbHksIGFuZCBzdHJpbmdpZmllcyBkZXRlcm1pbmlzdGljYWxseSBmb3Igc3RhYmxlIG9yZGVyaW5nXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gc2VyaWFsaXplXG4gICAqIEByZXR1cm4ge3N0cmluZ30gRGV0ZXJtaW5pc3RpYyBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbFxuICAgKi9cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdHJpbmdpZnkgPSByZXF1aXJlKFwianNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1wiKTtcbiAgICBjb25zdCBzb3J0S2V5c1JlY3Vyc2l2ZSA9IHJlcXVpcmUoXCJzb3J0LWtleXMtcmVjdXJzaXZlXCIpO1xuICAgIHJldHVybiBzdHJpbmdpZnkoc29ydEtleXNSZWN1cnNpdmUodGhpcy5wcmVTZXJpYWxpemUobW9kZWwpKSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBGYWJyaWMgZXZlbnQgbmFtZSBmcm9tIGNvbXBvbmVudHNcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBzdGFuZGFyZGl6ZWQgZXZlbnQgbmFtZSBieSBqb2luaW5nIHRhYmxlLCBldmVudCwgYW5kIG9wdGlvbmFsIG93bmVyIHdpdGggdW5kZXJzY29yZXNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSAtIFRoZSB0YWJsZS9jb2xsZWN0aW9uIG5hbWVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IFtvd25lcl0gLSBPcHRpb25hbCBvd25lciBpZGVudGlmaWVyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgZXZlbnQgbmFtZSBpbiBmb3JtYXQgXCJ0YWJsZV9ldmVudFwiIG9yIFwidGFibGVfZXZlbnRfb3duZXJcIlxuICogQGZ1bmN0aW9uIGdlbmVyYXRlRmFicmljRXZlbnROYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZShcbiAgdGFibGU6IHN0cmluZyxcbiAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcsXG4gIG93bmVyPzogc3RyaW5nXG4pIHtcbiAgY29uc3QgcGFyYW1zID0gW3RhYmxlLCBldmVudF07XG4gIGlmIChvd25lcikgcGFyYW1zLnB1c2gob3duZXIpO1xuICByZXR1cm4gcGFyYW1zLmpvaW4oXCJfXCIpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYSBGYWJyaWMgZXZlbnQgbmFtZSBpbnRvIGl0cyBjb21wb25lbnRzXG4gKiBAc3VtbWFyeSBTcGxpdHMgYW4gZXZlbnQgbmFtZSBieSB1bmRlcnNjb3JlcyBhbmQgZXh0cmFjdHMgdGFibGUsIGV2ZW50LCBhbmQgb3B0aW9uYWwgb3duZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIGV2ZW50IG5hbWUgdG8gcGFyc2VcbiAqIEByZXR1cm4ge3t0YWJsZTogc3RyaW5nLCBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZywgb3duZXI6IHN0cmluZ319IFRoZSBwYXJzZWQgY29tcG9uZW50cyBhcyBhIHN0cnVjdHVyZWQgb2JqZWN0XG4gKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgZXZlbnQgbmFtZSBmb3JtYXQgaXMgaW52YWxpZFxuICogQGZ1bmN0aW9uIHBhcnNlRXZlbnROYW1lXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBQYXJzZXIgYXMgcGFyc2VFdmVudE5hbWVcbiAqICAgQ2FsbGVyLT4+UGFyc2VyOiBwYXJzZUV2ZW50TmFtZShuYW1lKVxuICogICBQYXJzZXItPj5QYXJzZXI6IHNwbGl0IG5hbWUgYnkgXCJfXCJcbiAqICAgYWx0IHBhcnRzIGxlbmd0aCBpbnZhbGlkXG4gKiAgICAgUGFyc2VyLS0+PkNhbGxlcjogdGhyb3cgSW50ZXJuYWxFcnJvclxuICogICBlbHNlXG4gKiAgICAgUGFyc2VyLS0+PkNhbGxlcjogeyB0YWJsZSwgZXZlbnQsIG93bmVyPyB9XG4gKiAgIGVuZFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VFdmVudE5hbWUobmFtZTogc3RyaW5nKToge1xuICB0YWJsZT86IHN0cmluZztcbiAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc7XG4gIG93bmVyPzogc3RyaW5nO1xufSB7XG4gIGNvbnN0IHBhcnRzID0gbmFtZS5zcGxpdChcIl9cIik7XG4gIGlmIChwYXJ0cy5sZW5ndGggPCAyIHx8IHBhcnRzLmxlbmd0aCA+IDMpXG4gICAgcmV0dXJuIHsgdGFibGU6IHVuZGVmaW5lZCwgZXZlbnQ6IG5hbWUsIG93bmVyOiB1bmRlZmluZWQgfTtcbiAgcmV0dXJuIHtcbiAgICB0YWJsZTogcGFydHNbMF0sXG4gICAgZXZlbnQ6IHBhcnRzWzFdLFxuICAgIG93bmVyOiBwYXJ0c1syXSxcbiAgfSBhcyB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZztcbiAgICBvd25lcj86IHN0cmluZztcbiAgfTtcbn1cbiIsImltcG9ydCB7IHN0cmluZ0Zvcm1hdCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IE92ZXJmbG93RXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBPdmVyZmxvdy1zYWZlIGFkZGl0aW9uIG9wZXJhdGlvblxuICogQHN1bW1hcnkgQWRkcyB0d28gbnVtYmVycyBhbmQgdmVyaWZpZXMgbm8gb3ZlcmZsb3cgYnkgcmV2ZXJzZS1jaGVja2luZyB0aGUgb3BlcmFuZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gRmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtudW1iZXJ9IGIgLSBTZWNvbmQgb3BlcmFuZFxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgc3VtIG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvbiBhZGRcbiAqIEB0aHJvd3Mge092ZXJmbG93RXJyb3J9IG9uIGFkZGl0aW9uIG92ZXJmbG93XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGQoYTogbnVtYmVyLCBiOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBjID0gYSArIGI7XG4gIGlmIChhICE9PSBjIC0gYiB8fCBiICE9PSBjIC0gYSkge1xuICAgIHRocm93IG5ldyBPdmVyZmxvd0Vycm9yKGBBZGRpdGlvbiBvdmVyZmxvdzogJHthfSArICR7Yn1gKTtcbiAgfVxuICByZXR1cm4gYztcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3ZlcmZsb3ctc2FmZSBzdWJ0cmFjdGlvbiBvcGVyYXRpb25cbiAqIEBzdW1tYXJ5IFN1YnRyYWN0cyBiIGZyb20gYSBhbmQgdmFsaWRhdGVzIG5vIG92ZXJmbG93IGJ5IHJldmVyc2UtY2hlY2tpbmcgdGhlIG9wZXJhbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gYSAtIE1pbnVlbmRcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gU3VidHJhaGVuZFxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgZGlmZmVyZW5jZSBhIC0gYlxuICogQGZ1bmN0aW9uIHN1YlxuICogQHRocm93cyB7T3ZlcmZsb3dFcnJvcn0gb24gc3VidGFjdGlvbiBvdmVyZmxvd1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ViKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYyA9IGEgLSBiO1xuICBpZiAoYSAhPT0gYyArIGIgfHwgYiAhPT0gYSAtIGMpIHtcbiAgICB0aHJvdyBuZXcgT3ZlcmZsb3dFcnJvcihgU3VidHJhY3Rpb24gb3ZlcmZsb3c6ICR7YX0gLSAke2J9YCk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgU2FmZSBJbnRlZ2VyIFBhcnNlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZ1xuICpcbiAqIEBmdW5jdGlvbiBzYWZlUGFyc2VJbnRcbiAqXG4gKiBAdGhyb3dzIHtWYWxpZGF0aW9uRXJyb3J9IGlmIHBhcnNlSW50IHJldHVybnMgTmFOXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlSW50KHN0cmluZzogc3RyaW5nKTogbnVtYmVyIHtcbiAgLy8gUmVndWxhciBleHByZXNzaW9uIHRvIGNoZWNrIGlmIHN0cmluZyBvbmx5IGhhdmUgZGlnaXRzXG4gIGNvbnN0IGRpZ2l0UmVnZXggPSAvXlxcZCskLztcbiAgaWYgKCFkaWdpdFJlZ2V4LnRlc3Qoc3RyaW5nKSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBzdHJpbmdGb3JtYXQoXCJGYWlsZWQgdG8gcGFyc2U6IHswfVwiLCBcInN0cmluZyBjb250YWlucyBkaWdpdHNcIilcbiAgICApO1xuICB9XG4gIGNvbnN0IHBhcnNlZGludCA9IHBhcnNlSW50KHN0cmluZyk7XG4gIGlmIChpc05hTihwYXJzZWRpbnQpKSB7XG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHN0cmluZ0Zvcm1hdChcIkZhaWxlZCB0byBwYXJzZTogezB9XCIsIFwic3RyaW5nIGlzIG5vdCBhIHBhcnNhYmxlIGludGVnZXJcIilcbiAgICApO1xuICB9XG4gIHJldHVybiBwYXJzZWRpbnQ7XG59XG4iLCJpbXBvcnQge1xuICBKU09OU2VyaWFsaXplcixcbiAgTW9kZWwsXG4gIE1vZGVsS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuPiBleHRlbmRzIEpTT05TZXJpYWxpemVyPE0+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgb3ZlcnJpZGUgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcsIHRhYmxlTmFtZT86IHN0cmluZyk6IE0ge1xuICAgIGNvbnN0IGRlc2VyaWFsaXphdGlvbiA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICAvLyBjb25zdCBjbGFzc05hbWUgPSB0YWJsZU5hbWU7XG4gICAgLy8gaWYgKCFjbGFzc05hbWUpXG4gICAgLy8gICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBjbGFzcyByZWZlcmVuY2UgaW4gc2VyaWFsaXplZCBtb2RlbFwiKTtcblxuICAgIC8vIC8vIHRoaXMgd2lsbCByZXR1cm4gdW5kZWZpbmVkIHZhbHVlc1xuICAgIC8vIGNvbnN0IG1vZGVsOiBNID0gTW9kZWwuYnVpbGQoZGVzZXJpYWxpemF0aW9uLCBjbGFzc05hbWUpIGFzIHVua25vd24gYXMgTTtcblxuICAgIC8vIC8vIFBvcHVsYXRlIE1vZGVsXG4gICAgLy8gY29uc3QgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbiA9IE9iamVjdC5rZXlzKG1vZGVsKS5yZWR1Y2UoXG4gICAgLy8gICAoYWNjdW06IE0sIGtleSkgPT4ge1xuICAgIC8vICAgICAoYWNjdW0gYXMgUmVjb3JkPHN0cmluZywgYW55Pilba2V5XSA9XG4gICAgLy8gICAgICAgZGVzZXJpYWxpemF0aW9uW1JlcG9zaXRvcnkuY29sdW1uKGFjY3VtLCBrZXkpXTtcbiAgICAvLyAgICAgcmV0dXJuIGFjY3VtO1xuICAgIC8vICAgfSxcbiAgICAvLyAgIG1vZGVsXG4gICAgLy8gKTtcblxuICAgIC8vIGNvbnN0IHJlc3VsdCA9IE1vZGVsLmJ1aWxkKFxuICAgIC8vICAgcHJvY2Vzc2VkRGVzZWFsaXphdGlvbixcbiAgICAvLyAgIGNsYXNzTmFtZVxuICAgIC8vICkgYXMgdW5rbm93biBhcyBNO1xuXG4gICAgLy8gcmV0dXJuIHJlc3VsdDtcbiAgICByZXR1cm4gZGVzZXJpYWxpemF0aW9uO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2VyaWFsaXplKG1vZGVsOiBNLCBwdXRBbmNob3IgPSB0cnVlKTogc3RyaW5nIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHN0cmluZ2lmeSA9IHJlcXVpcmUoXCJqc29uLXN0cmluZ2lmeS1kZXRlcm1pbmlzdGljXCIpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3Qgc29ydEtleXNSZWN1cnNpdmUgPSByZXF1aXJlKFwic29ydC1rZXlzLXJlY3Vyc2l2ZVwiKTtcbiAgICBjb25zdCBwcmVTZXJpYWxpemF0aW9uID0gdGhpcy5wcmVTZXJpYWxpemUobW9kZWwsIHB1dEFuY2hvcik7XG4gICAgcmV0dXJuIHN0cmluZ2lmeShzb3J0S2V5c1JlY3Vyc2l2ZShwcmVTZXJpYWxpemF0aW9uKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcHJlU2VyaWFsaXplKG1vZGVsOiBNLCBwdXRBbmNob3I6IGJvb2xlYW4gPSB0cnVlKSB7XG4gICAgLy8gVE9ETzogbmVzdGVkIHByZXNlcmlhbGl6YXRpb24gKHNvIGluY3JlYXNlIHBlcmZvcm1hbmNlIHdoZW4gZGVzZXJpYWxpemluZylcbiAgICAvLyBUT0RPOiBWZXJpZnkgd2h5IHRoZXJlIGlzIG5vIG1ldGFkYXRhXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgbGV0IG1ldGFkYXRhO1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IE1ldGFkYXRhLm1vZGVsTmFtZShtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3Rvcik7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIG1ldGFkYXRhID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAocHV0QW5jaG9yKVxuICAgICAgdG9TZXJpYWxpemVbTW9kZWxLZXlzLkFOQ0hPUl0gPSBtZXRhZGF0YSB8fCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuXG4gICAgZnVuY3Rpb24gcHJlU2VyaWFsaXplKFxuICAgICAgdGhpczogU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8YW55PixcbiAgICAgIG9iajogYW55XG4gICAgKTogYW55IHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSByZXR1cm4gb2JqO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAocHJlU2VyaWFsaXplKTtcbiAgICAgIHJldHVybiB0aGlzLnByZVNlcmlhbGl6ZShvYmopO1xuICAgIH1cbiAgICBNb2RlbC5yZWxhdGlvbnMobW9kZWwpLmZvckVhY2goKHIpID0+IHtcbiAgICAgIHRvU2VyaWFsaXplW3JdID0gcHJlU2VyaWFsaXplLmNhbGwodGhpcywgdG9TZXJpYWxpemVbcl0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0b1NlcmlhbGl6ZTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBDbGllbnRCYXNlZFNlcnZpY2UsXG4gIENvbnRleHQsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgUGVyc2lzdGVuY2VLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCBGYWJyaWNDQVNlcnZpY2VzLCB7XG4gIEFmZmlsaWF0aW9uU2VydmljZSxcbiAgSUF0dHJpYnV0ZVJlcXVlc3QsXG4gIElkZW50aXR5U2VydmljZSxcbiAgSUVucm9sbFJlc3BvbnNlLFxuICBJUmVnaXN0ZXJSZXF1ZXN0LFxuICBJU2VydmljZVJlc3BvbnNlLFxuICBUTFNPcHRpb25zLFxufSBmcm9tIFwiZmFicmljLWNhLWNsaWVudFwiO1xuaW1wb3J0IHsgQ0FDb25maWcsIENyZWRlbnRpYWxzIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgQ29uZmxpY3RFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb3JlVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7XG4gIENlcnRpZmljYXRlUmVzcG9uc2UsXG4gIEZhYnJpY0lkZW50aXR5LFxuICBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0LFxuICBJZGVudGl0eVJlc3BvbnNlLFxufSBmcm9tIFwiLi4vLi4vc2hhcmVkL2ZhYnJpYy10eXBlc1wiO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gXCJmYWJyaWMtY29tbW9uXCI7XG5pbXBvcnQgeyBSZWdpc3RyYXRpb25FcnJvciB9IGZyb20gXCIuLi8uLi9zaGFyZWQvZXJyb3JzXCI7XG5pbXBvcnQgeyBDQV9ST0xFIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJS2V5VmFsdWVBdHRyaWJ1dGUgfSBmcm9tIFwiLi9GYWJyaWNFbnJvbGxtZW50U2VydmljZVwiO1xuaW1wb3J0IHsgSWRlbnRpdHkgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL2luZGV4XCI7XG5pbXBvcnQgeyBDcnlwdG9VdGlscyB9IGZyb20gXCIuLi9jcnlwdG9cIjtcblxuZXhwb3J0IGNsYXNzIEZhYnJpY0lkZW50aXR5U2VydmljZSBleHRlbmRzIENsaWVudEJhc2VkU2VydmljZTxcbiAgRmFicmljQ0FTZXJ2aWNlcyxcbiAgQ0FDb25maWdcbj4ge1xuICBwcm90ZWN0ZWQgX3VzZXIhOiBVc2VyO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHJvb3RDbGllbnQoKTogeyBuZXdDZXJ0aWZpY2F0ZVNlcnZpY2U6IGFueSB9IHtcbiAgICByZXR1cm4gKHRoaXMuY2xpZW50IGFzIGFueSlbXCJfRmFicmljQ2FTZXJ2aWNlc1wiXSBhcyBhbnk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHVzZXIoKTogVXNlciB7XG4gICAgaWYgKCF0aGlzLl91c2VyKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIFwiRmFicmljIGlkZW50aXR5IHNlcnZpY2Ugbm90IHByb3Blcmx5IHNldHVwOiBtaXNzaW5nIHVzZXJcIlxuICAgICAgKTtcbiAgICByZXR1cm4gdGhpcy5fdXNlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgY2VydGlmaWNhdGVzKCkge1xuICAgIHJldHVybiB0aGlzLnJvb3RDbGllbnQubmV3Q2VydGlmaWNhdGVTZXJ2aWNlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGFmZmlsaWF0aW9ucygpOiBBZmZpbGlhdGlvblNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5uZXdBZmZpbGlhdGlvblNlcnZpY2UoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgaWRlbnRpdGllcygpOiBJZGVudGl0eVNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5uZXdJZGVudGl0eVNlcnZpY2UoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRVc2VyKGNmZzogQ0FDb25maWcsIGN0eDogQ29udGV4dCkge1xuICAgIGNvbnN0IGxvZyA9IGN0eC5sb2dnZXIuZm9yKHRoaXMuZ2V0VXNlcik7XG4gICAgY29uc3QgeyBjYU5hbWUsIGNhQ2VydCwgY2FLZXksIHVybCwgaHNtIH0gPSBjZmc7XG5cbiAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgQ0EgdXNlciBmb3IgJHtjYU5hbWV9IGF0ICR7dXJsfWApO1xuICAgIGxvZy52ZXJib3NlKGBSZXRyaWV2aW5nIENBIGNlcnRpZmljYXRlIGZyb20gJHtjYUNlcnR9YCk7XG4gICAgY29uc3QgY2VydGlmaWNhdGUgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoY2FDZXJ0KTtcbiAgICBsZXQga2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKCFoc20pIHtcbiAgICAgIGlmICghY2FLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYE1pc3NpbmcgY2FLZXkgY29uZmlndXJhdGlvbiBmb3IgQ0EgJHtjYU5hbWV9LiBQcm92aWRlIGEga2V5IGRpcmVjdG9yeSBvciBjb25maWd1cmUgSFNNIHN1cHBvcnQuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbG9nLmRlYnVnKGBSZXRyaWV2aW5nIENBIGtleSBmcm9tICR7Y2FLZXl9YCk7XG4gICAgICBrZXkgPSBhd2FpdCBDb3JlVXRpbHMuZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoY2FLZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2cuZGVidWcoXG4gICAgICAgIGBVc2luZyBIU00gY29uZmlndXJhdGlvbiBmb3IgQ0EgJHtjYU5hbWV9IHdpdGggbGlicmFyeSAke2hzbS5saWJyYXJ5fWBcbiAgICAgICk7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgTG9hZGluZyBBZG1pbiB1c2VyIGZvciBjYSAke2NhTmFtZX1gKTtcbiAgICB0aGlzLl91c2VyID0gYXdhaXQgQ29yZVV0aWxzLmdldENBVXNlcihcImFkbWluXCIsIGtleSwgY2VydGlmaWNhdGUsIGNhTmFtZSwge1xuICAgICAgaHNtLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLl91c2VyO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdGlhbGl6ZShcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPHsgY29uZmlnOiBDQUNvbmZpZzsgY2xpZW50OiBGYWJyaWNDQVNlcnZpY2VzIH0+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBQZXJzaXN0ZW5jZUtleXMuSU5JVElBTElaQVRJT04sIHRydWUpXG4gICAgKS5mb3IodGhpcy5pbml0aWFsaXplKTtcbiAgICBjb25zdCBbY29uZmlnXSA9IGFyZ3M7XG4gICAgaWYgKCFjb25maWcpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTWlzc2luZyBGYWJyaWMgQ0EgY29uZmlndXJhdGlvblwiKTtcblxuICAgIGNvbnN0IHsgdXJsLCB0bHMsIGNhTmFtZSB9ID0gY29uZmlnO1xuICAgIGxvZy5pbmZvKGBJbml0aWFsaXppbmcgQ0EgQ2xpZW50IGZvciBDQSAke2NvbmZpZy5jYU5hbWV9IGF0ICR7Y29uZmlnLnVybH1gKTtcbiAgICBjb25zdCB7IHRydXN0ZWRSb290cywgdmVyaWZ5IH0gPSB0bHMgYXMgVExTT3B0aW9ucztcblxuICAgIGNvbnN0IHJvb3QgPSAodHJ1c3RlZFJvb3RzIGFzIHN0cmluZ1tdKVswXSBhcyBzdHJpbmc7XG4gICAgbG9nLmRlYnVnKGBSZXRyaWV2aW5nIENBIGNlcnRpZmljYXRlIGZyb20gJHtyb290fS4gY3dkOiAke3Byb2Nlc3MuY3dkKCl9YCk7XG5cbiAgICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGF3YWl0IENvcmVVdGlscy5nZXRGaWxlQ29udGVudChyb290KTtcblxuICAgIGxvZy5kZWJ1ZyhgQ0EgQ2VydGlmaWNhdGU6ICR7Y2VydGlmaWNhdGUudG9TdHJpbmcoKX1gKTtcblxuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBGYWJyaWNDQVNlcnZpY2VzKFxuICAgICAgdXJsLFxuICAgICAge1xuICAgICAgICB0cnVzdGVkUm9vdHM6IEJ1ZmZlci5mcm9tKGNlcnRpZmljYXRlKSxcbiAgICAgICAgdmVyaWZ5LFxuICAgICAgfSBhcyBUTFNPcHRpb25zLFxuICAgICAgY2FOYW1lXG4gICAgKTtcblxuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmdldFVzZXIoY29uZmlnLCBjdHgpO1xuICAgIGxvZy5kZWJ1ZyhgQ0EgdXNlciBsb2FkZWQ6ICR7dXNlci5nZXROYW1lKCl9YCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNsaWVudCxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzKC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+KTogUHJvbWlzZTxzdHJpbmdbXT47XG4gIGFzeW5jIGdldENlcnRpZmljYXRlcyhcbiAgICByZXF1ZXN0OiBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0LFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nW10+O1xuICBhc3luYyBnZXRDZXJ0aWZpY2F0ZXM8TUFQIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgZG9NYXA6IE1BUCxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPE1BUCBleHRlbmRzIGZhbHNlID8gQ2VydGlmaWNhdGVSZXNwb25zZSA6IHN0cmluZ1tdPjtcbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzPE1BUCBleHRlbmRzIGJvb2xlYW4+KFxuICAgIHJlcXVlc3Q6IEdldENlcnRpZmljYXRlc1JlcXVlc3QsXG4gICAgZG9NYXA6IE1BUCxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPE1BUCBleHRlbmRzIGZhbHNlID8gQ2VydGlmaWNhdGVSZXNwb25zZSA6IHN0cmluZ1tdPjtcbiAgYXN5bmMgZ2V0Q2VydGlmaWNhdGVzPE1BUCBleHRlbmRzIGJvb2xlYW4+KFxuICAgIHJlcXVlc3Q/OiBHZXRDZXJ0aWZpY2F0ZXNSZXF1ZXN0IHwgTUFQLFxuICAgIGRvTWFwOiBNQVAgPSB0cnVlIGFzIE1BUCxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPE1BUCBleHRlbmRzIGZhbHNlID8gQ2VydGlmaWNhdGVSZXNwb25zZSA6IHN0cmluZ1tdPiB7XG4gICAgaWYgKHJlcXVlc3QgaW5zdGFuY2VvZiBDb250ZXh0KSB7XG4gICAgICBhcmdzID0gW3JlcXVlc3RdO1xuICAgICAgZG9NYXAgPSB0cnVlIGFzIE1BUDtcbiAgICAgIHJlcXVlc3QgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcmVxdWVzdCA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgIGRvTWFwID0gcmVxdWVzdDtcbiAgICAgIHJlcXVlc3QgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZG9NYXAgIT09IFwiYm9vbGVhblwiKSB7XG4gICAgICBhcmdzID0gW2RvTWFwIGFzIE1heWJlQ29udGV4dHVhbEFyZzxhbnk+LCAuLi5hcmdzXTtcbiAgICAgIGRvTWFwID0gdHJ1ZSBhcyBNQVA7XG4gICAgfVxuXG4gICAgY29uc3QgeyBsb2cgfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBPcGVyYXRpb25LZXlzLlJFQUQsIHRydWUpKS5mb3IoXG4gICAgICB0aGlzLmdldENlcnRpZmljYXRlc1xuICAgICk7XG4gICAgbG9nLmRlYnVnKFxuICAgICAgYFJldHJpZXZpbmcgY2VydGlmaWNhdGVzJHtyZXF1ZXN0ID8gYCBmb3IgJHtyZXF1ZXN0LmlkfWAgOiBcIlwifSBmb3IgQ0EgJHt0aGlzLmNvbmZpZy5jYU5hbWV9YFxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2U6IENlcnRpZmljYXRlUmVzcG9uc2UgPSAoXG4gICAgICBhd2FpdCB0aGlzLmNlcnRpZmljYXRlcy5nZXRDZXJ0aWZpY2F0ZXMocmVxdWVzdCB8fCB7fSwgdGhpcy51c2VyKVxuICAgICkucmVzdWx0O1xuICAgIGxvZy52ZXJib3NlKGBGb3VuZCAke3Jlc3BvbnNlLmNlcnRzLmxlbmd0aH0gY2VydGlmaWNhdGVzYCk7XG4gICAgbG9nLmRlYnVnKHJlc3BvbnNlLmNlcnRzKTtcbiAgICByZXR1cm4gKFxuICAgICAgZG9NYXAgPyByZXNwb25zZS5jZXJ0cy5tYXAoKGMpID0+IGMuUEVNKSA6IHJlc3BvbnNlXG4gICAgKSBhcyBNQVAgZXh0ZW5kcyBmYWxzZSA/IENlcnRpZmljYXRlUmVzcG9uc2UgOiBzdHJpbmdbXTtcbiAgfVxuXG4gIGFzeW5jIGdldElkZW50aXRpZXMoY3R4OiBDb250ZXh0KTogUHJvbWlzZTxGYWJyaWNJZGVudGl0eVtdPiB7XG4gICAgY29uc3QgbG9nID0gY3R4LmxvZ2dlci5mb3IodGhpcy5nZXRJZGVudGl0aWVzKTtcbiAgICBsb2cudmVyYm9zZShgUmV0cmlldmluZyBJZGVudGl0aWVzIHVuZGVyIENBICR7dGhpcy5jb25maWcuY2FOYW1lfWApO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBJZGVudGl0eVJlc3BvbnNlID0gKGF3YWl0IHRoaXMuaWRlbnRpdGllcy5nZXRBbGwodGhpcy51c2VyKSlcbiAgICAgIC5yZXN1bHQ7XG4gICAgbG9nLnZlcmJvc2UoYEZvdW5kICR7cmVzcG9uc2UuaWRlbnRpdGllcy5sZW5ndGh9IElkZW50aXRpZXNgKTtcbiAgICBsb2cuZGVidWcocmVzcG9uc2UuaWRlbnRpdGllcyk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmlkZW50aXRpZXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlIGFmZmlsaWF0aW9ucyBmcm9tIHRoZSBDQS5cbiAgICogQHN1bW1hcnkgUXVlcmllcyB0aGUgQ0EgZm9yIHRoZSBsaXN0IG9mIGFmZmlsaWF0aW9ucyBhdmFpbGFibGUgdW5kZXIgdGhlIGNvbmZpZ3VyZWQgQ0EuXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGFmZmlsaWF0aW9ucyByZXN1bHQgcGF5bG9hZC5cbiAgICovXG4gIGFzeW5jIGdldEFmZmlsaWF0aW9ucyhjdHg6IENvbnRleHQpIHtcbiAgICBjb25zdCBsb2cgPSBjdHgubG9nZ2VyLmZvcih0aGlzLmdldEFmZmlsaWF0aW9ucyk7XG4gICAgbG9nLnZlcmJvc2UoYFJldHJpZXZpbmcgQWZmaWxpYXRpb25zIHVuZGVyIENBICR7dGhpcy5jb25maWcuY2FOYW1lfWApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gKGF3YWl0IHRoaXMuYWZmaWxpYXRpb25zLmdldEFsbCh0aGlzLnVzZXIpKS5yZXN1bHQ7XG4gICAgbG9nLnZlcmJvc2UoYEZvdW5kICR7cmVzcG9uc2UuYS5sZW5ndGh9IEFmZmlsaWF0aW9uc2ApO1xuICAgIGxvZy5kZWJ1ZyhKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpO1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUVycm9yKGU6IEVycm9yKSB7XG4gICAgY29uc3QgcmVnZXhwID0gLy4qY29kZTpcXHMoXFxkKykuKj9tZXNzYWdlOlxcc1tcIiddKC4rKVtcIiddL2dzO1xuICAgIGNvbnN0IG1hdGNoID0gcmVnZXhwLmV4ZWMoZS5tZXNzYWdlKTtcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKGUpO1xuICAgIGNvbnN0IFssIGNvZGUsIG1lc3NhZ2VdID0gbWF0Y2g7XG4gICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICBjYXNlIFwiNzRcIjpcbiAgICAgIGNhc2UgXCI3MVwiOlxuICAgICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IobWVzc2FnZSk7XG4gICAgICBjYXNlIFwiMjBcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IobWVzc2FnZSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZCBpZGVudGl0eSBkZXRhaWxzIGZyb20gdGhlIENBIGJ5IGVucm9sbG1lbnQgSUQuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhbmQgdmFsaWRhdGVzIGEgc2luZ2xlIGlkZW50aXR5LCB0aHJvd2luZyBOb3RGb3VuZEVycm9yIHdoZW4gbWlzc2luZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGVucm9sbG1lbnRJZCAtIEVucm9sbG1lbnQgSUQgdG8gbG9va3VwLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEZhYnJpY0lkZW50aXR5Pn0gVGhlIGlkZW50aXR5IGRldGFpbHMgc3RvcmVkIGluIHRoZSBDQS5cbiAgICovXG4gIGFzeW5jIHJlYWQoXG4gICAgZW5yb2xsbWVudElkOiBzdHJpbmcsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxGYWJyaWNJZGVudGl0eT4ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSAoYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgT3BlcmF0aW9uS2V5cy5SRUFELCB0cnVlKSkuZm9yKFxuICAgICAgdGhpcy5yZWFkXG4gICAgKTtcbiAgICBsb2cudmVyYm9zZShgUmV0cmlldmluZyBpZGVudGl0eSB3aXRoIGVucm9sbG1lbnQgSUQgJHtlbnJvbGxtZW50SWR9YCk7XG4gICAgbGV0IHJlc3VsdDogSVNlcnZpY2VSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5pZGVudGl0aWVzLmdldE9uZShlbnJvbGxtZW50SWQsIHRoaXMudXNlcik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYENvdWxkbid0IGZpbmQgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgQ291bGRuJ3QgZmluZCBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke3Jlc3VsdC5lcnJvcnMuam9pbihcIlxcblwiKX1gXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQgYXMgRmFicmljSWRlbnRpdHk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVyIGEgbmV3IGlkZW50aXR5IHdpdGggdGhlIENBLlxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgcmVnaXN0cmF0aW9uIHJlcXVlc3QgZm9yIGEgbmV3IGVucm9sbG1lbnQgSUQsIHJldHVybmluZyB0aGUgZW5yb2xsbWVudCBzZWNyZXQgdXBvbiBzdWNjZXNzLlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkIGZvciB0aGUgbmV3IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgZW5yb2xsbWVudCBzZWNyZXQgZm9yIHRoZSByZWdpc3RlcmVkIGlkZW50aXR5LlxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXIoXG4gICAgbW9kZWw6IENyZWRlbnRpYWxzLFxuICAgIGlzU3VwZXJVc2VyOiBib29sZWFuID0gZmFsc2UsXG4gICAgYWZmaWxpYXRpb246IHN0cmluZyA9IFwiXCIsXG4gICAgdXNlclJvbGU/OiBDQV9ST0xFIHwgc3RyaW5nLFxuICAgIGF0dHJzPzogSUtleVZhbHVlQXR0cmlidXRlLFxuICAgIG1heEVucm9sbG1lbnRzPzogbnVtYmVyLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBcInJlZ2lzdGVyXCIsIHRydWUpKS5mb3IoXG4gICAgICB0aGlzLnJlZ2lzdGVyXG4gICAgKTtcblxuICAgIGxldCByZWdpc3RyYXRpb246IHN0cmluZztcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyB1c2VyTmFtZSwgcGFzc3dvcmQgfSA9IG1vZGVsO1xuICAgICAgY29uc3QgcHJvcHMgPSB7XG4gICAgICAgIGVucm9sbG1lbnRJRDogdXNlck5hbWUgYXMgc3RyaW5nLFxuICAgICAgICBlbnJvbGxtZW50U2VjcmV0OiBwYXNzd29yZCxcbiAgICAgICAgYWZmaWxpYXRpb246IGFmZmlsaWF0aW9uLFxuICAgICAgICB1c2VyUm9sZTogdXNlclJvbGUsXG4gICAgICAgIGF0dHJzOiBhdHRycyxcbiAgICAgICAgbWF4RW5yb2xsbWVudHM6IG1heEVucm9sbG1lbnRzLFxuICAgICAgfSBhcyBJUmVnaXN0ZXJSZXF1ZXN0O1xuICAgICAgcmVnaXN0cmF0aW9uID0gYXdhaXQgdGhpcy5jbGllbnQucmVnaXN0ZXIocHJvcHMsIHRoaXMudXNlcik7XG4gICAgICBsb2cuaW5mbyhcbiAgICAgICAgYFJlZ2lzdHJhdGlvbiBmb3IgJHt1c2VyTmFtZX0gY3JlYXRlZCB3aXRoIHVzZXIgdHlwZSAke3VzZXJSb2xlID8/IFwiVW5kZWZpbmVkIFJvbGVcIn0gJHtpc1N1cGVyVXNlciA/IFwiYXMgc3VwZXIgdXNlclwiIDogXCJcIn1gXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVnaXN0cmF0aW9uO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyBpZGVudGl0eUZyb21FbnJvbGxtZW50KFxuICAgIGVucm9sbG1lbnQ6IElFbnJvbGxSZXNwb25zZSxcbiAgICBtc3BJZDogc3RyaW5nLFxuICAgIGN0eDogQ29udGV4dFxuICApOiBJZGVudGl0eSB7XG4gICAgY29uc3QgbG9nID0gY3R4LmxvZ2dlci5mb3IodGhpcy5pZGVudGl0eUZyb21FbnJvbGxtZW50KTtcbiAgICBjb25zdCB7IGNlcnRpZmljYXRlLCBrZXksIHJvb3RDZXJ0aWZpY2F0ZSB9ID0gZW5yb2xsbWVudDtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBHZW5lcmF0aW5nIElkZW50aXR5IGZyb20gY2VydGlmaWNhdGUgJHtjZXJ0aWZpY2F0ZX0gaW4gbXNwICR7bXNwSWR9YFxuICAgICk7XG4gICAgY29uc3QgY2xpZW50SWQgPSBDcnlwdG9VdGlscy5mYWJyaWNJZEZyb21DZXJ0aWZpY2F0ZShjZXJ0aWZpY2F0ZSk7XG4gICAgY29uc3QgaWQgPSBDcnlwdG9VdGlscy5lbmNvZGUoY2xpZW50SWQpO1xuICAgIGxvZy5kZWJ1ZyhgSWRlbnRpdHkgJHtjbGllbnRJZH0gYW5kIGVuY29kZWRJZCAke2lkfWApO1xuICAgIHJldHVybiBuZXcgSWRlbnRpdHkoe1xuICAgICAgaWQ6IGlkLFxuICAgICAgY3JlZGVudGlhbHM6IHtcbiAgICAgICAgaWQ6IGlkLFxuICAgICAgICBjZXJ0aWZpY2F0ZTogY2VydGlmaWNhdGUsXG4gICAgICAgIHByaXZhdGVLZXk6IGtleS50b0J5dGVzKCksXG4gICAgICAgIHJvb3RDZXJ0aWZpY2F0ZTogcm9vdENlcnRpZmljYXRlLFxuICAgICAgfSxcbiAgICAgIG1zcElkOiBtc3BJZCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRW5yb2xsIGFuIGlkZW50aXR5IHdpdGggdGhlIENBIHVzaW5nIGEgcmVnaXN0cmF0aW9uIHNlY3JldC5cbiAgICogQHN1bW1hcnkgRXhjaGFuZ2VzIHRoZSBlbnJvbGxtZW50IElEIGFuZCBzZWNyZXQgZm9yIGNlcnRpZmljYXRlcywgcmV0dXJuaW5nIGEgY29uc3RydWN0ZWQgSWRlbnRpdHkgbW9kZWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBlbnJvbGxtZW50SWQgLSBFbnJvbGxtZW50IElEIHRvIGVucm9sbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlZ2lzdHJhdGlvbiAtIEVucm9sbG1lbnQgc2VjcmV0IHJldHVybmVkIGF0IHJlZ2lzdHJhdGlvbiB0aW1lLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gVGhlIGVucm9sbGVkIGlkZW50aXR5IG9iamVjdCB3aXRoIGNyZWRlbnRpYWxzLlxuICAgKi9cbiAgYXN5bmMgZW5yb2xsKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIHJlZ2lzdHJhdGlvbjogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8SWRlbnRpdHk+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSAoYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgXCJlbnJvbGxcIiwgdHJ1ZSkpLmZvcihcbiAgICAgIHRoaXMuZW5yb2xsXG4gICAgKTtcbiAgICBsZXQgaWRlbnRpdHk6IElkZW50aXR5O1xuICAgIHRyeSB7XG4gICAgICBsb2cuZGVidWcoYEVucm9sbGluZyAke2Vucm9sbG1lbnRJZH1gKTtcbiAgICAgIGNvbnN0IGVucm9sbG1lbnQ6IElFbnJvbGxSZXNwb25zZSA9IGF3YWl0IHRoaXMuY2xpZW50LmVucm9sbCh7XG4gICAgICAgIGVucm9sbG1lbnRJRDogZW5yb2xsbWVudElkLFxuICAgICAgICBlbnJvbGxtZW50U2VjcmV0OiByZWdpc3RyYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGlkZW50aXR5ID0gRmFicmljSWRlbnRpdHlTZXJ2aWNlLmlkZW50aXR5RnJvbUVucm9sbG1lbnQoXG4gICAgICAgIGVucm9sbG1lbnQsXG4gICAgICAgIHRoaXMuY29uZmlnLmNhTmFtZSxcbiAgICAgICAgY3R4XG4gICAgICApO1xuICAgICAgbG9nLmluZm8oXG4gICAgICAgIGBTdWNjZXNzZnVsbHkgZW5yb2xsZWQgJHtlbnJvbGxtZW50SWR9IHVuZGVyICR7dGhpcy5jb25maWcuY2FOYW1lfSBhcyAke2lkZW50aXR5LmlkfWBcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICAgIHJldHVybiBpZGVudGl0eTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXIgYW5kIGVucm9sbCBhIG5ldyBpZGVudGl0eSBpbiBvbmUgc3RlcC5cbiAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIGEgbmV3IGVucm9sbG1lbnQgSUQgd2l0aCB0aGUgQ0EgYW5kIGltbWVkaWF0ZWx5IGV4Y2hhbmdlcyB0aGUgc2VjcmV0IHRvIGVucm9sbCwgcmV0dXJuaW5nIHRoZSBjcmVhdGVkIElkZW50aXR5LlxuICAgKiBAcGFyYW0ge0NyZWRlbnRpYWxzfSBtb2RlbCAtIENyZWRlbnRpYWxzIGZvciB0aGUgbmV3IGlkZW50aXR5IGNvbnRhaW5pbmcgdXNlck5hbWUgYW5kIHBhc3N3b3JkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N1cGVyVXNlcj1mYWxzZV0gLSBXaGV0aGVyIHRvIHJlZ2lzdGVyIHRoZSBpZGVudGl0eSBhcyBhIHN1cGVyIHVzZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWZmaWxpYXRpb249XCJcIl0gLSBBZmZpbGlhdGlvbiBzdHJpbmcgKGUuZy4sIG9yZzEuZGVwYXJ0bWVudDEpLlxuICAgKiBAcGFyYW0ge0NBX1JPTEUgfCBzdHJpbmd9IFt1c2VyUm9sZV0gLSBSb2xlIHRvIGFzc2lnbiB0byB0aGUgaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7SUtleVZhbHVlQXR0cmlidXRlfSBbYXR0cnNdIC0gT3B0aW9uYWwgYXR0cmlidXRlcyB0byBhdHRhY2ggdG8gdGhlIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW21heEVucm9sbG1lbnRzXSAtIE1heGltdW0gbnVtYmVyIG9mIGVucm9sbG1lbnRzIGFsbG93ZWQgZm9yIHRoZSBpZGVudGl0eS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxJZGVudGl0eT59IFRoZSBlbnJvbGxlZCBpZGVudGl0eS5cbiAgICovXG4gIGFzeW5jIHJlZ2lzdGVyQW5kRW5yb2xsKFxuICAgIG1vZGVsOiBDcmVkZW50aWFscyxcbiAgICBpc1N1cGVyVXNlcjogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGFmZmlsaWF0aW9uOiBzdHJpbmcgPSBcIlwiLFxuICAgIHVzZXJSb2xlPzogQ0FfUk9MRSB8IHN0cmluZyxcbiAgICBhdHRycz86IElLZXlWYWx1ZUF0dHJpYnV0ZSxcbiAgICBtYXhFbnJvbGxtZW50cz86IG51bWJlcixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPElkZW50aXR5PiB7XG4gICAgY29uc3QgeyBjdHggfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBcInJlZ2lzdGVyLWVucm9sbFwiLCB0cnVlKSkuZm9yKFxuICAgICAgdGhpcy5yZWdpc3RlckFuZEVucm9sbFxuICAgICk7XG4gICAgY29uc3QgcmVnaXN0cmF0aW9uID0gYXdhaXQgdGhpcy5yZWdpc3RlcihcbiAgICAgIG1vZGVsLFxuICAgICAgaXNTdXBlclVzZXIsXG4gICAgICBhZmZpbGlhdGlvbixcbiAgICAgIHVzZXJSb2xlLFxuICAgICAgYXR0cnMsXG4gICAgICBtYXhFbnJvbGxtZW50cyxcbiAgICAgIGN0eFxuICAgICk7XG4gICAgY29uc3QgeyB1c2VyTmFtZSB9ID0gbW9kZWw7XG4gICAgcmV0dXJuIHRoaXMuZW5yb2xsKHVzZXJOYW1lIGFzIHN0cmluZywgcmVnaXN0cmF0aW9uLCBjdHgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZS1lbnJvbGwgYW4gZXhpc3RpbmcgaWRlbnRpdHkgdXNpbmcgaXRzIGN1cnJlbnQgZW5yb2xsbWVudC5cbiAgICogQHN1bW1hcnkgUmVuZXdzIHRoZSBlbnJvbGxtZW50IGNlcnRpZmljYXRlIGJ5IGNhbGxpbmcgdGhlIENBIHJlZW5yb2xsLlxuICAgKiBAcGFyYW0ge1VzZXJ9IGN1cnJlbnRVc2VyIC0gQWxyZWFkeSBlbnJvbGxlZCB1c2VyLCBtdXN0IGhhdmUgYSBzaWduaW5nIGlkZW50aXR5LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gVGhlIHJlbmV3ZWQgaWRlbnRpdHkgb2JqZWN0IHdpdGggbmV3IGNyZWRlbnRpYWxzLlxuICAgKi9cbiAgYXN5bmMgcmVlbnJvbGwoXG4gICAgZW5yb2xsbWVudElkOiBzdHJpbmcsXG4gICAgaWRlbnRpdHk6IElkZW50aXR5LFxuICAgIGF0dHJSZXFzOiBJQXR0cmlidXRlUmVxdWVzdFtdID0gW10sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxJZGVudGl0eT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBcInJlZW5yb2xsXCIsIHRydWUpKS5mb3IoXG4gICAgICB0aGlzLnJlZW5yb2xsXG4gICAgKTtcblxuICAgIHRyeSB7XG4gICAgICBsb2cuZGVidWcoYFJlLWVucm9sbGluZyAke2Vucm9sbG1lbnRJZH1gKTtcblxuICAgICAgY29uc3QgeyBtc3BJZCwgY3JlZGVudGlhbHMgfSA9IGlkZW50aXR5O1xuXG4gICAgICBjb25zdCB1c2VyID0gVXNlci5jcmVhdGVVc2VyKFxuICAgICAgICBlbnJvbGxtZW50SWQsXG4gICAgICAgIFwiXCIsIC8vIGVucm9sbG1lbnRTZWNyZXRcbiAgICAgICAgbXNwSWQgfHwgdGhpcy51c2VyLmdldE1zcGlkKCksXG4gICAgICAgIGNyZWRlbnRpYWxzLmNlcnRpZmljYXRlLFxuICAgICAgICBjcmVkZW50aWFscy5wcml2YXRlS2V5XG4gICAgICApO1xuXG4gICAgICAvLyBSZXVzZSBjcnlwdG9TdWl0ZSBjb25maWdcbiAgICAgIHVzZXIuc2V0Q3J5cHRvU3VpdGUodGhpcy51c2VyLmdldENyeXB0b1N1aXRlKCkpO1xuXG4gICAgICBjb25zdCBlbnJvbGxtZW50ID0gYXdhaXQgdGhpcy5jbGllbnQucmVlbnJvbGwodXNlciwgYXR0clJlcXMpO1xuICAgICAgY29uc3QgbmV3SWRlbnRpdHkgPSBGYWJyaWNJZGVudGl0eVNlcnZpY2UuaWRlbnRpdHlGcm9tRW5yb2xsbWVudChcbiAgICAgICAgZW5yb2xsbWVudCxcbiAgICAgICAgdGhpcy5jb25maWcuY2FOYW1lLFxuICAgICAgICBjdHhcbiAgICAgICk7XG5cbiAgICAgIGxvZy5pbmZvKFxuICAgICAgICBgU3VjY2Vzc2Z1bGx5IHJlLWVucm9sbGVkICR7ZW5yb2xsbWVudElkfSB1bmRlciAke3RoaXMuY29uZmlnLmNhTmFtZX0gYXMgJHtuZXdJZGVudGl0eS5pZH1gXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gbmV3SWRlbnRpdHk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldm9rZXMgdGhlIGVucm9sbG1lbnQgb2YgYW4gaWRlbnRpdHkgd2l0aCB0aGUgc3BlY2lmaWVkIGVucm9sbG1lbnQgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBlbnJvbGxtZW50SWQgLSBUaGUgZW5yb2xsbWVudCBJRCBvZiB0aGUgaWRlbnRpdHkgdG8gYmUgcmV2b2tlZC5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlc3VsdCBvZiB0aGUgcmV2b2NhdGlvbiBvcGVyYXRpb24uXG4gICAqXG4gICAqIEB0aHJvd3Mge05vdEZvdW5kRXJyb3J9IElmIHRoZSBlbnJvbGxtZW50IHdpdGggdGhlIHNwZWNpZmllZCBJRCBkb2VzIG5vdCBleGlzdC5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlcmUgaXMgYW4gZXJyb3IgZHVyaW5nIHRoZSByZXZvY2F0aW9uIHByb2Nlc3MuXG4gICAqL1xuICBhc3luYyByZXZva2UoXG4gICAgZW5yb2xsbWVudElkOiBzdHJpbmcsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxJU2VydmljZVJlc3BvbnNlPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChhcmdzLCBcInJldm9rZVwiLCB0cnVlKSkuZm9yKHRoaXMucmV2b2tlKTtcbiAgICBsb2cudmVyYm9zZShgUmV2b2tpbmcgaWRlbnRpdHkgd2l0aCBlbnJvbGxtZW50IElEICR7ZW5yb2xsbWVudElkfWApO1xuICAgIGNvbnN0IGlkZW50aXR5ID0gYXdhaXQgdGhpcy5yZWFkKGVucm9sbG1lbnRJZCk7XG4gICAgaWYgKCFpZGVudGl0eSlcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IGZpbmQgZW5yb2xsbWVudCB3aXRoIGlkICR7ZW5yb2xsbWVudElkfWBcbiAgICAgICk7XG4gICAgbGV0IHJlc3VsdDogSVNlcnZpY2VSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5jbGllbnQucmV2b2tlKFxuICAgICAgICB7IGVucm9sbG1lbnRJRDogaWRlbnRpdHkuaWQsIHJlYXNvbjogXCJVc2VyIERlbGV0aW9uXCIgfSxcbiAgICAgICAgdGhpcy51c2VyXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IHJldm9rZSBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke2V9YFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFyZXN1bHQuc3VjY2VzcylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IHJldm9rZSBlbnJvbGxtZW50IHdpdGggaWQgJHtlbnJvbGxtZW50SWR9OiAke3Jlc3VsdC5lcnJvcnMuam9pbihcIlxcblwiKX1gXG4gICAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIENlcnRpZmljYXRlIEF1dGhvcml0eSByb2xlIHR5cGVzIHVzZWQgZHVyaW5nIGVucm9sbG1lbnQgYW5kIHJlZ2lzdHJhdGlvbi5cbiAqIEBzdW1tYXJ5IEVudW1lcmF0ZXMgdGhlIHN0YW5kYXJkIEh5cGVybGVkZ2VyIEZhYnJpYyBDQSByb2xlcyB0aGF0IGNhbiBiZSBhc3NpZ25lZCB0byBpZGVudGl0aWVzIHdoZW4gcmVnaXN0ZXJpbmcgd2l0aCB0aGUgQ0Egc2VydmljZS5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGVudW0gQ0FfUk9MRSB7XG4gIC8qKiBBZG1pbmlzdHJhdG9yIHJvbGUgd2l0aCBlbGV2YXRlZCBwcml2aWxlZ2VzIGZvciBtYW5hZ2luZyBpZGVudGl0aWVzIGFuZCBhZmZpbGlhdGlvbnMgKi9cbiAgQURNSU4gPSBcImFkbWluXCIsXG4gIC8qKiBTdGFuZGFyZCB1c2VyIHJvbGUgZm9yIGFwcGxpY2F0aW9uIGNsaWVudHMgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgbmV0d29yayAqL1xuICBVU0VSID0gXCJ1c2VyXCIsXG4gIC8qKiBDbGllbnQgcm9sZSB0eXBpY2FsbHkgdXNlZCBmb3IgU0RLLWJhc2VkIGludGVyYWN0aW9ucyBhbmQgc2VydmljZSBhY2NvdW50cyAqL1xuICBDTElFTlQgPSBcImNsaWVudFwiLFxufVxuIiwiaW1wb3J0IHsgRmFicmljQ2xpZW50RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdEZhYnJpY0NsaWVudEZsYWdzOiBGYWJyaWNDbGllbnRGbGFncyA9IE9iamVjdC5hc3NpZ24oe1xuICBldmFsdWF0ZVRpbWVvdXQ6IDUsXG4gIGVuZG9yc2VUaW1lb3V0OiAxNSxcbiAgc3VibWl0VGltZW91dDogNSxcbiAgY29tbWl0VGltZW91dDogNjAsXG59KSBhcyBhbnk7XG4iLCJpbXBvcnQgeyBpc0Jyb3dzZXIsIE1pbmlMb2dnZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IFVzZXIgfSBmcm9tIFwiZmFicmljLWNvbW1vblwiO1xuaW1wb3J0IHsgSWRlbnRpdHksIFNpZ25lciwgc2lnbmVycyB9IGZyb20gXCJAaHlwZXJsZWRnZXIvZmFicmljLWdhdGV3YXlcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZUltcG9ydCB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuXG5jb25zdCBsb2cgPSBuZXcgTWluaUxvZ2dlcihcImZhYnJpYy1mc1wiKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTG9hZHMgY29udGVudCBmcm9tIGEgZmlsZSBvciByZXR1cm5zIHRoZSBjb250ZW50IGlmIGFscmVhZHkgbG9hZGVkXG4gKiBAc3VtbWFyeSBEZXRlcm1pbmVzIGlmIHRoZSBpbnB1dCBpcyBhbHJlYWR5IGNvbnRlbnQgb3IgYSBwYXRoIHRvIGEgZmlsZSwgYW5kIGxvYWRzIHRoZSBmaWxlIGlmIG5lZWRlZFxuICogQHBhcmFtIHtzdHJpbmcgfCBVaW50OEFycmF5fSBjb250ZW50T3JQYXRoIC0gVGhlIGNvbnRlbnQgb3IgcGF0aCB0byBsb2FkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaWxlUmVhZGVyIC0gRnVuY3Rpb24gdG8gcmVhZCB0aGUgZmlsZSBpZiBjb250ZW50T3JQYXRoIGlzIGEgcGF0aFxuICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmcgfCBVaW50OEFycmF5IHwgQnVmZmVyPn0gVGhlIGNvbnRlbnRcbiAqIEBmdW5jdGlvbiBjb250ZW50T2ZMb2FkRmlsZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29udGVudE9mTG9hZEZpbGUoXG4gIGNvbnRlbnRPclBhdGg6IHN0cmluZyB8IFVpbnQ4QXJyYXksXG4gIGZpbGVSZWFkZXI6IChwYXRoOiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nIHwgVWludDhBcnJheSB8IEJ1ZmZlcj5cbikge1xuICBpZiAoY29udGVudE9yUGF0aCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHJldHVybiBjb250ZW50T3JQYXRoO1xuICBpZiAoXG4gICAgY29udGVudE9yUGF0aC5tYXRjaChcbiAgICAgIC8tLS0tLUJFR0lOIChDRVJUSUZJQ0FURXxLRVl8UFJJVkFURSBLRVkpLS0tLS0uKz8tLS0tLUVORCBcXDEtLS0tLSQvZ21zXG4gICAgKVxuICApXG4gICAgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG4gIHJldHVybiBhd2FpdCBmaWxlUmVhZGVyKGNvbnRlbnRPclBhdGgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIGZpbGUgZnJvbSB0aGUgZmlsZSBzeXN0ZW1cbiAqIEBzdW1tYXJ5IExvYWRzIGEgZmlsZSB1c2luZyB0aGUgTm9kZS5qcyBmaWxlIHN5c3RlbSBtb2R1bGVcbiAqIEBwYXJhbSB7c3RyaW5nIHwgQnVmZmVyfSBjb250ZW50T3JQYXRoIC0gVGhlIGNvbnRlbnQgb3IgcGF0aCB0byBsb2FkXG4gKiBAcmV0dXJuIHtQcm9taXNlPEJ1ZmZlcj59IFRoZSBmaWxlIGNvbnRlbnQgYXMgYSBCdWZmZXJcbiAqIEBmdW5jdGlvbiByZWFkRmlsZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEZpbGUoY29udGVudE9yUGF0aDogc3RyaW5nIHwgQnVmZmVyKSB7XG4gIGlmICh0eXBlb2YgY29udGVudE9yUGF0aCAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIGNvbnRlbnRPclBhdGg7XG5cbiAgY29uc3QgZmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIHJldHVybiBhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShwYXRoKTtcbiAgfTtcblxuICByZXR1cm4gYXdhaXQgZmlsZVJlYWRlcihjb250ZW50T3JQYXRoKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIENlcnRpZmljYXRlIEF1dGhvcml0eSB1c2VyXG4gKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHVzZXIgd2l0aCB0aGUgZ2l2ZW4gY3JlZGVudGlhbHMgZm9yIGludGVyYWN0aW5nIHdpdGggYSBGYWJyaWMgQ0FcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyTmFtZSAtIFRoZSB1c2VyIG5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcml2YXRlS2V5IC0gVGhlIHByaXZhdGUga2V5IGFzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gY2VydGlmaWNhdGUgLSBUaGUgY2VydGlmaWNhdGUgYXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc3BJZCAtIFRoZSBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgSURcbiAqIEByZXR1cm4ge1Byb21pc2U8VXNlcj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHVzZXJcbiAqIEBmdW5jdGlvbiBnZXRDQVVzZXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldENBVXNlcihcbiAgdXNlck5hbWU6IHN0cmluZyxcbiAgcHJpdmF0ZUtleTogc3RyaW5nLFxuICBjZXJ0aWZpY2F0ZTogc3RyaW5nLFxuICBtc3BJZDogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXI+IHtcbiAgbG9nLmRlYnVnKFxuICAgIGBDcmVhdGluZyBhIENBICR7bXNwSWR9IHVzZXIgJHt1c2VyTmFtZX0gd2l0aCBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlfWBcbiAgKTtcbiAgY29uc3QgdXNlciA9IG5ldyBVc2VyKHVzZXJOYW1lKTtcbiAgY29uc3QgY3J5cHRvU3VpdGUgPSBVc2VyLm5ld0NyeXB0b1N1aXRlKCk7XG4gIHVzZXIuc2V0Q3J5cHRvU3VpdGUoY3J5cHRvU3VpdGUpO1xuICBjb25zdCBpbXBvcnRlZEtleSA9IGNyeXB0b1N1aXRlLmNyZWF0ZUtleUZyb21SYXcocHJpdmF0ZUtleSk7XG4gIGF3YWl0IHVzZXIuc2V0RW5yb2xsbWVudChpbXBvcnRlZEtleSwgY2VydGlmaWNhdGUsIG1zcElkKTtcbiAgcmV0dXJuIHVzZXI7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgYW4gaWRlbnRpdHkgZnJvbSBhIGNlcnRpZmljYXRlIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgTG9hZHMgYSBjZXJ0aWZpY2F0ZSBmcm9tIGEgZGlyZWN0b3J5IGFuZCBjcmVhdGVzIGFuIElkZW50aXR5IG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IG1zcElkIC0gVGhlIE1lbWJlcnNoaXAgU2VydmljZSBQcm92aWRlciBJRFxuICogQHBhcmFtIHtzdHJpbmd9IGNlcnREaXJlY3RvcnlQYXRoIC0gUGF0aCB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJuIHtQcm9taXNlPElkZW50aXR5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGlkZW50aXR5XG4gKiBAZnVuY3Rpb24gZ2V0SWRlbnRpdHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jbGllbnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldElkZW50aXR5KFxuICBtc3BJZDogc3RyaW5nLFxuICBjZXJ0RGlyZWN0b3J5UGF0aDogc3RyaW5nXG4pOiBQcm9taXNlPElkZW50aXR5PiB7XG4gIGNvbnN0IGlkZW50aXR5RmlsZVJlYWRlciA9IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCB7IHByb21pc2VzIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwiZnNcIikpO1xuICAgIGNvbnN0IGNlcnRQYXRoID0gYXdhaXQgZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICBjb25zdCBjcmVkZW50aWFscyA9IGF3YWl0IHByb21pc2VzLnJlYWRGaWxlKGNlcnRQYXRoKTtcbiAgICByZXR1cm4gY3JlZGVudGlhbHM7XG4gIH07XG5cbiAgY29uc3QgY3JlZGVudGlhbHM6IFVpbnQ4QXJyYXkgPSAoYXdhaXQgY29udGVudE9mTG9hZEZpbGUoXG4gICAgY2VydERpcmVjdG9yeVBhdGgsXG4gICAgaWRlbnRpdHlGaWxlUmVhZGVyXG4gICkpIGFzIFVpbnQ4QXJyYXk7XG5cbiAgcmV0dXJuIHsgbXNwSWQsIGNyZWRlbnRpYWxzIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIGZ1bGwgcGF0aCBvZiB0aGUgZmlyc3QgZmlsZSBpbiBhIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgUmVhZHMgYSBkaXJlY3RvcnkgYW5kIHJldHVybnMgdGhlIHBhdGggdG8gdGhlIGZpcnN0IGZpbGUgZm91bmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBkaXJQYXRoIC0gUGF0aCB0byB0aGUgZGlyZWN0b3J5XG4gKiBAcmV0dXJuIHtQcm9taXNlPHN0cmluZz59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBmdWxsIHBhdGggb2YgdGhlIGZpcnN0IGZpbGVcbiAqIEBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuY2xpZW50XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lKGRpclBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgcHJvbWlzZXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChpbXBvcnQoXCJmc1wiKSk7XG4gIGNvbnN0IHsgam9pbiB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcInBhdGhcIikpO1xuICBjb25zdCBmaWxlcyA9IGF3YWl0IHByb21pc2VzLnJlYWRkaXIoZGlyUGF0aCk7XG4gIHJldHVybiBqb2luKGRpclBhdGgsIGZpbGVzWzBdKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY29udGVudCBvZiB0aGUgZmlyc3QgZmlsZSBpbiBhIGRpcmVjdG9yeVxuICogQHN1bW1hcnkgUmVhZHMgYSBkaXJlY3RvcnksIGZpbmRzIHRoZSBmaXJzdCBmaWxlLCBhbmQgcmV0dXJucyBpdHMgY29udGVudCBhcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IGRpclBhdGggLSBQYXRoIHRvIHRoZSBkaXJlY3RvcnlcbiAqIEByZXR1cm4ge1Byb21pc2U8c3RyaW5nPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNvbnRlbnQgb2YgdGhlIGZpcnN0IGZpbGVcbiAqIEBmdW5jdGlvbiBnZXRGaXJzdERpckZpbGVOYW1lQ29udGVudFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Rmlyc3REaXJGaWxlTmFtZUNvbnRlbnQoXG4gIGRpclBhdGg6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgeyBwcm9taXNlcyB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcImZzXCIpKTtcbiAgY29uc3QgeyBqb2luIH0gPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KFwicGF0aFwiKSk7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgcHJvbWlzZXMucmVhZGRpcihkaXJQYXRoKTtcbiAgcmV0dXJuIChhd2FpdCBwcm9taXNlcy5yZWFkRmlsZShqb2luKGRpclBhdGgsIGZpbGVzWzBdKSkpLnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldHMgYSBzaWduZXIgZnJvbSBhIGtleSBkaXJlY3RvcnlcbiAqIEBzdW1tYXJ5IExvYWRzIGEgcHJpdmF0ZSBrZXkgZnJvbSBhIGRpcmVjdG9yeSBhbmQgY3JlYXRlcyBhIFNpZ25lciBmb3IgRmFicmljIHRyYW5zYWN0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IGtleURpcmVjdG9yeVBhdGggLSBQYXRoIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgcHJpdmF0ZSBrZXlcbiAqIEByZXR1cm4ge1Byb21pc2U8U2lnbmVyPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHNpZ25lclxuICogQGZ1bmN0aW9uIGdldFNpZ25lclxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0U2lnbmVyKGtleURpcmVjdG9yeVBhdGg6IHN0cmluZyk6IFByb21pc2U8U2lnbmVyPiB7XG4gIGNvbnN0IHNpZ25lckZpbGVSZWFkZXIgPSBhc3luYyAocGF0aDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgeyBwcm9taXNlcyB9ID0gYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChcImZzXCIpKTtcbiAgICBjb25zdCBrZXlQYXRoID0gYXdhaXQgZ2V0Rmlyc3REaXJGaWxlTmFtZShwYXRoKTtcbiAgICByZXR1cm4gYXdhaXQgcHJvbWlzZXMucmVhZEZpbGUoa2V5UGF0aCk7XG4gIH07XG5cbiAgY29uc3QgcHJpdmF0ZUtleVBlbSA9IChhd2FpdCBjb250ZW50T2ZMb2FkRmlsZShcbiAgICBrZXlEaXJlY3RvcnlQYXRoLFxuICAgIHNpZ25lckZpbGVSZWFkZXJcbiAgKSkgYXMgQnVmZmVyO1xuICAvLyBOb2RlIGJhc2VkIGltcGxlbWVudGF0aW9uXG4gIC8vIHByaXZhdGVLZXkgPSBjcmVhdGVQcml2YXRlS2V5KHByaXZhdGVLZXlQZW0pO1xuICAvLyAtLVxuXG4gIC8vIHdlYiBiYXNlZCBpbXBsZW1lbnRhdGlvblxuICBjb25zdCBwcml2YXRlS2V5ID0gYXdhaXQgZXh0cmFjdFByaXZhdGVLZXkocHJpdmF0ZUtleVBlbSk7XG4gIGNvbnN0IGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHByaXZhdGVLZXkpO1xuICBjb25zdCBrID0gKHByaXZhdGVLZXkgYXMgYW55KVtrZXlzWzBdXTtcbiAgLy8gLS1cblxuICByZXR1cm4gc2lnbmVycy5uZXdQcml2YXRlS2V5U2lnbmVyKGsgYXMgYW55KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXh0cmFjdHMgYSBwcml2YXRlIGtleSBmcm9tIGEgUEVNIGJ1ZmZlclxuICogQHN1bW1hcnkgQ29udmVydHMgYSBQRU0tZW5jb2RlZCBwcml2YXRlIGtleSB0byBhIENyeXB0b0tleSBvYmplY3RcbiAqIEBwYXJhbSB7QnVmZmVyfSBwZW0gLSBUaGUgUEVNLWVuY29kZWQgcHJpdmF0ZSBrZXlcbiAqIEByZXR1cm4ge1Byb21pc2U8Q3J5cHRvS2V5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIENyeXB0b0tleVxuICogQGZ1bmN0aW9uIGV4dHJhY3RQcml2YXRlS2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuY2xpZW50XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBFeHRyYWN0UHJpdmF0ZUtleVxuICogICBwYXJ0aWNpcGFudCBTdWJ0bGVDcnlwdG9cbiAqXG4gKiAgIENhbGxlci0+PkV4dHJhY3RQcml2YXRlS2V5OiBleHRyYWN0UHJpdmF0ZUtleShwZW0pXG4gKiAgIEV4dHJhY3RQcml2YXRlS2V5LT4+RXh0cmFjdFByaXZhdGVLZXk6IEdldCBTdWJ0bGVDcnlwdG8gaW1wbGVtZW50YXRpb25cbiAqICAgRXh0cmFjdFByaXZhdGVLZXktPj5FeHRyYWN0UHJpdmF0ZUtleTogUGFyc2UgUEVNIGZvcm1hdFxuICogICBFeHRyYWN0UHJpdmF0ZUtleS0+PkV4dHJhY3RQcml2YXRlS2V5OiBDb252ZXJ0IHRvIGJpbmFyeSBERVJcbiAqICAgRXh0cmFjdFByaXZhdGVLZXktPj5TdWJ0bGVDcnlwdG86IGltcG9ydEtleShwa2NzOCwgYmluYXJ5RGVyLCBvcHRpb25zKVxuICogICBTdWJ0bGVDcnlwdG8tLT4+RXh0cmFjdFByaXZhdGVLZXk6IENyeXB0b0tleVxuICogICBFeHRyYWN0UHJpdmF0ZUtleS0tPj5DYWxsZXI6IENyeXB0b0tleVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXh0cmFjdFByaXZhdGVLZXkocGVtOiBCdWZmZXIpIHtcbiAgY29uc3QgbGliTmFtZSA9IFwiY3J5cHRvXCI7XG4gIGxldCBzdWJ0bGU7XG4gIGlmIChpc0Jyb3dzZXIoKSkge1xuICAgIHN1YnRsZSA9IChnbG9iYWxUaGlzIGFzIGFueSkuY3J5cHRvLnN1YnRsZTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBsaWIgPSAoYXdhaXQgbm9ybWFsaXplSW1wb3J0KGltcG9ydChsaWJOYW1lKSkpIGFzIGFueTtcbiAgICBzdWJ0bGUgPSBsaWIuc3VidGxlIHx8IGxpYi53ZWJjcnlwdG8uc3VidGxlO1xuICB9XG5cbiAgaWYgKCFzdWJ0bGUpIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBsb2FkIFN1YnRsZUNyeXB0byBtb2R1bGVcIik7XG5cbiAgZnVuY3Rpb24gc3RyMmFiKHN0cjogc3RyaW5nKSB7XG4gICAgY29uc3QgYnVmID0gbmV3IEFycmF5QnVmZmVyKHN0ci5sZW5ndGgpO1xuICAgIGNvbnN0IGJ1ZlZpZXcgPSBuZXcgVWludDhBcnJheShidWYpO1xuICAgIGZvciAobGV0IGkgPSAwLCBzdHJMZW4gPSBzdHIubGVuZ3RoOyBpIDwgc3RyTGVuOyBpKyspIHtcbiAgICAgIGJ1ZlZpZXdbaV0gPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZjtcbiAgfVxuXG4gIGNvbnN0IHN0ciA9IHBlbVxuICAgIC50b1N0cmluZyhcInV0ZjhcIilcbiAgICAucmVwbGFjZShcIi0tLS0tQkVHSU4gUFJJVkFURSBLRVktLS0tLVwiLCBcIlwiKVxuICAgIC5yZXBsYWNlQWxsKFwiXFxuXCIsIFwiXCIpXG4gICAgLnJlcGxhY2UoXCItLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tXCIsIFwiXCIpO1xuICBjb25zdCBkZWNvZGVkID0gQnVmZmVyLmZyb20oc3RyLCBcImJhc2U2NFwiKS50b1N0cmluZyhcImJpbmFyeVwiKTtcbiAgY29uc3QgYmluYXJ5RGVyID0gc3RyMmFiKGRlY29kZWQpO1xuXG4gIHRyeSB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgc3VidGxlLmltcG9ydEtleShcbiAgICAgIFwicGtjczhcIixcbiAgICAgIGJpbmFyeURlcixcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJFQ0RTQVwiLFxuICAgICAgICBuYW1lZEN1cnZlOiBcIlAtMjU2XCIsXG4gICAgICB9LFxuICAgICAgdHJ1ZSxcbiAgICAgIFtcInNpZ25cIl1cbiAgICApO1xuXG4gICAgcmV0dXJuIGtleTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEFkYXB0ZXJGbGFncyxcbiAgQ29uZGl0aW9uLFxuICBDb250ZXh0LFxuICBHcm91cE9wZXJhdG9yLFxuICBNYXliZUNvbnRleHR1YWxBcmcsXG4gIE9wZXJhdG9yLFxuICBPcmRlckRpcmVjdGlvbixcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBQcmVwYXJlZFN0YXRlbWVudCxcbiAgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLFxuICBRdWVyeUNsYXVzZSxcbiAgUXVlcnlFcnJvcixcbiAgUmVwb3NpdG9yeSxcbiAgU2VsZWN0U2VsZWN0b3IsXG4gIFNlcXVlbmNlLFxuICBTdGF0ZW1lbnQsXG4gIFN0YXRlbWVudEV4ZWN1dG9yLFxuICBWaWV3S2luZCxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudEFkYXB0ZXIgfSBmcm9tIFwiLi9GYWJyaWNDbGllbnRBZGFwdGVyXCI7XG5pbXBvcnQge1xuICBDb3VjaERCS2V5cyxcbiAgQ291Y2hEQk9wZXJhdG9yLFxuICBDb3VjaERCR3JvdXBPcGVyYXRvcixcbiAgQ291Y2hEQlF1ZXJ5TGltaXQsXG4gIE1hbmdvUXVlcnksXG4gIE1hbmdvT3BlcmF0b3IsXG4gIE1hbmdvU2VsZWN0b3IsXG4gIHRyYW5zbGF0ZU9wZXJhdG9ycyxcbiAgZ2VuZXJhdGVEZXNpZ25Eb2NOYW1lLFxuICBnZW5lcmF0ZVZpZXdOYW1lLFxuICBmaW5kVmlld01ldGFkYXRhLFxuICBDb3VjaERCVmlld01ldGFkYXRhLFxuICBWaWV3UmVzcG9uc2UsXG59IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IHRvQ2FtZWxDYXNlIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBEQktleXMsIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbnR5cGUgRmFicmljVmlld0Rlc2NyaXB0b3IgPSB7XG4gIGRkb2M6IHN0cmluZztcbiAgdmlldzogc3RyaW5nO1xuICBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufTtcblxudHlwZSBGYWJyaWNBZ2dyZWdhdGVJbmZvID1cbiAgfCB7XG4gICAgICBraW5kOiBWaWV3S2luZDtcbiAgICAgIG1ldGE6IENvdWNoREJWaWV3TWV0YWRhdGE7XG4gICAgICBkZXNjcmlwdG9yOiBGYWJyaWNWaWV3RGVzY3JpcHRvcjtcbiAgICAgIGNvdW50RGlzdGluY3Q/OiBib29sZWFuO1xuICAgIH1cbiAgfCB7XG4gICAgICBraW5kOiBcImF2Z1wiO1xuICAgICAgYXR0cmlidXRlOiBzdHJpbmc7XG4gICAgICBzdW1EZXNjcmlwdG9yOiBGYWJyaWNWaWV3RGVzY3JpcHRvcjtcbiAgICAgIGNvdW50RGVzY3JpcHRvcjogRmFicmljVmlld0Rlc2NyaXB0b3I7XG4gICAgfTtcblxuY29uc3QgZXNjYXBlUmVnRXhwID0gKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcgPT5cbiAgdmFsdWUucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpO1xuXG5mdW5jdGlvbiBuZXh0TGV4aWNvZ3JhcGhpY1N0cmluZyh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIFwiXFx1MDAwMFwiO1xuICBjb25zdCBjaGFycyA9IEFycmF5LmZyb20odmFsdWUpO1xuICBmb3IgKGxldCBpID0gY2hhcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICBjb25zdCBjb2RlID0gY2hhcnNbaV0uY29kZVBvaW50QXQoMCk7XG4gICAgaWYgKGNvZGUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgaWYgKGNvZGUgPCAweDEwZmZmZikge1xuICAgICAgY2hhcnNbaV0gPSBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlICsgMSk7XG4gICAgICByZXR1cm4gY2hhcnMuc2xpY2UoMCwgaSArIDEpLmpvaW4oXCJcIik7XG4gICAgfVxuICB9XG4gIHJldHVybiBgJHt2YWx1ZX1cXHUwMDAwYDtcbn1cblxuZnVuY3Rpb24gcHJlZml4UmFuZ2UocHJlZml4OiBzdHJpbmcpIHtcbiAgcmV0dXJuIHtcbiAgICBzdGFydDogcHJlZml4LFxuICAgIGVuZDogbmV4dExleGljb2dyYXBoaWNTdHJpbmcocHJlZml4KSxcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEZhYnJpY0NsaWVudFN0YXRlbWVudDxNIGV4dGVuZHMgTW9kZWwsIFI+IGV4dGVuZHMgU3RhdGVtZW50PFxuICBNLFxuICBGYWJyaWNDbGllbnRBZGFwdGVyLFxuICBSLFxuICBNYW5nb1F1ZXJ5XG4+IHtcbiAgY29uc3RydWN0b3IoYWRhcHRlcjogRmFicmljQ2xpZW50QWRhcHRlciwgb3ZlcnJpZGVzPzogUGFydGlhbDxBZGFwdGVyRmxhZ3M+KSB7XG4gICAgc3VwZXIoYWRhcHRlciwgb3ZlcnJpZGVzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBzcXVhc2goXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApOiBQcmVwYXJlZFN0YXRlbWVudDxhbnk+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBzcXVhc2hlZDogUHJlcGFyZWRTdGF0ZW1lbnQ8TT4gfCB1bmRlZmluZWQgPSBzdXBlci5zcXVhc2goXG4gICAgICBjdHggYXMgbmV2ZXJcbiAgICApO1xuICAgIGlmICghc3F1YXNoZWQpIHJldHVybiBzcXVhc2hlZDtcblxuICAgIGNvbnN0IHsgbWV0aG9kLCBwYXJhbXMsIGFyZ3MgfSA9IHNxdWFzaGVkO1xuICAgIGNvbnN0IHsgZGlyZWN0aW9uLCBsaW1pdCB9ID0gcGFyYW1zO1xuICAgIHN3aXRjaCAobWV0aG9kKSB7XG4gICAgICBjYXNlIFByZXBhcmVkU3RhdGVtZW50S2V5cy5GSU5EOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLlBBR0U6XG4gICAgICAgIGFyZ3MucHVzaChkaXJlY3Rpb24sIGxpbWl0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFByZXBhcmVkU3RhdGVtZW50S2V5cy5GSU5EX0JZOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLkxJU1RfQlk6XG4gICAgICAgIGFyZ3MucHVzaChkaXJlY3Rpb24pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLlBBR0VfQlk6XG4gICAgICAgIGFyZ3MucHVzaChkaXJlY3Rpb24sIGxpbWl0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFByZXBhcmVkU3RhdGVtZW50S2V5cy5GSU5EX09ORV9CWTpcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgbWV0aG9kICR7bWV0aG9kfWApO1xuICAgIH1cblxuICAgIHJldHVybiBzcXVhc2hlZDtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBleGVjdXRlUHJlcGFyZWQoXG4gICAgLi4uYXJnejogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCByZXBvID0gUmVwb3NpdG9yeS5mb3JNb2RlbCh0aGlzLmZyb21TZWxlY3RvciwgdGhpcy5hZGFwdGVyLmFsaWFzKTtcbiAgICBjb25zdCB7IG1ldGhvZCwgYXJncyB9ID0gdGhpcy5wcmVwYXJlZCBhcyBQcmVwYXJlZFN0YXRlbWVudDxhbnk+O1xuICAgIHJldHVybiByZXBvLnN0YXRlbWVudChtZXRob2QsIC4uLmFyZ3MsIC4uLmFyZ3opO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcHJlcGFyZShcbiAgICBjdHg/OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApOiBQcm9taXNlPFN0YXRlbWVudEV4ZWN1dG9yPE0sIFI+PiB7XG4gICAgY3R4ID1cbiAgICAgIGN0eCB8fFxuICAgICAgKGF3YWl0IHRoaXMuYWRhcHRlci5jb250ZXh0KFxuICAgICAgICBQZXJzaXN0ZW5jZUtleXMuUVVFUlksXG4gICAgICAgIHRoaXMub3ZlcnJpZGVzIHx8IHt9LFxuICAgICAgICB0aGlzLmZyb21TZWxlY3RvclxuICAgICAgKSk7XG5cbiAgICBpZiAoXG4gICAgICB0aGlzLmlzU2ltcGxlUXVlcnkoKSAmJlxuICAgICAgKGN0eCBhcyBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPikuZ2V0KFwiZm9yY2VQcmVwYXJlU2ltcGxlUXVlcmllc1wiKVxuICAgICkge1xuICAgICAgY29uc3Qgc3F1YXNoZWQgPSB0aGlzLnNxdWFzaChjdHggYXMgQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4pO1xuICAgICAgaWYgKHNxdWFzaGVkKSB7XG4gICAgICAgIHRoaXMucHJlcGFyZWQgPSBzcXVhc2hlZDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10gPSBbXTtcbiAgICBjb25zdCBwYXJhbXM6IGFueSA9IHt9IGFzIGFueTtcblxuICAgIGNvbnN0IHByZXBhcmVkOiBQcmVwYXJlZFN0YXRlbWVudDxhbnk+ID0ge1xuICAgICAgY2xhc3M6IHRoaXMuZnJvbVNlbGVjdG9yLFxuICAgICAgYXJncyxcbiAgICAgIHBhcmFtcyxcbiAgICB9IGFzIGFueTtcblxuICAgIGNvbnN0IG1ldGhvZDogc3RyaW5nW10gPSBbUXVlcnlDbGF1c2UuRklORF9CWV07XG5cbiAgICBpZiAodGhpcy53aGVyZUNvbmRpdGlvbikge1xuICAgICAgY29uc3QgcGFyc2VkID0gdGhpcy5wcmVwYXJlQ29uZGl0aW9uKHRoaXMud2hlcmVDb25kaXRpb24sIGN0eCBhcyBuZXZlcik7XG4gICAgICBtZXRob2QucHVzaChwYXJzZWQubWV0aG9kKTtcbiAgICAgIGlmIChwYXJzZWQuYXJncyAmJiBwYXJzZWQuYXJncy5sZW5ndGgpXG4gICAgICAgIGFyZ3MucHVzaCguLi4ocGFyc2VkLmFyZ3MgYXMgKHN0cmluZyB8IG51bWJlcilbXSkpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zZWxlY3RTZWxlY3RvcilcbiAgICAgIG1ldGhvZC5wdXNoKFxuICAgICAgICBRdWVyeUNsYXVzZS5TRUxFQ1QsXG4gICAgICAgIHRoaXMuc2VsZWN0U2VsZWN0b3Iuam9pbihgICR7UXVlcnlDbGF1c2UuQU5ELnRvTG93ZXJDYXNlKCl9IGApXG4gICAgICApO1xuICAgIGlmICh0aGlzLm9yZGVyQnlTZWxlY3RvcnM/Lmxlbmd0aCkge1xuICAgICAgbWV0aG9kLnB1c2goUXVlcnlDbGF1c2UuT1JERVJfQlksIHRoaXMub3JkZXJCeVNlbGVjdG9yc1swXVswXSBhcyBzdHJpbmcpO1xuICAgICAgYXJncy5wdXNoKHRoaXMub3JkZXJCeVNlbGVjdG9yc1swXVsxXSBhcyBhbnkpO1xuICAgIH1cbiAgICBwcmVwYXJlZC5tZXRob2QgPSB0b0NhbWVsQ2FzZShtZXRob2Quam9pbihcIiBcIikpO1xuICAgIHByZXBhcmVkLnBhcmFtcyA9IHBhcmFtcztcbiAgICB0aGlzLnByZXBhcmVkID0gcHJlcGFyZWQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBhIHJlY29yZCBmcm9tIENvdWNoREIvRmFicmljXG4gICAqIEBzdW1tYXJ5IEV4dHJhY3RzIHRoZSBJRCBmcm9tIGEgQ291Y2hEQiBkb2N1bWVudCBhbmQgcmV2ZXJ0cyBpdCB0byBhIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJvY2Vzc1JlY29yZChcbiAgICByOiBhbnksXG4gICAgcGtBdHRyOiBrZXlvZiBNLFxuICAgIHNlcXVlbmNlVHlwZTogXCJOdW1iZXJcIiB8IFwiQmlnSW50XCIgfCB1bmRlZmluZWQsXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApIHtcbiAgICBpZiAocltDb3VjaERCS2V5cy5JRF0pIHtcbiAgICAgIGNvbnN0IFssIC4uLmtleUFyZ3NdID0gcltDb3VjaERCS2V5cy5JRF0uc3BsaXQoQ291Y2hEQktleXMuU0VQQVJBVE9SKTtcbiAgICAgIGNvbnN0IGlkID0ga2V5QXJncy5qb2luKFwiX1wiKTtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KFxuICAgICAgICByLFxuICAgICAgICB0aGlzLmZyb21TZWxlY3RvcixcbiAgICAgICAgU2VxdWVuY2UucGFyc2VWYWx1ZShzZXF1ZW5jZVR5cGUsIGlkKSxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICBjdHhcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHJhdyBNYW5nbyBxdWVyeVxuICAgKiBAc3VtbWFyeSBTZW5kcyBhIHJhdyBNYW5nbyBxdWVyeSB0byBGYWJyaWMgYW5kIHByb2Nlc3NlcyB0aGUgcmVzdWx0c1xuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmF3PFI+KHJhd0lucHV0OiBNYW5nb1F1ZXJ5LCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJhdyk7XG4gICAgY29uc3QgYWdncmVnYXRvciA9IChyYXdJbnB1dCBhcyBhbnkpPy5hZ2dyZWdhdGVJbmZvO1xuICAgIGlmICgocmF3SW5wdXQgYXMgYW55KT8uYWdncmVnYXRlICYmIGFnZ3JlZ2F0b3IpIHtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBZ2dyZWdhdGU8Uj4oYWdncmVnYXRvciwgY3R4KTtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0czogYW55W10gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KFxuICAgICAgcmF3SW5wdXQsXG4gICAgICB0cnVlLFxuICAgICAgdGhpcy5mcm9tU2VsZWN0b3IsXG4gICAgICBjdHhcbiAgICApO1xuXG4gICAgY29uc3QgcGtBdHRyID0gTW9kZWwucGsodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS5nZXQoXG4gICAgICB0aGlzLmZyb21TZWxlY3RvcixcbiAgICAgIE1ldGFkYXRhLmtleShEQktleXMuSUQsIHBrQXR0ciBhcyBzdHJpbmcpXG4gICAgKT8udHlwZTtcblxuICAgIGlmICghdGhpcy5zZWxlY3RTZWxlY3RvcilcbiAgICAgIHJldHVybiByZXN1bHRzLm1hcCgocikgPT4gdGhpcy5wcm9jZXNzUmVjb3JkKHIsIHBrQXR0ciwgdHlwZSwgY3R4KSkgYXMgUjtcbiAgICByZXR1cm4gcmVzdWx0cyBhcyBSO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCdWlsZHMgYSBDb3VjaERCIE1hbmdvIHF1ZXJ5IGZyb20gdGhlIHN0YXRlbWVudFxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyB0aGUgc3RhdGVtZW50J3MgY29uZGl0aW9ucywgc2VsZWN0b3JzLCBhbmQgb3B0aW9ucyBpbnRvIGEgQ291Y2hEQiBNYW5nbyBxdWVyeVxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGJ1aWxkKCk6IE1hbmdvUXVlcnkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmJ1aWxkKTtcbiAgICBjb25zdCBhZ2dyZWdhdGVRdWVyeSA9IHRoaXMuYnVpbGRBZ2dyZWdhdGVRdWVyeSgpO1xuICAgIGlmIChhZ2dyZWdhdGVRdWVyeSkgcmV0dXJuIGFnZ3JlZ2F0ZVF1ZXJ5O1xuICAgIGNvbnN0IHNlbGVjdG9yczogTWFuZ29TZWxlY3RvciA9IHt9O1xuICAgIHNlbGVjdG9yc1tDb3VjaERCS2V5cy5UQUJMRV0gPSB7fTtcbiAgICBzZWxlY3RvcnNbQ291Y2hEQktleXMuVEFCTEVdID0gTW9kZWwudGFibGVOYW1lKHRoaXMuZnJvbVNlbGVjdG9yKTtcbiAgICBjb25zdCBxdWVyeTogTWFuZ29RdWVyeSA9IHsgc2VsZWN0b3I6IHNlbGVjdG9ycyB9O1xuICAgIGlmICh0aGlzLnNlbGVjdFNlbGVjdG9yKSBxdWVyeS5maWVsZHMgPSB0aGlzLnNlbGVjdFNlbGVjdG9yIGFzIHN0cmluZ1tdO1xuXG4gICAgaWYgKHRoaXMud2hlcmVDb25kaXRpb24pIHtcbiAgICAgIGNvbnN0IGNvbmRpdGlvbjogTWFuZ29TZWxlY3RvciA9IHRoaXMucGFyc2VDb25kaXRpb24oXG4gICAgICAgIENvbmRpdGlvbi5hbmQoXG4gICAgICAgICAgdGhpcy53aGVyZUNvbmRpdGlvbixcbiAgICAgICAgICBDb25kaXRpb24uYXR0cmlidXRlPE0+KENvdWNoREJLZXlzLlRBQkxFIGFzIGtleW9mIE0pLmVxKFxuICAgICAgICAgICAgcXVlcnkuc2VsZWN0b3JbQ291Y2hEQktleXMuVEFCTEVdXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNlbGVjdG9yO1xuICAgICAgY29uc3Qgc2VsZWN0b3JLZXlzID0gT2JqZWN0LmtleXMoY29uZGl0aW9uKSBhcyBNYW5nb09wZXJhdG9yW107XG4gICAgICBpZiAoXG4gICAgICAgIHNlbGVjdG9yS2V5cy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgT2JqZWN0LnZhbHVlcyhDb3VjaERCR3JvdXBPcGVyYXRvcikuaW5kZXhPZihzZWxlY3RvcktleXNbMF0pICE9PSAtMVxuICAgICAgKVxuICAgICAgICBzd2l0Y2ggKHNlbGVjdG9yS2V5c1swXSkge1xuICAgICAgICAgIGNhc2UgQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EOlxuICAgICAgICAgICAgY29uZGl0aW9uW0NvdWNoREJHcm91cE9wZXJhdG9yLkFORF0gPSBbXG4gICAgICAgICAgICAgIC4uLk9iamVjdC52YWx1ZXMoXG4gICAgICAgICAgICAgICAgY29uZGl0aW9uW0NvdWNoREJHcm91cE9wZXJhdG9yLkFORF0gYXMgTWFuZ29TZWxlY3RvclxuICAgICAgICAgICAgICApLnJlZHVjZSgoYWNjdW06IE1hbmdvU2VsZWN0b3JbXSwgdmFsOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXModmFsKTtcbiAgICAgICAgICAgICAgICBpZiAoa2V5cy5sZW5ndGggIT09IDEpXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiVG9vIG1hbnkga2V5cyBpbiBxdWVyeSBzZWxlY3Rvci4gc2hvdWxkIGJlIG9uZVwiXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGsgPSBrZXlzWzBdO1xuICAgICAgICAgICAgICAgIGlmIChrID09PSBDb3VjaERCR3JvdXBPcGVyYXRvci5BTkQpXG4gICAgICAgICAgICAgICAgICBhY2N1bS5wdXNoKC4uLih2YWxba10gYXMgYW55W10pKTtcbiAgICAgICAgICAgICAgICBlbHNlIGFjY3VtLnB1c2godmFsKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICAgICAgICAgIH0sIFtdKSxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBxdWVyeS5zZWxlY3RvciA9IGNvbmRpdGlvbjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgQ291Y2hEQkdyb3VwT3BlcmF0b3IuT1I6IHtcbiAgICAgICAgICAgIGNvbnN0IHM6IFJlY29yZDxhbnksIGFueT4gPSB7fTtcbiAgICAgICAgICAgIHNbQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EXSA9IFtcbiAgICAgICAgICAgICAgY29uZGl0aW9uLFxuICAgICAgICAgICAgICAuLi5PYmplY3QuZW50cmllcyhxdWVyeS5zZWxlY3RvcikubWFwKChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8YW55LCBhbnk+ID0ge307XG4gICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWw7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcXVlcnkuc2VsZWN0b3IgPSBzO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIHNob3VsZCBiZSBpbXBvc3NpYmxlXCIpO1xuICAgICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgT2JqZWN0LmVudHJpZXMoY29uZGl0aW9uKS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgICAgaWYgKHF1ZXJ5LnNlbGVjdG9yW2tleV0pXG4gICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgYEEgJHtrZXl9IHF1ZXJ5IHBhcmFtIGlzIGFib3V0IHRvIGJlIG92ZXJyaWRkZW46ICR7cXVlcnkuc2VsZWN0b3Jba2V5XX0gYnkgJHt2YWx9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBxdWVyeS5zZWxlY3RvcltrZXldID0gdmFsO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcmRlckJ5U2VsZWN0b3JzPy5sZW5ndGgpIHtcbiAgICAgIHF1ZXJ5LnNvcnQgPSBxdWVyeS5zb3J0IHx8IFtdO1xuICAgICAgcXVlcnkuc2VsZWN0b3IgPSBxdWVyeS5zZWxlY3RvciB8fCAoe30gYXMgTWFuZ29TZWxlY3Rvcik7XG4gICAgICBmb3IgKGNvbnN0IFtzZWxlY3RvcktleSwgZGlyZWN0aW9uXSBvZiB0aGlzLm9yZGVyQnlTZWxlY3RvcnMpIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSBzZWxlY3RvcktleSBhcyBzdHJpbmc7XG4gICAgICAgIGNvbnN0IHJlYzogUmVjb3JkPHN0cmluZywgT3JkZXJEaXJlY3Rpb24+ID0ge307XG4gICAgICAgIHJlY1tzZWxlY3Rvcl0gPSBkaXJlY3Rpb24gYXMgT3JkZXJEaXJlY3Rpb247XG4gICAgICAgIChxdWVyeS5zb3J0IGFzIFJlY29yZDxzdHJpbmcsIE9yZGVyRGlyZWN0aW9uPltdKS5wdXNoKHJlYyk7XG4gICAgICAgIGlmICghcXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdKSB7XG4gICAgICAgICAgcXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgICAgICAocXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdIGFzIE1hbmdvU2VsZWN0b3IpW0NvdWNoREJPcGVyYXRvci5CSUdHRVJdID1cbiAgICAgICAgICAgIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5saW1pdFNlbGVjdG9yKSB7XG4gICAgICBxdWVyeS5saW1pdCA9IHRoaXMubGltaXRTZWxlY3RvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLndhcm4oXG4gICAgICAgIGBObyBsaW1pdCBzZWxlY3RvciBkZWZpbmVkLiBVc2luZyBkZWZhdWx0IGNvdWNoZGIgbGltaXQgb2YgJHtDb3VjaERCUXVlcnlMaW1pdH1gXG4gICAgICApO1xuICAgICAgcXVlcnkubGltaXQgPSBDb3VjaERCUXVlcnlMaW1pdDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vZmZzZXRTZWxlY3RvcikgcXVlcnkuc2tpcCA9IHRoaXMub2Zmc2V0U2VsZWN0b3I7XG5cbiAgICByZXR1cm4gcXVlcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhIGNvbmRpdGlvbiBpbnRvIGEgQ291Y2hEQiBNYW5nbyBxdWVyeSBzZWxlY3RvclxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIENvbmRpdGlvbiBvYmplY3QgaW50byBhIENvdWNoREIgTWFuZ28gcXVlcnkgc2VsZWN0b3Igc3RydWN0dXJlXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcGFyc2VDb25kaXRpb24oY29uZGl0aW9uOiBDb25kaXRpb248TT4pOiBNYW5nb1F1ZXJ5IHtcbiAgICBmdW5jdGlvbiBtZXJnZShcbiAgICAgIG9wOiBNYW5nb09wZXJhdG9yLFxuICAgICAgb2JqMTogTWFuZ29TZWxlY3RvcixcbiAgICAgIG9iajI6IE1hbmdvU2VsZWN0b3JcbiAgICApOiBNYW5nb1F1ZXJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogTWFuZ29RdWVyeSA9IHsgc2VsZWN0b3I6IHt9IGFzIE1hbmdvU2VsZWN0b3IgfTtcbiAgICAgIHJlc3VsdC5zZWxlY3RvcltvcF0gPSBbb2JqMSwgb2JqMl07XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IHsgYXR0cjEsIG9wZXJhdG9yLCBjb21wYXJpc29uIH0gPSBjb25kaXRpb24gYXMgdW5rbm93biBhcyB7XG4gICAgICBhdHRyMTogc3RyaW5nIHwgQ29uZGl0aW9uPE0+O1xuICAgICAgb3BlcmF0b3I6IE9wZXJhdG9yIHwgR3JvdXBPcGVyYXRvcjtcbiAgICAgIGNvbXBhcmlzb246IGFueTtcbiAgICB9O1xuXG4gICAgaWYgKG9wZXJhdG9yID09PSBPcGVyYXRvci5TVEFSVFNfV0lUSCkge1xuICAgICAgaWYgKHR5cGVvZiBhdHRyMSAhPT0gXCJzdHJpbmdcIilcbiAgICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoXCJTVEFSVFNfV0lUSCByZXF1aXJlcyBhbiBhdHRyaWJ1dGUgbmFtZVwiKTtcbiAgICAgIGlmICh0eXBlb2YgY29tcGFyaXNvbiAhPT0gXCJzdHJpbmdcIilcbiAgICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoXCJTVEFSVFNfV0lUSCByZXF1aXJlcyBhIHN0cmluZyBjb21wYXJpc29uXCIpO1xuICAgICAgY29uc3QgcmFuZ2UgPSBwcmVmaXhSYW5nZShjb21wYXJpc29uKTtcbiAgICAgIGNvbnN0IHNlbGVjdG9yOiBNYW5nb1NlbGVjdG9yID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgIHNlbGVjdG9yW2F0dHIxXSA9IHt9IGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgICAoc2VsZWN0b3JbYXR0cjFdIGFzIE1hbmdvU2VsZWN0b3IpW0NvdWNoREJPcGVyYXRvci5CSUdHRVJfRVFdID0gcmFuZ2Uuc3RhcnQ7XG4gICAgICAoc2VsZWN0b3JbYXR0cjFdIGFzIE1hbmdvU2VsZWN0b3IpW0NvdWNoREJPcGVyYXRvci5TTUFMTEVSXSA9IHJhbmdlLmVuZDtcbiAgICAgIHJldHVybiB7IHNlbGVjdG9yIH07XG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdG9yID09PSBPcGVyYXRvci5FTkRTX1dJVEgpIHtcbiAgICAgIGlmICh0eXBlb2YgYXR0cjEgIT09IFwic3RyaW5nXCIpXG4gICAgICAgIHRocm93IG5ldyBRdWVyeUVycm9yKFwiRU5EU19XSVRIIHJlcXVpcmVzIGFuIGF0dHJpYnV0ZSBuYW1lXCIpO1xuICAgICAgaWYgKHR5cGVvZiBjb21wYXJpc29uICE9PSBcInN0cmluZ1wiKVxuICAgICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihcIkVORFNfV0lUSCByZXF1aXJlcyBhIHN0cmluZyBjb21wYXJpc29uXCIpO1xuICAgICAgY29uc3Qgc2VsZWN0b3I6IE1hbmdvU2VsZWN0b3IgPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgc2VsZWN0b3JbYXR0cjFdID0ge1xuICAgICAgICBbQ291Y2hEQk9wZXJhdG9yLlJFR0VYUF06IGAke2VzY2FwZVJlZ0V4cChjb21wYXJpc29uKX0kYCxcbiAgICAgIH0gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgIHJldHVybiB7IHNlbGVjdG9yIH07XG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdG9yID09PSBPcGVyYXRvci5CRVRXRUVOKSB7XG4gICAgICBjb25zdCBhdHRyID0gYXR0cjEgYXMgc3RyaW5nO1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbXBhcmlzb24pIHx8IGNvbXBhcmlzb24ubGVuZ3RoICE9PSAyKVxuICAgICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihcIkJFVFdFRU4gb3BlcmF0b3IgcmVxdWlyZXMgW21pbiwgbWF4XSBjb21wYXJpc29uXCIpO1xuICAgICAgY29uc3QgW21pbiwgbWF4XSA9IGNvbXBhcmlzb247XG4gICAgICBjb25zdCBvcEJldHdlZW46IE1hbmdvU2VsZWN0b3IgPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgb3BCZXR3ZWVuW2F0dHJdID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgIChvcEJldHdlZW5bYXR0cl0gYXMgTWFuZ29TZWxlY3RvcilbXG4gICAgICAgIHRyYW5zbGF0ZU9wZXJhdG9ycyhPcGVyYXRvci5CSUdHRVJfRVEpXG4gICAgICBdID0gbWluO1xuICAgICAgKG9wQmV0d2VlblthdHRyXSBhcyBNYW5nb1NlbGVjdG9yKVtcbiAgICAgICAgdHJhbnNsYXRlT3BlcmF0b3JzKE9wZXJhdG9yLlNNQUxMRVJfRVEpXG4gICAgICBdID0gbWF4O1xuICAgICAgcmV0dXJuIHsgc2VsZWN0b3I6IG9wQmV0d2VlbiB9O1xuICAgIH1cblxuICAgIGxldCBvcDogTWFuZ29TZWxlY3RvciA9IHt9IGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgaWYgKFxuICAgICAgW0dyb3VwT3BlcmF0b3IuQU5ELCBHcm91cE9wZXJhdG9yLk9SLCBPcGVyYXRvci5OT1RdLmluZGV4T2YoXG4gICAgICAgIG9wZXJhdG9yIGFzIEdyb3VwT3BlcmF0b3JcbiAgICAgICkgPT09IC0xXG4gICAgKSB7XG4gICAgICBvcFthdHRyMSBhcyBzdHJpbmddID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgIChvcFthdHRyMSBhcyBzdHJpbmddIGFzIE1hbmdvU2VsZWN0b3IpW3RyYW5zbGF0ZU9wZXJhdG9ycyhvcGVyYXRvcildID1cbiAgICAgICAgY29tcGFyaXNvbjtcbiAgICB9IGVsc2UgaWYgKG9wZXJhdG9yID09PSBPcGVyYXRvci5OT1QpIHtcbiAgICAgIG9wID0gdGhpcy5wYXJzZUNvbmRpdGlvbihhdHRyMSBhcyBDb25kaXRpb248TT4pLnNlbGVjdG9yIGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgICBvcFt0cmFuc2xhdGVPcGVyYXRvcnMoT3BlcmF0b3IuTk9UKV0gPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgKG9wW3RyYW5zbGF0ZU9wZXJhdG9ycyhPcGVyYXRvci5OT1QpXSBhcyBNYW5nb1NlbGVjdG9yKVtcbiAgICAgICAgKGF0dHIxIGFzIHVua25vd24gYXMgeyBhdHRyMTogc3RyaW5nIH0pLmF0dHIxXG4gICAgICBdID0gY29tcGFyaXNvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3AxOiBhbnkgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKGF0dHIxIGFzIENvbmRpdGlvbjxNPikuc2VsZWN0b3I7XG4gICAgICBjb25zdCBvcDI6IGFueSA9IHRoaXMucGFyc2VDb25kaXRpb24oY29tcGFyaXNvbiBhcyBDb25kaXRpb248TT4pLnNlbGVjdG9yO1xuICAgICAgb3AgPSBtZXJnZSh0cmFuc2xhdGVPcGVyYXRvcnMob3BlcmF0b3IpLCBvcDEsIG9wMikuc2VsZWN0b3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgc2VsZWN0b3I6IG9wIH07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1aWxkcyBhbiBhZ2dyZWdhdGUgcXVlcnkgaWYgYWdncmVnYXRpb24gaXMgcmVxdWVzdGVkXG4gICAqIEBzdW1tYXJ5IENoZWNrcyBmb3IgYWdncmVnYXRlIG9wZXJhdGlvbnMgYW5kIHJldHVybnMgYSBzcGVjaWFsIE1hbmdvUXVlcnkgZm9yIHRoZW1cbiAgICovXG4gIHByaXZhdGUgYnVpbGRBZ2dyZWdhdGVRdWVyeSgpOiBNYW5nb1F1ZXJ5IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuZnJvbVNlbGVjdG9yKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLmF2Z1NlbGVjdG9yKSB7XG4gICAgICBjb25zdCBhdHRyaWJ1dGUgPSBTdHJpbmcodGhpcy5hdmdTZWxlY3Rvcik7XG4gICAgICBjb25zdCBzdW1JbmZvID0gdGhpcy5jcmVhdGVBZ2dyZWdhdGVEZXNjcmlwdG9yKFwic3VtXCIsIGF0dHJpYnV0ZSk7XG4gICAgICBjb25zdCBjb3VudEluZm8gPSB0aGlzLmNyZWF0ZUFnZ3JlZ2F0ZURlc2NyaXB0b3IoXCJjb3VudFwiLCBhdHRyaWJ1dGUpO1xuICAgICAgaWYgKCFzdW1JbmZvIHx8ICFjb3VudEluZm8pXG4gICAgICAgIHRocm93IG5ldyBRdWVyeUVycm9yKFxuICAgICAgICAgIGBBdmcgb3BlcmF0aW9uIHJlcXVpcmVzIHN1bSBhbmQgY291bnQgdmlld3MgZm9yIGF0dHJpYnV0ZSAke2F0dHJpYnV0ZX1gXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVBZ2dyZWdhdGVRdWVyeSh7XG4gICAgICAgIGtpbmQ6IFwiYXZnXCIsXG4gICAgICAgIGF0dHJpYnV0ZSxcbiAgICAgICAgc3VtRGVzY3JpcHRvcjogc3VtSW5mby5kZXNjcmlwdG9yLFxuICAgICAgICBjb3VudERlc2NyaXB0b3I6IGNvdW50SW5mby5kZXNjcmlwdG9yLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmNvdW50RGlzdGluY3RTZWxlY3RvciAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgY29uc3QgYXR0cmlidXRlID1cbiAgICAgICAgdGhpcy5jb3VudERpc3RpbmN0U2VsZWN0b3IgPT0gbnVsbFxuICAgICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgICAgOiBTdHJpbmcodGhpcy5jb3VudERpc3RpbmN0U2VsZWN0b3IpO1xuICAgICAgY29uc3QgaW5mbyA9IHRoaXMuY3JlYXRlQWdncmVnYXRlRGVzY3JpcHRvcihcImRpc3RpbmN0XCIsIGF0dHJpYnV0ZSk7XG4gICAgICBpZiAoaW5mbykge1xuICAgICAgICBpbmZvLmNvdW50RGlzdGluY3QgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVBZ2dyZWdhdGVRdWVyeShpbmZvKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBhZ2dyZWdhdG9yVXNlZCA9XG4gICAgICB0eXBlb2YgdGhpcy5jb3VudFNlbGVjdG9yICE9PSBcInVuZGVmaW5lZFwiIHx8XG4gICAgICB0eXBlb2YgdGhpcy5jb3VudERpc3RpbmN0U2VsZWN0b3IgIT09IFwidW5kZWZpbmVkXCIgfHxcbiAgICAgICEhdGhpcy5taW5TZWxlY3RvciB8fFxuICAgICAgISF0aGlzLm1heFNlbGVjdG9yIHx8XG4gICAgICAhIXRoaXMuc3VtU2VsZWN0b3IgfHxcbiAgICAgICEhdGhpcy5kaXN0aW5jdFNlbGVjdG9yO1xuXG4gICAgY29uc3QgYWdncmVnYXRvckNoZWNrczogQXJyYXk8W1ZpZXdLaW5kLCBTZWxlY3RTZWxlY3RvcjxNPiB8IHVuZGVmaW5lZF0+ID0gW1xuICAgICAgW1xuICAgICAgICBcImNvdW50XCIsXG4gICAgICAgICh0aGlzLmNvdW50U2VsZWN0b3IgPz8gdW5kZWZpbmVkKSBhcyBTZWxlY3RTZWxlY3RvcjxNPiB8IHVuZGVmaW5lZCxcbiAgICAgIF0sXG4gICAgICBbXCJtYXhcIiwgdGhpcy5tYXhTZWxlY3Rvcl0sXG4gICAgICBbXCJtaW5cIiwgdGhpcy5taW5TZWxlY3Rvcl0sXG4gICAgICBbXCJzdW1cIiwgdGhpcy5zdW1TZWxlY3Rvcl0sXG4gICAgICBbXCJkaXN0aW5jdFwiLCB0aGlzLmRpc3RpbmN0U2VsZWN0b3JdLFxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IFtraW5kLCBzZWxlY3Rvcl0gb2YgYWdncmVnYXRvckNoZWNrcykge1xuICAgICAgY29uc3QgYXR0cmlidXRlID0gc2VsZWN0b3IgPyBTdHJpbmcoc2VsZWN0b3IpIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaW5mbyA9IHRoaXMuY3JlYXRlQWdncmVnYXRlRGVzY3JpcHRvcihraW5kLCBhdHRyaWJ1dGUpO1xuICAgICAgaWYgKGluZm8pIHJldHVybiB0aGlzLmNyZWF0ZUFnZ3JlZ2F0ZVF1ZXJ5KGluZm8pO1xuICAgIH1cblxuICAgIGlmIChhZ2dyZWdhdG9yVXNlZCkge1xuICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoXG4gICAgICAgIGBObyBDb3VjaERCIHZpZXcgbWV0YWRhdGEgZm91bmQgZm9yIHRhYmxlICR7TW9kZWwudGFibGVOYW1lKFxuICAgICAgICAgIHRoaXMuZnJvbVNlbGVjdG9yXG4gICAgICAgICl9IGFnZ3JlZ2F0b3JgXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGFuIGFnZ3JlZ2F0ZSBkZXNjcmlwdG9yIGZvciBhIHZpZXctYmFzZWQgYWdncmVnYXRpb25cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQWdncmVnYXRlRGVzY3JpcHRvcihcbiAgICBraW5kOiBWaWV3S2luZCxcbiAgICBhdHRyaWJ1dGU/OiBzdHJpbmdcbiAgKTogRXh0cmFjdDxGYWJyaWNBZ2dyZWdhdGVJbmZvLCB7IGtpbmQ6IFZpZXdLaW5kIH0+IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuZnJvbVNlbGVjdG9yKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IG1ldGFzID0gZmluZFZpZXdNZXRhZGF0YSh0aGlzLmZyb21TZWxlY3Rvciwga2luZCwgYXR0cmlidXRlKTtcbiAgICBpZiAoIW1ldGFzLmxlbmd0aCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBtZXRhID0gbWV0YXNbMF07XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKHRoaXMuZnJvbVNlbGVjdG9yKTtcbiAgICBjb25zdCB2aWV3TmFtZSA9IGdlbmVyYXRlVmlld05hbWUodGFibGVOYW1lLCBtZXRhLmF0dHJpYnV0ZSwga2luZCwgbWV0YSk7XG4gICAgY29uc3QgZGRvYyA9IG1ldGEuZGRvYyB8fCBnZW5lcmF0ZURlc2lnbkRvY05hbWUodGFibGVOYW1lLCB2aWV3TmFtZSk7XG4gICAgY29uc3Qgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHtcbiAgICAgIHJlZHVjZTogbWV0YS5yZWR1Y2UgIT09IHVuZGVmaW5lZCA/IHRydWUgOiAhbWV0YS5yZXR1cm5Eb2NzLFxuICAgIH07XG4gICAgaWYgKGtpbmQgPT09IFwiZGlzdGluY3RcIiB8fCBraW5kID09PSBcImdyb3VwQnlcIikgb3B0aW9ucy5ncm91cCA9IHRydWU7XG4gICAgcmV0dXJuIHtcbiAgICAgIGtpbmQsXG4gICAgICBtZXRhLFxuICAgICAgZGVzY3JpcHRvcjoge1xuICAgICAgICBkZG9jLFxuICAgICAgICB2aWV3OiB2aWV3TmFtZSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyB0aGUgc3BlY2lhbCBhZ2dyZWdhdGUgTWFuZ29RdWVyeSBtYXJrZXJcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQWdncmVnYXRlUXVlcnkoXG4gICAgaW5mbzogRmFicmljQWdncmVnYXRlSW5mb1xuICApOiBNYW5nb1F1ZXJ5ICYgeyBhZ2dyZWdhdGU6IHRydWU7IGFnZ3JlZ2F0ZUluZm86IEZhYnJpY0FnZ3JlZ2F0ZUluZm8gfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNlbGVjdG9yOiB7fSxcbiAgICAgIGFnZ3JlZ2F0ZTogdHJ1ZSxcbiAgICAgIGFnZ3JlZ2F0ZUluZm86IGluZm8sXG4gICAgfSBhcyBNYW5nb1F1ZXJ5ICYgeyBhZ2dyZWdhdGU6IHRydWU7IGFnZ3JlZ2F0ZUluZm86IEZhYnJpY0FnZ3JlZ2F0ZUluZm8gfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgYWRhcHRlciBjYXN0IHRvIEZhYnJpY0NsaWVudEFkYXB0ZXIgZm9yIHZpZXcgYWNjZXNzXG4gICAqL1xuICBwcml2YXRlIGdldEZhYnJpY0FkYXB0ZXIoKTogRmFicmljQ2xpZW50QWRhcHRlciB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlciBhcyBGYWJyaWNDbGllbnRBZGFwdGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhbiBhZ2dyZWdhdGUgcXVlcnkgdmlhIGFkYXB0ZXIncyB2aWV3IG1ldGhvZFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlQWdncmVnYXRlPFI+KFxuICAgIGluZm86IEZhYnJpY0FnZ3JlZ2F0ZUluZm8sXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPlxuICApOiBQcm9taXNlPFI+IHtcbiAgICBpZiAoIXRoaXMuaXNWaWV3QWdncmVnYXRlKGluZm8pKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVBdmVyYWdlPFI+KGluZm8sIGN0eCk7XG4gICAgfVxuICAgIGNvbnN0IGZhYnJpY0FkYXB0ZXIgPSB0aGlzLmdldEZhYnJpY0FkYXB0ZXIoKTtcbiAgICBjb25zdCB2aWV3SW5mbyA9IGluZm8gYXMgRXh0cmFjdDxGYWJyaWNBZ2dyZWdhdGVJbmZvLCB7IGtpbmQ6IFZpZXdLaW5kIH0+O1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmFicmljQWRhcHRlci52aWV3PFZpZXdSZXNwb25zZT4oXG4gICAgICB2aWV3SW5mby5kZXNjcmlwdG9yLmRkb2MsXG4gICAgICB2aWV3SW5mby5kZXNjcmlwdG9yLnZpZXcsXG4gICAgICB2aWV3SW5mby5kZXNjcmlwdG9yLm9wdGlvbnMsXG4gICAgICBjdHhcbiAgICApO1xuICAgIHJldHVybiB0aGlzLnByb2Nlc3NWaWV3UmVzcG9uc2U8Uj4oaW5mbywgcmVzcG9uc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIGF2ZXJhZ2UgY2FsY3VsYXRpb24gZnJvbSBzdW0gYW5kIGNvdW50IHZpZXdzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGhhbmRsZUF2ZXJhZ2U8Uj4oXG4gICAgaW5mbzogRmFicmljQWdncmVnYXRlSW5mbyxcbiAgICBjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+XG4gICk6IFByb21pc2U8Uj4ge1xuICAgIGlmIChpbmZvLmtpbmQgIT09IFwiYXZnXCIpXG4gICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihcIkF2ZXJhZ2UgZGVzY3JpcHRvciBpcyBub3QgdmFsaWRcIik7XG4gICAgY29uc3QgZmFicmljQWRhcHRlciA9IHRoaXMuZ2V0RmFicmljQWRhcHRlcigpO1xuICAgIGNvbnN0IFtzdW1EZXNjLCBjb3VudERlc2NdID0gW2luZm8uc3VtRGVzY3JpcHRvciwgaW5mby5jb3VudERlc2NyaXB0b3JdO1xuICAgIGNvbnN0IFtzdW1SZXNwb25zZSwgY291bnRSZXNwb25zZV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBmYWJyaWNBZGFwdGVyLnZpZXc8Vmlld1Jlc3BvbnNlPihcbiAgICAgICAgc3VtRGVzYy5kZG9jLFxuICAgICAgICBzdW1EZXNjLnZpZXcsXG4gICAgICAgIHN1bURlc2Mub3B0aW9ucyxcbiAgICAgICAgY3R4XG4gICAgICApLFxuICAgICAgZmFicmljQWRhcHRlci52aWV3PFZpZXdSZXNwb25zZT4oXG4gICAgICAgIGNvdW50RGVzYy5kZG9jLFxuICAgICAgICBjb3VudERlc2MudmlldyxcbiAgICAgICAgY291bnREZXNjLm9wdGlvbnMsXG4gICAgICAgIGN0eFxuICAgICAgKSxcbiAgICBdKTtcbiAgICBjb25zdCBzdW0gPSBzdW1SZXNwb25zZS5yb3dzPy5bMF0/LnZhbHVlID8/IDA7XG4gICAgY29uc3QgY291bnQgPSBjb3VudFJlc3BvbnNlLnJvd3M/LlswXT8udmFsdWUgPz8gMDtcbiAgICBpZiAoIWNvdW50KSByZXR1cm4gMCBhcyB1bmtub3duIGFzIFI7XG4gICAgcmV0dXJuIChzdW0gLyBjb3VudCkgYXMgdW5rbm93biBhcyBSO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgdGhlIHZpZXcgcmVzcG9uc2UgYmFzZWQgb24gYWdncmVnYXRlIGtpbmRcbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc1ZpZXdSZXNwb25zZTxSPihcbiAgICBpbmZvOiBGYWJyaWNBZ2dyZWdhdGVJbmZvLFxuICAgIHJlc3BvbnNlOiBWaWV3UmVzcG9uc2VcbiAgKTogUiB7XG4gICAgaWYgKGluZm8ua2luZCA9PT0gXCJhdmdcIilcbiAgICAgIHRocm93IG5ldyBRdWVyeUVycm9yKFxuICAgICAgICBcIkF2ZXJhZ2UgcmVzdWx0cyBzaG91bGQgYmUgaGFuZGxlZCBiZWZvcmUgcHJvY2Vzc2luZyByb3dzXCJcbiAgICAgICk7XG4gICAgY29uc3Qgcm93cyA9IHJlc3BvbnNlLnJvd3MgfHwgW107XG4gICAgY29uc3Qgdmlld0luZm8gPSBpbmZvIGFzIEV4dHJhY3Q8RmFicmljQWdncmVnYXRlSW5mbywgeyBraW5kOiBWaWV3S2luZCB9PjtcbiAgICBjb25zdCBtZXRhID0gdmlld0luZm8ubWV0YTtcbiAgICBpZiAodmlld0luZm8uY291bnREaXN0aW5jdCkge1xuICAgICAgcmV0dXJuIChyb3dzLmxlbmd0aCB8fCAwKSBhcyB1bmtub3duIGFzIFI7XG4gICAgfVxuICAgIGlmICh2aWV3SW5mby5raW5kID09PSBcImRpc3RpbmN0XCIgfHwgdmlld0luZm8ua2luZCA9PT0gXCJncm91cEJ5XCIpIHtcbiAgICAgIHJldHVybiByb3dzLm1hcCgocm93KSA9PiByb3cua2V5ID8/IHJvdy52YWx1ZSkgYXMgdW5rbm93biBhcyBSO1xuICAgIH1cbiAgICBpZiAobWV0YS5yZXR1cm5Eb2NzKSB7XG4gICAgICByZXR1cm4gcm93cy5tYXAoKHJvdykgPT4gcm93LnZhbHVlID8/IHJvdy5kb2MgPz8gcm93KSBhcyB1bmtub3duIGFzIFI7XG4gICAgfVxuICAgIGlmICghcm93cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiAodmlld0luZm8ua2luZCA9PT0gXCJjb3VudFwiID8gMCA6IG51bGwpIGFzIHVua25vd24gYXMgUjtcbiAgICB9XG4gICAgcmV0dXJuIChyb3dzWzBdLnZhbHVlID8/IHJvd3NbMF0ua2V5ID8/IG51bGwpIGFzIHVua25vd24gYXMgUjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVHlwZSBndWFyZCB0byBjaGVjayBpZiBpbmZvIGlzIGEgdmlldy1iYXNlZCBhZ2dyZWdhdGVcbiAgICovXG4gIHByaXZhdGUgaXNWaWV3QWdncmVnYXRlKFxuICAgIGluZm86IEZhYnJpY0FnZ3JlZ2F0ZUluZm9cbiAgKTogaW5mbyBpcyBFeHRyYWN0PEZhYnJpY0FnZ3JlZ2F0ZUluZm8sIHsga2luZDogVmlld0tpbmQgfT4ge1xuICAgIHJldHVybiBpbmZvLmtpbmQgIT09IFwiYXZnXCI7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgUGFnaW5hdG9yLFxuICBQcmVwYXJlZFN0YXRlbWVudCxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRBZGFwdGVyIH0gZnJvbSBcIi4vRmFicmljQ2xpZW50QWRhcHRlclwiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcblxuZXhwb3J0IGNsYXNzIEZhYnJpY0NsaWVudFBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgUGFnaW5hdG9yPFxuICBNLFxuICBNW10sXG4gIE1hbmdvUXVlcnlcbj4ge1xuICBib29rbWFyaz86IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyOiBGYWJyaWNDbGllbnRBZGFwdGVyLFxuICAgIHF1ZXJ5OiBNYW5nb1F1ZXJ5IHwgUHJlcGFyZWRTdGF0ZW1lbnQ8YW55PixcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHByb3RlY3RlZCBwcmVwYXJlKHJhd1N0YXRlbWVudDogTWFuZ29RdWVyeSk6IE1hbmdvUXVlcnkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgYFJhdyBxdWVyeSBhY2Nlc3MgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBhIHN1YmNsYXNzLiBvbmx5IHByZXBhcmVkIHN0YXRlbWVudHMgYXJlIG5hdGl2ZWx5IGF2YWlsYWJsZWBcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgcGFnZShcbiAgICBwYWdlOiBudW1iZXIgPSAxLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIHN1cGVyLnBhZ2UocGFnZSwgLi4uYXJncyk7IC8vIHRoaXMgd2lsbCBmYWlsIGZvciBub24tcHJlcGFyZWQgc3RhdGVtZW50c1xuICB9XG59XG4iLCJpbXBvcnQgXCIuLi9zaGFyZWQvb3ZlcnJpZGVzXCI7XG5pbXBvcnQge1xuICBDb3VjaERCS2V5cyxcbiAgdHlwZSBNYW5nb1F1ZXJ5LFxuICB0eXBlIFZpZXdSZXNwb25zZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgQ2xpZW50IH0gZnJvbSBcIkBncnBjL2dycGMtanNcIjtcbmltcG9ydCAqIGFzIGdycGMgZnJvbSBcIkBncnBjL2dycGMtanNcIjtcbmltcG9ydCB7XG4gIE1vZGVsLFxuICB0eXBlIE1vZGVsQ29uc3RydWN0b3IsXG4gIHR5cGUgU2VyaWFsaXplcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgZGVidWcsIGZpbmFsLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyB0eXBlIFBlZXJDb25maWcsIHR5cGUgU2VncmVnYXRlZE1vZGVsIH0gZnJvbSBcIi4uL3NoYXJlZC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgY29ubmVjdCxcbiAgdHlwZSBDb25uZWN0T3B0aW9ucyxcbiAgR2F0ZXdheSxcbiAgTmV0d29yayxcbiAgUHJvcG9zYWxPcHRpb25zLFxuICBDb250cmFjdCBhcyBDb250cmFrdCxcbiAgdHlwZSBTaWduZXIsXG59IGZyb20gXCJAaHlwZXJsZWRnZXIvZmFicmljLWdhdGV3YXlcIjtcbmltcG9ydCB7IGdldElkZW50aXR5LCBnZXRTaWduZXIgfSBmcm9tIFwiLi9mYWJyaWMtZnNcIjtcbmltcG9ydCB7XG4gIEJhc2VFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIENvbmZsaWN0RXJyb3IsXG4gIEJhZFJlcXVlc3RFcnJvcixcbiAgdHlwZSBQcmltYXJ5S2V5VHlwZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDb250ZXh0LFxuICBBZGFwdGVyLFxuICB0eXBlIEFkYXB0ZXJGbGFncyxcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIEZvcmJpZGRlbkVycm9yLFxuICBNaWdyYXRpb25FcnJvcixcbiAgT2JzZXJ2ZXJFcnJvcixcbiAgUGFnaW5nRXJyb3IsXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUXVlcnlFcnJvcixcbiAgUmVwb3NpdG9yeSxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgU3RhdGVtZW50LFxuICB0eXBlIFByZXBhcmVkU3RhdGVtZW50LFxuICBQYWdpbmF0b3IsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIHR5cGUgUHJlcGFyZWRNb2RlbCxcbiAgQWxsT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IENsaWVudFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vc2hhcmVkL0NsaWVudFNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudERpc3BhdGNoIH0gZnJvbSBcIi4vRmFicmljQ2xpZW50RGlzcGF0Y2hcIjtcbi8vIGltcG9ydCB7IEhTTVNpZ25lckZhY3RvcnlDdXN0b20gfSBmcm9tIFwiLi9mYWJyaWMtaHNtXCI7XG5pbXBvcnQgeyB0eXBlIENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDbGllbnRTdGF0ZW1lbnQgfSBmcm9tIFwiLi9GYWJyaWNDbGllbnRTdGF0ZW1lbnRcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudFBhZ2luYXRvciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudFBhZ2luYXRvclwiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50UmVwb3NpdG9yeSB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudFJlcG9zaXRvcnlcIjtcbmltcG9ydCB7XG4gIEVuZG9yc2VtZW50RXJyb3IsXG4gIEVuZG9yc2VtZW50UG9saWN5RXJyb3IsXG4gIE12Y2NSZWFkQ29uZmxpY3RFcnJvcixcbiAgUGhhbnRvbVJlYWRDb25mbGljdEVycm9yLFxuICBUcmFuc2FjdGlvblRpbWVvdXRFcnJvcixcbn0gZnJvbSBcIi4uL3NoYXJlZC9lcnJvcnNcIjtcbmltcG9ydCB7IEZhYnJpY0NsaWVudEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRGYWJyaWNDbGllbnRGbGFncyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgQ3J5cHRvVXRpbHMgfSBmcm9tIFwiLi9jcnlwdG9cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQWRhcHRlciBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBIeXBlcmxlZGdlciBGYWJyaWMgbmV0d29ya3NcbiAqIEBzdW1tYXJ5IFRoZSBGYWJyaWNBZGFwdGVyIGV4dGVuZHMgQ291Y2hEQkFkYXB0ZXIgdG8gcHJvdmlkZSBhIHNlYW1sZXNzIGludGVyZmFjZSBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBIeXBlcmxlZGdlciBGYWJyaWMgbmV0d29ya3MuXG4gKiBJdCBoYW5kbGVzIGNvbm5lY3Rpb24gbWFuYWdlbWVudCwgdHJhbnNhY3Rpb24gc3VibWlzc2lvbiwgYW5kIENSVUQgb3BlcmF0aW9ucyBhZ2FpbnN0IEZhYnJpYyBjaGFpbmNvZGUuXG4gKiBAdGVtcGxhdGUgUGVlckNvbmZpZyAtIENvbmZpZ3VyYXRpb24gdHlwZSBmb3IgY29ubmVjdGluZyB0byBhIEZhYnJpYyBwZWVyXG4gKiBAdGVtcGxhdGUgRmFicmljRmxhZ3MgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIENvbnRleHQ8RmFicmljRmxhZ3M+IC0gQ29udGV4dCB0eXBlIGNvbnRhaW5pbmcgRmFicmljLXNwZWNpZmljIGZsYWdzXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBmb3IgY29ubmVjdGluZyB0byBhIEZhYnJpYyBwZWVyXG4gKiBAcGFyYW0gYWxpYXMgLSBPcHRpb25hbCBhbGlhcyBmb3IgdGhlIGFkYXB0ZXIgaW5zdGFuY2VcbiAqIEBjbGFzcyBGYWJyaWNDbGllbnRBZGFwdGVyXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ3JlYXRlIGEgbmV3IEZhYnJpY0FkYXB0ZXIgaW5zdGFuY2VcbiAqIGNvbnN0IGNvbmZpZzogUGVlckNvbmZpZyA9IHtcbiAqICAgbXNwSWQ6ICdPcmcxTVNQJyxcbiAqICAgcGVlckVuZHBvaW50OiAnbG9jYWxob3N0OjcwNTEnLFxuICogICBjaGFubmVsTmFtZTogJ215Y2hhbm5lbCcsXG4gKiAgIGNoYWluY29kZU5hbWU6ICdteWNjJyxcbiAqICAgY29udHJhY3ROYW1lOiAnbXljb250cmFjdCcsXG4gKiAgIHRsc0NlcnRQYXRoOiAnL3BhdGgvdG8vdGxzL2NlcnQnLFxuICogICBjZXJ0RGlyZWN0b3J5UGF0aDogJy9wYXRoL3RvL2NlcnQvZGlyJyxcbiAqICAga2V5RGlyZWN0b3J5UGF0aDogJy9wYXRoL3RvL2tleS9kaXInXG4gKiB9O1xuICpcbiAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgRmFicmljQWRhcHRlcihjb25maWcsICdvcmcxLWFkYXB0ZXInKTtcbiAqXG4gKiAvLyBVc2UgdGhlIGFkYXB0ZXIgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgRmFicmljIG5ldHdvcmtcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFkYXB0ZXIucmVhZCgndXNlcnMnLCAndXNlcjEnLCBteVNlcmlhbGl6ZXIpO1xuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBGYWJyaWNBZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IEdhdGV3YXlcbiAqICAgcGFydGljaXBhbnQgTmV0d29ya1xuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBDaGFpbmNvZGVcbiAqXG4gKiAgIENsaWVudC0+PkZhYnJpY0FkYXB0ZXI6IGNyZWF0ZSh0YWJsZU5hbWUsIGlkLCBtb2RlbCwgdHJhbnNpZW50LCBzZXJpYWxpemVyKVxuICogICBGYWJyaWNBZGFwdGVyLT4+RmFicmljQWRhcHRlcjogc3VibWl0VHJhbnNhY3Rpb24oT3BlcmF0aW9uS2V5cy5DUkVBVEUsIFtzZXJpYWxpemVkTW9kZWxdLCB0cmFuc2llbnQpXG4gKiAgIEZhYnJpY0FkYXB0ZXItPj5HYXRld2F5OiBjb25uZWN0KClcbiAqICAgR2F0ZXdheS0+Pk5ldHdvcms6IGdldE5ldHdvcmsoY2hhbm5lbE5hbWUpXG4gKiAgIE5ldHdvcmstPj5Db250cmFjdDogZ2V0Q29udHJhY3QoY2hhaW5jb2RlTmFtZSwgY29udHJhY3ROYW1lKVxuICogICBGYWJyaWNBZGFwdGVyLT4+Q29udHJhY3Q6IHN1Ym1pdChhcGksIHByb3Bvc2FsT3B0aW9ucylcbiAqICAgQ29udHJhY3QtPj5DaGFpbmNvZGU6IGludm9rZVxuICogICBDaGFpbmNvZGUtLT4+Q29udHJhY3Q6IHJlc3BvbnNlXG4gKiAgIENvbnRyYWN0LS0+PkZhYnJpY0FkYXB0ZXI6IHJlc3VsdFxuICogICBGYWJyaWNBZGFwdGVyLT4+RmFicmljQWRhcHRlcjogZGVjb2RlKHJlc3VsdClcbiAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IHNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoZGVjb2RlZFJlc3VsdClcbiAqICAgRmFicmljQWRhcHRlci0tPj5DbGllbnQ6IGRlc2VyaWFsaXplZFJlc3VsdFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ2xpZW50QWRhcHRlciBleHRlbmRzIEFkYXB0ZXI8XG4gIFBlZXJDb25maWcsXG4gIENsaWVudCxcbiAgTWFuZ29RdWVyeSxcbiAgQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz5cbj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyB0ZXh0IGRlY29kZXIgZm9yIGNvbnZlcnRpbmcgVWludDhBcnJheSB0byBzdHJpbmdcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGY4XCIpO1xuXG4gIHByaXZhdGUgc3RhdGljIHNlcmlhbGl6ZXIgPSBuZXcgQ2xpZW50U2VyaWFsaXplcigpO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgbG9nID0gTG9nZ2luZy5mb3IoRmFicmljQ2xpZW50QWRhcHRlcik7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8YW55PiA9XG4gICAgRmFicmljQ2xpZW50QWRhcHRlci5zZXJpYWxpemVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNBZGFwdGVyIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggYSBIeXBlcmxlZGdlciBGYWJyaWMgbmV0d29ya1xuICAgKiBAcGFyYW0ge1BlZXJDb25maWd9IGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gZm9yIGNvbm5lY3RpbmcgdG8gYSBGYWJyaWMgcGVlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FsaWFzXSAtIE9wdGlvbmFsIGFsaWFzIGZvciB0aGUgYWRhcHRlciBpbnN0YW5jZVxuICAgKi9cbiAgY29uc3RydWN0b3IoY29uZmlnOiBQZWVyQ29uZmlnLCBhbGlhcz86IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgRGVmYXVsdEZhYnJpY0NsaWVudEZsYWdzLCBjb25maWcpLFxuICAgICAgRmFicmljRmxhdm91cixcbiAgICAgIGFsaWFzXG4gICAgKTtcbiAgfVxuXG4gIG92ZXJyaWRlIFN0YXRlbWVudDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8QWRhcHRlckZsYWdzPlxuICApOiBTdGF0ZW1lbnQ8TSwgRmFicmljQ2xpZW50QWRhcHRlciwgYW55LCBNYW5nb1F1ZXJ5PiB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDbGllbnRTdGF0ZW1lbnQodGhpcywgb3ZlcnJpZGVzKTtcbiAgfVxuXG4gIFBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHF1ZXJ5OiBQcmVwYXJlZFN0YXRlbWVudDxhbnk+IHwgTWFuZ29RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICk6IFBhZ2luYXRvcjxNLCBhbnksIE1hbmdvUXVlcnk+IHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NsaWVudFBhZ2luYXRvcih0aGlzLCBxdWVyeSwgc2l6ZSwgY2xhenopO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGZsYWdzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzIHwgc3RyaW5nLFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiB8IENvbnN0cnVjdG9yPE0+W10gfCB1bmRlZmluZWQsXG4gICAgZmxhZ3M6IFBhcnRpYWw8RmFicmljQ2xpZW50RmxhZ3M+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8RmFicmljQ2xpZW50RmxhZ3M+IHtcbiAgICBjb25zdCBmID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIGF3YWl0IHN1cGVyLmZsYWdzKFxuICAgICAgICBvcGVyYXRpb24sXG4gICAgICAgIG1vZGVsLFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmNvbmZpZywgZmxhZ3MpLFxuICAgICAgICAuLi5hcmdzXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gZjtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGNvbnRleHQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBvcGVyYXRpb246ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBBbGxPcGVyYXRpb25LZXlzLFxuICAgIG92ZXJyaWRlczogUGFydGlhbDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+IHwgQ29uc3RydWN0b3I8TT5bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dDxhbnk+PlxuICApOiBQcm9taXNlPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PiB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuY29udGV4dCk7XG4gICAgbG9nLnNpbGx5KFxuICAgICAgYGNyZWF0aW5nIG5ldyBjb250ZXh0IGZvciAke29wZXJhdGlvbn0gb3BlcmF0aW9uIG9uICR7bW9kZWwgPyAoQXJyYXkuaXNBcnJheShtb2RlbCkgPyBtb2RlbC5tYXAoKG0pID0+IE1vZGVsLnRhYmxlTmFtZShtKSkgOiBNb2RlbC50YWJsZU5hbWUobW9kZWwpKSA6IFwibm9cIn0gdGFibGUgJHtvdmVycmlkZXMgJiYgT2JqZWN0LmtleXMob3ZlcnJpZGVzKSA/IE9iamVjdC5rZXlzKG92ZXJyaWRlcykubGVuZ3RoIDogXCJub1wifSB3aXRoIGZsYWcgb3ZlcnJpZGVzYFxuICAgICk7XG4gICAgbGV0IGN0eCA9IGFyZ3MucG9wKCk7XG4gICAgaWYgKHR5cGVvZiBjdHggIT09IFwidW5kZWZpbmVkXCIgJiYgIShjdHggaW5zdGFuY2VvZiBDb250ZXh0KSkge1xuICAgICAgYXJncy5wdXNoKGN0eCk7XG4gICAgICBjdHggPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgb3ZlcnJpZGVzID0gY3R4XG4gICAgICA/IE9iamVjdC5hc3NpZ24oe30sIGN0eC50b092ZXJyaWRlcygpLCBvdmVycmlkZXMpXG4gICAgICA6IG92ZXJyaWRlcztcbiAgICBjb25zdCBmbGFncyA9IGF3YWl0IHRoaXMuZmxhZ3MoXG4gICAgICB0eXBlb2Ygb3BlcmF0aW9uID09PSBcInN0cmluZ1wiID8gb3BlcmF0aW9uIDogb3BlcmF0aW9uLm5hbWUsXG4gICAgICBtb2RlbCxcbiAgICAgIG92ZXJyaWRlcyBhcyBQYXJ0aWFsPEZhYnJpY0NsaWVudEZsYWdzPixcbiAgICAgIC4uLlsuLi5hcmdzLCBjdHhdLmZpbHRlcihCb29sZWFuKVxuICAgICk7XG5cbiAgICBpZiAoY3R4KSB7XG4gICAgICBpZiAoIShjdHggaW5zdGFuY2VvZiB0aGlzLkNvbnRleHQpKSB7XG4gICAgICAgIGNvbnN0IG5ld0N0eCA9IG5ldyB0aGlzLkNvbnRleHQoKS5hY2N1bXVsYXRlKHtcbiAgICAgICAgICAuLi5jdHhbXCJjYWNoZVwiXSxcbiAgICAgICAgICAuLi5mbGFncyxcbiAgICAgICAgICBwYXJlbnRDb250ZXh0OiBjdHgsXG4gICAgICAgIH0pIGFzIGFueTtcbiAgICAgICAgY3R4LmFjY3VtdWxhdGUoe1xuICAgICAgICAgIGNoaWxkQ29udGV4dHM6IFtcbiAgICAgICAgICAgIC4uLihjdHguZ2V0T3JVbmRlZmluZWQoXCJjaGlsZENvbnRleHRzXCIpIHx8IFtdKSxcbiAgICAgICAgICAgIG5ld0N0eCxcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ld0N0eDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1cnJlbnRPcCA9IGN0eC5nZXRPclVuZGVmaW5lZChcIm9wZXJhdGlvblwiKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRNb2RlbCA9IGN0eC5nZXRPclVuZGVmaW5lZChcImFmZmVjdGVkVGFibGVzXCIpO1xuICAgICAgaWYgKFxuICAgICAgICAhY3VycmVudE9wIHx8XG4gICAgICAgIGN1cnJlbnRPcCAhPT0gb3BlcmF0aW9uIHx8XG4gICAgICAgIChtb2RlbCAmJiBtb2RlbCAhPT0gY3VycmVudE1vZGVsKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IG5ld0N0eCA9IG5ldyB0aGlzLkNvbnRleHQoKS5hY2N1bXVsYXRlKHtcbiAgICAgICAgICAuLi5jdHhbXCJjYWNoZVwiXSxcbiAgICAgICAgICAuLi5mbGFncyxcbiAgICAgICAgICBwYXJlbnRDb250ZXh0OiBjdHgsXG4gICAgICAgIH0pIGFzIGFueTtcblxuICAgICAgICBjdHguYWNjdW11bGF0ZSh7XG4gICAgICAgICAgY2hpbGRDb250ZXh0czogW1xuICAgICAgICAgICAgLi4uKGN0eC5nZXRPclVuZGVmaW5lZChcImNoaWxkQ29udGV4dHNcIikgfHwgW10pLFxuICAgICAgICAgICAgbmV3Q3R4LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3Q3R4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGN0eC5hY2N1bXVsYXRlKGZsYWdzKSBhcyBhbnk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyB0aGlzLkNvbnRleHQoKS5hY2N1bXVsYXRlKHtcbiAgICAgIC4uLmZsYWdzLFxuICAgIH0pIGFzIGFueTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVjb2RlcyBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmdcbiAgICogQHN1bW1hcnkgQ29udmVydHMgYmluYXJ5IGRhdGEgcmVjZWl2ZWQgZnJvbSBGYWJyaWMgdG8gYSBzdHJpbmcgdXNpbmcgVVRGLTggZW5jb2RpbmdcbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBkYXRhIC0gVGhlIGJpbmFyeSBkYXRhIHRvIGRlY29kZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBkZWNvZGVkIHN0cmluZ1xuICAgKi9cbiAgZGVjb2RlKGRhdGE6IFVpbnQ4QXJyYXkpOiBzdHJpbmcge1xuICAgIHJldHVybiBGYWJyaWNDbGllbnRBZGFwdGVyLmRlY29kZXIuZGVjb2RlKGRhdGEpO1xuICB9XG5cbiAgb3ZlcnJpZGUgcmVwb3NpdG9yeTxcbiAgICBSIGV4dGVuZHMgUmVwb3NpdG9yeTxcbiAgICAgIGFueSxcbiAgICAgIEFkYXB0ZXI8UGVlckNvbmZpZywgQ2xpZW50LCBNYW5nb1F1ZXJ5LCBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgICA+LFxuICA+KCk6IENvbnN0cnVjdG9yPFI+IHtcbiAgICByZXR1cm4gRmFicmljQ2xpZW50UmVwb3NpdG9yeSBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yPFI+O1xuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVByZWZpeDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBbQ29uc3RydWN0b3I8TT4sIFByaW1hcnlLZXlUeXBlLCBSZWNvcmQ8c3RyaW5nLCBhbnk+LCAuLi5hbnlbXSwgQ29udGV4dF0ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGVQcmVmaXgpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuICAgIHJldHVybiBbY2xhenosIGlkLCByZWNvcmQsIC4uLmN0eEFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBtdWx0aXBsZSByZWNvcmRzIGZvciBjcmVhdGlvblxuICAgKiBAc3VtbWFyeSBBZGRzIG5lY2Vzc2FyeSBDb3VjaERCIGZpZWxkcyB0byBtdWx0aXBsZSByZWNvcmRzIGJlZm9yZSBjcmVhdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nW118bnVtYmVyW119IGlkcyAtIFRoZSBJRHMgb2YgdGhlIHJlY29yZHNcbiAgICogQHBhcmFtIG1vZGVscyAtIFRoZSBtb2RlbHMgdG8gcHJlcGFyZVxuICAgKiBAcmV0dXJuIEEgdHVwbGUgY29udGFpbmluZyB0aGUgdGFibGVOYW1lLCBpZHMsIGFuZCBwcmVwYXJlZCByZWNvcmRzXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIGlkcyBhbmQgbW9kZWxzIGFycmF5cyBoYXZlIGRpZmZlcmVudCBsZW5ndGhzXG4gICAqL1xuICBwcm90ZWN0ZWQgY3JlYXRlQWxsUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogc3RyaW5nW10gfCBudW1iZXJbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICkge1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZUFsbFByZWZpeCk7XG4gICAgY29uc3QgcmVjb3JkcyA9IGlkcy5tYXAoKGlkLCBjb3VudCkgPT4ge1xuICAgICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsc1tjb3VudF0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW2NsYXp6LCBpZHMsIHJlY29yZHMsIC4uLmN0eEFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIHVwZGF0ZUFsbFByZWZpeDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApIHtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGVBbGxQcmVmaXgpO1xuICAgIGNvbnN0IHJlY29yZHMgPSBpZHMubWFwKCgpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIFtjbGF6eiwgaWRzLCByZWNvcmRzLCAuLi5jdHhBcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBtdWx0aXBsZSByZWNvcmRzIGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uXG4gICAqIEBzdW1tYXJ5IFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byBjcmVhdGUgbXVsdGlwbGUgcmVjb3JkcyBpbiB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBpZHMgLSBBcnJheSBvZiByZWNvcmQgaWRlbnRpZmllcnNcbiAgICogQHBhcmFtIHtBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gbW9kZWxzIC0gQXJyYXkgb2YgcmVjb3JkIGRhdGFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0cmFuc2llbnQgLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8QXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCByZWNvcmRzXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGw8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWRzOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT5bXT4ge1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIC8vSEVSRSFcbiAgICBjb25zdCBjdHhBcmdzID0gWy4uLihhcmdzIGFzIHVua25vd24gYXMgYW55W10pXTtcbiAgICBsZXQgdHJhbnNpZW50ID0gY3R4QXJncy5zaGlmdCgpIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoXG4gICAgICBjdHhBcmdzIGFzIENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PixcbiAgICAgIHRoaXMuY3JlYXRlQWxsXG4gICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuXG4gICAgbG9nLmluZm8oYGFkZGluZyAke2lkcy5sZW5ndGh9IGVudHJpZXMgdG8gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLnZlcmJvc2UoYHBrczogJHtpZHN9YCk7XG5cbiAgICB0cmFuc2llbnQgPVxuICAgICAgdHJhbnNpZW50ICYmXG4gICAgICAoQXJyYXkuaXNBcnJheSh0cmFuc2llbnQpID8gdHJhbnNpZW50IDogT2JqZWN0LmtleXModHJhbnNpZW50KSkubGVuZ3RoXG4gICAgICAgID8geyBbdGFibGVOYW1lXTogdHJhbnNpZW50IH1cbiAgICAgICAgOiB7fTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLkNSRUFURV9BTEwsXG4gICAgICBbXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIG1vZGVscy5tYXAoKG0pID0+IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUobSwgY2xhenoubmFtZSkpXG4gICAgICAgICksXG4gICAgICBdLFxuICAgICAgdHJhbnNpZW50LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY2xhenoubmFtZVxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuZGVjb2RlKHJlc3VsdCkpLm1hcCgocjogYW55KSA9PiBKU09OLnBhcnNlKHIpKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgbXVsdGlwbGUgcmVjb3JkcyBpbiBhIHNpbmdsZSB0cmFuc2FjdGlvblxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gcmVhZCBtdWx0aXBsZSByZWNvcmRzIGZyb20gdGhlIEZhYnJpYyBsZWRnZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0gaWRzIC0gQXJyYXkgb2YgcmVjb3JkIGlkZW50aWZpZXJzIHRvIHJlYWRcbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXRyaWV2ZWQgcmVjb3Jkc1xuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZEFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkQWxsKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGxvZy5pbmZvKGByZWFkaW5nICR7aWRzLmxlbmd0aH0gZW50cmllcyB0byAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cudmVyYm9zZShgcGtzOiAke2lkc31gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTEwsXG4gICAgICBbSlNPTi5zdHJpbmdpZnkoaWRzKV0sXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5kZWNvZGUocmVzdWx0KSkubWFwKChyOiBhbnkpID0+IEpTT04ucGFyc2UocikpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG11bHRpcGxlIHJlY29yZHMgaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb25cbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIHVwZGF0ZSBtdWx0aXBsZSByZWNvcmRzIGluIHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGlkcyAtIEFycmF5IG9mIHJlY29yZCBpZGVudGlmaWVyc1xuICAgKiBAcGFyYW0ge0FycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+fSBtb2RlbHMgLSBBcnJheSBvZiB1cGRhdGVkIHJlY29yZCBkYXRhXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gdHJhbnNpZW50IC0gVHJhbnNpZW50IGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgcmVjb3Jkc1xuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlQWxsPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcbiAgICBjb25zdCBjdHhBcmdzID0gWy4uLihhcmdzIGFzIHVua25vd24gYXMgYW55W10pXTtcbiAgICBsZXQgdHJhbnNpZW50ID0gY3R4QXJncy5zaGlmdCgpIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoXG4gICAgICBjdHhBcmdzIGFzIENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PixcbiAgICAgIHRoaXMudXBkYXRlQWxsXG4gICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGxvZy5pbmZvKGB1cGRhdGluZyAke2lkcy5sZW5ndGh9IGVudHJpZXMgdG8gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLnZlcmJvc2UoYHBrczogJHtpZHN9YCk7XG4gICAgdHJhbnNpZW50ID1cbiAgICAgIHRyYW5zaWVudCAmJlxuICAgICAgKEFycmF5LmlzQXJyYXkodHJhbnNpZW50KSA/IHRyYW5zaWVudCA6IE9iamVjdC5rZXlzKHRyYW5zaWVudCkpLmxlbmd0aFxuICAgICAgICA/IHsgW3RhYmxlTmFtZV06IHRyYW5zaWVudCB9XG4gICAgICAgIDoge307XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5zdWJtaXRUcmFuc2FjdGlvbihcbiAgICAgIGN0eCxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMLFxuICAgICAgW1xuICAgICAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICBtb2RlbHMubWFwKChtKSA9PiB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG0sIGNsYXp6Lm5hbWUpKVxuICAgICAgICApLFxuICAgICAgXSxcbiAgICAgIHRyYW5zaWVudCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLmRlY29kZShyZXN1bHQpKS5tYXAoKHI6IGFueSkgPT4gSlNPTi5wYXJzZShyKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgcmVjb3JkcyBpbiBhIHNpbmdsZSB0cmFuc2FjdGlvblxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gZGVsZXRlIG11bHRpcGxlIHJlY29yZHMgZnJvbSB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+fSBpZHMgLSBBcnJheSBvZiByZWNvcmQgaWRlbnRpZmllcnMgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7U2VyaWFsaXplcjxhbnk+fSBzZXJpYWxpemVyIC0gU2VyaWFsaXplciBmb3IgdGhlIG1vZGVsIGRhdGFcbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIHJlY29yZHNcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZHM6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5kZWxldGVBbGwpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbG9nLmluZm8oYGRlbGV0aW5nICR7aWRzLmxlbmd0aH0gZW50cmllcyB0byAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cudmVyYm9zZShgcGtzOiAke2lkc31gKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEwsXG4gICAgICBbSlNPTi5zdHJpbmdpZnkoaWRzKV0sXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5kZWNvZGUocmVzdWx0KSkubWFwKChyOiBhbnkpID0+IEpTT04ucGFyc2UocikpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIG1vZGVsIGZvciBwZXJzaXN0ZW5jZVxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIG1vZGVsIGluc3RhbmNlIGludG8gYSBmb3JtYXQgc3VpdGFibGUgZm9yIGRhdGFiYXNlIHN0b3JhZ2UsXG4gICAqIGhhbmRsaW5nIGNvbHVtbiBtYXBwaW5nIGFuZCBzZXBhcmF0aW5nIHRyYW5zaWVudCBwcm9wZXJ0aWVzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcmVwYXJlXG4gICAqIEBwYXJhbSBwayAtIFRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0eSBuYW1lXG4gICAqIEByZXR1cm4gVGhlIHByZXBhcmVkIGRhdGFcbiAgICovXG4gIG92ZXJyaWRlIHByZXBhcmU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogU2VncmVnYXRlZE1vZGVsPE0+ICYgUHJlcGFyZWRNb2RlbCB7XG4gICAgY29uc3QgeyBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucHJlcGFyZSk7XG4gICAgY29uc3Qgc3BsaXQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuICAgIGlmICgobW9kZWwgYXMgYW55KVtQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEFdKSB7XG4gICAgICBsb2cuc2lsbHkoXG4gICAgICAgIGBQYXNzaW5nIGFsb25nIHBlcnNpc3RlbmNlIG1ldGFkYXRhIGZvciAkeyhtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV19YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzcGxpdC5tb2RlbCwgUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBLCB7XG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IChtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVjb3JkOiBzcGxpdC5tb2RlbCxcbiAgICAgIG1vZGVsOiBzcGxpdC5tb2RlbCxcbiAgICAgIGlkOiBtb2RlbFtNb2RlbC5wayhtb2RlbC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPildIGFzIHN0cmluZyxcbiAgICAgIHRyYW5zaWVudDogc3BsaXQudHJhbnNpZW50LFxuICAgICAgcHJpdmF0ZXM6IHNwbGl0LnByaXZhdGVzLFxuICAgICAgc2hhcmVkOiBzcGxpdC5zaGFyZWQsXG4gICAgfTtcbiAgfVxuXG4gIG92ZXJyaWRlIHJldmVydDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IE0ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJldmVydCk7XG4gICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGByZS1hZGRpbmcgdHJhbnNpZW50IHByb3BlcnRpZXM6ICR7T2JqZWN0LmtleXModHJhbnNpZW50KS5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zaWVudCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmIChrZXkgaW4gb2JqICYmIHR5cGVvZiBvYmpba2V5XSAhPT0gXCJ1bmRlZmluZWRcIilcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBUcmFuc2llbnQgcHJvcGVydHkgJHtrZXl9IGFscmVhZHkgZXhpc3RzIG9uIG1vZGVsICR7dHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gY2xhenogOiBjbGF6ei5uYW1lfS4gc2hvdWxkIGJlIGltcG9zc2libGVgXG4gICAgICAgICAgKTtcbiAgICAgICAgKG9iaiBhcyBNKVtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IChjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPikob2JqKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHNpbmdsZSByZWNvcmRcbiAgICogQHN1bW1hcnkgU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIGNyZWF0ZSBhIHJlY29yZCBpbiB0aGUgRmFicmljIGxlZGdlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgcmVjb3JkIGRhdGFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0cmFuc2llbnQgLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHJlY29yZFxuICAgKi9cbiAgQGRlYnVnKClcbiAgQGZpbmFsKClcbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICB0cmFuc2llbnQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgY3R4QXJncyA9IFsuLi4oYXJncyBhcyB1bmtub3duIGFzIGFueVtdKV07XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoXG4gICAgICBjdHhBcmdzIGFzIENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PixcbiAgICAgIHRoaXMuY3JlYXRlXG4gICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGxvZy52ZXJib3NlKGBhZGRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLmRlYnVnKGBwazogJHtpZH1gKTtcbiAgICB0cmFuc2llbnQgPVxuICAgICAgdHJhbnNpZW50ICYmIE9iamVjdC5rZXlzKHRyYW5zaWVudCkubGVuZ3RoXG4gICAgICAgID8geyBbdGFibGVOYW1lXTogdHJhbnNpZW50IH1cbiAgICAgICAgOiB7fTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnN1Ym1pdFRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBbdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCwgY2xhenoubmFtZSldLFxuICAgICAgdHJhbnNpZW50LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY2xhenoubmFtZVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZSh0aGlzLmRlY29kZShyZXN1bHQpKTtcbiAgfVxuXG4gIEBkZWJ1ZygpXG4gIEBmaW5hbCgpXG4gIGFzeW5jIGhlYWx0aGNoZWNrPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmhlYWx0aGNoZWNrKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuXG4gICAgbG9nLnZlcmJvc2UoYHJlYWRpbmcgZW50cnkgZnJvbSAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICBbXSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuZGVjb2RlKHJlc3VsdCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHNpbmdsZSByZWNvcmRcbiAgICogQHN1bW1hcnkgRXZhbHVhdGVzIGEgdHJhbnNhY3Rpb24gdG8gcmVhZCBhIHJlY29yZCBmcm9tIHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCByZWNvcmRcbiAgICovXG4gIEBkZWJ1ZygpXG4gIEBmaW5hbCgpXG4gIGFzeW5jIHJlYWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJlYWQpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG5cbiAgICBsb2cudmVyYm9zZShgcmVhZGluZyBlbnRyeSBmcm9tICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgIGxvZy5kZWJ1ZyhgcGs6ICR7aWR9YCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgW2lkLnRvU3RyaW5nKCldLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY2xhenoubmFtZVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZSh0aGlzLmRlY29kZShyZXN1bHQpKTtcbiAgfVxuXG4gIHVwZGF0ZVByZWZpeDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApIHtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGVQcmVmaXgpO1xuICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgLy8gcmVjb3JkW0NvdWNoREJLZXlzLklEXSA9IHRoaXMuZ2VuZXJhdGVJZCh0YWJsZU5hbWUsIGlkKTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuICAgIHJldHVybiBbY2xhenosIGlkLCByZWNvcmQsIC4uLmN0eEFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIGEgc2luZ2xlIHJlY29yZFxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gdXBkYXRlIGEgcmVjb3JkIGluIHRoZSBGYWJyaWMgbGVkZ2VyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSB1cGRhdGVkIHJlY29yZCBkYXRhXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gdHJhbnNpZW50IC0gVHJhbnNpZW50IGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCByZWNvcmRcbiAgICovXG4gIEBkZWJ1ZygpXG4gIEBmaW5hbCgpXG4gIGFzeW5jIHVwZGF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgdHJhbnNpZW50OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge30sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IGN0eEFyZ3MgPSBbLi4uKGFyZ3MgYXMgdW5rbm93biBhcyBhbnlbXSldO1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IHRoaXMubG9nQ3R4KFxuICAgICAgY3R4QXJncyBhcyBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj4sXG4gICAgICB0aGlzLnVwZGF0ZUFsbFxuICAgICk7XG4gICAgbG9nLmluZm8oYENMSUVOVCBVUERBVEUgY2xhc3MgOiAke3R5cGVvZiBjbGF6en1gKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuICAgIGxvZy52ZXJib3NlKGB1cGRhdGluZyBlbnRyeSB0byAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cuZGVidWcoYHBrOiAke2lkfWApO1xuICAgIHRyYW5zaWVudCA9XG4gICAgICB0cmFuc2llbnQgJiYgT2JqZWN0LmtleXModHJhbnNpZW50KS5sZW5ndGhcbiAgICAgICAgPyB7IFt0YWJsZU5hbWVdOiB0cmFuc2llbnQgfVxuICAgICAgICA6IHt9O1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc3VibWl0VHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIFt0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsLCBjbGF6ei5uYW1lIHx8IGNsYXp6KV0sIC8vIFRPRE8gc2hvdWxkIGJlIHJlY2V2aW5nIGNsYXNzIGJ1dCBpcyByZWNlaXZpbmcgc3RyaW5nXG4gICAgICB0cmFuc2llbnQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjbGF6ei5uYW1lXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKHRoaXMuZGVjb2RlKHJlc3VsdCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgc2luZ2xlIHJlY29yZFxuICAgKiBAc3VtbWFyeSBTdWJtaXRzIGEgdHJhbnNhY3Rpb24gdG8gZGVsZXRlIGEgcmVjb3JkIGZyb20gdGhlIEZhYnJpYyBsZWRnZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBpZCAtIFRoZSByZWNvcmQgaWRlbnRpZmllciB0byBkZWxldGVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGRlbGV0ZWQgcmVjb3JkXG4gICAqL1xuICBAZGVidWcoKVxuICBAZmluYWwoKVxuICBvdmVycmlkZSBhc3luYyBkZWxldGU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmRlbGV0ZSk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBsb2cudmVyYm9zZShgZGVsZXRpbmcgZW50cnkgZnJvbSAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICBsb2cuZGVidWcoYHBrOiAke2lkfWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc3VibWl0VHJhbnNhY3Rpb24oXG4gICAgICBjdHgsXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIFtpZC50b1N0cmluZygpXSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNsYXp6Lm5hbWVcbiAgICApO1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUodGhpcy5kZWNvZGUocmVzdWx0KSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIEZhYnJpYyBsZWRnZXJcbiAgICogQHN1bW1hcnkgRXZhbHVhdGVzIGEgdHJhbnNhY3Rpb24gdG8gcGVyZm9ybSBhIHF1ZXJ5IHVzaW5nIE1hbmdvIFF1ZXJ5IHN5bnRheFxuICAgKiBAdGVtcGxhdGUgViAtIFRoZSByZXR1cm4gdHlwZVxuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHJhd0lucHV0IC0gVGhlIE1hbmdvIFF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHBhcmFtIHtib29sZWFufSBwcm9jZXNzIC0gV2hldGhlciB0byBwcm9jZXNzIHRoZSByZXN1bHRcbiAgICogQHJldHVybiB7UHJvbWlzZTxWPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHF1ZXJ5IHJlc3VsdFxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBGYWJyaWNBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAgICogICBwYXJ0aWNpcGFudCBDaGFpbmNvZGVcbiAgICpcbiAgICogICBDbGllbnQtPj5GYWJyaWNBZGFwdGVyOiByYXcocmF3SW5wdXQsIHByb2Nlc3MpXG4gICAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KVxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5GYWJyaWNBZGFwdGVyOiBldmFsdWF0ZVRyYW5zYWN0aW9uKFwicXVlcnlcIiwgW2lucHV0XSlcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+Q29udHJhY3Q6IGV2YWx1YXRlKFwicXVlcnlcIiwgcHJvcG9zYWxPcHRpb25zKVxuICAgKiAgIENvbnRyYWN0LT4+Q2hhaW5jb2RlOiBpbnZva2VcbiAgICogICBDaGFpbmNvZGUtLT4+Q29udHJhY3Q6IHJlc3BvbnNlXG4gICAqICAgQ29udHJhY3QtLT4+RmFicmljQWRhcHRlcjogcmVzdWx0XG4gICAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IEpTT04ucGFyc2UoZGVjb2RlKHJlc3VsdCkpXG4gICAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IFByb2Nlc3MgcmVzdWx0IGJhc2VkIG9uIHR5cGVcbiAgICogICBGYWJyaWNBZGFwdGVyLS0+PkNsaWVudDogcHJvY2Vzc2VkIHJlc3VsdFxuICAgKi9cbiAgQGRlYnVnKClcbiAgYXN5bmMgcmF3PFYsIEQgZXh0ZW5kcyBib29sZWFuPihcbiAgICByYXdJbnB1dDogTWFuZ29RdWVyeSxcbiAgICBkb2NzT25seTogRCA9IHRydWUgYXMgRCxcbiAgICBjbGF6ejogTW9kZWxDb25zdHJ1Y3Rvcjxhbnk+LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+PlxuICApOiBQcm9taXNlPFY+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJhdyk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gY2xhenoubmFtZTtcbiAgICBsb2cuaW5mbyhgUGVyZm9ybWluZyByYXcgc3RhdGVtZW50IG9uIHRhYmxlICR7TW9kZWwudGFibGVOYW1lKGNsYXp6KX1gKTtcbiAgICBsZXQgdHJhbnNhY3Rpb25SZXN1bHQ6IGFueTtcbiAgICB0cnkge1xuICAgICAgdHJhbnNhY3Rpb25SZXN1bHQgPSBhd2FpdCB0aGlzLmV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgICAgIGN0eCxcbiAgICAgICAgXCJyYXdcIixcbiAgICAgICAgW0pTT04uc3RyaW5naWZ5KHJhd0lucHV0KSwgZG9jc09ubHldLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgdGFibGVOYW1lXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBKU09OLnBhcnNlKHRoaXMuZGVjb2RlKHRyYW5zYWN0aW9uUmVzdWx0KSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBGYWlsZWQgdG8gcHJvY2VzcyByZXN1bHQ6ICR7ZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZVJlY29yZCA9IChyZWNvcmQ6IFJlY29yZDxhbnksIGFueT4pID0+IHtcbiAgICAgIGlmIChNb2RlbC5pc01vZGVsKHJlY29yZCkpIHJldHVybiBNb2RlbC5idWlsZChyZWNvcmQpO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9O1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgaWYgKCFyZXN1bHQubGVuZ3RoKSByZXR1cm4gcmVzdWx0IGFzIFY7XG4gICAgICBjb25zdCBlbCA9IHJlc3VsdFswXTtcbiAgICAgIGlmIChNb2RlbC5pc01vZGVsKGVsKSlcbiAgICAgICAgLy8gaWYgdGhlIGZpcnN0IG9uZSBpcyBhIG1vZGVsLCBhbGwgYXJlIG1vZGVsc1xuICAgICAgICByZXR1cm4gcmVzdWx0Lm1hcCgoZWwpID0+IE1vZGVsLmJ1aWxkKGVsKSkgYXMgVjtcbiAgICAgIHJldHVybiByZXN1bHQgYXMgVjtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFyc2VSZWNvcmQocmVzdWx0IGFzIGFueSkgYXMgVjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSBDb3VjaERCIHZpZXcgcXVlcnkgYWdhaW5zdCB0aGUgRmFicmljIGNoYWluY29kZVxuICAgKiBAc3VtbWFyeSBFdmFsdWF0ZXMgYSB0cmFuc2FjdGlvbiB0byBxdWVyeSBhIGRlc2lnbiBkb2N1bWVudCB2aWV3XG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHZpZXcgcmVzcG9uc2UgdHlwZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gZGRvYyAtIERlc2lnbiBkb2N1bWVudCBuYW1lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2aWV3TmFtZSAtIFZpZXcgbmFtZVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9wdGlvbnMgLSBWaWV3IHF1ZXJ5IG9wdGlvbnNcbiAgICogQHBhcmFtIHsuLi5Db250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPj59IGFyZ3MgLSBPcHRpb25hbCBjb250ZXh0dWFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPFZpZXdSZXNwb25zZTxSPj59IFRoZSB2aWV3IHJlc3BvbnNlXG4gICAqL1xuICBAZGVidWcoKVxuICBhc3luYyB2aWV3PFI+KFxuICAgIGRkb2M6IHN0cmluZyxcbiAgICB2aWV3TmFtZTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4+XG4gICk6IFByb21pc2U8Vmlld1Jlc3BvbnNlPFI+PiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy52aWV3KTtcbiAgICBsb2cuaW5mbyhgUXVlcnlpbmcgdmlldyAke2Rkb2N9LyR7dmlld05hbWV9YCk7XG4gICAgbGV0IHRyYW5zYWN0aW9uUmVzdWx0OiBhbnk7XG4gICAgdHJ5IHtcbiAgICAgIHRyYW5zYWN0aW9uUmVzdWx0ID0gYXdhaXQgdGhpcy5ldmFsdWF0ZVRyYW5zYWN0aW9uKFxuICAgICAgICBjdHgsXG4gICAgICAgIFwidmlld1wiLFxuICAgICAgICBbZGRvYywgdmlld05hbWUsIEpTT04uc3RyaW5naWZ5KG9wdGlvbnMpXSxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICAgIGxldCByZXN1bHQ6IFZpZXdSZXNwb25zZTxSPjtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gSlNPTi5wYXJzZSh0aGlzLmRlY29kZSh0cmFuc2FjdGlvblJlc3VsdCkpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihgRmFpbGVkIHRvIHByb2Nlc3MgdmlldyByZXN1bHQ6ICR7ZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBvciBjcmVhdGVzIGEgZ1JQQyBjbGllbnQgZm9yIHRoZSBGYWJyaWMgcGVlclxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgY2FjaGVkIGNsaWVudCBvciBjcmVhdGVzIGEgbmV3IG9uZSBpZiBub25lIGV4aXN0c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPENsaWVudD59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBnUlBDIGNsaWVudFxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0Q2xpZW50KCk6IENsaWVudCB7XG4gICAgaWYgKCF0aGlzLl9jbGllbnQpXG4gICAgICB0aGlzLl9jbGllbnQgPSBGYWJyaWNDbGllbnRBZGFwdGVyLmdldENsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIEdhdGV3YXkgaW5zdGFuY2UgZm9yIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IEdhdGV3YXkgaW5zdGFuY2UgdXNpbmcgdGhlIGN1cnJlbnQgY2xpZW50XG4gICAqIEByZXR1cm4ge1Byb21pc2U8R2F0ZXdheT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBHYXRld2F5IGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgR2F0ZXdheShjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+KTogUHJvbWlzZTxHYXRld2F5PiB7XG4gICAgcmV0dXJuIEZhYnJpY0NsaWVudEFkYXB0ZXIuZ2V0R2F0ZXdheShjdHgsIHRoaXMuY29uZmlnLCB0aGlzLmNsaWVudCk7XG4gIH1cblxuICBwcml2YXRlIGdldENvbnRyYWN0TmFtZShjbGFzc05hbWU/OiBzdHJpbmcpIHtcbiAgICBpZiAoIWNsYXNzTmFtZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gYCR7Y2xhc3NOYW1lfUNvbnRyYWN0YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIENvbnRyYWN0IGluc3RhbmNlIGZvciB0aGUgRmFicmljIGNoYWluY29kZVxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IENvbnRyYWN0IGluc3RhbmNlIHVzaW5nIHRoZSBjdXJyZW50IEdhdGV3YXlcbiAgICogQHJldHVybiB7UHJvbWlzZTxDb250cmFrdD59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBDb250cmFjdCBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIENvbnRyYWN0KFxuICAgIGN0eDogQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgY29udHJhY3ROYW1lPzogc3RyaW5nXG4gICk6IFByb21pc2U8Q29udHJha3Q+IHtcbiAgICByZXR1cm4gRmFicmljQ2xpZW50QWRhcHRlci5nZXRDb250cmFjdChcbiAgICAgIGF3YWl0IHRoaXMuR2F0ZXdheShjdHgpLFxuICAgICAgdGhpcy5jb25maWcsXG4gICAgICBjb250cmFjdE5hbWVcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHRyYW5zYWN0aW9uIG9uIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBTdWJtaXRzIG9yIGV2YWx1YXRlcyBhIHRyYW5zYWN0aW9uIG9uIHRoZSBGYWJyaWMgY2hhaW5jb2RlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcGkgLSBUaGUgY2hhaW5jb2RlIGZ1bmN0aW9uIHRvIGNhbGxcbiAgICogQHBhcmFtIHtib29sZWFufSBzdWJtaXQgLSBXaGV0aGVyIHRvIHN1Ym1pdCAodHJ1ZSkgb3IgZXZhbHVhdGUgKGZhbHNlKSB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIC0gQXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGNoYWluY29kZSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHN0cmluZz59IFt0cmFuc2llbnREYXRhXSAtIFRyYW5zaWVudCBkYXRhIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBbZW5kb3JzaW5nT3JnYW5pemF0aW9uc10gLSBPcmdhbml6YXRpb25zIHRoYXQgbXVzdCBlbmRvcnNlIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFVpbnQ4QXJyYXk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdHJhbnNhY3Rpb24gcmVzdWx0XG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEZhYnJpY0FkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBHYXRld2F5XG4gICAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAgICogICBwYXJ0aWNpcGFudCBDaGFpbmNvZGVcbiAgICpcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+R2F0ZXdheTogY29ubmVjdCgpXG4gICAqICAgRmFicmljQWRhcHRlci0+PkNvbnRyYWN0OiBnZXRDb250cmFjdCgpXG4gICAqICAgYWx0IHN1Ym1pdCB0cmFuc2FjdGlvblxuICAgKiAgICAgRmFicmljQWRhcHRlci0+PkNvbnRyYWN0OiBzdWJtaXQoYXBpLCBwcm9wb3NhbE9wdGlvbnMpXG4gICAqICAgZWxzZSBldmFsdWF0ZSB0cmFuc2FjdGlvblxuICAgKiAgICAgRmFicmljQWRhcHRlci0+PkNvbnRyYWN0OiBldmFsdWF0ZShhcGksIHByb3Bvc2FsT3B0aW9ucylcbiAgICogICBlbmRcbiAgICogICBDb250cmFjdC0+PkNoYWluY29kZTogaW52b2tlXG4gICAqICAgQ2hhaW5jb2RlLS0+PkNvbnRyYWN0OiByZXNwb25zZVxuICAgKiAgIENvbnRyYWN0LS0+PkZhYnJpY0FkYXB0ZXI6IHJlc3VsdFxuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5HYXRld2F5OiBjbG9zZSgpXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgdHJhbnNhY3Rpb24oXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPixcbiAgICBhcGk6IHN0cmluZyxcbiAgICBzdWJtaXQgPSB0cnVlLFxuICAgIGFyZ3M/OiBhbnlbXSxcbiAgICB0cmFuc2llbnREYXRhOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30sXG4gICAgZW5kb3JzaW5nT3JnYW5pemF0aW9ucz86IEFycmF5PHN0cmluZz4sXG4gICAgY2xhc3NOYW1lPzogc3RyaW5nXG4gICk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnRyYW5zYWN0aW9uKTtcbiAgICBjb25zdCBnYXRld2F5ID0gYXdhaXQgdGhpcy5HYXRld2F5KGN0eCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbnRyYWN0ID0gYXdhaXQgdGhpcy5Db250cmFjdChcbiAgICAgICAgY3R4LFxuICAgICAgICB0aGlzLmdldENvbnRyYWN0TmFtZShjbGFzc05hbWUpXG4gICAgICApO1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGAke3N1Ym1pdCA/IFwiU3VibWl0XCIgOiBcIkV2YWx1YXRlXCJ9dGluZyB0cmFuc2FjdGlvbiAke3RoaXMuZ2V0Q29udHJhY3ROYW1lKGNsYXNzTmFtZSkgfHwgdGhpcy5jb25maWcuY29udHJhY3ROYW1lfS4ke2FwaX1gXG4gICAgICApO1xuICAgICAgbG9nLmRlYnVnKGBhcmdzOiAke2FyZ3M/Lm1hcCgoYSkgPT4gYS50b1N0cmluZygpKS5qb2luKFwiXFxuXCIpIHx8IFwibm9uZVwifWApO1xuICAgICAgY29uc3QgbWV0aG9kID0gc3VibWl0ID8gY29udHJhY3Quc3VibWl0IDogY29udHJhY3QuZXZhbHVhdGU7XG5cbiAgICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnMgPSBlbmRvcnNpbmdPcmdhbml6YXRpb25zPy5sZW5ndGhcbiAgICAgICAgPyBlbmRvcnNpbmdPcmdhbml6YXRpb25zXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcHJvcG9zYWxPcHRpb25zOiBQcm9wb3NhbE9wdGlvbnMgPSB7XG4gICAgICAgIGFyZ3VtZW50czogYXJncyB8fCBbXSxcbiAgICAgICAgdHJhbnNpZW50RGF0YTogT2JqZWN0LmVudHJpZXModHJhbnNpZW50RGF0YSkucmVkdWNlKFxuICAgICAgICAgIChhY2MsIFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgICAgIGFjY1trZXldID0gSlNPTi5zdHJpbmdpZnkodmFsKTtcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7fSBhcyB0eXBlb2YgdHJhbnNpZW50RGF0YVxuICAgICAgICApLFxuICAgICAgICAvLyAuLi4oZW5kb3JzaW5nT3JnYW5pemF0aW9ucyAmJiB7IGVuZG9yc2luZ09yZ2FuaXphdGlvbnMgfSkgLy8gbXNwSWQgbGlzdFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIGF3YWl0IG1ldGhvZC5jYWxsKGNvbnRyYWN0LCBhcGksIHByb3Bvc2FsT3B0aW9ucyk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5jb2RlID09PSAxMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZS5kZXRhaWxzWzBdLm1lc3NhZ2V9YCk7XG4gICAgICB9XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBDbG9zaW5nICR7dGhpcy5jb25maWcubXNwSWR9IGdhdGV3YXkgY29ubmVjdGlvbmApO1xuICAgICAgZ2F0ZXdheS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGFuIGVycm9yIGludG8gYSBCYXNlRXJyb3JcbiAgICogQHN1bW1hcnkgQ29udmVydHMgYW55IGVycm9yIGludG8gYSBzdGFuZGFyZGl6ZWQgQmFzZUVycm9yXG4gICAqIEBwYXJhbSB7RXJyb3IgfCBzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3JcbiAgICovXG4gIG92ZXJyaWRlIHBhcnNlRXJyb3I8RSBleHRlbmRzIEJhc2VFcnJvcj4oZXJyOiBFcnJvciB8IHN0cmluZyk6IEUge1xuICAgIHJldHVybiBGYWJyaWNDbGllbnRBZGFwdGVyLnBhcnNlRXJyb3I8RT4oZXJyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3VibWl0cyBhIHRyYW5zYWN0aW9uIHRvIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyBhIHRyYW5zYWN0aW9uIHRoYXQgbW9kaWZpZXMgdGhlIGxlZGdlciBzdGF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXBpIC0gVGhlIGNoYWluY29kZSBmdW5jdGlvbiB0byBjYWxsXG4gICAqIEBwYXJhbSB7YW55W119IFthcmdzXSAtIEFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBjaGFpbmNvZGUgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fSBbdHJhbnNpZW50RGF0YV0gLSBUcmFuc2llbnQgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPn0gW2VuZG9yc2luZ09yZ2FuaXphdGlvbnNdIC0gT3JnYW5pemF0aW9ucyB0aGF0IG11c3QgZW5kb3JzZSB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxVaW50OEFycmF5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHRyYW5zYWN0aW9uIHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgc3VibWl0VHJhbnNhY3Rpb24oXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPixcbiAgICBhcGk6IHN0cmluZyxcbiAgICBhcmdzPzogYW55W10sXG4gICAgdHJhbnNpZW50RGF0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICAgZW5kb3JzaW5nT3JnYW5pemF0aW9ucz86IEFycmF5PHN0cmluZz4sXG4gICAgY2xhc3NOYW1lPzogc3RyaW5nXG4gICk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgYXBpLFxuICAgICAgdHJ1ZSxcbiAgICAgIGFyZ3MsXG4gICAgICB0cmFuc2llbnREYXRhLFxuICAgICAgZW5kb3JzaW5nT3JnYW5pemF0aW9ucyxcbiAgICAgIGNsYXNzTmFtZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV2YWx1YXRlcyBhIHRyYW5zYWN0aW9uIG9uIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyBhIHRyYW5zYWN0aW9uIHRoYXQgZG9lcyBub3QgbW9kaWZ5IHRoZSBsZWRnZXIgc3RhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFwaSAtIFRoZSBjaGFpbmNvZGUgZnVuY3Rpb24gdG8gY2FsbFxuICAgKiBAcGFyYW0ge2FueVtdfSBbYXJnc10gLSBBcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgY2hhaW5jb2RlIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn0gW3RyYW5zaWVudERhdGFdIC0gVHJhbnNpZW50IGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IFtlbmRvcnNpbmdPcmdhbml6YXRpb25zXSAtIE9yZ2FuaXphdGlvbnMgdGhhdCBtdXN0IGVuZG9yc2UgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8VWludDhBcnJheT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB0cmFuc2FjdGlvbiByZXN1bHRcbiAgICovXG4gIGFzeW5jIGV2YWx1YXRlVHJhbnNhY3Rpb24oXG4gICAgY3R4OiBDb250ZXh0PEZhYnJpY0NsaWVudEZsYWdzPixcbiAgICBhcGk6IHN0cmluZyxcbiAgICBhcmdzPzogYW55W10sXG4gICAgdHJhbnNpZW50RGF0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICAgZW5kb3JzaW5nT3JnYW5pemF0aW9ucz86IEFycmF5PHN0cmluZz4sXG4gICAgY2xhc3NOYW1lPzogc3RyaW5nXG4gICk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9uKFxuICAgICAgY3R4LFxuICAgICAgYXBpLFxuICAgICAgZmFsc2UsXG4gICAgICBhcmdzLFxuICAgICAgdHJhbnNpZW50RGF0YSxcbiAgICAgIGVuZG9yc2luZ09yZ2FuaXphdGlvbnMsXG4gICAgICBjbGFzc05hbWVcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIEZhYnJpYyBuZXR3b3JrXG4gICAqIEBzdW1tYXJ5IENsb3NlcyB0aGUgZ1JQQyBjbGllbnQgaWYgaXQgZXhpc3RzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBjbGllbnQgaXMgY2xvc2VkXG4gICAqL1xuICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5jbGllbnQpIHtcbiAgICAgIHRoaXMubG9nLnZlcmJvc2UoYENsb3NpbmcgJHt0aGlzLmNvbmZpZy5tc3BJZH0gZ2F0ZXdheSBjbGllbnRgKTtcbiAgICAgIHRoaXMuY2xpZW50LmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIGEgQ29udHJhY3QgaW5zdGFuY2UgZnJvbSBhIEdhdGV3YXlcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIGEgY2hhaW5jb2RlIGNvbnRyYWN0IGZyb20gdGhlIHNwZWNpZmllZCBuZXR3b3JrXG4gICAqIEBwYXJhbSB7R2F0ZXdheX0gZ2F0ZXdheSAtIFRoZSBHYXRld2F5IGluc3RhbmNlXG4gICAqIEBwYXJhbSB7UGVlckNvbmZpZ30gY29uZmlnIC0gVGhlIHBlZXIgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJuIHtDb250cmFrdH0gVGhlIENvbnRyYWN0IGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgZ2V0Q29udHJhY3QoXG4gICAgZ2F0ZXdheTogR2F0ZXdheSxcbiAgICBjb25maWc6IFBlZXJDb25maWcsXG4gICAgY29udHJhY3ROYW1lPzogc3RyaW5nXG4gICk6IENvbnRyYWt0IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5nZXRDb250cmFjdCk7XG4gICAgY29uc3QgbmV0d29yayA9IHRoaXMuZ2V0TmV0d29yayhnYXRld2F5LCBjb25maWcuY2hhbm5lbCk7XG4gICAgbGV0IGNvbnRyYWN0OiBDb250cmFrdDtcbiAgICB0cnkge1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgUmV0cmlldmluZyBjaGFpbmNvZGUgJHtjb25maWcuY2hhaW5jb2RlTmFtZX0gY29udHJhY3QgJHtjb250cmFjdE5hbWUgfHwgY29uZmlnLmNvbnRyYWN0TmFtZX0gZnJvbSBuZXR3b3JrICR7Y29uZmlnLmNoYW5uZWx9YFxuICAgICAgKTtcbiAgICAgIGNvbnRyYWN0TmFtZSA9IGNvbnRyYWN0TmFtZSA/IGNvbnRyYWN0TmFtZSA6IGNvbmZpZy5jb250cmFjdE5hbWU7XG4gICAgICBjb250cmFjdCA9IG5ldHdvcmsuZ2V0Q29udHJhY3QoY29uZmlnLmNoYWluY29kZU5hbWUsIGNvbnRyYWN0TmFtZSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICAgIHJldHVybiBjb250cmFjdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIE5ldHdvcmsgaW5zdGFuY2UgZnJvbSBhIEdhdGV3YXlcbiAgICogQHN1bW1hcnkgQ29ubmVjdHMgdG8gYSBzcGVjaWZpYyBjaGFubmVsIG9uIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAcGFyYW0ge0dhdGV3YXl9IGdhdGV3YXkgLSBUaGUgR2F0ZXdheSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY2hhbm5lbCB0byBjb25uZWN0IHRvXG4gICAqIEByZXR1cm4ge05ldHdvcmt9IFRoZSBOZXR3b3JrIGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgZ2V0TmV0d29yayhnYXRld2F5OiBHYXRld2F5LCBjaGFubmVsTmFtZTogc3RyaW5nKTogTmV0d29yayB7XG4gICAgY29uc3QgbG9nID0gTG9nZ2luZy5mb3IodGhpcy5nZXROZXR3b3JrKTtcbiAgICBsZXQgbmV0d29yazogTmV0d29yaztcbiAgICB0cnkge1xuICAgICAgbG9nLmRlYnVnKGBDb25uZWN0aW5nIHRvIGNoYW5uZWwgJHtjaGFubmVsTmFtZX1gKTtcbiAgICAgIG5ldHdvcmsgPSBnYXRld2F5LmdldE5ldHdvcmsoY2hhbm5lbE5hbWUpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXR3b3JrO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIGEgR2F0ZXdheSBpbnN0YW5jZSBmb3IgY29ubmVjdGluZyB0byB0aGUgRmFicmljIG5ldHdvcmtcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIEdhdGV3YXkgdXNpbmcgdGhlIHByb3ZpZGVkIGNvbmZpZ3VyYXRpb24gYW5kIGNsaWVudFxuICAgKiBAcGFyYW0ge1BlZXJDb25maWd9IGNvbmZpZyAtIFRoZSBwZWVyIGNvbmZpZ3VyYXRpb25cbiAgICogQHBhcmFtIHtDbGllbnR9IFtjbGllbnRdIC0gT3B0aW9uYWwgZ1JQQyBjbGllbnQsIHdpbGwgYmUgY3JlYXRlZCBpZiBub3QgcHJvdmlkZWRcbiAgICogQHJldHVybiB7UHJvbWlzZTxHYXRld2F5Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIEdhdGV3YXkgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRHYXRld2F5KFxuICAgIGN0eDogQ29udGV4dDxGYWJyaWNDbGllbnRGbGFncz4sXG4gICAgY29uZmlnOiBQZWVyQ29uZmlnLFxuICAgIGNsaWVudD86IENsaWVudFxuICApIHtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGlvbihcbiAgICAgIGNsaWVudCB8fCAoYXdhaXQgdGhpcy5nZXRDbGllbnQoY29uZmlnKSksXG4gICAgICBjb25maWcsXG4gICAgICBjdHhcbiAgICApKSBhcyBHYXRld2F5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZ1JQQyBjbGllbnQgZm9yIGNvbm5lY3RpbmcgdG8gYSBGYWJyaWMgcGVlclxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIGNsaWVudCB3aXRoIFRMUyBjcmVkZW50aWFscyBmb3Igc2VjdXJlIGNvbW11bmljYXRpb25cbiAgICogQHBhcmFtIHtQZWVyQ29uZmlnfSBjb25maWcgLSBUaGUgcGVlciBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm4ge0NsaWVudH0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGdSUEMgY2xpZW50XG4gICAqL1xuICBzdGF0aWMgZ2V0Q2xpZW50KGNvbmZpZzogUGVlckNvbmZpZyk6IENsaWVudCB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuZ2V0Q2xpZW50KTtcbiAgICBsb2cuZGVidWcoYGdlbmVyYXRpbmcgVExTIGNyZWRlbnRpYWxzIGZvciBtc3AgJHtjb25maWcubXNwSWR9YCk7XG4gICAgbGV0IHBhdGhPckNlcnQ6IHN0cmluZyB8IEJ1ZmZlciA9IGNvbmZpZy50bHNDZXJ0IGFzIHN0cmluZyB8IEJ1ZmZlcjtcblxuICAgIGlmICh0eXBlb2YgcGF0aE9yQ2VydCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgaWYgKFxuICAgICAgICBwYXRoT3JDZXJ0Lm1hdGNoKFxuICAgICAgICAgIC8tLS0tLUJFR0lOIChDRVJUSUZJQ0FURXxLRVl8UFJJVkFURSBLRVkpLS0tLS0uKz8tLS0tLUVORCBcXDEtLS0tLSQvZ21zXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICBwYXRoT3JDZXJ0ID0gQnVmZmVyLmZyb20ocGF0aE9yQ2VydCwgXCJ1dGY4XCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBwYXRoT3JDZXJ0ID0gQnVmZmVyLmZyb20oZnMucmVhZEZpbGVTeW5jKHBhdGhPckNlcnQsIFwidXRmOFwiKSk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdG8gcmVhZCB0aGUgdGxzIGNlcnRpZmljYXRlIGZyb20gJHtwYXRoT3JDZXJ0fTogJHtlfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdGxzQ3JlZGVudGlhbHMgPSBncnBjLmNyZWRlbnRpYWxzLmNyZWF0ZVNzbChwYXRoT3JDZXJ0KTtcbiAgICBsb2cuZGVidWcoYGdlbmVyYXRpbmcgR2F0ZXdheSBDbGllbnQgZm9yIHVybCAke2NvbmZpZy5wZWVyRW5kcG9pbnR9YCk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoY29uZmlnLnBlZXJFbmRwb2ludCwgdGxzQ3JlZGVudGlhbHMsIHtcbiAgICAgIFwiZ3JwYy5tYXhfcmVjZWl2ZV9tZXNzYWdlX2xlbmd0aFwiOiAoY29uZmlnLnNpemVMaW1pdCB8fCAxNSkgKiAxMDI0ICogMTAyNCxcbiAgICAgIFwiZ3JwYy5tYXhfc2VuZF9tZXNzYWdlX2xlbmd0aFwiOiAoY29uZmlnLnNpemVMaW1pdCB8fCAxNSkgKiAxMDI0ICogMTAyNCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXN0YWJsaXNoZXMgYSBjb25uZWN0aW9uIHRvIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgR2F0ZXdheSBjb25uZWN0aW9uIHdpdGggaWRlbnRpdHkgYW5kIHNpZ25lclxuICAgKiBAcGFyYW0ge0NsaWVudH0gY2xpZW50IC0gVGhlIGdSUEMgY2xpZW50XG4gICAqIEBwYXJhbSB7UGVlckNvbmZpZ30gY29uZmlnIC0gVGhlIHBlZXIgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEdhdGV3YXk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY29ubmVjdGVkIEdhdGV3YXlcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgRmFicmljQWRhcHRlclxuICAgKiAgIHBhcnRpY2lwYW50IElkZW50aXR5XG4gICAqICAgcGFydGljaXBhbnQgU2lnbmVyXG4gICAqICAgcGFydGljaXBhbnQgR2F0ZXdheVxuICAgKlxuICAgKiAgIENhbGxlci0+PkZhYnJpY0FkYXB0ZXI6IGdldENvbm5lY3Rpb24oY2xpZW50LCBjb25maWcpXG4gICAqICAgRmFicmljQWRhcHRlci0+PklkZW50aXR5OiBnZXRJZGVudGl0eShtc3BJZCwgY2VydERpcmVjdG9yeVBhdGgpXG4gICAqICAgSWRlbnRpdHktLT4+RmFicmljQWRhcHRlcjogaWRlbnRpdHlcbiAgICogICBGYWJyaWNBZGFwdGVyLT4+U2lnbmVyOiBnZXRTaWduZXIoa2V5RGlyZWN0b3J5UGF0aClcbiAgICogICBTaWduZXItLT4+RmFicmljQWRhcHRlcjogc2lnbmVyXG4gICAqICAgRmFicmljQWRhcHRlci0+PkZhYnJpY0FkYXB0ZXI6IENyZWF0ZSBDb25uZWN0T3B0aW9uc1xuICAgKiAgIEZhYnJpY0FkYXB0ZXItPj5HYXRld2F5OiBjb25uZWN0KG9wdGlvbnMpXG4gICAqICAgR2F0ZXdheS0tPj5GYWJyaWNBZGFwdGVyOiBnYXRld2F5XG4gICAqICAgRmFicmljQWRhcHRlci0tPj5DYWxsZXI6IGdhdGV3YXlcbiAgICovXG4gIHN0YXRpYyBhc3luYyBnZXRDb25uZWN0aW9uKFxuICAgIGNsaWVudDogQ2xpZW50LFxuICAgIGNvbmZpZzogUGVlckNvbmZpZyxcbiAgICBjdHg6IENvbnRleHQ8RmFicmljQ2xpZW50RmxhZ3M+XG4gICkge1xuICAgIGNvbnN0IGxvZyA9IExvZ2dpbmcuZm9yKHRoaXMuZ2V0Q29ubmVjdGlvbik7XG4gICAgbG9nLmRlYnVnKFxuICAgICAgYFJldHJpZXZpbmcgUGVlciBJZGVudGl0eSBmb3IgJHtjb25maWcubXNwSWR9IHVuZGVyICR7Y29uZmlnLmNlcnRDZXJ0T3JEaXJlY3RvcnlQYXRofWBcbiAgICApO1xuICAgIGNvbnN0IGlkZW50aXR5ID0gYXdhaXQgZ2V0SWRlbnRpdHkoXG4gICAgICBjb25maWcubXNwSWQsXG4gICAgICBjb25maWcuY2VydENlcnRPckRpcmVjdG9yeVBhdGggYXMgYW55XG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgcHJlcGFyaW5nIHRyYW5zYWN0aW9uIHNpZ25lciBmb3IgJHtDcnlwdG9VdGlscy5mYWJyaWNJZEZyb21DZXJ0aWZpY2F0ZShpZGVudGl0eS5jcmVkZW50aWFscy50b1N0cmluZygpKX1gXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGxvZy5lcnJvcihgRmFpbGVkIHRvIGV4dHJhY3QgRmFicmljIElEIGZyb20gY2VydGlmaWNhdGVgLCBlIGFzIEVycm9yKTtcbiAgICB9XG5cbiAgICBsZXQgc2lnbmVyOiBTaWduZXI7XG4gICAgY29uc3QgY2xvc2UgPSAoKSA9PiB7fTtcbiAgICBpZiAoIWNvbmZpZy5oc20pIHtcbiAgICAgIHNpZ25lciA9IGF3YWl0IGdldFNpZ25lcihjb25maWcua2V5Q2VydE9yRGlyZWN0b3J5UGF0aCBhcyBhbnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjb25zdCBoc20gPSBuZXcgSFNNU2lnbmVyRmFjdG9yeUN1c3RvbShjb25maWcuaHNtLmxpYnJhcnkpO1xuICAgICAgLy8gY29uc3QgaWRlbnRpZmllciA9IGhzbS5nZXRTS0lGcm9tQ2VydGlmaWNhdGVQYXRoKFxuICAgICAgLy8gICBjb25maWcuY2VydENlcnRPckRpcmVjdG9yeVBhdGggYXMgYW55XG4gICAgICAvLyApO1xuICAgICAgLy8gY29uc3QgcGtjczExU2lnbmVyID0gaHNtLm5ld1NpZ25lcih7XG4gICAgICAvLyAgIGxhYmVsOiBjb25maWcuaHNtLnRva2VuTGFiZWwgYXMgc3RyaW5nLFxuICAgICAgLy8gICBwaW46IFN0cmluZyhjb25maWcuaHNtLnBpbikgYXMgc3RyaW5nLFxuICAgICAgLy8gICBpZGVudGlmaWVyOiBpZGVudGlmaWVyLFxuICAgICAgLy8gICAvLyB1c2VyVHlwZTogMSAvKkNLVV9VU0VSICovLFxuICAgICAgLy8gfSk7XG4gICAgICAvLyBzaWduZXIgPSBwa2NzMTFTaWduZXIuc2lnbmVyO1xuICAgICAgLy8gY2xvc2UgPSBwa2NzMTFTaWduZXIuY2xvc2U7XG4gICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcIkhTTSBOT1QgSU1QTEVNRU5URURcIik7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgIGNsaWVudCxcbiAgICAgIGlkZW50aXR5OiBpZGVudGl0eSxcbiAgICAgIHNpZ25lcjogc2lnbmVyLFxuICAgICAgLy8gRGVmYXVsdCB0aW1lb3V0cyBmb3IgZGlmZmVyZW50IGdSUEMgY2FsbHNcbiAgICAgIGV2YWx1YXRlT3B0aW9uczogKCkgPT4ge1xuICAgICAgICByZXR1cm4geyBkZWFkbGluZTogRGF0ZS5ub3coKSArIDEwMDAgKiBjdHguZ2V0KFwiZXZhbHVhdGVUaW1lb3V0XCIpIH07IC8vIGRlZmF1bHRzIHRvIDUgc2Vjb25kc1xuICAgICAgfSxcbiAgICAgIGVuZG9yc2VPcHRpb25zOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IGRlYWRsaW5lOiBEYXRlLm5vdygpICsgMTAwMCAqIGN0eC5nZXQoXCJlbmRvcnNlVGltZW91dFwiKSB9OyAvLyBkZWZhdWx0cyB0byAxNSBzZWNvbmRzXG4gICAgICB9LFxuICAgICAgc3VibWl0T3B0aW9uczogKCkgPT4ge1xuICAgICAgICByZXR1cm4geyBkZWFkbGluZTogRGF0ZS5ub3coKSArIDEwMDAgKiBjdHguZ2V0KFwic3VibWl0VGltZW91dFwiKSB9OyAvLyBkZWZhdWx0cyB0byA1IHNlY29uZHNcbiAgICAgIH0sXG4gICAgICBjb21taXRTdGF0dXNPcHRpb25zOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IGRlYWRsaW5lOiBEYXRlLm5vdygpICsgMTAwMCAqIGN0eC5nZXQoXCJjb21taXRUaW1lb3V0XCIpIH07IC8vIGRlZmF1bHRzIHRvIDEgbWludXRlXG4gICAgICB9LFxuICAgIH0gYXMgQ29ubmVjdE9wdGlvbnM7XG5cbiAgICBsb2cuZGVidWcoYENvbm5lY3RpbmcgdG8gJHtjb25maWcubXNwSWR9YCk7XG4gICAgY29uc3QgZ2F0ZXdheSA9IGNvbm5lY3Qob3B0aW9ucyk7XG5cbiAgICAvLyBUT0RPOiByZXBsYWNlP1xuICAgIGlmIChjb25maWcuaHNtKSB7XG4gICAgICBnYXRld2F5LmNsb3NlID0gbmV3IFByb3h5KGdhdGV3YXkuY2xvc2UsIHtcbiAgICAgICAgYXBwbHkodGFyZ2V0OiAoKSA9PiB2b2lkLCB0aGlzQXJnOiBhbnksIGFyZ0FycmF5OiBhbnlbXSk6IGFueSB7XG4gICAgICAgICAgUmVmbGVjdC5hcHBseSh0YXJnZXQsIHRoaXNBcmcsIGFyZ0FycmF5KTtcbiAgICAgICAgICBjbG9zZSgpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdhdGV3YXk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRGlzcGF0Y2ggaW5zdGFuY2UgZm9yIHRoZSBGYWJyaWMgY2xpZW50LlxuICAgKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIGlzIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyBhIG5ldyBGYWJyaWNDbGllbnREaXNwYXRjaCBpbnN0YW5jZSB0aGF0IGNhbiBiZSB1c2VkIHRvIGludGVyYWN0IHdpdGggdGhlIEZhYnJpYyBuZXR3b3JrLlxuICAgKiBAcmV0dXJucyB7RGlzcGF0Y2h9IEEgbmV3IERpc3BhdGNoIGluc3RhbmNlIGNvbmZpZ3VyZWQgZm9yIHRoZSBGYWJyaWMgY2xpZW50LlxuICAgKiBAcmVtYXJrcyBUaGUgRGlzcGF0Y2ggaW5zdGFuY2UgaXMgdXNlZCB0byBlbmNhcHN1bGF0ZSB0aGUgbG9naWMgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEZhYnJpYyBuZXR3b3JrLCBzdWNoIGFzIHN1Ym1pdHRpbmcgdHJhbnNhY3Rpb25zIG9yIHF1ZXJ5aW5nIGRhdGEuXG4gICAqIEBleGFtcGxlXG4gICAqIGNvbnN0IGZhYnJpY0Rpc3BhdGNoID0gZmFicmljQ2xpZW50QWRhcHRlci5EaXNwYXRjaCgpO1xuICAgKiBmYWJyaWNEaXNwYXRjaC5zdWJtaXRUcmFuc2FjdGlvbignY3JlYXRlUHJvZHVjdCcsIHsgbmFtZTogJ1Byb2R1Y3QgQScsIHByaWNlOiAxMDAgfSk7XG4gICAqL1xuICBvdmVycmlkZSBEaXNwYXRjaCgpOiBGYWJyaWNDbGllbnREaXNwYXRjaCB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDbGllbnRBZGFwdGVyW1wiX2Jhc2VEaXNwYXRjaFwiXSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYW4gZXJyb3IgaW50byBhIEJhc2VFcnJvclxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhbnkgZXJyb3IgaW50byBhIHN0YW5kYXJkaXplZCBCYXNlRXJyb3IgdXNpbmcgdGhlIHBhcmVudCBjbGFzcyBpbXBsZW1lbnRhdGlvblxuICAgKiBAcGFyYW0ge0Vycm9yIHwgc3RyaW5nfSBlcnIgLSBUaGUgZXJyb3IgdG8gcGFyc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gT3B0aW9uYWwgcmVhc29uIGZvciB0aGUgZXJyb3JcbiAgICogQHJldHVybiB7QmFzZUVycm9yfSBUaGUgcGFyc2VkIGVycm9yXG4gICAqL1xuICBwcm90ZWN0ZWQgc3RhdGljIHBhcnNlRXJyb3I8RSBleHRlbmRzIEJhc2VFcnJvcj4oZXJyOiBFcnJvciB8IHN0cmluZyk6IEUge1xuICAgIC8vIGlmIChcbiAgICAvLyAgIE1JU1NJTkdfUFJJVkFURV9EQVRBX1JFR0VYLnRlc3QoXG4gICAgLy8gICAgIHR5cGVvZiBlcnIgPT09IFwic3RyaW5nXCIgPyBlcnIgOiBlcnIubWVzc2FnZVxuICAgIC8vICAgKVxuICAgIC8vIClcbiAgICAvLyAgIHJldHVybiBuZXcgVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MoZXJyKSBhcyBFO1xuICAgIGNvbnN0IG1zZyA9IHR5cGVvZiBlcnIgPT09IFwic3RyaW5nXCIgPyBlcnIgOiBlcnIubWVzc2FnZTtcblxuICAgIGlmIChtc2cuaW5jbHVkZXMoXCJNVkNDX1JFQURfQ09ORkxJQ1RcIikpXG4gICAgICByZXR1cm4gbmV3IE12Y2NSZWFkQ29uZmxpY3RFcnJvcihlcnIpIGFzIEU7XG5cbiAgICBpZiAobXNnLmluY2x1ZGVzKFwiREVBRExJTkVfRVhDRUVERURcIikpXG4gICAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uVGltZW91dEVycm9yKGVycikgYXMgRTtcblxuICAgIGlmIChtc2cuaW5jbHVkZXMoXCJFTkRPUlNFTUVOVF9QT0xJQ1lfRkFJTFVSRVwiKSlcbiAgICAgIHJldHVybiBuZXcgRW5kb3JzZW1lbnRQb2xpY3lFcnJvcihlcnIpIGFzIEU7XG5cbiAgICBpZiAobXNnLmluY2x1ZGVzKFwiUEhBTlRPTV9SRUFEX0NPTkZMSUNUXCIpKVxuICAgICAgcmV0dXJuIG5ldyBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IoZXJyKSBhcyBFO1xuXG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIChlcnIgYXMgYW55KS5jb2RlKSB7XG4gICAgICBzd2l0Y2ggKChlcnIgYXMgYW55KS5jb2RlKSB7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICByZXR1cm4gbmV3IEVuZG9yc2VtZW50RXJyb3IoZXJyKSBhcyBFO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtc2cuaW5jbHVkZXMoTm90Rm91bmRFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKENvbmZsaWN0RXJyb3IubmFtZSkpIHJldHVybiBuZXcgQ29uZmxpY3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhCYWRSZXF1ZXN0RXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IEJhZFJlcXVlc3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhRdWVyeUVycm9yLm5hbWUpKSByZXR1cm4gbmV3IFF1ZXJ5RXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoUGFnaW5nRXJyb3IubmFtZSkpIHJldHVybiBuZXcgUGFnaW5nRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoVW5zdXBwb3J0ZWRFcnJvci5uYW1lKSlcbiAgICAgIHJldHVybiBuZXcgVW5zdXBwb3J0ZWRFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhNaWdyYXRpb25FcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBNaWdyYXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhPYnNlcnZlckVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE9ic2VydmVyRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQXV0aG9yaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoRm9yYmlkZGVuRXJyb3IubmFtZSkpIHJldHVybiBuZXcgRm9yYmlkZGVuRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQ29ubmVjdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBDb25uZWN0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoU2VyaWFsaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpIGFzIEU7XG4gIH1cbn1cblxuRmFicmljQ2xpZW50QWRhcHRlci5kZWNvcmF0aW9uKCk7XG5BZGFwdGVyLnNldEN1cnJlbnQoRmFicmljRmxhdm91cik7XG4iLCJpbXBvcnQge1xuICBBZGFwdGVyLFxuICBDb250ZXh0dWFsQXJncyxcbiAgRGlzcGF0Y2gsXG4gIEV2ZW50SWRzLFxuICBVbnN1cHBvcnRlZEVycm9yLFxuICBDb250ZXh0LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFBlZXJDb25maWcgfSBmcm9tIFwiLi4vc2hhcmVkL3R5cGVzXCI7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tIFwiQGdycGMvZ3JwYy1qc1wiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50QWRhcHRlciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7XG4gIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyxcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDaGFpbmNvZGVFdmVudCxcbiAgQ2xvc2VhYmxlQXN5bmNJdGVyYWJsZSxcbn0gZnJvbSBcIkBoeXBlcmxlZGdlci9mYWJyaWMtZ2F0ZXdheVwiO1xuaW1wb3J0IHsgcGFyc2VFdmVudE5hbWUgfSBmcm9tIFwiLi4vc2hhcmVkL2V2ZW50c1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFdmVudCBkaXNwYXRjaGVyIGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIGV2ZW50c1xuICogQHN1bW1hcnkgTGlzdGVucyBmb3IgYW5kIHByb2Nlc3NlcyBldmVudHMgZW1pdHRlZCBieSBGYWJyaWMgY2hhaW5jb2RlLCBkaXNwYXRjaGluZyB0aGVtIHRvIHJlZ2lzdGVyZWQgb2JzZXJ2ZXJzXG4gKiBAdGVtcGxhdGUgUGVlckNvbmZpZyAtIENvbmZpZ3VyYXRpb24gdHlwZSBmb3IgY29ubmVjdGluZyB0byBhIEZhYnJpYyBwZWVyXG4gKiBAcGFyYW0gY2xpZW50IC0gZ1JQQyBjbGllbnQgZm9yIGNvbm5lY3RpbmcgdG8gdGhlIEZhYnJpYyBuZXR3b3JrXG4gKiBAY2xhc3MgRmFicmljQ2xpZW50RGlzcGF0Y2hcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBuZXcgRmFicmljRGlzcGF0Y2ggaW5zdGFuY2VcbiAqIGNvbnN0IGNsaWVudCA9IGF3YWl0IEZhYnJpY0FkYXB0ZXIuZ2V0Q2xpZW50KHBlZXJDb25maWcpO1xuICogY29uc3QgZGlzcGF0Y2ggPSBuZXcgRmFicmljRGlzcGF0Y2goY2xpZW50KTtcbiAqXG4gKiAvLyBDb25maWd1cmUgdGhlIGRpc3BhdGNoIHdpdGggcGVlciBjb25maWd1cmF0aW9uXG4gKiBkaXNwYXRjaC5jb25maWd1cmUocGVlckNvbmZpZyk7XG4gKlxuICogLy8gUmVnaXN0ZXIgYW4gb2JzZXJ2ZXIgZm9yIGEgc3BlY2lmaWMgdGFibGUgYW5kIGV2ZW50XG4gKiBkaXNwYXRjaC5vYnNlcnZlKCd1c2VycycsICdjcmVhdGUnLCAoaWQpID0+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+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlciBvciBjb25maWcgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jb250ZXh0KFxuICAgICAgXCJkaXNwYXRjaFwiLFxuICAgICAge1xuICAgICAgICBjb3JyZWxhdGlvbklkOiB0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYWluY29kZU5hbWUsXG4gICAgICB9LFxuICAgICAgTW9kZWwgYXMgYW55XG4gICAgKTtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmluaXRpYWxpemUpO1xuICAgIGNvbnN0IGdhdGV3YXkgPSBhd2FpdCBGYWJyaWNDbGllbnRBZGFwdGVyLmdldEdhdGV3YXkoXG4gICAgICBjdHgsXG4gICAgICB0aGlzLmFkYXB0ZXIuY29uZmlnIGFzIFBlZXJDb25maWcsXG4gICAgICB0aGlzLmNsaWVudFxuICAgICk7XG4gICAgY29uc3QgbmV0d29yayA9IGdhdGV3YXkuZ2V0TmV0d29yayh0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYW5uZWwpO1xuICAgIGlmICghdGhpcy5hZGFwdGVyKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE5vIGFkYXB0ZXIgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgdGhpcy5saXN0ZW5pbmdTdGFjayA9IGF3YWl0IG5ldHdvcmsuZ2V0Q2hhaW5jb2RlRXZlbnRzKFxuICAgICAgdGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFpbmNvZGVOYW1lXG4gICAgKTtcbiAgICB0aGlzLmhhbmRsZUV2ZW50cyhjdHgpO1xuICB9XG59XG5cbmlmIChGYWJyaWNDbGllbnRBZGFwdGVyKVxuICBGYWJyaWNDbGllbnRBZGFwdGVyW1wiX2Jhc2VEaXNwYXRjaFwiXSA9IEZhYnJpY0NsaWVudERpc3BhdGNoO1xuIiwiaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9OQU1FID0gXCIjI1BBQ0tBR0UjI1wiO1xuXG5NZXRhZGF0YS5yZWdpc3RlckxpYnJhcnkoUEFDS0FHRV9OQU1FLCBWRVJTSU9OKTtcbiJdLCJuYW1lcyI6WyJGYWJyaWNDbGllbnRSZXBvc2l0b3J5IiwiUmVwb3NpdG9yeSIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImNsYXp6Iiwic3VwZXIiLCJ0aGlzIiwiX292ZXJyaWRlcyIsIk9iamVjdCIsImFzc2lnbiIsImlnbm9yZVZhbGlkYXRpb24iLCJpZ25vcmVIYW5kbGVycyIsImFsbG93UmF3U3RhdGVtZW50cyIsImZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXMiLCJmb3JjZVByZXBhcmVDb21wbGV4UXVlcmllcyIsImFsbG93R2VuZXJhdGlvbk92ZXJyaWRlIiwib3ZlcnJpZGUiLCJmbGFncyIsImZvciIsIk9ic2VydmVySGFuZGxlciIsInBhZ2luYXRlQnkiLCJrZXkiLCJvcmRlciIsInJlZiIsIm9mZnNldCIsImxpbWl0IiwiYXJncyIsImxvZyIsImN0eEFyZ3MiLCJsb2dDdHgiLCJQcmVwYXJlZFN0YXRlbWVudEtleXMiLCJQQUdFX0JZIiwidmVyYm9zZSIsIk1vZGVsIiwidGFibGVOYW1lIiwiY2xhc3MiLCJzdGF0ZW1lbnQiLCJuYW1lIiwiYm9va21hcmsiLCJsaXN0QnkiLCJMSVNUX0JZIiwiZmluZEJ5IiwidmFsdWUiLCJGSU5EX0JZIiwiZmluZE9uZUJ5IiwiRklORF9PTkVfQlkiLCJmaW5kIiwiT3JkZXJEaXJlY3Rpb24iLCJBU0MiLCJGSU5EIiwicGFnZSIsImRpcmVjdGlvbiIsIlBBR0UiLCJjdHgiLCJQZXJzaXN0ZW5jZUtleXMiLCJTVEFURU1FTlQiLCJjYWxsQXJncyIsInNsaWNlIiwicmVzdWx0IiwiSlNPTiIsInBhcnNlIiwiZGVjb2RlIiwiZXZhbHVhdGVUcmFuc2FjdGlvbiIsInN0cmluZ2lmeSIsInVuZGVmaW5lZCIsIkFycmF5IiwiaXNBcnJheSIsIm1hcCIsInIiLCJDb3VjaERCS2V5cyIsIlRBQkxFIiwiUGFnaW5hdG9yIiwiaXNTZXJpYWxpemVkUGFnZSIsImRhdGEiLCJkIiwiY291bnRPZiIsIkNPVU5UX09GIiwic3RtdEFyZ3MiLCJtYXhPZiIsIk1BWF9PRiIsIm1pbk9mIiwiTUlOX09GIiwiYXZnT2YiLCJBVkdfT0YiLCJzdW1PZiIsIlNVTV9PRiIsImRpc3RpbmN0T2YiLCJESVNUSU5DVF9PRiIsImdyb3VwT2YiLCJHUk9VUF9PRiIsImhlYWx0aGNoZWNrIiwiY3JlYXRlIiwibW9kZWwiLCJkZWJ1ZyIsInJlY29yZCIsImlkIiwidHJhbnNpZW50IiwicHJlcGFyZSIsInJldmVydCIsInVwZGF0ZSIsImNyZWF0ZUFsbFByZWZpeCIsIm1vZGVscyIsIk9wZXJhdGlvbktleXMiLCJDUkVBVEUiLCJnZXQiLCJpZ25vcmVWYWxpZGF0ZSIsImxlbmd0aCIsIlByb21pc2UiLCJhbGwiLCJhc3luYyIsIm0iLCJlbmZvcmNlREJEZWNvcmF0b3JzIiwiT04iLCJpZ25vcmVkUHJvcHMiLCJlcnJvcnMiLCJyZXNvbHZlIiwiaGFzRXJyb3JzIiwiZXJyb3JNZXNzYWdlcyIsInJlZHVjZUVycm9yc1RvUHJpbnQiLCJWYWxpZGF0aW9uRXJyb3IiLCJjcmVhdGVBbGwiLCJwcmVwYXJlZCIsImlkcyIsInAiLCJyZWNvcmRzIiwiaSIsInVwZGF0ZUFsbCIsInVwZGF0ZWQiLCJ1IiwiRVJDMjBUb2tlbiIsIkJhc2VNb2RlbCIsIl9fZGVjb3JhdGUiLCJwayIsInR5cGUiLCJTdHJpbmciLCJwcm90b3R5cGUiLCJjb2x1bW4iLCJyZXF1aXJlZCIsInRhYmxlIiwiRVJDMjBXYWxsZXQiLCJBbGxvd2FuY2UiLCJDbGllbnRTZXJpYWxpemVyIiwiSlNPTlNlcmlhbGl6ZXIiLCJwcmVTZXJpYWxpemUiLCJtb2RlbE5hbWUiLCJ0b1NlcmlhbGl6ZSIsIm1ldGFkYXRhIiwiTWV0YWRhdGEiLCJTZXJpYWxpemF0aW9uRXJyb3IiLCJNb2RlbEtleXMiLCJBTkNIT1IiLCJkZXNlcmlhbGl6ZSIsInN0ciIsImRlc2VyaWFsaXphdGlvbiIsImNsYXNzTmFtZSIsIkVycm9yIiwiYnVpbGQiLCJzZXJpYWxpemUiLCJGYWJyaWNFUkMyMENsaWVudFJlcG9zaXRvcnkiLCJzZXJpYWxpemVyIiwiZGVjb2RlciIsIlRleHREZWNvZGVyIiwidXBkYXRlT2JzZXJ2ZXJzIiwiZXZlbnQiLCJvYnNlcnZlckhhbmRsZXIiLCJJbnRlcm5hbEVycm9yIiwiY291bnQiLCJwYXJzZWRJZCIsIlNlcXVlbmNlIiwicGFyc2VWYWx1ZSIsInNlcXVlbmNlRm9yIiwidG9rZW5OYW1lIiwic3ltYm9sIiwiZGVjaW1hbHMiLCJOdW1iZXIiLCJ0b3RhbFN1cHBseSIsInRvdGFsIiwiYmFsYW5jZU9mIiwib3duZXIiLCJiYWxhbmNlIiwidHJhbnNmZXIiLCJ0byIsInRyYW5zZmVycmVkIiwic3VibWl0VHJhbnNhY3Rpb24iLCJ0b1N0cmluZyIsInRyYW5zZmVyRnJvbSIsImZyb20iLCJjb250ZXh0QXJncyIsIkNvbnRleHQiLCJhcHByb3ZlIiwic3BlbmRlciIsImFwcHJvdmVkIiwiYWxsb3dhbmNlIiwiaW5pdGlhbGl6ZSIsInRva2VuIiwiaW5pdGlsaWF6ZWQiLCJjaGVja0luaXRpYWxpemVkIiwibWludCIsImFtb3VudCIsImJ1cm4iLCJidXJuRnJvbSIsImFjY291bnQiLCJjbGllbnRBY2NvdW50QmFsYW5jZSIsInNlcmlhbGl6ZWRBY2NvdW50QmFsYW5jZSIsImNsaWVudEFjY291bnRJRCIsImVuc3VyZURpcmVjdG9yeUV4aXN0ZW5jZSIsImZpbGVQYXRoIiwiZnMiLCJyZXF1aXJlIiwicGF0aCIsImRpcm5hbWUiLCJleGlzdHNTeW5jIiwibWtkaXJTeW5jIiwiZ2VuZXJhdGVNb2RlbEluZGV4ZXMiLCJnZW5lcmF0ZUluZGV4ZXMiLCJnZW5lcmF0ZU1vZGVsRGVzaWduRG9jcyIsImFjY3VtIiwidmlld3MiLCJnZW5lcmF0ZVZpZXdzIiwic3RvcmFnZSIsImZvckVhY2giLCJkb2MiLCJfaWQiLCJyZWFkTW9kZWxGaWxlIiwiZmlsZSIsImV4cG9ydHMiLCJqb2luIiwicHJvY2VzcyIsImN3ZCIsInBhcmVudFBhdGgiLCJ2YWx1ZXMiLCJmaWx0ZXIiLCJlIiwicmVhZE1vZGVsRm9sZGVycyIsImZvbGRlcnMiLCJmb2xkZXIiLCJmaWxlcyIsInJlYWRkaXJTeW5jIiwid2l0aEZpbGVUeXBlcyIsInJlY3Vyc2l2ZSIsImYiLCJpc0ZpbGUiLCJlbmRzV2l0aCIsInB1c2giLCJ3cml0ZUluZGV4ZXMiLCJpbmRleGVzIiwiY29sbGVjdGlvbiIsImluZGV4Iiwid3JpdGVGaWxlU3luYyIsIndyaXRlRGVzaWduRG9jcyIsImRlc2lnbkRvY3MiLCJkb2NJZCIsInJlcGxhY2UiLCJwYXlsb2FkIiwiX3JldiIsIklkZW50aXR5Q3JlZGVudGlhbHMiLCJhcmciLCJkZXNjcmlwdGlvbiIsIkZhYnJpY01vZGVsS2V5cyIsIklkZW50aXR5VHlwZSIsIkZhYnJpY0ZsYXZvdXIiLCJJZGVudGl0eSIsIlg1MDkiLCJvbmVUb09uZSIsIkNhc2NhZGUiLCJDQVNDQURFIiwiZGVsZXRlIiwiQ29yZVV0aWxzIiwibG9nZ2VyIiwiTWluaUxvZ2dlciIsImNvbnRlbnRPZkxvYWRGaWxlIiwiY29udGVudE9yUGF0aCIsImZpbGVSZWFkZXIiLCJVaW50OEFycmF5IiwibWF0Y2giLCJyZWFkRmlsZSIsInByb21pc2VzIiwibm9ybWFsaXplSW1wb3J0IiwiaW1wb3J0IiwiZ2V0Q0FVc2VyIiwidXNlck5hbWUiLCJwcml2YXRlS2V5IiwiY2VydGlmaWNhdGUiLCJtc3BJZCIsIm9wdGlvbnMiLCJzdHJpbmdGb3JtYXQiLCJ1c2VyIiwiVXNlciIsImNvbmZpZyIsImhzbSIsInNvZnR3YXJlIiwibGliIiwibGlicmFyeSIsInNsb3QiLCJsYWJlbCIsInRva2VuTGFiZWwiLCJwaW4iLCJjcnlwdG9TdWl0ZSIsImdldENyeXB0b1N1aXRlIiwic2V0Q3J5cHRvU3VpdGUiLCJlbnJvbGxtZW50S2V5IiwiZ2V0SFNNRW5yb2xsbWVudEtleSIsImdldFNvZnR3YXJlRW5yb2xsbWVudEtleSIsInNldEVucm9sbG1lbnQiLCJuZXdDcnlwdG9TdWl0ZSIsImNyZWF0ZUtleUZyb21SYXciLCJza2kiLCJrZXlJZEhleCIsInRyaW0iLCJCdWZmZXIiLCJnZXRDZXJ0aWZpY2F0ZVNLSSIsImdldEtleSIsImlzUHJpdmF0ZSIsIng1MDkiLCJYNTA5Q2VydGlmaWNhdGUiLCJqd2siLCJwdWJsaWNLZXkiLCJleHBvcnQiLCJmb3JtYXQiLCJwcmVmaXgiLCJ4IiwieSIsImNyeXB0byIsImNyZWF0ZUhhc2giLCJjb25jYXQiLCJkaWdlc3QiLCJnZXRJZGVudGl0eSIsImNlcnREaXJlY3RvcnlQYXRoIiwiaWRlbnRpdHlGaWxlUmVhZGVyIiwiY2VydFBhdGgiLCJnZXRGaXJzdERpckZpbGVOYW1lIiwiY3JlZGVudGlhbHMiLCJkaXJQYXRoIiwicmVhZGRpciIsImdldEZpcnN0RGlyRmlsZU5hbWVDb250ZW50IiwiZ2V0RmlsZUNvbnRlbnQiLCJnZXRTaWduZXIiLCJrZXlEaXJlY3RvcnlQYXRoIiwic2lnbmVyRmlsZVJlYWRlciIsImtleVBhdGgiLCJwcml2YXRlS2V5UGVtIiwiZXh0cmFjdFByaXZhdGVLZXkiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiayIsInNpZ25lcnMiLCJuZXdQcml2YXRlS2V5U2lnbmVyIiwicGVtIiwibGliTmFtZSIsInN1YnRsZSIsImdsb2JhbFRoaXMiLCJ3aW5kb3ciLCJDcnlwdG8iLCJ3ZWJjcnlwdG8iLCJzdHIyYWIiLCJidWYiLCJBcnJheUJ1ZmZlciIsImJ1ZlZpZXciLCJzdHJMZW4iLCJjaGFyQ29kZUF0IiwicmVwbGFjZUFsbCIsImRlY29kZWQiLCJiaW5hcnlEZXIiLCJpbXBvcnRLZXkiLCJuYW1lZEN1cnZlIiwiY3J5cHRvUHJvdmlkZXIiLCJzZXQiLCJCQVNFX0FMUEhBQkVUIiwiQ1JZUFRPIiwiQmFzZUVuY29kZXIiLCJhbHBoYWJldCIsImJhc2VNYXAiLCJqIiwiY2hhckF0IiwieGMiLCJiYXNlIiwibGVhZGVyIiwiZmFjdG9yIiwiTWF0aCIsImlGYWN0b3IiLCJlbmNvZGUiLCJzb3VyY2UiLCJpc1ZpZXciLCJidWZmZXIiLCJieXRlT2Zmc2V0IiwiYnl0ZUxlbmd0aCIsInplcm9lcyIsInBiZWdpbiIsInBlbmQiLCJzaXplIiwiYjU4IiwiY2FycnkiLCJpdDEiLCJpdDIiLCJyZXBlYXQiLCJkZWNvZGVVbnNhZmUiLCJwc3oiLCJiMjU2IiwiaXQzIiwiaXQ0IiwidmNoIiwiQ3J5cHRvVXRpbHMiLCJiNThlbmNvZGVyIiwiQkFTRTU4IiwiZmFicmljSWRGcm9tQ2VydGlmaWNhdGUiLCJjZXJ0Iiwic3ViamVjdCIsImlzc3VlciIsInN0cmluZ1RvQXJyYXlCdWZmZXIiLCJleHRyYWN0S2V5IiwidXNhZ2VzIiwiUmVnRXhwIiwidG9VcHBlckNhc2UiLCJleHRyYWN0UHVibGljS2V5Iiwic2lnbiIsImJ1ZmYiLCJoYXNoIiwiYiIsInBhZFN0YXJ0IiwidmVyaWZ5Iiwic2lnbmF0dXJlIiwiZW5jcnlwdCIsImdldFN1YnRsZUNyeXB0byIsImlzQnJvd3NlciIsImRlY3J5cHQiLCJnZXRNYXN0ZXIiLCJ0ZXh0RW5jb2RlciIsIlRleHRFbmNvZGVyIiwiZ2VuR2VuZXNpcyIsInJhbmRvbVVVSUQiLCJpbXBvcnRlZEtleSIsIktFWV9BTEdPUllUSE0iLCJpdiIsImdldERlcml2YXRpb25LZXkiLCJzYWx0Iiwic2FsdEJ1ZmZlciIsInNhbHRIYXNoZWQiLCJwYXJhbXMiLCJIQVNIIiwiaXRlcmF0aW9ucyIsIklURVJBVElPTlMiLCJkZXJpdmF0aW9uIiwiZGVyaXZlQml0cyIsIktFWUxFTkdUSCIsIml2bGVuIiwia2V5bGVuIiwiZGVyaXZlZEtleSIsImltcG9ydGVkRW5jcnlwdGlvbktleSIsIkFMR09SWVRITSIsImVuY3J5cHRQaW4iLCJ0ZXh0Iiwia2V5T2JqZWN0IiwidGV4dEJ1ZmZlciIsImVuY3J5cHRlZFRleHQiLCJkZWNyeXB0UGluIiwidGV4dERlY29kZXIiLCJkZWNyeXB0ZWRUZXh0IiwiT3ZlcmZsb3dFcnJvciIsIm1zZyIsIkJhbGFuY2VFcnJvciIsIkFsbG93YW5jZUVycm9yIiwiUmVnaXN0cmF0aW9uRXJyb3IiLCJBdXRob3JpemF0aW9uRXJyb3IiLCJNaXNzaW5nQ29udGV4dEVycm9yIiwiVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MiLCJCYXNlRXJyb3IiLCJOb3RJbml0aWFsaXplZEVycm9yIiwiTWlzc2luZ1BLQ1NTMTFMaWIiLCJFbmRvcnNlbWVudEVycm9yIiwibWVzc2FnZSIsIk12Y2NSZWFkQ29uZmxpY3RFcnJvciIsIlBoYW50b21SZWFkQ29uZmxpY3RFcnJvciIsIkVuZG9yc2VtZW50UG9saWN5RXJyb3IiLCJUcmFuc2FjdGlvbkxpbWl0c0Vycm9yIiwiY29kZSIsIlRyYW5zYWN0aW9uVGltZW91dEVycm9yIiwiVHJhbnNhY3Rpb25CdWZmZXJTaXplRXJyb3IiLCJIRkNBSWRlbnRpdHlUeXBlIiwiSEZDQUlkZW50aXR5QXR0cmlidXRlcyIsIkZhYnJpY0Vucm9sbG1lbnRTZXJ2aWNlIiwiTG9nZ2VkQ2xhc3MiLCJjYUNvbmZpZyIsImNhTmFtZSIsImNhQ2VydCIsImNhS2V5IiwidXJsIiwiQ0EiLCJjYSIsInRscyIsInRydXN0ZWRSb290cyIsInJvb3QiLCJGYWJyaWNDQVNlcnZpY2VzIiwiQ2xpZW50IiwiY2xpZW50IiwiQ2VydGlmaWNhdGUiLCJjZXJ0aWZpY2F0ZVNlcnZpY2UiLCJuZXdDZXJ0aWZpY2F0ZVNlcnZpY2UiLCJBZmZpbGlhdGlvbnMiLCJhZmZpbGlhdGlvblNlcnZpY2UiLCJuZXdBZmZpbGlhdGlvblNlcnZpY2UiLCJJZGVudGl0aWVzIiwiaWRlbnRpdHlTZXJ2aWNlIiwibmV3SWRlbnRpdHlTZXJ2aWNlIiwiZ2V0Q2VydGlmaWNhdGVzIiwicmVxdWVzdCIsImRvTWFwIiwicmVzcG9uc2UiLCJjZXJ0cyIsImMiLCJQRU0iLCJnZXRJZGVudGl0aWVzIiwiaWRlbnRpdGllc1NlcnZpY2UiLCJnZXRBbGwiLCJpZGVudGl0aWVzIiwicGFyc2VFcnJvciIsInJlZ2V4cCIsImV4ZWMiLCJDb25mbGljdEVycm9yIiwiZ2V0QWZmaWxpYXRpb25zIiwiYSIsInJlYWQiLCJlbnJvbGxtZW50SWQiLCJnZXRPbmUiLCJOb3RGb3VuZEVycm9yIiwic3VjY2VzcyIsInJlZ2lzdGVyIiwiaXNTdXBlclVzZXIiLCJhZmZpbGlhdGlvbiIsInVzZXJSb2xlIiwiYXR0cnMiLCJtYXhFbnJvbGxtZW50cyIsInJlZ2lzdHJhdGlvbiIsInBhc3N3b3JkIiwicHJvcHMiLCJlbnJvbGxtZW50SUQiLCJlbnJvbGxtZW50U2VjcmV0IiwiaW5mbyIsImlkZW50aXR5RnJvbUVucm9sbG1lbnQiLCJlbnJvbGxtZW50Iiwicm9vdENlcnRpZmljYXRlIiwiTG9nZ2luZyIsImNsaWVudElkIiwibm93IiwiRGF0ZSIsInRvQnl0ZXMiLCJjcmVhdGVkT24iLCJ1cGRhdGVkT24iLCJlbnJvbGwiLCJpZGVudGl0eSIsInJlZ2lzdGVyQW5kRW5yb2xsIiwicmV2b2tlIiwicmVhc29uIiwiUmVnaXN0cmF0aW9uUmVxdWVzdEJ1aWxkZXIiLCJlcnJzIiwicm9sZSIsInNldEFmZmlsaWF0aW9uIiwiYWRkQXR0ciIsImF0dHIiLCJzZXRBdHRycyIsInNldEVucm9sbG1lbnRJRCIsInNldEVucm9sbG1lbnRTZWNyZXQiLCJzZXRNYXhFbnJvbGxtZW50cyIsInNldFJvbGUiLCJtaW5sZW5ndGgiLCJtaW4iLCJFUkMyMEV2ZW50cyIsIkZhYnJpY0Jhc2VNb2RlbCIsImNyZWF0ZWRBdCIsInVwZGF0ZWRBdCIsInZlcnNpb24iLCJ1c2VzIiwiRmFicmljSWRlbnRpZmllZEJhc2VNb2RlbCIsImNyZWF0ZWRCeSIsInVwZGF0ZWRCeSIsImlzU2hhcmVkIiwic2VncmVnYXRlIiwiaXNUcmFuc2llbnQiLCJkZWNvcmF0ZWRQcm9wZXJ0aWVzIiwidmFsaWRhdGFibGVQcm9wZXJ0aWVzIiwidHJhbnNpZW50UHJvcHMiLCJEQktleXMiLCJUUkFOU0lFTlQiLCJwcml2YXRlUHJvcGVydGllcyIsIlBSSVZBVEUiLCJzaGFyZWRQcm9wZXJ0aWVzIiwiU0hBUkVEIiwicHJpdmF0ZXMiLCJzaGFyZWQiLCJ0cmFuc2llbnRLZXlzIiwicHJpdmF0ZUtleXMiLCJzaGFyZWRLZXlzIiwiaW5jbHVkZXMiLCJzaG91bGRJbmNsdWRlSW5Nb2RlbCIsImJpbmQiLCJtaXJyb3JlZCIsIkZBQlJJQyIsIk1JUlJPUiIsIm93bmVyT2YiLCJtZXRhIiwiT1dORURfQlkiLCJtaXJyb3JlZEF0IiwiY29sbGVjdGlvbnNGb3IiLCJzaGFyZWRLZXkiLCJjb25zdHIiLCJwcml2YXRlTWV0YSIsInNoYXJlZE1ldGEiLCJwcml2YXRlQ29scyIsImNvbGxlY3Rpb25zIiwic2hhcmVkQ29scyIsIk1JUlJPUl9TS0lQX0ZMQUdfUFJFRklYIiwiZXh0cmFjdE1zcElkIiwiZ2V0TVNQSUQiLCJPd25lciIsInRhcmdldCIsInByb3BlcnR5S2V5IiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsTWV0aG9kIiwiYWNvdW50SWQiLCJjbGllbnRJZGVudGl0eSIsImdldElEIiwic2VsZWN0IiwidG9rZW5zIiwiZXhlY3V0ZSIsImFwcGx5Iiwib3duZWRCeU9uQ3JlYXRlIiwiY29udGV4dCIsInN0dWIiLCJjcmVhdG9yIiwiZ2V0Q3JlYXRvciIsIm1zcGlkIiwic2V0T3duZWRCeUtleVZhbHVlIiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwid3JpdGFibGUiLCJjb25maWd1cmFibGUiLCJvd25lZEJ5Iiwib2JqIiwiYXR0cmlidXRlIiwiZ2VuZXJhdGVkIiwicmVhZG9ubHkiLCJvbkNyZWF0ZSIsInByb3BNZXRhZGF0YSIsIkRlY29yYXRpb24iLCJkZWZpbmUiLCJkZWNvcmF0b3IiLCJ0cmFuc2FjdGlvbklkT25DcmVhdGUiLCJnZXRUeElEIiwidHJhbnNhY3Rpb25JZCIsIm9uVXBkYXRlIiwiVFJBTlNBQ1RJT05fSUQiLCJldmFsTWlycm9yTWV0YWRhdGEiLCJyZXNvbHZlciIsImNyZWF0ZU1pcnJvckhhbmRsZXIiLCJyZXBvIiwic2VncmVnYXRlZCIsIm1pcnJvciIsInVwZGF0ZU1pcnJvckhhbmRsZXIiLCJhcHBseVVwZGF0ZVZhbGlkYXRpb24iLCJtZXJnZUZvclVwZGF0ZSIsImRlbGV0ZU1pcnJvckhhbmRsZXIiLCJwa1Byb3AiLCJtaXJyb3JXcml0ZUd1YXJkIiwibXNwIiwiY29uZGl0aW9uIiwicmVhZE1pcnJvckhhbmRsZXIiLCJza2lwRmxhZ0tleSIsImZhYnJpY0N0eCIsIm1hdGNoZXMiLCJwdXQiLCJyZWFkRnJvbSIsInByaXZhdGVEYXRhIiwib25SZWFkIiwicHJpb3JpdHkiLCJvbkRlbGV0ZSIsImFmdGVyQ3JlYXRlIiwiYWZ0ZXJVcGRhdGUiLCJhZnRlckRlbGV0ZSIsIk1vZGVsQ29sbGVjdGlvbiIsIm9yZ05hbWUiLCJ0b1Bhc2NhbENhc2UiLCJOYW1lc3BhY2VDb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwiSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvbiIsIlNFR1JFR0FURURfQ09MTEVDVElPTl9FWFRSQUNUSU9OX1BSSU9SSVRZIiwiZXh0cmFjdFNlZ3JlZ2F0ZWRDb2xsZWN0aW9ucyIsImRhdGFBcnJheSIsImNvbGxlY3Rpb25SZXNvbHZlciIsImlzRnVsbHlTZWdyZWdhdGVkIiwicHVibGljS2V5cyIsIm1hcmtGdWxseVNlZ3JlZ2F0ZWQiLCJzZXFOYW1lIiwic2V0U2VxdWVuY2VTZWdyZWdhdGlvbiIsInNlZ3JlZ2F0ZWREYXRhT25DcmVhdGUiLCJrZXlBcnJheSIsIl9rIiwiVW5zdXBwb3J0ZWRFcnJvciIsIndyaXRlVG8iLCJzZWdyZWdhdGVkRGF0YU9uUmVhZCIsImdldE9yVW5kZWZpbmVkIiwic2VncmVnYXRlZERhdGFPblVwZGF0ZSIsIm9sZE1vZGVsIiwic2VncmVnYXRlZERhdGFPbkRlbGV0ZSIsImlubmVyU2VncmVnYXRlZCIsInNlZ3JlZ2F0ZWREZWMiLCJTZXQiLCJhZGQiLCJjb25zdHJNZXRhIiwiY29uc3RyQ29sbGVjdGlvbnMiLCJ0cmFuc2llbnRNZXRhIiwidXBkYXRlZFRyYW5zaWVudE1ldGEiLCJkZWNzIiwicHJvcGVydGllcyIsImdyb3VwTmFtZSIsImV4dHJhY3RHcm91cE5hbWUiLCJkYXRhR3JvdXBOYW1lIiwiZWFybHlFeHRyYWN0aW9uTWV0YSIsImVhcmx5RXh0cmFjdGlvbkdyb3VwU29ydCIsImdyb3VwIiwicHJvcCIsIm9uIiwiREJPcGVyYXRpb25zIiwiQUxMIiwic2hhcmVkRGF0YSIsIkRldGVybWluaXN0aWNTZXJpYWxpemVyIiwiZXJyb3IiLCJzZWxmIiwibyIsImNhbGwiLCJyZWxhdGlvbnMiLCJzb3J0S2V5c1JlY3Vyc2l2ZSIsImdlbmVyYXRlRmFicmljRXZlbnROYW1lIiwicGFyc2VFdmVudE5hbWUiLCJwYXJ0cyIsInNwbGl0Iiwic3ViIiwic2FmZVBhcnNlSW50Iiwic3RyaW5nIiwiZGlnaXRSZWdleCIsInRlc3QiLCJwYXJzZWRpbnQiLCJwYXJzZUludCIsImlzTmFOIiwiU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIiLCJwdXRBbmNob3IiLCJwcmVTZXJpYWxpemF0aW9uIiwiRmFicmljSWRlbnRpdHlTZXJ2aWNlIiwiQ2xpZW50QmFzZWRTZXJ2aWNlIiwicm9vdENsaWVudCIsIl91c2VyIiwiY2VydGlmaWNhdGVzIiwiYWZmaWxpYXRpb25zIiwiZ2V0VXNlciIsImNmZyIsIklOSVRJQUxJWkFUSU9OIiwiZ2V0TmFtZSIsIlJFQUQiLCJyZWVucm9sbCIsImF0dHJSZXFzIiwiY3JlYXRlVXNlciIsImdldE1zcGlkIiwibmV3SWRlbnRpdHkiLCJDQV9ST0xFIiwiRGVmYXVsdEZhYnJpY0NsaWVudEZsYWdzIiwiZXZhbHVhdGVUaW1lb3V0IiwiZW5kb3JzZVRpbWVvdXQiLCJzdWJtaXRUaW1lb3V0IiwiY29tbWl0VGltZW91dCIsImVzY2FwZVJlZ0V4cCIsIm5leHRMZXhpY29ncmFwaGljU3RyaW5nIiwiY2hhcnMiLCJjb2RlUG9pbnRBdCIsImZyb21Db2RlUG9pbnQiLCJwcmVmaXhSYW5nZSIsInN0YXJ0IiwiZW5kIiwiRmFicmljQ2xpZW50U3RhdGVtZW50IiwiU3RhdGVtZW50Iiwib3ZlcnJpZGVzIiwic3F1YXNoIiwic3F1YXNoZWQiLCJtZXRob2QiLCJleGVjdXRlUHJlcGFyZWQiLCJhcmd6IiwiZm9yTW9kZWwiLCJmcm9tU2VsZWN0b3IiLCJhbGlhcyIsIlFVRVJZIiwiaXNTaW1wbGVRdWVyeSIsIlF1ZXJ5Q2xhdXNlIiwid2hlcmVDb25kaXRpb24iLCJwYXJzZWQiLCJwcmVwYXJlQ29uZGl0aW9uIiwic2VsZWN0U2VsZWN0b3IiLCJTRUxFQ1QiLCJBTkQiLCJ0b0xvd2VyQ2FzZSIsIm9yZGVyQnlTZWxlY3RvcnMiLCJPUkRFUl9CWSIsInRvQ2FtZWxDYXNlIiwicHJvY2Vzc1JlY29yZCIsInBrQXR0ciIsInNlcXVlbmNlVHlwZSIsIklEIiwia2V5QXJncyIsIlNFUEFSQVRPUiIsInJhdyIsInJhd0lucHV0IiwiYWdncmVnYXRvciIsImFnZ3JlZ2F0ZUluZm8iLCJhZ2dyZWdhdGUiLCJleGVjdXRlQWdncmVnYXRlIiwicmVzdWx0cyIsImFnZ3JlZ2F0ZVF1ZXJ5IiwiYnVpbGRBZ2dyZWdhdGVRdWVyeSIsInNlbGVjdG9ycyIsInF1ZXJ5Iiwic2VsZWN0b3IiLCJmaWVsZHMiLCJwYXJzZUNvbmRpdGlvbiIsIkNvbmRpdGlvbiIsImFuZCIsImVxIiwic2VsZWN0b3JLZXlzIiwiQ291Y2hEQkdyb3VwT3BlcmF0b3IiLCJpbmRleE9mIiwicmVkdWNlIiwidmFsIiwiT1IiLCJzIiwiZW50cmllcyIsIndhcm4iLCJzb3J0Iiwic2VsZWN0b3JLZXkiLCJyZWMiLCJDb3VjaERCT3BlcmF0b3IiLCJCSUdHRVIiLCJsaW1pdFNlbGVjdG9yIiwiQ291Y2hEQlF1ZXJ5TGltaXQiLCJvZmZzZXRTZWxlY3RvciIsInNraXAiLCJtZXJnZSIsIm9wIiwib2JqMSIsIm9iajIiLCJhdHRyMSIsIm9wZXJhdG9yIiwiY29tcGFyaXNvbiIsIk9wZXJhdG9yIiwiU1RBUlRTX1dJVEgiLCJRdWVyeUVycm9yIiwicmFuZ2UiLCJCSUdHRVJfRVEiLCJTTUFMTEVSIiwiRU5EU19XSVRIIiwiUkVHRVhQIiwiQkVUV0VFTiIsIm1heCIsIm9wQmV0d2VlbiIsInRyYW5zbGF0ZU9wZXJhdG9ycyIsIlNNQUxMRVJfRVEiLCJHcm91cE9wZXJhdG9yIiwiTk9UIiwib3AxIiwib3AyIiwiYXZnU2VsZWN0b3IiLCJzdW1JbmZvIiwiY3JlYXRlQWdncmVnYXRlRGVzY3JpcHRvciIsImNvdW50SW5mbyIsImNyZWF0ZUFnZ3JlZ2F0ZVF1ZXJ5Iiwia2luZCIsInN1bURlc2NyaXB0b3IiLCJjb3VudERlc2NyaXB0b3IiLCJjb3VudERpc3RpbmN0U2VsZWN0b3IiLCJjb3VudERpc3RpbmN0IiwiYWdncmVnYXRvclVzZWQiLCJjb3VudFNlbGVjdG9yIiwibWluU2VsZWN0b3IiLCJtYXhTZWxlY3RvciIsInN1bVNlbGVjdG9yIiwiZGlzdGluY3RTZWxlY3RvciIsImFnZ3JlZ2F0b3JDaGVja3MiLCJtZXRhcyIsImZpbmRWaWV3TWV0YWRhdGEiLCJ2aWV3TmFtZSIsImdlbmVyYXRlVmlld05hbWUiLCJkZG9jIiwiZ2VuZXJhdGVEZXNpZ25Eb2NOYW1lIiwicmV0dXJuRG9jcyIsInZpZXciLCJnZXRGYWJyaWNBZGFwdGVyIiwiaXNWaWV3QWdncmVnYXRlIiwiaGFuZGxlQXZlcmFnZSIsImZhYnJpY0FkYXB0ZXIiLCJ2aWV3SW5mbyIsInByb2Nlc3NWaWV3UmVzcG9uc2UiLCJzdW1EZXNjIiwiY291bnREZXNjIiwic3VtUmVzcG9uc2UiLCJjb3VudFJlc3BvbnNlIiwic3VtIiwicm93cyIsInJvdyIsIkZhYnJpY0NsaWVudFBhZ2luYXRvciIsInJhd1N0YXRlbWVudCIsIkZhYnJpY0NsaWVudEFkYXB0ZXIiLCJBZGFwdGVyIiwib3BlcmF0aW9uIiwic2lsbHkiLCJwb3AiLCJ0b092ZXJyaWRlcyIsIkJvb2xlYW4iLCJuZXdDdHgiLCJhY2N1bXVsYXRlIiwicGFyZW50Q29udGV4dCIsImNoaWxkQ29udGV4dHMiLCJjdXJyZW50T3AiLCJjdXJyZW50TW9kZWwiLCJyZXBvc2l0b3J5IiwiY3JlYXRlUHJlZml4IiwidXBkYXRlQWxsUHJlZml4Iiwic2hpZnQiLCJCdWxrQ3J1ZE9wZXJhdGlvbktleXMiLCJDUkVBVEVfQUxMIiwicmVhZEFsbCIsIlJFQURfQUxMIiwiVVBEQVRFX0FMTCIsImRlbGV0ZUFsbCIsIkRFTEVURV9BTEwiLCJNRVRBREFUQSIsInVwZGF0ZVByZWZpeCIsIlVQREFURSIsIkRFTEVURSIsImRvY3NPbmx5IiwidHJhbnNhY3Rpb25SZXN1bHQiLCJwYXJzZVJlY29yZCIsImlzTW9kZWwiLCJlbCIsImdldENsaWVudCIsIl9jbGllbnQiLCJHYXRld2F5IiwiZ2V0R2F0ZXdheSIsImdldENvbnRyYWN0TmFtZSIsIkNvbnRyYWN0IiwiY29udHJhY3ROYW1lIiwiZ2V0Q29udHJhY3QiLCJ0cmFuc2FjdGlvbiIsImFwaSIsInN1Ym1pdCIsInRyYW5zaWVudERhdGEiLCJlbmRvcnNpbmdPcmdhbml6YXRpb25zIiwiZ2F0ZXdheSIsImNvbnRyYWN0IiwiZXZhbHVhdGUiLCJwcm9wb3NhbE9wdGlvbnMiLCJhcmd1bWVudHMiLCJhY2MiLCJkZXRhaWxzIiwiY2xvc2UiLCJlcnIiLCJuZXR3b3JrIiwiZ2V0TmV0d29yayIsImNoYW5uZWwiLCJjaGFpbmNvZGVOYW1lIiwiY2hhbm5lbE5hbWUiLCJnZXRDb25uZWN0aW9uIiwicGF0aE9yQ2VydCIsInRsc0NlcnQiLCJyZWFkRmlsZVN5bmMiLCJ0bHNDcmVkZW50aWFscyIsImdycGMiLCJjcmVhdGVTc2wiLCJwZWVyRW5kcG9pbnQiLCJzaXplTGltaXQiLCJjZXJ0Q2VydE9yRGlyZWN0b3J5UGF0aCIsInNpZ25lciIsImtleUNlcnRPckRpcmVjdG9yeVBhdGgiLCJldmFsdWF0ZU9wdGlvbnMiLCJkZWFkbGluZSIsImVuZG9yc2VPcHRpb25zIiwic3VibWl0T3B0aW9ucyIsImNvbW1pdFN0YXR1c09wdGlvbnMiLCJjb25uZWN0IiwiUHJveHkiLCJ0aGlzQXJnIiwiYXJnQXJyYXkiLCJSZWZsZWN0IiwiRGlzcGF0Y2giLCJCYWRSZXF1ZXN0RXJyb3IiLCJQYWdpbmdFcnJvciIsIk1pZ3JhdGlvbkVycm9yIiwiT2JzZXJ2ZXJFcnJvciIsIkZvcmJpZGRlbkVycm9yIiwiQ29ubmVjdGlvbkVycm9yIiwiZmluYWwiLCJEIiwiX2EiLCJkZWNvcmF0aW9uIiwic2V0Q3VycmVudCIsIkZhYnJpY0NsaWVudERpc3BhdGNoIiwibGlzdGVuaW5nU3RhY2siLCJwYXJzZVBheWxvYWQiLCJqc29uQnl0ZXMiLCJqc29uIiwib2JzZXJ2ZSIsIm9ic2VydmVyIiwidW5PYnNlcnZlIiwicmVmcmVzaCIsImhhbmRsZUV2ZW50cyIsImN0eEFyZyIsImNvcnJlbGF0aW9uSWQiLCJldnQiLCJldmVudE5hbWUiLCJ0YXJnZXRNb2RlbCIsIm1vZGVsUmVmIiwiZ2V0Q2hhaW5jb2RlRXZlbnRzIiwiVkVSU0lPTiIsIlBBQ0tBR0VfTkFNRSIsInJlZ2lzdGVyTGlicmFyeSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztJQXFETSxNQUFPQSwrQkFHSEMsS0FBQUE7UUFVUixXQUFBQyxDQUFZQyxTQUFhQztZQUN2QkMsTUFBTUYsU0FBU0M7WUFWRUUsS0FBQUMsYUFBYUMsT0FBT0MsT0FBTyxDQUFBLEdBQUlKLE1BQU0sZUFBZTtnQkFDckVLLGtCQUFrQjtnQkFDbEJDLGdCQUFnQjtnQkFDaEJDLG9CQUFvQjtnQkFDcEJDLDJCQUEyQjtnQkFDM0JDLDRCQUE0QjtnQkFDNUJDLHlCQUF5Qjs7QUFLM0I7UUFFUyxRQUFBQyxDQUFTQztZQUNoQixPQUFPWixNQUNKVyxTQUFTUixPQUFPQyxPQUFPLENBQUEsR0FBSVEsT0FBT1gsS0FBS0MsYUFDdkNXLElBQUlEO0FBQ1Q7UUFFbUIsZUFBQUU7WUFDakIsT0FBT2QsTUFBTWM7QUFDZjtRQUVTLGdCQUFNQyxDQUNiQyxLQUNBQyxPQUNBQyxNQUErQztZQUM3Q0MsUUFBUTtZQUNSQyxPQUFPO2NBRU5DO1lBRUgsT0FBTUMsS0FBRUEsS0FBR0MsU0FBRUEsa0JBQ0x0QixLQUFLdUIsT0FBT0gsTUFBTUksS0FBQUEsc0JBQXNCQyxTQUFTLE9BQ3ZEYixJQUFJWixLQUFLYztZQUNYTyxJQUFJSyxRQUNGLGNBQWNDLG9CQUFBQSxNQUFNQyxVQUFVNUIsS0FBSzZCLHlCQUF5QlosSUFBSUU7WUFFbEUsT0FBT25CLEtBQUs4QixVQUNWOUIsS0FBS2MsV0FBV2lCLE1BQ2hCaEIsS0FDQUMsT0FDQTtnQkFBRUcsT0FBT0YsSUFBSUU7Z0JBQU9ELFFBQVFELElBQUlDO2dCQUFRYyxVQUFVZixJQUFJZTtrQkFDbkRWO0FBRVA7UUFFUyxZQUFNVyxDQUNibEIsS0FDQUMsVUFDR0k7WUFFSCxPQUFNQyxLQUFFQSxLQUFHQyxTQUFFQSxrQkFDTHRCLEtBQUt1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