wherdr 2.5.0 → 2.6.0

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 (262) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{CXbAL3Yu.js → 2fsYF-LK.js} +41 -42
  3. package/.output/public/_nuxt/2fsYF-LK.js.br +0 -0
  4. package/.output/public/_nuxt/2fsYF-LK.js.gz +0 -0
  5. package/.output/public/_nuxt/{qODuBH5E.js → 3bE7s96N.js} +1 -1
  6. package/.output/public/_nuxt/6YTlf8ot.js +1 -0
  7. package/.output/public/_nuxt/6YTlf8ot.js.br +0 -0
  8. package/.output/public/_nuxt/6YTlf8ot.js.gz +0 -0
  9. package/.output/public/_nuxt/{BYZVrreW.js → 7KozZy5Y.js} +1 -1
  10. package/.output/public/_nuxt/{AgentView.B6zltno1.css → AgentView.BwyQIUef.css} +1 -1
  11. package/.output/public/_nuxt/AgentView.BwyQIUef.css.br +0 -0
  12. package/.output/public/_nuxt/AgentView.BwyQIUef.css.gz +0 -0
  13. package/.output/public/_nuxt/{BdJIc1Xf.js → B40shTLf.js} +1 -1
  14. package/.output/public/_nuxt/{BdJIc1Xf.js.br → B40shTLf.js.br} +0 -0
  15. package/.output/public/_nuxt/B40shTLf.js.gz +0 -0
  16. package/.output/public/_nuxt/B5cSia3P.js +62 -0
  17. package/.output/public/_nuxt/B5cSia3P.js.br +0 -0
  18. package/.output/public/_nuxt/B5cSia3P.js.gz +0 -0
  19. package/.output/public/_nuxt/BK1_9FXg.js +1 -0
  20. package/.output/public/_nuxt/BK1_9FXg.js.br +0 -0
  21. package/.output/public/_nuxt/BK1_9FXg.js.gz +0 -0
  22. package/.output/public/_nuxt/{CgUSTIM1.js → Bqz3nVVB.js} +1 -1
  23. package/.output/public/_nuxt/{CgUSTIM1.js.br → Bqz3nVVB.js.br} +0 -0
  24. package/.output/public/_nuxt/Bqz3nVVB.js.gz +0 -0
  25. package/.output/public/_nuxt/{DOVT2Tt8.js → ByLPJEo6.js} +1 -1
  26. package/.output/public/_nuxt/ByLPJEo6.js.br +0 -0
  27. package/.output/public/_nuxt/ByLPJEo6.js.gz +0 -0
  28. package/.output/public/_nuxt/C8tHIeGN.js +3 -0
  29. package/.output/public/_nuxt/C8tHIeGN.js.br +0 -0
  30. package/.output/public/_nuxt/C8tHIeGN.js.gz +0 -0
  31. package/.output/public/_nuxt/CAkH_IfS.js +9 -0
  32. package/.output/public/_nuxt/CAkH_IfS.js.br +0 -0
  33. package/.output/public/_nuxt/CAkH_IfS.js.gz +0 -0
  34. package/.output/public/_nuxt/COWXF9OU.js +123 -0
  35. package/.output/public/_nuxt/COWXF9OU.js.br +0 -0
  36. package/.output/public/_nuxt/COWXF9OU.js.gz +0 -0
  37. package/.output/public/_nuxt/{DMzjoyW_.js → CiG2Lovu.js} +1 -1
  38. package/.output/public/_nuxt/CiG2Lovu.js.br +0 -0
  39. package/.output/public/_nuxt/CiG2Lovu.js.gz +0 -0
  40. package/.output/public/_nuxt/CnjxEm0H.js +27 -0
  41. package/.output/public/_nuxt/CnjxEm0H.js.br +0 -0
  42. package/.output/public/_nuxt/CnjxEm0H.js.gz +0 -0
  43. package/.output/public/_nuxt/{PjGJWal8.js → DNs2cMBZ.js} +15 -15
  44. package/.output/public/_nuxt/DNs2cMBZ.js.br +0 -0
  45. package/.output/public/_nuxt/DNs2cMBZ.js.gz +0 -0
  46. package/.output/public/_nuxt/D_x7Rysx.js +31 -0
  47. package/.output/public/_nuxt/D_x7Rysx.js.br +0 -0
  48. package/.output/public/_nuxt/D_x7Rysx.js.gz +0 -0
  49. package/.output/public/_nuxt/{Bd0Z2zzq.js → T-qXNaMY.js} +1 -1
  50. package/.output/public/_nuxt/builds/latest.json +1 -1
  51. package/.output/public/_nuxt/builds/meta/e2ee8d99-6a6a-4754-934f-8b7dbecfcdcb.json +1 -0
  52. package/.output/public/_nuxt/entry.C_hImCpq.css +2 -0
  53. package/.output/public/_nuxt/entry.C_hImCpq.css.br +0 -0
  54. package/.output/public/_nuxt/entry.C_hImCpq.css.gz +0 -0
  55. package/.output/public/_nuxt/useViewport.D9mmYA6A.css +1 -0
  56. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css +1 -0
  57. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css.br +0 -0
  58. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css.gz +0 -0
  59. package/.output/public/sw.js +6 -2
  60. package/.output/server/chunks/_/branding.mjs +1 -1
  61. package/.output/server/chunks/_/fileDownload.mjs +1 -1
  62. package/.output/server/chunks/_/files.mjs +26 -3
  63. package/.output/server/chunks/_/machineOrder.mjs +1 -1
  64. package/.output/server/chunks/_/onboarding.mjs +1 -1
  65. package/.output/server/chunks/_/package.mjs +1 -1
  66. package/.output/server/chunks/_/plugins.mjs +1 -1
  67. package/.output/server/chunks/_/restart.mjs +1 -1
  68. package/.output/server/chunks/_/revoke.mjs +22 -0
  69. package/.output/server/chunks/_/selfupdate.mjs +2 -1
  70. package/.output/server/chunks/_/splitShell.mjs +1 -1
  71. package/.output/server/chunks/_/updates.mjs +18 -4
  72. package/.output/server/chunks/_/uploadHashes.mjs +46 -0
  73. package/.output/server/chunks/_/worktrees.mjs +1 -1
  74. package/.output/server/chunks/_/ws.mjs +3 -3
  75. package/.output/server/chunks/nitro/nitro.mjs +15525 -15000
  76. package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
  77. package/.output/server/chunks/routes/api/_..._.mjs +2 -2
  78. package/.output/server/chunks/routes/api/agents.post.mjs +2 -2
  79. package/.output/server/chunks/routes/api/ask-tab.post.mjs +2 -2
  80. package/.output/server/chunks/routes/api/attach.post.mjs +2 -2
  81. package/.output/server/chunks/routes/api/auth/disable.post.mjs +11 -4
  82. package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +9 -3
  83. package/.output/server/chunks/routes/api/auth/lock.post.mjs +2 -2
  84. package/.output/server/chunks/routes/api/auth/login/options.post.mjs +4 -4
  85. package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +2 -2
  86. package/.output/server/chunks/routes/api/auth/max-session.post.mjs +2 -2
  87. package/.output/server/chunks/routes/api/auth/register/options.post.mjs +2 -2
  88. package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +2 -2
  89. package/.output/server/chunks/routes/api/auth/status.get.mjs +7 -7
  90. package/.output/server/chunks/routes/api/changes.get.mjs +3 -3
  91. package/.output/server/chunks/routes/api/chat/image.get.mjs +3 -3
  92. package/.output/server/chunks/routes/api/chat.get.mjs +17 -46
  93. package/.output/server/chunks/routes/api/choose.post.mjs +3 -3
  94. package/.output/server/chunks/routes/api/claude-setup.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/claude-statusline.post.mjs +3 -3
  96. package/.output/server/chunks/routes/api/clear-queued-input.post.mjs +3 -3
  97. package/.output/server/chunks/routes/api/close/status.get.mjs +3 -3
  98. package/.output/server/chunks/routes/api/close-preview.get.mjs +2 -2
  99. package/.output/server/chunks/routes/api/close.post.mjs +2 -2
  100. package/.output/server/chunks/routes/api/codex-update.post.mjs +3 -3
  101. package/.output/server/chunks/routes/api/commands.get.mjs +3 -3
  102. package/.output/server/chunks/routes/api/config.get.mjs +3 -3
  103. package/.output/server/chunks/routes/api/dirs.get.mjs +3 -3
  104. package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +3 -3
  105. package/.output/server/chunks/routes/api/dismiss.post.mjs +3 -3
  106. package/.output/server/chunks/routes/api/effort.post.mjs +3 -3
  107. package/.output/server/chunks/routes/api/efforts.get.mjs +3 -3
  108. package/.output/server/chunks/routes/api/file.post.mjs +3 -3
  109. package/.output/server/chunks/routes/api/files/download.get.mjs +2 -2
  110. package/.output/server/chunks/routes/api/files/download.head.mjs +2 -2
  111. package/.output/server/chunks/routes/api/files/read.get.mjs +3 -3
  112. package/.output/server/chunks/routes/api/files.get.mjs +3 -3
  113. package/.output/server/chunks/routes/api/health.get.mjs +2 -2
  114. package/.output/server/chunks/routes/api/input.post.mjs +3 -3
  115. package/.output/server/chunks/routes/api/interrupt.post.mjs +3 -3
  116. package/.output/server/chunks/routes/api/isgit.get.mjs +3 -3
  117. package/.output/server/chunks/routes/api/machine/awake.get.mjs +3 -3
  118. package/.output/server/chunks/routes/api/machine/awake.post.mjs +3 -3
  119. package/.output/server/chunks/routes/api/machine/order.get.mjs +2 -2
  120. package/.output/server/chunks/routes/api/machine/order.post.mjs +2 -2
  121. package/.output/server/chunks/routes/api/machine/reconnect.post.mjs +3 -3
  122. package/.output/server/chunks/routes/api/machine/rename.post.mjs +3 -3
  123. package/.output/server/chunks/routes/api/machine/status.post.mjs +3 -3
  124. package/.output/server/chunks/routes/api/menu-left.post.mjs +3 -3
  125. package/.output/server/chunks/routes/api/menu.post.mjs +3 -3
  126. package/.output/server/chunks/routes/api/model.post.mjs +3 -3
  127. package/.output/server/chunks/routes/api/models.get.mjs +3 -3
  128. package/.output/server/chunks/routes/api/nav.post.mjs +3 -3
  129. package/.output/server/chunks/routes/api/onboarding.get.mjs +2 -2
  130. package/.output/server/chunks/routes/api/onboarding.post.mjs +2 -2
  131. package/.output/server/chunks/routes/api/phone.get.mjs +3 -3
  132. package/.output/server/chunks/routes/api/phone.post.mjs +3 -3
  133. package/.output/server/chunks/routes/api/plugins/actions.get.mjs +2 -2
  134. package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +2 -2
  135. package/.output/server/chunks/routes/api/plugins/projects.get.mjs +3 -3
  136. package/.output/server/chunks/routes/api/plugins/projects.post.mjs +3 -3
  137. package/.output/server/chunks/routes/api/prompt.post.mjs +3 -3
  138. package/.output/server/chunks/routes/api/push/devices.post.mjs +3 -3
  139. package/.output/server/chunks/routes/api/push/quiet.post.mjs +3 -3
  140. package/.output/server/chunks/routes/api/push/subscribe.post.mjs +5 -4
  141. package/.output/server/chunks/routes/api/push/test.post.mjs +3 -3
  142. package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +3 -3
  143. package/.output/server/chunks/routes/api/quotas.get.mjs +3 -3
  144. package/.output/server/chunks/routes/api/rename.post.mjs +2 -2
  145. package/.output/server/chunks/routes/api/requeue.post.mjs +3 -3
  146. package/.output/server/chunks/routes/api/restart.get.mjs +2 -2
  147. package/.output/server/chunks/routes/api/restart.post.mjs +2 -2
  148. package/.output/server/chunks/routes/api/reveal.post.mjs +3 -3
  149. package/.output/server/chunks/routes/api/screen-key.post.mjs +3 -3
  150. package/.output/server/chunks/routes/api/screen.get.mjs +3 -3
  151. package/.output/server/chunks/routes/api/search.get.mjs +3 -3
  152. package/.output/server/chunks/routes/api/seen.post.mjs +3 -3
  153. package/.output/server/chunks/routes/api/send-now.post.mjs +3 -3
  154. package/.output/server/chunks/routes/api/sessions.get.mjs +3 -3
  155. package/.output/server/chunks/routes/api/sessions.post.mjs +3 -3
  156. package/.output/server/chunks/routes/api/settings-tab.post.mjs +3 -3
  157. package/.output/server/chunks/routes/api/settings.get.mjs +3 -3
  158. package/.output/server/chunks/routes/api/settings.post.mjs +3 -3
  159. package/.output/server/chunks/routes/api/space.post.mjs +3 -3
  160. package/.output/server/chunks/routes/api/split-command.post.mjs +3 -3
  161. package/.output/server/chunks/routes/api/state.get.mjs +3 -3
  162. package/.output/server/chunks/routes/api/tasks/action.post.mjs +3 -3
  163. package/.output/server/chunks/routes/api/tasks/add.post.mjs +3 -3
  164. package/.output/server/chunks/routes/api/tasks/after.post.mjs +3 -3
  165. package/.output/server/chunks/routes/api/tasks/approve.post.mjs +3 -3
  166. package/.output/server/chunks/routes/api/tasks/archive-done.post.mjs +3 -3
  167. package/.output/server/chunks/routes/api/tasks/archived.get.mjs +3 -3
  168. package/.output/server/chunks/routes/api/tasks/autopilot.get.mjs +3 -3
  169. package/.output/server/chunks/routes/api/tasks/autopilot.post.mjs +3 -3
  170. package/.output/server/chunks/routes/api/tasks/board-settings.get.mjs +3 -3
  171. package/.output/server/chunks/routes/api/tasks/board-settings.post.mjs +3 -3
  172. package/.output/server/chunks/routes/api/tasks/coordinator.get.mjs +3 -3
  173. package/.output/server/chunks/routes/api/tasks/coordinator.post.mjs +3 -3
  174. package/.output/server/chunks/routes/api/tasks/describe.post.mjs +3 -3
  175. package/.output/server/chunks/routes/api/tasks/details.get.mjs +3 -3
  176. package/.output/server/chunks/routes/api/tasks/limit.post.mjs +3 -3
  177. package/.output/server/chunks/routes/api/tasks/links.get.mjs +4 -4
  178. package/.output/server/chunks/routes/api/tasks/models.get.mjs +3 -3
  179. package/.output/server/chunks/routes/api/tasks/pick.post.mjs +3 -3
  180. package/.output/server/chunks/routes/api/tasks/project.get.mjs +3 -3
  181. package/.output/server/chunks/routes/api/tasks/project.post.mjs +3 -3
  182. package/.output/server/chunks/routes/api/tasks/question.post.mjs +3 -3
  183. package/.output/server/chunks/routes/api/tasks/scheduled.get.mjs +3 -3
  184. package/.output/server/chunks/routes/api/tasks/settings.get.mjs +3 -3
  185. package/.output/server/chunks/routes/api/tasks/start.get.mjs +3 -3
  186. package/.output/server/chunks/routes/api/tasks/tell.post.mjs +3 -3
  187. package/.output/server/chunks/routes/api/tasks/transcript-image.get.mjs +47 -0
  188. package/.output/server/chunks/routes/api/tasks/transcript.get.mjs +48 -0
  189. package/.output/server/chunks/routes/api/tasks.get.mjs +3 -3
  190. package/.output/server/chunks/routes/api/unqueue.post.mjs +3 -3
  191. package/.output/server/chunks/routes/api/update/status.get.mjs +2 -2
  192. package/.output/server/chunks/routes/api/update.get.mjs +2 -2
  193. package/.output/server/chunks/routes/api/update.post.mjs +2 -2
  194. package/.output/server/chunks/routes/api/upload.post.mjs +3 -3
  195. package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +2 -2
  196. package/.output/server/chunks/routes/api/worktrees.get.mjs +2 -2
  197. package/.output/server/chunks/routes/favicon.ico.get.mjs +2 -2
  198. package/.output/server/chunks/routes/icons/_name_.get.mjs +3 -3
  199. package/.output/server/chunks/routes/renderer.mjs +4 -4
  200. package/.output/server/chunks/routes/uploads/_...name_.get.mjs +3 -3
  201. package/.output/server/chunks/routes/ws/_..._.mjs +3 -3
  202. package/.output/server/chunks/routes/ws/events.mjs +3 -3
  203. package/.output/server/chunks/routes/ws/term.mjs +3 -3
  204. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  205. package/.output/server/index.mjs +3 -3
  206. package/.output/server/package.json +1 -1
  207. package/README.md +1 -1
  208. package/bin/lib/tailnet.d.mts +7 -4
  209. package/bin/lib/tailnet.mjs +76 -18
  210. package/bin/lib/updater.mjs +6 -0
  211. package/docs/README.md +2 -0
  212. package/docs/conversation.md +9 -0
  213. package/docs/home.md +29 -0
  214. package/docs/installation.md +14 -5
  215. package/docs/networks.md +9 -4
  216. package/docs/plugins.md +1 -1
  217. package/docs/quick-start.md +7 -6
  218. package/docs/quotas.md +6 -3
  219. package/docs/release-notes-2.6.0.md +29 -0
  220. package/docs/security.md +54 -11
  221. package/docs/troubleshooting.md +4 -0
  222. package/package.json +1 -1
  223. package/.output/public/_nuxt/1gzTzt3j.js +0 -9
  224. package/.output/public/_nuxt/1gzTzt3j.js.br +0 -0
  225. package/.output/public/_nuxt/1gzTzt3j.js.gz +0 -0
  226. package/.output/public/_nuxt/AgentView.B6zltno1.css.br +0 -0
  227. package/.output/public/_nuxt/AgentView.B6zltno1.css.gz +0 -0
  228. package/.output/public/_nuxt/BdJIc1Xf.js.gz +0 -0
  229. package/.output/public/_nuxt/BrxmYJEM.js +0 -1
  230. package/.output/public/_nuxt/BrxmYJEM.js.br +0 -0
  231. package/.output/public/_nuxt/BrxmYJEM.js.gz +0 -0
  232. package/.output/public/_nuxt/C6fXOTRV.js +0 -3
  233. package/.output/public/_nuxt/C6fXOTRV.js.br +0 -0
  234. package/.output/public/_nuxt/C6fXOTRV.js.gz +0 -0
  235. package/.output/public/_nuxt/CXbAL3Yu.js.br +0 -0
  236. package/.output/public/_nuxt/CXbAL3Yu.js.gz +0 -0
  237. package/.output/public/_nuxt/Cf1C5Vkb.js +0 -27
  238. package/.output/public/_nuxt/Cf1C5Vkb.js.br +0 -0
  239. package/.output/public/_nuxt/Cf1C5Vkb.js.gz +0 -0
  240. package/.output/public/_nuxt/CgUSTIM1.js.gz +0 -0
  241. package/.output/public/_nuxt/CmTpxyM2.js +0 -62
  242. package/.output/public/_nuxt/CmTpxyM2.js.br +0 -0
  243. package/.output/public/_nuxt/CmTpxyM2.js.gz +0 -0
  244. package/.output/public/_nuxt/DMzjoyW_.js.br +0 -0
  245. package/.output/public/_nuxt/DMzjoyW_.js.gz +0 -0
  246. package/.output/public/_nuxt/DOVT2Tt8.js.br +0 -0
  247. package/.output/public/_nuxt/DOVT2Tt8.js.gz +0 -0
  248. package/.output/public/_nuxt/PjGJWal8.js.br +0 -0
  249. package/.output/public/_nuxt/PjGJWal8.js.gz +0 -0
  250. package/.output/public/_nuxt/WPcHpWhL.js +0 -31
  251. package/.output/public/_nuxt/WPcHpWhL.js.br +0 -0
  252. package/.output/public/_nuxt/WPcHpWhL.js.gz +0 -0
  253. package/.output/public/_nuxt/builds/meta/d4aab09d-c1c4-4743-b8aa-35541006e853.json +0 -1
  254. package/.output/public/_nuxt/entry.DosS87kQ.css +0 -2
  255. package/.output/public/_nuxt/entry.DosS87kQ.css.br +0 -0
  256. package/.output/public/_nuxt/entry.DosS87kQ.css.gz +0 -0
  257. package/.output/public/_nuxt/nfsDZG4P.js +0 -123
  258. package/.output/public/_nuxt/nfsDZG4P.js.br +0 -0
  259. package/.output/public/_nuxt/nfsDZG4P.js.gz +0 -0
  260. package/.output/public/_nuxt/tYQOxjM1.js +0 -1
  261. package/.output/public/_nuxt/tYQOxjM1.js.br +0 -0
  262. package/.output/public/_nuxt/tYQOxjM1.js.gz +0 -0
@@ -1,7 +1,7 @@
1
1
  import { b as base64ToUint8Array } from '../virtual/_raw-helpers.mjs';
2
2
 
3
3
  // ROLLUP_NO_REPLACE
