@sentry/node 7.105.0 → 8.0.0-alpha.2

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 (429) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +114 -38
  3. package/cjs/cron/index.js +15 -0
  4. package/cjs/cron/index.js.map +1 -0
  5. package/cjs/index.js +79 -99
  6. package/cjs/index.js.map +1 -1
  7. package/cjs/integrations/anr/index.js +5 -32
  8. package/cjs/integrations/anr/index.js.map +1 -1
  9. package/cjs/integrations/anr/worker-script.js +2 -2
  10. package/cjs/integrations/console.js +2 -13
  11. package/cjs/integrations/console.js.map +1 -1
  12. package/cjs/integrations/context.js +2 -16
  13. package/cjs/integrations/context.js.map +1 -1
  14. package/cjs/integrations/contextlines.js +6 -23
  15. package/cjs/integrations/contextlines.js.map +1 -1
  16. package/cjs/integrations/http.js +103 -354
  17. package/cjs/integrations/http.js.map +1 -1
  18. package/cjs/integrations/local-variables/index.js +0 -10
  19. package/cjs/integrations/local-variables/index.js.map +1 -1
  20. package/cjs/integrations/local-variables/local-variables-sync.js +31 -41
  21. package/cjs/integrations/local-variables/local-variables-sync.js.map +1 -1
  22. package/cjs/integrations/modules.js +19 -30
  23. package/cjs/integrations/modules.js.map +1 -1
  24. package/cjs/integrations/node-fetch.js +82 -0
  25. package/cjs/integrations/node-fetch.js.map +1 -0
  26. package/cjs/integrations/onuncaughtexception.js +15 -30
  27. package/cjs/integrations/onuncaughtexception.js.map +1 -1
  28. package/cjs/integrations/onunhandledrejection.js +3 -17
  29. package/cjs/integrations/onunhandledrejection.js.map +1 -1
  30. package/cjs/integrations/spotlight.js +4 -22
  31. package/cjs/integrations/spotlight.js.map +1 -1
  32. package/cjs/integrations/tracing/express.js +103 -0
  33. package/cjs/integrations/tracing/express.js.map +1 -0
  34. package/cjs/integrations/tracing/fastify.js +33 -0
  35. package/cjs/integrations/tracing/fastify.js.map +1 -0
  36. package/cjs/integrations/tracing/graphql.js +34 -0
  37. package/cjs/integrations/tracing/graphql.js.map +1 -0
  38. package/cjs/integrations/tracing/hapi/index.js +81 -0
  39. package/cjs/integrations/tracing/hapi/index.js.map +1 -0
  40. package/cjs/integrations/tracing/index.js +37 -0
  41. package/cjs/integrations/tracing/index.js.map +1 -0
  42. package/cjs/integrations/tracing/koa.js +21 -0
  43. package/cjs/integrations/tracing/koa.js.map +1 -0
  44. package/cjs/integrations/tracing/mongo.js +33 -0
  45. package/cjs/integrations/tracing/mongo.js.map +1 -0
  46. package/cjs/integrations/tracing/mongoose.js +33 -0
  47. package/cjs/integrations/tracing/mongoose.js.map +1 -0
  48. package/cjs/integrations/tracing/mysql.js +26 -0
  49. package/cjs/integrations/tracing/mysql.js.map +1 -0
  50. package/cjs/integrations/tracing/mysql2.js +33 -0
  51. package/cjs/integrations/tracing/mysql2.js.map +1 -0
  52. package/cjs/integrations/tracing/nest.js +26 -0
  53. package/cjs/integrations/tracing/nest.js.map +1 -0
  54. package/cjs/integrations/tracing/postgres.js +34 -0
  55. package/cjs/integrations/tracing/postgres.js.map +1 -0
  56. package/cjs/integrations/tracing/prisma.js +33 -0
  57. package/cjs/integrations/tracing/prisma.js.map +1 -0
  58. package/cjs/nodeVersion.js +5 -1
  59. package/cjs/nodeVersion.js.map +1 -1
  60. package/cjs/otel/contextManager.js +16 -0
  61. package/cjs/otel/contextManager.js.map +1 -0
  62. package/cjs/proxy/index.js +1 -2
  63. package/cjs/proxy/index.js.map +1 -1
  64. package/cjs/sdk/api.js +74 -0
  65. package/cjs/sdk/api.js.map +1 -0
  66. package/cjs/sdk/client.js +57 -0
  67. package/cjs/sdk/client.js.map +1 -0
  68. package/cjs/sdk/hub.js +104 -0
  69. package/cjs/sdk/hub.js.map +1 -0
  70. package/cjs/sdk/init.js +252 -0
  71. package/cjs/sdk/init.js.map +1 -0
  72. package/cjs/sdk/initOtel.js +70 -0
  73. package/cjs/sdk/initOtel.js.map +1 -0
  74. package/cjs/sdk/scope.js +18 -0
  75. package/cjs/sdk/scope.js.map +1 -0
  76. package/cjs/transports/http.js +2 -3
  77. package/cjs/transports/http.js.map +1 -1
  78. package/cjs/utils/addOriginToSpan.js +11 -0
  79. package/cjs/utils/addOriginToSpan.js.map +1 -0
  80. package/cjs/{integrations/utils → utils}/errorhandling.js +2 -1
  81. package/cjs/utils/errorhandling.js.map +1 -0
  82. package/cjs/utils/getRequestUrl.js +18 -0
  83. package/cjs/utils/getRequestUrl.js.map +1 -0
  84. package/cjs/utils/module.js.map +1 -0
  85. package/esm/cron/index.js +13 -0
  86. package/esm/cron/index.js.map +1 -0
  87. package/esm/index.js +28 -48
  88. package/esm/index.js.map +1 -1
  89. package/esm/integrations/anr/index.js +8 -34
  90. package/esm/integrations/anr/index.js.map +1 -1
  91. package/esm/integrations/anr/worker-script.js +2 -2
  92. package/esm/integrations/console.js +4 -14
  93. package/esm/integrations/console.js.map +1 -1
  94. package/esm/integrations/context.js +4 -17
  95. package/esm/integrations/context.js.map +1 -1
  96. package/esm/integrations/contextlines.js +8 -25
  97. package/esm/integrations/contextlines.js.map +1 -1
  98. package/esm/integrations/http.js +105 -353
  99. package/esm/integrations/http.js.map +1 -1
  100. package/esm/integrations/local-variables/index.js +2 -11
  101. package/esm/integrations/local-variables/index.js.map +1 -1
  102. package/esm/integrations/local-variables/local-variables-sync.js +32 -41
  103. package/esm/integrations/local-variables/local-variables-sync.js.map +1 -1
  104. package/esm/integrations/modules.js +21 -31
  105. package/esm/integrations/modules.js.map +1 -1
  106. package/esm/integrations/node-fetch.js +80 -0
  107. package/esm/integrations/node-fetch.js.map +1 -0
  108. package/esm/integrations/onuncaughtexception.js +17 -31
  109. package/esm/integrations/onuncaughtexception.js.map +1 -1
  110. package/esm/integrations/onunhandledrejection.js +5 -18
  111. package/esm/integrations/onunhandledrejection.js.map +1 -1
  112. package/esm/integrations/spotlight.js +3 -20
  113. package/esm/integrations/spotlight.js.map +1 -1
  114. package/esm/integrations/tracing/express.js +96 -0
  115. package/esm/integrations/tracing/express.js.map +1 -0
  116. package/esm/integrations/tracing/fastify.js +31 -0
  117. package/esm/integrations/tracing/fastify.js.map +1 -0
  118. package/esm/integrations/tracing/graphql.js +32 -0
  119. package/esm/integrations/tracing/graphql.js.map +1 -0
  120. package/esm/integrations/tracing/hapi/index.js +77 -0
  121. package/esm/integrations/tracing/hapi/index.js.map +1 -0
  122. package/esm/integrations/tracing/index.js +35 -0
  123. package/esm/integrations/tracing/index.js.map +1 -0
  124. package/esm/integrations/tracing/koa.js +19 -0
  125. package/esm/integrations/tracing/koa.js.map +1 -0
  126. package/esm/integrations/tracing/mongo.js +31 -0
  127. package/esm/integrations/tracing/mongo.js.map +1 -0
  128. package/esm/integrations/tracing/mongoose.js +31 -0
  129. package/esm/integrations/tracing/mongoose.js.map +1 -0
  130. package/esm/integrations/tracing/mysql.js +24 -0
  131. package/esm/integrations/tracing/mysql.js.map +1 -0
  132. package/esm/integrations/tracing/mysql2.js +31 -0
  133. package/esm/integrations/tracing/mysql2.js.map +1 -0
  134. package/esm/integrations/tracing/nest.js +24 -0
  135. package/esm/integrations/tracing/nest.js.map +1 -0
  136. package/esm/integrations/tracing/postgres.js +32 -0
  137. package/esm/integrations/tracing/postgres.js.map +1 -0
  138. package/esm/integrations/tracing/prisma.js +31 -0
  139. package/esm/integrations/tracing/prisma.js.map +1 -0
  140. package/esm/nodeVersion.js +5 -2
  141. package/esm/nodeVersion.js.map +1 -1
  142. package/esm/otel/contextManager.js +14 -0
  143. package/esm/otel/contextManager.js.map +1 -0
  144. package/esm/proxy/index.js +0 -1
  145. package/esm/proxy/index.js.map +1 -1
  146. package/esm/sdk/api.js +69 -0
  147. package/esm/sdk/api.js.map +1 -0
  148. package/esm/sdk/client.js +52 -0
  149. package/esm/sdk/client.js.map +1 -0
  150. package/esm/sdk/hub.js +102 -0
  151. package/esm/sdk/hub.js.map +1 -0
  152. package/esm/sdk/init.js +249 -0
  153. package/esm/sdk/init.js.map +1 -0
  154. package/esm/sdk/initOtel.js +67 -0
  155. package/esm/sdk/initOtel.js.map +1 -0
  156. package/esm/sdk/scope.js +16 -0
  157. package/esm/sdk/scope.js.map +1 -0
  158. package/esm/transports/http.js +0 -1
  159. package/esm/transports/http.js.map +1 -1
  160. package/esm/utils/addOriginToSpan.js +9 -0
  161. package/esm/utils/addOriginToSpan.js.map +1 -0
  162. package/esm/{integrations/utils → utils}/errorhandling.js +2 -1
  163. package/esm/utils/errorhandling.js.map +1 -0
  164. package/esm/utils/getRequestUrl.js +16 -0
  165. package/esm/utils/getRequestUrl.js.map +1 -0
  166. package/esm/utils/module.js.map +1 -0
  167. package/package.json +31 -23
  168. package/types/cron/index.d.ts +10 -0
  169. package/types/cron/index.d.ts.map +1 -0
  170. package/types/index.d.ts +30 -145
  171. package/types/index.d.ts.map +1 -1
  172. package/types/integrations/anr/index.d.ts +0 -15
  173. package/types/integrations/anr/index.d.ts.map +1 -1
  174. package/types/integrations/console.d.ts +2 -8
  175. package/types/integrations/console.d.ts.map +1 -1
  176. package/types/integrations/context.d.ts +3 -18
  177. package/types/integrations/context.d.ts.map +1 -1
  178. package/types/integrations/contextlines.d.ts +8 -10
  179. package/types/integrations/contextlines.d.ts.map +1 -1
  180. package/types/integrations/http.d.ts +8 -89
  181. package/types/integrations/http.d.ts.map +1 -1
  182. package/types/integrations/local-variables/common.d.ts +1 -0
  183. package/types/integrations/local-variables/common.d.ts.map +1 -1
  184. package/types/integrations/local-variables/index.d.ts +0 -11
  185. package/types/integrations/local-variables/index.d.ts.map +1 -1
  186. package/types/integrations/local-variables/local-variables-sync.d.ts +2 -1
  187. package/types/integrations/local-variables/local-variables-sync.d.ts.map +1 -1
  188. package/types/integrations/modules.d.ts +1 -7
  189. package/types/integrations/modules.d.ts.map +1 -1
  190. package/types/integrations/node-fetch.d.ts +15 -0
  191. package/types/integrations/node-fetch.d.ts.map +1 -0
  192. package/types/integrations/onuncaughtexception.d.ts +3 -12
  193. package/types/integrations/onuncaughtexception.d.ts.map +1 -1
  194. package/types/integrations/onunhandledrejection.d.ts +3 -10
  195. package/types/integrations/onunhandledrejection.d.ts.map +1 -1
  196. package/types/integrations/spotlight.d.ts +1 -10
  197. package/types/integrations/spotlight.d.ts.map +1 -1
  198. package/types/integrations/tracing/express.d.ts +37 -0
  199. package/types/integrations/tracing/express.d.ts.map +1 -0
  200. package/types/integrations/tracing/fastify.d.ts +7 -0
  201. package/types/integrations/tracing/fastify.d.ts.map +1 -0
  202. package/types/integrations/tracing/graphql.d.ts +7 -0
  203. package/types/integrations/tracing/graphql.d.ts.map +1 -0
  204. package/types/integrations/tracing/hapi/index.d.ts +18 -0
  205. package/types/integrations/tracing/hapi/index.d.ts.map +1 -0
  206. package/types/integrations/{hapi → tracing/hapi}/types.d.ts +1 -2
  207. package/types/integrations/tracing/hapi/types.d.ts.map +1 -0
  208. package/types/integrations/tracing/index.d.ts +6 -0
  209. package/types/integrations/tracing/index.d.ts.map +1 -0
  210. package/types/integrations/tracing/koa.d.ts +2 -0
  211. package/types/integrations/tracing/koa.d.ts.map +1 -0
  212. package/types/integrations/tracing/mongo.d.ts +7 -0
  213. package/types/integrations/tracing/mongo.d.ts.map +1 -0
  214. package/types/integrations/tracing/mongoose.d.ts +7 -0
  215. package/types/integrations/tracing/mongoose.d.ts.map +1 -0
  216. package/types/integrations/tracing/mysql.d.ts +7 -0
  217. package/types/integrations/tracing/mysql.d.ts.map +1 -0
  218. package/types/integrations/tracing/mysql2.d.ts +7 -0
  219. package/types/integrations/tracing/mysql2.d.ts.map +1 -0
  220. package/types/integrations/tracing/nest.d.ts +7 -0
  221. package/types/integrations/tracing/nest.d.ts.map +1 -0
  222. package/types/integrations/tracing/postgres.d.ts +7 -0
  223. package/types/integrations/tracing/postgres.d.ts.map +1 -0
  224. package/types/integrations/tracing/prisma.d.ts +11 -0
  225. package/types/integrations/tracing/prisma.d.ts.map +1 -0
  226. package/types/nodeVersion.d.ts +3 -3
  227. package/types/nodeVersion.d.ts.map +1 -1
  228. package/types/otel/contextManager.d.ts +10 -0
  229. package/types/otel/contextManager.d.ts.map +1 -0
  230. package/types/proxy/helpers.d.ts +0 -1
  231. package/types/proxy/helpers.d.ts.map +1 -1
  232. package/types/proxy/index.d.ts +0 -1
  233. package/types/proxy/index.d.ts.map +1 -1
  234. package/types/sdk/api.d.ts +18 -0
  235. package/types/sdk/api.d.ts.map +1 -0
  236. package/types/sdk/client.d.ts +17 -0
  237. package/types/sdk/client.d.ts.map +1 -0
  238. package/types/sdk/globals.d.ts +6 -0
  239. package/types/sdk/globals.d.ts.map +1 -0
  240. package/types/sdk/hub.d.ts +7 -0
  241. package/types/sdk/hub.d.ts.map +1 -0
  242. package/types/sdk/init.d.ts +9 -0
  243. package/types/sdk/init.d.ts.map +1 -0
  244. package/types/sdk/initOtel.d.ts +9 -0
  245. package/types/sdk/initOtel.d.ts.map +1 -0
  246. package/types/sdk/scope.d.ts +7 -0
  247. package/types/sdk/scope.d.ts.map +1 -0
  248. package/types/transports/http-module.d.ts +2 -5
  249. package/types/transports/http-module.d.ts.map +1 -1
  250. package/types/transports/http.d.ts.map +1 -1
  251. package/types/types.d.ts +25 -23
  252. package/types/types.d.ts.map +1 -1
  253. package/types/utils/addOriginToSpan.d.ts +5 -0
  254. package/types/utils/addOriginToSpan.d.ts.map +1 -0
  255. package/types/utils/errorhandling.d.ts.map +1 -0
  256. package/types/utils/getRequestUrl.d.ts +5 -0
  257. package/types/utils/getRequestUrl.d.ts.map +1 -0
  258. package/types/utils/module.d.ts.map +1 -0
  259. package/types/utils/prepareEvent.d.ts +17 -0
  260. package/types/utils/prepareEvent.d.ts.map +1 -0
  261. package/types-ts3.8/cron/index.d.ts +10 -0
  262. package/types-ts3.8/index.d.ts +30 -145
  263. package/types-ts3.8/integrations/anr/index.d.ts +0 -15
  264. package/types-ts3.8/integrations/console.d.ts +2 -8
  265. package/types-ts3.8/integrations/context.d.ts +3 -18
  266. package/types-ts3.8/integrations/contextlines.d.ts +8 -10
  267. package/types-ts3.8/integrations/http.d.ts +8 -89
  268. package/types-ts3.8/integrations/local-variables/common.d.ts +1 -0
  269. package/types-ts3.8/integrations/local-variables/index.d.ts +0 -11
  270. package/types-ts3.8/integrations/local-variables/local-variables-sync.d.ts +2 -1
  271. package/types-ts3.8/integrations/modules.d.ts +1 -7
  272. package/types-ts3.8/integrations/node-fetch.d.ts +15 -0
  273. package/types-ts3.8/integrations/onuncaughtexception.d.ts +3 -12
  274. package/types-ts3.8/integrations/onunhandledrejection.d.ts +3 -10
  275. package/types-ts3.8/integrations/spotlight.d.ts +1 -10
  276. package/types-ts3.8/integrations/tracing/express.d.ts +37 -0
  277. package/types-ts3.8/integrations/tracing/fastify.d.ts +7 -0
  278. package/types-ts3.8/integrations/tracing/graphql.d.ts +7 -0
  279. package/types-ts3.8/integrations/tracing/hapi/index.d.ts +18 -0
  280. package/types-ts3.8/integrations/{hapi → tracing/hapi}/types.d.ts +1 -2
  281. package/types-ts3.8/integrations/tracing/index.d.ts +6 -0
  282. package/types-ts3.8/integrations/tracing/koa.d.ts +2 -0
  283. package/types-ts3.8/integrations/tracing/mongo.d.ts +7 -0
  284. package/types-ts3.8/integrations/tracing/mongoose.d.ts +7 -0
  285. package/types-ts3.8/integrations/tracing/mysql.d.ts +7 -0
  286. package/types-ts3.8/integrations/tracing/mysql2.d.ts +7 -0
  287. package/types-ts3.8/integrations/tracing/nest.d.ts +7 -0
  288. package/types-ts3.8/integrations/tracing/postgres.d.ts +7 -0
  289. package/types-ts3.8/integrations/tracing/prisma.d.ts +11 -0
  290. package/types-ts3.8/nodeVersion.d.ts +3 -3
  291. package/types-ts3.8/otel/contextManager.d.ts +10 -0
  292. package/types-ts3.8/proxy/helpers.d.ts +0 -1
  293. package/types-ts3.8/proxy/index.d.ts +0 -1
  294. package/types-ts3.8/sdk/api.d.ts +18 -0
  295. package/types-ts3.8/sdk/client.d.ts +17 -0
  296. package/types-ts3.8/sdk/globals.d.ts +6 -0
  297. package/types-ts3.8/sdk/hub.d.ts +7 -0
  298. package/types-ts3.8/sdk/init.d.ts +9 -0
  299. package/types-ts3.8/sdk/initOtel.d.ts +9 -0
  300. package/types-ts3.8/sdk/scope.d.ts +7 -0
  301. package/types-ts3.8/transports/http-module.d.ts +2 -4
  302. package/types-ts3.8/types.d.ts +25 -23
  303. package/types-ts3.8/utils/addOriginToSpan.d.ts +5 -0
  304. package/types-ts3.8/utils/getRequestUrl.d.ts +5 -0
  305. package/types-ts3.8/utils/prepareEvent.d.ts +17 -0
  306. package/cjs/async/domain.js +0 -61
  307. package/cjs/async/domain.js.map +0 -1
  308. package/cjs/async/hooks.js +0 -50
  309. package/cjs/async/hooks.js.map +0 -1
  310. package/cjs/async/index.js +0 -22
  311. package/cjs/async/index.js.map +0 -1
  312. package/cjs/client.js +0 -39
  313. package/cjs/client.js.map +0 -1
  314. package/cjs/handlers.js +0 -340
  315. package/cjs/handlers.js.map +0 -1
  316. package/cjs/integrations/anr/legacy.js +0 -29
  317. package/cjs/integrations/anr/legacy.js.map +0 -1
  318. package/cjs/integrations/hapi/index.js +0 -161
  319. package/cjs/integrations/hapi/index.js.map +0 -1
  320. package/cjs/integrations/index.js +0 -32
  321. package/cjs/integrations/index.js.map +0 -1
  322. package/cjs/integrations/undici/index.js +0 -307
  323. package/cjs/integrations/undici/index.js.map +0 -1
  324. package/cjs/integrations/utils/errorhandling.js.map +0 -1
  325. package/cjs/integrations/utils/http.js +0 -225
  326. package/cjs/integrations/utils/http.js.map +0 -1
  327. package/cjs/module.js.map +0 -1
  328. package/cjs/requestDataDeprecated.js +0 -45
  329. package/cjs/requestDataDeprecated.js.map +0 -1
  330. package/cjs/sdk.js +0 -284
  331. package/cjs/sdk.js.map +0 -1
  332. package/cjs/tracing/index.js +0 -29
  333. package/cjs/tracing/index.js.map +0 -1
  334. package/cjs/tracing/integrations.js +0 -14
  335. package/cjs/tracing/integrations.js.map +0 -1
  336. package/cjs/utils.js +0 -45
  337. package/cjs/utils.js.map +0 -1
  338. package/esm/async/domain.js +0 -56
  339. package/esm/async/domain.js.map +0 -1
  340. package/esm/async/hooks.js +0 -45
  341. package/esm/async/hooks.js.map +0 -1
  342. package/esm/async/index.js +0 -20
  343. package/esm/async/index.js.map +0 -1
  344. package/esm/client.js +0 -37
  345. package/esm/client.js.map +0 -1
  346. package/esm/handlers.js +0 -330
  347. package/esm/handlers.js.map +0 -1
  348. package/esm/integrations/anr/legacy.js +0 -27
  349. package/esm/integrations/anr/legacy.js.map +0 -1
  350. package/esm/integrations/hapi/index.js +0 -156
  351. package/esm/integrations/hapi/index.js.map +0 -1
  352. package/esm/integrations/index.js +0 -16
  353. package/esm/integrations/index.js.map +0 -1
  354. package/esm/integrations/undici/index.js +0 -301
  355. package/esm/integrations/undici/index.js.map +0 -1
  356. package/esm/integrations/utils/errorhandling.js.map +0 -1
  357. package/esm/integrations/utils/http.js +0 -216
  358. package/esm/integrations/utils/http.js.map +0 -1
  359. package/esm/module.js.map +0 -1
  360. package/esm/requestDataDeprecated.js +0 -42
  361. package/esm/requestDataDeprecated.js.map +0 -1
  362. package/esm/sdk.js +0 -274
  363. package/esm/sdk.js.map +0 -1
  364. package/esm/tracing/index.js +0 -27
  365. package/esm/tracing/index.js.map +0 -1
  366. package/esm/tracing/integrations.js +0 -2
  367. package/esm/tracing/integrations.js.map +0 -1
  368. package/esm/utils.js +0 -43
  369. package/esm/utils.js.map +0 -1
  370. package/types/async/domain.d.ts +0 -5
  371. package/types/async/domain.d.ts.map +0 -1
  372. package/types/async/hooks.d.ts +0 -5
  373. package/types/async/hooks.d.ts.map +0 -1
  374. package/types/async/index.d.ts +0 -8
  375. package/types/async/index.d.ts.map +0 -1
  376. package/types/client.d.ts +0 -16
  377. package/types/client.d.ts.map +0 -1
  378. package/types/handlers.d.ts +0 -57
  379. package/types/handlers.d.ts.map +0 -1
  380. package/types/integrations/anr/legacy.d.ts +0 -22
  381. package/types/integrations/anr/legacy.d.ts.map +0 -1
  382. package/types/integrations/hapi/index.d.ts +0 -22
  383. package/types/integrations/hapi/index.d.ts.map +0 -1
  384. package/types/integrations/hapi/types.d.ts.map +0 -1
  385. package/types/integrations/index.d.ts +0 -14
  386. package/types/integrations/index.d.ts.map +0 -1
  387. package/types/integrations/local-variables/local-variables-async.d.ts +0 -14
  388. package/types/integrations/local-variables/local-variables-async.d.ts.map +0 -1
  389. package/types/integrations/undici/index.d.ts +0 -58
  390. package/types/integrations/undici/index.d.ts.map +0 -1
  391. package/types/integrations/undici/types.d.ts +0 -224
  392. package/types/integrations/undici/types.d.ts.map +0 -1
  393. package/types/integrations/utils/errorhandling.d.ts.map +0 -1
  394. package/types/integrations/utils/http.d.ts +0 -70
  395. package/types/integrations/utils/http.d.ts.map +0 -1
  396. package/types/module.d.ts.map +0 -1
  397. package/types/requestDataDeprecated.d.ts +0 -45
  398. package/types/requestDataDeprecated.d.ts.map +0 -1
  399. package/types/sdk.d.ts +0 -74
  400. package/types/sdk.d.ts.map +0 -1
  401. package/types/tracing/index.d.ts +0 -6
  402. package/types/tracing/index.d.ts.map +0 -1
  403. package/types/tracing/integrations.d.ts +0 -2
  404. package/types/tracing/integrations.d.ts.map +0 -1
  405. package/types/utils.d.ts +0 -10
  406. package/types/utils.d.ts.map +0 -1
  407. package/types-ts3.8/async/domain.d.ts +0 -5
  408. package/types-ts3.8/async/hooks.d.ts +0 -5
  409. package/types-ts3.8/async/index.d.ts +0 -8
  410. package/types-ts3.8/client.d.ts +0 -16
  411. package/types-ts3.8/handlers.d.ts +0 -57
  412. package/types-ts3.8/integrations/anr/legacy.d.ts +0 -22
  413. package/types-ts3.8/integrations/hapi/index.d.ts +0 -22
  414. package/types-ts3.8/integrations/index.d.ts +0 -14
  415. package/types-ts3.8/integrations/local-variables/local-variables-async.d.ts +0 -14
  416. package/types-ts3.8/integrations/undici/index.d.ts +0 -58
  417. package/types-ts3.8/integrations/undici/types.d.ts +0 -223
  418. package/types-ts3.8/integrations/utils/http.d.ts +0 -80
  419. package/types-ts3.8/requestDataDeprecated.d.ts +0 -45
  420. package/types-ts3.8/sdk.d.ts +0 -74
  421. package/types-ts3.8/tracing/index.d.ts +0 -6
  422. package/types-ts3.8/tracing/integrations.d.ts +0 -2
  423. package/types-ts3.8/utils.d.ts +0 -10
  424. /package/cjs/{module.js → utils/module.js} +0 -0
  425. /package/esm/{module.js → utils/module.js} +0 -0
  426. /package/types/{integrations/utils → utils}/errorhandling.d.ts +0 -0
  427. /package/types/{module.d.ts → utils/module.d.ts} +0 -0
  428. /package/types-ts3.8/{integrations/utils → utils}/errorhandling.d.ts +0 -0
  429. /package/types-ts3.8/{module.d.ts → utils/module.d.ts} +0 -0
@@ -1,2 +1,2 @@
1
- /*! @sentry/node 7.105.0 (e23dc27) | https://github.com/getsentry/sentry-javascript */
2
- export const base64WorkerScript="aW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJ2luc3BlY3Rvcic7CmltcG9ydCB7IHdvcmtlckRhdGEsIHBhcmVudFBvcnQgfSBmcm9tICd3b3JrZXJfdGhyZWFkcyc7CmltcG9ydCB7IHBvc2l4LCBzZXAgfSBmcm9tICdwYXRoJzsKaW1wb3J0ICogYXMgaHR0cCBmcm9tICdodHRwJzsKaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnOwppbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7CmltcG9ydCB7IFVSTCB9IGZyb20gJ3VybCc7CmltcG9ydCB7IGNyZWF0ZUd6aXAgfSBmcm9tICd6bGliJzsKaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnOwppbXBvcnQgKiBhcyBuZXQgZnJvbSAnbmV0JzsKaW1wb3J0ICogYXMgdGxzIGZyb20gJ3Rscyc7CgovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3VuYm91bmQtbWV0aG9kCmNvbnN0IG9iamVjdFRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgb25lIG9mIGEgZmV3IEVycm9yIG9yIEVycm9yLWxpa2UKICoge0BsaW5rIGlzRXJyb3J9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNFcnJvcih3YXQpIHsKICBzd2l0Y2ggKG9iamVjdFRvU3RyaW5nLmNhbGwod2F0KSkgewogICAgY2FzZSAnW29iamVjdCBFcnJvcl0nOgogICAgY2FzZSAnW29iamVjdCBFeGNlcHRpb25dJzoKICAgIGNhc2UgJ1tvYmplY3QgRE9NRXhjZXB0aW9uXSc6CiAgICAgIHJldHVybiB0cnVlOwogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuIGlzSW5zdGFuY2VPZih3YXQsIEVycm9yKTsKICB9Cn0KLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlIGlzIGFuIGluc3RhbmNlIG9mIHRoZSBnaXZlbiBidWlsdC1pbiBjbGFzcy4KICoKICogQHBhcmFtIHdhdCBUaGUgdmFsdWUgdG8gYmUgY2hlY2tlZAogKiBAcGFyYW0gY2xhc3NOYW1lCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzQnVpbHRpbih3YXQsIGNsYXNzTmFtZSkgewogIHJldHVybiBvYmplY3RUb1N0cmluZy5jYWxsKHdhdCkgPT09IGBbb2JqZWN0ICR7Y2xhc3NOYW1lfV1gOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGEgc3RyaW5nCiAqIHtAbGluayBpc1N0cmluZ30uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc1N0cmluZyh3YXQpIHsKICByZXR1cm4gaXNCdWlsdGluKHdhdCwgJ1N0cmluZycpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIG9iamVjdCBsaXRlcmFsLCBvciBhIGNsYXNzIGluc3RhbmNlLgogKiB7QGxpbmsgaXNQbGFpbk9iamVjdH0uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc1BsYWluT2JqZWN0KHdhdCkgewogIHJldHVybiBpc0J1aWx0aW4od2F0LCAnT2JqZWN0Jyk7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgYW4gRXZlbnQgaW5zdGFuY2UKICoge0BsaW5rIGlzRXZlbnR9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNFdmVudCh3YXQpIHsKICByZXR1cm4gdHlwZW9mIEV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2Yod2F0LCBFdmVudCk7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgYW4gRWxlbWVudCBpbnN0YW5jZQogKiB7QGxpbmsgaXNFbGVtZW50fS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzRWxlbWVudCh3YXQpIHsKICByZXR1cm4gdHlwZW9mIEVsZW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGlzSW5zdGFuY2VPZih3YXQsIEVsZW1lbnQpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUgaGFzIGEgdGhlbiBmdW5jdGlvbi4KICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqLwpmdW5jdGlvbiBpc1RoZW5hYmxlKHdhdCkgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MKICByZXR1cm4gQm9vbGVhbih3YXQgJiYgd2F0LnRoZW4gJiYgdHlwZW9mIHdhdC50aGVuID09PSAnZnVuY3Rpb24nKTsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlJ3MgdHlwZSBpcyBhIFN5bnRoZXRpY0V2ZW50CiAqIHtAbGluayBpc1N5bnRoZXRpY0V2ZW50fS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzU3ludGhldGljRXZlbnQod2F0KSB7CiAgcmV0dXJuIGlzUGxhaW5PYmplY3Qod2F0KSAmJiAnbmF0aXZlRXZlbnQnIGluIHdhdCAmJiAncHJldmVudERlZmF1bHQnIGluIHdhdCAmJiAnc3RvcFByb3BhZ2F0aW9uJyBpbiB3YXQ7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSBpcyBOYU4KICoge0BsaW5rIGlzTmFOfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzTmFOJDEod2F0KSB7CiAgcmV0dXJuIHR5cGVvZiB3YXQgPT09ICdudW1iZXInICYmIHdhdCAhPT0gd2F0Owp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIGluc3RhbmNlIG9mIHByb3ZpZGVkIGNvbnN0cnVjdG9yLgogKiB7QGxpbmsgaXNJbnN0YW5jZU9mfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEBwYXJhbSBiYXNlIEEgY29uc3RydWN0b3IgdG8gYmUgdXNlZCBpbiBhIGNoZWNrLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc0luc3RhbmNlT2Yod2F0LCBiYXNlKSB7CiAgdHJ5IHsKICAgIHJldHVybiB3YXQgaW5zdGFuY2VvZiBiYXNlOwogIH0gY2F0Y2ggKF9lKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGEgVnVlIFZpZXdNb2RlbC4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzVnVlVmlld01vZGVsKHdhdCkgewogIC8vIE5vdCB1c2luZyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIGJlY2F1c2UgaW4gVnVlIDMgaXQgd291bGQgcmVhZCB0aGUgaW5zdGFuY2UncyBTeW1ib2woU3ltYm9sLnRvU3RyaW5nVGFnKSBwcm9wZXJ0eS4KICByZXR1cm4gISEodHlwZW9mIHdhdCA9PT0gJ29iamVjdCcgJiYgd2F0ICE9PSBudWxsICYmICgod2F0ICkuX19pc1Z1ZSB8fCAod2F0ICkuX2lzVnVlKSk7Cn0KCi8qKiBJbnRlcm5hbCBnbG9iYWwgd2l0aCBjb21tb24gcHJvcGVydGllcyBhbmQgU2VudHJ5IGV4dGVuc2lvbnMgICovCgovLyBUaGUgY29kZSBiZWxvdyBmb3IgJ2lzR2xvYmFsT2JqJyBhbmQgJ0dMT0JBTF9PQkonIHdhcyBjb3BpZWQgZnJvbSBjb3JlLWpzIGJlZm9yZSBtb2RpZmljYXRpb24KLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvYmxvYi8xYjk0NGRmNTUyODJjZGM5OWM5MGRiNWY0OWViMGI2ZWRhMmNjMGEzL3BhY2thZ2VzL2NvcmUtanMvaW50ZXJuYWxzL2dsb2JhbC5qcwovLyBjb3JlLWpzIGhhcyB0aGUgZm9sbG93aW5nIGxpY2VuY2U6Ci8vCi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDIyIERlbmlzIFB1c2hrYXJldgovLwovLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5Ci8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0byBkZWFsCi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMKLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbAovLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKLy8KLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4KLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCi8vCi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAovLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUKLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgovLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLAovLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOCi8vIFRIRSBTT0ZUV0FSRS4KCi8qKiBSZXR1cm5zICdvYmonIGlmIGl0J3MgdGhlIGdsb2JhbCBvYmplY3QsIG90aGVyd2lzZSByZXR1cm5zIHVuZGVmaW5lZCAqLwpmdW5jdGlvbiBpc0dsb2JhbE9iaihvYmopIHsKICByZXR1cm4gb2JqICYmIG9iai5NYXRoID09IE1hdGggPyBvYmogOiB1bmRlZmluZWQ7Cn0KCi8qKiBHZXQncyB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgdGhlIGN1cnJlbnQgSmF2YVNjcmlwdCBydW50aW1lICovCmNvbnN0IEdMT0JBTF9PQkogPQogICh0eXBlb2YgZ2xvYmFsVGhpcyA9PSAnb2JqZWN0JyAmJiBpc0dsb2JhbE9iaihnbG9iYWxUaGlzKSkgfHwKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzCiAgKHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmood2luZG93KSkgfHwKICAodHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmooc2VsZikpIHx8CiAgKHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmooZ2xvYmFsKSkgfHwKICAoZnVuY3Rpb24gKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfSkoKSB8fAogIHt9OwoKLyoqCiAqIEBkZXByZWNhdGVkIFVzZSBHTE9CQUxfT0JKIGluc3RlYWQgb3IgV0lORE9XIGZyb20gQHNlbnRyeS9icm93c2VyLiBUaGlzIHdpbGwgYmUgcmVtb3ZlZCBpbiB2OAogKi8KZnVuY3Rpb24gZ2V0R2xvYmFsT2JqZWN0KCkgewogIHJldHVybiBHTE9CQUxfT0JKIDsKfQoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCmNvbnN0IFdJTkRPVyA9IGdldEdsb2JhbE9iamVjdCgpOwoKY29uc3QgREVGQVVMVF9NQVhfU1RSSU5HX0xFTkdUSCA9IDgwOwoKLyoqCiAqIEdpdmVuIGEgY2hpbGQgRE9NIGVsZW1lbnQsIHJldHVybnMgYSBxdWVyeS1zZWxlY3RvciBzdGF0ZW1lbnQgZGVzY3JpYmluZyB0aGF0CiAqIGFuZCBpdHMgYW5jZXN0b3JzCiAqIGUuZy4gW0hUTUxFbGVtZW50XSA9PiBib2R5ID4gZGl2ID4gaW5wdXQjZm9vLmJ0bltuYW1lPWJhel0KICogQHJldHVybnMgZ2VuZXJhdGVkIERPTSBwYXRoCiAqLwpmdW5jdGlvbiBodG1sVHJlZUFzU3RyaW5nKAogIGVsZW0sCiAgb3B0aW9ucyA9IHt9LAopIHsKICBpZiAoIWVsZW0pIHsKICAgIHJldHVybiAnPHVua25vd24+JzsKICB9CgogIC8vIHRyeS9jYXRjaCBib3RoOgogIC8vIC0gYWNjZXNzaW5nIGV2ZW50LnRhcmdldCAoc2VlIGdldHNlbnRyeS9yYXZlbi1qcyM4MzgsICM3NjgpCiAgLy8gLSBgaHRtbFRyZWVBc1N0cmluZ2AgYmVjYXVzZSBpdCdzIGNvbXBsZXgsIGFuZCBqdXN0IGFjY2Vzc2luZyB0aGUgRE9NIGluY29ycmVjdGx5CiAgLy8gLSBjYW4gdGhyb3cgYW4gZXhjZXB0aW9uIGluIHNvbWUgY2lyY3Vtc3RhbmNlcy4KICB0cnkgewogICAgbGV0IGN1cnJlbnRFbGVtID0gZWxlbSA7CiAgICBjb25zdCBNQVhfVFJBVkVSU0VfSEVJR0hUID0gNTsKICAgIGNvbnN0IG91dCA9IFtdOwogICAgbGV0IGhlaWdodCA9IDA7CiAgICBsZXQgbGVuID0gMDsKICAgIGNvbnN0IHNlcGFyYXRvciA9ICcgPiAnOwogICAgY29uc3Qgc2VwTGVuZ3RoID0gc2VwYXJhdG9yLmxlbmd0aDsKICAgIGxldCBuZXh0U3RyOwogICAgY29uc3Qga2V5QXR0cnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMpID8gb3B0aW9ucyA6IG9wdGlvbnMua2V5QXR0cnM7CiAgICBjb25zdCBtYXhTdHJpbmdMZW5ndGggPSAoIUFycmF5LmlzQXJyYXkob3B0aW9ucykgJiYgb3B0aW9ucy5tYXhTdHJpbmdMZW5ndGgpIHx8IERFRkFVTFRfTUFYX1NUUklOR19MRU5HVEg7CgogICAgd2hpbGUgKGN1cnJlbnRFbGVtICYmIGhlaWdodCsrIDwgTUFYX1RSQVZFUlNFX0hFSUdIVCkgewogICAgICBuZXh0U3RyID0gX2h0bWxFbGVtZW50QXNTdHJpbmcoY3VycmVudEVsZW0sIGtleUF0dHJzKTsKICAgICAgLy8gYmFpbCBvdXQgaWYKICAgICAgLy8gLSBuZXh0U3RyIGlzIHRoZSAnaHRtbCcgZWxlbWVudAogICAgICAvLyAtIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZyB0aGF0IHdvdWxkIGJlIGNyZWF0ZWQgZXhjZWVkcyBtYXhTdHJpbmdMZW5ndGgKICAgICAgLy8gICAoaWdub3JlIHRoaXMgbGltaXQgaWYgd2UgYXJlIG9uIHRoZSBmaXJzdCBpdGVyYXRpb24pCiAgICAgIGlmIChuZXh0U3RyID09PSAnaHRtbCcgfHwgKGhlaWdodCA+IDEgJiYgbGVuICsgb3V0Lmxlbmd0aCAqIHNlcExlbmd0aCArIG5leHRTdHIubGVuZ3RoID49IG1heFN0cmluZ0xlbmd0aCkpIHsKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgb3V0LnB1c2gobmV4dFN0cik7CgogICAgICBsZW4gKz0gbmV4dFN0ci5sZW5ndGg7CiAgICAgIGN1cnJlbnRFbGVtID0gY3VycmVudEVsZW0ucGFyZW50Tm9kZTsKICAgIH0KCiAgICByZXR1cm4gb3V0LnJldmVyc2UoKS5qb2luKHNlcGFyYXRvcik7CiAgfSBjYXRjaCAoX29PKSB7CiAgICByZXR1cm4gJzx1bmtub3duPic7CiAgfQp9CgovKioKICogUmV0dXJucyBhIHNpbXBsZSwgcXVlcnktc2VsZWN0b3IgcmVwcmVzZW50YXRpb24gb2YgYSBET00gZWxlbWVudAogKiBlLmcuIFtIVE1MRWxlbWVudF0gPT4gaW5wdXQjZm9vLmJ0bltuYW1lPWJhel0KICogQHJldHVybnMgZ2VuZXJhdGVkIERPTSBwYXRoCiAqLwpmdW5jdGlvbiBfaHRtbEVsZW1lbnRBc1N0cmluZyhlbCwga2V5QXR0cnMpIHsKICBjb25zdCBlbGVtID0gZWwKCjsKCiAgY29uc3Qgb3V0ID0gW107CiAgbGV0IGNsYXNzTmFtZTsKICBsZXQgY2xhc3NlczsKICBsZXQga2V5OwogIGxldCBhdHRyOwogIGxldCBpOwoKICBpZiAoIWVsZW0gfHwgIWVsZW0udGFnTmFtZSkgewogICAgcmV0dXJuICcnOwogIH0KCiAgLy8gQHRzLWV4cGVjdC1lcnJvciBXSU5ET1cgaGFzIEhUTUxFbGVtZW50CiAgaWYgKFdJTkRPVy5IVE1MRWxlbWVudCkgewogICAgLy8gSWYgdXNpbmcgdGhlIGNvbXBvbmVudCBuYW1lIGFubm90YXRpb24gcGx1Z2luLCB0aGlzIHZhbHVlIG1heSBiZSBhdmFpbGFibGUgb24gdGhlIERPTSBub2RlCiAgICBpZiAoZWxlbSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ICYmIGVsZW0uZGF0YXNldCAmJiBlbGVtLmRhdGFzZXRbJ3NlbnRyeUNvbXBvbmVudCddKSB7CiAgICAgIHJldHVybiBlbGVtLmRhdGFzZXRbJ3NlbnRyeUNvbXBvbmVudCddOwogICAgfQogIH0KCiAgb3V0LnB1c2goZWxlbS50YWdOYW1lLnRvTG93ZXJDYXNlKCkpOwoKICAvLyBQYWlycyBvZiBhdHRyaWJ1dGUga2V5cyBkZWZpbmVkIGluIGBzZXJpYWxpemVBdHRyaWJ1dGVgIGFuZCB0aGVpciB2YWx1ZXMgb24gZWxlbWVudC4KICBjb25zdCBrZXlBdHRyUGFpcnMgPQogICAga2V5QXR0cnMgJiYga2V5QXR0cnMubGVuZ3RoCiAgICAgID8ga2V5QXR0cnMuZmlsdGVyKGtleUF0dHIgPT4gZWxlbS5nZXRBdHRyaWJ1dGUoa2V5QXR0cikpLm1hcChrZXlBdHRyID0+IFtrZXlBdHRyLCBlbGVtLmdldEF0dHJpYnV0ZShrZXlBdHRyKV0pCiAgICAgIDogbnVsbDsKCiAgaWYgKGtleUF0dHJQYWlycyAmJiBrZXlBdHRyUGFpcnMubGVuZ3RoKSB7CiAgICBrZXlBdHRyUGFpcnMuZm9yRWFjaChrZXlBdHRyUGFpciA9PiB7CiAgICAgIG91dC5wdXNoKGBbJHtrZXlBdHRyUGFpclswXX09IiR7a2V5QXR0clBhaXJbMV19Il1gKTsKICAgIH0pOwogIH0gZWxzZSB7CiAgICBpZiAoZWxlbS5pZCkgewogICAgICBvdXQucHVzaChgIyR7ZWxlbS5pZH1gKTsKICAgIH0KCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0CiAgICBjbGFzc05hbWUgPSBlbGVtLmNsYXNzTmFtZTsKICAgIGlmIChjbGFzc05hbWUgJiYgaXNTdHJpbmcoY2xhc3NOYW1lKSkgewogICAgICBjbGFzc2VzID0gY2xhc3NOYW1lLnNwbGl0KC9ccysvKTsKICAgICAgZm9yIChpID0gMDsgaSA8IGNsYXNzZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBvdXQucHVzaChgLiR7Y2xhc3Nlc1tpXX1gKTsKICAgICAgfQogICAgfQogIH0KICBjb25zdCBhbGxvd2VkQXR0cnMgPSBbJ2FyaWEtbGFiZWwnLCAndHlwZScsICduYW1lJywgJ3RpdGxlJywgJ2FsdCddOwogIGZvciAoaSA9IDA7IGkgPCBhbGxvd2VkQXR0cnMubGVuZ3RoOyBpKyspIHsKICAgIGtleSA9IGFsbG93ZWRBdHRyc1tpXTsKICAgIGF0dHIgPSBlbGVtLmdldEF0dHJpYnV0ZShrZXkpOwogICAgaWYgKGF0dHIpIHsKICAgICAgb3V0LnB1c2goYFske2tleX09IiR7YXR0cn0iXWApOwogICAgfQogIH0KICByZXR1cm4gb3V0LmpvaW4oJycpOwp9CgovKioKICogVGhpcyBzZXJ2ZXMgYXMgYSBidWlsZCB0aW1lIGZsYWcgdGhhdCB3aWxsIGJlIHRydWUgYnkgZGVmYXVsdCwgYnV0IGZhbHNlIGluIG5vbi1kZWJ1ZyBidWlsZHMgb3IgaWYgdXNlcnMgcmVwbGFjZSBgX19TRU5UUllfREVCVUdfX2AgaW4gdGhlaXIgZ2VuZXJhdGVkIGNvZGUuCiAqCiAqIEFUVEVOVElPTjogVGhpcyBjb25zdGFudCBtdXN0IG5ldmVyIGNyb3NzIHBhY2thZ2UgYm91bmRhcmllcyAoaS5lLiBiZSBleHBvcnRlZCkgdG8gZ3VhcmFudGVlIHRoYXQgaXQgY2FuIGJlIHVzZWQgZm9yIHRyZWUgc2hha2luZy4KICovCmNvbnN0IERFQlVHX0JVSUxEJDEgPSAodHlwZW9mIF9fU0VOVFJZX0RFQlVHX18gPT09ICd1bmRlZmluZWQnIHx8IF9fU0VOVFJZX0RFQlVHX18pOwoKLyoqIFByZWZpeCBmb3IgbG9nZ2luZyBzdHJpbmdzICovCmNvbnN0IFBSRUZJWCA9ICdTZW50cnkgTG9nZ2VyICc7Cgpjb25zdCBDT05TT0xFX0xFVkVMUyA9IFsKICAnZGVidWcnLAogICdpbmZvJywKICAnd2FybicsCiAgJ2Vycm9yJywKICAnbG9nJywKICAnYXNzZXJ0JywKICAndHJhY2UnLApdIDsKCi8qKiBUaGlzIG1heSBiZSBtdXRhdGVkIGJ5IHRoZSBjb25zb2xlIGluc3RydW1lbnRhdGlvbi4gKi8KY29uc3Qgb3JpZ2luYWxDb25zb2xlTWV0aG9kcwoKID0ge307CgovKiogSlNEb2MgKi8KCi8qKgogKiBUZW1wb3JhcmlseSBkaXNhYmxlIHNlbnRyeSBjb25zb2xlIGluc3RydW1lbnRhdGlvbnMuCiAqCiAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gcnVuIGFnYWluc3QgdGhlIG9yaWdpbmFsIGBjb25zb2xlYCBtZXNzYWdlcwogKiBAcmV0dXJucyBUaGUgcmVzdWx0cyBvZiB0aGUgY2FsbGJhY2sKICovCmZ1bmN0aW9uIGNvbnNvbGVTYW5kYm94KGNhbGxiYWNrKSB7CiAgaWYgKCEoJ2NvbnNvbGUnIGluIEdMT0JBTF9PQkopKSB7CiAgICByZXR1cm4gY2FsbGJhY2soKTsKICB9CgogIGNvbnN0IGNvbnNvbGUgPSBHTE9CQUxfT0JKLmNvbnNvbGUgOwogIGNvbnN0IHdyYXBwZWRGdW5jcyA9IHt9OwoKICBjb25zdCB3cmFwcGVkTGV2ZWxzID0gT2JqZWN0LmtleXMob3JpZ2luYWxDb25zb2xlTWV0aG9kcykgOwoKICAvLyBSZXN0b3JlIGFsbCB3cmFwcGVkIGNvbnNvbGUgbWV0aG9kcwogIHdyYXBwZWRMZXZlbHMuZm9yRWFjaChsZXZlbCA9PiB7CiAgICBjb25zdCBvcmlnaW5hbENvbnNvbGVNZXRob2QgPSBvcmlnaW5hbENvbnNvbGVNZXRob2RzW2xldmVsXSA7CiAgICB3cmFwcGVkRnVuY3NbbGV2ZWxdID0gY29uc29sZVtsZXZlbF0gOwogICAgY29uc29sZVtsZXZlbF0gPSBvcmlnaW5hbENvbnNvbGVNZXRob2Q7CiAgfSk7CgogIHRyeSB7CiAgICByZXR1cm4gY2FsbGJhY2soKTsKICB9IGZpbmFsbHkgewogICAgLy8gUmV2ZXJ0IHJlc3RvcmF0aW9uIHRvIHdyYXBwZWQgc3RhdGUKICAgIHdyYXBwZWRMZXZlbHMuZm9yRWFjaChsZXZlbCA9PiB7CiAgICAgIGNvbnNvbGVbbGV2ZWxdID0gd3JhcHBlZEZ1bmNzW2xldmVsXSA7CiAgICB9KTsKICB9Cn0KCmZ1bmN0aW9uIG1ha2VMb2dnZXIoKSB7CiAgbGV0IGVuYWJsZWQgPSBmYWxzZTsKICBjb25zdCBsb2dnZXIgPSB7CiAgICBlbmFibGU6ICgpID0+IHsKICAgICAgZW5hYmxlZCA9IHRydWU7CiAgICB9LAogICAgZGlzYWJsZTogKCkgPT4gewogICAgICBlbmFibGVkID0gZmFsc2U7CiAgICB9LAogICAgaXNFbmFibGVkOiAoKSA9PiBlbmFibGVkLAogIH07CgogIGlmIChERUJVR19CVUlMRCQxKSB7CiAgICBDT05TT0xFX0xFVkVMUy5mb3JFYWNoKG5hbWUgPT4gewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQogICAgICBsb2dnZXJbbmFtZV0gPSAoLi4uYXJncykgPT4gewogICAgICAgIGlmIChlbmFibGVkKSB7CiAgICAgICAgICBjb25zb2xlU2FuZGJveCgoKSA9PiB7CiAgICAgICAgICAgIEdMT0JBTF9PQkouY29uc29sZVtuYW1lXShgJHtQUkVGSVh9WyR7bmFtZX1dOmAsIC4uLmFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9OwogICAgfSk7CiAgfSBlbHNlIHsKICAgIENPTlNPTEVfTEVWRUxTLmZvckVhY2gobmFtZSA9PiB7CiAgICAgIGxvZ2dlcltuYW1lXSA9ICgpID0+IHVuZGVmaW5lZDsKICAgIH0pOwogIH0KCiAgcmV0dXJuIGxvZ2dlciA7Cn0KCmNvbnN0IGxvZ2dlciA9IG1ha2VMb2dnZXIoKTsKCi8qKgogKiBSZW5kZXJzIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEc24uCiAqCiAqIEJ5IGRlZmF1bHQsIHRoaXMgd2lsbCByZW5kZXIgdGhlIHB1YmxpYyByZXByZXNlbnRhdGlvbiB3aXRob3V0IHRoZSBwYXNzd29yZAogKiBjb21wb25lbnQuIFRvIGdldCB0aGUgZGVwcmVjYXRlZCBwcml2YXRlIHJlcHJlc2VudGF0aW9uLCBzZXQgYHdpdGhQYXNzd29yZGAKICogdG8gdHJ1ZS4KICoKICogQHBhcmFtIHdpdGhQYXNzd29yZCBXaGVuIHNldCB0byB0cnVlLCB0aGUgcGFzc3dvcmQgd2lsbCBiZSBpbmNsdWRlZC4KICovCmZ1bmN0aW9uIGRzblRvU3RyaW5nKGRzbiwgd2l0aFBhc3N3b3JkID0gZmFsc2UpIHsKICBjb25zdCB7IGhvc3QsIHBhdGgsIHBhc3MsIHBvcnQsIHByb2plY3RJZCwgcHJvdG9jb2wsIHB1YmxpY0tleSB9ID0gZHNuOwogIHJldHVybiAoCiAgICBgJHtwcm90b2NvbH06Ly8ke3B1YmxpY0tleX0ke3dpdGhQYXNzd29yZCAmJiBwYXNzID8gYDoke3Bhc3N9YCA6ICcnfWAgKwogICAgYEAke2hvc3R9JHtwb3J0ID8gYDoke3BvcnR9YCA6ICcnfS8ke3BhdGggPyBgJHtwYXRofS9gIDogcGF0aH0ke3Byb2plY3RJZH1gCiAgKTsKfQoKLyoqIEFuIGVycm9yIGVtaXR0ZWQgYnkgU2VudHJ5IFNES3MgYW5kIHJlbGF0ZWQgdXRpbGl0aWVzLiAqLwpjbGFzcyBTZW50cnlFcnJvciBleHRlbmRzIEVycm9yIHsKICAvKiogRGlzcGxheSBuYW1lIG9mIHRoaXMgZXJyb3IgaW5zdGFuY2UuICovCgogICBjb25zdHJ1Y3RvciggbWVzc2FnZSwgbG9nTGV2ZWwgPSAnd2FybicpIHsKICAgIHN1cGVyKG1lc3NhZ2UpO3RoaXMubWVzc2FnZSA9IG1lc3NhZ2U7CiAgICB0aGlzLm5hbWUgPSBuZXcudGFyZ2V0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5uYW1lOwogICAgLy8gVGhpcyBzZXRzIHRoZSBwcm90b3R5cGUgdG8gYmUgYEVycm9yYCwgbm90IGBTZW50cnlFcnJvcmAuIEl0J3MgdW5jbGVhciB3aHkgd2UgZG8gdGhpcywgYnV0IGNvbW1lbnRpbmcgdGhpcyBsaW5lCiAgICAvLyBvdXQgY2F1c2VzIHZhcmlvdXMgKHNlZW1pbmdseSB0b3RhbGx5IHVucmVsYXRlZCkgcGxheXdyaWdodCB0ZXN0cyBjb25zaXN0ZW50bHkgdGltZSBvdXQuIEZZSSwgdGhpcyBtYWtlcwogICAgLy8gaW5zdGFuY2VzIG9mIGBTZW50cnlFcnJvcmAgZmFpbCBgb2JqIGluc3RhbmNlb2YgU2VudHJ5RXJyb3JgIGNoZWNrcy4KICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBuZXcudGFyZ2V0LnByb3RvdHlwZSk7CiAgICB0aGlzLmxvZ0xldmVsID0gbG9nTGV2ZWw7CiAgfQp9CgovKioKICogRW5jb2RlcyBnaXZlbiBvYmplY3QgaW50byB1cmwtZnJpZW5kbHkgZm9ybWF0CiAqCiAqIEBwYXJhbSBvYmplY3QgQW4gb2JqZWN0IHRoYXQgY29udGFpbnMgc2VyaWFsaXphYmxlIHZhbHVlcwogKiBAcmV0dXJucyBzdHJpbmcgRW5jb2RlZAogKi8KZnVuY3Rpb24gdXJsRW5jb2RlKG9iamVjdCkgewogIHJldHVybiBPYmplY3Qua2V5cyhvYmplY3QpCiAgICAubWFwKGtleSA9PiBgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQob2JqZWN0W2tleV0pfWApCiAgICAuam9pbignJicpOwp9CgovKioKICogVHJhbnNmb3JtcyBhbnkgYEVycm9yYCBvciBgRXZlbnRgIGludG8gYSBwbGFpbiBvYmplY3Qgd2l0aCBhbGwgb2YgdGhlaXIgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLCBhbmQgc29tZSBvZiB0aGVpcgogKiBub24tZW51bWVyYWJsZSBwcm9wZXJ0aWVzIGF0dGFjaGVkLgogKgogKiBAcGFyYW0gdmFsdWUgSW5pdGlhbCBzb3VyY2UgdGhhdCB3ZSBoYXZlIHRvIHRyYW5zZm9ybSBpbiBvcmRlciBmb3IgaXQgdG8gYmUgdXNhYmxlIGJ5IHRoZSBzZXJpYWxpemVyCiAqIEByZXR1cm5zIEFuIEV2ZW50IG9yIEVycm9yIHR1cm5lZCBpbnRvIGFuIG9iamVjdCAtIG9yIHRoZSB2YWx1ZSBhcmd1cm1lbnQgaXRzZWxmLCB3aGVuIHZhbHVlIGlzIG5laXRoZXIgYW4gRXZlbnQgbm9yCiAqICBhbiBFcnJvci4KICovCmZ1bmN0aW9uIGNvbnZlcnRUb1BsYWluT2JqZWN0KAogIHZhbHVlLAopCgogewogIGlmIChpc0Vycm9yKHZhbHVlKSkgewogICAgcmV0dXJuIHsKICAgICAgbWVzc2FnZTogdmFsdWUubWVzc2FnZSwKICAgICAgbmFtZTogdmFsdWUubmFtZSwKICAgICAgc3RhY2s6IHZhbHVlLnN0YWNrLAogICAgICAuLi5nZXRPd25Qcm9wZXJ0aWVzKHZhbHVlKSwKICAgIH07CiAgfSBlbHNlIGlmIChpc0V2ZW50KHZhbHVlKSkgewogICAgY29uc3QgbmV3T2JqCgogPSB7CiAgICAgIHR5cGU6IHZhbHVlLnR5cGUsCiAgICAgIHRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUudGFyZ2V0KSwKICAgICAgY3VycmVudFRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUuY3VycmVudFRhcmdldCksCiAgICAgIC4uLmdldE93blByb3BlcnRpZXModmFsdWUpLAogICAgfTsKCiAgICBpZiAodHlwZW9mIEN1c3RvbUV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2YodmFsdWUsIEN1c3RvbUV2ZW50KSkgewogICAgICBuZXdPYmouZGV0YWlsID0gdmFsdWUuZGV0YWlsOwogICAgfQoKICAgIHJldHVybiBuZXdPYmo7CiAgfSBlbHNlIHsKICAgIHJldHVybiB2YWx1ZTsKICB9Cn0KCi8qKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0YXJnZXQgb2YgYW4gYEV2ZW50YCBvYmplY3QgKi8KZnVuY3Rpb24gc2VyaWFsaXplRXZlbnRUYXJnZXQodGFyZ2V0KSB7CiAgdHJ5IHsKICAgIHJldHVybiBpc0VsZW1lbnQodGFyZ2V0KSA/IGh0bWxUcmVlQXNTdHJpbmcodGFyZ2V0KSA6IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0YXJnZXQpOwogIH0gY2F0Y2ggKF9vTykgewogICAgcmV0dXJuICc8dW5rbm93bj4nOwogIH0KfQoKLyoqIEZpbHRlcnMgb3V0IGFsbCBidXQgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMgKi8KZnVuY3Rpb24gZ2V0T3duUHJvcGVydGllcyhvYmopIHsKICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSB7CiAgICBjb25zdCBleHRyYWN0ZWRQcm9wcyA9IHt9OwogICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiBvYmopIHsKICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3BlcnR5KSkgewogICAgICAgIGV4dHJhY3RlZFByb3BzW3Byb3BlcnR5XSA9IChvYmogKVtwcm9wZXJ0eV07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBleHRyYWN0ZWRQcm9wczsKICB9IGVsc2UgewogICAgcmV0dXJuIHt9OwogIH0KfQoKLyoqCiAqIEdpdmVuIGFueSBvYmplY3QsIHJldHVybiBhIG5ldyBvYmplY3QgaGF2aW5nIHJlbW92ZWQgYWxsIGZpZWxkcyB3aG9zZSB2YWx1ZSB3YXMgYHVuZGVmaW5lZGAuCiAqIFdvcmtzIHJlY3Vyc2l2ZWx5IG9uIG9iamVjdHMgYW5kIGFycmF5cy4KICoKICogQXR0ZW50aW9uOiBUaGlzIGZ1bmN0aW9uIGtlZXBzIGNpcmN1bGFyIHJlZmVyZW5jZXMgaW4gdGhlIHJldHVybmVkIG9iamVjdC4KICovCmZ1bmN0aW9uIGRyb3BVbmRlZmluZWRLZXlzKGlucHV0VmFsdWUpIHsKICAvLyBUaGlzIG1hcCBrZWVwcyB0cmFjayBvZiB3aGF0IGFscmVhZHkgdmlzaXRlZCBub2RlcyBtYXAgdG8uCiAgLy8gT3VyIFNldCAtIGJhc2VkIG1lbW9CdWlsZGVyIGRvZXNuJ3Qgd29yayBoZXJlIGJlY2F1c2Ugd2Ugd2FudCB0byB0aGUgb3V0cHV0IG9iamVjdCB0byBoYXZlIHRoZSBzYW1lIGNpcmN1bGFyCiAgLy8gcmVmZXJlbmNlcyBhcyB0aGUgaW5wdXQgb2JqZWN0LgogIGNvbnN0IG1lbW9pemF0aW9uTWFwID0gbmV3IE1hcCgpOwoKICAvLyBUaGlzIGZ1bmN0aW9uIGp1c3QgcHJveGllcyBgX2Ryb3BVbmRlZmluZWRLZXlzYCB0byBrZWVwIHRoZSBgbWVtb0J1aWxkZXJgIG91dCBvZiB0aGlzIGZ1bmN0aW9uJ3MgQVBJCiAgcmV0dXJuIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCk7Cn0KCmZ1bmN0aW9uIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCkgewogIGlmIChpc1Bvam8oaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIG9iamVjdCBpdCB3YXMgbWFwcGVkIHRvIGluIHRoZSBuZXcgb2JqZWN0CiAgICBjb25zdCBtZW1vVmFsID0gbWVtb2l6YXRpb25NYXAuZ2V0KGlucHV0VmFsdWUpOwogICAgaWYgKG1lbW9WYWwgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gbWVtb1ZhbCA7CiAgICB9CgogICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTsKICAgIC8vIFN0b3JlIHRoZSBtYXBwaW5nIG9mIHRoaXMgdmFsdWUgaW4gY2FzZSB3ZSB2aXNpdCBpdCBhZ2FpbiwgaW4gY2FzZSBvZiBjaXJjdWxhciBkYXRhCiAgICBtZW1vaXphdGlvbk1hcC5zZXQoaW5wdXRWYWx1ZSwgcmV0dXJuVmFsdWUpOwoKICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGlucHV0VmFsdWUpKSB7CiAgICAgIGlmICh0eXBlb2YgaW5wdXRWYWx1ZVtrZXldICE9PSAndW5kZWZpbmVkJykgewogICAgICAgIHJldHVyblZhbHVlW2tleV0gPSBfZHJvcFVuZGVmaW5lZEtleXMoaW5wdXRWYWx1ZVtrZXldLCBtZW1vaXphdGlvbk1hcCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIGFycmF5IGl0IHdhcyBtYXBwZWQgdG8gaW4gdGhlIG5ldyBvYmplY3QKICAgIGNvbnN0IG1lbW9WYWwgPSBtZW1vaXphdGlvbk1hcC5nZXQoaW5wdXRWYWx1ZSk7CiAgICBpZiAobWVtb1ZhbCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZW1vVmFsIDsKICAgIH0KCiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IFtdOwogICAgLy8gU3RvcmUgdGhlIG1hcHBpbmcgb2YgdGhpcyB2YWx1ZSBpbiBjYXNlIHdlIHZpc2l0IGl0IGFnYWluLCBpbiBjYXNlIG9mIGNpcmN1bGFyIGRhdGEKICAgIG1lbW9pemF0aW9uTWFwLnNldChpbnB1dFZhbHVlLCByZXR1cm5WYWx1ZSk7CgogICAgaW5wdXRWYWx1ZS5mb3JFYWNoKChpdGVtKSA9PiB7CiAgICAgIHJldHVyblZhbHVlLnB1c2goX2Ryb3BVbmRlZmluZWRLZXlzKGl0ZW0sIG1lbW9pemF0aW9uTWFwKSk7CiAgICB9KTsKCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgcmV0dXJuIGlucHV0VmFsdWU7Cn0KCmZ1bmN0aW9uIGlzUG9qbyhpbnB1dCkgewogIGlmICghaXNQbGFpbk9iamVjdChpbnB1dCkpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CgogIHRyeSB7CiAgICBjb25zdCBuYW1lID0gKE9iamVjdC5nZXRQcm90b3R5cGVPZihpbnB1dCkgKS5jb25zdHJ1Y3Rvci5uYW1lOwogICAgcmV0dXJuICFuYW1lIHx8IG5hbWUgPT09ICdPYmplY3QnOwogIH0gY2F0Y2ggKGUpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQoKLyoqCiAqIERvZXMgdGhpcyBmaWxlbmFtZSBsb29rIGxpa2UgaXQncyBwYXJ0IG9mIHRoZSBhcHAgY29kZT8KICovCmZ1bmN0aW9uIGZpbGVuYW1lSXNJbkFwcChmaWxlbmFtZSwgaXNOYXRpdmUgPSBmYWxzZSkgewogIGNvbnN0IGlzSW50ZXJuYWwgPQogICAgaXNOYXRpdmUgfHwKICAgIChmaWxlbmFtZSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiBpdCdzIGFuIGFic29sdXRlIGxpbnV4IHBhdGgKICAgICAgIWZpbGVuYW1lLnN0YXJ0c1dpdGgoJy8nKSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiBpdCdzIGFuIGFic29sdXRlIHdpbmRvd3MgcGF0aAogICAgICAhZmlsZW5hbWUubWF0Y2goL15bQS1aXTovKSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiB0aGUgcGF0aCBpcyBzdGFydGluZyB3aXRoIGEgZG90CiAgICAgICFmaWxlbmFtZS5zdGFydHNXaXRoKCcuJykgJiYKICAgICAgLy8gSXQncyBub3QgaW50ZXJuYWwgaWYgdGhlIGZyYW1lIGhhcyBhIHByb3RvY29sLiBJbiBub2RlLCB0aGlzIGlzIHVzdWFsbHkgdGhlIGNhc2UgaWYgdGhlIGZpbGUgZ290IHByZS1wcm9jZXNzZWQgd2l0aCBhIGJ1bmRsZXIgbGlrZSB3ZWJwYWNrCiAgICAgICFmaWxlbmFtZS5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSk7IC8vIFNjaGVtYSBmcm9tOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzY0MTc4MgoKICAvLyBpbl9hcHAgaXMgYWxsIHRoYXQncyBub3QgYW4gaW50ZXJuYWwgTm9kZSBmdW5jdGlvbiBvciBhIG1vZHVsZSB3aXRoaW4gbm9kZV9tb2R1bGVzCiAgLy8gbm90ZSB0aGF0IGlzTmF0aXZlIGFwcGVhcnMgdG8gcmV0dXJuIHRydWUgZXZlbiBmb3Igbm9kZSBjb3JlIGxpYnJhcmllcwogIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3JhdmVuLW5vZGUvaXNzdWVzLzE3NgoKICByZXR1cm4gIWlzSW50ZXJuYWwgJiYgZmlsZW5hbWUgIT09IHVuZGVmaW5lZCAmJiAhZmlsZW5hbWUuaW5jbHVkZXMoJ25vZGVfbW9kdWxlcy8nKTsKfQoKY29uc3QgU1RBQ0tUUkFDRV9GUkFNRV9MSU1JVCA9IDUwOwpjb25zdCBTVFJJUF9GUkFNRV9SRUdFWFAgPSAvY2FwdHVyZU1lc3NhZ2V8Y2FwdHVyZUV4Y2VwdGlvbi87CgovKioKICogUmVtb3ZlcyBTZW50cnkgZnJhbWVzIGZyb20gdGhlIHRvcCBhbmQgYm90dG9tIG9mIHRoZSBzdGFjayBpZiBwcmVzZW50IGFuZCBlbmZvcmNlcyBhIGxpbWl0IG9mIG1heCBudW1iZXIgb2YgZnJhbWVzLgogKiBBc3N1bWVzIHN0YWNrIGlucHV0IGlzIG9yZGVyZWQgZnJvbSB0b3AgdG8gYm90dG9tIGFuZCByZXR1cm5zIHRoZSByZXZlcnNlIHJlcHJlc2VudGF0aW9uIHNvIGNhbGwgc2l0ZSBvZiB0aGUKICogZnVuY3Rpb24gdGhhdCBjYXVzZWQgdGhlIGNyYXNoIGlzIHRoZSBsYXN0IGZyYW1lIGluIHRoZSBhcnJheS4KICogQGhpZGRlbgogKi8KZnVuY3Rpb24gc3RyaXBTZW50cnlGcmFtZXNBbmRSZXZlcnNlKHN0YWNrKSB7CiAgaWYgKCFzdGFjay5sZW5ndGgpIHsKICAgIHJldHVybiBbXTsKICB9CgogIGNvbnN0IGxvY2FsU3RhY2sgPSBBcnJheS5mcm9tKHN0YWNrKTsKCiAgLy8gSWYgc3RhY2sgc3RhcnRzIHdpdGggb25lIG9mIG91ciBBUEkgY2FsbHMsIHJlbW92ZSBpdCAoc3RhcnRzLCBtZWFuaW5nIGl0J3MgdGhlIHRvcCBvZiB0aGUgc3RhY2sgLSBha2EgbGFzdCBjYWxsKQogIGlmICgvc2VudHJ5V3JhcHBlZC8udGVzdChsb2NhbFN0YWNrW2xvY2FsU3RhY2subGVuZ3RoIC0gMV0uZnVuY3Rpb24gfHwgJycpKSB7CiAgICBsb2NhbFN0YWNrLnBvcCgpOwogIH0KCiAgLy8gUmV2ZXJzaW5nIGluIHRoZSBtaWRkbGUgb2YgdGhlIHByb2NlZHVyZSBhbGxvd3MgdXMgdG8ganVzdCBwb3AgdGhlIHZhbHVlcyBvZmYgdGhlIHN0YWNrCiAgbG9jYWxTdGFjay5yZXZlcnNlKCk7CgogIC8vIElmIHN0YWNrIGVuZHMgd2l0aCBvbmUgb2Ygb3VyIGludGVybmFsIEFQSSBjYWxscywgcmVtb3ZlIGl0IChlbmRzLCBtZWFuaW5nIGl0J3MgdGhlIGJvdHRvbSBvZiB0aGUgc3RhY2sgLSBha2EgdG9wLW1vc3QgY2FsbCkKICBpZiAoU1RSSVBfRlJBTUVfUkVHRVhQLnRlc3QobG9jYWxTdGFja1tsb2NhbFN0YWNrLmxlbmd0aCAtIDFdLmZ1bmN0aW9uIHx8ICcnKSkgewogICAgbG9jYWxTdGFjay5wb3AoKTsKCiAgICAvLyBXaGVuIHVzaW5nIHN5bnRoZXRpYyBldmVudHMsIHdlIHdpbGwgaGF2ZSBhIDIgbGV2ZWxzIGRlZXAgc3RhY2ssIGFzIGBuZXcgRXJyb3IoJ1NlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24nKWAKICAgIC8vIGlzIHByb2R1Y2VkIHdpdGhpbiB0aGUgaHViIGl0c2VsZiwgbWFraW5nIGl0OgogICAgLy8KICAgIC8vICAgU2VudHJ5LmNhcHR1cmVFeGNlcHRpb24oKQogICAgLy8gICBnZXRDdXJyZW50SHViKCkuY2FwdHVyZUV4Y2VwdGlvbigpCiAgICAvLwogICAgLy8gaW5zdGVhZCBvZiBqdXN0IHRoZSB0b3AgYFNlbnRyeWAgY2FsbCBpdHNlbGYuCiAgICAvLyBUaGlzIGZvcmNlcyB1cyB0byBwb3NzaWJseSBzdHJpcCBhbiBhZGRpdGlvbmFsIGZyYW1lIGluIHRoZSBleGFjdCBzYW1lIHdhcyBhcyBhYm92ZS4KICAgIGlmIChTVFJJUF9GUkFNRV9SRUdFWFAudGVzdChsb2NhbFN0YWNrW2xvY2FsU3RhY2subGVuZ3RoIC0gMV0uZnVuY3Rpb24gfHwgJycpKSB7CiAgICAgIGxvY2FsU3RhY2sucG9wKCk7CiAgICB9CiAgfQoKICByZXR1cm4gbG9jYWxTdGFjay5zbGljZSgwLCBTVEFDS1RSQUNFX0ZSQU1FX0xJTUlUKS5tYXAoZnJhbWUgPT4gKHsKICAgIC4uLmZyYW1lLAogICAgZmlsZW5hbWU6IGZyYW1lLmZpbGVuYW1lIHx8IGxvY2FsU3RhY2tbbG9jYWxTdGFjay5sZW5ndGggLSAxXS5maWxlbmFtZSwKICAgIGZ1bmN0aW9uOiBmcmFtZS5mdW5jdGlvbiB8fCAnPycsCiAgfSkpOwp9Cgpjb25zdCBkZWZhdWx0RnVuY3Rpb25OYW1lID0gJzxhbm9ueW1vdXM+JzsKCi8qKgogKiBTYWZlbHkgZXh0cmFjdCBmdW5jdGlvbiBuYW1lIGZyb20gaXRzZWxmCiAqLwpmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWUoZm4pIHsKICB0cnkgewogICAgaWYgKCFmbiB8fCB0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRGdW5jdGlvbk5hbWU7CiAgICB9CiAgICByZXR1cm4gZm4ubmFtZSB8fCBkZWZhdWx0RnVuY3Rpb25OYW1lOwogIH0gY2F0Y2ggKGUpIHsKICAgIC8vIEp1c3QgYWNjZXNzaW5nIGN1c3RvbSBwcm9wcyBpbiBzb21lIFNlbGVuaXVtIGVudmlyb25tZW50cwogICAgLy8gY2FuIGNhdXNlIGEgIlBlcm1pc3Npb24gZGVuaWVkIiBleGNlcHRpb24gKHNlZSByYXZlbi1qcyM0OTUpLgogICAgcmV0dXJuIGRlZmF1bHRGdW5jdGlvbk5hbWU7CiAgfQp9CgovKioKICogVVVJRDQgZ2VuZXJhdG9yCiAqCiAqIEByZXR1cm5zIHN0cmluZyBHZW5lcmF0ZWQgVVVJRDQuCiAqLwpmdW5jdGlvbiB1dWlkNCgpIHsKICBjb25zdCBnYmwgPSBHTE9CQUxfT0JKIDsKICBjb25zdCBjcnlwdG8gPSBnYmwuY3J5cHRvIHx8IGdibC5tc0NyeXB0bzsKCiAgbGV0IGdldFJhbmRvbUJ5dGUgPSAoKSA9PiBNYXRoLnJhbmRvbSgpICogMTY7CiAgdHJ5IHsKICAgIGlmIChjcnlwdG8gJiYgY3J5cHRvLnJhbmRvbVVVSUQpIHsKICAgICAgcmV0dXJuIGNyeXB0by5yYW5kb21VVUlEKCkucmVwbGFjZSgvLS9nLCAnJyk7CiAgICB9CiAgICBpZiAoY3J5cHRvICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMpIHsKICAgICAgZ2V0UmFuZG9tQnl0ZSA9ICgpID0+IHsKICAgICAgICAvLyBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzIG1pZ2h0IHJldHVybiB1bmRlZmluZWQgaW5zdGVhZCBvZiB0aGUgdHlwZWQgYXJyYXkKICAgICAgICAvLyBpbiBvbGQgQ2hyb21pdW0gdmVyc2lvbnMgKGUuZy4gMjMuMC4xMjM1LjAgKDE1MTQyMikpCiAgICAgICAgLy8gSG93ZXZlciwgYHR5cGVkQXJyYXlgIGlzIHN0aWxsIGZpbGxlZCBpbi1wbGFjZS4KICAgICAgICAvLyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9DcnlwdG8vZ2V0UmFuZG9tVmFsdWVzI3R5cGVkYXJyYXkKICAgICAgICBjb25zdCB0eXBlZEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoMSk7CiAgICAgICAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyh0eXBlZEFycmF5KTsKICAgICAgICByZXR1cm4gdHlwZWRBcnJheVswXTsKICAgICAgfTsKICAgIH0KICB9IGNhdGNoIChfKSB7CiAgICAvLyBzb21lIHJ1bnRpbWVzIGNhbiBjcmFzaCBpbnZva2luZyBjcnlwdG8KICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQvaXNzdWVzLzg5MzUKICB9CgogIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTA1MDM0L2hvdy10by1jcmVhdGUtYS1ndWlkLXV1aWQtaW4tamF2YXNjcmlwdC8yMTE3NTIzIzIxMTc1MjMKICAvLyBDb25jYXRlbmF0aW5nIHRoZSBmb2xsb3dpbmcgbnVtYmVycyBhcyBzdHJpbmdzIHJlc3VsdHMgaW4gJzEwMDAwMDAwMTAwMDQwMDA4MDAwMTAwMDAwMDAwMDAwJwogIHJldHVybiAoKFsxZTddICkgKyAxZTMgKyA0ZTMgKyA4ZTMgKyAxZTExKS5yZXBsYWNlKC9bMDE4XS9nLCBjID0+CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZQogICAgKChjICkgXiAoKGdldFJhbmRvbUJ5dGUoKSAmIDE1KSA+PiAoKGMgKSAvIDQpKSkudG9TdHJpbmcoMTYpLAogICk7Cn0KCi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtbWVtYmVyLWFjY2VzcyAqLwovKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovCgovKioKICogSGVscGVyIHRvIGRlY3ljbGUganNvbiBvYmplY3RzCiAqLwpmdW5jdGlvbiBtZW1vQnVpbGRlcigpIHsKICBjb25zdCBoYXNXZWFrU2V0ID0gdHlwZW9mIFdlYWtTZXQgPT09ICdmdW5jdGlvbic7CiAgY29uc3QgaW5uZXIgPSBoYXNXZWFrU2V0ID8gbmV3IFdlYWtTZXQoKSA6IFtdOwogIGZ1bmN0aW9uIG1lbW9pemUob2JqKSB7CiAgICBpZiAoaGFzV2Vha1NldCkgewogICAgICBpZiAoaW5uZXIuaGFzKG9iaikpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpbm5lci5hZGQob2JqKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9wcmVmZXItZm9yLW9mCiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlubmVyLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gaW5uZXJbaV07CiAgICAgIGlmICh2YWx1ZSA9PT0gb2JqKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0KICAgIGlubmVyLnB1c2gob2JqKTsKICAgIHJldHVybiBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIHVubWVtb2l6ZShvYmopIHsKICAgIGlmIChoYXNXZWFrU2V0KSB7CiAgICAgIGlubmVyLmRlbGV0ZShvYmopOwogICAgfSBlbHNlIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbm5lci5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChpbm5lcltpXSA9PT0gb2JqKSB7CiAgICAgICAgICBpbm5lci5zcGxpY2UoaSwgMSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIFttZW1vaXplLCB1bm1lbW9pemVdOwp9CgovKioKICogUmVjdXJzaXZlbHkgbm9ybWFsaXplcyB0aGUgZ2l2ZW4gb2JqZWN0LgogKgogKiAtIENyZWF0ZXMgYSBjb3B5IHRvIHByZXZlbnQgb3JpZ2luYWwgaW5wdXQgbXV0YXRpb24KICogLSBTa2lwcyBub24tZW51bWVyYWJsZSBwcm9wZXJ0aWVzCiAqIC0gV2hlbiBzdHJpbmdpZnlpbmcsIGNhbGxzIGB0b0pTT05gIGlmIGltcGxlbWVudGVkCiAqIC0gUmVtb3ZlcyBjaXJjdWxhciByZWZlcmVuY2VzCiAqIC0gVHJhbnNsYXRlcyBub24tc2VyaWFsaXphYmxlIHZhbHVlcyAoYHVuZGVmaW5lZGAvYE5hTmAvZnVuY3Rpb25zKSB0byBzZXJpYWxpemFibGUgZm9ybWF0CiAqIC0gVHJhbnNsYXRlcyBrbm93biBnbG9iYWwgb2JqZWN0cy9jbGFzc2VzIHRvIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9ucwogKiAtIFRha2VzIGNhcmUgb2YgYEVycm9yYCBvYmplY3Qgc2VyaWFsaXphdGlvbgogKiAtIE9wdGlvbmFsbHkgbGltaXRzIGRlcHRoIG9mIGZpbmFsIG91dHB1dAogKiAtIE9wdGlvbmFsbHkgbGltaXRzIG51bWJlciBvZiBwcm9wZXJ0aWVzL2VsZW1lbnRzIGluY2x1ZGVkIGluIGFueSBzaW5nbGUgb2JqZWN0L2FycmF5CiAqCiAqIEBwYXJhbSBpbnB1dCBUaGUgb2JqZWN0IHRvIGJlIG5vcm1hbGl6ZWQuCiAqIEBwYXJhbSBkZXB0aCBUaGUgbWF4IGRlcHRoIHRvIHdoaWNoIHRvIG5vcm1hbGl6ZSB0aGUgb2JqZWN0LiAoQW55dGhpbmcgZGVlcGVyIHN0cmluZ2lmaWVkIHdob2xlLikKICogQHBhcmFtIG1heFByb3BlcnRpZXMgVGhlIG1heCBudW1iZXIgb2YgZWxlbWVudHMgb3IgcHJvcGVydGllcyB0byBiZSBpbmNsdWRlZCBpbiBhbnkgc2luZ2xlIGFycmF5IG9yCiAqIG9iamVjdCBpbiB0aGUgbm9ybWFsbGl6ZWQgb3V0cHV0LgogKiBAcmV0dXJucyBBIG5vcm1hbGl6ZWQgdmVyc2lvbiBvZiB0aGUgb2JqZWN0LCBvciBgIioqbm9uLXNlcmlhbGl6YWJsZSoqImAgaWYgYW55IGVycm9ycyBhcmUgdGhyb3duIGR1cmluZyBub3JtYWxpemF0aW9uLgogKi8KLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkKZnVuY3Rpb24gbm9ybWFsaXplKGlucHV0LCBkZXB0aCA9IDEwMCwgbWF4UHJvcGVydGllcyA9ICtJbmZpbml0eSkgewogIHRyeSB7CiAgICAvLyBzaW5jZSB3ZSdyZSBhdCB0aGUgb3V0ZXJtb3N0IGxldmVsLCB3ZSBkb24ndCBwcm92aWRlIGEga2V5CiAgICByZXR1cm4gdmlzaXQoJycsIGlucHV0LCBkZXB0aCwgbWF4UHJvcGVydGllcyk7CiAgfSBjYXRjaCAoZXJyKSB7CiAgICByZXR1cm4geyBFUlJPUjogYCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke2Vycn0pYCB9OwogIH0KfQoKLyoqCiAqIFZpc2l0cyBhIG5vZGUgdG8gcGVyZm9ybSBub3JtYWxpemF0aW9uIG9uIGl0CiAqCiAqIEBwYXJhbSBrZXkgVGhlIGtleSBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiBub2RlCiAqIEBwYXJhbSB2YWx1ZSBUaGUgbm9kZSB0byBiZSB2aXNpdGVkCiAqIEBwYXJhbSBkZXB0aCBPcHRpb25hbCBudW1iZXIgaW5kaWNhdGluZyB0aGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGgKICogQHBhcmFtIG1heFByb3BlcnRpZXMgT3B0aW9uYWwgbWF4aW11bSBudW1iZXIgb2YgcHJvcGVydGllcy9lbGVtZW50cyBpbmNsdWRlZCBpbiBhbnkgc2luZ2xlIG9iamVjdC9hcnJheQogKiBAcGFyYW0gbWVtbyBPcHRpb25hbCBNZW1vIGNsYXNzIGhhbmRsaW5nIGRlY3ljbGluZwogKi8KZnVuY3Rpb24gdmlzaXQoCiAga2V5LAogIHZhbHVlLAogIGRlcHRoID0gK0luZmluaXR5LAogIG1heFByb3BlcnRpZXMgPSArSW5maW5pdHksCiAgbWVtbyA9IG1lbW9CdWlsZGVyKCksCikgewogIGNvbnN0IFttZW1vaXplLCB1bm1lbW9pemVdID0gbWVtbzsKCiAgLy8gR2V0IHRoZSBzaW1wbGUgY2FzZXMgb3V0IG9mIHRoZSB3YXkgZmlyc3QKICBpZiAoCiAgICB2YWx1ZSA9PSBudWxsIHx8IC8vIHRoaXMgbWF0Y2hlcyBudWxsIGFuZCB1bmRlZmluZWQgLT4gZXFlcSBub3QgZXFlcWVxCiAgICAoWydudW1iZXInLCAnYm9vbGVhbicsICdzdHJpbmcnXS5pbmNsdWRlcyh0eXBlb2YgdmFsdWUpICYmICFpc05hTiQxKHZhbHVlKSkKICApIHsKICAgIHJldHVybiB2YWx1ZSA7CiAgfQoKICBjb25zdCBzdHJpbmdpZmllZCA9IHN0cmluZ2lmeVZhbHVlKGtleSwgdmFsdWUpOwoKICAvLyBBbnl0aGluZyB3ZSBjb3VsZCBwb3RlbnRpYWxseSBkaWcgaW50byBtb3JlIChvYmplY3RzIG9yIGFycmF5cykgd2lsbCBoYXZlIGNvbWUgYmFjayBhcyBgIltvYmplY3QgWFhYWF0iYC4KICAvLyBFdmVyeXRoaW5nIGVsc2Ugd2lsbCBoYXZlIGFscmVhZHkgYmVlbiBzZXJpYWxpemVkLCBzbyBpZiB3ZSBkb24ndCBzZWUgdGhhdCBwYXR0ZXJuLCB3ZSdyZSBkb25lLgogIGlmICghc3RyaW5naWZpZWQuc3RhcnRzV2l0aCgnW29iamVjdCAnKSkgewogICAgcmV0dXJuIHN0cmluZ2lmaWVkOwogIH0KCiAgLy8gRnJvbSBoZXJlIG9uLCB3ZSBjYW4gYXNzZXJ0IHRoYXQgYHZhbHVlYCBpcyBlaXRoZXIgYW4gb2JqZWN0IG9yIGFuIGFycmF5LgoKICAvLyBEbyBub3Qgbm9ybWFsaXplIG9iamVjdHMgdGhhdCB3ZSBrbm93IGhhdmUgYWxyZWFkeSBiZWVuIG5vcm1hbGl6ZWQuIEFzIGEgZ2VuZXJhbCBydWxlLCB0aGUKICAvLyAiX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18iIHByb3BlcnR5IHNob3VsZCBvbmx5IGJlIHVzZWQgc3BhcmluZ2x5IGFuZCBvbmx5IHNob3VsZCBvbmx5IGJlIHNldCBvbiBvYmplY3RzIHRoYXQKICAvLyBoYXZlIGFscmVhZHkgYmVlbiBub3JtYWxpemVkLgogIGlmICgodmFsdWUgKVsnX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18nXSkgewogICAgcmV0dXJuIHZhbHVlIDsKICB9CgogIC8vIFdlIGNhbiBzZXQgYF9fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfX2Agb24gYW4gb2JqZWN0IHRvIGVuc3VyZSB0aGF0IGZyb20gdGhlcmUKICAvLyBXZSBrZWVwIGEgY2VydGFpbiBhbW91bnQgb2YgZGVwdGguCiAgLy8gVGhpcyBzaG91bGQgYmUgdXNlZCBzcGFyaW5nbHksIGUuZy4gd2UgdXNlIGl0IGZvciB0aGUgcmVkdXggaW50ZWdyYXRpb24gdG8gZW5zdXJlIHdlIGdldCBhIGNlcnRhaW4gYW1vdW50IG9mIHN0YXRlLgogIGNvbnN0IHJlbWFpbmluZ0RlcHRoID0KICAgIHR5cGVvZiAodmFsdWUgKVsnX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fJ10gPT09ICdudW1iZXInCiAgICAgID8gKCh2YWx1ZSApWydfX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18nXSApCiAgICAgIDogZGVwdGg7CgogIC8vIFdlJ3JlIGFsc28gZG9uZSBpZiB3ZSd2ZSByZWFjaGVkIHRoZSBtYXggZGVwdGgKICBpZiAocmVtYWluaW5nRGVwdGggPT09IDApIHsKICAgIC8vIEF0IHRoaXMgcG9pbnQgd2Uga25vdyBgc2VyaWFsaXplZGAgaXMgYSBzdHJpbmcgb2YgdGhlIGZvcm0gYCJbb2JqZWN0IFhYWFhdImAuIENsZWFuIGl0IHVwIHNvIGl0J3MganVzdCBgIltYWFhYXSJgLgogICAgcmV0dXJuIHN0cmluZ2lmaWVkLnJlcGxhY2UoJ29iamVjdCAnLCAnJyk7CiAgfQoKICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IHZpc2l0ZWQgdGhpcyBicmFuY2gsIGJhaWwgb3V0LCBhcyBpdCdzIGNpcmN1bGFyIHJlZmVyZW5jZS4gSWYgbm90LCBub3RlIHRoYXQgd2UncmUgc2VlaW5nIGl0IG5vdy4KICBpZiAobWVtb2l6ZSh2YWx1ZSkpIHsKICAgIHJldHVybiAnW0NpcmN1bGFyIH5dJzsKICB9CgogIC8vIElmIHRoZSB2YWx1ZSBoYXMgYSBgdG9KU09OYCBtZXRob2QsIHdlIGNhbGwgaXQgdG8gZXh0cmFjdCBtb3JlIGluZm9ybWF0aW9uCiAgY29uc3QgdmFsdWVXaXRoVG9KU09OID0gdmFsdWUgOwogIGlmICh2YWx1ZVdpdGhUb0pTT04gJiYgdHlwZW9mIHZhbHVlV2l0aFRvSlNPTi50b0pTT04gPT09ICdmdW5jdGlvbicpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IGpzb25WYWx1ZSA9IHZhbHVlV2l0aFRvSlNPTi50b0pTT04oKTsKICAgICAgLy8gV2UgbmVlZCB0byBub3JtYWxpemUgdGhlIHJldHVybiB2YWx1ZSBvZiBgLnRvSlNPTigpYCBpbiBjYXNlIGl0IGhhcyBjaXJjdWxhciByZWZlcmVuY2VzCiAgICAgIHJldHVybiB2aXNpdCgnJywganNvblZhbHVlLCByZW1haW5pbmdEZXB0aCAtIDEsIG1heFByb3BlcnRpZXMsIG1lbW8pOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIC8vIHBhc3MgKFRoZSBidWlsdC1pbiBgdG9KU09OYCBmYWlsZWQsIGJ1dCB3ZSBjYW4gc3RpbGwgdHJ5IHRvIGRvIGl0IG91cnNlbHZlcykKICAgIH0KICB9CgogIC8vIEF0IHRoaXMgcG9pbnQgd2Uga25vdyB3ZSBlaXRoZXIgaGF2ZSBhbiBvYmplY3Qgb3IgYW4gYXJyYXksIHdlIGhhdmVuJ3Qgc2VlbiBpdCBiZWZvcmUsIGFuZCB3ZSdyZSBnb2luZyB0byByZWN1cnNlCiAgLy8gYmVjYXVzZSB3ZSBoYXZlbid0IHlldCByZWFjaGVkIHRoZSBtYXggZGVwdGguIENyZWF0ZSBhbiBhY2N1bXVsYXRvciB0byBob2xkIHRoZSByZXN1bHRzIG9mIHZpc2l0aW5nIGVhY2gKICAvLyBwcm9wZXJ0eS9lbnRyeSwgYW5kIGtlZXAgdHJhY2sgb2YgdGhlIG51bWJlciBvZiBpdGVtcyB3ZSBhZGQgdG8gaXQuCiAgY29uc3Qgbm9ybWFsaXplZCA9IChBcnJheS5pc0FycmF5KHZhbHVlKSA/IFtdIDoge30pIDsKICBsZXQgbnVtQWRkZWQgPSAwOwoKICAvLyBCZWZvcmUgd2UgYmVnaW4sIGNvbnZlcnRgRXJyb3JgIGFuZGBFdmVudGAgaW5zdGFuY2VzIGludG8gcGxhaW4gb2JqZWN0cywgc2luY2Ugc29tZSBvZiBlYWNoIG9mIHRoZWlyIHJlbGV2YW50CiAgLy8gcHJvcGVydGllcyBhcmUgbm9uLWVudW1lcmFibGUgYW5kIG90aGVyd2lzZSB3b3VsZCBnZXQgbWlzc2VkLgogIGNvbnN0IHZpc2l0YWJsZSA9IGNvbnZlcnRUb1BsYWluT2JqZWN0KHZhbHVlICk7CgogIGZvciAoY29uc3QgdmlzaXRLZXkgaW4gdmlzaXRhYmxlKSB7CiAgICAvLyBBdm9pZCBpdGVyYXRpbmcgb3ZlciBmaWVsZHMgaW4gdGhlIHByb3RvdHlwZSBpZiB0aGV5J3ZlIHNvbWVob3cgYmVlbiBleHBvc2VkIHRvIGVudW1lcmF0aW9uLgogICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmlzaXRhYmxlLCB2aXNpdEtleSkpIHsKICAgICAgY29udGludWU7CiAgICB9CgogICAgaWYgKG51bUFkZGVkID49IG1heFByb3BlcnRpZXMpIHsKICAgICAgbm9ybWFsaXplZFt2aXNpdEtleV0gPSAnW01heFByb3BlcnRpZXMgfl0nOwogICAgICBicmVhazsKICAgIH0KCiAgICAvLyBSZWN1cnNpdmVseSB2aXNpdCBhbGwgdGhlIGNoaWxkIG5vZGVzCiAgICBjb25zdCB2aXNpdFZhbHVlID0gdmlzaXRhYmxlW3Zpc2l0S2V5XTsKICAgIG5vcm1hbGl6ZWRbdmlzaXRLZXldID0gdmlzaXQodmlzaXRLZXksIHZpc2l0VmFsdWUsIHJlbWFpbmluZ0RlcHRoIC0gMSwgbWF4UHJvcGVydGllcywgbWVtbyk7CgogICAgbnVtQWRkZWQrKzsKICB9CgogIC8vIE9uY2Ugd2UndmUgdmlzaXRlZCBhbGwgdGhlIGJyYW5jaGVzLCByZW1vdmUgdGhlIHBhcmVudCBmcm9tIG1lbW8gc3RvcmFnZQogIHVubWVtb2l6ZSh2YWx1ZSk7CgogIC8vIFJldHVybiBhY2N1bXVsYXRlZCB2YWx1ZXMKICByZXR1cm4gbm9ybWFsaXplZDsKfQoKLyogZXNsaW50LWRpc2FibGUgY29tcGxleGl0eSAqLwovKioKICogU3RyaW5naWZ5IHRoZSBnaXZlbiB2YWx1ZS4gSGFuZGxlcyB2YXJpb3VzIGtub3duIHNwZWNpYWwgdmFsdWVzIGFuZCB0eXBlcy4KICoKICogTm90IG1lYW50IHRvIGJlIHVzZWQgb24gc2ltcGxlIHByaW1pdGl2ZXMgd2hpY2ggYWxyZWFkeSBoYXZlIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uLCBhcyBpdCB3aWxsLCBmb3IgZXhhbXBsZSwgdHVybgogKiB0aGUgbnVtYmVyIDEyMzEgaW50byAiW09iamVjdCBOdW1iZXJdIiwgbm9yIG9uIGBudWxsYCwgYXMgaXQgd2lsbCB0aHJvdy4KICoKICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0byBzdHJpbmdpZnkKICogQHJldHVybnMgQSBzdHJpbmdpZmllZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gdmFsdWUKICovCmZ1bmN0aW9uIHN0cmluZ2lmeVZhbHVlKAogIGtleSwKICAvLyB0aGlzIHR5cGUgaXMgYSB0aW55IGJpdCBvZiBhIGNoZWF0LCBzaW5jZSB0aGlzIGZ1bmN0aW9uIGRvZXMgaGFuZGxlIE5hTiAod2hpY2ggaXMgdGVjaG5pY2FsbHkgYSBudW1iZXIpLCBidXQgZm9yCiAgLy8gb3VyIGludGVybmFsIHVzZSwgaXQnbGwgZG8KICB2YWx1ZSwKKSB7CiAgdHJ5IHsKICAgIGlmIChrZXkgPT09ICdkb21haW4nICYmIHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgKHZhbHVlICkuX2V2ZW50cykgewogICAgICByZXR1cm4gJ1tEb21haW5dJzsKICAgIH0KCiAgICBpZiAoa2V5ID09PSAnZG9tYWluRW1pdHRlcicpIHsKICAgICAgcmV0dXJuICdbRG9tYWluRW1pdHRlcl0nOwogICAgfQoKICAgIC8vIEl0J3Mgc2FmZSB0byB1c2UgYGdsb2JhbGAsIGB3aW5kb3dgLCBhbmQgYGRvY3VtZW50YCBoZXJlIGluIHRoaXMgbWFubmVyLCBhcyB3ZSBhcmUgYXNzZXJ0aW5nIHVzaW5nIGB0eXBlb2ZgIGZpcnN0CiAgICAvLyB3aGljaCB3b24ndCB0aHJvdyBpZiB0aGV5IGFyZSBub3QgcHJlc2VudC4KCiAgICBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgPT09IGdsb2JhbCkgewogICAgICByZXR1cm4gJ1tHbG9iYWxdJzsKICAgIH0KCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzCiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgPT09IHdpbmRvdykgewogICAgICByZXR1cm4gJ1tXaW5kb3ddJzsKICAgIH0KCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzCiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiB2YWx1ZSA9PT0gZG9jdW1lbnQpIHsKICAgICAgcmV0dXJuICdbRG9jdW1lbnRdJzsKICAgIH0KCiAgICBpZiAoaXNWdWVWaWV3TW9kZWwodmFsdWUpKSB7CiAgICAgIHJldHVybiAnW1Z1ZVZpZXdNb2RlbF0nOwogICAgfQoKICAgIC8vIFJlYWN0J3MgU3ludGhldGljRXZlbnQgdGhpbmd5CiAgICBpZiAoaXNTeW50aGV0aWNFdmVudCh2YWx1ZSkpIHsKICAgICAgcmV0dXJuICdbU3ludGhldGljRXZlbnRdJzsKICAgIH0KCiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiB2YWx1ZSAhPT0gdmFsdWUpIHsKICAgICAgcmV0dXJuICdbTmFOXSc7CiAgICB9CgogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gYFtGdW5jdGlvbjogJHtnZXRGdW5jdGlvbk5hbWUodmFsdWUpfV1gOwogICAgfQoKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnKSB7CiAgICAgIHJldHVybiBgWyR7U3RyaW5nKHZhbHVlKX1dYDsKICAgIH0KCiAgICAvLyBzdHJpbmdpZmllZCBCaWdJbnRzIGFyZSBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIHJlZ3VsYXIgbnVtYmVycywgc28gd2UgbmVlZCB0byBsYWJlbCB0aGVtIHRvIGF2b2lkIGNvbmZ1c2lvbgogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2JpZ2ludCcpIHsKICAgICAgcmV0dXJuIGBbQmlnSW50OiAke1N0cmluZyh2YWx1ZSl9XWA7CiAgICB9CgogICAgLy8gTm93IHRoYXQgd2UndmUga25vY2tlZCBvdXQgYWxsIHRoZSBzcGVjaWFsIGNhc2VzIGFuZCB0aGUgcHJpbWl0aXZlcywgYWxsIHdlIGhhdmUgbGVmdCBhcmUgb2JqZWN0cy4gU2ltcGx5IGNhc3RpbmcKICAgIC8vIHRoZW0gdG8gc3RyaW5ncyBtZWFucyB0aGF0IGluc3RhbmNlcyBvZiBjbGFzc2VzIHdoaWNoIGhhdmVuJ3QgZGVmaW5lZCB0aGVpciBgdG9TdHJpbmdUYWdgIHdpbGwganVzdCBjb21lIG91dCBhcwogICAgLy8gYCJbb2JqZWN0IE9iamVjdF0iYC4gSWYgd2UgaW5zdGVhZCBsb29rIGF0IHRoZSBjb25zdHJ1Y3RvcidzIG5hbWUgKHdoaWNoIGlzIHRoZSBzYW1lIGFzIHRoZSBuYW1lIG9mIHRoZSBjbGFzcyksCiAgICAvLyB3ZSBjYW4gbWFrZSBzdXJlIHRoYXQgb25seSBwbGFpbiBvYmplY3RzIGNvbWUgb3V0IHRoYXQgd2F5LgogICAgY29uc3Qgb2JqTmFtZSA9IGdldENvbnN0cnVjdG9yTmFtZSh2YWx1ZSk7CgogICAgLy8gSGFuZGxlIEhUTUwgRWxlbWVudHMKICAgIGlmICgvXkhUTUwoXHcqKUVsZW1lbnQkLy50ZXN0KG9iak5hbWUpKSB7CiAgICAgIHJldHVybiBgW0hUTUxFbGVtZW50OiAke29iak5hbWV9XWA7CiAgICB9CgogICAgcmV0dXJuIGBbb2JqZWN0ICR7b2JqTmFtZX1dYDsKICB9IGNhdGNoIChlcnIpIHsKICAgIHJldHVybiBgKipub24tc2VyaWFsaXphYmxlKiogKCR7ZXJyfSlgOwogIH0KfQovKiBlc2xpbnQtZW5hYmxlIGNvbXBsZXhpdHkgKi8KCmZ1bmN0aW9uIGdldENvbnN0cnVjdG9yTmFtZSh2YWx1ZSkgewogIGNvbnN0IHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7CgogIHJldHVybiBwcm90b3R5cGUgPyBwcm90b3R5cGUuY29uc3RydWN0b3IubmFtZSA6ICdudWxsIHByb3RvdHlwZSc7Cn0KCi8qKgogKiBOb3JtYWxpemVzIFVSTHMgaW4gZXhjZXB0aW9ucyBhbmQgc3RhY2t0cmFjZXMgdG8gYSBiYXNlIHBhdGggc28gU2VudHJ5IGNhbiBmaW5nZXJwcmludAogKiBhY3Jvc3MgcGxhdGZvcm1zIGFuZCB3b3JraW5nIGRpcmVjdG9yeS4KICoKICogQHBhcmFtIHVybCBUaGUgVVJMIHRvIGJlIG5vcm1hbGl6ZWQuCiAqIEBwYXJhbSBiYXNlUGF0aCBUaGUgYXBwbGljYXRpb24gYmFzZSBwYXRoLgogKiBAcmV0dXJucyBUaGUgbm9ybWFsaXplZCBVUkwuCiAqLwpmdW5jdGlvbiBub3JtYWxpemVVcmxUb0Jhc2UodXJsLCBiYXNlUGF0aCkgewogIGNvbnN0IGVzY2FwZWRCYXNlID0gYmFzZVBhdGgKICAgIC8vIEJhY2tzbGFzaCB0byBmb3J3YXJkCiAgICAucmVwbGFjZSgvXFwvZywgJy8nKQogICAgLy8gRXNjYXBlIFJlZ0V4cCBzcGVjaWFsIGNoYXJhY3RlcnMKICAgIC5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywgJ1xcJCYnKTsKCiAgbGV0IG5ld1VybCA9IHVybDsKICB0cnkgewogICAgbmV3VXJsID0gZGVjb2RlVVJJKHVybCk7CiAgfSBjYXRjaCAoX09vKSB7CiAgICAvLyBTb21ldGltZSB0aGlzIGJyZWFrcwogIH0KICByZXR1cm4gKAogICAgbmV3VXJsCiAgICAgIC5yZXBsYWNlKC9cXC9nLCAnLycpCiAgICAgIC5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCAnJykgLy8gUmVtb3ZlIGludGVybWVkaWF0ZSBiYXNlIHBhdGgKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBzZW50cnktaW50ZXJuYWwvc2RrL25vLXJlZ2V4cC1jb25zdHJ1Y3RvcgogICAgICAucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke2VzY2FwZWRCYXNlfS8qYCwgJ2lnJyksICdhcHA6Ly8vJykKICApOwp9CgovLyBTbGlnaHRseSBtb2RpZmllZCAobm8gSUU4IHN1cHBvcnQsIEVTNikgYW5kIHRyYW5zY3JpYmVkIHRvIFR5cGVTY3JpcHQKCi8vIFNwbGl0IGEgZmlsZW5hbWUgaW50byBbcm9vdCwgZGlyLCBiYXNlbmFtZSwgZXh0XSwgdW5peCB2ZXJzaW9uCi8vICdyb290JyBpcyBqdXN0IGEgc2xhc2gsIG9yIG5vdGhpbmcuCmNvbnN0IHNwbGl0UGF0aFJlID0gL14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvOwovKiogSlNEb2MgKi8KZnVuY3Rpb24gc3BsaXRQYXRoKGZpbGVuYW1lKSB7CiAgLy8gVHJ1bmNhdGUgZmlsZXMgbmFtZXMgZ3JlYXRlciB0aGFuIDEwMjQgY2hhcmFjdGVycyB0byBhdm9pZCByZWdleCBkb3MKICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0L3B1bGwvODczNyNkaXNjdXNzaW9uX3IxMjg1NzE5MTcyCiAgY29uc3QgdHJ1bmNhdGVkID0gZmlsZW5hbWUubGVuZ3RoID4gMTAyNCA/IGA8dHJ1bmNhdGVkPiR7ZmlsZW5hbWUuc2xpY2UoLTEwMjQpfWAgOiBmaWxlbmFtZTsKICBjb25zdCBwYXJ0cyA9IHNwbGl0UGF0aFJlLmV4ZWModHJ1bmNhdGVkKTsKICByZXR1cm4gcGFydHMgPyBwYXJ0cy5zbGljZSgxKSA6IFtdOwp9CgovKiogSlNEb2MgKi8KZnVuY3Rpb24gZGlybmFtZShwYXRoKSB7CiAgY29uc3QgcmVzdWx0ID0gc3BsaXRQYXRoKHBhdGgpOwogIGNvbnN0IHJvb3QgPSByZXN1bHRbMF07CiAgbGV0IGRpciA9IHJlc3VsdFsxXTsKCiAgaWYgKCFyb290ICYmICFkaXIpIHsKICAgIC8vIE5vIGRpcm5hbWUgd2hhdHNvZXZlcgogICAgcmV0dXJuICcuJzsKICB9CgogIGlmIChkaXIpIHsKICAgIC8vIEl0IGhhcyBhIGRpcm5hbWUsIHN0cmlwIHRyYWlsaW5nIHNsYXNoCiAgICBkaXIgPSBkaXIuc2xpY2UoMCwgZGlyLmxlbmd0aCAtIDEpOwogIH0KCiAgcmV0dXJuIHJvb3QgKyBkaXI7Cn0KCi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1mdW5jdGlvbi1yZXR1cm4tdHlwZSAqLwoKLyoqIFN5bmNQcm9taXNlIGludGVybmFsIHN0YXRlcyAqLwp2YXIgU3RhdGVzOyAoZnVuY3Rpb24gKFN0YXRlcykgewogIC8qKiBQZW5kaW5nICovCiAgY29uc3QgUEVORElORyA9IDA7IFN0YXRlc1tTdGF0ZXNbIlBFTkRJTkciXSA9IFBFTkRJTkddID0gIlBFTkRJTkciOwogIC8qKiBSZXNvbHZlZCAvIE9LICovCiAgY29uc3QgUkVTT0xWRUQgPSAxOyBTdGF0ZXNbU3RhdGVzWyJSRVNPTFZFRCJdID0gUkVTT0xWRURdID0gIlJFU09MVkVEIjsKICAvKiogUmVqZWN0ZWQgLyBFcnJvciAqLwogIGNvbnN0IFJFSkVDVEVEID0gMjsgU3RhdGVzW1N0YXRlc1siUkVKRUNURUQiXSA9IFJFSkVDVEVEXSA9ICJSRUpFQ1RFRCI7Cn0pKFN0YXRlcyB8fCAoU3RhdGVzID0ge30pKTsKCi8vIE92ZXJsb2FkcyBzbyB3ZSBjYW4gY2FsbCByZXNvbHZlZFN5bmNQcm9taXNlIHdpdGhvdXQgYXJndW1lbnRzIGFuZCBnZW5lcmljIGFyZ3VtZW50CgovKioKICogQ3JlYXRlcyBhIHJlc29sdmVkIHN5bmMgcHJvbWlzZS4KICoKICogQHBhcmFtIHZhbHVlIHRoZSB2YWx1ZSB0byByZXNvbHZlIHRoZSBwcm9taXNlIHdpdGgKICogQHJldHVybnMgdGhlIHJlc29sdmVkIHN5bmMgcHJvbWlzZQogKi8KZnVuY3Rpb24gcmVzb2x2ZWRTeW5jUHJvbWlzZSh2YWx1ZSkgewogIHJldHVybiBuZXcgU3luY1Byb21pc2UocmVzb2x2ZSA9PiB7CiAgICByZXNvbHZlKHZhbHVlKTsKICB9KTsKfQoKLyoqCiAqIENyZWF0ZXMgYSByZWplY3RlZCBzeW5jIHByb21pc2UuCiAqCiAqIEBwYXJhbSB2YWx1ZSB0aGUgdmFsdWUgdG8gcmVqZWN0IHRoZSBwcm9taXNlIHdpdGgKICogQHJldHVybnMgdGhlIHJlamVjdGVkIHN5bmMgcHJvbWlzZQogKi8KZnVuY3Rpb24gcmVqZWN0ZWRTeW5jUHJvbWlzZShyZWFzb24pIHsKICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKChfLCByZWplY3QpID0+IHsKICAgIHJlamVjdChyZWFzb24pOwogIH0pOwp9CgovKioKICogVGhlbmFibGUgY2xhc3MgdGhhdCBiZWhhdmVzIGxpa2UgYSBQcm9taXNlIGFuZCBmb2xsb3dzIGl0J3MgaW50ZXJmYWNlCiAqIGJ1dCBpcyBub3QgYXN5bmMgaW50ZXJuYWxseQogKi8KY2xhc3MgU3luY1Byb21pc2UgewoKICAgY29uc3RydWN0b3IoCiAgICBleGVjdXRvciwKICApIHtTeW5jUHJvbWlzZS5wcm90b3R5cGUuX19pbml0LmNhbGwodGhpcyk7U3luY1Byb21pc2UucHJvdG90eXBlLl9faW5pdDIuY2FsbCh0aGlzKTtTeW5jUHJvbWlzZS5wcm90b3R5cGUuX19pbml0My5jYWxsKHRoaXMpO1N5bmNQcm9taXNlLnByb3RvdHlwZS5fX2luaXQ0LmNhbGwodGhpcyk7CiAgICB0aGlzLl9zdGF0ZSA9IFN0YXRlcy5QRU5ESU5HOwogICAgdGhpcy5faGFuZGxlcnMgPSBbXTsKCiAgICB0cnkgewogICAgICBleGVjdXRvcih0aGlzLl9yZXNvbHZlLCB0aGlzLl9yZWplY3QpOwogICAgfSBjYXRjaCAoZSkgewogICAgICB0aGlzLl9yZWplY3QoZSk7CiAgICB9CiAgfQoKICAvKiogSlNEb2MgKi8KICAgdGhlbigKICAgIG9uZnVsZmlsbGVkLAogICAgb25yZWplY3RlZCwKICApIHsKICAgIHJldHVybiBuZXcgU3luY1Byb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICB0aGlzLl9oYW5kbGVycy5wdXNoKFsKICAgICAgICBmYWxzZSwKICAgICAgICByZXN1bHQgPT4gewogICAgICAgICAgaWYgKCFvbmZ1bGZpbGxlZCkgewogICAgICAgICAgICAvLyBUT0RPOiDCr1xfKOODhClfL8KvCiAgICAgICAgICAgIC8vIFRPRE86IEZJWE1FCiAgICAgICAgICAgIHJlc29sdmUocmVzdWx0ICk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHJlc29sdmUob25mdWxmaWxsZWQocmVzdWx0KSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICByZWplY3QoZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHJlYXNvbiA9PiB7CiAgICAgICAgICBpZiAoIW9ucmVqZWN0ZWQpIHsKICAgICAgICAgICAgcmVqZWN0KHJlYXNvbik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHJlc29sdmUob25yZWplY3RlZChyZWFzb24pKTsKICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgIF0pOwogICAgICB0aGlzLl9leGVjdXRlSGFuZGxlcnMoKTsKICAgIH0pOwogIH0KCiAgLyoqIEpTRG9jICovCiAgIGNhdGNoKAogICAgb25yZWplY3RlZCwKICApIHsKICAgIHJldHVybiB0aGlzLnRoZW4odmFsID0+IHZhbCwgb25yZWplY3RlZCk7CiAgfQoKICAvKiogSlNEb2MgKi8KICAgZmluYWxseShvbmZpbmFsbHkpIHsKICAgIHJldHVybiBuZXcgU3luY1Byb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICBsZXQgdmFsOwogICAgICBsZXQgaXNSZWplY3RlZDsKCiAgICAgIHJldHVybiB0aGlzLnRoZW4oCiAgICAgICAgdmFsdWUgPT4gewogICAgICAgICAgaXNSZWplY3RlZCA9IGZhbHNlOwogICAgICAgICAgdmFsID0gdmFsdWU7CiAgICAgICAgICBpZiAob25maW5hbGx5KSB7CiAgICAgICAgICAgIG9uZmluYWxseSgpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgcmVhc29uID0+IHsKICAgICAgICAgIGlzUmVqZWN0ZWQgPSB0cnVlOwogICAgICAgICAgdmFsID0gcmVhc29uOwogICAgICAgICAgaWYgKG9uZmluYWxseSkgewogICAgICAgICAgICBvbmZpbmFsbHkoKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICApLnRoZW4oKCkgPT4gewogICAgICAgIGlmIChpc1JlamVjdGVkKSB7CiAgICAgICAgICByZWplY3QodmFsKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJlc29sdmUodmFsICk7CiAgICAgIH0pOwogICAgfSk7CiAgfQoKICAvKiogSlNEb2MgKi8KICAgIF9faW5pdCgpIHt0aGlzLl9yZXNvbHZlID0gKHZhbHVlKSA9PiB7CiAgICB0aGlzLl9zZXRSZXN1bHQoU3RhdGVzLlJFU09MVkVELCB2YWx1ZSk7CiAgfTt9CgogIC8qKiBKU0RvYyAqLwogICAgX19pbml0MigpIHt0aGlzLl9yZWplY3QgPSAocmVhc29uKSA9PiB7CiAgICB0aGlzLl9zZXRSZXN1bHQoU3RhdGVzLlJFSkVDVEVELCByZWFzb24pOwogIH07fQoKICAvKiogSlNEb2MgKi8KICAgIF9faW5pdDMoKSB7dGhpcy5fc2V0UmVzdWx0ID0gKHN0YXRlLCB2YWx1ZSkgPT4gewogICAgaWYgKHRoaXMuX3N0YXRlICE9PSBTdGF0ZXMuUEVORElORykgewogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGlzVGhlbmFibGUodmFsdWUpKSB7CiAgICAgIHZvaWQgKHZhbHVlICkudGhlbih0aGlzLl9yZXNvbHZlLCB0aGlzLl9yZWplY3QpOwogICAgICByZXR1cm47CiAgICB9CgogICAgdGhpcy5fc3RhdGUgPSBzdGF0ZTsKICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7CgogICAgdGhpcy5fZXhlY3V0ZUhhbmRsZXJzKCk7CiAgfTt9CgogIC8qKiBKU0RvYyAqLwogICAgX19pbml0NCgpIHt0aGlzLl9leGVjdXRlSGFuZGxlcnMgPSAoKSA9PiB7CiAgICBpZiAodGhpcy5fc3RhdGUgPT09IFN0YXRlcy5QRU5ESU5HKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBjb25zdCBjYWNoZWRIYW5kbGVycyA9IHRoaXMuX2hhbmRsZXJzLnNsaWNlKCk7CiAgICB0aGlzLl9oYW5kbGVycyA9IFtdOwoKICAgIGNhY2hlZEhhbmRsZXJzLmZvckVhY2goaGFuZGxlciA9PiB7CiAgICAgIGlmIChoYW5kbGVyWzBdKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFN0YXRlcy5SRVNPTFZFRCkgewogICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZmxvYXRpbmctcHJvbWlzZXMKICAgICAgICBoYW5kbGVyWzFdKHRoaXMuX3ZhbHVlICk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gU3RhdGVzLlJFSkVDVEVEKSB7CiAgICAgICAgaGFuZGxlclsyXSh0aGlzLl92YWx1ZSk7CiAgICAgIH0KCiAgICAgIGhhbmRsZXJbMF0gPSB0cnVlOwogICAgfSk7CiAgfTt9Cn0KCi8qKgogKiBDcmVhdGVzIGFuIG5ldyBQcm9taXNlQnVmZmVyIG9iamVjdCB3aXRoIHRoZSBzcGVjaWZpZWQgbGltaXQKICogQHBhcmFtIGxpbWl0IG1heCBudW1iZXIgb2YgcHJvbWlzZXMgdGhhdCBjYW4gYmUgc3RvcmVkIGluIHRoZSBidWZmZXIKICovCmZ1bmN0aW9uIG1ha2VQcm9taXNlQnVmZmVyKGxpbWl0KSB7CiAgY29uc3QgYnVmZmVyID0gW107CgogIGZ1bmN0aW9uIGlzUmVhZHkoKSB7CiAgICByZXR1cm4gbGltaXQgPT09IHVuZGVmaW5lZCB8fCBidWZmZXIubGVuZ3RoIDwgbGltaXQ7CiAgfQoKICAvKioKICAgKiBSZW1vdmUgYSBwcm9taXNlIGZyb20gdGhlIHF1ZXVlLgogICAqCiAgICogQHBhcmFtIHRhc2sgQ2FuIGJlIGFueSBQcm9taXNlTGlrZTxUPgogICAqIEByZXR1cm5zIFJlbW92ZWQgcHJvbWlzZS4KICAgKi8KICBmdW5jdGlvbiByZW1vdmUodGFzaykgewogICAgcmV0dXJuIGJ1ZmZlci5zcGxpY2UoYnVmZmVyLmluZGV4T2YodGFzayksIDEpWzBdOwogIH0KCiAgLyoqCiAgICogQWRkIGEgcHJvbWlzZSAocmVwcmVzZW50aW5nIGFuIGluLWZsaWdodCBhY3Rpb24pIHRvIHRoZSBxdWV1ZSwgYW5kIHNldCBpdCB0byByZW1vdmUgaXRzZWxmIG9uIGZ1bGZpbGxtZW50LgogICAqCiAgICogQHBhcmFtIHRhc2tQcm9kdWNlciBBIGZ1bmN0aW9uIHByb2R1Y2luZyBhbnkgUHJvbWlzZUxpa2U8VD47IEluIHByZXZpb3VzIHZlcnNpb25zIHRoaXMgdXNlZCB0byBiZSBgdGFzazoKICAgKiAgICAgICAgUHJvbWlzZUxpa2U8VD5gLCBidXQgdW5kZXIgdGhhdCBtb2RlbCwgUHJvbWlzZXMgd2VyZSBpbnN0YW50bHkgY3JlYXRlZCBvbiB0aGUgY2FsbC1zaXRlIGFuZCB0aGVpciBleGVjdXRvcgogICAqICAgICAgICBmdW5jdGlvbnMgdGhlcmVmb3JlIHJhbiBpbW1lZGlhdGVseS4gVGh1cywgZXZlbiBpZiB0aGUgYnVmZmVyIHdhcyBmdWxsLCB0aGUgYWN0aW9uIHN0aWxsIGhhcHBlbmVkLiBCeQogICAqICAgICAgICByZXF1aXJpbmcgdGhlIHByb21pc2UgdG8gYmUgd3JhcHBlZCBpbiBhIGZ1bmN0aW9uLCB3ZSBjYW4gZGVmZXIgcHJvbWlzZSBjcmVhdGlvbiB1bnRpbCBhZnRlciB0aGUgYnVmZmVyCiAgICogICAgICAgIGxpbWl0IGNoZWNrLgogICAqIEByZXR1cm5zIFRoZSBvcmlnaW5hbCBwcm9taXNlLgogICAqLwogIGZ1bmN0aW9uIGFkZCh0YXNrUHJvZHVjZXIpIHsKICAgIGlmICghaXNSZWFkeSgpKSB7CiAgICAgIHJldHVybiByZWplY3RlZFN5bmNQcm9taXNlKG5ldyBTZW50cnlFcnJvcignTm90IGFkZGluZyBQcm9taXNlIGJlY2F1c2UgYnVmZmVyIGxpbWl0IHdhcyByZWFjaGVkLicpKTsKICAgIH0KCiAgICAvLyBzdGFydCB0aGUgdGFzayBhbmQgYWRkIGl0cyBwcm9taXNlIHRvIHRoZSBxdWV1ZQogICAgY29uc3QgdGFzayA9IHRhc2tQcm9kdWNlcigpOwogICAgaWYgKGJ1ZmZlci5pbmRleE9mKHRhc2spID09PSAtMSkgewogICAgICBidWZmZXIucHVzaCh0YXNrKTsKICAgIH0KICAgIHZvaWQgdGFzawogICAgICAudGhlbigoKSA9PiByZW1vdmUodGFzaykpCiAgICAgIC8vIFVzZSBgdGhlbihudWxsLCByZWplY3Rpb25IYW5kbGVyKWAgcmF0aGVyIHRoYW4gYGNhdGNoKHJlamVjdGlvbkhhbmRsZXIpYCBzbyB0aGF0IHdlIGNhbiB1c2UgYFByb21pc2VMaWtlYAogICAgICAvLyByYXRoZXIgdGhhbiBgUHJvbWlzZWAuIGBQcm9taXNlTGlrZWAgZG9lc24ndCBoYXZlIGEgYC5jYXRjaGAgbWV0aG9kLCBtYWtpbmcgaXRzIHBvbHlmaWxsIHNtYWxsZXIuIChFUzUgZGlkbid0CiAgICAgIC8vIGhhdmUgcHJvbWlzZXMsIHNvIFRTIGhhcyB0byBwb2x5ZmlsbCB3aGVuIGRvd24tY29tcGlsaW5nLikKICAgICAgLnRoZW4obnVsbCwgKCkgPT4KICAgICAgICByZW1vdmUodGFzaykudGhlbihudWxsLCAoKSA9PiB7CiAgICAgICAgICAvLyBXZSBoYXZlIHRvIGFkZCBhbm90aGVyIGNhdGNoIGhlcmUgYmVjYXVzZSBgcmVtb3ZlKClgIHN0YXJ0cyBhIG5ldyBwcm9taXNlIGNoYWluLgogICAgICAgIH0pLAogICAgICApOwogICAgcmV0dXJuIHRhc2s7CiAgfQoKICAvKioKICAgKiBXYWl0IGZvciBhbGwgcHJvbWlzZXMgaW4gdGhlIHF1ZXVlIHRvIHJlc29sdmUgb3IgZm9yIHRpbWVvdXQgdG8gZXhwaXJlLCB3aGljaGV2ZXIgY29tZXMgZmlyc3QuCiAgICoKICAgKiBAcGFyYW0gdGltZW91dCBUaGUgdGltZSwgaW4gbXMsIGFmdGVyIHdoaWNoIHRvIHJlc29sdmUgdG8gYGZhbHNlYCBpZiB0aGUgcXVldWUgaXMgc3RpbGwgbm9uLWVtcHR5LiBQYXNzaW5nIGAwYCAob3IKICAgKiBub3QgcGFzc2luZyBhbnl0aGluZykgd2lsbCBtYWtlIHRoZSBwcm9taXNlIHdhaXQgYXMgbG9uZyBhcyBpdCB0YWtlcyBmb3IgdGhlIHF1ZXVlIHRvIGRyYWluIGJlZm9yZSByZXNvbHZpbmcgdG8KICAgKiBgdHJ1ZWAuCiAgICogQHJldHVybnMgQSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB0byBgdHJ1ZWAgaWYgdGhlIHF1ZXVlIGlzIGFscmVhZHkgZW1wdHkgb3IgZHJhaW5zIGJlZm9yZSB0aGUgdGltZW91dCwgYW5kCiAgICogYGZhbHNlYCBvdGhlcndpc2UKICAgKi8KICBmdW5jdGlvbiBkcmFpbih0aW1lb3V0KSB7CiAgICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgbGV0IGNvdW50ZXIgPSBidWZmZXIubGVuZ3RoOwoKICAgICAgaWYgKCFjb3VudGVyKSB7CiAgICAgICAgcmV0dXJuIHJlc29sdmUodHJ1ZSk7CiAgICAgIH0KCiAgICAgIC8vIHdhaXQgZm9yIGB0aW1lb3V0YCBtcyBhbmQgdGhlbiByZXNvbHZlIHRvIGBmYWxzZWAgKGlmIG5vdCBjYW5jZWxsZWQgZmlyc3QpCiAgICAgIGNvbnN0IGNhcHR1cmVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgIGlmICh0aW1lb3V0ICYmIHRpbWVvdXQgPiAwKSB7CiAgICAgICAgICByZXNvbHZlKGZhbHNlKTsKICAgICAgICB9CiAgICAgIH0sIHRpbWVvdXQpOwoKICAgICAgLy8gaWYgYWxsIHByb21pc2VzIHJlc29sdmUgaW4gdGltZSwgY2FuY2VsIHRoZSB0aW1lciBhbmQgcmVzb2x2ZSB0byBgdHJ1ZWAKICAgICAgYnVmZmVyLmZvckVhY2goaXRlbSA9PiB7CiAgICAgICAgdm9pZCByZXNvbHZlZFN5bmNQcm9taXNlKGl0ZW0pLnRoZW4oKCkgPT4gewogICAgICAgICAgaWYgKCEtLWNvdW50ZXIpIHsKICAgICAgICAgICAgY2xlYXJUaW1lb3V0KGNhcHR1cmVkU2V0VGltZW91dCk7CiAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfSk7CiAgICB9KTsKICB9CgogIHJldHVybiB7CiAgICAkOiBidWZmZXIsCiAgICBhZGQsCiAgICBkcmFpbiwKICB9Owp9Cgpjb25zdCBPTkVfU0VDT05EX0lOX01TID0gMTAwMDsKCi8qKgogKiBBIHBhcnRpYWwgZGVmaW5pdGlvbiBvZiB0aGUgW1BlcmZvcm1hbmNlIFdlYiBBUElde0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9QZXJmb3JtYW5jZX0KICogZm9yIGFjY2Vzc2luZyBhIGhpZ2gtcmVzb2x1dGlvbiBtb25vdG9uaWMgY2xvY2suCiAqLwoKLyoqCiAqIFJldHVybnMgYSB0aW1lc3RhbXAgaW4gc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaCB1c2luZyB0aGUgRGF0ZSBBUEkuCiAqCiAqIFRPRE8odjgpOiBSZXR1cm4gdHlwZSBzaG91bGQgYmUgcm91bmRlZC4KICovCmZ1bmN0aW9uIGRhdGVUaW1lc3RhbXBJblNlY29uZHMoKSB7CiAgcmV0dXJuIERhdGUubm93KCkgLyBPTkVfU0VDT05EX0lOX01TOwp9CgovKioKICogUmV0dXJucyBhIHdyYXBwZXIgYXJvdW5kIHRoZSBuYXRpdmUgUGVyZm9ybWFuY2UgQVBJIGJyb3dzZXIgaW1wbGVtZW50YXRpb24sIG9yIHVuZGVmaW5lZCBmb3IgYnJvd3NlcnMgdGhhdCBkbyBub3QKICogc3VwcG9ydCB0aGUgQVBJLgogKgogKiBXcmFwcGluZyB0aGUgbmF0aXZlIEFQSSB3b3JrcyBhcm91bmQgZGlmZmVyZW5jZXMgaW4gYmVoYXZpb3IgZnJvbSBkaWZmZXJlbnQgYnJvd3NlcnMuCiAqLwpmdW5jdGlvbiBjcmVhdGVVbml4VGltZXN0YW1wSW5TZWNvbmRzRnVuYygpIHsKICBjb25zdCB7IHBlcmZvcm1hbmNlIH0gPSBHTE9CQUxfT0JKIDsKICBpZiAoIXBlcmZvcm1hbmNlIHx8ICFwZXJmb3JtYW5jZS5ub3cpIHsKICAgIHJldHVybiBkYXRlVGltZXN0YW1wSW5TZWNvbmRzOwogIH0KCiAgLy8gU29tZSBicm93c2VyIGFuZCBlbnZpcm9ubWVudHMgZG9uJ3QgaGF2ZSBhIHRpbWVPcmlnaW4sIHNvIHdlIGZhbGxiYWNrIHRvCiAgLy8gdXNpbmcgRGF0ZS5ub3coKSB0byBjb21wdXRlIHRoZSBzdGFydGluZyB0aW1lLgogIGNvbnN0IGFwcHJveFN0YXJ0aW5nVGltZU9yaWdpbiA9IERhdGUubm93KCkgLSBwZXJmb3JtYW5jZS5ub3coKTsKICBjb25zdCB0aW1lT3JpZ2luID0gcGVyZm9ybWFuY2UudGltZU9yaWdpbiA9PSB1bmRlZmluZWQgPyBhcHByb3hTdGFydGluZ1RpbWVPcmlnaW4gOiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luOwoKICAvLyBwZXJmb3JtYW5jZS5ub3coKSBpcyBhIG1vbm90b25pYyBjbG9jaywgd2hpY2ggbWVhbnMgaXQgc3RhcnRzIGF0IDAgd2hlbiB0aGUgcHJvY2VzcyBiZWdpbnMuIFRvIGdldCB0aGUgY3VycmVudAogIC8vIHdhbGwgY2xvY2sgdGltZSAoYWN0dWFsIFVOSVggdGltZXN0YW1wKSwgd2UgbmVlZCB0byBhZGQgdGhlIHN0YXJ0aW5nIHRpbWUgb3JpZ2luIGFuZCB0aGUgY3VycmVudCB0aW1lIGVsYXBzZWQuCiAgLy8KICAvLyBUT0RPOiBUaGlzIGRvZXMgbm90IGFjY291bnQgZm9yIHRoZSBjYXNlIHdoZXJlIHRoZSBtb25vdG9uaWMgY2xvY2sgdGhhdCBwb3dlcnMgcGVyZm9ybWFuY2Uubm93KCkgZHJpZnRzIGZyb20gdGhlCiAgLy8gd2FsbCBjbG9jayB0aW1lLCB3aGljaCBjYXVzZXMgdGhlIHJldHVybmVkIHRpbWVzdGFtcCB0byBiZSBpbmFjY3VyYXRlLiBXZSBzaG91bGQgaW52ZXN0aWdhdGUgaG93IHRvIGRldGVjdCBhbmQKICAvLyBjb3JyZWN0IGZvciB0aGlzLgogIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvMjU5MAogIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL21kbi9jb250ZW50L2lzc3Vlcy80NzEzCiAgLy8gU2VlOiBodHRwczovL2Rldi50by9ub2Ftci93aGVuLWEtbWlsbGlzZWNvbmQtaXMtbm90LWEtbWlsbGlzZWNvbmQtM2g2CiAgcmV0dXJuICgpID0+IHsKICAgIHJldHVybiAodGltZU9yaWdpbiArIHBlcmZvcm1hbmNlLm5vdygpKSAvIE9ORV9TRUNPTkRfSU5fTVM7CiAgfTsKfQoKLyoqCiAqIFJldHVybnMgYSB0aW1lc3RhbXAgaW4gc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaCB1c2luZyBlaXRoZXIgdGhlIFBlcmZvcm1hbmNlIG9yIERhdGUgQVBJcywgZGVwZW5kaW5nIG9uIHRoZQogKiBhdmFpbGFiaWxpdHkgb2YgdGhlIFBlcmZvcm1hbmNlIEFQSS4KICoKICogQlVHOiBOb3RlIHRoYXQgYmVjYXVzZSBvZiBob3cgYnJvd3NlcnMgaW1wbGVtZW50IHRoZSBQZXJmb3JtYW5jZSBBUEksIHRoZSBjbG9jayBtaWdodCBzdG9wIHdoZW4gdGhlIGNvbXB1dGVyIGlzCiAqIGFzbGVlcC4gVGhpcyBjcmVhdGVzIGEgc2tldyBiZXR3ZWVuIGBkYXRlVGltZXN0YW1wSW5TZWNvbmRzYCBhbmQgYHRpbWVzdGFtcEluU2Vjb25kc2AuIFRoZQogKiBza2V3IGNhbiBncm93IHRvIGFyYml0cmFyeSBhbW91bnRzIGxpa2UgZGF5cywgd2Vla3Mgb3IgbW9udGhzLgogKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvMjU5MC4KICovCmNvbnN0IHRpbWVzdGFtcEluU2Vjb25kcyA9IGNyZWF0ZVVuaXhUaW1lc3RhbXBJblNlY29uZHNGdW5jKCk7CgovKioKICogVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgc2luY2UgdGhlIFVOSVggZXBvY2guIFRoaXMgdmFsdWUgaXMgb25seSB1c2FibGUgaW4gYSBicm93c2VyLCBhbmQgb25seSB3aGVuIHRoZQogKiBwZXJmb3JtYW5jZSBBUEkgaXMgYXZhaWxhYmxlLgogKi8KKCgpID0+IHsKICAvLyBVbmZvcnR1bmF0ZWx5IGJyb3dzZXJzIG1heSByZXBvcnQgYW4gaW5hY2N1cmF0ZSB0aW1lIG9yaWdpbiBkYXRhLCB0aHJvdWdoIGVpdGhlciBwZXJmb3JtYW5jZS50aW1lT3JpZ2luIG9yCiAgLy8gcGVyZm9ybWFuY2UudGltaW5nLm5hdmlnYXRpb25TdGFydCwgd2hpY2ggcmVzdWx0cyBpbiBwb29yIHJlc3VsdHMgaW4gcGVyZm9ybWFuY2UgZGF0YS4gV2Ugb25seSB0cmVhdCB0aW1lIG9yaWdpbgogIC8vIGRhdGEgYXMgcmVsaWFibGUgaWYgdGhleSBhcmUgd2l0aGluIGEgcmVhc29uYWJsZSB0aHJlc2hvbGQgb2YgdGhlIGN1cnJlbnQgdGltZS4KCiAgY29uc3QgeyBwZXJmb3JtYW5jZSB9ID0gR0xPQkFMX09CSiA7CiAgaWYgKCFwZXJmb3JtYW5jZSB8fCAhcGVyZm9ybWFuY2Uubm93KSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KCiAgY29uc3QgdGhyZXNob2xkID0gMzYwMCAqIDEwMDA7CiAgY29uc3QgcGVyZm9ybWFuY2VOb3cgPSBwZXJmb3JtYW5jZS5ub3coKTsKICBjb25zdCBkYXRlTm93ID0gRGF0ZS5ub3coKTsKCiAgLy8gaWYgdGltZU9yaWdpbiBpc24ndCBhdmFpbGFibGUgc2V0IGRlbHRhIHRvIHRocmVzaG9sZCBzbyBpdCBpc24ndCB1c2VkCiAgY29uc3QgdGltZU9yaWdpbkRlbHRhID0gcGVyZm9ybWFuY2UudGltZU9yaWdpbgogICAgPyBNYXRoLmFicyhwZXJmb3JtYW5jZS50aW1lT3JpZ2luICsgcGVyZm9ybWFuY2VOb3cgLSBkYXRlTm93KQogICAgOiB0aHJlc2hvbGQ7CiAgY29uc3QgdGltZU9yaWdpbklzUmVsaWFibGUgPSB0aW1lT3JpZ2luRGVsdGEgPCB0aHJlc2hvbGQ7CgogIC8vIFdoaWxlIHBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQgaXMgZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luLCBwZXJmb3JtYW5jZS50aW1lT3JpZ2luCiAgLy8gaXMgbm90IGFzIHdpZGVseSBzdXBwb3J0ZWQuIE5hbWVseSwgcGVyZm9ybWFuY2UudGltZU9yaWdpbiBpcyB1bmRlZmluZWQgaW4gU2FmYXJpIGFzIG9mIHdyaXRpbmcuCiAgLy8gQWxzbyBhcyBvZiB3cml0aW5nLCBwZXJmb3JtYW5jZS50aW1pbmcgaXMgbm90IGF2YWlsYWJsZSBpbiBXZWIgV29ya2VycyBpbiBtYWluc3RyZWFtIGJyb3dzZXJzLCBzbyBpdCBpcyBub3QgYWx3YXlzCiAgLy8gYSB2YWxpZCBmYWxsYmFjay4gSW4gdGhlIGFic2VuY2Ugb2YgYW4gaW5pdGlhbCB0aW1lIHByb3ZpZGVkIGJ5IHRoZSBicm93c2VyLCBmYWxsYmFjayB0byB0aGUgY3VycmVudCB0aW1lIGZyb20gdGhlCiAgLy8gRGF0ZSBBUEkuCiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgY29uc3QgbmF2aWdhdGlvblN0YXJ0ID0gcGVyZm9ybWFuY2UudGltaW5nICYmIHBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQ7CiAgY29uc3QgaGFzTmF2aWdhdGlvblN0YXJ0ID0gdHlwZW9mIG5hdmlnYXRpb25TdGFydCA9PT0gJ251bWJlcic7CiAgLy8gaWYgbmF2aWdhdGlvblN0YXJ0IGlzbid0IGF2YWlsYWJsZSBzZXQgZGVsdGEgdG8gdGhyZXNob2xkIHNvIGl0IGlzbid0IHVzZWQKICBjb25zdCBuYXZpZ2F0aW9uU3RhcnREZWx0YSA9IGhhc05hdmlnYXRpb25TdGFydCA/IE1hdGguYWJzKG5hdmlnYXRpb25TdGFydCArIHBlcmZvcm1hbmNlTm93IC0gZGF0ZU5vdykgOiB0aHJlc2hvbGQ7CiAgY29uc3QgbmF2aWdhdGlvblN0YXJ0SXNSZWxpYWJsZSA9IG5hdmlnYXRpb25TdGFydERlbHRhIDwgdGhyZXNob2xkOwoKICBpZiAodGltZU9yaWdpbklzUmVsaWFibGUgfHwgbmF2aWdhdGlvblN0YXJ0SXNSZWxpYWJsZSkgewogICAgLy8gVXNlIHRoZSBtb3JlIHJlbGlhYmxlIHRpbWUgb3JpZ2luCiAgICBpZiAodGltZU9yaWdpbkRlbHRhIDw9IG5hdmlnYXRpb25TdGFydERlbHRhKSB7CiAgICAgIHJldHVybiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5hdmlnYXRpb25TdGFydDsKICAgIH0KICB9CiAgcmV0dXJuIGRhdGVOb3c7Cn0pKCk7CgovKioKICogQ3JlYXRlcyBhbiBlbnZlbG9wZS4KICogTWFrZSBzdXJlIHRvIGFsd2F5cyBleHBsaWNpdGx5IHByb3ZpZGUgdGhlIGdlbmVyaWMgdG8gdGhpcyBmdW5jdGlvbgogKiBzbyB0aGF0IHRoZSBlbnZlbG9wZSB0eXBlcyByZXNvbHZlIGNvcnJlY3RseS4KICovCmZ1bmN0aW9uIGNyZWF0ZUVudmVsb3BlKGhlYWRlcnMsIGl0ZW1zID0gW10pIHsKICByZXR1cm4gW2hlYWRlcnMsIGl0ZW1zXSA7Cn0KCi8qKgogKiBDb252ZW5pZW5jZSBmdW5jdGlvbiB0byBsb29wIHRocm91Z2ggdGhlIGl0ZW1zIGFuZCBpdGVtIHR5cGVzIG9mIGFuIGVudmVsb3BlLgogKiAoVGhpcyBmdW5jdGlvbiB3YXMgbW9zdGx5IGNyZWF0ZWQgYmVjYXVzZSB3b3JraW5nIHdpdGggZW52ZWxvcGUgdHlwZXMgaXMgcGFpbmZ1bCBhdCB0aGUgbW9tZW50KQogKgogKiBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVlLCB0aGUgcmVzdCBvZiB0aGUgaXRlbXMgd2lsbCBiZSBza2lwcGVkLgogKi8KZnVuY3Rpb24gZm9yRWFjaEVudmVsb3BlSXRlbSgKICBlbnZlbG9wZSwKICBjYWxsYmFjaywKKSB7CiAgY29uc3QgZW52ZWxvcGVJdGVtcyA9IGVudmVsb3BlWzFdOwoKICBmb3IgKGNvbnN0IGVudmVsb3BlSXRlbSBvZiBlbnZlbG9wZUl0ZW1zKSB7CiAgICBjb25zdCBlbnZlbG9wZUl0ZW1UeXBlID0gZW52ZWxvcGVJdGVtWzBdLnR5cGU7CiAgICBjb25zdCByZXN1bHQgPSBjYWxsYmFjayhlbnZlbG9wZUl0ZW0sIGVudmVsb3BlSXRlbVR5cGUpOwoKICAgIGlmIChyZXN1bHQpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgfQoKICByZXR1cm4gZmFsc2U7Cn0KCi8qKgogKiBFbmNvZGUgYSBzdHJpbmcgdG8gVVRGOC4KICovCmZ1bmN0aW9uIGVuY29kZVVURjgoaW5wdXQsIHRleHRFbmNvZGVyKSB7CiAgY29uc3QgdXRmOCA9IHRleHRFbmNvZGVyIHx8IG5ldyBUZXh0RW5jb2RlcigpOwogIHJldHVybiB1dGY4LmVuY29kZShpbnB1dCk7Cn0KCi8qKgogKiBTZXJpYWxpemVzIGFuIGVudmVsb3BlLgogKi8KZnVuY3Rpb24gc2VyaWFsaXplRW52ZWxvcGUoZW52ZWxvcGUsIHRleHRFbmNvZGVyKSB7CiAgY29uc3QgW2VudkhlYWRlcnMsIGl0ZW1zXSA9IGVudmVsb3BlOwoKICAvLyBJbml0aWFsbHkgd2UgY29uc3RydWN0IG91ciBlbnZlbG9wZSBhcyBhIHN0cmluZyBhbmQgb25seSBjb252ZXJ0IHRvIGJpbmFyeSBjaHVua3MgaWYgd2UgZW5jb3VudGVyIGJpbmFyeSBkYXRhCiAgbGV0IHBhcnRzID0gSlNPTi5zdHJpbmdpZnkoZW52SGVhZGVycyk7CgogIGZ1bmN0aW9uIGFwcGVuZChuZXh0KSB7CiAgICBpZiAodHlwZW9mIHBhcnRzID09PSAnc3RyaW5nJykgewogICAgICBwYXJ0cyA9IHR5cGVvZiBuZXh0ID09PSAnc3RyaW5nJyA/IHBhcnRzICsgbmV4dCA6IFtlbmNvZGVVVEY4KHBhcnRzLCB0ZXh0RW5jb2RlciksIG5leHRdOwogICAgfSBlbHNlIHsKICAgICAgcGFydHMucHVzaCh0eXBlb2YgbmV4dCA9PT0gJ3N0cmluZycgPyBlbmNvZGVVVEY4KG5leHQsIHRleHRFbmNvZGVyKSA6IG5leHQpOwogICAgfQogIH0KCiAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7CiAgICBjb25zdCBbaXRlbUhlYWRlcnMsIHBheWxvYWRdID0gaXRlbTsKCiAgICBhcHBlbmQoYFxuJHtKU09OLnN0cmluZ2lmeShpdGVtSGVhZGVycyl9XG5gKTsKCiAgICBpZiAodHlwZW9mIHBheWxvYWQgPT09ICdzdHJpbmcnIHx8IHBheWxvYWQgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICAgIGFwcGVuZChwYXlsb2FkKTsKICAgIH0gZWxzZSB7CiAgICAgIGxldCBzdHJpbmdpZmllZFBheWxvYWQ7CiAgICAgIHRyeSB7CiAgICAgICAgc3RyaW5naWZpZWRQYXlsb2FkID0gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAvLyBJbiBjYXNlLCBkZXNwaXRlIGFsbCBvdXIgZWZmb3J0cyB0byBrZWVwIGBwYXlsb2FkYCBjaXJjdWxhci1kZXBlbmRlbmN5LWZyZWUsIGBKU09OLnN0cmluaWZ5KClgIHN0aWxsCiAgICAgICAgLy8gZmFpbHMsIHdlIHRyeSBhZ2FpbiBhZnRlciBub3JtYWxpemluZyBpdCBhZ2FpbiB3aXRoIGluZmluaXRlIG5vcm1hbGl6YXRpb24gZGVwdGguIFRoaXMgb2YgY291cnNlIGhhcyBhCiAgICAgICAgLy8gcGVyZm9ybWFuY2UgaW1wYWN0IGJ1dCBpbiB0aGlzIGNhc2UgYSBwZXJmb3JtYW5jZSBoaXQgaXMgYmV0dGVyIHRoYW4gdGhyb3dpbmcuCiAgICAgICAgc3RyaW5naWZpZWRQYXlsb2FkID0gSlNPTi5zdHJpbmdpZnkobm9ybWFsaXplKHBheWxvYWQpKTsKICAgICAgfQogICAgICBhcHBlbmQoc3RyaW5naWZpZWRQYXlsb2FkKTsKICAgIH0KICB9CgogIHJldHVybiB0eXBlb2YgcGFydHMgPT09ICdzdHJpbmcnID8gcGFydHMgOiBjb25jYXRCdWZmZXJzKHBhcnRzKTsKfQoKZnVuY3Rpb24gY29uY2F0QnVmZmVycyhidWZmZXJzKSB7CiAgY29uc3QgdG90YWxMZW5ndGggPSBidWZmZXJzLnJlZHVjZSgoYWNjLCBidWYpID0+IGFjYyArIGJ1Zi5sZW5ndGgsIDApOwoKICBjb25zdCBtZXJnZWQgPSBuZXcgVWludDhBcnJheSh0b3RhbExlbmd0aCk7CiAgbGV0IG9mZnNldCA9IDA7CiAgZm9yIChjb25zdCBidWZmZXIgb2YgYnVmZmVycykgewogICAgbWVyZ2VkLnNldChidWZmZXIsIG9mZnNldCk7CiAgICBvZmZzZXQgKz0gYnVmZmVyLmxlbmd0aDsKICB9CgogIHJldHVybiBtZXJnZWQ7Cn0KCmNvbnN0IElURU1fVFlQRV9UT19EQVRBX0NBVEVHT1JZX01BUCA9IHsKICBzZXNzaW9uOiAnc2Vzc2lvbicsCiAgc2Vzc2lvbnM6ICdzZXNzaW9uJywKICBhdHRhY2htZW50OiAnYXR0YWNobWVudCcsCiAgdHJhbnNhY3Rpb246ICd0cmFuc2FjdGlvbicsCiAgZXZlbnQ6ICdlcnJvcicsCiAgY2xpZW50X3JlcG9ydDogJ2ludGVybmFsJywKICB1c2VyX3JlcG9ydDogJ2RlZmF1bHQnLAogIHByb2ZpbGU6ICdwcm9maWxlJywKICByZXBsYXlfZXZlbnQ6ICdyZXBsYXknLAogIHJlcGxheV9yZWNvcmRpbmc6ICdyZXBsYXknLAogIGNoZWNrX2luOiAnbW9uaXRvcicsCiAgZmVlZGJhY2s6ICdmZWVkYmFjaycsCiAgc3BhbjogJ3NwYW4nLAogIC8vIFRPRE86IFRoaXMgaXMgYSB0ZW1wb3Jhcnkgd29ya2Fyb3VuZCB1bnRpbCB3ZSBoYXZlIGEgcHJvcGVyIGRhdGEgY2F0ZWdvcnkgZm9yIG1ldHJpY3MKICBzdGF0c2Q6ICd1bmtub3duJywKfTsKCi8qKgogKiBNYXBzIHRoZSB0eXBlIG9mIGFuIGVudmVsb3BlIGl0ZW0gdG8gYSBkYXRhIGNhdGVnb3J5LgogKi8KZnVuY3Rpb24gZW52ZWxvcGVJdGVtVHlwZVRvRGF0YUNhdGVnb3J5KHR5cGUpIHsKICByZXR1cm4gSVRFTV9UWVBFX1RPX0RBVEFfQ0FURUdPUllfTUFQW3R5cGVdOwp9CgovKiogRXh0cmFjdHMgdGhlIG1pbmltYWwgU0RLIGluZm8gZnJvbSBmcm9tIHRoZSBtZXRhZGF0YSBvciBhbiBldmVudHMgKi8KZnVuY3Rpb24gZ2V0U2RrTWV0YWRhdGFGb3JFbnZlbG9wZUhlYWRlcihtZXRhZGF0YU9yRXZlbnQpIHsKICBpZiAoIW1ldGFkYXRhT3JFdmVudCB8fCAhbWV0YWRhdGFPckV2ZW50LnNkaykgewogICAgcmV0dXJuOwogIH0KICBjb25zdCB7IG5hbWUsIHZlcnNpb24gfSA9IG1ldGFkYXRhT3JFdmVudC5zZGs7CiAgcmV0dXJuIHsgbmFtZSwgdmVyc2lvbiB9Owp9CgovKioKICogQ3JlYXRlcyBldmVudCBlbnZlbG9wZSBoZWFkZXJzLCBiYXNlZCBvbiBldmVudCwgc2RrIGluZm8gYW5kIHR1bm5lbAogKiBOb3RlOiBUaGlzIGZ1bmN0aW9uIHdhcyBleHRyYWN0ZWQgZnJvbSB0aGUgY29yZSBwYWNrYWdlIHRvIG1ha2UgaXQgYXZhaWxhYmxlIGluIFJlcGxheQogKi8KZnVuY3Rpb24gY3JlYXRlRXZlbnRFbnZlbG9wZUhlYWRlcnMoCiAgZXZlbnQsCiAgc2RrSW5mbywKICB0dW5uZWwsCiAgZHNuLAopIHsKICBjb25zdCBkeW5hbWljU2FtcGxpbmdDb250ZXh0ID0gZXZlbnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhICYmIGV2ZW50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YS5keW5hbWljU2FtcGxpbmdDb250ZXh0OwogIHJldHVybiB7CiAgICBldmVudF9pZDogZXZlbnQuZXZlbnRfaWQgLAogICAgc2VudF9hdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLAogICAgLi4uKHNka0luZm8gJiYgeyBzZGs6IHNka0luZm8gfSksCiAgICAuLi4oISF0dW5uZWwgJiYgZHNuICYmIHsgZHNuOiBkc25Ub1N0cmluZyhkc24pIH0pLAogICAgLi4uKGR5bmFtaWNTYW1wbGluZ0NvbnRleHQgJiYgewogICAgICB0cmFjZTogZHJvcFVuZGVmaW5lZEtleXMoeyAuLi5keW5hbWljU2FtcGxpbmdDb250ZXh0IH0pLAogICAgfSksCiAgfTsKfQoKLy8gSW50ZW50aW9uYWxseSBrZWVwaW5nIHRoZSBrZXkgYnJvYWQsIGFzIHdlIGRvbid0IGtub3cgZm9yIHN1cmUgd2hhdCByYXRlIGxpbWl0IGhlYWRlcnMgZ2V0IHJldHVybmVkIGZyb20gYmFja2VuZAoKY29uc3QgREVGQVVMVF9SRVRSWV9BRlRFUiA9IDYwICogMTAwMDsgLy8gNjAgc2Vjb25kcwoKLyoqCiAqIEV4dHJhY3RzIFJldHJ5LUFmdGVyIHZhbHVlIGZyb20gdGhlIHJlcXVlc3QgaGVhZGVyIG9yIHJldHVybnMgZGVmYXVsdCB2YWx1ZQogKiBAcGFyYW0gaGVhZGVyIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiAnUmV0cnktQWZ0ZXInIGhlYWRlcgogKiBAcGFyYW0gbm93IGN1cnJlbnQgdW5peCB0aW1lc3RhbXAKICoKICovCmZ1bmN0aW9uIHBhcnNlUmV0cnlBZnRlckhlYWRlcihoZWFkZXIsIG5vdyA9IERhdGUubm93KCkpIHsKICBjb25zdCBoZWFkZXJEZWxheSA9IHBhcnNlSW50KGAke2hlYWRlcn1gLCAxMCk7CiAgaWYgKCFpc05hTihoZWFkZXJEZWxheSkpIHsKICAgIHJldHVybiBoZWFkZXJEZWxheSAqIDEwMDA7CiAgfQoKICBjb25zdCBoZWFkZXJEYXRlID0gRGF0ZS5wYXJzZShgJHtoZWFkZXJ9YCk7CiAgaWYgKCFpc05hTihoZWFkZXJEYXRlKSkgewogICAgcmV0dXJuIGhlYWRlckRhdGUgLSBub3c7CiAgfQoKICByZXR1cm4gREVGQVVMVF9SRVRSWV9BRlRFUjsKfQoKLyoqCiAqIEdldHMgdGhlIHRpbWUgdGhhdCB0aGUgZ2l2ZW4gY2F0ZWdvcnkgaXMgZGlzYWJsZWQgdW50aWwgZm9yIHJhdGUgbGltaXRpbmcuCiAqIEluIGNhc2Ugbm8gY2F0ZWdvcnktc3BlY2lmaWMgbGltaXQgaXMgc2V0IGJ1dCBhIGdlbmVyYWwgcmF0ZSBsaW1pdCBhY3Jvc3MgYWxsIGNhdGVnb3JpZXMgaXMgYWN0aXZlLAogKiB0aGF0IHRpbWUgaXMgcmV0dXJuZWQuCiAqCiAqIEByZXR1cm4gdGhlIHRpbWUgaW4gbXMgdGhhdCB0aGUgY2F0ZWdvcnkgaXMgZGlzYWJsZWQgdW50aWwgb3IgMCBpZiB0aGVyZSdzIG5vIGFjdGl2ZSByYXRlIGxpbWl0LgogKi8KZnVuY3Rpb24gZGlzYWJsZWRVbnRpbChsaW1pdHMsIGNhdGVnb3J5KSB7CiAgcmV0dXJuIGxpbWl0c1tjYXRlZ29yeV0gfHwgbGltaXRzLmFsbCB8fCAwOwp9CgovKioKICogQ2hlY2tzIGlmIGEgY2F0ZWdvcnkgaXMgcmF0ZSBsaW1pdGVkCiAqLwpmdW5jdGlvbiBpc1JhdGVMaW1pdGVkKGxpbWl0cywgY2F0ZWdvcnksIG5vdyA9IERhdGUubm93KCkpIHsKICByZXR1cm4gZGlzYWJsZWRVbnRpbChsaW1pdHMsIGNhdGVnb3J5KSA+IG5vdzsKfQoKLyoqCiAqIFVwZGF0ZSByYXRlbGltaXRzIGZyb20gaW5jb21pbmcgaGVhZGVycy4KICoKICogQHJldHVybiB0aGUgdXBkYXRlZCBSYXRlTGltaXRzIG9iamVjdC4KICovCmZ1bmN0aW9uIHVwZGF0ZVJhdGVMaW1pdHMoCiAgbGltaXRzLAogIHsgc3RhdHVzQ29kZSwgaGVhZGVycyB9LAogIG5vdyA9IERhdGUubm93KCksCikgewogIGNvbnN0IHVwZGF0ZWRSYXRlTGltaXRzID0gewogICAgLi4ubGltaXRzLAogIH07CgogIC8vICJUaGUgbmFtZSBpcyBjYXNlLWluc2Vuc2l0aXZlLiIKICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSGVhZGVycy9nZXQKICBjb25zdCByYXRlTGltaXRIZWFkZXIgPSBoZWFkZXJzICYmIGhlYWRlcnNbJ3gtc2VudHJ5LXJhdGUtbGltaXRzJ107CiAgY29uc3QgcmV0cnlBZnRlckhlYWRlciA9IGhlYWRlcnMgJiYgaGVhZGVyc1sncmV0cnktYWZ0ZXInXTsKCiAgaWYgKHJhdGVMaW1pdEhlYWRlcikgewogICAgLyoqCiAgICAgKiByYXRlIGxpbWl0IGhlYWRlcnMgYXJlIG9mIHRoZSBmb3JtCiAgICAgKiAgICAgPGhlYWRlcj4sPGhlYWRlcj4sLi4KICAgICAqIHdoZXJlIGVhY2ggPGhlYWRlcj4gaXMgb2YgdGhlIGZvcm0KICAgICAqICAgICA8cmV0cnlfYWZ0ZXI+OiA8Y2F0ZWdvcmllcz46IDxzY29wZT46IDxyZWFzb25fY29kZT4KICAgICAqIHdoZXJlCiAgICAgKiAgICAgPHJldHJ5X2FmdGVyPiBpcyBhIGRlbGF5IGluIHNlY29uZHMKICAgICAqICAgICA8Y2F0ZWdvcmllcz4gaXMgdGhlIGV2ZW50IHR5cGUocykgKGVycm9yLCB0cmFuc2FjdGlvbiwgZXRjKSBiZWluZyByYXRlIGxpbWl0ZWQgYW5kIGlzIG9mIHRoZSBmb3JtCiAgICAgKiAgICAgICAgIDxjYXRlZ29yeT47PGNhdGVnb3J5PjsuLi4KICAgICAqICAgICA8c2NvcGU+IGlzIHdoYXQncyBiZWluZyBsaW1pdGVkIChvcmcsIHByb2plY3QsIG9yIGtleSkgLSBpZ25vcmVkIGJ5IFNESwogICAgICogICAgIDxyZWFzb25fY29kZT4gaXMgYW4gYXJiaXRyYXJ5IHN0cmluZyBsaWtlICJvcmdfcXVvdGEiIC0gaWdub3JlZCBieSBTREsKICAgICAqLwogICAgZm9yIChjb25zdCBsaW1pdCBvZiByYXRlTGltaXRIZWFkZXIudHJpbSgpLnNwbGl0KCcsJykpIHsKICAgICAgY29uc3QgW3JldHJ5QWZ0ZXIsIGNhdGVnb3JpZXNdID0gbGltaXQuc3BsaXQoJzonLCAyKTsKICAgICAgY29uc3QgaGVhZGVyRGVsYXkgPSBwYXJzZUludChyZXRyeUFmdGVyLCAxMCk7CiAgICAgIGNvbnN0IGRlbGF5ID0gKCFpc05hTihoZWFkZXJEZWxheSkgPyBoZWFkZXJEZWxheSA6IDYwKSAqIDEwMDA7IC8vIDYwc2VjIGRlZmF1bHQKICAgICAgaWYgKCFjYXRlZ29yaWVzKSB7CiAgICAgICAgdXBkYXRlZFJhdGVMaW1pdHMuYWxsID0gbm93ICsgZGVsYXk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChjb25zdCBjYXRlZ29yeSBvZiBjYXRlZ29yaWVzLnNwbGl0KCc7JykpIHsKICAgICAgICAgIHVwZGF0ZWRSYXRlTGltaXRzW2NhdGVnb3J5XSA9IG5vdyArIGRlbGF5OwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0gZWxzZSBpZiAocmV0cnlBZnRlckhlYWRlcikgewogICAgdXBkYXRlZFJhdGVMaW1pdHMuYWxsID0gbm93ICsgcGFyc2VSZXRyeUFmdGVySGVhZGVyKHJldHJ5QWZ0ZXJIZWFkZXIsIG5vdyk7CiAgfSBlbHNlIGlmIChzdGF0dXNDb2RlID09PSA0MjkpIHsKICAgIHVwZGF0ZWRSYXRlTGltaXRzLmFsbCA9IG5vdyArIDYwICogMTAwMDsKICB9CgogIHJldHVybiB1cGRhdGVkUmF0ZUxpbWl0czsKfQoKLyoqCiAqIEEgbm9kZS5qcyB3YXRjaGRvZyB0aW1lcgogKiBAcGFyYW0gcG9sbEludGVydmFsIFRoZSBpbnRlcnZhbCB0aGF0IHdlIGV4cGVjdCB0byBnZXQgcG9sbGVkIGF0CiAqIEBwYXJhbSBhbnJUaHJlc2hvbGQgVGhlIHRocmVzaG9sZCBmb3Igd2hlbiB3ZSBjb25zaWRlciBBTlIKICogQHBhcmFtIGNhbGxiYWNrIFRoZSBjYWxsYmFjayB0byBjYWxsIGZvciBBTlIKICogQHJldHVybnMgQW4gb2JqZWN0IHdpdGggYHBvbGxgIGFuZCBgZW5hYmxlZGAgZnVuY3Rpb25zIHtAbGluayBXYXRjaGRvZ1JldHVybn0KICovCmZ1bmN0aW9uIHdhdGNoZG9nVGltZXIoCiAgY3JlYXRlVGltZXIsCiAgcG9sbEludGVydmFsLAogIGFuclRocmVzaG9sZCwKICBjYWxsYmFjaywKKSB7CiAgY29uc3QgdGltZXIgPSBjcmVhdGVUaW1lcigpOwogIGxldCB0cmlnZ2VyZWQgPSBmYWxzZTsKICBsZXQgZW5hYmxlZCA9IHRydWU7CgogIHNldEludGVydmFsKCgpID0+IHsKICAgIGNvbnN0IGRpZmZNcyA9IHRpbWVyLmdldFRpbWVNcygpOwoKICAgIGlmICh0cmlnZ2VyZWQgPT09IGZhbHNlICYmIGRpZmZNcyA+IHBvbGxJbnRlcnZhbCArIGFuclRocmVzaG9sZCkgewogICAgICB0cmlnZ2VyZWQgPSB0cnVlOwogICAgICBpZiAoZW5hYmxlZCkgewogICAgICAgIGNhbGxiYWNrKCk7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoZGlmZk1zIDwgcG9sbEludGVydmFsICsgYW5yVGhyZXNob2xkKSB7CiAgICAgIHRyaWdnZXJlZCA9IGZhbHNlOwogICAgfQogIH0sIDIwKTsKCiAgcmV0dXJuIHsKICAgIHBvbGw6ICgpID0+IHsKICAgICAgdGltZXIucmVzZXQoKTsKICAgIH0sCiAgICBlbmFibGVkOiAoc3RhdGUpID0+IHsKICAgICAgZW5hYmxlZCA9IHN0YXRlOwogICAgfSwKICB9Owp9CgovLyB0eXBlcyBjb3BpZWQgZnJvbSBpbnNwZWN0b3IuZC50cwoKLyoqCiAqIENvbnZlcnRzIERlYnVnZ2VyLkNhbGxGcmFtZSB0byBTZW50cnkgU3RhY2tGcmFtZQogKi8KZnVuY3Rpb24gY2FsbEZyYW1lVG9TdGFja0ZyYW1lKAogIGZyYW1lLAogIHVybCwKICBnZXRNb2R1bGVGcm9tRmlsZW5hbWUsCikgewogIGNvbnN0IGZpbGVuYW1lID0gdXJsID8gdXJsLnJlcGxhY2UoL15maWxlOlwvXC8vLCAnJykgOiB1bmRlZmluZWQ7CgogIC8vIENhbGxGcmFtZSByb3cvY29sIGFyZSAwIGJhc2VkLCB3aGVyZWFzIFN0YWNrRnJhbWUgYXJlIDEgYmFzZWQKICBjb25zdCBjb2xubyA9IGZyYW1lLmxvY2F0aW9uLmNvbHVtbk51bWJlciA/IGZyYW1lLmxvY2F0aW9uLmNvbHVtbk51bWJlciArIDEgOiB1bmRlZmluZWQ7CiAgY29uc3QgbGluZW5vID0gZnJhbWUubG9jYXRpb24ubGluZU51bWJlciA/IGZyYW1lLmxvY2F0aW9uLmxpbmVOdW1iZXIgKyAxIDogdW5kZWZpbmVkOwoKICByZXR1cm4gZHJvcFVuZGVmaW5lZEtleXMoewogICAgZmlsZW5hbWUsCiAgICBtb2R1bGU6IGdldE1vZHVsZUZyb21GaWxlbmFtZShmaWxlbmFtZSksCiAgICBmdW5jdGlvbjogZnJhbWUuZnVuY3Rpb25OYW1lIHx8ICc/JywKICAgIGNvbG5vLAogICAgbGluZW5vLAogICAgaW5fYXBwOiBmaWxlbmFtZSA/IGZpbGVuYW1lSXNJbkFwcChmaWxlbmFtZSkgOiB1bmRlZmluZWQsCiAgfSk7Cn0KCi8qKgogKiBUaGlzIHNlcnZlcyBhcyBhIGJ1aWxkIHRpbWUgZmxhZyB0aGF0IHdpbGwgYmUgdHJ1ZSBieSBkZWZhdWx0LCBidXQgZmFsc2UgaW4gbm9uLWRlYnVnIGJ1aWxkcyBvciBpZiB1c2VycyByZXBsYWNlIGBfX1NFTlRSWV9ERUJVR19fYCBpbiB0aGVpciBnZW5lcmF0ZWQgY29kZS4KICoKICogQVRURU5USU9OOiBUaGlzIGNvbnN0YW50IG11c3QgbmV2ZXIgY3Jvc3MgcGFja2FnZSBib3VuZGFyaWVzIChpLmUuIGJlIGV4cG9ydGVkKSB0byBndWFyYW50ZWUgdGhhdCBpdCBjYW4gYmUgdXNlZCBmb3IgdHJlZSBzaGFraW5nLgogKi8KY29uc3QgREVCVUdfQlVJTEQgPSAodHlwZW9mIF9fU0VOVFJZX0RFQlVHX18gPT09ICd1bmRlZmluZWQnIHx8IF9fU0VOVFJZX0RFQlVHX18pOwoKLyoqCiAqIENyZWF0ZXMgYSBuZXcgYFNlc3Npb25gIG9iamVjdCBieSBzZXR0aW5nIGNlcnRhaW4gZGVmYXVsdCBwYXJhbWV0ZXJzLiBJZiBvcHRpb25hbCBAcGFyYW0gY29udGV4dAogKiBpcyBwYXNzZWQsIHRoZSBwYXNzZWQgcHJvcGVydGllcyBhcmUgYXBwbGllZCB0byB0aGUgc2Vzc2lvbiBvYmplY3QuCiAqCiAqIEBwYXJhbSBjb250ZXh0IChvcHRpb25hbCkgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHJldHVybmVkIHNlc3Npb24gb2JqZWN0CiAqCiAqIEByZXR1cm5zIGEgbmV3IGBTZXNzaW9uYCBvYmplY3QKICovCmZ1bmN0aW9uIG1ha2VTZXNzaW9uKGNvbnRleHQpIHsKICAvLyBCb3RoIHRpbWVzdGFtcCBhbmQgc3RhcnRlZCBhcmUgaW4gc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaC4KICBjb25zdCBzdGFydGluZ1RpbWUgPSB0aW1lc3RhbXBJblNlY29uZHMoKTsKCiAgY29uc3Qgc2Vzc2lvbiA9IHsKICAgIHNpZDogdXVpZDQoKSwKICAgIGluaXQ6IHRydWUsCiAgICB0aW1lc3RhbXA6IHN0YXJ0aW5nVGltZSwKICAgIHN0YXJ0ZWQ6IHN0YXJ0aW5nVGltZSwKICAgIGR1cmF0aW9uOiAwLAogICAgc3RhdHVzOiAnb2snLAogICAgZXJyb3JzOiAwLAogICAgaWdub3JlRHVyYXRpb246IGZhbHNlLAogICAgdG9KU09OOiAoKSA9PiBzZXNzaW9uVG9KU09OKHNlc3Npb24pLAogIH07CgogIGlmIChjb250ZXh0KSB7CiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb24sIGNvbnRleHQpOwogIH0KCiAgcmV0dXJuIHNlc3Npb247Cn0KCi8qKgogKiBVcGRhdGVzIGEgc2Vzc2lvbiBvYmplY3Qgd2l0aCB0aGUgcHJvcGVydGllcyBwYXNzZWQgaW4gdGhlIGNvbnRleHQuCiAqCiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIG11dGF0ZXMgdGhlIHBhc3NlZCBvYmplY3QgYW5kIHJldHVybnMgdm9pZC4KICogKEhhZCB0byBkbyB0aGlzIGluc3RlYWQgb2YgcmV0dXJuaW5nIGEgbmV3IGFuZCB1cGRhdGVkIHNlc3Npb24gYmVjYXVzZSBjbG9zaW5nIGFuZCBzZW5kaW5nIGEgc2Vzc2lvbgogKiBtYWtlcyBhbiB1cGRhdGUgdG8gdGhlIHNlc3Npb24gYWZ0ZXIgaXQgd2FzIHBhc3NlZCB0byB0aGUgc2VuZGluZyBsb2dpYy4KICogQHNlZSBCYXNlQ2xpZW50LmNhcHR1cmVTZXNzaW9uICkKICoKICogQHBhcmFtIHNlc3Npb24gdGhlIGBTZXNzaW9uYCB0byB1cGRhdGUKICogQHBhcmFtIGNvbnRleHQgdGhlIGBTZXNzaW9uQ29udGV4dGAgaG9sZGluZyB0aGUgcHJvcGVydGllcyB0aGF0IHNob3VsZCBiZSB1cGRhdGVkIGluIEBwYXJhbSBzZXNzaW9uCiAqLwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eQpmdW5jdGlvbiB1cGRhdGVTZXNzaW9uKHNlc3Npb24sIGNvbnRleHQgPSB7fSkgewogIGlmIChjb250ZXh0LnVzZXIpIHsKICAgIGlmICghc2Vzc2lvbi5pcEFkZHJlc3MgJiYgY29udGV4dC51c2VyLmlwX2FkZHJlc3MpIHsKICAgICAgc2Vzc2lvbi5pcEFkZHJlc3MgPSBjb250ZXh0LnVzZXIuaXBfYWRkcmVzczsKICAgIH0KCiAgICBpZiAoIXNlc3Npb24uZGlkICYmICFjb250ZXh0LmRpZCkgewogICAgICBzZXNzaW9uLmRpZCA9IGNvbnRleHQudXNlci5pZCB8fCBjb250ZXh0LnVzZXIuZW1haWwgfHwgY29udGV4dC51c2VyLnVzZXJuYW1lOwogICAgfQogIH0KCiAgc2Vzc2lvbi50aW1lc3RhbXAgPSBjb250ZXh0LnRpbWVzdGFtcCB8fCB0aW1lc3RhbXBJblNlY29uZHMoKTsKCiAgaWYgKGNvbnRleHQuYWJub3JtYWxfbWVjaGFuaXNtKSB7CiAgICBzZXNzaW9uLmFibm9ybWFsX21lY2hhbmlzbSA9IGNvbnRleHQuYWJub3JtYWxfbWVjaGFuaXNtOwogIH0KCiAgaWYgKGNvbnRleHQuaWdub3JlRHVyYXRpb24pIHsKICAgIHNlc3Npb24uaWdub3JlRHVyYXRpb24gPSBjb250ZXh0Lmlnbm9yZUR1cmF0aW9uOwogIH0KICBpZiAoY29udGV4dC5zaWQpIHsKICAgIC8vIEdvb2QgZW5vdWdoIHV1aWQgdmFsaWRhdGlvbi4g4oCUIEthbWlsCiAgICBzZXNzaW9uLnNpZCA9IGNvbnRleHQuc2lkLmxlbmd0aCA9PT0gMzIgPyBjb250ZXh0LnNpZCA6IHV1aWQ0KCk7CiAgfQogIGlmIChjb250ZXh0LmluaXQgIT09IHVuZGVmaW5lZCkgewogICAgc2Vzc2lvbi5pbml0ID0gY29udGV4dC5pbml0OwogIH0KICBpZiAoIXNlc3Npb24uZGlkICYmIGNvbnRleHQuZGlkKSB7CiAgICBzZXNzaW9uLmRpZCA9IGAke2NvbnRleHQuZGlkfWA7CiAgfQogIGlmICh0eXBlb2YgY29udGV4dC5zdGFydGVkID09PSAnbnVtYmVyJykgewogICAgc2Vzc2lvbi5zdGFydGVkID0gY29udGV4dC5zdGFydGVkOwogIH0KICBpZiAoc2Vzc2lvbi5pZ25vcmVEdXJhdGlvbikgewogICAgc2Vzc2lvbi5kdXJhdGlvbiA9IHVuZGVmaW5lZDsKICB9IGVsc2UgaWYgKHR5cGVvZiBjb250ZXh0LmR1cmF0aW9uID09PSAnbnVtYmVyJykgewogICAgc2Vzc2lvbi5kdXJhdGlvbiA9IGNvbnRleHQuZHVyYXRpb247CiAgfSBlbHNlIHsKICAgIGNvbnN0IGR1cmF0aW9uID0gc2Vzc2lvbi50aW1lc3RhbXAgLSBzZXNzaW9uLnN0YXJ0ZWQ7CiAgICBzZXNzaW9uLmR1cmF0aW9uID0gZHVyYXRpb24gPj0gMCA/IGR1cmF0aW9uIDogMDsKICB9CiAgaWYgKGNvbnRleHQucmVsZWFzZSkgewogICAgc2Vzc2lvbi5yZWxlYXNlID0gY29udGV4dC5yZWxlYXNlOwogIH0KICBpZiAoY29udGV4dC5lbnZpcm9ubWVudCkgewogICAgc2Vzc2lvbi5lbnZpcm9ubWVudCA9IGNvbnRleHQuZW52aXJvbm1lbnQ7CiAgfQogIGlmICghc2Vzc2lvbi5pcEFkZHJlc3MgJiYgY29udGV4dC5pcEFkZHJlc3MpIHsKICAgIHNlc3Npb24uaXBBZGRyZXNzID0gY29udGV4dC5pcEFkZHJlc3M7CiAgfQogIGlmICghc2Vzc2lvbi51c2VyQWdlbnQgJiYgY29udGV4dC51c2VyQWdlbnQpIHsKICAgIHNlc3Npb24udXNlckFnZW50ID0gY29udGV4dC51c2VyQWdlbnQ7CiAgfQogIGlmICh0eXBlb2YgY29udGV4dC5lcnJvcnMgPT09ICdudW1iZXInKSB7CiAgICBzZXNzaW9uLmVycm9ycyA9IGNvbnRleHQuZXJyb3JzOwogIH0KICBpZiAoY29udGV4dC5zdGF0dXMpIHsKICAgIHNlc3Npb24uc3RhdHVzID0gY29udGV4dC5zdGF0dXM7CiAgfQp9CgovKioKICogU2VyaWFsaXplcyBhIHBhc3NlZCBzZXNzaW9uIG9iamVjdCB0byBhIEpTT04gb2JqZWN0IHdpdGggYSBzbGlnaHRseSBkaWZmZXJlbnQgc3RydWN0dXJlLgogKiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHRoZSBTZW50cnkgYmFja2VuZCByZXF1aXJlcyBhIHNsaWdodGx5IGRpZmZlcmVudCBzY2hlbWEgb2YgYSBzZXNzaW9uCiAqIHRoYW4gdGhlIG9uZSB0aGUgSlMgU0RLcyB1c2UgaW50ZXJuYWxseS4KICoKICogQHBhcmFtIHNlc3Npb24gdGhlIHNlc3Npb24gdG8gYmUgY29udmVydGVkCiAqCiAqIEByZXR1cm5zIGEgSlNPTiBvYmplY3Qgb2YgdGhlIHBhc3NlZCBzZXNzaW9uCiAqLwpmdW5jdGlvbiBzZXNzaW9uVG9KU09OKHNlc3Npb24pIHsKICByZXR1cm4gZHJvcFVuZGVmaW5lZEtleXMoewogICAgc2lkOiBgJHtzZXNzaW9uLnNpZH1gLAogICAgaW5pdDogc2Vzc2lvbi5pbml0LAogICAgLy8gTWFrZSBzdXJlIHRoYXQgc2VjIGlzIGNvbnZlcnRlZCB0byBtcyBmb3IgZGF0ZSBjb25zdHJ1Y3RvcgogICAgc3RhcnRlZDogbmV3IERhdGUoc2Vzc2lvbi5zdGFydGVkICogMTAwMCkudG9JU09TdHJpbmcoKSwKICAgIHRpbWVzdGFtcDogbmV3IERhdGUoc2Vzc2lvbi50aW1lc3RhbXAgKiAxMDAwKS50b0lTT1N0cmluZygpLAogICAgc3RhdHVzOiBzZXNzaW9uLnN0YXR1cywKICAgIGVycm9yczogc2Vzc2lvbi5lcnJvcnMsCiAgICBkaWQ6IHR5cGVvZiBzZXNzaW9uLmRpZCA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHNlc3Npb24uZGlkID09PSAnc3RyaW5nJyA/IGAke3Nlc3Npb24uZGlkfWAgOiB1bmRlZmluZWQsCiAgICBkdXJhdGlvbjogc2Vzc2lvbi5kdXJhdGlvbiwKICAgIGFibm9ybWFsX21lY2hhbmlzbTogc2Vzc2lvbi5hYm5vcm1hbF9tZWNoYW5pc20sCiAgICBhdHRyczogewogICAgICByZWxlYXNlOiBzZXNzaW9uLnJlbGVhc2UsCiAgICAgIGVudmlyb25tZW50OiBzZXNzaW9uLmVudmlyb25tZW50LAogICAgICBpcF9hZGRyZXNzOiBzZXNzaW9uLmlwQWRkcmVzcywKICAgICAgdXNlcl9hZ2VudDogc2Vzc2lvbi51c2VyQWdlbnQsCiAgICB9LAogIH0pOwp9CgovKioKICogQXBwbHkgU2RrSW5mbyAobmFtZSwgdmVyc2lvbiwgcGFja2FnZXMsIGludGVncmF0aW9ucykgdG8gdGhlIGNvcnJlc3BvbmRpbmcgZXZlbnQga2V5LgogKiBNZXJnZSB3aXRoIGV4aXN0aW5nIGRhdGEgaWYgYW55LgogKiovCmZ1bmN0aW9uIGVuaGFuY2VFdmVudFdpdGhTZGtJbmZvKGV2ZW50LCBzZGtJbmZvKSB7CiAgaWYgKCFzZGtJbmZvKSB7CiAgICByZXR1cm4gZXZlbnQ7CiAgfQogIGV2ZW50LnNkayA9IGV2ZW50LnNkayB8fCB7fTsKICBldmVudC5zZGsubmFtZSA9IGV2ZW50LnNkay5uYW1lIHx8IHNka0luZm8ubmFtZTsKICBldmVudC5zZGsudmVyc2lvbiA9IGV2ZW50LnNkay52ZXJzaW9uIHx8IHNka0luZm8udmVyc2lvbjsKICBldmVudC5zZGsuaW50ZWdyYXRpb25zID0gWy4uLihldmVudC5zZGsuaW50ZWdyYXRpb25zIHx8IFtdKSwgLi4uKHNka0luZm8uaW50ZWdyYXRpb25zIHx8IFtdKV07CiAgZXZlbnQuc2RrLnBhY2thZ2VzID0gWy4uLihldmVudC5zZGsucGFja2FnZXMgfHwgW10pLCAuLi4oc2RrSW5mby5wYWNrYWdlcyB8fCBbXSldOwogIHJldHVybiBldmVudDsKfQoKLyoqIENyZWF0ZXMgYW4gZW52ZWxvcGUgZnJvbSBhIFNlc3Npb24gKi8KZnVuY3Rpb24gY3JlYXRlU2Vzc2lvbkVudmVsb3BlKAogIHNlc3Npb24sCiAgZHNuLAogIG1ldGFkYXRhLAogIHR1bm5lbCwKKSB7CiAgY29uc3Qgc2RrSW5mbyA9IGdldFNka01ldGFkYXRhRm9yRW52ZWxvcGVIZWFkZXIobWV0YWRhdGEpOwogIGNvbnN0IGVudmVsb3BlSGVhZGVycyA9IHsKICAgIHNlbnRfYXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSwKICAgIC4uLihzZGtJbmZvICYmIHsgc2RrOiBzZGtJbmZvIH0pLAogICAgLi4uKCEhdHVubmVsICYmIGRzbiAmJiB7IGRzbjogZHNuVG9TdHJpbmcoZHNuKSB9KSwKICB9OwoKICBjb25zdCBlbnZlbG9wZUl0ZW0gPQogICAgJ2FnZ3JlZ2F0ZXMnIGluIHNlc3Npb24gPyBbeyB0eXBlOiAnc2Vzc2lvbnMnIH0sIHNlc3Npb25dIDogW3sgdHlwZTogJ3Nlc3Npb24nIH0sIHNlc3Npb24udG9KU09OKCldOwoKICByZXR1cm4gY3JlYXRlRW52ZWxvcGUoZW52ZWxvcGVIZWFkZXJzLCBbZW52ZWxvcGVJdGVtXSk7Cn0KCi8qKgogKiBDcmVhdGUgYW4gRW52ZWxvcGUgZnJvbSBhbiBldmVudC4KICovCmZ1bmN0aW9uIGNyZWF0ZUV2ZW50RW52ZWxvcGUoCiAgZXZlbnQsCiAgZHNuLAogIG1ldGFkYXRhLAogIHR1bm5lbCwKKSB7CiAgY29uc3Qgc2RrSW5mbyA9IGdldFNka01ldGFkYXRhRm9yRW52ZWxvcGVIZWFkZXIobWV0YWRhdGEpOwoKICAvKgogICAgTm90ZTogRHVlIHRvIFRTLCBldmVudC50eXBlIG1heSBiZSBgcmVwbGF5X2V2ZW50YCwgdGhlb3JldGljYWxseS4KICAgIEluIHByYWN0aWNlLCB3ZSBuZXZlciBjYWxsIGBjcmVhdGVFdmVudEVudmVsb3BlYCB3aXRoIGByZXBsYXlfZXZlbnRgIHR5cGUsCiAgICBhbmQgd2UnZCBoYXZlIHRvIGFkanV0IGEgbG9vb3Qgb2YgdHlwZXMgdG8gbWFrZSB0aGlzIHdvcmsgcHJvcGVybHkuCiAgICBXZSB3YW50IHRvIGF2b2lkIGNhc3RpbmcgdGhpcyBhcm91bmQsIGFzIHRoYXQgY291bGQgbGVhZCB0byBidWdzIChlLmcuIHdoZW4gd2UgYWRkIGFub3RoZXIgdHlwZSkKICAgIFNvIHRoZSBzYWZlIGNob2ljZSBpcyB0byByZWFsbHkgZ3VhcmQgYWdhaW5zdCB0aGUgcmVwbGF5X2V2ZW50IHR5cGUgaGVyZS4KICAqLwogIGNvbnN0IGV2ZW50VHlwZSA9IGV2ZW50LnR5cGUgJiYgZXZlbnQudHlwZSAhPT0gJ3JlcGxheV9ldmVudCcgPyBldmVudC50eXBlIDogJ2V2ZW50JzsKCiAgZW5oYW5jZUV2ZW50V2l0aFNka0luZm8oZXZlbnQsIG1ldGFkYXRhICYmIG1ldGFkYXRhLnNkayk7CgogIGNvbnN0IGVudmVsb3BlSGVhZGVycyA9IGNyZWF0ZUV2ZW50RW52ZWxvcGVIZWFkZXJzKGV2ZW50LCBzZGtJbmZvLCB0dW5uZWwsIGRzbik7CgogIC8vIFByZXZlbnQgdGhpcyBkYXRhICh3aGljaCwgaWYgaXQgZXhpc3RzLCB3YXMgdXNlZCBpbiBlYXJsaWVyIHN0ZXBzIGluIHRoZSBwcm9jZXNzaW5nIHBpcGVsaW5lKSBmcm9tIGJlaW5nIHNlbnQgdG8KICAvLyBzZW50cnkuIChOb3RlOiBPdXIgdXNlIG9mIHRoaXMgcHJvcGVydHkgY29tZXMgYW5kIGdvZXMgd2l0aCB3aGF0ZXZlciB3ZSBtaWdodCBiZSBkZWJ1Z2dpbmcsIHdoYXRldmVyIGhhY2tzIHdlIG1heQogIC8vIGhhdmUgdGVtcG9yYXJpbHkgYWRkZWQsIGV0Yy4gRXZlbiBpZiB3ZSBkb24ndCBoYXBwZW4gdG8gYmUgdXNpbmcgaXQgYXQgc29tZSBwb2ludCBpbiB0aGUgZnV0dXJlLCBsZXQncyBub3QgZ2V0IHJpZAogIC8vIG9mIHRoaXMgYGRlbGV0ZWAsIGxlc3Qgd2UgbWlzcyBwdXR0aW5nIGl0IGJhY2sgaW4gdGhlIG5leHQgdGltZSB0aGUgcHJvcGVydHkgaXMgaW4gdXNlLikKICBkZWxldGUgZXZlbnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhOwoKICBjb25zdCBldmVudEl0ZW0gPSBbeyB0eXBlOiBldmVudFR5cGUgfSwgZXZlbnRdOwogIHJldHVybiBjcmVhdGVFbnZlbG9wZShlbnZlbG9wZUhlYWRlcnMsIFtldmVudEl0ZW1dKTsKfQoKY29uc3QgU0VOVFJZX0FQSV9WRVJTSU9OID0gJzcnOwoKLyoqIFJldHVybnMgdGhlIHByZWZpeCB0byBjb25zdHJ1Y3QgU2VudHJ5IGluZ2VzdGlvbiBBUEkgZW5kcG9pbnRzLiAqLwpmdW5jdGlvbiBnZXRCYXNlQXBpRW5kcG9pbnQoZHNuKSB7CiAgY29uc3QgcHJvdG9jb2wgPSBkc24ucHJvdG9jb2wgPyBgJHtkc24ucHJvdG9jb2x9OmAgOiAnJzsKICBjb25zdCBwb3J0ID0gZHNuLnBvcnQgPyBgOiR7ZHNuLnBvcnR9YCA6ICcnOwogIHJldHVybiBgJHtwcm90b2NvbH0vLyR7ZHNuLmhvc3R9JHtwb3J0fSR7ZHNuLnBhdGggPyBgLyR7ZHNuLnBhdGh9YCA6ICcnfS9hcGkvYDsKfQoKLyoqIFJldHVybnMgdGhlIGluZ2VzdCBBUEkgZW5kcG9pbnQgZm9yIHRhcmdldC4gKi8KZnVuY3Rpb24gX2dldEluZ2VzdEVuZHBvaW50KGRzbikgewogIHJldHVybiBgJHtnZXRCYXNlQXBpRW5kcG9pbnQoZHNuKX0ke2Rzbi5wcm9qZWN0SWR9L2VudmVsb3BlL2A7Cn0KCi8qKiBSZXR1cm5zIGEgVVJMLWVuY29kZWQgc3RyaW5nIHdpdGggYXV0aCBjb25maWcgc3VpdGFibGUgZm9yIGEgcXVlcnkgc3RyaW5nLiAqLwpmdW5jdGlvbiBfZW5jb2RlZEF1dGgoZHNuLCBzZGtJbmZvKSB7CiAgcmV0dXJuIHVybEVuY29kZSh7CiAgICAvLyBXZSBzZW5kIG9ubHkgdGhlIG1pbmltdW0gc2V0IG9mIHJlcXVpcmVkIGluZm9ybWF0aW9uLiBTZWUKICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQvaXNzdWVzLzI1NzIuCiAgICBzZW50cnlfa2V5OiBkc24ucHVibGljS2V5LAogICAgc2VudHJ5X3ZlcnNpb246IFNFTlRSWV9BUElfVkVSU0lPTiwKICAgIC4uLihzZGtJbmZvICYmIHsgc2VudHJ5X2NsaWVudDogYCR7c2RrSW5mby5uYW1lfS8ke3Nka0luZm8udmVyc2lvbn1gIH0pLAogIH0pOwp9CgovKioKICogUmV0dXJucyB0aGUgZW52ZWxvcGUgZW5kcG9pbnQgVVJMIHdpdGggYXV0aCBpbiB0aGUgcXVlcnkgc3RyaW5nLgogKgogKiBTZW5kaW5nIGF1dGggYXMgcGFydCBvZiB0aGUgcXVlcnkgc3RyaW5nIGFuZCBub3QgYXMgY3VzdG9tIEhUVFAgaGVhZGVycyBhdm9pZHMgQ09SUyBwcmVmbGlnaHQgcmVxdWVzdHMuCiAqLwpmdW5jdGlvbiBnZXRFbnZlbG9wZUVuZHBvaW50V2l0aFVybEVuY29kZWRBdXRoKAogIGRzbiwKICAvLyBUT0RPICh2OCk6IFJlbW92ZSBgdHVubmVsT3JPcHRpb25zYCBpbiBmYXZvciBvZiBgb3B0aW9uc2AsIGFuZCB1c2UgdGhlIHN1YnN0aXR1dGUgY29kZSBiZWxvdwogIC8vIG9wdGlvbnM6IENsaWVudE9wdGlvbnMgPSB7fSBhcyBDbGllbnRPcHRpb25zLAogIHR1bm5lbE9yT3B0aW9ucyA9IHt9ICwKKSB7CiAgLy8gVE9ETyAodjgpOiBVc2UgdGhpcyBjb2RlIGluc3RlYWQKICAvLyBjb25zdCB7IHR1bm5lbCwgX21ldGFkYXRhID0ge30gfSA9IG9wdGlvbnM7CiAgLy8gcmV0dXJuIHR1bm5lbCA/IHR1bm5lbCA6IGAke19nZXRJbmdlc3RFbmRwb2ludChkc24pfT8ke19lbmNvZGVkQXV0aChkc24sIF9tZXRhZGF0YS5zZGspfWA7CgogIGNvbnN0IHR1bm5lbCA9IHR5cGVvZiB0dW5uZWxPck9wdGlvbnMgPT09ICdzdHJpbmcnID8gdHVubmVsT3JPcHRpb25zIDogdHVubmVsT3JPcHRpb25zLnR1bm5lbDsKICBjb25zdCBzZGtJbmZvID0KICAgIHR5cGVvZiB0dW5uZWxPck9wdGlvbnMgPT09ICdzdHJpbmcnIHx8ICF0dW5uZWxPck9wdGlvbnMuX21ldGFkYXRhID8gdW5kZWZpbmVkIDogdHVubmVsT3JPcHRpb25zLl9tZXRhZGF0YS5zZGs7CgogIHJldHVybiB0dW5uZWwgPyB0dW5uZWwgOiBgJHtfZ2V0SW5nZXN0RW5kcG9pbnQoZHNuKX0/JHtfZW5jb2RlZEF1dGgoZHNuLCBzZGtJbmZvKX1gOwp9Cgpjb25zdCBERUZBVUxUX1RSQU5TUE9SVF9CVUZGRVJfU0laRSA9IDMwOwoKLyoqCiAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYSBTZW50cnkgYFRyYW5zcG9ydGAKICoKICogQHBhcmFtIG9wdGlvbnMKICogQHBhcmFtIG1ha2VSZXF1ZXN0CiAqLwpmdW5jdGlvbiBjcmVhdGVUcmFuc3BvcnQoCiAgb3B0aW9ucywKICBtYWtlUmVxdWVzdCwKICBidWZmZXIgPSBtYWtlUHJvbWlzZUJ1ZmZlcigKICAgIG9wdGlvbnMuYnVmZmVyU2l6ZSB8fCBERUZBVUxUX1RSQU5TUE9SVF9CVUZGRVJfU0laRSwKICApLAopIHsKICBsZXQgcmF0ZUxpbWl0cyA9IHt9OwogIGNvbnN0IGZsdXNoID0gKHRpbWVvdXQpID0+IGJ1ZmZlci5kcmFpbih0aW1lb3V0KTsKCiAgZnVuY3Rpb24gc2VuZChlbnZlbG9wZSkgewogICAgY29uc3QgZmlsdGVyZWRFbnZlbG9wZUl0ZW1zID0gW107CgogICAgLy8gRHJvcCByYXRlIGxpbWl0ZWQgaXRlbXMgZnJvbSBlbnZlbG9wZQogICAgZm9yRWFjaEVudmVsb3BlSXRlbShlbnZlbG9wZSwgKGl0ZW0sIHR5cGUpID0+IHsKICAgICAgY29uc3QgZW52ZWxvcGVJdGVtRGF0YUNhdGVnb3J5ID0gZW52ZWxvcGVJdGVtVHlwZVRvRGF0YUNhdGVnb3J5KHR5cGUpOwogICAgICBpZiAoaXNSYXRlTGltaXRlZChyYXRlTGltaXRzLCBlbnZlbG9wZUl0ZW1EYXRhQ2F0ZWdvcnkpKSB7CiAgICAgICAgY29uc3QgZXZlbnQgPSBnZXRFdmVudEZvckVudmVsb3BlSXRlbShpdGVtLCB0eXBlKTsKICAgICAgICBvcHRpb25zLnJlY29yZERyb3BwZWRFdmVudCgncmF0ZWxpbWl0X2JhY2tvZmYnLCBlbnZlbG9wZUl0ZW1EYXRhQ2F0ZWdvcnksIGV2ZW50KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBmaWx0ZXJlZEVudmVsb3BlSXRlbXMucHVzaChpdGVtKTsKICAgICAgfQogICAgfSk7CgogICAgLy8gU2tpcCBzZW5kaW5nIGlmIGVudmVsb3BlIGlzIGVtcHR5IGFmdGVyIGZpbHRlcmluZyBvdXQgcmF0ZSBsaW1pdGVkIGV2ZW50cwogICAgaWYgKGZpbHRlcmVkRW52ZWxvcGVJdGVtcy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHJlc29sdmVkU3luY1Byb21pc2UoKTsKICAgIH0KCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQogICAgY29uc3QgZmlsdGVyZWRFbnZlbG9wZSA9IGNyZWF0ZUVudmVsb3BlKGVudmVsb3BlWzBdLCBmaWx0ZXJlZEVudmVsb3BlSXRlbXMgKTsKCiAgICAvLyBDcmVhdGVzIGNsaWVudCByZXBvcnQgZm9yIGVhY2ggaXRlbSBpbiBhbiBlbnZlbG9wZQogICAgY29uc3QgcmVjb3JkRW52ZWxvcGVMb3NzID0gKHJlYXNvbikgPT4gewogICAgICBmb3JFYWNoRW52ZWxvcGVJdGVtKGZpbHRlcmVkRW52ZWxvcGUsIChpdGVtLCB0eXBlKSA9PiB7CiAgICAgICAgY29uc3QgZXZlbnQgPSBnZXRFdmVudEZvckVudmVsb3BlSXRlbShpdGVtLCB0eXBlKTsKICAgICAgICBvcHRpb25zLnJlY29yZERyb3BwZWRFdmVudChyZWFzb24sIGVudmVsb3BlSXRlbVR5cGVUb0RhdGFDYXRlZ29yeSh0eXBlKSwgZXZlbnQpOwogICAgICB9KTsKICAgIH07CgogICAgY29uc3QgcmVxdWVzdFRhc2sgPSAoKSA9PgogICAgICBtYWtlUmVxdWVzdCh7IGJvZHk6IHNlcmlhbGl6ZUVudmVsb3BlKGZpbHRlcmVkRW52ZWxvcGUsIG9wdGlvbnMudGV4dEVuY29kZXIpIH0pLnRoZW4oCiAgICAgICAgcmVzcG9uc2UgPT4gewogICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byB0aHJvdyBvbiBOT0sgcmVzcG9uc2VzLCBidXQgd2Ugd2FudCB0byBhdCBsZWFzdCBsb2cgdGhlbQogICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IHVuZGVmaW5lZCAmJiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA8IDIwMCB8fCByZXNwb25zZS5zdGF0dXNDb2RlID49IDMwMCkpIHsKICAgICAgICAgICAgREVCVUdfQlVJTEQgJiYgbG9nZ2VyLndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Jlc3BvbnNlLnN0YXR1c0NvZGV9IHRvIHNlbnQgZXZlbnQuYCk7CiAgICAgICAgICB9CgogICAgICAgICAgcmF0ZUxpbWl0cyA9IHVwZGF0ZVJhdGVMaW1pdHMocmF0ZUxpbWl0cywgcmVzcG9uc2UpOwogICAgICAgICAgcmV0dXJuIHJlc3BvbnNlOwogICAgICAgIH0sCiAgICAgICAgZXJyb3IgPT4gewogICAgICAgICAgcmVjb3JkRW52ZWxvcGVMb3NzKCduZXR3b3JrX2Vycm9yJyk7CiAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICB9LAogICAgICApOwoKICAgIHJldHVybiBidWZmZXIuYWRkKHJlcXVlc3RUYXNrKS50aGVuKAogICAgICByZXN1bHQgPT4gcmVzdWx0LAogICAgICBlcnJvciA9PiB7CiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgU2VudHJ5RXJyb3IpIHsKICAgICAgICAgIERFQlVHX0JVSUxEICYmIGxvZ2dlci5lcnJvcignU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuJyk7CiAgICAgICAgICByZWNvcmRFbnZlbG9wZUxvc3MoJ3F1ZXVlX292ZXJmbG93Jyk7CiAgICAgICAgICByZXR1cm4gcmVzb2x2ZWRTeW5jUHJvbWlzZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICB9CiAgICAgIH0sCiAgICApOwogIH0KCiAgLy8gV2UgdXNlIHRoaXMgdG8gaWRlbnRpZmlmeSBpZiB0aGUgdHJhbnNwb3J0IGlzIHRoZSBiYXNlIHRyYW5zcG9ydAogIC8vIFRPRE8gKHY4KTogUmVtb3ZlIHRoaXMgYWdhaW4gYXMgd2UnbGwgbm8gbG9uZ2VyIG5lZWQgaXQKICBzZW5kLl9fc2VudHJ5X19iYXNlVHJhbnNwb3J0X18gPSB0cnVlOwoKICByZXR1cm4gewogICAgc2VuZCwKICAgIGZsdXNoLAogIH07Cn0KCmZ1bmN0aW9uIGdldEV2ZW50Rm9yRW52ZWxvcGVJdGVtKGl0ZW0sIHR5cGUpIHsKICBpZiAodHlwZSAhPT0gJ2V2ZW50JyAmJiB0eXBlICE9PSAndHJhbnNhY3Rpb24nKSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KCiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoaXRlbSkgPyAoaXRlbSApWzFdIDogdW5kZWZpbmVkOwp9CgovKiogbm9ybWFsaXplcyBXaW5kb3dzIHBhdGhzICovCmZ1bmN0aW9uIG5vcm1hbGl6ZVdpbmRvd3NQYXRoKHBhdGgpIHsKICByZXR1cm4gcGF0aAogICAgLnJlcGxhY2UoL15bQS1aXTovLCAnJykgLy8gcmVtb3ZlIFdpbmRvd3Mtc3R5bGUgcHJlZml4CiAgICAucmVwbGFjZSgvXFwvZywgJy8nKTsgLy8gcmVwbGFjZSBhbGwgYFxgIGluc3RhbmNlcyB3aXRoIGAvYAp9CgovKiogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgZ2V0cyB0aGUgbW9kdWxlIG5hbWUgZnJvbSBhIGZpbGVuYW1lICovCmZ1bmN0aW9uIGNyZWF0ZUdldE1vZHVsZUZyb21GaWxlbmFtZSgKICBiYXNlUGF0aCA9IHByb2Nlc3MuYXJndlsxXSA/IGRpcm5hbWUocHJvY2Vzcy5hcmd2WzFdKSA6IHByb2Nlc3MuY3dkKCksCiAgaXNXaW5kb3dzID0gc2VwID09PSAnXFwnLAopIHsKICBjb25zdCBub3JtYWxpemVkQmFzZSA9IGlzV2luZG93cyA/IG5vcm1hbGl6ZVdpbmRvd3NQYXRoKGJhc2VQYXRoKSA6IGJhc2VQYXRoOwoKICByZXR1cm4gKGZpbGVuYW1lKSA9PiB7CiAgICBpZiAoIWZpbGVuYW1lKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBjb25zdCBub3JtYWxpemVkRmlsZW5hbWUgPSBpc1dpbmRvd3MgPyBub3JtYWxpemVXaW5kb3dzUGF0aChmaWxlbmFtZSkgOiBmaWxlbmFtZTsKCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0CiAgICBsZXQgeyBkaXIsIGJhc2U6IGZpbGUsIGV4dCB9ID0gcG9zaXgucGFyc2Uobm9ybWFsaXplZEZpbGVuYW1lKTsKCiAgICBpZiAoZXh0ID09PSAnLmpzJyB8fCBleHQgPT09ICcubWpzJyB8fCBleHQgPT09ICcuY2pzJykgewogICAgICBmaWxlID0gZmlsZS5zbGljZSgwLCBleHQubGVuZ3RoICogLTEpOwogICAgfQoKICAgIGlmICghZGlyKSB7CiAgICAgIC8vIE5vIGRpcm5hbWUgd2hhdHNvZXZlcgogICAgICBkaXIgPSAnLic7CiAgICB9CgogICAgY29uc3QgbiA9IGRpci5sYXN0SW5kZXhPZignL25vZGVfbW9kdWxlcycpOwogICAgaWYgKG4gPiAtMSkgewogICAgICByZXR1cm4gYCR7ZGlyLnNsaWNlKG4gKyAxNCkucmVwbGFjZSgvXC8vZywgJy4nKX06JHtmaWxlfWA7CiAgICB9CgogICAgLy8gTGV0J3Mgc2VlIGlmIGl0J3MgYSBwYXJ0IG9mIHRoZSBtYWluIG1vZHVsZQogICAgLy8gVG8gYmUgYSBwYXJ0IG9mIG1haW4gbW9kdWxlLCBpdCBoYXMgdG8gc2hhcmUgdGhlIHNhbWUgYmFzZQogICAgaWYgKGRpci5zdGFydHNXaXRoKG5vcm1hbGl6ZWRCYXNlKSkgewogICAgICBsZXQgbW9kdWxlTmFtZSA9IGRpci5zbGljZShub3JtYWxpemVkQmFzZS5sZW5ndGggKyAxKS5yZXBsYWNlKC9cLy9nLCAnLicpOwoKICAgICAgaWYgKG1vZHVsZU5hbWUpIHsKICAgICAgICBtb2R1bGVOYW1lICs9ICc6JzsKICAgICAgfQogICAgICBtb2R1bGVOYW1lICs9IGZpbGU7CgogICAgICByZXR1cm4gbW9kdWxlTmFtZTsKICAgIH0KCiAgICByZXR1cm4gZmlsZTsKICB9Owp9CgpmdW5jdGlvbiBfbnVsbGlzaENvYWxlc2NlJDIobGhzLCByaHNGbikgeyBpZiAobGhzICE9IG51bGwpIHsgcmV0dXJuIGxoczsgfSBlbHNlIHsgcmV0dXJuIHJoc0ZuKCk7IH0gfS8qKgogKiBUaGlzIGNvZGUgd2FzIG9yaWdpbmFsbHkgZm9ya2VkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL1Rvb1RhbGxOYXRlL3Byb3h5LWFnZW50cy90cmVlL2IxMzMyOTVmZDE2ZjY0NzU1NzhiNmIxNWJkOWI0ZTMzZWNiMGQwYjcKICogV2l0aCB0aGUgZm9sbG93aW5nIGxpY2VuY2U6CiAqCiAqIChUaGUgTUlUIExpY2Vuc2UpCiAqCiAqIENvcHlyaWdodCAoYykgMjAxMyBOYXRoYW4gUmFqbGljaCA8bmF0aGFuQHRvb3RhbGxuYXRlLm5ldD4qCiAqCiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZwogKiBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUKICogJ1NvZnR3YXJlJyksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZwogKiB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsCiAqIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0bwogKiBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8KICogdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOioKICoKICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUKICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuKgogKgogKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgJ0FTIElTJywgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwKICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GCiAqIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4KICogSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkKICogQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwKICogVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUKICogU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCiAqLwoKY29uc3QgSU5URVJOQUwgPSBTeW1ib2woJ0FnZW50QmFzZUludGVybmFsU3RhdGUnKTsKCmNsYXNzIEFnZW50IGV4dGVuZHMgaHR0cC5BZ2VudCB7CgogIC8vIFNldCBieSBgaHR0cC5BZ2VudGAgLSBtaXNzaW5nIGZyb20gYEB0eXBlcy9ub2RlYAoKICBjb25zdHJ1Y3RvcihvcHRzKSB7CiAgICBzdXBlcihvcHRzKTsKICAgIHRoaXNbSU5URVJOQUxdID0ge307CiAgfQoKICAvKioKICAgKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGlzIGFuIGBodHRwYCBvciBgaHR0cHNgIHJlcXVlc3QuCiAgICovCiAgaXNTZWN1cmVFbmRwb2ludChvcHRpb25zKSB7CiAgICBpZiAob3B0aW9ucykgewogICAgICAvLyBGaXJzdCBjaGVjayB0aGUgYHNlY3VyZUVuZHBvaW50YCBwcm9wZXJ0eSBleHBsaWNpdGx5LCBzaW5jZSB0aGlzCiAgICAgIC8vIG1lYW5zIHRoYXQgYSBwYXJlbnQgYEFnZW50YCBpcyAicGFzc2luZyB0aHJvdWdoIiB0byB0aGlzIGluc3RhbmNlLgogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSwgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1tZW1iZXItYWNjZXNzCiAgICAgIGlmICh0eXBlb2YgKG9wdGlvbnMgKS5zZWN1cmVFbmRwb2ludCA9PT0gJ2Jvb2xlYW4nKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbnMuc2VjdXJlRW5kcG9pbnQ7CiAgICAgIH0KCiAgICAgIC8vIElmIG5vIGV4cGxpY2l0IGBzZWN1cmVgIGVuZHBvaW50LCBjaGVjayBpZiBgcHJvdG9jb2xgIHByb3BlcnR5IGlzCiAgICAgIC8vIHNldC4gVGhpcyB3aWxsIHVzdWFsbHkgYmUgdGhlIGNhc2Ugc2luY2UgdXNpbmcgYSBmdWxsIHN0cmluZyBVUkwKICAgICAgLy8gb3IgYFVSTGAgaW5zdGFuY2Ugc2hvdWxkIGJlIHRoZSBtb3N0IGNvbW1vbiB1c2FnZS4KICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnByb3RvY29sID09PSAnc3RyaW5nJykgewogICAgICAgIHJldHVybiBvcHRpb25zLnByb3RvY29sID09PSAnaHR0cHM6JzsKICAgICAgfQogICAgfQoKICAgIC8vIEZpbmFsbHksIGlmIG5vIGBwcm90b2NvbGAgcHJvcGVydHkgd2FzIHNldCwgdGhlbiBmYWxsIGJhY2sgdG8KICAgIC8vIGNoZWNraW5nIHRoZSBzdGFjayB0cmFjZSBvZiB0aGUgY3VycmVudCBjYWxsIHN0YWNrLCBhbmQgdHJ5IHRvCiAgICAvLyBkZXRlY3QgdGhlICJodHRwcyIgbW9kdWxlLgogICAgY29uc3QgeyBzdGFjayB9ID0gbmV3IEVycm9yKCk7CiAgICBpZiAodHlwZW9mIHN0YWNrICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlOwogICAgcmV0dXJuIHN0YWNrLnNwbGl0KCdcbicpLnNvbWUobCA9PiBsLmluZGV4T2YoJyhodHRwcy5qczonKSAhPT0gLTEgfHwgbC5pbmRleE9mKCdub2RlOmh0dHBzOicpICE9PSAtMSk7CiAgfQoKICBjcmVhdGVTb2NrZXQocmVxLCBvcHRpb25zLCBjYikgewogICAgY29uc3QgY29ubmVjdE9wdHMgPSB7CiAgICAgIC4uLm9wdGlvbnMsCiAgICAgIHNlY3VyZUVuZHBvaW50OiB0aGlzLmlzU2VjdXJlRW5kcG9pbnQob3B0aW9ucyksCiAgICB9OwogICAgUHJvbWlzZS5yZXNvbHZlKCkKICAgICAgLnRoZW4oKCkgPT4gdGhpcy5jb25uZWN0KHJlcSwgY29ubmVjdE9wdHMpKQogICAgICAudGhlbihzb2NrZXQgPT4gewogICAgICAgIGlmIChzb2NrZXQgaW5zdGFuY2VvZiBodHRwLkFnZW50KSB7CiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGBhZGRSZXF1ZXN0KClgIGlzbid0IGRlZmluZWQgaW4gYEB0eXBlcy9ub2RlYAogICAgICAgICAgcmV0dXJuIHNvY2tldC5hZGRSZXF1ZXN0KHJlcSwgY29ubmVjdE9wdHMpOwogICAgICAgIH0KICAgICAgICB0aGlzW0lOVEVSTkFMXS5jdXJyZW50U29ja2V0ID0gc29ja2V0OwogICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgYGNyZWF0ZVNvY2tldCgpYCBpc24ndCBkZWZpbmVkIGluIGBAdHlwZXMvbm9kZWAKICAgICAgICBzdXBlci5jcmVhdGVTb2NrZXQocmVxLCBvcHRpb25zLCBjYik7CiAgICAgIH0sIGNiKTsKICB9CgogIGNyZWF0ZUNvbm5lY3Rpb24oKSB7CiAgICBjb25zdCBzb2NrZXQgPSB0aGlzW0lOVEVSTkFMXS5jdXJyZW50U29ja2V0OwogICAgdGhpc1tJTlRFUk5BTF0uY3VycmVudFNvY2tldCA9IHVuZGVmaW5lZDsKICAgIGlmICghc29ja2V0KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24nKTsKICAgIH0KICAgIHJldHVybiBzb2NrZXQ7CiAgfQoKICBnZXQgZGVmYXVsdFBvcnQoKSB7CiAgICByZXR1cm4gX251bGxpc2hDb2FsZXNjZSQyKHRoaXNbSU5URVJOQUxdLmRlZmF1bHRQb3J0LCAoKSA9PiAoICh0aGlzLnByb3RvY29sID09PSAnaHR0cHM6JyA/IDQ0MyA6IDgwKSkpOwogIH0KCiAgc2V0IGRlZmF1bHRQb3J0KHYpIHsKICAgIGlmICh0aGlzW0lOVEVSTkFMXSkgewogICAgICB0aGlzW0lOVEVSTkFMXS5kZWZhdWx0UG9ydCA9IHY7CiAgICB9CiAgfQoKICBnZXQgcHJvdG9jb2woKSB7CiAgICByZXR1cm4gX251bGxpc2hDb2FsZXNjZSQyKHRoaXNbSU5URVJOQUxdLnByb3RvY29sLCAoKSA9PiAoICh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKSA/ICdodHRwczonIDogJ2h0dHA6JykpKTsKICB9CgogIHNldCBwcm90b2NvbCh2KSB7CiAgICBpZiAodGhpc1tJTlRFUk5BTF0pIHsKICAgICAgdGhpc1tJTlRFUk5BTF0ucHJvdG9jb2wgPSB2OwogICAgfQogIH0KfQoKZnVuY3Rpb24gZGVidWckMSguLi5hcmdzKSB7CiAgbG9nZ2VyLmxvZygnW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXScsIC4uLmFyZ3MpOwp9CgpmdW5jdGlvbiBwYXJzZVByb3h5UmVzcG9uc2Uoc29ja2V0KSB7CiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgIC8vIHdlIG5lZWQgdG8gYnVmZmVyIGFueSBIVFRQIHRyYWZmaWMgdGhhdCBoYXBwZW5zIHdpdGggdGhlIHByb3h5IGJlZm9yZSB3ZSBnZXQKICAgIC8vIHRoZSBDT05ORUNUIHJlc3BvbnNlLCBzbyB0aGF0IGlmIHRoZSByZXNwb25zZSBpcyBhbnl0aGluZyBvdGhlciB0aGFuIGFuICIyMDAiCiAgICAvLyByZXNwb25zZSBjb2RlLCB0aGVuIHdlIGNhbiByZS1wbGF5IHRoZSAiZGF0YSIgZXZlbnRzIG9uIHRoZSBzb2NrZXQgb25jZSB0aGUKICAgIC8vIEhUVFAgcGFyc2VyIGlzIGhvb2tlZCB1cC4uLgogICAgbGV0IGJ1ZmZlcnNMZW5ndGggPSAwOwogICAgY29uc3QgYnVmZmVycyA9IFtdOwoKICAgIGZ1bmN0aW9uIHJlYWQoKSB7CiAgICAgIGNvbnN0IGIgPSBzb2NrZXQucmVhZCgpOwogICAgICBpZiAoYikgb25kYXRhKGIpOwogICAgICBlbHNlIHNvY2tldC5vbmNlKCdyZWFkYWJsZScsIHJlYWQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGNsZWFudXAoKSB7CiAgICAgIHNvY2tldC5yZW1vdmVMaXN0ZW5lcignZW5kJywgb25lbmQpOwogICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25lcnJvcik7CiAgICAgIHNvY2tldC5yZW1vdmVMaXN0ZW5lcigncmVhZGFibGUnLCByZWFkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBvbmVuZCgpIHsKICAgICAgY2xlYW51cCgpOwogICAgICBkZWJ1ZyQxKCdvbmVuZCcpOwogICAgICByZWplY3QobmV3IEVycm9yKCdQcm94eSBjb25uZWN0aW9uIGVuZGVkIGJlZm9yZSByZWNlaXZpbmcgQ09OTkVDVCByZXNwb25zZScpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBvbmVycm9yKGVycikgewogICAgICBjbGVhbnVwKCk7CiAgICAgIGRlYnVnJDEoJ29uZXJyb3IgJW8nLCBlcnIpOwogICAgICByZWplY3QoZXJyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBvbmRhdGEoYikgewogICAgICBidWZmZXJzLnB1c2goYik7CiAgICAgIGJ1ZmZlcnNMZW5ndGggKz0gYi5sZW5ndGg7CgogICAgICBjb25zdCBidWZmZXJlZCA9IEJ1ZmZlci5jb25jYXQoYnVmZmVycywgYnVmZmVyc0xlbmd0aCk7CiAgICAgIGNvbnN0IGVuZE9mSGVhZGVycyA9IGJ1ZmZlcmVkLmluZGV4T2YoJ1xyXG5cclxuJyk7CgogICAgICBpZiAoZW5kT2ZIZWFkZXJzID09PSAtMSkgewogICAgICAgIC8vIGtlZXAgYnVmZmVyaW5nCiAgICAgICAgZGVidWckMSgnaGF2ZSBub3QgcmVjZWl2ZWQgZW5kIG9mIEhUVFAgaGVhZGVycyB5ZXQuLi4nKTsKICAgICAgICByZWFkKCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBjb25zdCBoZWFkZXJQYXJ0cyA9IGJ1ZmZlcmVkLnNsaWNlKDAsIGVuZE9mSGVhZGVycykudG9TdHJpbmcoJ2FzY2lpJykuc3BsaXQoJ1xyXG4nKTsKICAgICAgY29uc3QgZmlyc3RMaW5lID0gaGVhZGVyUGFydHMuc2hpZnQoKTsKICAgICAgaWYgKCFmaXJzdExpbmUpIHsKICAgICAgICBzb2NrZXQuZGVzdHJveSgpOwogICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKCdObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlJykpOwogICAgICB9CiAgICAgIGNvbnN0IGZpcnN0TGluZVBhcnRzID0gZmlyc3RMaW5lLnNwbGl0KCcgJyk7CiAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSArZmlyc3RMaW5lUGFydHNbMV07CiAgICAgIGNvbnN0IHN0YXR1c1RleHQgPSBmaXJzdExpbmVQYXJ0cy5zbGljZSgyKS5qb2luKCcgJyk7CiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7fTsKICAgICAgZm9yIChjb25zdCBoZWFkZXIgb2YgaGVhZGVyUGFydHMpIHsKICAgICAgICBpZiAoIWhlYWRlcikgY29udGludWU7CiAgICAgICAgY29uc3QgZmlyc3RDb2xvbiA9IGhlYWRlci5pbmRleE9mKCc6Jyk7CiAgICAgICAgaWYgKGZpcnN0Q29sb24gPT09IC0xKSB7CiAgICAgICAgICBzb2NrZXQuZGVzdHJveSgpOwogICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7aGVhZGVyfSJgKSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGtleSA9IGhlYWRlci5zbGljZSgwLCBmaXJzdENvbG9uKS50b0xvd2VyQ2FzZSgpOwogICAgICAgIGNvbnN0IHZhbHVlID0gaGVhZGVyLnNsaWNlKGZpcnN0Q29sb24gKyAxKS50cmltU3RhcnQoKTsKICAgICAgICBjb25zdCBjdXJyZW50ID0gaGVhZGVyc1trZXldOwogICAgICAgIGlmICh0eXBlb2YgY3VycmVudCA9PT0gJ3N0cmluZycpIHsKICAgICAgICAgIGhlYWRlcnNba2V5XSA9IFtjdXJyZW50LCB2YWx1ZV07CiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGN1cnJlbnQpKSB7CiAgICAgICAgICBjdXJyZW50LnB1c2godmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBoZWFkZXJzW2tleV0gPSB2YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZGVidWckMSgnZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8nLCBmaXJzdExpbmUsIGhlYWRlcnMpOwogICAgICBjbGVhbnVwKCk7CiAgICAgIHJlc29sdmUoewogICAgICAgIGNvbm5lY3Q6IHsKICAgICAgICAgIHN0YXR1c0NvZGUsCiAgICAgICAgICBzdGF0dXNUZXh0LAogICAgICAgICAgaGVhZGVycywKICAgICAgICB9LAogICAgICAgIGJ1ZmZlcmVkLAogICAgICB9KTsKICAgIH0KCiAgICBzb2NrZXQub24oJ2Vycm9yJywgb25lcnJvcik7CiAgICBzb2NrZXQub24oJ2VuZCcsIG9uZW5kKTsKCiAgICByZWFkKCk7CiAgfSk7Cn0KCmZ1bmN0aW9uIF9udWxsaXNoQ29hbGVzY2UkMShsaHMsIHJoc0ZuKSB7IGlmIChsaHMgIT0gbnVsbCkgeyByZXR1cm4gbGhzOyB9IGVsc2UgeyByZXR1cm4gcmhzRm4oKTsgfSB9IGZ1bmN0aW9uIF9vcHRpb25hbENoYWluJDEob3BzKSB7IGxldCBsYXN0QWNjZXNzTEhTID0gdW5kZWZpbmVkOyBsZXQgdmFsdWUgPSBvcHNbMF07IGxldCBpID0gMTsgd2hpbGUgKGkgPCBvcHMubGVuZ3RoKSB7IGNvbnN0IG9wID0gb3BzW2ldOyBjb25zdCBmbiA9IG9wc1tpICsgMV07IGkgKz0gMjsgaWYgKChvcCA9PT0gJ29wdGlvbmFsQWNjZXNzJyB8fCBvcCA9PT0gJ29wdGlvbmFsQ2FsbCcpICYmIHZhbHVlID09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBpZiAob3AgPT09ICdhY2Nlc3MnIHx8IG9wID09PSAnb3B0aW9uYWxBY2Nlc3MnKSB7IGxhc3RBY2Nlc3NMSFMgPSB2YWx1ZTsgdmFsdWUgPSBmbih2YWx1ZSk7IH0gZWxzZSBpZiAob3AgPT09ICdjYWxsJyB8fCBvcCA9PT0gJ29wdGlvbmFsQ2FsbCcpIHsgdmFsdWUgPSBmbigoLi4uYXJncykgPT4gdmFsdWUuY2FsbChsYXN0QWNjZXNzTEhTLCAuLi5hcmdzKSk7IGxhc3RBY2Nlc3NMSFMgPSB1bmRlZmluZWQ7IH0gfSByZXR1cm4gdmFsdWU7IH0vKioKICogVGhpcyBjb2RlIHdhcyBvcmlnaW5hbGx5IGZvcmtlZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9Ub29UYWxsTmF0ZS9wcm94eS1hZ2VudHMvdHJlZS9iMTMzMjk1ZmQxNmY2NDc1NTc4YjZiMTViZDliNGUzM2VjYjBkMGI3CiAqIFdpdGggdGhlIGZvbGxvd2luZyBsaWNlbmNlOgogKgogKiAoVGhlIE1JVCBMaWNlbnNlKQogKgogKiBDb3B5cmlnaHQgKGMpIDIwMTMgTmF0aGFuIFJhamxpY2ggPG5hdGhhbkB0b290YWxsbmF0ZS5uZXQ+KgogKgogKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcKICogYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlCiAqICdTb2Z0d2FyZScpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcKICogd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLAogKiBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8KICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvCiAqIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoqCiAqCiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlCiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLioKICoKICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICdBUyBJUycsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsCiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRgogKiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuCiAqIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZCiAqIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsCiAqIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFCiAqIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgogKi8KCmZ1bmN0aW9uIGRlYnVnKC4uLmFyZ3MpIHsKICBsb2dnZXIubG9nKCdbaHR0cHMtcHJveHktYWdlbnRdJywgLi4uYXJncyk7Cn0KCi8qKgogKiBUaGUgYEh0dHBzUHJveHlBZ2VudGAgaW1wbGVtZW50cyBhbiBIVFRQIEFnZW50IHN1YmNsYXNzIHRoYXQgY29ubmVjdHMgdG8KICogdGhlIHNwZWNpZmllZCAiSFRUUChzKSBwcm94eSBzZXJ2ZXIiIGluIG9yZGVyIHRvIHByb3h5IEhUVFBTIHJlcXVlc3RzLgogKgogKiBPdXRnb2luZyBIVFRQIHJlcXVlc3RzIGFyZSBmaXJzdCB0dW5uZWxlZCB0aHJvdWdoIHRoZSBwcm94eSBzZXJ2ZXIgdXNpbmcgdGhlCiAqIGBDT05ORUNUYCBIVFRQIHJlcXVlc3QgbWV0aG9kIHRvIGVzdGFibGlzaCBhIGNvbm5lY3Rpb24gdG8gdGhlIHByb3h5IHNlcnZlciwKICogYW5kIHRoZW4gdGhlIHByb3h5IHNlcnZlciBjb25uZWN0cyB0byB0aGUgZGVzdGluYXRpb24gdGFyZ2V0IGFuZCBpc3N1ZXMgdGhlCiAqIEhUVFAgcmVxdWVzdCBmcm9tIHRoZSBwcm94eSBzZXJ2ZXIuCiAqCiAqIGBodHRwczpgIHJlcXVlc3RzIGhhdmUgdGhlaXIgc29ja2V0IGNvbm5lY3Rpb24gdXBncmFkZWQgdG8gVExTIG9uY2UKICogdGhlIGNvbm5lY3Rpb24gdG8gdGhlIHByb3h5IHNlcnZlciBoYXMgYmVlbiBlc3RhYmxpc2hlZC4KICovCmNsYXNzIEh0dHBzUHJveHlBZ2VudCBleHRlbmRzIEFnZW50IHsKICBzdGF0aWMgX19pbml0U3RhdGljKCkge3RoaXMucHJvdG9jb2xzID0gWydodHRwJywgJ2h0dHBzJ107IH0KCiAgY29uc3RydWN0b3IocHJveHksIG9wdHMpIHsKICAgIHN1cGVyKG9wdHMpOwogICAgdGhpcy5vcHRpb25zID0ge307CiAgICB0aGlzLnByb3h5ID0gdHlwZW9mIHByb3h5ID09PSAnc3RyaW5nJyA/IG5ldyBVUkwocHJveHkpIDogcHJveHk7CiAgICB0aGlzLnByb3h5SGVhZGVycyA9IF9udWxsaXNoQ29hbGVzY2UkMShfb3B0aW9uYWxDaGFpbiQxKFtvcHRzLCAnb3B0aW9uYWxBY2Nlc3MnLCBfMiA9PiBfMi5oZWFkZXJzXSksICgpID0+ICgge30pKTsKICAgIGRlYnVnKCdDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbycsIHRoaXMucHJveHkuaHJlZik7CgogICAgLy8gVHJpbSBvZmYgdGhlIGJyYWNrZXRzIGZyb20gSVB2NiBhZGRyZXNzZXMKICAgIGNvbnN0IGhvc3QgPSAodGhpcy5wcm94eS5ob3N0bmFtZSB8fCB0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywgJycpOwogICAgY29uc3QgcG9ydCA9IHRoaXMucHJveHkucG9ydCA/IHBhcnNlSW50KHRoaXMucHJveHkucG9ydCwgMTApIDogdGhpcy5wcm94eS5wcm90b2NvbCA9PT0gJ2h0dHBzOicgPyA0NDMgOiA4MDsKICAgIHRoaXMuY29ubmVjdE9wdHMgPSB7CiAgICAgIC8vIEF0dGVtcHQgdG8gbmVnb3RpYXRlIGh0dHAvMS4xIGZvciBwcm94eSBzZXJ2ZXJzIHRoYXQgc3VwcG9ydCBodHRwLzIKICAgICAgQUxQTlByb3RvY29sczogWydodHRwLzEuMSddLAogICAgICAuLi4ob3B0cyA/IG9taXQob3B0cywgJ2hlYWRlcnMnKSA6IG51bGwpLAogICAgICBob3N0LAogICAgICBwb3J0LAogICAgfTsKICB9CgogIC8qKgogICAqIENhbGxlZCB3aGVuIHRoZSBub2RlLWNvcmUgSFRUUCBjbGllbnQgbGlicmFyeSBpcyBjcmVhdGluZyBhCiAgICogbmV3IEhUVFAgcmVxdWVzdC4KICAgKi8KICBhc3luYyBjb25uZWN0KHJlcSwgb3B0cykgewogICAgY29uc3QgeyBwcm94eSB9ID0gdGhpczsKCiAgICBpZiAoIW9wdHMuaG9zdCkgewogICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTsKICAgIH0KCiAgICAvLyBDcmVhdGUgYSBzb2NrZXQgY29ubmVjdGlvbiB0byB0aGUgcHJveHkgc2VydmVyLgogICAgbGV0IHNvY2tldDsKICAgIGlmIChwcm94eS5wcm90b2NvbCA9PT0gJ2h0dHBzOicpIHsKICAgICAgZGVidWcoJ0NyZWF0aW5nIGB0bHMuU29ja2V0YDogJW8nLCB0aGlzLmNvbm5lY3RPcHRzKTsKICAgICAgY29uc3Qgc2VydmVybmFtZSA9IHRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZSB8fCB0aGlzLmNvbm5lY3RPcHRzLmhvc3Q7CiAgICAgIHNvY2tldCA9IHRscy5jb25uZWN0KHsKICAgICAgICAuLi50aGlzLmNvbm5lY3RPcHRzLAogICAgICAgIHNlcnZlcm5hbWU6IHNlcnZlcm5hbWUgJiYgbmV0LmlzSVAoc2VydmVybmFtZSkgPyB1bmRlZmluZWQgOiBzZXJ2ZXJuYW1lLAogICAgICB9KTsKICAgIH0gZWxzZSB7CiAgICAgIGRlYnVnKCdDcmVhdGluZyBgbmV0LlNvY2tldGA6ICVvJywgdGhpcy5jb25uZWN0T3B0cyk7CiAgICAgIHNvY2tldCA9IG5ldC5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpOwogICAgfQoKICAgIGNvbnN0IGhlYWRlcnMgPQogICAgICB0eXBlb2YgdGhpcy5wcm94eUhlYWRlcnMgPT09ICdmdW5jdGlvbicgPyB0aGlzLnByb3h5SGVhZGVycygpIDogeyAuLi50aGlzLnByb3h5SGVhZGVycyB9OwogICAgY29uc3QgaG9zdCA9IG5ldC5pc0lQdjYob3B0cy5ob3N0KSA/IGBbJHtvcHRzLmhvc3R9XWAgOiBvcHRzLmhvc3Q7CiAgICBsZXQgcGF5bG9hZCA9IGBDT05ORUNUICR7aG9zdH06JHtvcHRzLnBvcnR9IEhUVFAvMS4xXHJcbmA7CgogICAgLy8gSW5qZWN0IHRoZSBgUHJveHktQXV0aG9yaXphdGlvbmAgaGVhZGVyIGlmIG5lY2Vzc2FyeS4KICAgIGlmIChwcm94eS51c2VybmFtZSB8fCBwcm94eS5wYXNzd29yZCkgewogICAgICBjb25zdCBhdXRoID0gYCR7ZGVjb2RlVVJJQ29tcG9uZW50KHByb3h5LnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQocHJveHkucGFzc3dvcmQpfWA7CiAgICAgIGhlYWRlcnNbJ1Byb3h5LUF1dGhvcml6YXRpb24nXSA9IGBCYXNpYyAke0J1ZmZlci5mcm9tKGF1dGgpLnRvU3RyaW5nKCdiYXNlNjQnKX1gOwogICAgfQoKICAgIGhlYWRlcnMuSG9zdCA9IGAke2hvc3R9OiR7b3B0cy5wb3J0fWA7CgogICAgaWYgKCFoZWFkZXJzWydQcm94eS1Db25uZWN0aW9uJ10pIHsKICAgICAgaGVhZGVyc1snUHJveHktQ29ubmVjdGlvbiddID0gdGhpcy5rZWVwQWxpdmUgPyAnS2VlcC1BbGl2ZScgOiAnY2xvc2UnOwogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7CiAgICAgIHBheWxvYWQgKz0gYCR7bmFtZX06ICR7aGVhZGVyc1tuYW1lXX1cclxuYDsKICAgIH0KCiAgICBjb25zdCBwcm94eVJlc3BvbnNlUHJvbWlzZSA9IHBhcnNlUHJveHlSZXNwb25zZShzb2NrZXQpOwoKICAgIHNvY2tldC53cml0ZShgJHtwYXlsb2FkfVxyXG5gKTsKCiAgICBjb25zdCB7IGNvbm5lY3QsIGJ1ZmZlcmVkIH0gPSBhd2FpdCBwcm94eVJlc3BvbnNlUHJvbWlzZTsKICAgIHJlcS5lbWl0KCdwcm94eUNvbm5lY3QnLCBjb25uZWN0KTsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnQKICAgIC8vIEB0cy1pZ25vcmUgTm90IEV2ZW50RW1pdHRlciBpbiBOb2RlIHR5cGVzCiAgICB0aGlzLmVtaXQoJ3Byb3h5Q29ubmVjdCcsIGNvbm5lY3QsIHJlcSk7CgogICAgaWYgKGNvbm5lY3Quc3RhdHVzQ29kZSA9PT0gMjAwKSB7CiAgICAgIHJlcS5vbmNlKCdzb2NrZXQnLCByZXN1bWUpOwoKICAgICAgaWYgKG9wdHMuc2VjdXJlRW5kcG9pbnQpIHsKICAgICAgICAvLyBUaGUgcHJveHkgaXMgY29ubmVjdGluZyB0byBhIFRMUyBzZXJ2ZXIsIHNvIHVwZ3JhZGUKICAgICAgICAvLyB0aGlzIHNvY2tldCBjb25uZWN0aW9uIHRvIGEgVExTIGNvbm5lY3Rpb24uCiAgICAgICAgZGVidWcoJ1VwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMnKTsKICAgICAgICBjb25zdCBzZXJ2ZXJuYW1lID0gb3B0cy5zZXJ2ZXJuYW1lIHx8IG9wdHMuaG9zdDsKICAgICAgICByZXR1cm4gdGxzLmNvbm5lY3QoewogICAgICAgICAgLi4ub21pdChvcHRzLCAnaG9zdCcsICdwYXRoJywgJ3BvcnQnKSwKICAgICAgICAgIHNvY2tldCwKICAgICAgICAgIHNlcnZlcm5hbWU6IG5ldC5pc0lQKHNlcnZlcm5hbWUpID8gdW5kZWZpbmVkIDogc2VydmVybmFtZSwKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHNvY2tldDsKICAgIH0KCiAgICAvLyBTb21lIG90aGVyIHN0YXR1cyBjb2RlIHRoYXQncyBub3QgMjAwLi4uIG5lZWQgdG8gcmUtcGxheSB0aGUgSFRUUAogICAgLy8gaGVhZGVyICJkYXRhIiBldmVudHMgb250byB0aGUgc29ja2V0IG9uY2UgdGhlIEhUVFAgbWFjaGluZXJ5IGlzCiAgICAvLyBhdHRhY2hlZCBzbyB0aGF0IHRoZSBub2RlIGNvcmUgYGh0dHBgIGNhbiBwYXJzZSBhbmQgaGFuZGxlIHRoZQogICAgLy8gZXJyb3Igc3RhdHVzIGNvZGUuCgogICAgLy8gQ2xvc2UgdGhlIG9yaWdpbmFsIHNvY2tldCwgYW5kIGEgbmV3ICJmYWtlIiBzb2NrZXQgaXMgcmV0dXJuZWQKICAgIC8vIGluc3RlYWQsIHNvIHRoYXQgdGhlIHByb3h5IGRvZXNuJ3QgZ2V0IHRoZSBIVFRQIHJlcXVlc3QKICAgIC8vIHdyaXR0ZW4gdG8gaXQgKHdoaWNoIG1heSBjb250YWluIGBBdXRob3JpemF0aW9uYCBoZWFkZXJzIG9yIG90aGVyCiAgICAvLyBzZW5zaXRpdmUgZGF0YSkuCiAgICAvLwogICAgLy8gU2VlOiBodHRwczovL2hhY2tlcm9uZS5jb20vcmVwb3J0cy81NDE1MDIKICAgIHNvY2tldC5kZXN0cm95KCk7CgogICAgY29uc3QgZmFrZVNvY2tldCA9IG5ldyBuZXQuU29ja2V0KHsgd3JpdGFibGU6IGZhbHNlIH0pOwogICAgZmFrZVNvY2tldC5yZWFkYWJsZSA9IHRydWU7CgogICAgLy8gTmVlZCB0byB3YWl0IGZvciB0aGUgInNvY2tldCIgZXZlbnQgdG8gcmUtcGxheSB0aGUgImRhdGEiIGV2ZW50cy4KICAgIHJlcS5vbmNlKCdzb2NrZXQnLCAocykgPT4gewogICAgICBkZWJ1ZygnUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QnKTsKICAgICAgYXNzZXJ0KHMubGlzdGVuZXJDb3VudCgnZGF0YScpID4gMCk7CgogICAgICAvLyBSZXBsYXkgdGhlICJidWZmZXJlZCIgQnVmZmVyIG9udG8gdGhlIGZha2UgYHNvY2tldGAsIHNpbmNlIGF0CiAgICAgIC8vIHRoaXMgcG9pbnQgdGhlIEhUVFAgbW9kdWxlIG1hY2hpbmVyeSBoYXMgYmVlbiBob29rZWQgdXAgZm9yCiAgICAgIC8vIHRoZSB1c2VyLgogICAgICBzLnB1c2goYnVmZmVyZWQpOwogICAgICBzLnB1c2gobnVsbCk7CiAgICB9KTsKCiAgICByZXR1cm4gZmFrZVNvY2tldDsKICB9Cn0gSHR0cHNQcm94eUFnZW50Ll9faW5pdFN0YXRpYygpOwoKZnVuY3Rpb24gcmVzdW1lKHNvY2tldCkgewogIHNvY2tldC5yZXN1bWUoKTsKfQoKZnVuY3Rpb24gb21pdCgKICBvYmosCiAgLi4ua2V5cwopCgogewogIGNvbnN0IHJldCA9IHt9Cgo7CiAgbGV0IGtleTsKICBmb3IgKGtleSBpbiBvYmopIHsKICAgIGlmICgha2V5cy5pbmNsdWRlcyhrZXkpKSB7CiAgICAgIHJldFtrZXldID0gb2JqW2tleV07CiAgICB9CiAgfQogIHJldHVybiByZXQ7Cn0KCmZ1bmN0aW9uIF9udWxsaXNoQ29hbGVzY2UobGhzLCByaHNGbikgeyBpZiAobGhzICE9IG51bGwpIHsgcmV0dXJuIGxoczsgfSBlbHNlIHsgcmV0dXJuIHJoc0ZuKCk7IH0gfQovLyBFc3RpbWF0ZWQgbWF4aW11bSBzaXplIGZvciByZWFzb25hYmxlIHN0YW5kYWxvbmUgZXZlbnQKY29uc3QgR1pJUF9USFJFU0hPTEQgPSAxMDI0ICogMzI7CgovKioKICogR2V0cyBhIHN0cmVhbSBmcm9tIGEgVWludDhBcnJheSBvciBzdHJpbmcKICogUmVhZGFibGUuZnJvbSBpcyBpZGVhbCBidXQgd2FzIGFkZGVkIGluIG5vZGUuanMgdjEyLjMuMCBhbmQgdjEwLjE3LjAKICovCmZ1bmN0aW9uIHN0cmVhbUZyb21Cb2R5KGJvZHkpIHsKICByZXR1cm4gbmV3IFJlYWRhYmxlKHsKICAgIHJlYWQoKSB7CiAgICAgIHRoaXMucHVzaChib2R5KTsKICAgICAgdGhpcy5wdXNoKG51bGwpOwogICAgfSwKICB9KTsKfQoKLyoqCiAqIENyZWF0ZXMgYSBUcmFuc3BvcnQgdGhhdCB1c2VzIG5hdGl2ZSB0aGUgbmF0aXZlICdodHRwJyBhbmQgJ2h0dHBzJyBtb2R1bGVzIHRvIHNlbmQgZXZlbnRzIHRvIFNlbnRyeS4KICovCmZ1bmN0aW9uIG1ha2VOb2RlVHJhbnNwb3J0KG9wdGlvbnMpIHsKICBsZXQgdXJsU2VnbWVudHM7CgogIHRyeSB7CiAgICB1cmxTZWdtZW50cyA9IG5ldyBVUkwob3B0aW9ucy51cmwpOwogIH0gY2F0Y2ggKGUpIHsKICAgIGNvbnNvbGVTYW5kYm94KCgpID0+IHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUKICAgICAgY29uc29sZS53YXJuKAogICAgICAgICdbQHNlbnRyeS9ub2RlXTogSW52YWxpZCBkc24gb3IgdHVubmVsIG9wdGlvbiwgd2lsbCBub3Qgc2VuZCBhbnkgZXZlbnRzLiBUaGUgdHVubmVsIG9wdGlvbiBtdXN0IGJlIGEgZnVsbCBVUkwgd2hlbiB1c2VkLicsCiAgICAgICk7CiAgICB9KTsKICAgIHJldHVybiBjcmVhdGVUcmFuc3BvcnQob3B0aW9ucywgKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHt9KSk7CiAgfQoKICBjb25zdCBpc0h0dHBzID0gdXJsU2VnbWVudHMucHJvdG9jb2wgPT09ICdodHRwczonOwoKICAvLyBQcm94eSBwcmlvcml0aXphdGlvbjogaHR0cCA9PiBgb3B0aW9ucy5wcm94eWAgfCBgcHJvY2Vzcy5lbnYuaHR0cF9wcm94eWAKICAvLyBQcm94eSBwcmlvcml0aXphdGlvbjogaHR0cHMgPT4gYG9wdGlvbnMucHJveHlgIHwgYHByb2Nlc3MuZW52Lmh0dHBzX3Byb3h5YCB8IGBwcm9jZXNzLmVudi5odHRwX3Byb3h5YAogIGNvbnN0IHByb3h5ID0gYXBwbHlOb1Byb3h5T3B0aW9uKAogICAgdXJsU2VnbWVudHMsCiAgICBvcHRpb25zLnByb3h5IHx8IChpc0h0dHBzID8gcHJvY2Vzcy5lbnYuaHR0cHNfcHJveHkgOiB1bmRlZmluZWQpIHx8IHByb2Nlc3MuZW52Lmh0dHBfcHJveHksCiAgKTsKCiAgY29uc3QgbmF0aXZlSHR0cE1vZHVsZSA9IGlzSHR0cHMgPyBodHRwcyA6IGh0dHA7CiAgY29uc3Qga2VlcEFsaXZlID0gb3B0aW9ucy5rZWVwQWxpdmUgPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogb3B0aW9ucy5rZWVwQWxpdmU7CgogIC8vIFRPRE8odjcpOiBFdmFsdWF0ZSBpZiB3ZSBjYW4gc2V0IGtlZXBBbGl2ZSB0byB0cnVlLiBUaGlzIHdvdWxkIGludm9sdmUgdGVzdGluZyBmb3IgbWVtb3J5IGxlYWtzIGluIG9sZGVyIG5vZGUKICAvLyB2ZXJzaW9ucyg+PSA4KSBhcyB0aGV5IGhhZCBtZW1vcnkgbGVha3Mgd2hlbiB1c2luZyBpdDogIzI1NTUKICBjb25zdCBhZ2VudCA9IHByb3h5CiAgICA/IChuZXcgSHR0cHNQcm94eUFnZW50KHByb3h5KSApCiAgICA6IG5ldyBuYXRpdmVIdHRwTW9kdWxlLkFnZW50KHsga2VlcEFsaXZlLCBtYXhTb2NrZXRzOiAzMCwgdGltZW91dDogMjAwMCB9KTsKCiAgY29uc3QgcmVxdWVzdEV4ZWN1dG9yID0gY3JlYXRlUmVxdWVzdEV4ZWN1dG9yKG9wdGlvbnMsIF9udWxsaXNoQ29hbGVzY2Uob3B0aW9ucy5odHRwTW9kdWxlLCAoKSA9PiAoIG5hdGl2ZUh0dHBNb2R1bGUpKSwgYWdlbnQpOwogIHJldHVybiBjcmVhdGVUcmFuc3BvcnQob3B0aW9ucywgcmVxdWVzdEV4ZWN1dG9yKTsKfQoKLyoqCiAqIEhvbm9ycyB0aGUgYG5vX3Byb3h5YCBlbnYgdmFyaWFibGUgd2l0aCB0aGUgaGlnaGVzdCBwcmlvcml0eSB0byBhbGxvdyBmb3IgaG9zdHMgZXhjbHVzaW9uLgogKgogKiBAcGFyYW0gdHJhbnNwb3J0VXJsIFRoZSBVUkwgdGhlIHRyYW5zcG9ydCBpbnRlbmRzIHRvIHNlbmQgZXZlbnRzIHRvLgogKiBAcGFyYW0gcHJveHkgVGhlIGNsaWVudCBjb25maWd1cmVkIHByb3h5LgogKiBAcmV0dXJucyBBIHByb3h5IHRoZSB0cmFuc3BvcnQgc2hvdWxkIHVzZS4KICovCmZ1bmN0aW9uIGFwcGx5Tm9Qcm94eU9wdGlvbih0cmFuc3BvcnRVcmxTZWdtZW50cywgcHJveHkpIHsKICBjb25zdCB7IG5vX3Byb3h5IH0gPSBwcm9jZXNzLmVudjsKCiAgY29uc3QgdXJsSXNFeGVtcHRGcm9tUHJveHkgPQogICAgbm9fcHJveHkgJiYKICAgIG5vX3Byb3h5CiAgICAgIC5zcGxpdCgnLCcpCiAgICAgIC5zb21lKAogICAgICAgIGV4ZW1wdGlvbiA9PiB0cmFuc3BvcnRVcmxTZWdtZW50cy5ob3N0LmVuZHNXaXRoKGV4ZW1wdGlvbikgfHwgdHJhbnNwb3J0VXJsU2VnbWVudHMuaG9zdG5hbWUuZW5kc1dpdGgoZXhlbXB0aW9uKSwKICAgICAgKTsKCiAgaWYgKHVybElzRXhlbXB0RnJvbVByb3h5KSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0gZWxzZSB7CiAgICByZXR1cm4gcHJveHk7CiAgfQp9CgovKioKICogQ3JlYXRlcyBhIFJlcXVlc3RFeGVjdXRvciB0byBiZSB1c2VkIHdpdGggYGNyZWF0ZVRyYW5zcG9ydGAuCiAqLwpmdW5jdGlvbiBjcmVhdGVSZXF1ZXN0RXhlY3V0b3IoCiAgb3B0aW9ucywKICBodHRwTW9kdWxlLAogIGFnZW50LAopIHsKICBjb25zdCB7IGhvc3RuYW1lLCBwYXRobmFtZSwgcG9ydCwgcHJvdG9jb2wsIHNlYXJjaCB9ID0gbmV3IFVSTChvcHRpb25zLnVybCk7CiAgcmV0dXJuIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0KHJlcXVlc3QpIHsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGxldCBib2R5ID0gc3RyZWFtRnJvbUJvZHkocmVxdWVzdC5ib2R5KTsKCiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7IC4uLm9wdGlvbnMuaGVhZGVycyB9OwoKICAgICAgaWYgKHJlcXVlc3QuYm9keS5sZW5ndGggPiBHWklQX1RIUkVTSE9MRCkgewogICAgICAgIGhlYWRlcnNbJ2NvbnRlbnQtZW5jb2RpbmcnXSA9ICdnemlwJzsKICAgICAgICBib2R5ID0gYm9keS5waXBlKGNyZWF0ZUd6aXAoKSk7CiAgICAgIH0KCiAgICAgIGNvbnN0IHJlcSA9IGh0dHBNb2R1bGUucmVxdWVzdCgKICAgICAgICB7CiAgICAgICAgICBtZXRob2Q6ICdQT1NUJywKICAgICAgICAgIGFnZW50LAogICAgICAgICAgaGVhZGVycywKICAgICAgICAgIGhvc3RuYW1lLAogICAgICAgICAgcGF0aDogYCR7cGF0aG5hbWV9JHtzZWFyY2h9YCwKICAgICAgICAgIHBvcnQsCiAgICAgICAgICBwcm90b2NvbCwKICAgICAgICAgIGNhOiBvcHRpb25zLmNhQ2VydHMsCiAgICAgICAgfSwKICAgICAgICByZXMgPT4gewogICAgICAgICAgcmVzLm9uKCdkYXRhJywgKCkgPT4gewogICAgICAgICAgICAvLyBEcmFpbiBzb2NrZXQKICAgICAgICAgIH0pOwoKICAgICAgICAgIHJlcy5vbignZW5kJywgKCkgPT4gewogICAgICAgICAgICAvLyBEcmFpbiBzb2NrZXQKICAgICAgICAgIH0pOwoKICAgICAgICAgIHJlcy5zZXRFbmNvZGluZygndXRmOCcpOwoKICAgICAgICAgIC8vICJLZXktdmFsdWUgcGFpcnMgb2YgaGVhZGVyIG5hbWVzIGFuZCB2YWx1ZXMuIEhlYWRlciBuYW1lcyBhcmUgbG93ZXItY2FzZWQuIgogICAgICAgICAgLy8gaHR0cHM6Ly9ub2RlanMub3JnL2FwaS9odHRwLmh0bWwjaHR0cF9tZXNzYWdlX2hlYWRlcnMKICAgICAgICAgIGNvbnN0IHJldHJ5QWZ0ZXJIZWFkZXIgPSBfbnVsbGlzaENvYWxlc2NlKHJlcy5oZWFkZXJzWydyZXRyeS1hZnRlciddLCAoKSA9PiAoIG51bGwpKTsKICAgICAgICAgIGNvbnN0IHJhdGVMaW1pdHNIZWFkZXIgPSBfbnVsbGlzaENvYWxlc2NlKHJlcy5oZWFkZXJzWyd4LXNlbnRyeS1yYXRlLWxpbWl0cyddLCAoKSA9PiAoIG51bGwpKTsKCiAgICAgICAgICByZXNvbHZlKHsKICAgICAgICAgICAgc3RhdHVzQ29kZTogcmVzLnN0YXR1c0NvZGUsCiAgICAgICAgICAgIGhlYWRlcnM6IHsKICAgICAgICAgICAgICAncmV0cnktYWZ0ZXInOiByZXRyeUFmdGVySGVhZGVyLAogICAgICAgICAgICAgICd4LXNlbnRyeS1yYXRlLWxpbWl0cyc6IEFycmF5LmlzQXJyYXkocmF0ZUxpbWl0c0hlYWRlcikgPyByYXRlTGltaXRzSGVhZGVyWzBdIDogcmF0ZUxpbWl0c0hlYWRlciwKICAgICAgICAgICAgfSwKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICk7CgogICAgICByZXEub24oJ2Vycm9yJywgcmVqZWN0KTsKICAgICAgYm9keS5waXBlKHJlcSk7CiAgICB9KTsKICB9Owp9CgpmdW5jdGlvbiBfb3B0aW9uYWxDaGFpbihvcHMpIHsgbGV0IGxhc3RBY2Nlc3NMSFMgPSB1bmRlZmluZWQ7IGxldCB2YWx1ZSA9IG9wc1swXTsgbGV0IGkgPSAxOyB3aGlsZSAoaSA8IG9wcy5sZW5ndGgpIHsgY29uc3Qgb3AgPSBvcHNbaV07IGNvbnN0IGZuID0gb3BzW2kgKyAxXTsgaSArPSAyOyBpZiAoKG9wID09PSAnb3B0aW9uYWxBY2Nlc3MnIHx8IG9wID09PSAnb3B0aW9uYWxDYWxsJykgJiYgdmFsdWUgPT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGlmIChvcCA9PT0gJ2FjY2VzcycgfHwgb3AgPT09ICdvcHRpb25hbEFjY2VzcycpIHsgbGFzdEFjY2Vzc0xIUyA9IHZhbHVlOyB2YWx1ZSA9IGZuKHZhbHVlKTsgfSBlbHNlIGlmIChvcCA9PT0gJ2NhbGwnIHx8IG9wID09PSAnb3B0aW9uYWxDYWxsJykgeyB2YWx1ZSA9IGZuKCguLi5hcmdzKSA9PiB2YWx1ZS5jYWxsKGxhc3RBY2Nlc3NMSFMsIC4uLmFyZ3MpKTsgbGFzdEFjY2Vzc0xIUyA9IHVuZGVmaW5lZDsgfSB9IHJldHVybiB2YWx1ZTsgfQpjb25zdCBvcHRpb25zID0gd29ya2VyRGF0YTsKbGV0IHNlc3Npb247CmxldCBoYXNTZW50QW5yRXZlbnQgPSBmYWxzZTsKCmZ1bmN0aW9uIGxvZyhtc2cpIHsKICBpZiAob3B0aW9ucy5kZWJ1ZykgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUKICAgIGNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHttc2d9YCk7CiAgfQp9Cgpjb25zdCB1cmwgPSBnZXRFbnZlbG9wZUVuZHBvaW50V2l0aFVybEVuY29kZWRBdXRoKG9wdGlvbnMuZHNuKTsKY29uc3QgdHJhbnNwb3J0ID0gbWFrZU5vZGVUcmFuc3BvcnQoewogIHVybCwKICByZWNvcmREcm9wcGVkRXZlbnQ6ICgpID0+IHsKICAgIC8vCiAgfSwKfSk7Cgphc3luYyBmdW5jdGlvbiBzZW5kQWJub3JtYWxTZXNzaW9uKCkgewogIC8vIG9mIHdlIGhhdmUgYW4gZXhpc3Rpbmcgc2Vzc2lvbiBwYXNzZWQgZnJvbSB0aGUgbWFpbiB0aHJlYWQsIHNlbmQgaXQgYXMgYWJub3JtYWwKICBpZiAoc2Vzc2lvbikgewogICAgbG9nKCdTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24nKTsKICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbiwgeyBzdGF0dXM6ICdhYm5vcm1hbCcsIGFibm9ybWFsX21lY2hhbmlzbTogJ2Fucl9mb3JlZ3JvdW5kJyB9KTsKCiAgICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZVNlc3Npb25FbnZlbG9wZShzZXNzaW9uLCBvcHRpb25zLmRzbiwgb3B0aW9ucy5zZGtNZXRhZGF0YSk7CiAgICAvLyBMb2cgdGhlIGVudmVsb3BlIHNvIHRvIGFpZCBpbiB0ZXN0aW5nCiAgICBsb2coSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKTsKCiAgICBhd2FpdCB0cmFuc3BvcnQuc2VuZChlbnZlbG9wZSk7CgogICAgdHJ5IHsKICAgICAgLy8gTm90aWZ5IHRoZSBtYWluIHByb2Nlc3MgdGhhdCB0aGUgc2Vzc2lvbiBoYXMgZW5kZWQgc28gdGhlIHNlc3Npb24gY2FuIGJlIGNsZWFyZWQgZnJvbSB0aGUgc2NvcGUKICAgICAgX29wdGlvbmFsQ2hhaW4oW3BhcmVudFBvcnQsICdvcHRpb25hbEFjY2VzcycsIF8yID0+IF8yLnBvc3RNZXNzYWdlLCAnY2FsbCcsIF8zID0+IF8zKCdzZXNzaW9uLWVuZGVkJyldKTsKICAgIH0gY2F0Y2ggKF8pIHsKICAgICAgLy8gaWdub3JlCiAgICB9CiAgfQp9Cgpsb2coJ1N0YXJ0ZWQnKTsKCmZ1bmN0aW9uIHByZXBhcmVTdGFja0ZyYW1lcyhzdGFja0ZyYW1lcykgewogIGlmICghc3RhY2tGcmFtZXMpIHsKICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQoKICAvLyBTdHJpcCBTZW50cnkgZnJhbWVzIGFuZCByZXZlcnNlIHRoZSBzdGFjayBmcmFtZXMgc28gdGhleSBhcmUgaW4gdGhlIGNvcnJlY3Qgb3JkZXIKICBjb25zdCBzdHJpcHBlZEZyYW1lcyA9IHN0cmlwU2VudHJ5RnJhbWVzQW5kUmV2ZXJzZShzdGFja0ZyYW1lcyk7CgogIC8vIElmIHdlIGhhdmUgYW4gYXBwIHJvb3QgcGF0aCwgcmV3cml0ZSB0aGUgZmlsZW5hbWVzIHRvIGJlIHJlbGF0aXZlIHRvIHRoZSBhcHAgcm9vdAogIGlmIChvcHRpb25zLmFwcFJvb3RQYXRoKSB7CiAgICBmb3IgKGNvbnN0IGZyYW1lIG9mIHN0cmlwcGVkRnJhbWVzKSB7CiAgICAgIGlmICghZnJhbWUuZmlsZW5hbWUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgZnJhbWUuZmlsZW5hbWUgPSBub3JtYWxpemVVcmxUb0Jhc2UoZnJhbWUuZmlsZW5hbWUsIG9wdGlvbnMuYXBwUm9vdFBhdGgpOwogICAgfQogIH0KCiAgcmV0dXJuIHN0cmlwcGVkRnJhbWVzOwp9Cgphc3luYyBmdW5jdGlvbiBzZW5kQW5yRXZlbnQoZnJhbWVzLCB0cmFjZUNvbnRleHQpIHsKICBpZiAoaGFzU2VudEFuckV2ZW50KSB7CiAgICByZXR1cm47CiAgfQoKICBoYXNTZW50QW5yRXZlbnQgPSB0cnVlOwoKICBhd2FpdCBzZW5kQWJub3JtYWxTZXNzaW9uKCk7CgogIGxvZygnU2VuZGluZyBldmVudCcpOwoKICBjb25zdCBldmVudCA9IHsKICAgIGV2ZW50X2lkOiB1dWlkNCgpLAogICAgY29udGV4dHM6IHsgLi4ub3B0aW9ucy5jb250ZXh0cywgdHJhY2U6IHRyYWNlQ29udGV4dCB9LAogICAgcmVsZWFzZTogb3B0aW9ucy5yZWxlYXNlLAogICAgZW52aXJvbm1lbnQ6IG9wdGlvbnMuZW52aXJvbm1lbnQsCiAgICBkaXN0OiBvcHRpb25zLmRpc3QsCiAgICBwbGF0Zm9ybTogJ25vZGUnLAogICAgbGV2ZWw6ICdlcnJvcicsCiAgICBleGNlcHRpb246IHsKICAgICAgdmFsdWVzOiBbCiAgICAgICAgewogICAgICAgICAgdHlwZTogJ0FwcGxpY2F0aW9uTm90UmVzcG9uZGluZycsCiAgICAgICAgICB2YWx1ZTogYEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke29wdGlvbnMuYW5yVGhyZXNob2xkfSBtc2AsCiAgICAgICAgICBzdGFja3RyYWNlOiB7IGZyYW1lczogcHJlcGFyZVN0YWNrRnJhbWVzKGZyYW1lcykgfSwKICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgVUkgZG9lc24ndCBzYXkgJ0NyYXNoZWQgaW4nIGZvciB0aGUgc3RhY2sgdHJhY2UKICAgICAgICAgIG1lY2hhbmlzbTogeyB0eXBlOiAnQU5SJyB9LAogICAgICAgIH0sCiAgICAgIF0sCiAgICB9LAogICAgdGFnczogb3B0aW9ucy5zdGF0aWNUYWdzLAogIH07CgogIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRXZlbnRFbnZlbG9wZShldmVudCwgb3B0aW9ucy5kc24sIG9wdGlvbnMuc2RrTWV0YWRhdGEpOwogIC8vIExvZyB0aGUgZW52ZWxvcGUgc28gdG8gYWlkIGluIHRlc3RpbmcKICBsb2coSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKTsKCiAgYXdhaXQgdHJhbnNwb3J0LnNlbmQoZW52ZWxvcGUpOwogIGF3YWl0IHRyYW5zcG9ydC5mbHVzaCgyMDAwKTsKCiAgLy8gRGVsYXkgZm9yIDUgc2Vjb25kcyBzbyB0aGF0IHN0ZGlvIGNhbiBmbHVzaCBpbiB0aGUgbWFpbiBldmVudCBsb29wIGV2ZXIgcmVzdGFydHMuCiAgLy8gVGhpcyBpcyBtYWlubHkgZm9yIHRoZSBiZW5lZml0IG9mIGxvZ2dpbmcvZGVidWdnaW5nIGlzc3Vlcy4KICBzZXRUaW1lb3V0KCgpID0+IHsKICAgIHByb2Nlc3MuZXhpdCgwKTsKICB9LCA1MDAwKTsKfQoKbGV0IGRlYnVnZ2VyUGF1c2U7CgppZiAob3B0aW9ucy5jYXB0dXJlU3RhY2tUcmFjZSkgewogIGxvZygnQ29ubmVjdGluZyB0byBkZWJ1Z2dlcicpOwoKICBjb25zdCBzZXNzaW9uID0gbmV3IFNlc3Npb24oKSA7CiAgc2Vzc2lvbi5jb25uZWN0VG9NYWluVGhyZWFkKCk7CgogIGxvZygnQ29ubmVjdGVkIHRvIGRlYnVnZ2VyJyk7CgogIC8vIENvbGxlY3Qgc2NyaXB0SWQgLT4gdXJsIG1hcCBzbyB3ZSBjYW4gbG9vayB1cCB0aGUgZmlsZW5hbWVzIGxhdGVyCiAgY29uc3Qgc2NyaXB0cyA9IG5ldyBNYXAoKTsKCiAgc2Vzc2lvbi5vbignRGVidWdnZXIuc2NyaXB0UGFyc2VkJywgZXZlbnQgPT4gewogICAgc2NyaXB0cy5zZXQoZXZlbnQucGFyYW1zLnNjcmlwdElkLCBldmVudC5wYXJhbXMudXJsKTsKICB9KTsKCiAgc2Vzc2lvbi5vbignRGVidWdnZXIucGF1c2VkJywgZXZlbnQgPT4gewogICAgaWYgKGV2ZW50LnBhcmFtcy5yZWFzb24gIT09ICdvdGhlcicpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHRyeSB7CiAgICAgIGxvZygnRGVidWdnZXIgcGF1c2VkJyk7CgogICAgICAvLyBjb3B5IHRoZSBmcmFtZXMKICAgICAgY29uc3QgY2FsbEZyYW1lcyA9IFsuLi5ldmVudC5wYXJhbXMuY2FsbEZyYW1lc107CgogICAgICBjb25zdCBnZXRNb2R1bGVOYW1lID0gb3B0aW9ucy5hcHBSb290UGF0aCA/IGNyZWF0ZUdldE1vZHVsZUZyb21GaWxlbmFtZShvcHRpb25zLmFwcFJvb3RQYXRoKSA6ICgpID0+IHVuZGVmaW5lZDsKICAgICAgY29uc3Qgc3RhY2tGcmFtZXMgPSBjYWxsRnJhbWVzLm1hcChmcmFtZSA9PgogICAgICAgIGNhbGxGcmFtZVRvU3RhY2tGcmFtZShmcmFtZSwgc2NyaXB0cy5nZXQoZnJhbWUubG9jYXRpb24uc2NyaXB0SWQpLCBnZXRNb2R1bGVOYW1lKSwKICAgICAgKTsKCiAgICAgIC8vIEV2YWx1YXRlIGEgc2NyaXB0IGluIHRoZSBjdXJyZW50bHkgcGF1c2VkIGNvbnRleHQKICAgICAgc2Vzc2lvbi5wb3N0KAogICAgICAgICdSdW50aW1lLmV2YWx1YXRlJywKICAgICAgICB7CiAgICAgICAgICAvLyBHcmFiIHRoZSB0cmFjZSBjb250ZXh0IGZyb20gdGhlIGN1cnJlbnQgc2NvcGUKICAgICAgICAgIGV4cHJlc3Npb246CiAgICAgICAgICAgICdjb25zdCBjdHggPSBfX1NFTlRSWV9fLmh1Yi5nZXRTY29wZSgpLmdldFByb3BhZ2F0aW9uQ29udGV4dCgpOyBjdHgudHJhY2VJZCArICItIiArIGN0eC5zcGFuSWQgKyAiLSIgKyBjdHgucGFyZW50U3BhbklkJywKICAgICAgICAgIC8vIERvbid0IHJlLXRyaWdnZXIgdGhlIGRlYnVnZ2VyIGlmIHRoaXMgY2F1c2VzIGFuIGVycm9yCiAgICAgICAgICBzaWxlbnQ6IHRydWUsCiAgICAgICAgfSwKICAgICAgICAoXywgcGFyYW0pID0+IHsKICAgICAgICAgIGNvbnN0IHRyYWNlSWQgPSBwYXJhbSAmJiBwYXJhbS5yZXN1bHQgPyAocGFyYW0ucmVzdWx0LnZhbHVlICkgOiAnLS0nOwogICAgICAgICAgY29uc3QgW3RyYWNlX2lkLCBzcGFuX2lkLCBwYXJlbnRfc3Bhbl9pZF0gPSB0cmFjZUlkLnNwbGl0KCctJykgOwoKICAgICAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIucmVzdW1lJyk7CiAgICAgICAgICBzZXNzaW9uLnBvc3QoJ0RlYnVnZ2VyLmRpc2FibGUnKTsKCiAgICAgICAgICBjb25zdCBjb250ZXh0ID0gX29wdGlvbmFsQ2hhaW4oW3RyYWNlX2lkLCAnb3B0aW9uYWxBY2Nlc3MnLCBfNCA9PiBfNC5sZW5ndGhdKSAmJiBfb3B0aW9uYWxDaGFpbihbc3Bhbl9pZCwgJ29wdGlvbmFsQWNjZXNzJywgXzUgPT4gXzUubGVuZ3RoXSkgPyB7IHRyYWNlX2lkLCBzcGFuX2lkLCBwYXJlbnRfc3Bhbl9pZCB9IDogdW5kZWZpbmVkOwogICAgICAgICAgc2VuZEFuckV2ZW50KHN0YWNrRnJhbWVzLCBjb250ZXh0KS50aGVuKG51bGwsICgpID0+IHsKICAgICAgICAgICAgbG9nKCdTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuJyk7CiAgICAgICAgICB9KTsKICAgICAgICB9LAogICAgICApOwogICAgfSBjYXRjaCAoZSkgewogICAgICBzZXNzaW9uLnBvc3QoJ0RlYnVnZ2VyLnJlc3VtZScpOwogICAgICBzZXNzaW9uLnBvc3QoJ0RlYnVnZ2VyLmRpc2FibGUnKTsKICAgICAgdGhyb3cgZTsKICAgIH0KICB9KTsKCiAgZGVidWdnZXJQYXVzZSA9ICgpID0+IHsKICAgIHRyeSB7CiAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIuZW5hYmxlJywgKCkgPT4gewogICAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIucGF1c2UnKTsKICAgICAgfSk7CiAgICB9IGNhdGNoIChfKSB7CiAgICAgIC8vCiAgICB9CiAgfTsKfQoKZnVuY3Rpb24gY3JlYXRlSHJUaW1lcigpIHsKICAvLyBUT0RPICh2OCk6IFdlIGNhbiB1c2UgcHJvY2Vzcy5ocnRpbWUuYmlnaW50KCkgYWZ0ZXIgd2UgZHJvcCBub2RlIHY4CiAgbGV0IGxhc3RQb2xsID0gcHJvY2Vzcy5ocnRpbWUoKTsKCiAgcmV0dXJuIHsKICAgIGdldFRpbWVNczogKCkgPT4gewogICAgICBjb25zdCBbc2Vjb25kcywgbmFub1NlY29uZHNdID0gcHJvY2Vzcy5ocnRpbWUobGFzdFBvbGwpOwogICAgICByZXR1cm4gTWF0aC5mbG9vcihzZWNvbmRzICogMWUzICsgbmFub1NlY29uZHMgLyAxZTYpOwogICAgfSwKICAgIHJlc2V0OiAoKSA9PiB7CiAgICAgIGxhc3RQb2xsID0gcHJvY2Vzcy5ocnRpbWUoKTsKICAgIH0sCiAgfTsKfQoKZnVuY3Rpb24gd2F0Y2hkb2dUaW1lb3V0KCkgewogIGxvZygnV2F0Y2hkb2cgdGltZW91dCcpOwoKICBpZiAoZGVidWdnZXJQYXVzZSkgewogICAgbG9nKCdQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UnKTsKICAgIGRlYnVnZ2VyUGF1c2UoKTsKICB9IGVsc2UgewogICAgbG9nKCdDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlJyk7CiAgICBzZW5kQW5yRXZlbnQoKS50aGVuKG51bGwsICgpID0+IHsKICAgICAgbG9nKCdTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4nKTsKICAgIH0pOwogIH0KfQoKY29uc3QgeyBwb2xsIH0gPSB3YXRjaGRvZ1RpbWVyKGNyZWF0ZUhyVGltZXIsIG9wdGlvbnMucG9sbEludGVydmFsLCBvcHRpb25zLmFuclRocmVzaG9sZCwgd2F0Y2hkb2dUaW1lb3V0KTsKCl9vcHRpb25hbENoYWluKFtwYXJlbnRQb3J0LCAnb3B0aW9uYWxBY2Nlc3MnLCBfNiA9PiBfNi5vbiwgJ2NhbGwnLCBfNyA9PiBfNygnbWVzc2FnZScsIChtc2cpID0+IHsKICBpZiAobXNnLnNlc3Npb24pIHsKICAgIHNlc3Npb24gPSBtYWtlU2Vzc2lvbihtc2cuc2Vzc2lvbik7CiAgfQoKICBwb2xsKCk7Cn0pXSk7";
1
+ /*! @sentry/node 8.0.0-alpha.2 (894c151) | https://github.com/getsentry/sentry-javascript */
2
+ export const base64WorkerScript="aW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJ2luc3BlY3Rvcic7CmltcG9ydCB7IHdvcmtlckRhdGEsIHBhcmVudFBvcnQgfSBmcm9tICd3b3JrZXJfdGhyZWFkcyc7CmltcG9ydCB7IHBvc2l4LCBzZXAgfSBmcm9tICdwYXRoJzsKaW1wb3J0ICogYXMgaHR0cCBmcm9tICdodHRwJzsKaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnOwppbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7CmltcG9ydCB7IGNyZWF0ZUd6aXAgfSBmcm9tICd6bGliJzsKaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnOwppbXBvcnQgKiBhcyBuZXQgZnJvbSAnbmV0JzsKaW1wb3J0ICogYXMgdGxzIGZyb20gJ3Rscyc7CgovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3VuYm91bmQtbWV0aG9kCmNvbnN0IG9iamVjdFRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgb25lIG9mIGEgZmV3IEVycm9yIG9yIEVycm9yLWxpa2UKICoge0BsaW5rIGlzRXJyb3J9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNFcnJvcih3YXQpIHsKICBzd2l0Y2ggKG9iamVjdFRvU3RyaW5nLmNhbGwod2F0KSkgewogICAgY2FzZSAnW29iamVjdCBFcnJvcl0nOgogICAgY2FzZSAnW29iamVjdCBFeGNlcHRpb25dJzoKICAgIGNhc2UgJ1tvYmplY3QgRE9NRXhjZXB0aW9uXSc6CiAgICAgIHJldHVybiB0cnVlOwogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuIGlzSW5zdGFuY2VPZih3YXQsIEVycm9yKTsKICB9Cn0KLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlIGlzIGFuIGluc3RhbmNlIG9mIHRoZSBnaXZlbiBidWlsdC1pbiBjbGFzcy4KICoKICogQHBhcmFtIHdhdCBUaGUgdmFsdWUgdG8gYmUgY2hlY2tlZAogKiBAcGFyYW0gY2xhc3NOYW1lCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzQnVpbHRpbih3YXQsIGNsYXNzTmFtZSkgewogIHJldHVybiBvYmplY3RUb1N0cmluZy5jYWxsKHdhdCkgPT09IGBbb2JqZWN0ICR7Y2xhc3NOYW1lfV1gOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGEgc3RyaW5nCiAqIHtAbGluayBpc1N0cmluZ30uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc1N0cmluZyh3YXQpIHsKICByZXR1cm4gaXNCdWlsdGluKHdhdCwgJ1N0cmluZycpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIG9iamVjdCBsaXRlcmFsLCBvciBhIGNsYXNzIGluc3RhbmNlLgogKiB7QGxpbmsgaXNQbGFpbk9iamVjdH0uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc1BsYWluT2JqZWN0KHdhdCkgewogIHJldHVybiBpc0J1aWx0aW4od2F0LCAnT2JqZWN0Jyk7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgYW4gRXZlbnQgaW5zdGFuY2UKICoge0BsaW5rIGlzRXZlbnR9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNFdmVudCh3YXQpIHsKICByZXR1cm4gdHlwZW9mIEV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2Yod2F0LCBFdmVudCk7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgYW4gRWxlbWVudCBpbnN0YW5jZQogKiB7QGxpbmsgaXNFbGVtZW50fS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzRWxlbWVudCh3YXQpIHsKICByZXR1cm4gdHlwZW9mIEVsZW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGlzSW5zdGFuY2VPZih3YXQsIEVsZW1lbnQpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUgaGFzIGEgdGhlbiBmdW5jdGlvbi4KICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqLwpmdW5jdGlvbiBpc1RoZW5hYmxlKHdhdCkgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MKICByZXR1cm4gQm9vbGVhbih3YXQgJiYgd2F0LnRoZW4gJiYgdHlwZW9mIHdhdC50aGVuID09PSAnZnVuY3Rpb24nKTsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlJ3MgdHlwZSBpcyBhIFN5bnRoZXRpY0V2ZW50CiAqIHtAbGluayBpc1N5bnRoZXRpY0V2ZW50fS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzU3ludGhldGljRXZlbnQod2F0KSB7CiAgcmV0dXJuIGlzUGxhaW5PYmplY3Qod2F0KSAmJiAnbmF0aXZlRXZlbnQnIGluIHdhdCAmJiAncHJldmVudERlZmF1bHQnIGluIHdhdCAmJiAnc3RvcFByb3BhZ2F0aW9uJyBpbiB3YXQ7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSBpcyBOYU4KICoge0BsaW5rIGlzTmFOfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzTmFOJDEod2F0KSB7CiAgcmV0dXJuIHR5cGVvZiB3YXQgPT09ICdudW1iZXInICYmIHdhdCAhPT0gd2F0Owp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIGluc3RhbmNlIG9mIHByb3ZpZGVkIGNvbnN0cnVjdG9yLgogKiB7QGxpbmsgaXNJbnN0YW5jZU9mfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEBwYXJhbSBiYXNlIEEgY29uc3RydWN0b3IgdG8gYmUgdXNlZCBpbiBhIGNoZWNrLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc0luc3RhbmNlT2Yod2F0LCBiYXNlKSB7CiAgdHJ5IHsKICAgIHJldHVybiB3YXQgaW5zdGFuY2VvZiBiYXNlOwogIH0gY2F0Y2ggKF9lKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGEgVnVlIFZpZXdNb2RlbC4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzVnVlVmlld01vZGVsKHdhdCkgewogIC8vIE5vdCB1c2luZyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIGJlY2F1c2UgaW4gVnVlIDMgaXQgd291bGQgcmVhZCB0aGUgaW5zdGFuY2UncyBTeW1ib2woU3ltYm9sLnRvU3RyaW5nVGFnKSBwcm9wZXJ0eS4KICByZXR1cm4gISEodHlwZW9mIHdhdCA9PT0gJ29iamVjdCcgJiYgd2F0ICE9PSBudWxsICYmICgod2F0ICkuX19pc1Z1ZSB8fCAod2F0ICkuX2lzVnVlKSk7Cn0KCi8qKiBJbnRlcm5hbCBnbG9iYWwgd2l0aCBjb21tb24gcHJvcGVydGllcyBhbmQgU2VudHJ5IGV4dGVuc2lvbnMgICovCgovLyBUaGUgY29kZSBiZWxvdyBmb3IgJ2lzR2xvYmFsT2JqJyBhbmQgJ0dMT0JBTF9PQkonIHdhcyBjb3BpZWQgZnJvbSBjb3JlLWpzIGJlZm9yZSBtb2RpZmljYXRpb24KLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvYmxvYi8xYjk0NGRmNTUyODJjZGM5OWM5MGRiNWY0OWViMGI2ZWRhMmNjMGEzL3BhY2thZ2VzL2NvcmUtanMvaW50ZXJuYWxzL2dsb2JhbC5qcwovLyBjb3JlLWpzIGhhcyB0aGUgZm9sbG93aW5nIGxpY2VuY2U6Ci8vCi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDIyIERlbmlzIFB1c2hrYXJldgovLwovLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5Ci8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0byBkZWFsCi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMKLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbAovLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKLy8KLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4KLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCi8vCi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAovLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUKLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgovLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLAovLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOCi8vIFRIRSBTT0ZUV0FSRS4KCi8qKiBSZXR1cm5zICdvYmonIGlmIGl0J3MgdGhlIGdsb2JhbCBvYmplY3QsIG90aGVyd2lzZSByZXR1cm5zIHVuZGVmaW5lZCAqLwpmdW5jdGlvbiBpc0dsb2JhbE9iaihvYmopIHsKICByZXR1cm4gb2JqICYmIG9iai5NYXRoID09IE1hdGggPyBvYmogOiB1bmRlZmluZWQ7Cn0KCi8qKiBHZXQncyB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgdGhlIGN1cnJlbnQgSmF2YVNjcmlwdCBydW50aW1lICovCmNvbnN0IEdMT0JBTF9PQkogPQogICh0eXBlb2YgZ2xvYmFsVGhpcyA9PSAnb2JqZWN0JyAmJiBpc0dsb2JhbE9iaihnbG9iYWxUaGlzKSkgfHwKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzCiAgKHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmood2luZG93KSkgfHwKICAodHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmooc2VsZikpIHx8CiAgKHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgaXNHbG9iYWxPYmooZ2xvYmFsKSkgfHwKICAoZnVuY3Rpb24gKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfSkoKSB8fAogIHt9OwoKLyoqCiAqIEBkZXByZWNhdGVkIFVzZSBHTE9CQUxfT0JKIGluc3RlYWQgb3IgV0lORE9XIGZyb20gQHNlbnRyeS9icm93c2VyLiBUaGlzIHdpbGwgYmUgcmVtb3ZlZCBpbiB2OAogKi8KZnVuY3Rpb24gZ2V0R2xvYmFsT2JqZWN0KCkgewogIHJldHVybiBHTE9CQUxfT0JKIDsKfQoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCmNvbnN0IFdJTkRPVyA9IGdldEdsb2JhbE9iamVjdCgpOwoKY29uc3QgREVGQVVMVF9NQVhfU1RSSU5HX0xFTkdUSCA9IDgwOwoKLyoqCiAqIEdpdmVuIGEgY2hpbGQgRE9NIGVsZW1lbnQsIHJldHVybnMgYSBxdWVyeS1zZWxlY3RvciBzdGF0ZW1lbnQgZGVzY3JpYmluZyB0aGF0CiAqIGFuZCBpdHMgYW5jZXN0b3JzCiAqIGUuZy4gW0hUTUxFbGVtZW50XSA9PiBib2R5ID4gZGl2ID4gaW5wdXQjZm9vLmJ0bltuYW1lPWJhel0KICogQHJldHVybnMgZ2VuZXJhdGVkIERPTSBwYXRoCiAqLwpmdW5jdGlvbiBodG1sVHJlZUFzU3RyaW5nKAogIGVsZW0sCiAgb3B0aW9ucyA9IHt9LAopIHsKICBpZiAoIWVsZW0pIHsKICAgIHJldHVybiAnPHVua25vd24+JzsKICB9CgogIC8vIHRyeS9jYXRjaCBib3RoOgogIC8vIC0gYWNjZXNzaW5nIGV2ZW50LnRhcmdldCAoc2VlIGdldHNlbnRyeS9yYXZlbi1qcyM4MzgsICM3NjgpCiAgLy8gLSBgaHRtbFRyZWVBc1N0cmluZ2AgYmVjYXVzZSBpdCdzIGNvbXBsZXgsIGFuZCBqdXN0IGFjY2Vzc2luZyB0aGUgRE9NIGluY29ycmVjdGx5CiAgLy8gLSBjYW4gdGhyb3cgYW4gZXhjZXB0aW9uIGluIHNvbWUgY2lyY3Vtc3RhbmNlcy4KICB0cnkgewogICAgbGV0IGN1cnJlbnRFbGVtID0gZWxlbSA7CiAgICBjb25zdCBNQVhfVFJBVkVSU0VfSEVJR0hUID0gNTsKICAgIGNvbnN0IG91dCA9IFtdOwogICAgbGV0IGhlaWdodCA9IDA7CiAgICBsZXQgbGVuID0gMDsKICAgIGNvbnN0IHNlcGFyYXRvciA9ICcgPiAnOwogICAgY29uc3Qgc2VwTGVuZ3RoID0gc2VwYXJhdG9yLmxlbmd0aDsKICAgIGxldCBuZXh0U3RyOwogICAgY29uc3Qga2V5QXR0cnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMpID8gb3B0aW9ucyA6IG9wdGlvbnMua2V5QXR0cnM7CiAgICBjb25zdCBtYXhTdHJpbmdMZW5ndGggPSAoIUFycmF5LmlzQXJyYXkob3B0aW9ucykgJiYgb3B0aW9ucy5tYXhTdHJpbmdMZW5ndGgpIHx8IERFRkFVTFRfTUFYX1NUUklOR19MRU5HVEg7CgogICAgd2hpbGUgKGN1cnJlbnRFbGVtICYmIGhlaWdodCsrIDwgTUFYX1RSQVZFUlNFX0hFSUdIVCkgewogICAgICBuZXh0U3RyID0gX2h0bWxFbGVtZW50QXNTdHJpbmcoY3VycmVudEVsZW0sIGtleUF0dHJzKTsKICAgICAgLy8gYmFpbCBvdXQgaWYKICAgICAgLy8gLSBuZXh0U3RyIGlzIHRoZSAnaHRtbCcgZWxlbWVudAogICAgICAvLyAtIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZyB0aGF0IHdvdWxkIGJlIGNyZWF0ZWQgZXhjZWVkcyBtYXhTdHJpbmdMZW5ndGgKICAgICAgLy8gICAoaWdub3JlIHRoaXMgbGltaXQgaWYgd2UgYXJlIG9uIHRoZSBmaXJzdCBpdGVyYXRpb24pCiAgICAgIGlmIChuZXh0U3RyID09PSAnaHRtbCcgfHwgKGhlaWdodCA+IDEgJiYgbGVuICsgb3V0Lmxlbmd0aCAqIHNlcExlbmd0aCArIG5leHRTdHIubGVuZ3RoID49IG1heFN0cmluZ0xlbmd0aCkpIHsKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgb3V0LnB1c2gobmV4dFN0cik7CgogICAgICBsZW4gKz0gbmV4dFN0ci5sZW5ndGg7CiAgICAgIGN1cnJlbnRFbGVtID0gY3VycmVudEVsZW0ucGFyZW50Tm9kZTsKICAgIH0KCiAgICByZXR1cm4gb3V0LnJldmVyc2UoKS5qb2luKHNlcGFyYXRvcik7CiAgfSBjYXRjaCAoX29PKSB7CiAgICByZXR1cm4gJzx1bmtub3duPic7CiAgfQp9CgovKioKICogUmV0dXJucyBhIHNpbXBsZSwgcXVlcnktc2VsZWN0b3IgcmVwcmVzZW50YXRpb24gb2YgYSBET00gZWxlbWVudAogKiBlLmcuIFtIVE1MRWxlbWVudF0gPT4gaW5wdXQjZm9vLmJ0bltuYW1lPWJhel0KICogQHJldHVybnMgZ2VuZXJhdGVkIERPTSBwYXRoCiAqLwpmdW5jdGlvbiBfaHRtbEVsZW1lbnRBc1N0cmluZyhlbCwga2V5QXR0cnMpIHsKICBjb25zdCBlbGVtID0gZWwKCjsKCiAgY29uc3Qgb3V0ID0gW107CiAgbGV0IGNsYXNzTmFtZTsKICBsZXQgY2xhc3NlczsKICBsZXQga2V5OwogIGxldCBhdHRyOwogIGxldCBpOwoKICBpZiAoIWVsZW0gfHwgIWVsZW0udGFnTmFtZSkgewogICAgcmV0dXJuICcnOwogIH0KCiAgLy8gQHRzLWV4cGVjdC1lcnJvciBXSU5ET1cgaGFzIEhUTUxFbGVtZW50CiAgaWYgKFdJTkRPVy5IVE1MRWxlbWVudCkgewogICAgLy8gSWYgdXNpbmcgdGhlIGNvbXBvbmVudCBuYW1lIGFubm90YXRpb24gcGx1Z2luLCB0aGlzIHZhbHVlIG1heSBiZSBhdmFpbGFibGUgb24gdGhlIERPTSBub2RlCiAgICBpZiAoZWxlbSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ICYmIGVsZW0uZGF0YXNldCAmJiBlbGVtLmRhdGFzZXRbJ3NlbnRyeUNvbXBvbmVudCddKSB7CiAgICAgIHJldHVybiBlbGVtLmRhdGFzZXRbJ3NlbnRyeUNvbXBvbmVudCddOwogICAgfQogIH0KCiAgb3V0LnB1c2goZWxlbS50YWdOYW1lLnRvTG93ZXJDYXNlKCkpOwoKICAvLyBQYWlycyBvZiBhdHRyaWJ1dGUga2V5cyBkZWZpbmVkIGluIGBzZXJpYWxpemVBdHRyaWJ1dGVgIGFuZCB0aGVpciB2YWx1ZXMgb24gZWxlbWVudC4KICBjb25zdCBrZXlBdHRyUGFpcnMgPQogICAga2V5QXR0cnMgJiYga2V5QXR0cnMubGVuZ3RoCiAgICAgID8ga2V5QXR0cnMuZmlsdGVyKGtleUF0dHIgPT4gZWxlbS5nZXRBdHRyaWJ1dGUoa2V5QXR0cikpLm1hcChrZXlBdHRyID0+IFtrZXlBdHRyLCBlbGVtLmdldEF0dHJpYnV0ZShrZXlBdHRyKV0pCiAgICAgIDogbnVsbDsKCiAgaWYgKGtleUF0dHJQYWlycyAmJiBrZXlBdHRyUGFpcnMubGVuZ3RoKSB7CiAgICBrZXlBdHRyUGFpcnMuZm9yRWFjaChrZXlBdHRyUGFpciA9PiB7CiAgICAgIG91dC5wdXNoKGBbJHtrZXlBdHRyUGFpclswXX09IiR7a2V5QXR0clBhaXJbMV19Il1gKTsKICAgIH0pOwogIH0gZWxzZSB7CiAgICBpZiAoZWxlbS5pZCkgewogICAgICBvdXQucHVzaChgIyR7ZWxlbS5pZH1gKTsKICAgIH0KCiAgICBjbGFzc05hbWUgPSBlbGVtLmNsYXNzTmFtZTsKICAgIGlmIChjbGFzc05hbWUgJiYgaXNTdHJpbmcoY2xhc3NOYW1lKSkgewogICAgICBjbGFzc2VzID0gY2xhc3NOYW1lLnNwbGl0KC9ccysvKTsKICAgICAgZm9yIChpID0gMDsgaSA8IGNsYXNzZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBvdXQucHVzaChgLiR7Y2xhc3Nlc1tpXX1gKTsKICAgICAgfQogICAgfQogIH0KICBjb25zdCBhbGxvd2VkQXR0cnMgPSBbJ2FyaWEtbGFiZWwnLCAndHlwZScsICduYW1lJywgJ3RpdGxlJywgJ2FsdCddOwogIGZvciAoaSA9IDA7IGkgPCBhbGxvd2VkQXR0cnMubGVuZ3RoOyBpKyspIHsKICAgIGtleSA9IGFsbG93ZWRBdHRyc1tpXTsKICAgIGF0dHIgPSBlbGVtLmdldEF0dHJpYnV0ZShrZXkpOwogICAgaWYgKGF0dHIpIHsKICAgICAgb3V0LnB1c2goYFske2tleX09IiR7YXR0cn0iXWApOwogICAgfQogIH0KICByZXR1cm4gb3V0LmpvaW4oJycpOwp9CgovKioKICogVGhpcyBzZXJ2ZXMgYXMgYSBidWlsZCB0aW1lIGZsYWcgdGhhdCB3aWxsIGJlIHRydWUgYnkgZGVmYXVsdCwgYnV0IGZhbHNlIGluIG5vbi1kZWJ1ZyBidWlsZHMgb3IgaWYgdXNlcnMgcmVwbGFjZSBgX19TRU5UUllfREVCVUdfX2AgaW4gdGhlaXIgZ2VuZXJhdGVkIGNvZGUuCiAqCiAqIEFUVEVOVElPTjogVGhpcyBjb25zdGFudCBtdXN0IG5ldmVyIGNyb3NzIHBhY2thZ2UgYm91bmRhcmllcyAoaS5lLiBiZSBleHBvcnRlZCkgdG8gZ3VhcmFudGVlIHRoYXQgaXQgY2FuIGJlIHVzZWQgZm9yIHRyZWUgc2hha2luZy4KICovCmNvbnN0IERFQlVHX0JVSUxEJDEgPSAodHlwZW9mIF9fU0VOVFJZX0RFQlVHX18gPT09ICd1bmRlZmluZWQnIHx8IF9fU0VOVFJZX0RFQlVHX18pOwoKLyoqIFByZWZpeCBmb3IgbG9nZ2luZyBzdHJpbmdzICovCmNvbnN0IFBSRUZJWCA9ICdTZW50cnkgTG9nZ2VyICc7Cgpjb25zdCBDT05TT0xFX0xFVkVMUyA9IFsKICAnZGVidWcnLAogICdpbmZvJywKICAnd2FybicsCiAgJ2Vycm9yJywKICAnbG9nJywKICAnYXNzZXJ0JywKICAndHJhY2UnLApdIDsKCi8qKiBUaGlzIG1heSBiZSBtdXRhdGVkIGJ5IHRoZSBjb25zb2xlIGluc3RydW1lbnRhdGlvbi4gKi8KY29uc3Qgb3JpZ2luYWxDb25zb2xlTWV0aG9kcwoKID0ge307CgovKiogSlNEb2MgKi8KCi8qKgogKiBUZW1wb3JhcmlseSBkaXNhYmxlIHNlbnRyeSBjb25zb2xlIGluc3RydW1lbnRhdGlvbnMuCiAqCiAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gcnVuIGFnYWluc3QgdGhlIG9yaWdpbmFsIGBjb25zb2xlYCBtZXNzYWdlcwogKiBAcmV0dXJucyBUaGUgcmVzdWx0cyBvZiB0aGUgY2FsbGJhY2sKICovCmZ1bmN0aW9uIGNvbnNvbGVTYW5kYm94KGNhbGxiYWNrKSB7CiAgaWYgKCEoJ2NvbnNvbGUnIGluIEdMT0JBTF9PQkopKSB7CiAgICByZXR1cm4gY2FsbGJhY2soKTsKICB9CgogIGNvbnN0IGNvbnNvbGUgPSBHTE9CQUxfT0JKLmNvbnNvbGUgOwogIGNvbnN0IHdyYXBwZWRGdW5jcyA9IHt9OwoKICBjb25zdCB3cmFwcGVkTGV2ZWxzID0gT2JqZWN0LmtleXMob3JpZ2luYWxDb25zb2xlTWV0aG9kcykgOwoKICAvLyBSZXN0b3JlIGFsbCB3cmFwcGVkIGNvbnNvbGUgbWV0aG9kcwogIHdyYXBwZWRMZXZlbHMuZm9yRWFjaChsZXZlbCA9PiB7CiAgICBjb25zdCBvcmlnaW5hbENvbnNvbGVNZXRob2QgPSBvcmlnaW5hbENvbnNvbGVNZXRob2RzW2xldmVsXSA7CiAgICB3cmFwcGVkRnVuY3NbbGV2ZWxdID0gY29uc29sZVtsZXZlbF0gOwogICAgY29uc29sZVtsZXZlbF0gPSBvcmlnaW5hbENvbnNvbGVNZXRob2Q7CiAgfSk7CgogIHRyeSB7CiAgICByZXR1cm4gY2FsbGJhY2soKTsKICB9IGZpbmFsbHkgewogICAgLy8gUmV2ZXJ0IHJlc3RvcmF0aW9uIHRvIHdyYXBwZWQgc3RhdGUKICAgIHdyYXBwZWRMZXZlbHMuZm9yRWFjaChsZXZlbCA9PiB7CiAgICAgIGNvbnNvbGVbbGV2ZWxdID0gd3JhcHBlZEZ1bmNzW2xldmVsXSA7CiAgICB9KTsKICB9Cn0KCmZ1bmN0aW9uIG1ha2VMb2dnZXIoKSB7CiAgbGV0IGVuYWJsZWQgPSBmYWxzZTsKICBjb25zdCBsb2dnZXIgPSB7CiAgICBlbmFibGU6ICgpID0+IHsKICAgICAgZW5hYmxlZCA9IHRydWU7CiAgICB9LAogICAgZGlzYWJsZTogKCkgPT4gewogICAgICBlbmFibGVkID0gZmFsc2U7CiAgICB9LAogICAgaXNFbmFibGVkOiAoKSA9PiBlbmFibGVkLAogIH07CgogIGlmIChERUJVR19CVUlMRCQxKSB7CiAgICBDT05TT0xFX0xFVkVMUy5mb3JFYWNoKG5hbWUgPT4gewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQogICAgICBsb2dnZXJbbmFtZV0gPSAoLi4uYXJncykgPT4gewogICAgICAgIGlmIChlbmFibGVkKSB7CiAgICAgICAgICBjb25zb2xlU2FuZGJveCgoKSA9PiB7CiAgICAgICAgICAgIEdMT0JBTF9PQkouY29uc29sZVtuYW1lXShgJHtQUkVGSVh9WyR7bmFtZX1dOmAsIC4uLmFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9OwogICAgfSk7CiAgfSBlbHNlIHsKICAgIENPTlNPTEVfTEVWRUxTLmZvckVhY2gobmFtZSA9PiB7CiAgICAgIGxvZ2dlcltuYW1lXSA9ICgpID0+IHVuZGVmaW5lZDsKICAgIH0pOwogIH0KCiAgcmV0dXJuIGxvZ2dlciA7Cn0KCmNvbnN0IGxvZ2dlciA9IG1ha2VMb2dnZXIoKTsKCi8qKgogKiBSZW5kZXJzIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEc24uCiAqCiAqIEJ5IGRlZmF1bHQsIHRoaXMgd2lsbCByZW5kZXIgdGhlIHB1YmxpYyByZXByZXNlbnRhdGlvbiB3aXRob3V0IHRoZSBwYXNzd29yZAogKiBjb21wb25lbnQuIFRvIGdldCB0aGUgZGVwcmVjYXRlZCBwcml2YXRlIHJlcHJlc2VudGF0aW9uLCBzZXQgYHdpdGhQYXNzd29yZGAKICogdG8gdHJ1ZS4KICoKICogQHBhcmFtIHdpdGhQYXNzd29yZCBXaGVuIHNldCB0byB0cnVlLCB0aGUgcGFzc3dvcmQgd2lsbCBiZSBpbmNsdWRlZC4KICovCmZ1bmN0aW9uIGRzblRvU3RyaW5nKGRzbiwgd2l0aFBhc3N3b3JkID0gZmFsc2UpIHsKICBjb25zdCB7IGhvc3QsIHBhdGgsIHBhc3MsIHBvcnQsIHByb2plY3RJZCwgcHJvdG9jb2wsIHB1YmxpY0tleSB9ID0gZHNuOwogIHJldHVybiAoCiAgICBgJHtwcm90b2NvbH06Ly8ke3B1YmxpY0tleX0ke3dpdGhQYXNzd29yZCAmJiBwYXNzID8gYDoke3Bhc3N9YCA6ICcnfWAgKwogICAgYEAke2hvc3R9JHtwb3J0ID8gYDoke3BvcnR9YCA6ICcnfS8ke3BhdGggPyBgJHtwYXRofS9gIDogcGF0aH0ke3Byb2plY3RJZH1gCiAgKTsKfQoKLyoqIEFuIGVycm9yIGVtaXR0ZWQgYnkgU2VudHJ5IFNES3MgYW5kIHJlbGF0ZWQgdXRpbGl0aWVzLiAqLwpjbGFzcyBTZW50cnlFcnJvciBleHRlbmRzIEVycm9yIHsKICAvKiogRGlzcGxheSBuYW1lIG9mIHRoaXMgZXJyb3IgaW5zdGFuY2UuICovCgogICBjb25zdHJ1Y3RvciggbWVzc2FnZSwgbG9nTGV2ZWwgPSAnd2FybicpIHsKICAgIHN1cGVyKG1lc3NhZ2UpO3RoaXMubWVzc2FnZSA9IG1lc3NhZ2U7CiAgICB0aGlzLm5hbWUgPSBuZXcudGFyZ2V0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5uYW1lOwogICAgLy8gVGhpcyBzZXRzIHRoZSBwcm90b3R5cGUgdG8gYmUgYEVycm9yYCwgbm90IGBTZW50cnlFcnJvcmAuIEl0J3MgdW5jbGVhciB3aHkgd2UgZG8gdGhpcywgYnV0IGNvbW1lbnRpbmcgdGhpcyBsaW5lCiAgICAvLyBvdXQgY2F1c2VzIHZhcmlvdXMgKHNlZW1pbmdseSB0b3RhbGx5IHVucmVsYXRlZCkgcGxheXdyaWdodCB0ZXN0cyBjb25zaXN0ZW50bHkgdGltZSBvdXQuIEZZSSwgdGhpcyBtYWtlcwogICAgLy8gaW5zdGFuY2VzIG9mIGBTZW50cnlFcnJvcmAgZmFpbCBgb2JqIGluc3RhbmNlb2YgU2VudHJ5RXJyb3JgIGNoZWNrcy4KICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBuZXcudGFyZ2V0LnByb3RvdHlwZSk7CiAgICB0aGlzLmxvZ0xldmVsID0gbG9nTGV2ZWw7CiAgfQp9Cgpjb25zdCBTVEFDS1RSQUNFX0ZSQU1FX0xJTUlUID0gNTA7CmNvbnN0IFVOS05PV05fRlVOQ1RJT04gPSAnPyc7CmNvbnN0IFNUUklQX0ZSQU1FX1JFR0VYUCA9IC9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLzsKCi8qKgogKiBSZW1vdmVzIFNlbnRyeSBmcmFtZXMgZnJvbSB0aGUgdG9wIGFuZCBib3R0b20gb2YgdGhlIHN0YWNrIGlmIHByZXNlbnQgYW5kIGVuZm9yY2VzIGEgbGltaXQgb2YgbWF4IG51bWJlciBvZiBmcmFtZXMuCiAqIEFzc3VtZXMgc3RhY2sgaW5wdXQgaXMgb3JkZXJlZCBmcm9tIHRvcCB0byBib3R0b20gYW5kIHJldHVybnMgdGhlIHJldmVyc2UgcmVwcmVzZW50YXRpb24gc28gY2FsbCBzaXRlIG9mIHRoZQogKiBmdW5jdGlvbiB0aGF0IGNhdXNlZCB0aGUgY3Jhc2ggaXMgdGhlIGxhc3QgZnJhbWUgaW4gdGhlIGFycmF5LgogKiBAaGlkZGVuCiAqLwpmdW5jdGlvbiBzdHJpcFNlbnRyeUZyYW1lc0FuZFJldmVyc2Uoc3RhY2spIHsKICBpZiAoIXN0YWNrLmxlbmd0aCkgewogICAgcmV0dXJuIFtdOwogIH0KCiAgY29uc3QgbG9jYWxTdGFjayA9IEFycmF5LmZyb20oc3RhY2spOwoKICAvLyBJZiBzdGFjayBzdGFydHMgd2l0aCBvbmUgb2Ygb3VyIEFQSSBjYWxscywgcmVtb3ZlIGl0IChzdGFydHMsIG1lYW5pbmcgaXQncyB0aGUgdG9wIG9mIHRoZSBzdGFjayAtIGFrYSBsYXN0IGNhbGwpCiAgaWYgKC9zZW50cnlXcmFwcGVkLy50ZXN0KGxvY2FsU3RhY2tbbG9jYWxTdGFjay5sZW5ndGggLSAxXS5mdW5jdGlvbiB8fCAnJykpIHsKICAgIGxvY2FsU3RhY2sucG9wKCk7CiAgfQoKICAvLyBSZXZlcnNpbmcgaW4gdGhlIG1pZGRsZSBvZiB0aGUgcHJvY2VkdXJlIGFsbG93cyB1cyB0byBqdXN0IHBvcCB0aGUgdmFsdWVzIG9mZiB0aGUgc3RhY2sKICBsb2NhbFN0YWNrLnJldmVyc2UoKTsKCiAgLy8gSWYgc3RhY2sgZW5kcyB3aXRoIG9uZSBvZiBvdXIgaW50ZXJuYWwgQVBJIGNhbGxzLCByZW1vdmUgaXQgKGVuZHMsIG1lYW5pbmcgaXQncyB0aGUgYm90dG9tIG9mIHRoZSBzdGFjayAtIGFrYSB0b3AtbW9zdCBjYWxsKQogIGlmIChTVFJJUF9GUkFNRV9SRUdFWFAudGVzdChsb2NhbFN0YWNrW2xvY2FsU3RhY2subGVuZ3RoIC0gMV0uZnVuY3Rpb24gfHwgJycpKSB7CiAgICBsb2NhbFN0YWNrLnBvcCgpOwoKICAgIC8vIFdoZW4gdXNpbmcgc3ludGhldGljIGV2ZW50cywgd2Ugd2lsbCBoYXZlIGEgMiBsZXZlbHMgZGVlcCBzdGFjaywgYXMgYG5ldyBFcnJvcignU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbicpYAogICAgLy8gaXMgcHJvZHVjZWQgd2l0aGluIHRoZSBodWIgaXRzZWxmLCBtYWtpbmcgaXQ6CiAgICAvLwogICAgLy8gICBTZW50cnkuY2FwdHVyZUV4Y2VwdGlvbigpCiAgICAvLyAgIGdldEN1cnJlbnRIdWIoKS5jYXB0dXJlRXhjZXB0aW9uKCkKICAgIC8vCiAgICAvLyBpbnN0ZWFkIG9mIGp1c3QgdGhlIHRvcCBgU2VudHJ5YCBjYWxsIGl0c2VsZi4KICAgIC8vIFRoaXMgZm9yY2VzIHVzIHRvIHBvc3NpYmx5IHN0cmlwIGFuIGFkZGl0aW9uYWwgZnJhbWUgaW4gdGhlIGV4YWN0IHNhbWUgd2FzIGFzIGFib3ZlLgogICAgaWYgKFNUUklQX0ZSQU1FX1JFR0VYUC50ZXN0KGxvY2FsU3RhY2tbbG9jYWxTdGFjay5sZW5ndGggLSAxXS5mdW5jdGlvbiB8fCAnJykpIHsKICAgICAgbG9jYWxTdGFjay5wb3AoKTsKICAgIH0KICB9CgogIHJldHVybiBsb2NhbFN0YWNrLnNsaWNlKDAsIFNUQUNLVFJBQ0VfRlJBTUVfTElNSVQpLm1hcChmcmFtZSA9PiAoewogICAgLi4uZnJhbWUsCiAgICBmaWxlbmFtZTogZnJhbWUuZmlsZW5hbWUgfHwgbG9jYWxTdGFja1tsb2NhbFN0YWNrLmxlbmd0aCAtIDFdLmZpbGVuYW1lLAogICAgZnVuY3Rpb246IGZyYW1lLmZ1bmN0aW9uIHx8IFVOS05PV05fRlVOQ1RJT04sCiAgfSkpOwp9Cgpjb25zdCBkZWZhdWx0RnVuY3Rpb25OYW1lID0gJzxhbm9ueW1vdXM+JzsKCi8qKgogKiBTYWZlbHkgZXh0cmFjdCBmdW5jdGlvbiBuYW1lIGZyb20gaXRzZWxmCiAqLwpmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWUoZm4pIHsKICB0cnkgewogICAgaWYgKCFmbiB8fCB0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRGdW5jdGlvbk5hbWU7CiAgICB9CiAgICByZXR1cm4gZm4ubmFtZSB8fCBkZWZhdWx0RnVuY3Rpb25OYW1lOwogIH0gY2F0Y2ggKGUpIHsKICAgIC8vIEp1c3QgYWNjZXNzaW5nIGN1c3RvbSBwcm9wcyBpbiBzb21lIFNlbGVuaXVtIGVudmlyb25tZW50cwogICAgLy8gY2FuIGNhdXNlIGEgIlBlcm1pc3Npb24gZGVuaWVkIiBleGNlcHRpb24gKHNlZSByYXZlbi1qcyM0OTUpLgogICAgcmV0dXJuIGRlZmF1bHRGdW5jdGlvbk5hbWU7CiAgfQp9CgovKioKICogRW5jb2RlcyBnaXZlbiBvYmplY3QgaW50byB1cmwtZnJpZW5kbHkgZm9ybWF0CiAqCiAqIEBwYXJhbSBvYmplY3QgQW4gb2JqZWN0IHRoYXQgY29udGFpbnMgc2VyaWFsaXphYmxlIHZhbHVlcwogKiBAcmV0dXJucyBzdHJpbmcgRW5jb2RlZAogKi8KZnVuY3Rpb24gdXJsRW5jb2RlKG9iamVjdCkgewogIHJldHVybiBPYmplY3Qua2V5cyhvYmplY3QpCiAgICAubWFwKGtleSA9PiBgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQob2JqZWN0W2tleV0pfWApCiAgICAuam9pbignJicpOwp9CgovKioKICogVHJhbnNmb3JtcyBhbnkgYEVycm9yYCBvciBgRXZlbnRgIGludG8gYSBwbGFpbiBvYmplY3Qgd2l0aCBhbGwgb2YgdGhlaXIgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLCBhbmQgc29tZSBvZiB0aGVpcgogKiBub24tZW51bWVyYWJsZSBwcm9wZXJ0aWVzIGF0dGFjaGVkLgogKgogKiBAcGFyYW0gdmFsdWUgSW5pdGlhbCBzb3VyY2UgdGhhdCB3ZSBoYXZlIHRvIHRyYW5zZm9ybSBpbiBvcmRlciBmb3IgaXQgdG8gYmUgdXNhYmxlIGJ5IHRoZSBzZXJpYWxpemVyCiAqIEByZXR1cm5zIEFuIEV2ZW50IG9yIEVycm9yIHR1cm5lZCBpbnRvIGFuIG9iamVjdCAtIG9yIHRoZSB2YWx1ZSBhcmd1cm1lbnQgaXRzZWxmLCB3aGVuIHZhbHVlIGlzIG5laXRoZXIgYW4gRXZlbnQgbm9yCiAqICBhbiBFcnJvci4KICovCmZ1bmN0aW9uIGNvbnZlcnRUb1BsYWluT2JqZWN0KAogIHZhbHVlLAopCgogewogIGlmIChpc0Vycm9yKHZhbHVlKSkgewogICAgcmV0dXJuIHsKICAgICAgbWVzc2FnZTogdmFsdWUubWVzc2FnZSwKICAgICAgbmFtZTogdmFsdWUubmFtZSwKICAgICAgc3RhY2s6IHZhbHVlLnN0YWNrLAogICAgICAuLi5nZXRPd25Qcm9wZXJ0aWVzKHZhbHVlKSwKICAgIH07CiAgfSBlbHNlIGlmIChpc0V2ZW50KHZhbHVlKSkgewogICAgY29uc3QgbmV3T2JqCgogPSB7CiAgICAgIHR5cGU6IHZhbHVlLnR5cGUsCiAgICAgIHRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUudGFyZ2V0KSwKICAgICAgY3VycmVudFRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUuY3VycmVudFRhcmdldCksCiAgICAgIC4uLmdldE93blByb3BlcnRpZXModmFsdWUpLAogICAgfTsKCiAgICBpZiAodHlwZW9mIEN1c3RvbUV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2YodmFsdWUsIEN1c3RvbUV2ZW50KSkgewogICAgICBuZXdPYmouZGV0YWlsID0gdmFsdWUuZGV0YWlsOwogICAgfQoKICAgIHJldHVybiBuZXdPYmo7CiAgfSBlbHNlIHsKICAgIHJldHVybiB2YWx1ZTsKICB9Cn0KCi8qKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0YXJnZXQgb2YgYW4gYEV2ZW50YCBvYmplY3QgKi8KZnVuY3Rpb24gc2VyaWFsaXplRXZlbnRUYXJnZXQodGFyZ2V0KSB7CiAgdHJ5IHsKICAgIHJldHVybiBpc0VsZW1lbnQodGFyZ2V0KSA/IGh0bWxUcmVlQXNTdHJpbmcodGFyZ2V0KSA6IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0YXJnZXQpOwogIH0gY2F0Y2ggKF9vTykgewogICAgcmV0dXJuICc8dW5rbm93bj4nOwogIH0KfQoKLyoqIEZpbHRlcnMgb3V0IGFsbCBidXQgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMgKi8KZnVuY3Rpb24gZ2V0T3duUHJvcGVydGllcyhvYmopIHsKICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSB7CiAgICBjb25zdCBleHRyYWN0ZWRQcm9wcyA9IHt9OwogICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiBvYmopIHsKICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3BlcnR5KSkgewogICAgICAgIGV4dHJhY3RlZFByb3BzW3Byb3BlcnR5XSA9IChvYmogKVtwcm9wZXJ0eV07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBleHRyYWN0ZWRQcm9wczsKICB9IGVsc2UgewogICAgcmV0dXJuIHt9OwogIH0KfQoKLyoqCiAqIEdpdmVuIGFueSBvYmplY3QsIHJldHVybiBhIG5ldyBvYmplY3QgaGF2aW5nIHJlbW92ZWQgYWxsIGZpZWxkcyB3aG9zZSB2YWx1ZSB3YXMgYHVuZGVmaW5lZGAuCiAqIFdvcmtzIHJlY3Vyc2l2ZWx5IG9uIG9iamVjdHMgYW5kIGFycmF5cy4KICoKICogQXR0ZW50aW9uOiBUaGlzIGZ1bmN0aW9uIGtlZXBzIGNpcmN1bGFyIHJlZmVyZW5jZXMgaW4gdGhlIHJldHVybmVkIG9iamVjdC4KICovCmZ1bmN0aW9uIGRyb3BVbmRlZmluZWRLZXlzKGlucHV0VmFsdWUpIHsKICAvLyBUaGlzIG1hcCBrZWVwcyB0cmFjayBvZiB3aGF0IGFscmVhZHkgdmlzaXRlZCBub2RlcyBtYXAgdG8uCiAgLy8gT3VyIFNldCAtIGJhc2VkIG1lbW9CdWlsZGVyIGRvZXNuJ3Qgd29yayBoZXJlIGJlY2F1c2Ugd2Ugd2FudCB0byB0aGUgb3V0cHV0IG9iamVjdCB0byBoYXZlIHRoZSBzYW1lIGNpcmN1bGFyCiAgLy8gcmVmZXJlbmNlcyBhcyB0aGUgaW5wdXQgb2JqZWN0LgogIGNvbnN0IG1lbW9pemF0aW9uTWFwID0gbmV3IE1hcCgpOwoKICAvLyBUaGlzIGZ1bmN0aW9uIGp1c3QgcHJveGllcyBgX2Ryb3BVbmRlZmluZWRLZXlzYCB0byBrZWVwIHRoZSBgbWVtb0J1aWxkZXJgIG91dCBvZiB0aGlzIGZ1bmN0aW9uJ3MgQVBJCiAgcmV0dXJuIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCk7Cn0KCmZ1bmN0aW9uIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCkgewogIGlmIChpc1Bvam8oaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIG9iamVjdCBpdCB3YXMgbWFwcGVkIHRvIGluIHRoZSBuZXcgb2JqZWN0CiAgICBjb25zdCBtZW1vVmFsID0gbWVtb2l6YXRpb25NYXAuZ2V0KGlucHV0VmFsdWUpOwogICAgaWYgKG1lbW9WYWwgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gbWVtb1ZhbCA7CiAgICB9CgogICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTsKICAgIC8vIFN0b3JlIHRoZSBtYXBwaW5nIG9mIHRoaXMgdmFsdWUgaW4gY2FzZSB3ZSB2aXNpdCBpdCBhZ2FpbiwgaW4gY2FzZSBvZiBjaXJjdWxhciBkYXRhCiAgICBtZW1vaXphdGlvbk1hcC5zZXQoaW5wdXRWYWx1ZSwgcmV0dXJuVmFsdWUpOwoKICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGlucHV0VmFsdWUpKSB7CiAgICAgIGlmICh0eXBlb2YgaW5wdXRWYWx1ZVtrZXldICE9PSAndW5kZWZpbmVkJykgewogICAgICAgIHJldHVyblZhbHVlW2tleV0gPSBfZHJvcFVuZGVmaW5lZEtleXMoaW5wdXRWYWx1ZVtrZXldLCBtZW1vaXphdGlvbk1hcCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIGFycmF5IGl0IHdhcyBtYXBwZWQgdG8gaW4gdGhlIG5ldyBvYmplY3QKICAgIGNvbnN0IG1lbW9WYWwgPSBtZW1vaXphdGlvbk1hcC5nZXQoaW5wdXRWYWx1ZSk7CiAgICBpZiAobWVtb1ZhbCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZW1vVmFsIDsKICAgIH0KCiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IFtdOwogICAgLy8gU3RvcmUgdGhlIG1hcHBpbmcgb2YgdGhpcyB2YWx1ZSBpbiBjYXNlIHdlIHZpc2l0IGl0IGFnYWluLCBpbiBjYXNlIG9mIGNpcmN1bGFyIGRhdGEKICAgIG1lbW9pemF0aW9uTWFwLnNldChpbnB1dFZhbHVlLCByZXR1cm5WYWx1ZSk7CgogICAgaW5wdXRWYWx1ZS5mb3JFYWNoKChpdGVtKSA9PiB7CiAgICAgIHJldHVyblZhbHVlLnB1c2goX2Ryb3BVbmRlZmluZWRLZXlzKGl0ZW0sIG1lbW9pemF0aW9uTWFwKSk7CiAgICB9KTsKCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgcmV0dXJuIGlucHV0VmFsdWU7Cn0KCmZ1bmN0aW9uIGlzUG9qbyhpbnB1dCkgewogIGlmICghaXNQbGFpbk9iamVjdChpbnB1dCkpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CgogIHRyeSB7CiAgICBjb25zdCBuYW1lID0gKE9iamVjdC5nZXRQcm90b3R5cGVPZihpbnB1dCkgKS5jb25zdHJ1Y3Rvci5uYW1lOwogICAgcmV0dXJuICFuYW1lIHx8IG5hbWUgPT09ICdPYmplY3QnOwogIH0gY2F0Y2ggKGUpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQoKLyoqCiAqIFVVSUQ0IGdlbmVyYXRvcgogKgogKiBAcmV0dXJucyBzdHJpbmcgR2VuZXJhdGVkIFVVSUQ0LgogKi8KZnVuY3Rpb24gdXVpZDQoKSB7CiAgY29uc3QgZ2JsID0gR0xPQkFMX09CSiA7CiAgY29uc3QgY3J5cHRvID0gZ2JsLmNyeXB0byB8fCBnYmwubXNDcnlwdG87CgogIGxldCBnZXRSYW5kb21CeXRlID0gKCkgPT4gTWF0aC5yYW5kb20oKSAqIDE2OwogIHRyeSB7CiAgICBpZiAoY3J5cHRvICYmIGNyeXB0by5yYW5kb21VVUlEKSB7CiAgICAgIHJldHVybiBjcnlwdG8ucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywgJycpOwogICAgfQogICAgaWYgKGNyeXB0byAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKSB7CiAgICAgIGdldFJhbmRvbUJ5dGUgPSAoKSA9PiB7CiAgICAgICAgLy8gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyBtaWdodCByZXR1cm4gdW5kZWZpbmVkIGluc3RlYWQgb2YgdGhlIHR5cGVkIGFycmF5CiAgICAgICAgLy8gaW4gb2xkIENocm9taXVtIHZlcnNpb25zIChlLmcuIDIzLjAuMTIzNS4wICgxNTE0MjIpKQogICAgICAgIC8vIEhvd2V2ZXIsIGB0eXBlZEFycmF5YCBpcyBzdGlsbCBmaWxsZWQgaW4tcGxhY2UuCiAgICAgICAgLy8gQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ3J5cHRvL2dldFJhbmRvbVZhbHVlcyN0eXBlZGFycmF5CiAgICAgICAgY29uc3QgdHlwZWRBcnJheSA9IG5ldyBVaW50OEFycmF5KDEpOwogICAgICAgIGNyeXB0by5nZXRSYW5kb21WYWx1ZXModHlwZWRBcnJheSk7CiAgICAgICAgcmV0dXJuIHR5cGVkQXJyYXlbMF07CiAgICAgIH07CiAgICB9CiAgfSBjYXRjaCAoXykgewogICAgLy8gc29tZSBydW50aW1lcyBjYW4gY3Jhc2ggaW52b2tpbmcgY3J5cHRvCiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0L2lzc3Vlcy84OTM1CiAgfQoKICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzEwNTAzNC9ob3ctdG8tY3JlYXRlLWEtZ3VpZC11dWlkLWluLWphdmFzY3JpcHQvMjExNzUyMyMyMTE3NTIzCiAgLy8gQ29uY2F0ZW5hdGluZyB0aGUgZm9sbG93aW5nIG51bWJlcnMgYXMgc3RyaW5ncyByZXN1bHRzIGluICcxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCcKICByZXR1cm4gKChbMWU3XSApICsgMWUzICsgNGUzICsgOGUzICsgMWUxMSkucmVwbGFjZSgvWzAxOF0vZywgYyA9PgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2UKICAgICgoYyApIF4gKChnZXRSYW5kb21CeXRlKCkgJiAxNSkgPj4gKChjICkgLyA0KSkpLnRvU3RyaW5nKDE2KSwKICApOwp9CgovKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MgKi8KLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwoKLyoqCiAqIEhlbHBlciB0byBkZWN5Y2xlIGpzb24gb2JqZWN0cwogKi8KZnVuY3Rpb24gbWVtb0J1aWxkZXIoKSB7CiAgY29uc3QgaGFzV2Vha1NldCA9IHR5cGVvZiBXZWFrU2V0ID09PSAnZnVuY3Rpb24nOwogIGNvbnN0IGlubmVyID0gaGFzV2Vha1NldCA/IG5ldyBXZWFrU2V0KCkgOiBbXTsKICBmdW5jdGlvbiBtZW1vaXplKG9iaikgewogICAgaWYgKGhhc1dlYWtTZXQpIHsKICAgICAgaWYgKGlubmVyLmhhcyhvYmopKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaW5uZXIuYWRkKG9iaik7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvcHJlZmVyLWZvci1vZgogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbm5lci5sZW5ndGg7IGkrKykgewogICAgICBjb25zdCB2YWx1ZSA9IGlubmVyW2ldOwogICAgICBpZiAodmFsdWUgPT09IG9iaikgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICBpbm5lci5wdXNoKG9iaik7CiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiB1bm1lbW9pemUob2JqKSB7CiAgICBpZiAoaGFzV2Vha1NldCkgewogICAgICBpbm5lci5kZWxldGUob2JqKTsKICAgIH0gZWxzZSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5uZXIubGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAoaW5uZXJbaV0gPT09IG9iaikgewogICAgICAgICAgaW5uZXIuc3BsaWNlKGksIDEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBbbWVtb2l6ZSwgdW5tZW1vaXplXTsKfQoKLyoqCiAqIFJlY3Vyc2l2ZWx5IG5vcm1hbGl6ZXMgdGhlIGdpdmVuIG9iamVjdC4KICoKICogLSBDcmVhdGVzIGEgY29weSB0byBwcmV2ZW50IG9yaWdpbmFsIGlucHV0IG11dGF0aW9uCiAqIC0gU2tpcHMgbm9uLWVudW1lcmFibGUgcHJvcGVydGllcwogKiAtIFdoZW4gc3RyaW5naWZ5aW5nLCBjYWxscyBgdG9KU09OYCBpZiBpbXBsZW1lbnRlZAogKiAtIFJlbW92ZXMgY2lyY3VsYXIgcmVmZXJlbmNlcwogKiAtIFRyYW5zbGF0ZXMgbm9uLXNlcmlhbGl6YWJsZSB2YWx1ZXMgKGB1bmRlZmluZWRgL2BOYU5gL2Z1bmN0aW9ucykgdG8gc2VyaWFsaXphYmxlIGZvcm1hdAogKiAtIFRyYW5zbGF0ZXMga25vd24gZ2xvYmFsIG9iamVjdHMvY2xhc3NlcyB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvbnMKICogLSBUYWtlcyBjYXJlIG9mIGBFcnJvcmAgb2JqZWN0IHNlcmlhbGl6YXRpb24KICogLSBPcHRpb25hbGx5IGxpbWl0cyBkZXB0aCBvZiBmaW5hbCBvdXRwdXQKICogLSBPcHRpb25hbGx5IGxpbWl0cyBudW1iZXIgb2YgcHJvcGVydGllcy9lbGVtZW50cyBpbmNsdWRlZCBpbiBhbnkgc2luZ2xlIG9iamVjdC9hcnJheQogKgogKiBAcGFyYW0gaW5wdXQgVGhlIG9iamVjdCB0byBiZSBub3JtYWxpemVkLgogKiBAcGFyYW0gZGVwdGggVGhlIG1heCBkZXB0aCB0byB3aGljaCB0byBub3JtYWxpemUgdGhlIG9iamVjdC4gKEFueXRoaW5nIGRlZXBlciBzdHJpbmdpZmllZCB3aG9sZS4pCiAqIEBwYXJhbSBtYXhQcm9wZXJ0aWVzIFRoZSBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIG9yIHByb3BlcnRpZXMgdG8gYmUgaW5jbHVkZWQgaW4gYW55IHNpbmdsZSBhcnJheSBvcgogKiBvYmplY3QgaW4gdGhlIG5vcm1hbGxpemVkIG91dHB1dC4KICogQHJldHVybnMgQSBub3JtYWxpemVkIHZlcnNpb24gb2YgdGhlIG9iamVjdCwgb3IgYCIqKm5vbi1zZXJpYWxpemFibGUqKiJgIGlmIGFueSBlcnJvcnMgYXJlIHRocm93biBkdXJpbmcgbm9ybWFsaXphdGlvbi4KICovCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55CmZ1bmN0aW9uIG5vcm1hbGl6ZShpbnB1dCwgZGVwdGggPSAxMDAsIG1heFByb3BlcnRpZXMgPSArSW5maW5pdHkpIHsKICB0cnkgewogICAgLy8gc2luY2Ugd2UncmUgYXQgdGhlIG91dGVybW9zdCBsZXZlbCwgd2UgZG9uJ3QgcHJvdmlkZSBhIGtleQogICAgcmV0dXJuIHZpc2l0KCcnLCBpbnB1dCwgZGVwdGgsIG1heFByb3BlcnRpZXMpOwogIH0gY2F0Y2ggKGVycikgewogICAgcmV0dXJuIHsgRVJST1I6IGAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHtlcnJ9KWAgfTsKICB9Cn0KCi8qKgogKiBWaXNpdHMgYSBub2RlIHRvIHBlcmZvcm0gbm9ybWFsaXphdGlvbiBvbiBpdAogKgogKiBAcGFyYW0ga2V5IFRoZSBrZXkgY29ycmVzcG9uZGluZyB0byB0aGUgZ2l2ZW4gbm9kZQogKiBAcGFyYW0gdmFsdWUgVGhlIG5vZGUgdG8gYmUgdmlzaXRlZAogKiBAcGFyYW0gZGVwdGggT3B0aW9uYWwgbnVtYmVyIGluZGljYXRpbmcgdGhlIG1heGltdW0gcmVjdXJzaW9uIGRlcHRoCiAqIEBwYXJhbSBtYXhQcm9wZXJ0aWVzIE9wdGlvbmFsIG1heGltdW0gbnVtYmVyIG9mIHByb3BlcnRpZXMvZWxlbWVudHMgaW5jbHVkZWQgaW4gYW55IHNpbmdsZSBvYmplY3QvYXJyYXkKICogQHBhcmFtIG1lbW8gT3B0aW9uYWwgTWVtbyBjbGFzcyBoYW5kbGluZyBkZWN5Y2xpbmcKICovCmZ1bmN0aW9uIHZpc2l0KAogIGtleSwKICB2YWx1ZSwKICBkZXB0aCA9ICtJbmZpbml0eSwKICBtYXhQcm9wZXJ0aWVzID0gK0luZmluaXR5LAogIG1lbW8gPSBtZW1vQnVpbGRlcigpLAopIHsKICBjb25zdCBbbWVtb2l6ZSwgdW5tZW1vaXplXSA9IG1lbW87CgogIC8vIEdldCB0aGUgc2ltcGxlIGNhc2VzIG91dCBvZiB0aGUgd2F5IGZpcnN0CiAgaWYgKAogICAgdmFsdWUgPT0gbnVsbCB8fCAvLyB0aGlzIG1hdGNoZXMgbnVsbCBhbmQgdW5kZWZpbmVkIC0+IGVxZXEgbm90IGVxZXFlcQogICAgKFsnbnVtYmVyJywgJ2Jvb2xlYW4nLCAnc3RyaW5nJ10uaW5jbHVkZXModHlwZW9mIHZhbHVlKSAmJiAhaXNOYU4kMSh2YWx1ZSkpCiAgKSB7CiAgICByZXR1cm4gdmFsdWUgOwogIH0KCiAgY29uc3Qgc3RyaW5naWZpZWQgPSBzdHJpbmdpZnlWYWx1ZShrZXksIHZhbHVlKTsKCiAgLy8gQW55dGhpbmcgd2UgY291bGQgcG90ZW50aWFsbHkgZGlnIGludG8gbW9yZSAob2JqZWN0cyBvciBhcnJheXMpIHdpbGwgaGF2ZSBjb21lIGJhY2sgYXMgYCJbb2JqZWN0IFhYWFhdImAuCiAgLy8gRXZlcnl0aGluZyBlbHNlIHdpbGwgaGF2ZSBhbHJlYWR5IGJlZW4gc2VyaWFsaXplZCwgc28gaWYgd2UgZG9uJ3Qgc2VlIHRoYXQgcGF0dGVybiwgd2UncmUgZG9uZS4KICBpZiAoIXN0cmluZ2lmaWVkLnN0YXJ0c1dpdGgoJ1tvYmplY3QgJykpIHsKICAgIHJldHVybiBzdHJpbmdpZmllZDsKICB9CgogIC8vIEZyb20gaGVyZSBvbiwgd2UgY2FuIGFzc2VydCB0aGF0IGB2YWx1ZWAgaXMgZWl0aGVyIGFuIG9iamVjdCBvciBhbiBhcnJheS4KCiAgLy8gRG8gbm90IG5vcm1hbGl6ZSBvYmplY3RzIHRoYXQgd2Uga25vdyBoYXZlIGFscmVhZHkgYmVlbiBub3JtYWxpemVkLiBBcyBhIGdlbmVyYWwgcnVsZSwgdGhlCiAgLy8gIl9fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fIiBwcm9wZXJ0eSBzaG91bGQgb25seSBiZSB1c2VkIHNwYXJpbmdseSBhbmQgb25seSBzaG91bGQgb25seSBiZSBzZXQgb24gb2JqZWN0cyB0aGF0CiAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gbm9ybWFsaXplZC4KICBpZiAoKHZhbHVlIClbJ19fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fJ10pIHsKICAgIHJldHVybiB2YWx1ZSA7CiAgfQoKICAvLyBXZSBjYW4gc2V0IGBfX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX19gIG9uIGFuIG9iamVjdCB0byBlbnN1cmUgdGhhdCBmcm9tIHRoZXJlCiAgLy8gV2Uga2VlcCBhIGNlcnRhaW4gYW1vdW50IG9mIGRlcHRoLgogIC8vIFRoaXMgc2hvdWxkIGJlIHVzZWQgc3BhcmluZ2x5LCBlLmcuIHdlIHVzZSBpdCBmb3IgdGhlIHJlZHV4IGludGVncmF0aW9uIHRvIGVuc3VyZSB3ZSBnZXQgYSBjZXJ0YWluIGFtb3VudCBvZiBzdGF0ZS4KICBjb25zdCByZW1haW5pbmdEZXB0aCA9CiAgICB0eXBlb2YgKHZhbHVlIClbJ19fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXyddID09PSAnbnVtYmVyJwogICAgICA/ICgodmFsdWUgKVsnX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fJ10gKQogICAgICA6IGRlcHRoOwoKICAvLyBXZSdyZSBhbHNvIGRvbmUgaWYgd2UndmUgcmVhY2hlZCB0aGUgbWF4IGRlcHRoCiAgaWYgKHJlbWFpbmluZ0RlcHRoID09PSAwKSB7CiAgICAvLyBBdCB0aGlzIHBvaW50IHdlIGtub3cgYHNlcmlhbGl6ZWRgIGlzIGEgc3RyaW5nIG9mIHRoZSBmb3JtIGAiW29iamVjdCBYWFhYXSJgLiBDbGVhbiBpdCB1cCBzbyBpdCdzIGp1c3QgYCJbWFhYWF0iYC4KICAgIHJldHVybiBzdHJpbmdpZmllZC5yZXBsYWNlKCdvYmplY3QgJywgJycpOwogIH0KCiAgLy8gSWYgd2UndmUgYWxyZWFkeSB2aXNpdGVkIHRoaXMgYnJhbmNoLCBiYWlsIG91dCwgYXMgaXQncyBjaXJjdWxhciByZWZlcmVuY2UuIElmIG5vdCwgbm90ZSB0aGF0IHdlJ3JlIHNlZWluZyBpdCBub3cuCiAgaWYgKG1lbW9pemUodmFsdWUpKSB7CiAgICByZXR1cm4gJ1tDaXJjdWxhciB+XSc7CiAgfQoKICAvLyBJZiB0aGUgdmFsdWUgaGFzIGEgYHRvSlNPTmAgbWV0aG9kLCB3ZSBjYWxsIGl0IHRvIGV4dHJhY3QgbW9yZSBpbmZvcm1hdGlvbgogIGNvbnN0IHZhbHVlV2l0aFRvSlNPTiA9IHZhbHVlIDsKICBpZiAodmFsdWVXaXRoVG9KU09OICYmIHR5cGVvZiB2YWx1ZVdpdGhUb0pTT04udG9KU09OID09PSAnZnVuY3Rpb24nKSB7CiAgICB0cnkgewogICAgICBjb25zdCBqc29uVmFsdWUgPSB2YWx1ZVdpdGhUb0pTT04udG9KU09OKCk7CiAgICAgIC8vIFdlIG5lZWQgdG8gbm9ybWFsaXplIHRoZSByZXR1cm4gdmFsdWUgb2YgYC50b0pTT04oKWAgaW4gY2FzZSBpdCBoYXMgY2lyY3VsYXIgcmVmZXJlbmNlcwogICAgICByZXR1cm4gdmlzaXQoJycsIGpzb25WYWx1ZSwgcmVtYWluaW5nRGVwdGggLSAxLCBtYXhQcm9wZXJ0aWVzLCBtZW1vKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICAvLyBwYXNzIChUaGUgYnVpbHQtaW4gYHRvSlNPTmAgZmFpbGVkLCBidXQgd2UgY2FuIHN0aWxsIHRyeSB0byBkbyBpdCBvdXJzZWx2ZXMpCiAgICB9CiAgfQoKICAvLyBBdCB0aGlzIHBvaW50IHdlIGtub3cgd2UgZWl0aGVyIGhhdmUgYW4gb2JqZWN0IG9yIGFuIGFycmF5LCB3ZSBoYXZlbid0IHNlZW4gaXQgYmVmb3JlLCBhbmQgd2UncmUgZ29pbmcgdG8gcmVjdXJzZQogIC8vIGJlY2F1c2Ugd2UgaGF2ZW4ndCB5ZXQgcmVhY2hlZCB0aGUgbWF4IGRlcHRoLiBDcmVhdGUgYW4gYWNjdW11bGF0b3IgdG8gaG9sZCB0aGUgcmVzdWx0cyBvZiB2aXNpdGluZyBlYWNoCiAgLy8gcHJvcGVydHkvZW50cnksIGFuZCBrZWVwIHRyYWNrIG9mIHRoZSBudW1iZXIgb2YgaXRlbXMgd2UgYWRkIHRvIGl0LgogIGNvbnN0IG5vcm1hbGl6ZWQgPSAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyBbXSA6IHt9KSA7CiAgbGV0IG51bUFkZGVkID0gMDsKCiAgLy8gQmVmb3JlIHdlIGJlZ2luLCBjb252ZXJ0YEVycm9yYCBhbmRgRXZlbnRgIGluc3RhbmNlcyBpbnRvIHBsYWluIG9iamVjdHMsIHNpbmNlIHNvbWUgb2YgZWFjaCBvZiB0aGVpciByZWxldmFudAogIC8vIHByb3BlcnRpZXMgYXJlIG5vbi1lbnVtZXJhYmxlIGFuZCBvdGhlcndpc2Ugd291bGQgZ2V0IG1pc3NlZC4KICBjb25zdCB2aXNpdGFibGUgPSBjb252ZXJ0VG9QbGFpbk9iamVjdCh2YWx1ZSApOwoKICBmb3IgKGNvbnN0IHZpc2l0S2V5IGluIHZpc2l0YWJsZSkgewogICAgLy8gQXZvaWQgaXRlcmF0aW5nIG92ZXIgZmllbGRzIGluIHRoZSBwcm90b3R5cGUgaWYgdGhleSd2ZSBzb21laG93IGJlZW4gZXhwb3NlZCB0byBlbnVtZXJhdGlvbi4KICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZpc2l0YWJsZSwgdmlzaXRLZXkpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQoKICAgIGlmIChudW1BZGRlZCA+PSBtYXhQcm9wZXJ0aWVzKSB7CiAgICAgIG5vcm1hbGl6ZWRbdmlzaXRLZXldID0gJ1tNYXhQcm9wZXJ0aWVzIH5dJzsKICAgICAgYnJlYWs7CiAgICB9CgogICAgLy8gUmVjdXJzaXZlbHkgdmlzaXQgYWxsIHRoZSBjaGlsZCBub2RlcwogICAgY29uc3QgdmlzaXRWYWx1ZSA9IHZpc2l0YWJsZVt2aXNpdEtleV07CiAgICBub3JtYWxpemVkW3Zpc2l0S2V5XSA9IHZpc2l0KHZpc2l0S2V5LCB2aXNpdFZhbHVlLCByZW1haW5pbmdEZXB0aCAtIDEsIG1heFByb3BlcnRpZXMsIG1lbW8pOwoKICAgIG51bUFkZGVkKys7CiAgfQoKICAvLyBPbmNlIHdlJ3ZlIHZpc2l0ZWQgYWxsIHRoZSBicmFuY2hlcywgcmVtb3ZlIHRoZSBwYXJlbnQgZnJvbSBtZW1vIHN0b3JhZ2UKICB1bm1lbW9pemUodmFsdWUpOwoKICAvLyBSZXR1cm4gYWNjdW11bGF0ZWQgdmFsdWVzCiAgcmV0dXJuIG5vcm1hbGl6ZWQ7Cn0KCi8qIGVzbGludC1kaXNhYmxlIGNvbXBsZXhpdHkgKi8KLyoqCiAqIFN0cmluZ2lmeSB0aGUgZ2l2ZW4gdmFsdWUuIEhhbmRsZXMgdmFyaW91cyBrbm93biBzcGVjaWFsIHZhbHVlcyBhbmQgdHlwZXMuCiAqCiAqIE5vdCBtZWFudCB0byBiZSB1c2VkIG9uIHNpbXBsZSBwcmltaXRpdmVzIHdoaWNoIGFscmVhZHkgaGF2ZSBhIHN0cmluZyByZXByZXNlbnRhdGlvbiwgYXMgaXQgd2lsbCwgZm9yIGV4YW1wbGUsIHR1cm4KICogdGhlIG51bWJlciAxMjMxIGludG8gIltPYmplY3QgTnVtYmVyXSIsIG5vciBvbiBgbnVsbGAsIGFzIGl0IHdpbGwgdGhyb3cuCiAqCiAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gc3RyaW5naWZ5CiAqIEByZXR1cm5zIEEgc3RyaW5naWZpZWQgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIHZhbHVlCiAqLwpmdW5jdGlvbiBzdHJpbmdpZnlWYWx1ZSgKICBrZXksCiAgLy8gdGhpcyB0eXBlIGlzIGEgdGlueSBiaXQgb2YgYSBjaGVhdCwgc2luY2UgdGhpcyBmdW5jdGlvbiBkb2VzIGhhbmRsZSBOYU4gKHdoaWNoIGlzIHRlY2huaWNhbGx5IGEgbnVtYmVyKSwgYnV0IGZvcgogIC8vIG91ciBpbnRlcm5hbCB1c2UsIGl0J2xsIGRvCiAgdmFsdWUsCikgewogIHRyeSB7CiAgICBpZiAoa2V5ID09PSAnZG9tYWluJyAmJiB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmICh2YWx1ZSApLl9ldmVudHMpIHsKICAgICAgcmV0dXJuICdbRG9tYWluXSc7CiAgICB9CgogICAgaWYgKGtleSA9PT0gJ2RvbWFpbkVtaXR0ZXInKSB7CiAgICAgIHJldHVybiAnW0RvbWFpbkVtaXR0ZXJdJzsKICAgIH0KCiAgICAvLyBJdCdzIHNhZmUgdG8gdXNlIGBnbG9iYWxgLCBgd2luZG93YCwgYW5kIGBkb2N1bWVudGAgaGVyZSBpbiB0aGlzIG1hbm5lciwgYXMgd2UgYXJlIGFzc2VydGluZyB1c2luZyBgdHlwZW9mYCBmaXJzdAogICAgLy8gd2hpY2ggd29uJ3QgdGhyb3cgaWYgdGhleSBhcmUgbm90IHByZXNlbnQuCgogICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlID09PSBnbG9iYWwpIHsKICAgICAgcmV0dXJuICdbR2xvYmFsXSc7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtZ2xvYmFscwogICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlID09PSB3aW5kb3cpIHsKICAgICAgcmV0dXJuICdbV2luZG93XSc7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtZ2xvYmFscwogICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgPT09IGRvY3VtZW50KSB7CiAgICAgIHJldHVybiAnW0RvY3VtZW50XSc7CiAgICB9CgogICAgaWYgKGlzVnVlVmlld01vZGVsKHZhbHVlKSkgewogICAgICByZXR1cm4gJ1tWdWVWaWV3TW9kZWxdJzsKICAgIH0KCiAgICAvLyBSZWFjdCdzIFN5bnRoZXRpY0V2ZW50IHRoaW5neQogICAgaWYgKGlzU3ludGhldGljRXZlbnQodmFsdWUpKSB7CiAgICAgIHJldHVybiAnW1N5bnRoZXRpY0V2ZW50XSc7CiAgICB9CgogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgdmFsdWUgIT09IHZhbHVlKSB7CiAgICAgIHJldHVybiAnW05hTl0nOwogICAgfQoKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGBbRnVuY3Rpb246ICR7Z2V0RnVuY3Rpb25OYW1lKHZhbHVlKX1dYDsKICAgIH0KCiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJykgewogICAgICByZXR1cm4gYFske1N0cmluZyh2YWx1ZSl9XWA7CiAgICB9CgogICAgLy8gc3RyaW5naWZpZWQgQmlnSW50cyBhcmUgaW5kaXN0aW5ndWlzaGFibGUgZnJvbSByZWd1bGFyIG51bWJlcnMsIHNvIHdlIG5lZWQgdG8gbGFiZWwgdGhlbSB0byBhdm9pZCBjb25mdXNpb24KICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdiaWdpbnQnKSB7CiAgICAgIHJldHVybiBgW0JpZ0ludDogJHtTdHJpbmcodmFsdWUpfV1gOwogICAgfQoKICAgIC8vIE5vdyB0aGF0IHdlJ3ZlIGtub2NrZWQgb3V0IGFsbCB0aGUgc3BlY2lhbCBjYXNlcyBhbmQgdGhlIHByaW1pdGl2ZXMsIGFsbCB3ZSBoYXZlIGxlZnQgYXJlIG9iamVjdHMuIFNpbXBseSBjYXN0aW5nCiAgICAvLyB0aGVtIHRvIHN0cmluZ3MgbWVhbnMgdGhhdCBpbnN0YW5jZXMgb2YgY2xhc3NlcyB3aGljaCBoYXZlbid0IGRlZmluZWQgdGhlaXIgYHRvU3RyaW5nVGFnYCB3aWxsIGp1c3QgY29tZSBvdXQgYXMKICAgIC8vIGAiW29iamVjdCBPYmplY3RdImAuIElmIHdlIGluc3RlYWQgbG9vayBhdCB0aGUgY29uc3RydWN0b3IncyBuYW1lICh3aGljaCBpcyB0aGUgc2FtZSBhcyB0aGUgbmFtZSBvZiB0aGUgY2xhc3MpLAogICAgLy8gd2UgY2FuIG1ha2Ugc3VyZSB0aGF0IG9ubHkgcGxhaW4gb2JqZWN0cyBjb21lIG91dCB0aGF0IHdheS4KICAgIGNvbnN0IG9iak5hbWUgPSBnZXRDb25zdHJ1Y3Rvck5hbWUodmFsdWUpOwoKICAgIC8vIEhhbmRsZSBIVE1MIEVsZW1lbnRzCiAgICBpZiAoL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChvYmpOYW1lKSkgewogICAgICByZXR1cm4gYFtIVE1MRWxlbWVudDogJHtvYmpOYW1lfV1gOwogICAgfQoKICAgIHJldHVybiBgW29iamVjdCAke29iak5hbWV9XWA7CiAgfSBjYXRjaCAoZXJyKSB7CiAgICByZXR1cm4gYCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke2Vycn0pYDsKICB9Cn0KLyogZXNsaW50LWVuYWJsZSBjb21wbGV4aXR5ICovCgpmdW5jdGlvbiBnZXRDb25zdHJ1Y3Rvck5hbWUodmFsdWUpIHsKICBjb25zdCBwcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpOwoKICByZXR1cm4gcHJvdG90eXBlID8gcHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUgOiAnbnVsbCBwcm90b3R5cGUnOwp9CgovKioKICogTm9ybWFsaXplcyBVUkxzIGluIGV4Y2VwdGlvbnMgYW5kIHN0YWNrdHJhY2VzIHRvIGEgYmFzZSBwYXRoIHNvIFNlbnRyeSBjYW4gZmluZ2VycHJpbnQKICogYWNyb3NzIHBsYXRmb3JtcyBhbmQgd29ya2luZyBkaXJlY3RvcnkuCiAqCiAqIEBwYXJhbSB1cmwgVGhlIFVSTCB0byBiZSBub3JtYWxpemVkLgogKiBAcGFyYW0gYmFzZVBhdGggVGhlIGFwcGxpY2F0aW9uIGJhc2UgcGF0aC4KICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgVVJMLgogKi8KZnVuY3Rpb24gbm9ybWFsaXplVXJsVG9CYXNlKHVybCwgYmFzZVBhdGgpIHsKICBjb25zdCBlc2NhcGVkQmFzZSA9IGJhc2VQYXRoCiAgICAvLyBCYWNrc2xhc2ggdG8gZm9yd2FyZAogICAgLnJlcGxhY2UoL1xcL2csICcvJykKICAgIC8vIEVzY2FwZSBSZWdFeHAgc3BlY2lhbCBjaGFyYWN0ZXJzCiAgICAucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csICdcXCQmJyk7CgogIGxldCBuZXdVcmwgPSB1cmw7CiAgdHJ5IHsKICAgIG5ld1VybCA9IGRlY29kZVVSSSh1cmwpOwogIH0gY2F0Y2ggKF9PbykgewogICAgLy8gU29tZXRpbWUgdGhpcyBicmVha3MKICB9CiAgcmV0dXJuICgKICAgIG5ld1VybAogICAgICAucmVwbGFjZSgvXFwvZywgJy8nKQogICAgICAucmVwbGFjZSgvd2VicGFjazpcLz8vZywgJycpIC8vIFJlbW92ZSBpbnRlcm1lZGlhdGUgYmFzZSBwYXRoCiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAc2VudHJ5LWludGVybmFsL3Nkay9uby1yZWdleHAtY29uc3RydWN0b3IKICAgICAgLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtlc2NhcGVkQmFzZX0vKmAsICdpZycpLCAnYXBwOi8vLycpCiAgKTsKfQoKLy8gU2xpZ2h0bHkgbW9kaWZpZWQgKG5vIElFOCBzdXBwb3J0LCBFUzYpIGFuZCB0cmFuc2NyaWJlZCB0byBUeXBlU2NyaXB0CgovLyBTcGxpdCBhIGZpbGVuYW1lIGludG8gW3Jvb3QsIGRpciwgYmFzZW5hbWUsIGV4dF0sIHVuaXggdmVyc2lvbgovLyAncm9vdCcgaXMganVzdCBhIHNsYXNoLCBvciBub3RoaW5nLgpjb25zdCBzcGxpdFBhdGhSZSA9IC9eKFxTKzpcXHxcLz8pKFtcc1xTXSo/KSgoPzpcLnsxLDJ9fFteL1xcXSs/fCkoXC5bXi4vXFxdKnwpKSg/OlsvXFxdKikkLzsKLyoqIEpTRG9jICovCmZ1bmN0aW9uIHNwbGl0UGF0aChmaWxlbmFtZSkgewogIC8vIFRydW5jYXRlIGZpbGVzIG5hbWVzIGdyZWF0ZXIgdGhhbiAxMDI0IGNoYXJhY3RlcnMgdG8gYXZvaWQgcmVnZXggZG9zCiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9wdWxsLzg3MzcjZGlzY3Vzc2lvbl9yMTI4NTcxOTE3MgogIGNvbnN0IHRydW5jYXRlZCA9IGZpbGVuYW1lLmxlbmd0aCA+IDEwMjQgPyBgPHRydW5jYXRlZD4ke2ZpbGVuYW1lLnNsaWNlKC0xMDI0KX1gIDogZmlsZW5hbWU7CiAgY29uc3QgcGFydHMgPSBzcGxpdFBhdGhSZS5leGVjKHRydW5jYXRlZCk7CiAgcmV0dXJuIHBhcnRzID8gcGFydHMuc2xpY2UoMSkgOiBbXTsKfQoKLyoqIEpTRG9jICovCmZ1bmN0aW9uIGRpcm5hbWUocGF0aCkgewogIGNvbnN0IHJlc3VsdCA9IHNwbGl0UGF0aChwYXRoKTsKICBjb25zdCByb290ID0gcmVzdWx0WzBdOwogIGxldCBkaXIgPSByZXN1bHRbMV07CgogIGlmICghcm9vdCAmJiAhZGlyKSB7CiAgICAvLyBObyBkaXJuYW1lIHdoYXRzb2V2ZXIKICAgIHJldHVybiAnLic7CiAgfQoKICBpZiAoZGlyKSB7CiAgICAvLyBJdCBoYXMgYSBkaXJuYW1lLCBzdHJpcCB0cmFpbGluZyBzbGFzaAogICAgZGlyID0gZGlyLnNsaWNlKDAsIGRpci5sZW5ndGggLSAxKTsKICB9CgogIHJldHVybiByb290ICsgZGlyOwp9CgovKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvZXhwbGljaXQtZnVuY3Rpb24tcmV0dXJuLXR5cGUgKi8KCi8qKiBTeW5jUHJvbWlzZSBpbnRlcm5hbCBzdGF0ZXMgKi8KdmFyIFN0YXRlczsgKGZ1bmN0aW9uIChTdGF0ZXMpIHsKICAvKiogUGVuZGluZyAqLwogIGNvbnN0IFBFTkRJTkcgPSAwOyBTdGF0ZXNbU3RhdGVzWyJQRU5ESU5HIl0gPSBQRU5ESU5HXSA9ICJQRU5ESU5HIjsKICAvKiogUmVzb2x2ZWQgLyBPSyAqLwogIGNvbnN0IFJFU09MVkVEID0gMTsgU3RhdGVzW1N0YXRlc1siUkVTT0xWRUQiXSA9IFJFU09MVkVEXSA9ICJSRVNPTFZFRCI7CiAgLyoqIFJlamVjdGVkIC8gRXJyb3IgKi8KICBjb25zdCBSRUpFQ1RFRCA9IDI7IFN0YXRlc1tTdGF0ZXNbIlJFSkVDVEVEIl0gPSBSRUpFQ1RFRF0gPSAiUkVKRUNURUQiOwp9KShTdGF0ZXMgfHwgKFN0YXRlcyA9IHt9KSk7CgovLyBPdmVybG9hZHMgc28gd2UgY2FuIGNhbGwgcmVzb2x2ZWRTeW5jUHJvbWlzZSB3aXRob3V0IGFyZ3VtZW50cyBhbmQgZ2VuZXJpYyBhcmd1bWVudAoKLyoqCiAqIENyZWF0ZXMgYSByZXNvbHZlZCBzeW5jIHByb21pc2UuCiAqCiAqIEBwYXJhbSB2YWx1ZSB0aGUgdmFsdWUgdG8gcmVzb2x2ZSB0aGUgcHJvbWlzZSB3aXRoCiAqIEByZXR1cm5zIHRoZSByZXNvbHZlZCBzeW5jIHByb21pc2UKICovCmZ1bmN0aW9uIHJlc29sdmVkU3luY1Byb21pc2UodmFsdWUpIHsKICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKHJlc29sdmUgPT4gewogICAgcmVzb2x2ZSh2YWx1ZSk7CiAgfSk7Cn0KCi8qKgogKiBDcmVhdGVzIGEgcmVqZWN0ZWQgc3luYyBwcm9taXNlLgogKgogKiBAcGFyYW0gdmFsdWUgdGhlIHZhbHVlIHRvIHJlamVjdCB0aGUgcHJvbWlzZSB3aXRoCiAqIEByZXR1cm5zIHRoZSByZWplY3RlZCBzeW5jIHByb21pc2UKICovCmZ1bmN0aW9uIHJlamVjdGVkU3luY1Byb21pc2UocmVhc29uKSB7CiAgcmV0dXJuIG5ldyBTeW5jUHJvbWlzZSgoXywgcmVqZWN0KSA9PiB7CiAgICByZWplY3QocmVhc29uKTsKICB9KTsKfQoKLyoqCiAqIFRoZW5hYmxlIGNsYXNzIHRoYXQgYmVoYXZlcyBsaWtlIGEgUHJvbWlzZSBhbmQgZm9sbG93cyBpdCdzIGludGVyZmFjZQogKiBidXQgaXMgbm90IGFzeW5jIGludGVybmFsbHkKICovCmNsYXNzIFN5bmNQcm9taXNlIHsKCiAgIGNvbnN0cnVjdG9yKAogICAgZXhlY3V0b3IsCiAgKSB7U3luY1Byb21pc2UucHJvdG90eXBlLl9faW5pdC5jYWxsKHRoaXMpO1N5bmNQcm9taXNlLnByb3RvdHlwZS5fX2luaXQyLmNhbGwodGhpcyk7U3luY1Byb21pc2UucHJvdG90eXBlLl9faW5pdDMuY2FsbCh0aGlzKTtTeW5jUHJvbWlzZS5wcm90b3R5cGUuX19pbml0NC5jYWxsKHRoaXMpOwogICAgdGhpcy5fc3RhdGUgPSBTdGF0ZXMuUEVORElORzsKICAgIHRoaXMuX2hhbmRsZXJzID0gW107CgogICAgdHJ5IHsKICAgICAgZXhlY3V0b3IodGhpcy5fcmVzb2x2ZSwgdGhpcy5fcmVqZWN0KTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgdGhpcy5fcmVqZWN0KGUpOwogICAgfQogIH0KCiAgLyoqIEpTRG9jICovCiAgIHRoZW4oCiAgICBvbmZ1bGZpbGxlZCwKICAgIG9ucmVqZWN0ZWQsCiAgKSB7CiAgICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgdGhpcy5faGFuZGxlcnMucHVzaChbCiAgICAgICAgZmFsc2UsCiAgICAgICAgcmVzdWx0ID0+IHsKICAgICAgICAgIGlmICghb25mdWxmaWxsZWQpIHsKICAgICAgICAgICAgLy8gVE9ETzogwq9cXyjjg4QpXy/CrwogICAgICAgICAgICAvLyBUT0RPOiBGSVhNRQogICAgICAgICAgICByZXNvbHZlKHJlc3VsdCApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICByZXNvbHZlKG9uZnVsZmlsbGVkKHJlc3VsdCkpOwogICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgcmVqZWN0KGUpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICByZWFzb24gPT4gewogICAgICAgICAgaWYgKCFvbnJlamVjdGVkKSB7CiAgICAgICAgICAgIHJlamVjdChyZWFzb24pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICByZXNvbHZlKG9ucmVqZWN0ZWQocmVhc29uKSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICByZWplY3QoZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9LAogICAgICBdKTsKICAgICAgdGhpcy5fZXhlY3V0ZUhhbmRsZXJzKCk7CiAgICB9KTsKICB9CgogIC8qKiBKU0RvYyAqLwogICBjYXRjaCgKICAgIG9ucmVqZWN0ZWQsCiAgKSB7CiAgICByZXR1cm4gdGhpcy50aGVuKHZhbCA9PiB2YWwsIG9ucmVqZWN0ZWQpOwogIH0KCiAgLyoqIEpTRG9jICovCiAgIGZpbmFsbHkob25maW5hbGx5KSB7CiAgICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgbGV0IHZhbDsKICAgICAgbGV0IGlzUmVqZWN0ZWQ7CgogICAgICByZXR1cm4gdGhpcy50aGVuKAogICAgICAgIHZhbHVlID0+IHsKICAgICAgICAgIGlzUmVqZWN0ZWQgPSBmYWxzZTsKICAgICAgICAgIHZhbCA9IHZhbHVlOwogICAgICAgICAgaWYgKG9uZmluYWxseSkgewogICAgICAgICAgICBvbmZpbmFsbHkoKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHJlYXNvbiA9PiB7CiAgICAgICAgICBpc1JlamVjdGVkID0gdHJ1ZTsKICAgICAgICAgIHZhbCA9IHJlYXNvbjsKICAgICAgICAgIGlmIChvbmZpbmFsbHkpIHsKICAgICAgICAgICAgb25maW5hbGx5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgKS50aGVuKCgpID0+IHsKICAgICAgICBpZiAoaXNSZWplY3RlZCkgewogICAgICAgICAgcmVqZWN0KHZhbCk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICByZXNvbHZlKHZhbCApOwogICAgICB9KTsKICAgIH0pOwogIH0KCiAgLyoqIEpTRG9jICovCiAgICBfX2luaXQoKSB7dGhpcy5fcmVzb2x2ZSA9ICh2YWx1ZSkgPT4gewogICAgdGhpcy5fc2V0UmVzdWx0KFN0YXRlcy5SRVNPTFZFRCwgdmFsdWUpOwogIH07fQoKICAvKiogSlNEb2MgKi8KICAgIF9faW5pdDIoKSB7dGhpcy5fcmVqZWN0ID0gKHJlYXNvbikgPT4gewogICAgdGhpcy5fc2V0UmVzdWx0KFN0YXRlcy5SRUpFQ1RFRCwgcmVhc29uKTsKICB9O30KCiAgLyoqIEpTRG9jICovCiAgICBfX2luaXQzKCkge3RoaXMuX3NldFJlc3VsdCA9IChzdGF0ZSwgdmFsdWUpID0+IHsKICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gU3RhdGVzLlBFTkRJTkcpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChpc1RoZW5hYmxlKHZhbHVlKSkgewogICAgICB2b2lkICh2YWx1ZSApLnRoZW4odGhpcy5fcmVzb2x2ZSwgdGhpcy5fcmVqZWN0KTsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7CiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlOwoKICAgIHRoaXMuX2V4ZWN1dGVIYW5kbGVycygpOwogIH07fQoKICAvKiogSlNEb2MgKi8KICAgIF9faW5pdDQoKSB7dGhpcy5fZXhlY3V0ZUhhbmRsZXJzID0gKCkgPT4gewogICAgaWYgKHRoaXMuX3N0YXRlID09PSBTdGF0ZXMuUEVORElORykgewogICAgICByZXR1cm47CiAgICB9CgogICAgY29uc3QgY2FjaGVkSGFuZGxlcnMgPSB0aGlzLl9oYW5kbGVycy5zbGljZSgpOwogICAgdGhpcy5faGFuZGxlcnMgPSBbXTsKCiAgICBjYWNoZWRIYW5kbGVycy5mb3JFYWNoKGhhbmRsZXIgPT4gewogICAgICBpZiAoaGFuZGxlclswXSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX3N0YXRlID09PSBTdGF0ZXMuUkVTT0xWRUQpIHsKICAgICAgICBoYW5kbGVyWzFdKHRoaXMuX3ZhbHVlICk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gU3RhdGVzLlJFSkVDVEVEKSB7CiAgICAgICAgaGFuZGxlclsyXSh0aGlzLl92YWx1ZSk7CiAgICAgIH0KCiAgICAgIGhhbmRsZXJbMF0gPSB0cnVlOwogICAgfSk7CiAgfTt9Cn0KCi8qKgogKiBDcmVhdGVzIGFuIG5ldyBQcm9taXNlQnVmZmVyIG9iamVjdCB3aXRoIHRoZSBzcGVjaWZpZWQgbGltaXQKICogQHBhcmFtIGxpbWl0IG1heCBudW1iZXIgb2YgcHJvbWlzZXMgdGhhdCBjYW4gYmUgc3RvcmVkIGluIHRoZSBidWZmZXIKICovCmZ1bmN0aW9uIG1ha2VQcm9taXNlQnVmZmVyKGxpbWl0KSB7CiAgY29uc3QgYnVmZmVyID0gW107CgogIGZ1bmN0aW9uIGlzUmVhZHkoKSB7CiAgICByZXR1cm4gbGltaXQgPT09IHVuZGVmaW5lZCB8fCBidWZmZXIubGVuZ3RoIDwgbGltaXQ7CiAgfQoKICAvKioKICAgKiBSZW1vdmUgYSBwcm9taXNlIGZyb20gdGhlIHF1ZXVlLgogICAqCiAgICogQHBhcmFtIHRhc2sgQ2FuIGJlIGFueSBQcm9taXNlTGlrZTxUPgogICAqIEByZXR1cm5zIFJlbW92ZWQgcHJvbWlzZS4KICAgKi8KICBmdW5jdGlvbiByZW1vdmUodGFzaykgewogICAgcmV0dXJuIGJ1ZmZlci5zcGxpY2UoYnVmZmVyLmluZGV4T2YodGFzayksIDEpWzBdOwogIH0KCiAgLyoqCiAgICogQWRkIGEgcHJvbWlzZSAocmVwcmVzZW50aW5nIGFuIGluLWZsaWdodCBhY3Rpb24pIHRvIHRoZSBxdWV1ZSwgYW5kIHNldCBpdCB0byByZW1vdmUgaXRzZWxmIG9uIGZ1bGZpbGxtZW50LgogICAqCiAgICogQHBhcmFtIHRhc2tQcm9kdWNlciBBIGZ1bmN0aW9uIHByb2R1Y2luZyBhbnkgUHJvbWlzZUxpa2U8VD47IEluIHByZXZpb3VzIHZlcnNpb25zIHRoaXMgdXNlZCB0byBiZSBgdGFzazoKICAgKiAgICAgICAgUHJvbWlzZUxpa2U8VD5gLCBidXQgdW5kZXIgdGhhdCBtb2RlbCwgUHJvbWlzZXMgd2VyZSBpbnN0YW50bHkgY3JlYXRlZCBvbiB0aGUgY2FsbC1zaXRlIGFuZCB0aGVpciBleGVjdXRvcgogICAqICAgICAgICBmdW5jdGlvbnMgdGhlcmVmb3JlIHJhbiBpbW1lZGlhdGVseS4gVGh1cywgZXZlbiBpZiB0aGUgYnVmZmVyIHdhcyBmdWxsLCB0aGUgYWN0aW9uIHN0aWxsIGhhcHBlbmVkLiBCeQogICAqICAgICAgICByZXF1aXJpbmcgdGhlIHByb21pc2UgdG8gYmUgd3JhcHBlZCBpbiBhIGZ1bmN0aW9uLCB3ZSBjYW4gZGVmZXIgcHJvbWlzZSBjcmVhdGlvbiB1bnRpbCBhZnRlciB0aGUgYnVmZmVyCiAgICogICAgICAgIGxpbWl0IGNoZWNrLgogICAqIEByZXR1cm5zIFRoZSBvcmlnaW5hbCBwcm9taXNlLgogICAqLwogIGZ1bmN0aW9uIGFkZCh0YXNrUHJvZHVjZXIpIHsKICAgIGlmICghaXNSZWFkeSgpKSB7CiAgICAgIHJldHVybiByZWplY3RlZFN5bmNQcm9taXNlKG5ldyBTZW50cnlFcnJvcignTm90IGFkZGluZyBQcm9taXNlIGJlY2F1c2UgYnVmZmVyIGxpbWl0IHdhcyByZWFjaGVkLicpKTsKICAgIH0KCiAgICAvLyBzdGFydCB0aGUgdGFzayBhbmQgYWRkIGl0cyBwcm9taXNlIHRvIHRoZSBxdWV1ZQogICAgY29uc3QgdGFzayA9IHRhc2tQcm9kdWNlcigpOwogICAgaWYgKGJ1ZmZlci5pbmRleE9mKHRhc2spID09PSAtMSkgewogICAgICBidWZmZXIucHVzaCh0YXNrKTsKICAgIH0KICAgIHZvaWQgdGFzawogICAgICAudGhlbigoKSA9PiByZW1vdmUodGFzaykpCiAgICAgIC8vIFVzZSBgdGhlbihudWxsLCByZWplY3Rpb25IYW5kbGVyKWAgcmF0aGVyIHRoYW4gYGNhdGNoKHJlamVjdGlvbkhhbmRsZXIpYCBzbyB0aGF0IHdlIGNhbiB1c2UgYFByb21pc2VMaWtlYAogICAgICAvLyByYXRoZXIgdGhhbiBgUHJvbWlzZWAuIGBQcm9taXNlTGlrZWAgZG9lc24ndCBoYXZlIGEgYC5jYXRjaGAgbWV0aG9kLCBtYWtpbmcgaXRzIHBvbHlmaWxsIHNtYWxsZXIuIChFUzUgZGlkbid0CiAgICAgIC8vIGhhdmUgcHJvbWlzZXMsIHNvIFRTIGhhcyB0byBwb2x5ZmlsbCB3aGVuIGRvd24tY29tcGlsaW5nLikKICAgICAgLnRoZW4obnVsbCwgKCkgPT4KICAgICAgICByZW1vdmUodGFzaykudGhlbihudWxsLCAoKSA9PiB7CiAgICAgICAgICAvLyBXZSBoYXZlIHRvIGFkZCBhbm90aGVyIGNhdGNoIGhlcmUgYmVjYXVzZSBgcmVtb3ZlKClgIHN0YXJ0cyBhIG5ldyBwcm9taXNlIGNoYWluLgogICAgICAgIH0pLAogICAgICApOwogICAgcmV0dXJuIHRhc2s7CiAgfQoKICAvKioKICAgKiBXYWl0IGZvciBhbGwgcHJvbWlzZXMgaW4gdGhlIHF1ZXVlIHRvIHJlc29sdmUgb3IgZm9yIHRpbWVvdXQgdG8gZXhwaXJlLCB3aGljaGV2ZXIgY29tZXMgZmlyc3QuCiAgICoKICAgKiBAcGFyYW0gdGltZW91dCBUaGUgdGltZSwgaW4gbXMsIGFmdGVyIHdoaWNoIHRvIHJlc29sdmUgdG8gYGZhbHNlYCBpZiB0aGUgcXVldWUgaXMgc3RpbGwgbm9uLWVtcHR5LiBQYXNzaW5nIGAwYCAob3IKICAgKiBub3QgcGFzc2luZyBhbnl0aGluZykgd2lsbCBtYWtlIHRoZSBwcm9taXNlIHdhaXQgYXMgbG9uZyBhcyBpdCB0YWtlcyBmb3IgdGhlIHF1ZXVlIHRvIGRyYWluIGJlZm9yZSByZXNvbHZpbmcgdG8KICAgKiBgdHJ1ZWAuCiAgICogQHJldHVybnMgQSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB0byBgdHJ1ZWAgaWYgdGhlIHF1ZXVlIGlzIGFscmVhZHkgZW1wdHkgb3IgZHJhaW5zIGJlZm9yZSB0aGUgdGltZW91dCwgYW5kCiAgICogYGZhbHNlYCBvdGhlcndpc2UKICAgKi8KICBmdW5jdGlvbiBkcmFpbih0aW1lb3V0KSB7CiAgICByZXR1cm4gbmV3IFN5bmNQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgbGV0IGNvdW50ZXIgPSBidWZmZXIubGVuZ3RoOwoKICAgICAgaWYgKCFjb3VudGVyKSB7CiAgICAgICAgcmV0dXJuIHJlc29sdmUodHJ1ZSk7CiAgICAgIH0KCiAgICAgIC8vIHdhaXQgZm9yIGB0aW1lb3V0YCBtcyBhbmQgdGhlbiByZXNvbHZlIHRvIGBmYWxzZWAgKGlmIG5vdCBjYW5jZWxsZWQgZmlyc3QpCiAgICAgIGNvbnN0IGNhcHR1cmVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgIGlmICh0aW1lb3V0ICYmIHRpbWVvdXQgPiAwKSB7CiAgICAgICAgICByZXNvbHZlKGZhbHNlKTsKICAgICAgICB9CiAgICAgIH0sIHRpbWVvdXQpOwoKICAgICAgLy8gaWYgYWxsIHByb21pc2VzIHJlc29sdmUgaW4gdGltZSwgY2FuY2VsIHRoZSB0aW1lciBhbmQgcmVzb2x2ZSB0byBgdHJ1ZWAKICAgICAgYnVmZmVyLmZvckVhY2goaXRlbSA9PiB7CiAgICAgICAgdm9pZCByZXNvbHZlZFN5bmNQcm9taXNlKGl0ZW0pLnRoZW4oKCkgPT4gewogICAgICAgICAgaWYgKCEtLWNvdW50ZXIpIHsKICAgICAgICAgICAgY2xlYXJUaW1lb3V0KGNhcHR1cmVkU2V0VGltZW91dCk7CiAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfSk7CiAgICB9KTsKICB9CgogIHJldHVybiB7CiAgICAkOiBidWZmZXIsCiAgICBhZGQsCiAgICBkcmFpbiwKICB9Owp9CgovKioKICogRG9lcyB0aGlzIGZpbGVuYW1lIGxvb2sgbGlrZSBpdCdzIHBhcnQgb2YgdGhlIGFwcCBjb2RlPwogKi8KZnVuY3Rpb24gZmlsZW5hbWVJc0luQXBwKGZpbGVuYW1lLCBpc05hdGl2ZSA9IGZhbHNlKSB7CiAgY29uc3QgaXNJbnRlcm5hbCA9CiAgICBpc05hdGl2ZSB8fAogICAgKGZpbGVuYW1lICYmCiAgICAgIC8vIEl0J3Mgbm90IGludGVybmFsIGlmIGl0J3MgYW4gYWJzb2x1dGUgbGludXggcGF0aAogICAgICAhZmlsZW5hbWUuc3RhcnRzV2l0aCgnLycpICYmCiAgICAgIC8vIEl0J3Mgbm90IGludGVybmFsIGlmIGl0J3MgYW4gYWJzb2x1dGUgd2luZG93cyBwYXRoCiAgICAgICFmaWxlbmFtZS5tYXRjaCgvXltBLVpdOi8pICYmCiAgICAgIC8vIEl0J3Mgbm90IGludGVybmFsIGlmIHRoZSBwYXRoIGlzIHN0YXJ0aW5nIHdpdGggYSBkb3QKICAgICAgIWZpbGVuYW1lLnN0YXJ0c1dpdGgoJy4nKSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiB0aGUgZnJhbWUgaGFzIGEgcHJvdG9jb2wuIEluIG5vZGUsIHRoaXMgaXMgdXN1YWxseSB0aGUgY2FzZSBpZiB0aGUgZmlsZSBnb3QgcHJlLXByb2Nlc3NlZCB3aXRoIGEgYnVuZGxlciBsaWtlIHdlYnBhY2sKICAgICAgIWZpbGVuYW1lLm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKTsgLy8gU2NoZW1hIGZyb206IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zNjQxNzgyCgogIC8vIGluX2FwcCBpcyBhbGwgdGhhdCdzIG5vdCBhbiBpbnRlcm5hbCBOb2RlIGZ1bmN0aW9uIG9yIGEgbW9kdWxlIHdpdGhpbiBub2RlX21vZHVsZXMKICAvLyBub3RlIHRoYXQgaXNOYXRpdmUgYXBwZWFycyB0byByZXR1cm4gdHJ1ZSBldmVuIGZvciBub2RlIGNvcmUgbGlicmFyaWVzCiAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvcmF2ZW4tbm9kZS9pc3N1ZXMvMTc2CgogIHJldHVybiAhaXNJbnRlcm5hbCAmJiBmaWxlbmFtZSAhPT0gdW5kZWZpbmVkICYmICFmaWxlbmFtZS5pbmNsdWRlcygnbm9kZV9tb2R1bGVzLycpOwp9Cgpjb25zdCBPTkVfU0VDT05EX0lOX01TID0gMTAwMDsKCi8qKgogKiBBIHBhcnRpYWwgZGVmaW5pdGlvbiBvZiB0aGUgW1BlcmZvcm1hbmNlIFdlYiBBUElde0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9QZXJmb3JtYW5jZX0KICogZm9yIGFjY2Vzc2luZyBhIGhpZ2gtcmVzb2x1dGlvbiBtb25vdG9uaWMgY2xvY2suCiAqLwoKLyoqCiAqIFJldHVybnMgYSB0aW1lc3RhbXAgaW4gc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaCB1c2luZyB0aGUgRGF0ZSBBUEkuCiAqCiAqIFRPRE8odjgpOiBSZXR1cm4gdHlwZSBzaG91bGQgYmUgcm91bmRlZC4KICovCmZ1bmN0aW9uIGRhdGVUaW1lc3RhbXBJblNlY29uZHMoKSB7CiAgcmV0dXJuIERhdGUubm93KCkgLyBPTkVfU0VDT05EX0lOX01TOwp9CgovKioKICogUmV0dXJucyBhIHdyYXBwZXIgYXJvdW5kIHRoZSBuYXRpdmUgUGVyZm9ybWFuY2UgQVBJIGJyb3dzZXIgaW1wbGVtZW50YXRpb24sIG9yIHVuZGVmaW5lZCBmb3IgYnJvd3NlcnMgdGhhdCBkbyBub3QKICogc3VwcG9ydCB0aGUgQVBJLgogKgogKiBXcmFwcGluZyB0aGUgbmF0aXZlIEFQSSB3b3JrcyBhcm91bmQgZGlmZmVyZW5jZXMgaW4gYmVoYXZpb3IgZnJvbSBkaWZmZXJlbnQgYnJvd3NlcnMuCiAqLwpmdW5jdGlvbiBjcmVhdGVVbml4VGltZXN0YW1wSW5TZWNvbmRzRnVuYygpIHsKICBjb25zdCB7IHBlcmZvcm1hbmNlIH0gPSBHTE9CQUxfT0JKIDsKICBpZiAoIXBlcmZvcm1hbmNlIHx8ICFwZXJmb3JtYW5jZS5ub3cpIHsKICAgIHJldHVybiBkYXRlVGltZXN0YW1wSW5TZWNvbmRzOwogIH0KCiAgLy8gU29tZSBicm93c2VyIGFuZCBlbnZpcm9ubWVudHMgZG9uJ3QgaGF2ZSBhIHRpbWVPcmlnaW4sIHNvIHdlIGZhbGxiYWNrIHRvCiAgLy8gdXNpbmcgRGF0ZS5ub3coKSB0byBjb21wdXRlIHRoZSBzdGFydGluZyB0aW1lLgogIGNvbnN0IGFwcHJveFN0YXJ0aW5nVGltZU9yaWdpbiA9IERhdGUubm93KCkgLSBwZXJmb3JtYW5jZS5ub3coKTsKICBjb25zdCB0aW1lT3JpZ2luID0gcGVyZm9ybWFuY2UudGltZU9yaWdpbiA9PSB1bmRlZmluZWQgPyBhcHByb3hTdGFydGluZ1RpbWVPcmlnaW4gOiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luOwoKICAvLyBwZXJmb3JtYW5jZS5ub3coKSBpcyBhIG1vbm90b25pYyBjbG9jaywgd2hpY2ggbWVhbnMgaXQgc3RhcnRzIGF0IDAgd2hlbiB0aGUgcHJvY2VzcyBiZWdpbnMuIFRvIGdldCB0aGUgY3VycmVudAogIC8vIHdhbGwgY2xvY2sgdGltZSAoYWN0dWFsIFVOSVggdGltZXN0YW1wKSwgd2UgbmVlZCB0byBhZGQgdGhlIHN0YXJ0aW5nIHRpbWUgb3JpZ2luIGFuZCB0aGUgY3VycmVudCB0aW1lIGVsYXBzZWQuCiAgLy8KICAvLyBUT0RPOiBUaGlzIGRvZXMgbm90IGFjY291bnQgZm9yIHRoZSBjYXNlIHdoZXJlIHRoZSBtb25vdG9uaWMgY2xvY2sgdGhhdCBwb3dlcnMgcGVyZm9ybWFuY2Uubm93KCkgZHJpZnRzIGZyb20gdGhlCiAgLy8gd2FsbCBjbG9jayB0aW1lLCB3aGljaCBjYXVzZXMgdGhlIHJldHVybmVkIHRpbWVzdGFtcCB0byBiZSBpbmFjY3VyYXRlLiBXZSBzaG91bGQgaW52ZXN0aWdhdGUgaG93IHRvIGRldGVjdCBhbmQKICAvLyBjb3JyZWN0IGZvciB0aGlzLgogIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvMjU5MAogIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL21kbi9jb250ZW50L2lzc3Vlcy80NzEzCiAgLy8gU2VlOiBodHRwczovL2Rldi50by9ub2Ftci93aGVuLWEtbWlsbGlzZWNvbmQtaXMtbm90LWEtbWlsbGlzZWNvbmQtM2g2CiAgcmV0dXJuICgpID0+IHsKICAgIHJldHVybiAodGltZU9yaWdpbiArIHBlcmZvcm1hbmNlLm5vdygpKSAvIE9ORV9TRUNPTkRfSU5fTVM7CiAgfTsKfQoKLyoqCiAqIFJldHVybnMgYSB0aW1lc3RhbXAgaW4gc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaCB1c2luZyBlaXRoZXIgdGhlIFBlcmZvcm1hbmNlIG9yIERhdGUgQVBJcywgZGVwZW5kaW5nIG9uIHRoZQogKiBhdmFpbGFiaWxpdHkgb2YgdGhlIFBlcmZvcm1hbmNlIEFQSS4KICoKICogQlVHOiBOb3RlIHRoYXQgYmVjYXVzZSBvZiBob3cgYnJvd3NlcnMgaW1wbGVtZW50IHRoZSBQZXJmb3JtYW5jZSBBUEksIHRoZSBjbG9jayBtaWdodCBzdG9wIHdoZW4gdGhlIGNvbXB1dGVyIGlzCiAqIGFzbGVlcC4gVGhpcyBjcmVhdGVzIGEgc2tldyBiZXR3ZWVuIGBkYXRlVGltZXN0YW1wSW5TZWNvbmRzYCBhbmQgYHRpbWVzdGFtcEluU2Vjb25kc2AuIFRoZQogKiBza2V3IGNhbiBncm93IHRvIGFyYml0cmFyeSBhbW91bnRzIGxpa2UgZGF5cywgd2Vla3Mgb3IgbW9udGhzLgogKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvMjU5MC4KICovCmNvbnN0IHRpbWVzdGFtcEluU2Vjb25kcyA9IGNyZWF0ZVVuaXhUaW1lc3RhbXBJblNlY29uZHNGdW5jKCk7CgovKioKICogVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgc2luY2UgdGhlIFVOSVggZXBvY2guIFRoaXMgdmFsdWUgaXMgb25seSB1c2FibGUgaW4gYSBicm93c2VyLCBhbmQgb25seSB3aGVuIHRoZQogKiBwZXJmb3JtYW5jZSBBUEkgaXMgYXZhaWxhYmxlLgogKi8KKCgpID0+IHsKICAvLyBVbmZvcnR1bmF0ZWx5IGJyb3dzZXJzIG1heSByZXBvcnQgYW4gaW5hY2N1cmF0ZSB0aW1lIG9yaWdpbiBkYXRhLCB0aHJvdWdoIGVpdGhlciBwZXJmb3JtYW5jZS50aW1lT3JpZ2luIG9yCiAgLy8gcGVyZm9ybWFuY2UudGltaW5nLm5hdmlnYXRpb25TdGFydCwgd2hpY2ggcmVzdWx0cyBpbiBwb29yIHJlc3VsdHMgaW4gcGVyZm9ybWFuY2UgZGF0YS4gV2Ugb25seSB0cmVhdCB0aW1lIG9yaWdpbgogIC8vIGRhdGEgYXMgcmVsaWFibGUgaWYgdGhleSBhcmUgd2l0aGluIGEgcmVhc29uYWJsZSB0aHJlc2hvbGQgb2YgdGhlIGN1cnJlbnQgdGltZS4KCiAgY29uc3QgeyBwZXJmb3JtYW5jZSB9ID0gR0xPQkFMX09CSiA7CiAgaWYgKCFwZXJmb3JtYW5jZSB8fCAhcGVyZm9ybWFuY2Uubm93KSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KCiAgY29uc3QgdGhyZXNob2xkID0gMzYwMCAqIDEwMDA7CiAgY29uc3QgcGVyZm9ybWFuY2VOb3cgPSBwZXJmb3JtYW5jZS5ub3coKTsKICBjb25zdCBkYXRlTm93ID0gRGF0ZS5ub3coKTsKCiAgLy8gaWYgdGltZU9yaWdpbiBpc24ndCBhdmFpbGFibGUgc2V0IGRlbHRhIHRvIHRocmVzaG9sZCBzbyBpdCBpc24ndCB1c2VkCiAgY29uc3QgdGltZU9yaWdpbkRlbHRhID0gcGVyZm9ybWFuY2UudGltZU9yaWdpbgogICAgPyBNYXRoLmFicyhwZXJmb3JtYW5jZS50aW1lT3JpZ2luICsgcGVyZm9ybWFuY2VOb3cgLSBkYXRlTm93KQogICAgOiB0aHJlc2hvbGQ7CiAgY29uc3QgdGltZU9yaWdpbklzUmVsaWFibGUgPSB0aW1lT3JpZ2luRGVsdGEgPCB0aHJlc2hvbGQ7CgogIC8vIFdoaWxlIHBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQgaXMgZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luLCBwZXJmb3JtYW5jZS50aW1lT3JpZ2luCiAgLy8gaXMgbm90IGFzIHdpZGVseSBzdXBwb3J0ZWQuIE5hbWVseSwgcGVyZm9ybWFuY2UudGltZU9yaWdpbiBpcyB1bmRlZmluZWQgaW4gU2FmYXJpIGFzIG9mIHdyaXRpbmcuCiAgLy8gQWxzbyBhcyBvZiB3cml0aW5nLCBwZXJmb3JtYW5jZS50aW1pbmcgaXMgbm90IGF2YWlsYWJsZSBpbiBXZWIgV29ya2VycyBpbiBtYWluc3RyZWFtIGJyb3dzZXJzLCBzbyBpdCBpcyBub3QgYWx3YXlzCiAgLy8gYSB2YWxpZCBmYWxsYmFjay4gSW4gdGhlIGFic2VuY2Ugb2YgYW4gaW5pdGlhbCB0aW1lIHByb3ZpZGVkIGJ5IHRoZSBicm93c2VyLCBmYWxsYmFjayB0byB0aGUgY3VycmVudCB0aW1lIGZyb20gdGhlCiAgLy8gRGF0ZSBBUEkuCiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgY29uc3QgbmF2aWdhdGlvblN0YXJ0ID0gcGVyZm9ybWFuY2UudGltaW5nICYmIHBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQ7CiAgY29uc3QgaGFzTmF2aWdhdGlvblN0YXJ0ID0gdHlwZW9mIG5hdmlnYXRpb25TdGFydCA9PT0gJ251bWJlcic7CiAgLy8gaWYgbmF2aWdhdGlvblN0YXJ0IGlzbid0IGF2YWlsYWJsZSBzZXQgZGVsdGEgdG8gdGhyZXNob2xkIHNvIGl0IGlzbid0IHVzZWQKICBjb25zdCBuYXZpZ2F0aW9uU3RhcnREZWx0YSA9IGhhc05hdmlnYXRpb25TdGFydCA/IE1hdGguYWJzKG5hdmlnYXRpb25TdGFydCArIHBlcmZvcm1hbmNlTm93IC0gZGF0ZU5vdykgOiB0aHJlc2hvbGQ7CiAgY29uc3QgbmF2aWdhdGlvblN0YXJ0SXNSZWxpYWJsZSA9IG5hdmlnYXRpb25TdGFydERlbHRhIDwgdGhyZXNob2xkOwoKICBpZiAodGltZU9yaWdpbklzUmVsaWFibGUgfHwgbmF2aWdhdGlvblN0YXJ0SXNSZWxpYWJsZSkgewogICAgLy8gVXNlIHRoZSBtb3JlIHJlbGlhYmxlIHRpbWUgb3JpZ2luCiAgICBpZiAodGltZU9yaWdpbkRlbHRhIDw9IG5hdmlnYXRpb25TdGFydERlbHRhKSB7CiAgICAgIHJldHVybiBwZXJmb3JtYW5jZS50aW1lT3JpZ2luOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5hdmlnYXRpb25TdGFydDsKICAgIH0KICB9CiAgcmV0dXJuIGRhdGVOb3c7Cn0pKCk7CgovKioKICogQ3JlYXRlcyBhbiBlbnZlbG9wZS4KICogTWFrZSBzdXJlIHRvIGFsd2F5cyBleHBsaWNpdGx5IHByb3ZpZGUgdGhlIGdlbmVyaWMgdG8gdGhpcyBmdW5jdGlvbgogKiBzbyB0aGF0IHRoZSBlbnZlbG9wZSB0eXBlcyByZXNvbHZlIGNvcnJlY3RseS4KICovCmZ1bmN0aW9uIGNyZWF0ZUVudmVsb3BlKGhlYWRlcnMsIGl0ZW1zID0gW10pIHsKICByZXR1cm4gW2hlYWRlcnMsIGl0ZW1zXSA7Cn0KCi8qKgogKiBDb252ZW5pZW5jZSBmdW5jdGlvbiB0byBsb29wIHRocm91Z2ggdGhlIGl0ZW1zIGFuZCBpdGVtIHR5cGVzIG9mIGFuIGVudmVsb3BlLgogKiAoVGhpcyBmdW5jdGlvbiB3YXMgbW9zdGx5IGNyZWF0ZWQgYmVjYXVzZSB3b3JraW5nIHdpdGggZW52ZWxvcGUgdHlwZXMgaXMgcGFpbmZ1bCBhdCB0aGUgbW9tZW50KQogKgogKiBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVlLCB0aGUgcmVzdCBvZiB0aGUgaXRlbXMgd2lsbCBiZSBza2lwcGVkLgogKi8KZnVuY3Rpb24gZm9yRWFjaEVudmVsb3BlSXRlbSgKICBlbnZlbG9wZSwKICBjYWxsYmFjaywKKSB7CiAgY29uc3QgZW52ZWxvcGVJdGVtcyA9IGVudmVsb3BlWzFdOwoKICBmb3IgKGNvbnN0IGVudmVsb3BlSXRlbSBvZiBlbnZlbG9wZUl0ZW1zKSB7CiAgICBjb25zdCBlbnZlbG9wZUl0ZW1UeXBlID0gZW52ZWxvcGVJdGVtWzBdLnR5cGU7CiAgICBjb25zdCByZXN1bHQgPSBjYWxsYmFjayhlbnZlbG9wZUl0ZW0sIGVudmVsb3BlSXRlbVR5cGUpOwoKICAgIGlmIChyZXN1bHQpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgfQoKICByZXR1cm4gZmFsc2U7Cn0KCi8qKgogKiBFbmNvZGUgYSBzdHJpbmcgdG8gVVRGOCBhcnJheS4KICovCmZ1bmN0aW9uIGVuY29kZVVURjgoaW5wdXQpIHsKICByZXR1cm4gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGlucHV0KTsKfQoKLyoqCiAqIFNlcmlhbGl6ZXMgYW4gZW52ZWxvcGUuCiAqLwpmdW5jdGlvbiBzZXJpYWxpemVFbnZlbG9wZShlbnZlbG9wZSkgewogIGNvbnN0IFtlbnZIZWFkZXJzLCBpdGVtc10gPSBlbnZlbG9wZTsKCiAgLy8gSW5pdGlhbGx5IHdlIGNvbnN0cnVjdCBvdXIgZW52ZWxvcGUgYXMgYSBzdHJpbmcgYW5kIG9ubHkgY29udmVydCB0byBiaW5hcnkgY2h1bmtzIGlmIHdlIGVuY291bnRlciBiaW5hcnkgZGF0YQogIGxldCBwYXJ0cyA9IEpTT04uc3RyaW5naWZ5KGVudkhlYWRlcnMpOwoKICBmdW5jdGlvbiBhcHBlbmQobmV4dCkgewogICAgaWYgKHR5cGVvZiBwYXJ0cyA9PT0gJ3N0cmluZycpIHsKICAgICAgcGFydHMgPSB0eXBlb2YgbmV4dCA9PT0gJ3N0cmluZycgPyBwYXJ0cyArIG5leHQgOiBbZW5jb2RlVVRGOChwYXJ0cyksIG5leHRdOwogICAgfSBlbHNlIHsKICAgICAgcGFydHMucHVzaCh0eXBlb2YgbmV4dCA9PT0gJ3N0cmluZycgPyBlbmNvZGVVVEY4KG5leHQpIDogbmV4dCk7CiAgICB9CiAgfQoKICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgIGNvbnN0IFtpdGVtSGVhZGVycywgcGF5bG9hZF0gPSBpdGVtOwoKICAgIGFwcGVuZChgXG4ke0pTT04uc3RyaW5naWZ5KGl0ZW1IZWFkZXJzKX1cbmApOwoKICAgIGlmICh0eXBlb2YgcGF5bG9hZCA9PT0gJ3N0cmluZycgfHwgcGF5bG9hZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHsKICAgICAgYXBwZW5kKHBheWxvYWQpOwogICAgfSBlbHNlIHsKICAgICAgbGV0IHN0cmluZ2lmaWVkUGF5bG9hZDsKICAgICAgdHJ5IHsKICAgICAgICBzdHJpbmdpZmllZFBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShwYXlsb2FkKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIC8vIEluIGNhc2UsIGRlc3BpdGUgYWxsIG91ciBlZmZvcnRzIHRvIGtlZXAgYHBheWxvYWRgIGNpcmN1bGFyLWRlcGVuZGVuY3ktZnJlZSwgYEpTT04uc3RyaW5pZnkoKWAgc3RpbGwKICAgICAgICAvLyBmYWlscywgd2UgdHJ5IGFnYWluIGFmdGVyIG5vcm1hbGl6aW5nIGl0IGFnYWluIHdpdGggaW5maW5pdGUgbm9ybWFsaXphdGlvbiBkZXB0aC4gVGhpcyBvZiBjb3Vyc2UgaGFzIGEKICAgICAgICAvLyBwZXJmb3JtYW5jZSBpbXBhY3QgYnV0IGluIHRoaXMgY2FzZSBhIHBlcmZvcm1hbmNlIGhpdCBpcyBiZXR0ZXIgdGhhbiB0aHJvd2luZy4KICAgICAgICBzdHJpbmdpZmllZFBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShub3JtYWxpemUocGF5bG9hZCkpOwogICAgICB9CiAgICAgIGFwcGVuZChzdHJpbmdpZmllZFBheWxvYWQpOwogICAgfQogIH0KCiAgcmV0dXJuIHR5cGVvZiBwYXJ0cyA9PT0gJ3N0cmluZycgPyBwYXJ0cyA6IGNvbmNhdEJ1ZmZlcnMocGFydHMpOwp9CgpmdW5jdGlvbiBjb25jYXRCdWZmZXJzKGJ1ZmZlcnMpIHsKICBjb25zdCB0b3RhbExlbmd0aCA9IGJ1ZmZlcnMucmVkdWNlKChhY2MsIGJ1ZikgPT4gYWNjICsgYnVmLmxlbmd0aCwgMCk7CgogIGNvbnN0IG1lcmdlZCA9IG5ldyBVaW50OEFycmF5KHRvdGFsTGVuZ3RoKTsKICBsZXQgb2Zmc2V0ID0gMDsKICBmb3IgKGNvbnN0IGJ1ZmZlciBvZiBidWZmZXJzKSB7CiAgICBtZXJnZWQuc2V0KGJ1ZmZlciwgb2Zmc2V0KTsKICAgIG9mZnNldCArPSBidWZmZXIubGVuZ3RoOwogIH0KCiAgcmV0dXJuIG1lcmdlZDsKfQoKY29uc3QgSVRFTV9UWVBFX1RPX0RBVEFfQ0FURUdPUllfTUFQID0gewogIHNlc3Npb246ICdzZXNzaW9uJywKICBzZXNzaW9uczogJ3Nlc3Npb24nLAogIGF0dGFjaG1lbnQ6ICdhdHRhY2htZW50JywKICB0cmFuc2FjdGlvbjogJ3RyYW5zYWN0aW9uJywKICBldmVudDogJ2Vycm9yJywKICBjbGllbnRfcmVwb3J0OiAnaW50ZXJuYWwnLAogIHVzZXJfcmVwb3J0OiAnZGVmYXVsdCcsCiAgcHJvZmlsZTogJ3Byb2ZpbGUnLAogIHJlcGxheV9ldmVudDogJ3JlcGxheScsCiAgcmVwbGF5X3JlY29yZGluZzogJ3JlcGxheScsCiAgY2hlY2tfaW46ICdtb25pdG9yJywKICBmZWVkYmFjazogJ2ZlZWRiYWNrJywKICAvLyBUT0RPOiBUaGlzIGlzIGEgdGVtcG9yYXJ5IHdvcmthcm91bmQgdW50aWwgd2UgaGF2ZSBhIHByb3BlciBkYXRhIGNhdGVnb3J5IGZvciBtZXRyaWNzCiAgc3RhdHNkOiAndW5rbm93bicsCn07CgovKioKICogTWFwcyB0aGUgdHlwZSBvZiBhbiBlbnZlbG9wZSBpdGVtIHRvIGEgZGF0YSBjYXRlZ29yeS4KICovCmZ1bmN0aW9uIGVudmVsb3BlSXRlbVR5cGVUb0RhdGFDYXRlZ29yeSh0eXBlKSB7CiAgcmV0dXJuIElURU1fVFlQRV9UT19EQVRBX0NBVEVHT1JZX01BUFt0eXBlXTsKfQoKLyoqIEV4dHJhY3RzIHRoZSBtaW5pbWFsIFNESyBpbmZvIGZyb20gZnJvbSB0aGUgbWV0YWRhdGEgb3IgYW4gZXZlbnRzICovCmZ1bmN0aW9uIGdldFNka01ldGFkYXRhRm9yRW52ZWxvcGVIZWFkZXIobWV0YWRhdGFPckV2ZW50KSB7CiAgaWYgKCFtZXRhZGF0YU9yRXZlbnQgfHwgIW1ldGFkYXRhT3JFdmVudC5zZGspIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBtZXRhZGF0YU9yRXZlbnQuc2RrOwogIHJldHVybiB7IG5hbWUsIHZlcnNpb24gfTsKfQoKLyoqCiAqIENyZWF0ZXMgZXZlbnQgZW52ZWxvcGUgaGVhZGVycywgYmFzZWQgb24gZXZlbnQsIHNkayBpbmZvIGFuZCB0dW5uZWwKICogTm90ZTogVGhpcyBmdW5jdGlvbiB3YXMgZXh0cmFjdGVkIGZyb20gdGhlIGNvcmUgcGFja2FnZSB0byBtYWtlIGl0IGF2YWlsYWJsZSBpbiBSZXBsYXkKICovCmZ1bmN0aW9uIGNyZWF0ZUV2ZW50RW52ZWxvcGVIZWFkZXJzKAogIGV2ZW50LAogIHNka0luZm8sCiAgdHVubmVsLAogIGRzbiwKKSB7CiAgY29uc3QgZHluYW1pY1NhbXBsaW5nQ29udGV4dCA9IGV2ZW50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSAmJiBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEuZHluYW1pY1NhbXBsaW5nQ29udGV4dDsKICByZXR1cm4gewogICAgZXZlbnRfaWQ6IGV2ZW50LmV2ZW50X2lkICwKICAgIHNlbnRfYXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSwKICAgIC4uLihzZGtJbmZvICYmIHsgc2RrOiBzZGtJbmZvIH0pLAogICAgLi4uKCEhdHVubmVsICYmIGRzbiAmJiB7IGRzbjogZHNuVG9TdHJpbmcoZHNuKSB9KSwKICAgIC4uLihkeW5hbWljU2FtcGxpbmdDb250ZXh0ICYmIHsKICAgICAgdHJhY2U6IGRyb3BVbmRlZmluZWRLZXlzKHsgLi4uZHluYW1pY1NhbXBsaW5nQ29udGV4dCB9KSwKICAgIH0pLAogIH07Cn0KCi8vIEludGVudGlvbmFsbHkga2VlcGluZyB0aGUga2V5IGJyb2FkLCBhcyB3ZSBkb24ndCBrbm93IGZvciBzdXJlIHdoYXQgcmF0ZSBsaW1pdCBoZWFkZXJzIGdldCByZXR1cm5lZCBmcm9tIGJhY2tlbmQKCmNvbnN0IERFRkFVTFRfUkVUUllfQUZURVIgPSA2MCAqIDEwMDA7IC8vIDYwIHNlY29uZHMKCi8qKgogKiBFeHRyYWN0cyBSZXRyeS1BZnRlciB2YWx1ZSBmcm9tIHRoZSByZXF1ZXN0IGhlYWRlciBvciByZXR1cm5zIGRlZmF1bHQgdmFsdWUKICogQHBhcmFtIGhlYWRlciBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgJ1JldHJ5LUFmdGVyJyBoZWFkZXIKICogQHBhcmFtIG5vdyBjdXJyZW50IHVuaXggdGltZXN0YW1wCiAqCiAqLwpmdW5jdGlvbiBwYXJzZVJldHJ5QWZ0ZXJIZWFkZXIoaGVhZGVyLCBub3cgPSBEYXRlLm5vdygpKSB7CiAgY29uc3QgaGVhZGVyRGVsYXkgPSBwYXJzZUludChgJHtoZWFkZXJ9YCwgMTApOwogIGlmICghaXNOYU4oaGVhZGVyRGVsYXkpKSB7CiAgICByZXR1cm4gaGVhZGVyRGVsYXkgKiAxMDAwOwogIH0KCiAgY29uc3QgaGVhZGVyRGF0ZSA9IERhdGUucGFyc2UoYCR7aGVhZGVyfWApOwogIGlmICghaXNOYU4oaGVhZGVyRGF0ZSkpIHsKICAgIHJldHVybiBoZWFkZXJEYXRlIC0gbm93OwogIH0KCiAgcmV0dXJuIERFRkFVTFRfUkVUUllfQUZURVI7Cn0KCi8qKgogKiBHZXRzIHRoZSB0aW1lIHRoYXQgdGhlIGdpdmVuIGNhdGVnb3J5IGlzIGRpc2FibGVkIHVudGlsIGZvciByYXRlIGxpbWl0aW5nLgogKiBJbiBjYXNlIG5vIGNhdGVnb3J5LXNwZWNpZmljIGxpbWl0IGlzIHNldCBidXQgYSBnZW5lcmFsIHJhdGUgbGltaXQgYWNyb3NzIGFsbCBjYXRlZ29yaWVzIGlzIGFjdGl2ZSwKICogdGhhdCB0aW1lIGlzIHJldHVybmVkLgogKgogKiBAcmV0dXJuIHRoZSB0aW1lIGluIG1zIHRoYXQgdGhlIGNhdGVnb3J5IGlzIGRpc2FibGVkIHVudGlsIG9yIDAgaWYgdGhlcmUncyBubyBhY3RpdmUgcmF0ZSBsaW1pdC4KICovCmZ1bmN0aW9uIGRpc2FibGVkVW50aWwobGltaXRzLCBjYXRlZ29yeSkgewogIHJldHVybiBsaW1pdHNbY2F0ZWdvcnldIHx8IGxpbWl0cy5hbGwgfHwgMDsKfQoKLyoqCiAqIENoZWNrcyBpZiBhIGNhdGVnb3J5IGlzIHJhdGUgbGltaXRlZAogKi8KZnVuY3Rpb24gaXNSYXRlTGltaXRlZChsaW1pdHMsIGNhdGVnb3J5LCBub3cgPSBEYXRlLm5vdygpKSB7CiAgcmV0dXJuIGRpc2FibGVkVW50aWwobGltaXRzLCBjYXRlZ29yeSkgPiBub3c7Cn0KCi8qKgogKiBVcGRhdGUgcmF0ZWxpbWl0cyBmcm9tIGluY29taW5nIGhlYWRlcnMuCiAqCiAqIEByZXR1cm4gdGhlIHVwZGF0ZWQgUmF0ZUxpbWl0cyBvYmplY3QuCiAqLwpmdW5jdGlvbiB1cGRhdGVSYXRlTGltaXRzKAogIGxpbWl0cywKICB7IHN0YXR1c0NvZGUsIGhlYWRlcnMgfSwKICBub3cgPSBEYXRlLm5vdygpLAopIHsKICBjb25zdCB1cGRhdGVkUmF0ZUxpbWl0cyA9IHsKICAgIC4uLmxpbWl0cywKICB9OwoKICAvLyAiVGhlIG5hbWUgaXMgY2FzZS1pbnNlbnNpdGl2ZS4iCiAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hlYWRlcnMvZ2V0CiAgY29uc3QgcmF0ZUxpbWl0SGVhZGVyID0gaGVhZGVycyAmJiBoZWFkZXJzWyd4LXNlbnRyeS1yYXRlLWxpbWl0cyddOwogIGNvbnN0IHJldHJ5QWZ0ZXJIZWFkZXIgPSBoZWFkZXJzICYmIGhlYWRlcnNbJ3JldHJ5LWFmdGVyJ107CgogIGlmIChyYXRlTGltaXRIZWFkZXIpIHsKICAgIC8qKgogICAgICogcmF0ZSBsaW1pdCBoZWFkZXJzIGFyZSBvZiB0aGUgZm9ybQogICAgICogICAgIDxoZWFkZXI+LDxoZWFkZXI+LC4uCiAgICAgKiB3aGVyZSBlYWNoIDxoZWFkZXI+IGlzIG9mIHRoZSBmb3JtCiAgICAgKiAgICAgPHJldHJ5X2FmdGVyPjogPGNhdGVnb3JpZXM+OiA8c2NvcGU+OiA8cmVhc29uX2NvZGU+CiAgICAgKiB3aGVyZQogICAgICogICAgIDxyZXRyeV9hZnRlcj4gaXMgYSBkZWxheSBpbiBzZWNvbmRzCiAgICAgKiAgICAgPGNhdGVnb3JpZXM+IGlzIHRoZSBldmVudCB0eXBlKHMpIChlcnJvciwgdHJhbnNhY3Rpb24sIGV0YykgYmVpbmcgcmF0ZSBsaW1pdGVkIGFuZCBpcyBvZiB0aGUgZm9ybQogICAgICogICAgICAgICA8Y2F0ZWdvcnk+OzxjYXRlZ29yeT47Li4uCiAgICAgKiAgICAgPHNjb3BlPiBpcyB3aGF0J3MgYmVpbmcgbGltaXRlZCAob3JnLCBwcm9qZWN0LCBvciBrZXkpIC0gaWdub3JlZCBieSBTREsKICAgICAqICAgICA8cmVhc29uX2NvZGU+IGlzIGFuIGFyYml0cmFyeSBzdHJpbmcgbGlrZSAib3JnX3F1b3RhIiAtIGlnbm9yZWQgYnkgU0RLCiAgICAgKi8KICAgIGZvciAoY29uc3QgbGltaXQgb2YgcmF0ZUxpbWl0SGVhZGVyLnRyaW0oKS5zcGxpdCgnLCcpKSB7CiAgICAgIGNvbnN0IFtyZXRyeUFmdGVyLCBjYXRlZ29yaWVzXSA9IGxpbWl0LnNwbGl0KCc6JywgMik7CiAgICAgIGNvbnN0IGhlYWRlckRlbGF5ID0gcGFyc2VJbnQocmV0cnlBZnRlciwgMTApOwogICAgICBjb25zdCBkZWxheSA9ICghaXNOYU4oaGVhZGVyRGVsYXkpID8gaGVhZGVyRGVsYXkgOiA2MCkgKiAxMDAwOyAvLyA2MHNlYyBkZWZhdWx0CiAgICAgIGlmICghY2F0ZWdvcmllcykgewogICAgICAgIHVwZGF0ZWRSYXRlTGltaXRzLmFsbCA9IG5vdyArIGRlbGF5OwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoY29uc3QgY2F0ZWdvcnkgb2YgY2F0ZWdvcmllcy5zcGxpdCgnOycpKSB7CiAgICAgICAgICB1cGRhdGVkUmF0ZUxpbWl0c1tjYXRlZ29yeV0gPSBub3cgKyBkZWxheTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9IGVsc2UgaWYgKHJldHJ5QWZ0ZXJIZWFkZXIpIHsKICAgIHVwZGF0ZWRSYXRlTGltaXRzLmFsbCA9IG5vdyArIHBhcnNlUmV0cnlBZnRlckhlYWRlcihyZXRyeUFmdGVySGVhZGVyLCBub3cpOwogIH0gZWxzZSBpZiAoc3RhdHVzQ29kZSA9PT0gNDI5KSB7CiAgICB1cGRhdGVkUmF0ZUxpbWl0cy5hbGwgPSBub3cgKyA2MCAqIDEwMDA7CiAgfQoKICByZXR1cm4gdXBkYXRlZFJhdGVMaW1pdHM7Cn0KCi8qKgogKiBBIG5vZGUuanMgd2F0Y2hkb2cgdGltZXIKICogQHBhcmFtIHBvbGxJbnRlcnZhbCBUaGUgaW50ZXJ2YWwgdGhhdCB3ZSBleHBlY3QgdG8gZ2V0IHBvbGxlZCBhdAogKiBAcGFyYW0gYW5yVGhyZXNob2xkIFRoZSB0aHJlc2hvbGQgZm9yIHdoZW4gd2UgY29uc2lkZXIgQU5SCiAqIEBwYXJhbSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgdG8gY2FsbCBmb3IgQU5SCiAqIEByZXR1cm5zIEFuIG9iamVjdCB3aXRoIGBwb2xsYCBhbmQgYGVuYWJsZWRgIGZ1bmN0aW9ucyB7QGxpbmsgV2F0Y2hkb2dSZXR1cm59CiAqLwpmdW5jdGlvbiB3YXRjaGRvZ1RpbWVyKAogIGNyZWF0ZVRpbWVyLAogIHBvbGxJbnRlcnZhbCwKICBhbnJUaHJlc2hvbGQsCiAgY2FsbGJhY2ssCikgewogIGNvbnN0IHRpbWVyID0gY3JlYXRlVGltZXIoKTsKICBsZXQgdHJpZ2dlcmVkID0gZmFsc2U7CiAgbGV0IGVuYWJsZWQgPSB0cnVlOwoKICBzZXRJbnRlcnZhbCgoKSA9PiB7CiAgICBjb25zdCBkaWZmTXMgPSB0aW1lci5nZXRUaW1lTXMoKTsKCiAgICBpZiAodHJpZ2dlcmVkID09PSBmYWxzZSAmJiBkaWZmTXMgPiBwb2xsSW50ZXJ2YWwgKyBhbnJUaHJlc2hvbGQpIHsKICAgICAgdHJpZ2dlcmVkID0gdHJ1ZTsKICAgICAgaWYgKGVuYWJsZWQpIHsKICAgICAgICBjYWxsYmFjaygpOwogICAgICB9CiAgICB9CgogICAgaWYgKGRpZmZNcyA8IHBvbGxJbnRlcnZhbCArIGFuclRocmVzaG9sZCkgewogICAgICB0cmlnZ2VyZWQgPSBmYWxzZTsKICAgIH0KICB9LCAyMCk7CgogIHJldHVybiB7CiAgICBwb2xsOiAoKSA9PiB7CiAgICAgIHRpbWVyLnJlc2V0KCk7CiAgICB9LAogICAgZW5hYmxlZDogKHN0YXRlKSA9PiB7CiAgICAgIGVuYWJsZWQgPSBzdGF0ZTsKICAgIH0sCiAgfTsKfQoKLy8gdHlwZXMgY29waWVkIGZyb20gaW5zcGVjdG9yLmQudHMKCi8qKgogKiBDb252ZXJ0cyBEZWJ1Z2dlci5DYWxsRnJhbWUgdG8gU2VudHJ5IFN0YWNrRnJhbWUKICovCmZ1bmN0aW9uIGNhbGxGcmFtZVRvU3RhY2tGcmFtZSgKICBmcmFtZSwKICB1cmwsCiAgZ2V0TW9kdWxlRnJvbUZpbGVuYW1lLAopIHsKICBjb25zdCBmaWxlbmFtZSA9IHVybCA/IHVybC5yZXBsYWNlKC9eZmlsZTpcL1wvLywgJycpIDogdW5kZWZpbmVkOwoKICAvLyBDYWxsRnJhbWUgcm93L2NvbCBhcmUgMCBiYXNlZCwgd2hlcmVhcyBTdGFja0ZyYW1lIGFyZSAxIGJhc2VkCiAgY29uc3QgY29sbm8gPSBmcmFtZS5sb2NhdGlvbi5jb2x1bW5OdW1iZXIgPyBmcmFtZS5sb2NhdGlvbi5jb2x1bW5OdW1iZXIgKyAxIDogdW5kZWZpbmVkOwogIGNvbnN0IGxpbmVubyA9IGZyYW1lLmxvY2F0aW9uLmxpbmVOdW1iZXIgPyBmcmFtZS5sb2NhdGlvbi5saW5lTnVtYmVyICsgMSA6IHVuZGVmaW5lZDsKCiAgcmV0dXJuIGRyb3BVbmRlZmluZWRLZXlzKHsKICAgIGZpbGVuYW1lLAogICAgbW9kdWxlOiBnZXRNb2R1bGVGcm9tRmlsZW5hbWUoZmlsZW5hbWUpLAogICAgZnVuY3Rpb246IGZyYW1lLmZ1bmN0aW9uTmFtZSB8fCBVTktOT1dOX0ZVTkNUSU9OLAogICAgY29sbm8sCiAgICBsaW5lbm8sCiAgICBpbl9hcHA6IGZpbGVuYW1lID8gZmlsZW5hbWVJc0luQXBwKGZpbGVuYW1lKSA6IHVuZGVmaW5lZCwKICB9KTsKfQoKLyoqCiAqIFRoaXMgc2VydmVzIGFzIGEgYnVpbGQgdGltZSBmbGFnIHRoYXQgd2lsbCBiZSB0cnVlIGJ5IGRlZmF1bHQsIGJ1dCBmYWxzZSBpbiBub24tZGVidWcgYnVpbGRzIG9yIGlmIHVzZXJzIHJlcGxhY2UgYF9fU0VOVFJZX0RFQlVHX19gIGluIHRoZWlyIGdlbmVyYXRlZCBjb2RlLgogKgogKiBBVFRFTlRJT046IFRoaXMgY29uc3RhbnQgbXVzdCBuZXZlciBjcm9zcyBwYWNrYWdlIGJvdW5kYXJpZXMgKGkuZS4gYmUgZXhwb3J0ZWQpIHRvIGd1YXJhbnRlZSB0aGF0IGl0IGNhbiBiZSB1c2VkIGZvciB0cmVlIHNoYWtpbmcuCiAqLwpjb25zdCBERUJVR19CVUlMRCA9ICh0eXBlb2YgX19TRU5UUllfREVCVUdfXyA9PT0gJ3VuZGVmaW5lZCcgfHwgX19TRU5UUllfREVCVUdfXyk7CgovKioKICogQ3JlYXRlcyBhIG5ldyBgU2Vzc2lvbmAgb2JqZWN0IGJ5IHNldHRpbmcgY2VydGFpbiBkZWZhdWx0IHBhcmFtZXRlcnMuIElmIG9wdGlvbmFsIEBwYXJhbSBjb250ZXh0CiAqIGlzIHBhc3NlZCwgdGhlIHBhc3NlZCBwcm9wZXJ0aWVzIGFyZSBhcHBsaWVkIHRvIHRoZSBzZXNzaW9uIG9iamVjdC4KICoKICogQHBhcmFtIGNvbnRleHQgKG9wdGlvbmFsKSBhZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gYmUgYXBwbGllZCB0byB0aGUgcmV0dXJuZWQgc2Vzc2lvbiBvYmplY3QKICoKICogQHJldHVybnMgYSBuZXcgYFNlc3Npb25gIG9iamVjdAogKi8KZnVuY3Rpb24gbWFrZVNlc3Npb24oY29udGV4dCkgewogIC8vIEJvdGggdGltZXN0YW1wIGFuZCBzdGFydGVkIGFyZSBpbiBzZWNvbmRzIHNpbmNlIHRoZSBVTklYIGVwb2NoLgogIGNvbnN0IHN0YXJ0aW5nVGltZSA9IHRpbWVzdGFtcEluU2Vjb25kcygpOwoKICBjb25zdCBzZXNzaW9uID0gewogICAgc2lkOiB1dWlkNCgpLAogICAgaW5pdDogdHJ1ZSwKICAgIHRpbWVzdGFtcDogc3RhcnRpbmdUaW1lLAogICAgc3RhcnRlZDogc3RhcnRpbmdUaW1lLAogICAgZHVyYXRpb246IDAsCiAgICBzdGF0dXM6ICdvaycsCiAgICBlcnJvcnM6IDAsCiAgICBpZ25vcmVEdXJhdGlvbjogZmFsc2UsCiAgICB0b0pTT046ICgpID0+IHNlc3Npb25Ub0pTT04oc2Vzc2lvbiksCiAgfTsKCiAgaWYgKGNvbnRleHQpIHsKICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbiwgY29udGV4dCk7CiAgfQoKICByZXR1cm4gc2Vzc2lvbjsKfQoKLyoqCiAqIFVwZGF0ZXMgYSBzZXNzaW9uIG9iamVjdCB3aXRoIHRoZSBwcm9wZXJ0aWVzIHBhc3NlZCBpbiB0aGUgY29udGV4dC4KICoKICogTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gbXV0YXRlcyB0aGUgcGFzc2VkIG9iamVjdCBhbmQgcmV0dXJucyB2b2lkLgogKiAoSGFkIHRvIGRvIHRoaXMgaW5zdGVhZCBvZiByZXR1cm5pbmcgYSBuZXcgYW5kIHVwZGF0ZWQgc2Vzc2lvbiBiZWNhdXNlIGNsb3NpbmcgYW5kIHNlbmRpbmcgYSBzZXNzaW9uCiAqIG1ha2VzIGFuIHVwZGF0ZSB0byB0aGUgc2Vzc2lvbiBhZnRlciBpdCB3YXMgcGFzc2VkIHRvIHRoZSBzZW5kaW5nIGxvZ2ljLgogKiBAc2VlIEJhc2VDbGllbnQuY2FwdHVyZVNlc3Npb24gKQogKgogKiBAcGFyYW0gc2Vzc2lvbiB0aGUgYFNlc3Npb25gIHRvIHVwZGF0ZQogKiBAcGFyYW0gY29udGV4dCB0aGUgYFNlc3Npb25Db250ZXh0YCBob2xkaW5nIHRoZSBwcm9wZXJ0aWVzIHRoYXQgc2hvdWxkIGJlIHVwZGF0ZWQgaW4gQHBhcmFtIHNlc3Npb24KICovCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5CmZ1bmN0aW9uIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbiwgY29udGV4dCA9IHt9KSB7CiAgaWYgKGNvbnRleHQudXNlcikgewogICAgaWYgKCFzZXNzaW9uLmlwQWRkcmVzcyAmJiBjb250ZXh0LnVzZXIuaXBfYWRkcmVzcykgewogICAgICBzZXNzaW9uLmlwQWRkcmVzcyA9IGNvbnRleHQudXNlci5pcF9hZGRyZXNzOwogICAgfQoKICAgIGlmICghc2Vzc2lvbi5kaWQgJiYgIWNvbnRleHQuZGlkKSB7CiAgICAgIHNlc3Npb24uZGlkID0gY29udGV4dC51c2VyLmlkIHx8IGNvbnRleHQudXNlci5lbWFpbCB8fCBjb250ZXh0LnVzZXIudXNlcm5hbWU7CiAgICB9CiAgfQoKICBzZXNzaW9uLnRpbWVzdGFtcCA9IGNvbnRleHQudGltZXN0YW1wIHx8IHRpbWVzdGFtcEluU2Vjb25kcygpOwoKICBpZiAoY29udGV4dC5hYm5vcm1hbF9tZWNoYW5pc20pIHsKICAgIHNlc3Npb24uYWJub3JtYWxfbWVjaGFuaXNtID0gY29udGV4dC5hYm5vcm1hbF9tZWNoYW5pc207CiAgfQoKICBpZiAoY29udGV4dC5pZ25vcmVEdXJhdGlvbikgewogICAgc2Vzc2lvbi5pZ25vcmVEdXJhdGlvbiA9IGNvbnRleHQuaWdub3JlRHVyYXRpb247CiAgfQogIGlmIChjb250ZXh0LnNpZCkgewogICAgLy8gR29vZCBlbm91Z2ggdXVpZCB2YWxpZGF0aW9uLiDigJQgS2FtaWwKICAgIHNlc3Npb24uc2lkID0gY29udGV4dC5zaWQubGVuZ3RoID09PSAzMiA/IGNvbnRleHQuc2lkIDogdXVpZDQoKTsKICB9CiAgaWYgKGNvbnRleHQuaW5pdCAhPT0gdW5kZWZpbmVkKSB7CiAgICBzZXNzaW9uLmluaXQgPSBjb250ZXh0LmluaXQ7CiAgfQogIGlmICghc2Vzc2lvbi5kaWQgJiYgY29udGV4dC5kaWQpIHsKICAgIHNlc3Npb24uZGlkID0gYCR7Y29udGV4dC5kaWR9YDsKICB9CiAgaWYgKHR5cGVvZiBjb250ZXh0LnN0YXJ0ZWQgPT09ICdudW1iZXInKSB7CiAgICBzZXNzaW9uLnN0YXJ0ZWQgPSBjb250ZXh0LnN0YXJ0ZWQ7CiAgfQogIGlmIChzZXNzaW9uLmlnbm9yZUR1cmF0aW9uKSB7CiAgICBzZXNzaW9uLmR1cmF0aW9uID0gdW5kZWZpbmVkOwogIH0gZWxzZSBpZiAodHlwZW9mIGNvbnRleHQuZHVyYXRpb24gPT09ICdudW1iZXInKSB7CiAgICBzZXNzaW9uLmR1cmF0aW9uID0gY29udGV4dC5kdXJhdGlvbjsKICB9IGVsc2UgewogICAgY29uc3QgZHVyYXRpb24gPSBzZXNzaW9uLnRpbWVzdGFtcCAtIHNlc3Npb24uc3RhcnRlZDsKICAgIHNlc3Npb24uZHVyYXRpb24gPSBkdXJhdGlvbiA+PSAwID8gZHVyYXRpb24gOiAwOwogIH0KICBpZiAoY29udGV4dC5yZWxlYXNlKSB7CiAgICBzZXNzaW9uLnJlbGVhc2UgPSBjb250ZXh0LnJlbGVhc2U7CiAgfQogIGlmIChjb250ZXh0LmVudmlyb25tZW50KSB7CiAgICBzZXNzaW9uLmVudmlyb25tZW50ID0gY29udGV4dC5lbnZpcm9ubWVudDsKICB9CiAgaWYgKCFzZXNzaW9uLmlwQWRkcmVzcyAmJiBjb250ZXh0LmlwQWRkcmVzcykgewogICAgc2Vzc2lvbi5pcEFkZHJlc3MgPSBjb250ZXh0LmlwQWRkcmVzczsKICB9CiAgaWYgKCFzZXNzaW9uLnVzZXJBZ2VudCAmJiBjb250ZXh0LnVzZXJBZ2VudCkgewogICAgc2Vzc2lvbi51c2VyQWdlbnQgPSBjb250ZXh0LnVzZXJBZ2VudDsKICB9CiAgaWYgKHR5cGVvZiBjb250ZXh0LmVycm9ycyA9PT0gJ251bWJlcicpIHsKICAgIHNlc3Npb24uZXJyb3JzID0gY29udGV4dC5lcnJvcnM7CiAgfQogIGlmIChjb250ZXh0LnN0YXR1cykgewogICAgc2Vzc2lvbi5zdGF0dXMgPSBjb250ZXh0LnN0YXR1czsKICB9Cn0KCi8qKgogKiBTZXJpYWxpemVzIGEgcGFzc2VkIHNlc3Npb24gb2JqZWN0IHRvIGEgSlNPTiBvYmplY3Qgd2l0aCBhIHNsaWdodGx5IGRpZmZlcmVudCBzdHJ1Y3R1cmUuCiAqIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgdGhlIFNlbnRyeSBiYWNrZW5kIHJlcXVpcmVzIGEgc2xpZ2h0bHkgZGlmZmVyZW50IHNjaGVtYSBvZiBhIHNlc3Npb24KICogdGhhbiB0aGUgb25lIHRoZSBKUyBTREtzIHVzZSBpbnRlcm5hbGx5LgogKgogKiBAcGFyYW0gc2Vzc2lvbiB0aGUgc2Vzc2lvbiB0byBiZSBjb252ZXJ0ZWQKICoKICogQHJldHVybnMgYSBKU09OIG9iamVjdCBvZiB0aGUgcGFzc2VkIHNlc3Npb24KICovCmZ1bmN0aW9uIHNlc3Npb25Ub0pTT04oc2Vzc2lvbikgewogIHJldHVybiBkcm9wVW5kZWZpbmVkS2V5cyh7CiAgICBzaWQ6IGAke3Nlc3Npb24uc2lkfWAsCiAgICBpbml0OiBzZXNzaW9uLmluaXQsCiAgICAvLyBNYWtlIHN1cmUgdGhhdCBzZWMgaXMgY29udmVydGVkIHRvIG1zIGZvciBkYXRlIGNvbnN0cnVjdG9yCiAgICBzdGFydGVkOiBuZXcgRGF0ZShzZXNzaW9uLnN0YXJ0ZWQgKiAxMDAwKS50b0lTT1N0cmluZygpLAogICAgdGltZXN0YW1wOiBuZXcgRGF0ZShzZXNzaW9uLnRpbWVzdGFtcCAqIDEwMDApLnRvSVNPU3RyaW5nKCksCiAgICBzdGF0dXM6IHNlc3Npb24uc3RhdHVzLAogICAgZXJyb3JzOiBzZXNzaW9uLmVycm9ycywKICAgIGRpZDogdHlwZW9mIHNlc3Npb24uZGlkID09PSAnbnVtYmVyJyB8fCB0eXBlb2Ygc2Vzc2lvbi5kaWQgPT09ICdzdHJpbmcnID8gYCR7c2Vzc2lvbi5kaWR9YCA6IHVuZGVmaW5lZCwKICAgIGR1cmF0aW9uOiBzZXNzaW9uLmR1cmF0aW9uLAogICAgYWJub3JtYWxfbWVjaGFuaXNtOiBzZXNzaW9uLmFibm9ybWFsX21lY2hhbmlzbSwKICAgIGF0dHJzOiB7CiAgICAgIHJlbGVhc2U6IHNlc3Npb24ucmVsZWFzZSwKICAgICAgZW52aXJvbm1lbnQ6IHNlc3Npb24uZW52aXJvbm1lbnQsCiAgICAgIGlwX2FkZHJlc3M6IHNlc3Npb24uaXBBZGRyZXNzLAogICAgICB1c2VyX2FnZW50OiBzZXNzaW9uLnVzZXJBZ2VudCwKICAgIH0sCiAgfSk7Cn0KCi8qKgogKiBBcHBseSBTZGtJbmZvIChuYW1lLCB2ZXJzaW9uLCBwYWNrYWdlcywgaW50ZWdyYXRpb25zKSB0byB0aGUgY29ycmVzcG9uZGluZyBldmVudCBrZXkuCiAqIE1lcmdlIHdpdGggZXhpc3RpbmcgZGF0YSBpZiBhbnkuCiAqKi8KZnVuY3Rpb24gZW5oYW5jZUV2ZW50V2l0aFNka0luZm8oZXZlbnQsIHNka0luZm8pIHsKICBpZiAoIXNka0luZm8pIHsKICAgIHJldHVybiBldmVudDsKICB9CiAgZXZlbnQuc2RrID0gZXZlbnQuc2RrIHx8IHt9OwogIGV2ZW50LnNkay5uYW1lID0gZXZlbnQuc2RrLm5hbWUgfHwgc2RrSW5mby5uYW1lOwogIGV2ZW50LnNkay52ZXJzaW9uID0gZXZlbnQuc2RrLnZlcnNpb24gfHwgc2RrSW5mby52ZXJzaW9uOwogIGV2ZW50LnNkay5pbnRlZ3JhdGlvbnMgPSBbLi4uKGV2ZW50LnNkay5pbnRlZ3JhdGlvbnMgfHwgW10pLCAuLi4oc2RrSW5mby5pbnRlZ3JhdGlvbnMgfHwgW10pXTsKICBldmVudC5zZGsucGFja2FnZXMgPSBbLi4uKGV2ZW50LnNkay5wYWNrYWdlcyB8fCBbXSksIC4uLihzZGtJbmZvLnBhY2thZ2VzIHx8IFtdKV07CiAgcmV0dXJuIGV2ZW50Owp9CgovKiogQ3JlYXRlcyBhbiBlbnZlbG9wZSBmcm9tIGEgU2Vzc2lvbiAqLwpmdW5jdGlvbiBjcmVhdGVTZXNzaW9uRW52ZWxvcGUoCiAgc2Vzc2lvbiwKICBkc24sCiAgbWV0YWRhdGEsCiAgdHVubmVsLAopIHsKICBjb25zdCBzZGtJbmZvID0gZ2V0U2RrTWV0YWRhdGFGb3JFbnZlbG9wZUhlYWRlcihtZXRhZGF0YSk7CiAgY29uc3QgZW52ZWxvcGVIZWFkZXJzID0gewogICAgc2VudF9hdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLAogICAgLi4uKHNka0luZm8gJiYgeyBzZGs6IHNka0luZm8gfSksCiAgICAuLi4oISF0dW5uZWwgJiYgZHNuICYmIHsgZHNuOiBkc25Ub1N0cmluZyhkc24pIH0pLAogIH07CgogIGNvbnN0IGVudmVsb3BlSXRlbSA9CiAgICAnYWdncmVnYXRlcycgaW4gc2Vzc2lvbiA/IFt7IHR5cGU6ICdzZXNzaW9ucycgfSwgc2Vzc2lvbl0gOiBbeyB0eXBlOiAnc2Vzc2lvbicgfSwgc2Vzc2lvbi50b0pTT04oKV07CgogIHJldHVybiBjcmVhdGVFbnZlbG9wZShlbnZlbG9wZUhlYWRlcnMsIFtlbnZlbG9wZUl0ZW1dKTsKfQoKLyoqCiAqIENyZWF0ZSBhbiBFbnZlbG9wZSBmcm9tIGFuIGV2ZW50LgogKi8KZnVuY3Rpb24gY3JlYXRlRXZlbnRFbnZlbG9wZSgKICBldmVudCwKICBkc24sCiAgbWV0YWRhdGEsCiAgdHVubmVsLAopIHsKICBjb25zdCBzZGtJbmZvID0gZ2V0U2RrTWV0YWRhdGFGb3JFbnZlbG9wZUhlYWRlcihtZXRhZGF0YSk7CgogIC8qCiAgICBOb3RlOiBEdWUgdG8gVFMsIGV2ZW50LnR5cGUgbWF5IGJlIGByZXBsYXlfZXZlbnRgLCB0aGVvcmV0aWNhbGx5LgogICAgSW4gcHJhY3RpY2UsIHdlIG5ldmVyIGNhbGwgYGNyZWF0ZUV2ZW50RW52ZWxvcGVgIHdpdGggYHJlcGxheV9ldmVudGAgdHlwZSwKICAgIGFuZCB3ZSdkIGhhdmUgdG8gYWRqdXQgYSBsb29vdCBvZiB0eXBlcyB0byBtYWtlIHRoaXMgd29yayBwcm9wZXJseS4KICAgIFdlIHdhbnQgdG8gYXZvaWQgY2FzdGluZyB0aGlzIGFyb3VuZCwgYXMgdGhhdCBjb3VsZCBsZWFkIHRvIGJ1Z3MgKGUuZy4gd2hlbiB3ZSBhZGQgYW5vdGhlciB0eXBlKQogICAgU28gdGhlIHNhZmUgY2hvaWNlIGlzIHRvIHJlYWxseSBndWFyZCBhZ2FpbnN0IHRoZSByZXBsYXlfZXZlbnQgdHlwZSBoZXJlLgogICovCiAgY29uc3QgZXZlbnRUeXBlID0gZXZlbnQudHlwZSAmJiBldmVudC50eXBlICE9PSAncmVwbGF5X2V2ZW50JyA/IGV2ZW50LnR5cGUgOiAnZXZlbnQnOwoKICBlbmhhbmNlRXZlbnRXaXRoU2RrSW5mbyhldmVudCwgbWV0YWRhdGEgJiYgbWV0YWRhdGEuc2RrKTsKCiAgY29uc3QgZW52ZWxvcGVIZWFkZXJzID0gY3JlYXRlRXZlbnRFbnZlbG9wZUhlYWRlcnMoZXZlbnQsIHNka0luZm8sIHR1bm5lbCwgZHNuKTsKCiAgLy8gUHJldmVudCB0aGlzIGRhdGEgKHdoaWNoLCBpZiBpdCBleGlzdHMsIHdhcyB1c2VkIGluIGVhcmxpZXIgc3RlcHMgaW4gdGhlIHByb2Nlc3NpbmcgcGlwZWxpbmUpIGZyb20gYmVpbmcgc2VudCB0bwogIC8vIHNlbnRyeS4gKE5vdGU6IE91ciB1c2Ugb2YgdGhpcyBwcm9wZXJ0eSBjb21lcyBhbmQgZ29lcyB3aXRoIHdoYXRldmVyIHdlIG1pZ2h0IGJlIGRlYnVnZ2luZywgd2hhdGV2ZXIgaGFja3Mgd2UgbWF5CiAgLy8gaGF2ZSB0ZW1wb3JhcmlseSBhZGRlZCwgZXRjLiBFdmVuIGlmIHdlIGRvbid0IGhhcHBlbiB0byBiZSB1c2luZyBpdCBhdCBzb21lIHBvaW50IGluIHRoZSBmdXR1cmUsIGxldCdzIG5vdCBnZXQgcmlkCiAgLy8gb2YgdGhpcyBgZGVsZXRlYCwgbGVzdCB3ZSBtaXNzIHB1dHRpbmcgaXQgYmFjayBpbiB0aGUgbmV4dCB0aW1lIHRoZSBwcm9wZXJ0eSBpcyBpbiB1c2UuKQogIGRlbGV0ZSBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7CgogIGNvbnN0IGV2ZW50SXRlbSA9IFt7IHR5cGU6IGV2ZW50VHlwZSB9LCBldmVudF07CiAgcmV0dXJuIGNyZWF0ZUVudmVsb3BlKGVudmVsb3BlSGVhZGVycywgW2V2ZW50SXRlbV0pOwp9Cgpjb25zdCBTRU5UUllfQVBJX1ZFUlNJT04gPSAnNyc7CgovKiogUmV0dXJucyB0aGUgcHJlZml4IHRvIGNvbnN0cnVjdCBTZW50cnkgaW5nZXN0aW9uIEFQSSBlbmRwb2ludHMuICovCmZ1bmN0aW9uIGdldEJhc2VBcGlFbmRwb2ludChkc24pIHsKICBjb25zdCBwcm90b2NvbCA9IGRzbi5wcm90b2NvbCA/IGAke2Rzbi5wcm90b2NvbH06YCA6ICcnOwogIGNvbnN0IHBvcnQgPSBkc24ucG9ydCA/IGA6JHtkc24ucG9ydH1gIDogJyc7CiAgcmV0dXJuIGAke3Byb3RvY29sfS8vJHtkc24uaG9zdH0ke3BvcnR9JHtkc24ucGF0aCA/IGAvJHtkc24ucGF0aH1gIDogJyd9L2FwaS9gOwp9CgovKiogUmV0dXJucyB0aGUgaW5nZXN0IEFQSSBlbmRwb2ludCBmb3IgdGFyZ2V0LiAqLwpmdW5jdGlvbiBfZ2V0SW5nZXN0RW5kcG9pbnQoZHNuKSB7CiAgcmV0dXJuIGAke2dldEJhc2VBcGlFbmRwb2ludChkc24pfSR7ZHNuLnByb2plY3RJZH0vZW52ZWxvcGUvYDsKfQoKLyoqIFJldHVybnMgYSBVUkwtZW5jb2RlZCBzdHJpbmcgd2l0aCBhdXRoIGNvbmZpZyBzdWl0YWJsZSBmb3IgYSBxdWVyeSBzdHJpbmcuICovCmZ1bmN0aW9uIF9lbmNvZGVkQXV0aChkc24sIHNka0luZm8pIHsKICByZXR1cm4gdXJsRW5jb2RlKHsKICAgIC8vIFdlIHNlbmQgb25seSB0aGUgbWluaW11bSBzZXQgb2YgcmVxdWlyZWQgaW5mb3JtYXRpb24uIFNlZQogICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvMjU3Mi4KICAgIHNlbnRyeV9rZXk6IGRzbi5wdWJsaWNLZXksCiAgICBzZW50cnlfdmVyc2lvbjogU0VOVFJZX0FQSV9WRVJTSU9OLAogICAgLi4uKHNka0luZm8gJiYgeyBzZW50cnlfY2xpZW50OiBgJHtzZGtJbmZvLm5hbWV9LyR7c2RrSW5mby52ZXJzaW9ufWAgfSksCiAgfSk7Cn0KCi8qKgogKiBSZXR1cm5zIHRoZSBlbnZlbG9wZSBlbmRwb2ludCBVUkwgd2l0aCBhdXRoIGluIHRoZSBxdWVyeSBzdHJpbmcuCiAqCiAqIFNlbmRpbmcgYXV0aCBhcyBwYXJ0IG9mIHRoZSBxdWVyeSBzdHJpbmcgYW5kIG5vdCBhcyBjdXN0b20gSFRUUCBoZWFkZXJzIGF2b2lkcyBDT1JTIHByZWZsaWdodCByZXF1ZXN0cy4KICovCmZ1bmN0aW9uIGdldEVudmVsb3BlRW5kcG9pbnRXaXRoVXJsRW5jb2RlZEF1dGgoCiAgZHNuLAogIC8vIFRPRE8gKHY4KTogUmVtb3ZlIGB0dW5uZWxPck9wdGlvbnNgIGluIGZhdm9yIG9mIGBvcHRpb25zYCwgYW5kIHVzZSB0aGUgc3Vic3RpdHV0ZSBjb2RlIGJlbG93CiAgLy8gb3B0aW9uczogQ2xpZW50T3B0aW9ucyA9IHt9IGFzIENsaWVudE9wdGlvbnMsCiAgdHVubmVsT3JPcHRpb25zID0ge30gLAopIHsKICAvLyBUT0RPICh2OCk6IFVzZSB0aGlzIGNvZGUgaW5zdGVhZAogIC8vIGNvbnN0IHsgdHVubmVsLCBfbWV0YWRhdGEgPSB7fSB9ID0gb3B0aW9uczsKICAvLyByZXR1cm4gdHVubmVsID8gdHVubmVsIDogYCR7X2dldEluZ2VzdEVuZHBvaW50KGRzbil9PyR7X2VuY29kZWRBdXRoKGRzbiwgX21ldGFkYXRhLnNkayl9YDsKCiAgY29uc3QgdHVubmVsID0gdHlwZW9mIHR1bm5lbE9yT3B0aW9ucyA9PT0gJ3N0cmluZycgPyB0dW5uZWxPck9wdGlvbnMgOiB0dW5uZWxPck9wdGlvbnMudHVubmVsOwogIGNvbnN0IHNka0luZm8gPQogICAgdHlwZW9mIHR1bm5lbE9yT3B0aW9ucyA9PT0gJ3N0cmluZycgfHwgIXR1bm5lbE9yT3B0aW9ucy5fbWV0YWRhdGEgPyB1bmRlZmluZWQgOiB0dW5uZWxPck9wdGlvbnMuX21ldGFkYXRhLnNkazsKCiAgcmV0dXJuIHR1bm5lbCA/IHR1bm5lbCA6IGAke19nZXRJbmdlc3RFbmRwb2ludChkc24pfT8ke19lbmNvZGVkQXV0aChkc24sIHNka0luZm8pfWA7Cn0KCmNvbnN0IERFRkFVTFRfVFJBTlNQT1JUX0JVRkZFUl9TSVpFID0gMzA7CgovKioKICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBhIFNlbnRyeSBgVHJhbnNwb3J0YAogKgogKiBAcGFyYW0gb3B0aW9ucwogKiBAcGFyYW0gbWFrZVJlcXVlc3QKICovCmZ1bmN0aW9uIGNyZWF0ZVRyYW5zcG9ydCgKICBvcHRpb25zLAogIG1ha2VSZXF1ZXN0LAogIGJ1ZmZlciA9IG1ha2VQcm9taXNlQnVmZmVyKAogICAgb3B0aW9ucy5idWZmZXJTaXplIHx8IERFRkFVTFRfVFJBTlNQT1JUX0JVRkZFUl9TSVpFLAogICksCikgewogIGxldCByYXRlTGltaXRzID0ge307CiAgY29uc3QgZmx1c2ggPSAodGltZW91dCkgPT4gYnVmZmVyLmRyYWluKHRpbWVvdXQpOwoKICBmdW5jdGlvbiBzZW5kKGVudmVsb3BlKSB7CiAgICBjb25zdCBmaWx0ZXJlZEVudmVsb3BlSXRlbXMgPSBbXTsKCiAgICAvLyBEcm9wIHJhdGUgbGltaXRlZCBpdGVtcyBmcm9tIGVudmVsb3BlCiAgICBmb3JFYWNoRW52ZWxvcGVJdGVtKGVudmVsb3BlLCAoaXRlbSwgdHlwZSkgPT4gewogICAgICBjb25zdCBlbnZlbG9wZUl0ZW1EYXRhQ2F0ZWdvcnkgPSBlbnZlbG9wZUl0ZW1UeXBlVG9EYXRhQ2F0ZWdvcnkodHlwZSk7CiAgICAgIGlmIChpc1JhdGVMaW1pdGVkKHJhdGVMaW1pdHMsIGVudmVsb3BlSXRlbURhdGFDYXRlZ29yeSkpIHsKICAgICAgICBjb25zdCBldmVudCA9IGdldEV2ZW50Rm9yRW52ZWxvcGVJdGVtKGl0ZW0sIHR5cGUpOwogICAgICAgIG9wdGlvbnMucmVjb3JkRHJvcHBlZEV2ZW50KCdyYXRlbGltaXRfYmFja29mZicsIGVudmVsb3BlSXRlbURhdGFDYXRlZ29yeSwgZXZlbnQpOwogICAgICB9IGVsc2UgewogICAgICAgIGZpbHRlcmVkRW52ZWxvcGVJdGVtcy5wdXNoKGl0ZW0pOwogICAgICB9CiAgICB9KTsKCiAgICAvLyBTa2lwIHNlbmRpbmcgaWYgZW52ZWxvcGUgaXMgZW1wdHkgYWZ0ZXIgZmlsdGVyaW5nIG91dCByYXRlIGxpbWl0ZWQgZXZlbnRzCiAgICBpZiAoZmlsdGVyZWRFbnZlbG9wZUl0ZW1zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gcmVzb2x2ZWRTeW5jUHJvbWlzZSh7fSk7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkKICAgIGNvbnN0IGZpbHRlcmVkRW52ZWxvcGUgPSBjcmVhdGVFbnZlbG9wZShlbnZlbG9wZVswXSwgZmlsdGVyZWRFbnZlbG9wZUl0ZW1zICk7CgogICAgLy8gQ3JlYXRlcyBjbGllbnQgcmVwb3J0IGZvciBlYWNoIGl0ZW0gaW4gYW4gZW52ZWxvcGUKICAgIGNvbnN0IHJlY29yZEVudmVsb3BlTG9zcyA9IChyZWFzb24pID0+IHsKICAgICAgZm9yRWFjaEVudmVsb3BlSXRlbShmaWx0ZXJlZEVudmVsb3BlLCAoaXRlbSwgdHlwZSkgPT4gewogICAgICAgIGNvbnN0IGV2ZW50ID0gZ2V0RXZlbnRGb3JFbnZlbG9wZUl0ZW0oaXRlbSwgdHlwZSk7CiAgICAgICAgb3B0aW9ucy5yZWNvcmREcm9wcGVkRXZlbnQocmVhc29uLCBlbnZlbG9wZUl0ZW1UeXBlVG9EYXRhQ2F0ZWdvcnkodHlwZSksIGV2ZW50KTsKICAgICAgfSk7CiAgICB9OwoKICAgIGNvbnN0IHJlcXVlc3RUYXNrID0gKCkgPT4KICAgICAgbWFrZVJlcXVlc3QoeyBib2R5OiBzZXJpYWxpemVFbnZlbG9wZShmaWx0ZXJlZEVudmVsb3BlKSB9KS50aGVuKAogICAgICAgIHJlc3BvbnNlID0+IHsKICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gdGhyb3cgb24gTk9LIHJlc3BvbnNlcywgYnV0IHdlIHdhbnQgdG8gYXQgbGVhc3QgbG9nIHRoZW0KICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlICE9PSB1bmRlZmluZWQgJiYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPCAyMDAgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSA+PSAzMDApKSB7CiAgICAgICAgICAgIERFQlVHX0JVSUxEICYmIGxvZ2dlci53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHtyZXNwb25zZS5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApOwogICAgICAgICAgfQoKICAgICAgICAgIHJhdGVMaW1pdHMgPSB1cGRhdGVSYXRlTGltaXRzKHJhdGVMaW1pdHMsIHJlc3BvbnNlKTsKICAgICAgICAgIHJldHVybiByZXNwb25zZTsKICAgICAgICB9LAogICAgICAgIGVycm9yID0+IHsKICAgICAgICAgIHJlY29yZEVudmVsb3BlTG9zcygnbmV0d29ya19lcnJvcicpOwogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSwKICAgICAgKTsKCiAgICByZXR1cm4gYnVmZmVyLmFkZChyZXF1ZXN0VGFzaykudGhlbigKICAgICAgcmVzdWx0ID0+IHJlc3VsdCwKICAgICAgZXJyb3IgPT4gewogICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbnRyeUVycm9yKSB7CiAgICAgICAgICBERUJVR19CVUlMRCAmJiBsb2dnZXIuZXJyb3IoJ1NraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLicpOwogICAgICAgICAgcmVjb3JkRW52ZWxvcGVMb3NzKCdxdWV1ZV9vdmVyZmxvdycpOwogICAgICAgICAgcmV0dXJuIHJlc29sdmVkU3luY1Byb21pc2Uoe30pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICB9CiAgICAgIH0sCiAgICApOwogIH0KCiAgcmV0dXJuIHsKICAgIHNlbmQsCiAgICBmbHVzaCwKICB9Owp9CgpmdW5jdGlvbiBnZXRFdmVudEZvckVudmVsb3BlSXRlbShpdGVtLCB0eXBlKSB7CiAgaWYgKHR5cGUgIT09ICdldmVudCcgJiYgdHlwZSAhPT0gJ3RyYW5zYWN0aW9uJykgewogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CgogIHJldHVybiBBcnJheS5pc0FycmF5KGl0ZW0pID8gKGl0ZW0gKVsxXSA6IHVuZGVmaW5lZDsKfQoKZnVuY3Rpb24gX251bGxpc2hDb2FsZXNjZSQyKGxocywgcmhzRm4pIHsgaWYgKGxocyAhPSBudWxsKSB7IHJldHVybiBsaHM7IH0gZWxzZSB7IHJldHVybiByaHNGbigpOyB9IH0vKioKICogVGhpcyBjb2RlIHdhcyBvcmlnaW5hbGx5IGZvcmtlZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9Ub29UYWxsTmF0ZS9wcm94eS1hZ2VudHMvdHJlZS9iMTMzMjk1ZmQxNmY2NDc1NTc4YjZiMTViZDliNGUzM2VjYjBkMGI3CiAqIFdpdGggdGhlIGZvbGxvd2luZyBsaWNlbmNlOgogKgogKiAoVGhlIE1JVCBMaWNlbnNlKQogKgogKiBDb3B5cmlnaHQgKGMpIDIwMTMgTmF0aGFuIFJhamxpY2ggPG5hdGhhbkB0b290YWxsbmF0ZS5uZXQ+KgogKgogKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcKICogYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlCiAqICdTb2Z0d2FyZScpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcKICogd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLAogKiBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8KICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvCiAqIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoqCiAqCiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlCiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLioKICoKICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICdBUyBJUycsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsCiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRgogKiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuCiAqIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZCiAqIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsCiAqIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFCiAqIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgogKi8KCmNvbnN0IElOVEVSTkFMID0gU3ltYm9sKCdBZ2VudEJhc2VJbnRlcm5hbFN0YXRlJyk7CgpjbGFzcyBBZ2VudCBleHRlbmRzIGh0dHAuQWdlbnQgewoKICAvLyBTZXQgYnkgYGh0dHAuQWdlbnRgIC0gbWlzc2luZyBmcm9tIGBAdHlwZXMvbm9kZWAKCiAgY29uc3RydWN0b3Iob3B0cykgewogICAgc3VwZXIob3B0cyk7CiAgICB0aGlzW0lOVEVSTkFMXSA9IHt9OwogIH0KCiAgLyoqCiAgICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBpcyBhbiBgaHR0cGAgb3IgYGh0dHBzYCByZXF1ZXN0LgogICAqLwogIGlzU2VjdXJlRW5kcG9pbnQob3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMpIHsKICAgICAgLy8gRmlyc3QgY2hlY2sgdGhlIGBzZWN1cmVFbmRwb2ludGAgcHJvcGVydHkgZXhwbGljaXRseSwgc2luY2UgdGhpcwogICAgICAvLyBtZWFucyB0aGF0IGEgcGFyZW50IGBBZ2VudGAgaXMgInBhc3NpbmcgdGhyb3VnaCIgdG8gdGhpcyBpbnN0YW5jZS4KICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnksIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtbWVtYmVyLWFjY2VzcwogICAgICBpZiAodHlwZW9mIChvcHRpb25zICkuc2VjdXJlRW5kcG9pbnQgPT09ICdib29sZWFuJykgewogICAgICAgIHJldHVybiBvcHRpb25zLnNlY3VyZUVuZHBvaW50OwogICAgICB9CgogICAgICAvLyBJZiBubyBleHBsaWNpdCBgc2VjdXJlYCBlbmRwb2ludCwgY2hlY2sgaWYgYHByb3RvY29sYCBwcm9wZXJ0eSBpcwogICAgICAvLyBzZXQuIFRoaXMgd2lsbCB1c3VhbGx5IGJlIHRoZSBjYXNlIHNpbmNlIHVzaW5nIGEgZnVsbCBzdHJpbmcgVVJMCiAgICAgIC8vIG9yIGBVUkxgIGluc3RhbmNlIHNob3VsZCBiZSB0aGUgbW9zdCBjb21tb24gdXNhZ2UuCiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wcm90b2NvbCA9PT0gJ3N0cmluZycpIHsKICAgICAgICByZXR1cm4gb3B0aW9ucy5wcm90b2NvbCA9PT0gJ2h0dHBzOic7CiAgICAgIH0KICAgIH0KCiAgICAvLyBGaW5hbGx5LCBpZiBubyBgcHJvdG9jb2xgIHByb3BlcnR5IHdhcyBzZXQsIHRoZW4gZmFsbCBiYWNrIHRvCiAgICAvLyBjaGVja2luZyB0aGUgc3RhY2sgdHJhY2Ugb2YgdGhlIGN1cnJlbnQgY2FsbCBzdGFjaywgYW5kIHRyeSB0bwogICAgLy8gZGV0ZWN0IHRoZSAiaHR0cHMiIG1vZHVsZS4KICAgIGNvbnN0IHsgc3RhY2sgfSA9IG5ldyBFcnJvcigpOwogICAgaWYgKHR5cGVvZiBzdGFjayAhPT0gJ3N0cmluZycpIHJldHVybiBmYWxzZTsKICAgIHJldHVybiBzdGFjay5zcGxpdCgnXG4nKS5zb21lKGwgPT4gbC5pbmRleE9mKCcoaHR0cHMuanM6JykgIT09IC0xIHx8IGwuaW5kZXhPZignbm9kZTpodHRwczonKSAhPT0gLTEpOwogIH0KCiAgY3JlYXRlU29ja2V0KHJlcSwgb3B0aW9ucywgY2IpIHsKICAgIGNvbnN0IGNvbm5lY3RPcHRzID0gewogICAgICAuLi5vcHRpb25zLAogICAgICBzZWN1cmVFbmRwb2ludDogdGhpcy5pc1NlY3VyZUVuZHBvaW50KG9wdGlvbnMpLAogICAgfTsKICAgIFByb21pc2UucmVzb2x2ZSgpCiAgICAgIC50aGVuKCgpID0+IHRoaXMuY29ubmVjdChyZXEsIGNvbm5lY3RPcHRzKSkKICAgICAgLnRoZW4oc29ja2V0ID0+IHsKICAgICAgICBpZiAoc29ja2V0IGluc3RhbmNlb2YgaHR0cC5BZ2VudCkgewogICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBgYWRkUmVxdWVzdCgpYCBpc24ndCBkZWZpbmVkIGluIGBAdHlwZXMvbm9kZWAKICAgICAgICAgIHJldHVybiBzb2NrZXQuYWRkUmVxdWVzdChyZXEsIGNvbm5lY3RPcHRzKTsKICAgICAgICB9CiAgICAgICAgdGhpc1tJTlRFUk5BTF0uY3VycmVudFNvY2tldCA9IHNvY2tldDsKICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGBjcmVhdGVTb2NrZXQoKWAgaXNuJ3QgZGVmaW5lZCBpbiBgQHR5cGVzL25vZGVgCiAgICAgICAgc3VwZXIuY3JlYXRlU29ja2V0KHJlcSwgb3B0aW9ucywgY2IpOwogICAgICB9LCBjYik7CiAgfQoKICBjcmVhdGVDb25uZWN0aW9uKCkgewogICAgY29uc3Qgc29ja2V0ID0gdGhpc1tJTlRFUk5BTF0uY3VycmVudFNvY2tldDsKICAgIHRoaXNbSU5URVJOQUxdLmN1cnJlbnRTb2NrZXQgPSB1bmRlZmluZWQ7CiAgICBpZiAoIXNvY2tldCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uJyk7CiAgICB9CiAgICByZXR1cm4gc29ja2V0OwogIH0KCiAgZ2V0IGRlZmF1bHRQb3J0KCkgewogICAgcmV0dXJuIF9udWxsaXNoQ29hbGVzY2UkMih0aGlzW0lOVEVSTkFMXS5kZWZhdWx0UG9ydCwgKCkgPT4gKCAodGhpcy5wcm90b2NvbCA9PT0gJ2h0dHBzOicgPyA0NDMgOiA4MCkpKTsKICB9CgogIHNldCBkZWZhdWx0UG9ydCh2KSB7CiAgICBpZiAodGhpc1tJTlRFUk5BTF0pIHsKICAgICAgdGhpc1tJTlRFUk5BTF0uZGVmYXVsdFBvcnQgPSB2OwogICAgfQogIH0KCiAgZ2V0IHByb3RvY29sKCkgewogICAgcmV0dXJuIF9udWxsaXNoQ29hbGVzY2UkMih0aGlzW0lOVEVSTkFMXS5wcm90b2NvbCwgKCkgPT4gKCAodGhpcy5pc1NlY3VyZUVuZHBvaW50KCkgPyAnaHR0cHM6JyA6ICdodHRwOicpKSk7CiAgfQoKICBzZXQgcHJvdG9jb2wodikgewogICAgaWYgKHRoaXNbSU5URVJOQUxdKSB7CiAgICAgIHRoaXNbSU5URVJOQUxdLnByb3RvY29sID0gdjsKICAgIH0KICB9Cn0KCmZ1bmN0aW9uIGRlYnVnJDEoLi4uYXJncykgewogIGxvZ2dlci5sb2coJ1todHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0nLCAuLi5hcmdzKTsKfQoKZnVuY3Rpb24gcGFyc2VQcm94eVJlc3BvbnNlKHNvY2tldCkgewogIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAvLyB3ZSBuZWVkIHRvIGJ1ZmZlciBhbnkgSFRUUCB0cmFmZmljIHRoYXQgaGFwcGVucyB3aXRoIHRoZSBwcm94eSBiZWZvcmUgd2UgZ2V0CiAgICAvLyB0aGUgQ09OTkVDVCByZXNwb25zZSwgc28gdGhhdCBpZiB0aGUgcmVzcG9uc2UgaXMgYW55dGhpbmcgb3RoZXIgdGhhbiBhbiAiMjAwIgogICAgLy8gcmVzcG9uc2UgY29kZSwgdGhlbiB3ZSBjYW4gcmUtcGxheSB0aGUgImRhdGEiIGV2ZW50cyBvbiB0aGUgc29ja2V0IG9uY2UgdGhlCiAgICAvLyBIVFRQIHBhcnNlciBpcyBob29rZWQgdXAuLi4KICAgIGxldCBidWZmZXJzTGVuZ3RoID0gMDsKICAgIGNvbnN0IGJ1ZmZlcnMgPSBbXTsKCiAgICBmdW5jdGlvbiByZWFkKCkgewogICAgICBjb25zdCBiID0gc29ja2V0LnJlYWQoKTsKICAgICAgaWYgKGIpIG9uZGF0YShiKTsKICAgICAgZWxzZSBzb2NrZXQub25jZSgncmVhZGFibGUnLCByZWFkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjbGVhbnVwKCkgewogICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ2VuZCcsIG9uZW5kKTsKICAgICAgc29ja2V0LnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIG9uZXJyb3IpOwogICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ3JlYWRhYmxlJywgcmVhZCk7CiAgICB9CgogICAgZnVuY3Rpb24gb25lbmQoKSB7CiAgICAgIGNsZWFudXAoKTsKICAgICAgZGVidWckMSgnb25lbmQnKTsKICAgICAgcmVqZWN0KG5ldyBFcnJvcignUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UnKSk7CiAgICB9CgogICAgZnVuY3Rpb24gb25lcnJvcihlcnIpIHsKICAgICAgY2xlYW51cCgpOwogICAgICBkZWJ1ZyQxKCdvbmVycm9yICVvJywgZXJyKTsKICAgICAgcmVqZWN0KGVycik7CiAgICB9CgogICAgZnVuY3Rpb24gb25kYXRhKGIpIHsKICAgICAgYnVmZmVycy5wdXNoKGIpOwogICAgICBidWZmZXJzTGVuZ3RoICs9IGIubGVuZ3RoOwoKICAgICAgY29uc3QgYnVmZmVyZWQgPSBCdWZmZXIuY29uY2F0KGJ1ZmZlcnMsIGJ1ZmZlcnNMZW5ndGgpOwogICAgICBjb25zdCBlbmRPZkhlYWRlcnMgPSBidWZmZXJlZC5pbmRleE9mKCdcclxuXHJcbicpOwoKICAgICAgaWYgKGVuZE9mSGVhZGVycyA9PT0gLTEpIHsKICAgICAgICAvLyBrZWVwIGJ1ZmZlcmluZwogICAgICAgIGRlYnVnJDEoJ2hhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uJyk7CiAgICAgICAgcmVhZCgpOwogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgY29uc3QgaGVhZGVyUGFydHMgPSBidWZmZXJlZC5zbGljZSgwLCBlbmRPZkhlYWRlcnMpLnRvU3RyaW5nKCdhc2NpaScpLnNwbGl0KCdcclxuJyk7CiAgICAgIGNvbnN0IGZpcnN0TGluZSA9IGhlYWRlclBhcnRzLnNoaWZ0KCk7CiAgICAgIGlmICghZmlyc3RMaW5lKSB7CiAgICAgICAgc29ja2V0LmRlc3Ryb3koKTsKICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignTm8gaGVhZGVyIHJlY2VpdmVkIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZScpKTsKICAgICAgfQogICAgICBjb25zdCBmaXJzdExpbmVQYXJ0cyA9IGZpcnN0TGluZS5zcGxpdCgnICcpOwogICAgICBjb25zdCBzdGF0dXNDb2RlID0gK2ZpcnN0TGluZVBhcnRzWzFdOwogICAgICBjb25zdCBzdGF0dXNUZXh0ID0gZmlyc3RMaW5lUGFydHMuc2xpY2UoMikuam9pbignICcpOwogICAgICBjb25zdCBoZWFkZXJzID0ge307CiAgICAgIGZvciAoY29uc3QgaGVhZGVyIG9mIGhlYWRlclBhcnRzKSB7CiAgICAgICAgaWYgKCFoZWFkZXIpIGNvbnRpbnVlOwogICAgICAgIGNvbnN0IGZpcnN0Q29sb24gPSBoZWFkZXIuaW5kZXhPZignOicpOwogICAgICAgIGlmIChmaXJzdENvbG9uID09PSAtMSkgewogICAgICAgICAgc29ja2V0LmRlc3Ryb3koKTsKICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke2hlYWRlcn0iYCkpOwogICAgICAgIH0KICAgICAgICBjb25zdCBrZXkgPSBoZWFkZXIuc2xpY2UoMCwgZmlyc3RDb2xvbikudG9Mb3dlckNhc2UoKTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGhlYWRlci5zbGljZShmaXJzdENvbG9uICsgMSkudHJpbVN0YXJ0KCk7CiAgICAgICAgY29uc3QgY3VycmVudCA9IGhlYWRlcnNba2V5XTsKICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnQgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgICBoZWFkZXJzW2tleV0gPSBbY3VycmVudCwgdmFsdWVdOwogICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50KSkgewogICAgICAgICAgY3VycmVudC5wdXNoKHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaGVhZGVyc1trZXldID0gdmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGRlYnVnJDEoJ2dvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvJywgZmlyc3RMaW5lLCBoZWFkZXJzKTsKICAgICAgY2xlYW51cCgpOwogICAgICByZXNvbHZlKHsKICAgICAgICBjb25uZWN0OiB7CiAgICAgICAgICBzdGF0dXNDb2RlLAogICAgICAgICAgc3RhdHVzVGV4dCwKICAgICAgICAgIGhlYWRlcnMsCiAgICAgICAgfSwKICAgICAgICBidWZmZXJlZCwKICAgICAgfSk7CiAgICB9CgogICAgc29ja2V0Lm9uKCdlcnJvcicsIG9uZXJyb3IpOwogICAgc29ja2V0Lm9uKCdlbmQnLCBvbmVuZCk7CgogICAgcmVhZCgpOwogIH0pOwp9CgpmdW5jdGlvbiBfbnVsbGlzaENvYWxlc2NlJDEobGhzLCByaHNGbikgeyBpZiAobGhzICE9IG51bGwpIHsgcmV0dXJuIGxoczsgfSBlbHNlIHsgcmV0dXJuIHJoc0ZuKCk7IH0gfSBmdW5jdGlvbiBfb3B0aW9uYWxDaGFpbiQxKG9wcykgeyBsZXQgbGFzdEFjY2Vzc0xIUyA9IHVuZGVmaW5lZDsgbGV0IHZhbHVlID0gb3BzWzBdOyBsZXQgaSA9IDE7IHdoaWxlIChpIDwgb3BzLmxlbmd0aCkgeyBjb25zdCBvcCA9IG9wc1tpXTsgY29uc3QgZm4gPSBvcHNbaSArIDFdOyBpICs9IDI7IGlmICgob3AgPT09ICdvcHRpb25hbEFjY2VzcycgfHwgb3AgPT09ICdvcHRpb25hbENhbGwnKSAmJiB2YWx1ZSA9PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gaWYgKG9wID09PSAnYWNjZXNzJyB8fCBvcCA9PT0gJ29wdGlvbmFsQWNjZXNzJykgeyBsYXN0QWNjZXNzTEhTID0gdmFsdWU7IHZhbHVlID0gZm4odmFsdWUpOyB9IGVsc2UgaWYgKG9wID09PSAnY2FsbCcgfHwgb3AgPT09ICdvcHRpb25hbENhbGwnKSB7IHZhbHVlID0gZm4oKC4uLmFyZ3MpID0+IHZhbHVlLmNhbGwobGFzdEFjY2Vzc0xIUywgLi4uYXJncykpOyBsYXN0QWNjZXNzTEhTID0gdW5kZWZpbmVkOyB9IH0gcmV0dXJuIHZhbHVlOyB9LyoqCiAqIFRoaXMgY29kZSB3YXMgb3JpZ2luYWxseSBmb3JrZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vVG9vVGFsbE5hdGUvcHJveHktYWdlbnRzL3RyZWUvYjEzMzI5NWZkMTZmNjQ3NTU3OGI2YjE1YmQ5YjRlMzNlY2IwZDBiNwogKiBXaXRoIHRoZSBmb2xsb3dpbmcgbGljZW5jZToKICoKICogKFRoZSBNSVQgTGljZW5zZSkKICoKICogQ29weXJpZ2h0IChjKSAyMDEzIE5hdGhhbiBSYWpsaWNoIDxuYXRoYW5AdG9vdGFsbG5hdGUubmV0PioKICoKICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nCiAqIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZQogKiAnU29mdHdhcmUnKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nCiAqIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwKICogZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvCiAqIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0bwogKiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6KgogKgogKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZQogKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4qCiAqCiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAnQVMgSVMnLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELAogKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YKICogTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULgogKiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWQogKiBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULAogKiBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRQogKiBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KICovCgpmdW5jdGlvbiBkZWJ1ZyguLi5hcmdzKSB7CiAgbG9nZ2VyLmxvZygnW2h0dHBzLXByb3h5LWFnZW50XScsIC4uLmFyZ3MpOwp9CgovKioKICogVGhlIGBIdHRwc1Byb3h5QWdlbnRgIGltcGxlbWVudHMgYW4gSFRUUCBBZ2VudCBzdWJjbGFzcyB0aGF0IGNvbm5lY3RzIHRvCiAqIHRoZSBzcGVjaWZpZWQgIkhUVFAocykgcHJveHkgc2VydmVyIiBpbiBvcmRlciB0byBwcm94eSBIVFRQUyByZXF1ZXN0cy4KICoKICogT3V0Z29pbmcgSFRUUCByZXF1ZXN0cyBhcmUgZmlyc3QgdHVubmVsZWQgdGhyb3VnaCB0aGUgcHJveHkgc2VydmVyIHVzaW5nIHRoZQogKiBgQ09OTkVDVGAgSFRUUCByZXF1ZXN0IG1ldGhvZCB0byBlc3RhYmxpc2ggYSBjb25uZWN0aW9uIHRvIHRoZSBwcm94eSBzZXJ2ZXIsCiAqIGFuZCB0aGVuIHRoZSBwcm94eSBzZXJ2ZXIgY29ubmVjdHMgdG8gdGhlIGRlc3RpbmF0aW9uIHRhcmdldCBhbmQgaXNzdWVzIHRoZQogKiBIVFRQIHJlcXVlc3QgZnJvbSB0aGUgcHJveHkgc2VydmVyLgogKgogKiBgaHR0cHM6YCByZXF1ZXN0cyBoYXZlIHRoZWlyIHNvY2tldCBjb25uZWN0aW9uIHVwZ3JhZGVkIHRvIFRMUyBvbmNlCiAqIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBwcm94eSBzZXJ2ZXIgaGFzIGJlZW4gZXN0YWJsaXNoZWQuCiAqLwpjbGFzcyBIdHRwc1Byb3h5QWdlbnQgZXh0ZW5kcyBBZ2VudCB7CiAgc3RhdGljIF9faW5pdFN0YXRpYygpIHt0aGlzLnByb3RvY29scyA9IFsnaHR0cCcsICdodHRwcyddOyB9CgogIGNvbnN0cnVjdG9yKHByb3h5LCBvcHRzKSB7CiAgICBzdXBlcihvcHRzKTsKICAgIHRoaXMub3B0aW9ucyA9IHt9OwogICAgdGhpcy5wcm94eSA9IHR5cGVvZiBwcm94eSA9PT0gJ3N0cmluZycgPyBuZXcgVVJMKHByb3h5KSA6IHByb3h5OwogICAgdGhpcy5wcm94eUhlYWRlcnMgPSBfbnVsbGlzaENvYWxlc2NlJDEoX29wdGlvbmFsQ2hhaW4kMShbb3B0cywgJ29wdGlvbmFsQWNjZXNzJywgXzIgPT4gXzIuaGVhZGVyc10pLCAoKSA9PiAoIHt9KSk7CiAgICBkZWJ1ZygnQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8nLCB0aGlzLnByb3h5LmhyZWYpOwoKICAgIC8vIFRyaW0gb2ZmIHRoZSBicmFja2V0cyBmcm9tIElQdjYgYWRkcmVzc2VzCiAgICBjb25zdCBob3N0ID0gKHRoaXMucHJveHkuaG9zdG5hbWUgfHwgdGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csICcnKTsKICAgIGNvbnN0IHBvcnQgPSB0aGlzLnByb3h5LnBvcnQgPyBwYXJzZUludCh0aGlzLnByb3h5LnBvcnQsIDEwKSA6IHRoaXMucHJveHkucHJvdG9jb2wgPT09ICdodHRwczonID8gNDQzIDogODA7CiAgICB0aGlzLmNvbm5lY3RPcHRzID0gewogICAgICAvLyBBdHRlbXB0IHRvIG5lZ290aWF0ZSBodHRwLzEuMSBmb3IgcHJveHkgc2VydmVycyB0aGF0IHN1cHBvcnQgaHR0cC8yCiAgICAgIEFMUE5Qcm90b2NvbHM6IFsnaHR0cC8xLjEnXSwKICAgICAgLi4uKG9wdHMgPyBvbWl0KG9wdHMsICdoZWFkZXJzJykgOiBudWxsKSwKICAgICAgaG9zdCwKICAgICAgcG9ydCwKICAgIH07CiAgfQoKICAvKioKICAgKiBDYWxsZWQgd2hlbiB0aGUgbm9kZS1jb3JlIEhUVFAgY2xpZW50IGxpYnJhcnkgaXMgY3JlYXRpbmcgYQogICAqIG5ldyBIVFRQIHJlcXVlc3QuCiAgICovCiAgYXN5bmMgY29ubmVjdChyZXEsIG9wdHMpIHsKICAgIGNvbnN0IHsgcHJveHkgfSA9IHRoaXM7CgogICAgaWYgKCFvcHRzLmhvc3QpIHsKICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7CiAgICB9CgogICAgLy8gQ3JlYXRlIGEgc29ja2V0IGNvbm5lY3Rpb24gdG8gdGhlIHByb3h5IHNlcnZlci4KICAgIGxldCBzb2NrZXQ7CiAgICBpZiAocHJveHkucHJvdG9jb2wgPT09ICdodHRwczonKSB7CiAgICAgIGRlYnVnKCdDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvJywgdGhpcy5jb25uZWN0T3B0cyk7CiAgICAgIGNvbnN0IHNlcnZlcm5hbWUgPSB0aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWUgfHwgdGhpcy5jb25uZWN0T3B0cy5ob3N0OwogICAgICBzb2NrZXQgPSB0bHMuY29ubmVjdCh7CiAgICAgICAgLi4udGhpcy5jb25uZWN0T3B0cywKICAgICAgICBzZXJ2ZXJuYW1lOiBzZXJ2ZXJuYW1lICYmIG5ldC5pc0lQKHNlcnZlcm5hbWUpID8gdW5kZWZpbmVkIDogc2VydmVybmFtZSwKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBkZWJ1ZygnQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbycsIHRoaXMuY29ubmVjdE9wdHMpOwogICAgICBzb2NrZXQgPSBuZXQuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTsKICAgIH0KCiAgICBjb25zdCBoZWFkZXJzID0KICAgICAgdHlwZW9mIHRoaXMucHJveHlIZWFkZXJzID09PSAnZnVuY3Rpb24nID8gdGhpcy5wcm94eUhlYWRlcnMoKSA6IHsgLi4udGhpcy5wcm94eUhlYWRlcnMgfTsKICAgIGNvbnN0IGhvc3QgPSBuZXQuaXNJUHY2KG9wdHMuaG9zdCkgPyBgWyR7b3B0cy5ob3N0fV1gIDogb3B0cy5ob3N0OwogICAgbGV0IHBheWxvYWQgPSBgQ09OTkVDVCAke2hvc3R9OiR7b3B0cy5wb3J0fSBIVFRQLzEuMVxyXG5gOwoKICAgIC8vIEluamVjdCB0aGUgYFByb3h5LUF1dGhvcml6YXRpb25gIGhlYWRlciBpZiBuZWNlc3NhcnkuCiAgICBpZiAocHJveHkudXNlcm5hbWUgfHwgcHJveHkucGFzc3dvcmQpIHsKICAgICAgY29uc3QgYXV0aCA9IGAke2RlY29kZVVSSUNvbXBvbmVudChwcm94eS51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KHByb3h5LnBhc3N3b3JkKX1gOwogICAgICBoZWFkZXJzWydQcm94eS1BdXRob3JpemF0aW9uJ10gPSBgQmFzaWMgJHtCdWZmZXIuZnJvbShhdXRoKS50b1N0cmluZygnYmFzZTY0Jyl9YDsKICAgIH0KCiAgICBoZWFkZXJzLkhvc3QgPSBgJHtob3N0fToke29wdHMucG9ydH1gOwoKICAgIGlmICghaGVhZGVyc1snUHJveHktQ29ubmVjdGlvbiddKSB7CiAgICAgIGhlYWRlcnNbJ1Byb3h5LUNvbm5lY3Rpb24nXSA9IHRoaXMua2VlcEFsaXZlID8gJ0tlZXAtQWxpdmUnIDogJ2Nsb3NlJzsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkgewogICAgICBwYXlsb2FkICs9IGAke25hbWV9OiAke2hlYWRlcnNbbmFtZV19XHJcbmA7CiAgICB9CgogICAgY29uc3QgcHJveHlSZXNwb25zZVByb21pc2UgPSBwYXJzZVByb3h5UmVzcG9uc2Uoc29ja2V0KTsKCiAgICBzb2NrZXQud3JpdGUoYCR7cGF5bG9hZH1cclxuYCk7CgogICAgY29uc3QgeyBjb25uZWN0LCBidWZmZXJlZCB9ID0gYXdhaXQgcHJveHlSZXNwb25zZVByb21pc2U7CiAgICByZXEuZW1pdCgncHJveHlDb25uZWN0JywgY29ubmVjdCk7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50CiAgICAvLyBAdHMtaWdub3JlIE5vdCBFdmVudEVtaXR0ZXIgaW4gTm9kZSB0eXBlcwogICAgdGhpcy5lbWl0KCdwcm94eUNvbm5lY3QnLCBjb25uZWN0LCByZXEpOwoKICAgIGlmIChjb25uZWN0LnN0YXR1c0NvZGUgPT09IDIwMCkgewogICAgICByZXEub25jZSgnc29ja2V0JywgcmVzdW1lKTsKCiAgICAgIGlmIChvcHRzLnNlY3VyZUVuZHBvaW50KSB7CiAgICAgICAgLy8gVGhlIHByb3h5IGlzIGNvbm5lY3RpbmcgdG8gYSBUTFMgc2VydmVyLCBzbyB1cGdyYWRlCiAgICAgICAgLy8gdGhpcyBzb2NrZXQgY29ubmVjdGlvbiB0byBhIFRMUyBjb25uZWN0aW9uLgogICAgICAgIGRlYnVnKCdVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTJyk7CiAgICAgICAgY29uc3Qgc2VydmVybmFtZSA9IG9wdHMuc2VydmVybmFtZSB8fCBvcHRzLmhvc3Q7CiAgICAgICAgcmV0dXJuIHRscy5jb25uZWN0KHsKICAgICAgICAgIC4uLm9taXQob3B0cywgJ2hvc3QnLCAncGF0aCcsICdwb3J0JyksCiAgICAgICAgICBzb2NrZXQsCiAgICAgICAgICBzZXJ2ZXJuYW1lOiBuZXQuaXNJUChzZXJ2ZXJuYW1lKSA/IHVuZGVmaW5lZCA6IHNlcnZlcm5hbWUsCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBzb2NrZXQ7CiAgICB9CgogICAgLy8gU29tZSBvdGhlciBzdGF0dXMgY29kZSB0aGF0J3Mgbm90IDIwMC4uLiBuZWVkIHRvIHJlLXBsYXkgdGhlIEhUVFAKICAgIC8vIGhlYWRlciAiZGF0YSIgZXZlbnRzIG9udG8gdGhlIHNvY2tldCBvbmNlIHRoZSBIVFRQIG1hY2hpbmVyeSBpcwogICAgLy8gYXR0YWNoZWQgc28gdGhhdCB0aGUgbm9kZSBjb3JlIGBodHRwYCBjYW4gcGFyc2UgYW5kIGhhbmRsZSB0aGUKICAgIC8vIGVycm9yIHN0YXR1cyBjb2RlLgoKICAgIC8vIENsb3NlIHRoZSBvcmlnaW5hbCBzb2NrZXQsIGFuZCBhIG5ldyAiZmFrZSIgc29ja2V0IGlzIHJldHVybmVkCiAgICAvLyBpbnN0ZWFkLCBzbyB0aGF0IHRoZSBwcm94eSBkb2Vzbid0IGdldCB0aGUgSFRUUCByZXF1ZXN0CiAgICAvLyB3cml0dGVuIHRvIGl0ICh3aGljaCBtYXkgY29udGFpbiBgQXV0aG9yaXphdGlvbmAgaGVhZGVycyBvciBvdGhlcgogICAgLy8gc2Vuc2l0aXZlIGRhdGEpLgogICAgLy8KICAgIC8vIFNlZTogaHR0cHM6Ly9oYWNrZXJvbmUuY29tL3JlcG9ydHMvNTQxNTAyCiAgICBzb2NrZXQuZGVzdHJveSgpOwoKICAgIGNvbnN0IGZha2VTb2NrZXQgPSBuZXcgbmV0LlNvY2tldCh7IHdyaXRhYmxlOiBmYWxzZSB9KTsKICAgIGZha2VTb2NrZXQucmVhZGFibGUgPSB0cnVlOwoKICAgIC8vIE5lZWQgdG8gd2FpdCBmb3IgdGhlICJzb2NrZXQiIGV2ZW50IHRvIHJlLXBsYXkgdGhlICJkYXRhIiBldmVudHMuCiAgICByZXEub25jZSgnc29ja2V0JywgKHMpID0+IHsKICAgICAgZGVidWcoJ1JlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0Jyk7CiAgICAgIGFzc2VydChzLmxpc3RlbmVyQ291bnQoJ2RhdGEnKSA+IDApOwoKICAgICAgLy8gUmVwbGF5IHRoZSAiYnVmZmVyZWQiIEJ1ZmZlciBvbnRvIHRoZSBmYWtlIGBzb2NrZXRgLCBzaW5jZSBhdAogICAgICAvLyB0aGlzIHBvaW50IHRoZSBIVFRQIG1vZHVsZSBtYWNoaW5lcnkgaGFzIGJlZW4gaG9va2VkIHVwIGZvcgogICAgICAvLyB0aGUgdXNlci4KICAgICAgcy5wdXNoKGJ1ZmZlcmVkKTsKICAgICAgcy5wdXNoKG51bGwpOwogICAgfSk7CgogICAgcmV0dXJuIGZha2VTb2NrZXQ7CiAgfQp9IEh0dHBzUHJveHlBZ2VudC5fX2luaXRTdGF0aWMoKTsKCmZ1bmN0aW9uIHJlc3VtZShzb2NrZXQpIHsKICBzb2NrZXQucmVzdW1lKCk7Cn0KCmZ1bmN0aW9uIG9taXQoCiAgb2JqLAogIC4uLmtleXMKKQoKIHsKICBjb25zdCByZXQgPSB7fQoKOwogIGxldCBrZXk7CiAgZm9yIChrZXkgaW4gb2JqKSB7CiAgICBpZiAoIWtleXMuaW5jbHVkZXMoa2V5KSkgewogICAgICByZXRba2V5XSA9IG9ialtrZXldOwogICAgfQogIH0KICByZXR1cm4gcmV0Owp9CgpmdW5jdGlvbiBfbnVsbGlzaENvYWxlc2NlKGxocywgcmhzRm4pIHsgaWYgKGxocyAhPSBudWxsKSB7IHJldHVybiBsaHM7IH0gZWxzZSB7IHJldHVybiByaHNGbigpOyB9IH0KLy8gRXN0aW1hdGVkIG1heGltdW0gc2l6ZSBmb3IgcmVhc29uYWJsZSBzdGFuZGFsb25lIGV2ZW50CmNvbnN0IEdaSVBfVEhSRVNIT0xEID0gMTAyNCAqIDMyOwoKLyoqCiAqIEdldHMgYSBzdHJlYW0gZnJvbSBhIFVpbnQ4QXJyYXkgb3Igc3RyaW5nCiAqIFJlYWRhYmxlLmZyb20gaXMgaWRlYWwgYnV0IHdhcyBhZGRlZCBpbiBub2RlLmpzIHYxMi4zLjAgYW5kIHYxMC4xNy4wCiAqLwpmdW5jdGlvbiBzdHJlYW1Gcm9tQm9keShib2R5KSB7CiAgcmV0dXJuIG5ldyBSZWFkYWJsZSh7CiAgICByZWFkKCkgewogICAgICB0aGlzLnB1c2goYm9keSk7CiAgICAgIHRoaXMucHVzaChudWxsKTsKICAgIH0sCiAgfSk7Cn0KCi8qKgogKiBDcmVhdGVzIGEgVHJhbnNwb3J0IHRoYXQgdXNlcyBuYXRpdmUgdGhlIG5hdGl2ZSAnaHR0cCcgYW5kICdodHRwcycgbW9kdWxlcyB0byBzZW5kIGV2ZW50cyB0byBTZW50cnkuCiAqLwpmdW5jdGlvbiBtYWtlTm9kZVRyYW5zcG9ydChvcHRpb25zKSB7CiAgbGV0IHVybFNlZ21lbnRzOwoKICB0cnkgewogICAgdXJsU2VnbWVudHMgPSBuZXcgVVJMKG9wdGlvbnMudXJsKTsKICB9IGNhdGNoIChlKSB7CiAgICBjb25zb2xlU2FuZGJveCgoKSA9PiB7CiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlCiAgICAgIGNvbnNvbGUud2FybigKICAgICAgICAnW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4nLAogICAgICApOwogICAgfSk7CiAgICByZXR1cm4gY3JlYXRlVHJhbnNwb3J0KG9wdGlvbnMsICgpID0+IFByb21pc2UucmVzb2x2ZSh7fSkpOwogIH0KCiAgY29uc3QgaXNIdHRwcyA9IHVybFNlZ21lbnRzLnByb3RvY29sID09PSAnaHR0cHM6JzsKCiAgLy8gUHJveHkgcHJpb3JpdGl6YXRpb246IGh0dHAgPT4gYG9wdGlvbnMucHJveHlgIHwgYHByb2Nlc3MuZW52Lmh0dHBfcHJveHlgCiAgLy8gUHJveHkgcHJpb3JpdGl6YXRpb246IGh0dHBzID0+IGBvcHRpb25zLnByb3h5YCB8IGBwcm9jZXNzLmVudi5odHRwc19wcm94eWAgfCBgcHJvY2Vzcy5lbnYuaHR0cF9wcm94eWAKICBjb25zdCBwcm94eSA9IGFwcGx5Tm9Qcm94eU9wdGlvbigKICAgIHVybFNlZ21lbnRzLAogICAgb3B0aW9ucy5wcm94eSB8fCAoaXNIdHRwcyA/IHByb2Nlc3MuZW52Lmh0dHBzX3Byb3h5IDogdW5kZWZpbmVkKSB8fCBwcm9jZXNzLmVudi5odHRwX3Byb3h5LAogICk7CgogIGNvbnN0IG5hdGl2ZUh0dHBNb2R1bGUgPSBpc0h0dHBzID8gaHR0cHMgOiBodHRwOwogIGNvbnN0IGtlZXBBbGl2ZSA9IG9wdGlvbnMua2VlcEFsaXZlID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IG9wdGlvbnMua2VlcEFsaXZlOwoKICAvLyBUT0RPKHY3KTogRXZhbHVhdGUgaWYgd2UgY2FuIHNldCBrZWVwQWxpdmUgdG8gdHJ1ZS4gVGhpcyB3b3VsZCBpbnZvbHZlIHRlc3RpbmcgZm9yIG1lbW9yeSBsZWFrcyBpbiBvbGRlciBub2RlCiAgLy8gdmVyc2lvbnMoPj0gOCkgYXMgdGhleSBoYWQgbWVtb3J5IGxlYWtzIHdoZW4gdXNpbmcgaXQ6ICMyNTU1CiAgY29uc3QgYWdlbnQgPSBwcm94eQogICAgPyAobmV3IEh0dHBzUHJveHlBZ2VudChwcm94eSkgKQogICAgOiBuZXcgbmF0aXZlSHR0cE1vZHVsZS5BZ2VudCh7IGtlZXBBbGl2ZSwgbWF4U29ja2V0czogMzAsIHRpbWVvdXQ6IDIwMDAgfSk7CgogIGNvbnN0IHJlcXVlc3RFeGVjdXRvciA9IGNyZWF0ZVJlcXVlc3RFeGVjdXRvcihvcHRpb25zLCBfbnVsbGlzaENvYWxlc2NlKG9wdGlvbnMuaHR0cE1vZHVsZSwgKCkgPT4gKCBuYXRpdmVIdHRwTW9kdWxlKSksIGFnZW50KTsKICByZXR1cm4gY3JlYXRlVHJhbnNwb3J0KG9wdGlvbnMsIHJlcXVlc3RFeGVjdXRvcik7Cn0KCi8qKgogKiBIb25vcnMgdGhlIGBub19wcm94eWAgZW52IHZhcmlhYmxlIHdpdGggdGhlIGhpZ2hlc3QgcHJpb3JpdHkgdG8gYWxsb3cgZm9yIGhvc3RzIGV4Y2x1c2lvbi4KICoKICogQHBhcmFtIHRyYW5zcG9ydFVybCBUaGUgVVJMIHRoZSB0cmFuc3BvcnQgaW50ZW5kcyB0byBzZW5kIGV2ZW50cyB0by4KICogQHBhcmFtIHByb3h5IFRoZSBjbGllbnQgY29uZmlndXJlZCBwcm94eS4KICogQHJldHVybnMgQSBwcm94eSB0aGUgdHJhbnNwb3J0IHNob3VsZCB1c2UuCiAqLwpmdW5jdGlvbiBhcHBseU5vUHJveHlPcHRpb24odHJhbnNwb3J0VXJsU2VnbWVudHMsIHByb3h5KSB7CiAgY29uc3QgeyBub19wcm94eSB9ID0gcHJvY2Vzcy5lbnY7CgogIGNvbnN0IHVybElzRXhlbXB0RnJvbVByb3h5ID0KICAgIG5vX3Byb3h5ICYmCiAgICBub19wcm94eQogICAgICAuc3BsaXQoJywnKQogICAgICAuc29tZSgKICAgICAgICBleGVtcHRpb24gPT4gdHJhbnNwb3J0VXJsU2VnbWVudHMuaG9zdC5lbmRzV2l0aChleGVtcHRpb24pIHx8IHRyYW5zcG9ydFVybFNlZ21lbnRzLmhvc3RuYW1lLmVuZHNXaXRoKGV4ZW1wdGlvbiksCiAgICAgICk7CgogIGlmICh1cmxJc0V4ZW1wdEZyb21Qcm94eSkgewogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9IGVsc2UgewogICAgcmV0dXJuIHByb3h5OwogIH0KfQoKLyoqCiAqIENyZWF0ZXMgYSBSZXF1ZXN0RXhlY3V0b3IgdG8gYmUgdXNlZCB3aXRoIGBjcmVhdGVUcmFuc3BvcnRgLgogKi8KZnVuY3Rpb24gY3JlYXRlUmVxdWVzdEV4ZWN1dG9yKAogIG9wdGlvbnMsCiAgaHR0cE1vZHVsZSwKICBhZ2VudCwKKSB7CiAgY29uc3QgeyBob3N0bmFtZSwgcGF0aG5hbWUsIHBvcnQsIHByb3RvY29sLCBzZWFyY2ggfSA9IG5ldyBVUkwob3B0aW9ucy51cmwpOwogIHJldHVybiBmdW5jdGlvbiBtYWtlUmVxdWVzdChyZXF1ZXN0KSB7CiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICBsZXQgYm9keSA9IHN0cmVhbUZyb21Cb2R5KHJlcXVlc3QuYm9keSk7CgogICAgICBjb25zdCBoZWFkZXJzID0geyAuLi5vcHRpb25zLmhlYWRlcnMgfTsKCiAgICAgIGlmIChyZXF1ZXN0LmJvZHkubGVuZ3RoID4gR1pJUF9USFJFU0hPTEQpIHsKICAgICAgICBoZWFkZXJzWydjb250ZW50LWVuY29kaW5nJ10gPSAnZ3ppcCc7CiAgICAgICAgYm9keSA9IGJvZHkucGlwZShjcmVhdGVHemlwKCkpOwogICAgICB9CgogICAgICBjb25zdCByZXEgPSBodHRwTW9kdWxlLnJlcXVlc3QoCiAgICAgICAgewogICAgICAgICAgbWV0aG9kOiAnUE9TVCcsCiAgICAgICAgICBhZ2VudCwKICAgICAgICAgIGhlYWRlcnMsCiAgICAgICAgICBob3N0bmFtZSwKICAgICAgICAgIHBhdGg6IGAke3BhdGhuYW1lfSR7c2VhcmNofWAsCiAgICAgICAgICBwb3J0LAogICAgICAgICAgcHJvdG9jb2wsCiAgICAgICAgICBjYTogb3B0aW9ucy5jYUNlcnRzLAogICAgICAgIH0sCiAgICAgICAgcmVzID0+IHsKICAgICAgICAgIHJlcy5vbignZGF0YScsICgpID0+IHsKICAgICAgICAgICAgLy8gRHJhaW4gc29ja2V0CiAgICAgICAgICB9KTsKCiAgICAgICAgICByZXMub24oJ2VuZCcsICgpID0+IHsKICAgICAgICAgICAgLy8gRHJhaW4gc29ja2V0CiAgICAgICAgICB9KTsKCiAgICAgICAgICByZXMuc2V0RW5jb2RpbmcoJ3V0ZjgnKTsKCiAgICAgICAgICAvLyAiS2V5LXZhbHVlIHBhaXJzIG9mIGhlYWRlciBuYW1lcyBhbmQgdmFsdWVzLiBIZWFkZXIgbmFtZXMgYXJlIGxvd2VyLWNhc2VkLiIKICAgICAgICAgIC8vIGh0dHBzOi8vbm9kZWpzLm9yZy9hcGkvaHR0cC5odG1sI2h0dHBfbWVzc2FnZV9oZWFkZXJzCiAgICAgICAgICBjb25zdCByZXRyeUFmdGVySGVhZGVyID0gX251bGxpc2hDb2FsZXNjZShyZXMuaGVhZGVyc1sncmV0cnktYWZ0ZXInXSwgKCkgPT4gKCBudWxsKSk7CiAgICAgICAgICBjb25zdCByYXRlTGltaXRzSGVhZGVyID0gX251bGxpc2hDb2FsZXNjZShyZXMuaGVhZGVyc1sneC1zZW50cnktcmF0ZS1saW1pdHMnXSwgKCkgPT4gKCBudWxsKSk7CgogICAgICAgICAgcmVzb2x2ZSh7CiAgICAgICAgICAgIHN0YXR1c0NvZGU6IHJlcy5zdGF0dXNDb2RlLAogICAgICAgICAgICBoZWFkZXJzOiB7CiAgICAgICAgICAgICAgJ3JldHJ5LWFmdGVyJzogcmV0cnlBZnRlckhlYWRlciwKICAgICAgICAgICAgICAneC1zZW50cnktcmF0ZS1saW1pdHMnOiBBcnJheS5pc0FycmF5KHJhdGVMaW1pdHNIZWFkZXIpID8gcmF0ZUxpbWl0c0hlYWRlclswXSA6IHJhdGVMaW1pdHNIZWFkZXIsCiAgICAgICAgICAgIH0sCiAgICAgICAgICB9KTsKICAgICAgICB9LAogICAgICApOwoKICAgICAgcmVxLm9uKCdlcnJvcicsIHJlamVjdCk7CiAgICAgIGJvZHkucGlwZShyZXEpOwogICAgfSk7CiAgfTsKfQoKLyoqIG5vcm1hbGl6ZXMgV2luZG93cyBwYXRocyAqLwpmdW5jdGlvbiBub3JtYWxpemVXaW5kb3dzUGF0aChwYXRoKSB7CiAgcmV0dXJuIHBhdGgKICAgIC5yZXBsYWNlKC9eW0EtWl06LywgJycpIC8vIHJlbW92ZSBXaW5kb3dzLXN0eWxlIHByZWZpeAogICAgLnJlcGxhY2UoL1xcL2csICcvJyk7IC8vIHJlcGxhY2UgYWxsIGBcYCBpbnN0YW5jZXMgd2l0aCBgL2AKfQoKLyoqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGdldHMgdGhlIG1vZHVsZSBuYW1lIGZyb20gYSBmaWxlbmFtZSAqLwpmdW5jdGlvbiBjcmVhdGVHZXRNb2R1bGVGcm9tRmlsZW5hbWUoCiAgYmFzZVBhdGggPSBwcm9jZXNzLmFyZ3ZbMV0gPyBkaXJuYW1lKHByb2Nlc3MuYXJndlsxXSkgOiBwcm9jZXNzLmN3ZCgpLAogIGlzV2luZG93cyA9IHNlcCA9PT0gJ1xcJywKKSB7CiAgY29uc3Qgbm9ybWFsaXplZEJhc2UgPSBpc1dpbmRvd3MgPyBub3JtYWxpemVXaW5kb3dzUGF0aChiYXNlUGF0aCkgOiBiYXNlUGF0aDsKCiAgcmV0dXJuIChmaWxlbmFtZSkgPT4gewogICAgaWYgKCFmaWxlbmFtZSkgewogICAgICByZXR1cm47CiAgICB9CgogICAgY29uc3Qgbm9ybWFsaXplZEZpbGVuYW1lID0gaXNXaW5kb3dzID8gbm9ybWFsaXplV2luZG93c1BhdGgoZmlsZW5hbWUpIDogZmlsZW5hbWU7CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1jb25zdAogICAgbGV0IHsgZGlyLCBiYXNlOiBmaWxlLCBleHQgfSA9IHBvc2l4LnBhcnNlKG5vcm1hbGl6ZWRGaWxlbmFtZSk7CgogICAgaWYgKGV4dCA9PT0gJy5qcycgfHwgZXh0ID09PSAnLm1qcycgfHwgZXh0ID09PSAnLmNqcycpIHsKICAgICAgZmlsZSA9IGZpbGUuc2xpY2UoMCwgZXh0Lmxlbmd0aCAqIC0xKTsKICAgIH0KCiAgICBpZiAoIWRpcikgewogICAgICAvLyBObyBkaXJuYW1lIHdoYXRzb2V2ZXIKICAgICAgZGlyID0gJy4nOwogICAgfQoKICAgIGNvbnN0IG4gPSBkaXIubGFzdEluZGV4T2YoJy9ub2RlX21vZHVsZXMnKTsKICAgIGlmIChuID4gLTEpIHsKICAgICAgcmV0dXJuIGAke2Rpci5zbGljZShuICsgMTQpLnJlcGxhY2UoL1wvL2csICcuJyl9OiR7ZmlsZX1gOwogICAgfQoKICAgIC8vIExldCdzIHNlZSBpZiBpdCdzIGEgcGFydCBvZiB0aGUgbWFpbiBtb2R1bGUKICAgIC8vIFRvIGJlIGEgcGFydCBvZiBtYWluIG1vZHVsZSwgaXQgaGFzIHRvIHNoYXJlIHRoZSBzYW1lIGJhc2UKICAgIGlmIChkaXIuc3RhcnRzV2l0aChub3JtYWxpemVkQmFzZSkpIHsKICAgICAgbGV0IG1vZHVsZU5hbWUgPSBkaXIuc2xpY2Uobm9ybWFsaXplZEJhc2UubGVuZ3RoICsgMSkucmVwbGFjZSgvXC8vZywgJy4nKTsKCiAgICAgIGlmIChtb2R1bGVOYW1lKSB7CiAgICAgICAgbW9kdWxlTmFtZSArPSAnOic7CiAgICAgIH0KICAgICAgbW9kdWxlTmFtZSArPSBmaWxlOwoKICAgICAgcmV0dXJuIG1vZHVsZU5hbWU7CiAgICB9CgogICAgcmV0dXJuIGZpbGU7CiAgfTsKfQoKZnVuY3Rpb24gX29wdGlvbmFsQ2hhaW4ob3BzKSB7IGxldCBsYXN0QWNjZXNzTEhTID0gdW5kZWZpbmVkOyBsZXQgdmFsdWUgPSBvcHNbMF07IGxldCBpID0gMTsgd2hpbGUgKGkgPCBvcHMubGVuZ3RoKSB7IGNvbnN0IG9wID0gb3BzW2ldOyBjb25zdCBmbiA9IG9wc1tpICsgMV07IGkgKz0gMjsgaWYgKChvcCA9PT0gJ29wdGlvbmFsQWNjZXNzJyB8fCBvcCA9PT0gJ29wdGlvbmFsQ2FsbCcpICYmIHZhbHVlID09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBpZiAob3AgPT09ICdhY2Nlc3MnIHx8IG9wID09PSAnb3B0aW9uYWxBY2Nlc3MnKSB7IGxhc3RBY2Nlc3NMSFMgPSB2YWx1ZTsgdmFsdWUgPSBmbih2YWx1ZSk7IH0gZWxzZSBpZiAob3AgPT09ICdjYWxsJyB8fCBvcCA9PT0gJ29wdGlvbmFsQ2FsbCcpIHsgdmFsdWUgPSBmbigoLi4uYXJncykgPT4gdmFsdWUuY2FsbChsYXN0QWNjZXNzTEhTLCAuLi5hcmdzKSk7IGxhc3RBY2Nlc3NMSFMgPSB1bmRlZmluZWQ7IH0gfSByZXR1cm4gdmFsdWU7IH0KY29uc3Qgb3B0aW9ucyA9IHdvcmtlckRhdGE7CmxldCBzZXNzaW9uOwpsZXQgaGFzU2VudEFuckV2ZW50ID0gZmFsc2U7CgpmdW5jdGlvbiBsb2cobXNnKSB7CiAgaWYgKG9wdGlvbnMuZGVidWcpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlCiAgICBjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7bXNnfWApOwogIH0KfQoKY29uc3QgdXJsID0gZ2V0RW52ZWxvcGVFbmRwb2ludFdpdGhVcmxFbmNvZGVkQXV0aChvcHRpb25zLmRzbik7CmNvbnN0IHRyYW5zcG9ydCA9IG1ha2VOb2RlVHJhbnNwb3J0KHsKICB1cmwsCiAgcmVjb3JkRHJvcHBlZEV2ZW50OiAoKSA9PiB7CiAgICAvLwogIH0sCn0pOwoKYXN5bmMgZnVuY3Rpb24gc2VuZEFibm9ybWFsU2Vzc2lvbigpIHsKICAvLyBvZiB3ZSBoYXZlIGFuIGV4aXN0aW5nIHNlc3Npb24gcGFzc2VkIGZyb20gdGhlIG1haW4gdGhyZWFkLCBzZW5kIGl0IGFzIGFibm9ybWFsCiAgaWYgKHNlc3Npb24pIHsKICAgIGxvZygnU2VuZGluZyBhYm5vcm1hbCBzZXNzaW9uJyk7CiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb24sIHsgc3RhdHVzOiAnYWJub3JtYWwnLCBhYm5vcm1hbF9tZWNoYW5pc206ICdhbnJfZm9yZWdyb3VuZCcgfSk7CgogICAgY29uc3QgZW52ZWxvcGUgPSBjcmVhdGVTZXNzaW9uRW52ZWxvcGUoc2Vzc2lvbiwgb3B0aW9ucy5kc24sIG9wdGlvbnMuc2RrTWV0YWRhdGEpOwogICAgLy8gTG9nIHRoZSBlbnZlbG9wZSBzbyB0byBhaWQgaW4gdGVzdGluZwogICAgbG9nKEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSk7CgogICAgYXdhaXQgdHJhbnNwb3J0LnNlbmQoZW52ZWxvcGUpOwoKICAgIHRyeSB7CiAgICAgIC8vIE5vdGlmeSB0aGUgbWFpbiBwcm9jZXNzIHRoYXQgdGhlIHNlc3Npb24gaGFzIGVuZGVkIHNvIHRoZSBzZXNzaW9uIGNhbiBiZSBjbGVhcmVkIGZyb20gdGhlIHNjb3BlCiAgICAgIF9vcHRpb25hbENoYWluKFtwYXJlbnRQb3J0LCAnb3B0aW9uYWxBY2Nlc3MnLCBfMiA9PiBfMi5wb3N0TWVzc2FnZSwgJ2NhbGwnLCBfMyA9PiBfMygnc2Vzc2lvbi1lbmRlZCcpXSk7CiAgICB9IGNhdGNoIChfKSB7CiAgICAgIC8vIGlnbm9yZQogICAgfQogIH0KfQoKbG9nKCdTdGFydGVkJyk7CgpmdW5jdGlvbiBwcmVwYXJlU3RhY2tGcmFtZXMoc3RhY2tGcmFtZXMpIHsKICBpZiAoIXN0YWNrRnJhbWVzKSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KCiAgLy8gU3RyaXAgU2VudHJ5IGZyYW1lcyBhbmQgcmV2ZXJzZSB0aGUgc3RhY2sgZnJhbWVzIHNvIHRoZXkgYXJlIGluIHRoZSBjb3JyZWN0IG9yZGVyCiAgY29uc3Qgc3RyaXBwZWRGcmFtZXMgPSBzdHJpcFNlbnRyeUZyYW1lc0FuZFJldmVyc2Uoc3RhY2tGcmFtZXMpOwoKICAvLyBJZiB3ZSBoYXZlIGFuIGFwcCByb290IHBhdGgsIHJld3JpdGUgdGhlIGZpbGVuYW1lcyB0byBiZSByZWxhdGl2ZSB0byB0aGUgYXBwIHJvb3QKICBpZiAob3B0aW9ucy5hcHBSb290UGF0aCkgewogICAgZm9yIChjb25zdCBmcmFtZSBvZiBzdHJpcHBlZEZyYW1lcykgewogICAgICBpZiAoIWZyYW1lLmZpbGVuYW1lKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIGZyYW1lLmZpbGVuYW1lID0gbm9ybWFsaXplVXJsVG9CYXNlKGZyYW1lLmZpbGVuYW1lLCBvcHRpb25zLmFwcFJvb3RQYXRoKTsKICAgIH0KICB9CgogIHJldHVybiBzdHJpcHBlZEZyYW1lczsKfQoKYXN5bmMgZnVuY3Rpb24gc2VuZEFuckV2ZW50KGZyYW1lcywgdHJhY2VDb250ZXh0KSB7CiAgaWYgKGhhc1NlbnRBbnJFdmVudCkgewogICAgcmV0dXJuOwogIH0KCiAgaGFzU2VudEFuckV2ZW50ID0gdHJ1ZTsKCiAgYXdhaXQgc2VuZEFibm9ybWFsU2Vzc2lvbigpOwoKICBsb2coJ1NlbmRpbmcgZXZlbnQnKTsKCiAgY29uc3QgZXZlbnQgPSB7CiAgICBldmVudF9pZDogdXVpZDQoKSwKICAgIGNvbnRleHRzOiB7IC4uLm9wdGlvbnMuY29udGV4dHMsIHRyYWNlOiB0cmFjZUNvbnRleHQgfSwKICAgIHJlbGVhc2U6IG9wdGlvbnMucmVsZWFzZSwKICAgIGVudmlyb25tZW50OiBvcHRpb25zLmVudmlyb25tZW50LAogICAgZGlzdDogb3B0aW9ucy5kaXN0LAogICAgcGxhdGZvcm06ICdub2RlJywKICAgIGxldmVsOiAnZXJyb3InLAogICAgZXhjZXB0aW9uOiB7CiAgICAgIHZhbHVlczogWwogICAgICAgIHsKICAgICAgICAgIHR5cGU6ICdBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmcnLAogICAgICAgICAgdmFsdWU6IGBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHtvcHRpb25zLmFuclRocmVzaG9sZH0gbXNgLAogICAgICAgICAgc3RhY2t0cmFjZTogeyBmcmFtZXM6IHByZXBhcmVTdGFja0ZyYW1lcyhmcmFtZXMpIH0sCiAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIFVJIGRvZXNuJ3Qgc2F5ICdDcmFzaGVkIGluJyBmb3IgdGhlIHN0YWNrIHRyYWNlCiAgICAgICAgICBtZWNoYW5pc206IHsgdHlwZTogJ0FOUicgfSwKICAgICAgICB9LAogICAgICBdLAogICAgfSwKICAgIHRhZ3M6IG9wdGlvbnMuc3RhdGljVGFncywKICB9OwoKICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZUV2ZW50RW52ZWxvcGUoZXZlbnQsIG9wdGlvbnMuZHNuLCBvcHRpb25zLnNka01ldGFkYXRhKTsKICAvLyBMb2cgdGhlIGVudmVsb3BlIHNvIHRvIGFpZCBpbiB0ZXN0aW5nCiAgbG9nKEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSk7CgogIGF3YWl0IHRyYW5zcG9ydC5zZW5kKGVudmVsb3BlKTsKICBhd2FpdCB0cmFuc3BvcnQuZmx1c2goMjAwMCk7CgogIC8vIERlbGF5IGZvciA1IHNlY29uZHMgc28gdGhhdCBzdGRpbyBjYW4gZmx1c2ggaW4gdGhlIG1haW4gZXZlbnQgbG9vcCBldmVyIHJlc3RhcnRzLgogIC8vIFRoaXMgaXMgbWFpbmx5IGZvciB0aGUgYmVuZWZpdCBvZiBsb2dnaW5nL2RlYnVnZ2luZyBpc3N1ZXMuCiAgc2V0VGltZW91dCgoKSA9PiB7CiAgICBwcm9jZXNzLmV4aXQoMCk7CiAgfSwgNTAwMCk7Cn0KCmxldCBkZWJ1Z2dlclBhdXNlOwoKaWYgKG9wdGlvbnMuY2FwdHVyZVN0YWNrVHJhY2UpIHsKICBsb2coJ0Nvbm5lY3RpbmcgdG8gZGVidWdnZXInKTsKCiAgY29uc3Qgc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKCk7CiAgc2Vzc2lvbi5jb25uZWN0VG9NYWluVGhyZWFkKCk7CgogIGxvZygnQ29ubmVjdGVkIHRvIGRlYnVnZ2VyJyk7CgogIC8vIENvbGxlY3Qgc2NyaXB0SWQgLT4gdXJsIG1hcCBzbyB3ZSBjYW4gbG9vayB1cCB0aGUgZmlsZW5hbWVzIGxhdGVyCiAgY29uc3Qgc2NyaXB0cyA9IG5ldyBNYXAoKTsKCiAgc2Vzc2lvbi5vbignRGVidWdnZXIuc2NyaXB0UGFyc2VkJywgZXZlbnQgPT4gewogICAgc2NyaXB0cy5zZXQoZXZlbnQucGFyYW1zLnNjcmlwdElkLCBldmVudC5wYXJhbXMudXJsKTsKICB9KTsKCiAgc2Vzc2lvbi5vbignRGVidWdnZXIucGF1c2VkJywgZXZlbnQgPT4gewogICAgaWYgKGV2ZW50LnBhcmFtcy5yZWFzb24gIT09ICdvdGhlcicpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHRyeSB7CiAgICAgIGxvZygnRGVidWdnZXIgcGF1c2VkJyk7CgogICAgICAvLyBjb3B5IHRoZSBmcmFtZXMKICAgICAgY29uc3QgY2FsbEZyYW1lcyA9IFsuLi5ldmVudC5wYXJhbXMuY2FsbEZyYW1lc107CgogICAgICBjb25zdCBnZXRNb2R1bGVOYW1lID0gb3B0aW9ucy5hcHBSb290UGF0aCA/IGNyZWF0ZUdldE1vZHVsZUZyb21GaWxlbmFtZShvcHRpb25zLmFwcFJvb3RQYXRoKSA6ICgpID0+IHVuZGVmaW5lZDsKICAgICAgY29uc3Qgc3RhY2tGcmFtZXMgPSBjYWxsRnJhbWVzLm1hcChmcmFtZSA9PgogICAgICAgIGNhbGxGcmFtZVRvU3RhY2tGcmFtZShmcmFtZSwgc2NyaXB0cy5nZXQoZnJhbWUubG9jYXRpb24uc2NyaXB0SWQpLCBnZXRNb2R1bGVOYW1lKSwKICAgICAgKTsKCiAgICAgIC8vIEV2YWx1YXRlIGEgc2NyaXB0IGluIHRoZSBjdXJyZW50bHkgcGF1c2VkIGNvbnRleHQKICAgICAgc2Vzc2lvbi5wb3N0KAogICAgICAgICdSdW50aW1lLmV2YWx1YXRlJywKICAgICAgICB7CiAgICAgICAgICAvLyBHcmFiIHRoZSB0cmFjZSBjb250ZXh0IGZyb20gdGhlIGN1cnJlbnQgc2NvcGUKICAgICAgICAgIGV4cHJlc3Npb246CiAgICAgICAgICAgICdjb25zdCBjdHggPSBfX1NFTlRSWV9fLmFjcz8uZ2V0Q3VycmVudFNjb3BlKCkuZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkgfHwge307IGN0eC50cmFjZUlkICsgIi0iICsgY3R4LnNwYW5JZCArICItIiArIGN0eC5wYXJlbnRTcGFuSWQnLAogICAgICAgICAgLy8gRG9uJ3QgcmUtdHJpZ2dlciB0aGUgZGVidWdnZXIgaWYgdGhpcyBjYXVzZXMgYW4gZXJyb3IKICAgICAgICAgIHNpbGVudDogdHJ1ZSwKICAgICAgICB9LAogICAgICAgIChfLCBwYXJhbSkgPT4gewogICAgICAgICAgY29uc3QgdHJhY2VJZCA9IHBhcmFtICYmIHBhcmFtLnJlc3VsdCA/IChwYXJhbS5yZXN1bHQudmFsdWUgKSA6ICctLSc7CiAgICAgICAgICBjb25zdCBbdHJhY2VfaWQsIHNwYW5faWQsIHBhcmVudF9zcGFuX2lkXSA9IHRyYWNlSWQuc3BsaXQoJy0nKSA7CgogICAgICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5yZXN1bWUnKTsKICAgICAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIuZGlzYWJsZScpOwoKICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBfb3B0aW9uYWxDaGFpbihbdHJhY2VfaWQsICdvcHRpb25hbEFjY2VzcycsIF80ID0+IF80Lmxlbmd0aF0pICYmIF9vcHRpb25hbENoYWluKFtzcGFuX2lkLCAnb3B0aW9uYWxBY2Nlc3MnLCBfNSA9PiBfNS5sZW5ndGhdKSA/IHsgdHJhY2VfaWQsIHNwYW5faWQsIHBhcmVudF9zcGFuX2lkIH0gOiB1bmRlZmluZWQ7CiAgICAgICAgICBzZW5kQW5yRXZlbnQoc3RhY2tGcmFtZXMsIGNvbnRleHQpLnRoZW4obnVsbCwgKCkgPT4gewogICAgICAgICAgICBsb2coJ1NlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4nKTsKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIucmVzdW1lJyk7CiAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIuZGlzYWJsZScpOwogICAgICB0aHJvdyBlOwogICAgfQogIH0pOwoKICBkZWJ1Z2dlclBhdXNlID0gKCkgPT4gewogICAgdHJ5IHsKICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5lbmFibGUnLCAoKSA9PiB7CiAgICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5wYXVzZScpOwogICAgICB9KTsKICAgIH0gY2F0Y2ggKF8pIHsKICAgICAgLy8KICAgIH0KICB9Owp9CgpmdW5jdGlvbiBjcmVhdGVIclRpbWVyKCkgewogIC8vIFRPRE8gKHY4KTogV2UgY2FuIHVzZSBwcm9jZXNzLmhydGltZS5iaWdpbnQoKSBhZnRlciB3ZSBkcm9wIG5vZGUgdjgKICBsZXQgbGFzdFBvbGwgPSBwcm9jZXNzLmhydGltZSgpOwoKICByZXR1cm4gewogICAgZ2V0VGltZU1zOiAoKSA9PiB7CiAgICAgIGNvbnN0IFtzZWNvbmRzLCBuYW5vU2Vjb25kc10gPSBwcm9jZXNzLmhydGltZShsYXN0UG9sbCk7CiAgICAgIHJldHVybiBNYXRoLmZsb29yKHNlY29uZHMgKiAxZTMgKyBuYW5vU2Vjb25kcyAvIDFlNik7CiAgICB9LAogICAgcmVzZXQ6ICgpID0+IHsKICAgICAgbGFzdFBvbGwgPSBwcm9jZXNzLmhydGltZSgpOwogICAgfSwKICB9Owp9CgpmdW5jdGlvbiB3YXRjaGRvZ1RpbWVvdXQoKSB7CiAgbG9nKCdXYXRjaGRvZyB0aW1lb3V0Jyk7CgogIGlmIChkZWJ1Z2dlclBhdXNlKSB7CiAgICBsb2coJ1BhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZScpOwogICAgZGVidWdnZXJQYXVzZSgpOwogIH0gZWxzZSB7CiAgICBsb2coJ0NhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UnKTsKICAgIHNlbmRBbnJFdmVudCgpLnRoZW4obnVsbCwgKCkgPT4gewogICAgICBsb2coJ1NlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LicpOwogICAgfSk7CiAgfQp9Cgpjb25zdCB7IHBvbGwgfSA9IHdhdGNoZG9nVGltZXIoY3JlYXRlSHJUaW1lciwgb3B0aW9ucy5wb2xsSW50ZXJ2YWwsIG9wdGlvbnMuYW5yVGhyZXNob2xkLCB3YXRjaGRvZ1RpbWVvdXQpOwoKX29wdGlvbmFsQ2hhaW4oW3BhcmVudFBvcnQsICdvcHRpb25hbEFjY2VzcycsIF82ID0+IF82Lm9uLCAnY2FsbCcsIF83ID0+IF83KCdtZXNzYWdlJywgKG1zZykgPT4gewogIGlmIChtc2cuc2Vzc2lvbikgewogICAgc2Vzc2lvbiA9IG1ha2VTZXNzaW9uKG1zZy5zZXNzaW9uKTsKICB9CgogIHBvbGwoKTsKfSldKTs=";