@decaf-ts/for-fabric 0.1.55 → 0.1.57

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 (381) hide show
  1. package/dist/for-fabric.cjs +2 -1964
  2. package/dist/for-fabric.cjs.map +1 -0
  3. package/dist/for-fabric.js +2 -2099
  4. package/dist/for-fabric.js.map +1 -0
  5. package/lib/bin/cli.cjs +1 -2
  6. package/lib/bin/cli.js.map +1 -0
  7. package/lib/cli-module.cjs +1 -1
  8. package/lib/cli-module.js.map +1 -0
  9. package/lib/cli-utils.cjs +1 -1
  10. package/lib/cli-utils.js.map +1 -0
  11. package/lib/client/FabricClientAdapter.cjs +36 -1
  12. package/lib/client/FabricClientAdapter.d.ts +2 -1
  13. package/lib/client/FabricClientAdapter.js.map +1 -0
  14. package/lib/client/FabricClientDispatch.cjs +1 -1
  15. package/lib/client/FabricClientDispatch.js.map +1 -0
  16. package/lib/client/FabricClientPaginator.cjs +1 -1
  17. package/lib/client/FabricClientPaginator.js.map +1 -0
  18. package/lib/client/FabricClientRepository.cjs +1 -1
  19. package/lib/client/FabricClientRepository.js.map +1 -0
  20. package/lib/client/FabricClientStatement.cjs +1 -1
  21. package/lib/client/FabricClientStatement.js.map +1 -0
  22. package/lib/client/collections/generation.cjs +1 -1
  23. package/lib/client/collections/generation.js.map +1 -0
  24. package/lib/client/collections/index.cjs +1 -1
  25. package/lib/client/collections/index.js.map +1 -0
  26. package/lib/client/constants.cjs +1 -1
  27. package/lib/client/constants.js.map +1 -0
  28. package/lib/client/crypto.cjs +1 -1
  29. package/lib/client/crypto.js.map +1 -0
  30. package/lib/client/erc20/FabricERC20ClientRepository.cjs +1 -1
  31. package/lib/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  32. package/lib/client/erc20/index.cjs +1 -1
  33. package/lib/client/erc20/index.js.map +1 -0
  34. package/lib/client/fabric-fs.cjs +1 -1
  35. package/lib/client/fabric-fs.js.map +1 -0
  36. package/lib/client/fabric-hsm.cjs +1 -1
  37. package/lib/client/fabric-hsm.js.map +1 -0
  38. package/lib/client/index.cjs +2 -1
  39. package/lib/client/index.d.ts +1 -0
  40. package/lib/client/index.js.map +1 -0
  41. package/lib/client/indexes/generation.cjs +1 -1
  42. package/lib/client/indexes/generation.js.map +1 -0
  43. package/lib/client/indexes/index.cjs +1 -1
  44. package/lib/client/indexes/index.js.map +1 -0
  45. package/lib/client/logging.cjs +1 -1
  46. package/lib/client/logging.js.map +1 -0
  47. package/lib/client/services/FabricEnrollmentService.cjs +1 -1
  48. package/lib/client/services/FabricEnrollmentService.js.map +1 -0
  49. package/lib/client/services/FabricIdentityService.cjs +1 -1
  50. package/lib/client/services/FabricIdentityService.js.map +1 -0
  51. package/lib/client/services/RegistrationRequestBuilder.cjs +1 -1
  52. package/lib/client/services/RegistrationRequestBuilder.js.map +1 -0
  53. package/lib/client/services/constants.cjs +1 -1
  54. package/lib/client/services/constants.js.map +1 -0
  55. package/lib/client/services/index.cjs +1 -1
  56. package/lib/client/services/index.js.map +1 -0
  57. package/lib/client/types.cjs +1 -1
  58. package/lib/client/types.js.map +1 -0
  59. package/lib/client/utils.cjs +1 -1
  60. package/lib/client/utils.js.map +1 -0
  61. package/lib/contract/Address.cjs +1 -1
  62. package/lib/contract/Address.js.map +1 -0
  63. package/lib/contract/AddressContract.cjs +1 -1
  64. package/lib/contract/AddressContract.js.map +1 -0
  65. package/lib/contract/BatchContract.cjs +1 -1
  66. package/lib/contract/BatchContract.js.map +1 -0
  67. package/lib/contract/Product.cjs +1 -1
  68. package/lib/contract/Product.js.map +1 -0
  69. package/lib/contract/ProductContract.cjs +1 -1
  70. package/lib/contract/ProductContract.js.map +1 -0
  71. package/lib/contract/User.cjs +1 -1
  72. package/lib/contract/User.js.map +1 -0
  73. package/lib/contract/UserContract.cjs +1 -1
  74. package/lib/contract/UserContract.js.map +1 -0
  75. package/lib/contract/index.cjs +1 -1
  76. package/lib/contract/index.js.map +1 -0
  77. package/lib/contract/models/Audit.cjs +1 -1
  78. package/lib/contract/models/Audit.js.map +1 -0
  79. package/lib/contract/models/BaseIdentifiedModel.cjs +1 -1
  80. package/lib/contract/models/BaseIdentifiedModel.js.map +1 -0
  81. package/lib/contract/models/BaseModel.cjs +1 -1
  82. package/lib/contract/models/BaseModel.js.map +1 -0
  83. package/lib/contract/models/Batch.cjs +1 -1
  84. package/lib/contract/models/Batch.js.map +1 -0
  85. package/lib/contract/models/Leaflet.cjs +1 -1
  86. package/lib/contract/models/Leaflet.js.map +1 -0
  87. package/lib/contract/models/LeafletFile.cjs +1 -1
  88. package/lib/contract/models/LeafletFile.js.map +1 -0
  89. package/lib/contract/models/Market.cjs +1 -1
  90. package/lib/contract/models/Market.js.map +1 -0
  91. package/lib/contract/models/Product.cjs +1 -1
  92. package/lib/contract/models/Product.js.map +1 -0
  93. package/lib/contract/models/ProductStrength.cjs +1 -1
  94. package/lib/contract/models/ProductStrength.js.map +1 -0
  95. package/lib/contract/models/constants.cjs +1 -1
  96. package/lib/contract/models/constants.js.map +1 -0
  97. package/lib/contract/models/decorators.cjs +1 -1
  98. package/lib/contract/models/decorators.js.map +1 -0
  99. package/lib/contract/models/gtin.cjs +1 -1
  100. package/lib/contract/models/gtin.js.map +1 -0
  101. package/lib/contracts/ContractAdapter.cjs +3 -1
  102. package/lib/contracts/ContractAdapter.js.map +1 -0
  103. package/lib/contracts/ContractContext.cjs +1 -1
  104. package/lib/contracts/ContractContext.js.map +1 -0
  105. package/lib/contracts/ContractPrivateDataAdapter.cjs +1 -1
  106. package/lib/contracts/ContractPrivateDataAdapter.js.map +1 -0
  107. package/lib/contracts/FabricConstruction.cjs +1 -1
  108. package/lib/contracts/FabricConstruction.js.map +1 -0
  109. package/lib/contracts/FabricContractPaginator.cjs +1 -1
  110. package/lib/contracts/FabricContractPaginator.js.map +1 -0
  111. package/lib/contracts/FabricContractRepository.cjs +1 -1
  112. package/lib/contracts/FabricContractRepository.js.map +1 -0
  113. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +1 -1
  114. package/lib/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  115. package/lib/contracts/FabricContractSequence.cjs +1 -1
  116. package/lib/contracts/FabricContractSequence.js.map +1 -0
  117. package/lib/contracts/FabricContractStatement.cjs +1 -1
  118. package/lib/contracts/FabricContractStatement.js.map +1 -0
  119. package/lib/contracts/PrivateSequence.cjs +1 -1
  120. package/lib/contracts/PrivateSequence.js.map +1 -0
  121. package/lib/contracts/crud/crud-contract.cjs +1 -1
  122. package/lib/contracts/crud/crud-contract.js.map +1 -0
  123. package/lib/contracts/crud/index.cjs +1 -1
  124. package/lib/contracts/crud/index.js.map +1 -0
  125. package/lib/contracts/crud/serialized-crud-contract.cjs +1 -1
  126. package/lib/contracts/crud/serialized-crud-contract.js.map +1 -0
  127. package/lib/contracts/erc20/erc20contract.cjs +1 -1
  128. package/lib/contracts/erc20/erc20contract.js.map +1 -0
  129. package/lib/contracts/erc20/index.cjs +1 -1
  130. package/lib/contracts/erc20/index.js.map +1 -0
  131. package/lib/contracts/erc20/models.cjs +1 -1
  132. package/lib/contracts/erc20/models.js.map +1 -0
  133. package/lib/contracts/index.cjs +1 -1
  134. package/lib/contracts/index.js.map +1 -0
  135. package/lib/contracts/logging.cjs +1 -1
  136. package/lib/contracts/logging.js.map +1 -0
  137. package/lib/contracts/private-data.cjs +1 -1
  138. package/lib/contracts/private-data.js.map +1 -0
  139. package/lib/contracts/types.cjs +1 -1
  140. package/lib/contracts/types.d.ts +2 -0
  141. package/lib/contracts/types.js.map +1 -0
  142. package/lib/esm/bin/cli.js +1 -1
  143. package/lib/esm/bin/cli.js.map +1 -0
  144. package/lib/esm/cli-module.js +1 -1
  145. package/lib/esm/cli-module.js.map +1 -0
  146. package/lib/esm/cli-utils.js +1 -1
  147. package/lib/esm/cli-utils.js.map +1 -0
  148. package/lib/esm/client/FabricClientAdapter.d.ts +2 -1
  149. package/lib/esm/client/FabricClientAdapter.js +36 -1
  150. package/lib/esm/client/FabricClientAdapter.js.map +1 -0
  151. package/lib/esm/client/FabricClientDispatch.js +1 -1
  152. package/lib/esm/client/FabricClientDispatch.js.map +1 -0
  153. package/lib/esm/client/FabricClientPaginator.js +1 -1
  154. package/lib/esm/client/FabricClientPaginator.js.map +1 -0
  155. package/lib/esm/client/FabricClientRepository.js +1 -1
  156. package/lib/esm/client/FabricClientRepository.js.map +1 -0
  157. package/lib/esm/client/FabricClientStatement.js +1 -1
  158. package/lib/esm/client/FabricClientStatement.js.map +1 -0
  159. package/lib/esm/client/collections/generation.js +1 -1
  160. package/lib/esm/client/collections/generation.js.map +1 -0
  161. package/lib/esm/client/collections/index.js +1 -1
  162. package/lib/esm/client/collections/index.js.map +1 -0
  163. package/lib/esm/client/constants.js +1 -1
  164. package/lib/esm/client/constants.js.map +1 -0
  165. package/lib/esm/client/crypto.js +1 -1
  166. package/lib/esm/client/crypto.js.map +1 -0
  167. package/lib/esm/client/erc20/FabricERC20ClientRepository.js +1 -1
  168. package/lib/esm/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  169. package/lib/esm/client/erc20/index.js +1 -1
  170. package/lib/esm/client/erc20/index.js.map +1 -0
  171. package/lib/esm/client/fabric-fs.js +1 -1
  172. package/lib/esm/client/fabric-fs.js.map +1 -0
  173. package/lib/esm/client/fabric-hsm.js +1 -1
  174. package/lib/esm/client/fabric-hsm.js.map +1 -0
  175. package/lib/esm/client/index.d.ts +1 -0
  176. package/lib/esm/client/index.js +2 -1
  177. package/lib/esm/client/index.js.map +1 -0
  178. package/lib/esm/client/indexes/generation.js +1 -1
  179. package/lib/esm/client/indexes/generation.js.map +1 -0
  180. package/lib/esm/client/indexes/index.js +1 -1
  181. package/lib/esm/client/indexes/index.js.map +1 -0
  182. package/lib/esm/client/logging.js +1 -1
  183. package/lib/esm/client/logging.js.map +1 -0
  184. package/lib/esm/client/services/FabricEnrollmentService.js +1 -1
  185. package/lib/esm/client/services/FabricEnrollmentService.js.map +1 -0
  186. package/lib/esm/client/services/FabricIdentityService.js +1 -1
  187. package/lib/esm/client/services/FabricIdentityService.js.map +1 -0
  188. package/lib/esm/client/services/RegistrationRequestBuilder.js +1 -1
  189. package/lib/esm/client/services/RegistrationRequestBuilder.js.map +1 -0
  190. package/lib/esm/client/services/constants.js +1 -1
  191. package/lib/esm/client/services/constants.js.map +1 -0
  192. package/lib/esm/client/services/index.js +1 -1
  193. package/lib/esm/client/services/index.js.map +1 -0
  194. package/lib/esm/client/types.js +1 -1
  195. package/lib/esm/client/types.js.map +1 -0
  196. package/lib/esm/client/utils.js +1 -1
  197. package/lib/esm/client/utils.js.map +1 -0
  198. package/lib/esm/contract/Address.js +1 -1
  199. package/lib/esm/contract/Address.js.map +1 -0
  200. package/lib/esm/contract/AddressContract.js +1 -1
  201. package/lib/esm/contract/AddressContract.js.map +1 -0
  202. package/lib/esm/contract/BatchContract.js +1 -1
  203. package/lib/esm/contract/BatchContract.js.map +1 -0
  204. package/lib/esm/contract/Product.js +1 -1
  205. package/lib/esm/contract/Product.js.map +1 -0
  206. package/lib/esm/contract/ProductContract.js +1 -1
  207. package/lib/esm/contract/ProductContract.js.map +1 -0
  208. package/lib/esm/contract/User.js +1 -1
  209. package/lib/esm/contract/User.js.map +1 -0
  210. package/lib/esm/contract/UserContract.js +1 -1
  211. package/lib/esm/contract/UserContract.js.map +1 -0
  212. package/lib/esm/contract/index.js +1 -1
  213. package/lib/esm/contract/index.js.map +1 -0
  214. package/lib/esm/contract/models/Audit.js +1 -1
  215. package/lib/esm/contract/models/Audit.js.map +1 -0
  216. package/lib/esm/contract/models/BaseIdentifiedModel.js +1 -1
  217. package/lib/esm/contract/models/BaseIdentifiedModel.js.map +1 -0
  218. package/lib/esm/contract/models/BaseModel.js +1 -1
  219. package/lib/esm/contract/models/BaseModel.js.map +1 -0
  220. package/lib/esm/contract/models/Batch.js +1 -1
  221. package/lib/esm/contract/models/Batch.js.map +1 -0
  222. package/lib/esm/contract/models/Leaflet.js +1 -1
  223. package/lib/esm/contract/models/Leaflet.js.map +1 -0
  224. package/lib/esm/contract/models/LeafletFile.js +1 -1
  225. package/lib/esm/contract/models/LeafletFile.js.map +1 -0
  226. package/lib/esm/contract/models/Market.js +1 -1
  227. package/lib/esm/contract/models/Market.js.map +1 -0
  228. package/lib/esm/contract/models/Product.js +1 -1
  229. package/lib/esm/contract/models/Product.js.map +1 -0
  230. package/lib/esm/contract/models/ProductStrength.js +1 -1
  231. package/lib/esm/contract/models/ProductStrength.js.map +1 -0
  232. package/lib/esm/contract/models/constants.js +1 -1
  233. package/lib/esm/contract/models/constants.js.map +1 -0
  234. package/lib/esm/contract/models/decorators.js +1 -1
  235. package/lib/esm/contract/models/decorators.js.map +1 -0
  236. package/lib/esm/contract/models/gtin.js +1 -1
  237. package/lib/esm/contract/models/gtin.js.map +1 -0
  238. package/lib/esm/contracts/ContractAdapter.js +3 -1
  239. package/lib/esm/contracts/ContractAdapter.js.map +1 -0
  240. package/lib/esm/contracts/ContractContext.js +1 -1
  241. package/lib/esm/contracts/ContractContext.js.map +1 -0
  242. package/lib/esm/contracts/ContractPrivateDataAdapter.js +1 -1
  243. package/lib/esm/contracts/ContractPrivateDataAdapter.js.map +1 -0
  244. package/lib/esm/contracts/FabricConstruction.js +1 -1
  245. package/lib/esm/contracts/FabricConstruction.js.map +1 -0
  246. package/lib/esm/contracts/FabricContractPaginator.js +1 -1
  247. package/lib/esm/contracts/FabricContractPaginator.js.map +1 -0
  248. package/lib/esm/contracts/FabricContractRepository.js +1 -1
  249. package/lib/esm/contracts/FabricContractRepository.js.map +1 -0
  250. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +1 -1
  251. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  252. package/lib/esm/contracts/FabricContractSequence.js +1 -1
  253. package/lib/esm/contracts/FabricContractSequence.js.map +1 -0
  254. package/lib/esm/contracts/FabricContractStatement.js +1 -1
  255. package/lib/esm/contracts/FabricContractStatement.js.map +1 -0
  256. package/lib/esm/contracts/PrivateSequence.js +1 -1
  257. package/lib/esm/contracts/PrivateSequence.js.map +1 -0
  258. package/lib/esm/contracts/crud/crud-contract.js +1 -1
  259. package/lib/esm/contracts/crud/crud-contract.js.map +1 -0
  260. package/lib/esm/contracts/crud/index.js +1 -1
  261. package/lib/esm/contracts/crud/index.js.map +1 -0
  262. package/lib/esm/contracts/crud/serialized-crud-contract.js +1 -1
  263. package/lib/esm/contracts/crud/serialized-crud-contract.js.map +1 -0
  264. package/lib/esm/contracts/erc20/erc20contract.js +1 -1
  265. package/lib/esm/contracts/erc20/erc20contract.js.map +1 -0
  266. package/lib/esm/contracts/erc20/index.js +1 -1
  267. package/lib/esm/contracts/erc20/index.js.map +1 -0
  268. package/lib/esm/contracts/erc20/models.js +1 -1
  269. package/lib/esm/contracts/erc20/models.js.map +1 -0
  270. package/lib/esm/contracts/index.js +1 -1
  271. package/lib/esm/contracts/index.js.map +1 -0
  272. package/lib/esm/contracts/logging.js +1 -1
  273. package/lib/esm/contracts/logging.js.map +1 -0
  274. package/lib/esm/contracts/private-data.js +1 -1
  275. package/lib/esm/contracts/private-data.js.map +1 -0
  276. package/lib/esm/contracts/types.d.ts +2 -0
  277. package/lib/esm/contracts/types.js +1 -1
  278. package/lib/esm/contracts/types.js.map +1 -0
  279. package/lib/esm/index.js +1 -1
  280. package/lib/esm/index.js.map +1 -0
  281. package/lib/esm/shared/ClientSerializer.js +1 -1
  282. package/lib/esm/shared/ClientSerializer.js.map +1 -0
  283. package/lib/esm/shared/DeterministicSerializer.js +1 -1
  284. package/lib/esm/shared/DeterministicSerializer.js.map +1 -0
  285. package/lib/esm/shared/SimpleDeterministicSerializer.js +1 -1
  286. package/lib/esm/shared/SimpleDeterministicSerializer.js.map +1 -0
  287. package/lib/esm/shared/constants.js +1 -1
  288. package/lib/esm/shared/constants.js.map +1 -0
  289. package/lib/esm/shared/decorators.js +1 -1
  290. package/lib/esm/shared/decorators.js.map +1 -0
  291. package/lib/esm/shared/erc20/erc20-constants.js +1 -1
  292. package/lib/esm/shared/erc20/erc20-constants.js.map +1 -0
  293. package/lib/esm/shared/erc20/index.js +1 -1
  294. package/lib/esm/shared/erc20/index.js.map +1 -0
  295. package/lib/esm/shared/errors.js +1 -1
  296. package/lib/esm/shared/errors.js.map +1 -0
  297. package/lib/esm/shared/events.js +1 -1
  298. package/lib/esm/shared/events.js.map +1 -0
  299. package/lib/esm/shared/fabric-types.js +1 -1
  300. package/lib/esm/shared/fabric-types.js.map +1 -0
  301. package/lib/esm/shared/index.js +1 -1
  302. package/lib/esm/shared/index.js.map +1 -0
  303. package/lib/esm/shared/interfaces/Checkable.js +1 -1
  304. package/lib/esm/shared/interfaces/Checkable.js.map +1 -0
  305. package/lib/esm/shared/interfaces/index.js +1 -1
  306. package/lib/esm/shared/interfaces/index.js.map +1 -0
  307. package/lib/esm/shared/math.js +1 -1
  308. package/lib/esm/shared/math.js.map +1 -0
  309. package/lib/esm/shared/model/FabricBaseModel.js +1 -1
  310. package/lib/esm/shared/model/FabricBaseModel.js.map +1 -0
  311. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js +1 -1
  312. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  313. package/lib/esm/shared/model/Identity.js +1 -1
  314. package/lib/esm/shared/model/Identity.js.map +1 -0
  315. package/lib/esm/shared/model/IdentityCredentials.js +1 -1
  316. package/lib/esm/shared/model/IdentityCredentials.js.map +1 -0
  317. package/lib/esm/shared/model/index.js +1 -1
  318. package/lib/esm/shared/model/index.js.map +1 -0
  319. package/lib/esm/shared/overrides/Model.js +1 -1
  320. package/lib/esm/shared/overrides/Model.js.map +1 -0
  321. package/lib/esm/shared/overrides/index.js +1 -1
  322. package/lib/esm/shared/overrides/index.js.map +1 -0
  323. package/lib/esm/shared/overrides/overrides.js +1 -1
  324. package/lib/esm/shared/overrides/overrides.js.map +1 -0
  325. package/lib/esm/shared/types.js +1 -1
  326. package/lib/esm/shared/types.js.map +1 -0
  327. package/lib/esm/version.d.ts +1 -1
  328. package/lib/esm/version.js +2 -2
  329. package/lib/esm/version.js.map +1 -0
  330. package/lib/index.cjs +1 -1
  331. package/lib/index.js.map +1 -0
  332. package/lib/shared/ClientSerializer.cjs +1 -1
  333. package/lib/shared/ClientSerializer.js.map +1 -0
  334. package/lib/shared/DeterministicSerializer.cjs +1 -1
  335. package/lib/shared/DeterministicSerializer.js.map +1 -0
  336. package/lib/shared/SimpleDeterministicSerializer.cjs +1 -1
  337. package/lib/shared/SimpleDeterministicSerializer.js.map +1 -0
  338. package/lib/shared/constants.cjs +1 -1
  339. package/lib/shared/constants.js.map +1 -0
  340. package/lib/shared/decorators.cjs +1 -1
  341. package/lib/shared/decorators.js.map +1 -0
  342. package/lib/shared/erc20/erc20-constants.cjs +1 -1
  343. package/lib/shared/erc20/erc20-constants.js.map +1 -0
  344. package/lib/shared/erc20/index.cjs +1 -1
  345. package/lib/shared/erc20/index.js.map +1 -0
  346. package/lib/shared/errors.cjs +1 -1
  347. package/lib/shared/errors.js.map +1 -0
  348. package/lib/shared/events.cjs +1 -1
  349. package/lib/shared/events.js.map +1 -0
  350. package/lib/shared/fabric-types.cjs +1 -1
  351. package/lib/shared/fabric-types.js.map +1 -0
  352. package/lib/shared/index.cjs +1 -1
  353. package/lib/shared/index.js.map +1 -0
  354. package/lib/shared/interfaces/Checkable.cjs +1 -1
  355. package/lib/shared/interfaces/Checkable.js.map +1 -0
  356. package/lib/shared/interfaces/index.cjs +1 -1
  357. package/lib/shared/interfaces/index.js.map +1 -0
  358. package/lib/shared/math.cjs +1 -1
  359. package/lib/shared/math.js.map +1 -0
  360. package/lib/shared/model/FabricBaseModel.cjs +1 -1
  361. package/lib/shared/model/FabricBaseModel.js.map +1 -0
  362. package/lib/shared/model/FabricIdentifiedBaseModel.cjs +1 -1
  363. package/lib/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  364. package/lib/shared/model/Identity.cjs +1 -1
  365. package/lib/shared/model/Identity.js.map +1 -0
  366. package/lib/shared/model/IdentityCredentials.cjs +1 -1
  367. package/lib/shared/model/IdentityCredentials.js.map +1 -0
  368. package/lib/shared/model/index.cjs +1 -1
  369. package/lib/shared/model/index.js.map +1 -0
  370. package/lib/shared/overrides/Model.cjs +1 -1
  371. package/lib/shared/overrides/Model.js.map +1 -0
  372. package/lib/shared/overrides/index.cjs +1 -1
  373. package/lib/shared/overrides/index.js.map +1 -0
  374. package/lib/shared/overrides/overrides.cjs +1 -1
  375. package/lib/shared/overrides/overrides.js.map +1 -0
  376. package/lib/shared/types.cjs +1 -1
  377. package/lib/shared/types.js.map +1 -0
  378. package/lib/version.cjs +2 -2
  379. package/lib/version.d.ts +1 -1
  380. package/lib/version.js.map +1 -0
  381. package/package.json +1 -1
@@ -1,2099 +1,2 @@
1
- import { Model, JSONSerializer, ModelKeys, ValidationKeys, required, model, stringFormat } from "@decaf-ts/decorator-validation";
2
-
3
- import { Metadata, Decoration, propMetadata, description, uses, apply, metadata } from "@decaf-ts/decoration";
4
-
5
- import { DBKeys, OperationKeys, BulkCrudOperationKeys, BaseError, InternalError, NotFoundError, ConflictError, SerializationError, BadRequestError, onCreate, onCreateUpdate, version, readonly, onUpdate, transient, onRead, onDelete, ValidationError } from "@decaf-ts/db-decorators";
6
-
7
- import { PersistenceKeys, Context, ObserverHandler, Adapter, Repository, QueryError, PreparedStatementKeys, Condition, Sequence, SequenceModel, Serial, UUID, PagingError, AuthorizationError, UnsupportedError, MigrationError, ObserverError, ForbiddenError, ConnectionError, column, createdAt, updatedAt, createdBy, updatedBy, BaseModel, pk, oneToOne, Cascade, index, OrderDirection, table } from "@decaf-ts/core";
8
-
9
- import { CouchDBStatement, CouchDBKeys, CouchDBGroupOperator, CouchDBOperator, CouchDBPaginator, CouchDBAdapter } from "@decaf-ts/for-couchdb";
10
-
11
- import { Property, Object as Object$1, Contract, Transaction, Context as Context$1 } from "fabric-contract-api";
12
-
13
- import { Logging, MiniLogger, NumericLogLevels, LogLevel } from "@decaf-ts/logging";
14
-
15
- import { __decorate, __metadata } from "tslib";
16
-
17
- var FabricModelKeys;
18
-
19
- (function(FabricModelKeys) {
20
- FabricModelKeys["PRIVATE"] = "private";
21
- FabricModelKeys["SHARED"] = "shared";
22
- FabricModelKeys["FABRIC"] = "fabric.";
23
- FabricModelKeys["OWNEDBY"] = "owned-by";
24
- FabricModelKeys["TRANSACTION_ID"] = "transaction-id";
25
- })(FabricModelKeys || (FabricModelKeys = {}));
26
-
27
- var IdentityType;
28
-
29
- (function(IdentityType) {
30
- IdentityType["X509"] = "X.509";
31
- })(IdentityType || (IdentityType = {}));
32
-
33
- const FabricFlavour = "hlf-fabric";
34
-
35
- Model.prototype.isShared = function isShared() {
36
- return Model.isShared(this.constructor);
37
- };
38
-
39
- Model.prototype.isPrivate = function isPrivate() {
40
- return Model.isPrivate(this.constructor);
41
- };
42
-
43
- Model.prototype.segregate = function segregate() {
44
- return Model.segregate(this);
45
- };
46
-
47
- Model.segregate = function segregate(model) {
48
- if (!Model.isTransient(model)) return {
49
- model: model
50
- };
51
- const decoratedProperties = Metadata.validatableProperties(model.constructor);
52
- const transientProps = Metadata.get(model.constructor, DBKeys.TRANSIENT);
53
- const privateProperties = Metadata.get(model.constructor, FabricModelKeys.PRIVATE);
54
- const sharedProperties = Metadata.get(model.constructor, FabricModelKeys.PRIVATE);
55
- const result = {
56
- model: {},
57
- transient: {},
58
- private: {},
59
- shared: {}
60
- };
61
- const transientKeys = Object.keys(transientProps);
62
- const privateKeys = Object.keys(privateProperties);
63
- const sharedKeys = Object.keys(sharedProperties);
64
- for (const key of decoratedProperties) {
65
- const isTransient = transientKeys.includes(key);
66
- const isPrivate = privateKeys.includes(key);
67
- const isShared = sharedKeys.includes(key);
68
- if (isTransient) {
69
- result.transient = result.transient || {};
70
- result.transient[key] = model[key];
71
- if (isPrivate) {
72
- result.private = result.private || {};
73
- result.private[key] = model[key];
74
- }
75
- if (isShared) {
76
- result.shared = result.shared || {};
77
- result.shared[key] = model[key];
78
- }
79
- } else {
80
- result.model = result.model || {};
81
- result.model[key] = model[key];
82
- }
83
- }
84
- result.model = Model.build(result.model, model.constructor.name);
85
- return result;
86
- }.bind(Model);
87
-
88
- Model.tableName = function(model) {
89
- const target = model instanceof Model ? model.constructor : model;
90
- const meta = Metadata.get(target, PersistenceKeys.TABLE);
91
- if (meta) return meta;
92
- if (model instanceof Model) return model.constructor.name;
93
- return model.name;
94
- };
95
-
96
- Model.isPrivate = function isPrivate(model) {
97
- return !!Metadata.get(typeof model !== "function" ? model.constructor : model, FabricModelKeys.PRIVATE);
98
- }.bind(Model);
99
-
100
- Metadata.isShared = function isShared(model) {
101
- return !!Metadata.get(typeof model !== "function" ? model.constructor : model, FabricModelKeys.SHARED);
102
- }.bind(Metadata);
103
-
104
- class FabricContractContext extends Context {
105
- constructor() {
106
- super();
107
- }
108
- get stub() {
109
- return this.get("stub");
110
- }
111
- get timestamp() {
112
- return this.stub.getDateTimestamp();
113
- }
114
- get identity() {
115
- return this.get("identity");
116
- }
117
- toString() {
118
- return `fabric ctx${this.stub ? " with stub" : "without stub"}`;
119
- }
120
- }
121
-
122
- function generateFabricEventName(table, event, owner) {
123
- const params = [ table, event ];
124
- if (owner) params.push(owner);
125
- return params.join("_");
126
- }
127
-
128
- function parseEventName(name) {
129
- const parts = name.split("_");
130
- if (parts.length < 2 || parts.length > 3) return {
131
- table: undefined,
132
- event: name,
133
- owner: undefined
134
- };
135
- return {
136
- table: parts[0],
137
- event: parts[1],
138
- owner: parts[2]
139
- };
140
- }
141
-
142
- class FabricContractRepositoryObservableHandler extends ObserverHandler {
143
- constructor(supportedEvents = [ OperationKeys.CREATE, OperationKeys.UPDATE, OperationKeys.DELETE, BulkCrudOperationKeys.CREATE_ALL, BulkCrudOperationKeys.UPDATE_ALL, BulkCrudOperationKeys.DELETE_ALL ]) {
144
- super();
145
- this.supportedEvents = supportedEvents;
146
- }
147
- async updateObservers(clazz, event, id, ...args) {
148
- const {log: log, ctx: ctx} = Adapter.logCtx(this.updateObservers, event, false, ...args);
149
- const {stub: stub} = ctx;
150
- const [owner, payload] = args;
151
- const table = typeof clazz === "string" ? clazz : clazz.name;
152
- if (this.supportedEvents.indexOf(event) !== -1) {
153
- log.debug(`Emitting ${event} event`);
154
- const eventName = generateFabricEventName(table, event, owner);
155
- stub.setEvent(eventName, Buffer.from(JSON.stringify({
156
- id: id
157
- })));
158
- } else {
159
- stub.setEvent(event, Buffer.from(JSON.stringify(payload)));
160
- }
161
- }
162
- }
163
-
164
- class FabricContractRepository extends Repository {
165
- constructor(adapter, clazz, trackedEvents) {
166
- super(adapter, clazz);
167
- this.trackedEvents = trackedEvents;
168
- this._overrides = Object.assign({}, super["_overrides"], {
169
- ignoreValidation: false,
170
- ignoreHandlers: false,
171
- allowRawStatements: true,
172
- forcePrepareSimpleQueries: false,
173
- forcePrepareComplexQueries: false
174
- });
175
- }
176
- async paginateBy(key, order, ref = {
177
- offset: 1,
178
- limit: 10
179
- }, ...args) {
180
- let {offset: offset, bookmark: bookmark, limit: limit} = ref;
181
- if (!offset && !bookmark) throw new QueryError(`PaginateBy needs a page or a bookmark`);
182
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx(args, PreparedStatementKeys.PAGE_BY, true)).for(this.paginateBy);
183
- log.verbose(`paginating ${Model.tableName(this.class)} with page size ${limit}`);
184
- let paginator;
185
- if (bookmark) {
186
- paginator = await this.override({
187
- forcePrepareComplexQueries: false,
188
- forcePrepareSimpleQueries: false
189
- }).select().where(this.attr(Model.pk(this.class)).gt(bookmark)).orderBy([ key, order ]).paginate(limit, ...ctxArgs);
190
- offset = 1;
191
- } else if (offset) {
192
- paginator = await this.override({
193
- forcePrepareComplexQueries: false,
194
- forcePrepareSimpleQueries: false
195
- }).select().orderBy([ key, order ]).paginate(limit, ...ctxArgs);
196
- } else {
197
- throw new QueryError(`PaginateBy needs a page or a bookmark`);
198
- }
199
- const paged = await paginator.page(offset, bookmark, ...ctxArgs);
200
- return paginator.serialize(paged);
201
- }
202
- async statement(name, ...args) {
203
- const {log: log, ctx: ctx, ctxArgs: ctxArgs} = (await this.logCtx(args, PersistenceKeys.STATEMENT, true)).for(this.statement);
204
- if (!Repository.statements(this, name)) throw new QueryError(`Invalid prepared statement requested ${name}`);
205
- if (ctx.logger) {
206
- ctx.logger.info(`Repo statement: ${name} + ${args}`);
207
- }
208
- log.verbose(`Executing prepared statement ${name} with args ${ctxArgs}`);
209
- let result;
210
- try {
211
- result = await this[name](...ctxArgs);
212
- } catch (e) {
213
- if (e instanceof BaseError) throw e;
214
- throw new InternalError(`Failed to execute prepared statement ${name} with args ${ctxArgs}: ${e}`);
215
- }
216
- return result;
217
- }
218
- ObserverHandler() {
219
- return new FabricContractRepositoryObservableHandler;
220
- }
221
- async updateObservers(table, event, id, ...args) {
222
- if (!this.trackedEvents || this.trackedEvents.indexOf(event) !== -1) return await super.updateObservers(table, event, id, ...args);
223
- }
224
- }
225
-
226
- class FabricStatement extends CouchDBStatement {
227
- constructor(adapter) {
228
- super(adapter);
229
- }
230
- async executionPrefix(method, ...args) {
231
- const newArgs = args.filter(Boolean);
232
- if (args.length !== newArgs.length) throw new InternalError(`Received an undefined in the paginator for ${method}: ${args}`);
233
- return super.executionPrefix(method, ...args);
234
- }
235
- async raw(rawInput, ...args) {
236
- const {ctx: ctx} = this.logCtx(args, this.raw);
237
- const results = await this.adapter.raw(rawInput, true, ctx);
238
- const pkAttr = Model.pk(this.fromSelector);
239
- const type = Metadata.get(this.fromSelector, Metadata.key(DBKeys.ID, pkAttr))?.type;
240
- if (!this.selectSelector) return results.map(r => this.processRecord(r, pkAttr, type, ctx));
241
- return results;
242
- }
243
- build() {
244
- const selectors = {};
245
- selectors[CouchDBKeys.TABLE] = {};
246
- selectors[CouchDBKeys.TABLE] = Model.tableName(this.fromSelector);
247
- const query = {
248
- selector: selectors
249
- };
250
- if (this.selectSelector) query.fields = this.selectSelector;
251
- if (this.whereCondition) {
252
- const condition = this.parseCondition(Condition.and(this.whereCondition, Condition.attribute(CouchDBKeys.TABLE).eq(query.selector[CouchDBKeys.TABLE]))).selector;
253
- const selectorKeys = Object.keys(condition);
254
- if (selectorKeys.length === 1 && Object.values(CouchDBGroupOperator).indexOf(selectorKeys[0]) !== -1) switch (selectorKeys[0]) {
255
- case CouchDBGroupOperator.AND:
256
- condition[CouchDBGroupOperator.AND] = [ ...Object.values(condition[CouchDBGroupOperator.AND]).reduce((accum, val) => {
257
- const keys = Object.keys(val);
258
- if (keys.length !== 1) throw new Error("Too many keys in query selector. should be one");
259
- const k = keys[0];
260
- if (k === CouchDBGroupOperator.AND) accum.push(...val[k]); else accum.push(val);
261
- return accum;
262
- }, []) ];
263
- query.selector = condition;
264
- break;
265
-
266
- case CouchDBGroupOperator.OR:
267
- {
268
- const s = {};
269
- s[CouchDBGroupOperator.AND] = [ condition, ...Object.entries(query.selector).map(([key, val]) => {
270
- const result = {};
271
- result[key] = val;
272
- return result;
273
- }) ];
274
- query.selector = s;
275
- break;
276
- }
277
-
278
- default:
279
- throw new Error("This should be impossible");
280
- } else {
281
- Object.entries(condition).forEach(([key, val]) => {
282
- if (query.selector[key]) console.warn(`A ${key} query param is about to be overridden: ${query.selector[key]} by ${val}`);
283
- query.selector[key] = val;
284
- });
285
- }
286
- }
287
- if (this.orderBySelector) {
288
- query.sort = query.sort || [];
289
- query.selector = query.selector || {};
290
- const [selector, value] = this.orderBySelector;
291
- const rec = {};
292
- rec[selector] = value;
293
- query.sort.push(rec);
294
- if (!query.selector[selector]) {
295
- query.selector[selector] = {};
296
- query.selector[selector][CouchDBOperator.BIGGER] = null;
297
- }
298
- }
299
- if (this.limitSelector) query.limit = this.limitSelector;
300
- if (this.offsetSelector) query.skip = this.offsetSelector;
301
- return query;
302
- }
303
- }
304
-
305
- class FabricContractSequence extends Sequence {
306
- constructor(options, adapter) {
307
- super(options, adapter);
308
- }
309
- async current(...args) {
310
- const {ctx: ctx, log: log} = (await this.logCtx(args, OperationKeys.READ, true)).for(this.current);
311
- const {name: name, startWith: startWith} = this.options;
312
- try {
313
- const sequence = await this.repo.read(name, ctx);
314
- return this.parse(sequence.current);
315
- } catch (e) {
316
- if (e instanceof NotFoundError) {
317
- let cachedCurrent;
318
- try {
319
- log.debug(`Trying to resolve current sequence ${name} value from context`);
320
- cachedCurrent = ctx.get(name);
321
- log.debug(`Retrieved cached current value for sequence ${name}: ${cachedCurrent}`);
322
- } catch (e) {
323
- log.info(`No cached value for sequence ${name} in context`);
324
- cachedCurrent = startWith;
325
- }
326
- try {
327
- return this.parse(cachedCurrent);
328
- } catch (e) {
329
- throw new InternalError(`Failed to parse initial value for sequence ${startWith}: ${e}`);
330
- }
331
- }
332
- throw new InternalError(`Failed to retrieve current value for sequence ${name}: ${e}`);
333
- }
334
- }
335
- async increment(count, ctx) {
336
- const log = ctx.logger.for(this.increment);
337
- const {type: type, incrementBy: incrementBy, name: name} = this.options;
338
- if (!name) throw new InternalError("Sequence name is required");
339
- log.info(`Obtaining sequence lock for sequence ${name}`);
340
- return FabricContractSequence.lock.execute(async () => {
341
- const toIncrementBy = count || incrementBy;
342
- if (toIncrementBy % incrementBy !== 0) throw new InternalError(`Value to increment does not consider the incrementBy setting: ${incrementBy}`);
343
- const typeName = typeof type === "function" && type?.name ? type.name : type;
344
- const currentValue = await this.current(ctx);
345
- async function returnAndCache(res) {
346
- if (res instanceof Promise) res = await res;
347
- log.for(returnAndCache).info(`Storing new ${name} seq value in cache: ${res.current}`);
348
- ctx.cache.put(name, res.current);
349
- return res;
350
- }
351
- const performUpsert = async next => {
352
- try {
353
- return await returnAndCache(this.repo.update(new SequenceModel({
354
- id: name,
355
- current: next
356
- }), ctx));
357
- } catch (e) {
358
- if (e instanceof NotFoundError) {
359
- log.debug(`Sequence create ${name} current=${currentValue} next=${next}`);
360
- return returnAndCache(this.repo.create(new SequenceModel({
361
- id: name,
362
- current: next
363
- }), ctx));
364
- }
365
- throw e;
366
- }
367
- };
368
- const incrementSerial = base => {
369
- switch (typeName) {
370
- case Number.name:
371
- return this.parse(base) + toIncrementBy;
372
-
373
- case BigInt.name:
374
- return this.parse(base) + BigInt(toIncrementBy);
375
-
376
- case String.name:
377
- return this.parse(base);
378
-
379
- case "serial":
380
- return Serial.instance.generate(base);
381
-
382
- default:
383
- throw new InternalError("Should never happen");
384
- }
385
- };
386
- if (typeName === "uuid") {
387
- while (true) {
388
- const next = UUID.instance.generate(currentValue);
389
- try {
390
- const result = await performUpsert(next);
391
- log.debug(`Sequence uuid increment ${name} current=${currentValue} next=${next}`);
392
- return result.current;
393
- } catch (e) {
394
- if (e instanceof ConflictError) continue;
395
- throw e;
396
- }
397
- }
398
- }
399
- const next = incrementSerial(currentValue);
400
- const seq = await performUpsert(next);
401
- log.debug(`Sequence.increment ${name} current=${currentValue} next=${next}`);
402
- return seq.current;
403
- }, name);
404
- }
405
- }
406
-
407
- class SimpleDeterministicSerializer extends JSONSerializer {
408
- constructor() {
409
- super();
410
- }
411
- deserialize(str, tableName) {
412
- const deserialization = JSON.parse(str);
413
- return deserialization;
414
- }
415
- serialize(model, putAnchor = true) {
416
- const stringify = require("json-stringify-deterministic");
417
- const sortKeysRecursive = require("sort-keys-recursive");
418
- const preSerialization = this.preSerialize(model, putAnchor);
419
- return stringify(sortKeysRecursive(preSerialization));
420
- }
421
- preSerialize(model, putAnchor = true) {
422
- const toSerialize = Object.assign({}, model);
423
- let metadata;
424
- try {
425
- metadata = Metadata.modelName(model.constructor);
426
- } catch (error) {
427
- metadata = undefined;
428
- }
429
- if (putAnchor) toSerialize[ModelKeys.ANCHOR] = metadata || model.constructor.name;
430
- function preSerialize(obj) {
431
- if (typeof obj !== "object") return obj;
432
- if (Array.isArray(obj)) return obj.map(preSerialize);
433
- return this.preSerialize(obj);
434
- }
435
- Model.relations(model).forEach(r => {
436
- toSerialize[r] = preSerialize.call(this, toSerialize[r]);
437
- });
438
- return toSerialize;
439
- }
440
- }
441
-
442
- class FabricContractPaginator extends CouchDBPaginator {
443
- constructor(adapter, query, size, clazz) {
444
- super(adapter, query, size, clazz);
445
- }
446
- prepare(rawStatement) {
447
- const query = Object.assign({}, rawStatement);
448
- if (query.limit) this.limit = query.limit;
449
- query.limit = this.size;
450
- return query;
451
- }
452
- async page(page = 1, bookmark, ...args) {
453
- const {ctxArgs: ctxArgs, ctx: ctx, log: log} = this.adapter["logCtx"]([ bookmark, ...args ], this.page);
454
- if (this.isPreparedStatement()) return await this.pagePrepared(page, ...ctxArgs);
455
- const statement = Object.assign({}, this.statement);
456
- if (!this._recordCount || !this._totalPages) {
457
- this._totalPages = this._recordCount = 0;
458
- const countResults = await this.adapter.raw({
459
- ...statement,
460
- limit: Number.MAX_VALUE
461
- }, true, ...ctxArgs) || [];
462
- this._recordCount = countResults.length;
463
- if (this._recordCount > 0) {
464
- const size = statement?.limit || this.size;
465
- this._totalPages = Math.ceil(this._recordCount / size);
466
- return await this.page(page, ...ctxArgs);
467
- }
468
- } else {
469
- page = this.validatePage(page);
470
- statement.skip = (page - 1) * this.size;
471
- }
472
- if (page !== 1) {
473
- if (!this._bookmark) throw new PagingError("No bookmark. Did you start in the first page?");
474
- statement["bookmark"] = this._bookmark;
475
- }
476
- const rawResult = await this.adapter.raw(statement, true, ...ctxArgs);
477
- const {docs: docs, bookmark: nextBookmark, warning: warning} = rawResult;
478
- if (warning) log.warn(warning);
479
- if (!this.clazz) throw new PagingError("No statement target defined");
480
- const id = Model.pk(this.clazz);
481
- const type = Metadata.get(this.clazz, Metadata.key(DBKeys.ID, id))?.type;
482
- const results = statement.fields && statement.fields.length ? rawResult : rawResult.map(d => this.adapter.revert(d, this.clazz, Sequence.parseValue(type, d[id]), undefined, ctx));
483
- this._bookmark = nextBookmark;
484
- this._currentPage = page;
485
- return results;
486
- }
487
- }
488
-
489
- class OverflowError extends InternalError {
490
- constructor(msg) {
491
- super(msg, OverflowError.name);
492
- }
493
- }
494
-
495
- class BalanceError extends InternalError {
496
- constructor(msg) {
497
- super(msg, BalanceError.name);
498
- }
499
- }
500
-
501
- class AllowanceError extends InternalError {
502
- constructor(msg) {
503
- super(msg, AllowanceError.name);
504
- }
505
- }
506
-
507
- class RegistrationError extends AuthorizationError {
508
- constructor(msg) {
509
- super(msg, RegistrationError.name);
510
- }
511
- }
512
-
513
- class MissingContextError extends InternalError {
514
- constructor(msg) {
515
- super(msg, MissingContextError.name, 500);
516
- }
517
- }
518
-
519
- class UnauthorizedPrivateDataAccess extends BaseError {
520
- constructor(msg = "MISSING_PRIVATE_DATA_ERROR_MESSAGE") {
521
- super(UnauthorizedPrivateDataAccess.name, msg, 403);
522
- }
523
- }
524
-
525
- class NotInitializedError extends BaseError {
526
- constructor(msg) {
527
- super(NotInitializedError.name, msg, 409);
528
- }
529
- }
530
-
531
- class MissingPKCSS11Lib extends InternalError {
532
- constructor(msg) {
533
- super(msg, MissingPKCSS11Lib.name, 500);
534
- }
535
- }
536
-
537
- class EndorsementError extends InternalError {
538
- constructor(message) {
539
- super(message, EndorsementError.name, 500);
540
- }
541
- }
542
-
543
- class MvccReadConflictError extends InternalError {
544
- constructor(message) {
545
- super(message, MvccReadConflictError.name, 500);
546
- }
547
- }
548
-
549
- class PhantomReadConflictError extends InternalError {
550
- constructor(message) {
551
- super(message, PhantomReadConflictError.name, 500);
552
- }
553
- }
554
-
555
- class EndorsementPolicyError extends InternalError {
556
- constructor(message) {
557
- super(message, EndorsementPolicyError.name, 500);
558
- }
559
- }
560
-
561
- async function createdByOnFabricCreateUpdate(context, data, key, model) {
562
- try {
563
- const user = context.get("identity");
564
- model[key] = user.getID();
565
- } catch (e) {
566
- throw new UnsupportedError("No User found in context. Please provide a user in the context");
567
- }
568
- }
569
-
570
- async function pkFabricOnCreate(context, data, key, model) {
571
- if (!data.type || model[key]) {
572
- return;
573
- }
574
- const setPrimaryKeyValue = function(target, propertyKey, value) {
575
- Object.defineProperty(target, propertyKey, {
576
- enumerable: true,
577
- writable: false,
578
- configurable: true,
579
- value: value
580
- });
581
- };
582
- if (!data.name) data.name = Model.sequenceName(model, "pk");
583
- let sequence;
584
- try {
585
- sequence = await this.adapter.Sequence(data);
586
- } catch (e) {
587
- throw new InternalError(`Failed to instantiate Sequence ${data.name}: ${e}`);
588
- }
589
- const next = await sequence.next(context);
590
- setPrimaryKeyValue(model, key, next);
591
- }
592
-
593
- class FabricContractAdapter extends CouchDBAdapter {
594
- getClient() {
595
- throw new UnsupportedError("Client is not supported in Fabric contracts");
596
- }
597
- static {
598
- this.textDecoder = new TextDecoder("utf8");
599
- }
600
- static {
601
- this.serializer = new SimpleDeterministicSerializer;
602
- }
603
- get Context() {
604
- return FabricContractContext;
605
- }
606
- repository() {
607
- return FabricContractRepository;
608
- }
609
- Paginator(query, size, clazz) {
610
- return new FabricContractPaginator(this, query, size, clazz);
611
- }
612
- async Sequence(options) {
613
- return new FabricContractSequence(options, this);
614
- }
615
- constructor(scope, alias) {
616
- super(scope, FabricFlavour, alias);
617
- }
618
- for(config, ...args) {
619
- return super.for(config, ...args);
620
- }
621
- async create(clazz, id, model, ...args) {
622
- const {ctx: ctx, log: log} = this.logCtx(args, this.create);
623
- log.info(`in ADAPTER create with args ${args}`);
624
- const tableName = Model.tableName(clazz);
625
- try {
626
- log.info(`adding entry to ${tableName} table with pk ${id}`);
627
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
628
- model = await this.putState(composedKey, model, ctx);
629
- } catch (e) {
630
- throw this.parseError(e);
631
- }
632
- return model;
633
- }
634
- async read(clazz, id, ...args) {
635
- const {ctx: ctx, log: log} = this.logCtx(args, this.read);
636
- log.info(`in ADAPTER read with args ${args}`);
637
- const tableName = Model.tableName(clazz);
638
- let model;
639
- try {
640
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
641
- model = await this.readState(composedKey, ctx);
642
- } catch (e) {
643
- throw this.parseError(e);
644
- }
645
- return model;
646
- }
647
- async update(clazz, id, model, ...args) {
648
- const {ctx: ctx, log: log} = this.logCtx(args, this.update);
649
- const tableName = Model.tableName(clazz);
650
- try {
651
- log.verbose(`updating entry to ${tableName} table with pk ${id}`);
652
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
653
- model = await this.putState(composedKey, model, ctx);
654
- } catch (e) {
655
- throw this.parseError(e);
656
- }
657
- return model;
658
- }
659
- async delete(clazz, id, ...args) {
660
- const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.delete);
661
- const tableName = Model.tableName(clazz);
662
- let model;
663
- try {
664
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
665
- model = await this.read(clazz, id, ...ctxArgs);
666
- log.verbose(`deleting entry with pk ${id} from ${tableName} table`);
667
- await this.deleteState(composedKey, ctx);
668
- } catch (e) {
669
- throw this.parseError(e);
670
- }
671
- return model;
672
- }
673
- async deleteState(id, context) {
674
- const {ctx: ctx} = this.logCtx([ context ], this.deleteState);
675
- await ctx.stub.deleteState(id);
676
- }
677
- forPrivate(collection) {
678
- const toOverride = [ this.putState, this.readState, this.deleteState, this.queryResult, this.queryResultPaginated ].map(fn => fn.name);
679
- return new Proxy(this, {
680
- get(target, prop, receiver) {
681
- if (!toOverride.includes(prop)) return Reflect.get(target, prop, receiver);
682
- return new Proxy(target[prop], {
683
- async apply(fn, thisArg, argsList) {
684
- switch (prop) {
685
- case "putState":
686
- {
687
- const [stub, id, model] = argsList;
688
- await stub.putPrivateData(collection, id.toString(), model);
689
- return model;
690
- }
691
-
692
- case "deleteState":
693
- {
694
- const [stub, id] = argsList;
695
- return stub.deletePrivateData(collection, id);
696
- }
697
-
698
- case "readState":
699
- {
700
- const [stub, id] = argsList;
701
- return stub.getPrivateData(collection, id);
702
- }
703
-
704
- case "queryResult":
705
- {
706
- const [stub, rawInput] = argsList;
707
- return stub.getPrivateDataQueryResult(collection, rawInput);
708
- }
709
-
710
- case "queryResultPaginated":
711
- {
712
- const [stub, rawInput, limit, skip] = argsList;
713
- const iterator = await stub.getPrivateDataQueryResult(collection, rawInput);
714
- const results = [];
715
- let count = 0;
716
- let reachedBookmark = skip ? false : true;
717
- let lastKey = null;
718
- while (true) {
719
- const res = await iterator.next();
720
- if (res.value && res.value.value.toString()) {
721
- const recordKey = res.value.key;
722
- const recordValue = res.value.value.toString("utf8");
723
- if (!reachedBookmark) {
724
- if (recordKey === skip?.toString()) {
725
- reachedBookmark = true;
726
- }
727
- continue;
728
- }
729
- results.push({
730
- Key: recordKey,
731
- Record: JSON.parse(recordValue)
732
- });
733
- lastKey = recordKey;
734
- count++;
735
- if (count >= limit) {
736
- await iterator.close();
737
- return {
738
- iterator: results,
739
- metadata: {
740
- fetchedRecordsCount: results.length,
741
- bookmark: lastKey
742
- }
743
- };
744
- }
745
- }
746
- if (res.done) {
747
- await iterator.close();
748
- return {
749
- iterator: results,
750
- metadata: {
751
- fetchedRecordsCount: results.length,
752
- bookmark: ""
753
- }
754
- };
755
- }
756
- }
757
- }
758
-
759
- default:
760
- throw new InternalError(`Unsupported method override ${String(prop)}`);
761
- }
762
- }
763
- });
764
- }
765
- });
766
- }
767
- async putState(id, model, ctx) {
768
- let data;
769
- const {log: log} = this.logCtx([ ctx ], this.putState);
770
- try {
771
- data = Buffer.from(FabricContractAdapter.serializer.serialize(model, false));
772
- } catch (e) {
773
- throw new SerializationError(`Failed to serialize record with id ${id}: ${e}`);
774
- }
775
- const collection = ctx.get("segregated");
776
- if (collection) await ctx.stub.putPrivateData(collection, id.toString(), data); else await ctx.stub.putState(id.toString(), data);
777
- log.silly(`state stored${collection ? ` in ${collection} collection` : ""} under id ${id}`);
778
- return model;
779
- }
780
- async readState(id, ctx) {
781
- let result;
782
- const {log: log} = this.logCtx([ ctx ], this.readState);
783
- let res;
784
- const collection = ctx.get("segregated");
785
- if (collection) res = (await ctx.stub.getPrivateData(collection, id.toString())).toString(); else res = (await ctx.stub.getState(id.toString())).toString();
786
- if (!res) throw new NotFoundError(`Record with id ${id}${collection ? ` in ${collection} collection` : ""} not found`);
787
- log.silly(`state retrieved from${collection ? ` ${collection} collection` : ""} under id ${id}`);
788
- try {
789
- result = FabricContractAdapter.serializer.deserialize(res.toString());
790
- } catch (e) {
791
- throw new SerializationError(`Failed to parse record: ${e}`);
792
- }
793
- return result;
794
- }
795
- async queryResult(stub, rawInput, ...args) {
796
- const {ctx: ctx} = this.logCtx(args, this.queryResult);
797
- let res;
798
- const collection = ctx.get("segregated");
799
- if (collection) res = await ctx.stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput)); else res = await stub.getQueryResult(JSON.stringify(rawInput));
800
- return res;
801
- }
802
- async queryResultPaginated(stub, rawInput, limit = 250, skip, ...args) {
803
- const {ctx: ctx} = this.logCtx(args, this.readState);
804
- let res;
805
- const collection = ctx.get("segregated");
806
- if (collection) {
807
- rawInput.selector = {
808
- ...rawInput.selector,
809
- _id: skip ? {
810
- $gt: skip.toString()
811
- } : {
812
- $gte: ""
813
- }
814
- };
815
- const it = await stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput));
816
- res = {
817
- iterator: it,
818
- metadata: {
819
- fetchedRecordsCount: limit,
820
- bookmark: ""
821
- }
822
- };
823
- } else res = await stub.getQueryResultWithPagination(JSON.stringify(rawInput), limit, skip?.toString());
824
- return res;
825
- }
826
- mergeModels(results) {
827
- const extract = model => Object.entries(model).reduce((accum, [key, val]) => {
828
- if (typeof val !== "undefined") accum[key] = val;
829
- return accum;
830
- }, {});
831
- let finalModel = results.pop();
832
- for (const res of results) {
833
- finalModel = Object.assign({}, extract(finalModel), extract(res));
834
- }
835
- return finalModel;
836
- }
837
- decode(buffer) {
838
- return FabricContractAdapter.textDecoder.decode(buffer);
839
- }
840
- async flags(operation, model, flags) {
841
- let baseFlags = Object.assign({
842
- segregated: false
843
- }, flags);
844
- if (flags instanceof FabricContractContext) {} else if (flags.stub) {
845
- Object.assign(baseFlags, {
846
- stub: flags.stub,
847
- identity: flags.clientIdentity,
848
- logger: Logging.for(operation, {
849
- logLevel: false,
850
- timestamp: false,
851
- correlationId: flags.stub.getTxID()
852
- }, flags),
853
- correlationId: flags.stub.getTxID()
854
- });
855
- } else {
856
- baseFlags = Object.assign(baseFlags, flags || {});
857
- }
858
- return await super.flags(operation, model, baseFlags);
859
- }
860
- index(models) {
861
- return Promise.resolve(undefined);
862
- }
863
- async resultIterator(log, iterator, isHistory = false) {
864
- const allResults = [];
865
- let res = await iterator.next();
866
- while (!res.done) {
867
- if (res.value && res.value.value.toString()) {
868
- let jsonRes = {};
869
- log.debug(res.value.value.toString("utf8"));
870
- if (isHistory) {
871
- jsonRes.TxId = res.value.txId;
872
- jsonRes.Timestamp = res.value.timestamp;
873
- try {
874
- jsonRes.Value = JSON.parse(res.value.value.toString("utf8"));
875
- } catch (err) {
876
- log.error(err);
877
- jsonRes.Value = res.value.value.toString("utf8");
878
- }
879
- } else {
880
- try {
881
- jsonRes = JSON.parse(res.value.value.toString("utf8"));
882
- } catch (err) {
883
- log.error(err);
884
- jsonRes = res.value.value.toString("utf8");
885
- }
886
- }
887
- allResults.push(jsonRes);
888
- }
889
- res = await iterator.next();
890
- }
891
- log.debug(`Closing iterator after ${allResults.length} results`);
892
- iterator.close();
893
- return allResults;
894
- }
895
- async raw(rawInput, docsOnly = true, ...args) {
896
- const {log: log, ctx: ctx} = this.logCtx(args, this.raw);
897
- const {skip: skip, limit: limit} = rawInput;
898
- let iterator;
899
- if (limit || skip) {
900
- delete rawInput["limit"];
901
- delete rawInput["skip"];
902
- log.debug(`Retrieving paginated iterator: limit: ${limit}/ skip: ${skip}`);
903
- const response = await this.queryResultPaginated(ctx.stub, rawInput, limit || Number.MAX_VALUE, skip?.toString(), ctx);
904
- iterator = response.iterator;
905
- } else {
906
- log.debug("Retrieving iterator");
907
- iterator = await this.queryResult(ctx.stub, rawInput, ctx);
908
- }
909
- log.debug("Iterator acquired");
910
- const results = await this.resultIterator(log, iterator);
911
- log.debug(`returning ${Array.isArray(results) ? results.length : 1} results`);
912
- return results;
913
- }
914
- Statement() {
915
- return new FabricStatement(this);
916
- }
917
- async createAll(tableName, id, model, ...args) {
918
- if (id.length !== model.length) throw new InternalError("Ids and models must have the same length");
919
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.createAll);
920
- const tableLabel = Model.tableName(tableName);
921
- log.debug(`Creating ${id.length} entries ${tableLabel} table`);
922
- return Promise.all(id.map((i, count) => this.create(tableName, i, model[count], ...ctxArgs)));
923
- }
924
- async updateAll(tableName, id, model, ...args) {
925
- if (id.length !== model.length) throw new InternalError("Ids and models must have the same length");
926
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateAll);
927
- const tableLabel = Model.tableName(tableName);
928
- log.debug(`Updating ${id.length} entries ${tableLabel} table`);
929
- return Promise.all(id.map((i, count) => this.update(tableName, i, model[count], ...ctxArgs)));
930
- }
931
- prepare(model, ...args) {
932
- const {log: log} = this.logCtx(args, this.prepare);
933
- const tableName = Model.tableName(model.constructor);
934
- const pk = Model.pk(model.constructor);
935
- const split = Model.segregate(model);
936
- const result = Object.entries(split.model).reduce((accum, [key, val]) => {
937
- if (typeof val === "undefined") return accum;
938
- const mappedProp = Model.columnName(model, key);
939
- if (this.isReserved(mappedProp)) throw new InternalError(`Property name ${mappedProp} is reserved`);
940
- accum[mappedProp] = val;
941
- return accum;
942
- }, {});
943
- log.silly(`Preparing record for ${tableName} table with pk ${model[pk]}`);
944
- return {
945
- record: result,
946
- id: model[pk],
947
- transient: split.transient
948
- };
949
- }
950
- revert(obj, clazz, id, transient, ...args) {
951
- const {log: log} = this.logCtx(args, this.revert);
952
- const ob = {};
953
- const pk = Model.pk(clazz);
954
- ob[pk] = id;
955
- const m = typeof clazz === "string" ? Model.build(ob, clazz) : new clazz(ob);
956
- log.silly(`Rebuilding model ${m.constructor.name} id ${id}`);
957
- const result = Object.keys(m).reduce((accum, key) => {
958
- accum[key] = obj[Model.columnName(accum, key)];
959
- return accum;
960
- }, m);
961
- if (transient) {
962
- log.debug(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
963
- Object.entries(transient).forEach(([key, val]) => {
964
- if (key in result && result[key] !== undefined) throw new InternalError(`Transient property ${key} already exists on model ${m.constructor.name}. should be impossible`);
965
- result[key] = val;
966
- });
967
- }
968
- return result;
969
- }
970
- createPrefix(tableName, id, model, ...args) {
971
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.createPrefix);
972
- const record = {};
973
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
974
- Object.assign(record, model);
975
- return [ tableName, id, record, ...ctxArgs ];
976
- }
977
- updatePrefix(tableName, id, model, ...args) {
978
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.updatePrefix);
979
- const record = {};
980
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
981
- Object.assign(record, model);
982
- return [ tableName, id, record, ...ctxArgs ];
983
- }
984
- createAllPrefix(tableName, ids, models, ...args) {
985
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
986
- const ctx = args.pop();
987
- const records = ids.map((id, count) => {
988
- const record = {};
989
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
990
- Object.assign(record, models[count]);
991
- return record;
992
- });
993
- return [ tableName, ids, records, ctx ];
994
- }
995
- updateAllPrefix(tableName, ids, models, ...args) {
996
- if (ids.length !== models.length) throw new InternalError("Ids and models must have the same length");
997
- const ctx = args.pop();
998
- const records = ids.map((id, count) => {
999
- const record = {};
1000
- record[CouchDBKeys.TABLE] = Model.tableName(tableName);
1001
- Object.assign(record, models[count]);
1002
- return record;
1003
- });
1004
- return [ tableName, ids, records, ctx ];
1005
- }
1006
- parseError(err, reason) {
1007
- return FabricContractAdapter.parseError(reason || err);
1008
- }
1009
- logCtx(args, operation, allowCreate = false, overrides) {
1010
- if (!allowCreate) return super.logCtx(args, operation, allowCreate, overrides);
1011
- return super.logCtx.call(this, args, operation, allowCreate, overrides).then(res => {
1012
- if (!(res.ctx instanceof FabricContractContext)) throw new InternalError(`Invalid context binding`);
1013
- if (!res.ctx.stub) throw new InternalError(`Missing Stub`);
1014
- if (!res.ctx.identity) throw new InternalError(`Missing Identity`);
1015
- return Object.assign(res, {
1016
- stub: res.ctx.stub,
1017
- identity: res.ctx.identity
1018
- });
1019
- });
1020
- }
1021
- static parseError(err) {
1022
- const msg = typeof err === "string" ? err : err.message;
1023
- if (msg.includes(NotFoundError.name)) return new NotFoundError(err);
1024
- if (msg.includes(ConflictError.name)) return new ConflictError(err);
1025
- if (msg.includes(BadRequestError.name)) return new BadRequestError(err);
1026
- if (msg.includes(QueryError.name)) return new QueryError(err);
1027
- if (msg.includes(PagingError.name)) return new PagingError(err);
1028
- if (msg.includes(UnsupportedError.name)) return new UnsupportedError(err);
1029
- if (msg.includes(MigrationError.name)) return new MigrationError(err);
1030
- if (msg.includes(ObserverError.name)) return new ObserverError(err);
1031
- if (msg.includes(AuthorizationError.name)) return new AuthorizationError(err);
1032
- if (msg.includes(ForbiddenError.name)) return new ForbiddenError(err);
1033
- if (msg.includes(ConnectionError.name)) return new ConnectionError(err);
1034
- if (msg.includes(SerializationError.name)) return new SerializationError(err);
1035
- if (msg.includes("no ledger context")) return new MissingContextError(`No context found. this can be caused by debugging: ${msg}`);
1036
- return new InternalError(err);
1037
- }
1038
- static decoration() {
1039
- super.decoration();
1040
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.CREATED_BY).define(onCreate(createdByOnFabricCreateUpdate), propMetadata(PersistenceKeys.CREATED_BY, {})).apply();
1041
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.UPDATED_BY).define(onCreateUpdate(createdByOnFabricCreateUpdate), propMetadata(PersistenceKeys.UPDATED_BY, {})).apply();
1042
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.COLUMN).extend(Property()).apply();
1043
- Decoration.flavouredAs(FabricFlavour).for(ValidationKeys.DATE).extend(function fabricProperty() {
1044
- return (target, prop) => {
1045
- Property(prop, "string:date")(target, prop);
1046
- };
1047
- });
1048
- Decoration.flavouredAs(FabricFlavour).for(PersistenceKeys.TABLE).extend(function table(obj) {
1049
- const chain = [];
1050
- let current = typeof obj === "function" ? Metadata.constr(obj) : Metadata.constr(obj.constructor);
1051
- while (current && current !== Object && current.prototype) {
1052
- chain.push(current);
1053
- current = Object.getPrototypeOf(current);
1054
- }
1055
- console.log(chain.map(c => c.name || c));
1056
- while (chain.length > 0) {
1057
- const constructor = chain.pop();
1058
- console.log(`Calling on ${constructor.name}`);
1059
- Object$1()(constructor);
1060
- }
1061
- return Object$1()(obj);
1062
- }).apply();
1063
- }
1064
- }
1065
-
1066
- FabricContractAdapter.decoration();
1067
-
1068
- Adapter.setCurrent(FabricFlavour);
1069
-
1070
- class DeterministicSerializer extends JSONSerializer {
1071
- constructor() {
1072
- super();
1073
- }
1074
- preSerialize(model) {
1075
- const toSerialize = Object.assign({}, model);
1076
- let metadata;
1077
- try {
1078
- metadata = Metadata.modelName(model.constructor);
1079
- } catch (error) {
1080
- metadata = undefined;
1081
- }
1082
- toSerialize[ModelKeys.ANCHOR] = metadata || model.constructor.name;
1083
- const preSerialize = function preSerialize(obj) {
1084
- const self = this;
1085
- if (typeof obj !== "object") return obj;
1086
- if (Array.isArray(obj)) return obj.map(o => preSerialize.call(self, o));
1087
- return this.preSerialize.call(this, obj);
1088
- }.bind(this);
1089
- Model.relations(model).forEach(r => {
1090
- toSerialize[r] = preSerialize(toSerialize[r]);
1091
- });
1092
- return toSerialize;
1093
- }
1094
- deserialize(str) {
1095
- const deserialization = JSON.parse(str);
1096
- const className = deserialization[ModelKeys.ANCHOR];
1097
- if (!className) throw new Error("Could not find class reference in serialized model");
1098
- const model = Model.build(deserialization, className);
1099
- return model;
1100
- }
1101
- serialize(model) {
1102
- const stringify = require("json-stringify-deterministic");
1103
- const sortKeysRecursive = require("sort-keys-recursive");
1104
- return stringify(sortKeysRecursive(this.preSerialize(model)));
1105
- }
1106
- }
1107
-
1108
- var ERC20Events;
1109
-
1110
- (function(ERC20Events) {
1111
- ERC20Events["TRANSFER"] = "Transfer";
1112
- ERC20Events["APPROVAL"] = "Approval";
1113
- })(ERC20Events || (ERC20Events = {}));
1114
-
1115
- let FabricBaseModel = class FabricBaseModel extends Model {
1116
- constructor(arg) {
1117
- super(arg);
1118
- }
1119
- };
1120
-
1121
- __decorate([ description("Stores the original timestamp of creation"), column(), createdAt(), __metadata("design:type", Date) ], FabricBaseModel.prototype, "createdAt", void 0);
1122
-
1123
- __decorate([ description("Stores the timestamp of the last update"), column(), updatedAt(), __metadata("design:type", Date) ], FabricBaseModel.prototype, "updatedAt", void 0);
1124
-
1125
- __decorate([ description("Stores the version of the model"), column(), version(), __metadata("design:type", Number) ], FabricBaseModel.prototype, "version", void 0);
1126
-
1127
- FabricBaseModel = __decorate([ uses(FabricFlavour), __metadata("design:paramtypes", [ Object ]) ], FabricBaseModel);
1128
-
1129
- let FabricIdentifiedBaseModel = class FabricIdentifiedBaseModel extends FabricBaseModel {
1130
- constructor(arg) {
1131
- super(arg);
1132
- }
1133
- };
1134
-
1135
- __decorate([ description("Stores the creator"), column(), createdBy(), __metadata("design:type", String) ], FabricIdentifiedBaseModel.prototype, "createdBy", void 0);
1136
-
1137
- __decorate([ description("Stores the user that last updated the model"), column(), updatedBy(), __metadata("design:type", String) ], FabricIdentifiedBaseModel.prototype, "updatedBy", void 0);
1138
-
1139
- FabricIdentifiedBaseModel = __decorate([ uses(FabricFlavour), __metadata("design:paramtypes", [ Object ]) ], FabricIdentifiedBaseModel);
1140
-
1141
- let IdentityCredentials = class IdentityCredentials extends BaseModel {
1142
- constructor(arg) {
1143
- super(arg);
1144
- }
1145
- };
1146
-
1147
- __decorate([ description("Unique identifier of the credentials record"), column(), pk(), __metadata("design:type", String) ], IdentityCredentials.prototype, "id", void 0);
1148
-
1149
- __decorate([ description("PEM-encoded X.509 certificate for the identity"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "certificate", void 0);
1150
-
1151
- __decorate([ description("PEM-encoded root or intermediate certificate"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "rootCertificate", void 0);
1152
-
1153
- __decorate([ description("PEM-encoded private key"), column(), required(), __metadata("design:type", String) ], IdentityCredentials.prototype, "privateKey", void 0);
1154
-
1155
- IdentityCredentials = __decorate([ model(), __metadata("design:paramtypes", [ Object ]) ], IdentityCredentials);
1156
-
1157
- let Identity = class Identity extends BaseModel {
1158
- constructor(arg) {
1159
- super(arg);
1160
- this.type = IdentityType.X509;
1161
- }
1162
- };
1163
-
1164
- __decorate([ description("Unique identifier of the identity"), pk(), __metadata("design:type", String) ], Identity.prototype, "id", void 0);
1165
-
1166
- __decorate([ oneToOne(IdentityCredentials, {
1167
- update: Cascade.CASCADE,
1168
- delete: Cascade.CASCADE
1169
- }), __metadata("design:type", IdentityCredentials) ], Identity.prototype, "credentials", void 0);
1170
-
1171
- __decorate([ column(), required(), index(), __metadata("design:type", String) ], Identity.prototype, "mspId", void 0);
1172
-
1173
- __decorate([ column(), required(), __metadata("design:type", String) ], Identity.prototype, "type", void 0);
1174
-
1175
- Identity = __decorate([ model(), __metadata("design:paramtypes", [ Object ]) ], Identity);
1176
-
1177
- class ClientSerializer extends JSONSerializer {
1178
- constructor() {
1179
- super();
1180
- }
1181
- preSerialize(model, modelName) {
1182
- const toSerialize = Object.assign({}, model);
1183
- let metadata = Metadata.modelName(model.constructor);
1184
- if (!metadata || metadata === "Object") if (modelName) metadata = modelName; else throw new SerializationError(`Could not find metadata for ${model.constructor.name}`);
1185
- toSerialize[ModelKeys.ANCHOR] = metadata;
1186
- return toSerialize;
1187
- }
1188
- deserialize(str) {
1189
- const deserialization = JSON.parse(str);
1190
- const className = deserialization[ModelKeys.ANCHOR];
1191
- if (!className) throw new Error("Could not find class reference in serialized model");
1192
- const model = Model.build(deserialization, className);
1193
- return model;
1194
- }
1195
- serialize(model, modelName) {
1196
- return JSON.stringify(this.preSerialize(model, modelName));
1197
- }
1198
- }
1199
-
1200
- function Owner() {
1201
- return function(target, propertyKey, descriptor) {
1202
- const originalMethod = descriptor.value;
1203
- descriptor.value = async function(...args) {
1204
- const ctx = args[0];
1205
- const acountId = ctx.clientIdentity.getID();
1206
- const select = await this["tokenRepository"].select();
1207
- const tokens = await select.execute(ctx);
1208
- if (tokens.length == 0) {
1209
- throw new NotFoundError("No tokens avaialble");
1210
- }
1211
- if (tokens.length > 1) {
1212
- throw new NotFoundError(`To many token available : ${tokens.length}`);
1213
- }
1214
- if (tokens[0].owner != acountId) {
1215
- throw new AuthorizationError(`User not authorized to run ${propertyKey} on the token`);
1216
- }
1217
- return await originalMethod.apply(this, args);
1218
- };
1219
- return descriptor;
1220
- };
1221
- }
1222
-
1223
- async function ownedByOnCreate(context, data, key, model) {
1224
- const {stub: stub} = context;
1225
- const creator = await stub.getCreator();
1226
- const owner = creator.mspid;
1227
- const setOwnedByKeyValue = function(target, propertyKey, value) {
1228
- Object.defineProperty(target, propertyKey, {
1229
- enumerable: true,
1230
- writable: false,
1231
- configurable: true,
1232
- value: value
1233
- });
1234
- };
1235
- setOwnedByKeyValue(model, key, owner);
1236
- }
1237
-
1238
- function ownedBy() {
1239
- const key = getFabricModelKey(FabricModelKeys.OWNEDBY);
1240
- function ownedBy() {
1241
- return function(obj, attribute) {
1242
- return apply(required(), readonly(), onCreate(ownedByOnCreate), propMetadata(getFabricModelKey(FabricModelKeys.OWNEDBY), attribute))(obj, attribute);
1243
- };
1244
- }
1245
- return Decoration.for(key).define({
1246
- decorator: ownedBy,
1247
- args: []
1248
- }).apply();
1249
- }
1250
-
1251
- async function transactionIdOnCreate(context, data, key, model) {
1252
- const {stub: stub} = context;
1253
- model[key] = stub.getTxID();
1254
- }
1255
-
1256
- function transactionId() {
1257
- function transactionId() {
1258
- return function(obj, attribute) {
1259
- return apply(required(), readonly(), onCreate(transactionIdOnCreate), onUpdate(transactionIdOnCreate), propMetadata(Metadata.key(FabricModelKeys.FABRIC, attribute, FabricModelKeys.TRANSACTION_ID), attribute))(obj, attribute);
1260
- };
1261
- }
1262
- return Decoration.for(FabricModelKeys.TRANSACTION_ID).define({
1263
- decorator: transactionId,
1264
- args: []
1265
- }).apply();
1266
- }
1267
-
1268
- function getFabricModelKey(key) {
1269
- return Metadata.key(FabricModelKeys.FABRIC + key);
1270
- }
1271
-
1272
- const ImplicitPrivateCollection = model => `__${model.constructor.name}PrivateCollection`;
1273
-
1274
- async function segregatedDataOnCreate(context, data, keys, model) {
1275
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1276
- const collectionResolver = data[0].collections;
1277
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1278
- const rebuilt = keys.reduce((acc, k, i) => {
1279
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1280
- if (c !== collection) throw new UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1281
- acc[k] = model[k];
1282
- return acc;
1283
- }, {});
1284
- const toCreate = new this.class(rebuilt);
1285
- const created = await this.override({
1286
- segregated: collection
1287
- }).create(toCreate, context);
1288
- Object.assign(model, created);
1289
- }
1290
-
1291
- async function segregatedDataOnRead(context, data, keys, model) {
1292
- if (keys.length !== data.length) throw new InternalError(`Segregated data keys and metadata length mismatch`);
1293
- const collectionResolver = data[0].collections;
1294
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1295
- const rebuilt = keys.reduce((acc, k, i) => {
1296
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1297
- if (c !== collection) throw new UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1298
- acc[k] = model[k];
1299
- return acc;
1300
- }, {});
1301
- const toCreate = new this.class(rebuilt);
1302
- const created = await this.override({
1303
- segregated: collection
1304
- }).create(toCreate, context);
1305
- Object.assign(model, created);
1306
- }
1307
-
1308
- async function segregatedDataOnUpdate(context, data, key, model, oldModel) {}
1309
-
1310
- async function segregatedDataOnDelete(context, data, key, model) {}
1311
-
1312
- function segregated(collection, type) {
1313
- return function innerSegregated(target, propertyKey) {
1314
- function segregatedDec(target, propertyKey) {
1315
- if (!propertyKey) {
1316
- const props = Metadata.properties(target) || [];
1317
- for (const prop of props) segregated(collection, type)(target, prop);
1318
- return target;
1319
- }
1320
- const key = Metadata.key(type, propertyKey);
1321
- const constr = target.constructor;
1322
- const meta = Metadata.get(constr, key) || {};
1323
- const collections = new Set(meta.collections || []);
1324
- collections.add(collection);
1325
- meta.collections = [ ...collections ];
1326
- Metadata.set(constr, key, meta);
1327
- }
1328
- const decs = [];
1329
- if (!propertyKey) {
1330
- Metadata.properties(target)?.forEach(p => segregated(collection, type)(target, p));
1331
- return metadata(type, true)(target);
1332
- } else {
1333
- decs.push(transient(), segregatedDec, onCreate(segregatedDataOnCreate, {
1334
- collections: collection
1335
- }, {
1336
- priority: 95,
1337
- group: typeof collection === "string" ? collection : collection.toString()
1338
- }), onRead(segregatedDataOnRead, {
1339
- collections: collection
1340
- }, {
1341
- priority: 95,
1342
- group: typeof collection === "string" ? collection : collection.toString()
1343
- }), onUpdate(segregatedDataOnUpdate, {
1344
- collections: collection
1345
- }, {
1346
- priority: 95,
1347
- group: typeof collection === "string" ? collection : collection.toString()
1348
- }), onDelete(segregatedDataOnDelete, {
1349
- collections: collection
1350
- }, {
1351
- priority: 95,
1352
- group: typeof collection === "string" ? collection : collection.toString()
1353
- }));
1354
- }
1355
- return apply(...decs)(target, propertyKey);
1356
- };
1357
- }
1358
-
1359
- function privateData(collection = ImplicitPrivateCollection) {
1360
- function privateData(collection) {
1361
- return segregated(collection, FabricModelKeys.PRIVATE);
1362
- }
1363
- return Decoration.for(FabricModelKeys.PRIVATE).define({
1364
- decorator: privateData,
1365
- args: [ collection ]
1366
- }).apply();
1367
- }
1368
-
1369
- function sharedData(collection) {
1370
- function sharedData(collection) {
1371
- return segregated(collection, FabricModelKeys.SHARED);
1372
- }
1373
- return Decoration.for(FabricModelKeys.SHARED).define({
1374
- decorator: sharedData,
1375
- args: [ collection ]
1376
- }).apply();
1377
- }
1378
-
1379
- function add(a, b) {
1380
- const c = a + b;
1381
- if (a !== c - b || b !== c - a) {
1382
- throw new OverflowError(`Addition overflow: ${a} + ${b}`);
1383
- }
1384
- return c;
1385
- }
1386
-
1387
- function sub(a, b) {
1388
- const c = a - b;
1389
- if (a !== c + b || b !== a - c) {
1390
- throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
1391
- }
1392
- return c;
1393
- }
1394
-
1395
- function safeParseInt(string) {
1396
- const digitRegex = /^\d+$/;
1397
- if (!digitRegex.test(string)) {
1398
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string contains digits"));
1399
- }
1400
- const parsedint = parseInt(string);
1401
- if (isNaN(parsedint)) {
1402
- throw new ValidationError(stringFormat("Failed to parse: {0}", "string is not a parsable integer"));
1403
- }
1404
- return parsedint;
1405
- }
1406
-
1407
- Object$1()(Date);
1408
-
1409
- class FabricCrudContract extends Contract {
1410
- static {
1411
- this.adapter = new FabricContractAdapter;
1412
- }
1413
- static {
1414
- this.serializer = new DeterministicSerializer;
1415
- }
1416
- constructor(name, clazz) {
1417
- super(name);
1418
- this.clazz = clazz;
1419
- this.initialized = false;
1420
- this.repo = Repository.forModel(clazz);
1421
- }
1422
- async listBy(ctx, key, order, ...args) {
1423
- const {ctxArgs: ctxArgs, log: log} = (await this.logCtx([ ...args, ctx ], PreparedStatementKeys.LIST_BY, true)).for(this.listBy);
1424
- log.info(`Running listBy key ${key}, order ${order} and args ${ctxArgs}`);
1425
- return this.repo.listBy(key, order, ...ctxArgs);
1426
- }
1427
- async paginateBy(ctx, key, order, ref = {
1428
- offset: 1,
1429
- limit: 10
1430
- }, ...args) {
1431
- const {ctxArgs: ctxArgs, log: log} = (await this.logCtx([ ...args, ctx ], PreparedStatementKeys.PAGE_BY, true)).for(this.paginateBy);
1432
- log.info(`Running paginateBy key ${key}, order ${order} with size ${ref.limit} and args ${ctxArgs}`);
1433
- return this.repo.paginateBy(key, order, ref, ...ctxArgs);
1434
- }
1435
- async findOneBy(ctx, key, value, ...args) {
1436
- const {ctxArgs: ctxArgs, log: log} = (await this.logCtx([ ...args, ctx ], PreparedStatementKeys.FIND_ONE_BY, true)).for(this.findOneBy);
1437
- log.info(`Running findOneBy key ${key}, value: ${value} with args ${ctxArgs}`);
1438
- return this.repo.findOneBy(key, value, ...ctxArgs);
1439
- }
1440
- async statement(ctx, method, ...args) {
1441
- const {ctxArgs: ctxArgs, log: log} = (await this.logCtx([ ...args, ctx ], PersistenceKeys.STATEMENT, true)).for(this.statement);
1442
- log.info(`Running statement ${method} with args ${ctxArgs}`);
1443
- return this.repo.statement(method, ...ctxArgs);
1444
- }
1445
- async create(ctx, model, ...args) {
1446
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], OperationKeys.CREATE, true)).for(this.create);
1447
- log.info(`CONTRACT CREATE, ${ctxArgs}`);
1448
- if (typeof model === "string") model = this.deserialize(model);
1449
- log.info(`Creating model: ${JSON.stringify(model)}`);
1450
- const transient = this.getTransientData(ctx);
1451
- log.info(`Merging transient data...`);
1452
- model = Model.merge(model, transient, this.clazz);
1453
- return this.repo.create(model, ...ctxArgs);
1454
- }
1455
- async read(ctx, key, ...args) {
1456
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], OperationKeys.READ, true)).for(this.create);
1457
- log.info(`reading entry with pk ${key} `);
1458
- return this.repo.read(key, ...ctxArgs);
1459
- }
1460
- getTransientData(ctx) {
1461
- const transientMap = ctx.stub.getTransient();
1462
- let transient = {};
1463
- if (transientMap.has(this.repo.tableName)) {
1464
- transient = JSON.parse(transientMap.get(this.repo.tableName)?.toString("utf8"));
1465
- }
1466
- return transient;
1467
- }
1468
- async update(ctx, model, ...args) {
1469
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], OperationKeys.UPDATE, true)).for(this.update);
1470
- if (typeof model === "string") model = this.deserialize(model);
1471
- log.info(`Updating model: ${JSON.stringify(model)}`);
1472
- const transient = this.getTransientData(ctx);
1473
- log.info(`Merging transient data...`);
1474
- model = Model.merge(model, transient, this.clazz);
1475
- return this.repo.update(model, ...ctxArgs);
1476
- }
1477
- async delete(ctx, key, ...args) {
1478
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], OperationKeys.DELETE, true)).for(this.delete);
1479
- log.info(`deleting entry with pk ${key} `);
1480
- return this.repo.delete(String(key), ...ctxArgs);
1481
- }
1482
- async deleteAll(ctx, keys, ...args) {
1483
- const {ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], BulkCrudOperationKeys.DELETE_ALL, true)).for(this.deleteAll);
1484
- if (typeof keys === "string") keys = JSON.parse(keys);
1485
- return this.repo.deleteAll(keys, ...ctxArgs);
1486
- }
1487
- async readAll(ctx, keys, ...args) {
1488
- const {ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], BulkCrudOperationKeys.READ_ALL, true)).for(this.create);
1489
- if (typeof keys === "string") keys = JSON.parse(keys);
1490
- return this.repo.readAll(keys, ...ctxArgs);
1491
- }
1492
- async updateAll(ctx, models, ...args) {
1493
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], BulkCrudOperationKeys.UPDATE_ALL, true)).for(this.updateAll);
1494
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
1495
- log.info(`updating ${models.length} entries to the table`);
1496
- return this.repo.updateAll(models, ...ctxArgs);
1497
- }
1498
- async query(context, condition, orderBy, order = OrderDirection.ASC, limit, skip, ...args) {
1499
- const {ctxArgs: ctxArgs} = (await this.logCtx([ ...args, context ], PersistenceKeys.QUERY, true)).for(this.create);
1500
- return this.repo.query(condition, orderBy, order, limit, skip, ...ctxArgs);
1501
- }
1502
- async raw(ctx, rawInput, docsOnly, ...args) {
1503
- const {ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], "raw", true)).for(this.raw);
1504
- return FabricCrudContract.adapter.raw(rawInput, docsOnly, ...ctxArgs);
1505
- }
1506
- serialize(model) {
1507
- return FabricCrudContract.serializer.serialize(model);
1508
- }
1509
- deserialize(str) {
1510
- return FabricCrudContract.serializer.deserialize(str);
1511
- }
1512
- async init(ctx) {
1513
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ctx ], PersistenceKeys.INITIALIZATION, true)).for(this.init);
1514
- log.info(`Running contract ${this.getName()} initialization...`);
1515
- this.initialized = true;
1516
- log.info(`Contract initialization completed.`);
1517
- }
1518
- async healthcheck(ctx) {
1519
- const {log: log} = (await this.logCtx([ ctx ], "healthcheck", true)).for(this.healthcheck);
1520
- log.info(`Running Healthcheck: ${this.initialized}...`);
1521
- return {
1522
- healthcheck: this.initialized
1523
- };
1524
- }
1525
- async createAll(ctx, models, ...args) {
1526
- const {log: log, ctxArgs: ctxArgs} = (await this.logCtx([ ...args, ctx ], BulkCrudOperationKeys.CREATE_ALL, true)).for(this.createAll);
1527
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
1528
- log.info(`adding ${models.length} entries to the table`);
1529
- return this.repo.createAll(models, ...ctxArgs);
1530
- }
1531
- logCtx(args, operation, allowCreate = false) {
1532
- const ctx = args.pop();
1533
- if (!ctx || !ctx.stub) {
1534
- throw new MissingContextError(`No valid context provided...`);
1535
- }
1536
- const contextualized = FabricCrudContract.adapter["logCtx"]([ this.clazz, ...args ], operation, allowCreate, ctx);
1537
- function squashArgs(ctx) {
1538
- ctx.ctxArgs.shift();
1539
- return ctx;
1540
- }
1541
- if (!(contextualized instanceof Promise)) return squashArgs(contextualized);
1542
- return contextualized.then(squashArgs);
1543
- }
1544
- }
1545
-
1546
- class SerializedCrudContract extends FabricCrudContract {
1547
- constructor(name, clazz) {
1548
- super(name, clazz);
1549
- }
1550
- async create(ctx, model) {
1551
- return this.serialize(await super.create(ctx, model));
1552
- }
1553
- async read(ctx, key) {
1554
- return this.serialize(await super.read(ctx, key));
1555
- }
1556
- async update(ctx, model) {
1557
- return this.serialize(await super.update(ctx, model));
1558
- }
1559
- async delete(ctx, key) {
1560
- return this.serialize(await super.delete(ctx, key));
1561
- }
1562
- async deleteAll(ctx, keys) {
1563
- const parsedKeys = JSON.parse(keys);
1564
- return JSON.stringify((await super.deleteAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1565
- }
1566
- async readAll(ctx, keys) {
1567
- const parsedKeys = JSON.parse(keys);
1568
- return JSON.stringify((await super.readAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1569
- }
1570
- async updateAll(ctx, models) {
1571
- const list = JSON.parse(models);
1572
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1573
- return JSON.stringify((await super.updateAll(ctx, modelList)).map(m => this.serialize(m)));
1574
- }
1575
- async statement(ctx, method, args) {
1576
- try {
1577
- args = JSON.parse(args);
1578
- } catch (e) {
1579
- throw new SerializationError(`Invalid args: ${e}`);
1580
- }
1581
- if (!Array.isArray(args)) throw new SerializationError(`Invalid args: ${JSON.stringify(args)}. must be an array`);
1582
- return JSON.stringify(await super.statement(ctx, method, ...args));
1583
- }
1584
- async listBy(ctx, key, order) {
1585
- return JSON.stringify(await super.listBy(ctx, key, order));
1586
- }
1587
- async paginateBy(ctx, key, order, ref) {
1588
- try {
1589
- ref = JSON.parse(ref);
1590
- } catch (e) {
1591
- throw new SerializationError(`Failed to deserialize paginateBy reference: ${e}`);
1592
- }
1593
- return JSON.stringify(await super.paginateBy(ctx, key, order, ref));
1594
- }
1595
- async findOneBy(ctx, key, value) {
1596
- return JSON.stringify(await super.findOneBy(ctx, key, value));
1597
- }
1598
- async query(ctx, condition, orderBy, order, limit, skip) {
1599
- let cond;
1600
- try {
1601
- cond = Condition.from(JSON.parse(condition));
1602
- } catch (e) {
1603
- throw new SerializationError(`Invalid condition: ${e}`);
1604
- }
1605
- return JSON.stringify(await super.query(ctx, cond, orderBy, order, limit, skip));
1606
- }
1607
- async init(ctx) {
1608
- await super.init(ctx);
1609
- }
1610
- async healthcheck(ctx) {
1611
- return JSON.stringify(await super.healthcheck(ctx));
1612
- }
1613
- async createAll(context, models) {
1614
- const list = JSON.parse(models);
1615
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1616
- const result = await super.createAll(context, modelList);
1617
- return JSON.stringify(result.map(m => this.serialize(m)));
1618
- }
1619
- }
1620
-
1621
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "create", null);
1622
-
1623
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "read", null);
1624
-
1625
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "update", null);
1626
-
1627
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "delete", null);
1628
-
1629
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "deleteAll", null);
1630
-
1631
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "readAll", null);
1632
-
1633
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "updateAll", null);
1634
-
1635
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "statement", null);
1636
-
1637
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "listBy", null);
1638
-
1639
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "paginateBy", null);
1640
-
1641
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "findOneBy", null);
1642
-
1643
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "init", null);
1644
-
1645
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "healthcheck", null);
1646
-
1647
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "createAll", null);
1648
-
1649
- let ERC20Token = class ERC20Token extends BaseModel {
1650
- constructor(m) {
1651
- super(m);
1652
- }
1653
- };
1654
-
1655
- __decorate([ pk({
1656
- type: String
1657
- }), __metadata("design:type", String) ], ERC20Token.prototype, "name", void 0);
1658
-
1659
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "owner", void 0);
1660
-
1661
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Token.prototype, "symbol", void 0);
1662
-
1663
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Token.prototype, "decimals", void 0);
1664
-
1665
- ERC20Token = __decorate([ table("erc20_tokens"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Token);
1666
-
1667
- let ERC20Wallet = class ERC20Wallet extends BaseModel {
1668
- constructor(m) {
1669
- super(m);
1670
- }
1671
- };
1672
-
1673
- __decorate([ pk({
1674
- type: String
1675
- }), __metadata("design:type", String) ], ERC20Wallet.prototype, "id", void 0);
1676
-
1677
- __decorate([ column(), required(), __metadata("design:type", String) ], ERC20Wallet.prototype, "token", void 0);
1678
-
1679
- __decorate([ column(), required(), __metadata("design:type", Number) ], ERC20Wallet.prototype, "balance", void 0);
1680
-
1681
- __decorate([ column(), __metadata("design:type", String) ], ERC20Wallet.prototype, "captive", void 0);
1682
-
1683
- ERC20Wallet = __decorate([ table("erc20_wallets"), model(), __metadata("design:paramtypes", [ Object ]) ], ERC20Wallet);
1684
-
1685
- let Allowance = class Allowance extends BaseModel {
1686
- constructor(m) {
1687
- super(m);
1688
- }
1689
- };
1690
-
1691
- __decorate([ pk({
1692
- type: String
1693
- }), column(), required(), __metadata("design:type", String) ], Allowance.prototype, "owner", void 0);
1694
-
1695
- __decorate([ column(), required(), __metadata("design:type", String) ], Allowance.prototype, "spender", void 0);
1696
-
1697
- __decorate([ column(), required(), __metadata("design:type", Number) ], Allowance.prototype, "value", void 0);
1698
-
1699
- Allowance = __decorate([ table("erc20_allowances"), model(), __metadata("design:paramtypes", [ Object ]) ], Allowance);
1700
-
1701
- class FabricERC20Contract extends FabricCrudContract {
1702
- constructor(name) {
1703
- super(name, ERC20Wallet);
1704
- FabricERC20Contract.adapter = FabricERC20Contract.adapter || new FabricContractAdapter;
1705
- this.walletRepository = FabricContractRepository.forModel(ERC20Wallet, FabricERC20Contract.adapter.alias);
1706
- this.tokenRepository = FabricContractRepository.forModel(ERC20Token, FabricERC20Contract.adapter.alias);
1707
- this.allowanceRepository = FabricContractRepository.forModel(Allowance, FabricERC20Contract.adapter.alias);
1708
- }
1709
- async TokenName(context) {
1710
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1711
- await this.CheckInitialized(ctx);
1712
- const select = this.tokenRepository.select();
1713
- const token = (await select.execute(ctx))[0];
1714
- return token.name;
1715
- }
1716
- async Symbol(context) {
1717
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1718
- await this.CheckInitialized(ctx);
1719
- const select = this.tokenRepository.select();
1720
- const token = (await select.execute(ctx))[0];
1721
- return token.symbol;
1722
- }
1723
- async Decimals(context) {
1724
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1725
- await this.CheckInitialized(ctx);
1726
- const select = this.tokenRepository.select();
1727
- const token = (await select.execute(ctx))[0];
1728
- return token.decimals;
1729
- }
1730
- async TotalSupply(context) {
1731
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1732
- await this.CheckInitialized(ctx);
1733
- const select = this.walletRepository.select();
1734
- const wallets = await select.execute(ctx);
1735
- if (wallets.length == 0) {
1736
- throw new NotFoundError(`The token ${this.getName()} does not exist`);
1737
- }
1738
- let total = 0;
1739
- wallets.forEach(wallet => {
1740
- total += wallet.balance;
1741
- });
1742
- return total;
1743
- }
1744
- async BalanceOf(context, owner) {
1745
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1746
- await this.CheckInitialized(ctx);
1747
- const wallet = await this.walletRepository.read(owner, ctx);
1748
- return wallet.balance;
1749
- }
1750
- async Transfer(context, to, value) {
1751
- const {ctx: ctx} = await this.logCtx([ context ], this.Transfer);
1752
- await this.CheckInitialized(ctx);
1753
- const from = ctx.identity.getID();
1754
- const transferResp = await this._transfer(from, to, value, ctx);
1755
- if (!transferResp) {
1756
- throw new InternalError("Failed to transfer");
1757
- }
1758
- return true;
1759
- }
1760
- async TransferFrom(context, from, to, value) {
1761
- const {ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1762
- await this.CheckInitialized(ctx);
1763
- const spender = ctx.identity.getID();
1764
- const allowance = await this._getAllowance(from, spender, ctx);
1765
- if (!allowance || allowance.value < 0) {
1766
- throw new AllowanceError(`spender ${spender} has no allowance from ${from}`);
1767
- }
1768
- const currentAllowance = allowance.value;
1769
- if (currentAllowance < value) {
1770
- throw new BalanceError("The spender does not have enough allowance to spend.");
1771
- }
1772
- const updatedAllowance = sub(currentAllowance, value);
1773
- const newAllowance = Object.assign({}, allowance, {
1774
- value: updatedAllowance
1775
- });
1776
- await this.allowanceRepository.update(newAllowance, ctx);
1777
- const transferResp = await this._transfer(from, to, value, ctx);
1778
- if (!transferResp) {
1779
- throw new InternalError("Failed to transfer");
1780
- }
1781
- return true;
1782
- }
1783
- async _transfer(from, to, value, ctx) {
1784
- const log = ctx.logger;
1785
- if (from === to) {
1786
- throw new AuthorizationError("cannot transfer to and from same client account");
1787
- }
1788
- if (value < 0) {
1789
- throw new BalanceError("transfer amount cannot be negative");
1790
- }
1791
- const fromWallet = await this.walletRepository.read(from, ctx);
1792
- const fromBalance = fromWallet.balance;
1793
- if (fromBalance < value) {
1794
- throw new BalanceError(`client account ${from} has insufficient funds.`);
1795
- }
1796
- let toWallet;
1797
- let newToWallet = false;
1798
- try {
1799
- toWallet = await this.walletRepository.read(to, ctx);
1800
- } catch (e) {
1801
- if (e instanceof BaseError) {
1802
- if (e.code === 404) {
1803
- toWallet = new ERC20Wallet({
1804
- id: to,
1805
- balance: 0,
1806
- token: await this.TokenName(ctx)
1807
- });
1808
- newToWallet = true;
1809
- } else {
1810
- throw new InternalError(e.message);
1811
- }
1812
- } else {
1813
- throw new InternalError(e);
1814
- }
1815
- }
1816
- const toBalance = toWallet.balance;
1817
- const fromUpdatedBalance = sub(fromBalance, value);
1818
- const toUpdatedBalance = add(toBalance, value);
1819
- const updatedFromWallet = Object.assign({}, fromWallet, {
1820
- balance: fromUpdatedBalance
1821
- });
1822
- await this.walletRepository.update(updatedFromWallet, ctx);
1823
- const updatedToWallet = Object.assign({}, toWallet, {
1824
- balance: toUpdatedBalance
1825
- });
1826
- if (newToWallet) {
1827
- await this.walletRepository.create(updatedToWallet, ctx);
1828
- } else {
1829
- await this.walletRepository.update(updatedToWallet, ctx);
1830
- }
1831
- const transferEvent = {
1832
- from: from,
1833
- to: to,
1834
- value: value
1835
- };
1836
- this.repo.refresh(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx).catch(e => log.error(`Failed to notify transfer: ${e}`));
1837
- return true;
1838
- }
1839
- async Approve(context, spender, value) {
1840
- const {ctx: ctx, ctxArgs: ctxArgs} = await this.logCtx([ context ], this.Approve);
1841
- await this.CheckInitialized(ctx);
1842
- const owner = ctx.identity.getID();
1843
- let allowance = await this._getAllowance(owner, spender, ctx);
1844
- const ownerWallet = await this.walletRepository.read(owner, ...ctxArgs);
1845
- if (ownerWallet.balance < value) {
1846
- throw new BalanceError(`client account ${owner} has insufficient funds.`);
1847
- }
1848
- if (allowance) {
1849
- allowance.value = value;
1850
- await this.allowanceRepository.update(allowance, ...ctxArgs);
1851
- } else {
1852
- allowance = new Allowance({
1853
- owner: owner,
1854
- spender: spender,
1855
- value: value
1856
- });
1857
- await this.allowanceRepository.create(allowance, ...ctxArgs);
1858
- }
1859
- const approvalEvent = {
1860
- owner: owner,
1861
- spender: spender,
1862
- value: value
1863
- };
1864
- this.repo.refresh(ERC20Token, ERC20Events.APPROVAL, "", approvalEvent, ctx);
1865
- return true;
1866
- }
1867
- async Allowance(context, owner, spender) {
1868
- const {ctx: ctx} = await this.logCtx([ context ], this.Allowance);
1869
- await this.CheckInitialized(ctx);
1870
- const allowance = await this._getAllowance(owner, spender, ctx);
1871
- if (!allowance) {
1872
- throw new AllowanceError(`spender ${spender} has no allowance from ${owner}`);
1873
- }
1874
- return allowance.value;
1875
- }
1876
- async _getAllowance(owner, spender, ctx) {
1877
- const allowanceCondition = Condition.and(Condition.attribute("owner").eq(owner), Condition.attribute("spender").eq(spender));
1878
- const allowance = await this.allowanceRepository.select().where(allowanceCondition).execute(ctx);
1879
- return allowance?.[0];
1880
- }
1881
- async Initialize(context, token) {
1882
- const {ctx: ctx} = await this.logCtx([ context ], this.Initialize);
1883
- const tokens = await this.tokenRepository.select().execute(ctx);
1884
- if (tokens.length > 0) {
1885
- throw new AuthorizationError("contract options are already set, client is not authorized to change them");
1886
- }
1887
- token.owner = ctx.identity.getID();
1888
- await this.tokenRepository.create(token, ctx);
1889
- return true;
1890
- }
1891
- async CheckInitialized(context) {
1892
- const {ctx: ctx} = await this.logCtx([ context ], this.CheckInitialized);
1893
- const tokens = await this.tokenRepository.select().execute(ctx);
1894
- if (tokens.length == 0) {
1895
- throw new NotInitializedError("contract options need to be set before calling any function, call Initialize() to initialize contract");
1896
- }
1897
- }
1898
- async Mint(context, amount) {
1899
- const {ctx: ctx} = await this.logCtx([ context ], this.Mint);
1900
- await this.CheckInitialized(ctx);
1901
- const minter = ctx.identity.getID();
1902
- if (amount <= 0) {
1903
- throw new ValidationError("mint amount must be a positive integer");
1904
- }
1905
- let minterWallet;
1906
- try {
1907
- minterWallet = await this.walletRepository.read(minter, ctx);
1908
- const currentBalance = minterWallet.balance;
1909
- const updatedBalance = add(currentBalance, amount);
1910
- const updatedminter = Object.assign({}, minterWallet, {
1911
- balance: updatedBalance
1912
- });
1913
- await this.walletRepository.update(updatedminter, ctx);
1914
- } catch (e) {
1915
- if (e instanceof BaseError) {
1916
- if (e.code === 404) {
1917
- const newWallet = new ERC20Wallet({
1918
- id: minter,
1919
- balance: amount,
1920
- token: await this.TokenName(context)
1921
- });
1922
- await this.walletRepository.create(newWallet, ctx);
1923
- } else {
1924
- throw new InternalError(e.message);
1925
- }
1926
- } else {
1927
- throw new InternalError(e);
1928
- }
1929
- }
1930
- const transferEvent = {
1931
- from: "0x0",
1932
- to: minter,
1933
- value: amount
1934
- };
1935
- const eventHandler = this.repo.ObserverHandler();
1936
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1937
- }
1938
- async Burn(context, amount) {
1939
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.Burn);
1940
- await this.CheckInitialized(ctx);
1941
- const minter = ctx.identity.getID();
1942
- const minterWallet = await this.walletRepository.read(minter, ctx);
1943
- const currentBalance = minterWallet.balance;
1944
- if (currentBalance < amount) {
1945
- throw new BalanceError(`Minter has insufficient funds.`);
1946
- }
1947
- const updatedBalance = sub(currentBalance, amount);
1948
- const updatedminter = Object.assign({}, minterWallet, {
1949
- balance: updatedBalance
1950
- });
1951
- await this.walletRepository.update(updatedminter, ctx);
1952
- log.info(`${amount} tokens were burned`);
1953
- const transferEvent = {
1954
- from: minter,
1955
- to: "0x0",
1956
- value: amount
1957
- };
1958
- const eventHandler = this.repo.ObserverHandler();
1959
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1960
- }
1961
- async BurnFrom(context, account, amount) {
1962
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1963
- await this.CheckInitialized(ctx);
1964
- const accountWallet = await this.walletRepository.read(account, ctx);
1965
- const currentBalance = accountWallet.balance;
1966
- if (currentBalance < amount) {
1967
- throw new BalanceError(`${account} has insufficient funds.`);
1968
- }
1969
- const updatedBalance = sub(currentBalance, amount);
1970
- const updatedaccount = Object.assign({}, accountWallet, {
1971
- balance: updatedBalance
1972
- });
1973
- await this.walletRepository.update(updatedaccount, ctx);
1974
- log.info(`${amount} tokens were burned from ${account}`);
1975
- const transferEvent = {
1976
- from: account,
1977
- to: "0x0",
1978
- value: amount
1979
- };
1980
- const eventHandler = this.repo.ObserverHandler();
1981
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1982
- }
1983
- async ClientAccountBalance(context) {
1984
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1985
- await this.CheckInitialized(ctx);
1986
- const clientAccountID = ctx.identity.getID();
1987
- const clientWallet = await this.walletRepository.read(clientAccountID, ctx);
1988
- if (!clientWallet) {
1989
- throw new BalanceError(`The account ${clientAccountID} does not exist`);
1990
- }
1991
- return clientWallet.balance;
1992
- }
1993
- async ClientAccountID(context) {
1994
- const {ctx: ctx} = await this.logCtx([ context ], this.ClientAccountID);
1995
- await this.CheckInitialized(ctx);
1996
- const clientAccountID = ctx.identity.getID();
1997
- return clientAccountID;
1998
- }
1999
- }
2000
-
2001
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TokenName", null);
2002
-
2003
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Symbol", null);
2004
-
2005
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Decimals", null);
2006
-
2007
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TotalSupply", null);
2008
-
2009
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BalanceOf", null);
2010
-
2011
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Transfer", null);
2012
-
2013
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TransferFrom", null);
2014
-
2015
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Approve", null);
2016
-
2017
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, String ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Allowance", null);
2018
-
2019
- __decorate([ Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, ERC20Token ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Initialize", null);
2020
-
2021
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "CheckInitialized", null);
2022
-
2023
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Mint", null);
2024
-
2025
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Burn", null);
2026
-
2027
- __decorate([ Owner(), Transaction(), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1, String, Number ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BurnFrom", null);
2028
-
2029
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountBalance", null);
2030
-
2031
- __decorate([ Transaction(false), __metadata("design:type", Function), __metadata("design:paramtypes", [ Context$1 ]), __metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountID", null);
2032
-
2033
- const contracts = [ FabricERC20Contract ];
2034
-
2035
- class ContractLogger extends MiniLogger {
2036
- constructor(context, conf, ctx) {
2037
- super(context, conf);
2038
- if (!ctx) {
2039
- this.logger = new MiniLogger(context, conf);
2040
- } else {
2041
- this.logger = ctx.logging.getLogger(context);
2042
- ctx.logging.setLevel(conf?.level || Logging.getConfig().level);
2043
- }
2044
- }
2045
- log(level, msg, stack) {
2046
- if (NumericLogLevels[this.config("level")] < NumericLogLevels[level]) return;
2047
- let method;
2048
- switch (level) {
2049
- case LogLevel.benchmark:
2050
- method = this.logger.verbose;
2051
- break;
2052
-
2053
- case LogLevel.info:
2054
- method = this.logger.info;
2055
- break;
2056
-
2057
- case LogLevel.verbose:
2058
- method = this.logger.verbose;
2059
- break;
2060
-
2061
- case LogLevel.debug:
2062
- method = this.logger.debug;
2063
- break;
2064
-
2065
- case LogLevel.error:
2066
- method = this.logger.error;
2067
- break;
2068
-
2069
- case LogLevel.trace:
2070
- method = this.logger.trace;
2071
- break;
2072
-
2073
- case LogLevel.warn:
2074
- method = this.logger.warn;
2075
- break;
2076
-
2077
- case LogLevel.silly:
2078
- method = this.logger.silly;
2079
- break;
2080
-
2081
- default:
2082
- throw new InternalError("Invalid log level");
2083
- }
2084
- method.call(this.logger, this.createLog(level, msg, stack));
2085
- }
2086
- }
2087
-
2088
- const factory = (object, config, ctx) => new ContractLogger(object || ContractLogger.name, config || {}, ctx);
2089
-
2090
- Logging.setFactory(factory);
2091
-
2092
- const VERSION = "0.1.54";
2093
-
2094
- const PACKAGE_NAME = "@decaf-ts/for-fabric";
2095
-
2096
- Metadata.registerLibrary(PACKAGE_NAME, VERSION);
2097
-
2098
- export { ContractLogger, FabricContractAdapter, FabricContractContext, FabricContractPaginator, FabricContractRepository, FabricContractRepositoryObservableHandler, FabricCrudContract, FabricStatement, PACKAGE_NAME, SerializedCrudContract, VERSION, contracts, createdByOnFabricCreateUpdate, pkFabricOnCreate };
2099
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWZhYnJpYy5qcyIsInNvdXJjZXMiOlsiLi4vc3JjL3NoYXJlZC9jb25zdGFudHMudHMiLCIuLi9zcmMvc2hhcmVkL292ZXJyaWRlcy9vdmVycmlkZXMudHMiLCIuLi9zcmMvY29udHJhY3RzL0NvbnRyYWN0Q29udGV4dC50cyIsIi4uL3NyYy9zaGFyZWQvZXZlbnRzLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlci50cyIsIi4uL3NyYy9jb250cmFjdHMvRmFicmljQ29udHJhY3RSZXBvc2l0b3J5LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFN0YXRlbWVudC50cyIsIi4uL3NyYy9jb250cmFjdHMvRmFicmljQ29udHJhY3RTZXF1ZW5jZS50cyIsIi4uL3NyYy9zaGFyZWQvU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIudHMiLCIuLi9zcmMvY29udHJhY3RzL0ZhYnJpY0NvbnRyYWN0UGFnaW5hdG9yLnRzIiwiLi4vc3JjL3NoYXJlZC9lcnJvcnMudHMiLCIuLi9zcmMvY29udHJhY3RzL0NvbnRyYWN0QWRhcHRlci50cyIsIi4uL3NyYy9zaGFyZWQvRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIudHMiLCIuLi9zcmMvc2hhcmVkL2VyYzIwL2VyYzIwLWNvbnN0YW50cy50cyIsIi4uL3NyYy9zaGFyZWQvbW9kZWwvRmFicmljQmFzZU1vZGVsLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9GYWJyaWNJZGVudGlmaWVkQmFzZU1vZGVsLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9JZGVudGl0eUNyZWRlbnRpYWxzLnRzIiwiLi4vc3JjL3NoYXJlZC9tb2RlbC9JZGVudGl0eS50cyIsIi4uL3NyYy9zaGFyZWQvQ2xpZW50U2VyaWFsaXplci50cyIsIi4uL3NyYy9zaGFyZWQvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9zaGFyZWQvbWF0aC50cyIsIi4uL3NyYy9jb250cmFjdHMvY3J1ZC9jcnVkLWNvbnRyYWN0LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9jcnVkL3NlcmlhbGl6ZWQtY3J1ZC1jb250cmFjdC50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvbW9kZWxzLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9lcmMyMC9lcmMyMGNvbnRyYWN0LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9lcmMyMC9pbmRleC50cyIsIi4uL3NyYy9jb250cmFjdHMvbG9nZ2luZy50cyIsIi4uL3NyYy92ZXJzaW9uLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGRlc2NyaXB0aW9uIEtleXMgdXNlZCB0byBtYXJrIEZhYnJpYy1zcGVjaWZpYyBtb2RlbCBtZXRhZGF0YVxuICogQHN1bW1hcnkgRW51bWVyYXRpb24gb2Ygc3BlY2lhbCBrZXlzIHVzZWQgYnkgdGhlIHNlcmlhbGl6YXRpb24gbGF5ZXIgdG8gcGVyc2lzdCBGYWJyaWMtcmVsYXRlZCBmbGFncyBvbiBtb2RlbHNcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGVudW0gRmFicmljTW9kZWxLZXlzIHtcbiAgLyoqIFByaXZhdGUgZGF0YSBtYXJrZXIgdXNlZCB0byB0YWcgcHJvcGVydGllcyBvciBtb2RlbHMgZm9yIEZhYnJpYyBwcml2YXRlIGNvbGxlY3Rpb25zICovXG4gIFBSSVZBVEUgPSBcInByaXZhdGVcIixcbiAgU0hBUkVEID0gXCJzaGFyZWRcIixcbiAgLyoqIE5hbWVzcGFjZSBwcmVmaXggdXNlZCBmb3IgRmFicmljLXNwZWNpZmljIG1ldGFkYXRhIGtleXMgKi9cbiAgRkFCUklDID0gXCJmYWJyaWMuXCIsXG4gIE9XTkVEQlkgPSBcIm93bmVkLWJ5XCIsXG4gIFRSQU5TQUNUSU9OX0lEID0gXCJ0cmFuc2FjdGlvbi1pZFwiLFxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3VwcG9ydGVkIGlkZW50aXR5IHR5cGVzIGZvciBGYWJyaWMgY3JlZGVudGlhbHNcbiAqIEBzdW1tYXJ5IEVudW1lcmF0aW9uIG9mIGlkZW50aXR5IGZvcm1hdHMgcmVjb2duaXplZCBieSB0aGlzIGxpYnJhcnlcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGVudW0gSWRlbnRpdHlUeXBlIHtcbiAgLyoqIFN0YW5kYXJkIFguNTA5IGlkZW50aXR5IGZvcm1hdCB1c2VkIGJ5IEh5cGVybGVkZ2VyIEZhYnJpYyAqL1xuICBYNTA5ID0gXCJYLjUwOVwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdHJpbmcgaWRlbnRpZmllciBmb3IgdGhlIEZhYnJpYyBhZGFwdGVyIGZsYXZvdXJcbiAqIEBzdW1tYXJ5IFVzZWQgdG8gdGFnIGFkYXB0ZXJzL3JlcG9zaXRvcmllcyB0aGF0IG9wZXJhdGUgYWdhaW5zdCBIeXBlcmxlZGdlciBGYWJyaWNcbiAqIEBjb25zdCBGYWJyaWNGbGF2b3VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBjb25zdCBGYWJyaWNGbGF2b3VyID0gXCJobGYtZmFicmljXCI7XG4iLCJpbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbi8vIGltcG9ydCB7IHZhbGlkYXRlQ29tcGFyZSB9IGZyb20gXCIuLi9tb2RlbC92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbi8vIGltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbi8vIGltcG9ydCB7IFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L2Vycm9yc1wiO1xuaW1wb3J0IHsgRmFicmljTW9kZWxLZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgU2VncmVnYXRlZE1vZGVsIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyBEQktleXMsIFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgUGVyc2lzdGVuY2VLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5cbk1vZGVsLnByb3RvdHlwZS5pc1NoYXJlZCA9IGZ1bmN0aW9uIGlzU2hhcmVkPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IE1cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gTW9kZWwuaXNTaGFyZWQodGhpcy5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjxNPik7XG59O1xuXG5Nb2RlbC5wcm90b3R5cGUuaXNQcml2YXRlID0gZnVuY3Rpb24gaXNQcml2YXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IE1cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gTW9kZWwuaXNQcml2YXRlKHRoaXMuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3I8TT4pO1xufTtcblxuTW9kZWwucHJvdG90eXBlLnNlZ3JlZ2F0ZSA9IGZ1bmN0aW9uIHNlZ3JlZ2F0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBNXG4pOiBTZWdyZWdhdGVkTW9kZWw8TT4ge1xuICByZXR1cm4gTW9kZWwuc2VncmVnYXRlKHRoaXMpO1xufTtcblxuKE1vZGVsIGFzIGFueSkuc2VncmVnYXRlID0gZnVuY3Rpb24gc2VncmVnYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNXG4pOiBTZWdyZWdhdGVkTW9kZWw8TT4ge1xuICBpZiAoIU1vZGVsLmlzVHJhbnNpZW50KG1vZGVsKSkgcmV0dXJuIHsgbW9kZWw6IG1vZGVsIH07XG4gIGNvbnN0IGRlY29yYXRlZFByb3BlcnRpZXMgPSBNZXRhZGF0YS52YWxpZGF0YWJsZVByb3BlcnRpZXMoXG4gICAgbW9kZWwuY29uc3RydWN0b3IgYXMgYW55XG4gICk7XG5cbiAgY29uc3QgdHJhbnNpZW50UHJvcHMgPSBNZXRhZGF0YS5nZXQoXG4gICAgbW9kZWwuY29uc3RydWN0b3IgYXMgYW55LFxuICAgIERCS2V5cy5UUkFOU0lFTlRcbiAgKTtcbiAgY29uc3QgcHJpdmF0ZVByb3BlcnRpZXMgPSBNZXRhZGF0YS5nZXQoXG4gICAgbW9kZWwuY29uc3RydWN0b3IgYXMgYW55LFxuICAgIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFXG4gICk7XG4gIGNvbnN0IHNoYXJlZFByb3BlcnRpZXMgPSBNZXRhZGF0YS5nZXQoXG4gICAgbW9kZWwuY29uc3RydWN0b3IgYXMgYW55LFxuICAgIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFXG4gICk7XG5cbiAgY29uc3QgcmVzdWx0OiBTZWdyZWdhdGVkTW9kZWw8TT4gPSB7XG4gICAgbW9kZWw6IHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+LFxuICAgIHRyYW5zaWVudDoge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT4sXG4gICAgcHJpdmF0ZToge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT4sXG4gICAgc2hhcmVkOiB7fSBhcyBSZWNvcmQ8a2V5b2YgTSwgYW55PixcbiAgfTtcblxuICBjb25zdCB0cmFuc2llbnRLZXlzID0gT2JqZWN0LmtleXModHJhbnNpZW50UHJvcHMpO1xuICBjb25zdCBwcml2YXRlS2V5cyA9IE9iamVjdC5rZXlzKHByaXZhdGVQcm9wZXJ0aWVzKTtcbiAgY29uc3Qgc2hhcmVkS2V5cyA9IE9iamVjdC5rZXlzKHNoYXJlZFByb3BlcnRpZXMpO1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIGRlY29yYXRlZFByb3BlcnRpZXMpIHtcbiAgICBjb25zdCBpc1RyYW5zaWVudCA9IHRyYW5zaWVudEtleXMuaW5jbHVkZXMoa2V5KTtcbiAgICBjb25zdCBpc1ByaXZhdGUgPSBwcml2YXRlS2V5cy5pbmNsdWRlcyhrZXkpO1xuICAgIGNvbnN0IGlzU2hhcmVkID0gc2hhcmVkS2V5cy5pbmNsdWRlcyhrZXkpO1xuICAgIGlmIChpc1RyYW5zaWVudCkge1xuICAgICAgcmVzdWx0LnRyYW5zaWVudCA9IHJlc3VsdC50cmFuc2llbnQgfHwgKHt9IGFzIGFueSk7XG4gICAgICAocmVzdWx0LnRyYW5zaWVudCBhcyBhbnkpW2tleV0gPSBtb2RlbFtrZXkgYXMga2V5b2YgTV07XG4gICAgICBpZiAoaXNQcml2YXRlKSB7XG4gICAgICAgIHJlc3VsdC5wcml2YXRlID0gcmVzdWx0LnByaXZhdGUgfHwgKHt9IGFzIGFueSk7XG4gICAgICAgIChyZXN1bHQucHJpdmF0ZSBhcyBhbnkpW2tleV0gPSBtb2RlbFtrZXkgYXMga2V5b2YgTV07XG4gICAgICB9XG4gICAgICBpZiAoaXNTaGFyZWQpIHtcbiAgICAgICAgcmVzdWx0LnNoYXJlZCA9IHJlc3VsdC5zaGFyZWQgfHwgKHt9IGFzIGFueSk7XG4gICAgICAgIChyZXN1bHQuc2hhcmVkIGFzIGFueSlba2V5XSA9IG1vZGVsW2tleSBhcyBrZXlvZiBNXTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0Lm1vZGVsID0gcmVzdWx0Lm1vZGVsIHx8IHt9O1xuICAgICAgKHJlc3VsdC5tb2RlbCBhcyBhbnkpW2tleV0gPSAobW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55Pilba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXN1bHQubW9kZWwgPSBNb2RlbC5idWlsZChyZXN1bHQubW9kZWwsIG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpO1xuICByZXR1cm4gcmVzdWx0IGFzIFNlZ3JlZ2F0ZWRNb2RlbDxNPjtcbn0uYmluZChNb2RlbCk7XG5cbihNb2RlbCBhcyBhbnkpLnRhYmxlTmFtZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogQ29uc3RydWN0b3I8TT4gfCBNXG4pOiBzdHJpbmcge1xuICBjb25zdCB0YXJnZXQgPSBtb2RlbCBpbnN0YW5jZW9mIE1vZGVsID8gbW9kZWwuY29uc3RydWN0b3IgOiBtb2RlbDtcbiAgY29uc3QgbWV0YSA9IE1ldGFkYXRhLmdldCh0YXJnZXQgYXMgYW55LCBQZXJzaXN0ZW5jZUtleXMuVEFCTEUpO1xuICBpZiAobWV0YSkgcmV0dXJuIG1ldGE7XG4gIGlmIChtb2RlbCBpbnN0YW5jZW9mIE1vZGVsKSByZXR1cm4gbW9kZWwuY29uc3RydWN0b3IubmFtZTtcbiAgcmV0dXJuIG1vZGVsLm5hbWU7XG59O1xuXG4oTW9kZWwgYXMgYW55KS5pc1ByaXZhdGUgPSBmdW5jdGlvbiBpc1ByaXZhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIU1ldGFkYXRhLmdldChcbiAgICB0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpIDogbW9kZWwsXG4gICAgRmFicmljTW9kZWxLZXlzLlBSSVZBVEVcbiAgKTtcbn0uYmluZChNb2RlbCk7XG5cbihNZXRhZGF0YSBhcyBhbnkpLmlzU2hhcmVkID0gZnVuY3Rpb24gaXNTaGFyZWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPlxuKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIU1ldGFkYXRhLmdldChcbiAgICB0eXBlb2YgbW9kZWwgIT09IFwiZnVuY3Rpb25cIiA/IChtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpIDogbW9kZWwsXG4gICAgRmFicmljTW9kZWxLZXlzLlNIQVJFRFxuICApO1xufS5iaW5kKE1ldGFkYXRhKTtcbiIsImltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgQ2hhaW5jb2RlU3R1YiwgQ2xpZW50SWRlbnRpdHkgfSBmcm9tIFwiZmFicmljLXNoaW0tYXBpXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnRleHQgY2xhc3MgZm9yIEZhYnJpYyBjaGFpbmNvZGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgYWNjZXNzIHRvIEZhYnJpYy1zcGVjaWZpYyBjb250ZXh0IGVsZW1lbnRzIGxpa2Ugc3R1YiwgaWRlbnRpdHksIGFuZCBsb2dnZXIgdG8gYmUgdXNlZCBieSByZXBvc2l0b3JpZXMgYW5kIGFkYXB0ZXJzIGR1cmluZyBjb250cmFjdCBleGVjdXRpb24uXG4gKiBAdGVtcGxhdGUgRiAtIEZsYWdzIHNwZWNpZmljIHRvIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAcGFyYW0ge29iamVjdH0gW2FyZ3NdIC0gT3B0aW9uYWwgaW5pdGlhbGl6YXRpb24gYXJndW1lbnRzIHBhc3NlZCB0byB0aGUgYmFzZSBDb250ZXh0XG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdCBtZXRob2RcbiAqIGNvbnN0IGNvbnRleHQgPSBuZXcgRmFicmljQ29udHJhY3RDb250ZXh0KCk7XG4gKiAvLyBPcHRpb25hbGx5IHNldCB2YWx1ZXMgdmlhIHRoZSBiYXNlIENvbnRleHQgQVBJXG4gKiBjb250ZXh0LnNldCgnc3R1YicsIGN0eC5zdHViKTtcbiAqIGNvbnRleHQuc2V0KCdjbGllbnRJZGVudGl0eScsIGN0eC5jbGllbnRJZGVudGl0eSk7XG4gKiBjb250ZXh0LnNldCgnbG9nZ2VyJywgY29udHJhY3RMb2dnZXIpO1xuICpcbiAqIC8vIEFjY2VzcyBjb250ZXh0IHByb3BlcnRpZXNcbiAqIGNvbnN0IHRpbWVzdGFtcCA9IGNvbnRleHQudGltZXN0YW1wO1xuICogY29uc3QgY3JlYXRvciA9IGNvbnRleHQuaWRlbnRpdHkuZ2V0SUQoKTtcbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBDb250ZXh0XG4gKiAgIHBhcnRpY2lwYW50IExlZGdlclxuICogICBDb250cmFjdC0+PkNvbnRleHQ6IG5ldyBGYWJyaWNDb250cmFjdENvbnRleHQoKVxuICogICBDb250cmFjdC0+PkNvbnRleHQ6IHNldCgnc3R1Yid8J2NsaWVudElkZW50aXR5J3wnbG9nZ2VyJywgLi4uKVxuICogICBDb250ZXh0LS0+PkNvbnRyYWN0OiB0aW1lc3RhbXAsIGlkZW50aXR5LCBsb2dnZXJcbiAqICAgQ29udHJhY3QtPj5MZWRnZXI6IEludGVyYWN0IHZpYSBzdHViXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDb250cmFjdENvbnRleHQgZXh0ZW5kcyBDb250ZXh0PEZhYnJpY0NvbnRyYWN0RmxhZ3M+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IEZhYnJpY0NvbnRyYWN0Q29udGV4dCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyB0aGUgY29udGV4dCB3aXRoIEZhYnJpYy1zcGVjaWZpYyBmbGFnc1xuICAgKi9cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY2hhaW5jb2RlIHN0dWJcbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgQ2hhaW5jb2RlU3R1YiBpbnN0YW5jZSBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgbGVkZ2VyXG4gICAqIEByZXR1cm4ge0NoYWluY29kZVN0dWJ9IFRoZSBjaGFpbmNvZGUgc3R1YlxuICAgKi9cbiAgZ2V0IHN0dWIoKTogQ2hhaW5jb2RlU3R1YiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFwic3R1YlwiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdHJhbnNhY3Rpb24gdGltZXN0YW1wXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSB0aW1lc3RhbXAgZ2V0dGVyIHRvIHVzZSB0aGUgc3R1YidzIHRpbWVzdGFtcFxuICAgKiBAcmV0dXJuIHtEYXRlfSBUaGUgdHJhbnNhY3Rpb24gdGltZXN0YW1wXG4gICAqL1xuICBvdmVycmlkZSBnZXQgdGltZXN0YW1wKCk6IERhdGUge1xuICAgIHJldHVybiB0aGlzLnN0dWIuZ2V0RGF0ZVRpbWVzdGFtcCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBjbGllbnQgaWRlbnRpdHlcbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgQ2xpZW50SWRlbnRpdHkgaW5zdGFuY2UgZm9yIHRoZSB0cmFuc2FjdGlvbiBzdWJtaXR0ZXJcbiAgICogQHJldHVybiB7Q2xpZW50SWRlbnRpdHl9IFRoZSBjbGllbnQgaWRlbnRpdHlcbiAgICovXG4gIGdldCBpZGVudGl0eSgpOiBDbGllbnRJZGVudGl0eSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFwiaWRlbnRpdHlcIik7XG4gIH1cblxuICBvdmVycmlkZSB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYGZhYnJpYyBjdHgke3RoaXMuc3R1YiA/IFwiIHdpdGggc3R1YlwiIDogXCJ3aXRob3V0IHN0dWJcIn1gO1xuICB9XG59XG4iLCJpbXBvcnQgeyBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgRmFicmljIGV2ZW50IG5hbWUgZnJvbSBjb21wb25lbnRzXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgc3RhbmRhcmRpemVkIGV2ZW50IG5hbWUgYnkgam9pbmluZyB0YWJsZSwgZXZlbnQsIGFuZCBvcHRpb25hbCBvd25lciB3aXRoIHVuZGVyc2NvcmVzXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUvY29sbGVjdGlvbiBuYW1lXG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmd9IGV2ZW50IC0gVGhlIGV2ZW50IHR5cGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbb3duZXJdIC0gT3B0aW9uYWwgb3duZXIgaWRlbnRpZmllclxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIGV2ZW50IG5hbWUgaW4gZm9ybWF0IFwidGFibGVfZXZlbnRcIiBvciBcInRhYmxlX2V2ZW50X293bmVyXCJcbiAqIEBmdW5jdGlvbiBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWUoXG4gIHRhYmxlOiBzdHJpbmcsXG4gIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nLFxuICBvd25lcj86IHN0cmluZ1xuKSB7XG4gIGNvbnN0IHBhcmFtcyA9IFt0YWJsZSwgZXZlbnRdO1xuICBpZiAob3duZXIpIHBhcmFtcy5wdXNoKG93bmVyKTtcbiAgcmV0dXJuIHBhcmFtcy5qb2luKFwiX1wiKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgRmFicmljIGV2ZW50IG5hbWUgaW50byBpdHMgY29tcG9uZW50c1xuICogQHN1bW1hcnkgU3BsaXRzIGFuIGV2ZW50IG5hbWUgYnkgdW5kZXJzY29yZXMgYW5kIGV4dHJhY3RzIHRhYmxlLCBldmVudCwgYW5kIG9wdGlvbmFsIG93bmVyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBldmVudCBuYW1lIHRvIHBhcnNlXG4gKiBAcmV0dXJuIHt7dGFibGU6IHN0cmluZywgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcsIG93bmVyOiBzdHJpbmd9fSBUaGUgcGFyc2VkIGNvbXBvbmVudHMgYXMgYSBzdHJ1Y3R1cmVkIG9iamVjdFxuICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlIGV2ZW50IG5hbWUgZm9ybWF0IGlzIGludmFsaWRcbiAqIEBmdW5jdGlvbiBwYXJzZUV2ZW50TmFtZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgUGFyc2VyIGFzIHBhcnNlRXZlbnROYW1lXG4gKiAgIENhbGxlci0+PlBhcnNlcjogcGFyc2VFdmVudE5hbWUobmFtZSlcbiAqICAgUGFyc2VyLT4+UGFyc2VyOiBzcGxpdCBuYW1lIGJ5IFwiX1wiXG4gKiAgIGFsdCBwYXJ0cyBsZW5ndGggaW52YWxpZFxuICogICAgIFBhcnNlci0tPj5DYWxsZXI6IHRocm93IEludGVybmFsRXJyb3JcbiAqICAgZWxzZVxuICogICAgIFBhcnNlci0tPj5DYWxsZXI6IHsgdGFibGUsIGV2ZW50LCBvd25lcj8gfVxuICogICBlbmRcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRXZlbnROYW1lKG5hbWU6IHN0cmluZyk6IHtcbiAgdGFibGU/OiBzdHJpbmc7XG4gIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nO1xuICBvd25lcj86IHN0cmluZztcbn0ge1xuICBjb25zdCBwYXJ0cyA9IG5hbWUuc3BsaXQoXCJfXCIpO1xuICBpZiAocGFydHMubGVuZ3RoIDwgMiB8fCBwYXJ0cy5sZW5ndGggPiAzKVxuICAgIHJldHVybiB7IHRhYmxlOiB1bmRlZmluZWQsIGV2ZW50OiBuYW1lLCBvd25lcjogdW5kZWZpbmVkIH07XG4gIHJldHVybiB7XG4gICAgdGFibGU6IHBhcnRzWzBdLFxuICAgIGV2ZW50OiBwYXJ0c1sxXSxcbiAgICBvd25lcjogcGFydHNbMl0sXG4gIH0gYXMge1xuICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgZXZlbnQ6IE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc7XG4gICAgb3duZXI/OiBzdHJpbmc7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7XG4gIEFkYXB0ZXIsXG4gIENvbnRleHR1YWxBcmdzLFxuICBFdmVudElkcyxcbiAgT2JzZXJ2ZXJIYW5kbGVyLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IGdlbmVyYXRlRmFicmljRXZlbnROYW1lIH0gZnJvbSBcIi4uL3NoYXJlZC9ldmVudHNcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT2JzZXJ2ZXIgaGFuZGxlciBmb3IgRmFicmljIGNoYWluY29kZSBldmVudHNcbiAqIEBzdW1tYXJ5IEVtaXRzIGV2ZW50cyBvbiB0aGUgRmFicmljIGxlZGdlciB3aGVuIHJlcG9zaXRvcnkgb3BlcmF0aW9ucyBvY2N1clxuICogQGNsYXNzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyXG4gKiBAZXh0ZW5kcyB7T2JzZXJ2ZXJIYW5kbGVyfVxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdFxuICogaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgfSBmcm9tICdAZGVjYWYtdHMvZm9yLWZhYnJpYyc7XG4gKlxuICogLy8gQ3JlYXRlIGEgaGFuZGxlciB3aXRoIGRlZmF1bHQgc3VwcG9ydGVkIGV2ZW50c1xuICogY29uc3QgaGFuZGxlciA9IG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlcigpO1xuICpcbiAqIC8vIEVtaXQgYW4gZXZlbnRcbiAqIGF3YWl0IGhhbmRsZXIudXBkYXRlT2JzZXJ2ZXJzKFxuICogICBsb2dnZXIsXG4gKiAgICdhc3NldHMnLFxuICogICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAqICAgJ2Fzc2V0MScsXG4gKiAgIGNvbnRleHRcbiAqICk7XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBPYnNlcnZhYmxlSGFuZGxlclxuICogICBwYXJ0aWNpcGFudCBTdHViXG4gKiAgIHBhcnRpY2lwYW50IExlZGdlclxuICpcbiAqICAgUmVwb3NpdG9yeS0+Pk9ic2VydmFibGVIYW5kbGVyOiB1cGRhdGVPYnNlcnZlcnMobG9nLCB0YWJsZSwgZXZlbnQsIGlkLCBjdHgpXG4gKiAgIE9ic2VydmFibGVIYW5kbGVyLT4+T2JzZXJ2YWJsZUhhbmRsZXI6IENoZWNrIGlmIGV2ZW50IGlzIHN1cHBvcnRlZFxuICogICBPYnNlcnZhYmxlSGFuZGxlci0+Pk9ic2VydmFibGVIYW5kbGVyOiBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSh0YWJsZSwgZXZlbnQsIG93bmVyKVxuICogICBPYnNlcnZhYmxlSGFuZGxlci0+PlN0dWI6IHNldEV2ZW50KGV2ZW50TmFtZSwgcGF5bG9hZClcbiAqICAgU3R1Yi0+PkxlZGdlcjogUmVjb3JkIGV2ZW50XG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciBleHRlbmRzIE9ic2VydmVySGFuZGxlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyB0aGUgaGFuZGxlciB3aXRoIGEgbGlzdCBvZiBzdXBwb3J0ZWQgZXZlbnRzXG4gICAqIEBwYXJhbSB7QXJyYXk8T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZz59IFtzdXBwb3J0ZWRFdmVudHNdIC0gRXZlbnRzIHRoYXQgd2lsbCB0cmlnZ2VyIEZhYnJpYyBldmVudHNcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgc3VwcG9ydGVkRXZlbnRzOiAoXG4gICAgICB8IE9wZXJhdGlvbktleXNcbiAgICAgIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzXG4gICAgICB8IHN0cmluZ1xuICAgIClbXSA9IFtcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5DUkVBVEVfQUxMLFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLlVQREFURV9BTEwsXG4gICAgICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuREVMRVRFX0FMTCxcbiAgICBdXG4gICkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgb2JzZXJ2ZXJzIGJ5IGVtaXR0aW5nIEZhYnJpYyBldmVudHNcbiAgICogQHN1bW1hcnkgRW1pdHMgZXZlbnRzIG9uIHRoZSBGYWJyaWMgbGVkZ2VyIGZvciBzdXBwb3J0ZWQgZXZlbnQgdHlwZXNcbiAgICogQHBhcmFtIHtMb2dnZXJ9IGxvZyAtIExvZ2dlciBpbnN0YW5jZSBmb3IgZGVidWdnaW5nXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSAtIFRoZSB0YWJsZS9jb2xsZWN0aW9uIG5hbWVcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nfSBldmVudCAtIFRoZSBldmVudCB0eXBlXG4gICAqIEBwYXJhbSB7RXZlbnRJZHN9IGlkIC0gVGhlIGV2ZW50IGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtGYWJyaWNDb250cmFjdENvbnRleHR9IGN0eCAtIFRoZSBGYWJyaWMgY29udHJhY3QgY29udGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW293bmVyXSAtIE9wdGlvbmFsIG93bmVyIGlkZW50aWZpZXIgZm9yIHRoZSBldmVudFxuICAgKiBAcGFyYW0ge29iamVjdCB8IHN0cmluZyB8IHVuZGVmaW5lZH0gW293bmVyXSAtIE9wdGlvbmFsIHBheWxvYWQgZm9yIHRoZSBldmVudFxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlT2JzZXJ2ZXJzKFxuICAgIGNsYXp6OiBzdHJpbmcgfCBDb25zdHJ1Y3Rvcjxhbnk+LFxuICAgIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nLFxuICAgIGlkOiBFdmVudElkcyxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IEFkYXB0ZXIubG9nQ3R4PEZhYnJpY0NvbnRyYWN0Q29udGV4dD4oXG4gICAgICB0aGlzLnVwZGF0ZU9ic2VydmVycyxcbiAgICAgIGV2ZW50LFxuICAgICAgZmFsc2UsXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgICBjb25zdCB7IHN0dWIgfSA9IGN0eDtcbiAgICBjb25zdCBbb3duZXIsIHBheWxvYWRdID0gYXJncztcbiAgICBjb25zdCB0YWJsZSA9IHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IGNsYXp6IDogY2xhenoubmFtZTtcbiAgICBpZiAodGhpcy5zdXBwb3J0ZWRFdmVudHMuaW5kZXhPZihldmVudCkgIT09IC0xKSB7XG4gICAgICBsb2cuZGVidWcoYEVtaXR0aW5nICR7ZXZlbnR9IGV2ZW50YCk7XG4gICAgICBjb25zdCBldmVudE5hbWUgPSBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSh0YWJsZSwgZXZlbnQsIG93bmVyKTtcbiAgICAgIHN0dWIuc2V0RXZlbnQoZXZlbnROYW1lLCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeSh7IGlkOiBpZCB9KSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHViLnNldEV2ZW50KGV2ZW50LCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShwYXlsb2FkKSkpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgUmVwb3NpdG9yeSxcbiAgT2JzZXJ2ZXJIYW5kbGVyLFxuICBFdmVudElkcyxcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgUXVlcnlFcnJvcixcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBQcmVwYXJlZFN0YXRlbWVudEtleXMsXG4gIE9yZGVyRGlyZWN0aW9uLFxuICBTZXJpYWxpemVkUGFnZSxcbiAgUGFnaW5hdG9yLFxuICBEaXJlY3Rpb25MaW1pdE9mZnNldCxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlclwiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIEludGVybmFsRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuL0NvbnRyYWN0QWRhcHRlclwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXBvc2l0b3J5IGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIG1vZGVsc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgQ1JVRCBvcGVyYXRpb25zIGZvciBtb2RlbHMgd2l0aGluIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RzXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgTWFuZ29RdWVyeSAtIFF1ZXJ5IHR5cGUgZm9yIENvdWNoREItbGlrZSBxdWVyaWVzXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RBZGFwdGVyIC0gQWRhcHRlciB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0RmxhZ3MgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0Q29udGV4dCAtIENvbnRleHQgdHlwZSBmb3IgRmFicmljIGNvbnRyYWN0IG9wZXJhdGlvbnNcbiAqXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0QWRhcHRlcn0gW2FkYXB0ZXJdIC0gVGhlIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIHN0YXRlIGRhdGFiYXNlXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbY2xhenpdIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5PE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc+fSBbdHJhY2tlZEV2ZW50c10gLSBFdmVudHMgdG8gdHJhY2sgZm9yIG9ic2VydmVyIG5vdGlmaWNhdGlvbnNcbiAqXG4gKiBAY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW4gYSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRyYWN0IGNsYXNzXG4gKiBpbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnksIEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gJ0BkZWNhZi10cy9mb3ItZmFicmljJztcbiAqXG4gKiBAdGFibGUoJ2Fzc2V0cycpXG4gKiBjbGFzcyBBc3NldCBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGlkKClcbiAqICAgaWQ6IHN0cmluZztcbiAqXG4gKiAgIEBwcm9wZXJ0eSgpXG4gKiAgIGRhdGE6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBleHBvcnQgY2xhc3MgTXlDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHtcbiAqICAgcHJpdmF0ZSBhZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuICogICBwcml2YXRlIHJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxBc3NldD47XG4gKlxuICogICBjb25zdHJ1Y3RvcigpIHtcbiAqICAgICBzdXBlcignTXlDb250cmFjdCcpO1xuICogICAgIHRoaXMucmVwb3NpdG9yeSA9IG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8QXNzZXQ+KHRoaXMuYWRhcHRlciwgQXNzZXQpO1xuICogICB9XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KCk7XG4gKiAgICAgYXNzZXQuaWQgPSBpZDtcbiAqICAgICBhc3NldC5kYXRhID0gZGF0YTtcbiAqXG4gKiAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmNyZWF0ZShhc3NldCwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdGF0ZURCXG4gKlxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IGNyZWF0ZShtb2RlbCwgY3R4KVxuICogICBSZXBvc2l0b3J5LT4+QWRhcHRlcjogcHJlcGFyZShtb2RlbCwgcGspXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgcmVjb3JkLCB0cmFuc2llbnQsIGN0eClcbiAqICAgQWRhcHRlci0+PlN0YXRlREI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3RhdGVEQi0tPj5BZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogcmVjb3JkXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiByZXZlcnQocmVjb3JkLCBjbGFzcywgcGssIGlkLCB0cmFuc2llbnQpXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogbW9kZWxcbiAqICAgUmVwb3NpdG9yeS0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgUmVwb3NpdG9yeTxcbiAgTSxcbiAgRmFicmljQ29udHJhY3RBZGFwdGVyXG4+IHtcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIF9vdmVycmlkZXMgPSBPYmplY3QuYXNzaWduKHt9LCBzdXBlcltcIl9vdmVycmlkZXNcIl0sIHtcbiAgICBpZ25vcmVWYWxpZGF0aW9uOiBmYWxzZSxcbiAgICBpZ25vcmVIYW5kbGVyczogZmFsc2UsXG4gICAgYWxsb3dSYXdTdGF0ZW1lbnRzOiB0cnVlLFxuICAgIGZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXM6IGZhbHNlLFxuICAgIGZvcmNlUHJlcGFyZUNvbXBsZXhRdWVyaWVzOiBmYWxzZSxcbiAgfSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgYWRhcHRlcj86IEZhYnJpY0NvbnRyYWN0QWRhcHRlcixcbiAgICBjbGF6ej86IENvbnN0cnVjdG9yPE0+LFxuICAgIHByb3RlY3RlZCB0cmFja2VkRXZlbnRzPzogKE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcpW11cbiAgKSB7XG4gICAgc3VwZXIoYWRhcHRlciwgY2xhenopO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcGFnaW5hdGVCeShcbiAgICBrZXk6IGtleW9mIE0sXG4gICAgb3JkZXI6IE9yZGVyRGlyZWN0aW9uLFxuICAgIHJlZjogT21pdDxEaXJlY3Rpb25MaW1pdE9mZnNldCwgXCJkaXJlY3Rpb25cIj4gPSB7XG4gICAgICBvZmZzZXQ6IDEsXG4gICAgICBsaW1pdDogMTAsXG4gICAgfSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFNlcmlhbGl6ZWRQYWdlPE0+PiB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1jb25zdFxuICAgIGxldCB7IG9mZnNldCwgYm9va21hcmssIGxpbWl0IH0gPSByZWY7XG4gICAgaWYgKCFvZmZzZXQgJiYgIWJvb2ttYXJrKVxuICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoYFBhZ2luYXRlQnkgbmVlZHMgYSBwYWdlIG9yIGEgYm9va21hcmtgKTtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLlBBR0VfQlksIHRydWUpXG4gICAgKS5mb3IodGhpcy5wYWdpbmF0ZUJ5KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBwYWdpbmF0aW5nICR7TW9kZWwudGFibGVOYW1lKHRoaXMuY2xhc3MpfSB3aXRoIHBhZ2Ugc2l6ZSAke2xpbWl0fWBcbiAgICApO1xuXG4gICAgbGV0IHBhZ2luYXRvcjogUGFnaW5hdG9yPE0+O1xuICAgIGlmIChib29rbWFyaykge1xuICAgICAgcGFnaW5hdG9yID0gYXdhaXQgdGhpcy5vdmVycmlkZSh7XG4gICAgICAgIGZvcmNlUHJlcGFyZUNvbXBsZXhRdWVyaWVzOiBmYWxzZSxcbiAgICAgICAgZm9yY2VQcmVwYXJlU2ltcGxlUXVlcmllczogZmFsc2UsXG4gICAgICB9IGFzIGFueSlcbiAgICAgICAgLnNlbGVjdCgpXG4gICAgICAgIC53aGVyZSh0aGlzLmF0dHIoTW9kZWwucGsodGhpcy5jbGFzcykpLmd0KGJvb2ttYXJrKSlcbiAgICAgICAgLm9yZGVyQnkoW2tleSwgb3JkZXJdKVxuICAgICAgICAucGFnaW5hdGUobGltaXQgYXMgbnVtYmVyLCAuLi5jdHhBcmdzKTtcbiAgICAgIG9mZnNldCA9IDE7XG4gICAgfSBlbHNlIGlmIChvZmZzZXQpIHtcbiAgICAgIHBhZ2luYXRvciA9IGF3YWl0IHRoaXMub3ZlcnJpZGUoe1xuICAgICAgICBmb3JjZVByZXBhcmVDb21wbGV4UXVlcmllczogZmFsc2UsXG4gICAgICAgIGZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXM6IGZhbHNlLFxuICAgICAgfSBhcyBhbnkpXG4gICAgICAgIC5zZWxlY3QoKVxuICAgICAgICAub3JkZXJCeShba2V5LCBvcmRlcl0pXG4gICAgICAgIC5wYWdpbmF0ZShsaW1pdCBhcyBudW1iZXIsIC4uLmN0eEFyZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihgUGFnaW5hdGVCeSBuZWVkcyBhIHBhZ2Ugb3IgYSBib29rbWFya2ApO1xuICAgIH1cbiAgICBjb25zdCBwYWdlZCA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKG9mZnNldCwgYm9va21hcmssIC4uLmN0eEFyZ3MpO1xuICAgIHJldHVybiBwYWdpbmF0b3Iuc2VyaWFsaXplKHBhZ2VkKSBhcyBTZXJpYWxpemVkUGFnZTxNPjtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHN0YXRlbWVudChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKSB7XG4gICAgY29uc3QgeyBsb2csIGN0eCwgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoYXJncywgUGVyc2lzdGVuY2VLZXlzLlNUQVRFTUVOVCwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLnN0YXRlbWVudCk7XG4gICAgaWYgKCFSZXBvc2l0b3J5LnN0YXRlbWVudHModGhpcywgbmFtZSBhcyBrZXlvZiB0eXBlb2YgdGhpcykpXG4gICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihgSW52YWxpZCBwcmVwYXJlZCBzdGF0ZW1lbnQgcmVxdWVzdGVkICR7bmFtZX1gKTtcbiAgICBpZiAoY3R4LmxvZ2dlcikge1xuICAgICAgY3R4LmxvZ2dlci5pbmZvKGBSZXBvIHN0YXRlbWVudDogJHtuYW1lfSArICR7YXJnc31gKTtcbiAgICB9XG4gICAgbG9nLnZlcmJvc2UoYEV4ZWN1dGluZyBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfWApO1xuXG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCAodGhpcyBhcyBhbnkpW25hbWVdKC4uLmN0eEFyZ3MpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgQmFzZUVycm9yKSB0aHJvdyBlO1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gZXhlY3V0ZSBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgb2JzZXJ2ZXIgaGFuZGxlciBmb3IgdGhpcyByZXBvc2l0b3J5XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgYSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciBpbnN0YW5jZVxuICAgKiBAcmV0dXJuIHtPYnNlcnZlckhhbmRsZXJ9IFRoZSBvYnNlcnZlciBoYW5kbGVyXG4gICAqL1xuICBvdmVycmlkZSBPYnNlcnZlckhhbmRsZXIoKTogT2JzZXJ2ZXJIYW5kbGVyIHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgb2JzZXJ2ZXJzIGJhc2VkIG9uIHRyYWNrZWQgZXZlbnRzXG4gICAqIEBzdW1tYXJ5IEZpbHRlcnMgZXZlbnRzIGJhc2VkIG9uIHRyYWNrZWRFdmVudHMgYW5kIGRlbGVnYXRlcyB0byB0aGUgcGFyZW50IG1ldGhvZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUvY29sbGVjdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICAgKiBAcGFyYW0ge0V2ZW50SWRzfSBpZCAtIFRoZSBldmVudCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIG9ic2VydmVycyBhcmUgdXBkYXRlZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlT2JzZXJ2ZXJzKFxuICAgIHRhYmxlOiBDb25zdHJ1Y3RvcjxNPiB8IHN0cmluZyxcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMudHJhY2tlZEV2ZW50cyB8fCB0aGlzLnRyYWNrZWRFdmVudHMuaW5kZXhPZihldmVudCkgIT09IC0xKVxuICAgICAgcmV0dXJuIGF3YWl0IHN1cGVyLnVwZGF0ZU9ic2VydmVycyh0YWJsZSwgZXZlbnQsIGlkLCAuLi5hcmdzKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQge1xuICBDb3VjaERCQWRhcHRlcixcbiAgQ291Y2hEQkdyb3VwT3BlcmF0b3IsXG4gIENvdWNoREJLZXlzLFxuICBDb3VjaERCT3BlcmF0b3IsXG4gIE1hbmdvT3BlcmF0b3IsXG4gIE1hbmdvUXVlcnksXG4gIE1hbmdvU2VsZWN0b3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHsgQ291Y2hEQlN0YXRlbWVudCB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7XG4gIENvbmRpdGlvbixcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgT3JkZXJEaXJlY3Rpb24sXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMsIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RhdGVtZW50IHdyYXBwZXIgZm9yIGV4ZWN1dGluZyBNYW5nbyBxdWVyaWVzIHdpdGhpbiBGYWJyaWMgY29udHJhY3RzXG4gKiBAc3VtbWFyeSBCcmlkZ2VzIENvdWNoREItc3R5bGUgcXVlcmllcyB0byBGYWJyaWMgdmlhIHRoZSBGYWJyaWNDb250cmFjdEFkYXB0ZXIsIGhhbmRsaW5nIGlkZW50aXR5IGFuZCBwcmltYXJ5IGtleSBwcm9qZWN0aW9uIHdoZW4gbmVlZGVkLlxuICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlIHRoaXMgc3RhdGVtZW50IG9wZXJhdGVzIG9uXG4gKiBAdGVtcGxhdGUgUiAtIFJlc3VsdCB0eXBlIHJldHVybmVkIGJ5IHRoZSBzdGF0ZW1lbnRcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RBZGFwdGVyfSBhZGFwdGVyIC0gVGhlIEZhYnJpYyBjb250cmFjdCBhZGFwdGVyIHVzZWQgZm9yIHJhdyBleGVjdXRpb25cbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHQgY2Fycnlpbmcgc3R1YiBhbmQgaWRlbnRpdHlcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRmFicmljU3RhdGVtZW50XG4gKiBAZXhhbXBsZVxuICogY29uc3Qgc3RtdCA9IG5ldyBGYWJyaWNTdGF0ZW1lbnQ8TXlNb2RlbCwgTXlNb2RlbFtdPihhZGFwdGVyLCBjdHgpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RtdC5yYXc8TXlNb2RlbFtdPih7IHNlbGVjdG9yOiB7IHR5cGU6ICdNeU1vZGVsJyB9IH0pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgU3RhdGVtZW50XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgTGVkZ2VyXG4gKiAgIEFwcC0+PlN0YXRlbWVudDogcmF3KHsgc2VsZWN0b3IgfSlcbiAqICAgU3RhdGVtZW50LT4+QWRhcHRlcjogYWRhcHRlci5yYXcobWFuZ28sIHRydWUsIGN0eClcbiAqICAgQWRhcHRlci0+PkxlZGdlcjogRXZhbHVhdGUgcXVlcnlcbiAqICAgQWRhcHRlci0tPj5TdGF0ZW1lbnQ6IHJvd3NcbiAqICAgU3RhdGVtZW50LS0+PkFwcDogbW9kZWxzXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsLCBSPiBleHRlbmRzIENvdWNoREJTdGF0ZW1lbnQ8XG4gIE0sXG4gIENvdWNoREJBZGFwdGVyPGFueSwgdm9pZCwgRmFicmljQ29udHJhY3RDb250ZXh0PixcbiAgUlxuPiB7XG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXI6IENvdWNoREJBZGFwdGVyPGFueSwgdm9pZCwgRmFicmljQ29udHJhY3RDb250ZXh0Pikge1xuICAgIHN1cGVyKGFkYXB0ZXIpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGV4ZWN1dGlvblByZWZpeChcbiAgICBtZXRob2Q6IGFueSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApIHtcbiAgICBjb25zdCBuZXdBcmdzID0gYXJncy5maWx0ZXIoXG4gICAgICBCb29sZWFuXG4gICAgKSBhcyBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PjtcbiAgICBpZiAoYXJncy5sZW5ndGggIT09IG5ld0FyZ3MubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBSZWNlaXZlZCBhbiB1bmRlZmluZWQgaW4gdGhlIHBhZ2luYXRvciBmb3IgJHttZXRob2R9OiAke2FyZ3N9YFxuICAgICAgKTtcbiAgICByZXR1cm4gc3VwZXIuZXhlY3V0aW9uUHJlZml4KG1ldGhvZCwgLi4uYXJncyk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyByYXc8Uj4oXG4gICAgcmF3SW5wdXQ6IE1hbmdvUXVlcnksXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yYXcpO1xuXG4gICAgY29uc3QgcmVzdWx0czogYW55W10gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KHJhd0lucHV0LCB0cnVlLCBjdHgpO1xuXG4gICAgY29uc3QgcGtBdHRyID0gTW9kZWwucGsodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS5nZXQoXG4gICAgICB0aGlzLmZyb21TZWxlY3RvcixcbiAgICAgIE1ldGFkYXRhLmtleShEQktleXMuSUQsIHBrQXR0ciBhcyBzdHJpbmcpXG4gICAgKT8udHlwZTtcblxuICAgIGlmICghdGhpcy5zZWxlY3RTZWxlY3RvcilcbiAgICAgIHJldHVybiByZXN1bHRzLm1hcCgocikgPT4gdGhpcy5wcm9jZXNzUmVjb3JkKHIsIHBrQXR0ciwgdHlwZSwgY3R4KSkgYXMgUjtcbiAgICByZXR1cm4gcmVzdWx0cyBhcyBSO1xuICB9XG5cbiAgb3ZlcnJpZGUgYnVpbGQoKTogTWFuZ29RdWVyeSB7XG4gICAgY29uc3Qgc2VsZWN0b3JzOiBNYW5nb1NlbGVjdG9yID0ge307XG4gICAgc2VsZWN0b3JzW0NvdWNoREJLZXlzLlRBQkxFXSA9IHt9O1xuICAgIHNlbGVjdG9yc1tDb3VjaERCS2V5cy5UQUJMRV0gPSBNb2RlbC50YWJsZU5hbWUodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IHF1ZXJ5OiBNYW5nb1F1ZXJ5ID0geyBzZWxlY3Rvcjogc2VsZWN0b3JzIH07XG4gICAgaWYgKHRoaXMuc2VsZWN0U2VsZWN0b3IpIHF1ZXJ5LmZpZWxkcyA9IHRoaXMuc2VsZWN0U2VsZWN0b3IgYXMgc3RyaW5nW107XG5cbiAgICBpZiAodGhpcy53aGVyZUNvbmRpdGlvbikge1xuICAgICAgY29uc3QgY29uZGl0aW9uOiBNYW5nb1NlbGVjdG9yID0gdGhpcy5wYXJzZUNvbmRpdGlvbihcbiAgICAgICAgQ29uZGl0aW9uLmFuZChcbiAgICAgICAgICB0aGlzLndoZXJlQ29uZGl0aW9uLFxuICAgICAgICAgIENvbmRpdGlvbi5hdHRyaWJ1dGU8TT4oQ291Y2hEQktleXMuVEFCTEUgYXMga2V5b2YgTSkuZXEoXG4gICAgICAgICAgICBxdWVyeS5zZWxlY3RvcltDb3VjaERCS2V5cy5UQUJMRV1cbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc2VsZWN0b3I7XG4gICAgICBjb25zdCBzZWxlY3RvcktleXMgPSBPYmplY3Qua2V5cyhjb25kaXRpb24pIGFzIE1hbmdvT3BlcmF0b3JbXTtcbiAgICAgIGlmIChcbiAgICAgICAgc2VsZWN0b3JLZXlzLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICBPYmplY3QudmFsdWVzKENvdWNoREJHcm91cE9wZXJhdG9yKS5pbmRleE9mKHNlbGVjdG9yS2V5c1swXSkgIT09IC0xXG4gICAgICApXG4gICAgICAgIHN3aXRjaCAoc2VsZWN0b3JLZXlzWzBdKSB7XG4gICAgICAgICAgY2FzZSBDb3VjaERCR3JvdXBPcGVyYXRvci5BTkQ6XG4gICAgICAgICAgICBjb25kaXRpb25bQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EXSA9IFtcbiAgICAgICAgICAgICAgLi4uT2JqZWN0LnZhbHVlcyhcbiAgICAgICAgICAgICAgICBjb25kaXRpb25bQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EXSBhcyBNYW5nb1NlbGVjdG9yXG4gICAgICAgICAgICAgICkucmVkdWNlKChhY2N1bTogTWFuZ29TZWxlY3RvcltdLCB2YWw6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyh2YWwpO1xuICAgICAgICAgICAgICAgIGlmIChrZXlzLmxlbmd0aCAhPT0gMSlcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJUb28gbWFueSBrZXlzIGluIHF1ZXJ5IHNlbGVjdG9yLiBzaG91bGQgYmUgb25lXCJcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgayA9IGtleXNbMF07XG4gICAgICAgICAgICAgICAgaWYgKGsgPT09IENvdWNoREJHcm91cE9wZXJhdG9yLkFORClcbiAgICAgICAgICAgICAgICAgIGFjY3VtLnB1c2goLi4uKHZhbFtrXSBhcyBhbnlbXSkpO1xuICAgICAgICAgICAgICAgIGVsc2UgYWNjdW0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgICAgICAgfSwgW10pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yID0gY29uZGl0aW9uO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBDb3VjaERCR3JvdXBPcGVyYXRvci5PUjoge1xuICAgICAgICAgICAgY29uc3QgczogUmVjb3JkPGFueSwgYW55PiA9IHt9O1xuICAgICAgICAgICAgc1tDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdID0gW1xuICAgICAgICAgICAgICBjb25kaXRpb24sXG4gICAgICAgICAgICAgIC4uLk9iamVjdC5lbnRyaWVzKHF1ZXJ5LnNlbGVjdG9yKS5tYXAoKFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxhbnksIGFueT4gPSB7fTtcbiAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBxdWVyeS5zZWxlY3RvciA9IHM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgc2hvdWxkIGJlIGltcG9zc2libGVcIik7XG4gICAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBPYmplY3QuZW50cmllcyhjb25kaXRpb24pLmZvckVhY2goKFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgICBpZiAocXVlcnkuc2VsZWN0b3Jba2V5XSlcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgYEEgJHtrZXl9IHF1ZXJ5IHBhcmFtIGlzIGFib3V0IHRvIGJlIG92ZXJyaWRkZW46ICR7cXVlcnkuc2VsZWN0b3Jba2V5XX0gYnkgJHt2YWx9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBxdWVyeS5zZWxlY3RvcltrZXldID0gdmFsO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcmRlckJ5U2VsZWN0b3IpIHtcbiAgICAgIHF1ZXJ5LnNvcnQgPSBxdWVyeS5zb3J0IHx8IFtdO1xuICAgICAgcXVlcnkuc2VsZWN0b3IgPSBxdWVyeS5zZWxlY3RvciB8fCAoe30gYXMgTWFuZ29TZWxlY3Rvcik7XG4gICAgICBjb25zdCBbc2VsZWN0b3IsIHZhbHVlXSA9IHRoaXMub3JkZXJCeVNlbGVjdG9yIGFzIFtcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBPcmRlckRpcmVjdGlvbixcbiAgICAgIF07XG4gICAgICBjb25zdCByZWM6IGFueSA9IHt9O1xuICAgICAgcmVjW3NlbGVjdG9yXSA9IHZhbHVlO1xuICAgICAgKHF1ZXJ5LnNvcnQgYXMgYW55W10pLnB1c2gocmVjIGFzIGFueSk7XG4gICAgICBpZiAoIXF1ZXJ5LnNlbGVjdG9yW3NlbGVjdG9yXSkge1xuICAgICAgICBxdWVyeS5zZWxlY3RvcltzZWxlY3Rvcl0gPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgICAocXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdIGFzIE1hbmdvU2VsZWN0b3IpW0NvdWNoREJPcGVyYXRvci5CSUdHRVJdID1cbiAgICAgICAgICBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmxpbWl0U2VsZWN0b3IpIHF1ZXJ5LmxpbWl0ID0gdGhpcy5saW1pdFNlbGVjdG9yO1xuXG4gICAgaWYgKHRoaXMub2Zmc2V0U2VsZWN0b3IpIHF1ZXJ5LnNraXAgPSB0aGlzLm9mZnNldFNlbGVjdG9yO1xuXG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBDb25mbGljdEVycm9yLFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBPcGVyYXRpb25LZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7XG4gIEFkYXB0ZXIsXG4gIENvbnRleHQsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgU2VxdWVuY2UsXG4gIFNlcXVlbmNlTW9kZWwsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgU2VyaWFsLFxuICBVbnN1cHBvcnRlZEVycm9yLFxuICBVVUlELFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IExvZ2dpbmcsIHN0eWxlIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIHNlcXVlbmNlIGdlbmVyYXRpb25cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgZnJhbWV3b3JrIGZvciBnZW5lcmF0aW5nIHNlcXVlbnRpYWwgdmFsdWVzIChsaWtlIHByaW1hcnkga2V5cykgaW4gdGhlIHBlcnNpc3RlbmNlIGxheWVyLlxuICogSW1wbGVtZW50YXRpb25zIG9mIHRoaXMgY2xhc3MgaGFuZGxlIHRoZSBzcGVjaWZpY3Mgb2YgaG93IHNlcXVlbmNlcyBhcmUgc3RvcmVkIGFuZCBpbmNyZW1lbnRlZCBpbiBkaWZmZXJlbnRcbiAqIGRhdGFiYXNlIHN5c3RlbXMuXG4gKiBAcGFyYW0ge1NlcXVlbmNlT3B0aW9uc30gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIHNlcXVlbmNlIGdlbmVyYXRvclxuICogQGNsYXNzIFNlcXVlbmNlXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gRXhhbXBsZSBpbXBsZW1lbnRhdGlvbiBmb3IgYSBzcGVjaWZpYyBkYXRhYmFzZVxuICogY2xhc3MgUG9zdGdyZXNTZXF1ZW5jZSBleHRlbmRzIFNlcXVlbmNlIHtcbiAqICAgY29uc3RydWN0b3Iob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKSB7XG4gKiAgICAgc3VwZXIob3B0aW9ucyk7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIG5leHQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvbiB0byBnZXQgbmV4dCB2YWx1ZSBmcm9tIFBvc3RncmVTUUwgc2VxdWVuY2VcbiAqICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm9wdGlvbnMuZXhlY3V0b3IucmF3KGBTRUxFQ1QgbmV4dHZhbCgnJHt0aGlzLm9wdGlvbnMubmFtZX0nKWApO1xuICogICAgIHJldHVybiBwYXJzZUludChyZXN1bHQucm93c1swXS5uZXh0dmFsKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgY3VycmVudCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uIHRvIGdldCBjdXJyZW50IHZhbHVlIGZyb20gUG9zdGdyZVNRTCBzZXF1ZW5jZVxuICogICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMub3B0aW9ucy5leGVjdXRvci5yYXcoYFNFTEVDVCBjdXJydmFsKCcke3RoaXMub3B0aW9ucy5uYW1lfScpYCk7XG4gKiAgICAgcmV0dXJuIHBhcnNlSW50KHJlc3VsdC5yb3dzWzBdLmN1cnJ2YWwpO1xuICogICB9XG4gKlxuICogICBhc3luYyByYW5nZShjb3VudDogbnVtYmVyKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uIHRvIGdldCBhIHJhbmdlIG9mIHZhbHVlc1xuICogICAgIGNvbnN0IHZhbHVlczogbnVtYmVyW10gPSBbXTtcbiAqICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAqICAgICAgIHZhbHVlcy5wdXNoKGF3YWl0IHRoaXMubmV4dCgpKTtcbiAqICAgICB9XG4gKiAgICAgcmV0dXJuIHZhbHVlcztcbiAqICAgfVxuICogfVxuICpcbiAqIC8vIFVzYWdlXG4gKiBjb25zdCBzZXF1ZW5jZSA9IG5ldyBQb3N0Z3Jlc1NlcXVlbmNlKHtcbiAqICAgbmFtZTogJ3VzZXJfaWRfc2VxJyxcbiAqICAgZXhlY3V0b3I6IGRiRXhlY3V0b3JcbiAqIH0pO1xuICpcbiAqIGNvbnN0IG5leHRJZCA9IGF3YWl0IHNlcXVlbmNlLm5leHQoKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RTZXF1ZW5jZSBleHRlbmRzIFNlcXVlbmNlIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IHNlcXVlbmNlIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IFByb3RlY3RlZCBjb25zdHJ1Y3RvciB0aGF0IGluaXRpYWxpemVzIHRoZSBzZXF1ZW5jZSB3aXRoIHRoZSBwcm92aWRlZCBvcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMsIGFkYXB0ZXI6IEFkYXB0ZXI8YW55LCBhbnksIGFueT4pIHtcbiAgICBzdXBlcihvcHRpb25zLCBhZGFwdGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBzZXF1ZW5jZVxuICAgKiBAc3VtbWFyeSBHZXRzIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBzZXF1ZW5jZSBmcm9tIHN0b3JhZ2UuIElmIHRoZSBzZXF1ZW5jZVxuICAgKiBkb2Vzbid0IGV4aXN0IHlldCwgaXQgcmV0dXJucyB0aGUgY29uZmlndXJlZCBzdGFydGluZyB2YWx1ZS5cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgY3VycmVudCBzZXF1ZW5jZSB2YWx1ZVxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgY3VycmVudChcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8YW55PlxuICApOiBQcm9taXNlPHN0cmluZyB8IG51bWJlciB8IGJpZ2ludD4ge1xuICAgIGNvbnN0IHsgY3R4LCBsb2cgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KGFyZ3MsIE9wZXJhdGlvbktleXMuUkVBRCwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLmN1cnJlbnQpO1xuICAgIGNvbnN0IHsgbmFtZSwgc3RhcnRXaXRoIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNlcXVlbmNlOiBTZXF1ZW5jZU1vZGVsID0gYXdhaXQgdGhpcy5yZXBvLnJlYWQobmFtZSBhcyBzdHJpbmcsIGN0eCk7XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZShzZXF1ZW5jZS5jdXJyZW50IGFzIHN0cmluZyB8IG51bWJlcik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXJyb3IpIHtcbiAgICAgICAgbGV0IGNhY2hlZEN1cnJlbnQ6IGFueTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsb2cuZGVidWcoXG4gICAgICAgICAgICBgVHJ5aW5nIHRvIHJlc29sdmUgY3VycmVudCBzZXF1ZW5jZSAke25hbWV9IHZhbHVlIGZyb20gY29udGV4dGBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNhY2hlZEN1cnJlbnQgPSBjdHguZ2V0KG5hbWUpO1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgICAgIGBSZXRyaWV2ZWQgY2FjaGVkIGN1cnJlbnQgdmFsdWUgZm9yIHNlcXVlbmNlICR7bmFtZX06ICR7Y2FjaGVkQ3VycmVudH1gXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICBsb2cuaW5mbyhgTm8gY2FjaGVkIHZhbHVlIGZvciBzZXF1ZW5jZSAke25hbWV9IGluIGNvbnRleHRgKTtcbiAgICAgICAgICBjYWNoZWRDdXJyZW50ID0gc3RhcnRXaXRoO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2UoY2FjaGVkQ3VycmVudCk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBwYXJzZSBpbml0aWFsIHZhbHVlIGZvciBzZXF1ZW5jZSAke3N0YXJ0V2l0aH06ICR7ZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmV0cmlldmUgY3VycmVudCB2YWx1ZSBmb3Igc2VxdWVuY2UgJHtuYW1lfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbmNyZW1lbnRzIHRoZSBzZXF1ZW5jZSB2YWx1ZVxuICAgKiBAc3VtbWFyeSBJbmNyZWFzZXMgdGhlIGN1cnJlbnQgc2VxdWVuY2UgdmFsdWUgYnkgdGhlIHNwZWNpZmllZCBhbW91bnQgYW5kIHBlcnNpc3RzXG4gICAqIHRoZSBuZXcgdmFsdWUgdG8gc3RvcmFnZS4gVGhpcyBtZXRob2QgaGFuZGxlcyBib3RoIG51bWVyaWMgYW5kIEJpZ0ludCBzZXF1ZW5jZSB0eXBlcy5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnR9IGN1cnJlbnQgLSBUaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgc2VxdWVuY2VcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtjb3VudF0gLSBPcHRpb25hbCBhbW91bnQgdG8gaW5jcmVtZW50IGJ5LCBkZWZhdWx0cyB0byB0aGUgc2VxdWVuY2UncyBpbmNyZW1lbnRCeSB2YWx1ZVxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgc2VxdWVuY2UgdmFsdWUgYWZ0ZXIgaW5jcmVtZW50aW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgaW5jcmVtZW50KFxuICAgIGNvdW50OiBudW1iZXIgfCB1bmRlZmluZWQsXG4gICAgY3R4OiBDb250ZXh0PGFueT5cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+IHtcbiAgICBjb25zdCBsb2cgPSBjdHgubG9nZ2VyLmZvcih0aGlzLmluY3JlbWVudCk7XG4gICAgY29uc3QgeyB0eXBlLCBpbmNyZW1lbnRCeSwgbmFtZSB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGlmICghbmFtZSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJTZXF1ZW5jZSBuYW1lIGlzIHJlcXVpcmVkXCIpO1xuICAgIGxvZy5pbmZvKGBPYnRhaW5pbmcgc2VxdWVuY2UgbG9jayBmb3Igc2VxdWVuY2UgJHtuYW1lfWApO1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdFNlcXVlbmNlLmxvY2suZXhlY3V0ZShhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0b0luY3JlbWVudEJ5ID0gY291bnQgfHwgaW5jcmVtZW50Qnk7XG4gICAgICBpZiAodG9JbmNyZW1lbnRCeSAlIGluY3JlbWVudEJ5ICE9PSAwKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgVmFsdWUgdG8gaW5jcmVtZW50IGRvZXMgbm90IGNvbnNpZGVyIHRoZSBpbmNyZW1lbnRCeSBzZXR0aW5nOiAke2luY3JlbWVudEJ5fWBcbiAgICAgICAgKTtcbiAgICAgIGNvbnN0IHR5cGVOYW1lID1cbiAgICAgICAgdHlwZW9mIHR5cGUgPT09IFwiZnVuY3Rpb25cIiAmJiAodHlwZSBhcyBhbnkpPy5uYW1lXG4gICAgICAgICAgPyAodHlwZSBhcyBhbnkpLm5hbWVcbiAgICAgICAgICA6IHR5cGU7XG4gICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBhd2FpdCB0aGlzLmN1cnJlbnQoY3R4KTtcblxuICAgICAgYXN5bmMgZnVuY3Rpb24gcmV0dXJuQW5kQ2FjaGUoXG4gICAgICAgIHJlczogU2VxdWVuY2VNb2RlbCB8IFByb21pc2U8U2VxdWVuY2VNb2RlbD5cbiAgICAgICkge1xuICAgICAgICBpZiAocmVzIGluc3RhbmNlb2YgUHJvbWlzZSkgcmVzID0gYXdhaXQgcmVzO1xuICAgICAgICBsb2dcbiAgICAgICAgICAuZm9yKHJldHVybkFuZENhY2hlKVxuICAgICAgICAgIC5pbmZvKGBTdG9yaW5nIG5ldyAke25hbWV9IHNlcSB2YWx1ZSBpbiBjYWNoZTogJHtyZXMuY3VycmVudH1gKTtcbiAgICAgICAgY3R4LmNhY2hlLnB1dChuYW1lIGFzIHN0cmluZywgcmVzLmN1cnJlbnQpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwZXJmb3JtVXBzZXJ0ID0gYXN5bmMgKFxuICAgICAgICBuZXh0OiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgICAgICk6IFByb21pc2U8U2VxdWVuY2VNb2RlbD4gPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBhd2FpdCByZXR1cm5BbmRDYWNoZShcbiAgICAgICAgICAgIHRoaXMucmVwby51cGRhdGUoXG4gICAgICAgICAgICAgIG5ldyBTZXF1ZW5jZU1vZGVsKHsgaWQ6IG5hbWUsIGN1cnJlbnQ6IG5leHQgfSksXG4gICAgICAgICAgICAgIGN0eFxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgTm90Rm91bmRFcnJvcikge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFxuICAgICAgICAgICAgICBgU2VxdWVuY2UgY3JlYXRlICR7bmFtZX0gY3VycmVudD0ke2N1cnJlbnRWYWx1ZSBhcyBhbnl9IG5leHQ9JHtuZXh0IGFzIGFueX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJldHVybkFuZENhY2hlKFxuICAgICAgICAgICAgICB0aGlzLnJlcG8uY3JlYXRlKFxuICAgICAgICAgICAgICAgIG5ldyBTZXF1ZW5jZU1vZGVsKHsgaWQ6IG5hbWUsIGN1cnJlbnQ6IG5leHQgfSksXG4gICAgICAgICAgICAgICAgY3R4XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGluY3JlbWVudFNlcmlhbCA9IChcbiAgICAgICAgYmFzZTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICAgICApOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQgPT4ge1xuICAgICAgICBzd2l0Y2ggKHR5cGVOYW1lKSB7XG4gICAgICAgICAgY2FzZSBOdW1iZXIubmFtZTpcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5wYXJzZShiYXNlKSBhcyBudW1iZXIpICsgdG9JbmNyZW1lbnRCeTtcbiAgICAgICAgICBjYXNlIEJpZ0ludC5uYW1lOlxuICAgICAgICAgICAgcmV0dXJuICh0aGlzLnBhcnNlKGJhc2UpIGFzIGJpZ2ludCkgKyBCaWdJbnQodG9JbmNyZW1lbnRCeSk7XG4gICAgICAgICAgY2FzZSBTdHJpbmcubmFtZTpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcnNlKGJhc2UpO1xuICAgICAgICAgIGNhc2UgXCJzZXJpYWxcIjpcbiAgICAgICAgICAgIHJldHVybiBTZXJpYWwuaW5zdGFuY2UuZ2VuZXJhdGUoYmFzZSBhcyBzdHJpbmcpO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIlNob3VsZCBuZXZlciBoYXBwZW5cIik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlTmFtZSA9PT0gXCJ1dWlkXCIpIHtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICBjb25zdCBuZXh0ID0gVVVJRC5pbnN0YW5jZS5nZW5lcmF0ZShjdXJyZW50VmFsdWUgYXMgc3RyaW5nKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGVyZm9ybVVwc2VydChuZXh0KTtcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgICAgICAgYFNlcXVlbmNlIHV1aWQgaW5jcmVtZW50ICR7bmFtZX0gY3VycmVudD0ke2N1cnJlbnRWYWx1ZSBhcyBhbnl9IG5leHQ9JHtuZXh0IGFzIGFueX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5jdXJyZW50IGFzIHN0cmluZyB8IG51bWJlciB8IGJpZ2ludDtcbiAgICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIENvbmZsaWN0RXJyb3IpIGNvbnRpbnVlO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV4dCA9IGluY3JlbWVudFNlcmlhbChjdXJyZW50VmFsdWUpO1xuICAgICAgY29uc3Qgc2VxID0gYXdhaXQgcGVyZm9ybVVwc2VydChuZXh0KTtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFNlcXVlbmNlLmluY3JlbWVudCAke25hbWV9IGN1cnJlbnQ9JHtjdXJyZW50VmFsdWUgYXMgYW55fSBuZXh0PSR7bmV4dCBhcyBhbnl9YFxuICAgICAgKTtcbiAgICAgIHJldHVybiBzZXEuY3VycmVudCBhcyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gICAgfSwgbmFtZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEpTT05TZXJpYWxpemVyLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuZXhwb3J0IGNsYXNzIFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4+IGV4dGVuZHMgSlNPTlNlcmlhbGl6ZXI8TT4ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBvdmVycmlkZSBkZXNlcmlhbGl6ZShzdHI6IHN0cmluZywgdGFibGVOYW1lPzogc3RyaW5nKTogTSB7XG4gICAgY29uc3QgZGVzZXJpYWxpemF0aW9uID0gSlNPTi5wYXJzZShzdHIpO1xuICAgIC8vIGNvbnN0IGNsYXNzTmFtZSA9IHRhYmxlTmFtZTtcbiAgICAvLyBpZiAoIWNsYXNzTmFtZSlcbiAgICAvLyAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBmaW5kIGNsYXNzIHJlZmVyZW5jZSBpbiBzZXJpYWxpemVkIG1vZGVsXCIpO1xuXG4gICAgLy8gLy8gdGhpcyB3aWxsIHJldHVybiB1bmRlZmluZWQgdmFsdWVzXG4gICAgLy8gY29uc3QgbW9kZWw6IE0gPSBNb2RlbC5idWlsZChkZXNlcmlhbGl6YXRpb24sIGNsYXNzTmFtZSkgYXMgdW5rbm93biBhcyBNO1xuXG4gICAgLy8gLy8gUG9wdWxhdGUgTW9kZWxcbiAgICAvLyBjb25zdCBwcm9jZXNzZWREZXNlYWxpemF0aW9uID0gT2JqZWN0LmtleXMobW9kZWwpLnJlZHVjZShcbiAgICAvLyAgIChhY2N1bTogTSwga2V5KSA9PiB7XG4gICAgLy8gICAgIChhY2N1bSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtrZXldID1cbiAgICAvLyAgICAgICBkZXNlcmlhbGl6YXRpb25bUmVwb3NpdG9yeS5jb2x1bW4oYWNjdW0sIGtleSldO1xuICAgIC8vICAgICByZXR1cm4gYWNjdW07XG4gICAgLy8gICB9LFxuICAgIC8vICAgbW9kZWxcbiAgICAvLyApO1xuXG4gICAgLy8gY29uc3QgcmVzdWx0ID0gTW9kZWwuYnVpbGQoXG4gICAgLy8gICBwcm9jZXNzZWREZXNlYWxpemF0aW9uLFxuICAgIC8vICAgY2xhc3NOYW1lXG4gICAgLy8gKSBhcyB1bmtub3duIGFzIE07XG5cbiAgICAvLyByZXR1cm4gcmVzdWx0O1xuICAgIHJldHVybiBkZXNlcmlhbGl6YXRpb247XG4gIH1cblxuICBvdmVycmlkZSBzZXJpYWxpemUobW9kZWw6IE0sIHB1dEFuY2hvciA9IHRydWUpOiBzdHJpbmcge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3Qgc3RyaW5naWZ5ID0gcmVxdWlyZShcImpzb24tc3RyaW5naWZ5LWRldGVybWluaXN0aWNcIik7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBzb3J0S2V5c1JlY3Vyc2l2ZSA9IHJlcXVpcmUoXCJzb3J0LWtleXMtcmVjdXJzaXZlXCIpO1xuICAgIGNvbnN0IHByZVNlcmlhbGl6YXRpb24gPSB0aGlzLnByZVNlcmlhbGl6ZShtb2RlbCwgcHV0QW5jaG9yKTtcbiAgICByZXR1cm4gc3RyaW5naWZ5KHNvcnRLZXlzUmVjdXJzaXZlKHByZVNlcmlhbGl6YXRpb24pKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBwcmVTZXJpYWxpemUobW9kZWw6IE0sIHB1dEFuY2hvcjogYm9vbGVhbiA9IHRydWUpIHtcbiAgICAvLyBUT0RPOiBuZXN0ZWQgcHJlc2VyaWFsaXphdGlvbiAoc28gaW5jcmVhc2UgcGVyZm9ybWFuY2Ugd2hlbiBkZXNlcmlhbGl6aW5nKVxuICAgIC8vIFRPRE86IFZlcmlmeSB3aHkgdGhlcmUgaXMgbm8gbWV0YWRhdGFcbiAgICBjb25zdCB0b1NlcmlhbGl6ZTogUmVjb3JkPHN0cmluZywgYW55PiA9IE9iamVjdC5hc3NpZ24oe30sIG1vZGVsKTtcbiAgICBsZXQgbWV0YWRhdGE7XG4gICAgdHJ5IHtcbiAgICAgIG1ldGFkYXRhID0gTWV0YWRhdGEubW9kZWxOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgbWV0YWRhdGEgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGlmIChwdXRBbmNob3IpXG4gICAgICB0b1NlcmlhbGl6ZVtNb2RlbEtleXMuQU5DSE9SXSA9IG1ldGFkYXRhIHx8IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG5cbiAgICBmdW5jdGlvbiBwcmVTZXJpYWxpemUoXG4gICAgICB0aGlzOiBTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxhbnk+LFxuICAgICAgb2JqOiBhbnlcbiAgICApOiBhbnkge1xuICAgICAgaWYgKHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIpIHJldHVybiBvYmo7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSByZXR1cm4gb2JqLm1hcChwcmVTZXJpYWxpemUpO1xuICAgICAgcmV0dXJuIHRoaXMucHJlU2VyaWFsaXplKG9iaik7XG4gICAgfVxuICAgIE1vZGVsLnJlbGF0aW9ucyhtb2RlbCkuZm9yRWFjaCgocikgPT4ge1xuICAgICAgdG9TZXJpYWxpemVbcl0gPSBwcmVTZXJpYWxpemUuY2FsbCh0aGlzLCB0b1NlcmlhbGl6ZVtyXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRvU2VyaWFsaXplO1xuICB9XG59XG4iLCJpbXBvcnQgeyBNYXliZUNvbnRleHR1YWxBcmcsIFBhZ2luZ0Vycm9yLCBTZXF1ZW5jZSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSBcIi4vQ29udHJhY3RBZGFwdGVyXCI7XG5pbXBvcnQgeyBDb3VjaERCUGFnaW5hdG9yLCBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQYWdpbmF0b3IgZm9yIENvdWNoREIgcXVlcnkgcmVzdWx0c1xuICogQHN1bW1hcnkgSW1wbGVtZW50cyBwYWdpbmF0aW9uIGZvciBDb3VjaERCIHF1ZXJpZXMgdXNpbmcgYm9va21hcmtzIGZvciBlZmZpY2llbnQgbmF2aWdhdGlvbiB0aHJvdWdoIHJlc3VsdCBzZXRzXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIHRoYXQgZXh0ZW5kcyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmVzdWx0IHR5cGVcbiAqIEBwYXJhbSB7RmFicmljQ288YW55LCBhbnksIGFueT59IGFkYXB0ZXIgLSBUaGUgQ291Y2hEQiBhZGFwdGVyXG4gKiBAcGFyYW0ge01hbmdvUXVlcnl9IHF1ZXJ5IC0gVGhlIE1hbmdvIHF1ZXJ5IHRvIHBhZ2luYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZSAtIFRoZSBwYWdlIHNpemVcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gKiBAY2xhc3MgQ291Y2hEQlBhZ2luYXRvclxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgb2YgdXNpbmcgQ291Y2hEQlBhZ2luYXRvclxuICogY29uc3QgYWRhcHRlciA9IG5ldyBNeUNvdWNoREJBZGFwdGVyKHNjb3BlKTtcbiAqIGNvbnN0IHF1ZXJ5ID0geyBzZWxlY3RvcjogeyB0eXBlOiBcInVzZXJcIiB9IH07XG4gKiBjb25zdCBwYWdpbmF0b3IgPSBuZXcgQ291Y2hEQlBhZ2luYXRvcihhZGFwdGVyLCBxdWVyeSwgMTAsIFVzZXIpO1xuICpcbiAqIC8vIEdldCB0aGUgZmlyc3QgcGFnZVxuICogY29uc3QgcGFnZTEgPSBhd2FpdCBwYWdpbmF0b3IucGFnZSgxKTtcbiAqXG4gKiAvLyBHZXQgdGhlIG5leHQgcGFnZVxuICogY29uc3QgcGFnZTIgPSBhd2FpdCBwYWdpbmF0b3IucGFnZSgyKTtcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0UGFnaW5hdG9yPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4+IGV4dGVuZHMgQ291Y2hEQlBhZ2luYXRvcjxNPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBDb3VjaERCUGFnaW5hdG9yIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgcGFnaW5hdG9yIGZvciBDb3VjaERCIHF1ZXJ5IHJlc3VsdHNcbiAgICogQHBhcmFtIHtDb3VjaERCQWRhcHRlcjxhbnksIGFueSwgYW55LCBhbnk+fSBhZGFwdGVyIC0gVGhlIENvdWNoREIgYWRhcHRlclxuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHF1ZXJ5IC0gVGhlIE1hbmdvIHF1ZXJ5IHRvIHBhZ2luYXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIC0gVGhlIHBhZ2Ugc2l6ZVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgYWRhcHRlcjogRmFicmljQ29udHJhY3RBZGFwdGVyLFxuICAgIHF1ZXJ5OiBNYW5nb1F1ZXJ5LFxuICAgIHNpemU6IG51bWJlcixcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT5cbiAgKSB7XG4gICAgc3VwZXIoYWRhcHRlciwgcXVlcnksIHNpemUsIGNsYXp6KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYSBxdWVyeSBmb3IgcGFnaW5hdGlvblxuICAgKiBAc3VtbWFyeSBNb2RpZmllcyB0aGUgcmF3IHF1ZXJ5IHRvIGluY2x1ZGUgcGFnaW5hdGlvbiBwYXJhbWV0ZXJzXG4gICAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcmF3U3RhdGVtZW50IC0gVGhlIG9yaWdpbmFsIE1hbmdvIHF1ZXJ5XG4gICAqIEByZXR1cm4ge01hbmdvUXVlcnl9IFRoZSBwcmVwYXJlZCBxdWVyeSB3aXRoIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHByZXBhcmUocmF3U3RhdGVtZW50OiBNYW5nb1F1ZXJ5KTogTWFuZ29RdWVyeSB7XG4gICAgY29uc3QgcXVlcnk6IE1hbmdvUXVlcnkgPSBPYmplY3QuYXNzaWduKHt9LCByYXdTdGF0ZW1lbnQpO1xuICAgIGlmIChxdWVyeS5saW1pdCkgdGhpcy5saW1pdCA9IHF1ZXJ5LmxpbWl0O1xuXG4gICAgcXVlcnkubGltaXQgPSB0aGlzLnNpemU7XG5cbiAgICByZXR1cm4gcXVlcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHNwZWNpZmljIHBhZ2Ugb2YgcmVzdWx0c1xuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgcXVlcnkgd2l0aCBwYWdpbmF0aW9uIGFuZCBwcm9jZXNzZXMgdGhlIHJlc3VsdHNcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtwYWdlPTFdIC0gVGhlIHBhZ2UgbnVtYmVyIHRvIHJldHJpZXZlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UltdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgcmVzdWx0c1xuICAgKiBAdGhyb3dzIHtQYWdpbmdFcnJvcn0gSWYgdHJ5aW5nIHRvIGFjY2VzcyBhIHBhZ2Ugb3RoZXIgdGhhbiB0aGUgZmlyc3Qgd2l0aG91dCBhIGJvb2ttYXJrLCBvciBpZiBubyBjbGFzcyBpcyBkZWZpbmVkXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IENvdWNoREJQYWdpbmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgQ291Y2hEQlxuICAgKlxuICAgKiAgIENsaWVudC0+PkNvdWNoREJQYWdpbmF0b3I6IHBhZ2UocGFnZU51bWJlcilcbiAgICogICBOb3RlIG92ZXIgQ291Y2hEQlBhZ2luYXRvcjogQ2xvbmUgc3RhdGVtZW50XG4gICAqICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IHZhbGlkYXRlUGFnZShwYWdlKVxuICAgKlxuICAgKiAgIGFsdCBwYWdlICE9PSAxXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQ2hlY2sgYm9va21hcmtcbiAgICogICAgIGFsdCBObyBib29rbWFya1xuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLS0+PkNsaWVudDogVGhyb3cgUGFnaW5nRXJyb3JcbiAgICogICAgIGVsc2UgSGFzIGJvb2ttYXJrXG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBBZGQgYm9va21hcmsgdG8gc3RhdGVtZW50XG4gICAqICAgICBlbmRcbiAgICogICBlbmRcbiAgICpcbiAgICogICBDb3VjaERCUGFnaW5hdG9yLT4+QWRhcHRlcjogcmF3KHN0YXRlbWVudCwgZmFsc2UpXG4gICAqICAgQWRhcHRlci0+PkNvdWNoREI6IEV4ZWN1dGUgcXVlcnlcbiAgICogICBDb3VjaERCLS0+PkFkYXB0ZXI6IFJldHVybiByZXN1bHRzXG4gICAqICAgQWRhcHRlci0tPj5Db3VjaERCUGFnaW5hdG9yOiBSZXR1cm4gTWFuZ29SZXNwb25zZVxuICAgKlxuICAgKiAgIE5vdGUgb3ZlciBDb3VjaERCUGFnaW5hdG9yOiBQcm9jZXNzIHJlc3VsdHNcbiAgICpcbiAgICogICBhbHQgSGFzIHdhcm5pbmdcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBMb2cgd2FybmluZ1xuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBDaGVjayBmb3IgY2xhenpcbiAgICpcbiAgICogICBhbHQgTm8gY2xhenpcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItLT4+Q2xpZW50OiBUaHJvdyBQYWdpbmdFcnJvclxuICAgKiAgIGVsc2UgSGFzIGNsYXp6XG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogRmluZCBwcmltYXJ5IGtleVxuICAgKlxuICAgKiAgICAgYWx0IEhhcyBmaWVsZHMgaW4gc3RhdGVtZW50XG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBVc2UgZG9jcyBkaXJlY3RseVxuICAgKiAgICAgZWxzZSBObyBmaWVsZHNcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFByb2Nlc3MgZWFjaCBkb2N1bWVudFxuICAgKiAgICAgICBsb29wIEZvciBlYWNoIGRvY3VtZW50XG4gICAqICAgICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IEV4dHJhY3Qgb3JpZ2luYWwgSURcbiAgICogICAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+QWRhcHRlcjogcmV2ZXJ0KGRvYywgY2xhenosIHBrRGVmLmlkLCBwYXJzZWRJZClcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbmRcbiAgICpcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBTdG9yZSBib29rbWFya1xuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFVwZGF0ZSBjdXJyZW50UGFnZVxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0tPj5DbGllbnQ6IFJldHVybiByZXN1bHRzXG4gICAqICAgZW5kXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBwYWdlKFxuICAgIHBhZ2U6IG51bWJlciA9IDEsXG4gICAgYm9va21hcms/OiBhbnksXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPGFueT5cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MsIGN0eCwgbG9nIH0gPSB0aGlzLmFkYXB0ZXJbXCJsb2dDdHhcIl0oXG4gICAgICBbYm9va21hcmssIC4uLmFyZ3NdLFxuICAgICAgdGhpcy5wYWdlXG4gICAgKTtcbiAgICBpZiAodGhpcy5pc1ByZXBhcmVkU3RhdGVtZW50KCkpXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5wYWdlUHJlcGFyZWQocGFnZSwgLi4uY3R4QXJncyk7XG4gICAgY29uc3Qgc3RhdGVtZW50ID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZW1lbnQpO1xuXG4gICAgaWYgKCF0aGlzLl9yZWNvcmRDb3VudCB8fCAhdGhpcy5fdG90YWxQYWdlcykge1xuICAgICAgdGhpcy5fdG90YWxQYWdlcyA9IHRoaXMuX3JlY29yZENvdW50ID0gMDtcbiAgICAgIGNvbnN0IGNvdW50UmVzdWx0cyA9XG4gICAgICAgIChhd2FpdCB0aGlzLmFkYXB0ZXIucmF3PE1bXSwgdHJ1ZT4oXG4gICAgICAgICAgeyAuLi5zdGF0ZW1lbnQsIGxpbWl0OiBOdW1iZXIuTUFYX1ZBTFVFIH0sXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAuLi5jdHhBcmdzXG4gICAgICAgICkpIHx8IFtdO1xuICAgICAgdGhpcy5fcmVjb3JkQ291bnQgPSBjb3VudFJlc3VsdHMubGVuZ3RoO1xuICAgICAgaWYgKHRoaXMuX3JlY29yZENvdW50ID4gMCkge1xuICAgICAgICBjb25zdCBzaXplID0gc3RhdGVtZW50Py5saW1pdCB8fCB0aGlzLnNpemU7XG4gICAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSBNYXRoLmNlaWwodGhpcy5fcmVjb3JkQ291bnQgLyBzaXplKTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucGFnZShwYWdlLCAuLi5jdHhBcmdzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcGFnZSA9IHRoaXMudmFsaWRhdGVQYWdlKHBhZ2UpO1xuICAgICAgc3RhdGVtZW50LnNraXAgPSAocGFnZSAtIDEpICogdGhpcy5zaXplO1xuICAgIH1cblxuICAgIGlmIChwYWdlICE9PSAxKSB7XG4gICAgICBpZiAoIXRoaXMuX2Jvb2ttYXJrKVxuICAgICAgICB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBib29rbWFyay4gRGlkIHlvdSBzdGFydCBpbiB0aGUgZmlyc3QgcGFnZT9cIik7XG4gICAgICBzdGF0ZW1lbnRbXCJib29rbWFya1wiXSA9IHRoaXMuX2Jvb2ttYXJrIGFzIHN0cmluZztcbiAgICB9XG4gICAgY29uc3QgcmF3UmVzdWx0ID0gKGF3YWl0IHRoaXMuYWRhcHRlci5yYXcoXG4gICAgICBzdGF0ZW1lbnQsXG4gICAgICB0cnVlLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICkpIGFzIGFueTtcblxuICAgIGNvbnN0IHsgZG9jcywgYm9va21hcms6IG5leHRCb29rbWFyaywgd2FybmluZyB9ID0gcmF3UmVzdWx0O1xuICAgIGlmICh3YXJuaW5nKSBsb2cud2Fybih3YXJuaW5nKTtcbiAgICBpZiAoIXRoaXMuY2xhenopIHRocm93IG5ldyBQYWdpbmdFcnJvcihcIk5vIHN0YXRlbWVudCB0YXJnZXQgZGVmaW5lZFwiKTtcbiAgICBjb25zdCBpZCA9IE1vZGVsLnBrKHRoaXMuY2xhenopO1xuICAgIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS5nZXQoXG4gICAgICB0aGlzLmNsYXp6LFxuICAgICAgTWV0YWRhdGEua2V5KERCS2V5cy5JRCwgaWQgYXMgc3RyaW5nKVxuICAgICk/LnR5cGU7XG4gICAgY29uc3QgcmVzdWx0cyA9XG4gICAgICBzdGF0ZW1lbnQuZmllbGRzICYmIHN0YXRlbWVudC5maWVsZHMubGVuZ3RoXG4gICAgICAgID8gcmF3UmVzdWx0IC8vIGhhcyBmaWVsZHMgbWVhbnMgaXRzIG5vdCBmdWxsIG1vZGVsXG4gICAgICAgIDogcmF3UmVzdWx0Lm1hcCgoZDogYW55KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAgICAgICAgICAgZCxcbiAgICAgICAgICAgICAgdGhpcy5jbGF6eixcbiAgICAgICAgICAgICAgU2VxdWVuY2UucGFyc2VWYWx1ZSh0eXBlLCBkW2lkXSksXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY3R4XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgIHRoaXMuX2Jvb2ttYXJrID0gbmV4dEJvb2ttYXJrO1xuICAgIHRoaXMuX2N1cnJlbnRQYWdlID0gcGFnZTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxufVxuIiwiaW1wb3J0IHsgQmFzZUVycm9yLCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBBdXRob3JpemF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbi8vIGltcG9ydCB7IE1JU1NJTkdfUFJJVkFURV9EQVRBX0VSUk9SX01FU1NBR0UgfSBmcm9tIFwiLi4vY29udHJhY3RzL3ByaXZhdGUtZGF0YVwiO1xuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGFuIG92ZXJmbG93IGVycm9yIGluIGFyaXRobWV0aWMgb3BlcmF0aW9ucyBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIE92ZXJmbG93RXJyb3JcbiAqIEBleHRlbmRzIEludGVybmFsRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBPdmVyZmxvd0Vycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIE92ZXJmbG93RXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiBiYWxhbmNlIHRvIHBlcmZvcm0gYSB0cmFuc2FjdGlvbiBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEJhbGFuY2VFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIEJhbGFuY2VFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBCYWxhbmNlRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiBiYWxhbmNlIHRvIHBlcmZvcm0gYSB0cmFuc2FjdGlvbiBpbiBTbWFydCBDb250cmFjdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEJhbGFuY2VFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIEFsbG93YW5jZUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIEFsbG93YW5jZUVycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgcmVnaXN0cmF0aW5nIG5ldyBlbnRpdGllc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgUmVnaXN0cmF0aW9uRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnQgRXJyb3JzXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpc3RyYXRpb25FcnJvciBleHRlbmRzIEF1dGhvcml6YXRpb25FcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIFJlZ2lzdHJhdGlvbkVycm9yLm5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIGFuIHVuc3VwcG9ydGVkIG9wZXJhdGlvbiBpcyBhdHRlbXB0ZWRcbiAqIEBzdW1tYXJ5IFRoaXMgZXJyb3IgaXMgdGhyb3duIHdoZW4gYW4gb3BlcmF0aW9uIGlzIHJlcXVlc3RlZCB0aGF0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIGN1cnJlbnRcbiAqIHBlcnNpc3RlbmNlIGFkYXB0ZXIgb3IgY29uZmlndXJhdGlvbi4gSXQgZXh0ZW5kcyB0aGUgQmFzZUVycm9yIGNsYXNzIGFuZCBzZXRzIGEgNTAwIHN0YXR1cyBjb2RlLlxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIGFuIEVycm9yIG9iamVjdCB0byB3cmFwXG4gKiBAY2xhc3MgVW5zdXBwb3J0ZWRFcnJvclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFRocm93aW5nIGFuIFVuc3VwcG9ydGVkRXJyb3JcbiAqIGlmICghYWRhcHRlci5zdXBwb3J0c1RyYW5zYWN0aW9ucygpKSB7XG4gKiAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKCdUcmFuc2FjdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgYnkgdGhpcyBhZGFwdGVyJyk7XG4gKiB9XG4gKlxuICogLy8gQ2F0Y2hpbmcgYW4gVW5zdXBwb3J0ZWRFcnJvclxuICogdHJ5IHtcbiAqICAgYXdhaXQgYWRhcHRlci5iZWdpblRyYW5zYWN0aW9uKCk7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBVbnN1cHBvcnRlZEVycm9yKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcignT3BlcmF0aW9uIG5vdCBzdXBwb3J0ZWQ6JywgZXJyb3IubWVzc2FnZSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIE1pc3NpbmdDb250ZXh0RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgTWlzc2luZ0NvbnRleHRFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IgPSBcIk1JU1NJTkdfUFJJVkFURV9EQVRBX0VSUk9SX01FU1NBR0VcIikge1xuICAgIHN1cGVyKFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzLm5hbWUsIG1zZywgNDAzKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYW4gZXJyb3IgdGhhdCBvY2N1cnMgd2hlbiBhIHJlcXVpcmVkIGluaXRpYWxpemF0aW9uIHN0ZXAgaXMgbm90IHBlcmZvcm1lZC5cbiAqXG4gKiBAY2xhc3MgTm90SW5pdGlhbGl6ZWRFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nIHwgRXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIGFuIEVycm9yIG9iamVjdCB0byB3cmFwLlxuICpcbiAqIEB0aHJvd3Mge05vdEluaXRpYWxpemVkRXJyb3J9IC0gVGhyb3dzIGFuIGVycm9yIHdoZW4gYSByZXF1aXJlZCBpbml0aWFsaXphdGlvbiBzdGVwIGlzIG5vdCBwZXJmb3JtZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluaXRpYWxpemUgdGhlIGFwcGxpY2F0aW9uXG4gKiBpZiAoIWlzSW5pdGlhbGl6ZWQpIHtcbiAqICAgdGhyb3cgbmV3IE5vdEluaXRpYWxpemVkRXJyb3IoJ0FwcGxpY2F0aW9uIGlzIG5vdCBpbml0aWFsaXplZCcpO1xuICogfVxuICpcbiAqIC8vIENhdGNoaW5nIGFuIE5vdEluaXRpYWxpemVkRXJyb3JcbiAqIHRyeSB7XG4gKiAgIC8vIFBlcmZvcm0gb3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgaW5pdGlhbGl6YXRpb25cbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE5vdEluaXRpYWxpemVkRXJyb3IpIHtcbiAqICAgICBjb25zb2xlLmVycm9yKCdJbml0aWFsaXphdGlvbiBlcnJvcjonLCBlcnJvci5tZXNzYWdlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBOb3RJbml0aWFsaXplZEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKE5vdEluaXRpYWxpemVkRXJyb3IubmFtZSwgbXNnLCA0MDkpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNaXNzaW5nUEtDU1MxMUxpYiBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBNaXNzaW5nUEtDU1MxMUxpYi5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBFbmRvcnNlbWVudEVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgRW5kb3JzZW1lbnRFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNdmNjUmVhZENvbmZsaWN0RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBNdmNjUmVhZENvbmZsaWN0RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGhhbnRvbVJlYWRDb25mbGljdEVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgUGhhbnRvbVJlYWRDb25mbGljdEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEVuZG9yc2VtZW50UG9saWN5RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBFbmRvcnNlbWVudFBvbGljeUVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvdWNoREJBZGFwdGVyLCBDb3VjaERCS2V5cywgTWFuZ29RdWVyeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IE1vZGVsLCBWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RDb250ZXh0IH0gZnJvbSBcIi4vQ29udHJhY3RDb250ZXh0XCI7XG5pbXBvcnQge1xuICBCYWRSZXF1ZXN0RXJyb3IsXG4gIEJhc2VFcnJvcixcbiAgQ29uZmxpY3RFcnJvcixcbiAgSW50ZXJuYWxFcnJvcixcbiAgTm90Rm91bmRFcnJvcixcbiAgb25DcmVhdGUsXG4gIG9uQ3JlYXRlVXBkYXRlLFxuICBQcmltYXJ5S2V5VHlwZSxcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7XG4gIENvbnRleHQgYXMgQ3R4LFxuICBPYmplY3QgYXMgRmFicmljT2JqZWN0LFxuICBQcm9wZXJ0eSxcbiAgUHJvcGVydHkgYXMgRmFicmljUHJvcGVydHksXG59IGZyb20gXCJmYWJyaWMtY29udHJhY3QtYXBpXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7XG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUmVsYXRpb25zTWV0YWRhdGEsXG4gIFNlcXVlbmNlLFxuICBTZXF1ZW5jZU9wdGlvbnMsXG4gIFVuc3VwcG9ydGVkRXJyb3IsXG4gIEFkYXB0ZXIsXG4gIFByZXBhcmVkTW9kZWwsXG4gIFJlcG9zaXRvcnksXG4gIFF1ZXJ5RXJyb3IsXG4gIFBhZ2luZ0Vycm9yLFxuICBNaWdyYXRpb25FcnJvcixcbiAgT2JzZXJ2ZXJFcnJvcixcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBGb3JiaWRkZW5FcnJvcixcbiAgQ29ubmVjdGlvbkVycm9yLFxuICBDb250ZXh0dWFsaXplZEFyZ3MsXG4gIENvbnRleHQsXG4gIFJhd1Jlc3VsdCxcbiAgUGFnaW5hdG9yLFxuICBDb250ZXh0dWFsQXJncyxcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBNZXRob2RPck9wZXJhdGlvbixcbiAgQWxsT3BlcmF0aW9uS2V5cyxcbiAgRmxhZ3NPZixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlcIjtcbmltcG9ydCB7XG4gIENoYWluY29kZVN0dWIsXG4gIENsaWVudElkZW50aXR5LFxuICBJdGVyYXRvcnMsXG4gIFN0YXRlUXVlcnlSZXNwb25zZSxcbn0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuaW1wb3J0IHsgRmFicmljU3RhdGVtZW50IH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RTdGF0ZW1lbnRcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0U2VxdWVuY2UgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFNlcXVlbmNlXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyIH0gZnJvbSBcIi4uL3NoYXJlZC9TaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplclwiO1xuaW1wb3J0IHtcbiAgQ29uc3RydWN0b3IsXG4gIERlY29yYXRpb24sXG4gIE1ldGFkYXRhLFxuICBwcm9wTWV0YWRhdGEsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RQYWdpbmF0b3IgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFBhZ2luYXRvclwiO1xuaW1wb3J0IHsgTWlzc2luZ0NvbnRleHRFcnJvciB9IGZyb20gXCIuLi9zaGFyZWQvZXJyb3JzXCI7XG5cbmV4cG9ydCB0eXBlIEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxcbiAgQVJHUyBleHRlbmRzIGFueVtdID0gYW55W10sXG4gIEVYVEVORCBleHRlbmRzIGJvb2xlYW4gPSBmYWxzZSxcbj4gPSBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTLCBFWFRFTkQ+ICYge1xuICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjcmVhdG9yIG9yIHVwZGF0ZXIgZmllbGQgaW4gYSBtb2RlbCBiYXNlZCBvbiB0aGUgdXNlciBpbiB0aGUgY29udGV4dFxuICogQHN1bW1hcnkgQ2FsbGJhY2sgZnVuY3Rpb24gdXNlZCBpbiBkZWNvcmF0b3JzIHRvIGF1dG9tYXRpY2FsbHkgc2V0IHRoZSBjcmVhdGVkX2J5IG9yIHVwZGF0ZWRfYnkgZmllbGRzXG4gKiB3aXRoIHRoZSB1c2VybmFtZSBmcm9tIHRoZSBjb250ZXh0IHdoZW4gYSBkb2N1bWVudCBpcyBjcmVhdGVkIG9yIHVwZGF0ZWRcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgTmFub1JlcG9zaXRvcnk8TT5cbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgUmVsYXRpb25zTWV0YWRhdGFcbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY29udGV4dCAtIFRoZSBvcGVyYXRpb24gY29udGV4dCBjb250YWluaW5nIHVzZXIgaW5mb3JtYXRpb25cbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSByZWxhdGlvbiBtZXRhZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0IHdpdGggdGhlIHVzZXJuYW1lXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIGJlaW5nIGNyZWF0ZWQgb3IgdXBkYXRlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBGIGFzIGNyZWF0ZWRCeU9uTmFub0NyZWF0ZVVwZGF0ZVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENvbnRleHRcbiAqICAgcGFydGljaXBhbnQgTSBhcyBNb2RlbFxuICogICBGLT4+QzogZ2V0KFwidXNlclwiKVxuICogICBDLS0+PkY6IHVzZXIgb2JqZWN0XG4gKiAgIEYtPj5NOiBzZXQga2V5IHRvIHVzZXIubmFtZVxuICogICBOb3RlIG92ZXIgRjogSWYgbm8gdXNlciBpbiBjb250ZXh0XG4gKiAgIEYtLT4+RjogdGhyb3cgVW5zdXBwb3J0ZWRFcnJvclxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgdXNlciA9IGNvbnRleHQuZ2V0KFwiaWRlbnRpdHlcIikgYXMgQ2xpZW50SWRlbnRpdHk7XG4gICAgbW9kZWxba2V5XSA9IHVzZXIuZ2V0SUQoKSBhcyBNW3R5cGVvZiBrZXldO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJObyBVc2VyIGZvdW5kIGluIGNvbnRleHQuIFBsZWFzZSBwcm92aWRlIGEgdXNlciBpbiB0aGUgY29udGV4dFwiXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmltYXJ5IGtleSBhdXRvLWFzc2lnbm1lbnQgY2FsbGJhY2sgZm9yIEZhYnJpYyBtb2RlbHNcbiAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhbmQgYXNzaWducyBhIHByaW1hcnkga2V5IHZhbHVlIHRvIHRoZSBzcGVjaWZpZWQgbW9kZWwgcHJvcGVydHkgdXNpbmcgYSBGYWJyaWMtYmFja2VkIHNlcXVlbmNlIHdoZW4gdGhlIG1vZGVsIGlzIGNyZWF0ZWQuIElmIHRoZSBzZXF1ZW5jZSBuYW1lIGlzIG5vdCBwcm92aWRlZCBpbiBvcHRpb25zLCBpdCBpcyBkZXJpdmVkIGZyb20gdGhlIG1vZGVsIHZpYSBzZXF1ZW5jZU5hbWVGb3JNb2RlbC4gVGhlIGFzc2lnbmVkIGtleSBpcyBkZWZpbmVkIGFzIG5vbi13cml0YWJsZSBhbmQgZW51bWVyYWJsZS5cbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWwgZm9yIHRoZSB0YXJnZXQgaW5zdGFuY2VcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGZvciByZXBvc2l0b3J5IGNvbnRleHRcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgU2VxdWVuY2VPcHRpb25zIHRvIGNvbmZpZ3VyZSBzZXF1ZW5jZSBiZWhhdmlvclxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBGYWJyaWNDb250cmFjdEZsYWdzIGZvciBjb250ZXh0dWFsIGZsYWdzXG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZSBpbnZva2luZyB0aGUgY2FsbGJhY2tcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjb250ZXh0IC0gRmFicmljIGNvbnRyYWN0IGNvbnRleHQgY29udGFpbmluZyBpbnZvY2F0aW9uIG1ldGFkYXRhXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBTZXF1ZW5jZSBvcHRpb25zIHVzZWQgdG8gY29uZmlndXJlIG9yIGxvY2F0ZSB0aGUgc2VxdWVuY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZSB0byBhc3NpZ24gb24gdGhlIG1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHJlY2VpdmUgdGhlIGdlbmVyYXRlZCBwcmltYXJ5IGtleVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUmVzb2x2ZXMgd2hlbiB0aGUga2V5IGlzIGFzc2lnbmVkIG9yIHdoZW4gbm8gYWN0aW9uIGlzIHJlcXVpcmVkXG4gKiBAZnVuY3Rpb24gcGtGYWJyaWNPbkNyZWF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBSIGFzIFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb250ZXh0PEY+XG4gKiAgIHBhcnRpY2lwYW50IFMgYXMgRmFicmljQ29udHJhY3REQlNlcXVlbmNlXG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgUi0+PlI6IGRlcml2ZSBzZXF1ZW5jZSBuYW1lIGlmIG1pc3NpbmdcbiAqICAgUi0+PlM6IGFkYXB0ZXIuU2VxdWVuY2Uob3B0aW9ucylcbiAqICAgUy0tPj5SOiBzZXF1ZW5jZSBpbnN0YW5jZVxuICogICBSLT4+UzogbmV4dChjb250ZXh0KVxuICogICBTLS0+PlI6IG5leHQgdmFsdWVcbiAqICAgUi0+Pk06IGRlZmluZSBub24td3JpdGFibGUgcHJpbWFyeSBrZXlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBrRmFicmljT25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgZGF0YTogU2VxdWVuY2VPcHRpb25zLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFkYXRhLnR5cGUgfHwgbW9kZWxba2V5XSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldFByaW1hcnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG4gIGlmICghZGF0YS5uYW1lKSBkYXRhLm5hbWUgPSBNb2RlbC5zZXF1ZW5jZU5hbWUobW9kZWwsIFwicGtcIik7XG4gIGxldCBzZXF1ZW5jZTogU2VxdWVuY2U7XG4gIHRyeSB7XG4gICAgc2VxdWVuY2UgPSAoYXdhaXQgdGhpcy5hZGFwdGVyLlNlcXVlbmNlKGRhdGEpKSBhcyBTZXF1ZW5jZTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGluc3RhbnRpYXRlIFNlcXVlbmNlICR7ZGF0YS5uYW1lfTogJHtlfWBcbiAgICApO1xuICB9XG5cbiAgY29uc3QgbmV4dCA9IGF3YWl0IHNlcXVlbmNlLm5leHQoY29udGV4dCBhcyBGYWJyaWNDb250cmFjdENvbnRleHQpO1xuICBzZXRQcmltYXJ5S2V5VmFsdWUobW9kZWwsIGtleSBhcyBzdHJpbmcsIG5leHQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBZGFwdGVyIGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIHN0YXRlIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgQ291Y2hEQi1saWtlIGludGVyZmFjZSBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlIGZyb20gd2l0aGluIGEgY2hhaW5jb2RlIGNvbnRyYWN0XG4gKiBAdGVtcGxhdGUgdm9pZCAtIE5vIGNvbmZpZ3VyYXRpb24gbmVlZGVkIGZvciBjb250cmFjdCBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RGbGFncyAtIEZsYWdzIHNwZWNpZmljIHRvIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RDb250ZXh0IC0gQ29udGV4dCB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdCBjbGFzc1xuICogaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBwcml2YXRlIGFkYXB0ZXIgPSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyKCk7XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IG1vZGVsID0geyBpZCwgZGF0YSwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH07XG4gKiAgICAgYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZSgnYXNzZXRzJywgaWQsIG1vZGVsLCB7fSwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdHViXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAqXG4gKiAgIENvbnRyYWN0LT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgbW9kZWwsIHRyYW5zaWVudCwgY3R4KVxuICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IFNlcmlhbGl6ZSBtb2RlbCB0byBKU09OXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PlN0dWI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3R1Yi0+PlN0YXRlREI6IFdyaXRlIGRhdGFcbiAqICAgU3RhdGVEQi0tPj5TdHViOiBTdWNjZXNzXG4gKiAgIFN0dWItLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlciBleHRlbmRzIENvdWNoREJBZGFwdGVyPFxuICBhbnksXG4gIHZvaWQsXG4gIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBnZXRDbGllbnQoKTogdm9pZCB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXCJDbGllbnQgaXMgbm90IHN1cHBvcnRlZCBpbiBGYWJyaWMgY29udHJhY3RzXCIpO1xuICB9XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGV4dCBkZWNvZGVyIGZvciBjb252ZXJ0aW5nIGJpbmFyeSBkYXRhIHRvIHN0cmluZ3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKFwidXRmOFwiKTtcblxuICBwcm90ZWN0ZWQgc3RhdGljIHJlYWRvbmx5IHNlcmlhbGl6ZXIgPSBuZXcgU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIoKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnRleHQgY29uc3RydWN0b3IgZm9yIHRoaXMgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgQ29udGV4dCBjb25zdHJ1Y3RvciB3aXRoIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGdldCBDb250ZXh0KCk6IENvbnN0cnVjdG9yPEZhYnJpY0NvbnRyYWN0Q29udGV4dD4ge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdENvbnRleHQ7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSByZXBvc2l0b3J5IGNvbnN0cnVjdG9yIGZvciB0aGlzIGFkYXB0ZXJcbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGNvbnN0cnVjdG9yIGZvciBjcmVhdGluZyByZXBvc2l0b3JpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3RvcjxSZXBvc2l0b3J5PE0sIE1hbmdvUXVlcnksIEZhYnJpY0NvbnRyYWN0QWRhcHRlciwgRmFicmljQ29udHJhY3RGbGFncywgRmFicmljQ29udHJhY3RDb250ZXh0Pj59IFRoZSByZXBvc2l0b3J5IGNvbnN0cnVjdG9yXG4gICAqL1xuICBvdmVycmlkZSByZXBvc2l0b3J5PFxuICAgIFIgZXh0ZW5kcyBSZXBvc2l0b3J5PFxuICAgICAgYW55LFxuICAgICAgQWRhcHRlcjxhbnksIHZvaWQsIE1hbmdvUXVlcnksIENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4+XG4gICAgPixcbiAgPigpOiBDb25zdHJ1Y3RvcjxSPiB7XG4gICAgcmV0dXJuIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yPFI+O1xuICB9XG5cbiAgb3ZlcnJpZGUgUGFnaW5hdG9yPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgcXVlcnk6IE1hbmdvUXVlcnksXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPlxuICApOiBQYWdpbmF0b3I8TSwgYW55LCBNYW5nb1F1ZXJ5PiB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDb250cmFjdFBhZ2luYXRvcih0aGlzLCBxdWVyeSwgc2l6ZSwgY2xhenopO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgU2VxdWVuY2Uob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKTogUHJvbWlzZTxTZXF1ZW5jZT4ge1xuICAgIHJldHVybiBuZXcgRmFicmljQ29udHJhY3RTZXF1ZW5jZShvcHRpb25zLCB0aGlzIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGFuIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3ZvaWR9IHNjb3BlIC0gTm90IHVzZWQgaW4gdGhpcyBhZGFwdGVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWxpYXNdIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyIGluc3RhbmNlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogdm9pZCwgYWxpYXM/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgRmFicmljRmxhdm91ciwgYWxpYXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZm9yKGNvbmZpZzogUGFydGlhbDxhbnk+LCAuLi5hcmdzOiBhbnkpOiB0eXBlb2YgdGhpcyB7XG4gICAgcmV0dXJuIHN1cGVyLmZvcihjb25maWcsIC4uLmFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcmVjb3JkIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWwgYW5kIHN0b3JlcyBpdCBpbiB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5pbmZvKGBpbiBBREFQVEVSIGNyZWF0ZSB3aXRoIGFyZ3MgJHthcmdzfWApO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5pbmZvKGBhZGRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlIHdpdGggcGsgJHtpZH1gKTtcbiAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gY3R4LnN0dWIuY3JlYXRlQ29tcG9zaXRlS2V5KHRhYmxlTmFtZSwgW1N0cmluZyhpZCldKTtcbiAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5wdXRTdGF0ZShjb21wb3NlZEtleSwgbW9kZWwsIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgYSByZWNvcmQgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIGFuZCBkZXNlcmlhbGl6ZXMgYSByZWNvcmQgZnJvbSB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBzdHViIGFuZCBsb2dnZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IHsgY3R4LCBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmVhZCk7XG4gICAgbG9nLmluZm8oYGluIEFEQVBURVIgcmVhZCB3aXRoIGFyZ3MgJHthcmdzfWApO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG5cbiAgICBsZXQgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gY3R4LnN0dWIuY3JlYXRlQ29tcG9zaXRlS2V5KHRhYmxlTmFtZSwgW1N0cmluZyhpZCldKTtcbiAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5yZWFkU3RhdGUoY29tcG9zZWRLZXksIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHJlY29yZCBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgU2VyaWFsaXplcyBhIG1vZGVsIGFuZCB1cGRhdGVzIGl0IGluIHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBpZCAtIFRoZSByZWNvcmQgaWRlbnRpZmllclxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIHVwZGF0ZWQgcmVjb3JkIGRhdGFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0cmFuc2llbnQgLSBUcmFuc2llbnQgZGF0YSAobm90IHVzZWQgaW4gdGhpcyBpbXBsZW1lbnRhdGlvbilcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBzdHViIGFuZCBsb2dnZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgcmVjb3JkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IHsgY3R4LCBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMudXBkYXRlKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUoY2xhenopO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxvZy52ZXJib3NlKGB1cGRhdGluZyBlbnRyeSB0byAke3RhYmxlTmFtZX0gdGFibGUgd2l0aCBwayAke2lkfWApO1xuICAgICAgY29uc3QgY29tcG9zZWRLZXkgPSBjdHguc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnB1dFN0YXRlKGNvbXBvc2VkS2V5LCBtb2RlbCwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVjb3JkIGZyb20gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIHJlY29yZCBhbmQgdGhlbiByZW1vdmVzIGl0IGZyb20gdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGVsZXRlZCByZWNvcmRcbiAgICovXG4gIGFzeW5jIGRlbGV0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5kZWxldGUpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG4gICAgbGV0IG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb21wb3NlZEtleSA9IGN0eC5zdHViLmNyZWF0ZUNvbXBvc2l0ZUtleSh0YWJsZU5hbWUsIFtTdHJpbmcoaWQpXSk7XG4gICAgICBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZChjbGF6eiwgaWQsIC4uLmN0eEFyZ3MpO1xuICAgICAgbG9nLnZlcmJvc2UoYGRlbGV0aW5nIGVudHJ5IHdpdGggcGsgJHtpZH0gZnJvbSAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICAgIGF3YWl0IHRoaXMuZGVsZXRlU3RhdGUoY29tcG9zZWRLZXksIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVTdGF0ZShpZDogc3RyaW5nLCBjb250ZXh0OiBGYWJyaWNDb250cmFjdENvbnRleHQpIHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmRlbGV0ZVN0YXRlKTtcbiAgICBhd2FpdCBjdHguc3R1Yi5kZWxldGVTdGF0ZShpZCk7XG4gIH1cblxuICBmb3JQcml2YXRlKGNvbGxlY3Rpb246IHN0cmluZyk6IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB7XG4gICAgY29uc3QgdG9PdmVycmlkZSA9IFtcbiAgICAgIHRoaXMucHV0U3RhdGUsXG4gICAgICB0aGlzLnJlYWRTdGF0ZSxcbiAgICAgIHRoaXMuZGVsZXRlU3RhdGUsXG4gICAgICB0aGlzLnF1ZXJ5UmVzdWx0LFxuICAgICAgdGhpcy5xdWVyeVJlc3VsdFBhZ2luYXRlZCxcbiAgICBdLm1hcCgoZm4pID0+IGZuLm5hbWUpO1xuICAgIHJldHVybiBuZXcgUHJveHkodGhpcywge1xuICAgICAgZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICAgICAgaWYgKCF0b092ZXJyaWRlLmluY2x1ZGVzKHByb3AgYXMgc3RyaW5nKSlcbiAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcik7XG4gICAgICAgIHJldHVybiBuZXcgUHJveHkoKHRhcmdldCBhcyBhbnkpW3Byb3BdLCB7XG4gICAgICAgICAgYXN5bmMgYXBwbHkoZm4sIHRoaXNBcmcsIGFyZ3NMaXN0KSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHByb3ApIHtcbiAgICAgICAgICAgICAgY2FzZSBcInB1dFN0YXRlXCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgaWQsIG1vZGVsXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIGF3YWl0IHN0dWIucHV0UHJpdmF0ZURhdGEoY29sbGVjdGlvbiwgaWQudG9TdHJpbmcoKSwgbW9kZWwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlU3RhdGVcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCBpZF0gPSBhcmdzTGlzdDtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHN0dWIgYXMgQ2hhaW5jb2RlU3R1YikuZGVsZXRlUHJpdmF0ZURhdGEoXG4gICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICAgICAgICAgICAgaWRcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNhc2UgXCJyZWFkU3RhdGVcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCBpZF0gPSBhcmdzTGlzdDtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3R1Yi5nZXRQcml2YXRlRGF0YShjb2xsZWN0aW9uLCBpZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2FzZSBcInF1ZXJ5UmVzdWx0XCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgcmF3SW5wdXRdID0gYXJnc0xpc3Q7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0dWIuZ2V0UHJpdmF0ZURhdGFRdWVyeVJlc3VsdChjb2xsZWN0aW9uLCByYXdJbnB1dCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2FzZSBcInF1ZXJ5UmVzdWx0UGFnaW5hdGVkXCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbc3R1YiwgcmF3SW5wdXQsIGxpbWl0LCBza2lwXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZXJhdG9yID0gYXdhaXQgKFxuICAgICAgICAgICAgICAgICAgc3R1YiBhcyBDaGFpbmNvZGVTdHViXG4gICAgICAgICAgICAgICAgKS5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KGNvbGxlY3Rpb24sIHJhd0lucHV0KTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHRzOiBhbnlbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IHJlYWNoZWRCb29rbWFyayA9IHNraXAgPyBmYWxzZSA6IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3RLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGl0ZXJhdG9yLm5leHQoKTtcblxuICAgICAgICAgICAgICAgICAgaWYgKHJlcy52YWx1ZSAmJiByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWNvcmRLZXkgPSByZXMudmFsdWUua2V5O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWNvcmRWYWx1ZSA9IChyZXMudmFsdWUudmFsdWUgYXMgYW55KS50b1N0cmluZyhcbiAgICAgICAgICAgICAgICAgICAgICBcInV0ZjhcIlxuICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgYSBza2lwLCBza2lwIHVudGlsIHdlIHJlYWNoIGl0XG4gICAgICAgICAgICAgICAgICAgIGlmICghcmVhY2hlZEJvb2ttYXJrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJlY29yZEtleSA9PT0gc2tpcD8udG9TdHJpbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVhY2hlZEJvb2ttYXJrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgIEtleTogcmVjb3JkS2V5LFxuICAgICAgICAgICAgICAgICAgICAgIFJlY29yZDogSlNPTi5wYXJzZShyZWNvcmRWYWx1ZSksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBsYXN0S2V5ID0gcmVjb3JkS2V5O1xuICAgICAgICAgICAgICAgICAgICBjb3VudCsrO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGl0ZXJhdG9yLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yOlxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzIGFzIHVua25vd24gYXMgSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZWRSZWNvcmRzQ291bnQ6IHJlc3VsdHMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBib29rbWFyazogbGFzdEtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBpZiAocmVzLmRvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgaXRlcmF0b3IuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRvcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgYXMgdW5rbm93biBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmZXRjaGVkUmVjb3Jkc0NvdW50OiByZXN1bHRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvb2ttYXJrOiBcIlwiLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICBgVW5zdXBwb3J0ZWQgbWV0aG9kIG92ZXJyaWRlICR7U3RyaW5nKHByb3ApfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBwdXRTdGF0ZShcbiAgICBpZDogc3RyaW5nLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0XG4gICkge1xuICAgIGxldCBkYXRhOiBCdWZmZXI7XG5cbiAgICBjb25zdCB7IGxvZyB9ID0gdGhpcy5sb2dDdHgoW2N0eF0sIHRoaXMucHV0U3RhdGUpO1xuICAgIHRyeSB7XG4gICAgICBkYXRhID0gQnVmZmVyLmZyb20oXG4gICAgICAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCBhcyBNb2RlbCwgZmFsc2UpXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gc2VyaWFsaXplIHJlY29yZCB3aXRoIGlkICR7aWR9OiAke2V9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY3R4LmdldChcInNlZ3JlZ2F0ZWRcIik7XG4gICAgaWYgKGNvbGxlY3Rpb24pXG4gICAgICBhd2FpdCBjdHguc3R1Yi5wdXRQcml2YXRlRGF0YShjb2xsZWN0aW9uLCBpZC50b1N0cmluZygpLCBkYXRhKTtcbiAgICBlbHNlIGF3YWl0IGN0eC5zdHViLnB1dFN0YXRlKGlkLnRvU3RyaW5nKCksIGRhdGEpO1xuXG4gICAgbG9nLnNpbGx5KFxuICAgICAgYHN0YXRlIHN0b3JlZCR7Y29sbGVjdGlvbiA/IGAgaW4gJHtjb2xsZWN0aW9ufSBjb2xsZWN0aW9uYCA6IFwiXCJ9IHVuZGVyIGlkICR7aWR9YFxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRTdGF0ZShpZDogc3RyaW5nLCBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCkge1xuICAgIGxldCByZXN1bHQ6IGFueTtcblxuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChbY3R4XSwgdGhpcy5yZWFkU3RhdGUpO1xuICAgIGxldCByZXM6IHN0cmluZztcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY3R4LmdldChcInNlZ3JlZ2F0ZWRcIik7XG4gICAgaWYgKGNvbGxlY3Rpb24pXG4gICAgICByZXMgPSAoXG4gICAgICAgIGF3YWl0IGN0eC5zdHViLmdldFByaXZhdGVEYXRhKGNvbGxlY3Rpb24sIGlkLnRvU3RyaW5nKCkpXG4gICAgICApLnRvU3RyaW5nKCk7XG4gICAgZWxzZSByZXMgPSAoYXdhaXQgY3R4LnN0dWIuZ2V0U3RhdGUoaWQudG9TdHJpbmcoKSkpLnRvU3RyaW5nKCk7XG5cbiAgICBpZiAoIXJlcylcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFxuICAgICAgICBgUmVjb3JkIHdpdGggaWQgJHtpZH0ke2NvbGxlY3Rpb24gPyBgIGluICR7Y29sbGVjdGlvbn0gY29sbGVjdGlvbmAgOiBcIlwifSBub3QgZm91bmRgXG4gICAgICApO1xuICAgIGxvZy5zaWxseShcbiAgICAgIGBzdGF0ZSByZXRyaWV2ZWQgZnJvbSR7Y29sbGVjdGlvbiA/IGAgJHtjb2xsZWN0aW9ufSBjb2xsZWN0aW9uYCA6IFwiXCJ9IHVuZGVyIGlkICR7aWR9YFxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IEZhYnJpY0NvbnRyYWN0QWRhcHRlci5zZXJpYWxpemVyLmRlc2VyaWFsaXplKHJlcy50b1N0cmluZygpKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBGYWlsZWQgdG8gcGFyc2UgcmVjb3JkOiAke2V9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBxdWVyeVJlc3VsdChcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViLFxuICAgIHJhd0lucHV0OiBhbnksXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5xdWVyeVJlc3VsdCk7XG4gICAgbGV0IHJlczogSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcjtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY3R4LmdldChcInNlZ3JlZ2F0ZWRcIik7XG4gICAgaWYgKGNvbGxlY3Rpb24pXG4gICAgICByZXMgPSBhd2FpdCBjdHguc3R1Yi5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShyYXdJbnB1dClcbiAgICAgICk7XG4gICAgZWxzZSByZXMgPSBhd2FpdCBzdHViLmdldFF1ZXJ5UmVzdWx0KEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KSk7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgIHN0dWI6IENoYWluY29kZVN0dWIsXG4gICAgcmF3SW5wdXQ6IGFueSxcbiAgICBsaW1pdDogbnVtYmVyID0gMjUwLFxuICAgIHNraXA/OiBudW1iZXIsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxTdGF0ZVF1ZXJ5UmVzcG9uc2U8SXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcj4+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkU3RhdGUpO1xuICAgIGxldCByZXM6IFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPjtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY3R4LmdldChcInNlZ3JlZ2F0ZWRcIik7XG4gICAgaWYgKGNvbGxlY3Rpb24pIHtcbiAgICAgIHJhd0lucHV0LnNlbGVjdG9yID0ge1xuICAgICAgICAuLi5yYXdJbnB1dC5zZWxlY3RvcixcbiAgICAgICAgX2lkOiBza2lwID8geyAkZ3Q6IHNraXAudG9TdHJpbmcoKSB9IDogeyAkZ3RlOiBcIlwiIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgaXQgPSBhd2FpdCBzdHViLmdldFByaXZhdGVEYXRhUXVlcnlSZXN1bHQoXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KVxuICAgICAgKTtcbiAgICAgIHJlcyA9IHtcbiAgICAgICAgaXRlcmF0b3I6IGl0LFxuICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgIGZldGNoZWRSZWNvcmRzQ291bnQ6IGxpbWl0LFxuICAgICAgICAgIGJvb2ttYXJrOiBcIlwiLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9IGVsc2VcbiAgICAgIHJlcyA9IGF3YWl0IHN0dWIuZ2V0UXVlcnlSZXN1bHRXaXRoUGFnaW5hdGlvbihcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocmF3SW5wdXQpLFxuICAgICAgICBsaW1pdCxcbiAgICAgICAgc2tpcD8udG9TdHJpbmcoKVxuICAgICAgKTtcblxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWVyZ2VNb2RlbHMocmVzdWx0czogUmVjb3JkPHN0cmluZywgYW55PltdKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgZXh0cmFjdCA9IChtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PikgPT5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG1vZGVsKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSBcInVuZGVmaW5lZFwiKSBhY2N1bVtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICBsZXQgZmluYWxNb2RlbDogUmVjb3JkPHN0cmluZywgYW55PiA9IHJlc3VsdHMucG9wKCkgYXMgUmVjb3JkPHN0cmluZywgYW55PjtcblxuICAgIGZvciAoY29uc3QgcmVzIG9mIHJlc3VsdHMpIHtcbiAgICAgIGZpbmFsTW9kZWwgPSBPYmplY3QuYXNzaWduKHt9LCBleHRyYWN0KGZpbmFsTW9kZWwpLCBleHRyYWN0KHJlcykpO1xuICAgIH1cblxuICAgIHJldHVybiBmaW5hbE1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNvZGVzIGJpbmFyeSBkYXRhIHRvIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcgdXNpbmcgVVRGLTggZW5jb2RpbmdcbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgLSBUaGUgYmluYXJ5IGRhdGEgdG8gZGVjb2RlXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGRlY29kZWQgc3RyaW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgZGVjb2RlKGJ1ZmZlcjogVWludDhBcnJheSkge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdEFkYXB0ZXIudGV4dERlY29kZXIuZGVjb2RlKGJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgb3BlcmF0aW9uIGZsYWdzIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICAgKiBAc3VtbWFyeSBNZXJnZXMgZGVmYXVsdCBmbGFncyB3aXRoIEZhYnJpYy1zcGVjaWZpYyBjb250ZXh0IGluZm9ybWF0aW9uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz59IGZsYWdzIC0gUGFydGlhbCBmbGFncyB0byBtZXJnZSB3aXRoIGRlZmF1bHRzXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEByZXR1cm4ge0ZhYnJpY0NvbnRyYWN0RmxhZ3N9IFRoZSBtZXJnZWQgZmxhZ3NcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogQWxsT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4gfCB1bmRlZmluZWQsXG4gICAgZmxhZ3M6IFBhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz4gfCBGYWJyaWNDb250cmFjdENvbnRleHQgfCBDdHggfCBhbnlcbiAgKTogUHJvbWlzZTxGYWJyaWNDb250cmFjdEZsYWdzPiB7XG4gICAgbGV0IGJhc2VGbGFncyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7XG4gICAgICAgIHNlZ3JlZ2F0ZWQ6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGZsYWdzXG4gICAgKTtcbiAgICBpZiAoZmxhZ3MgaW5zdGFuY2VvZiBGYWJyaWNDb250cmFjdENvbnRleHQpIHtcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9IGVsc2UgaWYgKChmbGFncyBhcyBDdHgpLnN0dWIpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24oYmFzZUZsYWdzLCB7XG4gICAgICAgIHN0dWI6IGZsYWdzLnN0dWIsXG4gICAgICAgIGlkZW50aXR5OiAoZmxhZ3MgYXMgQ3R4KS5jbGllbnRJZGVudGl0eSxcbiAgICAgICAgbG9nZ2VyOiBMb2dnaW5nLmZvcihcbiAgICAgICAgICBvcGVyYXRpb24sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbG9nTGV2ZWw6IGZhbHNlLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBmYWxzZSxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IChmbGFncyBhcyBDdHgpLnN0dWIuZ2V0VHhJRCgpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZmxhZ3NcbiAgICAgICAgKSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogKGZsYWdzIGFzIEN0eCkuc3R1Yi5nZXRUeElEKCksXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYmFzZUZsYWdzID0gT2JqZWN0LmFzc2lnbihiYXNlRmxhZ3MsIGZsYWdzIHx8IHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGF3YWl0IHN1cGVyLmZsYWdzKFxuICAgICAgb3BlcmF0aW9uLFxuICAgICAgbW9kZWwsXG4gICAgICBiYXNlRmxhZ3MgYXMgYW55XG4gICAgKSkgYXMgRmFicmljQ29udHJhY3RGbGFncztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhbiBpbmRleCBmb3IgYSBtb2RlbFxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBpcyBub3QgaW1wbGVtZW50ZWQgZm9yIEZhYnJpYyBjb250cmFjdHMgYW5kIHJldHVybnMgYSByZXNvbHZlZCBwcm9taXNlXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWxzIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyBpbW1lZGlhdGVseVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBwcm90ZWN0ZWQgaW5kZXg8TT4obW9kZWxzOiBDb25zdHJ1Y3RvcjxNPik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIHJlc3VsdHMgZnJvbSBhIHN0YXRlIHF1ZXJ5IGl0ZXJhdG9yXG4gICAqIEBzdW1tYXJ5IEl0ZXJhdGVzIHRocm91Z2ggcXVlcnkgcmVzdWx0cyBhbmQgY29udmVydHMgdGhlbSB0byBhIHN0cnVjdHVyZWQgZm9ybWF0XG4gICAqIEBwYXJhbSB7TG9nZ2VyfSBsb2cgLSBMb2dnZXIgaW5zdGFuY2UgZm9yIGRlYnVnZ2luZ1xuICAgKiBAcGFyYW0ge0l0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3J9IGl0ZXJhdG9yIC0gVGhlIHN0YXRlIHF1ZXJ5IGl0ZXJhdG9yXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzSGlzdG9yeT1mYWxzZV0gLSBXaGV0aGVyIHRoaXMgaXMgYSBoaXN0b3J5IHF1ZXJ5XG4gICAqIEByZXR1cm4ge1Byb21pc2U8YW55W10+fSBQcm9taXNlIHJlc29sdmluZyB0byBhbiBhcnJheSBvZiBwcm9jZXNzZWQgcmVzdWx0c1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAgICogICBwYXJ0aWNpcGFudCBSZXN1bHRJdGVyYXRvclxuICAgKiAgIHBhcnRpY2lwYW50IEl0ZXJhdG9yXG4gICAqXG4gICAqICAgQ2FsbGVyLT4+UmVzdWx0SXRlcmF0b3I6IHJlc3VsdEl0ZXJhdG9yKGxvZywgaXRlcmF0b3IsIGlzSGlzdG9yeSlcbiAgICogICBsb29wIFVudGlsIGRvbmVcbiAgICogICAgIFJlc3VsdEl0ZXJhdG9yLT4+SXRlcmF0b3I6IG5leHQoKVxuICAgKiAgICAgSXRlcmF0b3ItLT4+UmVzdWx0SXRlcmF0b3I6IHsgdmFsdWUsIGRvbmUgfVxuICAgKiAgICAgYWx0IEhhcyB2YWx1ZVxuICAgKiAgICAgICBSZXN1bHRJdGVyYXRvci0+PlJlc3VsdEl0ZXJhdG9yOiBQcm9jZXNzIHZhbHVlIGJhc2VkIG9uIGlzSGlzdG9yeVxuICAgKiAgICAgICBSZXN1bHRJdGVyYXRvci0+PlJlc3VsdEl0ZXJhdG9yOiBBZGQgdG8gcmVzdWx0cyBhcnJheVxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqICAgUmVzdWx0SXRlcmF0b3ItPj5JdGVyYXRvcjogY2xvc2UoKVxuICAgKiAgIFJlc3VsdEl0ZXJhdG9yLS0+PkNhbGxlcjogYWxsUmVzdWx0c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlc3VsdEl0ZXJhdG9yKFxuICAgIGxvZzogTG9nZ2VyLFxuICAgIGl0ZXJhdG9yOiBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yLFxuICAgIGlzSGlzdG9yeSA9IGZhbHNlXG4gICkge1xuICAgIGNvbnN0IGFsbFJlc3VsdHMgPSBbXTtcbiAgICBsZXQgcmVzOiB7IHZhbHVlOiBhbnk7IGRvbmU6IGJvb2xlYW4gfSA9IGF3YWl0IGl0ZXJhdG9yLm5leHQoKTtcbiAgICB3aGlsZSAoIXJlcy5kb25lKSB7XG4gICAgICBpZiAocmVzLnZhbHVlICYmIHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZygpKSB7XG4gICAgICAgIGxldCBqc29uUmVzOiBhbnkgPSB7fTtcbiAgICAgICAgbG9nLmRlYnVnKHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgICAgICBpZiAoaXNIaXN0b3J5IC8qICYmIGlzSGlzdG9yeSA9PT0gdHJ1ZSovKSB7XG4gICAgICAgICAganNvblJlcy5UeElkID0gcmVzLnZhbHVlLnR4SWQ7XG4gICAgICAgICAganNvblJlcy5UaW1lc3RhbXAgPSByZXMudmFsdWUudGltZXN0YW1wO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBqc29uUmVzLlZhbHVlID0gSlNPTi5wYXJzZShyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgbG9nLmVycm9yKGVycik7XG4gICAgICAgICAgICBqc29uUmVzLlZhbHVlID0gcmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGpzb25SZXMgPSBKU09OLnBhcnNlKHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICBsb2cuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIGpzb25SZXMgPSByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhbGxSZXN1bHRzLnB1c2goanNvblJlcyk7XG4gICAgICB9XG4gICAgICByZXMgPSBhd2FpdCBpdGVyYXRvci5uZXh0KCk7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgQ2xvc2luZyBpdGVyYXRvciBhZnRlciAke2FsbFJlc3VsdHMubGVuZ3RofSByZXN1bHRzYCk7XG4gICAgaXRlcmF0b3IuY2xvc2UoKTsgLy8gcHVycG9zZWx5IG5vdCBhd2FpdC4gbGV0IGl0ZXJhdG9yIGNsb3NlIG9uIGl0cyBvd25cbiAgICByZXR1cm4gYWxsUmVzdWx0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSByYXcgcXVlcnkgYWdhaW5zdCB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUGVyZm9ybXMgYSByaWNoIHF1ZXJ5IHVzaW5nIENvdWNoREIgc3ludGF4IGFnYWluc3QgdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSByZXR1cm4gdHlwZVxuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHJhd0lucHV0IC0gVGhlIE1hbmdvIFF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHBhcmFtIHtib29sZWFufSBkb2NzT25seSAtIFdoZXRoZXIgdG8gcmV0dXJuIG9ubHkgZG9jdW1lbnRzIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFI+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcXVlcnkgcmVzdWx0c1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAgICogICBwYXJ0aWNpcGFudCBGYWJyaWNDb250cmFjdEFkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBTdHViXG4gICAqICAgcGFydGljaXBhbnQgU3RhdGVEQlxuICAgKlxuICAgKiAgIENhbGxlci0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogcmF3KHJhd0lucHV0LCBkb2NzT25seSwgY3R4KVxuICAgKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogRXh0cmFjdCBsaW1pdCBhbmQgc2tpcFxuICAgKiAgIGFsdCBXaXRoIHBhZ2luYXRpb25cbiAgICogICAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PlN0dWI6IGdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24ocXVlcnksIGxpbWl0LCBza2lwKVxuICAgKiAgIGVsc2UgV2l0aG91dCBwYWdpbmF0aW9uXG4gICAqICAgICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5TdHViOiBnZXRRdWVyeVJlc3VsdChxdWVyeSlcbiAgICogICBlbmRcbiAgICogICBTdHViLT4+U3RhdGVEQjogRXhlY3V0ZSBxdWVyeVxuICAgKiAgIFN0YXRlREItLT4+U3R1YjogSXRlcmF0b3JcbiAgICogICBTdHViLS0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogSXRlcmF0b3JcbiAgICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IHJlc3VsdEl0ZXJhdG9yKGxvZywgaXRlcmF0b3IpXG4gICAqICAgRmFicmljQ29udHJhY3RBZGFwdGVyLS0+PkNhbGxlcjogcmVzdWx0c1xuICAgKi9cbiAgYXN5bmMgcmF3PFIsIEQgZXh0ZW5kcyBib29sZWFuPihcbiAgICByYXdJbnB1dDogTWFuZ29RdWVyeSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZG9jc09ubHk6IEQgPSB0cnVlIGFzIEQsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFJhd1Jlc3VsdDxSLCBEPj4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmF3KTtcblxuICAgIGNvbnN0IHsgc2tpcCwgbGltaXQgfSA9IHJhd0lucHV0O1xuICAgIGxldCBpdGVyYXRvcjogSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcjtcbiAgICBpZiAobGltaXQgfHwgc2tpcCkge1xuICAgICAgZGVsZXRlIHJhd0lucHV0W1wibGltaXRcIl07XG4gICAgICBkZWxldGUgcmF3SW5wdXRbXCJza2lwXCJdO1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgUmV0cmlldmluZyBwYWdpbmF0ZWQgaXRlcmF0b3I6IGxpbWl0OiAke2xpbWl0fS8gc2tpcDogJHtza2lwfWBcbiAgICAgICk7XG4gICAgICBjb25zdCByZXNwb25zZTogU3RhdGVRdWVyeVJlc3BvbnNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+ID1cbiAgICAgICAgKGF3YWl0IHRoaXMucXVlcnlSZXN1bHRQYWdpbmF0ZWQoXG4gICAgICAgICAgY3R4LnN0dWIsXG4gICAgICAgICAgcmF3SW5wdXQsXG4gICAgICAgICAgbGltaXQgfHwgTnVtYmVyLk1BWF9WQUxVRSxcbiAgICAgICAgICAoc2tpcCBhcyBhbnkpPy50b1N0cmluZygpLFxuICAgICAgICAgIGN0eFxuICAgICAgICApKSBhcyBTdGF0ZVF1ZXJ5UmVzcG9uc2U8SXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcj47XG4gICAgICBpdGVyYXRvciA9IHJlc3BvbnNlLml0ZXJhdG9yO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2cuZGVidWcoXCJSZXRyaWV2aW5nIGl0ZXJhdG9yXCIpO1xuICAgICAgaXRlcmF0b3IgPSAoYXdhaXQgdGhpcy5xdWVyeVJlc3VsdChcbiAgICAgICAgY3R4LnN0dWIsXG4gICAgICAgIHJhd0lucHV0LFxuICAgICAgICBjdHhcbiAgICAgICkpIGFzIEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhcIkl0ZXJhdG9yIGFjcXVpcmVkXCIpO1xuXG4gICAgY29uc3QgcmVzdWx0cyA9IChhd2FpdCB0aGlzLnJlc3VsdEl0ZXJhdG9yKGxvZywgaXRlcmF0b3IpKSBhcyBSO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGByZXR1cm5pbmcgJHtBcnJheS5pc0FycmF5KHJlc3VsdHMpID8gcmVzdWx0cy5sZW5ndGggOiAxfSByZXN1bHRzYFxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdHMgYXMgYW55O1xuICB9XG5cbiAgb3ZlcnJpZGUgU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbD4oKTogRmFicmljU3RhdGVtZW50PE0sIGFueT4ge1xuICAgIHJldHVybiBuZXcgRmFicmljU3RhdGVtZW50KHRoaXMgYXMgYW55KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhYmxlTmFtZTogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKGlkLmxlbmd0aCAhPT0gbW9kZWwubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZUFsbCk7XG4gICAgY29uc3QgdGFibGVMYWJlbCA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIGxvZy5kZWJ1ZyhgQ3JlYXRpbmcgJHtpZC5sZW5ndGh9IGVudHJpZXMgJHt0YWJsZUxhYmVsfSB0YWJsZWApO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgIGlkLm1hcCgoaSwgY291bnQpID0+IHRoaXMuY3JlYXRlKHRhYmxlTmFtZSwgaSwgbW9kZWxbY291bnRdLCAuLi5jdHhBcmdzKSlcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlQWxsPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBpZiAoaWQubGVuZ3RoICE9PSBtb2RlbC5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMudXBkYXRlQWxsKTtcbiAgICBjb25zdCB0YWJsZUxhYmVsID0gTW9kZWwudGFibGVOYW1lKHRhYmxlTmFtZSk7XG4gICAgbG9nLmRlYnVnKGBVcGRhdGluZyAke2lkLmxlbmd0aH0gZW50cmllcyAke3RhYmxlTGFiZWx9IHRhYmxlYCk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgaWQubWFwKChpLCBjb3VudCkgPT4gdGhpcy51cGRhdGUodGFibGVOYW1lLCBpLCBtb2RlbFtjb3VudF0sIC4uLmN0eEFyZ3MpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIG1vZGVsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwa1xuICAgKiBAcGFyYW0gYXJnc1xuICAgKi9cbiAgb3ZlcnJpZGUgcHJlcGFyZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogUHJlcGFyZWRNb2RlbCB7XG4gICAgY29uc3QgeyBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucHJlcGFyZSk7XG5cbiAgICBjb25zdCB0YWJsZU5hbWUgPSBNb2RlbC50YWJsZU5hbWUobW9kZWwuY29uc3RydWN0b3IgYXMgYW55KTtcbiAgICBjb25zdCBwayA9IE1vZGVsLnBrKG1vZGVsLmNvbnN0cnVjdG9yIGFzIGFueSk7XG4gICAgY29uc3Qgc3BsaXQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuICAgIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5lbnRyaWVzKHNwbGl0Lm1vZGVsKS5yZWR1Y2UoXG4gICAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybiBhY2N1bTtcbiAgICAgICAgY29uc3QgbWFwcGVkUHJvcCA9IE1vZGVsLmNvbHVtbk5hbWUobW9kZWwsIGtleSBhcyBhbnkpO1xuICAgICAgICBpZiAodGhpcy5pc1Jlc2VydmVkKG1hcHBlZFByb3ApKVxuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBQcm9wZXJ0eSBuYW1lICR7bWFwcGVkUHJvcH0gaXMgcmVzZXJ2ZWRgKTtcbiAgICAgICAgYWNjdW1bbWFwcGVkUHJvcF0gPSB2YWw7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sXG4gICAgICB7fVxuICAgICk7XG5cbiAgICBsb2cuc2lsbHkoXG4gICAgICBgUHJlcGFyaW5nIHJlY29yZCBmb3IgJHt0YWJsZU5hbWV9IHRhYmxlIHdpdGggcGsgJHsobW9kZWwgYXMgYW55KVtwa119YFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVjb3JkOiByZXN1bHQsXG4gICAgICBpZDogKG1vZGVsIGFzIGFueSlbcGtdIGFzIHN0cmluZyxcbiAgICAgIHRyYW5zaWVudDogc3BsaXQudHJhbnNpZW50LFxuICAgIH07XG4gIH1cblxuICBvdmVycmlkZSByZXZlcnQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogTSB7XG4gICAgY29uc3QgeyBsb2cgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmV2ZXJ0KTtcbiAgICBjb25zdCBvYjogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIGNvbnN0IHBrID0gTW9kZWwucGsoY2xhenopO1xuICAgIG9iW3BrIGFzIHN0cmluZ10gPSBpZDtcbiAgICBjb25zdCBtID0gKFxuICAgICAgdHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gTW9kZWwuYnVpbGQob2IsIGNsYXp6KSA6IG5ldyBjbGF6eihvYilcbiAgICApIGFzIE07XG4gICAgbG9nLnNpbGx5KGBSZWJ1aWxkaW5nIG1vZGVsICR7bS5jb25zdHJ1Y3Rvci5uYW1lfSBpZCAke2lkfWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5rZXlzKG0pLnJlZHVjZSgoYWNjdW06IE0sIGtleSkgPT4ge1xuICAgICAgKGFjY3VtIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tleV0gPVxuICAgICAgICBvYmpbTW9kZWwuY29sdW1uTmFtZShhY2N1bSwga2V5IGFzIGFueSldO1xuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sIG0pO1xuXG4gICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgcmUtYWRkaW5nIHRyYW5zaWVudCBwcm9wZXJ0aWVzOiAke09iamVjdC5rZXlzKHRyYW5zaWVudCkuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBPYmplY3QuZW50cmllcyh0cmFuc2llbnQpLmZvckVhY2goKFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgaWYgKGtleSBpbiByZXN1bHQgJiYgKHJlc3VsdCBhcyBhbnkpW2tleV0gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBUcmFuc2llbnQgcHJvcGVydHkgJHtrZXl9IGFscmVhZHkgZXhpc3RzIG9uIG1vZGVsICR7bS5jb25zdHJ1Y3Rvci5uYW1lfS4gc2hvdWxkIGJlIGltcG9zc2libGVgXG4gICAgICAgICAgKTtcbiAgICAgICAgcmVzdWx0W2tleSBhcyBrZXlvZiBNXSA9IHZhbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBjcmVhdGVQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApIHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMuY3JlYXRlUHJlZml4KTtcbiAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gTW9kZWwudGFibGVOYW1lKHRhYmxlTmFtZSk7XG4gICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsKTtcblxuICAgIHJldHVybiBbdGFibGVOYW1lLCBpZCwgcmVjb3JkLCAuLi5jdHhBcmdzXSBhcyBbXG4gICAgICBDb25zdHJ1Y3RvcjxNPixcbiAgICAgIFByaW1hcnlLZXlUeXBlLFxuICAgICAgUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAgIC4uLmFueVtdLFxuICAgICAgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIF07XG4gIH1cblxuICBvdmVycmlkZSB1cGRhdGVQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBhbnlbXSB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZVByZWZpeCk7XG4gICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbCk7XG5cbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uY3R4QXJnc10gYXMgW1xuICAgICAgQ29uc3RydWN0b3I8TT4sXG4gICAgICBQcmltYXJ5S2V5VHlwZSxcbiAgICAgIFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgICAuLi5hbnlbXSxcbiAgICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBdO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGNyZWF0ZUFsbFByZWZpeDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhYmxlTmFtZTogQ29uc3RydWN0b3I8TT4sXG4gICAgaWRzOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IFsuLi5hbnksIEZhYnJpY0NvbnRyYWN0Q29udGV4dF1cbiAgKTogKHN0cmluZyB8IHN0cmluZ1tdIHwgbnVtYmVyW10gfCBSZWNvcmQ8c3RyaW5nLCBhbnk+W10pW10ge1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuXG4gICAgY29uc3QgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHQgPSBhcmdzLnBvcCgpO1xuXG4gICAgY29uc3QgcmVjb3JkcyA9IGlkcy5tYXAoKGlkLCBjb3VudCkgPT4ge1xuICAgICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gTW9kZWwudGFibGVOYW1lKHRhYmxlTmFtZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWxzW2NvdW50XSk7XG4gICAgICByZXR1cm4gcmVjb3JkO1xuICAgIH0pO1xuICAgIHJldHVybiBbdGFibGVOYW1lLCBpZHMsIHJlY29yZHMsIGN0eCBhcyBhbnldO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHVwZGF0ZUFsbFByZWZpeDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhYmxlTmFtZTogQ29uc3RydWN0b3I8TT4sXG4gICAgaWRzOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IFsuLi5hbnksIEZhYnJpY0NvbnRyYWN0Q29udGV4dF1cbiAgKSB7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG5cbiAgICBjb25zdCBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCA9IGFyZ3MucG9wKCk7XG5cbiAgICBjb25zdCByZWNvcmRzID0gaWRzLm1hcCgoaWQsIGNvdW50KSA9PiB7XG4gICAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSBNb2RlbC50YWJsZU5hbWUodGFibGVOYW1lKTtcbiAgICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbHNbY291bnRdKTtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkcywgcmVjb3JkcywgY3R4IGFzIGFueV07XG4gIH1cblxuICBvdmVycmlkZSBwYXJzZUVycm9yPEUgZXh0ZW5kcyBCYXNlRXJyb3I+KFxuICAgIGVycjogRXJyb3IgfCBzdHJpbmcsXG4gICAgcmVhc29uPzogc3RyaW5nXG4gICk6IEUge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdEFkYXB0ZXIucGFyc2VFcnJvcihyZWFzb24gfHwgZXJyKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBsb2dDdHg8XG4gICAgQVJHUyBleHRlbmRzIGFueVtdID0gYW55W10sXG4gICAgTUVUSE9EIGV4dGVuZHMgTWV0aG9kT3JPcGVyYXRpb24gPSBNZXRob2RPck9wZXJhdGlvbixcbiAgPihcbiAgICBhcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPixcbiAgICBvcGVyYXRpb246IE1FVEhPRFxuICApOiBGYWJyaWNDb250ZXh0dWFsaXplZEFyZ3M8QVJHUywgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlPjtcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGxvZ0N0eDxcbiAgICBBUkdTIGV4dGVuZHMgYW55W10gPSBhbnlbXSxcbiAgICBNRVRIT0QgZXh0ZW5kcyBNZXRob2RPck9wZXJhdGlvbiA9IE1ldGhvZE9yT3BlcmF0aW9uLFxuICA+KFxuICAgIGFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+LFxuICAgIG9wZXJhdGlvbjogTUVUSE9ELFxuICAgIGFsbG93Q3JlYXRlOiBmYWxzZVxuICApOiBGYWJyaWNDb250ZXh0dWFsaXplZEFyZ3M8QVJHUywgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlPjtcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGxvZ0N0eDxcbiAgICBBUkdTIGV4dGVuZHMgYW55W10gPSBhbnlbXSxcbiAgICBNRVRIT0QgZXh0ZW5kcyBNZXRob2RPck9wZXJhdGlvbiA9IE1ldGhvZE9yT3BlcmF0aW9uLFxuICA+KFxuICAgIGFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+LFxuICAgIG9wZXJhdGlvbjogTUVUSE9ELFxuICAgIGFsbG93Q3JlYXRlOiB0cnVlLFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8RmxhZ3NPZjxGYWJyaWNDb250cmFjdENvbnRleHQ+PlxuICApOiBQcm9taXNlPFxuICAgIEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+XG4gID47XG4gIHByb3RlY3RlZCBvdmVycmlkZSBsb2dDdHg8XG4gICAgQVJHUyBleHRlbmRzIGFueVtdID0gYW55W10sXG4gICAgTUVUSE9EIGV4dGVuZHMgTWV0aG9kT3JPcGVyYXRpb24gPSBNZXRob2RPck9wZXJhdGlvbixcbiAgPihcbiAgICBhcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPixcbiAgICBvcGVyYXRpb246IE1FVEhPRCxcbiAgICBhbGxvd0NyZWF0ZTogYm9vbGVhbiA9IGZhbHNlLFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8RmxhZ3NPZjxGYWJyaWNDb250cmFjdENvbnRleHQ+PiB8IEN0eFxuICApOlxuICAgIHwgUHJvbWlzZTxcbiAgICAgICAgRmFicmljQ29udGV4dHVhbGl6ZWRBcmdzPEFSR1MsIE1FVEhPRCBleHRlbmRzIHN0cmluZyA/IHRydWUgOiBmYWxzZT5cbiAgICAgID5cbiAgICB8IEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+IHtcbiAgICBpZiAoIWFsbG93Q3JlYXRlKVxuICAgICAgcmV0dXJuIHN1cGVyLmxvZ0N0eDxBUkdTLCBNRVRIT0Q+KFxuICAgICAgICBhcmdzLFxuICAgICAgICBvcGVyYXRpb24gYXMgYW55LFxuICAgICAgICBhbGxvd0NyZWF0ZSBhcyBhbnksXG4gICAgICAgIG92ZXJyaWRlcyBhcyBhbnlcbiAgICAgICkgYXMgYW55O1xuXG4gICAgcmV0dXJuIHN1cGVyLmxvZ0N0eFxuICAgICAgLmNhbGwodGhpcywgYXJncywgb3BlcmF0aW9uIGFzIGFueSwgYWxsb3dDcmVhdGUsIG92ZXJyaWRlcyBhcyBhbnkpXG4gICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgIGlmICghKHJlcy5jdHggaW5zdGFuY2VvZiBGYWJyaWNDb250cmFjdENvbnRleHQpKVxuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBJbnZhbGlkIGNvbnRleHQgYmluZGluZ2ApO1xuICAgICAgICBpZiAoIXJlcy5jdHguc3R1YikgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE1pc3NpbmcgU3R1YmApO1xuICAgICAgICBpZiAoIXJlcy5jdHguaWRlbnRpdHkpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBNaXNzaW5nIElkZW50aXR5YCk7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHJlcywge1xuICAgICAgICAgIHN0dWI6IHJlcy5jdHguc3R1YixcbiAgICAgICAgICBpZGVudGl0eTogcmVzLmN0eC5pZGVudGl0eSxcbiAgICAgICAgfSk7XG4gICAgICB9KSBhcyBhbnk7XG4gIH1cblxuICAvLyBvdmVycmlkZSBsb2dDdHg8XG4gIC8vICAgQVJHUyBleHRlbmRzIGFueVtdID0gYW55W10sXG4gIC8vICAgTUVUSE9EIGV4dGVuZHMgTWV0aG9kT3JPcGVyYXRpb24gPSBNZXRob2RPck9wZXJhdGlvbixcbiAgLy8gPihcbiAgLy8gICBhcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPixcbiAgLy8gICBtZXRob2Q6IE1FVEhPRFxuICAvLyApOiBDb250ZXh0dWFsaXplZEFyZ3M8XG4gIC8vICAgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAvLyAgIEFSR1MsXG4gIC8vICAgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlXG4gIC8vID4gJiB7XG4gIC8vICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgLy8gICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gIC8vIH07XG4gIC8vIG92ZXJyaWRlIGxvZ0N0eDxcbiAgLy8gICBBUkdTIGV4dGVuZHMgYW55W10gPSBhbnlbXSxcbiAgLy8gICBNRVRIT0QgZXh0ZW5kcyBNZXRob2RPck9wZXJhdGlvbiA9IE1ldGhvZE9yT3BlcmF0aW9uLFxuICAvLyA+KFxuICAvLyAgIGFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+LFxuICAvLyAgIG1ldGhvZDogTUVUSE9ELFxuICAvLyAgIGFsbG93Q3JlYXRlOiBmYWxzZSxcbiAgLy8gICBvdmVycmlkZXM/OiBQYXJ0aWFsPEZhYnJpY0NvbnRyYWN0RmxhZ3M+XG4gIC8vICk6IENvbnRleHR1YWxpemVkQXJnczxcbiAgLy8gICBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gIC8vICAgQVJHUyxcbiAgLy8gICBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2VcbiAgLy8gPiAmIHtcbiAgLy8gICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAvLyAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gfTtcbiAgLy8gb3ZlcnJpZGUgbG9nQ3R4PFxuICAvLyAgIEFSR1MgZXh0ZW5kcyBhbnlbXSA9IGFueVtdLFxuICAvLyAgIE1FVEhPRCBleHRlbmRzIE1ldGhvZE9yT3BlcmF0aW9uID0gTWV0aG9kT3JPcGVyYXRpb24sXG4gIC8vID4oXG4gIC8vICAgYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4sXG4gIC8vICAgbWV0aG9kOiBNRVRIT0QsXG4gIC8vICAgYWxsb3dDcmVhdGU6IHRydWUsXG4gIC8vICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGYWJyaWNDb250cmFjdEZsYWdzPlxuICAvLyApOiBQcm9taXNlPFxuICAvLyAgIENvbnRleHR1YWxpemVkQXJnczxcbiAgLy8gICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgLy8gICAgIEFSR1MsXG4gIC8vICAgICBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2VcbiAgLy8gICA+ICYge1xuICAvLyAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgLy8gICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gICB9XG4gIC8vID47XG4gIC8vIG92ZXJyaWRlIGxvZ0N0eDxcbiAgLy8gICBBUkdTIGV4dGVuZHMgYW55W10gPSBhbnlbXSxcbiAgLy8gICBNRVRIT0QgZXh0ZW5kcyBNZXRob2RPck9wZXJhdGlvbiA9IE1ldGhvZE9yT3BlcmF0aW9uLFxuICAvLyA+KFxuICAvLyAgIGFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+LFxuICAvLyAgIG1ldGhvZDogTUVUSE9ELFxuICAvLyAgIGFsbG93Q3JlYXRlOiBib29sZWFuID0gZmFsc2UsXG4gIC8vICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGYWJyaWNDb250cmFjdEZsYWdzPlxuICAvLyApOlxuICAvLyAgIHwgKENvbnRleHR1YWxpemVkQXJnczxcbiAgLy8gICAgICAgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAvLyAgICAgICBBUkdTLFxuICAvLyAgICAgICBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2VcbiAgLy8gICAgID4gJiB7XG4gIC8vICAgICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gIC8vICAgICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gICAgIH0pXG4gIC8vICAgfCBQcm9taXNlPFxuICAvLyAgICAgICBDb250ZXh0dWFsaXplZEFyZ3M8XG4gIC8vICAgICAgICAgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAvLyAgICAgICAgIEFSR1MsXG4gIC8vICAgICAgICAgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlXG4gIC8vICAgICAgID4gJiB7XG4gIC8vICAgICAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgLy8gICAgICAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gIC8vICAgICAgIH1cbiAgLy8gICAgID4ge1xuICAvLyAgIGNvbnN0IHJlc3BvbnNlID0gc3VwZXIubG9nQ3R4KFxuICAvLyAgICAgYXJncyxcbiAgLy8gICAgIG1ldGhvZCxcbiAgLy8gICAgIGFsbG93Q3JlYXRlIGFzIGFueSxcbiAgLy8gICAgIG92ZXJyaWRlcyBhcyBhbnlcbiAgLy8gICApIGFzXG4gIC8vICAgICB8IENvbnRleHR1YWxpemVkQXJnczxcbiAgLy8gICAgICAgICBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gIC8vICAgICAgICAgQVJHUyxcbiAgLy8gICAgICAgICBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2VcbiAgLy8gICAgICAgPlxuICAvLyAgICAgfCBQcm9taXNlPFxuICAvLyAgICAgICAgIENvbnRleHR1YWxpemVkQXJnczxcbiAgLy8gICAgICAgICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgLy8gICAgICAgICAgIEFSR1MsXG4gIC8vICAgICAgICAgICBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2VcbiAgLy8gICAgICAgICA+XG4gIC8vICAgICAgID47XG4gIC8vXG4gIC8vICAgY29uc3QgYXR0YWNoID0gPFQgZXh0ZW5kcyBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPj4oXG4gIC8vICAgICByZXNwOiBUXG4gIC8vICAgKSA9PlxuICAvLyAgICAgT2JqZWN0LmFzc2lnbihyZXNwLCB7XG4gIC8vICAgICAgIHN0dWI6IHJlc3AuY3R4LnN0dWIsXG4gIC8vICAgICAgIGlkZW50aXR5OiByZXNwLmN0eC5pZGVudGl0eSxcbiAgLy8gICAgIH0pIGFzIFQgJiB7XG4gIC8vICAgICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gIC8vICAgICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gICAgIH07XG4gIC8vXG4gIC8vICAgcmV0dXJuIHJlc3BvbnNlIGluc3RhbmNlb2YgUHJvbWlzZVxuICAvLyAgICAgPyByZXNwb25zZS50aGVuKGF0dGFjaClcbiAgLy8gICAgIDogYXR0YWNoKHJlc3BvbnNlKTtcbiAgLy8gfVxuXG4gIHN0YXRpYyBvdmVycmlkZSBwYXJzZUVycm9yPEUgZXh0ZW5kcyBCYXNlRXJyb3I+KGVycjogRXJyb3IgfCBzdHJpbmcpOiBFIHtcbiAgICAvLyBpZiAoXG4gICAgLy8gICBNSVNTSU5HX1BSSVZBVEVfREFUQV9SRUdFWC50ZXN0KFxuICAgIC8vICAgICB0eXBlb2YgZXJyID09PSBcInN0cmluZ1wiID8gZXJyIDogZXJyLm1lc3NhZ2VcbiAgICAvLyAgIClcbiAgICAvLyApXG4gICAgLy8gICByZXR1cm4gbmV3IFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzKGVycikgYXMgRTtcbiAgICBjb25zdCBtc2cgPSB0eXBlb2YgZXJyID09PSBcInN0cmluZ1wiID8gZXJyIDogZXJyLm1lc3NhZ2U7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhOb3RGb3VuZEVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE5vdEZvdW5kRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQ29uZmxpY3RFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKEJhZFJlcXVlc3RFcnJvci5uYW1lKSlcbiAgICAgIHJldHVybiBuZXcgQmFkUmVxdWVzdEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKFF1ZXJ5RXJyb3IubmFtZSkpIHJldHVybiBuZXcgUXVlcnlFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhQYWdpbmdFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBQYWdpbmdFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhVbnN1cHBvcnRlZEVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBVbnN1cHBvcnRlZEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKE1pZ3JhdGlvbkVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE1pZ3JhdGlvbkVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKE9ic2VydmVyRXJyb3IubmFtZSkpIHJldHVybiBuZXcgT2JzZXJ2ZXJFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhBdXRob3JpemF0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IEF1dGhvcml6YXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhGb3JiaWRkZW5FcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBGb3JiaWRkZW5FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhDb25uZWN0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhTZXJpYWxpemF0aW9uRXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IFNlcmlhbGl6YXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhcIm5vIGxlZGdlciBjb250ZXh0XCIpKVxuICAgICAgcmV0dXJuIG5ldyBNaXNzaW5nQ29udGV4dEVycm9yKFxuICAgICAgICBgTm8gY29udGV4dCBmb3VuZC4gdGhpcyBjYW4gYmUgY2F1c2VkIGJ5IGRlYnVnZ2luZzogJHttc2d9YFxuICAgICAgKSBhcyBFO1xuXG4gICAgcmV0dXJuIG5ldyBJbnRlcm5hbEVycm9yKGVycikgYXMgRTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1ldGhvZCBmb3IgZGVjb3JhdGlvbiBvdmVycmlkZXNcbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzL2V4dGVuZHMgZGVjYWYgZGVjb3JhdGlvbiB3aXRoIEZhYnJpYy1zcGVjaWZpYyBmdW5jdGlvbmFsaXR5XG4gICAqIEBzdGF0aWNcbiAgICogQG92ZXJyaWRlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgZGVjb3JhdGlvbigpOiB2b2lkIHtcbiAgICBzdXBlci5kZWNvcmF0aW9uKCk7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuQ1JFQVRFRF9CWSlcbiAgICAgIC5kZWZpbmUoXG4gICAgICAgIG9uQ3JlYXRlKGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5DUkVBVEVEX0JZLCB7fSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuVVBEQVRFRF9CWSlcbiAgICAgIC5kZWZpbmUoXG4gICAgICAgIG9uQ3JlYXRlVXBkYXRlKGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFBlcnNpc3RlbmNlS2V5cy5VUERBVEVEX0JZLCB7fSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuQ09MVU1OKVxuICAgICAgLmV4dGVuZChGYWJyaWNQcm9wZXJ0eSgpKVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKFZhbGlkYXRpb25LZXlzLkRBVEUpXG4gICAgICAuZXh0ZW5kKGZ1bmN0aW9uIGZhYnJpY1Byb3BlcnR5KCkge1xuICAgICAgICByZXR1cm4gKHRhcmdldDogYW55LCBwcm9wPzogYW55KSA9PiB7XG4gICAgICAgICAgUHJvcGVydHkocHJvcCwgXCJzdHJpbmc6ZGF0ZVwiKSh0YXJnZXQsIHByb3ApO1xuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKFBlcnNpc3RlbmNlS2V5cy5UQUJMRSlcbiAgICAgIC5leHRlbmQoZnVuY3Rpb24gdGFibGUob2JqOiBhbnkpIHtcbiAgICAgICAgY29uc3QgY2hhaW46IGFueVtdID0gW107XG4gICAgICAgIGxldCBjdXJyZW50ID1cbiAgICAgICAgICB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgID8gTWV0YWRhdGEuY29uc3RyKG9iailcbiAgICAgICAgICAgIDogTWV0YWRhdGEuY29uc3RyKG9iai5jb25zdHJ1Y3Rvcik7XG5cbiAgICAgICAgd2hpbGUgKGN1cnJlbnQgJiYgY3VycmVudCAhPT0gT2JqZWN0ICYmIGN1cnJlbnQucHJvdG90eXBlKSB7XG4gICAgICAgICAgY2hhaW4ucHVzaChjdXJyZW50KTtcbiAgICAgICAgICBjdXJyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGN1cnJlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5sb2coY2hhaW4ubWFwKChjKSA9PiBjLm5hbWUgfHwgYykpO1xuXG4gICAgICAgIC8vIEFwcGx5IGZyb20gdGhlIGJhc2UgY2xhc3MgZG93biB0byB0aGUgZGVjb3JhdGVkIGNsYXNzXG4gICAgICAgIHdoaWxlIChjaGFpbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgY29uc3RydWN0b3IgPSBjaGFpbi5wb3AoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgQ2FsbGluZyBvbiAke2NvbnN0cnVjdG9yLm5hbWV9YCk7XG4gICAgICAgICAgRmFicmljT2JqZWN0KCkoY29uc3RydWN0b3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIEZhYnJpY09iamVjdCgpKG9iaik7XG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG4gIH1cbn1cblxuRmFicmljQ29udHJhY3RBZGFwdGVyLmRlY29yYXRpb24oKTtcbkFkYXB0ZXIuc2V0Q3VycmVudChGYWJyaWNGbGF2b3VyKTtcbiIsIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHtcbiAgSlNPTlNlcmlhbGl6ZXIsXG4gIE1vZGVsLFxuICBNb2RlbEtleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGV0ZXJtaW5pc3RpYyBKU09OIHNlcmlhbGl6ZXIgZm9yIEZhYnJpYyBtb2RlbHNcbiAqIEBzdW1tYXJ5IEVuc3VyZXMgc3RhYmxlLCBkZXRlcm1pbmlzdGljIEpTT04gb3V0cHV0IGJ5IHNvcnRpbmcgb2JqZWN0IGtleXMgcmVjdXJzaXZlbHkgYmVmb3JlIHN0cmluZ2lmaWNhdGlvbiwgd2hpY2ggaXMgaW1wb3J0YW50IGZvciBGYWJyaWMgZW5kb3JzZW1lbnQgYW5kIGhhc2hpbmcuIEV4dGVuZHMgSlNPTlNlcmlhbGl6ZXIgdG8gcGx1ZyBpbnRvIGV4aXN0aW5nIERlY2FmIG1vZGVsIHNlcmlhbGl6YXRpb24gZmxvdy5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIERlY2FmIE1vZGVsIHN1YnR5cGUgc2VyaWFsaXplZCBieSB0aGlzIGluc3RhbmNlXG4gKiBAcGFyYW0ge3ZvaWR9IFtjb25zdHJ1Y3Rvcl0gTm8gcHVibGljIGNvbnN0cnVjdG9yIGFyZ3VtZW50c1xuICogQGNsYXNzIERldGVybWluaXN0aWNTZXJpYWxpemVyXG4gKiBAZXhhbXBsZVxuICogY29uc3Qgc2VyaWFsaXplciA9IG5ldyBEZXRlcm1pbmlzdGljU2VyaWFsaXplcjxNeU1vZGVsPigpO1xuICogY29uc3QganNvbiA9IHNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsKTtcbiAqIGNvbnN0IHJlYnVpbHQgPSBzZXJpYWxpemVyLmRlc2VyaWFsaXplKGpzb24pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgRFMgYXMgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXJcbiAqICAgQ2FsbGVyLT4+RFM6IHNlcmlhbGl6ZShtb2RlbClcbiAqICAgRFMtPj5EUzogcHJlU2VyaWFsaXplKG1vZGVsKVxuICogICBEUy0+PkRTOiBzb3J0LWtleXMtcmVjdXJzaXZlXG4gKiAgIERTLT4+RFM6IGpzb24tc3RyaW5naWZ5LWRldGVybWluaXN0aWNcbiAqICAgRFMtLT4+Q2FsbGVyOiBzdHJpbmdcbiAqICAgQ2FsbGVyLT4+RFM6IGRlc2VyaWFsaXplKHN0cmluZylcbiAqICAgRFMtLT4+Q2FsbGVyOiBtb2RlbFxuICovXG5leHBvcnQgY2xhc3MgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbj4gZXh0ZW5kcyBKU09OU2VyaWFsaXplcjxNPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHByZVNlcmlhbGl6ZShtb2RlbDogTSkge1xuICAgIC8vIFRPRE86IG5lc3RlZCBwcmVzZXJpYWxpemF0aW9uIChzbyBpbmNyZWFzZSBwZXJmb3JtYW5jZSB3aGVuIGRlc2VyaWFsaXppbmcpXG4gICAgLy8gVE9ETzogVmVyaWZ5IHdoeSB0aGVyZSBpcyBubyBtZXRhZGF0YVxuICAgIGNvbnN0IHRvU2VyaWFsaXplOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gT2JqZWN0LmFzc2lnbih7fSwgbW9kZWwpO1xuICAgIGxldCBtZXRhZGF0YTtcbiAgICB0cnkge1xuICAgICAgbWV0YWRhdGEgPSBNZXRhZGF0YS5tb2RlbE5hbWUobW9kZWwuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3IpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBtZXRhZGF0YSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdG9TZXJpYWxpemVbTW9kZWxLZXlzLkFOQ0hPUl0gPSBtZXRhZGF0YSB8fCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuXG4gICAgY29uc3QgcHJlU2VyaWFsaXplID0gZnVuY3Rpb24gcHJlU2VyaWFsaXplKFxuICAgICAgdGhpczogRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8YW55PixcbiAgICAgIG9iajogYW55XG4gICAgKTogYW55IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBpZiAodHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIikgcmV0dXJuIG9iajtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHJldHVybiBvYmoubWFwKChvKSA9PiBwcmVTZXJpYWxpemUuY2FsbChzZWxmLCBvKSk7XG4gICAgICByZXR1cm4gdGhpcy5wcmVTZXJpYWxpemUuY2FsbCh0aGlzLCBvYmopO1xuICAgIH0uYmluZCh0aGlzKTtcblxuICAgIE1vZGVsLnJlbGF0aW9ucyhtb2RlbCkuZm9yRWFjaCgocikgPT4ge1xuICAgICAgdG9TZXJpYWxpemVbcl0gPSBwcmVTZXJpYWxpemUodG9TZXJpYWxpemVbcl0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0b1NlcmlhbGl6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZWJ1aWxkcyBhIG1vZGVsIGZyb20gYSBzZXJpYWxpemF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIGl0IGZhaWxzIHRvIHBhcnNlIHRoZSBzdHJpbmcsIG9yIHRvIGJ1aWxkIHRoZSBtb2RlbFxuICAgKi9cbiAgb3ZlcnJpZGUgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcpOiBNIHtcbiAgICBjb25zdCBkZXNlcmlhbGl6YXRpb24gPSBKU09OLnBhcnNlKHN0cik7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gZGVzZXJpYWxpemF0aW9uW01vZGVsS2V5cy5BTkNIT1JdO1xuICAgIGlmICghY2xhc3NOYW1lKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgY2xhc3MgcmVmZXJlbmNlIGluIHNlcmlhbGl6ZWQgbW9kZWxcIik7XG4gICAgY29uc3QgbW9kZWw6IE0gPSBNb2RlbC5idWlsZChkZXNlcmlhbGl6YXRpb24sIGNsYXNzTmFtZSkgYXMgdW5rbm93biBhcyBNO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2VyaWFsaXplIGEgbW9kZWwgaW50byBhIGRldGVybWluaXN0aWMgSlNPTiBzdHJpbmdcbiAgICogQHN1bW1hcnkgUHJlcGFyZXMgdGhlIG1vZGVsIHdpdGggcHJlU2VyaWFsaXplLCBzb3J0cyBrZXlzIHJlY3Vyc2l2ZWx5LCBhbmQgc3RyaW5naWZpZXMgZGV0ZXJtaW5pc3RpY2FsbHkgZm9yIHN0YWJsZSBvcmRlcmluZ1xuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHNlcmlhbGl6ZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IERldGVybWluaXN0aWMgSlNPTiByZXByZXNlbnRhdGlvbiBvZiB0aGUgbW9kZWxcbiAgICovXG4gIG92ZXJyaWRlIHNlcmlhbGl6ZShtb2RlbDogTSk6IHN0cmluZyB7XG4gICAgY29uc3Qgc3RyaW5naWZ5ID0gcmVxdWlyZShcImpzb24tc3RyaW5naWZ5LWRldGVybWluaXN0aWNcIik7XG4gICAgY29uc3Qgc29ydEtleXNSZWN1cnNpdmUgPSByZXF1aXJlKFwic29ydC1rZXlzLXJlY3Vyc2l2ZVwiKTtcbiAgICByZXR1cm4gc3RyaW5naWZ5KHNvcnRLZXlzUmVjdXJzaXZlKHRoaXMucHJlU2VyaWFsaXplKG1vZGVsKSkpO1xuICB9XG59XG4iLCIvKipcbiAqIEVudW0gcmVwcmVzZW50aW5nIHRoZSBldmVudHMgZW1pdHRlZCBieSBhbiBFUkMyMCBjb250cmFjdC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhpcyBlbnVtIGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHNwZWNpZmljIGV2ZW50cyB0aGF0IGNhbiBiZSBlbWl0dGVkIGJ5IGFuIEVSQzIwIGNvbnRyYWN0LlxuICogVGhlIGV2ZW50cyBhcmUgbmFtZWQgYWNjb3JkaW5nIHRvIHRoZSBFSVAtMjAgc3RhbmRhcmQuXG4gKi9cbmV4cG9ydCBlbnVtIEVSQzIwRXZlbnRzIHtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGB0cmFuc2ZlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIHN1Y2Nlc3NmdWxseS5cbiAgICpcbiAgICogQHBhcmFtIGZyb20gLSBUaGUgYWRkcmVzcyBvZiB0aGUgc2VuZGVyLlxuICAgKiBAcGFyYW0gdG8gLSBUaGUgYWRkcmVzcyBvZiB0aGUgcmVjaXBpZW50LlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgYW1vdW50IG9mIHRva2VucyB0cmFuc2ZlcnJlZC5cbiAgICovXG4gIFRSQU5TRkVSID0gXCJUcmFuc2ZlclwiLFxuXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYW4gYGFwcHJvdmVgIGZ1bmN0aW9uIGlzIGNhbGxlZCBzdWNjZXNzZnVsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBvd25lciAtIFRoZSBhZGRyZXNzIG9mIHRoZSB0b2tlbiBvd25lci5cbiAgICogQHBhcmFtIHNwZW5kZXIgLSBUaGUgYWRkcmVzcyBvZiB0aGUgYXBwcm92ZWQgc3BlbmRlci5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiB0b2tlbnMgYXBwcm92ZWQgZm9yIHRoZSBzcGVuZGVyLlxuICAgKi9cbiAgQVBQUk9WQUwgPSBcIkFwcHJvdmFsXCIsXG59XG4iLCJpbXBvcnQgeyBNb2RlbCwgdHlwZSBNb2RlbEFyZyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGNvbHVtbiwgY3JlYXRlZEF0LCB1cGRhdGVkQXQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IGRlc2NyaXB0aW9uLCB1c2VzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUHJvcGVydHkgfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuXG5AdXNlcyhGYWJyaWNGbGF2b3VyKVxuZXhwb3J0IGNsYXNzIEZhYnJpY0Jhc2VNb2RlbCBleHRlbmRzIE1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBvcmlnaW5hbCB0aW1lc3RhbXAgb2YgY3JlYXRpb25cIilcbiAgQGNvbHVtbigpXG4gIEBjcmVhdGVkQXQoKVxuICBjcmVhdGVkQXQhOiBEYXRlO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdGltZXN0YW1wIG9mIHRoZSBsYXN0IHVwZGF0ZVwiKVxuICBAY29sdW1uKClcbiAgQHVwZGF0ZWRBdCgpXG4gIHVwZGF0ZWRBdCE6IERhdGU7XG5cbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2RlbFwiKVxuICBAY29sdW1uKClcbiAgQHZlcnNpb24oKVxuICB2ZXJzaW9uITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0Jhc2VNb2RlbD4pIHtcbiAgICBzdXBlcihhcmcpO1xuICB9XG59XG4iLCJpbXBvcnQgeyB0eXBlIE1vZGVsQXJnIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgY29sdW1uLCBjcmVhdGVkQnksIHVwZGF0ZWRCeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24sIHVzZXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0ZsYXZvdXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBGYWJyaWNCYXNlTW9kZWwgfSBmcm9tIFwiLi9GYWJyaWNCYXNlTW9kZWxcIjtcblxuQHVzZXMoRmFicmljRmxhdm91cilcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNJZGVudGlmaWVkQmFzZU1vZGVsIGV4dGVuZHMgRmFicmljQmFzZU1vZGVsIHtcbiAgQGRlc2NyaXB0aW9uKFwiU3RvcmVzIHRoZSBjcmVhdG9yXCIpXG4gIEBjb2x1bW4oKVxuICBAY3JlYXRlZEJ5KClcbiAgY3JlYXRlZEJ5ITogc3RyaW5nO1xuXG4gIEBkZXNjcmlwdGlvbihcIlN0b3JlcyB0aGUgdXNlciB0aGF0IGxhc3QgdXBkYXRlZCB0aGUgbW9kZWxcIilcbiAgQGNvbHVtbigpXG4gIEB1cGRhdGVkQnkoKVxuICB1cGRhdGVkQnkhOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPEZhYnJpY0lkZW50aWZpZWRCYXNlTW9kZWw+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQmFzZU1vZGVsLCBjb2x1bW4sIHBrIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBtb2RlbCwgdHlwZSBNb2RlbEFyZywgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBkZXNjcmlwdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBJZGVudGl0eSBjcmVkZW50aWFsIG1vZGVsIHN0b3JpbmcgY3J5cHRvZ3JhcGhpYyBtYXRlcmlhbHNcbiAqIEBzdW1tYXJ5IEhvbGRzIGNlcnRpZmljYXRlIGNoYWluIGFuZCBwcml2YXRlIGtleSBpbmZvcm1hdGlvbiBmb3IgYSBGYWJyaWMgaWRlbnRpdHksIG1hbmFnZWQgYXMgYSBzZXBhcmF0ZSBlbnRpdHkgbGlua2VkIGZyb20gSWRlbnRpdHlcbiAqIEBwYXJhbSB7TW9kZWxBcmc8SWRlbnRpdHlDcmVkZW50aWFscz59IFthcmddIC0gT3B0aW9uYWwgaW5pdGlhbGl6YXRpb24gb2JqZWN0IHVzZWQgdG8gcG9wdWxhdGUgbW9kZWwgZmllbGRzXG4gKiBAY2xhc3MgSWRlbnRpdHlDcmVkZW50aWFsc1xuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBjcmVkZW50aWFscyBlbnRyeVxuICogY29uc3QgY3JlZHMgPSBuZXcgSWRlbnRpdHlDcmVkZW50aWFscyh7IGlkOiBcImNyZWRzMVwiLCBjZXJ0aWZpY2F0ZTogXCIuLi5cIiwgcm9vdENlcnRpZmljYXRlOiBcIi4uLlwiLCBwcml2YXRlS2V5OiBcIi4uLlwiIH0pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgTW9kZWwgYXMgSWRlbnRpdHlDcmVkZW50aWFsc1xuICogICBBcHAtPj5Nb2RlbDogbmV3IElkZW50aXR5Q3JlZGVudGlhbHMoeyBpZCwgY2VydGlmaWNhdGUsIHJvb3RDZXJ0aWZpY2F0ZSwgcHJpdmF0ZUtleSB9KVxuICogICBNb2RlbC0tPj5BcHA6IGluc3RhbmNlXG4gKiBAc2VlIG1vZGVsXG4gKi9cbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgSWRlbnRpdHlDcmVkZW50aWFscyBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGNyZWRlbnRpYWxzIHJlY29yZFxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSBmb3IgcmVmZXJlbmNpbmcgdGhpcyBjcmVkZW50aWFscyBlbnRyeVxuICAgKi9cbiAgQGRlc2NyaXB0aW9uKFwiVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGNyZWRlbnRpYWxzIHJlY29yZFwiKVxuICBAY29sdW1uKClcbiAgQHBrKClcbiAgaWQhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQRU0tZW5jb2RlZCBYLjUwOSBjZXJ0aWZpY2F0ZSBmb3IgdGhlIGlkZW50aXR5XG4gICAqIEBzdW1tYXJ5IExlYWYgY2VydGlmaWNhdGUgYXNzb2NpYXRlZCB3aXRoIHRoZSBpZGVudGl0eVxuICAgKi9cbiAgQGRlc2NyaXB0aW9uKFwiUEVNLWVuY29kZWQgWC41MDkgY2VydGlmaWNhdGUgZm9yIHRoZSBpZGVudGl0eVwiKVxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgY2VydGlmaWNhdGUhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQRU0tZW5jb2RlZCByb290IG9yIGludGVybWVkaWF0ZSBjZXJ0aWZpY2F0ZVxuICAgKiBAc3VtbWFyeSBSb290IG9mIHRydXN0IHVzZWQgdG8gdmFsaWRhdGUgdGhlIGxlYWYgY2VydGlmaWNhdGVcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlBFTS1lbmNvZGVkIHJvb3Qgb3IgaW50ZXJtZWRpYXRlIGNlcnRpZmljYXRlXCIpXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICByb290Q2VydGlmaWNhdGUhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQRU0tZW5jb2RlZCBwcml2YXRlIGtleSBtYXRlcmlhbFxuICAgKiBAc3VtbWFyeSBQcml2YXRlIGtleSBjb3JyZXNwb25kaW5nIHRvIHRoZSBpZGVudGl0eSBjZXJ0aWZpY2F0ZVxuICAgKi9cbiAgQGRlc2NyaXB0aW9uKFwiUEVNLWVuY29kZWQgcHJpdmF0ZSBrZXlcIilcbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIHByaXZhdGVLZXkhOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoYXJnPzogTW9kZWxBcmc8SWRlbnRpdHlDcmVkZW50aWFscz4pIHtcbiAgICBzdXBlcihhcmcpO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBCYXNlTW9kZWwsXG4gIENhc2NhZGUsXG4gIGNvbHVtbixcbiAgaW5kZXgsXG4gIG9uZVRvT25lLFxuICBwayxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBtb2RlbCwgdHlwZSBNb2RlbEFyZywgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBJZGVudGl0eUNyZWRlbnRpYWxzIH0gZnJvbSBcIi4vSWRlbnRpdHlDcmVkZW50aWFsc1wiO1xuaW1wb3J0IHsgSWRlbnRpdHlUeXBlIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZGVzY3JpcHRpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSWRlbnRpdHkgbW9kZWwgcmVwcmVzZW50aW5nIGEgRmFicmljIHdhbGxldCBlbnRyeVxuICogQHN1bW1hcnkgRW5jYXBzdWxhdGVzIGFuIGlkZW50aXR5IHN0b3JlZCBpbiBhIEZhYnJpYyB3YWxsZXQsIGluY2x1ZGluZyBpdHMgTVNQIGlkZW50aWZpZXIsIGNyZWRlbnRpYWwgbGlua2FnZSwgYW5kIHR5cGUgaW5mb3JtYXRpb24uIEJ1aWx0IG9uIEJhc2VNb2RlbCBmb3IgaW50ZWdyYXRpb24gd2l0aCBEZWNhZiB2YWxpZGF0aW9uIGFuZCBwZXJzaXN0ZW5jZS5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8SWRlbnRpdHk+fSBbYXJnXSAtIE9wdGlvbmFsIGluaXRpYWxpemF0aW9uIG9iamVjdCB1c2VkIHRvIHBvcHVsYXRlIG1vZGVsIGZpZWxkc1xuICogQGNsYXNzIElkZW50aXR5XG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgbmV3IGlkZW50aXR5IHJlZmVyZW5jaW5nIGV4aXN0aW5nIGNyZWRlbnRpYWxzXG4gKiBjb25zdCBpZCA9IG5ldyBJZGVudGl0eSh7IGlkOiBcInVzZXIxXCIsIG1zcElkOiBcIk9yZzFNU1BcIiwgdHlwZTogSWRlbnRpdHlUeXBlLlg1MDkgfSk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBNb2RlbCBhcyBJZGVudGl0eVxuICogICBBcHAtPj5Nb2RlbDogbmV3IElkZW50aXR5KHsgaWQsIG1zcElkLCB0eXBlIH0pXG4gKiAgIE1vZGVsLS0+PkFwcDogaW5zdGFuY2VcbiAqL1xuQG1vZGVsKClcbmV4cG9ydCBjbGFzcyBJZGVudGl0eSBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGlkZW50aXR5IGluIHRoZSB3YWxsZXRcbiAgICogQHN1bW1hcnkgUHJpbWFyeSBrZXkgdXNlZCB0byByZWZlcmVuY2UgdGhpcyBpZGVudGl0eSByZWNvcmRcbiAgICovXG4gIEBkZXNjcmlwdGlvbihcIlVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBpZGVudGl0eVwiKVxuICBAcGsoKVxuICBpZCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpbmsgdG8gdGhlIGlkZW50aXR5IGNyZWRlbnRpYWxzIHN0b3JlZCBzZXBhcmF0ZWx5XG4gICAqIEBzdW1tYXJ5IE9uZS10by1vbmUgcmVsYXRpb25zaGlwIHRvIHRoZSBjcmVkZW50aWFscyBlbnRpdHk7IGNhc2NhZGVzIG9uIHVwZGF0ZSBhbmQgZGVsZXRlXG4gICAqL1xuICBAb25lVG9PbmUoSWRlbnRpdHlDcmVkZW50aWFscywge1xuICAgIHVwZGF0ZTogQ2FzY2FkZS5DQVNDQURFLFxuICAgIGRlbGV0ZTogQ2FzY2FkZS5DQVNDQURFLFxuICB9KVxuICBjcmVkZW50aWFscyE6IElkZW50aXR5Q3JlZGVudGlhbHM7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNZW1iZXJzaGlwIFNlcnZpY2UgUHJvdmlkZXIgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBUaGUgTVNQIElEIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG9yZ2FuaXphdGlvbiB0aGF0IGlzc3VlZCB0aGlzIGlkZW50aXR5XG4gICAqL1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgQGluZGV4KClcbiAgbXNwSWQhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUeXBlIG9mIGlkZW50aXR5XG4gICAqIEBzdW1tYXJ5IEluZGljYXRlcyB0aGUgaWRlbnRpdHkgZW5jb2RpbmcvZm9ybWF0OyBkZWZhdWx0cyB0byBYLjUwOVxuICAgKi9cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIHR5cGU6IElkZW50aXR5VHlwZSA9IElkZW50aXR5VHlwZS5YNTA5O1xuXG4gIGNvbnN0cnVjdG9yKGFyZzogTW9kZWxBcmc8SWRlbnRpdHk+KSB7XG4gICAgc3VwZXIoYXJnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgSlNPTlNlcmlhbGl6ZXIsXG4gIE1vZGVsLFxuICBNb2RlbEtleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENsaWVudC1zaWRlIEpTT04gc2VyaWFsaXplciBmb3IgRGVjYWYgbW9kZWxzIHRhcmdldGluZyBIeXBlcmxlZGdlciBGYWJyaWNcbiAqIEBzdW1tYXJ5IEV4dGVuZHMgdGhlIGJhc2UgSlNPTlNlcmlhbGl6ZXIgdG8gZW1iZWQgbW9kZWwgbWV0YWRhdGEgKGFuY2hvcikgcmVxdWlyZWQgdG8gcmVjb25zdHJ1Y3QgaW5zdGFuY2VzIG9uIHRoZSBjbGllbnQsIGFuZCB0byBzYWZlbHkgc2VyaWFsaXplL2Rlc2VyaWFsaXplIEZhYnJpYy1ib3VuZCBtb2RlbHMuXG4gKiBAdGVtcGxhdGUgTSBleHRlbmRzIE1vZGVsIC0gVGhlIERlY2FmIG1vZGVsIHR5cGUgaGFuZGxlZCBieSB0aGlzIHNlcmlhbGl6ZXJcbiAqIEBwYXJhbSB7dm9pZH0gW2NvbnN0cnVjdG9yXSBObyBwdWJsaWMgY29uc3RydWN0b3IgYXJndW1lbnRzOyBwcm92aWRlZCBmb3IgZG9jdW1lbnRhdGlvbiBjb21wbGV0ZW5lc3NcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgQ2xpZW50U2VyaWFsaXplclxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHNlcmlhbGl6ZXIgPSBuZXcgQ2xpZW50U2VyaWFsaXplcjxVc2VyPigpO1xuICogY29uc3QganNvbiA9IHNlcmlhbGl6ZXIuc2VyaWFsaXplKG5ldyBVc2VyKHsgaWQ6IFwiMVwiLCBuYW1lOiBcIkFsaWNlXCIgfSkpO1xuICogY29uc3QgdXNlciA9IHNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoanNvbik7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBTZXJpYWxpemVyIGFzIENsaWVudFNlcmlhbGl6ZXJcbiAqICAgcGFydGljaXBhbnQgTW9kZWxcbiAqICAgQXBwLT4+U2VyaWFsaXplcjogc2VyaWFsaXplKG1vZGVsKVxuICogICBTZXJpYWxpemVyLT4+U2VyaWFsaXplcjogcHJlU2VyaWFsaXplKG1vZGVsKVxuICogICBTZXJpYWxpemVyLS0+PkFwcDogSlNPTiBzdHJpbmdcbiAqICAgQXBwLT4+U2VyaWFsaXplcjogZGVzZXJpYWxpemUoanNvbilcbiAqICAgU2VyaWFsaXplci0+PlNlcmlhbGl6ZXI6IEpTT04ucGFyc2UoanNvbilcbiAqICAgU2VyaWFsaXplci0+Pk1vZGVsOiBNb2RlbC5idWlsZChwYXJzZWQsIGFuY2hvcilcbiAqICAgTW9kZWwtLT4+QXBwOiBpbnN0YW5jZVxuICovXG5leHBvcnQgY2xhc3MgQ2xpZW50U2VyaWFsaXplcjxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgSlNPTlNlcmlhbGl6ZXI8TT4ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICB9XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZSBhIG1vZGVsIGZvciBKU09OIHNlcmlhbGl6YXRpb24gZW1iZWRkaW5nIGNsYXNzIGFuY2hvclxuICAgKiBAc3VtbWFyeSBDbG9uZXMgdGhlIG1vZGVsIGFuZCBpbmplY3RzIHRoZSBjbGFzcyBtZXRhZGF0YSBhbmNob3Igc28gaXQgY2FuIGJlIHJlY29uc3RydWN0ZWQgZHVyaW5nIGRlc2VyaWFsaXphdGlvbi4gRmFsbHMgYmFjayB0byBwcm92aWRlZCB0YWJsZSBuYW1lIGlmIG1ldGFkYXRhIGlzIG5vdCBhdmFpbGFibGUuXG4gICAqIEB0ZW1wbGF0ZSBNIC0gTW9kZWwgdHlwZSBoYW5kbGVkIGJ5IHRoaXMgc2VyaWFsaXplclxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHNlcmlhbGl6ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21vZGVsTmFtZV0gLSBPcHRpb25hbCB0YWJsZSBuYW1lIHRvIHVzZSB3aGVuIG1ldGFkYXRhIGNhbm5vdCBiZSBkZXJpdmVkXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGFueT59IEEgcGxhaW4gb2JqZWN0IHJlYWR5IHRvIGJlIEpTT04uc3RyaW5naWZ5J2RcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBwcmVTZXJpYWxpemUobW9kZWw6IE0sIG1vZGVsTmFtZT86IHN0cmluZykge1xuICAgIC8vIFRPRE86IG5lc3RlZCBwcmVzZXJpYWxpemF0aW9uIChzbyBpbmNyZWFzZSBwZXJmb3JtYW5jZSB3aGVuIGRlc2VyaWFsaXppbmcpXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgbGV0IG1ldGFkYXRhID0gTWV0YWRhdGEubW9kZWxOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yPE0+KTtcblxuICAgIGlmICghbWV0YWRhdGEgfHwgbWV0YWRhdGEgPT09IFwiT2JqZWN0XCIpXG4gICAgICBpZiAobW9kZWxOYW1lKSBtZXRhZGF0YSA9IG1vZGVsTmFtZTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgICBgQ291bGQgbm90IGZpbmQgbWV0YWRhdGEgZm9yICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX1gXG4gICAgICAgICk7XG4gICAgdG9TZXJpYWxpemVbTW9kZWxLZXlzLkFOQ0hPUl0gPSBtZXRhZGF0YTtcbiAgICByZXR1cm4gdG9TZXJpYWxpemU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYnVpbGRzIGEgbW9kZWwgZnJvbSBpdHMgSlNPTiBzZXJpYWxpemF0aW9uXG4gICAqIEBzdW1tYXJ5IFBhcnNlcyB0aGUgSlNPTiBzdHJpbmcsIHJldHJpZXZlcyB0aGUgZW1iZWRkZWQgbW9kZWwgYW5jaG9yLCBhbmQgdXNlcyBNb2RlbC5idWlsZCB0byByZWNvbnN0cnVjdCB0aGUgb3JpZ2luYWwgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFRoZSBKU09OIHN0cmluZyBwcmV2aW91c2x5IHByb2R1Y2VkIGJ5IHNlcmlhbGl6ZVxuICAgKiBAcmV0dXJuIHtNfSBUaGUgcmVjb25zdHJ1Y3RlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgb3ZlcnJpZGUgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcpOiBNIHtcbiAgICBjb25zdCBkZXNlcmlhbGl6YXRpb24gPSBKU09OLnBhcnNlKHN0cik7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gZGVzZXJpYWxpemF0aW9uW01vZGVsS2V5cy5BTkNIT1JdO1xuICAgIGlmICghY2xhc3NOYW1lKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgY2xhc3MgcmVmZXJlbmNlIGluIHNlcmlhbGl6ZWQgbW9kZWxcIik7XG4gICAgY29uc3QgbW9kZWw6IE0gPSBNb2RlbC5idWlsZChkZXNlcmlhbGl6YXRpb24sIGNsYXNzTmFtZSkgYXMgdW5rbm93biBhcyBNO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2VyaWFsaXplcyBhIG1vZGVsIHRvIGEgSlNPTiBzdHJpbmdcbiAgICogQHN1bW1hcnkgUHJlcGFyZXMgdGhlIG1vZGVsIHZpYSBwcmVTZXJpYWxpemUsIGVtYmVkZGluZyBtZXRhZGF0YSBuZWVkZWQgZm9yIHJlY29uc3RydWN0aW9uLCBhbmQgcmV0dXJucyBhIEpTT04gc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gc2VyaWFsaXplXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFibGVdIC0gT3B0aW9uYWwgdGFibGUgbmFtZSB0byBpbmNsdWRlIGFzIGFuY2hvciB3aGVuIG1ldGFkYXRhIGlzIHVuYXZhaWxhYmxlXG4gICAqIEByZXR1cm4ge3N0cmluZ30gQSBKU09OIHN0cmluZyBjb250YWluaW5nIHRoZSBzZXJpYWxpemVkIG1vZGVsIHdpdGggYW5jaG9yIG1ldGFkYXRhXG4gICAqL1xuICBvdmVycmlkZSBzZXJpYWxpemUobW9kZWw6IE0sIG1vZGVsTmFtZT86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMucHJlU2VyaWFsaXplKG1vZGVsLCBtb2RlbE5hbWUpKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQXV0aG9yaXphdGlvbkVycm9yLFxuICBSZXBvLFxuICBDb250ZXh0LFxuICBVbnN1cHBvcnRlZEVycm9yLFxuICBSZXBvc2l0b3J5LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7XG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIG9uQ3JlYXRlLFxuICBvbkRlbGV0ZSxcbiAgb25SZWFkLFxuICBvblVwZGF0ZSxcbiAgcmVhZG9ubHksXG4gIHRyYW5zaWVudCxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBNb2RlbCwgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNNb2RlbEtleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB0eXBlIHsgQ29udGV4dCBhcyBITENvbnRleHQgfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgRmFicmljRVJDMjBDb250cmFjdCB9IGZyb20gXCIuLi9jb250cmFjdHMvZXJjMjAvZXJjMjBjb250cmFjdFwiO1xuaW1wb3J0IHtcbiAgYXBwbHksXG4gIENvbnN0cnVjdG9yLFxuICBEZWNvcmF0aW9uLFxuICBtZXRhZGF0YSxcbiAgTWV0YWRhdGEsXG4gIHByb3BNZXRhZGF0YSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogRGVjb3JhdG9yIGZvciBtYXJraW5nIG1ldGhvZHMgdGhhdCByZXF1aXJlIG93bmVyc2hpcCBhdXRob3JpemF0aW9uLlxuICogQ2hlY2tzIHRoZSBvd25lciBvZiB0aGUgdG9rZW4gYmVmb3JlIGFsbG93aW5nIHRoZSBtZXRob2QgdG8gYmUgZXhlY3V0ZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNsYXNzIFRva2VuQ29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7XG4gKiAgIEBPd25lcigpXG4gKiAgIGFzeW5jIE1pbnQoY3R4OiBDb250ZXh0LCBhbW91bnQ6IG51bWJlcikge1xuICogICAgIC8vIE1pbnQgdG9rZW4gbG9naWNcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQHJldHVybnMge01ldGhvZERlY29yYXRvcn0gQSBtZXRob2QgZGVjb3JhdG9yIHRoYXQgY2hlY2tzIG93bmVyc2hpcCBhdXRob3JpemF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT3duZXIoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoXG4gICAgdGFyZ2V0OiBhbnksXG4gICAgcHJvcGVydHlLZXk6IHN0cmluZyxcbiAgICBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3JcbiAgKSB7XG4gICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgZGVzY3JpcHRvci52YWx1ZSA9IGFzeW5jIGZ1bmN0aW9uIChcbiAgICAgIHRoaXM6IEZhYnJpY0VSQzIwQ29udHJhY3QsXG4gICAgICAuLi5hcmdzOiBhbnlbXVxuICAgICkge1xuICAgICAgY29uc3QgY3R4OiBITENvbnRleHQgPSBhcmdzWzBdO1xuICAgICAgY29uc3QgYWNvdW50SWQgPSBjdHguY2xpZW50SWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgICAgY29uc3Qgc2VsZWN0ID0gYXdhaXQgKHRoaXMgYXMgRmFicmljRVJDMjBDb250cmFjdClbXG4gICAgICAgIFwidG9rZW5SZXBvc2l0b3J5XCJcbiAgICAgIF0uc2VsZWN0KCk7XG5cbiAgICAgIGNvbnN0IHRva2VucyA9IGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCk7XG5cbiAgICAgIGlmICh0b2tlbnMubGVuZ3RoID09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXCJObyB0b2tlbnMgYXZhaWFsYmxlXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAodG9rZW5zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoYFRvIG1hbnkgdG9rZW4gYXZhaWxhYmxlIDogJHt0b2tlbnMubGVuZ3RofWApO1xuICAgICAgfVxuXG4gICAgICBpZiAodG9rZW5zWzBdLm93bmVyICE9IGFjb3VudElkKSB7XG4gICAgICAgIHRocm93IG5ldyBBdXRob3JpemF0aW9uRXJyb3IoXG4gICAgICAgICAgYFVzZXIgbm90IGF1dGhvcml6ZWQgdG8gcnVuICR7cHJvcGVydHlLZXl9IG9uIHRoZSB0b2tlbmBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF3YWl0IG9yaWdpbmFsTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH07XG5cbiAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG93bmVkQnlPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsPGJvb2xlYW4+LFxuICBSIGV4dGVuZHMgUmVwbzxNPixcbiAgVixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8YW55PixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc3R1YiB9ID0gY29udGV4dCBhcyBhbnk7XG5cbiAgY29uc3QgY3JlYXRvciA9IGF3YWl0IHN0dWIuZ2V0Q3JlYXRvcigpO1xuICBjb25zdCBvd25lciA9IGNyZWF0b3IubXNwaWQ7XG5cbiAgY29uc3Qgc2V0T3duZWRCeUtleVZhbHVlID0gZnVuY3Rpb24gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFyZ2V0OiBNLFxuICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludFxuICApIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBwcm9wZXJ0eUtleSwge1xuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICB9KTtcbiAgfTtcblxuICBzZXRPd25lZEJ5S2V5VmFsdWUobW9kZWwsIGtleSBhcyBzdHJpbmcsIG93bmVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG93bmVkQnkoKSB7XG4gIGNvbnN0IGtleSA9IGdldEZhYnJpY01vZGVsS2V5KEZhYnJpY01vZGVsS2V5cy5PV05FREJZKTtcblxuICBmdW5jdGlvbiBvd25lZEJ5KCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAob2JqOiBhbnksIGF0dHJpYnV0ZT86IGFueSkge1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICByZXF1aXJlZCgpLFxuICAgICAgICByZWFkb25seSgpLFxuICAgICAgICBvbkNyZWF0ZShvd25lZEJ5T25DcmVhdGUpLFxuICAgICAgICBwcm9wTWV0YWRhdGEoZ2V0RmFicmljTW9kZWxLZXkoRmFicmljTW9kZWxLZXlzLk9XTkVEQlkpLCBhdHRyaWJ1dGUpXG4gICAgICApKG9iaiwgYXR0cmlidXRlKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKGtleSlcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogb3duZWRCeSxcbiAgICAgIGFyZ3M6IFtdLFxuICAgIH0pXG4gICAgLmFwcGx5KCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0cmFuc2FjdGlvbklkT25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbDxib29sZWFuPixcbiAgUiBleHRlbmRzIFJlcG88TT4sXG4gIFYsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PGFueT4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHN0dWIgfSA9IGNvbnRleHQgYXMgYW55O1xuICBtb2RlbFtrZXldID0gc3R1Yi5nZXRUeElEKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2FjdGlvbklkKCkge1xuICBmdW5jdGlvbiB0cmFuc2FjdGlvbklkKCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAob2JqOiBhbnksIGF0dHJpYnV0ZT86IGFueSkge1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICByZXF1aXJlZCgpLFxuICAgICAgICByZWFkb25seSgpLFxuICAgICAgICBvbkNyZWF0ZSh0cmFuc2FjdGlvbklkT25DcmVhdGUpLFxuICAgICAgICBvblVwZGF0ZSh0cmFuc2FjdGlvbklkT25DcmVhdGUpLFxuICAgICAgICBwcm9wTWV0YWRhdGEoXG4gICAgICAgICAgTWV0YWRhdGEua2V5KFxuICAgICAgICAgICAgRmFicmljTW9kZWxLZXlzLkZBQlJJQyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZSxcbiAgICAgICAgICAgIEZhYnJpY01vZGVsS2V5cy5UUkFOU0FDVElPTl9JRFxuICAgICAgICAgICksXG4gICAgICAgICAgYXR0cmlidXRlXG4gICAgICAgIClcbiAgICAgICkob2JqLCBhdHRyaWJ1dGUpO1xuICAgIH07XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLlRSQU5TQUNUSU9OX0lEKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiB0cmFuc2FjdGlvbklkLFxuICAgICAgYXJnczogW10sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZhYnJpY01vZGVsS2V5KGtleTogc3RyaW5nKSB7XG4gIHJldHVybiBNZXRhZGF0YS5rZXkoRmFicmljTW9kZWxLZXlzLkZBQlJJQyArIGtleSk7XG59XG5cbmV4cG9ydCB0eXBlIENvbGxlY3Rpb25SZXNvbHZlciA9IDxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSA9PiBzdHJpbmc7XG5cbmV4cG9ydCBjb25zdCBJbXBsaWNpdFByaXZhdGVDb2xsZWN0aW9uOiBDb2xsZWN0aW9uUmVzb2x2ZXIgPSA8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbikgPT4ge1xuICByZXR1cm4gYF9fJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfVByaXZhdGVDb2xsZWN0aW9uYDtcbn07XG5cbmV4cG9ydCB0eXBlIFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGEgPSB7XG4gIGNvbGxlY3Rpb25zOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXI7XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPbkNyZWF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljRmxhZ3M+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW10sXG4gIGtleXM6IChrZXlvZiBNKVtdLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChrZXlzLmxlbmd0aCAhPT0gZGF0YS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IGRhdGFbMF0uY29sbGVjdGlvbnM7XG4gIGNvbnN0IGNvbGxlY3Rpb24gPVxuICAgIHR5cGVvZiBjb2xsZWN0aW9uUmVzb2x2ZXIgPT09IFwic3RyaW5nXCJcbiAgICAgID8gY29sbGVjdGlvblJlc29sdmVyXG4gICAgICA6IGNvbGxlY3Rpb25SZXNvbHZlcihtb2RlbCk7XG5cbiAgY29uc3QgcmVidWlsdCA9IGtleXMucmVkdWNlKFxuICAgIChhY2M6IFJlY29yZDxrZXlvZiBNLCBhbnk+LCBrLCBpKSA9PiB7XG4gICAgICBjb25zdCBjID1cbiAgICAgICAgdHlwZW9mIGRhdGFbaV0uY29sbGVjdGlvbnMgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IGRhdGFbaV0uY29sbGVjdGlvbnNcbiAgICAgICAgICA6IGRhdGFbaV0uY29sbGVjdGlvbnMobW9kZWwpO1xuICAgICAgaWYgKGMgIT09IGNvbGxlY3Rpb24pXG4gICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICAgIGBTZWdyZWdhdGVkIGRhdGEgY29sbGVjdGlvbiBtaXNtYXRjaDogJHtjfSB2cyAke2NvbGxlY3Rpb259YFxuICAgICAgICApO1xuICAgICAgYWNjW2tdID0gbW9kZWxba107XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT5cbiAgKTtcblxuICBjb25zdCB0b0NyZWF0ZSA9IG5ldyB0aGlzLmNsYXNzKHJlYnVpbHQpO1xuXG4gIC8vIGNvbnN0IHNlZ3JlZ2F0ZWQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuXG4gIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB0aGlzLm92ZXJyaWRlKHsgc2VncmVnYXRlZDogY29sbGVjdGlvbiB9IGFzIGFueSkuY3JlYXRlKFxuICAgIHRvQ3JlYXRlLFxuICAgIGNvbnRleHRcbiAgKTtcbiAgT2JqZWN0LmFzc2lnbihtb2RlbCwgY3JlYXRlZCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uUmVhZDxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljRmxhZ3M+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW10sXG4gIGtleXM6IChrZXlvZiBNKVtdLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChrZXlzLmxlbmd0aCAhPT0gZGF0YS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgU2VncmVnYXRlZCBkYXRhIGtleXMgYW5kIG1ldGFkYXRhIGxlbmd0aCBtaXNtYXRjaGBcbiAgICApO1xuXG4gIGNvbnN0IGNvbGxlY3Rpb25SZXNvbHZlciA9IGRhdGFbMF0uY29sbGVjdGlvbnM7XG4gIGNvbnN0IGNvbGxlY3Rpb24gPVxuICAgIHR5cGVvZiBjb2xsZWN0aW9uUmVzb2x2ZXIgPT09IFwic3RyaW5nXCJcbiAgICAgID8gY29sbGVjdGlvblJlc29sdmVyXG4gICAgICA6IGNvbGxlY3Rpb25SZXNvbHZlcihtb2RlbCk7XG5cbiAgY29uc3QgcmVidWlsdCA9IGtleXMucmVkdWNlKFxuICAgIChhY2M6IFJlY29yZDxrZXlvZiBNLCBhbnk+LCBrLCBpKSA9PiB7XG4gICAgICBjb25zdCBjID1cbiAgICAgICAgdHlwZW9mIGRhdGFbaV0uY29sbGVjdGlvbnMgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IGRhdGFbaV0uY29sbGVjdGlvbnNcbiAgICAgICAgICA6IGRhdGFbaV0uY29sbGVjdGlvbnMobW9kZWwpO1xuICAgICAgaWYgKGMgIT09IGNvbGxlY3Rpb24pXG4gICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICAgIGBTZWdyZWdhdGVkIGRhdGEgY29sbGVjdGlvbiBtaXNtYXRjaDogJHtjfSB2cyAke2NvbGxlY3Rpb259YFxuICAgICAgICApO1xuICAgICAgYWNjW2tdID0gbW9kZWxba107XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge30gYXMgUmVjb3JkPGtleW9mIE0sIGFueT5cbiAgKTtcblxuICBjb25zdCB0b0NyZWF0ZSA9IG5ldyB0aGlzLmNsYXNzKHJlYnVpbHQpO1xuXG4gIC8vIGNvbnN0IHNlZ3JlZ2F0ZWQgPSBNb2RlbC5zZWdyZWdhdGUobW9kZWwpO1xuXG4gIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB0aGlzLm92ZXJyaWRlKHsgc2VncmVnYXRlZDogY29sbGVjdGlvbiB9IGFzIGFueSkuY3JlYXRlKFxuICAgIHRvQ3JlYXRlLFxuICAgIGNvbnRleHRcbiAgKTtcbiAgT2JqZWN0LmFzc2lnbihtb2RlbCwgY3JlYXRlZCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWdyZWdhdGVkRGF0YU9uVXBkYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IFJlcG9zaXRvcnk8TSwgYW55PixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNGbGFncz4sXG4gIGRhdGE6IFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGFbXSxcbiAga2V5OiBrZXlvZiBNW10sXG4gIG1vZGVsOiBNLFxuICBvbGRNb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7fVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPbkRlbGV0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBWIGV4dGVuZHMgU2VncmVnYXRlZERhdGFNZXRhZGF0YSxcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljRmxhZ3M+LFxuICBkYXRhOiBWW10sXG4gIGtleToga2V5b2YgTVtdLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7fVxuXG5mdW5jdGlvbiBzZWdyZWdhdGVkKFxuICBjb2xsZWN0aW9uOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIsXG4gIHR5cGU6IEZhYnJpY01vZGVsS2V5cy5QUklWQVRFIHwgRmFicmljTW9kZWxLZXlzLlNIQVJFRFxuKSB7XG4gIHJldHVybiBmdW5jdGlvbiBpbm5lclNlZ3JlZ2F0ZWQodGFyZ2V0OiBvYmplY3QsIHByb3BlcnR5S2V5PzogYW55KSB7XG4gICAgZnVuY3Rpb24gc2VncmVnYXRlZERlYyh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpIHtcbiAgICAgIGlmICghcHJvcGVydHlLZXkpIHtcbiAgICAgICAgY29uc3QgcHJvcHMgPSBNZXRhZGF0YS5wcm9wZXJ0aWVzKHRhcmdldCBhcyBDb25zdHJ1Y3RvcikgfHwgW107XG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBwcm9wcykgc2VncmVnYXRlZChjb2xsZWN0aW9uLCB0eXBlKSh0YXJnZXQsIHByb3ApO1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBrZXkgPSBNZXRhZGF0YS5rZXkodHlwZSwgcHJvcGVydHlLZXkpO1xuICAgICAgY29uc3QgY29uc3RyOiBDb25zdHJ1Y3RvciA9IHRhcmdldC5jb25zdHJ1Y3RvciBhcyBDb25zdHJ1Y3RvcjtcblxuICAgICAgY29uc3QgbWV0YSA9IE1ldGFkYXRhLmdldChjb25zdHIgYXMgQ29uc3RydWN0b3IsIGtleSkgfHwge307XG4gICAgICBjb25zdCBjb2xsZWN0aW9ucyA9IG5ldyBTZXQobWV0YS5jb2xsZWN0aW9ucyB8fCBbXSk7XG4gICAgICBjb2xsZWN0aW9ucy5hZGQoY29sbGVjdGlvbik7XG4gICAgICBtZXRhLmNvbGxlY3Rpb25zID0gWy4uLmNvbGxlY3Rpb25zXTtcbiAgICAgIE1ldGFkYXRhLnNldChjb25zdHIgYXMgQ29uc3RydWN0b3IsIGtleSwgbWV0YSk7XG4gICAgfVxuICAgIGNvbnN0IGRlY3M6IGFueVtdID0gW107XG4gICAgaWYgKCFwcm9wZXJ0eUtleSkge1xuICAgICAgLy8gZGVjb3JhdGVkIGF0IHRoZSBjbGFzcyBsZXZlbFxuICAgICAgTWV0YWRhdGEucHJvcGVydGllcyh0YXJnZXQgYXMgQ29uc3RydWN0b3IpPy5mb3JFYWNoKChwKSA9PlxuICAgICAgICBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIHR5cGUpKHRhcmdldCwgcClcbiAgICAgICk7XG4gICAgICByZXR1cm4gbWV0YWRhdGEodHlwZSwgdHJ1ZSkodGFyZ2V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVjcy5wdXNoKFxuICAgICAgICB0cmFuc2llbnQoKSxcbiAgICAgICAgc2VncmVnYXRlZERlYyxcbiAgICAgICAgb25DcmVhdGUoXG4gICAgICAgICAgc2VncmVnYXRlZERhdGFPbkNyZWF0ZSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvblJlYWQoXG4gICAgICAgICAgc2VncmVnYXRlZERhdGFPblJlYWQgYXMgYW55LFxuICAgICAgICAgIHsgY29sbGVjdGlvbnM6IGNvbGxlY3Rpb24gfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwcmlvcml0eTogOTUsXG4gICAgICAgICAgICBncm91cDpcbiAgICAgICAgICAgICAgdHlwZW9mIGNvbGxlY3Rpb24gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICA6IGNvbGxlY3Rpb24udG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgICksXG4gICAgICAgIG9uVXBkYXRlKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25VcGRhdGUgYXMgYW55LFxuICAgICAgICAgIHsgY29sbGVjdGlvbnM6IGNvbGxlY3Rpb24gfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwcmlvcml0eTogOTUsXG4gICAgICAgICAgICBncm91cDpcbiAgICAgICAgICAgICAgdHlwZW9mIGNvbGxlY3Rpb24gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICA6IGNvbGxlY3Rpb24udG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgICksXG4gICAgICAgIG9uRGVsZXRlKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25EZWxldGUgYXMgYW55LFxuICAgICAgICAgIHsgY29sbGVjdGlvbnM6IGNvbGxlY3Rpb24gfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwcmlvcml0eTogOTUsXG4gICAgICAgICAgICBncm91cDpcbiAgICAgICAgICAgICAgdHlwZW9mIGNvbGxlY3Rpb24gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICA6IGNvbGxlY3Rpb24udG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBhcHBseSguLi5kZWNzKSh0YXJnZXQsIHByb3BlcnR5S2V5KTtcbiAgICAvLyByZXR1cm4gYXBwbHkoKSh0YXJnZXQsIHByb3BlcnR5S2V5KTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByaXZhdGVEYXRhKFxuICBjb2xsZWN0aW9uOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIgPSBJbXBsaWNpdFByaXZhdGVDb2xsZWN0aW9uXG4pIHtcbiAgZnVuY3Rpb24gcHJpdmF0ZURhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gICAgcmV0dXJuIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgRmFicmljTW9kZWxLZXlzLlBSSVZBVEUpO1xuICB9XG5cbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKEZhYnJpY01vZGVsS2V5cy5QUklWQVRFKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiBwcml2YXRlRGF0YSxcbiAgICAgIGFyZ3M6IFtjb2xsZWN0aW9uXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2hhcmVkRGF0YShjb2xsZWN0aW9uOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIpIHtcbiAgZnVuY3Rpb24gc2hhcmVkRGF0YShjb2xsZWN0aW9uOiBzdHJpbmcgfCBDb2xsZWN0aW9uUmVzb2x2ZXIpIHtcbiAgICByZXR1cm4gc2VncmVnYXRlZChjb2xsZWN0aW9uLCBGYWJyaWNNb2RlbEtleXMuU0hBUkVEKTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuU0hBUkVEKVxuICAgIC5kZWZpbmUoe1xuICAgICAgZGVjb3JhdG9yOiBzaGFyZWREYXRhLFxuICAgICAgYXJnczogW2NvbGxlY3Rpb25dLFxuICAgIH0pXG4gICAgLmFwcGx5KCk7XG59XG4vL1xuLy8gZXhwb3J0IGZ1bmN0aW9uIHByaXZhdGVEYXRhKGNvbGxlY3Rpb24/OiBzdHJpbmcpIHtcbi8vICAgaWYgKCFjb2xsZWN0aW9uKSB7XG4vLyAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29sbGVjdGlvbiBuYW1lIGlzIHJlcXVpcmVkXCIpO1xuLy8gICB9XG4vL1xuLy8gICBjb25zdCBrZXk6IHN0cmluZyA9IEZhYnJpY01vZGVsS2V5cy5QUklWQVRFO1xuLy9cbi8vICAgcmV0dXJuIGZ1bmN0aW9uIHByaXZhdGVEYXRhPE0gZXh0ZW5kcyBNb2RlbD4oXG4vLyAgICAgbW9kZWw6IE0gfCBDb25zdHJ1Y3RvcjxNPixcbi8vICAgICBhdHRyaWJ1dGU/OiBhbnlcbi8vICAgKSB7XG4vLyAgICAgY29uc3QgY29uc3RyID1cbi8vICAgICAgIG1vZGVsIGluc3RhbmNlb2YgTW9kZWwgPyAobW9kZWwuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3IpIDogbW9kZWw7XG4vL1xuLy8gICAgIGNvbnN0IG1ldGFEYXRhOiBhbnkgPSBNZXRhZGF0YS5nZXQoY29uc3RyKTtcbi8vICAgICBjb25zdCBtb2RlbGRhdGEgPSBtZXRhRGF0YT8ucHJpdmF0ZT8uY29sbGVjdGlvbnMgfHwgW107XG4vL1xuLy8gICAgIHByb3BNZXRhZGF0YShrZXksIHtcbi8vICAgICAgIC4uLighYXR0cmlidXRlICYmIHtcbi8vICAgICAgICAgY29sbGVjdGlvbnM6IG1vZGVsZGF0YVxuLy8gICAgICAgICAgID8gWy4uLm5ldyBTZXQoWy4uLm1vZGVsZGF0YSwgY29sbGVjdGlvbl0pXVxuLy8gICAgICAgICAgIDogW2NvbGxlY3Rpb25dLFxuLy8gICAgICAgfSksXG4vLyAgICAgICBpc1ByaXZhdGU6ICFhdHRyaWJ1dGUsXG4vLyAgICAgfSkoYXR0cmlidXRlID8gY29uc3RyIDogbW9kZWwpO1xuLy9cbi8vICAgICBpZiAoYXR0cmlidXRlKSB7XG4vLyAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhID1cbi8vICAgICAgICAgKG1ldGFEYXRhPy5wcml2YXRlPy5bYXR0cmlidXRlXSBhcyBhbnkpPy5jb2xsZWN0aW9ucyB8fCBbXTtcbi8vICAgICAgIHByb3BNZXRhZGF0YShNZXRhZGF0YS5rZXkoa2V5LCBhdHRyaWJ1dGUpLCB7XG4vLyAgICAgICAgIGNvbGxlY3Rpb25zOiBhdHRyaWJ1dGVEYXRhXG4vLyAgICAgICAgICAgPyBbLi4ubmV3IFNldChbLi4uYXR0cmlidXRlRGF0YSwgY29sbGVjdGlvbl0pXVxuLy8gICAgICAgICAgIDogW2NvbGxlY3Rpb25dLFxuLy8gICAgICAgfSkobW9kZWwsIGF0dHJpYnV0ZSk7XG4vLyAgICAgICB0cmFuc2llbnQoKShtb2RlbCwgYXR0cmlidXRlKTtcbi8vICAgICB9XG4vLyAgIH07XG4vLyB9XG4iLCJpbXBvcnQgeyBzdHJpbmdGb3JtYXQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPdmVyZmxvd0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3ZlcmZsb3ctc2FmZSBhZGRpdGlvbiBvcGVyYXRpb25cbiAqIEBzdW1tYXJ5IEFkZHMgdHdvIG51bWJlcnMgYW5kIHZlcmlmaWVzIG5vIG92ZXJmbG93IGJ5IHJldmVyc2UtY2hlY2tpbmcgdGhlIG9wZXJhbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gYSAtIEZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gU2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIHN1bSBvZiBhIGFuZCBiXG4gKiBAZnVuY3Rpb24gYWRkXG4gKiBAdGhyb3dzIHtPdmVyZmxvd0Vycm9yfSBvbiBhZGRpdGlvbiBvdmVyZmxvd1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYyA9IGEgKyBiO1xuICBpZiAoYSAhPT0gYyAtIGIgfHwgYiAhPT0gYyAtIGEpIHtcbiAgICB0aHJvdyBuZXcgT3ZlcmZsb3dFcnJvcihgQWRkaXRpb24gb3ZlcmZsb3c6ICR7YX0gKyAke2J9YCk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE92ZXJmbG93LXNhZmUgc3VidHJhY3Rpb24gb3BlcmF0aW9uXG4gKiBAc3VtbWFyeSBTdWJ0cmFjdHMgYiBmcm9tIGEgYW5kIHZhbGlkYXRlcyBubyBvdmVyZmxvdyBieSByZXZlcnNlLWNoZWNraW5nIHRoZSBvcGVyYW5kc1xuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBNaW51ZW5kXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFN1YnRyYWhlbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGRpZmZlcmVuY2UgYSAtIGJcbiAqIEBmdW5jdGlvbiBzdWJcbiAqIEB0aHJvd3Mge092ZXJmbG93RXJyb3J9IG9uIHN1YnRhY3Rpb24gb3ZlcmZsb3dcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YihhOiBudW1iZXIsIGI6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGMgPSBhIC0gYjtcbiAgaWYgKGEgIT09IGMgKyBiIHx8IGIgIT09IGEgLSBjKSB7XG4gICAgdGhyb3cgbmV3IE92ZXJmbG93RXJyb3IoYFN1YnRyYWN0aW9uIG92ZXJmbG93OiAke2F9IC0gJHtifWApO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFNhZmUgSW50ZWdlciBQYXJzZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcbiAqXG4gKiBAZnVuY3Rpb24gc2FmZVBhcnNlSW50XG4gKlxuICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBpZiBwYXJzZUludCByZXR1cm5zIE5hTlxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZUludChzdHJpbmc6IHN0cmluZyk6IG51bWJlciB7XG4gIC8vIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBjaGVjayBpZiBzdHJpbmcgb25seSBoYXZlIGRpZ2l0c1xuICBjb25zdCBkaWdpdFJlZ2V4ID0gL15cXGQrJC87XG4gIGlmICghZGlnaXRSZWdleC50ZXN0KHN0cmluZykpIHtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgc3RyaW5nRm9ybWF0KFwiRmFpbGVkIHRvIHBhcnNlOiB7MH1cIiwgXCJzdHJpbmcgY29udGFpbnMgZGlnaXRzXCIpXG4gICAgKTtcbiAgfVxuICBjb25zdCBwYXJzZWRpbnQgPSBwYXJzZUludChzdHJpbmcpO1xuICBpZiAoaXNOYU4ocGFyc2VkaW50KSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBzdHJpbmdGb3JtYXQoXCJGYWlsZWQgdG8gcGFyc2U6IHswfVwiLCBcInN0cmluZyBpcyBub3QgYSBwYXJzYWJsZSBpbnRlZ2VyXCIpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gcGFyc2VkaW50O1xufVxuIiwiaW1wb3J0IFwiLi4vLi4vc2hhcmVkL292ZXJyaWRlc1wiO1xuaW1wb3J0IHtcbiAgRmFicmljQ29udGV4dHVhbGl6ZWRBcmdzLFxuICBGYWJyaWNDb250cmFjdEFkYXB0ZXIsXG59IGZyb20gXCIuLi9Db250cmFjdEFkYXB0ZXJcIjtcbmltcG9ydCB7XG4gIENvbnRleHQgYXMgQ3R4LFxuICBDb250cmFjdCxcbiAgT2JqZWN0IGFzIEZhYnJpY09iamVjdCxcbn0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IE1vZGVsLCBTZXJpYWxpemVyIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHtcbiAgQ29uZGl0aW9uLFxuICBEaXJlY3Rpb25MaW1pdE9mZnNldCxcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBNZXRob2RPck9wZXJhdGlvbixcbiAgT3JkZXJEaXJlY3Rpb24sXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUHJlcGFyZWRTdGF0ZW1lbnRLZXlzLFxuICBSZXBvc2l0b3J5LFxuICBTZXJpYWxpemVkUGFnZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBEZXRlcm1pbmlzdGljU2VyaWFsaXplciB9IGZyb20gXCIuLi8uLi9zaGFyZWQvRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXJcIjtcbmltcG9ydCB7IE1hbmdvUXVlcnkgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1jb3VjaGRiXCI7XG5pbXBvcnQgeyBDaGVja2FibGUsIGhlYWx0aGNoZWNrIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9pbnRlcmZhY2VzL0NoZWNrYWJsZVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7XG4gIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyxcbiAgT3BlcmF0aW9uS2V5cyxcbiAgUHJpbWFyeUtleVR5cGUsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWlzc2luZ0NvbnRleHRFcnJvciB9IGZyb20gXCIuLi8uLi9zaGFyZWQvaW5kZXhcIjtcblxuRmFicmljT2JqZWN0KCkoRGF0ZSk7XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGNvbnRyYWN0IGNsYXNzIGZvciBDUlVEIG9wZXJhdGlvbnMgaW4gRmFicmljIGNoYWluY29kZVxuICogQHN1bW1hcnkgUHJvdmlkZXMgc3RhbmRhcmQgY3JlYXRlLCByZWFkLCB1cGRhdGUsIGFuZCBkZWxldGUgb3BlcmF0aW9ucyBmb3IgbW9kZWxzIGluIEZhYnJpYyBjaGFpbmNvZGVcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEBjbGFzcyBGYWJyaWNDcnVkQ29udHJhY3RcbiAqIEBleHRlbmRzIHtDb250cmFjdH1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBEZWZpbmUgYSBtb2RlbFxuICogQHRhYmxlKCdhc3NldHMnKVxuICogY2xhc3MgQXNzZXQgZXh0ZW5kcyBNb2RlbCB7XG4gKiAgIEBpZCgpXG4gKiAgIGlkOiBzdHJpbmc7XG4gKlxuICogICBAcHJvcGVydHkoKVxuICogICBkYXRhOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogLy8gQ3JlYXRlIGEgY29udHJhY3QgdGhhdCBleHRlbmRzIEZhYnJpY0NydWRDb250cmFjdFxuICogZXhwb3J0IGNsYXNzIEFzc2V0Q29udHJhY3QgZXh0ZW5kcyBGYWJyaWNDcnVkQ29udHJhY3Q8QXNzZXQ+IHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgc3VwZXIoJ0Fzc2V0Q29udHJhY3QnLCBBc3NldCk7XG4gKiAgIH1cbiAqXG4gKiAgIC8vIEFkZCBjdXN0b20gbWV0aG9kcyBhcyBuZWVkZWRcbiAqICAgYXN5bmMgZ2V0QXNzZXRIaXN0b3J5KGN0eDogQ29udGV4dCwgaWQ6IHN0cmluZyk6IFByb21pc2U8YW55W10+IHtcbiAqICAgICAvLyBDdXN0b20gaW1wbGVtZW50YXRpb25cbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgU3RhdGVEQlxuICpcbiAqICAgQ2xpZW50LT4+Q29udHJhY3Q6IGNyZWF0ZShjdHgsIG1vZGVsKVxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IHJlcG9zaXRvcnkoY3R4KVxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IGNyZWF0ZShtb2RlbCwgY3R4KVxuICogICBSZXBvc2l0b3J5LT4+QWRhcHRlcjogY3JlYXRlKHRhYmxlTmFtZSwgaWQsIHJlY29yZCwgdHJhbnNpZW50LCBjdHgpXG4gKiAgIEFkYXB0ZXItPj5TdGF0ZURCOiBwdXRTdGF0ZShpZCwgc2VyaWFsaXplZERhdGEpXG4gKiAgIFN0YXRlREItLT4+QWRhcHRlcjogU3VjY2Vzc1xuICogICBBZGFwdGVyLS0+PlJlcG9zaXRvcnk6IHJlY29yZFxuICogICBSZXBvc2l0b3J5LS0+PkNvbnRyYWN0OiBtb2RlbFxuICogICBDb250cmFjdC0tPj5DbGllbnQ6IG1vZGVsXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNDcnVkQ29udHJhY3Q8TSBleHRlbmRzIE1vZGVsPlxuICBleHRlbmRzIENvbnRyYWN0XG4gIGltcGxlbWVudHMgQ2hlY2thYmxlXG57XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2hhcmVkIGFkYXB0ZXIgaW5zdGFuY2UgZm9yIGFsbCBjb250cmFjdCBpbnN0YW5jZXNcbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgYWRhcHRlcjogRmFicmljQ29udHJhY3RBZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSByZXBvOiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8TT47XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBzZXJpYWxpemVyID0gbmV3IERldGVybWluaXN0aWNTZXJpYWxpemVyKCk7XG5cbiAgcHJvdGVjdGVkIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IEZhYnJpY0NydWRDb250cmFjdCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIGNvbnRyYWN0IHdpdGggYSBuYW1lIGFuZCBtb2RlbCBjbGFzc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjb250cmFjdFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKi9cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKG5hbWUpO1xuICAgIHRoaXMucmVwbyA9IFJlcG9zaXRvcnkuZm9yTW9kZWwoY2xhenopO1xuXG4gICAgLy8gcHJlZml4TWV0aG9kKHRoaXMpO1xuICB9XG5cbiAgYXN5bmMgbGlzdEJ5KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleTogc3RyaW5nIHwga2V5b2YgTSxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TVtdIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBsb2cgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCBQcmVwYXJlZFN0YXRlbWVudEtleXMuTElTVF9CWSwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLmxpc3RCeSk7XG4gICAgbG9nLmluZm8oXG4gICAgICBgUnVubmluZyBsaXN0Qnkga2V5ICR7a2V5IGFzIHN0cmluZ30sIG9yZGVyICR7b3JkZXJ9IGFuZCBhcmdzICR7Y3R4QXJnc31gXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmxpc3RCeShcbiAgICAgIGtleSBhcyBrZXlvZiBNLFxuICAgICAgb3JkZXIgYXMgT3JkZXJEaXJlY3Rpb24sXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHBhZ2luYXRlQnkoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5OiBzdHJpbmcgfCBrZXlvZiBNLFxuICAgIG9yZGVyOiBzdHJpbmcsXG4gICAgcmVmOiBPbWl0PERpcmVjdGlvbkxpbWl0T2Zmc2V0LCBcImRpcmVjdGlvblwiPiB8IHN0cmluZyA9IHtcbiAgICAgIG9mZnNldDogMSxcbiAgICAgIGxpbWl0OiAxMCxcbiAgICB9LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8U2VyaWFsaXplZFBhZ2U8TT4gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MsIGxvZyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIFByZXBhcmVkU3RhdGVtZW50S2V5cy5QQUdFX0JZLCB0cnVlKVxuICAgICkuZm9yKHRoaXMucGFnaW5hdGVCeSk7XG4gICAgbG9nLmluZm8oXG4gICAgICBgUnVubmluZyBwYWdpbmF0ZUJ5IGtleSAke2tleSBhcyBzdHJpbmd9LCBvcmRlciAke29yZGVyfSB3aXRoIHNpemUgJHsocmVmIGFzIGFueSkubGltaXR9IGFuZCBhcmdzICR7Y3R4QXJnc31gXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnBhZ2luYXRlQnkoXG4gICAgICBrZXkgYXMga2V5b2YgTSxcbiAgICAgIG9yZGVyIGFzIGFueSxcbiAgICAgIHJlZiBhcyBhbnksXG4gICAgICAuLi5jdHhBcmdzXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGZpbmRPbmVCeShcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXk6IHN0cmluZyB8IGtleW9mIE0sXG4gICAgdmFsdWU6IGFueSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE0gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MsIGxvZyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIFByZXBhcmVkU3RhdGVtZW50S2V5cy5GSU5EX09ORV9CWSwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLmZpbmRPbmVCeSk7XG4gICAgbG9nLmluZm8oXG4gICAgICBgUnVubmluZyBmaW5kT25lQnkga2V5ICR7a2V5IGFzIHN0cmluZ30sIHZhbHVlOiAke3ZhbHVlfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfWBcbiAgICApO1xuICAgIHJldHVybiB0aGlzLnJlcG8uZmluZE9uZUJ5KGtleSBhcyBrZXlvZiBNLCB2YWx1ZSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBhc3luYyBzdGF0ZW1lbnQoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MsIGxvZyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIFBlcnNpc3RlbmNlS2V5cy5TVEFURU1FTlQsIHRydWUpXG4gICAgKS5mb3IodGhpcy5zdGF0ZW1lbnQpO1xuICAgIGxvZy5pbmZvKGBSdW5uaW5nIHN0YXRlbWVudCAke21ldGhvZH0gd2l0aCBhcmdzICR7Y3R4QXJnc31gKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnN0YXRlbWVudChtZXRob2QsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgc2luZ2xlIG1vZGVsIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyBjcmVhdGUgbWV0aG9kXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCBtb2RlbFxuICAgKi9cbiAgYXN5bmMgY3JlYXRlKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIG1vZGVsOiBzdHJpbmcgfCBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8c3RyaW5nIHwgTT4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgT3BlcmF0aW9uS2V5cy5DUkVBVEUsIHRydWUpXG4gICAgKS5mb3IodGhpcy5jcmVhdGUpO1xuICAgIGxvZy5pbmZvKGBDT05UUkFDVCBDUkVBVEUsICR7Y3R4QXJnc31gKTtcblxuICAgIGlmICh0eXBlb2YgbW9kZWwgPT09IFwic3RyaW5nXCIpIG1vZGVsID0gdGhpcy5kZXNlcmlhbGl6ZTxNPihtb2RlbCkgYXMgTTtcblxuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBtb2RlbDogJHtKU09OLnN0cmluZ2lmeShtb2RlbCl9YCk7XG5cbiAgICBjb25zdCB0cmFuc2llbnQgPSB0aGlzLmdldFRyYW5zaWVudERhdGEoY3R4KTtcblxuICAgIGxvZy5pbmZvKGBNZXJnaW5nIHRyYW5zaWVudCBkYXRhLi4uYCk7XG4gICAgbW9kZWwgPSBNb2RlbC5tZXJnZShtb2RlbCwgdHJhbnNpZW50LCB0aGlzLmNsYXp6KSBhcyBNO1xuXG4gICAgcmV0dXJuIHRoaXMucmVwby5jcmVhdGUobW9kZWwsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHNpbmdsZSBtb2RlbCBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyByZWFkIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgbW9kZWwgdG8gcmVhZFxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCBtb2RlbFxuICAgKi9cbiAgYXN5bmMgcmVhZChcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXk6IFByaW1hcnlLZXlUeXBlIHwgc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgT3BlcmF0aW9uS2V5cy5SRUFELCB0cnVlKVxuICAgICkuZm9yKHRoaXMuY3JlYXRlKTtcbiAgICBsb2cuaW5mbyhgcmVhZGluZyBlbnRyeSB3aXRoIHBrICR7a2V5fSBgKTtcblxuICAgIHJldHVybiB0aGlzLnJlcG8ucmVhZChrZXksIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFRyYW5zaWVudERhdGEoY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQpOiBhbnkge1xuICAgIGNvbnN0IHRyYW5zaWVudE1hcCA9IGN0eC5zdHViLmdldFRyYW5zaWVudCgpO1xuICAgIGxldCB0cmFuc2llbnQ6IGFueSA9IHt9O1xuXG4gICAgaWYgKHRyYW5zaWVudE1hcC5oYXMoKHRoaXMucmVwbyBhcyBhbnkpLnRhYmxlTmFtZSkpIHtcbiAgICAgIHRyYW5zaWVudCA9IEpTT04ucGFyc2UoXG4gICAgICAgICh0cmFuc2llbnRNYXAuZ2V0KCh0aGlzLnJlcG8gYXMgYW55KS50YWJsZU5hbWUpIGFzIEJ1ZmZlcik/LnRvU3RyaW5nKFxuICAgICAgICAgIFwidXRmOFwiXG4gICAgICAgICkgYXMgc3RyaW5nXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2llbnQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgYSBzaW5nbGUgbW9kZWwgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIHVwZGF0ZSBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB1cGRhdGVkIG1vZGVsXG4gICAqL1xuICBhc3luYyB1cGRhdGUoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWw6IHN0cmluZyB8IE0sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCBPcGVyYXRpb25LZXlzLlVQREFURSwgdHJ1ZSlcbiAgICApLmZvcih0aGlzLnVwZGF0ZSk7XG4gICAgaWYgKHR5cGVvZiBtb2RlbCA9PT0gXCJzdHJpbmdcIikgbW9kZWwgPSB0aGlzLmRlc2VyaWFsaXplPE0+KG1vZGVsKSBhcyBNO1xuXG4gICAgbG9nLmluZm8oYFVwZGF0aW5nIG1vZGVsOiAke0pTT04uc3RyaW5naWZ5KG1vZGVsKX1gKTtcblxuICAgIGNvbnN0IHRyYW5zaWVudCA9IHRoaXMuZ2V0VHJhbnNpZW50RGF0YShjdHgpO1xuXG4gICAgbG9nLmluZm8oYE1lcmdpbmcgdHJhbnNpZW50IGRhdGEuLi5gKTtcbiAgICBtb2RlbCA9IE1vZGVsLm1lcmdlKG1vZGVsLCB0cmFuc2llbnQsIHRoaXMuY2xhenopIGFzIE07XG4gICAgcmV0dXJuIHRoaXMucmVwby51cGRhdGUobW9kZWwsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgc2luZ2xlIG1vZGVsIGZyb20gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIGRlbGV0ZSBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGtleSAtIFRoZSBrZXkgb2YgdGhlIG1vZGVsIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGRlbGV0ZWQgbW9kZWxcbiAgICovXG4gIGFzeW5jIGRlbGV0ZShcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXk6IFByaW1hcnlLZXlUeXBlIHwgc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSAoXG4gICAgICBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsIHRydWUpXG4gICAgKS5mb3IodGhpcy5kZWxldGUpO1xuICAgIGxvZy5pbmZvKGBkZWxldGluZyBlbnRyeSB3aXRoIHBrICR7a2V5fSBgKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmRlbGV0ZShTdHJpbmcoa2V5KSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgbW9kZWxzIGZyb20gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIGRlbGV0ZUFsbCBtZXRob2RcbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGtleXMgb2YgdGhlIG1vZGVscyB0byBkZWxldGVcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGRlbGV0ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyBkZWxldGVBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5czogUHJpbWFyeUtleVR5cGVbXSB8IHN0cmluZyxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE1bXSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5ERUxFVEVfQUxMLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuZGVsZXRlQWxsKTtcbiAgICBpZiAodHlwZW9mIGtleXMgPT09IFwic3RyaW5nXCIpIGtleXMgPSBKU09OLnBhcnNlKGtleXMpIGFzIHN0cmluZ1tdO1xuICAgIHJldHVybiB0aGlzLnJlcG8uZGVsZXRlQWxsKGtleXMsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBtdWx0aXBsZSBtb2RlbHMgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgcmVhZEFsbCBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGtleXMgb2YgdGhlIG1vZGVscyB0byByZWFkXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXRyaWV2ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyByZWFkQWxsKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleXM6IFByaW1hcnlLZXlUeXBlW10gfCBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTEwsIHRydWUpXG4gICAgKS5mb3IodGhpcy5jcmVhdGUpO1xuICAgIGlmICh0eXBlb2Yga2V5cyA9PT0gXCJzdHJpbmdcIikga2V5cyA9IEpTT04ucGFyc2Uoa2V5cykgYXMgc3RyaW5nW107XG4gICAgcmV0dXJuIHRoaXMucmVwby5yZWFkQWxsKGtleXMsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG11bHRpcGxlIG1vZGVscyBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgdXBkYXRlQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byB1cGRhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyB1cGRhdGVBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWxzOiBzdHJpbmcgfCBNW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMLCB0cnVlKVxuICAgICkuZm9yKHRoaXMudXBkYXRlQWxsKTtcbiAgICBpZiAodHlwZW9mIG1vZGVscyA9PT0gXCJzdHJpbmdcIilcbiAgICAgIG1vZGVscyA9IChKU09OLnBhcnNlKG1vZGVscykgYXMgW10pXG4gICAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKSBhcyBhbnk7XG5cbiAgICBsb2cuaW5mbyhgdXBkYXRpbmcgJHttb2RlbHMubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiB0aGlzLnJlcG8udXBkYXRlQWxsKG1vZGVscyBhcyB1bmtub3duIGFzIE1bXSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcXVlcnkgd2l0aCB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbnMgYW5kIG9wdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgc2ltcGxpZmllZCB3YXkgdG8gcXVlcnkgdGhlIGRhdGFiYXNlIHdpdGggY29tbW9uIHF1ZXJ5IHBhcmFtZXRlcnMuXG4gICAqIEBwYXJhbSB7Q29uZGl0aW9uPE0+fSBjb25kaXRpb24gLSBUaGUgY29uZGl0aW9uIHRvIGZpbHRlciByZWNvcmRzLlxuICAgKiBAcGFyYW0gb3JkZXJCeSAtIFRoZSBmaWVsZCB0byBvcmRlciByZXN1bHRzIGJ5LlxuICAgKiBAcGFyYW0ge09yZGVyRGlyZWN0aW9ufSBbb3JkZXI9T3JkZXJEaXJlY3Rpb24uQVNDXSAtIFRoZSBzb3J0IGRpcmVjdGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtsaW1pdF0gLSBPcHRpb25hbCBtYXhpbXVtIG51bWJlciBvZiByZXN1bHRzIHRvIHJldHVybi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtza2lwXSAtIE9wdGlvbmFsIG51bWJlciBvZiByZXN1bHRzIHRvIHNraXAuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gVGhlIHF1ZXJ5IHJlc3VsdHMgYXMgbW9kZWwgaW5zdGFuY2VzLlxuICAgKi9cbiAgYXN5bmMgcXVlcnkoXG4gICAgY29udGV4dDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGNvbmRpdGlvbjogQ29uZGl0aW9uPE0+IHwgc3RyaW5nLFxuICAgIG9yZGVyQnk6IHN0cmluZyB8IGtleW9mIE0sXG4gICAgb3JkZXI6IE9yZGVyRGlyZWN0aW9uIHwgc3RyaW5nID0gT3JkZXJEaXJlY3Rpb24uQVNDLFxuICAgIGxpbWl0PzogbnVtYmVyLFxuICAgIHNraXA/OiBudW1iZXIsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjb250ZXh0XSwgUGVyc2lzdGVuY2VLZXlzLlFVRVJZLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuY3JlYXRlKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnF1ZXJ5KFxuICAgICAgY29uZGl0aW9uIGFzIENvbmRpdGlvbjxNPixcbiAgICAgIG9yZGVyQnkgYXMga2V5b2YgTSxcbiAgICAgIG9yZGVyIGFzIE9yZGVyRGlyZWN0aW9uLFxuICAgICAgbGltaXQsXG4gICAgICBza2lwLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIHJhdyBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHthbnl9IHJhd0lucHV0IC0gVGhlIHF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHBhcmFtIHtib29sZWFufSBkb2NzT25seSAtIFdoZXRoZXIgdG8gcmV0dXJuIG9ubHkgZG9jdW1lbnRzXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBxdWVyeSByZXN1bHRzXG4gICAqL1xuICBhc3luYyByYXcoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgcmF3SW5wdXQ6IE1hbmdvUXVlcnksXG4gICAgZG9jc09ubHk6IGJvb2xlYW4sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgXCJyYXdcIiwgdHJ1ZSkpLmZvcihcbiAgICAgIHRoaXMucmF3XG4gICAgKTtcbiAgICByZXR1cm4gRmFicmljQ3J1ZENvbnRyYWN0LmFkYXB0ZXIucmF3KHJhd0lucHV0LCBkb2NzT25seSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2VyaWFsaXplKG1vZGVsOiBNKTogc3RyaW5nIHtcbiAgICByZXR1cm4gRmFicmljQ3J1ZENvbnRyYWN0LnNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBkZXNlcmlhbGl6ZTxNIGV4dGVuZHMgTW9kZWw+KHN0cjogc3RyaW5nKTogTSB7XG4gICAgcmV0dXJuIChcbiAgICAgIEZhYnJpY0NydWRDb250cmFjdC5zZXJpYWxpemVyIGFzIHVua25vd24gYXMgU2VyaWFsaXplcjxNPlxuICAgICkuZGVzZXJpYWxpemUoc3RyKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpbml0KGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IChcbiAgICAgIGF3YWl0IHRoaXMubG9nQ3R4KFtjdHhdLCBQZXJzaXN0ZW5jZUtleXMuSU5JVElBTElaQVRJT04sIHRydWUpXG4gICAgKS5mb3IodGhpcy5pbml0KTtcbiAgICBsb2cuaW5mbyhgUnVubmluZyBjb250cmFjdCAke3RoaXMuZ2V0TmFtZSgpfSBpbml0aWFsaXphdGlvbi4uLmApO1xuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIGxvZy5pbmZvKGBDb250cmFjdCBpbml0aWFsaXphdGlvbiBjb21wbGV0ZWQuYCk7XG4gIH1cblxuICBhc3luYyBoZWFsdGhjaGVjayhcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICApOiBQcm9taXNlPHN0cmluZyB8IGhlYWx0aGNoZWNrPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IChhd2FpdCB0aGlzLmxvZ0N0eChbY3R4XSwgXCJoZWFsdGhjaGVja1wiLCB0cnVlKSkuZm9yKFxuICAgICAgdGhpcy5oZWFsdGhjaGVja1xuICAgICk7XG4gICAgbG9nLmluZm8oYFJ1bm5pbmcgSGVhbHRoY2hlY2s6ICR7dGhpcy5pbml0aWFsaXplZH0uLi5gKTtcbiAgICByZXR1cm4geyBoZWFsdGhjaGVjazogdGhpcy5pbml0aWFsaXplZCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG11bHRpcGxlIG1vZGVscyBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgY3JlYXRlQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byBjcmVhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNyZWF0ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyBjcmVhdGVBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWxzOiBzdHJpbmcgfCBNW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gKFxuICAgICAgYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5DUkVBVEVfQUxMLCB0cnVlKVxuICAgICkuZm9yKHRoaXMuY3JlYXRlQWxsKTtcbiAgICBpZiAodHlwZW9mIG1vZGVscyA9PT0gXCJzdHJpbmdcIilcbiAgICAgIG1vZGVscyA9IChKU09OLnBhcnNlKG1vZGVscykgYXMgW10pXG4gICAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKSBhcyBhbnk7XG5cbiAgICBsb2cuaW5mbyhgYWRkaW5nICR7bW9kZWxzLmxlbmd0aH0gZW50cmllcyB0byB0aGUgdGFibGVgKTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmNyZWF0ZUFsbChtb2RlbHMgYXMgdW5rbm93biBhcyBNW10sIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGxvZ0N0eDxcbiAgICBBUkdTIGV4dGVuZHMgYW55W10gPSBhbnlbXSxcbiAgICBNRVRIT0QgZXh0ZW5kcyBNZXRob2RPck9wZXJhdGlvbiA9IE1ldGhvZE9yT3BlcmF0aW9uLFxuICA+KFxuICAgIGFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+LFxuICAgIG9wZXJhdGlvbjogTUVUSE9EXG4gICk6IEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+O1xuICBwcm90ZWN0ZWQgbG9nQ3R4PFxuICAgIEFSR1MgZXh0ZW5kcyBhbnlbXSA9IGFueVtdLFxuICAgIE1FVEhPRCBleHRlbmRzIE1ldGhvZE9yT3BlcmF0aW9uID0gTWV0aG9kT3JPcGVyYXRpb24sXG4gID4oXG4gICAgYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4sXG4gICAgb3BlcmF0aW9uOiBNRVRIT0QsXG4gICAgYWxsb3dDcmVhdGU6IGZhbHNlXG4gICk6IEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+O1xuICBwcm90ZWN0ZWQgbG9nQ3R4PFxuICAgIEFSR1MgZXh0ZW5kcyBhbnlbXSA9IGFueVtdLFxuICAgIE1FVEhPRCBleHRlbmRzIE1ldGhvZE9yT3BlcmF0aW9uID0gTWV0aG9kT3JPcGVyYXRpb24sXG4gID4oXG4gICAgYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4sXG4gICAgb3BlcmF0aW9uOiBNRVRIT0QsXG4gICAgYWxsb3dDcmVhdGU6IHRydWVcbiAgKTogUHJvbWlzZTxcbiAgICBGYWJyaWNDb250ZXh0dWFsaXplZEFyZ3M8QVJHUywgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlPlxuICA+O1xuICBwcm90ZWN0ZWQgbG9nQ3R4PFxuICAgIEFSR1MgZXh0ZW5kcyBhbnlbXSA9IGFueVtdLFxuICAgIE1FVEhPRCBleHRlbmRzIE1ldGhvZE9yT3BlcmF0aW9uID0gTWV0aG9kT3JPcGVyYXRpb24sXG4gID4oXG4gICAgYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4sXG4gICAgb3BlcmF0aW9uOiBNRVRIT0QsXG4gICAgYWxsb3dDcmVhdGU6IGJvb2xlYW4gPSBmYWxzZVxuICApOlxuICAgIHwgUHJvbWlzZTxcbiAgICAgICAgRmFicmljQ29udGV4dHVhbGl6ZWRBcmdzPEFSR1MsIE1FVEhPRCBleHRlbmRzIHN0cmluZyA/IHRydWUgOiBmYWxzZT5cbiAgICAgID5cbiAgICB8IEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+IHtcbiAgICBjb25zdCBjdHggPSBhcmdzLnBvcCgpO1xuICAgIGlmICghY3R4IHx8ICFjdHguc3R1Yikge1xuICAgICAgdGhyb3cgbmV3IE1pc3NpbmdDb250ZXh0RXJyb3IoYE5vIHZhbGlkIGNvbnRleHQgcHJvdmlkZWQuLi5gKTtcbiAgICB9XG4gICAgY29uc3QgY29udGV4dHVhbGl6ZWQgPSBGYWJyaWNDcnVkQ29udHJhY3QuYWRhcHRlcltcImxvZ0N0eFwiXShcbiAgICAgIFt0aGlzLmNsYXp6IGFzIGFueSwgLi4uYXJnc10gYXMgYW55LFxuICAgICAgb3BlcmF0aW9uLFxuICAgICAgYWxsb3dDcmVhdGUgYXMgYW55LFxuICAgICAgY3R4XG4gICAgKSBhc1xuICAgICAgfCBGYWJyaWNDb250ZXh0dWFsaXplZEFyZ3M8QVJHUywgTUVUSE9EIGV4dGVuZHMgc3RyaW5nID8gdHJ1ZSA6IGZhbHNlPlxuICAgICAgfCBQcm9taXNlPFxuICAgICAgICAgIEZhYnJpY0NvbnRleHR1YWxpemVkQXJnczxBUkdTLCBNRVRIT0QgZXh0ZW5kcyBzdHJpbmcgPyB0cnVlIDogZmFsc2U+XG4gICAgICAgID47XG4gICAgZnVuY3Rpb24gc3F1YXNoQXJncyhjdHg6IEZhYnJpY0NvbnRleHR1YWxpemVkQXJncykge1xuICAgICAgY3R4LmN0eEFyZ3Muc2hpZnQoKTsgLy8gcmVtb3ZlcyBhZGRlZCBtb2RlbCB0byBhcmdzXG4gICAgICByZXR1cm4gY3R4IGFzIGFueTtcbiAgICB9XG5cbiAgICBpZiAoIShjb250ZXh0dWFsaXplZCBpbnN0YW5jZW9mIFByb21pc2UpKSByZXR1cm4gc3F1YXNoQXJncyhjb250ZXh0dWFsaXplZCk7XG4gICAgcmV0dXJuIGNvbnRleHR1YWxpemVkLnRoZW4oc3F1YXNoQXJncyk7XG4gIH1cbiAgLy9cbiAgLy8gcHJvdGVjdGVkIHN0YXRpYyBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgLy8gICB0aGlzOiBhbnksXG4gIC8vICAgYXJnczogQVJHUyxcbiAgLy8gICBtZXRob2Q6IHN0cmluZ1xuICAvLyApOiBQcm9taXNlPFxuICAvLyAgIENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAvLyAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgLy8gICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gICB9XG4gIC8vID47XG4gIC8vIHByb3RlY3RlZCBzdGF0aWMgYXN5bmMgbG9nQ3R4PEFSR1MgZXh0ZW5kcyBhbnlbXT4oXG4gIC8vICAgdGhpczogYW55LFxuICAvLyAgIGFyZ3M6IEFSR1MsXG4gIC8vICAgbWV0aG9kOiAoLi4uYXJnczogYW55W10pID0+IGFueVxuICAvLyApOiBQcm9taXNlPFxuICAvLyAgIENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAvLyAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgLy8gICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgLy8gICB9XG4gIC8vID47XG4gIC8vIHByb3RlY3RlZCBzdGF0aWMgYXN5bmMgbG9nQ3R4PEFSR1MgZXh0ZW5kcyBhbnlbXT4oXG4gIC8vICAgdGhpczogYW55LFxuICAvLyAgIGFyZ3M6IEFSR1MsXG4gIC8vICAgbWV0aG9kOiAoKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkpIHwgc3RyaW5nXG4gIC8vICk6IFByb21pc2U8XG4gIC8vICAgQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gIC8vICAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAvLyAgICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICAvLyAgIH1cbiAgLy8gPiB7XG4gIC8vICAgaWYgKGFyZ3MubGVuZ3RoIDwgMSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJObyBjb250ZXh0IHByb3ZpZGVkXCIpO1xuICAvLyAgIGNvbnN0IGN0eCA9IGFyZ3MucG9wKCkgYXMgRmFicmljQ29udHJhY3RDb250ZXh0IHwgQ29udGV4dDtcbiAgLy8gICBpZiAoY3R4IGluc3RhbmNlb2YgRmFicmljQ29udHJhY3RDb250ZXh0KVxuICAvLyAgICAgcmV0dXJuIHtcbiAgLy8gICAgICAgY3R4LFxuICAvLyAgICAgICBsb2c6IChcbiAgLy8gICAgICAgICBjdHgubG9nZ2VyIHx8XG4gIC8vICAgICAgICAgbmV3IENvbnRyYWN0TG9nZ2VyKCh0aGlzIGFzIGFueSk/Lm5hbWUgfHwgXCJDb250cmFjdFwiLCB1bmRlZmluZWQpXG4gIC8vICAgICAgIClcbiAgLy8gICAgICAgICAuY2xlYXIoKVxuICAvLyAgICAgICAgIC5mb3IodGhpcylcbiAgLy8gICAgICAgICAuZm9yKG1ldGhvZCksXG4gIC8vICAgICAgIGN0eEFyZ3M6IFsuLi5hcmdzLCBjdHhdLFxuICAvLyAgICAgICBzdHViOiBjdHguc3R1YixcbiAgLy8gICAgICAgaWRlbnRpdHk6IGN0eC5pZGVudGl0eSxcbiAgLy8gICAgIH07XG4gIC8vXG4gIC8vICAgaWYgKCEoY3R4IGluc3RhbmNlb2YgQ3R4KSlcbiAgLy8gICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm8gdmFsaWQgY29udGV4dCBwcm92aWRlZFwiKTtcbiAgLy9cbiAgLy8gICBmdW5jdGlvbiBnZXRPcCgpIHtcbiAgLy8gICAgIGlmICh0eXBlb2YgbWV0aG9kID09PSBcInN0cmluZ1wiKSByZXR1cm4gbWV0aG9kO1xuICAvLyAgICAgc3dpdGNoIChtZXRob2QubmFtZSkge1xuICAvLyAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAvLyAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuUkVBRDpcbiAgLy8gICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLlVQREFURTpcbiAgLy8gICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLkRFTEVURTpcbiAgLy8gICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTDpcbiAgLy8gICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTEw6XG4gIC8vICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLlVQREFURV9BTEw6XG4gIC8vICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEw6XG4gIC8vICAgICAgICAgcmV0dXJuIG1ldGhvZC5uYW1lO1xuICAvLyAgICAgICBkZWZhdWx0OlxuICAvLyAgICAgICAgIHJldHVybiBtZXRob2QubmFtZTtcbiAgLy8gICAgIH1cbiAgLy8gICB9XG4gIC8vXG4gIC8vICAgY29uc3Qgb3ZlcnJpZGVzID0ge1xuICAvLyAgICAgY29ycmVsYXRpb25JZDogY3R4LnN0dWIuZ2V0VHhJRCgpLFxuICAvLyAgIH07XG4gIC8vICAgY29uc3QgY29udGV4dCA9IGF3YWl0IEZhYnJpY0NydWRDb250cmFjdC5hZGFwdGVyLmNvbnRleHQoXG4gIC8vICAgICBnZXRPcCgpLFxuICAvLyAgICAgb3ZlcnJpZGVzIGFzIGFueSxcbiAgLy8gICAgIHRoaXMuY2xhenosXG4gIC8vICAgICBjdHhcbiAgLy8gICApO1xuICAvL1xuICAvLyAgIGNvbnN0IGJhc2VMb2dnZXIgPVxuICAvLyAgICAgY29udGV4dC5sb2dnZXIgfHxcbiAgLy8gICAgIG5ldyBDb250cmFjdExvZ2dlcigodGhpcyBhcyBhbnkpPy5uYW1lIHx8IFwiQ29udHJhY3RcIiwgdW5kZWZpbmVkLCBjdHgpO1xuICAvLyAgIGNvbnN0IGxvZyA9IChcbiAgLy8gICAgIHRoaXNcbiAgLy8gICAgICAgPyBiYXNlTG9nZ2VyLmZvcih0aGlzKS5mb3IobWV0aG9kKVxuICAvLyAgICAgICA6IGJhc2VMb2dnZXIuY2xlYXIoKS5mb3IodGhpcykuZm9yKG1ldGhvZClcbiAgLy8gICApIGFzIExvZ2dlck9mPEZhYnJpY0NvbnRyYWN0Q29udGV4dD47XG4gIC8vICAgcmV0dXJuIHtcbiAgLy8gICAgIGN0eDogY29udGV4dCxcbiAgLy8gICAgIGxvZzogbG9nLFxuICAvLyAgICAgc3R1YjogY29udGV4dC5zdHViLFxuICAvLyAgICAgaWRlbnRpdHk6IGNvbnRleHQuaWRlbnRpdHksXG4gIC8vICAgICBjdHhBcmdzOiBbLi4uYXJncywgY29udGV4dF0sXG4gIC8vICAgfTtcbiAgLy8gfVxufVxuIiwiaW1wb3J0IHsgRmFicmljQ3J1ZENvbnRyYWN0IH0gZnJvbSBcIi4vY3J1ZC1jb250cmFjdFwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb250ZXh0IGFzIEN0eCwgVHJhbnNhY3Rpb24gfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IENvbmRpdGlvbiwgT3JkZXJEaXJlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDUlVEIGNvbnRyYWN0IHZhcmlhbnQgdGhhdCBzZXJpYWxpemVzL2Rlc2VyaWFsaXplcyBwYXlsb2Fkc1xuICogQHN1bW1hcnkgRXhwb3NlcyB0aGUgc2FtZSBDUlVEIG9wZXJhdGlvbnMgYXMgRmFicmljQ3J1ZENvbnRyYWN0IGJ1dCB0YWtlcyBhbmQgcmV0dXJucyBKU09OIHN0cmluZ3MgdG8gZmFjaWxpdGF0ZSBzaW1wbGUgY2xpZW50IGludGVyYWN0aW9ucy5cbiAqIEB0ZW1wbGF0ZSBNIC0gTW9kZWwgdHlwZSBoYW5kbGVkIGJ5IHRoaXMgY29udHJhY3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIGNvbnRyYWN0IG5hbWVcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yIHVzZWQgdG8gaW5zdGFudGlhdGUgbW9kZWxzIGZyb20gSlNPTlxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBTZXJpYWxpemVkQ3J1ZENvbnRyYWN0XG4gKiBAZXhhbXBsZVxuICogY29uc3QgY29udHJhY3QgPSBuZXcgU2VyaWFsaXplZENydWRDb250cmFjdDxNeU1vZGVsPignTXlNb2RlbENvbnRyYWN0JywgTXlNb2RlbCk7XG4gKiAvLyBDbGllbnQgc3VibWl0cyBKU09OIHN0cmluZyBwYXlsb2FkcyBhbmQgcmVjZWl2ZXMgSlNPTiBzdHJpbmcgcmVzcG9uc2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJpYWxpemVkQ3J1ZENvbnRyYWN0PFxuICBNIGV4dGVuZHMgTW9kZWwsXG4+IGV4dGVuZHMgRmFicmljQ3J1ZENvbnRyYWN0PE0+IHtcbiAgY29uc3RydWN0b3IobmFtZTogc3RyaW5nLCBjbGF6ejogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBzdXBlcihuYW1lLCBjbGF6eik7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBjcmVhdGUoY3R4OiBDdHgsIG1vZGVsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSgoYXdhaXQgc3VwZXIuY3JlYXRlKGN0eCBhcyBhbnksIG1vZGVsKSkgYXMgTSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQoY3R4OiBDdHgsIGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemUoKGF3YWl0IHN1cGVyLnJlYWQoY3R4IGFzIGFueSwga2V5KSkgYXMgTSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyB1cGRhdGUoY3R4OiBDdHgsIG1vZGVsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSgoYXdhaXQgc3VwZXIudXBkYXRlKGN0eCwgbW9kZWwpKSBhcyBNKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZShjdHg6IEN0eCwga2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSgoYXdhaXQgc3VwZXIuZGVsZXRlKGN0eCBhcyBhbnksIGtleSkpIGFzIE0pO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKClcbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlQWxsKGN0eDogQ3R4LCBrZXlzOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHBhcnNlZEtleXM6IHN0cmluZ1tdID0gSlNPTi5wYXJzZShrZXlzKTtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAoKGF3YWl0IHN1cGVyLmRlbGV0ZUFsbChjdHggYXMgYW55LCBwYXJzZWRLZXlzKSkgYXMgTVtdKS5tYXAoXG4gICAgICAgIChtKSA9PiB0aGlzLnNlcmlhbGl6ZShtKSBhcyBzdHJpbmdcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyByZWFkQWxsKGN0eDogQ3R4LCBrZXlzOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHBhcnNlZEtleXM6IHN0cmluZ1tdID0gSlNPTi5wYXJzZShrZXlzKTtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAoKGF3YWl0IHN1cGVyLnJlYWRBbGwoY3R4IGFzIGFueSwgcGFyc2VkS2V5cykpIGFzIE1bXSkubWFwKChtKSA9PlxuICAgICAgICB0aGlzLnNlcmlhbGl6ZShtKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGwoY3R4OiBDdHgsIG1vZGVsczogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsaXN0OiBzdHJpbmdbXSA9IEpTT04ucGFyc2UobW9kZWxzKTtcbiAgICBjb25zdCBtb2RlbExpc3Q6IE1bXSA9IGxpc3RcbiAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAubWFwKChtKSA9PiBuZXcgdGhpcy5jbGF6eihtKSk7XG5cbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAoKGF3YWl0IHN1cGVyLnVwZGF0ZUFsbChjdHggYXMgYW55LCBtb2RlbExpc3QpKSBhcyBNW10pLm1hcChcbiAgICAgICAgKG0pID0+IHRoaXMuc2VyaWFsaXplKG0pIGFzIHN0cmluZ1xuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHN0YXRlbWVudChjdHg6IEN0eCwgbWV0aG9kOiBzdHJpbmcsIGFyZ3M6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBhcmdzID0gSlNPTi5wYXJzZShhcmdzKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBJbnZhbGlkIGFyZ3M6ICR7ZX1gKTtcbiAgICB9XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGFyZ3MpKVxuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEludmFsaWQgYXJnczogJHtKU09OLnN0cmluZ2lmeShhcmdzKX0uIG11c3QgYmUgYW4gYXJyYXlgXG4gICAgICApO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhd2FpdCBzdXBlci5zdGF0ZW1lbnQoY3R4LCBtZXRob2QsIC4uLmFyZ3MpKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgbGlzdEJ5KGN0eDogQ3R4LCBrZXk6IHN0cmluZywgb3JkZXI6IHN0cmluZykge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgIGF3YWl0IHN1cGVyLmxpc3RCeShjdHgsIGtleSBhcyBrZXlvZiBNLCBvcmRlciBhcyBPcmRlckRpcmVjdGlvbilcbiAgICApO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGN0eDogQ3R4LFxuICAgIGtleTogc3RyaW5nLFxuICAgIG9yZGVyOiBzdHJpbmcsXG4gICAgcmVmOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICB0cnkge1xuICAgICAgcmVmID0gSlNPTi5wYXJzZShyZWYpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gZGVzZXJpYWxpemUgcGFnaW5hdGVCeSByZWZlcmVuY2U6ICR7ZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoXG4gICAgICBhd2FpdCBzdXBlci5wYWdpbmF0ZUJ5KGN0eCwga2V5LCBvcmRlciBhcyBhbnksIHJlZiBhcyBhbnkpXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgZmluZE9uZUJ5KGN0eDogQ3R4LCBrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhd2FpdCBzdXBlci5maW5kT25lQnkoY3R4LCBrZXksIHZhbHVlKSk7XG4gIH1cblxuICAvLyBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHF1ZXJ5KFxuICAgIGN0eDogQ3R4LFxuICAgIGNvbmRpdGlvbjogc3RyaW5nLFxuICAgIG9yZGVyQnk6IHN0cmluZyxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIGxpbWl0PzogbnVtYmVyLFxuICAgIHNraXA/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBsZXQgY29uZDogQ29uZGl0aW9uPGFueT47XG4gICAgdHJ5IHtcbiAgICAgIGNvbmQgPSBDb25kaXRpb24uZnJvbShKU09OLnBhcnNlKGNvbmRpdGlvbikpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoYEludmFsaWQgY29uZGl0aW9uOiAke2V9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFxuICAgICAgYXdhaXQgc3VwZXIucXVlcnkoY3R4LCBjb25kLCBvcmRlckJ5LCBvcmRlciBhcyBhbnksIGxpbWl0LCBza2lwKVxuICAgICk7XG4gIH1cbiAgLy9cbiAgLy8gLy8gQFRyYW5zYWN0aW9uKGZhbHNlKVxuICAvLyBvdmVycmlkZSBhc3luYyByYXcoXG4gIC8vICAgY29udGV4dDogQ3R4LFxuICAvLyAgIHJhd0lucHV0OiBzdHJpbmcsXG4gIC8vICAgZG9jc09ubHk6IGJvb2xlYW4sXG4gIC8vICAgLi4uYXJnczogc3RyaW5nW11cbiAgLy8gKTogUHJvbWlzZTxhbnk+IHtcbiAgLy8gICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJhdyk7XG4gIC8vICAgY29uc3QgcGFyc2VkSW5wdXQ6IE1hbmdvUXVlcnkgPSBKU09OLnBhcnNlKHJhd0lucHV0KTtcbiAgLy8gICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXdhaXQgc3VwZXIucmF3KGN0eCwgcGFyc2VkSW5wdXQsIGRvY3NPbmx5LCAuLi5hcmdzKSk7XG4gIC8vIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBpbml0KGN0eDogQ3R4KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgc3VwZXIuaW5pdChjdHgpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBoZWFsdGhjaGVjayhjdHg6IEN0eCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgLy9UT0RPOiBUUklNIE5PVCBXT1JLSU5HIENIRUNLIExBVEVSXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGF3YWl0IHN1cGVyLmhlYWx0aGNoZWNrKGN0eCBhcyBhbnkpKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbChjb250ZXh0OiBDdHgsIG1vZGVsczogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsaXN0OiBzdHJpbmdbXSA9IEpTT04ucGFyc2UobW9kZWxzKTtcbiAgICBjb25zdCBtb2RlbExpc3Q6IE1bXSA9IGxpc3RcbiAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAubWFwKChtKSA9PiBuZXcgdGhpcy5jbGF6eihtKSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgc3VwZXIuY3JlYXRlQWxsKGNvbnRleHQsIG1vZGVsTGlzdCkpIGFzIE1bXTtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0Lm1hcCgobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nKSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEJhc2VNb2RlbCwgY29sdW1uLCBwaywgdGFibGUgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IG1vZGVsLCB0eXBlIE1vZGVsQXJnLCByZXF1aXJlZCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRVJDMjAgdG9rZW4gbWV0YWRhdGEgbW9kZWxcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gRVJDMjAgdG9rZW4gZGVmaW5pdGlvbiB3aXRoaW4gdGhlIEZhYnJpYyBFUkMyMCBzYW1wbGUsIGluY2x1ZGluZyBuYW1lLCBzeW1ib2wsIGRlY2ltYWxzLCBhbmQgdGhlIG93bmluZyBpZGVudGl0eS4gVXNlZCB0byBkZWZpbmUgdGhlIHVuaXF1ZSB0b2tlbiBtYW5hZ2VkIGJ5IHRoZSBjb250cmFjdC5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8RVJDMjBUb2tlbj59IFttXSAtIE9wdGlvbmFsIHBhcnRpYWwgZGF0YSBvciBhbm90aGVyIGluc3RhbmNlIHRvIGluaXRpYWxpemUgdGhlIG1vZGVsXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEVSQzIwVG9rZW5cbiAqIEBleGFtcGxlXG4gKiBjb25zdCB0b2tlbiA9IG5ldyBFUkMyMFRva2VuKHsgbmFtZTogXCJNeVRva2VuXCIsIHN5bWJvbDogXCJNVEtcIiwgZGVjaW1hbHM6IDE4LCBvd25lcjogXCJ4NTA5OjouLi5cIiB9KTtcbiAqIC8vIFBlcnNpc3QgdGhyb3VnaCBhIHJlcG9zaXRvcnk6IGF3YWl0IHJlcG8uY3JlYXRlKHRva2VuLCBjdHgpXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBSZXBvXG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgQXBwLT4+UmVwbzogY3JlYXRlKG5ldyBFUkMyMFRva2VuKHsuLi59KSwgY3R4KVxuICogICBSZXBvLT4+QWRhcHRlcjogY3JlYXRlKHRhYmxlLCBpZD1uYW1lLCByZWNvcmQsIGZsYWdzKVxuICogICBBZGFwdGVyLS0+PlJlcG86IHN0b3JlZFxuICogICBSZXBvLS0+PkFwcDogbW9kZWxcbiAqL1xuQHRhYmxlKFwiZXJjMjBfdG9rZW5zXCIpXG5AbW9kZWwoKVxuZXhwb3J0IGNsYXNzIEVSQzIwVG9rZW4gZXh0ZW5kcyBCYXNlTW9kZWwge1xuICBAcGsoeyB0eXBlOiBTdHJpbmcgfSlcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiB1bmlxdWUgbmFtZVxuICAgKiBAc3VtbWFyeSBTZXJ2ZXMgYXMgdGhlIHByaW1hcnkga2V5IGZvciB0aGUgRVJDMjAgdG9rZW4gZGVmaW5pdGlvbjsgdHlwaWNhbGx5IGEgaHVtYW4tcmVhZGFibGUgaWRlbnRpZmllclxuICAgKi9cbiAgbmFtZSE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBPd25pbmcgaWRlbnRpdHkgb2YgdGhlIHRva2VuXG4gICAqIEBzdW1tYXJ5IFguNTA5IHN1YmplY3Qgb3IgTVNQIGlkZW50aXR5IHN0cmluZyB0aGF0IGRlbm90ZXMgd2hvIG93bnMvY29udHJvbHMgdGhlIHRva2VuIGRlZmluaXRpb25cbiAgICovXG4gIG93bmVyITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiBzeW1ib2xcbiAgICogQHN1bW1hcnkgU2hvcnQgdGlja2VyLWxpa2Ugc3ltYm9sIHVzZWQgdG8gcmVwcmVzZW50IHRoZSB0b2tlbiAoZS5nLiwgTVRLKVxuICAgKi9cbiAgc3ltYm9sITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNpbWFsIHByZWNpc2lvbiBmb3IgdG9rZW4gYW1vdW50c1xuICAgKiBAc3VtbWFyeSBOdW1iZXIgb2YgZGlnaXRzIGFmdGVyIHRoZSBkZWNpbWFsIHNlcGFyYXRvciB1c2VkIHdoZW4gZm9ybWF0dGluZyB0b2tlbiBiYWxhbmNlc1xuICAgKi9cbiAgZGVjaW1hbHMhOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IobT86IE1vZGVsQXJnPEVSQzIwV2FsbGV0Pikge1xuICAgIHN1cGVyKG0pO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVSQzIwIHdhbGxldCBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGhvbGRlciBhY2NvdW50IGZvciBhbiBFUkMyMCB0b2tlbiB3aXRoaW4gdGhlIEZhYnJpYyBuZXR3b3JrLCB0cmFja2luZyBiYWxhbmNlIGFuZCB0b2tlbiBhc3NvY2lhdGlvbi5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8RVJDMjBXYWxsZXQ+fSBbbV0gLSBPcHRpb25hbCBwYXJ0aWFsIGRhdGEgb3IgYW5vdGhlciBpbnN0YW5jZSB0byBpbml0aWFsaXplIHRoZSBtb2RlbFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBFUkMyMFdhbGxldFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHdhbGxldCA9IG5ldyBFUkMyMFdhbGxldCh7IGlkOiBcImFjY3QxXCIsIHRva2VuOiBcIk15VG9rZW5cIiwgYmFsYW5jZTogMTAwMCB9KTtcbiAqIC8vIFVwZGF0ZSBiYWxhbmNlIHZpYSByZXBvc2l0b3J5OiBhd2FpdCByZXBvLnVwZGF0ZSh3YWxsZXQsIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgQXBwLT4+UmVwbzogcmVhZChcImFjY3QxXCIsIGN0eClcbiAqICAgUmVwby0tPj5BcHA6IEVSQzIwV2FsbGV0XG4gKi9cbkB0YWJsZShcImVyYzIwX3dhbGxldHNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBXYWxsZXQgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICBAcGsoeyB0eXBlOiBTdHJpbmcgfSlcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXYWxsZXQgdW5pcXVlIGlkZW50aWZpZXJcbiAgICogQHN1bW1hcnkgUHJpbWFyeSBrZXkgZm9yIHRoZSB3YWxsZXQ7IGNvbW1vbmx5IHJlZmVyZW5jZXMgYW4gYWNjb3VudCBvciBpZGVudGl0eVxuICAgKi9cbiAgaWQhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNzb2NpYXRlZCB0b2tlbiBuYW1lXG4gICAqIEBzdW1tYXJ5IFJlZmVyZW5jZXMgdGhlIEVSQzIwVG9rZW4gdGhpcyB3YWxsZXQgaG9sZHM7IG1haW50YWluZWQgYXMgYSByZWxhdGlvbnNoaXAgZm9yIGNhc2NhZGluZyB1cGRhdGVzL2RlbGV0ZXNcbiAgICovXG4gIHRva2VuITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRva2VuIGJhbGFuY2UgZm9yIHRoaXMgd2FsbGV0XG4gICAqIEBzdW1tYXJ5IEN1cnJlbnQgYW1vdW50IG9mIHRoZSBhc3NvY2lhdGVkIHRva2VuIGhlbGQgYnkgdGhpcyB3YWxsZXRcbiAgICovXG4gIGJhbGFuY2UhOiBudW1iZXI7XG5cbiAgQGNvbHVtbigpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2FwdGl2ZSBmbGFnIG9yIGlkZW50aWZpZXJcbiAgICogQHN1bW1hcnkgT3B0aW9uYWwgZmllbGQgdXNlZCBieSBzb21lIGZsb3dzIHRvIG1hcmsgbm9uLXRyYW5zZmVyYWJsZSBmdW5kcyBvciBtYW5hZ2VkIGN1c3RvZHlcbiAgICovXG4gIGNhcHRpdmUhOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IobT86IE1vZGVsQXJnPEVSQzIwV2FsbGV0Pikge1xuICAgIHN1cGVyKG0pO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVSQzIwIGFsbG93YW5jZSBtb2RlbFxuICogQHN1bW1hcnkgQ2FwdHVyZXMgYW4gYXBwcm92YWwgcmVsYXRpb25zaGlwIHdoZXJlIGFuIG93bmVyIGFsbG93cyBhIHNwZW5kZXIgdG8gdHJhbnNmZXIgdXAgdG8gYSBjZXJ0YWluIHZhbHVlIGZyb20gdGhlIG93bmVyJ3Mgd2FsbGV0LlxuICogQHBhcmFtIHtNb2RlbEFyZzxBbGxvd2FuY2U+fSBbbV0gLSBPcHRpb25hbCBwYXJ0aWFsIGRhdGEgb3IgYW5vdGhlciBpbnN0YW5jZSB0byBpbml0aWFsaXplIHRoZSBtb2RlbFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBBbGxvd2FuY2VcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBhbGxvd2FuY2UgPSBuZXcgQWxsb3dhbmNlKHsgb3duZXI6IFwiYWNjdDFcIiwgc3BlbmRlcjogXCJhY2N0MlwiLCB2YWx1ZTogNTAgfSk7XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBBcHAtPj5BcHA6IG5ldyBBbGxvd2FuY2UoeyBvd25lciwgc3BlbmRlciwgdmFsdWUgfSlcbiAqL1xuQHRhYmxlKFwiZXJjMjBfYWxsb3dhbmNlc1wiKVxuQG1vZGVsKClcbmV4cG9ydCBjbGFzcyBBbGxvd2FuY2UgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICBAcGsoeyB0eXBlOiBTdHJpbmcgfSlcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBbGxvd2FuY2UgdW5pcXVlIGlkZW50aWZpZXJcbiAgICogQHN1bW1hcnkgUHJpbWFyeSBrZXkgZm9yIHRoZSBhbGxvd2FuY2U7IHR5cGljYWxseSBhIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgYXBwcm92YWwgcmVsYXRpb25zaGlwXG4gICAqL1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBPd25lciB3YWxsZXQgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBXYWxsZXQgdGhhdCBhdXRob3JpemVzIHRoZSBhbGxvd2FuY2VcbiAgICovXG4gIG93bmVyITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNwZW5kZXIgd2FsbGV0IGlkZW50aWZpZXJcbiAgICogQHN1bW1hcnkgV2FsbGV0IGFsbG93ZWQgdG8gc3BlbmQgdXAgdG8gdGhlIGFwcHJvdmVkIHZhbHVlIGZyb20gdGhlIG93bmVyXG4gICAqL1xuICBzcGVuZGVyITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFwcHJvdmVkIHZhbHVlXG4gICAqIEBzdW1tYXJ5IE1heGltdW0gdG9rZW4gYW1vdW50IHRoZSBzcGVuZGVyIG1heSB0cmFuc2ZlciBvbiBiZWhhbGYgb2YgdGhlIG93bmVyXG4gICAqL1xuICB2YWx1ZSE6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihtPzogTW9kZWxBcmc8QWxsb3dhbmNlPikge1xuICAgIHN1cGVyKG0pO1xuICB9XG59XG4iLCJpbXBvcnQgeyBBdXRob3JpemF0aW9uRXJyb3IsIENvbmRpdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgQ29udGV4dCwgVHJhbnNhY3Rpb24gfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgYWRkLCBzdWIgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL21hdGhcIjtcbmltcG9ydCB7XG4gIEFsbG93YW5jZUVycm9yLFxuICBCYWxhbmNlRXJyb3IsXG4gIE5vdEluaXRpYWxpemVkRXJyb3IsXG59IGZyb20gXCIuLi8uLi9zaGFyZWQvZXJyb3JzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEFkYXB0ZXIgfSBmcm9tIFwiLi4vQ29udHJhY3RBZGFwdGVyXCI7XG5pbXBvcnQgeyBBbGxvd2FuY2UsIEVSQzIwVG9rZW4sIEVSQzIwV2FsbGV0IH0gZnJvbSBcIi4vbW9kZWxzXCI7XG5pbXBvcnQgeyBPd25lciB9IGZyb20gXCIuLi8uLi9zaGFyZWQvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeVwiO1xuaW1wb3J0IHR5cGUgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi4vQ29udHJhY3RDb250ZXh0XCI7XG5pbXBvcnQge1xuICBCYXNlRXJyb3IsXG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIFZhbGlkYXRpb25FcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBGYWJyaWNDcnVkQ29udHJhY3QgfSBmcm9tIFwiLi4vY3J1ZC9jcnVkLWNvbnRyYWN0XCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciB9IGZyb20gXCIuLi9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlclwiO1xuaW1wb3J0IHsgRVJDMjBFdmVudHMgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL2VyYzIwL2VyYzIwLWNvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCB0b2tlbiBjb250cmFjdCBiYXNlIGZvciBIeXBlcmxlZGdlciBGYWJyaWNcbiAqIEBzdW1tYXJ5IEltcGxlbWVudHMgRVJDMjAtbGlrZSB0b2tlbiBsb2dpYyB1c2luZyByZXBvc2l0b3JpZXMgYW5kIGFkYXB0ZXJzLCBwcm92aWRpbmcgc3RhbmRhcmQgdG9rZW4gb3BlcmF0aW9ucyBzdWNoIGFzIGJhbGFuY2UgcXVlcmllcywgdHJhbnNmZXJzLCBhcHByb3ZhbHMsIG1pbnRpbmcgYW5kIGJ1cm5pbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBjb250cmFjdCBuYW1lIHVzZWQgdG8gc2NvcGUgdG9rZW4gaWRlbnRpdHlcbiAqIEBub3RlIGh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtMjBcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRmFicmljRVJDMjBDb250cmFjdFxuICogQGV4YW1wbGVcbiAqIGNsYXNzIE15VG9rZW5Db250cmFjdCBleHRlbmRzIEZhYnJpY0VSQzIwQ29udHJhY3Qge1xuICogICBjb25zdHJ1Y3RvcigpIHsgc3VwZXIoJ015VG9rZW4nKTsgfVxuICogfVxuICogLy8gVGhlIGNvbnRyYWN0IGV4cG9zZXMgbWV0aG9kcyBsaWtlIFRyYW5zZmVyLCBBcHByb3ZlLCBNaW50LCBCdXJuLCBldGMuXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBXYWxsZXRSZXBvXG4gKiAgIHBhcnRpY2lwYW50IFRva2VuUmVwb1xuICogICBwYXJ0aWNpcGFudCBMZWRnZXJcbiAqICAgQ2xpZW50LT4+Q29udHJhY3Q6IFRyYW5zZmVyKGN0eCwgdG8sIHZhbHVlKVxuICogICBDb250cmFjdC0+PldhbGxldFJlcG86IHJlYWQoZnJvbSlcbiAqICAgQ29udHJhY3QtPj5XYWxsZXRSZXBvOiByZWFkKHRvKVxuICogICBDb250cmFjdC0+PkxlZGdlcjogcHV0U3RhdGUodXBkYXRlZCBiYWxhbmNlcylcbiAqICAgQ29udHJhY3QtLT4+Q2xpZW50OiBzdWNjZXNzXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGYWJyaWNFUkMyMENvbnRyYWN0IGV4dGVuZHMgRmFicmljQ3J1ZENvbnRyYWN0PEVSQzIwV2FsbGV0PiB7XG4gIHByaXZhdGUgd2FsbGV0UmVwb3NpdG9yeTogRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PEVSQzIwV2FsbGV0PjtcblxuICBwcml2YXRlIHRva2VuUmVwb3NpdG9yeTogRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PEVSQzIwVG9rZW4+O1xuXG4gIHByaXZhdGUgYWxsb3dhbmNlUmVwb3NpdG9yeTogRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PEFsbG93YW5jZT47XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZykge1xuICAgIHN1cGVyKG5hbWUsIEVSQzIwV2FsbGV0KTtcblxuICAgIEZhYnJpY0VSQzIwQ29udHJhY3QuYWRhcHRlciA9XG4gICAgICBGYWJyaWNFUkMyMENvbnRyYWN0LmFkYXB0ZXIgfHwgbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuXG4gICAgdGhpcy53YWxsZXRSZXBvc2l0b3J5ID0gRmFicmljQ29udHJhY3RSZXBvc2l0b3J5LmZvck1vZGVsKFxuICAgICAgRVJDMjBXYWxsZXQsXG4gICAgICBGYWJyaWNFUkMyMENvbnRyYWN0LmFkYXB0ZXIuYWxpYXNcbiAgICApO1xuXG4gICAgdGhpcy50b2tlblJlcG9zaXRvcnkgPSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkuZm9yTW9kZWwoXG4gICAgICBFUkMyMFRva2VuLFxuICAgICAgRmFicmljRVJDMjBDb250cmFjdC5hZGFwdGVyLmFsaWFzXG4gICAgKTtcblxuICAgIHRoaXMuYWxsb3dhbmNlUmVwb3NpdG9yeSA9IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeS5mb3JNb2RlbChcbiAgICAgIEFsbG93YW5jZSxcbiAgICAgIEZhYnJpY0VSQzIwQ29udHJhY3QuYWRhcHRlci5hbGlhc1xuICAgICk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIFRva2VuTmFtZShjb250ZXh0OiBDb250ZXh0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBzZWxlY3QgPSB0aGlzLnRva2VuUmVwb3NpdG9yeS5zZWxlY3QoKTtcbiAgICBjb25zdCB0b2tlbiA9IChhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpKVswXTtcblxuICAgIHJldHVybiB0b2tlbi5uYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgc3ltYm9sIG9mIHRoZSB0b2tlbi4gRS5nLiDigJxISVjigJ0uXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcmV0dXJucyB7U3RyaW5nfSBSZXR1cm5zIHRoZSBzeW1ib2wgb2YgdGhlIHRva2VuXG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIFN5bWJvbChjb250ZXh0OiBDb250ZXh0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBzZWxlY3QgPSB0aGlzLnRva2VuUmVwb3NpdG9yeS5zZWxlY3QoKTtcbiAgICBjb25zdCB0b2tlbiA9IChhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpKVswXTtcblxuICAgIHJldHVybiB0b2tlbi5zeW1ib2w7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBudW1iZXIgb2YgZGVjaW1hbHMgdGhlIHRva2VuIHVzZXNcbiAgICogZS5nLiA4LCBtZWFucyB0byBkaXZpZGUgdGhlIHRva2VuIGFtb3VudCBieSAxMDAwMDAwMDAgdG8gZ2V0IGl0cyB1c2VyIHJlcHJlc2VudGF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHJldHVybnMge051bWJlcn0gUmV0dXJucyB0aGUgbnVtYmVyIG9mIGRlY2ltYWxzXG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIERlY2ltYWxzKGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IHNlbGVjdCA9IHRoaXMudG9rZW5SZXBvc2l0b3J5LnNlbGVjdCgpO1xuICAgIGNvbnN0IHRva2VuID0gKGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCkpWzBdO1xuXG4gICAgcmV0dXJuIHRva2VuLmRlY2ltYWxzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdG90YWwgdG9rZW4gc3VwcGx5LlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHJldHVybnMge051bWJlcn0gUmV0dXJucyB0aGUgdG90YWwgdG9rZW4gc3VwcGx5XG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIFRvdGFsU3VwcGx5KGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IHNlbGVjdCA9IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5zZWxlY3QoKTtcbiAgICBjb25zdCB3YWxsZXRzID0gYXdhaXQgc2VsZWN0LmV4ZWN1dGUoY3R4KTtcblxuICAgIGlmICh3YWxsZXRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihgVGhlIHRva2VuICR7dGhpcy5nZXROYW1lKCl9IGRvZXMgbm90IGV4aXN0YCk7XG4gICAgfVxuXG4gICAgbGV0IHRvdGFsID0gMDtcblxuICAgIHdhbGxldHMuZm9yRWFjaCgod2FsbGV0KSA9PiB7XG4gICAgICB0b3RhbCArPSB3YWxsZXQuYmFsYW5jZTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0b3RhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYWxhbmNlT2YgcmV0dXJucyB0aGUgYmFsYW5jZSBvZiB0aGUgZ2l2ZW4gYWNjb3VudC5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjdHggdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG93bmVyIFRoZSBvd25lciBmcm9tIHdoaWNoIHRoZSBiYWxhbmNlIHdpbGwgYmUgcmV0cmlldmVkXG4gICAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgdGhlIGFjY291bnQgYmFsYW5jZVxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBCYWxhbmNlT2YoY29udGV4dDogQ29udGV4dCwgb3duZXI6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQob3duZXIsIGN0eCk7XG5cbiAgICByZXR1cm4gd2FsbGV0LmJhbGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVHJhbnNmZXIgdHJhbnNmZXJzIHRva2VucyBmcm9tIGNsaWVudCBhY2NvdW50IHRvIHJlY2lwaWVudCBhY2NvdW50LlxuICAgKiBAZGVzY3JpcHRpb24gcmVjaXBpZW50IGFjY291bnQgbXVzdCBiZSBhIHZhbGlkIGNsaWVudElEIGFzIHJldHVybmVkIGJ5IHRoZSBDbGllbnRBY2NvdW50SUQoKSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0byBUaGUgcmVjaXBpZW50XG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYW1vdW50IG9mIHRva2VuIHRvIGJlIHRyYW5zZmVycmVkXG4gICAqXG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBSZXR1cm4gd2hldGhlciB0aGUgdHJhbnNmZXIgd2FzIHN1Y2Nlc3NmdWwgb3Igbm90XG4gICAqL1xuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBUcmFuc2ZlcihcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIHRvOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlclxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVHJhbnNmZXIpO1xuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IGZyb20gPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGNvbnN0IHRyYW5zZmVyUmVzcCA9IGF3YWl0IHRoaXMuX3RyYW5zZmVyKGZyb20sIHRvLCB2YWx1ZSwgY3R4KTtcbiAgICBpZiAoIXRyYW5zZmVyUmVzcCkge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJGYWlsZWQgdG8gdHJhbnNmZXJcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmZXIgYHZhbHVlYCBhbW91bnQgb2YgdG9rZW5zIGZyb20gYGZyb21gIHRvIGB0b2AuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZnJvbSBUaGUgc2VuZGVyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0byBUaGUgcmVjaXBpZW50XG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYW1vdW50IG9mIHRva2VuIHRvIGJlIHRyYW5zZmVycmVkXG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBSZXR1cm4gd2hldGhlciB0aGUgdHJhbnNmZXIgd2FzIHN1Y2Nlc3NmdWwgb3Igbm90XG4gICAqL1xuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBUcmFuc2ZlckZyb20oXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICB2YWx1ZTogbnVtYmVyXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5CdXJuRnJvbSk7XG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgLy8gUmV0cmlldmUgdGhlIGFsbG93YW5jZSBvZiB0aGUgc3BlbmRlclxuXG4gICAgY29uc3Qgc3BlbmRlciA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgY29uc3QgYWxsb3dhbmNlID0gYXdhaXQgdGhpcy5fZ2V0QWxsb3dhbmNlKGZyb20sIHNwZW5kZXIsIGN0eCk7XG4gICAgaWYgKCFhbGxvd2FuY2UgfHwgYWxsb3dhbmNlLnZhbHVlIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEFsbG93YW5jZUVycm9yKFxuICAgICAgICBgc3BlbmRlciAke3NwZW5kZXJ9IGhhcyBubyBhbGxvd2FuY2UgZnJvbSAke2Zyb219YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50QWxsb3dhbmNlID0gYWxsb3dhbmNlLnZhbHVlO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHRyYW5zZmVycmVkIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgYWxsb3dhbmNlXG4gICAgaWYgKGN1cnJlbnRBbGxvd2FuY2UgPCB2YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihcbiAgICAgICAgXCJUaGUgc3BlbmRlciBkb2VzIG5vdCBoYXZlIGVub3VnaCBhbGxvd2FuY2UgdG8gc3BlbmQuXCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRGVjcmVhc2UgdGhlIGFsbG93YW5jZVxuICAgIGNvbnN0IHVwZGF0ZWRBbGxvd2FuY2UgPSBzdWIoY3VycmVudEFsbG93YW5jZSwgdmFsdWUpO1xuICAgIGNvbnN0IG5ld0FsbG93YW5jZSA9IE9iamVjdC5hc3NpZ24oe30sIGFsbG93YW5jZSwge1xuICAgICAgdmFsdWU6IHVwZGF0ZWRBbGxvd2FuY2UsXG4gICAgfSk7XG5cbiAgICBhd2FpdCB0aGlzLmFsbG93YW5jZVJlcG9zaXRvcnkudXBkYXRlKG5ld0FsbG93YW5jZSwgY3R4KTtcblxuICAgIC8vUmVhbGl6ZSB0aGUgdHJhbnNmZXJcbiAgICBjb25zdCB0cmFuc2ZlclJlc3AgPSBhd2FpdCB0aGlzLl90cmFuc2Zlcihmcm9tLCB0bywgdmFsdWUsIGN0eCk7XG4gICAgaWYgKCF0cmFuc2ZlclJlc3ApIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiRmFpbGVkIHRvIHRyYW5zZmVyXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYXN5bmMgX3RyYW5zZmVyKFxuICAgIGZyb206IHN0cmluZyxcbiAgICB0bzogc3RyaW5nLFxuICAgIHZhbHVlOiBudW1iZXIsXG4gICAgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgKSB7XG4gICAgY29uc3QgbG9nID0gY3R4LmxvZ2dlcjtcblxuICAgIGlmIChmcm9tID09PSB0bykge1xuICAgICAgdGhyb3cgbmV3IEF1dGhvcml6YXRpb25FcnJvcihcbiAgICAgICAgXCJjYW5ub3QgdHJhbnNmZXIgdG8gYW5kIGZyb20gc2FtZSBjbGllbnQgYWNjb3VudFwiXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSA8IDApIHtcbiAgICAgIC8vIHRyYW5zZmVyIG9mIDAgaXMgYWxsb3dlZCBpbiBFUkMyMCwgc28ganVzdCB2YWxpZGF0ZSBhZ2FpbnN0IG5lZ2F0aXZlIGFtb3VudHNcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoXCJ0cmFuc2ZlciBhbW91bnQgY2Fubm90IGJlIG5lZ2F0aXZlXCIpO1xuICAgIH1cblxuICAgIC8vIFJldHJpZXZlIHRoZSBjdXJyZW50IGJhbGFuY2Ugb2YgdGhlIHNlbmRlclxuXG4gICAgY29uc3QgZnJvbVdhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKGZyb20sIGN0eCk7XG5cbiAgICBjb25zdCBmcm9tQmFsYW5jZSA9IGZyb21XYWxsZXQuYmFsYW5jZTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSBzZW5kZXIgaGFzIGVub3VnaCB0b2tlbnMgdG8gc3BlbmQuXG4gICAgaWYgKGZyb21CYWxhbmNlIDwgdmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoYGNsaWVudCBhY2NvdW50ICR7ZnJvbX0gaGFzIGluc3VmZmljaWVudCBmdW5kcy5gKTtcbiAgICB9XG5cbiAgICAvLyBSZXRyaWV2ZSB0aGUgY3VycmVudCBiYWxhbmNlIG9mIHRoZSByZWNlcGllbnRcblxuICAgIGxldCB0b1dhbGxldDogRVJDMjBXYWxsZXQ7XG4gICAgbGV0IG5ld1RvV2FsbGV0OiBib29sZWFuID0gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIHRvV2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQodG8sIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBCYXNlRXJyb3IpIHtcbiAgICAgICAgaWYgKGUuY29kZSA9PT0gNDA0KSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHdhbGxldCBmb3IgdGhlIG1pbnRlclxuICAgICAgICAgIHRvV2FsbGV0ID0gbmV3IEVSQzIwV2FsbGV0KHtcbiAgICAgICAgICAgIGlkOiB0byxcbiAgICAgICAgICAgIGJhbGFuY2U6IDAsXG4gICAgICAgICAgICB0b2tlbjogYXdhaXQgdGhpcy5Ub2tlbk5hbWUoY3R4IGFzIGFueSksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgbmV3VG9XYWxsZXQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUgYXMgc3RyaW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0b0JhbGFuY2UgPSB0b1dhbGxldC5iYWxhbmNlO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBiYWxhbmNlXG4gICAgY29uc3QgZnJvbVVwZGF0ZWRCYWxhbmNlID0gc3ViKGZyb21CYWxhbmNlLCB2YWx1ZSk7XG4gICAgY29uc3QgdG9VcGRhdGVkQmFsYW5jZSA9IGFkZCh0b0JhbGFuY2UsIHZhbHVlKTtcblxuICAgIGNvbnN0IHVwZGF0ZWRGcm9tV2FsbGV0ID0gT2JqZWN0LmFzc2lnbih7fSwgZnJvbVdhbGxldCwge1xuICAgICAgYmFsYW5jZTogZnJvbVVwZGF0ZWRCYWxhbmNlLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnVwZGF0ZSh1cGRhdGVkRnJvbVdhbGxldCwgY3R4KTtcblxuICAgIGNvbnN0IHVwZGF0ZWRUb1dhbGxldCA9IE9iamVjdC5hc3NpZ24oe30sIHRvV2FsbGV0LCB7XG4gICAgICBiYWxhbmNlOiB0b1VwZGF0ZWRCYWxhbmNlLFxuICAgIH0pO1xuXG4gICAgaWYgKG5ld1RvV2FsbGV0KSB7XG4gICAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkuY3JlYXRlKHVwZGF0ZWRUb1dhbGxldCwgY3R4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnVwZGF0ZSh1cGRhdGVkVG9XYWxsZXQsIGN0eCk7XG4gICAgfVxuXG4gICAgLy8gRW1pdCB0aGUgVHJhbnNmZXIgZXZlbnRcbiAgICBjb25zdCB0cmFuc2ZlckV2ZW50ID0geyBmcm9tLCB0bywgdmFsdWU6IHZhbHVlIH07XG5cbiAgICB0aGlzLnJlcG9cbiAgICAgIC5yZWZyZXNoKFxuICAgICAgICBFUkMyMFRva2VuIGFzIGFueSxcbiAgICAgICAgRVJDMjBFdmVudHMuVFJBTlNGRVIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRyYW5zZmVyRXZlbnQsXG4gICAgICAgIGN0eCBhcyB1bmtub3duIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgICAgKVxuICAgICAgLmNhdGNoKChlKSA9PiBsb2cuZXJyb3IoYEZhaWxlZCB0byBub3RpZnkgdHJhbnNmZXI6ICR7ZX1gKSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgYHNwZW5kZXJgIHRvIHNwZW5kIGB2YWx1ZWAgYW1vdW50IG9mIHRva2VucyBmcm9tIHRoZSBvd25lci4gTmV3IEFwcHJvdmUgY2FsbHMgb3ZlcnJpZGUgdGhlIHByZXZpb3VzIGFsbG93YW5jZS5cbiAgICogQG5vdGUgaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBTL2VpcC0yMFxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGN0eCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3BlbmRlciBUaGUgc3BlbmRlclxuICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGFtb3VudCBvZiB0b2tlbnMgdG8gYmUgYXBwcm92ZWQgZm9yIHRyYW5zZmVyXG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBSZXR1cm4gd2hldGhlciB0aGUgYXBwcm92YWwgd2FzIHN1Y2Nlc3NmdWwgb3Igbm90XG4gICAqL1xuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBBcHByb3ZlKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgc3BlbmRlcjogc3RyaW5nLFxuICAgIHZhbHVlOiBudW1iZXJcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgeyBjdHgsIGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5BcHByb3ZlKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IG93bmVyID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBsZXQgYWxsb3dhbmNlID0gYXdhaXQgdGhpcy5fZ2V0QWxsb3dhbmNlKG93bmVyLCBzcGVuZGVyLCBjdHgpO1xuXG4gICAgY29uc3Qgb3duZXJXYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChvd25lciwgLi4uY3R4QXJncyk7XG5cbiAgICBpZiAob3duZXJXYWxsZXQuYmFsYW5jZSA8IHZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKGBjbGllbnQgYWNjb3VudCAke293bmVyfSBoYXMgaW5zdWZmaWNpZW50IGZ1bmRzLmApO1xuICAgIH1cblxuICAgIGlmIChhbGxvd2FuY2UpIHtcbiAgICAgIC8vIE92ZXJ3cml0ZSB0aGUgYWxsb3dhbmNlXG4gICAgICBhbGxvd2FuY2UudmFsdWUgPSB2YWx1ZTtcbiAgICAgIGF3YWl0IHRoaXMuYWxsb3dhbmNlUmVwb3NpdG9yeS51cGRhdGUoYWxsb3dhbmNlLCAuLi5jdHhBcmdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxsb3dhbmNlID0gbmV3IEFsbG93YW5jZSh7XG4gICAgICAgIG93bmVyOiBvd25lcixcbiAgICAgICAgc3BlbmRlcjogc3BlbmRlcixcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMuYWxsb3dhbmNlUmVwb3NpdG9yeS5jcmVhdGUoYWxsb3dhbmNlLCAuLi5jdHhBcmdzKTtcbiAgICB9XG5cbiAgICAvLyBFbWl0IHRoZSBBcHByb3ZhbCBldmVudFxuICAgIGNvbnN0IGFwcHJvdmFsRXZlbnQgPSB7IG93bmVyLCBzcGVuZGVyLCB2YWx1ZTogdmFsdWUgfTtcbiAgICB0aGlzLnJlcG8ucmVmcmVzaChcbiAgICAgIEVSQzIwVG9rZW4gYXMgYW55LFxuICAgICAgRVJDMjBFdmVudHMuQVBQUk9WQUwsXG4gICAgICBcIlwiLFxuICAgICAgYXBwcm92YWxFdmVudCxcbiAgICAgIGN0eCBhcyB1bmtub3duIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgICk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhbW91bnQgb2YgdG9rZW5zIHdoaWNoIGAgYCBpcyBhbGxvd2VkIHRvIHdpdGhkcmF3IGZyb20gYG93bmVyYC5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjdHggdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG93bmVyIFRoZSBvd25lciBvZiB0b2tlbnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNwZW5kZXIgVGhlIHNwZW5kZXIgd2hvIGFyZSBhYmxlIHRvIHRyYW5zZmVyIHRoZSB0b2tlbnNcbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJuIHRoZSBhbW91bnQgb2YgcmVtYWluaW5nIHRva2VucyBhbGxvd2VkIHRvIHNwZW50XG4gICAqL1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIEFsbG93YW5jZShcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIG93bmVyOiBzdHJpbmcsXG4gICAgc3BlbmRlcjogc3RyaW5nXG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5BbGxvd2FuY2UpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3QgYWxsb3dhbmNlID0gYXdhaXQgdGhpcy5fZ2V0QWxsb3dhbmNlKG93bmVyLCBzcGVuZGVyLCBjdHgpO1xuXG4gICAgaWYgKCFhbGxvd2FuY2UpIHtcbiAgICAgIHRocm93IG5ldyBBbGxvd2FuY2VFcnJvcihcbiAgICAgICAgYHNwZW5kZXIgJHtzcGVuZGVyfSBoYXMgbm8gYWxsb3dhbmNlIGZyb20gJHtvd25lcn1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYWxsb3dhbmNlLnZhbHVlO1xuICB9XG5cbiAgYXN5bmMgX2dldEFsbG93YW5jZShcbiAgICBvd25lcjogc3RyaW5nLFxuICAgIHNwZW5kZXI6IHN0cmluZyxcbiAgICBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICApOiBQcm9taXNlPEFsbG93YW5jZT4ge1xuICAgIGNvbnN0IGFsbG93YW5jZUNvbmRpdGlvbiA9IENvbmRpdGlvbi5hbmQoXG4gICAgICBDb25kaXRpb24uYXR0cmlidXRlPEFsbG93YW5jZT4oXCJvd25lclwiKS5lcShvd25lciksXG4gICAgICBDb25kaXRpb24uYXR0cmlidXRlPEFsbG93YW5jZT4oXCJzcGVuZGVyXCIpLmVxKHNwZW5kZXIpXG4gICAgKTtcblxuICAgIGNvbnN0IGFsbG93YW5jZSA9IGF3YWl0IHRoaXMuYWxsb3dhbmNlUmVwb3NpdG9yeVxuICAgICAgLnNlbGVjdCgpXG4gICAgICAud2hlcmUoYWxsb3dhbmNlQ29uZGl0aW9uKVxuICAgICAgLmV4ZWN1dGUoY3R4KTtcbiAgICByZXR1cm4gYWxsb3dhbmNlPy5bMF07XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT0gRXh0ZW5kZWQgRnVuY3Rpb25zID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIFNldCBvcHRpb25hbCBpbmZvbWF0aW9uIGZvciBhIHRva2VuLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGN0eCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdG9rZW5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBUaGUgc3ltYm9sIG9mIHRoZSB0b2tlblxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGVjaW1hbHMgVGhlIGRlY2ltYWxzIG9mIHRoZSB0b2tlblxuICAgKiBAcGFyYW0ge1N0cmluZ30gdG90YWxTdXBwbHkgVGhlIHRvdGFsU3VwcGx5IG9mIHRoZSB0b2tlblxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgSW5pdGlhbGl6ZShjb250ZXh0OiBDb250ZXh0LCB0b2tlbjogRVJDMjBUb2tlbikge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuSW5pdGlhbGl6ZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgbm90IGFscmVhZHkgc2V0LCBjbGllbnQgaXMgbm90IGF1dGhvcml6ZWQgdG8gY2hhbmdlIHRoZW0gb25jZSBpbnRpdGlhbGl6ZWRcbiAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5zZWxlY3QoKS5leGVjdXRlKGN0eCk7XG4gICAgaWYgKHRva2Vucy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgICBcImNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0LCBjbGllbnQgaXMgbm90IGF1dGhvcml6ZWQgdG8gY2hhbmdlIHRoZW1cIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0b2tlbi5vd25lciA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuY3JlYXRlKHRva2VuLCBjdHgpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBDaGVja3MgdGhhdCBjb250cmFjdCBvcHRpb25zIGhhdmUgYmVlbiBhbHJlYWR5IGluaXRpYWxpemVkXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgQ2hlY2tJbml0aWFsaXplZChjb250ZXh0OiBDb250ZXh0KSB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5DaGVja0luaXRpYWxpemVkKTtcbiAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5zZWxlY3QoKS5leGVjdXRlKGN0eCk7XG4gICAgaWYgKHRva2Vucy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IE5vdEluaXRpYWxpemVkRXJyb3IoXG4gICAgICAgIFwiY29udHJhY3Qgb3B0aW9ucyBuZWVkIHRvIGJlIHNldCBiZWZvcmUgY2FsbGluZyBhbnkgZnVuY3Rpb24sIGNhbGwgSW5pdGlhbGl6ZSgpIHRvIGluaXRpYWxpemUgY29udHJhY3RcIlxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWludCBjcmVhdGVzIG5ldyB0b2tlbnMgYW5kIGFkZHMgdGhlbSB0byBtaW50ZXIncyBhY2NvdW50IGJhbGFuY2VcbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgYW1vdW50IG9mIHRva2VucyB0byBiZSBtaW50ZWRcbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIGJhbGFuY2VcbiAgICovXG4gIEBPd25lcigpXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIE1pbnQoY29udGV4dDogQ29udGV4dCwgYW1vdW50OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLk1pbnQpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgLy8gR2V0IElEIG9mIHN1Ym1pdHRpbmcgY2xpZW50IGlkZW50aXR5XG4gICAgY29uc3QgbWludGVyID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBpZiAoYW1vdW50IDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXCJtaW50IGFtb3VudCBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlclwiKTtcbiAgICB9XG5cbiAgICBsZXQgbWludGVyV2FsbGV0OiBFUkMyMFdhbGxldDtcbiAgICB0cnkge1xuICAgICAgbWludGVyV2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQobWludGVyLCBjdHgpO1xuXG4gICAgICBjb25zdCBjdXJyZW50QmFsYW5jZSA9IG1pbnRlcldhbGxldC5iYWxhbmNlO1xuXG4gICAgICBjb25zdCB1cGRhdGVkQmFsYW5jZSA9IGFkZChjdXJyZW50QmFsYW5jZSwgYW1vdW50KTtcblxuICAgICAgY29uc3QgdXBkYXRlZG1pbnRlciA9IE9iamVjdC5hc3NpZ24oe30sIG1pbnRlcldhbGxldCwge1xuICAgICAgICBiYWxhbmNlOiB1cGRhdGVkQmFsYW5jZSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkudXBkYXRlKHVwZGF0ZWRtaW50ZXIsIGN0eCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBCYXNlRXJyb3IpIHtcbiAgICAgICAgaWYgKGUuY29kZSA9PT0gNDA0KSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHdhbGxldCBmb3IgdGhlIG1pbnRlclxuICAgICAgICAgIGNvbnN0IG5ld1dhbGxldCA9IG5ldyBFUkMyMFdhbGxldCh7XG4gICAgICAgICAgICBpZDogbWludGVyLFxuICAgICAgICAgICAgYmFsYW5jZTogYW1vdW50LFxuICAgICAgICAgICAgdG9rZW46IGF3YWl0IHRoaXMuVG9rZW5OYW1lKGNvbnRleHQpLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5jcmVhdGUobmV3V2FsbGV0LCBjdHgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUgYXMgc3RyaW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFbWl0IHRoZSBUcmFuc2ZlciBldmVudFxuICAgIGNvbnN0IHRyYW5zZmVyRXZlbnQgPSB7IGZyb206IFwiMHgwXCIsIHRvOiBtaW50ZXIsIHZhbHVlOiBhbW91bnQgfTtcbiAgICBjb25zdCBldmVudEhhbmRsZXIgPVxuICAgICAgdGhpcy5yZXBvLk9ic2VydmVySGFuZGxlcigpIGFzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyO1xuICAgIGV2ZW50SGFuZGxlci51cGRhdGVPYnNlcnZlcnMoXG4gICAgICBFUkMyMFRva2VuLFxuICAgICAgRVJDMjBFdmVudHMuVFJBTlNGRVIsXG4gICAgICBcIlwiLFxuICAgICAgdHJhbnNmZXJFdmVudCxcbiAgICAgIGN0eCBhcyB1bmtub3duIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQnVybiByZWRlZW0gdG9rZW5zIGZyb20gbWludGVyJ3MgYWNjb3VudCBiYWxhbmNlXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IGFtb3VudCBvZiB0b2tlbnMgdG8gYmUgYnVybmVkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBiYWxhbmNlXG4gICAqL1xuICBAT3duZXIoKVxuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBCdXJuKGNvbnRleHQ6IENvbnRleHQsIGFtb3VudDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkJ1cm4pO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3QgbWludGVyID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBjb25zdCBtaW50ZXJXYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChtaW50ZXIsIGN0eCk7XG5cbiAgICBjb25zdCBjdXJyZW50QmFsYW5jZSA9IG1pbnRlcldhbGxldC5iYWxhbmNlO1xuXG4gICAgaWYgKGN1cnJlbnRCYWxhbmNlIDwgYW1vdW50KSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKGBNaW50ZXIgaGFzIGluc3VmZmljaWVudCBmdW5kcy5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVkQmFsYW5jZSA9IHN1YihjdXJyZW50QmFsYW5jZSwgYW1vdW50KTtcblxuICAgIGNvbnN0IHVwZGF0ZWRtaW50ZXIgPSBPYmplY3QuYXNzaWduKHt9LCBtaW50ZXJXYWxsZXQsIHtcbiAgICAgIGJhbGFuY2U6IHVwZGF0ZWRCYWxhbmNlLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnVwZGF0ZSh1cGRhdGVkbWludGVyLCBjdHgpO1xuXG4gICAgbG9nLmluZm8oYCR7YW1vdW50fSB0b2tlbnMgd2VyZSBidXJuZWRgKTtcblxuICAgIC8vIEVtaXQgdGhlIFRyYW5zZmVyIGV2ZW50XG4gICAgY29uc3QgdHJhbnNmZXJFdmVudCA9IHsgZnJvbTogbWludGVyLCB0bzogXCIweDBcIiwgdmFsdWU6IGFtb3VudCB9O1xuICAgIGNvbnN0IGV2ZW50SGFuZGxlciA9XG4gICAgICB0aGlzLnJlcG8uT2JzZXJ2ZXJIYW5kbGVyKCkgYXMgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXI7XG4gICAgZXZlbnRIYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAgICAgIEVSQzIwVG9rZW4sXG4gICAgICBFUkMyMEV2ZW50cy5UUkFOU0ZFUixcbiAgICAgIFwiXCIsXG4gICAgICB0cmFuc2ZlckV2ZW50LFxuICAgICAgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdXJuRnJvbSByZWRlZW0gdG9rZW5zIGZyb20gYWNjb3VudCBhbGxvd2VuY2UgYW5kIGJhbGFuY2VcbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBhY2NvdW50IGFjY291bnQgZnJvbSB3aGVyZSB0b2tlbnMgd2lsbCBiZSBidXJuZWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBhbW91bnQgb2YgdG9rZW5zIHRvIGJlIGJ1cm5lZFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgYmFsYW5jZVxuICAgKi9cbiAgQE93bmVyKClcbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgQnVybkZyb20oXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICBhY2NvdW50OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkJ1cm5Gcm9tKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IGFjY291bnRXYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChhY2NvdW50LCBjdHgpO1xuXG4gICAgY29uc3QgY3VycmVudEJhbGFuY2UgPSBhY2NvdW50V2FsbGV0LmJhbGFuY2U7XG5cbiAgICBpZiAoY3VycmVudEJhbGFuY2UgPCBhbW91bnQpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoYCR7YWNjb3VudH0gaGFzIGluc3VmZmljaWVudCBmdW5kcy5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVkQmFsYW5jZSA9IHN1YihjdXJyZW50QmFsYW5jZSwgYW1vdW50KTtcblxuICAgIGNvbnN0IHVwZGF0ZWRhY2NvdW50ID0gT2JqZWN0LmFzc2lnbih7fSwgYWNjb3VudFdhbGxldCwge1xuICAgICAgYmFsYW5jZTogdXBkYXRlZEJhbGFuY2UsXG4gICAgfSk7XG5cbiAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkudXBkYXRlKHVwZGF0ZWRhY2NvdW50LCBjdHgpO1xuXG4gICAgbG9nLmluZm8oYCR7YW1vdW50fSB0b2tlbnMgd2VyZSBidXJuZWQgZnJvbSAke2FjY291bnR9YCk7XG5cbiAgICAvLyBFbWl0IHRoZSBUcmFuc2ZlciBldmVudFxuICAgIGNvbnN0IHRyYW5zZmVyRXZlbnQgPSB7IGZyb206IGFjY291bnQsIHRvOiBcIjB4MFwiLCB2YWx1ZTogYW1vdW50IH07XG4gICAgY29uc3QgZXZlbnRIYW5kbGVyID1cbiAgICAgIHRoaXMucmVwby5PYnNlcnZlckhhbmRsZXIoKSBhcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlcjtcbiAgICBldmVudEhhbmRsZXIudXBkYXRlT2JzZXJ2ZXJzKFxuICAgICAgRVJDMjBUb2tlbixcbiAgICAgIEVSQzIwRXZlbnRzLlRSQU5TRkVSLFxuICAgICAgXCJcIixcbiAgICAgIHRyYW5zZmVyRXZlbnQsXG4gICAgICBjdHggYXMgdW5rbm93biBhcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENsaWVudEFjY291bnRCYWxhbmNlIHJldHVybnMgdGhlIGJhbGFuY2Ugb2YgdGhlIHJlcXVlc3RpbmcgY2xpZW50J3MgYWNjb3VudC5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgdGhlIGFjY291bnQgYmFsYW5jZVxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBDbGllbnRBY2NvdW50QmFsYW5jZShjb250ZXh0OiBDb250ZXh0KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICAvLyBHZXQgSUQgb2Ygc3VibWl0dGluZyBjbGllbnQgaWRlbnRpdHlcbiAgICBjb25zdCBjbGllbnRBY2NvdW50SUQgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGNvbnN0IGNsaWVudFdhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKGNsaWVudEFjY291bnRJRCwgY3R4KTtcblxuICAgIGlmICghY2xpZW50V2FsbGV0KSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKGBUaGUgYWNjb3VudCAke2NsaWVudEFjY291bnRJRH0gZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xpZW50V2FsbGV0LmJhbGFuY2U7XG4gIH1cblxuICAvLyBDbGllbnRBY2NvdW50SUQgcmV0dXJucyB0aGUgaWQgb2YgdGhlIHJlcXVlc3RpbmcgY2xpZW50J3MgYWNjb3VudC5cbiAgLy8gSW4gdGhpcyBpbXBsZW1lbnRhdGlvbiwgdGhlIGNsaWVudCBhY2NvdW50IElEIGlzIHRoZSBjbGllbnRJZCBpdHNlbGYuXG4gIC8vIFVzZXJzIGNhbiB1c2UgdGhpcyBmdW5jdGlvbiB0byBnZXQgdGhlaXIgb3duIGFjY291bnQgaWQsIHdoaWNoIHRoZXkgY2FuIHRoZW4gZ2l2ZSB0byBvdGhlcnMgYXMgdGhlIHBheW1lbnQgYWRkcmVzc1xuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIENsaWVudEFjY291bnRJRChjb250ZXh0OiBDb250ZXh0KSB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5DbGllbnRBY2NvdW50SUQpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgLy8gR2V0IElEIG9mIHN1Ym1pdHRpbmcgY2xpZW50IGlkZW50aXR5XG4gICAgY29uc3QgY2xpZW50QWNjb3VudElEID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG4gICAgcmV0dXJuIGNsaWVudEFjY291bnRJRDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRmFicmljRVJDMjBDb250cmFjdCB9IGZyb20gXCIuL2VyYzIwY29udHJhY3RcIjtcblxuZXhwb3J0ICogZnJvbSBcIi4uL0ZhYnJpY0NvbnRyYWN0U3RhdGVtZW50XCI7XG5cbmV4cG9ydCBjb25zdCBjb250cmFjdHM6IGFueVtdID0gW0ZhYnJpY0VSQzIwQ29udHJhY3RdO1xuIiwiaW1wb3J0IHtcbiAgTG9nZ2VyRmFjdG9yeSxcbiAgTG9nZ2luZyxcbiAgTG9nZ2VyLFxuICBMb2dMZXZlbCxcbiAgTWluaUxvZ2dlcixcbiAgTnVtZXJpY0xvZ0xldmVscyxcbiAgU3RyaW5nTGlrZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBDb250ZXh0IGFzIEN0eCB9IGZyb20gXCJmYWJyaWMtY29udHJhY3QtYXBpXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIExvZ2dlciBpbXBsZW1lbnRhdGlvbiBmb3IgRmFicmljIGNoYWluY29kZSBjb250cmFjdHNcbiAqIEBzdW1tYXJ5IEFkYXB0cyB0aGUgc3RhbmRhcmQgbG9nZ2luZyBpbnRlcmZhY2UgdG8gd29yayB3aXRoIEZhYnJpYydzIGNoYWluY29kZSBjb250ZXh0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRleHQgLSBUaGUgbG9nZ2luZyBjb250ZXh0IG5hbWVcbiAqIEBwYXJhbSB7UGFydGlhbDxMb2dnaW5nQ29uZmlnPiB8IHVuZGVmaW5lZH0gY29uZiAtIE9wdGlvbmFsIGxvZ2dpbmcgY29uZmlndXJhdGlvblxuICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAqXG4gKiBAY2xhc3MgQ29udHJhY3RMb2dnZXJcbiAqIEBleHRlbmRzIHtNaW5pTG9nZ2VyfVxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdFxuICogaW1wb3J0IHsgQ29udHJhY3RMb2dnZXIgfSBmcm9tICdAZGVjYWYtdHMvZm9yLWZhYnJpYyc7XG4gKlxuICogZXhwb3J0IGNsYXNzIE15Q29udHJhY3QgZXh0ZW5kcyBDb250cmFjdCB7XG4gKiAgIEBUcmFuc2FjdGlvbigpXG4gKiAgIGFzeW5jIG15RnVuY3Rpb24oY3R4OiBDb250ZXh0KTogUHJvbWlzZTx2b2lkPiB7XG4gKiAgICAgY29uc3QgbG9nZ2VyID0gbmV3IENvbnRyYWN0TG9nZ2VyKCdNeUNvbnRyYWN0JywgeyBsZXZlbDogJ2luZm8nIH0sIGN0eCk7XG4gKlxuICogICAgIGxvZ2dlci5pbmZvKCdQcm9jZXNzaW5nIHRyYW5zYWN0aW9uJyk7XG4gKiAgICAgbG9nZ2VyLmRlYnVnKCdUcmFuc2FjdGlvbiBkZXRhaWxzOicsIHsgLi4uIH0pO1xuICpcbiAqICAgICAvLyBEbyBzb21ldGhpbmdcbiAqXG4gKiAgICAgbG9nZ2VyLmluZm8oJ1RyYW5zYWN0aW9uIGNvbXBsZXRlJyk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgQ29udHJhY3RMb2dnZXIgZXh0ZW5kcyBNaW5pTG9nZ2VyIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgdW5kZXJseWluZyBGYWJyaWMgbG9nZ2VyIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgbG9nZ2VyITogTG9nZ2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNvbnRleHQ6IHN0cmluZyxcbiAgICBjb25mOiBQYXJ0aWFsPExvZ2dpbmdDb25maWc+IHwgdW5kZWZpbmVkLFxuICAgIGN0eD86IEN0eFxuICApIHtcbiAgICBzdXBlcihjb250ZXh0LCBjb25mKTtcblxuICAgIGlmICghY3R4KSB7XG4gICAgICB0aGlzLmxvZ2dlciA9IG5ldyBNaW5pTG9nZ2VyKGNvbnRleHQsIGNvbmYpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlciA9IGN0eC5sb2dnaW5nLmdldExvZ2dlcihjb250ZXh0KSBhcyB1bmtub3duIGFzIExvZ2dlcjtcbiAgICAgIGN0eC5sb2dnaW5nLnNldExldmVsKGNvbmY/LmxldmVsIHx8IExvZ2dpbmcuZ2V0Q29uZmlnKCkubGV2ZWwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIHNwZWNpZmllZCBsZXZlbFxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgbG9nIG1ldGhvZCB0byB1c2UgdGhlIEZhYnJpYyBjb250ZXh0J3MgbG9nZ2VyXG4gICAqIEBwYXJhbSB7TG9nTGV2ZWx9IGxldmVsIC0gVGhlIGxvZyBsZXZlbFxuICAgKiBAcGFyYW0ge1N0cmluZ0xpa2UgfCBFcnJvcn0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gbG9nXG4gICAqIEBwYXJhbSB7RXJyb3J9IFtzdGFja10gLSBPcHRpb25hbCBzdGFjayB0cmFjZSBmb3IgZXJyb3JzXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgbG9nKFxuICAgIGxldmVsOiBMb2dMZXZlbCxcbiAgICBtc2c6IFN0cmluZ0xpa2UgfCBFcnJvcixcbiAgICBzdGFjaz86IEVycm9yXG4gICkge1xuICAgIGlmIChcbiAgICAgIE51bWVyaWNMb2dMZXZlbHNbdGhpcy5jb25maWcoXCJsZXZlbFwiKSBhcyBMb2dMZXZlbF0gPFxuICAgICAgTnVtZXJpY0xvZ0xldmVsc1tsZXZlbF1cbiAgICApXG4gICAgICByZXR1cm47XG5cbiAgICBsZXQgbWV0aG9kO1xuICAgIHN3aXRjaCAobGV2ZWwpIHtcbiAgICAgIGNhc2UgTG9nTGV2ZWwuYmVuY2htYXJrOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci52ZXJib3NlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTG9nTGV2ZWwuaW5mbzpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIuaW5mbztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLnZlcmJvc2U6XG4gICAgICAgIG1ldGhvZCA9IHRoaXMubG9nZ2VyLnZlcmJvc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC5kZWJ1ZzpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIuZGVidWc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC5lcnJvcjpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIuZXJyb3I7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC50cmFjZTpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIudHJhY2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC53YXJuOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci53YXJuO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTG9nTGV2ZWwuc2lsbHk6XG4gICAgICAgIG1ldGhvZCA9IHRoaXMubG9nZ2VyLnNpbGx5O1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSW52YWxpZCBsb2cgbGV2ZWxcIik7XG4gICAgfVxuICAgIG1ldGhvZC5jYWxsKHRoaXMubG9nZ2VyLCB0aGlzLmNyZWF0ZUxvZyhsZXZlbCwgbXNnLCBzdGFjaykpO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEZhY3RvcnkgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIENvbnRyYWN0TG9nZ2VyIGluc3RhbmNlc1xuICogQHN1bW1hcnkgQ3JlYXRlcyBhIG5ldyBDb250cmFjdExvZ2dlciB3aXRoIHRoZSBnaXZlbiBjb250ZXh0LCBjb25maWcsIGFuZCBGYWJyaWMgY29udGV4dFxuICogQHBhcmFtIHtzdHJpbmd9IG9iamVjdCAtIFRoZSBsb2dnaW5nIGNvbnRleHQgbmFtZVxuICogQHBhcmFtIHtQYXJ0aWFsPExvZ2dpbmdDb25maWc+IHwgdW5kZWZpbmVkfSBjb25maWcgLSBPcHRpb25hbCBsb2dnaW5nIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gKiBAcmV0dXJuIHtDb250cmFjdExvZ2dlcn0gQSBuZXcgQ29udHJhY3RMb2dnZXIgaW5zdGFuY2VcbiAqIEBmdW5jdGlvbiBmYWN0b3J5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZhYnJpYy5jb250cmFjdHNcbiAqL1xuY29uc3QgZmFjdG9yeTogTG9nZ2VyRmFjdG9yeSA9IChcbiAgb2JqZWN0Pzogc3RyaW5nLFxuICBjb25maWc/OiBQYXJ0aWFsPExvZ2dpbmdDb25maWc+LFxuICBjdHg/OiBDdHhcbikgPT4ge1xuICByZXR1cm4gbmV3IENvbnRyYWN0TG9nZ2VyKFxuICAgIG9iamVjdCB8fCBDb250cmFjdExvZ2dlci5uYW1lLFxuICAgIGNvbmZpZyB8fCB7fSxcbiAgICBjdHggYXMgQ3R4XG4gICk7XG59O1xuXG4vLyBTZXQgdGhlIGZhY3RvcnkgYXMgdGhlIGRlZmF1bHQgbG9nZ2VyIGZhY3RvcnlcbkxvZ2dpbmcuc2V0RmFjdG9yeShmYWN0b3J5KTtcbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9IFwiIyNQQUNLQUdFIyNcIjtcblxuTWV0YWRhdGEucmVnaXN0ZXJMaWJyYXJ5KFBBQ0tBR0VfTkFNRSwgVkVSU0lPTik7XG4iXSwibmFtZXMiOlsiRmFicmljTW9kZWxLZXlzIiwiSWRlbnRpdHlUeXBlIiwiRmFicmljRmxhdm91ciIsIk1vZGVsIiwicHJvdG90eXBlIiwiaXNTaGFyZWQiLCJ0aGlzIiwiY29uc3RydWN0b3IiLCJpc1ByaXZhdGUiLCJzZWdyZWdhdGUiLCJtb2RlbCIsImlzVHJhbnNpZW50IiwiZGVjb3JhdGVkUHJvcGVydGllcyIsIk1ldGFkYXRhIiwidmFsaWRhdGFibGVQcm9wZXJ0aWVzIiwidHJhbnNpZW50UHJvcHMiLCJnZXQiLCJEQktleXMiLCJUUkFOU0lFTlQiLCJwcml2YXRlUHJvcGVydGllcyIsIlBSSVZBVEUiLCJzaGFyZWRQcm9wZXJ0aWVzIiwicmVzdWx0IiwidHJhbnNpZW50IiwicHJpdmF0ZSIsInNoYXJlZCIsInRyYW5zaWVudEtleXMiLCJPYmplY3QiLCJrZXlzIiwicHJpdmF0ZUtleXMiLCJzaGFyZWRLZXlzIiwia2V5IiwiaW5jbHVkZXMiLCJidWlsZCIsIm5hbWUiLCJiaW5kIiwidGFibGVOYW1lIiwidGFyZ2V0IiwibWV0YSIsIlBlcnNpc3RlbmNlS2V5cyIsIlRBQkxFIiwiU0hBUkVEIiwiRmFicmljQ29udHJhY3RDb250ZXh0IiwiQ29udGV4dCIsInN1cGVyIiwic3R1YiIsInRpbWVzdGFtcCIsImdldERhdGVUaW1lc3RhbXAiLCJpZGVudGl0eSIsInRvU3RyaW5nIiwiZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWUiLCJ0YWJsZSIsImV2ZW50Iiwib3duZXIiLCJwYXJhbXMiLCJwdXNoIiwiam9pbiIsInBhcnNlRXZlbnROYW1lIiwicGFydHMiLCJzcGxpdCIsImxlbmd0aCIsInVuZGVmaW5lZCIsIkZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIiwiT2JzZXJ2ZXJIYW5kbGVyIiwic3VwcG9ydGVkRXZlbnRzIiwiT3BlcmF0aW9uS2V5cyIsIkNSRUFURSIsIlVQREFURSIsIkRFTEVURSIsIkJ1bGtDcnVkT3BlcmF0aW9uS2V5cyIsIkNSRUFURV9BTEwiLCJVUERBVEVfQUxMIiwiREVMRVRFX0FMTCIsInVwZGF0ZU9ic2VydmVycyIsImNsYXp6IiwiaWQiLCJhcmdzIiwibG9nIiwiY3R4IiwiQWRhcHRlciIsImxvZ0N0eCIsInBheWxvYWQiLCJpbmRleE9mIiwiZGVidWciLCJldmVudE5hbWUiLCJzZXRFdmVudCIsIkJ1ZmZlciIsImZyb20iLCJKU09OIiwic3RyaW5naWZ5IiwiRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IiwiUmVwb3NpdG9yeSIsImFkYXB0ZXIiLCJ0cmFja2VkRXZlbnRzIiwiX292ZXJyaWRlcyIsImFzc2lnbiIsImlnbm9yZVZhbGlkYXRpb24iLCJpZ25vcmVIYW5kbGVycyIsImFsbG93UmF3U3RhdGVtZW50cyIsImZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXMiLCJmb3JjZVByZXBhcmVDb21wbGV4UXVlcmllcyIsInBhZ2luYXRlQnkiLCJvcmRlciIsInJlZiIsIm9mZnNldCIsImxpbWl0IiwiYm9va21hcmsiLCJRdWVyeUVycm9yIiwiY3R4QXJncyIsIlByZXBhcmVkU3RhdGVtZW50S2V5cyIsIlBBR0VfQlkiLCJmb3IiLCJ2ZXJib3NlIiwiY2xhc3MiLCJwYWdpbmF0b3IiLCJvdmVycmlkZSIsInNlbGVjdCIsIndoZXJlIiwiYXR0ciIsInBrIiwiZ3QiLCJvcmRlckJ5IiwicGFnaW5hdGUiLCJwYWdlZCIsInBhZ2UiLCJzZXJpYWxpemUiLCJzdGF0ZW1lbnQiLCJTVEFURU1FTlQiLCJzdGF0ZW1lbnRzIiwibG9nZ2VyIiwiaW5mbyIsImUiLCJCYXNlRXJyb3IiLCJJbnRlcm5hbEVycm9yIiwiRmFicmljU3RhdGVtZW50IiwiQ291Y2hEQlN0YXRlbWVudCIsImV4ZWN1dGlvblByZWZpeCIsIm1ldGhvZCIsIm5ld0FyZ3MiLCJmaWx0ZXIiLCJCb29sZWFuIiwicmF3IiwicmF3SW5wdXQiLCJyZXN1bHRzIiwicGtBdHRyIiwiZnJvbVNlbGVjdG9yIiwidHlwZSIsIklEIiwic2VsZWN0U2VsZWN0b3IiLCJtYXAiLCJyIiwicHJvY2Vzc1JlY29yZCIsInNlbGVjdG9ycyIsIkNvdWNoREJLZXlzIiwicXVlcnkiLCJzZWxlY3RvciIsImZpZWxkcyIsIndoZXJlQ29uZGl0aW9uIiwiY29uZGl0aW9uIiwicGFyc2VDb25kaXRpb24iLCJDb25kaXRpb24iLCJhbmQiLCJhdHRyaWJ1dGUiLCJlcSIsInNlbGVjdG9yS2V5cyIsInZhbHVlcyIsIkNvdWNoREJHcm91cE9wZXJhdG9yIiwiQU5EIiwicmVkdWNlIiwiYWNjdW0iLCJ2YWwiLCJFcnJvciIsImsiLCJPUiIsInMiLCJlbnRyaWVzIiwiZm9yRWFjaCIsImNvbnNvbGUiLCJ3YXJuIiwib3JkZXJCeVNlbGVjdG9yIiwic29ydCIsInZhbHVlIiwicmVjIiwiQ291Y2hEQk9wZXJhdG9yIiwiQklHR0VSIiwibGltaXRTZWxlY3RvciIsIm9mZnNldFNlbGVjdG9yIiwic2tpcCIsIkZhYnJpY0NvbnRyYWN0U2VxdWVuY2UiLCJTZXF1ZW5jZSIsIm9wdGlvbnMiLCJjdXJyZW50IiwiUkVBRCIsInN0YXJ0V2l0aCIsInNlcXVlbmNlIiwicmVwbyIsInJlYWQiLCJwYXJzZSIsIk5vdEZvdW5kRXJyb3IiLCJjYWNoZWRDdXJyZW50IiwiaW5jcmVtZW50IiwiY291bnQiLCJpbmNyZW1lbnRCeSIsImxvY2siLCJleGVjdXRlIiwiYXN5bmMiLCJ0b0luY3JlbWVudEJ5IiwidHlwZU5hbWUiLCJjdXJyZW50VmFsdWUiLCJyZXR1cm5BbmRDYWNoZSIsInJlcyIsIlByb21pc2UiLCJjYWNoZSIsInB1dCIsInBlcmZvcm1VcHNlcnQiLCJuZXh0IiwidXBkYXRlIiwiU2VxdWVuY2VNb2RlbCIsImNyZWF0ZSIsImluY3JlbWVudFNlcmlhbCIsImJhc2UiLCJOdW1iZXIiLCJCaWdJbnQiLCJTdHJpbmciLCJTZXJpYWwiLCJpbnN0YW5jZSIsImdlbmVyYXRlIiwiVVVJRCIsIkNvbmZsaWN0RXJyb3IiLCJzZXEiLCJTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplciIsIkpTT05TZXJpYWxpemVyIiwiZGVzZXJpYWxpemUiLCJzdHIiLCJkZXNlcmlhbGl6YXRpb24iLCJwdXRBbmNob3IiLCJyZXF1aXJlIiwic29ydEtleXNSZWN1cnNpdmUiLCJwcmVTZXJpYWxpemF0aW9uIiwicHJlU2VyaWFsaXplIiwidG9TZXJpYWxpemUiLCJtZXRhZGF0YSIsIm1vZGVsTmFtZSIsImVycm9yIiwiTW9kZWxLZXlzIiwiQU5DSE9SIiwib2JqIiwiQXJyYXkiLCJpc0FycmF5IiwicmVsYXRpb25zIiwiY2FsbCIsIkZhYnJpY0NvbnRyYWN0UGFnaW5hdG9yIiwiQ291Y2hEQlBhZ2luYXRvciIsInNpemUiLCJwcmVwYXJlIiwicmF3U3RhdGVtZW50IiwiaXNQcmVwYXJlZFN0YXRlbWVudCIsInBhZ2VQcmVwYXJlZCIsIl9yZWNvcmRDb3VudCIsIl90b3RhbFBhZ2VzIiwiY291bnRSZXN1bHRzIiwiTUFYX1ZBTFVFIiwiTWF0aCIsImNlaWwiLCJ2YWxpZGF0ZVBhZ2UiLCJfYm9va21hcmsiLCJQYWdpbmdFcnJvciIsInJhd1Jlc3VsdCIsImRvY3MiLCJuZXh0Qm9va21hcmsiLCJ3YXJuaW5nIiwiZCIsInJldmVydCIsInBhcnNlVmFsdWUiLCJfY3VycmVudFBhZ2UiLCJPdmVyZmxvd0Vycm9yIiwibXNnIiwiQmFsYW5jZUVycm9yIiwiQWxsb3dhbmNlRXJyb3IiLCJSZWdpc3RyYXRpb25FcnJvciIsIkF1dGhvcml6YXRpb25FcnJvciIsIk1pc3NpbmdDb250ZXh0RXJyb3IiLCJVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyIsIk5vdEluaXRpYWxpemVkRXJyb3IiLCJNaXNzaW5nUEtDU1MxMUxpYiIsIkVuZG9yc2VtZW50RXJyb3IiLCJtZXNzYWdlIiwiTXZjY1JlYWRDb25mbGljdEVycm9yIiwiUGhhbnRvbVJlYWRDb25mbGljdEVycm9yIiwiRW5kb3JzZW1lbnRQb2xpY3lFcnJvciIsImNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlIiwiY29udGV4dCIsImRhdGEiLCJ1c2VyIiwiZ2V0SUQiLCJVbnN1cHBvcnRlZEVycm9yIiwicGtGYWJyaWNPbkNyZWF0ZSIsInNldFByaW1hcnlLZXlWYWx1ZSIsInByb3BlcnR5S2V5IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwid3JpdGFibGUiLCJjb25maWd1cmFibGUiLCJzZXF1ZW5jZU5hbWUiLCJGYWJyaWNDb250cmFjdEFkYXB0ZXIiLCJDb3VjaERCQWRhcHRlciIsImdldENsaWVudCIsInRleHREZWNvZGVyIiwiVGV4dERlY29kZXIiLCJzZXJpYWxpemVyIiwicmVwb3NpdG9yeSIsIlBhZ2luYXRvciIsInNjb3BlIiwiYWxpYXMiLCJjb25maWciLCJjb21wb3NlZEtleSIsImNyZWF0ZUNvbXBvc2l0ZUtleSIsInB1dFN0YXRlIiwicGFyc2VFcnJvciIsInJlYWRTdGF0ZSIsImRlbGV0ZSIsImRlbGV0ZVN0YXRlIiwiZm9yUHJpdmF0ZSIsImNvbGxlY3Rpb24iLCJ0b092ZXJyaWRlIiwicXVlcnlSZXN1bHQiLCJxdWVyeVJlc3VsdFBhZ2luYXRlZCIsImZuIiwiUHJveHkiLCJwcm9wIiwicmVjZWl2ZXIiLCJSZWZsZWN0IiwiYXBwbHkiLCJ0aGlzQXJnIiwiYXJnc0xpc3QiLCJwdXRQcml2YXRlRGF0YSIsImRlbGV0ZVByaXZhdGVEYXRhIiwiZ2V0UHJpdmF0ZURhdGEiLCJnZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0IiwiaXRlcmF0b3IiLCJyZWFjaGVkQm9va21hcmsiLCJsYXN0S2V5IiwicmVjb3JkS2V5IiwicmVjb3JkVmFsdWUiLCJLZXkiLCJSZWNvcmQiLCJjbG9zZSIsImZldGNoZWRSZWNvcmRzQ291bnQiLCJkb25lIiwiU2VyaWFsaXphdGlvbkVycm9yIiwic2lsbHkiLCJnZXRTdGF0ZSIsImdldFF1ZXJ5UmVzdWx0IiwiX2lkIiwiJGd0IiwiJGd0ZSIsIml0IiwiZ2V0UXVlcnlSZXN1bHRXaXRoUGFnaW5hdGlvbiIsIm1lcmdlTW9kZWxzIiwiZXh0cmFjdCIsImZpbmFsTW9kZWwiLCJwb3AiLCJkZWNvZGUiLCJidWZmZXIiLCJmbGFncyIsIm9wZXJhdGlvbiIsImJhc2VGbGFncyIsInNlZ3JlZ2F0ZWQiLCJjbGllbnRJZGVudGl0eSIsIkxvZ2dpbmciLCJsb2dMZXZlbCIsImNvcnJlbGF0aW9uSWQiLCJnZXRUeElEIiwiaW5kZXgiLCJtb2RlbHMiLCJyZXNvbHZlIiwicmVzdWx0SXRlcmF0b3IiLCJpc0hpc3RvcnkiLCJhbGxSZXN1bHRzIiwianNvblJlcyIsIlR4SWQiLCJ0eElkIiwiVGltZXN0YW1wIiwiVmFsdWUiLCJlcnIiLCJkb2NzT25seSIsInJlc3BvbnNlIiwiU3RhdGVtZW50IiwiY3JlYXRlQWxsIiwidGFibGVMYWJlbCIsImFsbCIsImkiLCJ1cGRhdGVBbGwiLCJtYXBwZWRQcm9wIiwiY29sdW1uTmFtZSIsImlzUmVzZXJ2ZWQiLCJyZWNvcmQiLCJvYiIsIm0iLCJjcmVhdGVQcmVmaXgiLCJ1cGRhdGVQcmVmaXgiLCJjcmVhdGVBbGxQcmVmaXgiLCJpZHMiLCJyZWNvcmRzIiwidXBkYXRlQWxsUHJlZml4IiwicmVhc29uIiwiYWxsb3dDcmVhdGUiLCJvdmVycmlkZXMiLCJ0aGVuIiwiQmFkUmVxdWVzdEVycm9yIiwiTWlncmF0aW9uRXJyb3IiLCJPYnNlcnZlckVycm9yIiwiRm9yYmlkZGVuRXJyb3IiLCJDb25uZWN0aW9uRXJyb3IiLCJkZWNvcmF0aW9uIiwiRGVjb3JhdGlvbiIsImZsYXZvdXJlZEFzIiwiQ1JFQVRFRF9CWSIsImRlZmluZSIsIm9uQ3JlYXRlIiwicHJvcE1ldGFkYXRhIiwiVVBEQVRFRF9CWSIsIm9uQ3JlYXRlVXBkYXRlIiwiQ09MVU1OIiwiZXh0ZW5kIiwiRmFicmljUHJvcGVydHkiLCJWYWxpZGF0aW9uS2V5cyIsIkRBVEUiLCJmYWJyaWNQcm9wZXJ0eSIsIlByb3BlcnR5IiwiY2hhaW4iLCJjb25zdHIiLCJnZXRQcm90b3R5cGVPZiIsImMiLCJGYWJyaWNPYmplY3QiLCJzZXRDdXJyZW50IiwiRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIiLCJzZWxmIiwibyIsImNsYXNzTmFtZSIsIkVSQzIwRXZlbnRzIiwiRmFicmljQmFzZU1vZGVsIiwiYXJnIiwiX19kZWNvcmF0ZSIsImRlc2NyaXB0aW9uIiwiY29sdW1uIiwiY3JlYXRlZEF0IiwiRGF0ZSIsInVwZGF0ZWRBdCIsInZlcnNpb24iLCJ1c2VzIiwiRmFicmljSWRlbnRpZmllZEJhc2VNb2RlbCIsImNyZWF0ZWRCeSIsInVwZGF0ZWRCeSIsIklkZW50aXR5Q3JlZGVudGlhbHMiLCJCYXNlTW9kZWwiLCJyZXF1aXJlZCIsIklkZW50aXR5IiwiWDUwOSIsIm9uZVRvT25lIiwiQ2FzY2FkZSIsIkNBU0NBREUiLCJDbGllbnRTZXJpYWxpemVyIiwiT3duZXIiLCJkZXNjcmlwdG9yIiwib3JpZ2luYWxNZXRob2QiLCJhY291bnRJZCIsInRva2VucyIsIm93bmVkQnlPbkNyZWF0ZSIsImNyZWF0b3IiLCJnZXRDcmVhdG9yIiwibXNwaWQiLCJzZXRPd25lZEJ5S2V5VmFsdWUiLCJvd25lZEJ5IiwiZ2V0RmFicmljTW9kZWxLZXkiLCJPV05FREJZIiwicmVhZG9ubHkiLCJkZWNvcmF0b3IiLCJ0cmFuc2FjdGlvbklkT25DcmVhdGUiLCJ0cmFuc2FjdGlvbklkIiwib25VcGRhdGUiLCJGQUJSSUMiLCJUUkFOU0FDVElPTl9JRCIsIkltcGxpY2l0UHJpdmF0ZUNvbGxlY3Rpb24iLCJzZWdyZWdhdGVkRGF0YU9uQ3JlYXRlIiwiY29sbGVjdGlvblJlc29sdmVyIiwiY29sbGVjdGlvbnMiLCJyZWJ1aWx0IiwiYWNjIiwidG9DcmVhdGUiLCJjcmVhdGVkIiwic2VncmVnYXRlZERhdGFPblJlYWQiLCJzZWdyZWdhdGVkRGF0YU9uVXBkYXRlIiwib2xkTW9kZWwiLCJzZWdyZWdhdGVkRGF0YU9uRGVsZXRlIiwiaW5uZXJTZWdyZWdhdGVkIiwic2VncmVnYXRlZERlYyIsInByb3BzIiwicHJvcGVydGllcyIsIlNldCIsImFkZCIsInNldCIsImRlY3MiLCJwIiwicHJpb3JpdHkiLCJncm91cCIsIm9uUmVhZCIsIm9uRGVsZXRlIiwicHJpdmF0ZURhdGEiLCJzaGFyZWREYXRhIiwiYSIsImIiLCJzdWIiLCJzYWZlUGFyc2VJbnQiLCJzdHJpbmciLCJkaWdpdFJlZ2V4IiwidGVzdCIsIlZhbGlkYXRpb25FcnJvciIsInN0cmluZ0Zvcm1hdCIsInBhcnNlZGludCIsInBhcnNlSW50IiwiaXNOYU4iLCJGYWJyaWNDcnVkQ29udHJhY3QiLCJDb250cmFjdCIsImluaXRpYWxpemVkIiwiZm9yTW9kZWwiLCJsaXN0QnkiLCJMSVNUX0JZIiwiZmluZE9uZUJ5IiwiRklORF9PTkVfQlkiLCJnZXRUcmFuc2llbnREYXRhIiwibWVyZ2UiLCJ0cmFuc2llbnRNYXAiLCJnZXRUcmFuc2llbnQiLCJoYXMiLCJkZWxldGVBbGwiLCJyZWFkQWxsIiwiUkVBRF9BTEwiLCJPcmRlckRpcmVjdGlvbiIsIkFTQyIsIlFVRVJZIiwiaW5pdCIsIklOSVRJQUxJWkFUSU9OIiwiZ2V0TmFtZSIsImhlYWx0aGNoZWNrIiwiY29udGV4dHVhbGl6ZWQiLCJzcXVhc2hBcmdzIiwic2hpZnQiLCJTZXJpYWxpemVkQ3J1ZENvbnRyYWN0IiwicGFyc2VkS2V5cyIsImxpc3QiLCJtb2RlbExpc3QiLCJjb25kIiwiVHJhbnNhY3Rpb24iLCJDdHgiLCJFUkMyMFRva2VuIiwiRVJDMjBXYWxsZXQiLCJBbGxvd2FuY2UiLCJGYWJyaWNFUkMyMENvbnRyYWN0Iiwid2FsbGV0UmVwb3NpdG9yeSIsInRva2VuUmVwb3NpdG9yeSIsImFsbG93YW5jZVJlcG9zaXRvcnkiLCJUb2tlbk5hbWUiLCJDaGVja0luaXRpYWxpemVkIiwidG9rZW4iLCJTeW1ib2wiLCJzeW1ib2wiLCJEZWNpbWFscyIsImRlY2ltYWxzIiwiVG90YWxTdXBwbHkiLCJ3YWxsZXRzIiwidG90YWwiLCJ3YWxsZXQiLCJiYWxhbmNlIiwiQmFsYW5jZU9mIiwiVHJhbnNmZXIiLCJ0byIsInRyYW5zZmVyUmVzcCIsIl90cmFuc2ZlciIsIlRyYW5zZmVyRnJvbSIsIkJ1cm5Gcm9tIiwic3BlbmRlciIsImFsbG93YW5jZSIsIl9nZXRBbGxvd2FuY2UiLCJjdXJyZW50QWxsb3dhbmNlIiwidXBkYXRlZEFsbG93YW5jZSIsIm5ld0FsbG93YW5jZSIsImZyb21XYWxsZXQiLCJmcm9tQmFsYW5jZSIsInRvV2FsbGV0IiwibmV3VG9XYWxsZXQiLCJjb2RlIiwidG9CYWxhbmNlIiwiZnJvbVVwZGF0ZWRCYWxhbmNlIiwidG9VcGRhdGVkQmFsYW5jZSIsInVwZGF0ZWRGcm9tV2FsbGV0IiwidXBkYXRlZFRvV2FsbGV0IiwidHJhbnNmZXJFdmVudCIsInJlZnJlc2giLCJUUkFOU0ZFUiIsImNhdGNoIiwiQXBwcm92ZSIsIm93bmVyV2FsbGV0IiwiYXBwcm92YWxFdmVudCIsIkFQUFJPVkFMIiwiYWxsb3dhbmNlQ29uZGl0aW9uIiwiSW5pdGlhbGl6ZSIsIk1pbnQiLCJhbW91bnQiLCJtaW50ZXIiLCJtaW50ZXJXYWxsZXQiLCJjdXJyZW50QmFsYW5jZSIsInVwZGF0ZWRCYWxhbmNlIiwidXBkYXRlZG1pbnRlciIsIm5ld1dhbGxldCIsImV2ZW50SGFuZGxlciIsIkJ1cm4iLCJhY2NvdW50IiwiYWNjb3VudFdhbGxldCIsInVwZGF0ZWRhY2NvdW50IiwiQ2xpZW50QWNjb3VudEJhbGFuY2UiLCJjbGllbnRBY2NvdW50SUQiLCJjbGllbnRXYWxsZXQiLCJDbGllbnRBY2NvdW50SUQiLCJfX21ldGFkYXRhIiwiY29udHJhY3RzIiwiQ29udHJhY3RMb2dnZXIiLCJNaW5pTG9nZ2VyIiwiY29uZiIsImxvZ2dpbmciLCJnZXRMb2dnZXIiLCJzZXRMZXZlbCIsImxldmVsIiwiZ2V0Q29uZmlnIiwic3RhY2siLCJOdW1lcmljTG9nTGV2ZWxzIiwiTG9nTGV2ZWwiLCJiZW5jaG1hcmsiLCJ0cmFjZSIsImNyZWF0ZUxvZyIsImZhY3RvcnkiLCJvYmplY3QiLCJzZXRGYWN0b3J5IiwiVkVSU0lPTiIsIlBBQ0tBR0VfTkFNRSIsInJlZ2lzdGVyTGlicmFyeSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7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
1
+ import{Model as t,JSONSerializer as e,ModelKeys as r,ValidationKeys as i,required as n,model as s}from"@decaf-ts/decorator-validation";import{Metadata as a,Decoration as o,propMetadata as c,description as l,uses as u}from"@decaf-ts/decoration";import{DBKeys as p,OperationKeys as d,BulkCrudOperationKeys as g,BaseError as h,InternalError as y,NotFoundError as w,ConflictError as f,SerializationError as m,BadRequestError as b,onCreate as x,onCreateUpdate as S,version as v,ValidationError as A}from"@decaf-ts/db-decorators";import{PersistenceKeys as C,Context as k,ObserverHandler as O,Adapter as N,Repository as P,QueryError as R,PreparedStatementKeys as E,Condition as $,Sequence as z,UUID as T,SequenceModel as I,Serial as B,PagingError as D,UnsupportedError as F,MigrationError as j,ObserverError as _,AuthorizationError as q,ForbiddenError as L,ConnectionError as J,column as M,createdAt as U,updatedAt as V,createdBy as Q,updatedBy as H,pk as Y,BaseModel as K,oneToOne as X,Cascade as G,index as W,OrderDirection as Z,table as tt}from"@decaf-ts/core";import{CouchDBStatement as et,CouchDBKeys as rt,CouchDBGroupOperator as it,CouchDBOperator as nt,CouchDBPaginator as st,CouchDBAdapter as at}from"@decaf-ts/for-couchdb";import{Property as ot,Object as ct,Contract as lt,Transaction as ut,Context as pt}from"fabric-contract-api";import{Logging as dt,MiniLogger as gt,NumericLogLevels as ht,LogLevel as yt}from"@decaf-ts/logging";import{__decorate as wt,__metadata as ft}from"tslib";var mt,bt;(t=>{t.PRIVATE="private",t.SHARED="shared",t.FABRIC="fabric.",t.OWNEDBY="owned-by",t.TRANSACTION_ID="transaction-id"})(mt||(mt={})),(t=>{t.X509="X.509"})(bt||(bt={}));const xt="hlf-fabric";t.prototype.isShared=function(){return t.isShared(this.constructor)},t.prototype.isPrivate=function(){return t.isPrivate(this.constructor)},t.prototype.segregate=function(){return t.segregate(this)},t.segregate=(e=>{if(!t.isTransient(e))return{model:e};const r=a.validatableProperties(e.constructor),i=a.get(e.constructor,p.TRANSIENT),n=a.get(e.constructor,mt.PRIVATE),s=a.get(e.constructor,mt.PRIVATE),o={model:{},transient:{},private:{},shared:{}},c=Object.keys(i),l=Object.keys(n),u=Object.keys(s);for(const t of r){const r=c.includes(t),i=l.includes(t),n=u.includes(t);r?(o.transient=o.transient||{},o.transient[t]=e[t],i&&(o.private=o.private||{},o.private[t]=e[t]),n&&(o.shared=o.shared||{},o.shared[t]=e[t])):(o.model=o.model||{},o.model[t]=e[t])}return o.model=t.build(o.model,e.constructor.name),o}).bind(t),t.tableName=e=>{const r=e instanceof t?e.constructor:e;return a.get(r,C.TABLE)||(e instanceof t?e.constructor.name:e.name)},t.isPrivate=(t=>!!a.get("function"!=typeof t?t.constructor:t,mt.PRIVATE)).bind(t),a.isShared=(t=>!!a.get("function"!=typeof t?t.constructor:t,mt.SHARED)).bind(a);class St extends k{constructor(){super()}get stub(){return this.get("stub")}get timestamp(){return this.stub.getDateTimestamp()}get identity(){return this.get("identity")}toString(){return"fabric ctx"+(this.stub?" with stub":"without stub")}}class vt extends O{constructor(t=[d.CREATE,d.UPDATE,d.DELETE,g.CREATE_ALL,g.UPDATE_ALL,g.DELETE_ALL]){super(),this.supportedEvents=t}async updateObservers(t,e,r,...i){const{log:n,ctx:s}=N.logCtx(this.updateObservers,e,!1,...i),{stub:a}=s,[o,c]=i,l="string"==typeof t?t:t.name;if(-1!==this.supportedEvents.indexOf(e)){n.debug(`Emitting ${e} event`);const t=((t,e,r)=>{const i=[t,e];return r&&i.push(r),i.join("_")})(l,e,o);a.setEvent(t,Buffer.from(JSON.stringify({id:r})))}else a.setEvent(e,Buffer.from(JSON.stringify(c)))}}class At extends P{constructor(t,e,r){super(t,e),this.trackedEvents=r,this._overrides=Object.assign({},super._overrides,{ignoreValidation:!1,ignoreHandlers:!1,allowRawStatements:!0,forcePrepareSimpleQueries:!1,forcePrepareComplexQueries:!1})}async paginateBy(e,r,i={offset:1,limit:10},...n){let{offset:s,bookmark:a,limit:o}=i;if(!s&&!a)throw new R("PaginateBy needs a page or a bookmark");const{log:c,ctxArgs:l}=(await this.logCtx(n,E.PAGE_BY,!0)).for(this.paginateBy);let u;if(c.verbose(`paginating ${t.tableName(this.class)} with page size ${o}`),a)u=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().where(this.attr(t.pk(this.class)).gt(a)).orderBy([e,r]).paginate(o,...l),s=1;else{if(!s)throw new R("PaginateBy needs a page or a bookmark");u=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().orderBy([e,r]).paginate(o,...l)}const p=await u.page(s,a,...l);return u.serialize(p)}async statement(t,...e){const{log:r,ctx:i,ctxArgs:n}=(await this.logCtx(e,C.STATEMENT,!0)).for(this.statement);if(!P.statements(this,t))throw new R("Invalid prepared statement requested "+t);let s;i.logger&&i.logger.info(`Repo statement: ${t} + ${e}`),r.verbose(`Executing prepared statement ${t} with args ${n}`);try{s=await this[t](...n)}catch(e){if(e instanceof h)throw e;throw new y(`Failed to execute prepared statement ${t} with args ${n}: ${e}`)}return s}ObserverHandler(){return new vt}async updateObservers(t,e,r,...i){if(!this.trackedEvents||-1!==this.trackedEvents.indexOf(e))return await super.updateObservers(t,e,r,...i)}}class Ct extends et{constructor(t){super(t)}async executionPrefix(t,...e){const r=e.filter(Boolean);if(e.length!==r.length)throw new y(`Received an undefined in the paginator for ${t}: ${e}`);return super.executionPrefix(t,...e)}async raw(e,...r){const{ctx:i}=this.logCtx(r,this.raw),n=await this.adapter.raw(e,!0,i),s=t.pk(this.fromSelector),o=a.get(this.fromSelector,a.key(p.ID,s))?.type;return this.selectSelector?n:n.map(t=>this.processRecord(t,s,o,i))}build(){const e={};e[rt.TABLE]={},e[rt.TABLE]=t.tableName(this.fromSelector);const r={selector:e};if(this.selectSelector&&(r.fields=this.selectSelector),this.whereCondition){const t=this.parseCondition($.and(this.whereCondition,$.attribute(rt.TABLE).eq(r.selector[rt.TABLE]))).selector,e=Object.keys(t);if(1===e.length&&-1!==Object.values(it).indexOf(e[0]))switch(e[0]){case it.AND:t[it.AND]=[...Object.values(t[it.AND]).reduce((t,e)=>{const r=Object.keys(e);if(1!==r.length)throw Error("Too many keys in query selector. should be one");const i=r[0];return i===it.AND?t.push(...e[i]):t.push(e),t},[])],r.selector=t;break;case it.OR:{const e={};e[it.AND]=[t,...Object.entries(r.selector).map(([t,e])=>{const r={};return r[t]=e,r})],r.selector=e;break}default:throw Error("This should be impossible")}else Object.entries(t).forEach(([t,e])=>{r.selector[t],r.selector[t]=e})}if(this.orderBySelector){r.sort=r.sort||[],r.selector=r.selector||{};const[t,e]=this.orderBySelector,i={};i[t]=e,r.sort.push(i),r.selector[t]||(r.selector[t]={},r.selector[t][nt.BIGGER]=null)}return this.limitSelector&&(r.limit=this.limitSelector),this.offsetSelector&&(r.skip=this.offsetSelector),r}}class kt extends z{constructor(t,e){super(t,e)}async current(...t){const{ctx:e,log:r}=(await this.logCtx(t,d.READ,!0)).for(this.current),{name:i,startWith:n}=this.options;try{const t=await this.repo.read(i,e);return this.parse(t.current)}catch(t){if(t instanceof w){let t;try{r.debug(`Trying to resolve current sequence ${i} value from context`),t=e.get(i),r.debug(`Retrieved cached current value for sequence ${i}: ${t}`)}catch(e){r.info(`No cached value for sequence ${i} in context`),t=n}try{return this.parse(t)}catch(t){throw new y(`Failed to parse initial value for sequence ${n}: ${t}`)}}throw new y(`Failed to retrieve current value for sequence ${i}: ${t}`)}}async increment(t,e){const r=e.logger.for(this.increment),{type:i,incrementBy:n,name:s}=this.options;if(!s)throw new y("Sequence name is required");return r.info("Obtaining sequence lock for sequence "+s),kt.lock.execute(async()=>{const a=t||n;if(a%n!==0)throw new y("Value to increment does not consider the incrementBy setting: "+n);const o="function"==typeof i&&i?.name?i.name:i,c=await this.current(e);async function l(t){return t instanceof Promise&&(t=await t),r.for(l).info(`Storing new ${s} seq value in cache: ${t.current}`),e.cache.put(s,t.current),t}const u=async t=>{try{return await l(this.repo.update(new I({id:s,current:t}),e))}catch(i){if(i instanceof w)return r.debug(`Sequence create ${s} current=${c} next=${t}`),l(this.repo.create(new I({id:s,current:t}),e));throw i}};if("uuid"===o)for(;;){const t=T.instance.generate(c);try{const e=await u(t);return r.debug(`Sequence uuid increment ${s} current=${c} next=${t}`),e.current}catch(t){if(t instanceof f)continue;throw t}}const p=(t=>{switch(o){case Number.name:return this.parse(t)+a;case BigInt.name:return this.parse(t)+BigInt(a);case String.name:return this.parse(t);case"serial":return B.instance.generate(t);default:throw new y("Should never happen")}})(c),d=await u(p);return r.debug(`Sequence.increment ${s} current=${c} next=${p}`),d.current},s)}}class Ot extends e{constructor(){super()}deserialize(t,e){return JSON.parse(t)}serialize(t,e=!0){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t,e)))}preSerialize(e,i=!0){const n=Object.assign({},e);let s;try{s=a.modelName(e.constructor)}catch(t){s=void 0}function o(t){return"object"!=typeof t?t:Array.isArray(t)?t.map(o):this.preSerialize(t)}return i&&(n[r.ANCHOR]=s||e.constructor.name),t.relations(e).forEach(t=>{n[t]=o.call(this,n[t])}),n}}class Nt extends st{constructor(t,e,r,i){super(t,e,r,i)}prepare(t){const e=Object.assign({},t);return e.limit&&(this.limit=e.limit),e.limit=this.size,e}async page(e=1,r,...i){const{ctxArgs:n,ctx:s,log:o}=this.adapter.logCtx([r,...i],this.page);if(this.isPreparedStatement())return await this.pagePrepared(e,...n);const c=Object.assign({},this.statement);if(this._recordCount&&this._totalPages)e=this.validatePage(e),c.skip=(e-1)*this.size;else{this._totalPages=this._recordCount=0;const t=await this.adapter.raw({...c,limit:Number.MAX_VALUE},!0,...n)||[];if(this._recordCount=t.length,this._recordCount>0){const t=c?.limit||this.size;return this._totalPages=Math.ceil(this._recordCount/t),await this.page(e,...n)}}if(1!==e){if(!this._bookmark)throw new D("No bookmark. Did you start in the first page?");c.bookmark=this._bookmark}const l=await this.adapter.raw(c,!0,...n),{docs:u,bookmark:d,warning:g}=l;if(g&&o.warn(g),!this.clazz)throw new D("No statement target defined");const h=t.pk(this.clazz),y=a.get(this.clazz,a.key(p.ID,h))?.type,w=c.fields&&c.fields.length?l:l.map(t=>this.adapter.revert(t,this.clazz,z.parseValue(y,t[h]),void 0,s));return this._bookmark=d,this._currentPage=e,w}}class Pt extends y{constructor(t){super(t,Pt.name)}}class Rt extends y{constructor(t){super(t,Rt.name)}}class Et extends y{constructor(t){super(t,Et.name)}}class $t extends y{constructor(t){super(t,$t.name,500)}}class zt extends h{constructor(t){super(zt.name,t,409)}}async function Tt(t,e,r,i){try{const e=t.get("identity");i[r]=e.getID()}catch(t){throw new F("No User found in context. Please provide a user in the context")}}async function It(e,r,i,n){if(!r.type||n[i])return;let s;r.name||(r.name=t.sequenceName(n,"pk"));try{s=await this.adapter.Sequence(r)}catch(t){throw new y(`Failed to instantiate Sequence ${r.name}: ${t}`)}const a=await s.next(e);Object.defineProperty(n,i,{enumerable:!0,writable:!1,configurable:!0,value:a})}class Bt extends at{getClient(){throw new F("Client is not supported in Fabric contracts")}static{this.textDecoder=new TextDecoder("utf8")}static{this.serializer=new Ot}get Context(){return St}repository(){return At}Paginator(t,e,r){return new Nt(this,t,e,r)}async Sequence(t){return new kt(t,this)}constructor(t,e){super(t,xt,e)}for(t,...e){return super.for(t,...e)}async create(e,r,i,...n){const{ctx:s,log:a}=this.logCtx(n,this.create);a.info("in ADAPTER create with args "+n);const o=t.tableName(e);try{a.info(`adding entry to ${o} table with pk ${r}`);const t=s.stub.createCompositeKey(o,[r+""]);i=await this.putState(t,i,s)}catch(t){throw this.parseError(t)}return i}async read(e,r,...i){const{ctx:n,log:s}=this.logCtx(i,this.read);s.info("in ADAPTER read with args "+i);const a=t.tableName(e);let o;try{const t=n.stub.createCompositeKey(a,[r+""]);o=await this.readState(t,n)}catch(t){throw this.parseError(t)}return o}async update(e,r,i,...n){const{ctx:s,log:a}=this.logCtx(n,this.update),o=t.tableName(e);try{a.verbose(`updating entry to ${o} table with pk ${r}`);const t=s.stub.createCompositeKey(o,[r+""]);i=await this.putState(t,i,s)}catch(t){throw this.parseError(t)}return i}async delete(e,r,...i){const{ctx:n,log:s,ctxArgs:a}=this.logCtx(i,this.delete),o=t.tableName(e);let c;try{const t=n.stub.createCompositeKey(o,[r+""]);c=await this.read(e,r,...a),s.verbose(`deleting entry with pk ${r} from ${o} table`),await this.deleteState(t,n)}catch(t){throw this.parseError(t)}return c}async deleteState(t,e){const{ctx:r}=this.logCtx([e],this.deleteState);await r.stub.deleteState(t)}forPrivate(t){const e=[this.putState,this.readState,this.deleteState,this.queryResult,this.queryResultPaginated].map(t=>t.name);return new Proxy(this,{get:(r,i,n)=>e.includes(i)?new Proxy(r[i],{async apply(e,r,n){switch(i){case"putState":{const[e,r,i]=n;return await e.putPrivateData(t,r.toString(),i),i}case"deleteState":{const[e,r]=n;return e.deletePrivateData(t,r)}case"readState":{const[e,r]=n;return e.getPrivateData(t,r)}case"queryResult":{const[e,r]=n;return e.getPrivateDataQueryResult(t,r)}case"queryResultPaginated":{const[e,r,i,s]=n,a=await e.getPrivateDataQueryResult(t,r),o=[];let c=0,l=!s,u=null;for(;;){const t=await a.next();if(t.value&&t.value.value.toString()){const e=t.value.key,r=t.value.value.toString("utf8");if(!l){e===s?.toString()&&(l=!0);continue}if(o.push({Key:e,Record:JSON.parse(r)}),u=e,c++,c>=i)return await a.close(),{iterator:o,metadata:{fetchedRecordsCount:o.length,bookmark:u}}}if(t.done)return await a.close(),{iterator:o,metadata:{fetchedRecordsCount:o.length,bookmark:""}}}}default:throw new y("Unsupported method override "+i)}}}):Reflect.get(r,i,n)})}async putState(t,e,r){let i;const{log:n}=this.logCtx([r],this.putState);try{i=Buffer.from(Bt.serializer.serialize(e,!1))}catch(e){throw new m(`Failed to serialize record with id ${t}: ${e}`)}const s=r.get("segregated");return s?await r.stub.putPrivateData(s,t.toString(),i):await r.stub.putState(t.toString(),i),n.silly(`state stored${s?` in ${s} collection`:""} under id ${t}`),e}async readState(t,e){let r;const{log:i}=this.logCtx([e],this.readState);let n;const s=e.get("segregated");if(n=s?(await e.stub.getPrivateData(s,t.toString())).toString():(await e.stub.getState(t.toString())).toString(),!n)throw new w(`Record with id ${t}${s?` in ${s} collection`:""} not found`);i.silly(`state retrieved from${s?` ${s} collection`:""} under id ${t}`);try{r=Bt.serializer.deserialize(n.toString())}catch(t){throw new m("Failed to parse record: "+t)}return r}async queryResult(t,e,...r){const{ctx:i}=this.logCtx(r,this.queryResult);let n;const s=i.get("segregated");return n=s?await i.stub.getPrivateDataQueryResult(s,JSON.stringify(e)):await t.getQueryResult(JSON.stringify(e)),n}async queryResultPaginated(t,e,r=250,i,...n){const{ctx:s}=this.logCtx(n,this.readState);let a;const o=s.get("segregated");return o?(e.selector={...e.selector,_id:i?{$gt:i.toString()}:{$gte:""}},a={iterator:await t.getPrivateDataQueryResult(o,JSON.stringify(e)),metadata:{fetchedRecordsCount:r,bookmark:""}}):a=await t.getQueryResultWithPagination(JSON.stringify(e),r,i?.toString()),a}mergeModels(t){const e=t=>Object.entries(t).reduce((t,[e,r])=>(void 0!==r&&(t[e]=r),t),{});let r=t.pop();for(const i of t)r=Object.assign({},e(r),e(i));return r}decode(t){return Bt.textDecoder.decode(t)}async flags(t,e,r){let i=Object.assign({segregated:!1},r);return r instanceof St||(r.stub?Object.assign(i,{stub:r.stub,identity:r.clientIdentity,cert:r.clientIdentity.getIDBytes().toString(),roles:r.clientIdentity.getAttributeValue("roles"),logger:dt.for(t,{logLevel:!1,timestamp:!1,correlationId:r.stub.getTxID()},r),correlationId:r.stub.getTxID()}):i=Object.assign(i,r||{})),await super.flags(t,e,i)}index(t){return Promise.resolve(void 0)}async resultIterator(t,e,r=!1){const i=[];let n=await e.next();for(;!n.done;){if(n.value&&n.value.value.toString()){let e={};if(t.debug(n.value.value.toString("utf8")),r){e.TxId=n.value.txId,e.Timestamp=n.value.timestamp;try{e.Value=JSON.parse(n.value.value.toString("utf8"))}catch(r){t.error(r),e.Value=n.value.value.toString("utf8")}}else try{e=JSON.parse(n.value.value.toString("utf8"))}catch(r){t.error(r),e=n.value.value.toString("utf8")}i.push(e)}n=await e.next()}return t.debug(`Closing iterator after ${i.length} results`),e.close(),i}async raw(t,e=!0,...r){const{log:i,ctx:n}=this.logCtx(r,this.raw),{skip:s,limit:a}=t;let o;a||s?(delete t.limit,delete t.skip,i.debug(`Retrieving paginated iterator: limit: ${a}/ skip: ${s}`),o=(await this.queryResultPaginated(n.stub,t,a||Number.MAX_VALUE,s?.toString(),n)).iterator):(i.debug("Retrieving iterator"),o=await this.queryResult(n.stub,t,n)),i.debug("Iterator acquired");const c=await this.resultIterator(i,o);return i.debug(`returning ${Array.isArray(c)?c.length:1} results`),c}Statement(){return new Ct(this)}async createAll(e,r,i,...n){if(r.length!==i.length)throw new y("Ids and models must have the same length");const{log:s,ctxArgs:a}=this.logCtx(n,this.createAll),o=t.tableName(e);return s.debug(`Creating ${r.length} entries ${o} table`),Promise.all(r.map((t,r)=>this.create(e,t,i[r],...a)))}async updateAll(e,r,i,...n){if(r.length!==i.length)throw new y("Ids and models must have the same length");const{log:s,ctxArgs:a}=this.logCtx(n,this.updateAll),o=t.tableName(e);return s.debug(`Updating ${r.length} entries ${o} table`),Promise.all(r.map((t,r)=>this.update(e,t,i[r],...a)))}prepare(e,...r){const{log:i}=this.logCtx(r,this.prepare),n=t.tableName(e.constructor),s=t.pk(e.constructor),a=t.segregate(e),o=Object.entries(a.model).reduce((r,[i,n])=>{if(void 0===n)return r;const s=t.columnName(e,i);if(this.isReserved(s))throw new y(`Property name ${s} is reserved`);return r[s]=n,r},{});return i.silly(`Preparing record for ${n} table with pk ${e[s]}`),{record:o,id:e[s],transient:a.transient}}revert(e,r,i,n,...s){const{log:a}=this.logCtx(s,this.revert),o={};o[t.pk(r)]=i;const c="string"==typeof r?t.build(o,r):new r(o);a.silly(`Rebuilding model ${c.constructor.name} id ${i}`);const l=Object.keys(c).reduce((r,i)=>(r[i]=e[t.columnName(r,i)],r),c);return n&&(a.debug("re-adding transient properties: "+Object.keys(n).join(", ")),Object.entries(n).forEach(([t,e])=>{if(t in l&&void 0!==l[t])throw new y(`Transient property ${t} already exists on model ${c.constructor.name}. should be impossible`);l[t]=e})),l}createPrefix(e,r,i,...n){const{ctxArgs:s}=this.logCtx(n,this.createPrefix),a={};return a[rt.TABLE]=t.tableName(e),Object.assign(a,i),[e,r,a,...s]}updatePrefix(e,r,i,...n){const{ctxArgs:s}=this.logCtx(n,this.updatePrefix),a={};return a[rt.TABLE]=t.tableName(e),Object.assign(a,i),[e,r,a,...s]}createAllPrefix(e,r,i,...n){if(r.length!==i.length)throw new y("Ids and models must have the same length");const s=n.pop(),a=r.map((r,n)=>{const s={};return s[rt.TABLE]=t.tableName(e),Object.assign(s,i[n]),s});return[e,r,a,s]}updateAllPrefix(e,r,i,...n){if(r.length!==i.length)throw new y("Ids and models must have the same length");const s=n.pop(),a=r.map((r,n)=>{const s={};return s[rt.TABLE]=t.tableName(e),Object.assign(s,i[n]),s});return[e,r,a,s]}parseError(t,e){return Bt.parseError(e||t)}logCtx(t,e,r=!1,i){return r?super.logCtx.call(this,t,e,r,i).then(t=>{if(!(t.ctx instanceof St))throw new y("Invalid context binding");if(!t.ctx.stub)throw new y("Missing Stub");if(!t.ctx.identity)throw new y("Missing Identity");return Object.assign(t,{stub:t.ctx.stub,identity:t.ctx.identity})}):super.logCtx(t,e,r,i)}static parseError(t){const e="string"==typeof t?t:t.message;return e.includes(w.name)?new w(t):e.includes(f.name)?new f(t):e.includes(b.name)?new b(t):e.includes(R.name)?new R(t):e.includes(D.name)?new D(t):e.includes(F.name)?new F(t):e.includes(j.name)?new j(t):e.includes(_.name)?new _(t):e.includes(q.name)?new q(t):e.includes(L.name)?new L(t):e.includes(J.name)?new J(t):e.includes(m.name)?new m(t):e.includes("no ledger context")?new $t("No context found. this can be caused by debugging: "+e):new y(t)}static decoration(){super.decoration(),o.flavouredAs(xt).for(C.CREATED_BY).define(x(Tt),c(C.CREATED_BY,{})).apply(),o.flavouredAs(xt).for(C.UPDATED_BY).define(S(Tt),c(C.UPDATED_BY,{})).apply(),o.flavouredAs(xt).for(C.COLUMN).extend(ot()).apply(),o.flavouredAs(xt).for(i.DATE).extend(()=>(t,e)=>{ot(e,"string:date")(t,e)}),o.flavouredAs(xt).for(C.TABLE).extend(t=>{const e=[];let r="function"==typeof t?a.constr(t):a.constr(t.constructor);for(;r&&r!==Object&&r.prototype;)e.push(r),r=Object.getPrototypeOf(r);for(;e.length>0;){const t=e.pop();ct()(t)}return ct()(t)}).apply()}}Bt.decoration(),N.setCurrent(xt);class Dt extends e{constructor(){super()}preSerialize(e){const i=Object.assign({},e);let n;try{n=a.modelName(e.constructor)}catch(t){n=void 0}i[r.ANCHOR]=n||e.constructor.name;const s=function t(e){const r=this;return"object"!=typeof e?e:Array.isArray(e)?e.map(e=>t.call(r,e)):this.preSerialize.call(this,e)}.bind(this);return t.relations(e).forEach(t=>{i[t]=s(i[t])}),i}deserialize(e){const i=JSON.parse(e),n=i[r.ANCHOR];if(!n)throw Error("Could not find class reference in serialized model");return t.build(i,n)}serialize(t){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t)))}}var Ft;(t=>{t.TRANSFER="Transfer",t.APPROVAL="Approval"})(Ft||(Ft={}));let jt=class extends t{constructor(t){super(t)}};wt([l("Stores the original timestamp of creation"),M(),U(),ft("design:type",Date)],jt.prototype,"createdAt",void 0),wt([l("Stores the timestamp of the last update"),M(),V(),ft("design:type",Date)],jt.prototype,"updatedAt",void 0),wt([l("Stores the version of the model"),M(),v(),ft("design:type",Number)],jt.prototype,"version",void 0),jt=wt([u(xt),ft("design:paramtypes",[Object])],jt);let _t=class extends jt{constructor(t){super(t)}};wt([l("Stores the creator"),M(),Q(),ft("design:type",String)],_t.prototype,"createdBy",void 0),wt([l("Stores the user that last updated the model"),M(),H(),ft("design:type",String)],_t.prototype,"updatedBy",void 0),_t=wt([u(xt),ft("design:paramtypes",[Object])],_t);let qt=class extends K{constructor(t){super(t)}};wt([l("Unique identifier of the credentials record"),M(),Y(),ft("design:type",String)],qt.prototype,"id",void 0),wt([l("PEM-encoded X.509 certificate for the identity"),M(),n(),ft("design:type",String)],qt.prototype,"certificate",void 0),wt([l("PEM-encoded root or intermediate certificate"),M(),n(),ft("design:type",String)],qt.prototype,"rootCertificate",void 0),wt([l("PEM-encoded private key"),M(),n(),ft("design:type",String)],qt.prototype,"privateKey",void 0),qt=wt([s(),ft("design:paramtypes",[Object])],qt);let Lt=class extends K{constructor(t){super(t),this.type=bt.X509}};function Jt(){return function(t,e,r){const i=r.value;return r.value=async function(...t){const r=t[0],n=r.clientIdentity.getID(),s=await this.tokenRepository.select(),a=await s.execute(r);if(0==a.length)throw new w("No tokens avaialble");if(a.length>1)throw new w("To many token available : "+a.length);if(a[0].owner!=n)throw new q(`User not authorized to run ${e} on the token`);return await i.apply(this,t)},r}}function Mt(t,e){const r=t+e;if(t!==r-e||e!==r-t)throw new Pt(`Addition overflow: ${t} + ${e}`);return r}function Ut(t,e){const r=t-e;if(t!==r+e||e!==t-r)throw new Pt(`Subtraction overflow: ${t} - ${e}`);return r}wt([l("Unique identifier of the identity"),Y(),ft("design:type",String)],Lt.prototype,"id",void 0),wt([X(qt,{update:G.CASCADE,delete:G.CASCADE}),ft("design:type",qt)],Lt.prototype,"credentials",void 0),wt([M(),n(),W(),ft("design:type",String)],Lt.prototype,"mspId",void 0),wt([M(),n(),ft("design:type",String)],Lt.prototype,"type",void 0),Lt=wt([s(),ft("design:paramtypes",[Object])],Lt),ct()(Date);class Vt extends lt{static{this.adapter=new Bt}static{this.serializer=new Dt}constructor(t,e){super(t),this.clazz=e,this.initialized=!1,this.repo=P.forModel(e)}async listBy(t,e,r,...i){const{ctxArgs:n,log:s}=(await this.logCtx([...i,t],E.LIST_BY,!0)).for(this.listBy);return s.info(`Running listBy key ${e}, order ${r} and args ${n}`),this.repo.listBy(e,r,...n)}async paginateBy(t,e,r,i={offset:1,limit:10},...n){const{ctxArgs:s,log:a}=(await this.logCtx([...n,t],E.PAGE_BY,!0)).for(this.paginateBy);return a.info(`Running paginateBy key ${e}, order ${r} with size ${i.limit} and args ${s}`),this.repo.paginateBy(e,r,i,...s)}async findOneBy(t,e,r,...i){const{ctxArgs:n,log:s}=(await this.logCtx([...i,t],E.FIND_ONE_BY,!0)).for(this.findOneBy);return s.info(`Running findOneBy key ${e}, value: ${r} with args ${n}`),this.repo.findOneBy(e,r,...n)}async statement(t,e,...r){const{ctxArgs:i,log:n}=(await this.logCtx([...r,t],C.STATEMENT,!0)).for(this.statement);return n.info(`Running statement ${e} with args ${i}`),this.repo.statement(e,...i)}async create(e,r,...i){const{log:n,ctxArgs:s}=(await this.logCtx([...i,e],d.CREATE,!0)).for(this.create);n.info("CONTRACT CREATE, "+s),"string"==typeof r&&(r=this.deserialize(r)),n.info("Creating model: "+JSON.stringify(r));const a=this.getTransientData(e);return n.info("Merging transient data..."),r=t.merge(r,a,this.clazz),this.repo.create(r,...s)}async read(t,e,...r){const{log:i,ctxArgs:n}=(await this.logCtx([...r,t],d.READ,!0)).for(this.create);return i.info(`reading entry with pk ${e} `),this.repo.read(e,...n)}getTransientData(t){const e=t.stub.getTransient();let r={};return e.has(this.repo.tableName)&&(r=JSON.parse(e.get(this.repo.tableName)?.toString("utf8"))),r}async update(e,r,...i){const{log:n,ctxArgs:s}=(await this.logCtx([...i,e],d.UPDATE,!0)).for(this.update);"string"==typeof r&&(r=this.deserialize(r)),n.info("Updating model: "+JSON.stringify(r));const a=this.getTransientData(e);return n.info("Merging transient data..."),r=t.merge(r,a,this.clazz),this.repo.update(r,...s)}async delete(t,e,...r){const{log:i,ctxArgs:n}=(await this.logCtx([...r,t],d.DELETE,!0)).for(this.delete);return i.info(`deleting entry with pk ${e} `),this.repo.delete(e+"",...n)}async deleteAll(t,e,...r){const{ctxArgs:i}=(await this.logCtx([...r,t],g.DELETE_ALL,!0)).for(this.deleteAll);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.deleteAll(e,...i)}async readAll(t,e,...r){const{ctxArgs:i}=(await this.logCtx([...r,t],g.READ_ALL,!0)).for(this.create);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.readAll(e,...i)}async updateAll(t,e,...r){const{log:i,ctxArgs:n}=(await this.logCtx([...r,t],g.UPDATE_ALL,!0)).for(this.updateAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),i.info(`updating ${e.length} entries to the table`),this.repo.updateAll(e,...n)}async query(t,e,r,i=Z.ASC,n,s,...a){const{ctxArgs:o}=(await this.logCtx([...a,t],C.QUERY,!0)).for(this.create);return this.repo.query(e,r,i,n,s,...o)}async raw(t,e,r,...i){const{ctxArgs:n}=(await this.logCtx([...i,t],"raw",!0)).for(this.raw);return Vt.adapter.raw(e,r,...n)}serialize(t){return Vt.serializer.serialize(t)}deserialize(t){return Vt.serializer.deserialize(t)}async init(t){const{log:e,ctxArgs:r}=(await this.logCtx([t],C.INITIALIZATION,!0)).for(this.init);e.info(`Running contract ${this.getName()} initialization...`),this.initialized=!0,e.info("Contract initialization completed.")}async healthcheck(t){const{log:e}=(await this.logCtx([t],"healthcheck",!0)).for(this.healthcheck);return e.info(`Running Healthcheck: ${this.initialized}...`),{healthcheck:this.initialized}}async createAll(t,e,...r){const{log:i,ctxArgs:n}=(await this.logCtx([...r,t],g.CREATE_ALL,!0)).for(this.createAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),i.info(`adding ${e.length} entries to the table`),this.repo.createAll(e,...n)}logCtx(t,e,r=!1){const i=t.pop();if(!i||!i.stub)throw new $t("No valid context provided...");const n=Vt.adapter.logCtx([this.clazz,...t],e,r,i);function s(t){return t.ctxArgs.shift(),t}return n instanceof Promise?n.then(s):s(n)}}class Qt extends Vt{constructor(t,e){super(t,e)}async create(t,e){return this.serialize(await super.create(t,e))}async read(t,e){return this.serialize(await super.read(t,e))}async update(t,e){return this.serialize(await super.update(t,e))}async delete(t,e){return this.serialize(await super.delete(t,e))}async deleteAll(t,e){const r=JSON.parse(e);return JSON.stringify((await super.deleteAll(t,r)).map(t=>this.serialize(t)))}async readAll(t,e){const r=JSON.parse(e);return JSON.stringify((await super.readAll(t,r)).map(t=>this.serialize(t)))}async updateAll(t,e){const r=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t));return JSON.stringify((await super.updateAll(t,r)).map(t=>this.serialize(t)))}async statement(t,e,r){try{r=JSON.parse(r)}catch(t){throw new m("Invalid args: "+t)}if(!Array.isArray(r))throw new m(`Invalid args: ${JSON.stringify(r)}. must be an array`);return JSON.stringify(await super.statement(t,e,...r))}async listBy(t,e,r){return JSON.stringify(await super.listBy(t,e,r))}async paginateBy(t,e,r,i){try{i=JSON.parse(i)}catch(t){throw new m("Failed to deserialize paginateBy reference: "+t)}return JSON.stringify(await super.paginateBy(t,e,r,i))}async findOneBy(t,e,r){return JSON.stringify(await super.findOneBy(t,e,r))}async query(t,e,r,i,n,s){let a;try{a=$.from(JSON.parse(e))}catch(t){throw new m("Invalid condition: "+t)}return JSON.stringify(await super.query(t,a,r,i,n,s))}async init(t){await super.init(t)}async healthcheck(t){return JSON.stringify(await super.healthcheck(t))}async createAll(t,e){const r=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t)),i=await super.createAll(t,r);return JSON.stringify(i.map(t=>this.serialize(t)))}}wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"create",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"read",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"update",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"delete",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"deleteAll",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"readAll",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"updateAll",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String,String]),ft("design:returntype",Promise)],Qt.prototype,"statement",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String,String]),ft("design:returntype",Promise)],Qt.prototype,"listBy",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String,String,String]),ft("design:returntype",Promise)],Qt.prototype,"paginateBy",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String,String]),ft("design:returntype",Promise)],Qt.prototype,"findOneBy",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Qt.prototype,"init",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Qt.prototype,"healthcheck",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Qt.prototype,"createAll",null);let Ht=class extends K{constructor(t){super(t)}};wt([Y({type:String}),ft("design:type",String)],Ht.prototype,"name",void 0),wt([M(),n(),ft("design:type",String)],Ht.prototype,"owner",void 0),wt([M(),n(),ft("design:type",String)],Ht.prototype,"symbol",void 0),wt([M(),n(),ft("design:type",Number)],Ht.prototype,"decimals",void 0),Ht=wt([tt("erc20_tokens"),s(),ft("design:paramtypes",[Object])],Ht);let Yt=class extends K{constructor(t){super(t)}};wt([Y({type:String}),ft("design:type",String)],Yt.prototype,"id",void 0),wt([M(),n(),ft("design:type",String)],Yt.prototype,"token",void 0),wt([M(),n(),ft("design:type",Number)],Yt.prototype,"balance",void 0),wt([M(),ft("design:type",String)],Yt.prototype,"captive",void 0),Yt=wt([tt("erc20_wallets"),s(),ft("design:paramtypes",[Object])],Yt);let Kt=class extends K{constructor(t){super(t)}};wt([Y({type:String}),M(),n(),ft("design:type",String)],Kt.prototype,"owner",void 0),wt([M(),n(),ft("design:type",String)],Kt.prototype,"spender",void 0),wt([M(),n(),ft("design:type",Number)],Kt.prototype,"value",void 0),Kt=wt([tt("erc20_allowances"),s(),ft("design:paramtypes",[Object])],Kt);class Xt extends Vt{constructor(t){super(t,Yt),Xt.adapter=Xt.adapter||new Bt,this.walletRepository=At.forModel(Yt,Xt.adapter.alias),this.tokenRepository=At.forModel(Ht,Xt.adapter.alias),this.allowanceRepository=At.forModel(Kt,Xt.adapter.alias)}async TokenName(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].name}async Symbol(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].symbol}async Decimals(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].decimals}async TotalSupply(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.walletRepository.select(),i=await r.execute(e);if(0==i.length)throw new w(`The token ${this.getName()} does not exist`);let n=0;return i.forEach(t=>{n+=t.balance}),n}async BalanceOf(t,e){const{ctx:r}=await this.logCtx([t],this.TokenName);return await this.CheckInitialized(r),(await this.walletRepository.read(e,r)).balance}async Transfer(t,e,r){const{ctx:i}=await this.logCtx([t],this.Transfer);await this.CheckInitialized(i);const n=i.identity.getID();if(!await this._transfer(n,e,r,i))throw new y("Failed to transfer");return!0}async TransferFrom(t,e,r,i){const{ctx:n}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(n);const s=n.identity.getID(),a=await this._getAllowance(e,s,n);if(!a||0>a.value)throw new Et(`spender ${s} has no allowance from ${e}`);const o=a.value;if(i>o)throw new Rt("The spender does not have enough allowance to spend.");const c=Ut(o,i),l=Object.assign({},a,{value:c});if(await this.allowanceRepository.update(l,n),!await this._transfer(e,r,i,n))throw new y("Failed to transfer");return!0}async _transfer(t,e,r,i){const n=i.logger;if(t===e)throw new q("cannot transfer to and from same client account");if(0>r)throw new Rt("transfer amount cannot be negative");const s=await this.walletRepository.read(t,i),a=s.balance;if(r>a)throw new Rt(`client account ${t} has insufficient funds.`);let o,c=!1;try{o=await this.walletRepository.read(e,i)}catch(t){if(!(t instanceof h))throw new y(t);if(404!==t.code)throw new y(t.message);o=new Yt({id:e,balance:0,token:await this.TokenName(i)}),c=!0}const l=o.balance,u=Ut(a,r),p=Mt(l,r),d=Object.assign({},s,{balance:u});await this.walletRepository.update(d,i);const g=Object.assign({},o,{balance:p});c?await this.walletRepository.create(g,i):await this.walletRepository.update(g,i);const w={from:t,to:e,value:r};return this.repo.refresh(Ht,Ft.TRANSFER,"",w,i).catch(t=>n.error("Failed to notify transfer: "+t)),!0}async Approve(t,e,r){const{ctx:i,ctxArgs:n}=await this.logCtx([t],this.Approve);await this.CheckInitialized(i);const s=i.identity.getID();let a=await this._getAllowance(s,e,i);if((await this.walletRepository.read(s,...n)).balance<r)throw new Rt(`client account ${s} has insufficient funds.`);a?(a.value=r,await this.allowanceRepository.update(a,...n)):(a=new Kt({owner:s,spender:e,value:r}),await this.allowanceRepository.create(a,...n));const o={owner:s,spender:e,value:r};return this.repo.refresh(Ht,Ft.APPROVAL,"",o,i),!0}async Allowance(t,e,r){const{ctx:i}=await this.logCtx([t],this.Allowance);await this.CheckInitialized(i);const n=await this._getAllowance(e,r,i);if(!n)throw new Et(`spender ${r} has no allowance from ${e}`);return n.value}async _getAllowance(t,e,r){const i=$.and($.attribute("owner").eq(t),$.attribute("spender").eq(e)),n=await this.allowanceRepository.select().where(i).execute(r);return n?.[0]}async Initialize(t,e){const{ctx:r}=await this.logCtx([t],this.Initialize);if((await this.tokenRepository.select().execute(r)).length>0)throw new q("contract options are already set, client is not authorized to change them");return e.owner=r.identity.getID(),await this.tokenRepository.create(e,r),!0}async CheckInitialized(t){const{ctx:e}=await this.logCtx([t],this.CheckInitialized);if(0==(await this.tokenRepository.select().execute(e)).length)throw new zt("contract options need to be set before calling any function, call Initialize() to initialize contract")}async Mint(t,e){const{ctx:r}=await this.logCtx([t],this.Mint);await this.CheckInitialized(r);const i=r.identity.getID();if(0>=e)throw new A("mint amount must be a positive integer");let n;try{n=await this.walletRepository.read(i,r);const t=Mt(n.balance,e),s=Object.assign({},n,{balance:t});await this.walletRepository.update(s,r)}catch(n){if(!(n instanceof h))throw new y(n);if(404!==n.code)throw new y(n.message);{const n=new Yt({id:i,balance:e,token:await this.TokenName(t)});await this.walletRepository.create(n,r)}}const s={from:"0x0",to:i,value:e};this.repo.ObserverHandler().updateObservers(Ht,Ft.TRANSFER,"",s,r)}async Burn(t,e){const{log:r,ctx:i}=await this.logCtx([t],this.Burn);await this.CheckInitialized(i);const n=i.identity.getID(),s=await this.walletRepository.read(n,i),a=s.balance;if(e>a)throw new Rt("Minter has insufficient funds.");const o=Ut(a,e),c=Object.assign({},s,{balance:o});await this.walletRepository.update(c,i),r.info(e+" tokens were burned");const l={from:n,to:"0x0",value:e};this.repo.ObserverHandler().updateObservers(Ht,Ft.TRANSFER,"",l,i)}async BurnFrom(t,e,r){const{log:i,ctx:n}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(n);const s=await this.walletRepository.read(e,n),a=s.balance;if(r>a)throw new Rt(e+" has insufficient funds.");const o=Ut(a,r),c=Object.assign({},s,{balance:o});await this.walletRepository.update(c,n),i.info(`${r} tokens were burned from ${e}`);const l={from:e,to:"0x0",value:r};this.repo.ObserverHandler().updateObservers(Ht,Ft.TRANSFER,"",l,n)}async ClientAccountBalance(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=e.identity.getID(),i=await this.walletRepository.read(r,e);if(!i)throw new Rt(`The account ${r} does not exist`);return i.balance}async ClientAccountID(t){const{ctx:e}=await this.logCtx([t],this.ClientAccountID);return await this.CheckInitialized(e),e.identity.getID()}}wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"TokenName",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"Symbol",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"Decimals",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"TotalSupply",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String]),ft("design:returntype",Promise)],Xt.prototype,"BalanceOf",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String,Number]),ft("design:returntype",Promise)],Xt.prototype,"Transfer",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String,String,Number]),ft("design:returntype",Promise)],Xt.prototype,"TransferFrom",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String,Number]),ft("design:returntype",Promise)],Xt.prototype,"Approve",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt,String,String]),ft("design:returntype",Promise)],Xt.prototype,"Allowance",null),wt([ut(),ft("design:type",Function),ft("design:paramtypes",[pt,Ht]),ft("design:returntype",Promise)],Xt.prototype,"Initialize",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"CheckInitialized",null),wt([Jt(),ut(),ft("design:type",Function),ft("design:paramtypes",[pt,Number]),ft("design:returntype",Promise)],Xt.prototype,"Mint",null),wt([Jt(),ut(),ft("design:type",Function),ft("design:paramtypes",[pt,Number]),ft("design:returntype",Promise)],Xt.prototype,"Burn",null),wt([Jt(),ut(),ft("design:type",Function),ft("design:paramtypes",[pt,String,Number]),ft("design:returntype",Promise)],Xt.prototype,"BurnFrom",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"ClientAccountBalance",null),wt([ut(!1),ft("design:type",Function),ft("design:paramtypes",[pt]),ft("design:returntype",Promise)],Xt.prototype,"ClientAccountID",null);const Gt=[Xt];class Wt extends gt{constructor(t,e,r){super(t,e),r?(this.logger=r.logging.getLogger(t),r.logging.setLevel(e?.level||dt.getConfig().level)):this.logger=new gt(t,e)}log(t,e,r){if(ht[this.config("level")]<ht[t])return;let i;switch(t){case yt.benchmark:i=this.logger.verbose;break;case yt.info:i=this.logger.info;break;case yt.verbose:i=this.logger.verbose;break;case yt.debug:i=this.logger.debug;break;case yt.error:i=this.logger.error;break;case yt.trace:i=this.logger.trace;break;case yt.warn:i=this.logger.warn;break;case yt.silly:i=this.logger.silly;break;default:throw new y("Invalid log level")}i.call(this.logger,this.createLog(t,e,r))}}dt.setFactory((t,e,r)=>new Wt(t||Wt.name,e||{},r));const Zt="##VERSION##",te="##PACKAGE##";a.registerLibrary(te,Zt);export{Wt as ContractLogger,Bt as FabricContractAdapter,St as FabricContractContext,Nt as FabricContractPaginator,At as FabricContractRepository,vt as FabricContractRepositoryObservableHandler,Vt as FabricCrudContract,Ct as FabricStatement,te as PACKAGE_NAME,Qt as SerializedCrudContract,Zt as VERSION,Gt as contracts,Tt as createdByOnFabricCreateUpdate,It as pkFabricOnCreate};
2
+ //# sourceMappingURL=for-fabric.js.map