{"id":201,"date":"2026-04-27T15:07:19","date_gmt":"2026-04-27T15:07:19","guid":{"rendered":"https:\/\/incometaxbill.com\/wp\/capital-gains-tax-calculator\/"},"modified":"2026-05-07T08:30:55","modified_gmt":"2026-05-07T08:30:55","slug":"capital-gains-tax-calculator","status":"publish","type":"page","link":"https:\/\/incometaxbill.com\/wp\/capital-gains-tax-calculator\/","title":{"rendered":"2026 Capital Gains Tax Calculator"},"content":{"rendered":"\n<style>\n.itb-capgains-calculator * {\n  box-sizing: border-box;\n}\n\n.itb-capgains-calculator {\n  --itb-bg: #0b0f14;\n  --itb-card: #161b22;\n  --itb-panel: #0d1117;\n  --itb-line: #2d333b;\n  --itb-text: #e6edf3;\n  --itb-muted: #a7b3c2;\n  --itb-accent: #ffb020;\n  --itb-good: #52d273;\n  --itb-bad: #ff7b72;\n  width: min(1160px, calc(100% - 32px));\n  margin: 0 auto;\n  padding: 36px 0 54px;\n  color: var(--itb-text);\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n  line-height: 1.55;\n}\n\nbody.itb-capgains-standalone {\n  margin: 0;\n  background: var(--itb-bg, #0b0f14);\n}\n\n.itb-capgains-calculator a {\n  color: var(--itb-accent);\n}\n\n.itb-capgains-kicker {\n  margin: 0 0 8px;\n  color: var(--itb-accent);\n  font-size: .78rem;\n  font-weight: 800;\n  letter-spacing: .08em;\n  text-transform: uppercase;\n}\n\n.itb-capgains-calculator h1 {\n  max-width: 920px;\n  margin: 0;\n  color: #f4f7fa;\n  font-size: clamp(2.05rem, 5vw, 3.35rem);\n  line-height: 1.05;\n}\n\n.itb-capgains-lede {\n  max-width: 930px;\n  margin: 14px 0 24px;\n  color: var(--itb-muted);\n  font-size: 1rem;\n}\n\n.itb-capgains-layout {\n  display: grid;\n  grid-template-columns: minmax(0, 1fr) 390px;\n  gap: 20px;\n  align-items: start;\n}\n\n.itb-capgains-card,\n.itb-calculator-results,\n.itb-sponsor-box,\n.itb-capgains-ad-placeholder {\n  background: var(--itb-card);\n  border: 1px solid rgba(255, 255, 255, .08);\n  border-radius: 8px;\n  box-shadow: 0 12px 30px rgba(0, 0, 0, .22);\n  padding: 22px;\n  margin-bottom: 18px;\n}\n\n.itb-capgains-card h2,\n.itb-calculator-results h2 {\n  margin: 0 0 16px;\n  padding-bottom: 10px;\n  border-bottom: 2px solid var(--itb-line);\n  color: var(--itb-muted);\n  font-size: .9rem;\n  letter-spacing: .07em;\n  text-transform: uppercase;\n}\n\n.itb-capgains-grid {\n  display: grid;\n  grid-template-columns: repeat(2, minmax(0, 1fr));\n  gap: 14px;\n}\n\n.itb-capgains-grid.itb-capgains-grid-3 {\n  grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n.itb-capgains-field {\n  display: flex;\n  flex-direction: column;\n  min-width: 0;\n}\n\n.itb-capgains-field-wide {\n  grid-column: 1 \/ -1;\n}\n\n.itb-capgains-field label,\n.itb-capgains-field-label {\n  margin-bottom: 6px;\n  color: var(--itb-muted);\n  font-size: .84rem;\n  font-weight: 700;\n}\n\n.itb-required {\n  display: inline-block;\n  margin-left: 4px;\n  color: var(--itb-accent);\n  font-size: .7rem;\n  font-weight: 800;\n  letter-spacing: .04em;\n  text-transform: uppercase;\n}\n\n.itb-capgains-field input,\n.itb-capgains-field select {\n  width: 100%;\n  min-height: 44px;\n  border: 1.5px solid var(--itb-line);\n  border-radius: 8px;\n  background: var(--itb-panel);\n  color: var(--itb-text);\n  padding: 9px 10px;\n  font: inherit;\n}\n\n.itb-capgains-helper,\n.itb-capgains-note {\n  margin: 8px 0 0;\n  color: var(--itb-muted);\n  font-size: .82rem;\n}\n\n.itb-capgains-warning,\n.itb-capgains-error {\n  padding: 12px 14px;\n  border-left: 3px solid var(--itb-accent);\n  background: rgba(255, 176, 32, .08);\n  border-radius: 8px;\n  color: #d6dee8;\n  font-size: .86rem;\n  margin: 12px 0;\n}\n\n.itb-capgains-error {\n  border-left-color: var(--itb-bad);\n  background: rgba(255, 123, 114, .09);\n}\n\n.itb-capgains-checkbox-line {\n  display: flex;\n  align-items: flex-start;\n  gap: 8px;\n  color: var(--itb-muted);\n  font-size: .9rem;\n}\n\n.itb-capgains-checkbox-line input {\n  margin-top: 4px;\n}\n\n.itb-capgains-actions {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 10px;\n  margin-top: 16px;\n}\n\n.itb-capgains-calculator button,\n.itb-capgains-calculator .itb-capgains-button {\n  min-height: 42px;\n  border: 0;\n  border-radius: 8px;\n  background: var(--itb-accent);\n  color: #111 !important;\n  cursor: pointer;\n  font-weight: 850;\n  padding: 10px 14px;\n  text-decoration: none;\n}\n\n.itb-capgains-calculator button.itb-capgains-secondary {\n  background: var(--itb-panel);\n  color: var(--itb-text) !important;\n  border: 1px solid var(--itb-line);\n}\n\n.itb-calculator-results {\n  position: sticky;\n  top: 18px;\n}\n\n.itb-capgains-headline {\n  padding: 16px;\n  background: var(--itb-panel);\n  border: 1px solid var(--itb-line);\n  border-radius: 8px;\n  margin-bottom: 12px;\n}\n\n.itb-capgains-headline span {\n  display: block;\n  color: var(--itb-muted);\n  font-size: .78rem;\n  font-weight: 800;\n  letter-spacing: .05em;\n  text-transform: uppercase;\n}\n\n.itb-capgains-headline strong {\n  display: block;\n  color: #f4f7fa;\n  font-size: 1.45rem;\n  line-height: 1.2;\n  margin-top: 4px;\n  overflow-wrap: anywhere;\n}\n\n.itb-capgains-row {\n  display: flex;\n  justify-content: space-between;\n  gap: 14px;\n  padding: 9px 0;\n  border-bottom: 1px solid var(--itb-line);\n  color: var(--itb-muted);\n  font-size: .88rem;\n}\n\n.itb-capgains-row strong {\n  color: var(--itb-text);\n  text-align: right;\n}\n\n.itb-capgains-ad-placeholder {\n  width: 100%;\n  max-width: 100%;\n  min-height: 90px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  overflow: hidden;\n  text-align: center;\n  color: var(--itb-muted);\n  font-size: .78rem;\n  letter-spacing: .08em;\n  text-transform: uppercase;\n}\n\n.itb-capgains-ad-placeholder ins,\n.itb-capgains-ad-placeholder iframe,\n.itb-result-ad-slot ins,\n.itb-result-ad-slot iframe {\n  max-width: 100% !important;\n}\n\n.itb-result-ad-slot {\n  width: 100%;\n  max-width: 100%;\n  min-height: 76px;\n  margin: 18px 0;\n  padding: 18px;\n  box-shadow: none;\n}\n\n.itb-capgains-tool-list,\n.itb-calculator-menu-list {\n  display: grid;\n  gap: 10px;\n  margin: 12px 0 0 !important;\n  padding: 0 !important;\n  list-style: none !important;\n}\n\n.itb-capgains-tool-list li,\n.itb-calculator-menu-list li {\n  margin: 0 !important;\n  padding: 0 !important;\n}\n\n.itb-capgains-tool-list a,\n.itb-calculator-menu-list a {\n  display: block;\n  padding: 10px 12px;\n  border: 1px solid var(--itb-line);\n  border-radius: 8px;\n  background: var(--itb-panel);\n  color: var(--itb-text);\n  text-decoration: none;\n  font-weight: 750;\n}\n\n.itb-calculator-menu[data-no-auto-ads] ins,\n.itb-calculator-menu[data-no-auto-ads] iframe,\n.itb-calculator-menu[data-no-auto-ads] .adsbygoogle,\n.itb-calculator-menu[data-no-auto-ads] .google-auto-placed,\n.itb-calculator-menu[data-no-auto-ads] [id^=\"google_ads\"],\n.itb-calculator-menu[data-no-auto-ads] [id^=\"aswift\"],\n.itb-calculator-menu[data-no-auto-ads] > :has(ins),\n.itb-calculator-menu[data-no-auto-ads] > :has(iframe),\n.itb-calculator-menu[data-no-auto-ads] > :has(.adsbygoogle),\n.itb-calculator-menu[data-no-auto-ads] > :has(.google-auto-placed),\n.itb-calculator-menu[data-no-auto-ads] .itb-calculator-menu-list > :has(ins),\n.itb-calculator-menu[data-no-auto-ads] .itb-calculator-menu-list > :has(iframe),\n.itb-calculator-menu[data-no-auto-ads] .itb-calculator-menu-list > :has(.adsbygoogle),\n.itb-calculator-menu[data-no-auto-ads] .itb-calculator-menu-list > :has(.google-auto-placed) {\n  display: none !important;\n  min-height: 0 !important;\n  height: 0 !important;\n  margin: 0 !important;\n  padding: 0 !important;\n}\n\n.itb-capgains-faq-item {\n  margin-bottom: 14px;\n}\n\n.itb-capgains-faq-item h3 {\n  margin: 0 0 4px;\n  color: #f4f7fa;\n  font-size: 1rem;\n}\n\n.itb-capgains-faq-item p,\n.itb-capgains-card p,\n.itb-capgains-card li {\n  color: var(--itb-muted);\n}\n\n.itb-capgains-hidden {\n  display: none !important;\n}\n\n@media (max-width: 920px) {\n  .itb-capgains-layout,\n  .itb-capgains-grid,\n  .itb-capgains-grid.itb-capgains-grid-3 {\n    grid-template-columns: 1fr;\n  }\n  .itb-calculator-results {\n    position: static;\n  }\n}\n\n@media (max-width: 560px) {\n  .itb-capgains-calculator {\n    width: calc(100% - 20px);\n    padding-top: 22px;\n  }\n  .itb-capgains-card,\n  .itb-calculator-results,\n  .itb-sponsor-box,\n  .itb-capgains-ad-placeholder {\n    padding: 16px;\n  }\n  .itb-capgains-ad-placeholder {\n    min-height: 100px;\n  }\n  .itb-result-ad-slot {\n    margin: 20px 0;\n    padding: 14px;\n  }\n  .itb-capgains-actions button {\n    width: 100%;\n  }\n}\n\n@media print {\n  body * {\n    visibility: hidden !important;\n  }\n  .itb-capgains-calculator,\n  .itb-capgains-calculator h1,\n  .itb-calculator-results,\n  .itb-calculator-results *,\n  .itb-capgains-print-keep,\n  .itb-capgains-print-keep * {\n    visibility: visible !important;\n  }\n  .itb-capgains-calculator {\n    width: 100% !important;\n    padding: 0 !important;\n    color: #111 !important;\n  }\n  .itb-capgains-layout {\n    display: block !important;\n  }\n  .itb-capgains-form,\n  .itb-capgains-ad-placeholder,\n  .itb-result-ad-slot,\n  .itb-sponsor-box,\n  .itb-capgains-actions,\n  .itb-capgains-tools,\n  .itb-capgains-faqs,\n  nav,\n  header,\n  footer,\n  .adsbygoogle,\n  .google-auto-placed {\n    display: none !important;\n  }\n  .itb-calculator-results,\n  .itb-capgains-print-keep {\n    display: block !important;\n    position: static !important;\n    box-shadow: none !important;\n    border: 1px solid #999 !important;\n    color: #111 !important;\n    background: #fff !important;\n  }\n}\n\n<\/style>\n<main class=\"itb-capgains-calculator\" data-itb-capgains-calculator>\n    \n<p class=\"itb-capgains-lede\">Estimate taxes on a sale of stocks, crypto, real estate, collectibles, or other investment assets.<\/p>\n    <p class=\"itb-capgains-note itb-top-privacy\">Your entries are calculated in your browser and are not saved.<\/p>\n    <div class=\"itb-capgains-layout\">\n      <form class=\"itb-capgains-form\" data-capgains-form aria-label=\"2026 capital gains tax calculator inputs\">\n        <section class=\"itb-capgains-card\">\n          <h2>Sale details<\/h2>\n          <div class=\"itb-capgains-grid\">\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-asset-type\">Asset type <span class=\"itb-required\">Required<\/span><\/label>\n              <select id=\"itb-asset-type\" data-field=\"assetType\">\n                <option value=\"stock\">Stock, ETF, or mutual fund<\/option>\n                <option value=\"crypto\">Crypto<\/option>\n                <option value=\"real_estate\">Real estate<\/option>\n                <option value=\"primary_residence\">Primary residence<\/option>\n                <option value=\"collectible\">Collectible<\/option>\n                <option value=\"other\">Other investment asset<\/option>\n              <\/select>\n              <p class=\"itb-capgains-helper\">Use the asset type that best matches the sale. Real estate and primary residence calculations are simplified planning estimates.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-basis\">Purchase price or cost basis <span class=\"itb-required\">Required<\/span><\/label>\n              <input id=\"itb-basis\" type=\"number\" min=\"0\" step=\"1\" data-field=\"purchasePrice\" value=\"50000\" aria-describedby=\"itb-basis-help\">\n              <p id=\"itb-basis-help\" class=\"itb-capgains-helper\">Use what you paid, plus basis adjustments you know. This may come from brokerage, exchange, or closing records.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-sale-price\">Sale price <span class=\"itb-required\">Required<\/span><\/label>\n              <input id=\"itb-sale-price\" type=\"number\" min=\"0\" step=\"1\" data-field=\"salePrice\" value=\"100000\" aria-describedby=\"itb-sale-help\">\n              <p id=\"itb-sale-help\" class=\"itb-capgains-helper\">Use the gross sale amount before subtracting selling expenses.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-selling-expenses\">Selling expenses<\/label>\n              <input id=\"itb-selling-expenses\" type=\"number\" min=\"0\" step=\"1\" data-field=\"sellingExpenses\" value=\"0\" aria-describedby=\"itb-expenses-help\">\n              <p id=\"itb-expenses-help\" class=\"itb-capgains-helper\">Include commissions, transaction fees, broker fees, real estate agent commissions, transfer fees, and other selling costs if known.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-purchase-date\">Purchase date <span class=\"itb-required\">Required unless using override<\/span><\/label>\n              <input id=\"itb-purchase-date\" type=\"date\" data-field=\"purchaseDate\" value=\"2024-01-15\" aria-describedby=\"itb-date-help\">\n              <p id=\"itb-date-help\" class=\"itb-capgains-helper\">Assets held more than one year are generally treated as long-term. Assets held one year or less are generally short-term.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-sale-date\">Sale date <span class=\"itb-required\">Required unless using override<\/span><\/label>\n              <input id=\"itb-sale-date\" type=\"date\" data-field=\"saleDate\" value=\"2026-02-01\">\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-holding-override\">Holding period override<\/label>\n              <select id=\"itb-holding-override\" data-field=\"holdingPeriodOverride\" aria-describedby=\"itb-holding-override-help\">\n                <option value=\"\">Use dates<\/option>\n                <option value=\"long_term\">Long-term<\/option>\n                <option value=\"short_term\">Short-term<\/option>\n              <\/select>\n              <p id=\"itb-holding-override-help\" class=\"itb-capgains-helper\">Leave this on \u201cUse dates\u201d for the normal estimate. Choose long-term or short-term to test a what-if scenario or override the date-based result.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-losses\">Capital losses available to offset gain<\/label>\n              <input id=\"itb-losses\" type=\"number\" min=\"0\" step=\"1\" data-field=\"capitalLosses\" value=\"0\" aria-describedby=\"itb-losses-help\">\n              <p id=\"itb-losses-help\" class=\"itb-capgains-helper\">Enter capital losses you expect to use against this gain. If you are not sure, leave this blank.<\/p>\n            <\/div>\n          <\/div>\n          <div class=\"itb-capgains-warning itb-capgains-hidden\" data-real-estate-warning>This calculator can estimate a basic real estate sale using sale price, basis, selling expenses, holding period, and optional depreciation recapture. It does not handle installment sales, 1031 exchanges, full depreciation schedules, passive activity rules, or Form 4797-level treatment.<\/div>\n          <div class=\"itb-capgains-warning itb-capgains-hidden\" data-crypto-warning>This calculator handles a simplified single crypto sale. It does not import exchange records, reconcile wallets, calculate FIFO\/LIFO\/specific-identification lots, handle staking rewards, mining income, airdrops, DeFi transactions, NFTs, stablecoin transactions, wallet transfers, crypto-to-crypto swaps, or full Form 8949 reporting.<\/div>\n        <\/section>\n\n        <section class=\"itb-capgains-card\">\n          <h2>Tax profile<\/h2>\n          <div class=\"itb-capgains-grid\">\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-tax-year\">Tax year<\/label>\n              <select id=\"itb-tax-year\" data-field=\"taxYear\">\n                <option value=\"2026\" selected>2026<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-filing-status\">Filing status <span class=\"itb-required\">Required<\/span><\/label>\n              <select id=\"itb-filing-status\" data-field=\"filingStatus\">\n                <option value=\"single\">Single<\/option>\n                <option value=\"married_filing_jointly\">Married Filing Jointly<\/option>\n                <option value=\"married_filing_separately\">Married Filing Separately<\/option>\n                <option value=\"head_of_household\">Head of Household<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-taxable-income\">Taxable income before this gain <span class=\"itb-required\">Required<\/span><\/label>\n              <input id=\"itb-taxable-income\" type=\"number\" min=\"0\" step=\"1\" data-field=\"taxableIncomeBeforeGain\" value=\"100000\" aria-describedby=\"itb-taxable-income-help\">\n              <p id=\"itb-taxable-income-help\" class=\"itb-capgains-helper\">Enter your estimated taxable income for the year before adding this capital gain. This is not just income earned before the sale date.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-magi\">Modified AGI without this sale&#8217;s gain<\/label>\n              <input id=\"itb-magi\" type=\"number\" min=\"0\" step=\"1\" data-field=\"magiBeforeGain\" aria-describedby=\"itb-magi-help\">\n              <p id=\"itb-magi-help\" class=\"itb-capgains-helper\">Used for NIIT. If blank, the calculator estimates MAGI from taxable income before this gain plus this sale&#8217;s taxable gain and labels the NIIT result as simplified.<\/p>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"itb-capgains-card\">\n          <h2>State and local tax<\/h2>\n          <div class=\"itb-capgains-grid\">\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-state\">State of residence <span class=\"itb-required\">Required<\/span><\/label>\n              <select id=\"itb-state\" data-field=\"stateOfResidence\" aria-describedby=\"itb-state-help\"><\/select>\n              <p id=\"itb-state-help\" class=\"itb-capgains-helper\">Many states tax capital gains as regular income, while some states have no broad individual income tax or special rules.<\/p>\n            <\/div>\n            <div class=\"itb-capgains-field itb-capgains-hidden\" data-nyc-resident-field>\n              <label for=\"itb-nyc-resident\">Did you live in New York City?<\/label>\n              <select id=\"itb-nyc-resident\" data-field=\"isNYCResident\">\n                <option value=\"no\">No<\/option>\n                <option value=\"yes\">Yes<\/option>\n              <\/select>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"itb-capgains-card\">\n          <button type=\"button\" class=\"itb-capgains-secondary\" data-advanced-toggle aria-expanded=\"false\" aria-controls=\"itb-advanced-options\">Advanced options<\/button>\n          <div id=\"itb-advanced-options\" class=\"itb-capgains-hidden\" data-advanced-panel>\n            <p class=\"itb-capgains-note\">Most users can leave this section closed. Use these fields only if you have more detailed tax information.<\/p>\n            <div class=\"itb-capgains-grid\">\n              <div class=\"itb-capgains-field\">\n                <label for=\"itb-adjusted-basis\">Manually enter adjusted basis<\/label>\n                <input id=\"itb-adjusted-basis\" type=\"number\" min=\"0\" step=\"1\" data-field=\"adjustedBasis\">\n                <p class=\"itb-capgains-helper\">Use this if basis differs because of improvements, return of capital, depreciation, inheritance, gifts, stock splits, or reinvestments.<\/p>\n              <\/div>\n              <div class=\"itb-capgains-field\">\n                <label for=\"itb-depreciation\">Rental or business property depreciation recapture<\/label>\n                <input id=\"itb-depreciation\" type=\"number\" min=\"0\" step=\"1\" data-field=\"depreciationRecapture\" value=\"0\">\n                <p class=\"itb-capgains-helper\">Most stock, crypto, and personal-use home sales can leave this at zero. Use it only if you sold rental real estate or business property and know the recapture amount from your records or tax preparer.<\/p>\n              <\/div>\n              <div class=\"itb-capgains-field itb-capgains-field-wide\">\n                <label for=\"itb-state-local-rate\">Override state\/local tax rate for this gain (%)<\/label>\n                <input id=\"itb-state-local-rate\" type=\"number\" min=\"0\" max=\"100\" step=\"0.01\" data-field=\"stateLocalRateOverride\">\n                <p class=\"itb-capgains-helper\">Optional. Use this only if you know the state or local rate that should apply to this gain. In many states, capital gains are taxed as ordinary income, so this may be your marginal state\/local income tax rate on additional income. This replaces the built-in state\/local estimate; it does not add to it.<\/p>\n              <\/div>\n              <div class=\"itb-capgains-field\">\n                <label for=\"itb-niit-override\">NIIT override<\/label>\n                <input id=\"itb-niit-override\" type=\"number\" min=\"0\" step=\"1\" data-field=\"niitOverride\">\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"itb-capgains-card itb-capgains-hidden\" data-primary-residence-section>\n          <h2>Primary residence exclusion<\/h2>\n          <div class=\"itb-capgains-grid\">\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-home-owned\">Did you own the home for at least 2 of the last 5 years?<\/label>\n              <select id=\"itb-home-owned\" data-field=\"homeOwnedTwoYears\">\n                <option value=\"yes\">Yes<\/option>\n                <option value=\"no\">No<\/option>\n                <option value=\"not_sure\">Not sure<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-home-used\">Did you use it as your main home for at least 2 of the last 5 years?<\/label>\n              <select id=\"itb-home-used\" data-field=\"homeUsedTwoYears\">\n                <option value=\"yes\">Yes<\/option>\n                <option value=\"no\">No<\/option>\n                <option value=\"not_sure\">Not sure<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-home-recent\">Have you used the home sale exclusion in the last 2 years?<\/label>\n              <select id=\"itb-home-recent\" data-field=\"homeExclusionUsedRecently\">\n                <option value=\"no\">No<\/option>\n                <option value=\"yes\">Yes<\/option>\n                <option value=\"not_sure\">Not sure<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"itb-capgains-field\">\n              <label for=\"itb-home-exclusion\">Section 121 primary home exclusion amount<\/label>\n              <input id=\"itb-home-exclusion\" type=\"number\" min=\"0\" step=\"1\" data-field=\"manualHomeExclusion\">\n            <\/div>\n          <\/div>\n          <p class=\"itb-capgains-note\">The home sale exclusion has eligibility rules. This calculator uses a simplified estimate and does not determine full eligibility.<\/p>\n        <\/section>\n\n        <section class=\"itb-capgains-card\">\n          <div class=\"itb-capgains-actions\">\n            <button type=\"button\" data-calculate>Calculate<\/button>\n            <button type=\"button\" class=\"itb-capgains-secondary\" data-reset-calculator>Reset Calculator<\/button>\n          <\/div>\n        <\/section>\n      <\/form>\n\n      <aside class=\"itb-calculator-results\" data-calculator-results aria-live=\"polite\">\n        <h2>Results<\/h2>\n        <p class=\"itb-capgains-note\">Your entries are calculated in your browser. IncomeTaxBill.com does not save the numbers you enter.<\/p>\n        <div data-validation-messages><\/div>\n        <div data-empty-results>Enter your sale details and calculate your result.<\/div>\n        <div data-result-content class=\"itb-capgains-hidden\">\n          <div class=\"itb-copyable-results\" data-copyable-results><\/div>\n          <div class=\"itb-capgains-ad-placeholder itb-result-ad-slot\">Advertisement<\/div>\n        <\/div>\n        <div class=\"itb-capgains-actions\">\n          <button type=\"button\" class=\"itb-capgains-secondary\" data-copy-results>Copy Results<\/button>\n          <button type=\"button\" class=\"itb-capgains-secondary\" data-print-results>Print or Save Results<\/button>\n        <\/div>\n        <p class=\"itb-capgains-note\" data-copy-status><\/p>\n        <div class=\"itb-sponsor-box\">Interested in sponsoring this tax calculator? Contact us to discuss relevant advertising or partnership opportunities.<\/div>\n      <\/aside>\n    <\/div>\n\n    <section class=\"itb-capgains-card itb-capgains-print-keep\">\n      <h2>Disclaimer<\/h2>\n      <p>This calculator is a simplified self-help planning tool. It does not prepare a tax return and is not tax, legal, accounting, or investment advice. Results are hypothetical estimates based on the information entered and simplified tax assumptions. Capital gains taxes can depend on exact taxable income, holding period, basis, losses, depreciation, exclusions, state law, local tax rules, and other facts. IncomeTaxBill.com does not guarantee that the result applies to your individual circumstances. Confirm your tax obligations before relying on the result.<\/p>\n    <\/section>\n\n    <div class=\"itb-capgains-ad-placeholder\">Advertisement<\/div>\n\n    <section class=\"itb-capgains-card itb-capgains-quickstart\" aria-label=\"How to use this calculator\">\n      <h2>How to use this calculator<\/h2>\n      <p>Start with the asset type, sale price, cost basis, dates, filing status, taxable income before this gain, and state of residence. Then calculate the estimate. Some choices, such as crypto, real estate, primary residence, or collectibles, will show extra notes or fields when they matter.<\/p>\n      <p class=\"itb-capgains-note\">Required fields are marked. Most users can leave Advanced options closed.<\/p>\n    <\/section>\n\n    <section class=\"itb-capgains-card\">\n      <h2>2026 calculator notes<\/h2>\n      <p><strong>Updated for 2026:<\/strong> federal long-term capital gains thresholds, Net Investment Income Tax assumptions, and state\/local planning inputs where supported.<\/p>\n      <p>This calculator estimates federal capital gains tax, Net Investment Income Tax, state tax, local tax where applicable, total estimated tax, and after-tax proceeds.<\/p>\n    <\/section>\n\n    <section class=\"itb-capgains-card\">\n      <h2>How This Capital Gains Tax Calculator Works<\/h2>\n      <p>This calculator estimates your gain, determines whether the gain appears short-term or long-term, applies federal capital gains or ordinary income tax rules, estimates Net Investment Income Tax when applicable, and then estimates state and local tax where supported.<\/p>\n      <p>For long-term gains, the calculator does not apply one flat rate to the entire gain unless the entire gain falls within one bracket. Long-term gains may stack across the 0%, 15%, and 20% federal capital gains brackets depending on filing status and other taxable income for the year.<\/p>\n      <p>For short-term gains, the calculator estimates the additional ordinary income tax caused by adding the short-term gain to your taxable income.<\/p>\n    <\/section>\n\n    <section class=\"itb-capgains-card itb-capgains-print-keep\">\n      <h2>What This Calculator Does Not Handle<\/h2>\n      <ul>\n        <li>Full 1031 exchange calculations<\/li>\n        <li>Installment sales, QSBS exclusions, AMT, wash sales, or full depreciation schedules<\/li>\n        <li>Partnership K-1 capital gains, trusts, estates, or nonresident alien rules<\/li>\n        <li>State part-year residency, every state credit or deduction, or every local tax rule<\/li>\n        <li>Crypto exchange imports, wallet imports, multiple lots, FIFO, LIFO, specific identification, DeFi, NFTs, or full Form 8949 reporting<\/li>\n      <\/ul>\n    <\/section>\n\n\n    <section class=\"itb-capgains-card itb-worked-examples\">\n      <h2>Example Capital Gains Tax Scenarios<\/h2>\n      <p>These simplified examples show how the calculator can be used. Final tax can vary based on total income, losses, basis adjustments, state law, and special asset rules.<\/p>\n      <ul>\n        <li><strong>Stock sale with a $25,000 long-term gain:<\/strong> enter sale price, basis, holding period, filing status, and other taxable income to estimate whether the gain falls in the 0%, 15%, or 20% federal bracket.<\/li>\n        <li><strong>Crypto sale with a short-term gain:<\/strong> short-term gains are generally estimated through ordinary income tax rates rather than the long-term capital gains brackets.<\/li>\n        <li><strong>Home sale planning:<\/strong> the primary residence option can model a simplified exclusion estimate, but the full home-sale exclusion rules should be checked separately.<\/li>\n      <\/ul>\n    <\/section>\n\n    <section class=\"itb-capgains-card itb-calculator-menu\" data-no-auto-ads>\n      <h2>Related Tax Calculators and Guides<\/h2>\n      <ul class=\"itb-calculator-menu-list\">\n        <li><a href=\"\/wp\/2026-federal-income-tax-calculator\/\">2026 Federal Income Tax Calculator<\/a><\/li>\n        <li><a href=\"\/wp\/state-tax-lookup-401k-hsa-take-home-pay\/\">2026 State Income Tax Rates and Brackets by State<\/a><\/li>\n        <li><a href=\"\/wp\/2026-quarterly-estimated-tax-calculator\/\">2026 Quarterly Estimated Tax Calculator<\/a><\/li>\n        <li><a href=\"\/wp\/2026\/05\/03\/quarterly-taxes-for-freelancers-side-businesses\/\">Quarterly Taxes for Freelancers and Side Businesses<\/a><\/li>\n      <\/ul>\n    <\/section>\n\n    <section class=\"itb-capgains-card itb-capgains-faqs\">\n      <h2>FAQs<\/h2>\n      <div class=\"itb-capgains-faq-item\"><h3>What is capital gains tax?<\/h3><p>Capital gains tax is tax on profit from selling an asset for more than its tax basis. Stocks, ETFs, mutual funds, crypto, real estate, collectibles, and other investments may create capital gains when sold.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>What is the difference between short-term and long-term capital gains?<\/h3><p>Short-term capital gains generally apply to assets held for one year or less and are usually taxed like ordinary income. Long-term capital gains generally apply to assets held for more than one year and may qualify for lower federal tax rates.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>How do capital gains tax brackets work?<\/h3><p>Federal long-term capital gains brackets are graduated. Part of a gain may fall in the 0% bracket, another part may fall in the 15% bracket, and high-income gains may reach the 20% bracket. This calculator estimates the gain across brackets instead of applying one flat rate to the entire gain.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does this calculator include state capital gains tax?<\/h3><p>Yes, where state data is available. Many states tax capital gains as ordinary income, some states have no broad individual income tax, and some states have special capital gains rules. State results are labeled as simplified when appropriate.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does New York tax capital gains?<\/h3><p>New York generally taxes capital gains through its regular income tax system. New York City residents may also owe New York City resident income tax.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Do states without income tax have capital gains tax?<\/h3><p>States without a broad individual income tax generally do not tax capital gains through a regular state income tax in this simplified model. Other taxes or special rules may still apply.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does this calculator include Net Investment Income Tax?<\/h3><p>Yes. The calculator estimates the 3.8% Net Investment Income Tax when income appears to exceed the applicable threshold. If modified adjusted gross income is not entered, the NIIT result is simplified.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does this calculator handle home sale exclusions?<\/h3><p>It includes a simplified primary residence exclusion estimate for users who indicate they may qualify. The full home sale exclusion has detailed eligibility rules, so the result should not be treated as a tax return calculation.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does this calculator handle crypto gains?<\/h3><p>Yes, basic crypto sales can be entered like other investment sales. The calculator estimates gain based on sale price, basis, expenses, holding period, and tax profile. It does not import exchange records or prepare Form 8949.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Does this calculator handle collectibles?<\/h3><p>It includes a simplified collectibles estimate. Collectibles may be taxed differently from ordinary long-term capital gains, so users should confirm treatment before relying on the result.<\/p><\/div>\n      <div class=\"itb-capgains-faq-item\"><h3>Why is this only an estimate?<\/h3><p>Capital gains tax can depend on exact income, basis, holding period, losses, asset type, depreciation, exclusions, state law, local tax rules, and other facts. This calculator is a planning tool, not a tax return.<\/p><\/div>\n    <\/section>\n  <\/main>\n<script>new Function(atob(\"KGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7CgogIHdpbmRvdy5JVEJDYXBpdGFsR2FpbnNGZWRlcmFsTFRDRzIwMjYgPSB7CiAgICBqdXJpc2RpY3Rpb246ICJVbml0ZWQgU3RhdGVzIiwKICAgIHRheFllYXI6IDIwMjYsCiAgICBkYXRhVmludGFnZTogIjIwMjYgSVJTIGluZmxhdGlvbi1hZGp1c3RlZCB0aHJlc2hvbGRzIiwKICAgIGxhc3RVcGRhdGVkOiAiMjAyNi0wNC0yNyIsCiAgICBzb3VyY2VOYW1lOiAiSVJTIFJldi4gUHJvYy4gMjAyNS0zMiwgU2VjdGlvbiA0LjAzIiwKICAgIHNvdXJjZVVybDogImh0dHBzOi8vd3d3Lmlycy5nb3YvcHViL2lycy1kcm9wL3JwLTI1LTMyLnBkZiIsCiAgICBzb3VyY2VUeXBlOiAib2ZmaWNpYWxfaXJzX3JldmVudWVfcHJvY2VkdXJlIiwKICAgIHJldHJpZXZlZERhdGU6ICIyMDI2LTA0LTI3IiwKICAgIHZlcmlmaWVkQnk6ICJyZXF1aXJlc19odW1hbl9yZXZpZXciLAogICAgYWNjdXJhY3lTdGF0dXM6ICJvZmZpY2lhbF8yMDI2IiwKICAgIG5vdGVzOiAiTWF4aW11bSB6ZXJvLXJhdGUgYW5kIG1heGltdW0gMTUtcGVyY2VudC1yYXRlIGFtb3VudHMgZm9yIDIwMjYgbG9uZy10ZXJtIGNhcGl0YWwgZ2FpbnMuIiwKICAgIHRocmVzaG9sZHM6IHsKICAgICAgc2luZ2xlOiB7IG1heGltdW1aZXJvUmF0ZUFtb3VudDogNDk0NTAsIG1heGltdW0xNVJhdGVBbW91bnQ6IDU0NTUwMCB9LAogICAgICBtYXJyaWVkX2ZpbGluZ19qb2ludGx5OiB7IG1heGltdW1aZXJvUmF0ZUFtb3VudDogOTg5MDAsIG1heGltdW0xNVJhdGVBbW91bnQ6IDYxMzcwMCB9LAogICAgICBtYXJyaWVkX2ZpbGluZ19zZXBhcmF0ZWx5OiB7IG1heGltdW1aZXJvUmF0ZUFtb3VudDogNDk0NTAsIG1heGltdW0xNVJhdGVBbW91bnQ6IDMwNjg1MCB9LAogICAgICBoZWFkX29mX2hvdXNlaG9sZDogeyBtYXhpbXVtWmVyb1JhdGVBbW91bnQ6IDY2MjAwLCBtYXhpbXVtMTVSYXRlQW1vdW50OiA1Nzk2MDAgfQogICAgfQogIH07Cn0pKCk7CgoKKGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7CgogIHdpbmRvdy5JVEJGZWRlcmFsT3JkaW5hcnlJbmNvbWUyMDI2ID0gewogICAganVyaXNkaWN0aW9uOiAiVW5pdGVkIFN0YXRlcyIsCiAgICB0YXhZZWFyOiAyMDI2LAogICAgZGF0YVZpbnRhZ2U6ICIyMDI2IElSUyBpbmZsYXRpb24tYWRqdXN0ZWQgdGF4IHJhdGUgdGFibGVzIiwKICAgIGxhc3RVcGRhdGVkOiAiMjAyNi0wNC0yNyIsCiAgICBzb3VyY2VOYW1lOiAiSVJTIFJldi4gUHJvYy4gMjAyNS0zMiwgU2VjdGlvbiA0LjAxIiwKICAgIHNvdXJjZVVybDogImh0dHBzOi8vd3d3Lmlycy5nb3YvcHViL2lycy1kcm9wL3JwLTI1LTMyLnBkZiIsCiAgICBzb3VyY2VUeXBlOiAib2ZmaWNpYWxfaXJzX3JldmVudWVfcHJvY2VkdXJlIiwKICAgIHJldHJpZXZlZERhdGU6ICIyMDI2LTA0LTI3IiwKICAgIHZlcmlmaWVkQnk6ICJyZXF1aXJlc19odW1hbl9yZXZpZXciLAogICAgYWNjdXJhY3lTdGF0dXM6ICJvZmZpY2lhbF8yMDI2IiwKICAgIG5vdGVzOiAiT3JkaW5hcnkgaW5jb21lIGJyYWNrZXRzIHVzZWQgZm9yIHNob3J0LXRlcm0gY2FwaXRhbCBnYWluIGluY3JlbWVudGFsIHRheCBlc3RpbWF0ZXMuIiwKICAgIGJyYWNrZXRzOiB7CiAgICAgIG1hcnJpZWRfZmlsaW5nX2pvaW50bHk6IFsKICAgICAgICB7IHVwVG86IDI0ODAwLCByYXRlOiAwLjEwLCBiYXNlVGF4OiAwLCBvdmVyOiAwIH0sCiAgICAgICAgeyB1cFRvOiAxMDA4MDAsIHJhdGU6IDAuMTIsIGJhc2VUYXg6IDI0ODAsIG92ZXI6IDI0ODAwIH0sCiAgICAgICAgeyB1cFRvOiAyMTE0MDAsIHJhdGU6IDAuMjIsIGJhc2VUYXg6IDExNjAwLCBvdmVyOiAxMDA4MDAgfSwKICAgICAgICB7IHVwVG86IDQwMzU1MCwgcmF0ZTogMC4yNCwgYmFzZVRheDogMzU5MzIsIG92ZXI6IDIxMTQwMCB9LAogICAgICAgIHsgdXBUbzogNTEyNDUwLCByYXRlOiAwLjMyLCBiYXNlVGF4OiA4MjA0OCwgb3ZlcjogNDAzNTUwIH0sCiAgICAgICAgeyB1cFRvOiA3Njg3MDAsIHJhdGU6IDAuMzUsIGJhc2VUYXg6IDExNjg5Niwgb3ZlcjogNTEyNDUwIH0sCiAgICAgICAgeyB1cFRvOiBudWxsLCByYXRlOiAwLjM3LCBiYXNlVGF4OiAyMDY1ODMuNTAsIG92ZXI6IDc2ODcwMCB9CiAgICAgIF0sCiAgICAgIGhlYWRfb2ZfaG91c2Vob2xkOiBbCiAgICAgICAgeyB1cFRvOiAxNzcwMCwgcmF0ZTogMC4xMCwgYmFzZVRheDogMCwgb3ZlcjogMCB9LAogICAgICAgIHsgdXBUbzogNjc0NTAsIHJhdGU6IDAuMTIsIGJhc2VUYXg6IDE3NzAsIG92ZXI6IDE3NzAwIH0sCiAgICAgICAgeyB1cFRvOiAxMDU3MDAsIHJhdGU6IDAuMjIsIGJhc2VUYXg6IDc3NDAsIG92ZXI6IDY3NDUwIH0sCiAgICAgICAgeyB1cFRvOiAyMDE3NTAsIHJhdGU6IDAuMjQsIGJhc2VUYXg6IDE2MTU1LCBvdmVyOiAxMDU3MDAgfSwKICAgICAgICB7IHVwVG86IDI1NjIwMCwgcmF0ZTogMC4zMiwgYmFzZVRheDogMzkyMDcsIG92ZXI6IDIwMTc1MCB9LAogICAgICAgIHsgdXBUbzogNjQwNjAwLCByYXRlOiAwLjM1LCBiYXNlVGF4OiA1NjYzMSwgb3ZlcjogMjU2MjAwIH0sCiAgICAgICAgeyB1cFRvOiBudWxsLCByYXRlOiAwLjM3LCBiYXNlVGF4OiAxOTExNzEsIG92ZXI6IDY0MDYwMCB9CiAgICAgIF0sCiAgICAgIHNpbmdsZTogWwogICAgICAgIHsgdXBUbzogMTI0MDAsIHJhdGU6IDAuMTAsIGJhc2VUYXg6IDAsIG92ZXI6IDAgfSwKICAgICAgICB7IHVwVG86IDUwNDAwLCByYXRlOiAwLjEyLCBiYXNlVGF4OiAxMjQwLCBvdmVyOiAxMjQwMCB9LAogICAgICAgIHsgdXBUbzogMTA1NzAwLCByYXRlOiAwLjIyLCBiYXNlVGF4OiA1ODAwLCBvdmVyOiA1MDQwMCB9LAogICAgICAgIHsgdXBUbzogMjAxNzc1LCByYXRlOiAwLjI0LCBiYXNlVGF4OiAxNzk2Niwgb3ZlcjogMTA1NzAwIH0sCiAgICAgICAgeyB1cFRvOiAyNTYyMjUsIHJhdGU6IDAuMzIsIGJhc2VUYXg6IDQxMDI0LCBvdmVyOiAyMDE3NzUgfSwKICAgICAgICB7IHVwVG86IDY0MDYwMCwgcmF0ZTogMC4zNSwgYmFzZVRheDogNTg0NDgsIG92ZXI6IDI1NjIyNSB9LAogICAgICAgIHsgdXBUbzogbnVsbCwgcmF0ZTogMC4zNywgYmFzZVRheDogMTkyOTc5LjI1LCBvdmVyOiA2NDA2MDAgfQogICAgICBdLAogICAgICBtYXJyaWVkX2ZpbGluZ19zZXBhcmF0ZWx5OiBbCiAgICAgICAgeyB1cFRvOiAxMjQwMCwgcmF0ZTogMC4xMCwgYmFzZVRheDogMCwgb3ZlcjogMCB9LAogICAgICAgIHsgdXBUbzogNTA0MDAsIHJhdGU6IDAuMTIsIGJhc2VUYXg6IDEyNDAsIG92ZXI6IDEyNDAwIH0sCiAgICAgICAgeyB1cFRvOiAxMDU3MDAsIHJhdGU6IDAuMjIsIGJhc2VUYXg6IDU4MDAsIG92ZXI6IDUwNDAwIH0sCiAgICAgICAgeyB1cFRvOiAyMDE3NzUsIHJhdGU6IDAuMjQsIGJhc2VUYXg6IDE3OTY2LCBvdmVyOiAxMDU3MDAgfSwKICAgICAgICB7IHVwVG86IDI1NjIyNSwgcmF0ZTogMC4zMiwgYmFzZVRheDogNDEwMjQsIG92ZXI6IDIwMTc3NSB9LAogICAgICAgIHsgdXBUbzogMzg0MzUwLCByYXRlOiAwLjM1LCBiYXNlVGF4OiA1ODQ0OCwgb3ZlcjogMjU2MjI1IH0sCiAgICAgICAgeyB1cFRvOiBudWxsLCByYXRlOiAwLjM3LCBiYXNlVGF4OiAxMDMyOTEuNzUsIG92ZXI6IDM4NDM1MCB9CiAgICAgIF0KICAgIH0KICB9Owp9KSgpOwoKCihmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwoKICB3aW5kb3cuSVRCRmVkZXJhbE5JSVREYXRhID0gewogICAganVyaXNkaWN0aW9uOiAiVW5pdGVkIFN0YXRlcyIsCiAgICB0YXhZZWFyOiAibGF0ZXN0X2F2YWlsYWJsZSIsCiAgICBkYXRhVmludGFnZTogIklSUyBOSUlUIHN0YXR1dG9yeSB0aHJlc2hvbGQgZ3VpZGFuY2UiLAogICAgbGFzdFVwZGF0ZWQ6ICIyMDI2LTA0LTI3IiwKICAgIHNvdXJjZU5hbWU6ICJJUlMgTmV0IEludmVzdG1lbnQgSW5jb21lIFRheCBndWlkYW5jZSIsCiAgICBzb3VyY2VVcmw6ICJodHRwczovL3d3dy5pcnMuZ292L2luZGl2aWR1YWxzL25ldC1pbnZlc3RtZW50LWluY29tZS10YXgiLAogICAgc291cmNlVHlwZTogIm9mZmljaWFsX2lyc190b3BpYyIsCiAgICByZXRyaWV2ZWREYXRlOiAiMjAyNi0wNC0yNyIsCiAgICB2ZXJpZmllZEJ5OiAicmVxdWlyZXNfaHVtYW5fcmV2aWV3IiwKICAgIGFjY3VyYWN5U3RhdHVzOiAib2ZmaWNpYWxfbGF0ZXN0X2F2YWlsYWJsZSIsCiAgICBub3RlczogIk5JSVQgYXBwbGllcyBhdCAzLjglIHRvIHRoZSBsZXNzZXIgb2YgbmV0IGludmVzdG1lbnQgaW5jb21lIG9yIE1BR0kgYWJvdmUgdGhlIGZpbGluZyBzdGF0dXMgdGhyZXNob2xkLiIsCiAgICByYXRlOiAwLjAzOCwKICAgIHRocmVzaG9sZHM6IHsKICAgICAgc2luZ2xlOiAyMDAwMDAsCiAgICAgIGhlYWRfb2ZfaG91c2Vob2xkOiAyMDAwMDAsCiAgICAgIG1hcnJpZWRfZmlsaW5nX2pvaW50bHk6IDI1MDAwMCwKICAgICAgbWFycmllZF9maWxpbmdfc2VwYXJhdGVseTogMTI1MDAwCiAgICB9CiAgfTsKfSkoKTsKCgooZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgY29uc3QgdW5zdXBwb3J0ZWQgPSB7CiAgICBicm9hZEluZGl2aWR1YWxJbmNvbWVUYXg6IHRydWUsCiAgICBkZWZhdWx0Q2FwaXRhbEdhaW5zVHJlYXRtZW50OiAibm90X2ltcGxlbWVudGVkIiwKICAgIHN1cHBvcnRlZDogZmFsc2UsCiAgICBsb2NhbFRheE1heUFwcGx5OiBmYWxzZSwKICAgIGFjY3VyYWN5U3RhdHVzOiAibm90X2ltcGxlbWVudGVkIiwKICAgIHZlcmlmaWVkQnk6ICJyZXF1aXJlc19odW1hbl9yZXZpZXciLAogICAgc291cmNlVHlwZTogInVuc3VwcG9ydGVkIiwKICAgIHNvdXJjZU5hbWU6ICJTdGF0ZSBjYXBpdGFsIGdhaW5zIHRyZWF0bWVudCBub3QgaW1wbGVtZW50ZWQgaW4gVmVyc2lvbiAxIiwKICAgIHNvdXJjZVVybDogIiIsCiAgICBkYXRhVmludGFnZTogIm5vdCBpbXBsZW1lbnRlZCIsCiAgICBsYXN0VXBkYXRlZDogIjIwMjYtMDQtMjciLAogICAgcmV0cmlldmVkRGF0ZTogIjIwMjYtMDQtMjciLAogICAgbm90ZXM6ICJTdGF0ZSBjYXBpdGFsIGdhaW5zIGVzdGltYXRlIGlzIG5vdCB5ZXQgYXZhaWxhYmxlIGZvciB0aGlzIHN0YXRlLiIKICB9OwoKICBmdW5jdGlvbiBzdGF0ZShuYW1lLCBhYmJyZXZpYXRpb24sIG92ZXJyaWRlcykgewogICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHVuc3VwcG9ydGVkLCB7IG5hbWUsIGFiYnJldmlhdGlvbiwganVyaXNkaWN0aW9uOiBuYW1lLCB0YXhZZWFyOiAyMDI2IH0sIG92ZXJyaWRlcyB8fCB7fSk7CiAgfQoKICBmdW5jdGlvbiBub0Jyb2FkSW5jb21lVGF4KG5hbWUsIGFiYnJldmlhdGlvbiwgc291cmNlVXJsKSB7CiAgICByZXR1cm4gc3RhdGUobmFtZSwgYWJicmV2aWF0aW9uLCB7CiAgICAgIGJyb2FkSW5kaXZpZHVhbEluY29tZVRheDogZmFsc2UsCiAgICAgIGRlZmF1bHRDYXBpdGFsR2FpbnNUcmVhdG1lbnQ6ICJub19icm9hZF9pbmRpdmlkdWFsX2luY29tZV90YXgiLAogICAgICBzdXBwb3J0ZWQ6IHRydWUsCiAgICAgIGFjY3VyYWN5U3RhdHVzOiAic2ltcGxpZmllZF9yZXF1aXJlc19yZXZpZXciLAogICAgICBzb3VyY2VUeXBlOiAib2ZmaWNpYWxfc3RhdGVfdGF4X2FnZW5jeSIsCiAgICAgIHNvdXJjZU5hbWU6IG5hbWUgKyAiIHRheCBhZ2VuY3kgaW5kaXZpZHVhbCBpbmNvbWUgdGF4IGd1aWRhbmNlIiwKICAgICAgc291cmNlVXJsLAogICAgICBkYXRhVmludGFnZTogImxhdGVzdCBhdmFpbGFibGUgc3RhdGUgZ3VpZGFuY2UiLAogICAgICBub3RlczogIlRoaXMgc3RhdGUgZG9lcyBub3QgaGF2ZSBhIGJyb2FkIGluZGl2aWR1YWwgaW5jb21lIHRheCBpbiB0aGlzIHNpbXBsaWZpZWQgbW9kZWwuIE90aGVyIHRheGVzIG9yIHNwZWNpYWwgcnVsZXMgbWF5IHN0aWxsIGFwcGx5LiIKICAgIH0pOwogIH0KCiAgd2luZG93LklUQlN0YXRlQ2FwaXRhbEdhaW5zRGF0YSA9IHsKICAgIHRheFllYXI6IDIwMjYsCiAgICBsYXN0VXBkYXRlZDogIjIwMjYtMDQtMjciLAogICAgdmVyaWZpZWRCeTogInJlcXVpcmVzX2h1bWFuX3JldmlldyIsCiAgICBub3RlczogIkFsbCBzdGF0ZSBlbnRyaWVzIHJlcXVpcmUgaHVtYW4gcmV2aWV3IGJlZm9yZSBwdWJsaWNhdGlvbi4gVW5zdXBwb3J0ZWQgc3RhdGVzIGludGVudGlvbmFsbHkgZG8gbm90IGZhYnJpY2F0ZSBwcmVjaXNlIGVzdGltYXRlcy4iLAogICAgc3RhdGVzOiB7CiAgICAgIEFMOiBzdGF0ZSgiQWxhYmFtYSIsICJBTCIpLCBBSzogbm9Ccm9hZEluY29tZVRheCgiQWxhc2thIiwgIkFLIiwgImh0dHBzOi8vdGF4LmFsYXNrYS5nb3YvIiksCiAgICAgIEFaOiBzdGF0ZSgiQXJpem9uYSIsICJBWiIpLCBBUjogc3RhdGUoIkFya2Fuc2FzIiwgIkFSIiksCiAgICAgIENBOiBzdGF0ZSgiQ2FsaWZvcm5pYSIsICJDQSIsIHsKICAgICAgICBkZWZhdWx0Q2FwaXRhbEdhaW5zVHJlYXRtZW50OiAidGF4ZWRfYXNfb3JkaW5hcnlfaW5jb21lIiwKICAgICAgICBzdXBwb3J0ZWQ6IGZhbHNlLAogICAgICAgIGFjY3VyYWN5U3RhdHVzOiAibm90X2ltcGxlbWVudGVkIiwKICAgICAgICBzb3VyY2VUeXBlOiAib2ZmaWNpYWxfc3RhdGVfdGF4X2FnZW5jeSIsCiAgICAgICAgc291cmNlTmFtZTogIkNhbGlmb3JuaWEgRnJhbmNoaXNlIFRheCBCb2FyZCBjYXBpdGFsIGdhaW5zIGd1aWRhbmNlIiwKICAgICAgICBzb3VyY2VVcmw6ICJodHRwczovL3d3dy5mdGIuY2EuZ292L2ZpbGUvcGVyc29uYWwvaW5jb21lLXR5cGVzL2NhcGl0YWwtZ2FpbnMtYW5kLWxvc3Nlcy5odG1sIiwKICAgICAgICBub3RlczogIkNhbGlmb3JuaWEgY2FwaXRhbCBnYWlucyBlc3RpbWF0ZSBpcyBub3QgaW1wbGVtZW50ZWQgeWV0LiBGZWRlcmFsIHRheCBpcyBzdGlsbCBlc3RpbWF0ZWQuIgogICAgICB9KSwKICAgICAgQ086IHN0YXRlKCJDb2xvcmFkbyIsICJDTyIpLCBDVDogc3RhdGUoIkNvbm5lY3RpY3V0IiwgIkNUIiksCiAgICAgIERDOiBzdGF0ZSgiRGlzdHJpY3Qgb2YgQ29sdW1iaWEiLCAiREMiKSwgREU6IHN0YXRlKCJEZWxhd2FyZSIsICJERSIpLAogICAgICBGTDogbm9Ccm9hZEluY29tZVRheCgiRmxvcmlkYSIsICJGTCIsICJodHRwczovL2Zsb3JpZGFyZXZlbnVlLmNvbS8iKSwKICAgICAgR0E6IHN0YXRlKCJHZW9yZ2lhIiwgIkdBIiksIEhJOiBzdGF0ZSgiSGF3YWlpIiwgIkhJIiksIElEOiBzdGF0ZSgiSWRhaG8iLCAiSUQiKSwKICAgICAgSUw6IHN0YXRlKCJJbGxpbm9pcyIsICJJTCIpLCBJTjogc3RhdGUoIkluZGlhbmEiLCAiSU4iKSwgSUE6IHN0YXRlKCJJb3dhIiwgIklBIiksCiAgICAgIEtTOiBzdGF0ZSgiS2Fuc2FzIiwgIktTIiksIEtZOiBzdGF0ZSgiS2VudHVja3kiLCAiS1kiKSwgTEE6IHN0YXRlKCJMb3Vpc2lhbmEiLCAiTEEiKSwKICAgICAgTUU6IHN0YXRlKCJNYWluZSIsICJNRSIpLCBNRDogc3RhdGUoIk1hcnlsYW5kIiwgIk1EIiwgeyBsb2NhbFRheE1heUFwcGx5OiB0cnVlIH0pLAogICAgICBNQTogc3RhdGUoIk1hc3NhY2h1c2V0dHMiLCAiTUEiLCB7CiAgICAgICAgZGVmYXVsdENhcGl0YWxHYWluc1RyZWF0bWVudDogInByZWZlcmVudGlhbF9vcl9zcGVjaWFsX3J1bGVzIiwKICAgICAgICBzdXBwb3J0ZWQ6IGZhbHNlLAogICAgICAgIGFjY3VyYWN5U3RhdHVzOiAibm90X2ltcGxlbWVudGVkIiwKICAgICAgICBzb3VyY2VUeXBlOiAib2ZmaWNpYWxfc3RhdGVfdGF4X2FnZW5jeSIsCiAgICAgICAgc291cmNlTmFtZTogIk1hc3NhY2h1c2V0dHMgRGVwYXJ0bWVudCBvZiBSZXZlbnVlIGNhcGl0YWwgZ2FpbnMgZ3VpZGFuY2UiLAogICAgICAgIHNvdXJjZVVybDogImh0dHBzOi8vd3d3Lm1hc3MuZ292L2luZm8tZGV0YWlscy9tYXNzYWNodXNldHRzLXRheC1yYXRlcyIsCiAgICAgICAgbm90ZXM6ICJNYXNzYWNodXNldHRzIGhhcyBzcGVjaWFsIGNhcGl0YWwgZ2FpbnMgdHJlYXRtZW50LiBTdGF0ZSBlc3RpbWF0ZSBpcyBub3QgaW1wbGVtZW50ZWQgeWV0LiIKICAgICAgfSksCiAgICAgIE1JOiBzdGF0ZSgiTWljaGlnYW4iLCAiTUkiKSwgTU46IHN0YXRlKCJNaW5uZXNvdGEiLCAiTU4iKSwgTVM6IHN0YXRlKCJNaXNzaXNzaXBwaSIsICJNUyIpLAogICAgICBNTzogc3RhdGUoIk1pc3NvdXJpIiwgIk1PIiksIE1UOiBzdGF0ZSgiTW9udGFuYSIsICJNVCIpLCBORTogc3RhdGUoIk5lYnJhc2thIiwgIk5FIiksCiAgICAgIE5WOiBub0Jyb2FkSW5jb21lVGF4KCJOZXZhZGEiLCAiTlYiLCAiaHR0cHM6Ly90YXgubnYuZ292LyIpLAogICAgICBOSDogbm9Ccm9hZEluY29tZVRheCgiTmV3IEhhbXBzaGlyZSIsICJOSCIsICJodHRwczovL3d3dy5yZXZlbnVlLm5oLmdvdi8iKSwKICAgICAgTko6IHN0YXRlKCJOZXcgSmVyc2V5IiwgIk5KIiwgewogICAgICAgIGRlZmF1bHRDYXBpdGFsR2FpbnNUcmVhdG1lbnQ6ICJ0YXhlZF9hc19vcmRpbmFyeV9pbmNvbWUiLAogICAgICAgIHN1cHBvcnRlZDogZmFsc2UsCiAgICAgICAgYWNjdXJhY3lTdGF0dXM6ICJub3RfaW1wbGVtZW50ZWQiLAogICAgICAgIHNvdXJjZVR5cGU6ICJvZmZpY2lhbF9zdGF0ZV90YXhfYWdlbmN5IiwKICAgICAgICBzb3VyY2VOYW1lOiAiTmV3IEplcnNleSBEaXZpc2lvbiBvZiBUYXhhdGlvbiBjYXBpdGFsIGdhaW5zIGd1aWRhbmNlIiwKICAgICAgICBzb3VyY2VVcmw6ICJodHRwczovL3d3dy5uai5nb3YvdHJlYXN1cnkvdGF4YXRpb24vIiwKICAgICAgICBub3RlczogIk5ldyBKZXJzZXkgc3RhdGUgY2FwaXRhbCBnYWlucyBlc3RpbWF0ZSBpcyBub3QgaW1wbGVtZW50ZWQgeWV0LiIKICAgICAgfSksCiAgICAgIE5NOiBzdGF0ZSgiTmV3IE1leGljbyIsICJOTSIpLAogICAgICBOWTogc3RhdGUoIk5ldyBZb3JrIiwgIk5ZIiwgewogICAgICAgIGRlZmF1bHRDYXBpdGFsR2FpbnNUcmVhdG1lbnQ6ICJ0YXhlZF9hc19vcmRpbmFyeV9pbmNvbWUiLAogICAgICAgIHN1cHBvcnRlZDogdHJ1ZSwKICAgICAgICBsb2NhbFRheE1heUFwcGx5OiB0cnVlLAogICAgICAgIGFjY3VyYWN5U3RhdHVzOiAic2ltcGxpZmllZF9yZXF1aXJlc19yZXZpZXciLAogICAgICAgIHNvdXJjZVR5cGU6ICJvZmZpY2lhbF9zdGF0ZV90YXhfYWdlbmN5IiwKICAgICAgICBzb3VyY2VOYW1lOiAiTmV3IFlvcmsgU3RhdGUgcGVyc29uYWwgaW5jb21lIHRheCBmb3JtcyBhbmQgaW5zdHJ1Y3Rpb25zIiwKICAgICAgICBzb3VyY2VVcmw6ICJodHRwczovL3d3dy50YXgubnkuZ292L2Zvcm1zL2N1cnJlbnQtZm9ybXMvaXQvaXQyMDFpLmh0bSIsCiAgICAgICAgZGF0YVZpbnRhZ2U6ICJsYXRlc3QgYXZhaWxhYmxlIE5ldyBZb3JrIHJhdGUgYXNzdW1wdGlvbnMiLAogICAgICAgIG5vdGVzOiAiU2ltcGxpZmllZCBpbmNyZW1lbnRhbCBOZXcgWW9yayBTdGF0ZSBvcmRpbmFyeSBpbmNvbWUgdGF4IGVzdGltYXRlLiBSZXF1aXJlcyBodW1hbiByZXZpZXcgYmVmb3JlIHB1YmxpY2F0aW9uLiIsCiAgICAgICAgc3RhbmRhcmREZWR1Y3Rpb246IHsKICAgICAgICAgIHNpbmdsZTogODAwMCwKICAgICAgICAgIG1hcnJpZWRfZmlsaW5nX2pvaW50bHk6IDE2MDUwLAogICAgICAgICAgbWFycmllZF9maWxpbmdfc2VwYXJhdGVseTogODAwMCwKICAgICAgICAgIGhlYWRfb2ZfaG91c2Vob2xkOiAxMTIwMAogICAgICAgIH0sCiAgICAgICAgYnJhY2tldHM6IHsKICAgICAgICAgIHNpbmdsZTogWwogICAgICAgICAgICB7IHVwVG86IDg1MDAsIHJhdGU6IDAuMDQgfSwgeyB1cFRvOiAxMTcwMCwgcmF0ZTogMC4wNDUgfSwKICAgICAgICAgICAgeyB1cFRvOiAxMzkwMCwgcmF0ZTogMC4wNTI1IH0sIHsgdXBUbzogODA2NTAsIHJhdGU6IDAuMDU1IH0sCiAgICAgICAgICAgIHsgdXBUbzogMjE1NDAwLCByYXRlOiAwLjA2IH0sIHsgdXBUbzogMTA3NzU1MCwgcmF0ZTogMC4wNjg1IH0sCiAgICAgICAgICAgIHsgdXBUbzogNTAwMDAwMCwgcmF0ZTogMC4wOTY1IH0sIHsgdXBUbzogMjUwMDAwMDAsIHJhdGU6IDAuMTAzIH0sCiAgICAgICAgICAgIHsgdXBUbzogbnVsbCwgcmF0ZTogMC4xMDkgfQogICAgICAgICAgXSwKICAgICAgICAgIG1hcnJpZWRfZmlsaW5nX2pvaW50bHk6IFsKICAgICAgICAgICAgeyB1cFRvOiAxNzE1MCwgcmF0ZTogMC4wNCB9LCB7IHVwVG86IDIzNjAwLCByYXRlOiAwLjA0NSB9LAogICAgICAgICAgICB7IHVwVG86IDI3OTAwLCByYXRlOiAwLjA1MjUgfSwgeyB1cFRvOiAxNjE1NTAsIHJhdGU6IDAuMDU1IH0sCiAgICAgICAgICAgIHsgdXBUbzogMzIzMjAwLCByYXRlOiAwLjA2IH0sIHsgdXBUbzogMjE1NTM1MCwgcmF0ZTogMC4wNjg1IH0sCiAgICAgICAgICAgIHsgdXBUbzogNTAwMDAwMCwgcmF0ZTogMC4wOTY1IH0sIHsgdXBUbzogMjUwMDAwMDAsIHJhdGU6IDAuMTAzIH0sCiAgICAgICAgICAgIHsgdXBUbzogbnVsbCwgcmF0ZTogMC4xMDkgfQogICAgICAgICAgXSwKICAgICAgICAgIG1hcnJpZWRfZmlsaW5nX3NlcGFyYXRlbHk6IFsKICAgICAgICAgICAgeyB1cFRvOiA4NTAwLCByYXRlOiAwLjA0IH0sIHsgdXBUbzogMTE3MDAsIHJhdGU6IDAuMDQ1IH0sCiAgICAgICAgICAgIHsgdXBUbzogMTM5MDAsIHJhdGU6IDAuMDUyNSB9LCB7IHVwVG86IDgwNjUwLCByYXRlOiAwLjA1NSB9LAogICAgICAgICAgICB7IHVwVG86IDIxNTQwMCwgcmF0ZTogMC4wNiB9LCB7IHVwVG86IDEwNzc1NTAsIHJhdGU6IDAuMDY4NSB9LAogICAgICAgICAgICB7IHVwVG86IDUwMDAwMDAsIHJhdGU6IDAuMDk2NSB9LCB7IHVwVG86IDI1MDAwMDAwLCByYXRlOiAwLjEwMyB9LAogICAgICAgICAgICB7IHVwVG86IG51bGwsIHJhdGU6IDAuMTA5IH0KICAgICAgICAgIF0sCiAgICAgICAgICBoZWFkX29mX2hvdXNlaG9sZDogWwogICAgICAgICAgICB7IHVwVG86IDEyODAwLCByYXRlOiAwLjA0IH0sIHsgdXBUbzogMTc2NTAsIHJhdGU6IDAuMDQ1IH0sCiAgICAgICAgICAgIHsgdXBUbzogMjA5MDAsIHJhdGU6IDAuMDUyNSB9LCB7IHVwVG86IDEwNzY1MCwgcmF0ZTogMC4wNTUgfSwKICAgICAgICAgICAgeyB1cFRvOiAyNjkzMDAsIHJhdGU6IDAuMDYgfSwgeyB1cFRvOiAxNjE2NDUwLCByYXRlOiAwLjA2ODUgfSwKICAgICAgICAgICAgeyB1cFRvOiA1MDAwMDAwLCByYXRlOiAwLjA5NjUgfSwgeyB1cFRvOiAyNTAwMDAwMCwgcmF0ZTogMC4xMDMgfSwKICAgICAgICAgICAgeyB1cFRvOiBudWxsLCByYXRlOiAwLjEwOSB9CiAgICAgICAgICBdCiAgICAgICAgfQogICAgICB9KSwKICAgICAgTkM6IHN0YXRlKCJOb3J0aCBDYXJvbGluYSIsICJOQyIpLCBORDogc3RhdGUoIk5vcnRoIERha290YSIsICJORCIpLCBPSDogc3RhdGUoIk9oaW8iLCAiT0giLCB7IGxvY2FsVGF4TWF5QXBwbHk6IHRydWUgfSksCiAgICAgIE9LOiBzdGF0ZSgiT2tsYWhvbWEiLCAiT0siKSwgT1I6IHN0YXRlKCJPcmVnb24iLCAiT1IiKSwKICAgICAgUEE6IHN0YXRlKCJQZW5uc3lsdmFuaWEiLCAiUEEiLCB7CiAgICAgICAgZGVmYXVsdENhcGl0YWxHYWluc1RyZWF0bWVudDogInRheGVkX2FzX29yZGluYXJ5X2luY29tZSIsCiAgICAgICAgc3VwcG9ydGVkOiB0cnVlLAogICAgICAgIGxvY2FsVGF4TWF5QXBwbHk6IHRydWUsCiAgICAgICAgYWNjdXJhY3lTdGF0dXM6ICJzaW1wbGlmaWVkX3JlcXVpcmVzX3JldmlldyIsCiAgICAgICAgc291cmNlVHlwZTogIm9mZmljaWFsX3N0YXRlX3RheF9hZ2VuY3kiLAogICAgICAgIHNvdXJjZU5hbWU6ICJQZW5uc3lsdmFuaWEgRGVwYXJ0bWVudCBvZiBSZXZlbnVlIHBlcnNvbmFsIGluY29tZSB0YXggZ3VpZGFuY2UiLAogICAgICAgIHNvdXJjZVVybDogImh0dHBzOi8vd3d3LnBhLmdvdi9hZ2VuY2llcy9yZXZlbnVlLmh0bWwiLAogICAgICAgIGRhdGFWaW50YWdlOiAibGF0ZXN0IGF2YWlsYWJsZSBQZW5uc3lsdmFuaWEgZmxhdCBQSVQgcmF0ZSBhc3N1bXB0aW9uIiwKICAgICAgICBub3RlczogIlNpbXBsaWZpZWQgUGVubnN5bHZhbmlhIGZsYXQgcGVyc29uYWwgaW5jb21lIHRheCBlc3RpbWF0ZS4gUEEgbG9jYWwgdGF4ZXMgYXJlIG5vdCBpbmNsdWRlZC4iLAogICAgICAgIGZsYXRSYXRlOiAwLjAzMDcKICAgICAgfSksCiAgICAgIFJJOiBzdGF0ZSgiUmhvZGUgSXNsYW5kIiwgIlJJIiksIFNDOiBzdGF0ZSgiU291dGggQ2Fyb2xpbmEiLCAiU0MiKSwKICAgICAgU0Q6IG5vQnJvYWRJbmNvbWVUYXgoIlNvdXRoIERha290YSIsICJTRCIsICJodHRwczovL2Rvci5zZC5nb3YvIiksCiAgICAgIFROOiBub0Jyb2FkSW5jb21lVGF4KCJUZW5uZXNzZWUiLCAiVE4iLCAiaHR0cHM6Ly93d3cudG4uZ292L3JldmVudWUuaHRtbCIpLAogICAgICBUWDogbm9Ccm9hZEluY29tZVRheCgiVGV4YXMiLCAiVFgiLCAiaHR0cHM6Ly9jb21wdHJvbGxlci50ZXhhcy5nb3YvdGF4ZXMvIiksCiAgICAgIFVUOiBzdGF0ZSgiVXRhaCIsICJVVCIpLCBWVDogc3RhdGUoIlZlcm1vbnQiLCAiVlQiKSwgVkE6IHN0YXRlKCJWaXJnaW5pYSIsICJWQSIpLAogICAgICBXQTogc3RhdGUoIldhc2hpbmd0b24iLCAiV0EiLCB7CiAgICAgICAgYnJvYWRJbmRpdmlkdWFsSW5jb21lVGF4OiBmYWxzZSwKICAgICAgICBkZWZhdWx0Q2FwaXRhbEdhaW5zVHJlYXRtZW50OiAicHJlZmVyZW50aWFsX29yX3NwZWNpYWxfcnVsZXMiLAogICAgICAgIHN1cHBvcnRlZDogZmFsc2UsCiAgICAgICAgYWNjdXJhY3lTdGF0dXM6ICJub3RfaW1wbGVtZW50ZWQiLAogICAgICAgIHNvdXJjZVR5cGU6ICJvZmZpY2lhbF9zdGF0ZV90YXhfYWdlbmN5IiwKICAgICAgICBzb3VyY2VOYW1lOiAiV2FzaGluZ3RvbiBEZXBhcnRtZW50IG9mIFJldmVudWUgY2FwaXRhbCBnYWlucyB0YXggZ3VpZGFuY2UiLAogICAgICAgIHNvdXJjZVVybDogImh0dHBzOi8vZG9yLndhLmdvdi90YXhlcy1yYXRlcy9vdGhlci10YXhlcy9jYXBpdGFsLWdhaW5zLXRheCIsCiAgICAgICAgbm90ZXM6ICJXYXNoaW5ndG9uIGhhcyBhIHNlcGFyYXRlIGNhcGl0YWwgZ2FpbnMgdGF4IHJlZ2ltZS4gVmVyc2lvbiAxIGRvZXMgbm90IGVzdGltYXRlIGl0LiIKICAgICAgfSksCiAgICAgIFdWOiBzdGF0ZSgiV2VzdCBWaXJnaW5pYSIsICJXViIpLCBXSTogc3RhdGUoIldpc2NvbnNpbiIsICJXSSIpLAogICAgICBXWTogbm9Ccm9hZEluY29tZVRheCgiV3lvbWluZyIsICJXWSIsICJodHRwczovL3JldmVudWUud3lvLmdvdi8iKQogICAgfQogIH07Cn0pKCk7CgoKKGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7CgogIHdpbmRvdy5JVEJMb2NhbFRheERhdGEgPSB7CiAgICBqdXJpc2RpY3Rpb25zOiB7CiAgICAgIE5ZQzogewogICAgICAgIGp1cmlzZGljdGlvbjogIk5ldyBZb3JrIENpdHkiLAogICAgICAgIHRheFllYXI6IDIwMjYsCiAgICAgICAgZGF0YVZpbnRhZ2U6ICJMYXRlc3QgYXZhaWxhYmxlIE5ZQyByZXNpZGVudCBpbmNvbWUgdGF4IHJhdGUgYXNzdW1wdGlvbnMiLAogICAgICAgIGxhc3RVcGRhdGVkOiAiMjAyNi0wNC0yNyIsCiAgICAgICAgc291cmNlTmFtZTogIk5ldyBZb3JrIFN0YXRlIHBlcnNvbmFsIGluY29tZSB0YXggZm9ybXMgYW5kIGNpdHkgcmVzaWRlbnQgdGF4IGluc3RydWN0aW9ucyIsCiAgICAgICAgc291cmNlVXJsOiAiaHR0cHM6Ly93d3cudGF4Lm55Lmdvdi9mb3Jtcy9jdXJyZW50LWZvcm1zL2l0L2l0MjAxaS5odG0iLAogICAgICAgIHNvdXJjZVR5cGU6ICJvZmZpY2lhbF9jaXR5X3RheF9hZ2VuY3kiLAogICAgICAgIHJldHJpZXZlZERhdGU6ICIyMDI2LTA0LTI3IiwKICAgICAgICB2ZXJpZmllZEJ5OiAicmVxdWlyZXNfaHVtYW5fcmV2aWV3IiwKICAgICAgICBhY2N1cmFjeVN0YXR1czogInNpbXBsaWZpZWRfcmVxdWlyZXNfcmV2aWV3IiwKICAgICAgICBub3RlczogIlNpbXBsaWZpZWQgTllDIHJlc2lkZW50IHRheCBpbXBhY3QgZXN0aW1hdGUuIEFwcGxpZXMgb25seSB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgTmV3IFlvcmsgYW5kIE5ZQyByZXNpZGVudC4iLAogICAgICAgIHN1cHBvcnRlZDogdHJ1ZSwKICAgICAgICBicmFja2V0czogewogICAgICAgICAgc2luZ2xlOiBbCiAgICAgICAgICAgIHsgdXBUbzogMTIwMDAsIHJhdGU6IDAuMDMwNzggfSwKICAgICAgICAgICAgeyB1cFRvOiAyNTAwMCwgcmF0ZTogMC4wMzc2MiB9LAogICAgICAgICAgICB7IHVwVG86IDUwMDAwLCByYXRlOiAwLjAzODE5IH0sCiAgICAgICAgICAgIHsgdXBUbzogbnVsbCwgcmF0ZTogMC4wMzg3NiB9CiAgICAgICAgICBdLAogICAgICAgICAgbWFycmllZF9maWxpbmdfam9pbnRseTogWwogICAgICAgICAgICB7IHVwVG86IDIxNjAwLCByYXRlOiAwLjAzMDc4IH0sCiAgICAgICAgICAgIHsgdXBUbzogNDUwMDAsIHJhdGU6IDAuMDM3NjIgfSwKICAgICAgICAgICAgeyB1cFRvOiA5MDAwMCwgcmF0ZTogMC4wMzgxOSB9LAogICAgICAgICAgICB7IHVwVG86IG51bGwsIHJhdGU6IDAuMDM4NzYgfQogICAgICAgICAgXSwKICAgICAgICAgIG1hcnJpZWRfZmlsaW5nX3NlcGFyYXRlbHk6IFsKICAgICAgICAgICAgeyB1cFRvOiAxMjAwMCwgcmF0ZTogMC4wMzA3OCB9LAogICAgICAgICAgICB7IHVwVG86IDI1MDAwLCByYXRlOiAwLjAzNzYyIH0sCiAgICAgICAgICAgIHsgdXBUbzogNTAwMDAsIHJhdGU6IDAuMDM4MTkgfSwKICAgICAgICAgICAgeyB1cFRvOiBudWxsLCByYXRlOiAwLjAzODc2IH0KICAgICAgICAgIF0sCiAgICAgICAgICBoZWFkX29mX2hvdXNlaG9sZDogWwogICAgICAgICAgICB7IHVwVG86IDE0NDAwLCByYXRlOiAwLjAzMDc4IH0sCiAgICAgICAgICAgIHsgdXBUbzogMzAwMDAsIHJhdGU6IDAuMDM3NjIgfSwKICAgICAgICAgICAgeyB1cFRvOiA2MDAwMCwgcmF0ZTogMC4wMzgxOSB9LAogICAgICAgICAgICB7IHVwVG86IG51bGwsIHJhdGU6IDAuMDM4NzYgfQogICAgICAgICAgXQogICAgICAgIH0KICAgICAgfQogICAgfQogIH07Cn0pKCk7CgoKKGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7CgogIHdpbmRvdy5JVEJDYXBpdGFsR2FpbnNEYXRhU291cmNlcyA9IHsKICAgIGxhc3RVcGRhdGVkOiAiMjAyNi0wNC0yNyIsCiAgICBub3RlczogWwogICAgICAiRmVkZXJhbCAyMDI2IG9yZGluYXJ5IGluY29tZSBhbmQgbG9uZy10ZXJtIGNhcGl0YWwgZ2FpbnMgdGhyZXNob2xkcyBhcmUgc291cmNlZCBmcm9tIElSUyBSZXYuIFByb2MuIDIwMjUtMzIuIiwKICAgICAgIk5JSVQgZGF0YSBpcyBzb3VyY2VkIGZyb20gSVJTIE5ldCBJbnZlc3RtZW50IEluY29tZSBUYXggZ3VpZGFuY2UuIiwKICAgICAgIlN0YXRlIGFuZCBsb2NhbCBlbnRyaWVzIHJlbWFpbiBtYXJrZWQgcmVxdWlyZXNfaHVtYW5fcmV2aWV3IGV2ZW4gd2hlbiBhIHNpbXBsaWZpZWQgY2FsY3VsYXRpb24gaXMgcHJlc2VudC4iCiAgICBdCiAgfTsKfSkoKTsKCgooZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgY29uc3QgREFUQSA9IHsKICAgIGx0Y2c6IHdpbmRvdy5JVEJDYXBpdGFsR2FpbnNGZWRlcmFsTFRDRzIwMjYsCiAgICBvcmRpbmFyeTogd2luZG93LklUQkZlZGVyYWxPcmRpbmFyeUluY29tZTIwMjYsCiAgICBuaWl0OiB3aW5kb3cuSVRCRmVkZXJhbE5JSVREYXRhLAogICAgc3RhdGVzOiB3aW5kb3cuSVRCU3RhdGVDYXBpdGFsR2FpbnNEYXRhLAogICAgbG9jYWw6IHdpbmRvdy5JVEJMb2NhbFRheERhdGEKICB9OwoKICBjb25zdCBGSUxJTkdfTEFCRUxTID0gewogICAgc2luZ2xlOiAiU2luZ2xlIiwKICAgIG1hcnJpZWRfZmlsaW5nX2pvaW50bHk6ICJNYXJyaWVkIEZpbGluZyBKb2ludGx5IiwKICAgIG1hcnJpZWRfZmlsaW5nX3NlcGFyYXRlbHk6ICJNYXJyaWVkIEZpbGluZyBTZXBhcmF0ZWx5IiwKICAgIGhlYWRfb2ZfaG91c2Vob2xkOiAiSGVhZCBvZiBIb3VzZWhvbGQiCiAgfTsKCiAgY29uc3QgQVNTRVRfTEFCRUxTID0gewogICAgc3RvY2s6ICJTdG9jaywgRVRGLCBvciBtdXR1YWwgZnVuZCIsCiAgICBjcnlwdG86ICJDcnlwdG8iLAogICAgcmVhbF9lc3RhdGU6ICJSZWFsIGVzdGF0ZSIsCiAgICBwcmltYXJ5X3Jlc2lkZW5jZTogIlByaW1hcnkgcmVzaWRlbmNlIiwKICAgIGNvbGxlY3RpYmxlOiAiQ29sbGVjdGlibGUiLAogICAgb3RoZXI6ICJPdGhlciBpbnZlc3RtZW50IGFzc2V0IgogIH07CgogIGNvbnN0IFJFTEFURURfVE9PTFMgPSBbCiAgICB7IGxhYmVsOiAiMjAyNiBGZWRlcmFsIEluY29tZSBUYXggQ2FsY3VsYXRvciIsIHVybDogIi93cC8yMDI2LWZlZGVyYWwtaW5jb21lLXRheC1jYWxjdWxhdG9yLyIgfSwKICAgIHsgbGFiZWw6ICIyMDI2IFF1YXJ0ZXJseSBFc3RpbWF0ZWQgVGF4IENhbGN1bGF0b3IiLCB1cmw6ICIvd3AvMjAyNi1xdWFydGVybHktZXN0aW1hdGVkLXRheC1jYWxjdWxhdG9yLyIgfSwKICAgIHsgbGFiZWw6ICI0MDEoayksIEhTQSBhbmQgUGF5cm9sbCBCZW5lZml0cyBDYWxjdWxhdG9yIiwgdXJsOiAiL3dwL3ByZXRheC1zYXZpbmdzLXRha2UtaG9tZS1wYXktY2FsY3VsYXRvci8iIH0sCiAgICB7IGxhYmVsOiAiTllDIENvbW11dGVyIFRheCBDYWxjdWxhdG9yIiwgdXJsOiAiL3dwL255Yy1jb21tdXRlci10YXgtY2FsY3VsYXRvci8iIH0sCiAgICB7IGxhYmVsOiAiTllDIFBhcnQtWWVhciBSZXNpZGVudCBUYXggQ2FsY3VsYXRvciIsIHVybDogIi93cC9ueWMtcGFydC15ZWFyLXJlc2lkZW50LXRheC1jYWxjdWxhdG9yLyIgfQogIF07CgogIGZ1bmN0aW9uIG1vbmV5KHZhbHVlKSB7CiAgICByZXR1cm4gbmV3IEludGwuTnVtYmVyRm9ybWF0KCJlbi1VUyIsIHsgc3R5bGU6ICJjdXJyZW5jeSIsIGN1cnJlbmN5OiAiVVNEIiwgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiAwIH0pLmZvcm1hdChNYXRoLnJvdW5kKHZhbHVlIHx8IDApKTsKICB9CgogIGZ1bmN0aW9uIHBlcmNlbnQodmFsdWUpIHsKICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkgcmV0dXJuICJOL0EiOwogICAgcmV0dXJuICh2YWx1ZSAqIDEwMCkudG9GaXhlZCgyKSArICIlIjsKICB9CgogIGZ1bmN0aW9uIG51bWJlcih2YWx1ZSkgewogICAgaWYgKHZhbHVlID09PSAiIiB8fCB2YWx1ZSA9PSBudWxsKSByZXR1cm4gMDsKICAgIGNvbnN0IHBhcnNlZCA9IE51bWJlcih2YWx1ZSk7CiAgICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKHBhcnNlZCkgPyBwYXJzZWQgOiAwOwogIH0KCiAgZnVuY3Rpb24gb3B0aW9uYWxOdW1iZXIodmFsdWUpIHsKICAgIGlmICh2YWx1ZSA9PT0gIiIgfHwgdmFsdWUgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICBjb25zdCBwYXJzZWQgPSBOdW1iZXIodmFsdWUpOwogICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShwYXJzZWQpID8gcGFyc2VkIDogbnVsbDsKICB9CgogIGZ1bmN0aW9uIGZpZWxkVmFsdWUoZm9ybSwgZmllbGQpIHsKICAgIGNvbnN0IGVsZW1lbnQgPSBmb3JtLnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWZpZWxkPSInICsgZmllbGQgKyAnIl0nKTsKICAgIGlmICghZWxlbWVudCkgcmV0dXJuICIiOwogICAgaWYgKGVsZW1lbnQudHlwZSA9PT0gImNoZWNrYm94IikgcmV0dXJuIGVsZW1lbnQuY2hlY2tlZCA\/ICJ5ZXMiIDogIm5vIjsKICAgIHJldHVybiBlbGVtZW50LnZhbHVlOwogIH0KCiAgZnVuY3Rpb24gZmllbGRTZXQoZm9ybSwgZmllbGQsIHZhbHVlKSB7CiAgICBjb25zdCBlbGVtZW50ID0gZm9ybS5xdWVyeVNlbGVjdG9yKCdbZGF0YS1maWVsZD0iJyArIGZpZWxkICsgJyJdJyk7CiAgICBpZiAoIWVsZW1lbnQpIHJldHVybjsKICAgIGlmIChlbGVtZW50LnR5cGUgPT09ICJjaGVja2JveCIpIGVsZW1lbnQuY2hlY2tlZCA9IHZhbHVlID09PSAieWVzIiB8fCB2YWx1ZSA9PT0gdHJ1ZTsKICAgIGVsc2UgZWxlbWVudC52YWx1ZSA9IHZhbHVlOwogIH0KCiAgZnVuY3Rpb24gbm9ybWFsaXplSW5wdXRzKHJhdykgewogICAgY29uc3QgYWRqdXN0ZWRCYXNpcyA9IG9wdGlvbmFsTnVtYmVyKHJhdy5hZGp1c3RlZEJhc2lzKTsKICAgIGNvbnN0IG1hbnVhbEhvbWVFeGNsdXNpb24gPSBvcHRpb25hbE51bWJlcihyYXcubWFudWFsSG9tZUV4Y2x1c2lvbik7CiAgICBjb25zdCBzdGF0ZUxvY2FsUmF0ZU92ZXJyaWRlID0gb3B0aW9uYWxOdW1iZXIocmF3LnN0YXRlTG9jYWxSYXRlT3ZlcnJpZGUpOwogICAgY29uc3QgbmlpdE92ZXJyaWRlID0gb3B0aW9uYWxOdW1iZXIocmF3Lm5paXRPdmVycmlkZSk7CiAgICByZXR1cm4gewogICAgICB0YXhZZWFyOiByYXcudGF4WWVhciB8fCAiMjAyNiIsCiAgICAgIGFzc2V0VHlwZTogcmF3LmFzc2V0VHlwZSB8fCAic3RvY2siLAogICAgICBwdXJjaGFzZVByaWNlOiBudW1iZXIocmF3LnB1cmNoYXNlUHJpY2UpLAogICAgICBzYWxlUHJpY2U6IG51bWJlcihyYXcuc2FsZVByaWNlKSwKICAgICAgc2VsbGluZ0V4cGVuc2VzOiBudW1iZXIocmF3LnNlbGxpbmdFeHBlbnNlcyksCiAgICAgIHB1cmNoYXNlRGF0ZTogcmF3LnB1cmNoYXNlRGF0ZSB8fCAiIiwKICAgICAgc2FsZURhdGU6IHJhdy5zYWxlRGF0ZSB8fCAiIiwKICAgICAgaG9sZGluZ1BlcmlvZE92ZXJyaWRlOiByYXcuaG9sZGluZ1BlcmlvZE92ZXJyaWRlIHx8ICIiLAogICAgICBjYXBpdGFsTG9zc2VzOiBudW1iZXIocmF3LmNhcGl0YWxMb3NzZXMpLAogICAgICBmaWxpbmdTdGF0dXM6IHJhdy5maWxpbmdTdGF0dXMgfHwgIiIsCiAgICAgIHRheGFibGVJbmNvbWVCZWZvcmVHYWluOiBudW1iZXIocmF3LnRheGFibGVJbmNvbWVCZWZvcmVHYWluKSwKICAgICAgbWFnaUJlZm9yZUdhaW46IG9wdGlvbmFsTnVtYmVyKHJhdy5tYWdpQmVmb3JlR2FpbiksCiAgICAgIHN0YXRlT2ZSZXNpZGVuY2U6IHJhdy5zdGF0ZU9mUmVzaWRlbmNlIHx8ICIiLAogICAgICBpc05ZQ1Jlc2lkZW50OiByYXcuc3RhdGVPZlJlc2lkZW5jZSA9PT0gIk5ZIiA\/IHJhdy5pc05ZQ1Jlc2lkZW50ID09PSAieWVzIiB8fCByYXcuaXNOWUNSZXNpZGVudCA9PT0gdHJ1ZSA6IGZhbHNlLAogICAgICBhZGp1c3RlZEJhc2lzLAogICAgICBkZXByZWNpYXRpb25SZWNhcHR1cmU6IG51bWJlcihyYXcuZGVwcmVjaWF0aW9uUmVjYXB0dXJlKSwKICAgICAgc3RhdGVMb2NhbFJhdGVPdmVycmlkZSwKICAgICAgbmlpdE92ZXJyaWRlLAogICAgICBob21lT3duZWRUd29ZZWFyczogcmF3LmhvbWVPd25lZFR3b1llYXJzIHx8IHJhdy5ob21lT3duZWRVc2VkVHdvWWVhcnMgfHwgInllcyIsCiAgICAgIGhvbWVVc2VkVHdvWWVhcnM6IHJhdy5ob21lVXNlZFR3b1llYXJzIHx8IHJhdy5ob21lT3duZWRVc2VkVHdvWWVhcnMgfHwgInllcyIsCiAgICAgIGhvbWVFeGNsdXNpb25Vc2VkUmVjZW50bHk6IHJhdy5ob21lRXhjbHVzaW9uVXNlZFJlY2VudGx5IHx8ICJubyIsCiAgICAgIG1hbnVhbEhvbWVFeGNsdXNpb24KICAgIH07CiAgfQoKICBmdW5jdGlvbiBjb2xsZWN0SW5wdXQoZm9ybSkgewogICAgY29uc3QgcmF3ID0ge307CiAgICBmb3JtLnF1ZXJ5U2VsZWN0b3JBbGwoIltkYXRhLWZpZWxkXSIpLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHsKICAgICAgcmF3W2VsZW1lbnQuZ2V0QXR0cmlidXRlKCJkYXRhLWZpZWxkIildID0gZWxlbWVudC50eXBlID09PSAiY2hlY2tib3giID8gKGVsZW1lbnQuY2hlY2tlZCA\/ICJ5ZXMiIDogIm5vIikgOiBlbGVtZW50LnZhbHVlOwogICAgfSk7CiAgICByZXR1cm4gbm9ybWFsaXplSW5wdXRzKHJhdyk7CiAgfQoKICBmdW5jdGlvbiB2YWxpZGF0ZUlucHV0cyhpbnB1dCkgewogICAgY29uc3QgZXJyb3JzID0gW107CiAgICBpZiAoIWlucHV0LmZpbGluZ1N0YXR1cykgZXJyb3JzLnB1c2goIkNob29zZSBhIGZpbGluZyBzdGF0dXMgdG8gY2FsY3VsYXRlIGFuIGVzdGltYXRlLiIpOwogICAgaWYgKCFpbnB1dC5zdGF0ZU9mUmVzaWRlbmNlKSBlcnJvcnMucHVzaCgiQ2hvb3NlIGEgc3RhdGUgb2YgcmVzaWRlbmNlIHRvIGNhbGN1bGF0ZSBhbiBlc3RpbWF0ZS4iKTsKICAgIGlmICghaW5wdXQucHVyY2hhc2VQcmljZSAmJiBpbnB1dC5hZGp1c3RlZEJhc2lzID09IG51bGwpIGVycm9ycy5wdXNoKCJFbnRlciB5b3VyIHB1cmNoYXNlIHByaWNlIG9yIGNvc3QgYmFzaXMgdG8gY2FsY3VsYXRlIGFuIGVzdGltYXRlLiIpOwogICAgaWYgKCFpbnB1dC5zYWxlUHJpY2UpIGVycm9ycy5wdXNoKCJFbnRlciB5b3VyIHNhbGUgcHJpY2UgdG8gY2FsY3VsYXRlIGFuIGVzdGltYXRlLiIpOwogICAgY29uc3QgY2hlY2tzID0gWwogICAgICBbIlB1cmNoYXNlIHByaWNlIG9yIGJhc2lzIiwgaW5wdXQucHVyY2hhc2VQcmljZV0sCiAgICAgIFsiU2FsZSBwcmljZSIsIGlucHV0LnNhbGVQcmljZV0sCiAgICAgIFsiU2VsbGluZyBleHBlbnNlcyIsIGlucHV0LnNlbGxpbmdFeHBlbnNlc10sCiAgICAgIFsiQ2FwaXRhbCBsb3NzZXMiLCBpbnB1dC5jYXBpdGFsTG9zc2VzXSwKICAgICAgWyJUYXhhYmxlIGluY29tZSBiZWZvcmUgdGhpcyBnYWluIiwgaW5wdXQudGF4YWJsZUluY29tZUJlZm9yZUdhaW5dLAogICAgICBbIkRlcHJlY2lhdGlvbiByZWNhcHR1cmUiLCBpbnB1dC5kZXByZWNpYXRpb25SZWNhcHR1cmVdCiAgICBdOwogICAgY2hlY2tzLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgaWYgKGl0ZW1bMV0gPCAwKSBlcnJvcnMucHVzaChpdGVtWzBdICsgIiBjYW5ub3QgYmUgbmVnYXRpdmUuIik7CiAgICB9KTsKICAgIGlmIChpbnB1dC5hZGp1c3RlZEJhc2lzICE9IG51bGwgJiYgaW5wdXQuYWRqdXN0ZWRCYXNpcyA8IDApIGVycm9ycy5wdXNoKCJBZGp1c3RlZCBiYXNpcyBjYW5ub3QgYmUgbmVnYXRpdmUuIik7CiAgICBpZiAoaW5wdXQuc3RhdGVMb2NhbFJhdGVPdmVycmlkZSAhPSBudWxsICYmIGlucHV0LnN0YXRlTG9jYWxSYXRlT3ZlcnJpZGUgPCAwKSBlcnJvcnMucHVzaCgiT3ZlcnJpZGUgc3RhdGUvbG9jYWwgdGF4IHJhdGUgZm9yIHRoaXMgZ2FpbiBjYW5ub3QgYmUgbmVnYXRpdmUuIik7CiAgICBpZiAoaW5wdXQuc3RhdGVMb2NhbFJhdGVPdmVycmlkZSAhPSBudWxsICYmIGlucHV0LnN0YXRlTG9jYWxSYXRlT3ZlcnJpZGUgPiAxMDApIGVycm9ycy5wdXNoKCJPdmVycmlkZSBzdGF0ZS9sb2NhbCB0YXggcmF0ZSBmb3IgdGhpcyBnYWluIGNhbm5vdCBiZSBhYm92ZSAxMDAlLiIpOwogICAgaWYgKGlucHV0Lm5paXRPdmVycmlkZSAhPSBudWxsICYmIGlucHV0Lm5paXRPdmVycmlkZSA8IDApIGVycm9ycy5wdXNoKCJOSUlUIG92ZXJyaWRlIGNhbm5vdCBiZSBuZWdhdGl2ZS4iKTsKICAgIGlmICghaW5wdXQuaG9sZGluZ1BlcmlvZE92ZXJyaWRlKSB7CiAgICAgIGlmICghaW5wdXQucHVyY2hhc2VEYXRlIHx8ICFpbnB1dC5zYWxlRGF0ZSkgZXJyb3JzLnB1c2goIkVudGVyIHB1cmNoYXNlIGFuZCBzYWxlIGRhdGVzLCBvciBjaG9vc2Ugd2hldGhlciB0aGUgZ2FpbiBpcyBzaG9ydC10ZXJtIG9yIGxvbmctdGVybS4iKTsKICAgICAgY29uc3QgcHVyY2hhc2UgPSBEYXRlLnBhcnNlKGlucHV0LnB1cmNoYXNlRGF0ZSk7CiAgICAgIGNvbnN0IHNhbGUgPSBEYXRlLnBhcnNlKGlucHV0LnNhbGVEYXRlKTsKICAgICAgaWYgKGlucHV0LnB1cmNoYXNlRGF0ZSAmJiBpbnB1dC5zYWxlRGF0ZSkgewogICAgICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHB1cmNoYXNlKSB8fCAhTnVtYmVyLmlzRmluaXRlKHNhbGUpKSBlcnJvcnMucHVzaCgiRW50ZXIgdmFsaWQgcHVyY2hhc2UgYW5kIHNhbGUgZGF0ZXMuIik7CiAgICAgICAgZWxzZSBpZiAoc2FsZSA8IHB1cmNoYXNlKSBlcnJvcnMucHVzaCgiU2FsZSBkYXRlIGNhbm5vdCBiZSBiZWZvcmUgcHVyY2hhc2UgZGF0ZS4iKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGVycm9yczsKICB9CgogIGZ1bmN0aW9uIGRldGVybWluZUhvbGRpbmdQZXJpb2QoaW5wdXQpIHsKICAgIGlmIChpbnB1dC5ob2xkaW5nUGVyaW9kT3ZlcnJpZGUgPT09ICJsb25nX3Rlcm0iKSByZXR1cm4geyBob2xkaW5nUGVyaW9kOiAiTG9uZy10ZXJtIiwgaXNMb25nVGVybTogdHJ1ZSwgZGF5c0hlbGQ6IG51bGwsIG92ZXJyaWRkZW46IHRydWUgfTsKICAgIGlmIChpbnB1dC5ob2xkaW5nUGVyaW9kT3ZlcnJpZGUgPT09ICJzaG9ydF90ZXJtIikgcmV0dXJuIHsgaG9sZGluZ1BlcmlvZDogIlNob3J0LXRlcm0iLCBpc0xvbmdUZXJtOiBmYWxzZSwgZGF5c0hlbGQ6IG51bGwsIG92ZXJyaWRkZW46IHRydWUgfTsKICAgIGNvbnN0IHB1cmNoYXNlID0gRGF0ZS5wYXJzZShpbnB1dC5wdXJjaGFzZURhdGUpOwogICAgY29uc3Qgc2FsZSA9IERhdGUucGFyc2UoaW5wdXQuc2FsZURhdGUpOwogICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocHVyY2hhc2UpIHx8ICFOdW1iZXIuaXNGaW5pdGUoc2FsZSkpIHJldHVybiB7IGhvbGRpbmdQZXJpb2Q6ICJVbmtub3duIiwgaXNMb25nVGVybTogZmFsc2UsIGRheXNIZWxkOiBudWxsLCBvdmVycmlkZGVuOiBmYWxzZSB9OwogICAgY29uc3QgZGF5c0hlbGQgPSBNYXRoLmZsb29yKChzYWxlIC0gcHVyY2hhc2UpIC8gODY0MDAwMDApOwogICAgY29uc3QgYW5uaXZlcnNhcnkgPSBuZXcgRGF0ZShwdXJjaGFzZSk7CiAgICBhbm5pdmVyc2FyeS5zZXRGdWxsWWVhcihhbm5pdmVyc2FyeS5nZXRGdWxsWWVhcigpICsgMSk7CiAgICBjb25zdCBpc0xvbmdUZXJtID0gc2FsZSA+IGFubml2ZXJzYXJ5LmdldFRpbWUoKTsKICAgIGNvbnN0IGRheXNGcm9tT25lWWVhciA9IE1hdGgucm91bmQoKHNhbGUgLSBhbm5pdmVyc2FyeS5nZXRUaW1lKCkpIC8gODY0MDAwMDApOwogICAgcmV0dXJuIHsgaG9sZGluZ1BlcmlvZDogaXNMb25nVGVybSA\/ICJMb25nLXRlcm0iIDogIlNob3J0LXRlcm0iLCBpc0xvbmdUZXJtLCBkYXlzSGVsZCwgZGF5c0Zyb21PbmVZZWFyLCBvdmVycmlkZGVuOiBmYWxzZSB9OwogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlR3Jvc3NHYWluKGlucHV0KSB7CiAgICByZXR1cm4gaW5wdXQuc2FsZVByaWNlIC0gaW5wdXQucHVyY2hhc2VQcmljZTsKICB9CgogIGZ1bmN0aW9uIGFwcGFyZW50SG9tZUV4Y2x1c2lvbihpbnB1dCwgbmV0R2FpbikgewogICAgaWYgKGlucHV0LmFzc2V0VHlwZSAhPT0gInByaW1hcnlfcmVzaWRlbmNlIikgcmV0dXJuIHsgYW1vdW50OiAwLCBhcHBsaWVkOiBmYWxzZSwgd2FybmluZzogIiIgfTsKICAgIGNvbnN0IG1heEV4Y2x1c2lvbiA9IGlucHV0LmZpbGluZ1N0YXR1cyA9PT0gIm1hcnJpZWRfZmlsaW5nX2pvaW50bHkiID8gNTAwMDAwIDogMjUwMDAwOwogICAgaWYgKGlucHV0Lm1hbnVhbEhvbWVFeGNsdXNpb24gIT0gbnVsbCkgewogICAgICByZXR1cm4geyBhbW91bnQ6IE1hdGgubWluKG5ldEdhaW4sIGlucHV0Lm1hbnVhbEhvbWVFeGNsdXNpb24pLCBhcHBsaWVkOiBpbnB1dC5tYW51YWxIb21lRXhjbHVzaW9uID4gMCwgd2FybmluZzogIlByaW1hcnkgcmVzaWRlbmNlIGV4Y2x1c2lvbiB3YXMgbWFudWFsbHkgZW50ZXJlZCBhbmQgaXMgdHJlYXRlZCBhcyBzaW1wbGlmaWVkLiIgfTsKICAgIH0KICAgIGlmIChpbnB1dC5ob21lT3duZWRUd29ZZWFycyA9PT0gInllcyIgJiYgaW5wdXQuaG9tZVVzZWRUd29ZZWFycyA9PT0gInllcyIgJiYgaW5wdXQuaG9tZUV4Y2x1c2lvblVzZWRSZWNlbnRseSA9PT0gIm5vIikgewogICAgICByZXR1cm4geyBhbW91bnQ6IE1hdGgubWluKG5ldEdhaW4sIG1heEV4Y2x1c2lvbiksIGFwcGxpZWQ6IHRydWUsIHdhcm5pbmc6ICJTaW1wbGlmaWVkIFNlY3Rpb24gMTIxIGhvbWUgc2FsZSBleGNsdXNpb24gYXBwbGllZC4gQ29uZmlybSBmdWxsIGVsaWdpYmlsaXR5IGJlZm9yZSByZWx5aW5nIG9uIHRoZSByZXN1bHQuIiB9OwogICAgfQogICAgcmV0dXJuIHsgYW1vdW50OiAwLCBhcHBsaWVkOiBmYWxzZSwgd2FybmluZzogIlRoZSBob21lIHNhbGUgZXhjbHVzaW9uIGhhcyBvd25lcnNoaXAsIHVzZSwgYW5kIHRpbWluZyBydWxlcy4gQmVjYXVzZSBlbGlnaWJpbGl0eSB3YXMgbm90IGNsZWFybHkgY29uZmlybWVkLCB0aGlzIGNhbGN1bGF0b3IgZGlkIG5vdCBhdXRvbWF0aWNhbGx5IGFwcGx5IHRoZSBleGNsdXNpb24uIiB9OwogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlVGF4YWJsZUdhaW4oaW5wdXQpIHsKICAgIGNvbnN0IGJhc2lzID0gaW5wdXQuYWRqdXN0ZWRCYXNpcyAhPSBudWxsID8gaW5wdXQuYWRqdXN0ZWRCYXNpcyA6IGlucHV0LnB1cmNoYXNlUHJpY2U7CiAgICBjb25zdCBncm9zc0dhaW4gPSBpbnB1dC5zYWxlUHJpY2UgLSBpbnB1dC5wdXJjaGFzZVByaWNlOwogICAgY29uc3QgbmV0R2FpbkJlZm9yZUV4Y2x1c2lvbiA9IGlucHV0LnNhbGVQcmljZSAtIGlucHV0LnNlbGxpbmdFeHBlbnNlcyAtIGJhc2lzOwogICAgY29uc3QgaG9tZUV4Y2x1c2lvbiA9IGFwcGFyZW50SG9tZUV4Y2x1c2lvbihpbnB1dCwgTWF0aC5tYXgoMCwgbmV0R2FpbkJlZm9yZUV4Y2x1c2lvbikpOwogICAgY29uc3QgYWZ0ZXJFeGNsdXNpb24gPSBNYXRoLm1heCgwLCBuZXRHYWluQmVmb3JlRXhjbHVzaW9uIC0gaG9tZUV4Y2x1c2lvbi5hbW91bnQpOwogICAgY29uc3QgY2FwaXRhbExvc3Nlc0FwcGxpZWQgPSBNYXRoLm1pbihhZnRlckV4Y2x1c2lvbiwgaW5wdXQuY2FwaXRhbExvc3Nlcyk7CiAgICBjb25zdCB0YXhhYmxlR2FpbiA9IE1hdGgubWF4KDAsIGFmdGVyRXhjbHVzaW9uIC0gY2FwaXRhbExvc3Nlc0FwcGxpZWQpOwogICAgcmV0dXJuIHsgYmFzaXMsIGdyb3NzR2FpbiwgbmV0R2FpbjogbmV0R2FpbkJlZm9yZUV4Y2x1c2lvbiwgaG9tZUV4Y2x1c2lvbiwgY2FwaXRhbExvc3Nlc0FwcGxpZWQsIHRheGFibGVHYWluIH07CiAgfQoKICBmdW5jdGlvbiB0YXhGcm9tQnJhY2tldHMoaW5jb21lLCBicmFja2V0cykgewogICAgaWYgKGluY29tZSA8PSAwKSByZXR1cm4gMDsKICAgIGxldCBwcmV2aW91cyA9IDA7CiAgICBsZXQgdGF4ID0gMDsKICAgIGZvciAoY29uc3QgYnJhY2tldCBvZiBicmFja2V0cykgewogICAgICBjb25zdCB0b3AgPSBicmFja2V0LnVwVG8gPT0gbnVsbCA\/IEluZmluaXR5IDogYnJhY2tldC51cFRvOwogICAgICBjb25zdCBzbGljZSA9IE1hdGgubWF4KDAsIE1hdGgubWluKGluY29tZSwgdG9wKSAtIHByZXZpb3VzKTsKICAgICAgdGF4ICs9IHNsaWNlICogYnJhY2tldC5yYXRlOwogICAgICBpZiAoaW5jb21lIDw9IHRvcCkgYnJlYWs7CiAgICAgIHByZXZpb3VzID0gdG9wOwogICAgfQogICAgcmV0dXJuIHRheDsKICB9CgogIGZ1bmN0aW9uIHRheEZyb21CYXNlQnJhY2tldHMoaW5jb21lLCBicmFja2V0cykgewogICAgaWYgKGluY29tZSA8PSAwKSByZXR1cm4gMDsKICAgIGZvciAoY29uc3QgYnJhY2tldCBvZiBicmFja2V0cykgewogICAgICBjb25zdCB0b3AgPSBicmFja2V0LnVwVG8gPT0gbnVsbCA\/IEluZmluaXR5IDogYnJhY2tldC51cFRvOwogICAgICBpZiAoaW5jb21lIDw9IHRvcCkgcmV0dXJuIGJyYWNrZXQuYmFzZVRheCArIChpbmNvbWUgLSBicmFja2V0Lm92ZXIpICogYnJhY2tldC5yYXRlOwogICAgfQogICAgcmV0dXJuIDA7CiAgfQoKICBmdW5jdGlvbiBpbmNyZW1lbnRhbE9yZGluYXJ5VGF4KGJlZm9yZUluY29tZSwgYWRkZWRJbmNvbWUsIGJyYWNrZXRzKSB7CiAgICByZXR1cm4gTWF0aC5tYXgoMCwgdGF4RnJvbUJhc2VCcmFja2V0cyhiZWZvcmVJbmNvbWUgKyBhZGRlZEluY29tZSwgYnJhY2tldHMpIC0gdGF4RnJvbUJhc2VCcmFja2V0cyhiZWZvcmVJbmNvbWUsIGJyYWNrZXRzKSk7CiAgfQoKICBmdW5jdGlvbiBjYWxjdWxhdGVMb25nVGVybUZlZGVyYWxDYXBpdGFsR2FpbnNUYXgoaW5wdXQsIHRheGFibGVHYWluKSB7CiAgICBjb25zdCB0aHJlc2hvbGRzID0gREFUQS5sdGNnLnRocmVzaG9sZHNbaW5wdXQuZmlsaW5nU3RhdHVzXTsKICAgIGxldCByZW1haW5pbmcgPSB0YXhhYmxlR2FpbjsKICAgIGxldCB0YXggPSAwOwogICAgY29uc3QgemVyb1Jvb20gPSBNYXRoLm1heCgwLCB0aHJlc2hvbGRzLm1heGltdW1aZXJvUmF0ZUFtb3VudCAtIGlucHV0LnRheGFibGVJbmNvbWVCZWZvcmVHYWluKTsKICAgIGNvbnN0IHplcm9TbGljZSA9IE1hdGgubWluKHJlbWFpbmluZywgemVyb1Jvb20pOwogICAgcmVtYWluaW5nIC09IHplcm9TbGljZTsKICAgIGNvbnN0IGluY29tZUFmdGVyWmVybyA9IGlucHV0LnRheGFibGVJbmNvbWVCZWZvcmVHYWluICsgemVyb1NsaWNlOwogICAgY29uc3QgZmlmdGVlblJvb20gPSBNYXRoLm1heCgwLCB0aHJlc2hvbGRzLm1heGltdW0xNVJhdGVBbW91bnQgLSBpbmNvbWVBZnRlclplcm8pOwogICAgY29uc3QgZmlmdGVlblNsaWNlID0gTWF0aC5taW4ocmVtYWluaW5nLCBmaWZ0ZWVuUm9vbSk7CiAgICB0YXggKz0gZmlmdGVlblNsaWNlICogMC4xNTsKICAgIHJlbWFpbmluZyAtPSBmaWZ0ZWVuU2xpY2U7CiAgICB0YXggKz0gcmVtYWluaW5nICogMC4yMDsKICAgIHJldHVybiB7IHRheEFtb3VudDogdGF4LCB6ZXJvU2xpY2UsIGZpZnRlZW5TbGljZSwgdHdlbnR5U2xpY2U6IHJlbWFpbmluZyB9OwogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlU2hvcnRUZXJtRmVkZXJhbFRheEltcGFjdChpbnB1dCwgdGF4YWJsZUdhaW4pIHsKICAgIHJldHVybiBpbmNyZW1lbnRhbE9yZGluYXJ5VGF4KGlucHV0LnRheGFibGVJbmNvbWVCZWZvcmVHYWluLCB0YXhhYmxlR2FpbiwgREFUQS5vcmRpbmFyeS5icmFja2V0c1tpbnB1dC5maWxpbmdTdGF0dXNdKTsKICB9CgogIGZ1bmN0aW9uIGNhbGN1bGF0ZU5JSVQoaW5wdXQsIHRheGFibGVHYWluKSB7CiAgICBpZiAoaW5wdXQubmlpdE92ZXJyaWRlICE9IG51bGwpIHJldHVybiB7IGFtb3VudDogaW5wdXQubmlpdE92ZXJyaWRlLCBtYWdpRXN0aW1hdGVkOiBmYWxzZSwgb3ZlcnJpZGRlbjogdHJ1ZSB9OwogICAgY29uc3QgbWFnaUJlZm9yZSA9IGlucHV0Lm1hZ2lCZWZvcmVHYWluID09IG51bGwgPyBpbnB1dC50YXhhYmxlSW5jb21lQmVmb3JlR2FpbiA6IGlucHV0Lm1hZ2lCZWZvcmVHYWluOwogICAgY29uc3QgbWFnaUFmdGVyID0gbWFnaUJlZm9yZSArIHRheGFibGVHYWluOwogICAgY29uc3QgdGhyZXNob2xkID0gREFUQS5uaWl0LnRocmVzaG9sZHNbaW5wdXQuZmlsaW5nU3RhdHVzXTsKICAgIGNvbnN0IGV4Y2VzcyA9IE1hdGgubWF4KDAsIG1hZ2lBZnRlciAtIHRocmVzaG9sZCk7CiAgICByZXR1cm4geyBhbW91bnQ6IE1hdGgubWluKHRheGFibGVHYWluLCBleGNlc3MpICogREFUQS5uaWl0LnJhdGUsIG1hZ2lFc3RpbWF0ZWQ6IGlucHV0Lm1hZ2lCZWZvcmVHYWluID09IG51bGwsIG92ZXJyaWRkZW46IGZhbHNlIH07CiAgfQoKICBmdW5jdGlvbiBjYWxjdWxhdGVTdGF0ZUluY3JlbWVudChpbnB1dCwgdGF4YWJsZUdhaW4sIHN0YXRlRGF0YSkgewogICAgY29uc3QgYmVmb3JlID0gTWF0aC5tYXgoMCwgaW5wdXQudGF4YWJsZUluY29tZUJlZm9yZUdhaW4gLSAoc3RhdGVEYXRhLnN0YW5kYXJkRGVkdWN0aW9uID8gc3RhdGVEYXRhLnN0YW5kYXJkRGVkdWN0aW9uW2lucHV0LmZpbGluZ1N0YXR1c10gfHwgMCA6IDApKTsKICAgIGlmIChzdGF0ZURhdGEuZmxhdFJhdGUgIT0gbnVsbCkgcmV0dXJuIHRheGFibGVHYWluICogc3RhdGVEYXRhLmZsYXRSYXRlOwogICAgaWYgKHN0YXRlRGF0YS5icmFja2V0cykgcmV0dXJuIE1hdGgubWF4KDAsIHRheEZyb21CcmFja2V0cyhiZWZvcmUgKyB0YXhhYmxlR2Fpbiwgc3RhdGVEYXRhLmJyYWNrZXRzW2lucHV0LmZpbGluZ1N0YXR1c10pIC0gdGF4RnJvbUJyYWNrZXRzKGJlZm9yZSwgc3RhdGVEYXRhLmJyYWNrZXRzW2lucHV0LmZpbGluZ1N0YXR1c10pKTsKICAgIHJldHVybiAwOwogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlU3RhdGVDYXBpdGFsR2FpbnNUYXgoaW5wdXQsIHRheGFibGVHYWluKSB7CiAgICBjb25zdCBzdGF0ZURhdGEgPSBEQVRBLnN0YXRlcy5zdGF0ZXNbaW5wdXQuc3RhdGVPZlJlc2lkZW5jZV07CiAgICBjb25zdCB3YXJuaW5ncyA9IFtdOwogICAgaWYgKCFzdGF0ZURhdGEpIHsKICAgICAgcmV0dXJuIHsgYW1vdW50OiAwLCBzdXBwb3J0ZWQ6IGZhbHNlLCBsYWJlbDogIlN0YXRlIGNhcGl0YWwgZ2FpbnMgZXN0aW1hdGUgdW5hdmFpbGFibGUiLCB3YXJuaW5nczogWyJTdGF0ZSBjYXBpdGFsIGdhaW5zIGVzdGltYXRlIGlzIG5vdCB5ZXQgYXZhaWxhYmxlIGZvciB0aGlzIHN0YXRlLiJdLCBkYXRhTm90ZTogIiIgfTsKICAgIH0KICAgIGlmIChpbnB1dC5zdGF0ZUxvY2FsUmF0ZU92ZXJyaWRlICE9IG51bGwpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBhbW91bnQ6IHRheGFibGVHYWluICogKGlucHV0LnN0YXRlTG9jYWxSYXRlT3ZlcnJpZGUgLyAxMDApLAogICAgICAgIHN1cHBvcnRlZDogdHJ1ZSwKICAgICAgICBsYWJlbDogIk92ZXJyaWRlIHN0YXRlL2xvY2FsIHRheCBvbiB0aGlzIGdhaW4iLAogICAgICAgIHdhcm5pbmdzOiBbIk92ZXJyaWRlIHN0YXRlL2xvY2FsIHRheCByYXRlIHdhcyBlbnRlcmVkLiBUaGUgY2FsY3VsYXRvciBhcHBsaWVkIHRoYXQgcGVyY2VudGFnZSB0byB0aGlzIHNhbGUncyB0YXhhYmxlIGdhaW4gaW5zdGVhZCBvZiB1c2luZyB0aGUgYnVpbHQtaW4gc3RhdGUvbG9jYWwgZXN0aW1hdGUuIEl0IHJlcGxhY2VzIHRoZSBidWlsdC1pbiBlc3RpbWF0ZSBhbmQgZG9lcyBub3QgYWRkIHRvIGl0LiJdLAogICAgICAgIGRhdGFOb3RlOiBkYXRhTm90ZSgiU3RhdGUgZGF0YSIsIHN0YXRlRGF0YSkKICAgICAgfTsKICAgIH0KICAgIGlmIChzdGF0ZURhdGEuZGVmYXVsdENhcGl0YWxHYWluc1RyZWF0bWVudCA9PT0gIm5vX2Jyb2FkX2luZGl2aWR1YWxfaW5jb21lX3RheCIgJiYgc3RhdGVEYXRhLnN1cHBvcnRlZCkgewogICAgICByZXR1cm4geyBhbW91bnQ6IDAsIHN1cHBvcnRlZDogdHJ1ZSwgbGFiZWw6ICJFc3RpbWF0ZWQgc3RhdGUgY2FwaXRhbCBnYWlucyB0YXgiLCB3YXJuaW5nczogW3N0YXRlRGF0YS5ub3Rlc10sIGRhdGFOb3RlOiBkYXRhTm90ZShzdGF0ZURhdGEubmFtZSArICIgZGF0YSIsIHN0YXRlRGF0YSkgfTsKICAgIH0KICAgIGlmICghc3RhdGVEYXRhLnN1cHBvcnRlZCkgewogICAgICByZXR1cm4geyBhbW91bnQ6IDAsIHN1cHBvcnRlZDogZmFsc2UsIGxhYmVsOiAiU3RhdGUgY2FwaXRhbCBnYWlucyBlc3RpbWF0ZSB1bmF2YWlsYWJsZSIsIHdhcm5pbmdzOiBbc3RhdGVEYXRhLm5vdGVzIHx8ICJTdGF0ZSBjYXBpdGFsIGdhaW5zIGVzdGltYXRlIGlzIG5vdCB5ZXQgYXZhaWxhYmxlIGZvciB0aGlzIHN0YXRlLiJdLCBkYXRhTm90ZTogZGF0YU5vdGUoc3RhdGVEYXRhLm5hbWUgKyAiIGRhdGEiLCBzdGF0ZURhdGEpIH07CiAgICB9CiAgICB3YXJuaW5ncy5wdXNoKHN0YXRlRGF0YS5ub3RlcyB8fCAiU3RhdGUgY2FwaXRhbCBnYWlucyBjYWxjdWxhdGlvbiBpcyBzaW1wbGlmaWVkLiIpOwogICAgcmV0dXJuIHsgYW1vdW50OiBjYWxjdWxhdGVTdGF0ZUluY3JlbWVudChpbnB1dCwgdGF4YWJsZUdhaW4sIHN0YXRlRGF0YSksIHN1cHBvcnRlZDogdHJ1ZSwgbGFiZWw6ICJFc3RpbWF0ZWQgc3RhdGUgY2FwaXRhbCBnYWlucyB0YXgiLCB3YXJuaW5ncywgZGF0YU5vdGU6IGRhdGFOb3RlKHN0YXRlRGF0YS5uYW1lICsgIiBkYXRhIiwgc3RhdGVEYXRhKSB9OwogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlTG9jYWxUYXgoaW5wdXQsIHRheGFibGVHYWluKSB7CiAgICBpZiAoaW5wdXQuc3RhdGVMb2NhbFJhdGVPdmVycmlkZSAhPSBudWxsKSByZXR1cm4geyBhbW91bnQ6IDAsIHN1cHBvcnRlZDogZmFsc2UsIHdhcm5pbmdzOiBbXSwgZGF0YU5vdGU6ICIiIH07CiAgICBpZiAoaW5wdXQuc3RhdGVPZlJlc2lkZW5jZSAhPT0gIk5ZIiB8fCAhaW5wdXQuaXNOWUNSZXNpZGVudCkgcmV0dXJuIHsgYW1vdW50OiAwLCBzdXBwb3J0ZWQ6IGZhbHNlLCB3YXJuaW5nczogW10sIGRhdGFOb3RlOiAiIiB9OwogICAgY29uc3QgbnljID0gREFUQS5sb2NhbC5qdXJpc2RpY3Rpb25zLk5ZQzsKICAgIGNvbnN0IGJlZm9yZSA9IGlucHV0LnRheGFibGVJbmNvbWVCZWZvcmVHYWluOwogICAgY29uc3QgYW1vdW50ID0gTWF0aC5tYXgoMCwgdGF4RnJvbUJyYWNrZXRzKGJlZm9yZSArIHRheGFibGVHYWluLCBueWMuYnJhY2tldHNbaW5wdXQuZmlsaW5nU3RhdHVzXSkgLSB0YXhGcm9tQnJhY2tldHMoYmVmb3JlLCBueWMuYnJhY2tldHNbaW5wdXQuZmlsaW5nU3RhdHVzXSkpOwogICAgcmV0dXJuIHsgYW1vdW50LCBzdXBwb3J0ZWQ6IHRydWUsIGxhYmVsOiAiTllDIHJlc2lkZW50IHRheCBlc3RpbWF0ZSIsIHdhcm5pbmdzOiBbbnljLm5vdGVzXSwgZGF0YU5vdGU6IGRhdGFOb3RlKCJOZXcgWW9yayBDaXR5IGRhdGEiLCBueWMpIH07CiAgfQoKICBmdW5jdGlvbiBjYWxjdWxhdGVBZnRlclRheFByb2NlZWRzKGlucHV0LCB0b3RhbEVzdGltYXRlZFRheCkgewogICAgcmV0dXJuIGlucHV0LnNhbGVQcmljZSAtIGlucHV0LnNlbGxpbmdFeHBlbnNlcyAtIHRvdGFsRXN0aW1hdGVkVGF4OwogIH0KCiAgZnVuY3Rpb24gZGF0YU5vdGUobGFiZWwsIHNvdXJjZSkgewogICAgaWYgKCFzb3VyY2UpIHJldHVybiAiIjsKICAgIHJldHVybiBsYWJlbCArICI6ICIgKyBzb3VyY2UuZGF0YVZpbnRhZ2UgKyAiLiBTb3VyY2U6ICIgKyBzb3VyY2Uuc291cmNlTmFtZSArICIuIExhc3QgdXBkYXRlZDogIiArIHNvdXJjZS5sYXN0VXBkYXRlZCArICIuIEFjY3VyYWN5IHN0YXR1czogIiArIHNvdXJjZS5hY2N1cmFjeVN0YXR1cyArICIuIjsKICB9CgogIGZ1bmN0aW9uIGNhbGN1bGF0ZUNhcGl0YWxHYWluc1NjZW5hcmlvKGlucHV0KSB7CiAgICBpbnB1dCA9IG5vcm1hbGl6ZUlucHV0cyhpbnB1dCB8fCB7fSk7CiAgICBjb25zdCB2YWxpZGF0aW9uRXJyb3JzID0gdmFsaWRhdGVJbnB1dHMoaW5wdXQpOwogICAgY29uc3QgZ2FpblByZXZpZXcgPSBjYWxjdWxhdGVUYXhhYmxlR2FpbihpbnB1dCk7CiAgICBpZiAoIXZhbGlkYXRpb25FcnJvcnMubGVuZ3RoICYmIGdhaW5QcmV2aWV3LnRheGFibGVHYWluIDw9IDApIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB2YWxpZGF0aW9uRXJyb3JzOiBbIk5vIHRheGFibGUgZ2FpbiB3YXMgZXN0aW1hdGVkLiBZb3VyIGJhc2lzLCBzZWxsaW5nIGV4cGVuc2VzLCBleGNsdXNpb25zLCBvciBjYXBpdGFsIGxvc3NlcyBtYXkgZnVsbHkgb2Zmc2V0IHRoaXMgZ2Fpbi4gTm8gY2FwaXRhbCBnYWlucyB0YXggaXMgZXN0aW1hdGVkIGZvciB0aGlzIHNhbGUsIGJ1dCBvdGhlciB0YXggcnVsZXMgbWF5IHN0aWxsIGFwcGx5LiJdCiAgICAgIH07CiAgICB9CiAgICBpZiAodmFsaWRhdGlvbkVycm9ycy5sZW5ndGgpIHJldHVybiB7IHZhbGlkYXRpb25FcnJvcnMgfTsKCiAgICBjb25zdCBob2xkaW5nID0gZGV0ZXJtaW5lSG9sZGluZ1BlcmlvZChpbnB1dCk7CiAgICBjb25zdCBnYWluID0gZ2FpblByZXZpZXc7CiAgICBsZXQgZmVkZXJhbENhcGl0YWxHYWluc1RheCA9IDA7CiAgICBsZXQgZmVkZXJhbE9yZGluYXJ5SW5jb21lVGF4T25TaG9ydFRlcm1HYWluID0gMDsKICAgIGxldCBjb2xsZWN0aWJsZXNUYXggPSAwOwogICAgbGV0IGRlcHJlY2lhdGlvblJlY2FwdHVyZVRheCA9IDA7CiAgICBsZXQgbHRjZ0RldGFpbCA9IG51bGw7CiAgICBjb25zdCB3YXJuaW5ncyA9IFtdOwoKICAgIGlmIChob2xkaW5nLm92ZXJyaWRkZW4pIHdhcm5pbmdzLnB1c2goIkhvbGRpbmcgcGVyaW9kIHdhcyBtYW51YWxseSBvdmVycmlkZGVuLiIpOwogICAgaWYgKCFob2xkaW5nLm92ZXJyaWRkZW4gJiYgTnVtYmVyLmlzRmluaXRlKGhvbGRpbmcuZGF5c0Zyb21PbmVZZWFyKSAmJiBNYXRoLmFicyhob2xkaW5nLmRheXNGcm9tT25lWWVhcikgPD0gMzApIHsKICAgICAgd2FybmluZ3MucHVzaCgiVGhlIGhvbGRpbmcgcGVyaW9kIGlzIGNsb3NlIHRvIHRoZSBvbmUteWVhciBib3VuZGFyeS4gVGhpcyBjYWxjdWxhdG9yIHVzZXMgZGF0ZS1iYXNlZCBwbGFubmluZyBsb2dpYywgYnV0IHlvdSBzaG91bGQgY29uZmlybSB0aGUgc2hvcnQtdGVybSBvciBsb25nLXRlcm0gY2xhc3NpZmljYXRpb24gYmVmb3JlIHJlbHlpbmcgb24gdGhlIHJlc3VsdC4iKTsKICAgIH0KICAgIGlmIChpbnB1dC5jYXBpdGFsTG9zc2VzID4gMCkgd2FybmluZ3MucHVzaCgiQ2FwaXRhbCBsb3NzZXMgd2VyZSBlbnRlcmVkIG1hbnVhbGx5LiIpOwogICAgaWYgKGlucHV0LmFzc2V0VHlwZSA9PT0gImNyeXB0byIpIHdhcm5pbmdzLnB1c2goIkNyeXB0byBjYWxjdWxhdGlvbiBpcyBsaW1pdGVkIHRvIGEgc2ltcGxpZmllZCBzaW5nbGUtc2FsZSBlc3RpbWF0ZS4iKTsKICAgIGlmIChnYWluLmhvbWVFeGNsdXNpb24ud2FybmluZykgd2FybmluZ3MucHVzaChnYWluLmhvbWVFeGNsdXNpb24ud2FybmluZyk7CgogICAgbGV0IHJlZ3VsYXJUYXhhYmxlR2FpbiA9IGdhaW4udGF4YWJsZUdhaW47CiAgICBpZiAoaW5wdXQuZGVwcmVjaWF0aW9uUmVjYXB0dXJlID4gMCkgewogICAgICBjb25zdCByZWNhcHR1cmVBbW91bnQgPSBNYXRoLm1pbihyZWd1bGFyVGF4YWJsZUdhaW4sIGlucHV0LmRlcHJlY2lhdGlvblJlY2FwdHVyZSk7CiAgICAgIGRlcHJlY2lhdGlvblJlY2FwdHVyZVRheCA9IHJlY2FwdHVyZUFtb3VudCAqIDAuMjU7CiAgICAgIHJlZ3VsYXJUYXhhYmxlR2FpbiAtPSByZWNhcHR1cmVBbW91bnQ7CiAgICAgIHdhcm5pbmdzLnB1c2goIlNpbXBsaWZpZWQgZGVwcmVjaWF0aW9uIHJlY2FwdHVyZSBlc3RpbWF0ZSB1c2VzIHRoZSAyNSUgbWF4aW11bSByYXRlLiBZb3VyIGFjdHVhbCByYXRlIG1heSBiZSBsb3dlciBhbmQgdGhpcyBkb2VzIG5vdCByZXBsYWNlIEZvcm0gNDc5NyB0cmVhdG1lbnQuIik7CiAgICB9CgogICAgaWYgKGhvbGRpbmcuaXNMb25nVGVybSkgewogICAgICBpZiAoaW5wdXQuYXNzZXRUeXBlID09PSAiY29sbGVjdGlibGUiKSB7CiAgICAgICAgY29sbGVjdGlibGVzVGF4ID0gTWF0aC5taW4oY2FsY3VsYXRlU2hvcnRUZXJtRmVkZXJhbFRheEltcGFjdChpbnB1dCwgcmVndWxhclRheGFibGVHYWluKSwgcmVndWxhclRheGFibGVHYWluICogMC4yOCk7CiAgICAgICAgd2FybmluZ3MucHVzaCgiQ29sbGVjdGlibGVzIG1heSBiZSBzdWJqZWN0IHRvIGEgc3BlY2lhbCBtYXhpbXVtIGZlZGVyYWwgcmF0ZS4gVGhpcyBjYWxjdWxhdG9yIHVzZXMgYSBzaW1wbGlmaWVkIGVzdGltYXRlIGFuZCBkb2VzIG5vdCBkZXRlcm1pbmUgZXZlcnkgY29sbGVjdGlibGVzIHRheCBydWxlLiIpOwogICAgICB9IGVsc2UgewogICAgICAgIGx0Y2dEZXRhaWwgPSBjYWxjdWxhdGVMb25nVGVybUZlZGVyYWxDYXBpdGFsR2FpbnNUYXgoaW5wdXQsIHJlZ3VsYXJUYXhhYmxlR2Fpbik7CiAgICAgICAgZmVkZXJhbENhcGl0YWxHYWluc1RheCA9IGx0Y2dEZXRhaWwudGF4QW1vdW50OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBmZWRlcmFsT3JkaW5hcnlJbmNvbWVUYXhPblNob3J0VGVybUdhaW4gPSBjYWxjdWxhdGVTaG9ydFRlcm1GZWRlcmFsVGF4SW1wYWN0KGlucHV0LCByZWd1bGFyVGF4YWJsZUdhaW4pOwogICAgfQoKICAgIGNvbnN0IG5paXRSZXN1bHQgPSBjYWxjdWxhdGVOSUlUKGlucHV0LCBnYWluLnRheGFibGVHYWluKTsKICAgIGlmIChuaWl0UmVzdWx0Lm1hZ2lFc3RpbWF0ZWQpIHdhcm5pbmdzLnB1c2goIk5JSVQgZGVwZW5kcyBvbiBtb2RpZmllZCBhZGp1c3RlZCBncm9zcyBpbmNvbWUuIEJlY2F1c2UgeW91IGRpZCBub3QgZW50ZXIgTUFHSSwgdGhpcyBjYWxjdWxhdG9yIGVzdGltYXRlcyBNQUdJIGZyb20gdGF4YWJsZSBpbmNvbWUgYmVmb3JlIHRoaXMgZ2FpbiBwbHVzIHRoaXMgc2FsZSdzIHRheGFibGUgZ2Fpbi4iKTsKICAgIGlmIChuaWl0UmVzdWx0Lm92ZXJyaWRkZW4pIHdhcm5pbmdzLnB1c2goIk5JSVQgd2FzIG1hbnVhbGx5IG92ZXJyaWRkZW4uIik7CgogICAgY29uc3Qgc3RhdGVSZXN1bHQgPSBjYWxjdWxhdGVTdGF0ZUNhcGl0YWxHYWluc1RheChpbnB1dCwgZ2Fpbi50YXhhYmxlR2Fpbik7CiAgICBjb25zdCBsb2NhbFJlc3VsdCA9IGNhbGN1bGF0ZUxvY2FsVGF4KGlucHV0LCBnYWluLnRheGFibGVHYWluKTsKICAgIHdhcm5pbmdzLnB1c2guYXBwbHkod2FybmluZ3MsIHN0YXRlUmVzdWx0Lndhcm5pbmdzKTsKICAgIHdhcm5pbmdzLnB1c2guYXBwbHkod2FybmluZ3MsIGxvY2FsUmVzdWx0Lndhcm5pbmdzKTsKCiAgICBjb25zdCB0b3RhbEVzdGltYXRlZFRheCA9IGZlZGVyYWxDYXBpdGFsR2FpbnNUYXggKyBmZWRlcmFsT3JkaW5hcnlJbmNvbWVUYXhPblNob3J0VGVybUdhaW4gKyBjb2xsZWN0aWJsZXNUYXggKyBkZXByZWNpYXRpb25SZWNhcHR1cmVUYXggKyBuaWl0UmVzdWx0LmFtb3VudCArIHN0YXRlUmVzdWx0LmFtb3VudCArIGxvY2FsUmVzdWx0LmFtb3VudDsKICAgIGNvbnN0IGFmdGVyVGF4UHJvY2VlZHMgPSBjYWxjdWxhdGVBZnRlclRheFByb2NlZWRzKGlucHV0LCB0b3RhbEVzdGltYXRlZFRheCk7CiAgICBjb25zdCBhZnRlclRheEdhaW4gPSBnYWluLnRheGFibGVHYWluIC0gdG90YWxFc3RpbWF0ZWRUYXg7CiAgICBjb25zdCBlZmZlY3RpdmVUYXhSYXRlT25HYWluID0gZ2Fpbi50YXhhYmxlR2FpbiA+IDAgPyB0b3RhbEVzdGltYXRlZFRheCAvIGdhaW4udGF4YWJsZUdhaW4gOiBudWxsOwoKICAgIGNvbnN0IGRhdGFWaW50YWdlTm90ZXMgPSBbCiAgICAgIGRhdGFOb3RlKCJGZWRlcmFsIGNhcGl0YWwgZ2FpbnMgZGF0YSIsIERBVEEubHRjZyksCiAgICAgIGRhdGFOb3RlKCJGZWRlcmFsIG9yZGluYXJ5IGluY29tZSBkYXRhIiwgREFUQS5vcmRpbmFyeSksCiAgICAgIGRhdGFOb3RlKCJGZWRlcmFsIE5JSVQgZGF0YSIsIERBVEEubmlpdCkKICAgIF07CiAgICBpZiAoc3RhdGVSZXN1bHQuZGF0YU5vdGUpIGRhdGFWaW50YWdlTm90ZXMucHVzaChzdGF0ZVJlc3VsdC5kYXRhTm90ZSk7CiAgICBpZiAobG9jYWxSZXN1bHQuZGF0YU5vdGUpIGRhdGFWaW50YWdlTm90ZXMucHVzaChsb2NhbFJlc3VsdC5kYXRhTm90ZSk7CgogICAgY29uc3QgaGFzU3RhdGVMb2NhbEVzdGltYXRlID0gc3RhdGVSZXN1bHQuc3VwcG9ydGVkIHx8IGxvY2FsUmVzdWx0LnN1cHBvcnRlZDsKICAgIGNvbnN0IGhlYWRsaW5lUmVzdWx0cyA9IFsKICAgICAgWyJUb3RhbCBlc3RpbWF0ZWQgdGF4IG9uIHRoaXMgc2FsZSIsIG1vbmV5KHRvdGFsRXN0aW1hdGVkVGF4KV0sCiAgICAgIFsiRmVkZXJhbCB0YXggb24gdGhpcyBnYWluIiwgbW9uZXkoZmVkZXJhbENhcGl0YWxHYWluc1RheCArIGZlZGVyYWxPcmRpbmFyeUluY29tZVRheE9uU2hvcnRUZXJtR2FpbiArIGNvbGxlY3RpYmxlc1RheCArIGRlcHJlY2lhdGlvblJlY2FwdHVyZVRheCldLAogICAgICBbIk5JSVQgZXN0aW1hdGUiLCBtb25leShuaWl0UmVzdWx0LmFtb3VudCldLAogICAgICBbIlN0YXRlL2xvY2FsIHRheCBlc3RpbWF0ZSIsIGhhc1N0YXRlTG9jYWxFc3RpbWF0ZSA\/IG1vbmV5KHN0YXRlUmVzdWx0LmFtb3VudCArIGxvY2FsUmVzdWx0LmFtb3VudCkgOiAiVW5hdmFpbGFibGUiXSwKICAgICAgWyJBZnRlci10YXggc2FsZSBwcm9jZWVkcyIsIG1vbmV5KGFmdGVyVGF4UHJvY2VlZHMpXSwKICAgICAgWyJFZmZlY3RpdmUgdGF4IHJhdGUgb24gdGF4YWJsZSBnYWluIiwgcGVyY2VudChlZmZlY3RpdmVUYXhSYXRlT25HYWluKV0KICAgIF07CgogICAgY29uc3QgZGlzcGxheVJvd3MgPSBbCiAgICAgIFsiQXNzZXQgdHlwZSIsIEFTU0VUX0xBQkVMU1tpbnB1dC5hc3NldFR5cGVdXSwKICAgICAgWyJIb2xkaW5nIHBlcmlvZCBjbGFzc2lmaWNhdGlvbiIsIGhvbGRpbmcuaG9sZGluZ1BlcmlvZF0sCiAgICAgIFsiUHVyY2hhc2UgcHJpY2Ugb3IgYmFzaXMiLCBtb25leShnYWluLmJhc2lzKV0sCiAgICAgIFsiU2FsZSBwcmljZSIsIG1vbmV5KGlucHV0LnNhbGVQcmljZSldLAogICAgICBbIlNlbGxpbmcgZXhwZW5zZXMiLCBtb25leShpbnB1dC5zZWxsaW5nRXhwZW5zZXMpXSwKICAgICAgWyJJbml0aWFsIGdhaW4iLCBtb25leShnYWluLmdyb3NzR2FpbildLAogICAgICBbIk5ldCBnYWluIGJlZm9yZSBleGNsdXNpb25zIGFuZCBsb3NzZXMiLCBtb25leShnYWluLm5ldEdhaW4pXSwKICAgICAgWyJIb21lIHNhbGUgZXhjbHVzaW9uIGFwcGxpZWQiLCBtb25leShnYWluLmhvbWVFeGNsdXNpb24uYW1vdW50KV0sCiAgICAgIFsiQ2FwaXRhbCBsb3NzZXMgYXBwbGllZCIsIG1vbmV5KGdhaW4uY2FwaXRhbExvc3Nlc0FwcGxpZWQpXSwKICAgICAgWyJUYXhhYmxlIGdhaW4gZnJvbSB0aGlzIHNhbGUiLCBtb25leShnYWluLnRheGFibGVHYWluKV0sCiAgICAgIFsiRmVkZXJhbCBjYXBpdGFsIGdhaW5zIHRheCBvbiB0aGlzIGdhaW4iLCBtb25leShmZWRlcmFsQ2FwaXRhbEdhaW5zVGF4KV0sCiAgICAgIFsiRmVkZXJhbCBvcmRpbmFyeSBpbmNvbWUgdGF4IG9uIHNob3J0LXRlcm0gZ2FpbiIsIG1vbmV5KGZlZGVyYWxPcmRpbmFyeUluY29tZVRheE9uU2hvcnRUZXJtR2FpbildLAogICAgICBbIkNvbGxlY3RpYmxlcyB0YXggZXN0aW1hdGUiLCBtb25leShjb2xsZWN0aWJsZXNUYXgpXSwKICAgICAgWyJTaW1wbGlmaWVkIGRlcHJlY2lhdGlvbiByZWNhcHR1cmUgZXN0aW1hdGUiLCBtb25leShkZXByZWNpYXRpb25SZWNhcHR1cmVUYXgpXSwKICAgICAgWyJOSUlUIGVzdGltYXRlIiwgbW9uZXkobmlpdFJlc3VsdC5hbW91bnQpXSwKICAgICAgW3N0YXRlUmVzdWx0LmxhYmVsLCBzdGF0ZVJlc3VsdC5zdXBwb3J0ZWQgPyBtb25leShzdGF0ZVJlc3VsdC5hbW91bnQpIDogIlVuYXZhaWxhYmxlIl0sCiAgICAgIFtsb2NhbFJlc3VsdC5sYWJlbCB8fCAiTG9jYWwgdGF4IGVzdGltYXRlIiwgbG9jYWxSZXN1bHQuc3VwcG9ydGVkID8gbW9uZXkobG9jYWxSZXN1bHQuYW1vdW50KSA6ICJOb3QgYXBwbGljYWJsZSJdLAogICAgICBbIlRvdGFsIGVzdGltYXRlZCB0YXggb24gdGhpcyBzYWxlIiwgbW9uZXkodG90YWxFc3RpbWF0ZWRUYXgpXSwKICAgICAgWyJBZnRlci10YXggc2FsZSBwcm9jZWVkcyIsIG1vbmV5KGFmdGVyVGF4UHJvY2VlZHMpXSwKICAgICAgWyJBZnRlci10YXggZ2FpbiIsIG1vbmV5KGFmdGVyVGF4R2FpbildLAogICAgICBbIkVmZmVjdGl2ZSB0YXggcmF0ZSBvbiB0YXhhYmxlIGdhaW4iLCBwZXJjZW50KGVmZmVjdGl2ZVRheFJhdGVPbkdhaW4pXQogICAgXS5maWx0ZXIoZnVuY3Rpb24gKHJvdykgewogICAgICBpZiAoL0NvbGxlY3RpYmxlcy8udGVzdChyb3dbMF0pICYmIGNvbGxlY3RpYmxlc1RheCA9PT0gMCkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAoL2RlcHJlY2lhdGlvbi9pLnRlc3Qocm93WzBdKSAmJiBkZXByZWNpYXRpb25SZWNhcHR1cmVUYXggPT09IDApIHJldHVybiBmYWxzZTsKICAgICAgaWYgKC9Ib21lIHNhbGUvLnRlc3Qocm93WzBdKSAmJiBnYWluLmhvbWVFeGNsdXNpb24uYW1vdW50ID09PSAwKSByZXR1cm4gZmFsc2U7CiAgICAgIGlmICgvRmVkZXJhbCBjYXBpdGFsIGdhaW5zLy50ZXN0KHJvd1swXSkgJiYgZmVkZXJhbENhcGl0YWxHYWluc1RheCA9PT0gMCkgcmV0dXJuIGhvbGRpbmcuaXNMb25nVGVybSAmJiBpbnB1dC5hc3NldFR5cGUgIT09ICJjb2xsZWN0aWJsZSI7CiAgICAgIGlmICgvc2hvcnQtdGVybS8udGVzdChyb3dbMF0pICYmIGZlZGVyYWxPcmRpbmFyeUluY29tZVRheE9uU2hvcnRUZXJtR2FpbiA9PT0gMCkgcmV0dXJuICFob2xkaW5nLmlzTG9uZ1Rlcm07CiAgICAgIGlmICgvTG9jYWwgdGF4IGVzdGltYXRlfE5ZQyByZXNpZGVudCB0YXggZXN0aW1hdGUvLnRlc3Qocm93WzBdKSAmJiAhbG9jYWxSZXN1bHQuc3VwcG9ydGVkKSByZXR1cm4gZmFsc2U7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSk7CgogICAgcmV0dXJuIHsKICAgICAgdGF4WWVhcjogaW5wdXQudGF4WWVhciwKICAgICAgZmlsaW5nU3RhdHVzOiBpbnB1dC5maWxpbmdTdGF0dXMsCiAgICAgIGFzc2V0VHlwZTogaW5wdXQuYXNzZXRUeXBlLAogICAgICBwdXJjaGFzZVByaWNlOiBpbnB1dC5wdXJjaGFzZVByaWNlLAogICAgICBhZGp1c3RlZEJhc2lzOiBnYWluLmJhc2lzLAogICAgICBzYWxlUHJpY2U6IGlucHV0LnNhbGVQcmljZSwKICAgICAgc2VsbGluZ0V4cGVuc2VzOiBpbnB1dC5zZWxsaW5nRXhwZW5zZXMsCiAgICAgIGdyb3NzR2FpbjogZ2Fpbi5ncm9zc0dhaW4sCiAgICAgIG5ldEdhaW46IGdhaW4ubmV0R2FpbiwKICAgICAgY2FwaXRhbExvc3Nlc0FwcGxpZWQ6IGdhaW4uY2FwaXRhbExvc3Nlc0FwcGxpZWQsCiAgICAgIHRheGFibGVHYWluOiBnYWluLnRheGFibGVHYWluLAogICAgICBob2xkaW5nUGVyaW9kOiBob2xkaW5nLmhvbGRpbmdQZXJpb2QsCiAgICAgIGlzTG9uZ1Rlcm06IGhvbGRpbmcuaXNMb25nVGVybSwKICAgICAgZmVkZXJhbENhcGl0YWxHYWluc1RheCwKICAgICAgZmVkZXJhbE9yZGluYXJ5SW5jb21lVGF4T25TaG9ydFRlcm1HYWluLAogICAgICBjb2xsZWN0aWJsZXNUYXgsCiAgICAgIGRlcHJlY2lhdGlvblJlY2FwdHVyZVRheCwKICAgICAgbmlpdDogbmlpdFJlc3VsdC5hbW91bnQsCiAgICAgIHN0YXRlVGF4OiBzdGF0ZVJlc3VsdC5hbW91bnQsCiAgICAgIGxvY2FsVGF4OiBsb2NhbFJlc3VsdC5hbW91bnQsCiAgICAgIHRvdGFsRXN0aW1hdGVkVGF4LAogICAgICBhZnRlclRheFByb2NlZWRzLAogICAgICBhZnRlclRheEdhaW4sCiAgICAgIGVmZmVjdGl2ZVRheFJhdGVPbkdhaW4sCiAgICAgIHdhcm5pbmdzOiBBcnJheS5mcm9tKG5ldyBTZXQod2FybmluZ3MpKSwKICAgICAgZGF0YVZpbnRhZ2VOb3RlczogQXJyYXkuZnJvbShuZXcgU2V0KGRhdGFWaW50YWdlTm90ZXMuZmlsdGVyKEJvb2xlYW4pKSksCiAgICAgIGRpc3BsYXlSb3dzLAogICAgICBoZWFkbGluZVJlc3VsdHMsCiAgICAgIGx0Y2dEZXRhaWwsCiAgICAgIHZhbGlkYXRpb25FcnJvcnM6IFtdCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gZXNjYXBlSHRtbCh2YWx1ZSkgewogICAgY29uc3QgYW1wID0gU3RyaW5nLmZyb21DaGFyQ29kZSgzOCk7CiAgICByZXR1cm4gU3RyaW5nKHZhbHVlKQogICAgICAucmVwbGFjZShuZXcgUmVnRXhwKFN0cmluZy5mcm9tQ2hhckNvZGUoNjApLCAiZyIpLCBhbXAgKyAibHQ7IikKICAgICAgLnJlcGxhY2UobmV3IFJlZ0V4cChTdHJpbmcuZnJvbUNoYXJDb2RlKDYyKSwgImciKSwgYW1wICsgImd0OyIpCiAgICAgIC5yZXBsYWNlKG5ldyBSZWdFeHAoU3RyaW5nLmZyb21DaGFyQ29kZSgzNCksICJnIiksIGFtcCArICJxdW90OyIpCiAgICAgIC5yZXBsYWNlKG5ldyBSZWdFeHAoU3RyaW5nLmZyb21DaGFyQ29kZSgzOSksICJnIiksIGFtcCArICIjMDM5OyIpOwogIH0KCiAgZnVuY3Rpb24gcmVuZGVyUmVzdWx0cyhyb290LCByZXN1bHQpIHsKICAgIGNvbnN0IHZhbGlkYXRpb25Cb3ggPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXZhbGlkYXRpb24tbWVzc2FnZXNdIik7CiAgICB2YWxpZGF0aW9uQm94LmlubmVySFRNTCA9ICIiOwogICAgaWYgKHJlc3VsdC52YWxpZGF0aW9uRXJyb3JzICYmIHJlc3VsdC52YWxpZGF0aW9uRXJyb3JzLmxlbmd0aCkgewogICAgICB2YWxpZGF0aW9uQm94LmlubmVySFRNTCA9IHJlc3VsdC52YWxpZGF0aW9uRXJyb3JzLm1hcChmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICByZXR1cm4gJzxkaXYgY2xhc3M9Iml0Yi1jYXBnYWlucy1lcnJvciI+JyArIGVzY2FwZUh0bWwoZXJyb3IpICsgIjwvZGl2PiI7CiAgICAgIH0pLmpvaW4oIiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBlbXB0eSA9IHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtZW1wdHktcmVzdWx0c10iKTsKICAgIGNvbnN0IGNvbnRlbnQgPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXJlc3VsdC1jb250ZW50XSIpOwogICAgY29uc3QgY29weWFibGUgPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLWNvcHlhYmxlLXJlc3VsdHNdIik7CiAgICBlbXB0eS5jbGFzc0xpc3QuYWRkKCJpdGItY2FwZ2FpbnMtaGlkZGVuIik7CiAgICBjb250ZW50LmNsYXNzTGlzdC5yZW1vdmUoIml0Yi1jYXBnYWlucy1oaWRkZW4iKTsKICAgIGNvcHlhYmxlLmlubmVySFRNTCA9CiAgICAgIHJlc3VsdC5oZWFkbGluZVJlc3VsdHMubWFwKGZ1bmN0aW9uIChyb3cpIHsKICAgICAgICByZXR1cm4gJzxkaXYgY2xhc3M9Iml0Yi1jYXBnYWlucy1oZWFkbGluZSI+PHNwYW4+JyArIGVzY2FwZUh0bWwocm93WzBdKSArICI8L3NwYW4+PHN0cm9uZz4iICsgZXNjYXBlSHRtbChyb3dbMV0pICsgIjwvc3Ryb25nPjwvZGl2PiI7CiAgICAgIH0pLmpvaW4oIiIpICsKICAgICAgcmVzdWx0LmRpc3BsYXlSb3dzLm1hcChmdW5jdGlvbiAocm93KSB7CiAgICAgICAgcmV0dXJuICc8ZGl2IGNsYXNzPSJpdGItY2FwZ2FpbnMtcm93Ij48c3Bhbj4nICsgZXNjYXBlSHRtbChyb3dbMF0pICsgIjwvc3Bhbj48c3Ryb25nPiIgKyBlc2NhcGVIdG1sKHJvd1sxXSkgKyAiPC9zdHJvbmc+PC9kaXY+IjsKICAgICAgfSkuam9pbigiIikgKwogICAgICAnPGRpdiBjbGFzcz0iaXRiLWNhcGdhaW5zLXdhcm5pbmciPjxzdHJvbmc+V2FybmluZ3MgYW5kIGxpbWl0YXRpb25zPC9zdHJvbmc+JyArCiAgICAgIHJlc3VsdC53YXJuaW5ncy5tYXAoZnVuY3Rpb24gKHdhcm5pbmcpIHsgcmV0dXJuICI8cD4iICsgZXNjYXBlSHRtbCh3YXJuaW5nKSArICI8L3A+IjsgfSkuam9pbigiIikgKwogICAgICAiPC9kaXY+IiArCiAgICAgICc8ZGl2IGNsYXNzPSJpdGItY2FwZ2FpbnMtd2FybmluZyI+PHN0cm9uZz5EYXRhIG5vdGVzPC9zdHJvbmc+JyArCiAgICAgIHJlc3VsdC5kYXRhVmludGFnZU5vdGVzLm1hcChmdW5jdGlvbiAobm90ZSkgeyByZXR1cm4gIjxwPiIgKyBlc2NhcGVIdG1sKG5vdGUpICsgIjwvcD4iOyB9KS5qb2luKCIiKSArCiAgICAgICI8L2Rpdj4iOwogIH0KCiAgZnVuY3Rpb24gY29weVJlc3VsdHMocm9vdCkgewogICAgY29uc3Qgc3RhdHVzID0gcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1jb3B5LXN0YXR1c10iKTsKICAgIGlmIChyb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXJlc3VsdC1jb250ZW50XSIpLmNsYXNzTGlzdC5jb250YWlucygiaXRiLWNhcGdhaW5zLWhpZGRlbiIpKSB7CiAgICAgIHN0YXR1cy50ZXh0Q29udGVudCA9ICJQbGVhc2UgY2FsY3VsYXRlIHlvdXIgcmVzdWx0IGZpcnN0LiI7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHRleHQgPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLWNvcHlhYmxlLXJlc3VsdHNdIikuaW5uZXJUZXh0LnRyaW0oKTsKICAgIGlmICghbmF2aWdhdG9yLmNsaXBib2FyZCB8fCAhbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQpIHsKICAgICAgc3RhdHVzLnRleHRDb250ZW50ID0gIkNvcHkgaXMgdW5hdmFpbGFibGUgaW4gdGhpcyBicm93c2VyLiI7CiAgICAgIHJldHVybjsKICAgIH0KICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHRleHQpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICBzdGF0dXMudGV4dENvbnRlbnQgPSAiUmVzdWx0IHN1bW1hcnkgY29waWVkLiI7CiAgICB9KS5jYXRjaChmdW5jdGlvbiAoKSB7CiAgICAgIHN0YXR1cy50ZXh0Q29udGVudCA9ICJDb3B5IGZhaWxlZC4gU2VsZWN0IHRoZSByZXN1bHQgdGV4dCBhbmQgY29weSBpdCBtYW51YWxseS4iOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBwcmludFJlc3VsdHMoKSB7CiAgICB3aW5kb3cucHJpbnQoKTsKICB9CgogIGZ1bmN0aW9uIHNldFZpc2libGUoZWxlbWVudCwgdmlzaWJsZSkgewogICAgaWYgKCFlbGVtZW50KSByZXR1cm47CiAgICBlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoIml0Yi1jYXBnYWlucy1oaWRkZW4iLCAhdmlzaWJsZSk7CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVEaXNjbG9zdXJlKHJvb3QpIHsKICAgIGNvbnN0IGZvcm0gPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLWNhcGdhaW5zLWZvcm1dIik7CiAgICBjb25zdCBhc3NldFR5cGUgPSBmaWVsZFZhbHVlKGZvcm0sICJhc3NldFR5cGUiKTsKICAgIGNvbnN0IHN0YXRlID0gZmllbGRWYWx1ZShmb3JtLCAic3RhdGVPZlJlc2lkZW5jZSIpOwogICAgc2V0VmlzaWJsZShyb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXByaW1hcnktcmVzaWRlbmNlLXNlY3Rpb25dIiksIGFzc2V0VHlwZSA9PT0gInByaW1hcnlfcmVzaWRlbmNlIik7CiAgICBzZXRWaXNpYmxlKHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtY3J5cHRvLXdhcm5pbmddIiksIGFzc2V0VHlwZSA9PT0gImNyeXB0byIpOwogICAgc2V0VmlzaWJsZShyb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXJlYWwtZXN0YXRlLXdhcm5pbmddIiksIGFzc2V0VHlwZSA9PT0gInJlYWxfZXN0YXRlIik7CiAgICBzZXRWaXNpYmxlKHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtbnljLXJlc2lkZW50LWZpZWxkXSIpLCBzdGF0ZSA9PT0gIk5ZIik7CiAgICBpZiAoc3RhdGUgIT09ICJOWSIpIHsKICAgICAgY29uc3QgbnljID0gZm9ybS5xdWVyeVNlbGVjdG9yKCdbZGF0YS1maWVsZD0iaXNOWUNSZXNpZGVudCJdJyk7CiAgICAgIGlmIChueWMpIG55Yy52YWx1ZSA9ICJubyI7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwb3B1bGF0ZVN0YXRlT3B0aW9ucyhyb290KSB7CiAgICBjb25zdCBzZWxlY3QgPSByb290LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWZpZWxkPSJzdGF0ZU9mUmVzaWRlbmNlIl0nKTsKICAgIGlmICghc2VsZWN0IHx8IHNlbGVjdC5vcHRpb25zLmxlbmd0aCkgcmV0dXJuOwogICAgY29uc3Qgc3RhdGVzID0gREFUQS5zdGF0ZXMuc3RhdGVzOwogICAgT2JqZWN0LmtleXMoc3RhdGVzKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgIHJldHVybiBzdGF0ZXNbYV0ubmFtZS5sb2NhbGVDb21wYXJlKHN0YXRlc1tiXS5uYW1lKTsKICAgIH0pLmZvckVhY2goZnVuY3Rpb24gKGNvZGUpIHsKICAgICAgY29uc3Qgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgib3B0aW9uIik7CiAgICAgIG9wdGlvbi52YWx1ZSA9IGNvZGU7CiAgICAgIG9wdGlvbi50ZXh0Q29udGVudCA9IHN0YXRlc1tjb2RlXS5uYW1lOwogICAgICBpZiAoY29kZSA9PT0gIk5ZIikgb3B0aW9uLnNlbGVjdGVkID0gdHJ1ZTsKICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHBvcHVsYXRlUmVsYXRlZFRvb2xzKHJvb3QpIHsKICAgIGNvbnN0IGxpc3QgPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXJlbGF0ZWQtdG9vbHNdIik7CiAgICBpZiAoIWxpc3QpIHJldHVybjsKICAgIGxpc3QuaW5uZXJIVE1MID0gUkVMQVRFRF9UT09MUy5tYXAoZnVuY3Rpb24gKHRvb2wpIHsKICAgICAgaWYgKCF0b29sLnVybCkgcmV0dXJuICI8bGk+IiArIGVzY2FwZUh0bWwodG9vbC5sYWJlbCkgKyAodG9vbC5jb21pbmdTb29uID8gIiA8c3Bhbj5Db21pbmcgc29vbjwvc3Bhbj4iIDogIiIpICsgIjwvbGk+IjsKICAgICAgcmV0dXJuICc8bGk+PGEgaHJlZj0iJyArIGVzY2FwZUh0bWwodG9vbC51cmwpICsgJyI+JyArIGVzY2FwZUh0bWwodG9vbC5sYWJlbCkgKyAiPC9hPjwvbGk+IjsKICAgIH0pLmpvaW4oIiIpOwogIH0KCiAgZnVuY3Rpb24gcmVzZXRDYWxjdWxhdG9yKHJvb3QpIHsKICAgIGNvbnN0IGZvcm0gPSByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLWNhcGdhaW5zLWZvcm1dIik7CiAgICBmb3JtLnF1ZXJ5U2VsZWN0b3JBbGwoIltkYXRhLWZpZWxkXSIpLmZvckVhY2goZnVuY3Rpb24gKGZpZWxkKSB7CiAgICAgIGlmIChmaWVsZC50eXBlID09PSAiY2hlY2tib3giKSB7CiAgICAgICAgZmllbGQuY2hlY2tlZCA9IGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIGZpZWxkLnZhbHVlID0gIiI7CiAgICAgIH0KICAgIH0pOwogICAgZmllbGRTZXQoZm9ybSwgImFzc2V0VHlwZSIsICJzdG9jayIpOwogICAgZmllbGRTZXQoZm9ybSwgInRheFllYXIiLCAiMjAyNiIpOwogICAgZmllbGRTZXQoZm9ybSwgImZpbGluZ1N0YXR1cyIsICJzaW5nbGUiKTsKICAgIGZpZWxkU2V0KGZvcm0sICJzdGF0ZU9mUmVzaWRlbmNlIiwgIk5ZIik7CiAgICBmaWVsZFNldChmb3JtLCAiaXNOWUNSZXNpZGVudCIsICJubyIpOwogICAgZmllbGRTZXQoZm9ybSwgImhvbWVPd25lZFR3b1llYXJzIiwgInllcyIpOwogICAgZmllbGRTZXQoZm9ybSwgImhvbWVVc2VkVHdvWWVhcnMiLCAieWVzIik7CiAgICBmaWVsZFNldChmb3JtLCAiaG9tZUV4Y2x1c2lvblVzZWRSZWNlbnRseSIsICJubyIpOwoKICAgIGNvbnN0IGFkdmFuY2VkVG9nZ2xlID0gcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1hZHZhbmNlZC10b2dnbGVdIik7CiAgICBjb25zdCBhZHZhbmNlZFBhbmVsID0gcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1hZHZhbmNlZC1wYW5lbF0iKTsKICAgIGlmIChhZHZhbmNlZFRvZ2dsZSkgYWR2YW5jZWRUb2dnbGUuc2V0QXR0cmlidXRlKCJhcmlhLWV4cGFuZGVkIiwgImZhbHNlIik7CiAgICBpZiAoYWR2YW5jZWRQYW5lbCkgYWR2YW5jZWRQYW5lbC5jbGFzc0xpc3QuYWRkKCJpdGItY2FwZ2FpbnMtaGlkZGVuIik7CgogICAgdXBkYXRlRGlzY2xvc3VyZShyb290KTsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtcmVzdWx0LWNvbnRlbnRdIikuY2xhc3NMaXN0LmFkZCgiaXRiLWNhcGdhaW5zLWhpZGRlbiIpOwogICAgcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1lbXB0eS1yZXN1bHRzXSIpLmNsYXNzTGlzdC5yZW1vdmUoIml0Yi1jYXBnYWlucy1oaWRkZW4iKTsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtY29weS1zdGF0dXNdIikudGV4dENvbnRlbnQgPSAiIjsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtdmFsaWRhdGlvbi1tZXNzYWdlc10iKS5pbm5lckhUTUwgPSAiIjsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtY29weWFibGUtcmVzdWx0c10iKS5pbm5lckhUTUwgPSAiIjsKICB9CgogIGZ1bmN0aW9uIGluaXRDYWxjdWxhdG9yKHJvb3QpIHsKICAgIGlmIChyb290LmRhdGFzZXQuaXRiQ2FwZ2FpbnNJbml0aWFsaXplZCA9PT0gInRydWUiKSByZXR1cm47CiAgICByb290LmRhdGFzZXQuaXRiQ2FwZ2FpbnNJbml0aWFsaXplZCA9ICJ0cnVlIjsKICAgIHBvcHVsYXRlU3RhdGVPcHRpb25zKHJvb3QpOwogICAgcG9wdWxhdGVSZWxhdGVkVG9vbHMocm9vdCk7CiAgICBjb25zdCBmb3JtID0gcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1jYXBnYWlucy1mb3JtXSIpOwogICAgdXBkYXRlRGlzY2xvc3VyZShyb290KTsKICAgIGZ1bmN0aW9uIHJ1bkNhbGN1bGF0aW9uKCkgewogICAgICByZW5kZXJSZXN1bHRzKHJvb3QsIGNhbGN1bGF0ZUNhcGl0YWxHYWluc1NjZW5hcmlvKGNvbGxlY3RJbnB1dChmb3JtKSkpOwogICAgfQogICAgZm9ybS5hZGRFdmVudExpc3RlbmVyKCJjaGFuZ2UiLCBmdW5jdGlvbiAoKSB7IHVwZGF0ZURpc2Nsb3N1cmUocm9vdCk7IH0pOwogICAgcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1hZHZhbmNlZC10b2dnbGVdIikuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCBmdW5jdGlvbiAoZXZlbnQpIHsKICAgICAgY29uc3QgZXhwYW5kZWQgPSBldmVudC5jdXJyZW50VGFyZ2V0LmdldEF0dHJpYnV0ZSgiYXJpYS1leHBhbmRlZCIpID09PSAidHJ1ZSI7CiAgICAgIGV2ZW50LmN1cnJlbnRUYXJnZXQuc2V0QXR0cmlidXRlKCJhcmlhLWV4cGFuZGVkIiwgZXhwYW5kZWQgPyAiZmFsc2UiIDogInRydWUiKTsKICAgICAgcm9vdC5xdWVyeVNlbGVjdG9yKCJbZGF0YS1hZHZhbmNlZC1wYW5lbF0iKS5jbGFzc0xpc3QudG9nZ2xlKCJpdGItY2FwZ2FpbnMtaGlkZGVuIiwgZXhwYW5kZWQpOwogICAgfSk7CiAgICBmb3JtLmFkZEV2ZW50TGlzdGVuZXIoInN1Ym1pdCIsIGZ1bmN0aW9uIChldmVudCkgewogICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBydW5DYWxjdWxhdGlvbigpOwogICAgfSk7CiAgICByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLWNhbGN1bGF0ZV0iKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIHJ1bkNhbGN1bGF0aW9uKTsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtcmVzZXQtY2FsY3VsYXRvcl0iKS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIGZ1bmN0aW9uICgpIHsgcmVzZXRDYWxjdWxhdG9yKHJvb3QpOyB9KTsKICAgIHJvb3QucXVlcnlTZWxlY3RvcigiW2RhdGEtY29weS1yZXN1bHRzXSIpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgZnVuY3Rpb24gKCkgeyBjb3B5UmVzdWx0cyhyb290KTsgfSk7CiAgICByb290LnF1ZXJ5U2VsZWN0b3IoIltkYXRhLXByaW50LXJlc3VsdHNdIikuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCBwcmludFJlc3VsdHMpOwogIH0KCiAgZnVuY3Rpb24gaW5pdEFsbCgpIHsKICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIltkYXRhLWl0Yi1jYXBnYWlucy1jYWxjdWxhdG9yXSIpLmZvckVhY2goaW5pdENhbGN1bGF0b3IpOwogIH0KCiAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICJsb2FkaW5nIikgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsIGluaXRBbGwpOwogIGVsc2UgaW5pdEFsbCgpOwoKICB3aW5kb3cuSVRCQ2FwaXRhbEdhaW5zQ2FsY3VsYXRvciA9IHsKICAgIG5vcm1hbGl6ZUlucHV0cywKICAgIHZhbGlkYXRlSW5wdXRzLAogICAgZGV0ZXJtaW5lSG9sZGluZ1BlcmlvZCwKICAgIGNhbGN1bGF0ZUdyb3NzR2FpbiwKICAgIGNhbGN1bGF0ZVRheGFibGVHYWluLAogICAgY2FsY3VsYXRlTG9uZ1Rlcm1GZWRlcmFsQ2FwaXRhbEdhaW5zVGF4LAogICAgY2FsY3VsYXRlU2hvcnRUZXJtRmVkZXJhbFRheEltcGFjdCwKICAgIGNhbGN1bGF0ZU5JSVQsCiAgICBjYWxjdWxhdGVTdGF0ZUNhcGl0YWxHYWluc1RheCwKICAgIGNhbGN1bGF0ZUxvY2FsVGF4LAogICAgY2FsY3VsYXRlQWZ0ZXJUYXhQcm9jZWVkcywKICAgIGNhbGN1bGF0ZUNhcGl0YWxHYWluc1NjZW5hcmlvLAogICAgcmVuZGVyUmVzdWx0cywKICAgIGNvcHlSZXN1bHRzLAogICAgcHJpbnRSZXN1bHRzLAogICAgcmVzZXRDYWxjdWxhdG9yCiAgfTsKfSkoKTsKCgooZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgZnVuY3Rpb24gYmFzZUlucHV0KG92ZXJyaWRlcykgewogICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oewogICAgICB0YXhZZWFyOiAiMjAyNiIsCiAgICAgIGFzc2V0VHlwZTogInN0b2NrIiwKICAgICAgcHVyY2hhc2VQcmljZTogNTAwMDAsCiAgICAgIHNhbGVQcmljZTogMTAwMDAwLAogICAgICBzZWxsaW5nRXhwZW5zZXM6IDAsCiAgICAgIHB1cmNoYXNlRGF0ZTogIjIwMjQtMDEtMDEiLAogICAgICBzYWxlRGF0ZTogIjIwMjYtMDItMDEiLAogICAgICBob2xkaW5nUGVyaW9kT3ZlcnJpZGU6ICIiLAogICAgICBjYXBpdGFsTG9zc2VzOiAwLAogICAgICBmaWxpbmdTdGF0dXM6ICJzaW5nbGUiLAogICAgICB0YXhhYmxlSW5jb21lQmVmb3JlR2FpbjogMTAwMDAwLAogICAgICBtYWdpQmVmb3JlR2FpbjogMTAwMDAwLAogICAgICBmZWRlcmFsVGF4UGFpZDogMCwKICAgICAgc3RhdGVPZlJlc2lkZW5jZTogIkZMIiwKICAgICAgaXNOWUNSZXNpZGVudDogZmFsc2UsCiAgICAgIHN0YXRlVGF4UGFpZDogMCwKICAgICAgYWRqdXN0ZWRCYXNpczogbnVsbCwKICAgICAgZGVwcmVjaWF0aW9uUmVjYXB0dXJlOiAwLAogICAgICBzdGF0ZUxvY2FsUmF0ZU92ZXJyaWRlOiBudWxsLAogICAgICBuaWl0T3ZlcnJpZGU6IG51bGwsCiAgICAgIGhvbWVPd25lZFR3b1llYXJzOiAieWVzIiwKICAgICAgaG9tZVVzZWRUd29ZZWFyczogInllcyIsCiAgICAgIGhvbWVFeGNsdXNpb25Vc2VkUmVjZW50bHk6ICJubyIsCiAgICAgIG1hbnVhbEhvbWVFeGNsdXNpb246IG51bGwKICAgIH0sIG92ZXJyaWRlcyB8fCB7fSk7CiAgfQoKICBmdW5jdGlvbiBhc3NlcnRBcHByb3hFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCB0b2xlcmFuY2UsIGxhYmVsKSB7CiAgICBjb25zdCBwYXNzID0gTWF0aC5hYnMoYWN0dWFsIC0gZXhwZWN0ZWQpIDw9IHRvbGVyYW5jZTsKICAgIGNvbnNvbGUubG9nKChwYXNzID8gIlBBU1MiIDogIkZBSUwiKSArICIgLSAiICsgbGFiZWwsIHsgZXhwZWN0ZWQsIGFjdHVhbCwgdG9sZXJhbmNlIH0pOwogICAgcmV0dXJuIHBhc3M7CiAgfQoKICBmdW5jdGlvbiBhc3NlcnRDb25kaXRpb24oY29uZGl0aW9uLCBsYWJlbCwgZGV0YWlscykgewogICAgY29uc29sZS5sb2coKGNvbmRpdGlvbiA\/ICJQQVNTIiA6ICJGQUlMIikgKyAiIC0gIiArIGxhYmVsLCBkZXRhaWxzIHx8IHt9KTsKICAgIHJldHVybiAhIWNvbmRpdGlvbjsKICB9CgogIGZ1bmN0aW9uIHJ1bkNhc2UobmFtZSwgaW5wdXQsIGNoZWNrKSB7CiAgICBjb25zdCByZXN1bHQgPSB3aW5kb3cuSVRCQ2FwaXRhbEdhaW5zQ2FsY3VsYXRvci5jYWxjdWxhdGVDYXBpdGFsR2FpbnNTY2VuYXJpbyhiYXNlSW5wdXQoaW5wdXQpKTsKICAgIGNvbnN0IHBhc3MgPSBjaGVjayhyZXN1bHQpOwogICAgY29uc29sZS5sb2coIlRlc3Q6IiwgbmFtZSwgcGFzcyA\/ICJQQVNTIiA6ICJGQUlMIiwgeyBpbnB1dCwgcmVzdWx0IH0pOwogICAgcmV0dXJuIHBhc3M7CiAgfQoKICB3aW5kb3cucnVuQ2FwaXRhbEdhaW5zQ2FsY3VsYXRvclRlc3RzID0gZnVuY3Rpb24gKCkgewogICAgY29uc3QgdGVzdHMgPSBbXTsKICAgIHRlc3RzLnB1c2gocnVuQ2FzZSgiTG9uZy10ZXJtIGdhaW4gZW50aXJlbHkgd2l0aGluIDAlIGJyYWNrZXQiLCB7CiAgICAgIHRheGFibGVJbmNvbWVCZWZvcmVHYWluOiAxMDAwMCwKICAgICAgcHVyY2hhc2VQcmljZTogMTAwMDAsCiAgICAgIHNhbGVQcmljZTogMjAwMDAKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLmZlZGVyYWxDYXBpdGFsR2FpbnNUYXgsIDAsIDEsICIwJSBMVENHIGJyYWNrZXQiKTsKICAgIH0pKTsKICAgIHRlc3RzLnB1c2gocnVuQ2FzZSgiTG9uZy10ZXJtIGdhaW4gY3Jvc3NpbmcgZnJvbSAwJSBpbnRvIDE1JSIsIHsKICAgICAgdGF4YWJsZUluY29tZUJlZm9yZUdhaW46IDQwMDAwLAogICAgICBwdXJjaGFzZVByaWNlOiAxLAogICAgICBzYWxlUHJpY2U6IDIwMDAxCiAgICB9LCBmdW5jdGlvbiAocikgewogICAgICByZXR1cm4gYXNzZXJ0Q29uZGl0aW9uKHIuZmVkZXJhbENhcGl0YWxHYWluc1RheCA+IDAgJiYgci5mZWRlcmFsQ2FwaXRhbEdhaW5zVGF4IDwgMzAwMCwgIkxUQ0cgY3Jvc3NlcyBpbnRvIDE1JSIsIHsgdGF4OiByLmZlZGVyYWxDYXBpdGFsR2FpbnNUYXggfSk7CiAgICB9KSk7CiAgICB0ZXN0cy5wdXNoKHJ1bkNhc2UoIkxvbmctdGVybSBnYWluIGNyb3NzaW5nIGZyb20gMTUlIGludG8gMjAlIiwgewogICAgICB0YXhhYmxlSW5jb21lQmVmb3JlR2FpbjogNTQwMDAwLAogICAgICBwdXJjaGFzZVByaWNlOiAxLAogICAgICBzYWxlUHJpY2U6IDIwMDAxCiAgICB9LCBmdW5jdGlvbiAocikgewogICAgICByZXR1cm4gYXNzZXJ0Q29uZGl0aW9uKHIubHRjZ0RldGFpbC50d2VudHlTbGljZSA+IDAsICJMVENHIGhhcyAyMCUgc2xpY2UiLCByLmx0Y2dEZXRhaWwpOwogICAgfSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJTaG9ydC10ZXJtIGdhaW4gdGF4ZWQgYXMgaW5jcmVtZW50YWwgb3JkaW5hcnkgaW5jb21lIiwgewogICAgICBwdXJjaGFzZURhdGU6ICIyMDI2LTAxLTAxIiwKICAgICAgc2FsZURhdGU6ICIyMDI2LTA2LTAxIgogICAgfSwgZnVuY3Rpb24gKHIpIHsKICAgICAgcmV0dXJuIGFzc2VydENvbmRpdGlvbihyLmZlZGVyYWxPcmRpbmFyeUluY29tZVRheE9uU2hvcnRUZXJtR2FpbiA+IDAgJiYgci5mZWRlcmFsQ2FwaXRhbEdhaW5zVGF4ID09PSAwLCAic2hvcnQtdGVybSBvcmRpbmFyeSB0YXggYXBwbGllZCIsIHIpOwogICAgfSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJOSUlUIGJlbG93IHRocmVzaG9sZCByZXR1cm5zIHplcm8iLCB7CiAgICAgIHRheGFibGVJbmNvbWVCZWZvcmVHYWluOiAxMDAwMDAsCiAgICAgIG1hZ2lCZWZvcmVHYWluOiAxMDAwMDAKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLm5paXQsIDAsIDEsICJOSUlUIGJlbG93IHRocmVzaG9sZCIpOwogICAgfSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJOSUlUIGFib3ZlIHRocmVzaG9sZCBhcHBsaWVzIHRvIGxlc3NlciB2YWx1ZSIsIHsKICAgICAgdGF4YWJsZUluY29tZUJlZm9yZUdhaW46IDIxMDAwMCwKICAgICAgbWFnaUJlZm9yZUdhaW46IDIxMDAwMCwKICAgICAgcHVyY2hhc2VQcmljZTogMSwKICAgICAgc2FsZVByaWNlOiAxMDAwMDEKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLm5paXQsIDM4MDAsIDIsICJOSUlUIGxlc3NlciBvZiBnYWluIG9yIGV4Y2VzcyBNQUdJIik7CiAgICB9KSk7CiAgICB0ZXN0cy5wdXNoKHJ1bkNhc2UoIlByaW1hcnkgcmVzaWRlbmNlIGV4Y2x1c2lvbiBhcHBsaWVzIiwgewogICAgICBhc3NldFR5cGU6ICJwcmltYXJ5X3Jlc2lkZW5jZSIsCiAgICAgIHB1cmNoYXNlUHJpY2U6IDEwMDAwMCwKICAgICAgc2FsZVByaWNlOiA0MDAwMDAsCiAgICAgIHRheGFibGVJbmNvbWVCZWZvcmVHYWluOiAxMDAwMDAKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLnRheGFibGVHYWluLCA1MDAwMCwgMSwgInNpbmdsZSAkMjUwayBleGNsdXNpb24iKTsKICAgIH0pKTsKICAgIHRlc3RzLnB1c2gocnVuQ2FzZSgiUHJpbWFyeSByZXNpZGVuY2UgZXhjbHVzaW9uIGRvZXMgbm90IGFwcGx5IiwgewogICAgICBhc3NldFR5cGU6ICJwcmltYXJ5X3Jlc2lkZW5jZSIsCiAgICAgIHB1cmNoYXNlUHJpY2U6IDEwMDAwMCwKICAgICAgc2FsZVByaWNlOiA0MDAwMDAsCiAgICAgIGhvbWVPd25lZFR3b1llYXJzOiAibm8iLAogICAgICBob21lVXNlZFR3b1llYXJzOiAieWVzIgogICAgfSwgZnVuY3Rpb24gKHIpIHsKICAgICAgcmV0dXJuIGFzc2VydEFwcHJveEVxdWFsKHIudGF4YWJsZUdhaW4sIDMwMDAwMCwgMSwgIm5vIGhvbWUgZXhjbHVzaW9uIik7CiAgICB9KSk7CiAgICB0ZXN0cy5wdXNoKHJ1bkNhc2UoIkZsb3JpZGEgc2hvd3MgemVybyBzdGF0ZSB0YXgiLCB7CiAgICAgIHN0YXRlT2ZSZXNpZGVuY2U6ICJGTCIKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLnN0YXRlVGF4LCAwLCAxLCAiRmxvcmlkYSBzdGF0ZSB0YXggemVybyIpOwogICAgfSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJVbnN1cHBvcnRlZCBzdGF0ZSBkb2VzIG5vdCBmYWJyaWNhdGUgc3RhdGUgdGF4IiwgewogICAgICBzdGF0ZU9mUmVzaWRlbmNlOiAiQ0EiCiAgICB9LCBmdW5jdGlvbiAocikgewogICAgICByZXR1cm4gYXNzZXJ0Q29uZGl0aW9uKHIuc3RhdGVUYXggPT09IDAgJiYgci53YXJuaW5ncy5zb21lKGZ1bmN0aW9uICh3KSB7IHJldHVybiAvbm90IGltcGxlbWVudGVkfG5vdCB5ZXQvaS50ZXN0KHcpOyB9KSwgInVuc3VwcG9ydGVkIHN0YXRlIHdhcm5zIHdpdGhvdXQgZmFicmljYXRlZCB0YXgiLCByLndhcm5pbmdzKTsKICAgIH0pKTsKICAgIHRlc3RzLnB1c2gocnVuQ2FzZSgiTmV3IFlvcmsgU3RhdGUgZXN0aW1hdGUgYXBwZWFycyIsIHsKICAgICAgc3RhdGVPZlJlc2lkZW5jZTogIk5ZIgogICAgfSwgZnVuY3Rpb24gKHIpIHsKICAgICAgcmV0dXJuIGFzc2VydENvbmRpdGlvbihyLnN0YXRlVGF4ID4gMCwgIk5ZIHN0YXRlIGVzdGltYXRlIGFwcGVhcnMiLCB7IHN0YXRlVGF4OiByLnN0YXRlVGF4IH0pOwogICAgfSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJOWUMgZXN0aW1hdGUgb25seSB3aGVuIE5ZQyByZXNpZGVudCIsIHsKICAgICAgc3RhdGVPZlJlc2lkZW5jZTogIk5ZIiwKICAgICAgaXNOWUNSZXNpZGVudDogdHJ1ZQogICAgfSwgZnVuY3Rpb24gKHIpIHsKICAgICAgY29uc3Qgd2l0aE5ZQyA9IHIubG9jYWxUYXggPiAwOwogICAgICBjb25zdCB3aXRob3V0ID0gd2luZG93LklUQkNhcGl0YWxHYWluc0NhbGN1bGF0b3IuY2FsY3VsYXRlQ2FwaXRhbEdhaW5zU2NlbmFyaW8oYmFzZUlucHV0KHsgc3RhdGVPZlJlc2lkZW5jZTogIk5ZIiwgaXNOWUNSZXNpZGVudDogZmFsc2UgfSkpLmxvY2FsVGF4ID09PSAwOwogICAgICByZXR1cm4gYXNzZXJ0Q29uZGl0aW9uKHdpdGhOWUMgJiYgd2l0aG91dCwgIk5ZQyBsb2NhbCB0YXggZ2F0ZWQgYnkgTllDIHJlc2lkZW5jeSIsIHsgd2l0aE5ZQzogci5sb2NhbFRheCwgd2l0aG91dCB9KTsKICAgIH0pKTsKICAgIHRlc3RzLnB1c2gocnVuQ2FzZSgiTWFudWFsIHN0YXRlL2xvY2FsIGNhcGl0YWwgZ2FpbiByYXRlIHJlcGxhY2VzIGJ1aWx0LWluIHN0YXRlIGFuZCBsb2NhbCB0YXgiLCB7CiAgICAgIHN0YXRlT2ZSZXNpZGVuY2U6ICJOWSIsCiAgICAgIGlzTllDUmVzaWRlbnQ6IHRydWUsCiAgICAgIHN0YXRlTG9jYWxSYXRlT3ZlcnJpZGU6IDIuNDY4CiAgICB9LCBmdW5jdGlvbiAocikgewogICAgICBjb25zdCBidWlsdEluID0gd2luZG93LklUQkNhcGl0YWxHYWluc0NhbGN1bGF0b3IuY2FsY3VsYXRlQ2FwaXRhbEdhaW5zU2NlbmFyaW8oYmFzZUlucHV0KHsgc3RhdGVPZlJlc2lkZW5jZTogIk5ZIiwgaXNOWUNSZXNpZGVudDogdHJ1ZSB9KSk7CiAgICAgIGNvbnN0IGV4cGVjdGVkVG90YWwgPSByLmZlZGVyYWxDYXBpdGFsR2FpbnNUYXggKyByLmZlZGVyYWxPcmRpbmFyeUluY29tZVRheE9uU2hvcnRUZXJtR2FpbiArIHIuY29sbGVjdGlibGVzVGF4ICsgci5kZXByZWNpYXRpb25SZWNhcHR1cmVUYXggKyByLm5paXQgKyAxMjM0OwogICAgICBjb25zdCBoYXNNYW51YWxSb3cgPSByLmRpc3BsYXlSb3dzLnNvbWUoZnVuY3Rpb24gKHJvdykgeyByZXR1cm4gcm93WzBdID09PSAiT3ZlcnJpZGUgc3RhdGUvbG9jYWwgdGF4IG9uIHRoaXMgZ2FpbiIgJiYgcm93WzFdID09PSAiJDEsMjM0IjsgfSk7CiAgICAgIGNvbnN0IGhhc05vTG9jYWxSb3cgPSAhci5kaXNwbGF5Um93cy5zb21lKGZ1bmN0aW9uIChyb3cpIHsgcmV0dXJuIC9OWUMgcmVzaWRlbnQgdGF4IGVzdGltYXRlfExvY2FsIHRheCBlc3RpbWF0ZS8udGVzdChyb3dbMF0pOyB9KTsKICAgICAgcmV0dXJuIGFzc2VydENvbmRpdGlvbigKICAgICAgICBNYXRoLmFicyhyLnN0YXRlVGF4IC0gMTIzNCkgPCAwLjAxICYmCiAgICAgICAgci5sb2NhbFRheCA9PT0gMCAmJgogICAgICAgIE1hdGguYWJzKHIudG90YWxFc3RpbWF0ZWRUYXggLSBleHBlY3RlZFRvdGFsKSA8IDAuMDEgJiYKICAgICAgICBidWlsdEluLmxvY2FsVGF4ID4gMCAmJgogICAgICAgIGhhc01hbnVhbFJvdyAmJgogICAgICAgIGhhc05vTG9jYWxSb3csCiAgICAgICAgIm1hbnVhbCBzdGF0ZS9sb2NhbCBjYXBpdGFsIGdhaW4gcmF0ZSBpcyBjb3VudGVkIG9uY2UiLAogICAgICAgIHsgc3RhdGVUYXg6IHIuc3RhdGVUYXgsIGxvY2FsVGF4OiByLmxvY2FsVGF4LCB0b3RhbEVzdGltYXRlZFRheDogci50b3RhbEVzdGltYXRlZFRheCwgZXhwZWN0ZWRUb3RhbCwgYnVpbHRJbkxvY2FsVGF4OiBidWlsdEluLmxvY2FsVGF4LCBoYXNNYW51YWxSb3csIGhhc05vTG9jYWxSb3cgfQogICAgICApOwogICAgfSkpOwogICAgdGVzdHMucHVzaCgoZnVuY3Rpb24gKCkgewogICAgICBjb25zdCBjb3B5YWJsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICBjb3B5YWJsZS5zZXRBdHRyaWJ1dGUoImRhdGEtY29weWFibGUtcmVzdWx0cyIsICIiKTsKICAgICAgY29weWFibGUuaW5uZXJIVE1MID0gIjxkaXY+UmVzdWx0IG9ubHk8L2Rpdj4iOwogICAgICBjb25zdCBhZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICBhZC50ZXh0Q29udGVudCA9ICJBZHZlcnRpc2VtZW50IjsKICAgICAgY29uc3QgcGFzcyA9ICFjb3B5YWJsZS5pbm5lclRleHQuaW5jbHVkZXMoIkFkdmVydGlzZW1lbnQiKTsKICAgICAgY29uc29sZS5sb2coKHBhc3MgPyAiUEFTUyIgOiAiRkFJTCIpICsgIiAtIENvcHkgUmVzdWx0cyBleGNsdWRlcyBhZHZlcnRpc2VtZW50IHBsYWNlaG9sZGVycyIpOwogICAgICByZXR1cm4gcGFzczsKICAgIH0oKSkpOwogICAgdGVzdHMucHVzaChydW5DYXNlKCJFZmZlY3RpdmUgdGF4IHJhdGUgdXNlcyB0YXhhYmxlIGdhaW4gYXMgZGVub21pbmF0b3IiLCB7CiAgICAgIHN0YXRlT2ZSZXNpZGVuY2U6ICJGTCIKICAgIH0sIGZ1bmN0aW9uIChyKSB7CiAgICAgIHJldHVybiBhc3NlcnRBcHByb3hFcXVhbChyLmVmZmVjdGl2ZVRheFJhdGVPbkdhaW4sIHIudG90YWxFc3RpbWF0ZWRUYXggLyByLnRheGFibGVHYWluLCAwLjAwMDEsICJlZmZlY3RpdmUgcmF0ZSBkZW5vbWluYXRvciIpOwogICAgfSkpOwogICAgY29uc3QgcGFzc2VkID0gdGVzdHMuZmlsdGVyKEJvb2xlYW4pLmxlbmd0aDsKICAgIGNvbnNvbGUubG9nKCJDYXBpdGFsIGdhaW5zIGNhbGN1bGF0b3IgdGVzdHMgY29tcGxldGU6IiwgcGFzc2VkICsgIi8iICsgdGVzdHMubGVuZ3RoICsgIiBwYXNzZWQiKTsKICAgIHJldHVybiB7IHBhc3NlZCwgdG90YWw6IHRlc3RzLmxlbmd0aCB9OwogIH07Cn0pKCk7Cg==\"))();<\/script>\n<script type=\"application\/ld+json\">{\"@context\":\"https:\/\/schema.org\",\"@type\":\"WebApplication\",\"name\":\"2026 Capital Gains Tax Calculator\",\"applicationCategory\":\"FinanceApplication\",\"operatingSystem\":\"Web\",\"description\":\"A browser-based planning calculator for estimating federal capital gains tax, Net Investment Income Tax, state tax, local tax where applicable, total estimated tax, and after-tax proceeds.\",\"offers\":{\"@type\":\"Offer\",\"price\":\"0\",\"priceCurrency\":\"USD\"},\"url\":\"https:\/\/incometaxbill.com\/wp\/capital-gains-tax-calculator\/\"}<\/script>\n<script type=\"application\/ld+json\">{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"What is capital gains tax?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Capital gains tax is tax on profit from selling an asset for more than its tax basis. Stocks, ETFs, mutual funds, crypto, real estate, collectibles, and other investments may create capital gains when sold.\"}},{\"@type\":\"Question\",\"name\":\"What is the difference between short-term and long-term capital gains?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Short-term capital gains generally apply to assets held for one year or less and are usually taxed like ordinary income. Long-term capital gains generally apply to assets held for more than one year and may qualify for lower federal tax rates.\"}},{\"@type\":\"Question\",\"name\":\"How do capital gains tax brackets work?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Federal long-term capital gains brackets are graduated. Part of a gain may fall in the 0% bracket, another part may fall in the 15% bracket, and high-income gains may reach the 20% bracket. This calculator estimates the gain across brackets instead of applying one flat rate to the entire gain.\"}},{\"@type\":\"Question\",\"name\":\"Does this calculator include state capital gains tax?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes, where state data is available. Many states tax capital gains as ordinary income, some states have no broad individual income tax, and some states have special capital gains rules. State results are labeled as simplified when appropriate.\"}},{\"@type\":\"Question\",\"name\":\"Does New York tax capital gains?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"New York generally taxes capital gains through its regular income tax system. New York City residents may also owe New York City resident income tax.\"}},{\"@type\":\"Question\",\"name\":\"Do states without income tax have capital gains tax?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"States without a broad individual income tax generally do not tax capital gains through a regular state income tax in this simplified model. Other taxes or special rules may still apply.\"}},{\"@type\":\"Question\",\"name\":\"Does this calculator include Net Investment Income Tax?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. The calculator estimates the 3.8% Net Investment Income Tax when income appears to exceed the applicable threshold. If modified adjusted gross income is not entered, the NIIT result is simplified.\"}},{\"@type\":\"Question\",\"name\":\"Does this calculator handle home sale exclusions?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"It includes a simplified primary residence exclusion estimate for users who indicate they may qualify. The full home sale exclusion has detailed eligibility rules, so the result should not be treated as a tax return calculation.\"}},{\"@type\":\"Question\",\"name\":\"Does this calculator handle crypto gains?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes, basic crypto sales can be entered like other investment sales. The calculator estimates gain based on sale price, basis, expenses, holding period, and tax profile. It does not import exchange records or prepare Form 8949.\"}},{\"@type\":\"Question\",\"name\":\"Does this calculator handle collectibles?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"It includes a simplified collectibles estimate. Collectibles may be taxed differently from ordinary long-term capital gains, so users should confirm treatment before relying on the result.\"}},{\"@type\":\"Question\",\"name\":\"Why is this only an estimate?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Capital gains tax can depend on exact income, basis, holding period, losses, asset type, depreciation, exclusions, state law, local tax rules, and other facts. This calculator is a planning tool, not a tax return.\"}}]}<\/script>\n","protected":false},"excerpt":{"rendered":"<p>Estimate 2026 capital gains tax on stocks, crypto, real estate, collectibles, and other asset sales with federal and state planning inputs.<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"class_list":["post-201","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/pages\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":13,"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/pages\/201\/revisions"}],"predecessor-version":[{"id":457,"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/pages\/201\/revisions\/457"}],"wp:attachment":[{"href":"https:\/\/incometaxbill.com\/wp\/wp-json\/wp\/v2\/media?parent=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}