4
- const herdrPlugin = base64ToUint8Array("IyEvYmluL3NoCiMgd2hlcmRyIGFzIGEgSGVyZHIgcGx1Z2luIChoZXJkci1wbHVnaW4udG9tbCk6IGJ1aWxkIChpbnN0YWxsICsgZmlyc3Qgc3RhcnQpLAojIHRoZSBwYW5lbCwgc3RhcnQsIHN0b3AsIHN0YXR1cywgb3BlbiwgdXBkYXRlLCBzZXJ2aWNlLCBza2lsbCwga2V5LgojCiMgICBoZXJkciBwbHVnaW4gaW5zdGFsbCA8b3duZXI+L3doZXJkcgojCiMgSGVyZHIgYnVpbGRzIGEgcGx1Z2luIGluIGEgdGVtcG9yYXJ5IGZvbGRlciwgdGhlbiBtb3ZlcyBpdDogYSBzZXJ2ZXIgc3RhcnRlZAojIGZyb20gdGhlIGNoZWNrb3V0IGR1cmluZyB0aGUgYnVpbGQgd291bGQgbG9zZSBpdHMgZmlsZXMuICRXSEVSRFJfRElSL2FwcAojIHN0YXlzIHB1dCwgYWNyb3NzIHBsdWdpbiB1cGRhdGVzIHRvbywgc28gdGhlIGJ1aWxkIGNhbiBzdGFydCB3aGVyZHIgYW5kIGEKIyBsb2dpbiBzZXJ2aWNlIGNhbiBwb2ludCBhdCBpdC4KIyBTYWZldHkgcnVsZXM6CiMgICAtIG5vdGhpbmcgZ2xvYmFsIGlzIGluc3RhbGxlZCwgbm8gc3VkbzsgZmlsZXMgYXJlIG9ubHkgd3JpdHRlbiB0byB0aGUKIyAgICAgcGx1Z2luIGZvbGRlciBhbmQgJFdIRVJEUl9ESVIgKGRlZmF1bHQgfi93aGVyZHIpLCBhbmQgdGhlCiMgICAgIGxvZ2luIHNlcnZpY2Ugb25seSB3aGVuIGFza2VkIChrZXkgQSBvZiB0aGUgcGFuZWwpLCBwbHVzIGEgIndoZXJkciIKIyAgICAgbGluayBpbiB0aGUgYWdlbnRzJyB1c2VyIHNraWxsIGZvbGRlcnMgKHNlZSBjbWRfc2tpbGwpLCBwbHVzIG9uZSBtYXJrZWQKIyAgICAgYmxvY2sgYXBwZW5kZWQgdG8gSGVyZHIncyBjb25maWcudG9tbDogdGhlIGtleSB0aGF0IG9wZW5zIHRoZSBwYW5lbAojICAgICAoc2VlIGNtZF9rZXkpOwojICAgLSB0aGUgaW5zdGFsbCBzdGFydHMgd2hlcmRyLCBhbmQgSGVyZHIncyBzdGFydHVwIGhvb2sgc3RhcnRzIGl0IGFnYWluLAojICAgICBidXQgb25seSB3aGVuIG5vdGhpbmcgYW5zd2VycyBvbiB0aGUgcG9ydDogYSB3aGVyZHIgc3RhcnRlZCBhbm90aGVyIHdheQojICAgICAoc3lzdGVtZCwgYnkgaGFuZCkgaXMgbmV2ZXIgdG91Y2hlZCwgbm8gc2Vjb25kIHdoZXJkciBpcyBzdGFydGVkOwojICAgLSBzdG9wIG9ubHkgc3RvcHMgd2hhdCB0aGlzIHBsdWdpbiBzdGFydGVkIChpdHMgcGlkIG9yIGl0cyBsb2dpbiBzZXJ2aWNlKS4KIwojIFVuaW5zdGFsbDogSGVyZHIgaGFzIG5vIHVuaW5zdGFsbCBob29rLiBTdG9wIHdoZXJkciAoYW5kIHJlbW92ZSB0aGUgbG9naW4KIyBzZXJ2aWNlKSBmcm9tIHRoZSBwYW5lbCBmaXJzdCwgdGhlbjoKIyAgIHNoIHNjcmlwdHMvaGVyZHItcGx1Z2luLnNoIHNraWxsIHVuaW5zdGFsbCAgIChpbiB0aGUgcGx1Z2luIGZvbGRlcikKIyAgIHNoIHNjcmlwdHMvaGVyZHItcGx1Z2luLnNoIGtleSB1bmluc3RhbGwgICAgICh0aGUgSGVyZHIga2V5IG9mIHRoZSBwYW5lbCkKIyAgIGhlcmRyIHBsdWdpbiB1bmluc3RhbGwgPG93bmVyPi53aGVyZHIgJiYgcm0gLXJmIH4vd2hlcmRyCiMKIyBTZXR0aW5ncyAoJFdIRVJEUl9ESVIvcGx1Z2luLmVudiwgb3IgdGhlIGVudmlyb25tZW50KToKIyAgIFdIRVJEUl9QT1JUICBsb2NhbCBwb3J0ICAgICAgICAgICAgICAoZGVmYXVsdDogNzY4MykKIyAgIEFQUF9VUkwgICAgICBwcml2YXRlIEhUVFBTIGFkZHJlc3MKIyAgIFdIRVJEUl9SVU5USU1FICBhYnNvbHV0ZSBwYXRoIG9mIG5vZGUgLyBidW4gKGZvdW5kIGF0IGluc3RhbGwpCgpzZXQgLWV1CgpST09UPSIkKGNkICIkKGRpcm5hbWUgIiQwIikvLi4iICYmIHB3ZCAtUCkiCiMgQnVpbGQgY29tbWFuZHMgZ2V0IG5vIHBsdWdpbiBlbnZpcm9ubWVudDogdGhlIGZvbGRlciBjaG9zZW4gYXQgaW5zdGFsbAojIHRpbWUgaXMgcmVtZW1iZXJlZCBpbiB0aGUgcGx1Z2luIGNoZWNrb3V0IGZvciB0aGUgcnVudGltZSBjb21tYW5kcy4KaWYgWyAteiAiJHtXSEVSRFJfRElSOi19IiBdICYmIFsgLWYgIiRST09ULy53aGVyZHItZGlyIiBdOyB0aGVuCiAgV0hFUkRSX0RJUj0iJChjYXQgIiRST09ULy53aGVyZHItZGlyIikiCmZpCkRJUj0iJHtXSEVSRFJfRElSOi0kSE9NRS93aGVyZHJ9IgpjYXNlICIkRElSIiBpbiAvKikgOzsgKikgRElSPSIkUFdELyRESVIiIDs7IGVzYWMKQ09ORj0iJERJUi9wbHVnaW4uZW52IgojIE5hdGl2ZSBtb2RlOiB0aGUgaW5zdGFsbGVkIGNvcHkgb2Ygd2hlcmRyIChiaW4gKyBidWlsdCBzZXJ2ZXIpLgpBUFA9IiRESVIvYXBwIgojIEdpdEh1YiBzb3VyY2Ugb2YgdGhpcyBwbHVnaW46IGl0cyBtYW5pZmVzdCBpZCB3aXRoICIvIiBmb3IgIi4iIChvd25lci53aGVyZHIpLgpTT1VSQ0U9IiQoc2VkIC1uICdzL15pZCA9ICJcKC4qXCkiJC9cMS9wJyAiJFJPT1QvaGVyZHItcGx1Z2luLnRvbWwiIHwgaGVhZCAtbiAxIHwgdHIgLiAvKSIKIyBUaGUgZW52aXJvbm1lbnQgd2lucyBvdmVyIHBsdWdpbi5lbnYuCkVOVl9QT1JUPSIke1dIRVJEUl9QT1JUOi19IiBFTlZfQVBQX1VSTD0iJHtBUFBfVVJMOi19IiBFTlZfUlVOVElNRT0iJHtXSEVSRFJfUlVOVElNRTotfSIKaWYgWyAtZiAiJENPTkYiIF07IHRoZW4KICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzEwOTAKICAuICIkQ09ORiIKZmkKTEVHQUNZX01PREU9IiR7V0hFUkRSX01PREU6LX0iClBPUlQ9IiR7RU5WX1BPUlQ6LSR7V0hFUkRSX1BPUlQ6LTc2ODN9fSIKQVBQX1VSTD0iJHtFTlZfQVBQX1VSTDotJHtBUFBfVVJMOi19fSIKIyBOYXRpdmUgbW9kZTogYWJzb2x1dGUgcGF0aCBvZiB0aGUgbm9kZSAob3IgYnVuKSB0aGF0IHJ1bnMgdGhlIHNlcnZlci4gSGVyZHIKIyBydW5zIGFjdGlvbnMgd2l0aCBpdHMgc2VydmVyJ3MgUEFUSCwgd2hpY2ggb2Z0ZW4gbGFja3MgbnZtIC8gbiAvIGZubSBmb2xkZXJzLgpSVU5USU1FPSIke0VOVl9SVU5USU1FOi0ke1dIRVJEUl9SVU5USU1FOi19fSIKVVJMPSJodHRwOi8vbG9jYWxob3N0OiRQT1JUIgoKc2F5KCkgeyBwcmludGYgJyVzXG4nICIkKiI7IH0Kb2soKSB7IHByaW50ZiAnICDinJMgJXNcbicgIiQqIjsgfQp3YXJuKCkgeyBwcmludGYgJyAgISAlc1xuJyAiJCoiID4mMjsgfQpkaWUoKSB7IHByaW50ZiAnICDinJcgJXNcbicgIiQqIiA+JjI7IGV4aXQgMTsgfQoKIyBBbnkgSFRUUCBhbnN3ZXIgY291bnRzIChhIGxvY2tlZCB3aGVyZHIgYW5zd2VycyA0MDEpOiB0aGUgcG9ydCBpcyB0YWtlbi4KYW5zd2VycygpIHsKICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICBjb2RlPSIkKGN1cmwgLXMgLW8gL2Rldi9udWxsIC0tbWF4LXRpbWUgMiAtdyAnJXtodHRwX2NvZGV9JyAiaHR0cDovLzEyNy4wLjAuMTokUE9SVC8iIDI+L2Rldi9udWxsIHx8IHRydWUpIgogICAgWyAtbiAiJGNvZGUiIF0gJiYgWyAiJGNvZGUiICE9ICIwMDAiIF0KICBlbGlmIGNvbW1hbmQgLXYgbmMgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICBuYyAteiAxMjcuMC4wLjEgIiRQT1JUIiA+L2Rldi9udWxsIDI+JjEKICBlbHNlCiAgICBkaWUgImN1cmwgb3IgbmMgaXMgbmVlZGVkIHRvIGNoZWNrIHBvcnQgJFBPUlQuIgogIGZpCn0KCiMgTWFqb3IgdmVyc2lvbiBvZiBhIG5vZGUgYmluYXJ5LCAwIHdoZW4gaXQgaXMgbm90IG9uZS4Kbm9kZV9tYWpvcigpIHsKICAiJDEiIC1wICdwcm9jZXNzLnZlcnNpb25zLm5vZGUuc3BsaXQoIi4iKVswXScgMj4vZGV2L251bGwgfHwgZWNobyAwCn0KCiMgQSB1c2FibGUgcnVudGltZTogTm9kZS5qcyAyMiBvciBuZXdlciwgb3IgQnVuIChpdCBydW5zIHRoZSBidWlsdCBzZXJ2ZXIgdG9vKS4KcnVudGltZV9vaygpIHsKICBbIC1uICIkMSIgXSAmJiBbIC14ICIkMSIgXSAmJiBbICEgLWQgIiQxIiBdIHx8IHJldHVybiAxCiAgY2FzZSAiJChiYXNlbmFtZSAiJDEiKSIgaW4KICAgIGJ1bikgIiQxIiAtLXZlcnNpb24gPi9kZXYvbnVsbCAyPiYxIDs7CiAgICAqKSBbICIkKG5vZGVfbWFqb3IgIiQxIikiIC1nZSAyMiBdIDI+L2Rldi9udWxsIDs7CiAgZXNhYwp9CgojIEFic29sdXRlIHBhdGggb2YgdGhlIHJ1bnRpbWU6IFdIRVJEUl9SVU5USU1FLCB0aGVuIG5vZGUgb24gdGhlIFBBVEgsIHRoZW4gdGhlCiMgdXN1YWwgaW5zdGFsbCBmb2xkZXJzIChuLCBudm0sIFZvbHRhLCBmbm0sIGFzZGYsIEhvbWVicmV3KSwgdGhlbiBCdW4uCiMgUHJpbnRzIG5vdGhpbmcgYW5kIGZhaWxzIHdoZW4gbm9uZSBpcyBmb3VuZC4KZmluZF9ydW50aW1lKCkgewogIGZvciBjIGluICIkUlVOVElNRSIgIiQoY29tbWFuZCAtdiBub2RlIDI+L2Rldi9udWxsIHx8IHRydWUpIiBcCiAgICAiJEhPTUUvLm4vYmluL25vZGUiICIke05fUFJFRklYOiskTl9QUkVGSVgvYmluL25vZGV9IiBcCiAgICAkKGxzIC1kICIkSE9NRSIvLm52bS92ZXJzaW9ucy9ub2RlL3YqL2Jpbi9ub2RlIDI+L2Rldi9udWxsIHwgc29ydCAtciAtVikgXAogICAgIiRIT01FLy52b2x0YS9iaW4vbm9kZSIgXAogICAgJChscyAtZCAiJEhPTUUiLy5sb2NhbC9zaGFyZS9mbm0vbm9kZS12ZXJzaW9ucy8qL2luc3RhbGxhdGlvbi9iaW4vbm9kZSAiJEhPTUUiLy5mbm0vbm9kZS12ZXJzaW9ucy8qL2luc3RhbGxhdGlvbi9iaW4vbm9kZSAyPi9kZXYvbnVsbCB8IHNvcnQgLXIgLVYpIFwKICAgICIkSE9NRS8uYXNkZi9zaGltcy9ub2RlIiAvb3B0L2hvbWVicmV3L2Jpbi9ub2RlIC91c3IvbG9jYWwvYmluL25vZGUgL3Vzci9iaW4vbm9kZSBcCiAgICAiJChjb21tYW5kIC12IGJ1biAyPi9kZXYvbnVsbCB8fCB0cnVlKSIgIiRIT01FLy5idW4vYmluL2J1biIgL29wdC9ob21lYnJldy9iaW4vYnVuIC91c3IvbG9jYWwvYmluL2J1bjsgZG8KICAgIGlmIHJ1bnRpbWVfb2sgIiRjIjsgdGhlbiBlY2hvICIkYyI7IHJldHVybiAwOyBmaQogIGRvbmUKICByZXR1cm4gMQp9CgpSVU5USU1FX0hFTFA9Ik5vZGUuanMgMjIgb3IgbmV3ZXIgKG9yIEJ1bikgaXMgcmVxdWlyZWQgdG8gcnVuIHdoZXJkci4KICAgICBJbnN0YWxsIGl0IGZyb20gaHR0cHM6Ly9ub2RlanMub3JnLCBvciBzZXQgaXRzIGFic29sdXRlIHBhdGggaW4gJENPTkY6CiAgICAgICBXSEVSRFJfUlVOVElNRT0vcGF0aC90by9ub2RlIgoKaGVyZHJfYmluKCkgewogIGlmIFsgLW4gIiR7SEVSRFJfQklOX1BBVEg6LX0iIF07IHRoZW4gZWNobyAiJEhFUkRSX0JJTl9QQVRIIgogIGVsaWYgWyAteCAiJEhPTUUvLmxvY2FsL2Jpbi9oZXJkciIgXTsgdGhlbiBlY2hvICIkSE9NRS8ubG9jYWwvYmluL2hlcmRyIgogIGVsc2UgY29tbWFuZCAtdiBoZXJkciAyPi9kZXYvbnVsbCB8fCBlY2hvIGhlcmRyCiAgZmkKfQoKIyBUaGUgY29tbWFuZHMgb2YgdGhlIG5hdGl2ZSBtb2RlOiB0aGUgaW5zdGFsbGVkIGNvcHksIG9yIHRoZSBjaGVja291dCBpdHNlbGYKIyAoYSBsaW5rZWQgcGx1Z2luIGJ1aWx0IGJ5IGhhbmQsIG9yIGEgcGx1Z2luIGluc3RhbGxlZCBiZWZvcmUgJEFQUCBleGlzdGVkKS4KY2xpX3Jvb3QoKSB7CiAgaWYgWyAtZiAiJEFQUC9iaW4vd2hlcmRyLm1qcyIgXSAmJiBbIC1mICIkQVBQLy5vdXRwdXQvc2VydmVyL2luZGV4Lm1qcyIgXTsgdGhlbiBlY2hvICIkQVBQIjsgZWxzZSBlY2hvICIkUk9PVCI7IGZpCn0KCiMgVGhlIHBlcnNvbiBydW5uaW5nIGBoZXJkciBwbHVnaW4gaW5zdGFsbGAgc2VlcyBvbmx5IEhlcmRyJ3Mgb3duIGxpbmVzOiB0aGUKIyBvdXRwdXQgb2YgYnVpbGQgY29tbWFuZHMgaXMgY2FwdHVyZWQuIEltcG9ydGFudCBsaW5lcyBhbHNvIGdvIHRvIHRoZSB0ZXJtaW5hbC4KdGVsbCgpIHsKICBwcmludGYgJyVzXG4nICIkKiIKICB7IHByaW50ZiAnJXNcbicgIiQqIiA+IC9kZXYvdHR5OyB9IDI+L2Rldi9udWxsIHx8IHRydWUKfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gYnVpbGQKY21kX2J1aWxkKCkgewogIHRlbGwgIndoZXJkcjogaW5zdGFsbGluZyBpbiAkRElSIgogICMgRmlyc3QgaW5zdGFsbCAobm8gcGx1Z2luLmVudiB5ZXQpOiB0aGUgYnJvd3NlciBvcGVucyBvbiB0aGUgc2V0dXAgZ3VpZGUKICAjIG9uY2Ugd2hlcmRyIHJ1bnMuIFVwZGF0ZXMga2VlcCBwbHVnaW4uZW52IGFuZCBvcGVuIG5vdGhpbmcuCiAgRklSU1RfSU5TVEFMTD0wCiAgWyAtZiAiJENPTkYiIF0gfHwgRklSU1RfSU5TVEFMTD0xCiAgbWtkaXIgLXAgIiRESVIiCiAgcHJpbnRmICclc1xuJyAiJERJUiIgPiAiJFJPT1QvLndoZXJkci1kaXIiCgogIGlmIFsgIiRMRUdBQ1lfTU9ERSIgPSBkb2NrZXIgXTsgdGhlbgogICAgdGVsbCAid2hlcmRyIDIuMCByZW1vdmVzIERvY2tlciBzdXBwb3J0OiBzd2l0Y2hpbmcgdGhpcyBwbHVnaW4gdG8gdGhlIG5hdGl2ZSBzZXJ2aWNlLiIKICAgIHRlbGwgIlN0b3AgdGhlIG9sZCAxLnggaW5zdGFuY2UgYmVmb3JlIHN0YXJ0aW5nIHRoZSBuYXRpdmUgc2VydmljZTsga2VlcCBpdHMgZGF0YSBmb2xkZXIuIgogICAgdGVsbCAiTWlncmF0aW9uOiBodHRwczovL2dpdGh1Yi5jb20vJFNPVVJDRS9ibG9iL21haW4vZG9jcy9taWdyYXRlLWZyb20tMS54LWRvY2tlci5tZCIKICBmaQogIGJ1aWxkX25hdGl2ZQogICMgV3JpdHRlbiBsYXN0OiBhIGZhaWxlZCBidWlsZCBrZWVwcyBubyBoYWxmLW1hZGUgY2hvaWNlLiBSZXdyaXR0ZW4gb24gZWFjaAogICMgaW5zdGFsbCBmcm9tIHRoZSBtZXJnZWQgc2V0dGluZ3MgKGVudmlyb25tZW50IG92ZXIgdGhlIHByZXZpb3VzIGZpbGUpLgogIHdyaXRlX2NvbmYKICBvayAicGx1Z2luLmVudiB3cml0dGVuIChuYXRpdmUgc2VydmljZSkiCiAgKCBjbWRfc2tpbGwgcmVmcmVzaCApIHx8IHdhcm4gIndoZXJkciBza2lsbCBub3QgbGlua2VkIChvcHRpb25hbCk6IHJ1biAkMCBza2lsbCBpbnN0YWxsIgogICggY21kX2tleSBpbnN0YWxsICkgfHwgd2FybiAibm8gSGVyZHIga2V5IGZvciB0aGUgcGFuZWwgKG9wdGlvbmFsKTogcnVuICQwIGtleSBpbnN0YWxsIgogIGJ1aWxkX3N0YXJ0Cn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHNraWxsCiMgSW5zdGFsbGF0aW9uIGlzIHNoYXJlZCB3aXRoIG5wbSAvIEhvbWVicmV3LgpjbWRfc2tpbGwoKSB7CiAgY2FzZSAiJHsxOi19IiBpbgogICAgcmVmcmVzaHxpbnN0YWxsKQogICAgICBXSEVSRFJfRElSPSIkRElSIiBzaCAiJFJPT1QvYmluL2xpYi9pbnN0YWxsLXNraWxsLnNoIiAiJDEiICIkUk9PVCIKICAgICAgOzsKICAgIHVuaW5zdGFsbCkgV0hFUkRSX0RJUj0iJERJUiIgc2ggIiRST09UL2Jpbi9saWIvaW5zdGFsbC1za2lsbC5zaCIgdW5pbnN0YWxsICIkUk9PVCIgOzsKICAgICopIGRpZSAidXNhZ2U6ICQwIHNraWxsIGluc3RhbGx8dW5pbnN0YWxsIiA7OwogIGVzYWMKfQoKIyBMYXN0IHN0ZXAgb2YgdGhlIGluc3RhbGw6IHN0YXJ0IHdoZXJkciAob3IgcmVzdGFydCB0aGUgb25lIHRoaXMgcGx1Z2luCiMgcnVucywgb24gYW4gdXBkYXRlKS4gTmV2ZXIgZmFpbHMgdGhlIGluc3RhbGw6IGEgd2hlcmRyIHRoYXQgY2Fubm90IHN0YXJ0IGlzCiMgcmVwb3J0ZWQgd2l0aCB3aGF0IHRvIGRvLCB0aGUgcGx1Z2luIHN0YXlzIGluc3RhbGxlZC4KYnVpbGRfc3RhcnQoKSB7CiAgc2V0ICtlCiAgb3V0PSIkKCAoY21kX3N0YXJ0KSAyPiYxICkiCiAgY29kZT0kPwogIHNldCAtZQogIHByaW50ZiAnJXNcbicgIiRvdXQiCiAgaWYgWyAiJGNvZGUiIC1lcSAwIF0gJiYgYW5zd2VyczsgdGhlbgogICAgIyBodHRwczovL3doZXJkci5kZXYvaW5zdGFsbCBwcmludHMgaXRzIG93biBzdW1tYXJ5IChXSEVSRFJfSU5TVEFMTEVSPTEpLgogICAgcXVpZXQ9MAogICAgWyAiJHtXSEVSRFJfSU5TVEFMTEVSOi0wfSIgPSAxIF0gJiYgcXVpZXQ9MQogICAgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIiCiAgICBbICIkcXVpZXQiID0gMSBdIHx8IHRlbGwgIuKckyB3aGVyZHIgaXMgcnVubmluZyDihpIgJFVSTCIKICAgIGlmIFsgIiRxdWlldCIgIT0gMSBdOyB0aGVuCiAgICAgIGtleT0iJChrZXlfYm91bmQpIgogICAgICBpZiBbIC1uICIka2V5IiBdOyB0aGVuIHRlbGwgIiAgSW4gSGVyZHIsICRrZXkgb3BlbnMgdGhlIHdoZXJkciBwYW5lbC4iCiAgICAgIGVsc2UgdGVsbCAiICBJbiBIZXJkcjogaGVyZHIgcGx1Z2luIGFjdGlvbiBpbnZva2UgcGFuZWwgLS1wbHVnaW4gJFBMVUdJTl9JRCIKICAgICAgZmkKICAgIGZpCiAgICBpZiBbICIke0ZJUlNUX0lOU1RBTEw6LTB9IiA9IDEgXTsgdGhlbgogICAgICAjIEFscmVhZHkgcHVibGlzaGVkIG9uIHRoZSB0YWlsbmV0IChhIHJlaW5zdGFsbCwgb3IgYHRhaWxzY2FsZSBzZXJ2ZWAKICAgICAgIyBydW4gZmlyc3QpOiB0aGUgZ3VpZGUgb3BlbnMgb24gdGhhdCBhZGRyZXNzLCB3aGVyZSBwYXNza2V5cyBiZWxvbmcuCiAgICAgIGd1aWRlPSIkKG9wZW5fYWRkcmVzcykvIy9zZXR1cCIKICAgICAgaWYgb3Blbl9icm93c2VyICIkZ3VpZGUiOyB0aGVuIFsgIiRxdWlldCIgPSAxIF0gfHwgdGVsbCAiICBTZXR1cCBndWlkZSBvcGVuZWQgaW4geW91ciBicm93c2VyOiAkZ3VpZGUiCiAgICAgIGVsc2UgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIgIFNldHVwIGd1aWRlOiBvcGVuICRndWlkZSBpbiBhIGJyb3dzZXIiCiAgICAgIGZpCiAgICBmaQogICAgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIgIFBob25lOiBwcmVzcyBQIGluIHRoZSBwYW5lbCB0byBnZXQgeW91ciBUYWlsc2NhbGUgYWRkcmVzcyAocHJpdmF0ZSBuZXR3b3JrIG9ubHkpLiIKICBlbHNlCiAgICB0ZWxsICIiCiAgICB0ZWxsICIhIHdoZXJkciBpcyBpbnN0YWxsZWQgYnV0IGRpZCBub3Qgc3RhcnQ6IgogICAgcHJpbnRmICclc1xuJyAiJG91dCIgfCB0YWlsIC1uIDggfCB3aGlsZSBJRlM9IHJlYWQgLXIgbDsgZG8gdGVsbCAiICAgICRsIjsgZG9uZQogICAgdGVsbCAiICBPcGVuIHRoZSB3aGVyZHIgcGFuZWwgaW4gSGVyZHIsIHRoZW4gcHJlc3MgUyB0byBzdGFydCBpdCBvciBMIGZvciBpdHMgbG9nLiIKICBmaQp9Cgp3cml0ZV9jb25mKCkgewogIHsKICAgIGVjaG8gIiMgd2hlcmRyIEhlcmRyIHBsdWdpbiBzZXR0aW5ncyAoaGVyZHItcGx1Z2luLnNoKS4iCiAgICBlY2hvICJXSEVSRFJfUE9SVD0kUE9SVCIKICAgIGVjaG8gIiMgTmF0aXZlIG1vZGU6IHByaXZhdGUgSFRUUFMgYWRkcmVzcyAodGFpbHNjYWxlIHNlcnZlKSwgZm9yIHB1c2ggbm90aWZpY2F0aW9ucy4iCiAgICBlY2hvICJBUFBfVVJMPSR7QVBQX1VSTDotfSIKICAgIGVjaG8gIiMgQWJzb2x1dGUgcGF0aCBvZiB0aGUgbm9kZSAoMjIrKSBvciBidW4gdGhhdCBydW5zIHdoZXJkci4iCiAgICBlY2hvICJXSEVSRFJfUlVOVElNRT0kUlVOVElNRSIKICB9ID4gIiRDT05GIgp9CgojIFByZWZlciB0aGUgcmVsZWFzZSBhcmNoaXZlLCB0aGVuIHRoZSBhbHJlYWR5LWJ1aWx0IG5wbSBwYWNrYWdlLiBDb21waWxlIG9ubHkKIyB3aGVuIG5laXRoZXIgc291cmNlIHByb3ZpZGVzIGEgdXNhYmxlIHBhY2thZ2Ugb2YgdGhpcyBleGFjdCB2ZXJzaW9uLgpmZXRjaF9wcmVidWlsdCgpIHsKICBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxICYmIGNvbW1hbmQgLXYgdGFyID4vZGV2L251bGwgMj4mMSB8fCByZXR1cm4gMQogIHZlcnNpb249IiQoc2VkIC1uICdzL152ZXJzaW9uID0gIlwoLipcKSIkL1wxL3AnICIkUk9PVC9oZXJkci1wbHVnaW4udG9tbCIgfCBoZWFkIC1uIDEpIgogIHRtcD0iJChta3RlbXAgLWQpIgogIGZvciBzb3VyY2UgaW4gZ2l0aHViIG5wbTsgZG8KICAgIHJtIC1yZiAiJHRtcC9wYWNrYWdlIgogICAgaWYgWyAiJHNvdXJjZSIgPSBnaXRodWIgXTsgdGhlbgogICAgICB1cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS8kU09VUkNFL3JlbGVhc2VzL2Rvd25sb2FkL3YkdmVyc2lvbi93aGVyZHItJHZlcnNpb24udGd6IgogICAgICBjdXJsIC1mc1NMIC0tbWF4LXRpbWUgMTIwICIkdXJsIiAtbyAiJHRtcC93aGVyZHIudGd6IiAyPi9kZXYvbnVsbCBcCiAgICAgICAgJiYgY3VybCAtZnNTTCAtLW1heC10aW1lIDMwICIkdXJsLnNoYTI1NiIgLW8gIiR0bXAvY2hlY2tzdW0iIDI+L2Rldi9udWxsIFwKICAgICAgICAmJiAiJFJVTlRJTUUiICIkUk9PVC9iaW4vbGliL3ZlcmlmeS1yZWxlYXNlLm1qcyIgIiR0bXAvd2hlcmRyLnRneiIgIiR0bXAvY2hlY2tzdW0iIDI+L2Rldi9udWxsIHx8IGNvbnRpbnVlCiAgICBlbHNlCiAgICAgIHVybD0iaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvd2hlcmRyLy0vd2hlcmRyLSR2ZXJzaW9uLnRneiIKICAgICAgY3VybCAtZnNTTCAtLW1heC10aW1lIDEyMCAiJHVybCIgLW8gIiR0bXAvd2hlcmRyLnRneiIgMj4vZGV2L251bGwgXAogICAgICAgICYmIGN1cmwgLWZzU0wgLS1tYXgtdGltZSAzMCAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvd2hlcmRyLyR2ZXJzaW9uIiAtbyAiJHRtcC9tZXRhZGF0YSIgMj4vZGV2L251bGwgXAogICAgICAgICYmICIkUlVOVElNRSIgIiRST09UL2Jpbi9saWIvdmVyaWZ5LXJlbGVhc2UubWpzIiAiJHRtcC93aGVyZHIudGd6IiAiJHRtcC9tZXRhZGF0YSIgbnBtICIkdmVyc2lvbiIgMj4vZGV2L251bGwgfHwgY29udGludWUKICAgIGZpCiAgICB0YXIgLXh6ZiAiJHRtcC93aGVyZHIudGd6IiAtQyAiJHRtcCIgMj4vZGV2L251bGwgfHwgY29udGludWUKICAgIFsgLWYgIiR0bXAvcGFja2FnZS8ub3V0cHV0L3NlcnZlci9pbmRleC5tanMiIF0gXAogICAgICAmJiBbIC1kICIkdG1wL3BhY2thZ2UvYmluIiBdICYmIFsgLWYgIiR0bXAvcGFja2FnZS9wYWNrYWdlLmpzb24iIF0gfHwgY29udGludWUKICAgICMgTGVnYWN5IHBhY2thZ2VzIGhhdmUgbmVpdGhlciB0aGUgc2tpbGwgbm9yIGl0cyBoZWxwZXJzLiBLZWVwIHRoZQogICAgIyBjaGVja291dCdzIGNvbW1hbmRzIHNvIHBsdWdpbiBza2lsbCBpbnN0YWxsL3VuaW5zdGFsbCBzdGlsbCB3b3JrLgogICAgZm9yIGVudHJ5IGluIC5vdXRwdXQgYmluIHBhY2thZ2UuanNvbiBza2lsbHM7IGRvCiAgICAgIFsgLWUgIiR0bXAvcGFja2FnZS8kZW50cnkiIF0gfHwgY29udGludWUKICAgICAgaWYgWyAiJGVudHJ5IiA9IGJpbiBdOyB0aGVuCiAgICAgICAgWyAtZiAiJHRtcC9wYWNrYWdlL3NraWxscy93aGVyZHIvU0tJTEwubWQiIF0gXAogICAgICAgICAgJiYgWyAtZiAiJHRtcC9wYWNrYWdlL2Jpbi9saWIvaW5zdGFsbC1za2lsbC5zaCIgXSB8fCBjb250aW51ZQogICAgICBmaQogICAgICBybSAtcmYgIiRST09ULyRlbnRyeSIKICAgICAgbXYgIiR0bXAvcGFja2FnZS8kZW50cnkiICIkUk9PVC8kZW50cnkiCiAgICBkb25lCiAgICBybSAtcmYgIiR0bXAiCiAgICBvayAid2hlcmRyICR2ZXJzaW9uIGRvd25sb2FkZWQgKCRzb3VyY2UgcGFja2FnZSwgY2hlY2tzdW0gbWF0Y2hlZCkiCiAgICByZXR1cm4gMAogIGRvbmUKICBybSAtcmYgIiR0bXAiCiAgcmV0dXJuIDEKfQoKIyBxcmNvZGUtdGVybWluYWwgKHRoZSBwYW5lbCdzIFFSIGNvZGUpLCB0aGUgb25seSBwYWNrYWdlIHRoZSBjb21tYW5kcyBuZWVkCiMgYXQgcnVudGltZSwgd2hlbiB0aGUgZm9sZGVyIGRvZXMgbm90IGhhdmUgaXQgeWV0IChubyBucG0gY2kgd2FzIHJ1bikuCmZldGNoX3FyKCkgewogIFsgLWYgIiQxL25vZGVfbW9kdWxlcy9xcmNvZGUtdGVybWluYWwvcGFja2FnZS5qc29uIiBdICYmIHJldHVybiAwCiAgY29tbWFuZCAtdiBjdXJsID4vZGV2L251bGwgMj4mMSAmJiBjb21tYW5kIC12IHRhciA+L2Rldi9udWxsIDI+JjEgfHwgcmV0dXJuIDAKICB0bXA9IiQobWt0ZW1wIC1kKSIKICBpZiBjdXJsIC1mc1NMIC0tbWF4LXRpbWUgNjAgaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvcXJjb2RlLXRlcm1pbmFsLy0vcXJjb2RlLXRlcm1pbmFsLTAuMTIuMC50Z3ogLW8gIiR0bXAvcXIudGd6IiAyPi9kZXYvbnVsbCBcCiAgICAmJiB0YXIgLXh6ZiAiJHRtcC9xci50Z3oiIC1DICIkdG1wIjsgdGhlbgogICAgbWtkaXIgLXAgIiQxL25vZGVfbW9kdWxlcyIKICAgIHJtIC1yZiAiJDEvbm9kZV9tb2R1bGVzL3FyY29kZS10ZXJtaW5hbCIKICAgIG12ICIkdG1wL3BhY2thZ2UiICIkMS9ub2RlX21vZHVsZXMvcXJjb2RlLXRlcm1pbmFsIgogIGVsc2UKICAgIHdhcm4gIk5vIFFSIGNvZGUgaW4gdGhlIHBhbmVsIChxcmNvZGUtdGVybWluYWwgY291bGQgbm90IGJlIGRvd25sb2FkZWQpLiIKICBmaQogIHJtIC1yZiAiJHRtcCIKfQoKYnVpbGRfbmF0aXZlKCkgewogIFJVTlRJTUU9IiQoZmluZF9ydW50aW1lKSIgfHwgZGllICIkUlVOVElNRV9IRUxQIgogIG9rICJSdW50aW1lOiAkUlVOVElNRSAoJCgiJFJVTlRJTUUiIC0tdmVyc2lvbiAyPi9kZXYvbnVsbCkpIgogIGlmIGZldGNoX3ByZWJ1aWx0OyB0aGVuCiAgICBpbnN0YWxsX2FwcAogICAgcmV0dXJuIDAKICBmaQogIGNhc2UgIiQoYmFzZW5hbWUgIiRSVU5USU1FIikiIGluCiAgICBidW4pIGRpZSAiVGhlIHByZWJ1aWx0IHdoZXJkciBwYWNrYWdlIGNvdWxkIG5vdCBiZSBkb3dubG9hZGVkLCBhbmQgYnVpbGRpbmcgaXQgbmVlZHMgTm9kZS5qcyAyMiB3aXRoIG5wbS4KICAgICBDaGVjayB0aGUgbmV0d29yaywgb3IgaW5zdGFsbCBOb2RlLmpzIDIyLCB0aGVuIGluc3RhbGwgdGhlIHBsdWdpbiBhZ2Fpbi4iIDs7CiAgZXNhYwogIGJpbmRpcj0iJChkaXJuYW1lICIkUlVOVElNRSIpIgogIFsgLXggIiRiaW5kaXIvbnBtIiBdIHx8IGNvbW1hbmQgLXYgbnBtID4vZGV2L251bGwgMj4mMSB8fCBkaWUgIm5wbSBpcyBtaXNzaW5nIChpdCBjb21lcyB3aXRoIE5vZGUuanMpLiIKICB0ZWxsICJ3aGVyZHI6IGJ1aWxkaW5nIChhIGZldyBtaW51dGVzIHRoZSBmaXJzdCB0aW1lKeKApiIKICAoCiAgICBjZCAiJFJPT1QiCiAgICBQQVRIPSIkYmluZGlyOiRQQVRIIiBucG0gY2kgLS1uby1hdWRpdCAtLW5vLWZ1bmQKICAgIFBBVEg9IiRiaW5kaXI6JFBBVEgiIG5wbSBydW4gYnVpbGQKICApCiAgb2sgIndoZXJkciBidWlsdCBpbiB0aGUgcGx1Z2luIGZvbGRlciIKICBpbnN0YWxsX2FwcAp9CgojIENvcGllcyB0aGUgY29tbWFuZHMgYW5kIHRoZSBidWlsdCBzZXJ2ZXIgdG8gJEFQUCwgd2hpY2ggb3V0bGl2ZXMgdGhpcwojIGNoZWNrb3V0LiBBIHdoZXJkciB0aGlzIHBsdWdpbiBydW5zIGZyb20gdGhlIHByZXZpb3VzIGNvcHkgaXMgc3RvcHBlZCBmb3IKIyB0aGUgc3dhcDsgYnVpbGRfc3RhcnQgc3RhcnRzIHRoZSBuZXcgb25lLgppbnN0YWxsX2FwcCgpIHsKICAjIE5pdHJvIGxpbmtzIHNvbWUgcGFja2FnZXMgKHRzbGliKSB0byBpdHMgb3duIGZvbGRlcjogY29waWVzLCBub3QgbGlua3MuCiAgaWYgWyAtZCAiJFJPT1QvLm91dHB1dC9zZXJ2ZXIvbm9kZV9tb2R1bGVzIiBdOyB0aGVuICIkUlVOVElNRSIgIiRST09UL3NjcmlwdHMvcGFjay1vdXRwdXQubWpzIiA+L2Rldi9udWxsOyBmaQogIG5ldz0iJEFQUC5uZXciCiAgcm0gLXJmICIkbmV3IgogIG1rZGlyIC1wICIkbmV3IgogIGNwIC1SICIkUk9PVC9iaW4iICIkUk9PVC9za2lsbHMiICIkUk9PVC8ub3V0cHV0IiAiJFJPT1QvcGFja2FnZS5qc29uIiAiJG5ldy8iCiAgaWYgWyAtZCAiJFJPT1Qvbm9kZV9tb2R1bGVzL3FyY29kZS10ZXJtaW5hbCIgXTsgdGhlbgogICAgbWtkaXIgLXAgIiRuZXcvbm9kZV9tb2R1bGVzIgogICAgY3AgLVIgIiRST09UL25vZGVfbW9kdWxlcy9xcmNvZGUtdGVybWluYWwiICIkbmV3L25vZGVfbW9kdWxlcy8iCiAgZmkKICBmZXRjaF9xciAiJG5ldyIKICAjIFRoZSB3aGVyZHIgdGhpcyBwbHVnaW4gcnVucyAoZnJvbSB0aGUgcHJldmlvdXMgY29weSwgb3IgZnJvbSBhbiBvbGRlcgogICMgcGx1Z2luIGNoZWNrb3V0KTogc3RvcHBlZCBmb3IgdGhlIHN3YXAsIHN0YXJ0ZWQgYWdhaW4gYnkgYnVpbGRfc3RhcnQuCiAgaWYgWyAtZiAiJERJUi93aGVyZHIucGlkIiBdIHx8IFsgLWYgIiRBUFAvYmluL3doZXJkci5tanMiIF07IHRoZW4gY2xpIHN0b3AgPi9kZXYvbnVsbCAyPiYxIHx8IHRydWU7IGZpCiAgcm0gLXJmICIkQVBQLm9sZCIKICBpZiBbIC1kICIkQVBQIiBdOyB0aGVuIG12ICIkQVBQIiAiJEFQUC5vbGQiOyBmaQogIG12ICIkbmV3IiAiJEFQUCIKICBybSAtcmYgIiRBUFAub2xkIgogIG9rICJ3aGVyZHIgJChzZWQgLW4gJ3MvXiAqInZlcnNpb24iOiAqIlwoLipcKSIsJC9cMS9wJyAiJEFQUC9wYWNrYWdlLmpzb24iIHwgaGVhZCAtbiAxKSBpbnN0YWxsZWQgaW4gJEFQUCIKfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gc3RhcnQKY21kX3N0YXJ0KCkgewogIGlmIGFuc3dlcnM7IHRoZW4KICAgIHNheSAid2hlcmRyOiBzb21ldGhpbmcgYWxyZWFkeSBhbnN3ZXJzIG9uIHBvcnQgJFBPUlQsIG5vdGhpbmcgdG8gc3RhcnQgKCRVUkwpLiIKICAgIHJldHVybiAwCiAgZmkKICBzdGFydF9uYXRpdmUKfQoKIyBOYXRpdmUgbW9kZTogdGhlIHdoZXJkciBjb21tYW5kIChiaW4vd2hlcmRyLm1qcykgZG9lcyB0aGUgd29yaywgd2l0aCB0aGUKIyBydW50aW1lIHNhdmVkIGF0IGluc3RhbGw7IGl0IHNheXMgInN0YXJ0ZWQiIG9ubHkgb25jZSB0aGUgcG9ydCBhbnN3ZXJzLgplbnN1cmVfcnVudGltZSgpIHsKICBpZiAhIHJ1bnRpbWVfb2sgIiRSVU5USU1FIjsgdGhlbgogICAgc2F2ZWQ9IiRSVU5USU1FIgogICAgUlVOVElNRT0iJChmaW5kX3J1bnRpbWUpIiB8fCBkaWUgIiR7c2F2ZWQ6K1RoZSBzYXZlZCBydW50aW1lICgkc2F2ZWQpIGlzIGdvbmUuIH0kUlVOVElNRV9IRUxQIgogICAgd2FybiAiJHtzYXZlZDorJHNhdmVkIGlzIGdvbmU6IH11c2luZyAkUlVOVElNRSAoc2F2ZWQgaW4gJENPTkYpLiIKICAgIHdyaXRlX2NvbmYKICBmaQp9CgpjbGkoKSB7CiAgZW5zdXJlX3J1bnRpbWUKICBzb2NrPSIke0hFUkRSX1NPQ0tFVF9QQVRIOi19IgogICMgQSBwbHVnaW4gc3RhcnRlZCBmcm9tIGEgbmFtZWQgSGVyZHIgc2Vzc2lvbiBkcml2ZXMgdGhhdCBzZXNzaW9uLgogIHNlc3Npb249IiIKICBjYXNlICIkc29jayIgaW4gKi9zZXNzaW9ucy8qL2hlcmRyLnNvY2spIHNlc3Npb249IiQoYmFzZW5hbWUgIiQoZGlybmFtZSAiJHNvY2siKSIpIiA7OyBlc2FjCiAgKAogICAgY2QgIiRESVIiCiAgICBIRVJEUl9CSU49IiQoaGVyZHJfYmluKSIKICAgICMgVGhlIHJ1bnRpbWUncyBmb2xkZXIgZmlyc3Q6IHRvb2xzIGl0IHN0YXJ0cyBmaW5kIHRoZSBzYW1lIG5vZGUuCiAgICBQQVRIPSIkKGRpcm5hbWUgIiRSVU5USU1FIik6JFBBVEgiCiAgICBleHBvcnQgUEFUSCBXSEVSRFJfRElSPSIkRElSIiBXSEVSRFJfUlVOVElNRT0iJFJVTlRJTUUiIEhPU1Q9MTI3LjAuMC4xIFBPUlQgSEVSRFJfQklOCiAgICBpZiBbIC1uICIkc2Vzc2lvbiIgXTsgdGhlbiBleHBvcnQgSEVSRFJfV0VCX1NFU1NJT049IiRzZXNzaW9uIjsgZmkKICAgIGlmIFsgLW4gIiRzb2NrIiBdOyB0aGVuIGV4cG9ydCBIRVJEUl9TT0NLPSIkc29jayI7IGZpCiAgICBpZiBbIC1uICIke0FQUF9VUkw6LX0iIF07IHRoZW4gZXhwb3J0IEFQUF9VUkw7IGZpCiAgICBleGVjICIkUlVOVElNRSIgIiQoY2xpX3Jvb3QpL2Jpbi93aGVyZHIubWpzIiAiJEAiCiAgKQp9CgpzdGFydF9uYXRpdmUoKSB7CiAgWyAtZiAiJChjbGlfcm9vdCkvLm91dHB1dC9zZXJ2ZXIvaW5kZXgubWpzIiBdIHx8IGRpZSAid2hlcmRyIGlzIG5vdCBidWlsdDogaW5zdGFsbCB0aGUgcGx1Z2luIGFnYWluIChoZXJkciBwbHVnaW4gaW5zdGFsbCAkU09VUkNFIC0teWVzKS4iCiAgbWtkaXIgLXAgIiRESVIiCiAgY2xpIHN0YXJ0Cn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzdG9wCmNtZF9zdG9wKCkgeyBjbGkgc3RvcDsgfQpjbWRfc3RhdHVzKCkgeyBjbGkgc3RhdHVzOyBzYXkgIiAgUGx1Z2luICAgbmF0aXZlIHNlcnZpY2UsIHNldHRpbmdzIGluICRDT05GIjsgfQpjbWRfbG9ncygpIHsgY2xpIGxvZ3MgLS1mb2xsb3c7IH0KY21kX2RvY3RvcigpIHsgY2xpIGRvY3RvcjsgfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIG9wZW4KIyBUaGUgZGVmYXVsdCBicm93c2VyLCBvbiBhIGNvbXB1dGVyIHdpdGggYSBzY3JlZW4gb25seTogYG9wZW5gIG9uIG1hY09TLAojIGB4ZGctb3BlbmAgb24gTGludXggd2l0aCBhIGRpc3BsYXkuIEZhaWxzIChvcGVucyBub3RoaW5nKSBvbiBhIGhlYWRsZXNzIHNlcnZlciwKIyBvciB3aXRoIFdIRVJEUl9OT19CUk9XU0VSPTEgKHNldCBieSBodHRwczovL3doZXJkci5kZXYvaW5zdGFsbCBvdmVyIFNTSCkuCm9wZW5fYnJvd3NlcigpIHsKICBpZiBbICIke1dIRVJEUl9OT19CUk9XU0VSOi0wfSIgPSAiMSIgXTsgdGhlbiByZXR1cm4gMQogIGVsaWYgWyAiJCh1bmFtZSAtcykiID0gIkRhcndpbiIgXSAmJiBjb21tYW5kIC12IG9wZW4gPi9kZXYvbnVsbCAyPiYxOyB0aGVuIG9wZW4gIiQxIgogIGVsaWYgWyAtbiAiJHtESVNQTEFZOi19JHtXQVlMQU5EX0RJU1BMQVk6LX0iIF0gJiYgY29tbWFuZCAtdiB4ZGctb3BlbiA+L2Rldi9udWxsIDI+JjE7IHRoZW4geGRnLW9wZW4gIiQxIiA+L2Rldi9udWxsIDI+JjEgJgogIGVsc2UgcmV0dXJuIDEKICBmaQp9CgojIFRoZSB0YWlsc2NhbGUgQ0xJOiBvbiB0aGUgUEFUSCwgb3IgaW5zaWRlIHRoZSBtYWNPUyBhcHAuCnRhaWxzY2FsZV9iaW4oKSB7CiAgaWYgY29tbWFuZCAtdiB0YWlsc2NhbGUgPi9kZXYvbnVsbCAyPiYxOyB0aGVuIGNvbW1hbmQgLXYgdGFpbHNjYWxlCiAgZWxpZiBbIC14IC9BcHBsaWNhdGlvbnMvVGFpbHNjYWxlLmFwcC9Db250ZW50cy9NYWNPUy9UYWlsc2NhbGUgXTsgdGhlbiBlY2hvIC9BcHBsaWNhdGlvbnMvVGFpbHNjYWxlLmFwcC9Db250ZW50cy9NYWNPUy9UYWlsc2NhbGUKICBlbHNlIHJldHVybiAxCiAgZmkKfQoKIyAiPG1hY2hpbmU+Ljx0YWlsbmV0Pi50cy5uZXRbOnBvcnRdIiBvZiB0aGUgYWRkcmVzcyBgdGFpbHNjYWxlIHNlcnZlYAojIHB1Ymxpc2hlcyBmb3Igd2hlcmRyJ3MgbG9jYWwgcG9ydCwgcmVhZCBmcm9tIFRhaWxzY2FsZSBvbiB0aGlzIG1hY2hpbmUuCnNlcnZlZF9ob3N0KCkgewogIHRzPSIkKHRhaWxzY2FsZV9iaW4pIiB8fCByZXR1cm4gMQogICMgIjxuYW1lPjo8aHR0cHMgcG9ydD4iIG9mIHRoZSBXZWIgZW50cnkgd2hvc2UgcHJveHkgdGFyZ2V0cyBvdXIgcG9ydC4KICBob3N0PSIkKCIkdHMiIHNlcnZlIHN0YXR1cyAtLWpzb24gMj4vZGV2L251bGwgfCB0ciAneywnICdcblxuJyB8IGF3ayAtdiBwb3J0PSIkUE9SVCIgJwogICAgLyJbXiJdKjpbMC05XSsiWyBcdF0qOlsgXHRdKiQvIHsga2V5ID0gJDA7IHN1YigvXlteIl0qIi8sICIiLCBrZXkpOyBzdWIoLyIuKiQvLCAiIiwga2V5KSB9CiAgICAvIlByb3h5Ii8gJiYgJDAgfiAoIlwiKGh0dHBzPzovLyk/KDEyN1xcLjBcXC4wXFwuMXxsb2NhbGhvc3QpOiIgcG9ydCAiLz9cIiIpIHsgcHJpbnQga2V5OyBleGl0IH0nKSIKICBbIC1uICIkaG9zdCIgXSB8fCByZXR1cm4gMQogIHByaW50ZiAnJXNcbicgIiR7aG9zdCU6NDQzfSIKfQoKIyBEb2VzIHRoZSBwaG9uZSBhZGRyZXNzIGFuc3dlcj8gIm9rIiAod2hlcmRyLCBhbmQgaXQgYWNjZXB0cyB0aGF0IGFkZHJlc3MpLAojICJob3N0IiAod2hlcmRyIHJlZnVzZXMgdGhhdCBhZGRyZXNzKSwgb3IgIm5vbmUiLiAvYXBpL2hlYWx0aCBnb2VzIHRocm91Z2gKIyB3aGVyZHIncyBob3N0IGNoZWNrOyB0aGUgc3RhdGljIG1hbmlmZXN0IGFuc3dlcnMgZm9yIGFueSBob3N0IG5hbWUgYW5kIG9ubHkKIyByZWNvZ25pemVzIGEgd2hlcmRyIG9sZGVyIHRoYW4gdGhhdCByb3V0ZS4KcGhvbmVfcmVhY2goKSB7CiAgY29tbWFuZCAtdiBjdXJsID4vZGV2L251bGwgMj4mMSB8fCB7IGVjaG8gbm9uZTsgcmV0dXJuIDA7IH0KICBib2R5PSIkKGN1cmwgLXMgLS1tYXgtdGltZSA4ICIkezF9YXBpL2hlYWx0aCIgMj4vZGV2L251bGwgfHwgdHJ1ZSkiCiAgY2FzZSAiJGJvZHkiIGluCiAgICAqJyJuYW1lIjoid2hlcmRyIicqKSBlY2hvIG9rIDs7CiAgICAqJyJjb2RlIjoiaG9zdCInKikgZWNobyBob3N0IDs7CiAgICAqKSBpZiBjdXJsIC1mc1MgLS1tYXgtdGltZSA4ICIkezF9bWFuaWZlc3Qud2VibWFuaWZlc3QiIDI+L2Rldi9udWxsIHwgZ3JlcCAtcSB3aGVyZHI7IHRoZW4gZWNobyBvazsgZWxzZSBlY2hvIG5vbmU7IGZpIDs7CiAgZXNhYwp9CgojIFRoZSB0YWlsbmV0IGFkZHJlc3MgYHRhaWxzY2FsZSBzZXJ2ZWAgYWxyZWFkeSBwdWJsaXNoZXMgZm9yIHdoZXJkcidzIGxvY2FsCiMgcG9ydCAoaHR0cHM6Ly88bWFjaGluZT4uPHRhaWxuZXQ+LnRzLm5ldFs6cG9ydF0pLCBvbmx5IHdoZW4gaXQgYW5zd2VycyBsaWtlCiMgd2hlcmRyLiBQYXNza2V5cyBhcmUgdGllZCB0byB0aGUgYWRkcmVzczogdGhhdCBpcyB0aGUgb25lIHRvIG9wZW4uCnRhaWxuZXRfYWRkcmVzcygpIHsKICBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxIHx8IHJldHVybiAxCiAgaG9zdD0iJChzZXJ2ZWRfaG9zdCkiIHx8IHJldHVybiAxCiAgWyAiJChwaG9uZV9yZWFjaCAiaHR0cHM6Ly8kaG9zdC8iKSIgPSBvayBdIHx8IHJldHVybiAxCiAgcHJpbnRmICdodHRwczovLyVzXG4nICIkaG9zdCIKfQoKIyBUaGUgYWRkcmVzcyB0byBvcGVuOiB0aGUgdGFpbG5ldCBvbmUgd2hlbiBwdWJsaXNoZWQgYW5kIGFuc3dlcmluZywgZWxzZSBsb2NhbGhvc3QuCm9wZW5fYWRkcmVzcygpIHsgdGFpbG5ldF9hZGRyZXNzIHx8IHByaW50ZiAnJXNcbicgIiRVUkwiOyB9CgpjbWRfb3BlbigpIHsKICBhZGRyZXNzPSIkKG9wZW5fYWRkcmVzcykiCiAgb3Blbl9icm93c2VyICIkYWRkcmVzcyIgfHwgdHJ1ZQogIHNheSAiJGFkZHJlc3MiCn0KCiMgYGFkZHJlc3NgOiB3aGF0IGBvcGVuYCB3b3VsZCBvcGVuLCB3aXRob3V0IG9wZW5pbmcgaXQgKGh0dHBzOi8vd2hlcmRyLmRldi9pbnN0YWxsKS4KY21kX2FkZHJlc3MoKSB7IG9wZW5fYWRkcmVzczsgfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB1cGRhdGUKY21kX3VwZGF0ZSgpIHsKICBzYXkgIlVwZGF0aW5nIHRoZSB3aGVyZHIgcGx1Z2luIGZyb20gJHtTT1VSQ0V94oCmIgogICIkKGhlcmRyX2JpbikiIHBsdWdpbiBpbnN0YWxsICIkU09VUkNFIiAtLXJlZiBtYWluIC0teWVzCn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHBob25lCiMgUGhvbmUgc2V0dXAgdXNlcyB0aGUgbmF0aXZlIGNvbW1hbmQuCmNtZF9waG9uZSgpIHsgY2xpIHBob25lOyB9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzZXJ2aWNlCmNtZF9zZXJ2aWNlKCkgewogIGNhc2UgIiR7MTotfSIgaW4gaW5zdGFsbHx1bmluc3RhbGwpIDs7ICopIGRpZSAidXNhZ2U6ICQwIHNlcnZpY2UgaW5zdGFsbHx1bmluc3RhbGwiIDs7IGVzYWMKICBjbGkgc2VydmljZSAiJDEiCiAgIyBXaXRob3V0IHRoZSBzZXJ2aWNlLCB0aGUgcGx1Z2luIHJ1bnMgd2hlcmRyIGFnYWluIChhbmQgaXRzIHN0YXJ0dXAgaG9vawogICMgc3RhcnRzIGl0IHdpdGggSGVyZHIpLgogIGlmIFsgIiQxIiA9ICJ1bmluc3RhbGwiIF07IHRoZW4gY21kX3N0YXJ0OyBmaQp9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBrZXkKIyBBIEhlcmRyIGtleSB0aGF0IG9wZW5zIHRoZSB3aGVyZHIgcGFuZWw6IEhlcmRyIHYxIHBsdWdpbnMgaGF2ZSBubyBtZW51LCBzbwojIHRoZSBpbnN0YWxsIGFwcGVuZHMgb25lIG1hcmtlZCBbW2tleXMuY29tbWFuZF1dIGJsb2NrIHRvIEhlcmRyJ3MKIyBjb25maWcudG9tbCwgb24gdGhlIGZpcnN0IGZyZWUga2V5IG9mIEhPVEtFWVMgKG5ldmVyIG9uZSBIZXJkciBvciB0aGUgdXNlcgojIGFscmVhZHkgYmluZHMpLiBFeGlzdGluZyBsaW5lcyBhcmUgbmV2ZXIgY2hhbmdlZDogdGhlIGJsb2NrIGlzIG9ubHkgZXZlcgojIGFwcGVuZGVkLCB0aGVuIHJlbW92ZWQgYnkgYGtleSB1bmluc3RhbGxgLiBOb3RoaW5nIGlzIGFkZGVkIHdoZW4gdGhlIHBhbmVsCiMgYWxyZWFkeSBoYXMgYSBrZXksIG9yIHdoZW4gbm8gY2FuZGlkYXRlIGlzIGZyZWUuCkhPVEtFWVM9IiR7V0hFUkRSX0hPVEtFWVM6LXByZWZpeCtpIHByZWZpeCt1IHByZWZpeCt5IHByZWZpeCttIHByZWZpeCthbHQrd30iCkhFUkRSX0NPTkZJRz0iJHtIRVJEUl9DT05GSUdfUEFUSDotJHtYREdfQ09ORklHX0hPTUU6LSRIT01FLy5jb25maWd9L2hlcmRyL2NvbmZpZy50b21sfSIKUExVR0lOX0lEPSIkKHByaW50ZiAnJXMnICIkU09VUkNFIiB8IHRyIC8gLikiClBBTkVMX0FDVElPTj0iJFBMVUdJTl9JRC5wYW5lbCIKS0VZX0JFR0lOPSIjIHdoZXJkcjoga2V5IHRoYXQgb3BlbnMgdGhlIHdoZXJkciBwYW5lbCAocmVtb3ZlIHRoaXMgYmxvY2sgdG8gdW5iaW5kIGl0KSIKS0VZX0VORD0iIyBlbmQgd2hlcmRyIgoKIyBIZXJkcidzIGRlZmF1bHQga2V5bWFwLCBmcm9tIHRoZSBydW5uaW5nIGJpbmFyeSB3aGVuIGl0IGNhbiBwcmludCBpdCwKIyBvdGhlcndpc2UgYXMgb2YgSGVyZHIgMC45LjMgKCJuYW1lPFRBQj5rZXkiIGxpbmVzKS4KZGVmYXVsdF9rZXlzKCkgewogIG91dD0iJCgiJChoZXJkcl9iaW4pIiAtLWRlZmF1bHQtY29uZmlnIDI+L2Rldi9udWxsIHwgYXdrICcKICAgIC9eXFtrZXlzXF0vIHsgayA9IDE7IG5leHQgfQogICAgayAmJiAvXlxbLyB7IGV4aXQgfQogICAgayAmJiBtYXRjaCgkMCwgL14jIFthLXpfXSsgPSAiW14iXSoiLykgewogICAgICBsaW5lID0gc3Vic3RyKCQwLCAzLCBSTEVOR1RIIC0gMik7IGVxID0gaW5kZXgobGluZSwgIiA9ICIpCiAgICAgIHYgPSBzdWJzdHIobGluZSwgZXEgKyA0KTsgc3ViKC8iJC8sICIiLCB2KQogICAgICBpZiAodiAhPSAiIikgcHJpbnRmICIlc1x0JXNcbiIsIHN1YnN0cihsaW5lLCAxLCBlcSAtIDEpLCB2CiAgICB9JykiIHx8IG91dD0iIgogIGlmIFsgLW4gIiRvdXQiIF07IHRoZW4gcHJpbnRmICclc1xuJyAiJG91dCI7IHJldHVybjsgZmkKICBmb3IgcCBpbiBoZWxwOj8gc2V0dGluZ3M6cyBkZXRhY2g6cSByZWxvYWRfY29uZmlnOnNoaWZ0K3Igb3Blbl9ub3RpZmljYXRpb25fdGFyZ2V0Om8gXAogICAgd29ya3NwYWNlX3BpY2tlcjp3IGdvdG86ZyBuZXdfd29ya3NwYWNlOnNoaWZ0K24gbmV3X3dvcmt0cmVlOnNoaWZ0K2cgcmVuYW1lX3dvcmtzcGFjZTpzaGlmdCt3IFwKICAgIGNsb3NlX3dvcmtzcGFjZTpzaGlmdCtkIG5ld190YWI6YyByZW5hbWVfdGFiOnNoaWZ0K3QgcHJldmlvdXNfdGFiOnAgbmV4dF90YWI6biBcCiAgICBjbG9zZV90YWI6c2hpZnQreCByZW5hbWVfcGFuZTpzaGlmdCtwIGVkaXRfc2Nyb2xsYmFjazplIGZvY3VzX3BhbmVfbGVmdDpoIGZvY3VzX3BhbmVfZG93bjpqIFwKICAgIGZvY3VzX3BhbmVfdXA6ayBmb2N1c19wYW5lX3JpZ2h0OmwgY3ljbGVfcGFuZV9uZXh0OnRhYiBjeWNsZV9wYW5lX3ByZXZpb3VzOnNoaWZ0K3RhYiBcCiAgICBzcGxpdF92ZXJ0aWNhbDp2IHNwbGl0X2hvcml6b250YWw6bWludXMgY2xvc2VfcGFuZTp4IHpvb206eiByZXNpemVfbW9kZTpyIHRvZ2dsZV9zaWRlYmFyOmI7IGRvCiAgICBwcmludGYgJyVzXHRwcmVmaXgrJXNcbicgIiR7cCUlOip9IiAiJHtwIyo6fSIKICBkb25lCn0KCiMgT25lIGxpbmUgb24gdGhlIGNvbmZpZzogImJvdW5kIDxrZXk+IiB3aGVuIGEgW1trZXlzLmNvbW1hbmRdXSBhbHJlYWR5IHJ1bnMKIyB0aGUgcGFuZWwsIGVsc2UgImZyZWUgPGtleT4iIChmaXJzdCBmcmVlIGNhbmRpZGF0ZSkgb3IgIm5vbmUiLiBBbHNvCiMgIm9sZCA8a2V5PiIgZm9yIGEgYmluZGluZyBvZiB0aGUgcGFuZWwncyBmb3JtZXIgYWN0aW9uIGlkICg8aWQ+LndoZXJkcikuCmtleV9zY2FuKCkgewogIGRlZmF1bHRzPSIkKGRlZmF1bHRfa2V5cykiCiAgeyBwcmludGYgJyVzXG4nICIkZGVmYXVsdHMiOyBwcmludGYgJ1wwMDFcbic7IGNhdCAiJEhFUkRSX0NPTkZJRyIgMj4vZGV2L251bGw7IH0gfCBhd2sgXAogICAgLXYgY2FuZHM9IiRIT1RLRVlTIiAtdiBhY3Rpb249IiRQQU5FTF9BQ1RJT04iIC12IG9sZD0iJFBMVUdJTl9JRC53aGVyZHIiICcKICAgIGZ1bmN0aW9uIG5vcm0oaykgewogICAgICBnc3ViKC9bIFx0XS8sICIiLCBrKQogICAgICAjICJwcmVmaXgrVyIgaXMgInByZWZpeCtzaGlmdCt3IgogICAgICBpZiAobWF0Y2goaywgL1wrW0EtWl0kLykpIGsgPSBzdWJzdHIoaywgMSwgUlNUQVJUKSAic2hpZnQrIiB0b2xvd2VyKHN1YnN0cihrLCBSU1RBUlQgKyAxKSkKICAgICAgcmV0dXJuIHRvbG93ZXIoaykKICAgIH0KICAgIGZ1bmN0aW9uIHN0cmluZ3Mocywgb3V0LCAgIG4pIHsKICAgICAgbiA9IDAKICAgICAgd2hpbGUgKG1hdGNoKHMsIC8iW14iXSoiLykpIHsgb3V0Wysrbl0gPSBzdWJzdHIocywgUlNUQVJUICsgMSwgUkxFTkdUSCAtIDIpOyBzID0gc3Vic3RyKHMsIFJTVEFSVCArIFJMRU5HVEgpIH0KICAgICAgcmV0dXJuIG4KICAgIH0KICAgIGZ1bmN0aW9uIGZsdXNoKCkgewogICAgICBpZiAoY2tleSAhPSAiIiAmJiBjbWQgPT0gYWN0aW9uICYmIGJvdW5kID09ICIiKSBib3VuZCA9IGNrZXkKICAgICAgaWYgKGNrZXkgIT0gIiIgJiYgY21kID09IG9sZCAmJiBvbGRrZXkgPT0gIiIpIG9sZGtleSA9IGNrZXkKICAgICAgY2tleSA9ICIiOyBjbWQgPSAiIgogICAgfQogICAgJDAgPT0gIlwwMDEiIHsgY29uZiA9IDE7IG5leHQgfQogICAgIWNvbmYgeyBzcGxpdCgkMCwgZCwgIlx0Iik7IGRlZltkWzFdXSA9IGRbMl07IG5leHQgfQogICAgL15bIFx0XSpcWy8gewogICAgICBmbHVzaCgpOyB0ID0gJDA7IHN1YigvIy4qLywgIiIsIHQpOyBnc3ViKC9bIFx0XS8sICIiLCB0KQogICAgICBzZWN0ID0gdCA9PSAiW2tleXNdIiA/ICJrZXlzIiA6IHQgPT0gIltba2V5cy5jb21tYW5kXV0iID8gImNtZCIgOiAiIgogICAgICBuZXh0CiAgICB9CiAgICAvXlsgXHRdKigjfCQpLyB7IG5leHQgfQogICAgewogICAgICBlcSA9IGluZGV4KCQwLCAiPSIpOyBpZiAoIWVxKSBuZXh0CiAgICAgIG5hbWUgPSBzdWJzdHIoJDAsIDEsIGVxIC0gMSk7IGdzdWIoL1sgXHRdLywgIiIsIG5hbWUpOyB2YWwgPSBzdWJzdHIoJDAsIGVxICsgMSkKICAgICAgaWYgKHNlY3QgPT0gImtleXMiKSB7CiAgICAgICAgb3ZlcltuYW1lXSA9IDE7IG4gPSBzdHJpbmdzKHZhbCwgcykKICAgICAgICBmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykgdGFrZW5bbm9ybShzW2ldKV0gPSAxCiAgICAgIH0gZWxzZSBpZiAoc2VjdCA9PSAiY21kIiAmJiBzdHJpbmdzKHZhbCwgcykpIHsKICAgICAgICBpZiAobmFtZSA9PSAia2V5IikgeyBja2V5ID0gc1sxXTsgdGFrZW5bbm9ybShzWzFdKV0gPSAxIH0KICAgICAgICBpZiAobmFtZSA9PSAiY29tbWFuZCIpIGNtZCA9IHNbMV0KICAgICAgfQogICAgfQogICAgRU5EIHsKICAgICAgZmx1c2goKQogICAgICBpZiAob2xka2V5ICE9ICIiKSBwcmludCAib2xkICIgb2xka2V5CiAgICAgIGlmIChib3VuZCAhPSAiIikgeyBwcmludCAiYm91bmQgIiBib3VuZDsgZXhpdCB9CiAgICAgIGZvciAoYSBpbiBkZWYpIGlmICghKGEgaW4gb3ZlcikpIHRha2VuW25vcm0oZGVmW2FdKV0gPSAxCiAgICAgIG4gPSBzcGxpdChjYW5kcywgYywgIiAiKQogICAgICBmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykgaWYgKCEobm9ybShjW2ldKSBpbiB0YWtlbikpIHsgcHJpbnQgImZyZWUgIiBjW2ldOyBleGl0IH0KICAgICAgcHJpbnQgIm5vbmUiCiAgICB9Jwp9CgojIFRoZSBrZXkgYm91bmQgdG8gdGhlIHBhbmVsLCBpZiBhbnkuCmtleV9ib3VuZCgpIHsga2V5X3NjYW4gfCBzZWQgLW4gJ3MvXmJvdW5kIC8vcCc7IH0KCiMgSGVyZHIgYXBwbGllcyBrZXliaW5kaW5ncyBvbiBgaGVyZHIgc2VydmVyIHJlbG9hZC1jb25maWdgIChubyByZXN0YXJ0KS4Ka2V5X3JlbG9hZCgpIHsKICBpZiAiJChoZXJkcl9iaW4pIiBzZXJ2ZXIgcmVsb2FkLWNvbmZpZyA+L2Rldi9udWxsIDI+JjE7IHRoZW4KICAgIHRlbGwgIiAgSGVyZHIgcmVsb2FkZWQgaXRzIGNvbmZpZzogbm8gcmVzdGFydCBuZWVkZWQuIgogIGVsc2UKICAgIHRlbGwgIiAgUnVuIGhlcmRyIHNlcnZlciByZWxvYWQtY29uZmlnIChvciByZXN0YXJ0IEhlcmRyKSB0byBhcHBseSBpdC4iCiAgZmkKfQoKY21kX2tleSgpIHsKICBjYXNlICIkezE6LX0iIGluCiAgICBpbnN0YWxsKQogICAgICBzY2FuPSIkKGtleV9zY2FuKSIKICAgICAgb2xkPSIkKHByaW50ZiAnJXNcbicgIiRzY2FuIiB8IHNlZCAtbiAncy9eb2xkIC8vcCcpIgogICAgICBbIC16ICIkb2xkIiBdIHx8IHdhcm4gIiRvbGQgcnVucyAkUExVR0lOX0lELndoZXJkciwgcmVuYW1lZCAkUEFORUxfQUNUSU9OOiBlZGl0IHRoYXQgbGluZSBvZiAkSEVSRFJfQ09ORklHLiIKICAgICAgcmVzPSIkKHByaW50ZiAnJXNcbicgIiRzY2FuIiB8IHNlZCAnL15vbGQgL2QnKSIKICAgICAgY2FzZSAiJHJlcyIgaW4KICAgICAgICBib3VuZFwgKikgdGVsbCAiUHJlc3MgJHtyZXMjYm91bmQgfSBpbiBIZXJkciB0byBvcGVuIHRoZSB3aGVyZHIgcGFuZWwuIiA7OwogICAgICAgIGZyZWVcICopCiAgICAgICAgICBrZXk9IiR7cmVzI2ZyZWUgfSIKICAgICAgICAgIG1rZGlyIC1wICIkKGRpcm5hbWUgIiRIRVJEUl9DT05GSUciKSIKICAgICAgICAgIGJsb2NrPSIkKHByaW50ZiAnJXNcbltba2V5cy5jb21tYW5kXV1cbmtleSA9ICIlcyJcbnR5cGUgPSAicGx1Z2luX2FjdGlvbiJcbmNvbW1hbmQgPSAiJXMiXG5kZXNjcmlwdGlvbiA9ICJ3aGVyZHIiXG4lcycgXAogICAgICAgICAgICAiJEtFWV9CRUdJTiIgIiRrZXkiICIkUEFORUxfQUNUSU9OIiAiJEtFWV9FTkQiKSIKICAgICAgICAgIHNlcD0iIgogICAgICAgICAgaWYgWyAtcyAiJEhFUkRSX0NPTkZJRyIgXTsgdGhlbgogICAgICAgICAgICBzZXA9IgoiCiAgICAgICAgICAgICMgQSBsYXN0IGxpbmUgd2l0aG91dCBpdHMgbmV3bGluZSBnZXRzIG9uZSBmaXJzdC4KICAgICAgICAgICAgWyAiJCh0YWlsIC1jIDEgIiRIRVJEUl9DT05GSUciIHwgb2QgLUFuIC1jIHwgdHIgLWQgJyAnKSIgPSAnXG4nIF0gfHwgc2VwPSIKJHNlcCIKICAgICAgICAgIGZpCiAgICAgICAgICAjIENoZWNrZWQgb24gYSBjb3B5IGZpcnN0IHdoZW4gdGhpcyBIZXJkciBjYW4gdmFsaWRhdGUgYSBjb25maWc6CiAgICAgICAgICAjIGEgY29uZmlnIEhlcmRyIHdvdWxkIHJlamVjdCBpcyBuZXZlciB3cml0dGVuLgogICAgICAgICAgdG1wPSIkSEVSRFJfQ09ORklHLndoZXJkci1jaGVjay50b21sIgogICAgICAgICAgeyBpZiBbIC1mICIkSEVSRFJfQ09ORklHIiBdOyB0aGVuIGNhdCAiJEhFUkRSX0NPTkZJRyI7IGZpOyBwcmludGYgJyVzJXNcbicgIiRzZXAiICIkYmxvY2siOyB9ID4gIiR0bXAiCiAgICAgICAgICBpZiAiJChoZXJkcl9iaW4pIiBjb25maWcgLS1oZWxwID4vZGV2L251bGwgMj4mMSAmJiAhIEhFUkRSX0NPTkZJR19QQVRIPSIkdG1wIiAiJChoZXJkcl9iaW4pIiBjb25maWcgY2hlY2sgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgICAgIHJtIC1mICIkdG1wIgogICAgICAgICAgICB3YXJuICJubyBIZXJkciBrZXkgYWRkZWQ6ICRIRVJEUl9DT05GSUcgd291bGQgbm90IHZhbGlkYXRlIHdpdGggaXQgKGhlcmRyIGNvbmZpZyBjaGVjaykuIgogICAgICAgICAgICByZXR1cm4gMAogICAgICAgICAgZmkKICAgICAgICAgIHJtIC1mICIkdG1wIgogICAgICAgICAgcHJpbnRmICclcyVzXG4nICIkc2VwIiAiJGJsb2NrIiA+PiAiJEhFUkRSX0NPTkZJRyIKICAgICAgICAgIG9rICJIZXJkciBrZXkgJGtleSBhZGRlZCB0byAkSEVSRFJfQ09ORklHIgogICAgICAgICAgdGVsbCAiUHJlc3MgJGtleSBpbiBIZXJkciB0byBvcGVuIHRoZSB3aGVyZHIgcGFuZWwuIgogICAgICAgICAga2V5X3JlbG9hZAogICAgICAgICAgOzsKICAgICAgICAqKSB3YXJuICJubyBIZXJkciBrZXkgYWRkZWQ6ICRIT1RLRVlTIGFyZSBhbGwgdGFrZW4uIEJpbmQgb25lIHRvICRQQU5FTF9BQ1RJT04gKHR5cGUgPSBcInBsdWdpbl9hY3Rpb25cIikgaW4gJEhFUkRSX0NPTkZJRy4iIDs7CiAgICAgIGVzYWMKICAgICAgOzsKICAgIHVuaW5zdGFsbCkKICAgICAgaWYgISBncmVwIC1xeEYgIiRLRVlfQkVHSU4iICIkSEVSRFJfQ09ORklHIiAyPi9kZXYvbnVsbDsgdGhlbiBvayAibm8gd2hlcmRyIGtleSBpbiAkSEVSRFJfQ09ORklHIjsgcmV0dXJuIDA7IGZpCiAgICAgICMgRHJvcHMgdGhlIG1hcmtlZCBibG9jayBhbmQgdGhlIGJsYW5rIGxpbmUgd3JpdHRlbiBiZWZvcmUgaXQuCiAgICAgIHRtcD0iJEhFUkRSX0NPTkZJRy53aGVyZHItdG1wIgogICAgICBhd2sgLXYgYj0iJEtFWV9CRUdJTiIgLXYgZT0iJEtFWV9FTkQiICcKICAgICAgICAkMCA9PSBiIHsgc2tpcCA9IDE7IGlmIChibGFuaykgYmxhbmstLTsgbmV4dCB9CiAgICAgICAgc2tpcCB7IGlmICgkMCA9PSBlKSBza2lwID0gMDsgbmV4dCB9CiAgICAgICAgJDAgPT0gIiIgeyBibGFuaysrOyBuZXh0IH0KICAgICAgICB7IHdoaWxlIChibGFuaykgeyBwcmludCAiIjsgYmxhbmstLSB9IHByaW50IH0KICAgICAgICBFTkQgeyB3aGlsZSAoYmxhbmspIHsgcHJpbnQgIiI7IGJsYW5rLS0gfSB9JyAiJEhFUkRSX0NPTkZJRyIgPiAiJHRtcCIKICAgICAgIyBSZXdyaXR0ZW4gaW4gcGxhY2U6IHRoZSBmaWxlIGtlZXBzIGl0cyBvd25lciBhbmQgbW9kZS4KICAgICAgY2F0ICIkdG1wIiA+ICIkSEVSRFJfQ09ORklHIiAmJiBybSAtZiAiJHRtcCIKICAgICAgb2sgIndoZXJkciBrZXkgcmVtb3ZlZCBmcm9tICRIRVJEUl9DT05GSUciCiAgICAgIGtleV9yZWxvYWQKICAgICAgOzsKICAgIHN0YXR1cykgYj0iJChrZXlfYm91bmQpIjsgaWYgWyAtbiAiJGIiIF07IHRoZW4gc2F5ICIkYiI7IGVsc2Ugc2F5ICJub25lIjsgZmkgOzsKICAgICopIGRpZSAidXNhZ2U6ICQwIGtleSBpbnN0YWxsfHVuaW5zdGFsbHxzdGF0dXMiIDs7CiAgZXNhYwp9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwYW5lbAojIFRoZSAicGFuZWwiIGFjdGlvbjogb25lIHBvcHVwIHdpdGggdGhlIHN0YXRlLCBPcGVuIHdoZXJkciwgU2V0IHVwIG15IHBob25lCiMgKG9wZW5zIFNldHRpbmdzIOKAuiBQaG9uZSkgYW5kIHRoZSBvdGhlciBjb21tYW5kcyAoYmluL2xpYi9wYW5lbC5tanMpLAojIGRyaXZpbmcgdGhpcyBzY3JpcHQuCmNtZF9wYW5lbCgpIHsKICBjb250cm9sPSIkKHByaW50ZiAnWyJzaCIsIiVzIl0nICIkKHByaW50ZiAnJXMnICIkUk9PVC9zY3JpcHRzL2hlcmRyLXBsdWdpbi5zaCIgfCBzZWQgJ3MvW1xcIl0vXFwmL2cnKSIpIgogIFdIRVJEUl9DT05UUk9MPSIkY29udHJvbCIgV0hFUkRSX0hPVEtFWT0iJChrZXlfYm91bmQpIiBjbGkgcGFuZWwKfQoKY21kX3Jlc3RhcnQoKSB7IGNtZF9zdG9wOyBjbWRfc3RhcnQ7IH0KCmNhc2UgIiR7MTotfSIgaW4KICBidWlsZCkgY21kX2J1aWxkIDs7CiAgcGFuZWwpIGNtZF9wYW5lbCA7OwogIHN0YXJ0fHN0b3B8cmVzdGFydHxzdGF0dXN8b3BlbnxhZGRyZXNzfHVwZGF0ZXxwaG9uZXxsb2dzfGRvY3RvcikgImNtZF8kMSIgOzsKICBzZXJ2aWNlKSBjbWRfc2VydmljZSAiJHsyOi19IiA7OwogIHNraWxsKSBjbWRfc2tpbGwgIiR7MjotfSIgOzsKICBrZXkpIGNtZF9rZXkgIiR7MjotfSIgOzsKICAqKSBkaWUgInVzYWdlOiAkMCBidWlsZHxwYW5lbHxzdGFydHxzdG9wfHJlc3RhcnR8c3RhdHVzfG9wZW58YWRkcmVzc3x1cGRhdGV8cGhvbmV8bG9nc3xkb2N0b3J8c2VydmljZSBpbnN0YWxsfHVuaW5zdGFsbHxza2lsbCBpbnN0YWxsfHVuaW5zdGFsbHxrZXkgaW5zdGFsbHx1bmluc3RhbGx8c3RhdHVzIiA7Owplc2FjCg==");
4
+ const herdrPlugin = base64ToUint8Array("IyEvYmluL3NoCiMgd2hlcmRyIGFzIGEgSGVyZHIgcGx1Z2luIChoZXJkci1wbHVnaW4udG9tbCk6IGJ1aWxkIChpbnN0YWxsICsgZmlyc3Qgc3RhcnQpLAojIHRoZSBwYW5lbCwgc3RhcnQsIHN0b3AsIHN0YXR1cywgb3BlbiwgdXBkYXRlLCBzZXJ2aWNlLCBza2lsbCwga2V5LgojCiMgICBoZXJkciBwbHVnaW4gaW5zdGFsbCA8b3duZXI+L3doZXJkcgojCiMgSGVyZHIgYnVpbGRzIGEgcGx1Z2luIGluIGEgdGVtcG9yYXJ5IGZvbGRlciwgdGhlbiBtb3ZlcyBpdDogYSBzZXJ2ZXIgc3RhcnRlZAojIGZyb20gdGhlIGNoZWNrb3V0IGR1cmluZyB0aGUgYnVpbGQgd291bGQgbG9zZSBpdHMgZmlsZXMuICRXSEVSRFJfRElSL2FwcAojIHN0YXlzIHB1dCwgYWNyb3NzIHBsdWdpbiB1cGRhdGVzIHRvbywgc28gdGhlIGJ1aWxkIGNhbiBzdGFydCB3aGVyZHIgYW5kIGEKIyBsb2dpbiBzZXJ2aWNlIGNhbiBwb2ludCBhdCBpdC4KIyBTYWZldHkgcnVsZXM6CiMgICAtIG5vdGhpbmcgZ2xvYmFsIGlzIGluc3RhbGxlZCwgbm8gc3VkbzsgZmlsZXMgYXJlIG9ubHkgd3JpdHRlbiB0byB0aGUKIyAgICAgcGx1Z2luIGZvbGRlciBhbmQgJFdIRVJEUl9ESVIgKGRlZmF1bHQgfi93aGVyZHIpLCBhbmQgdGhlCiMgICAgIGxvZ2luIHNlcnZpY2Ugb25seSB3aGVuIGFza2VkIChrZXkgQSBvZiB0aGUgcGFuZWwpLCBwbHVzIGEgIndoZXJkciIKIyAgICAgbGluayBpbiB0aGUgYWdlbnRzJyB1c2VyIHNraWxsIGZvbGRlcnMgKHNlZSBjbWRfc2tpbGwpLCBwbHVzIG9uZSBtYXJrZWQKIyAgICAgYmxvY2sgYXBwZW5kZWQgdG8gSGVyZHIncyBjb25maWcudG9tbDogdGhlIGtleSB0aGF0IG9wZW5zIHRoZSBwYW5lbAojICAgICAoc2VlIGNtZF9rZXkpOwojICAgLSB0aGUgaW5zdGFsbCBzdGFydHMgd2hlcmRyLCBhbmQgSGVyZHIncyBzdGFydHVwIGhvb2sgc3RhcnRzIGl0IGFnYWluLAojICAgICBidXQgb25seSB3aGVuIG5vdGhpbmcgYW5zd2VycyBvbiB0aGUgcG9ydDogYSB3aGVyZHIgc3RhcnRlZCBhbm90aGVyIHdheQojICAgICAoc3lzdGVtZCwgYnkgaGFuZCkgaXMgbmV2ZXIgdG91Y2hlZCwgbm8gc2Vjb25kIHdoZXJkciBpcyBzdGFydGVkOwojICAgLSBzdG9wIG9ubHkgc3RvcHMgd2hhdCB0aGlzIHBsdWdpbiBzdGFydGVkIChpdHMgcGlkIG9yIGl0cyBsb2dpbiBzZXJ2aWNlKS4KIwojIFVuaW5zdGFsbDogSGVyZHIgaGFzIG5vIHVuaW5zdGFsbCBob29rLiBTdG9wIHdoZXJkciAoYW5kIHJlbW92ZSB0aGUgbG9naW4KIyBzZXJ2aWNlKSBmcm9tIHRoZSBwYW5lbCBmaXJzdCwgdGhlbjoKIyAgIHNoIHNjcmlwdHMvaGVyZHItcGx1Z2luLnNoIHNraWxsIHVuaW5zdGFsbCAgIChpbiB0aGUgcGx1Z2luIGZvbGRlcikKIyAgIHNoIHNjcmlwdHMvaGVyZHItcGx1Z2luLnNoIGtleSB1bmluc3RhbGwgICAgICh0aGUgSGVyZHIga2V5IG9mIHRoZSBwYW5lbCkKIyAgIGhlcmRyIHBsdWdpbiB1bmluc3RhbGwgPG93bmVyPi53aGVyZHIgJiYgcm0gLXJmIH4vd2hlcmRyCiMKIyBTZXR0aW5ncyAoJFdIRVJEUl9ESVIvcGx1Z2luLmVudiwgb3IgdGhlIGVudmlyb25tZW50KToKIyAgIFdIRVJEUl9QT1JUICBsb2NhbCBwb3J0ICAgICAgICAgICAgICAoZGVmYXVsdDogNzY4MykKIyAgIEFQUF9VUkwgICAgICBwcml2YXRlIEhUVFBTIGFkZHJlc3MKIyAgIFdIRVJEUl9SVU5USU1FICBhYnNvbHV0ZSBwYXRoIG9mIG5vZGUgLyBidW4gKGZvdW5kIGF0IGluc3RhbGwpCgpzZXQgLWV1CgpST09UPSIkKGNkICIkKGRpcm5hbWUgIiQwIikvLi4iICYmIHB3ZCAtUCkiCiMgQnVpbGQgY29tbWFuZHMgZ2V0IG5vIHBsdWdpbiBlbnZpcm9ubWVudDogdGhlIGZvbGRlciBjaG9zZW4gYXQgaW5zdGFsbAojIHRpbWUgaXMgcmVtZW1iZXJlZCBpbiB0aGUgcGx1Z2luIGNoZWNrb3V0IGZvciB0aGUgcnVudGltZSBjb21tYW5kcy4KaWYgWyAteiAiJHtXSEVSRFJfRElSOi19IiBdICYmIFsgLWYgIiRST09ULy53aGVyZHItZGlyIiBdOyB0aGVuCiAgV0hFUkRSX0RJUj0iJChjYXQgIiRST09ULy53aGVyZHItZGlyIikiCmZpCkRJUj0iJHtXSEVSRFJfRElSOi0kSE9NRS93aGVyZHJ9IgpjYXNlICIkRElSIiBpbiAvKikgOzsgKikgRElSPSIkUFdELyRESVIiIDs7IGVzYWMKQ09ORj0iJERJUi9wbHVnaW4uZW52IgojIE5hdGl2ZSBtb2RlOiB0aGUgaW5zdGFsbGVkIGNvcHkgb2Ygd2hlcmRyIChiaW4gKyBidWlsdCBzZXJ2ZXIpLgpBUFA9IiRESVIvYXBwIgojIEdpdEh1YiBzb3VyY2Ugb2YgdGhpcyBwbHVnaW46IGl0cyBtYW5pZmVzdCBpZCB3aXRoICIvIiBmb3IgIi4iIChvd25lci53aGVyZHIpLgpTT1VSQ0U9IiQoc2VkIC1uICdzL15pZCA9ICJcKC4qXCkiJC9cMS9wJyAiJFJPT1QvaGVyZHItcGx1Z2luLnRvbWwiIHwgaGVhZCAtbiAxIHwgdHIgLiAvKSIKIyBUaGUgZW52aXJvbm1lbnQgd2lucyBvdmVyIHBsdWdpbi5lbnYuCkVOVl9QT1JUPSIke1dIRVJEUl9QT1JUOi19IiBFTlZfQVBQX1VSTD0iJHtBUFBfVVJMOi19IiBFTlZfUlVOVElNRT0iJHtXSEVSRFJfUlVOVElNRTotfSIKaWYgWyAtZiAiJENPTkYiIF07IHRoZW4KICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzEwOTAKICAuICIkQ09ORiIKZmkKTEVHQUNZX01PREU9IiR7V0hFUkRSX01PREU6LX0iClBPUlQ9IiR7RU5WX1BPUlQ6LSR7V0hFUkRSX1BPUlQ6LTc2ODN9fSIKQVBQX1VSTD0iJHtFTlZfQVBQX1VSTDotJHtBUFBfVVJMOi19fSIKIyBOYXRpdmUgbW9kZTogYWJzb2x1dGUgcGF0aCBvZiB0aGUgbm9kZSAob3IgYnVuKSB0aGF0IHJ1bnMgdGhlIHNlcnZlci4gSGVyZHIKIyBydW5zIGFjdGlvbnMgd2l0aCBpdHMgc2VydmVyJ3MgUEFUSCwgd2hpY2ggb2Z0ZW4gbGFja3MgbnZtIC8gbiAvIGZubSBmb2xkZXJzLgpSVU5USU1FPSIke0VOVl9SVU5USU1FOi0ke1dIRVJEUl9SVU5USU1FOi19fSIKVVJMPSJodHRwOi8vbG9jYWxob3N0OiRQT1JUIgoKc2F5KCkgeyBwcmludGYgJyVzXG4nICIkKiI7IH0Kb2soKSB7IHByaW50ZiAnICDinJMgJXNcbicgIiQqIjsgfQp3YXJuKCkgeyBwcmludGYgJyAgISAlc1xuJyAiJCoiID4mMjsgfQpkaWUoKSB7IHByaW50ZiAnICDinJcgJXNcbicgIiQqIiA+JjI7IGV4aXQgMTsgfQoKIyBBbnkgSFRUUCBhbnN3ZXIgY291bnRzIChhIGxvY2tlZCB3aGVyZHIgYW5zd2VycyA0MDEpOiB0aGUgcG9ydCBpcyB0YWtlbi4KYW5zd2VycygpIHsKICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICBjb2RlPSIkKGN1cmwgLXMgLW8gL2Rldi9udWxsIC0tbWF4LXRpbWUgMiAtdyAnJXtodHRwX2NvZGV9JyAiaHR0cDovLzEyNy4wLjAuMTokUE9SVC8iIDI+L2Rldi9udWxsIHx8IHRydWUpIgogICAgWyAtbiAiJGNvZGUiIF0gJiYgWyAiJGNvZGUiICE9ICIwMDAiIF0KICBlbGlmIGNvbW1hbmQgLXYgbmMgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICBuYyAteiAxMjcuMC4wLjEgIiRQT1JUIiA+L2Rldi9udWxsIDI+JjEKICBlbHNlCiAgICBkaWUgImN1cmwgb3IgbmMgaXMgbmVlZGVkIHRvIGNoZWNrIHBvcnQgJFBPUlQuIgogIGZpCn0KCiMgTWFqb3IgdmVyc2lvbiBvZiBhIG5vZGUgYmluYXJ5LCAwIHdoZW4gaXQgaXMgbm90IG9uZS4Kbm9kZV9tYWpvcigpIHsKICAiJDEiIC1wICdwcm9jZXNzLnZlcnNpb25zLm5vZGUuc3BsaXQoIi4iKVswXScgMj4vZGV2L251bGwgfHwgZWNobyAwCn0KCiMgQSB1c2FibGUgcnVudGltZTogTm9kZS5qcyAyMiBvciBuZXdlciwgb3IgQnVuIChpdCBydW5zIHRoZSBidWlsdCBzZXJ2ZXIgdG9vKS4KcnVudGltZV9vaygpIHsKICBbIC1uICIkMSIgXSAmJiBbIC14ICIkMSIgXSAmJiBbICEgLWQgIiQxIiBdIHx8IHJldHVybiAxCiAgY2FzZSAiJChiYXNlbmFtZSAiJDEiKSIgaW4KICAgIGJ1bikgIiQxIiAtLXZlcnNpb24gPi9kZXYvbnVsbCAyPiYxIDs7CiAgICAqKSBbICIkKG5vZGVfbWFqb3IgIiQxIikiIC1nZSAyMiBdIDI+L2Rldi9udWxsIDs7CiAgZXNhYwp9CgojIEFic29sdXRlIHBhdGggb2YgdGhlIHJ1bnRpbWU6IFdIRVJEUl9SVU5USU1FLCB0aGVuIG5vZGUgb24gdGhlIFBBVEgsIHRoZW4gdGhlCiMgdXN1YWwgaW5zdGFsbCBmb2xkZXJzIChuLCBudm0sIFZvbHRhLCBmbm0sIGFzZGYsIEhvbWVicmV3KSwgdGhlbiBCdW4uCiMgUHJpbnRzIG5vdGhpbmcgYW5kIGZhaWxzIHdoZW4gbm9uZSBpcyBmb3VuZC4KZmluZF9ydW50aW1lKCkgewogIGZvciBjIGluICIkUlVOVElNRSIgIiQoY29tbWFuZCAtdiBub2RlIDI+L2Rldi9udWxsIHx8IHRydWUpIiBcCiAgICAiJEhPTUUvLm4vYmluL25vZGUiICIke05fUFJFRklYOiskTl9QUkVGSVgvYmluL25vZGV9IiBcCiAgICAkKGxzIC1kICIkSE9NRSIvLm52bS92ZXJzaW9ucy9ub2RlL3YqL2Jpbi9ub2RlIDI+L2Rldi9udWxsIHwgc29ydCAtciAtVikgXAogICAgIiRIT01FLy52b2x0YS9iaW4vbm9kZSIgXAogICAgJChscyAtZCAiJEhPTUUiLy5sb2NhbC9zaGFyZS9mbm0vbm9kZS12ZXJzaW9ucy8qL2luc3RhbGxhdGlvbi9iaW4vbm9kZSAiJEhPTUUiLy5mbm0vbm9kZS12ZXJzaW9ucy8qL2luc3RhbGxhdGlvbi9iaW4vbm9kZSAyPi9kZXYvbnVsbCB8IHNvcnQgLXIgLVYpIFwKICAgICIkSE9NRS8uYXNkZi9zaGltcy9ub2RlIiAvb3B0L2hvbWVicmV3L2Jpbi9ub2RlIC91c3IvbG9jYWwvYmluL25vZGUgL3Vzci9iaW4vbm9kZSBcCiAgICAiJChjb21tYW5kIC12IGJ1biAyPi9kZXYvbnVsbCB8fCB0cnVlKSIgIiRIT01FLy5idW4vYmluL2J1biIgL29wdC9ob21lYnJldy9iaW4vYnVuIC91c3IvbG9jYWwvYmluL2J1bjsgZG8KICAgIGlmIHJ1bnRpbWVfb2sgIiRjIjsgdGhlbiBlY2hvICIkYyI7IHJldHVybiAwOyBmaQogIGRvbmUKICByZXR1cm4gMQp9CgpSVU5USU1FX0hFTFA9Ik5vZGUuanMgMjIgb3IgbmV3ZXIgKG9yIEJ1bikgaXMgcmVxdWlyZWQgdG8gcnVuIHdoZXJkci4KICAgICBJbnN0YWxsIGl0IGZyb20gaHR0cHM6Ly9ub2RlanMub3JnLCBvciBzZXQgaXRzIGFic29sdXRlIHBhdGggaW4gJENPTkY6CiAgICAgICBXSEVSRFJfUlVOVElNRT0vcGF0aC90by9ub2RlIgoKaGVyZHJfYmluKCkgewogIGlmIFsgLW4gIiR7SEVSRFJfQklOX1BBVEg6LX0iIF07IHRoZW4gZWNobyAiJEhFUkRSX0JJTl9QQVRIIgogIGVsaWYgWyAteCAiJEhPTUUvLmxvY2FsL2Jpbi9oZXJkciIgXTsgdGhlbiBlY2hvICIkSE9NRS8ubG9jYWwvYmluL2hlcmRyIgogIGVsc2UgY29tbWFuZCAtdiBoZXJkciAyPi9kZXYvbnVsbCB8fCBlY2hvIGhlcmRyCiAgZmkKfQoKIyBUaGUgY29tbWFuZHMgb2YgdGhlIG5hdGl2ZSBtb2RlOiB0aGUgaW5zdGFsbGVkIGNvcHksIG9yIHRoZSBjaGVja291dCBpdHNlbGYKIyAoYSBsaW5rZWQgcGx1Z2luIGJ1aWx0IGJ5IGhhbmQsIG9yIGEgcGx1Z2luIGluc3RhbGxlZCBiZWZvcmUgJEFQUCBleGlzdGVkKS4KY2xpX3Jvb3QoKSB7CiAgaWYgWyAtZiAiJEFQUC9iaW4vd2hlcmRyLm1qcyIgXSAmJiBbIC1mICIkQVBQLy5vdXRwdXQvc2VydmVyL2luZGV4Lm1qcyIgXTsgdGhlbiBlY2hvICIkQVBQIjsgZWxzZSBlY2hvICIkUk9PVCI7IGZpCn0KCiMgVGhlIHBlcnNvbiBydW5uaW5nIGBoZXJkciBwbHVnaW4gaW5zdGFsbGAgc2VlcyBvbmx5IEhlcmRyJ3Mgb3duIGxpbmVzOiB0aGUKIyBvdXRwdXQgb2YgYnVpbGQgY29tbWFuZHMgaXMgY2FwdHVyZWQuIEltcG9ydGFudCBsaW5lcyBhbHNvIGdvIHRvIHRoZSB0ZXJtaW5hbC4KdGVsbCgpIHsKICBwcmludGYgJyVzXG4nICIkKiIKICB7IHByaW50ZiAnJXNcbicgIiQqIiA+IC9kZXYvdHR5OyB9IDI+L2Rldi9udWxsIHx8IHRydWUKfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gYnVpbGQKY21kX2J1aWxkKCkgewogIHRlbGwgIndoZXJkcjogaW5zdGFsbGluZyBpbiAkRElSIgogICMgRmlyc3QgaW5zdGFsbCAobm8gcGx1Z2luLmVudiB5ZXQpOiB0aGUgYnJvd3NlciBvcGVucyBvbiB0aGUgc2V0dXAgZ3VpZGUKICAjIG9uY2Ugd2hlcmRyIHJ1bnMuIFVwZGF0ZXMga2VlcCBwbHVnaW4uZW52IGFuZCBvcGVuIG5vdGhpbmcuCiAgRklSU1RfSU5TVEFMTD0wCiAgWyAtZiAiJENPTkYiIF0gfHwgRklSU1RfSU5TVEFMTD0xCiAgbWtkaXIgLXAgIiRESVIiCiAgcHJpbnRmICclc1xuJyAiJERJUiIgPiAiJFJPT1QvLndoZXJkci1kaXIiCgogIGlmIFsgIiRMRUdBQ1lfTU9ERSIgPSBkb2NrZXIgXTsgdGhlbgogICAgdGVsbCAid2hlcmRyIDIuMCByZW1vdmVzIERvY2tlciBzdXBwb3J0OiBzd2l0Y2hpbmcgdGhpcyBwbHVnaW4gdG8gdGhlIG5hdGl2ZSBzZXJ2aWNlLiIKICAgIHRlbGwgIlN0b3AgdGhlIG9sZCAxLnggaW5zdGFuY2UgYmVmb3JlIHN0YXJ0aW5nIHRoZSBuYXRpdmUgc2VydmljZTsga2VlcCBpdHMgZGF0YSBmb2xkZXIuIgogICAgdGVsbCAiTWlncmF0aW9uOiBodHRwczovL2dpdGh1Yi5jb20vJFNPVVJDRS9ibG9iL21haW4vZG9jcy9taWdyYXRlLWZyb20tMS54LWRvY2tlci5tZCIKICBmaQogIGJ1aWxkX25hdGl2ZQogICMgV3JpdHRlbiBsYXN0OiBhIGZhaWxlZCBidWlsZCBrZWVwcyBubyBoYWxmLW1hZGUgY2hvaWNlLiBSZXdyaXR0ZW4gb24gZWFjaAogICMgaW5zdGFsbCBmcm9tIHRoZSBtZXJnZWQgc2V0dGluZ3MgKGVudmlyb25tZW50IG92ZXIgdGhlIHByZXZpb3VzIGZpbGUpLgogIHdyaXRlX2NvbmYKICBvayAicGx1Z2luLmVudiB3cml0dGVuIChuYXRpdmUgc2VydmljZSkiCiAgKCBjbWRfc2tpbGwgcmVmcmVzaCApIHx8IHdhcm4gIndoZXJkciBza2lsbCBub3QgbGlua2VkIChvcHRpb25hbCk6IHJ1biAkMCBza2lsbCBpbnN0YWxsIgogICggY21kX2tleSBpbnN0YWxsICkgfHwgd2FybiAibm8gSGVyZHIga2V5IGZvciB0aGUgcGFuZWwgKG9wdGlvbmFsKTogcnVuICQwIGtleSBpbnN0YWxsIgogIGJ1aWxkX3N0YXJ0Cn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHNraWxsCiMgSW5zdGFsbGF0aW9uIGlzIHNoYXJlZCB3aXRoIG5wbSAvIEhvbWVicmV3LgpjbWRfc2tpbGwoKSB7CiAgY2FzZSAiJHsxOi19IiBpbgogICAgcmVmcmVzaHxpbnN0YWxsKQogICAgICBXSEVSRFJfRElSPSIkRElSIiBzaCAiJFJPT1QvYmluL2xpYi9pbnN0YWxsLXNraWxsLnNoIiAiJDEiICIkUk9PVCIKICAgICAgOzsKICAgIHVuaW5zdGFsbCkgV0hFUkRSX0RJUj0iJERJUiIgc2ggIiRST09UL2Jpbi9saWIvaW5zdGFsbC1za2lsbC5zaCIgdW5pbnN0YWxsICIkUk9PVCIgOzsKICAgICopIGRpZSAidXNhZ2U6ICQwIHNraWxsIGluc3RhbGx8dW5pbnN0YWxsIiA7OwogIGVzYWMKfQoKIyBMYXN0IHN0ZXAgb2YgdGhlIGluc3RhbGw6IHN0YXJ0IHdoZXJkciAob3IgcmVzdGFydCB0aGUgb25lIHRoaXMgcGx1Z2luCiMgcnVucywgb24gYW4gdXBkYXRlKS4gTmV2ZXIgZmFpbHMgdGhlIGluc3RhbGw6IGEgd2hlcmRyIHRoYXQgY2Fubm90IHN0YXJ0IGlzCiMgcmVwb3J0ZWQgd2l0aCB3aGF0IHRvIGRvLCB0aGUgcGx1Z2luIHN0YXlzIGluc3RhbGxlZC4KYnVpbGRfc3RhcnQoKSB7CiAgc2V0ICtlCiAgb3V0PSIkKCAoY21kX3N0YXJ0KSAyPiYxICkiCiAgY29kZT0kPwogIHNldCAtZQogIHByaW50ZiAnJXNcbicgIiRvdXQiCiAgaWYgWyAiJGNvZGUiIC1lcSAwIF0gJiYgYW5zd2VyczsgdGhlbgogICAgIyBodHRwczovL3doZXJkci5kZXYvaW5zdGFsbCBwcmludHMgaXRzIG93biBzdW1tYXJ5IChXSEVSRFJfSU5TVEFMTEVSPTEpLgogICAgcXVpZXQ9MAogICAgWyAiJHtXSEVSRFJfSU5TVEFMTEVSOi0wfSIgPSAxIF0gJiYgcXVpZXQ9MQogICAgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIiCiAgICBbICIkcXVpZXQiID0gMSBdIHx8IHRlbGwgIuKckyB3aGVyZHIgaXMgcnVubmluZyDihpIgJFVSTCIKICAgIGlmIFsgIiRxdWlldCIgIT0gMSBdOyB0aGVuCiAgICAgIGtleT0iJChrZXlfYm91bmQpIgogICAgICBpZiBbIC1uICIka2V5IiBdOyB0aGVuIHRlbGwgIiAgSW4gSGVyZHIsICRrZXkgb3BlbnMgdGhlIHdoZXJkciBwYW5lbC4iCiAgICAgIGVsc2UgdGVsbCAiICBJbiBIZXJkcjogaGVyZHIgcGx1Z2luIGFjdGlvbiBpbnZva2UgcGFuZWwgLS1wbHVnaW4gJFBMVUdJTl9JRCIKICAgICAgZmkKICAgIGZpCiAgICBpZiBbICIke0ZJUlNUX0lOU1RBTEw6LTB9IiA9IDEgXTsgdGhlbgogICAgICAjIEFscmVhZHkgcHVibGlzaGVkIG9uIHRoZSB0YWlsbmV0IChhIHJlaW5zdGFsbCwgb3IgYHRhaWxzY2FsZSBzZXJ2ZWAKICAgICAgIyBydW4gZmlyc3QpOiB0aGUgZ3VpZGUgb3BlbnMgb24gdGhhdCBhZGRyZXNzLCB3aGVyZSBwYXNza2V5cyBiZWxvbmcuCiAgICAgIGd1aWRlPSIkKG9wZW5fYWRkcmVzcykvIy9zZXR1cCIKICAgICAgaWYgb3Blbl9icm93c2VyICIkZ3VpZGUiOyB0aGVuIFsgIiRxdWlldCIgPSAxIF0gfHwgdGVsbCAiICBTZXR1cCBndWlkZSBvcGVuZWQgaW4geW91ciBicm93c2VyOiAkZ3VpZGUiCiAgICAgIGVsc2UgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIgIFNldHVwIGd1aWRlOiBvcGVuICRndWlkZSBpbiBhIGJyb3dzZXIiCiAgICAgIGZpCiAgICBmaQogICAgWyAiJHF1aWV0IiA9IDEgXSB8fCB0ZWxsICIgIFBob25lOiBwcmVzcyBQIGluIHRoZSBwYW5lbCB0byBnZXQgeW91ciBUYWlsc2NhbGUgYWRkcmVzcyAocHJpdmF0ZSBuZXR3b3JrIG9ubHkpLiIKICBlbHNlCiAgICB0ZWxsICIiCiAgICB0ZWxsICIhIHdoZXJkciBpcyBpbnN0YWxsZWQgYnV0IGRpZCBub3Qgc3RhcnQ6IgogICAgcHJpbnRmICclc1xuJyAiJG91dCIgfCB0YWlsIC1uIDggfCB3aGlsZSBJRlM9IHJlYWQgLXIgbDsgZG8gdGVsbCAiICAgICRsIjsgZG9uZQogICAgdGVsbCAiICBPcGVuIHRoZSB3aGVyZHIgcGFuZWwgaW4gSGVyZHIsIHRoZW4gcHJlc3MgUyB0byBzdGFydCBpdCBvciBMIGZvciBpdHMgbG9nLiIKICBmaQp9Cgp3cml0ZV9jb25mKCkgewogIHsKICAgIGVjaG8gIiMgd2hlcmRyIEhlcmRyIHBsdWdpbiBzZXR0aW5ncyAoaGVyZHItcGx1Z2luLnNoKS4iCiAgICBlY2hvICJXSEVSRFJfUE9SVD0kUE9SVCIKICAgIGVjaG8gIiMgTmF0aXZlIG1vZGU6IHByaXZhdGUgSFRUUFMgYWRkcmVzcyAodGFpbHNjYWxlIHNlcnZlKSwgZm9yIHB1c2ggbm90aWZpY2F0aW9ucy4iCiAgICBlY2hvICJBUFBfVVJMPSR7QVBQX1VSTDotfSIKICAgIGVjaG8gIiMgQWJzb2x1dGUgcGF0aCBvZiB0aGUgbm9kZSAoMjIrKSBvciBidW4gdGhhdCBydW5zIHdoZXJkci4iCiAgICBlY2hvICJXSEVSRFJfUlVOVElNRT0kUlVOVElNRSIKICB9ID4gIiRDT05GIgp9CgojIFByZWZlciB0aGUgcmVsZWFzZSBhcmNoaXZlLCB0aGVuIHRoZSBhbHJlYWR5LWJ1aWx0IG5wbSBwYWNrYWdlLiBDb21waWxlIG9ubHkKIyB3aGVuIG5laXRoZXIgc291cmNlIHByb3ZpZGVzIGEgdXNhYmxlIHBhY2thZ2Ugb2YgdGhpcyBleGFjdCB2ZXJzaW9uLgpmZXRjaF9wcmVidWlsdCgpIHsKICBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxICYmIGNvbW1hbmQgLXYgdGFyID4vZGV2L251bGwgMj4mMSB8fCByZXR1cm4gMQogIHZlcnNpb249IiQoc2VkIC1uICdzL152ZXJzaW9uID0gIlwoLipcKSIkL1wxL3AnICIkUk9PVC9oZXJkci1wbHVnaW4udG9tbCIgfCBoZWFkIC1uIDEpIgogIHRtcD0iJChta3RlbXAgLWQpIgogIGZvciBzb3VyY2UgaW4gZ2l0aHViIG5wbTsgZG8KICAgIHJtIC1yZiAiJHRtcC9wYWNrYWdlIgogICAgaWYgWyAiJHNvdXJjZSIgPSBnaXRodWIgXTsgdGhlbgogICAgICB1cmw9Imh0dHBzOi8vZ2l0aHViLmNvbS8kU09VUkNFL3JlbGVhc2VzL2Rvd25sb2FkL3YkdmVyc2lvbi93aGVyZHItJHZlcnNpb24udGd6IgogICAgICBjdXJsIC1mc1NMIC0tbWF4LXRpbWUgMTIwICIkdXJsIiAtbyAiJHRtcC93aGVyZHIudGd6IiAyPi9kZXYvbnVsbCBcCiAgICAgICAgJiYgY3VybCAtZnNTTCAtLW1heC10aW1lIDMwICIkdXJsLnNoYTI1NiIgLW8gIiR0bXAvY2hlY2tzdW0iIDI+L2Rldi9udWxsIFwKICAgICAgICAmJiAiJFJVTlRJTUUiICIkUk9PVC9iaW4vbGliL3ZlcmlmeS1yZWxlYXNlLm1qcyIgIiR0bXAvd2hlcmRyLnRneiIgIiR0bXAvY2hlY2tzdW0iIDI+L2Rldi9udWxsIHx8IGNvbnRpbnVlCiAgICBlbHNlCiAgICAgIHVybD0iaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvd2hlcmRyLy0vd2hlcmRyLSR2ZXJzaW9uLnRneiIKICAgICAgY3VybCAtZnNTTCAtLW1heC10aW1lIDEyMCAiJHVybCIgLW8gIiR0bXAvd2hlcmRyLnRneiIgMj4vZGV2L251bGwgXAogICAgICAgICYmIGN1cmwgLWZzU0wgLS1tYXgtdGltZSAzMCAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvd2hlcmRyLyR2ZXJzaW9uIiAtbyAiJHRtcC9tZXRhZGF0YSIgMj4vZGV2L251bGwgXAogICAgICAgICYmICIkUlVOVElNRSIgIiRST09UL2Jpbi9saWIvdmVyaWZ5LXJlbGVhc2UubWpzIiAiJHRtcC93aGVyZHIudGd6IiAiJHRtcC9tZXRhZGF0YSIgbnBtICIkdmVyc2lvbiIgMj4vZGV2L251bGwgfHwgY29udGludWUKICAgIGZpCiAgICB0YXIgLXh6ZiAiJHRtcC93aGVyZHIudGd6IiAtQyAiJHRtcCIgMj4vZGV2L251bGwgfHwgY29udGludWUKICAgIFsgLWYgIiR0bXAvcGFja2FnZS8ub3V0cHV0L3NlcnZlci9pbmRleC5tanMiIF0gXAogICAgICAmJiBbIC1kICIkdG1wL3BhY2thZ2UvYmluIiBdICYmIFsgLWYgIiR0bXAvcGFja2FnZS9wYWNrYWdlLmpzb24iIF0gfHwgY29udGludWUKICAgICMgTGVnYWN5IHBhY2thZ2VzIGhhdmUgbmVpdGhlciB0aGUgc2tpbGwgbm9yIGl0cyBoZWxwZXJzLiBLZWVwIHRoZQogICAgIyBjaGVja291dCdzIGNvbW1hbmRzIHNvIHBsdWdpbiBza2lsbCBpbnN0YWxsL3VuaW5zdGFsbCBzdGlsbCB3b3JrLgogICAgZm9yIGVudHJ5IGluIC5vdXRwdXQgYmluIHBhY2thZ2UuanNvbiBza2lsbHM7IGRvCiAgICAgIFsgLWUgIiR0bXAvcGFja2FnZS8kZW50cnkiIF0gfHwgY29udGludWUKICAgICAgaWYgWyAiJGVudHJ5IiA9IGJpbiBdOyB0aGVuCiAgICAgICAgWyAtZiAiJHRtcC9wYWNrYWdlL3NraWxscy93aGVyZHIvU0tJTEwubWQiIF0gXAogICAgICAgICAgJiYgWyAtZiAiJHRtcC9wYWNrYWdlL2Jpbi9saWIvaW5zdGFsbC1za2lsbC5zaCIgXSB8fCBjb250aW51ZQogICAgICBmaQogICAgICBybSAtcmYgIiRST09ULyRlbnRyeSIKICAgICAgbXYgIiR0bXAvcGFja2FnZS8kZW50cnkiICIkUk9PVC8kZW50cnkiCiAgICBkb25lCiAgICBybSAtcmYgIiR0bXAiCiAgICBvayAid2hlcmRyICR2ZXJzaW9uIGRvd25sb2FkZWQgKCRzb3VyY2UgcGFja2FnZSwgY2hlY2tzdW0gbWF0Y2hlZCkiCiAgICByZXR1cm4gMAogIGRvbmUKICBybSAtcmYgIiR0bXAiCiAgcmV0dXJuIDEKfQoKIyBxcmNvZGUtdGVybWluYWwgKHRoZSBwYW5lbCdzIFFSIGNvZGUpLCB0aGUgb25seSBwYWNrYWdlIHRoZSBjb21tYW5kcyBuZWVkCiMgYXQgcnVudGltZSwgd2hlbiB0aGUgZm9sZGVyIGRvZXMgbm90IGhhdmUgaXQgeWV0IChubyBucG0gY2kgd2FzIHJ1bikuCmZldGNoX3FyKCkgewogIFsgLWYgIiQxL25vZGVfbW9kdWxlcy9xcmNvZGUtdGVybWluYWwvcGFja2FnZS5qc29uIiBdICYmIHJldHVybiAwCiAgY29tbWFuZCAtdiBjdXJsID4vZGV2L251bGwgMj4mMSAmJiBjb21tYW5kIC12IHRhciA+L2Rldi9udWxsIDI+JjEgfHwgcmV0dXJuIDAKICB0bXA9IiQobWt0ZW1wIC1kKSIKICBpZiBjdXJsIC1mc1NMIC0tbWF4LXRpbWUgNjAgaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvcXJjb2RlLXRlcm1pbmFsLy0vcXJjb2RlLXRlcm1pbmFsLTAuMTIuMC50Z3ogLW8gIiR0bXAvcXIudGd6IiAyPi9kZXYvbnVsbCBcCiAgICAmJiB0YXIgLXh6ZiAiJHRtcC9xci50Z3oiIC1DICIkdG1wIjsgdGhlbgogICAgbWtkaXIgLXAgIiQxL25vZGVfbW9kdWxlcyIKICAgIHJtIC1yZiAiJDEvbm9kZV9tb2R1bGVzL3FyY29kZS10ZXJtaW5hbCIKICAgIG12ICIkdG1wL3BhY2thZ2UiICIkMS9ub2RlX21vZHVsZXMvcXJjb2RlLXRlcm1pbmFsIgogIGVsc2UKICAgIHdhcm4gIk5vIFFSIGNvZGUgaW4gdGhlIHBhbmVsIChxcmNvZGUtdGVybWluYWwgY291bGQgbm90IGJlIGRvd25sb2FkZWQpLiIKICBmaQogIHJtIC1yZiAiJHRtcCIKfQoKYnVpbGRfbmF0aXZlKCkgewogIFJVTlRJTUU9IiQoZmluZF9ydW50aW1lKSIgfHwgZGllICIkUlVOVElNRV9IRUxQIgogIG9rICJSdW50aW1lOiAkUlVOVElNRSAoJCgiJFJVTlRJTUUiIC0tdmVyc2lvbiAyPi9kZXYvbnVsbCkpIgogIGlmIGZldGNoX3ByZWJ1aWx0OyB0aGVuCiAgICBpbnN0YWxsX2FwcAogICAgcmV0dXJuIDAKICBmaQogIGNhc2UgIiQoYmFzZW5hbWUgIiRSVU5USU1FIikiIGluCiAgICBidW4pIGRpZSAiVGhlIHByZWJ1aWx0IHdoZXJkciBwYWNrYWdlIGNvdWxkIG5vdCBiZSBkb3dubG9hZGVkLCBhbmQgYnVpbGRpbmcgaXQgbmVlZHMgTm9kZS5qcyAyMiB3aXRoIG5wbS4KICAgICBDaGVjayB0aGUgbmV0d29yaywgb3IgaW5zdGFsbCBOb2RlLmpzIDIyLCB0aGVuIGluc3RhbGwgdGhlIHBsdWdpbiBhZ2Fpbi4iIDs7CiAgZXNhYwogIGJpbmRpcj0iJChkaXJuYW1lICIkUlVOVElNRSIpIgogIFsgLXggIiRiaW5kaXIvbnBtIiBdIHx8IGNvbW1hbmQgLXYgbnBtID4vZGV2L251bGwgMj4mMSB8fCBkaWUgIm5wbSBpcyBtaXNzaW5nIChpdCBjb21lcyB3aXRoIE5vZGUuanMpLiIKICB0ZWxsICJ3aGVyZHI6IGJ1aWxkaW5nIChhIGZldyBtaW51dGVzIHRoZSBmaXJzdCB0aW1lKeKApiIKICAoCiAgICBjZCAiJFJPT1QiCiAgICBQQVRIPSIkYmluZGlyOiRQQVRIIiBucG0gY2kgLS1uby1hdWRpdCAtLW5vLWZ1bmQKICAgIFBBVEg9IiRiaW5kaXI6JFBBVEgiIG5wbSBydW4gYnVpbGQKICApCiAgb2sgIndoZXJkciBidWlsdCBpbiB0aGUgcGx1Z2luIGZvbGRlciIKICBpbnN0YWxsX2FwcAp9CgojIENvcGllcyB0aGUgY29tbWFuZHMgYW5kIHRoZSBidWlsdCBzZXJ2ZXIgdG8gJEFQUCwgd2hpY2ggb3V0bGl2ZXMgdGhpcwojIGNoZWNrb3V0LiBBIHdoZXJkciB0aGlzIHBsdWdpbiBydW5zIGZyb20gdGhlIHByZXZpb3VzIGNvcHkgaXMgc3RvcHBlZCBmb3IKIyB0aGUgc3dhcDsgYnVpbGRfc3RhcnQgc3RhcnRzIHRoZSBuZXcgb25lLgppbnN0YWxsX2FwcCgpIHsKICAjIE5pdHJvIGxpbmtzIHNvbWUgcGFja2FnZXMgKHRzbGliKSB0byBpdHMgb3duIGZvbGRlcjogY29waWVzLCBub3QgbGlua3MuCiAgaWYgWyAtZCAiJFJPT1QvLm91dHB1dC9zZXJ2ZXIvbm9kZV9tb2R1bGVzIiBdOyB0aGVuICIkUlVOVElNRSIgIiRST09UL3NjcmlwdHMvcGFjay1vdXRwdXQubWpzIiA+L2Rldi9udWxsOyBmaQogIG5ldz0iJEFQUC5uZXciCiAgcm0gLXJmICIkbmV3IgogIG1rZGlyIC1wICIkbmV3IgogIGNwIC1SICIkUk9PVC9iaW4iICIkUk9PVC9za2lsbHMiICIkUk9PVC8ub3V0cHV0IiAiJFJPT1QvcGFja2FnZS5qc29uIiAiJG5ldy8iCiAgaWYgWyAtZCAiJFJPT1Qvbm9kZV9tb2R1bGVzL3FyY29kZS10ZXJtaW5hbCIgXTsgdGhlbgogICAgbWtkaXIgLXAgIiRuZXcvbm9kZV9tb2R1bGVzIgogICAgY3AgLVIgIiRST09UL25vZGVfbW9kdWxlcy9xcmNvZGUtdGVybWluYWwiICIkbmV3L25vZGVfbW9kdWxlcy8iCiAgZmkKICBmZXRjaF9xciAiJG5ldyIKICAjIFRoZSB3aGVyZHIgdGhpcyBwbHVnaW4gcnVucyAoZnJvbSB0aGUgcHJldmlvdXMgY29weSwgb3IgZnJvbSBhbiBvbGRlcgogICMgcGx1Z2luIGNoZWNrb3V0KTogc3RvcHBlZCBmb3IgdGhlIHN3YXAsIHN0YXJ0ZWQgYWdhaW4gYnkgYnVpbGRfc3RhcnQuCiAgaWYgWyAtZiAiJERJUi93aGVyZHIucGlkIiBdIHx8IFsgLWYgIiRBUFAvYmluL3doZXJkci5tanMiIF07IHRoZW4gY2xpIHN0b3AgPi9kZXYvbnVsbCAyPiYxIHx8IHRydWU7IGZpCiAgcm0gLXJmICIkQVBQLm9sZCIKICBpZiBbIC1kICIkQVBQIiBdOyB0aGVuIG12ICIkQVBQIiAiJEFQUC5vbGQiOyBmaQogIG12ICIkbmV3IiAiJEFQUCIKICBybSAtcmYgIiRBUFAub2xkIgogIG9rICJ3aGVyZHIgJChzZWQgLW4gJ3MvXiAqInZlcnNpb24iOiAqIlwoLipcKSIsJC9cMS9wJyAiJEFQUC9wYWNrYWdlLmpzb24iIHwgaGVhZCAtbiAxKSBpbnN0YWxsZWQgaW4gJEFQUCIKfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gc3RhcnQKY21kX3N0YXJ0KCkgewogIGlmIGFuc3dlcnM7IHRoZW4KICAgIHNheSAid2hlcmRyOiBzb21ldGhpbmcgYWxyZWFkeSBhbnN3ZXJzIG9uIHBvcnQgJFBPUlQsIG5vdGhpbmcgdG8gc3RhcnQgKCRVUkwpLiIKICAgIHJldHVybiAwCiAgZmkKICBzdGFydF9uYXRpdmUKfQoKIyBOYXRpdmUgbW9kZTogdGhlIHdoZXJkciBjb21tYW5kIChiaW4vd2hlcmRyLm1qcykgZG9lcyB0aGUgd29yaywgd2l0aCB0aGUKIyBydW50aW1lIHNhdmVkIGF0IGluc3RhbGw7IGl0IHNheXMgInN0YXJ0ZWQiIG9ubHkgb25jZSB0aGUgcG9ydCBhbnN3ZXJzLgplbnN1cmVfcnVudGltZSgpIHsKICBpZiAhIHJ1bnRpbWVfb2sgIiRSVU5USU1FIjsgdGhlbgogICAgc2F2ZWQ9IiRSVU5USU1FIgogICAgUlVOVElNRT0iJChmaW5kX3J1bnRpbWUpIiB8fCBkaWUgIiR7c2F2ZWQ6K1RoZSBzYXZlZCBydW50aW1lICgkc2F2ZWQpIGlzIGdvbmUuIH0kUlVOVElNRV9IRUxQIgogICAgd2FybiAiJHtzYXZlZDorJHNhdmVkIGlzIGdvbmU6IH11c2luZyAkUlVOVElNRSAoc2F2ZWQgaW4gJENPTkYpLiIKICAgIHdyaXRlX2NvbmYKICBmaQp9CgpjbGkoKSB7CiAgZW5zdXJlX3J1bnRpbWUKICBzb2NrPSIke0hFUkRSX1NPQ0tFVF9QQVRIOi19IgogICMgQSBwbHVnaW4gc3RhcnRlZCBmcm9tIGEgbmFtZWQgSGVyZHIgc2Vzc2lvbiBkcml2ZXMgdGhhdCBzZXNzaW9uLgogIHNlc3Npb249IiIKICBjYXNlICIkc29jayIgaW4gKi9zZXNzaW9ucy8qL2hlcmRyLnNvY2spIHNlc3Npb249IiQoYmFzZW5hbWUgIiQoZGlybmFtZSAiJHNvY2siKSIpIiA7OyBlc2FjCiAgKAogICAgY2QgIiRESVIiCiAgICBIRVJEUl9CSU49IiQoaGVyZHJfYmluKSIKICAgICMgVGhlIHJ1bnRpbWUncyBmb2xkZXIgZmlyc3Q6IHRvb2xzIGl0IHN0YXJ0cyBmaW5kIHRoZSBzYW1lIG5vZGUuCiAgICBQQVRIPSIkKGRpcm5hbWUgIiRSVU5USU1FIik6JFBBVEgiCiAgICBleHBvcnQgUEFUSCBXSEVSRFJfRElSPSIkRElSIiBXSEVSRFJfUlVOVElNRT0iJFJVTlRJTUUiIEhPU1Q9MTI3LjAuMC4xIFBPUlQgSEVSRFJfQklOCiAgICBpZiBbIC1uICIkc2Vzc2lvbiIgXTsgdGhlbiBleHBvcnQgSEVSRFJfV0VCX1NFU1NJT049IiRzZXNzaW9uIjsgZmkKICAgIGlmIFsgLW4gIiRzb2NrIiBdOyB0aGVuIGV4cG9ydCBIRVJEUl9TT0NLPSIkc29jayI7IGZpCiAgICBpZiBbIC1uICIke0FQUF9VUkw6LX0iIF07IHRoZW4gZXhwb3J0IEFQUF9VUkw7IGZpCiAgICBleGVjICIkUlVOVElNRSIgIiQoY2xpX3Jvb3QpL2Jpbi93aGVyZHIubWpzIiAiJEAiCiAgKQp9CgpzdGFydF9uYXRpdmUoKSB7CiAgWyAtZiAiJChjbGlfcm9vdCkvLm91dHB1dC9zZXJ2ZXIvaW5kZXgubWpzIiBdIHx8IGRpZSAid2hlcmRyIGlzIG5vdCBidWlsdDogaW5zdGFsbCB0aGUgcGx1Z2luIGFnYWluIChoZXJkciBwbHVnaW4gaW5zdGFsbCAkU09VUkNFIC0teWVzKS4iCiAgbWtkaXIgLXAgIiRESVIiCiAgY2xpIHN0YXJ0Cn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzdG9wCmNtZF9zdG9wKCkgeyBjbGkgc3RvcDsgfQpjbWRfc3RhdHVzKCkgeyBjbGkgc3RhdHVzOyBzYXkgIiAgUGx1Z2luICAgbmF0aXZlIHNlcnZpY2UsIHNldHRpbmdzIGluICRDT05GIjsgfQpjbWRfbG9ncygpIHsgY2xpIGxvZ3MgLS1mb2xsb3c7IH0KY21kX2RvY3RvcigpIHsgY2xpIGRvY3RvcjsgfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIG9wZW4KIyBUaGUgZGVmYXVsdCBicm93c2VyLCBvbiBhIGNvbXB1dGVyIHdpdGggYSBzY3JlZW4gb25seTogYG9wZW5gIG9uIG1hY09TLAojIGB4ZGctb3BlbmAgb24gTGludXggd2l0aCBhIGRpc3BsYXkuIEZhaWxzIChvcGVucyBub3RoaW5nKSBvbiBhIGhlYWRsZXNzIHNlcnZlciwKIyBvciB3aXRoIFdIRVJEUl9OT19CUk9XU0VSPTEgKHNldCBieSBodHRwczovL3doZXJkci5kZXYvaW5zdGFsbCBvdmVyIFNTSCkuCm9wZW5fYnJvd3NlcigpIHsKICBpZiBbICIke1dIRVJEUl9OT19CUk9XU0VSOi0wfSIgPSAiMSIgXTsgdGhlbiByZXR1cm4gMQogIGVsaWYgWyAiJCh1bmFtZSAtcykiID0gIkRhcndpbiIgXSAmJiBjb21tYW5kIC12IG9wZW4gPi9kZXYvbnVsbCAyPiYxOyB0aGVuIG9wZW4gIiQxIgogIGVsaWYgWyAtbiAiJHtESVNQTEFZOi19JHtXQVlMQU5EX0RJU1BMQVk6LX0iIF0gJiYgY29tbWFuZCAtdiB4ZGctb3BlbiA+L2Rldi9udWxsIDI+JjE7IHRoZW4geGRnLW9wZW4gIiQxIiA+L2Rldi9udWxsIDI+JjEgJgogIGVsc2UgcmV0dXJuIDEKICBmaQp9CgojIFRoZSB0YWlsc2NhbGUgQ0xJOiBvbiB0aGUgUEFUSCwgb3IgaW5zaWRlIHRoZSBtYWNPUyBhcHAuCnRhaWxzY2FsZV9iaW4oKSB7CiAgaWYgY29tbWFuZCAtdiB0YWlsc2NhbGUgPi9kZXYvbnVsbCAyPiYxOyB0aGVuIGNvbW1hbmQgLXYgdGFpbHNjYWxlCiAgZWxpZiBbIC14IC9BcHBsaWNhdGlvbnMvVGFpbHNjYWxlLmFwcC9Db250ZW50cy9NYWNPUy9UYWlsc2NhbGUgXTsgdGhlbiBlY2hvIC9BcHBsaWNhdGlvbnMvVGFpbHNjYWxlLmFwcC9Db250ZW50cy9NYWNPUy9UYWlsc2NhbGUKICBlbHNlIHJldHVybiAxCiAgZmkKfQoKIyAiPG1hY2hpbmU+Ljx0YWlsbmV0Pi50cy5uZXRbOnBvcnRdIiBvZiB0aGUgYWRkcmVzcyBgdGFpbHNjYWxlIHNlcnZlYAojIHB1Ymxpc2hlcyBmb3Igd2hlcmRyJ3MgbG9jYWwgcG9ydCwgcmVhZCBmcm9tIFRhaWxzY2FsZSBvbiB0aGlzIG1hY2hpbmUuCnNlcnZlZF9ob3N0KCkgewogIHRzPSIkKHRhaWxzY2FsZV9iaW4pIiB8fCByZXR1cm4gMQogICMgIjxuYW1lPjo8aHR0cHMgcG9ydD4iIG9mIHRoZSBXZWIgZW50cnkgd2hvc2UgcHJveHkgdGFyZ2V0cyBvdXIgcG9ydC4KICBob3N0PSIkKCIkdHMiIHNlcnZlIHN0YXR1cyAtLWpzb24gMj4vZGV2L251bGwgfCB0ciAneywnICdcblxuJyB8IGF3ayAtdiBwb3J0PSIkUE9SVCIgJwogICAgLyJbXiJdKjpbMC05XSsiWyBcdF0qOlsgXHRdKiQvIHsga2V5ID0gJDA7IHN1YigvXlteIl0qIi8sICIiLCBrZXkpOyBzdWIoLyIuKiQvLCAiIiwga2V5KSB9CiAgICAvIlByb3h5Ii8gJiYgJDAgfiAoIlwiKGh0dHBzPzovLyk/KDEyN1xcLjBcXC4wXFwuMXxsb2NhbGhvc3QpOiIgcG9ydCAiLz9cIiIpIHsgcHJpbnQga2V5OyBleGl0IH0nKSIKICBbIC1uICIkaG9zdCIgXSB8fCByZXR1cm4gMQogIHByaW50ZiAnJXNcbicgIiR7aG9zdCU6NDQzfSIKfQoKIyBEb2VzIHRoZSBwaG9uZSBhZGRyZXNzIGFuc3dlcj8gIm9rIiAod2hlcmRyLCBhbmQgaXQgYWNjZXB0cyB0aGF0IGFkZHJlc3MpLAojICJob3N0IiAod2hlcmRyIHJlZnVzZXMgdGhhdCBhZGRyZXNzKSwgb3IgIm5vbmUiLiAvYXBpL2hlYWx0aCBnb2VzIHRocm91Z2gKIyB3aGVyZHIncyBob3N0IGNoZWNrOyB0aGUgc3RhdGljIG1hbmlmZXN0IGFuc3dlcnMgZm9yIGFueSBob3N0IG5hbWUgYW5kIG9ubHkKIyByZWNvZ25pemVzIGEgd2hlcmRyIG9sZGVyIHRoYW4gdGhhdCByb3V0ZS4KcGhvbmVfcmVhY2goKSB7CiAgY29tbWFuZCAtdiBjdXJsID4vZGV2L251bGwgMj4mMSB8fCB7IGVjaG8gbm9uZTsgcmV0dXJuIDA7IH0KICBib2R5PSIkKGN1cmwgLXMgLS1tYXgtdGltZSA4ICIkezF9YXBpL2hlYWx0aCIgMj4vZGV2L251bGwgfHwgdHJ1ZSkiCiAgY2FzZSAiJGJvZHkiIGluCiAgICAqJyJuYW1lIjoid2hlcmRyIicqKSBlY2hvIG9rIDs7CiAgICAqJyJjb2RlIjoiaG9zdCInKikgZWNobyBob3N0IDs7CiAgICAqKSBpZiBjdXJsIC1mc1MgLS1tYXgtdGltZSA4ICIkezF9bWFuaWZlc3Qud2VibWFuaWZlc3QiIDI+L2Rldi9udWxsIHwgZ3JlcCAtcSB3aGVyZHI7IHRoZW4gZWNobyBvazsgZWxzZSBlY2hvIG5vbmU7IGZpIDs7CiAgZXNhYwp9CgojIFRoZSB0YWlsbmV0IGFkZHJlc3MgYHRhaWxzY2FsZSBzZXJ2ZWAgYWxyZWFkeSBwdWJsaXNoZXMgZm9yIHdoZXJkcidzIGxvY2FsCiMgcG9ydCAoaHR0cHM6Ly88bWFjaGluZT4uPHRhaWxuZXQ+LnRzLm5ldFs6cG9ydF0pLCBvbmx5IHdoZW4gaXQgYW5zd2VycyBsaWtlCiMgd2hlcmRyLiBQYXNza2V5cyBhcmUgdGllZCB0byB0aGUgYWRkcmVzczogdGhhdCBpcyB0aGUgb25lIHRvIG9wZW4uCnRhaWxuZXRfYWRkcmVzcygpIHsKICBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxIHx8IHJldHVybiAxCiAgaG9zdD0iJChzZXJ2ZWRfaG9zdCkiIHx8IHJldHVybiAxCiAgWyAiJChwaG9uZV9yZWFjaCAiaHR0cHM6Ly8kaG9zdC8iKSIgPSBvayBdIHx8IHJldHVybiAxCiAgcHJpbnRmICdodHRwczovLyVzXG4nICIkaG9zdCIKfQoKIyBUaGUgYWRkcmVzcyB0byBvcGVuOiB0aGUgdGFpbG5ldCBvbmUgd2hlbiBwdWJsaXNoZWQgYW5kIGFuc3dlcmluZywgZWxzZSBsb2NhbGhvc3QuCm9wZW5fYWRkcmVzcygpIHsgdGFpbG5ldF9hZGRyZXNzIHx8IHByaW50ZiAnJXNcbicgIiRVUkwiOyB9CgpjbWRfb3BlbigpIHsKICBhZGRyZXNzPSIkKG9wZW5fYWRkcmVzcykiCiAgb3Blbl9icm93c2VyICIkYWRkcmVzcyIgfHwgdHJ1ZQogIHNheSAiJGFkZHJlc3MiCn0KCiMgYGFkZHJlc3NgOiB3aGF0IGBvcGVuYCB3b3VsZCBvcGVuLCB3aXRob3V0IG9wZW5pbmcgaXQgKGh0dHBzOi8vd2hlcmRyLmRldi9pbnN0YWxsKS4KY21kX2FkZHJlc3MoKSB7IG9wZW5fYWRkcmVzczsgfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB1cGRhdGUKIyBGcm9tIHRoZSByZWxlYXNlIGJyYW5jaCBvZiB0aGlzIG1ham9yIChgMi54YCksIG5ldmVyIGBtYWluYCwgd2hpY2ggaG9sZHMgdGhlCiMgbmV4dCBtYWpvci4KY21kX3VwZGF0ZSgpIHsKICBtYWpvcj0iJChzZWQgLW4gJ3MvXnZlcnNpb24gPSAiXChbMC05XSpcKVwuLioiJC9cMS9wJyAiJFJPT1QvaGVyZHItcGx1Z2luLnRvbWwiIHwgaGVhZCAtbiAxKSIKICBzYXkgIlVwZGF0aW5nIHRoZSB3aGVyZHIgcGx1Z2luIGZyb20gJHtTT1VSQ0V9ICgke21ham9yfS54KeKApiIKICAiJChoZXJkcl9iaW4pIiBwbHVnaW4gaW5zdGFsbCAiJFNPVVJDRSIgLS1yZWYgIiR7bWFqb3J9LngiIC0teWVzCn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHBob25lCiMgUGhvbmUgc2V0dXAgdXNlcyB0aGUgbmF0aXZlIGNvbW1hbmQuCmNtZF9waG9uZSgpIHsgY2xpIHBob25lOyB9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzZXJ2aWNlCmNtZF9zZXJ2aWNlKCkgewogIGNhc2UgIiR7MTotfSIgaW4gaW5zdGFsbHx1bmluc3RhbGwpIDs7ICopIGRpZSAidXNhZ2U6ICQwIHNlcnZpY2UgaW5zdGFsbHx1bmluc3RhbGwiIDs7IGVzYWMKICBjbGkgc2VydmljZSAiJDEiCiAgIyBXaXRob3V0IHRoZSBzZXJ2aWNlLCB0aGUgcGx1Z2luIHJ1bnMgd2hlcmRyIGFnYWluIChhbmQgaXRzIHN0YXJ0dXAgaG9vawogICMgc3RhcnRzIGl0IHdpdGggSGVyZHIpLgogIGlmIFsgIiQxIiA9ICJ1bmluc3RhbGwiIF07IHRoZW4gY21kX3N0YXJ0OyBmaQp9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBrZXkKIyBBIEhlcmRyIGtleSB0aGF0IG9wZW5zIHRoZSB3aGVyZHIgcGFuZWw6IEhlcmRyIHYxIHBsdWdpbnMgaGF2ZSBubyBtZW51LCBzbwojIHRoZSBpbnN0YWxsIGFwcGVuZHMgb25lIG1hcmtlZCBbW2tleXMuY29tbWFuZF1dIGJsb2NrIHRvIEhlcmRyJ3MKIyBjb25maWcudG9tbCwgb24gdGhlIGZpcnN0IGZyZWUga2V5IG9mIEhPVEtFWVMgKG5ldmVyIG9uZSBIZXJkciBvciB0aGUgdXNlcgojIGFscmVhZHkgYmluZHMpLiBFeGlzdGluZyBsaW5lcyBhcmUgbmV2ZXIgY2hhbmdlZDogdGhlIGJsb2NrIGlzIG9ubHkgZXZlcgojIGFwcGVuZGVkLCB0aGVuIHJlbW92ZWQgYnkgYGtleSB1bmluc3RhbGxgLiBOb3RoaW5nIGlzIGFkZGVkIHdoZW4gdGhlIHBhbmVsCiMgYWxyZWFkeSBoYXMgYSBrZXksIG9yIHdoZW4gbm8gY2FuZGlkYXRlIGlzIGZyZWUuCkhPVEtFWVM9IiR7V0hFUkRSX0hPVEtFWVM6LXByZWZpeCtpIHByZWZpeCt1IHByZWZpeCt5IHByZWZpeCttIHByZWZpeCthbHQrd30iCkhFUkRSX0NPTkZJRz0iJHtIRVJEUl9DT05GSUdfUEFUSDotJHtYREdfQ09ORklHX0hPTUU6LSRIT01FLy5jb25maWd9L2hlcmRyL2NvbmZpZy50b21sfSIKUExVR0lOX0lEPSIkKHByaW50ZiAnJXMnICIkU09VUkNFIiB8IHRyIC8gLikiClBBTkVMX0FDVElPTj0iJFBMVUdJTl9JRC5wYW5lbCIKS0VZX0JFR0lOPSIjIHdoZXJkcjoga2V5IHRoYXQgb3BlbnMgdGhlIHdoZXJkciBwYW5lbCAocmVtb3ZlIHRoaXMgYmxvY2sgdG8gdW5iaW5kIGl0KSIKS0VZX0VORD0iIyBlbmQgd2hlcmRyIgoKIyBIZXJkcidzIGRlZmF1bHQga2V5bWFwLCBmcm9tIHRoZSBydW5uaW5nIGJpbmFyeSB3aGVuIGl0IGNhbiBwcmludCBpdCwKIyBvdGhlcndpc2UgYXMgb2YgSGVyZHIgMC45LjMgKCJuYW1lPFRBQj5rZXkiIGxpbmVzKS4KZGVmYXVsdF9rZXlzKCkgewogIG91dD0iJCgiJChoZXJkcl9iaW4pIiAtLWRlZmF1bHQtY29uZmlnIDI+L2Rldi9udWxsIHwgYXdrICcKICAgIC9eXFtrZXlzXF0vIHsgayA9IDE7IG5leHQgfQogICAgayAmJiAvXlxbLyB7IGV4aXQgfQogICAgayAmJiBtYXRjaCgkMCwgL14jIFthLXpfXSsgPSAiW14iXSoiLykgewogICAgICBsaW5lID0gc3Vic3RyKCQwLCAzLCBSTEVOR1RIIC0gMik7IGVxID0gaW5kZXgobGluZSwgIiA9ICIpCiAgICAgIHYgPSBzdWJzdHIobGluZSwgZXEgKyA0KTsgc3ViKC8iJC8sICIiLCB2KQogICAgICBpZiAodiAhPSAiIikgcHJpbnRmICIlc1x0JXNcbiIsIHN1YnN0cihsaW5lLCAxLCBlcSAtIDEpLCB2CiAgICB9JykiIHx8IG91dD0iIgogIGlmIFsgLW4gIiRvdXQiIF07IHRoZW4gcHJpbnRmICclc1xuJyAiJG91dCI7IHJldHVybjsgZmkKICBmb3IgcCBpbiBoZWxwOj8gc2V0dGluZ3M6cyBkZXRhY2g6cSByZWxvYWRfY29uZmlnOnNoaWZ0K3Igb3Blbl9ub3RpZmljYXRpb25fdGFyZ2V0Om8gXAogICAgd29ya3NwYWNlX3BpY2tlcjp3IGdvdG86ZyBuZXdfd29ya3NwYWNlOnNoaWZ0K24gbmV3X3dvcmt0cmVlOnNoaWZ0K2cgcmVuYW1lX3dvcmtzcGFjZTpzaGlmdCt3IFwKICAgIGNsb3NlX3dvcmtzcGFjZTpzaGlmdCtkIG5ld190YWI6YyByZW5hbWVfdGFiOnNoaWZ0K3QgcHJldmlvdXNfdGFiOnAgbmV4dF90YWI6biBcCiAgICBjbG9zZV90YWI6c2hpZnQreCByZW5hbWVfcGFuZTpzaGlmdCtwIGVkaXRfc2Nyb2xsYmFjazplIGZvY3VzX3BhbmVfbGVmdDpoIGZvY3VzX3BhbmVfZG93bjpqIFwKICAgIGZvY3VzX3BhbmVfdXA6ayBmb2N1c19wYW5lX3JpZ2h0OmwgY3ljbGVfcGFuZV9uZXh0OnRhYiBjeWNsZV9wYW5lX3ByZXZpb3VzOnNoaWZ0K3RhYiBcCiAgICBzcGxpdF92ZXJ0aWNhbDp2IHNwbGl0X2hvcml6b250YWw6bWludXMgY2xvc2VfcGFuZTp4IHpvb206eiByZXNpemVfbW9kZTpyIHRvZ2dsZV9zaWRlYmFyOmI7IGRvCiAgICBwcmludGYgJyVzXHRwcmVmaXgrJXNcbicgIiR7cCUlOip9IiAiJHtwIyo6fSIKICBkb25lCn0KCiMgT25lIGxpbmUgb24gdGhlIGNvbmZpZzogImJvdW5kIDxrZXk+IiB3aGVuIGEgW1trZXlzLmNvbW1hbmRdXSBhbHJlYWR5IHJ1bnMKIyB0aGUgcGFuZWwsIGVsc2UgImZyZWUgPGtleT4iIChmaXJzdCBmcmVlIGNhbmRpZGF0ZSkgb3IgIm5vbmUiLiBBbHNvCiMgIm9sZCA8a2V5PiIgZm9yIGEgYmluZGluZyBvZiB0aGUgcGFuZWwncyBmb3JtZXIgYWN0aW9uIGlkICg8aWQ+LndoZXJkcikuCmtleV9zY2FuKCkgewogIGRlZmF1bHRzPSIkKGRlZmF1bHRfa2V5cykiCiAgeyBwcmludGYgJyVzXG4nICIkZGVmYXVsdHMiOyBwcmludGYgJ1wwMDFcbic7IGNhdCAiJEhFUkRSX0NPTkZJRyIgMj4vZGV2L251bGw7IH0gfCBhd2sgXAogICAgLXYgY2FuZHM9IiRIT1RLRVlTIiAtdiBhY3Rpb249IiRQQU5FTF9BQ1RJT04iIC12IG9sZD0iJFBMVUdJTl9JRC53aGVyZHIiICcKICAgIGZ1bmN0aW9uIG5vcm0oaykgewogICAgICBnc3ViKC9bIFx0XS8sICIiLCBrKQogICAgICAjICJwcmVmaXgrVyIgaXMgInByZWZpeCtzaGlmdCt3IgogICAgICBpZiAobWF0Y2goaywgL1wrW0EtWl0kLykpIGsgPSBzdWJzdHIoaywgMSwgUlNUQVJUKSAic2hpZnQrIiB0b2xvd2VyKHN1YnN0cihrLCBSU1RBUlQgKyAxKSkKICAgICAgcmV0dXJuIHRvbG93ZXIoaykKICAgIH0KICAgIGZ1bmN0aW9uIHN0cmluZ3Mocywgb3V0LCAgIG4pIHsKICAgICAgbiA9IDAKICAgICAgd2hpbGUgKG1hdGNoKHMsIC8iW14iXSoiLykpIHsgb3V0Wysrbl0gPSBzdWJzdHIocywgUlNUQVJUICsgMSwgUkxFTkdUSCAtIDIpOyBzID0gc3Vic3RyKHMsIFJTVEFSVCArIFJMRU5HVEgpIH0KICAgICAgcmV0dXJuIG4KICAgIH0KICAgIGZ1bmN0aW9uIGZsdXNoKCkgewogICAgICBpZiAoY2tleSAhPSAiIiAmJiBjbWQgPT0gYWN0aW9uICYmIGJvdW5kID09ICIiKSBib3VuZCA9IGNrZXkKICAgICAgaWYgKGNrZXkgIT0gIiIgJiYgY21kID09IG9sZCAmJiBvbGRrZXkgPT0gIiIpIG9sZGtleSA9IGNrZXkKICAgICAgY2tleSA9ICIiOyBjbWQgPSAiIgogICAgfQogICAgJDAgPT0gIlwwMDEiIHsgY29uZiA9IDE7IG5leHQgfQogICAgIWNvbmYgeyBzcGxpdCgkMCwgZCwgIlx0Iik7IGRlZltkWzFdXSA9IGRbMl07IG5leHQgfQogICAgL15bIFx0XSpcWy8gewogICAgICBmbHVzaCgpOyB0ID0gJDA7IHN1YigvIy4qLywgIiIsIHQpOyBnc3ViKC9bIFx0XS8sICIiLCB0KQogICAgICBzZWN0ID0gdCA9PSAiW2tleXNdIiA/ICJrZXlzIiA6IHQgPT0gIltba2V5cy5jb21tYW5kXV0iID8gImNtZCIgOiAiIgogICAgICBuZXh0CiAgICB9CiAgICAvXlsgXHRdKigjfCQpLyB7IG5leHQgfQogICAgewogICAgICBlcSA9IGluZGV4KCQwLCAiPSIpOyBpZiAoIWVxKSBuZXh0CiAgICAgIG5hbWUgPSBzdWJzdHIoJDAsIDEsIGVxIC0gMSk7IGdzdWIoL1sgXHRdLywgIiIsIG5hbWUpOyB2YWwgPSBzdWJzdHIoJDAsIGVxICsgMSkKICAgICAgaWYgKHNlY3QgPT0gImtleXMiKSB7CiAgICAgICAgb3ZlcltuYW1lXSA9IDE7IG4gPSBzdHJpbmdzKHZhbCwgcykKICAgICAgICBmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykgdGFrZW5bbm9ybShzW2ldKV0gPSAxCiAgICAgIH0gZWxzZSBpZiAoc2VjdCA9PSAiY21kIiAmJiBzdHJpbmdzKHZhbCwgcykpIHsKICAgICAgICBpZiAobmFtZSA9PSAia2V5IikgeyBja2V5ID0gc1sxXTsgdGFrZW5bbm9ybShzWzFdKV0gPSAxIH0KICAgICAgICBpZiAobmFtZSA9PSAiY29tbWFuZCIpIGNtZCA9IHNbMV0KICAgICAgfQogICAgfQogICAgRU5EIHsKICAgICAgZmx1c2goKQogICAgICBpZiAob2xka2V5ICE9ICIiKSBwcmludCAib2xkICIgb2xka2V5CiAgICAgIGlmIChib3VuZCAhPSAiIikgeyBwcmludCAiYm91bmQgIiBib3VuZDsgZXhpdCB9CiAgICAgIGZvciAoYSBpbiBkZWYpIGlmICghKGEgaW4gb3ZlcikpIHRha2VuW25vcm0oZGVmW2FdKV0gPSAxCiAgICAgIG4gPSBzcGxpdChjYW5kcywgYywgIiAiKQogICAgICBmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykgaWYgKCEobm9ybShjW2ldKSBpbiB0YWtlbikpIHsgcHJpbnQgImZyZWUgIiBjW2ldOyBleGl0IH0KICAgICAgcHJpbnQgIm5vbmUiCiAgICB9Jwp9CgojIFRoZSBrZXkgYm91bmQgdG8gdGhlIHBhbmVsLCBpZiBhbnkuCmtleV9ib3VuZCgpIHsga2V5X3NjYW4gfCBzZWQgLW4gJ3MvXmJvdW5kIC8vcCc7IH0KCiMgSGVyZHIgYXBwbGllcyBrZXliaW5kaW5ncyBvbiBgaGVyZHIgc2VydmVyIHJlbG9hZC1jb25maWdgIChubyByZXN0YXJ0KS4Ka2V5X3JlbG9hZCgpIHsKICBpZiAiJChoZXJkcl9iaW4pIiBzZXJ2ZXIgcmVsb2FkLWNvbmZpZyA+L2Rldi9udWxsIDI+JjE7IHRoZW4KICAgIHRlbGwgIiAgSGVyZHIgcmVsb2FkZWQgaXRzIGNvbmZpZzogbm8gcmVzdGFydCBuZWVkZWQuIgogIGVsc2UKICAgIHRlbGwgIiAgUnVuIGhlcmRyIHNlcnZlciByZWxvYWQtY29uZmlnIChvciByZXN0YXJ0IEhlcmRyKSB0byBhcHBseSBpdC4iCiAgZmkKfQoKY21kX2tleSgpIHsKICBjYXNlICIkezE6LX0iIGluCiAgICBpbnN0YWxsKQogICAgICBzY2FuPSIkKGtleV9zY2FuKSIKICAgICAgb2xkPSIkKHByaW50ZiAnJXNcbicgIiRzY2FuIiB8IHNlZCAtbiAncy9eb2xkIC8vcCcpIgogICAgICBbIC16ICIkb2xkIiBdIHx8IHdhcm4gIiRvbGQgcnVucyAkUExVR0lOX0lELndoZXJkciwgcmVuYW1lZCAkUEFORUxfQUNUSU9OOiBlZGl0IHRoYXQgbGluZSBvZiAkSEVSRFJfQ09ORklHLiIKICAgICAgcmVzPSIkKHByaW50ZiAnJXNcbicgIiRzY2FuIiB8IHNlZCAnL15vbGQgL2QnKSIKICAgICAgY2FzZSAiJHJlcyIgaW4KICAgICAgICBib3VuZFwgKikgdGVsbCAiUHJlc3MgJHtyZXMjYm91bmQgfSBpbiBIZXJkciB0byBvcGVuIHRoZSB3aGVyZHIgcGFuZWwuIiA7OwogICAgICAgIGZyZWVcICopCiAgICAgICAgICBrZXk9IiR7cmVzI2ZyZWUgfSIKICAgICAgICAgIG1rZGlyIC1wICIkKGRpcm5hbWUgIiRIRVJEUl9DT05GSUciKSIKICAgICAgICAgIGJsb2NrPSIkKHByaW50ZiAnJXNcbltba2V5cy5jb21tYW5kXV1cbmtleSA9ICIlcyJcbnR5cGUgPSAicGx1Z2luX2FjdGlvbiJcbmNvbW1hbmQgPSAiJXMiXG5kZXNjcmlwdGlvbiA9ICJ3aGVyZHIiXG4lcycgXAogICAgICAgICAgICAiJEtFWV9CRUdJTiIgIiRrZXkiICIkUEFORUxfQUNUSU9OIiAiJEtFWV9FTkQiKSIKICAgICAgICAgIHNlcD0iIgogICAgICAgICAgaWYgWyAtcyAiJEhFUkRSX0NPTkZJRyIgXTsgdGhlbgogICAgICAgICAgICBzZXA9IgoiCiAgICAgICAgICAgICMgQSBsYXN0IGxpbmUgd2l0aG91dCBpdHMgbmV3bGluZSBnZXRzIG9uZSBmaXJzdC4KICAgICAgICAgICAgWyAiJCh0YWlsIC1jIDEgIiRIRVJEUl9DT05GSUciIHwgb2QgLUFuIC1jIHwgdHIgLWQgJyAnKSIgPSAnXG4nIF0gfHwgc2VwPSIKJHNlcCIKICAgICAgICAgIGZpCiAgICAgICAgICAjIENoZWNrZWQgb24gYSBjb3B5IGZpcnN0IHdoZW4gdGhpcyBIZXJkciBjYW4gdmFsaWRhdGUgYSBjb25maWc6CiAgICAgICAgICAjIGEgY29uZmlnIEhlcmRyIHdvdWxkIHJlamVjdCBpcyBuZXZlciB3cml0dGVuLgogICAgICAgICAgdG1wPSIkSEVSRFJfQ09ORklHLndoZXJkci1jaGVjay50b21sIgogICAgICAgICAgeyBpZiBbIC1mICIkSEVSRFJfQ09ORklHIiBdOyB0aGVuIGNhdCAiJEhFUkRSX0NPTkZJRyI7IGZpOyBwcmludGYgJyVzJXNcbicgIiRzZXAiICIkYmxvY2siOyB9ID4gIiR0bXAiCiAgICAgICAgICBpZiAiJChoZXJkcl9iaW4pIiBjb25maWcgLS1oZWxwID4vZGV2L251bGwgMj4mMSAmJiAhIEhFUkRSX0NPTkZJR19QQVRIPSIkdG1wIiAiJChoZXJkcl9iaW4pIiBjb25maWcgY2hlY2sgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgICAgIHJtIC1mICIkdG1wIgogICAgICAgICAgICB3YXJuICJubyBIZXJkciBrZXkgYWRkZWQ6ICRIRVJEUl9DT05GSUcgd291bGQgbm90IHZhbGlkYXRlIHdpdGggaXQgKGhlcmRyIGNvbmZpZyBjaGVjaykuIgogICAgICAgICAgICByZXR1cm4gMAogICAgICAgICAgZmkKICAgICAgICAgIHJtIC1mICIkdG1wIgogICAgICAgICAgcHJpbnRmICclcyVzXG4nICIkc2VwIiAiJGJsb2NrIiA+PiAiJEhFUkRSX0NPTkZJRyIKICAgICAgICAgIG9rICJIZXJkciBrZXkgJGtleSBhZGRlZCB0byAkSEVSRFJfQ09ORklHIgogICAgICAgICAgdGVsbCAiUHJlc3MgJGtleSBpbiBIZXJkciB0byBvcGVuIHRoZSB3aGVyZHIgcGFuZWwuIgogICAgICAgICAga2V5X3JlbG9hZAogICAgICAgICAgOzsKICAgICAgICAqKSB3YXJuICJubyBIZXJkciBrZXkgYWRkZWQ6ICRIT1RLRVlTIGFyZSBhbGwgdGFrZW4uIEJpbmQgb25lIHRvICRQQU5FTF9BQ1RJT04gKHR5cGUgPSBcInBsdWdpbl9hY3Rpb25cIikgaW4gJEhFUkRSX0NPTkZJRy4iIDs7CiAgICAgIGVzYWMKICAgICAgOzsKICAgIHVuaW5zdGFsbCkKICAgICAgaWYgISBncmVwIC1xeEYgIiRLRVlfQkVHSU4iICIkSEVSRFJfQ09ORklHIiAyPi9kZXYvbnVsbDsgdGhlbiBvayAibm8gd2hlcmRyIGtleSBpbiAkSEVSRFJfQ09ORklHIjsgcmV0dXJuIDA7IGZpCiAgICAgICMgRHJvcHMgdGhlIG1hcmtlZCBibG9jayBhbmQgdGhlIGJsYW5rIGxpbmUgd3JpdHRlbiBiZWZvcmUgaXQuCiAgICAgIHRtcD0iJEhFUkRSX0NPTkZJRy53aGVyZHItdG1wIgogICAgICBhd2sgLXYgYj0iJEtFWV9CRUdJTiIgLXYgZT0iJEtFWV9FTkQiICcKICAgICAgICAkMCA9PSBiIHsgc2tpcCA9IDE7IGlmIChibGFuaykgYmxhbmstLTsgbmV4dCB9CiAgICAgICAgc2tpcCB7IGlmICgkMCA9PSBlKSBza2lwID0gMDsgbmV4dCB9CiAgICAgICAgJDAgPT0gIiIgeyBibGFuaysrOyBuZXh0IH0KICAgICAgICB7IHdoaWxlIChibGFuaykgeyBwcmludCAiIjsgYmxhbmstLSB9IHByaW50IH0KICAgICAgICBFTkQgeyB3aGlsZSAoYmxhbmspIHsgcHJpbnQgIiI7IGJsYW5rLS0gfSB9JyAiJEhFUkRSX0NPTkZJRyIgPiAiJHRtcCIKICAgICAgIyBSZXdyaXR0ZW4gaW4gcGxhY2U6IHRoZSBmaWxlIGtlZXBzIGl0cyBvd25lciBhbmQgbW9kZS4KICAgICAgY2F0ICIkdG1wIiA+ICIkSEVSRFJfQ09ORklHIiAmJiBybSAtZiAiJHRtcCIKICAgICAgb2sgIndoZXJkciBrZXkgcmVtb3ZlZCBmcm9tICRIRVJEUl9DT05GSUciCiAgICAgIGtleV9yZWxvYWQKICAgICAgOzsKICAgIHN0YXR1cykgYj0iJChrZXlfYm91bmQpIjsgaWYgWyAtbiAiJGIiIF07IHRoZW4gc2F5ICIkYiI7IGVsc2Ugc2F5ICJub25lIjsgZmkgOzsKICAgICopIGRpZSAidXNhZ2U6ICQwIGtleSBpbnN0YWxsfHVuaW5zdGFsbHxzdGF0dXMiIDs7CiAgZXNhYwp9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwYW5lbAojIFRoZSAicGFuZWwiIGFjdGlvbjogb25lIHBvcHVwIHdpdGggdGhlIHN0YXRlLCBPcGVuIHdoZXJkciwgU2V0IHVwIG15IHBob25lCiMgKG9wZW5zIFNldHRpbmdzIOKAuiBQaG9uZSkgYW5kIHRoZSBvdGhlciBjb21tYW5kcyAoYmluL2xpYi9wYW5lbC5tanMpLAojIGRyaXZpbmcgdGhpcyBzY3JpcHQuCmNtZF9wYW5lbCgpIHsKICBjb250cm9sPSIkKHByaW50ZiAnWyJzaCIsIiVzIl0nICIkKHByaW50ZiAnJXMnICIkUk9PVC9zY3JpcHRzL2hlcmRyLXBsdWdpbi5zaCIgfCBzZWQgJ3MvW1xcIl0vXFwmL2cnKSIpIgogIFdIRVJEUl9DT05UUk9MPSIkY29udHJvbCIgV0hFUkRSX0hPVEtFWT0iJChrZXlfYm91bmQpIiBjbGkgcGFuZWwKfQoKY21kX3Jlc3RhcnQoKSB7IGNtZF9zdG9wOyBjbWRfc3RhcnQ7IH0KCmNhc2UgIiR7MTotfSIgaW4KICBidWlsZCkgY21kX2J1aWxkIDs7CiAgcGFuZWwpIGNtZF9wYW5lbCA7OwogIHN0YXJ0fHN0b3B8cmVzdGFydHxzdGF0dXN8b3BlbnxhZGRyZXNzfHVwZGF0ZXxwaG9uZXxsb2dzfGRvY3RvcikgImNtZF8kMSIgOzsKICBzZXJ2aWNlKSBjbWRfc2VydmljZSAiJHsyOi19IiA7OwogIHNraWxsKSBjbWRfc2tpbGwgIiR7MjotfSIgOzsKICBrZXkpIGNtZF9rZXkgIiR7MjotfSIgOzsKICAqKSBkaWUgInVzYWdlOiAkMCBidWlsZHxwYW5lbHxzdGFydHxzdG9wfHJlc3RhcnR8c3RhdHVzfG9wZW58YWRkcmVzc3x1cGRhdGV8cGhvbmV8bG9nc3xkb2N0b3J8c2VydmljZSBpbnN0YWxsfHVuaW5zdGFsbHxza2lsbCBpbnN0YWxsfHVuaW5zdGFsbHxrZXkgaW5zdGFsbHx1bmluc3RhbGx8c3RhdHVzIiA7Owplc2FjCg==");
5
5
 
