@decaf-ts/for-fabric 0.1.45 → 0.1.46

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