@decaf-ts/for-fabric 0.1.94 → 0.1.95

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