@decaf-ts/for-fabric 0.1.78 → 0.1.79

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