6
6
  export { herdrPlugin as default };
7
7
  //# sourceMappingURL=herdr-plugin.mjs.map
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const _____ = defineEventHandler((event) => sendError(event, 404, { error: "Not found" }));
35
35
 
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const agents_post = defineApi((event, b) => createAgent(b));
35
35
 
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const askTab_post = defineApi(async (event, b) => {
35
35
  var _a;
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const attach_post = defineApi((event, b) => {
35
35
  const q = getQuery(event);
@@ -1,4 +1,5 @@
1
- import { a as defineApi, k as auth, r as reqOf } from '../../../nitro/nitro.mjs';
1
+ import { a as defineApi, k as auth, r as reqOf, l as eventClients } from '../../../nitro/nitro.mjs';
2
+ import { r as revokeEverywhere, a as askPushResubscribe } from '../../../_/revoke.mjs';
2
3
  import 'node:http';
3
4
  import 'node:https';
4
5
  import 'node:crypto';
@@ -23,15 +24,21 @@ import 'node:util';
23
24
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
25
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
26
  import 'web-push';
27
+ import 'node:zlib';
28
+ import '@simplewebauthn/server';
26
29
  import 'node:net';
27
30
  import 'node:string_decoder';
28
31
  import 'node:fs/promises';
29
32
  import 'node:readline';
30
33
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
34
+ import '../../../_/ws.mjs';
33
35
 
34
- const disable_post = defineApi((event) => auth.disable(reqOf(event)));
36
+ const disable_post = defineApi(async (event) => {
37
+ const r = auth.disable(reqOf(event));
38
+ await revokeEverywhere();
39
+ askPushResubscribe(eventClients.values());
40
+ return r;
41
+ });
35
42
 
36
43
  export { disable_post as default };
37
44
  //# sourceMappingURL=disable.post.mjs.map
@@ -1,4 +1,5 @@
1
1
  import { a as defineApi, k as auth, r as reqOf } from '../../../nitro/nitro.mjs';
2
+ import { r as revokeEverywhere } from '../../../_/revoke.mjs';
2
3
  import 'node:http';
3
4
  import 'node:https';
4
5
  import 'node:crypto';
@@ -23,15 +24,20 @@ import 'node:util';
23
24
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
25
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
26
  import 'web-push';
27
+ import 'node:zlib';
28
+ import '@simplewebauthn/server';
26
29
  import 'node:net';
27
30
  import 'node:string_decoder';
28
31
  import 'node:fs/promises';
29
32
  import 'node:readline';
30
33
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
34
+ import '../../../_/ws.mjs';
33
35
 
34
- const lockAll_post = defineApi((event) => auth.lockAll(reqOf(event)));
36
+ const lockAll_post = defineApi(async (event) => {
37
+ const r = auth.lockAll(reqOf(event));
38
+ await revokeEverywhere();
39
+ return r;
40
+ });
35
41
 
36
42
  export { lockAll_post as default };
37
43
  //# sourceMappingURL=lock-all.post.mjs.map
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const lock_post = defineApi((event) => auth.lock(reqOf(event)));
35
35
 
@@ -1,4 +1,4 @@
1
- import { a as defineApi, k as auth, r as reqOf } from '../../../../nitro/nitro.mjs';
1
+ import { a as defineApi, k as auth, r as reqOf, y as clientKey } from '../../../../nitro/nitro.mjs';
2
2
  import 'node:http';
3
3
  import 'node:https';
4
4
  import 'node:crypto';
@@ -23,15 +23,15 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
- const options_post = defineApi((event) => auth.loginOptions(reqOf(event)));
34
+ const options_post = defineApi((event) => auth.loginOptions(reqOf(event), clientKey(event)));
35
35
 
36
36
  export { options_post as default };
37
37
  //# sourceMappingURL=options.post.mjs.map
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const verify_post = defineApi((event, body) => auth.loginVerify(reqOf(event), body));
35
35
 
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const maxSession_post = defineApi((event, body) => auth.setMaxSession(reqOf(event), body == null ? void 0 : body.days));
35
35
 
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const options_post = defineApi((event, body) => auth.registerOptions(reqOf(event), body));
35
35
 
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const verify_post = defineApi((event, body) => auth.registerVerify(reqOf(event), body));
35
35
 
@@ -1,4 +1,4 @@
1
- import { a as defineApi, l as localMachineLabel, k as auth, r as reqOf, i as getQuery } from '../../../nitro/nitro.mjs';
1
+ import { a as defineApi, k as auth, r as reqOf, i as getQuery, z as localMachineLabel } from '../../../nitro/nitro.mjs';
2
2
  import 'node:http';
3
3
  import 'node:https';
4
4
  import 'node:crypto';
@@ -23,18 +23,18 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
- const status_get = defineApi((event) => ({
35
- ...auth.status(reqOf(event), { resume: getQuery(event).resume === "1" }),
36
- hostLabel: localMachineLabel()
37
- }));
34
+ const status_get = defineApi((event) => {
35
+ const st = auth.status(reqOf(event), { resume: getQuery(event).resume === "1" });
36
+ return st.unlocked ? { ...st, hostLabel: localMachineLabel() } : st;
37
+ });
38
38
 
39
39
  export { status_get as default };
40
40
  //# sourceMappingURL=status.get.mjs.map
@@ -1,4 +1,4 @@
1
- import { a as defineApi, i as getQuery, f as findPane, H as HerdrError, m as machineFor } from '../../nitro/nitro.mjs';
1
+ import { a as defineApi, i as getQuery, f as findPane, H as HerdrError, B as machineFor } from '../../nitro/nitro.mjs';
2
2
  import { r as readChanges } from '../../_/changes.mjs';
3
3
  import 'node:http';
4
4
  import 'node:https';
@@ -24,13 +24,13 @@ import 'node:util';
24
24
  import 'qrcode-terminal/vendor/QRCode/index.js';
25
25
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
26
26
  import 'web-push';
27
+ import 'node:zlib';
28
+ import '@simplewebauthn/server';
27
29
  import 'node:net';
28
30
  import 'node:string_decoder';
29
31
  import 'node:fs/promises';
30
32
  import 'node:readline';
31
33
  import 'node:url';
32
- import 'node:zlib';
33
- import '@simplewebauthn/server';
34
34
 
35
35
  const changes_get = defineApi(async (event) => {
36
36
  const q = getQuery(event);
@@ -1,4 +1,4 @@
1
- import { d as defineEventHandler, i as getQuery, f as findPane, y as transcripts, s as sendError, I as sendImage } from '../../../nitro/nitro.mjs';
1
+ import { d as defineEventHandler, i as getQuery, f as findPane, J as transcripts, s as sendError, T as sendImage } from '../../../nitro/nitro.mjs';
2
2
  import 'node:http';
3
3
  import 'node:https';
4
4
  import 'node:crypto';
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const image_get = defineEventHandler(async (event) => {
35
35
  const q = getQuery(event);
@@ -1,9 +1,8 @@
1
- import { U as UPLOAD_DIR, u as uploadNames, n as runHerdrCli, o as parseIntegrationStatus, a as defineApi, i as getQuery, f as findPane, H as HerdrError, q as machineOfPane, t as fmt, v as takenBackOf, x as chatDelta, y as transcripts, z as missingIntegration, B as multiMachine, C as integrationCommand, D as chatPasted, E as withoutTakenBack, F as withSentText, G as currentModel } from '../../nitro/nitro.mjs';
2
- import { createHash } from 'node:crypto';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
1
+ import { C as runHerdrCli, D as parseIntegrationStatus, a as defineApi, i as getQuery, f as findPane, H as HerdrError, E as machineOfPane, F as fmt, G as takenBackOf, I as chatDelta, J as transcripts, K as missingIntegration, L as multiMachine, M as integrationCommand, N as chatPasted, O as withoutTakenBack, Q as withSentText, R as currentModel } from '../../nitro/nitro.mjs';
2
+ import { a as addUploadHashes } from '../../_/uploadHashes.mjs';
5
3
  import 'node:http';
6
4
  import 'node:https';
5
+ import 'node:crypto';
7
6
  import 'stream';
8
7
  import 'events';
9
8
  import 'http';
@@ -17,6 +16,7 @@ import 'url';
17
16
  import 'node:events';
18
17
  import 'node:buffer';
19
18
  import 'node:fs';
19
+ import 'node:path';
20
20
  import 'node:os';
21
21
  import 'node:child_process';
22
22
  import 'node:dns';
@@ -24,51 +24,13 @@ import 'node:util';
24
24
  import 'qrcode-terminal/vendor/QRCode/index.js';
25
25
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
26
26
  import 'web-push';
27
+ import 'node:zlib';
28
+ import '@simplewebauthn/server';
27
29
  import 'node:net';
28
30
  import 'node:string_decoder';
31
+ import 'node:fs/promises';
29
32
  import 'node:readline';
30
33
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
-
34
- const UPLOAD_PATH = /\.cache\/herdr-web\/uploads\/([\w-]+\.[a-z]+)/g;
35
- const CACHE_MAX = 500;
36
- const cache$1 = /* @__PURE__ */ new Map();
37
- async function uploadHash(dir, name) {
38
- const key = `${dir}
39
- ${name}`;
40
- if (cache$1.has(key)) return cache$1.get(key);
41
- let hash = null;
42
- try {
43
- hash = createHash("sha256").update(await fs.readFile(path.join(dir, path.basename(name)))).digest("hex");
44
- } catch {
45
- hash = null;
46
- }
47
- if (cache$1.size >= CACHE_MAX) cache$1.delete(cache$1.keys().next().value);
48
- cache$1.set(key, hash);
49
- return hash;
50
- }
51
- async function addUploadHashes(items, dir = UPLOAD_DIR) {
52
- var _a;
53
- for (const it of items) {
54
- if (it.role === "user") {
55
- const names = uploadNames(it.text);
56
- if (!names.length) continue;
57
- const own = (await Promise.all(names.map((n) => uploadHash(dir, n)))).filter((h) => !!h);
58
- const hashes = [...it.hashes || [], ...own.filter((h) => {
59
- var _a2;
60
- return !((_a2 = it.hashes) == null ? void 0 : _a2.includes(h));
61
- })];
62
- if (hashes.length) it.hashes = hashes;
63
- } else if (it.images === 1) {
64
- const names = [...new Set([...`${it.text}
65
- ${((_a = it.omp) == null ? void 0 : _a.target) || ""}`.matchAll(UPLOAD_PATH)].map((m) => m[1]))];
66
- if (names.length !== 1) continue;
67
- const h = await uploadHash(dir, names[0]);
68
- if (h) it.hashes = [h];
69
- }
70
- }
71
- }
72
34
 
73
35
  const ttl = Number(process.env.WHERDR_INTEGRATION_TTL_MS);
74
36
  const TTL_MS = Number.isFinite(ttl) && ttl >= 0 ? ttl : 6e4;
@@ -100,7 +62,14 @@ const chat_get = defineApi(async (event) => {
100
62
  const count = num("n");
101
63
  const since = chatDelta.sinceOf(p.id, sent, count);
102
64
  const from = num("from");
65
+ const gone = new AbortController();
66
+ const res = event.node.res;
67
+ const onClose = () => {
68
+ if (!res.writableFinished) gone.abort(new HerdrError("aborted", "Request aborted"));
69
+ };
70
+ res.once("close", onClose);
103
71
  const r = await transcripts.chat(p, {
72
+ signal: gone.signal,
104
73
  since: mark ? since.endsWith(mark) ? since.slice(0, -mark.length) : "" : since,
105
74
  from,
106
75
  // re-read from this byte (bottom of the conversation already shown)
@@ -125,7 +94,9 @@ const chat_get = defineApi(async (event) => {
125
94
  }
126
95
  }
127
96
  if (r.queue && r.queue.length) r.queue = withSentText(p.id, r.queue);
128
- return r.available ? { ...r, model: await currentModel(p).catch(() => null) } : r;
97
+ const out = r.available && !gone.signal.aborted ? { ...r, model: await currentModel(p).catch(() => null) } : r;
98
+ res.off("close", onClose);
99
+ return out;
129
100
  });
130
101
 
131
102
  export { chat_get as default };
@@ -1,4 +1,4 @@
1
- import { H as HerdrError, J as keysFor, K as parseChoices, L as parseOmpField, a as defineApi, P as PANE_RE, f as findPane, M as withPaneLock, N as selfUpdates, O as restarting, Q as updateChoices, R as UPDATE_LABELS, S as updateRestartPlan, T as restarts, p as poll, h as herdr, y as transcripts, b as screenChoices, V as usesTerminalException, W as sameQuestion, X as sleep, g as choicesCache } from '../../nitro/nitro.mjs';
1
+ import { H as HerdrError, V as keysFor, W as parseChoices, X as parseOmpField, a as defineApi, P as PANE_RE, f as findPane, Y as withPaneLock, Z as selfUpdates, _ as restarting, $ as updateChoices, a0 as UPDATE_LABELS, a1 as updateRestartPlan, a2 as restarts, p as poll, h as herdr, J as transcripts, b as screenChoices, a3 as usesTerminalException, a4 as sameQuestion, a5 as sleep, g as choicesCache } from '../../nitro/nitro.mjs';
2
2
  import 'node:http';
3
3
  import 'node:https';
4
4
  import 'node:crypto';
@@ -23,13 +23,13 @@ import 'node:util';
23
23
  import 'qrcode-terminal/vendor/QRCode/index.js';
24
24
  import 'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js';
25
25
  import 'web-push';
26
+ import 'node:zlib';
27
+ import '@simplewebauthn/server';
26
28
  import 'node:net';
27
29
  import 'node:string_decoder';
28
30
  import 'node:fs/promises';
29
31
  import 'node:readline';
30
32
  import 'node:url';
31
- import 'node:zlib';
32
- import '@simplewebauthn/server';
33
33
 
34
34
  const OPEN_MS = 3e3;
35
35
  const answering = /* @__PURE__ */ new Set();