~evanj/cms

8efa6eb4fd1aad49d40bb3850530c531add998da — Evan M Jones 6 months ago 4ad0cb1
WIP(stripe): *.
122 files changed, 17141 insertions(+), 40 deletions(-)

M TODO
M cms.go
M go.mod
M go.sum
M internal/c/doc/doc.go
A internal/c/stripe/stripe.go
A internal/c/stripe/stripe_test.go
M internal/c/user/user.go
M internal/m/tier/tier.go
M internal/s/db/db.go
A internal/s/db/sql/00001.sql
A internal/s/stripe/stripe.go
A internal/s/stripe/stripe_test.go
M internal/s/tmpl/html/_header.html
M internal/s/tmpl/html/index.html
A internal/s/tmpl/html/stripe.html
M internal/s/tmpl/tmpls_embed.go
A vendor/github.com/stripe/stripe-go/v71/.gitignore
A vendor/github.com/stripe/stripe-go/v71/.travis.yml
A vendor/github.com/stripe/stripe-go/v71/CHANGELOG
A vendor/github.com/stripe/stripe-go/v71/CHANGELOG.md
A vendor/github.com/stripe/stripe-go/v71/CODE_OF_CONDUCT.md
A vendor/github.com/stripe/stripe-go/v71/LICENSE
A vendor/github.com/stripe/stripe-go/v71/Makefile
A vendor/github.com/stripe/stripe-go/v71/README.md
A vendor/github.com/stripe/stripe-go/v71/VERSION
A vendor/github.com/stripe/stripe-go/v71/account.go
A vendor/github.com/stripe/stripe-go/v71/accountlink.go
A vendor/github.com/stripe/stripe-go/v71/address.go
A vendor/github.com/stripe/stripe-go/v71/applepaydomain.go
A vendor/github.com/stripe/stripe-go/v71/application.go
A vendor/github.com/stripe/stripe-go/v71/balance.go
A vendor/github.com/stripe/stripe-go/v71/balancetransaction.go
A vendor/github.com/stripe/stripe-go/v71/bankaccount.go
A vendor/github.com/stripe/stripe-go/v71/billingportal_session.go
A vendor/github.com/stripe/stripe-go/v71/bitcoinreceiver.go
A vendor/github.com/stripe/stripe-go/v71/bitcointransaction.go
A vendor/github.com/stripe/stripe-go/v71/capability.go
A vendor/github.com/stripe/stripe-go/v71/card.go
A vendor/github.com/stripe/stripe-go/v71/charge.go
A vendor/github.com/stripe/stripe-go/v71/checkout/session/client.go
A vendor/github.com/stripe/stripe-go/v71/checkout_session.go
A vendor/github.com/stripe/stripe-go/v71/countryspec.go
A vendor/github.com/stripe/stripe-go/v71/coupon.go
A vendor/github.com/stripe/stripe-go/v71/creditnote.go
A vendor/github.com/stripe/stripe-go/v71/currency.go
A vendor/github.com/stripe/stripe-go/v71/customer.go
A vendor/github.com/stripe/stripe-go/v71/customer/client.go
A vendor/github.com/stripe/stripe-go/v71/customerbalancetransaction.go
A vendor/github.com/stripe/stripe-go/v71/discount.go
A vendor/github.com/stripe/stripe-go/v71/dispute.go
A vendor/github.com/stripe/stripe-go/v71/ephemeralkey.go
A vendor/github.com/stripe/stripe-go/v71/error.go
A vendor/github.com/stripe/stripe-go/v71/event.go
A vendor/github.com/stripe/stripe-go/v71/exchangerate.go
A vendor/github.com/stripe/stripe-go/v71/fee.go
A vendor/github.com/stripe/stripe-go/v71/feerefund.go
A vendor/github.com/stripe/stripe-go/v71/file.go
A vendor/github.com/stripe/stripe-go/v71/filelink.go
A vendor/github.com/stripe/stripe-go/v71/form/form.go
A vendor/github.com/stripe/stripe-go/v71/go.mod
A vendor/github.com/stripe/stripe-go/v71/go.sum
A vendor/github.com/stripe/stripe-go/v71/invoice.go
A vendor/github.com/stripe/stripe-go/v71/invoiceitem.go
A vendor/github.com/stripe/stripe-go/v71/issuing_authorization.go
A vendor/github.com/stripe/stripe-go/v71/issuing_card.go
A vendor/github.com/stripe/stripe-go/v71/issuing_cardholder.go
A vendor/github.com/stripe/stripe-go/v71/issuing_dispute.go
A vendor/github.com/stripe/stripe-go/v71/issuing_transaction.go
A vendor/github.com/stripe/stripe-go/v71/iter.go
A vendor/github.com/stripe/stripe-go/v71/lineitem.go
A vendor/github.com/stripe/stripe-go/v71/lineitem/client.go
A vendor/github.com/stripe/stripe-go/v71/log.go
A vendor/github.com/stripe/stripe-go/v71/loginlink.go
A vendor/github.com/stripe/stripe-go/v71/mandate.go
A vendor/github.com/stripe/stripe-go/v71/oauth.go
A vendor/github.com/stripe/stripe-go/v71/order.go
A vendor/github.com/stripe/stripe-go/v71/orderreturn.go
A vendor/github.com/stripe/stripe-go/v71/params.go
A vendor/github.com/stripe/stripe-go/v71/paymentintent.go
A vendor/github.com/stripe/stripe-go/v71/paymentmethod.go
A vendor/github.com/stripe/stripe-go/v71/paymentsource.go
A vendor/github.com/stripe/stripe-go/v71/payout.go
A vendor/github.com/stripe/stripe-go/v71/person.go
A vendor/github.com/stripe/stripe-go/v71/plan.go
A vendor/github.com/stripe/stripe-go/v71/price.go
A vendor/github.com/stripe/stripe-go/v71/product.go
A vendor/github.com/stripe/stripe-go/v71/radar_earlyfraudwarning.go
A vendor/github.com/stripe/stripe-go/v71/radar_valuelist.go
A vendor/github.com/stripe/stripe-go/v71/radar_valuelistitem.go
A vendor/github.com/stripe/stripe-go/v71/recipient.go
A vendor/github.com/stripe/stripe-go/v71/recipienttransfer.go
A vendor/github.com/stripe/stripe-go/v71/refund.go
A vendor/github.com/stripe/stripe-go/v71/reporting_reportrun.go
A vendor/github.com/stripe/stripe-go/v71/reporting_reporttype.go
A vendor/github.com/stripe/stripe-go/v71/reversal.go
A vendor/github.com/stripe/stripe-go/v71/review.go
A vendor/github.com/stripe/stripe-go/v71/setupintent.go
A vendor/github.com/stripe/stripe-go/v71/sigma_scheduledqueryrun.go
A vendor/github.com/stripe/stripe-go/v71/sku.go
A vendor/github.com/stripe/stripe-go/v71/source.go
A vendor/github.com/stripe/stripe-go/v71/sourcetransaction.go
A vendor/github.com/stripe/stripe-go/v71/stripe.go
A vendor/github.com/stripe/stripe-go/v71/sub.go
A vendor/github.com/stripe/stripe-go/v71/subitem.go
A vendor/github.com/stripe/stripe-go/v71/subschedule.go
A vendor/github.com/stripe/stripe-go/v71/taxid.go
A vendor/github.com/stripe/stripe-go/v71/taxrate.go
A vendor/github.com/stripe/stripe-go/v71/terminal_connectiontoken.go
A vendor/github.com/stripe/stripe-go/v71/terminal_location.go
A vendor/github.com/stripe/stripe-go/v71/terminal_reader.go
A vendor/github.com/stripe/stripe-go/v71/threedsecure.go
A vendor/github.com/stripe/stripe-go/v71/token.go
A vendor/github.com/stripe/stripe-go/v71/topup.go
A vendor/github.com/stripe/stripe-go/v71/transfer.go
A vendor/github.com/stripe/stripe-go/v71/usagerecord.go
A vendor/github.com/stripe/stripe-go/v71/usagerecordsummary.go
A vendor/github.com/stripe/stripe-go/v71/v32_migration_guide.md
A vendor/github.com/stripe/stripe-go/v71/v71_migration_guide.md
A vendor/github.com/stripe/stripe-go/v71/webhook/client.go
A vendor/github.com/stripe/stripe-go/v71/webhookendpoint.go
M vendor/modules.txt
M TODO => TODO +1 -0
@@ 5,6 5,7 @@ Official Go API
Depth option on APIs
No zero length varchar
Pay Goatounter
Pay logo: mybrandnewlogo.com
Doc pages: Contact, FAQ, Terms, Privacy 
Restrict file uploads for free users
Object storage implementation BYOB

M cms.go => cms.go +30 -14
@@ 15,31 15,39 @@ import (
	"git.sr.ht/~evanj/cms/internal/c/hook"
	"git.sr.ht/~evanj/cms/internal/c/redirect"
	"git.sr.ht/~evanj/cms/internal/c/space"
	"git.sr.ht/~evanj/cms/internal/c/stripe"
	"git.sr.ht/~evanj/cms/internal/c/user"
	"git.sr.ht/~evanj/cms/internal/s/cache"
	"git.sr.ht/~evanj/cms/internal/s/db"
	webhook "git.sr.ht/~evanj/cms/internal/s/hook"
	libstripe "git.sr.ht/~evanj/cms/internal/s/stripe"
	"git.sr.ht/~evanj/cms/pkg/e3"
	_ "git.sr.ht/~evanj/embed" // For embedding static assets during build.
	"git.sr.ht/~evanj/security"

	_ "git.sr.ht/~evanj/embed" // For embedding static assets during build.
)

var (
	app *App

	port             = os.Getenv("PORT")
	dbtype           = os.Getenv("DBTYPE")
	dbcreds          = os.Getenv("DB")
	url              = os.Getenv("URL")
	secret           = os.Getenv("SECRET")
	memcacheKey      = os.Getenv("MEMCACHE_KEY")
	memcacheServer   = os.Getenv("MEMCACHE_SERVER")
	e3user           = os.Getenv("E3_USER")
	e3pass           = os.Getenv("E3_PASS")
	e3url            = os.Getenv("E3_URL")
	signupEnabled    = os.Getenv("SIGNUP_ENABLE") == "true"
	staticDir        = os.Getenv("STATIC_DIR")
	analyticsEnabled = os.Getenv("ANALYTICS_ENABLE") == "true"
	port                = os.Getenv("PORT")
	dbtype              = os.Getenv("DBTYPE")
	dbcreds             = os.Getenv("DB")
	url                 = os.Getenv("URL")
	secret              = os.Getenv("SECRET")
	memcacheKey         = os.Getenv("MEMCACHE_KEY")
	memcacheServer      = os.Getenv("MEMCACHE_SERVER")
	e3user              = os.Getenv("E3_USER")
	e3pass              = os.Getenv("E3_PASS")
	e3url               = os.Getenv("E3_URL")
	signupEnabled       = os.Getenv("SIGNUP_ENABLE") == "true"
	staticDir           = os.Getenv("STATIC_DIR")
	analyticsEnabled    = os.Getenv("ANALYTICS_ENABLE") == "true"
	stripeSuccessURL    = os.Getenv("STRIPE_SUCCESS_URL")
	stripeErrorURL      = os.Getenv("STRIPE_ERROR_URL")
	stripePK            = os.Getenv("STRIPE_PK")
	stripeSK            = os.Getenv("STRIPE_SK")
	stripeWebhookSecret = os.Getenv("STRIPE_WEBHOOK_SECRET")
)

type App struct {


@@ 100,6 108,7 @@ func init() {

	fs := e3.New(e3user, e3pass, e3url)
	c := c.New(log.New(w, "[cms:content] ", 0), cacher, analyticsEnabled)
	libs := libstripe.New(stripeSuccessURL, stripeErrorURL, stripePK, stripeSK)

	app = &App{
		applogger,


@@ 127,6 136,7 @@ func init() {
				log.New(w, "[cms:user] ", 0),
				cacher,
				signupEnabled,
				libs,
			),
			"hook": hook.New(
				c,


@@ 151,6 161,12 @@ func init() {
				log.New(w, "[cms:doc] ", 0),
				cacher,
			),
			"stripe": http.StripPrefix("/stripe", stripe.New(
				c,
				log.New(w, "[cms:stripe] ", 0),
				cacher,
				stripeWebhookSecret,
			)),
		},
	}
}

M go.mod => go.mod +1 -0
@@ 12,5 12,6 @@ require (
	github.com/golang/mock v1.4.3
	github.com/google/uuid v1.1.1
	github.com/pkg/errors v0.9.1
	github.com/stripe/stripe-go/v71 v71.28.0
	golang.org/x/sync v0.0.0-20190423024810-112230192c58
)

M go.sum => go.sum +16 -0
@@ 10,6 10,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=


@@ 25,6 27,13 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stripe/stripe-go/v71 v71.28.0 h1:9nCL4gvsLuEA8ZA0HGKWWioJbKJaXpL4jA46GGTV03g=
github.com/stripe/stripe-go/v71 v71.28.0/go.mod h1:BXYwMQe+xjYomcy5/qaTGyoyVMTP3wDCHa7DVFvg8+Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=


@@ 33,10 42,13 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=


@@ 44,7 56,11 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20200301222351-066e0c02454c h1:FD7jysxM+EJqg5UYYy3XYDsAiUickFsn4UiaanJkf8c=
golang.org/x/tools v0.0.0-20200301222351-066e0c02454c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

M internal/c/doc/doc.go => internal/c/doc/doc.go +7 -0
@@ 17,6 17,7 @@ var pages = map[string]*template.Template{
	"/page/privacy": tmpl.MustParse("html/privacy.html"),
	"/page/contact": tmpl.MustParse("html/contact.html"),
	"/page/billing": tmpl.MustParse("html/billing.html"),
	"/page/stripe":  tmpl.MustParse("html/stripe.html"),
}

type Doc struct {


@@ 43,7 44,13 @@ func (d *Doc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
		http.NotFound(w, r)
		return
	}

	q := r.URL.Query()

	d.HTML(w, r, page, map[string]interface{}{
		"User": user,
		// Only used for signup billing.
		"StripeCheckoutSessionID": q.Get("StripeCheckoutSessionID"),
		"StripePK":                q.Get("StripePK"),
	})
}

A internal/c/stripe/stripe.go => internal/c/stripe/stripe.go +99 -0
@@ 0,0 1,99 @@
package stripe

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"git.sr.ht/~evanj/cms/internal/c"
	"git.sr.ht/~evanj/cms/internal/m/user"
	"git.sr.ht/~evanj/cms/internal/s/stripe"
	libstripe "github.com/stripe/stripe-go/v71"
	webhook "github.com/stripe/stripe-go/v71/webhook"
)

type StripeEndpoint struct {
	*c.Controller
	log                 *log.Logger
	db                  DBer
	stripeWebhookSecret string
}

type DBer interface {
	UserGetFromToken(token string) (user.User, error)
}

func New(c *c.Controller, l *log.Logger, db DBer, stripeWebhookSecret string) *StripeEndpoint {
	return &StripeEndpoint{c, l, db, stripeWebhookSecret}
}

func (s *StripeEndpoint) webhook(w http.ResponseWriter, r *http.Request) {
	// webhook from Stripe.
	bytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		s.ErrorString(w, r, http.StatusBadRequest, "failed to ready body")
		return
	}

	event, err := webhook.ConstructEvent(bytes, r.Header.Get("Stripe-Signature"), s.stripeWebhookSecret)
	if err != nil {
		s.log.Println("you do not have access")
		s.ErrorString(w, r, http.StatusForbidden, "you do not have access")
		return
	}

	switch event.Type {
	case "payment_intent.succeeded":
		var pi libstripe.PaymentIntent
		err := json.Unmarshal(event.Data.Raw, &pi)
		if err != nil {
			s.Error2(w, r, http.StatusBadRequest, fmt.Errorf("error parsing webhook JSON: %w\n", err))
			return
		}
		if pi.Customer == nil {
			s.ErrorString(w, r, http.StatusBadRequest, "no customer for payment")
			return
		}

		userToken, ok := pi.Customer.Metadata[stripe.KeyUserToken]
		if !ok {
			s.ErrorString(w, r, http.StatusBadRequest, "no user associated with customer")
			return
		}

		user, err := s.db.UserGetFromToken(userToken)
		if err != nil {
			s.ErrorString(w, r, http.StatusBadRequest, "no user for token")
			return
		}

		// TODO: Add payment to user/org.
		_ = user
		s.log.Println("success with getting user from PI")

	default:
		s.Error2(w, r, http.StatusBadRequest, fmt.Errorf("unexpected event type: %s\n", event.Type))
		return
	}

	s.log.Println("successfully completed stripe webhook")
	s.Redirect(w, r, "/")
}

func (s *StripeEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Handle users requests.
	switch r.URL.Path {
	case "/success":
		s.log.Println("redirect user success")
		s.Redirect(w, r, "/")
		return
	case "/error":
		s.log.Println("user error")
		s.ErrorString(w, r, http.StatusInternalServerError, "failed to process request: you have not been charged")
		return
	}

	s.webhook(w, r)
}

A internal/c/stripe/stripe_test.go => internal/c/stripe/stripe_test.go +1 -0
@@ 0,0 1,1 @@
package stripe_test

M internal/c/user/user.go => internal/c/user/user.go +35 -4
@@ 2,8 2,10 @@ package user

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"

	"git.sr.ht/~evanj/cms/internal/c"


@@ 17,6 19,7 @@ var (
	indexHTML   = tmpl.MustParse("html/index.html")
	ErrNoUser   = errors.New("incorrect user credentials")
	ErrNoSignup = errors.New("signups are forbidden at this time")
	ErrNoTier   = errors.New("invalid tier")
)

type User struct {


@@ 24,6 27,7 @@ type User struct {
	log           *log.Logger
	db            dber
	signupEnabled bool
	stripe        Striper
}

type dber interface {


@@ 33,12 37,17 @@ type dber interface {
	SpacesPerUser(user user.User, before int) (space.SpaceList, error)
}

func New(c *c.Controller, log *log.Logger, db dber, signupEnabled bool) *User {
type Striper interface {
	StartCheckout(user user.User, t tier.Tier) (string, string, error)
}

func New(c *c.Controller, log *log.Logger, db dber, signupEnabled bool, s Striper) *User {
	return &User{
		c,
		log,
		db,
		signupEnabled,
		s,
	}
}



@@ 70,15 79,37 @@ func (l *User) signup(w http.ResponseWriter, r *http.Request) {
	username := r.FormValue("username")
	password := r.FormValue("password")
	verify := r.FormValue("verify")
	t, ok := tier.ByName(r.FormValue("tier"))
	if !ok {
		fmt.Println(r.FormValue("tier"))
		l.Error2(w, r, http.StatusBadRequest, ErrNoTier)
		return
	}

	user, err := l.db.UserNew(username, password, verify)
	if err != nil {
		l.Error(w, r, http.StatusBadRequest, err.Error())
		l.Error2(w, r, http.StatusBadRequest, err)
		return
	}

	l.SetCookieUser(w, r, user)
	l.Redirect(w, r, "/")

	if t.Is(tier.Free) {
		l.Redirect(w, r, "/")
		return
	}

	stripeCheckoutSessionID, stripePK, err := l.stripe.StartCheckout(user, t)
	if err != nil {
		l.Error2(w, r, http.StatusInternalServerError, err)
		return
	}

	form := url.Values{
		"StripeCheckoutSessionID": {stripeCheckoutSessionID},
		"StripePK":                {stripePK},
	}

	l.Redirect(w, r, "/page/stripe?"+form.Encode())
}

func (l *User) home(w http.ResponseWriter, r *http.Request) {

M internal/m/tier/tier.go => internal/m/tier/tier.go +40 -15
@@ 1,8 1,8 @@
package tier

type Tier struct {
	Name, Price, TimeUnit string
	Opts                  []TierOpt
	Name, Price, TimeUnit, StripePriceID string
	Opts                                 []TierOpt
}

type TierOpt struct {


@@ 14,6 14,7 @@ var (
		"Free",
		"$0",
		"forever",
		"",
		[]TierOpt{
			{"Non-commercial use"},
			{"One space"},


@@ 27,6 28,7 @@ var (
		"Business",
		"$15",
		"mo",
		"price_1H4Eq2KQkRnlhurZmVtyjumS",
		[]TierOpt{
			{"Commercial use"},
			{"Five spaces"},


@@ 40,6 42,7 @@ var (
		"Enterprise",
		"$50",
		"mo",
		"price_1H4Eq2KQkRnlhurZHul3PwBB",
		[]TierOpt{
			{"Commercial use"},
			{"Unlimited spaces"},


@@ 49,23 52,45 @@ var (
		},
	}

	SelfHost = Tier{
		"Self host",
		"$500",
		"once",
		[]TierOpt{
			{"Commercial use"},
			{"Unlimited spaces"},
			{"Unlimited users"},
			{"Unlimited API requests/min"},
			{"Bring your object storage"},
		},
	}
	// SelfHost = Tier{
	// 	"Self host",
	// 	"$500",
	// 	"once",
	// 	[]TierOpt{
	// 		{"Commercial use"},
	// 		{"Unlimited spaces"},
	// 		{"Unlimited users"},
	// 		{"Unlimited API requests/min"},
	// 		{"Bring your object storage"},
	// 	},
	// }

	Tiers = []Tier{
		Free,
		Business,
		Enterprise,
		SelfHost,
		// SelfHost,
	}
)

func ByName(n string) (Tier, bool) {
	for _, t := range Tiers {
		if t.Name == n {
			return t, true
		}
	}
	return Tier{}, false
}

func ByStripePriceID(n string) (Tier, bool) {
	for _, t := range Tiers {
		if t.StripePriceID == n {
			return t, true
		}
	}
	return Tier{}, false
}

func (t Tier) Is(test Tier) bool {
	return t.Name == test.Name
}

M internal/s/db/db.go => internal/s/db/db.go +3 -3
@@ 99,10 99,10 @@ func NewWithConn(log *log.Logger, sec securer, conn *sql.DB) (*DB, error) {
	return db, nil
}

// createTables does our "migration" -migration in quotes as we just dummy
// migrate does our "migration" -migration in quotes as we just dummy
// attempt to create tables on every server startup and ignore "table already
// exists" errors.
func (db *DB) createTables() []error {
func (db *DB) migrate() []error {
	var errors []error
	var err error



@@ 347,7 347,7 @@ func (db *DB) createTables() []error {
// Mainly, we are runnin CREATE TABLE and some INSERT INTO of predefined
// value types.
func (db *DB) EnsureSetup() error {
	for _, err := range db.createTables() {
	for _, err := range db.migrate() {
		errmsg := err.Error()

		if err != nil && strings.Contains(errmsg, "Table ") && strings.Contains(errmsg, "already exists") {

A internal/s/db/sql/00001.sql => internal/s/db/sql/00001.sql +0 -0
A internal/s/stripe/stripe.go => internal/s/stripe/stripe.go +90 -0
@@ 0,0 1,90 @@
package stripe

import (
	"fmt"

	"git.sr.ht/~evanj/cms/internal/m/tier"
	"git.sr.ht/~evanj/cms/internal/m/user"
	lib "github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/checkout/session"
	"github.com/stripe/stripe-go/v71/customer"
)

const (
	KeyUserToken = "StripeKeyCMSUserID"
)

type Stripe struct {
	sucesssURL, cancelURL string
	pk, sk                string
}

func New(sucesssURL, cancelURL, pk, sk string) Stripe {
	// Stripe sucks.
	lib.Key = sk
	return Stripe{
		sucesssURL, cancelURL,
		pk, sk,
	}
}

func (s Stripe) StartCheckout(user user.User, t tier.Tier) (string, string, error) {
	customerParams := &lib.CustomerParams{
		Params: lib.Params{
			Metadata: map[string]string{
				KeyUserToken: user.Token(),
			},
		},
		Name: lib.String(user.Name()),
	}

	c, err := customer.New(customerParams)
	if err != nil {
		return "", "", err
	}

	params := &lib.CheckoutSessionParams{
		Customer: lib.String(c.ID),
		PaymentMethodTypes: lib.StringSlice([]string{
			"card",
		}),
		LineItems: []*lib.CheckoutSessionLineItemParams{
			&lib.CheckoutSessionLineItemParams{
				Price:    lib.String(t.StripePriceID),
				Quantity: lib.Int64(1),
			},
		},
		Mode:       lib.String("subscription"),
		SuccessURL: lib.String(fmt.Sprintf("%s?session_id={CHECKOUT_SESSION_ID}", s.sucesssURL)),
		CancelURL:  lib.String(s.cancelURL),
	}

	sess, err := session.New(params)
	if err != nil {
		return "", "", err
	}

	return sess.ID, s.pk, nil
}

// func (s Stripe) CompleteCheckout(sessionID string) (tier.Tier, error) {
// 	sess, _ := session.Get(sessionID, nil)
// 	userID, ok := sess.Metadata[KeyUserToken]
// 	if !ok {
// 		return tier.Tier{}, errors.New("no user associated with transaction")
// 	}
//
// 	i := session.ListLineItems(sessionID, nil)
// 	for i.Next() {
// 		li := i.LineItem()
// 		if li.Price != nil {
// 			t, ok := tier.ByStripePriceID(li.Price.ID)
// 			if !ok {
// 				return tier.Tier{}, errors.New("invalid stripe response: checkout not complete")
// 			}
// 			return t, nil
// 		}
// 	}
//
// 	return tier.Tier{}, errors.New("tier subscription could not be found")
// }

A internal/s/stripe/stripe_test.go => internal/s/stripe/stripe_test.go +1 -0
@@ 0,0 1,1 @@
package stripe_test

M internal/s/tmpl/html/_header.html => internal/s/tmpl/html/_header.html +1 -1
@@ 2,7 2,7 @@
  <nav class='container navbar navbar-expand-lg navbar-dark'>
    <a class='navbar-brand' href='/'>
      <img width=50 height=50 src='/static/img/logo-white.svg'>
      Skipper CMS
      <span class='d-none d-lg-inline'>Skipper CMS</span>
    </a>
    <button class='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
      <span class='navbar-toggler-icon'></span>

M internal/s/tmpl/html/index.html => internal/s/tmpl/html/index.html +8 -1
@@ 158,7 158,7 @@
          <h1 class="display-4 text-center mb-5">Pricing</h1>
        </div>
      </div>
      <div class="row row-cols-1 row-cols-md-2 row-cols-xl-4 mb-5 text-center">
      <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 mb-5 text-center">
        {{range .Tiers}}
        <div class="col">
          <div class="card mb-4 shadow-sm">


@@ 258,6 258,13 @@
                    <input name=password type="password" id="signupInputPassword" class="mb-3 form-control" placeholder="Password" required>
                    <label for="signupInputVerify" class="sr-only">Confirm Password</label>
                    <input name=verify type="password" id="signupInputVerify" class="mb-3 form-control" placeholder="Confirm Password" required>
                    <label for="signupInputPlan" class="sr-only">Select tier</label>
                    <select name=tier id="signupInputPlan" class="w-100 form-control mb-3" required>
                      <option disabled selected value>Payment tier</option>
                      {{range .Tiers}}
                        <option value="{{.Name}}">{{.Name}}</option>
                      {{end}}
                    </select>
                    <button class="btn btn-lg btn-primary btn-block" type="submit">Go</button>
                  </form>
                </div>

A internal/s/tmpl/html/stripe.html => internal/s/tmpl/html/stripe.html +31 -0
@@ 0,0 1,31 @@
<!DOCTYPE html>
<html lang=en>
<head>
  {{ template "html/_head.html" }}
  <title>CMS | Docs</title>
</head>
<body class='page bg-light'>
  <style>{{ template "css/main.css" }}</style>
  <main>
    {{ template "html/_header.html" $ }}
    <div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
      <h1 class="display-4">Processing...</h1>
    </div>
    {{ template "html/_footer.html" $ }}
  </main>
  {{ template "html/_scripts.html" }}
  <script src="//js.stripe.com/v3/"></script>
  <script>
    (function() { 
      var stripe = Stripe('{{.StripePK}}');
      var checkoutButton = document.getElementById('checkout-button');
      stripe.redirectToCheckout({
        sessionId: '{{.StripeCheckoutSessionID}}'
      }).then(function (result) {
        console.log(result)
        alert(result.error.message);
      });
    })();
  </script>
</body>
</html>

M internal/s/tmpl/tmpls_embed.go => internal/s/tmpl/tmpls_embed.go +4 -2
@@ 24,7 24,7 @@ func init() {

	tmpls["html/_head.html"] = tostring("PG1ldGEgY2hhcnNldD0ndXRmLTgnPgo8bWV0YSBuYW1lPSd2aWV3cG9ydCcgY29udGVudD0nd2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEnPgo8bGluayByZWw9J2ljb24nIHR5cGU9J2ltYWdlL3gtaWNvbicgaHJlZj0naHR0cHM6Ly9mYXZpY29uLmV2YW5qb24uZXMvMC8xMDUvMjE3LzMyL2Zhdmljb24uaWNvJyAvPgo8bGluayByZWw9J3N0eWxlc2hlZXQnIGhyZWY9Jy9zdGF0aWMvY3NzL2Jvb3RzdHJhcC5taW4uY3NzJyAvPgo=")

	tmpls["html/_header.html"] = tostring("PGhlYWRlciBjbGFzcz0nYmctcHJpbWFyeSc+CiAgPG5hdiBjbGFzcz0nY29udGFpbmVyIG5hdmJhciBuYXZiYXItZXhwYW5kLWxnIG5hdmJhci1kYXJrJz4KICAgIDxhIGNsYXNzPSduYXZiYXItYnJhbmQnIGhyZWY9Jy8nPgogICAgICA8aW1nIHdpZHRoPTUwIGhlaWdodD01MCBzcmM9Jy9zdGF0aWMvaW1nL2xvZ28td2hpdGUuc3ZnJz4KICAgICAgU2tpcHBlciBDTVMKICAgIDwvYT4KICAgIDxidXR0b24gY2xhc3M9J25hdmJhci10b2dnbGVyJyB0eXBlPSdidXR0b24nIGRhdGEtdG9nZ2xlPSdjb2xsYXBzZScgZGF0YS10YXJnZXQ9JyNuYXZiYXJTdXBwb3J0ZWRDb250ZW50JyBhcmlhLWNvbnRyb2xzPSduYXZiYXJTdXBwb3J0ZWRDb250ZW50JyBhcmlhLWV4cGFuZGVkPSdmYWxzZScgYXJpYS1sYWJlbD0nVG9nZ2xlIG5hdmlnYXRpb24nPgogICAgICA8c3BhbiBjbGFzcz0nbmF2YmFyLXRvZ2dsZXItaWNvbic+PC9zcGFuPgogICAgPC9idXR0b24+CiAgICA8ZGl2IGNsYXNzPSdjb2xsYXBzZSBuYXZiYXItY29sbGFwc2UnIGlkPSduYXZiYXJTdXBwb3J0ZWRDb250ZW50Jz4KICAgICAgPHVsIGNsYXNzPSduYXZiYXItbmF2IG1sLWF1dG8nPgogICAgICAgIHt7IGlmIC5TcGFjZSB9fQogICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nLyc+SG9tZTwvYT48L2xpPgogICAgICAgIHt7IGVuZCB9fQogICAgICAgIHt7IGlmIC5Db250ZW50VHlwZSB9fQogICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nL3NwYWNlL3t7IC5TcGFjZS5JRCB9fSc+e3sgLlNwYWNlLk5hbWUgfX08L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiAuSG9vayB9fQogICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nL3NwYWNlL3t7IC5TcGFjZS5JRCB9fSc+e3sgLlNwYWNlLk5hbWUgfX08L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiAuQ29udGVudCB9fQogICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nL2NvbnRlbnR0eXBlL3t7IC5TcGFjZS5JRH19L3t7IC5Db250ZW50VHlwZS5JRCB9fSc+e3sgLkNvbnRlbnRUeXBlLk5hbWUgfX08L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiBhbmQgLlNwYWNlIChub3QgLkNvbnRlbnRUeXBlKSAobm90IC5Ib29rKSB9fQogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2NvcHlNb2RhbCIgY2xhc3M9J25hdi1saW5rJyBocmVmPScjJz5Db3B5PC9hPjwvbGk+CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjdXBkYXRlTW9kYWwiIGNsYXNzPSduYXYtbGluaycgaHJlZj0nIyc+VXBkYXRlPC9hPjwvbGk+CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjZGVsZXRlTW9kYWwiIGNsYXNzPSduYXYtbGluaycgaHJlZj0nIyc+RGVsZXRlPC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgYW5kIC5Db250ZW50VHlwZSAobm90IC5Db250ZW50KSB9fQogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI3VwZGF0ZU1vZGFsIiBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9JyMnPlVwZGF0ZTwvYT48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2RlbGV0ZU1vZGFsIiBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9JyMnPkRlbGV0ZTwvYT48L2xpPgogICAgICAgIHt7IGVuZCB9fQogICAgICAgIHt7IGlmIC5Db250ZW50IH19CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48aW5wdXQgdHlwZT1zdWJtaXQgY2xhc3M9ImJ0biBidG4tbGluayBuYXYtbGluayBib3JkZXItMCIgdmFsdWU9U2F2ZSAvPjwvbGk+CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjZGVsZXRlTW9kYWwiIGNsYXNzPSduYXYtbGluaycgaHJlZj0nIyc+RGVsZXRlPC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgLkhvb2sgfX0KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNkZWxldGVNb2RhbCIgY2xhc3M9J25hdi1saW5rJyBocmVmPScjJz5EZWxldGU8L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiAuVXNlciB9fQogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+CiAgICAgICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3VzZXIvbG9nb3V0JyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1zdWJtaXQgY2xhc3M9ImJ0biBidG4tbGluayBuYXYtbGluayBib3JkZXItMCIgdmFsdWU9TG9nb3V0IC8+CiAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgIDwvbGk+CiAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgY2xhc3M9J25hdi1saW5rJyBocmVmPScvI3NpZ251cCc+U2lnbnVwPC9hPjwvbGk+CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy8jbG9naW4nPkxvZ2luPC9hPjwvbGk+CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy8jcHJpY2luZyc+UHJpY2luZzwvYT48L2xpPgogICAgICAgIHt7IGVuZH19CiAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgY2xhc3M9J25hdi1saW5rJyBocmVmPScvcGFnZS9kb2MnPkRvY3M8L2E+PC9saT4KICAgICAgPC91bD4KICAgIDwvZGl2PgogIDwvbmF2Pgo8L2hlYWRlcj4K")
	tmpls["html/_header.html"] = tostring("PGhlYWRlciBjbGFzcz0nYmctcHJpbWFyeSc+CiAgPG5hdiBjbGFzcz0nY29udGFpbmVyIG5hdmJhciBuYXZiYXItZXhwYW5kLWxnIG5hdmJhci1kYXJrJz4KICAgIDxhIGNsYXNzPSduYXZiYXItYnJhbmQnIGhyZWY9Jy8nPgogICAgICA8aW1nIHdpZHRoPTUwIGhlaWdodD01MCBzcmM9Jy9zdGF0aWMvaW1nL2xvZ28td2hpdGUuc3ZnJz4KICAgICAgPHNwYW4gY2xhc3M9J2Qtbm9uZSBkLWxnLWlubGluZSc+U2tpcHBlciBDTVM8L3NwYW4+CiAgICA8L2E+CiAgICA8YnV0dG9uIGNsYXNzPSduYXZiYXItdG9nZ2xlcicgdHlwZT0nYnV0dG9uJyBkYXRhLXRvZ2dsZT0nY29sbGFwc2UnIGRhdGEtdGFyZ2V0PScjbmF2YmFyU3VwcG9ydGVkQ29udGVudCcgYXJpYS1jb250cm9scz0nbmF2YmFyU3VwcG9ydGVkQ29udGVudCcgYXJpYS1leHBhbmRlZD0nZmFsc2UnIGFyaWEtbGFiZWw9J1RvZ2dsZSBuYXZpZ2F0aW9uJz4KICAgICAgPHNwYW4gY2xhc3M9J25hdmJhci10b2dnbGVyLWljb24nPjwvc3Bhbj4KICAgIDwvYnV0dG9uPgogICAgPGRpdiBjbGFzcz0nY29sbGFwc2UgbmF2YmFyLWNvbGxhcHNlJyBpZD0nbmF2YmFyU3VwcG9ydGVkQ29udGVudCc+CiAgICAgIDx1bCBjbGFzcz0nbmF2YmFyLW5hdiBtbC1hdXRvJz4KICAgICAgICB7eyBpZiAuU3BhY2UgfX0KICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy8nPkhvbWU8L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiAuQ29udGVudFR5cGUgfX0KICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy9zcGFjZS97eyAuU3BhY2UuSUQgfX0nPnt7IC5TcGFjZS5OYW1lIH19PC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgLkhvb2sgfX0KICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy9zcGFjZS97eyAuU3BhY2UuSUQgfX0nPnt7IC5TcGFjZS5OYW1lIH19PC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgLkNvbnRlbnQgfX0KICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9Jy9jb250ZW50dHlwZS97eyAuU3BhY2UuSUR9fS97eyAuQ29udGVudFR5cGUuSUQgfX0nPnt7IC5Db250ZW50VHlwZS5OYW1lIH19PC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgYW5kIC5TcGFjZSAobm90IC5Db250ZW50VHlwZSkgKG5vdCAuSG9vaykgfX0KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNjb3B5TW9kYWwiIGNsYXNzPSduYXYtbGluaycgaHJlZj0nIyc+Q29weTwvYT48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI3VwZGF0ZU1vZGFsIiBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9JyMnPlVwZGF0ZTwvYT48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2RlbGV0ZU1vZGFsIiBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9JyMnPkRlbGV0ZTwvYT48L2xpPgogICAgICAgIHt7IGVuZCB9fQogICAgICAgIHt7IGlmIGFuZCAuQ29udGVudFR5cGUgKG5vdCAuQ29udGVudCkgfX0KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiN1cGRhdGVNb2RhbCIgY2xhc3M9J25hdi1saW5rJyBocmVmPScjJz5VcGRhdGU8L2E+PC9saT4KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNkZWxldGVNb2RhbCIgY2xhc3M9J25hdi1saW5rJyBocmVmPScjJz5EZWxldGU8L2E+PC9saT4KICAgICAgICB7eyBlbmQgfX0KICAgICAgICB7eyBpZiAuQ29udGVudCB9fQogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGlucHV0IHR5cGU9c3VibWl0IGNsYXNzPSJidG4gYnRuLWxpbmsgbmF2LWxpbmsgYm9yZGVyLTAiIHZhbHVlPVNhdmUgLz48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2RlbGV0ZU1vZGFsIiBjbGFzcz0nbmF2LWxpbmsnIGhyZWY9JyMnPkRlbGV0ZTwvYT48L2xpPgogICAgICAgIHt7IGVuZCB9fQogICAgICAgIHt7IGlmIC5Ib29rIH19CiAgICAgICAgICA8bGkgY2xhc3M9J25hdi1pdGVtJz48YSBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjZGVsZXRlTW9kYWwiIGNsYXNzPSduYXYtbGluaycgaHJlZj0nIyc+RGVsZXRlPC9hPjwvbGk+CiAgICAgICAge3sgZW5kIH19CiAgICAgICAge3sgaWYgLlVzZXIgfX0KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPgogICAgICAgICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy91c2VyL2xvZ291dCcgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9c3VibWl0IGNsYXNzPSJidG4gYnRuLWxpbmsgbmF2LWxpbmsgYm9yZGVyLTAiIHZhbHVlPUxvZ291dCAvPgogICAgICAgICAgICA8L2Zvcm0+CiAgICAgICAgICA8L2xpPgogICAgICAgIHt7IGVsc2UgfX0KICAgICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nLyNzaWdudXAnPlNpZ251cDwvYT48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgY2xhc3M9J25hdi1saW5rJyBocmVmPScvI2xvZ2luJz5Mb2dpbjwvYT48L2xpPgogICAgICAgICAgPGxpIGNsYXNzPSduYXYtaXRlbSc+PGEgY2xhc3M9J25hdi1saW5rJyBocmVmPScvI3ByaWNpbmcnPlByaWNpbmc8L2E+PC9saT4KICAgICAgICB7eyBlbmR9fQogICAgICAgIDxsaSBjbGFzcz0nbmF2LWl0ZW0nPjxhIGNsYXNzPSduYXYtbGluaycgaHJlZj0nL3BhZ2UvZG9jJz5Eb2NzPC9hPjwvbGk+CiAgICAgIDwvdWw+CiAgICA8L2Rpdj4KICA8L25hdj4KPC9oZWFkZXI+Cg==")

	tmpls["html/_scripts.html"] = tostring("PHNjcmlwdCBzcmM9Jy9zdGF0aWMvanMvcG9wcGVyLm1pbi5qcyc+PC9zY3JpcHQ+CjxzY3JpcHQgc3JjPScvc3RhdGljL2pzL2Jvb3RzdHJhcC5taW4uanMnPjwvc2NyaXB0Pgo=")



@@ 42,7 42,7 @@ func init() {

	tmpls["html/hook.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19IHwge3sgLkhvb2suVVJMIH19PC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0naG9vayBiZy1saWdodCc+CiAgPHN0eWxlPnt7IHRlbXBsYXRlICJjc3MvbWFpbi5jc3MiIH19PC9zdHlsZT4KICA8bWFpbj4KICAgIHt7IHRlbXBsYXRlICJodG1sL19oZWFkZXIuaHRtbCIgJCB9fQogICAgPGRpdiBjbGFzcz0icHJpY2luZy1oZWFkZXIgcHgtMyBweS0zIHB0LW1kLTUgcGItbWQtNCBteC1hdXRvIHRleHQtY2VudGVyIj4KICAgICAgPGgxIGNsYXNzPSJkaXNwbGF5LTQiPnt7IC5Ib29rLlVSTCB9fTwvaDE+CiAgICA8L2Rpdj4KICAgIDxhcnRpY2xlIGNsYXNzPWNvbnRhaW5lcj4KICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvaG9vaycgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHR5cGU9aGlkZGVuIG5hbWU9bWV0aG9kIHZhbHVlPURFTEVURSAvPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9aG9vayB2YWx1ZT0ie3sgLkhvb2suSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9ImRlbGV0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJkZWxldGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImRlbGV0ZU1vZGFsTGFiZWwiPkRlbGV0ZSB7eyAuSG9vay5VUkwgfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KICAgIDwvZGl2PgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiAkIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvbWFpbi5qcyIgJCB9fTwvc2NyaXB0Pgo8L2JvZHk+CjwvaHRtbD4K")

	tmpls["html/index.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUzwvdGl0bGU+CjwvaGVhZD4KPGJvZHkgY2xhc3M9J2luZGV4IGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICB7e2lmIG5vdCAuVXNlcn19CiAgICA8ZGl2IGNsYXNzPSdjb250YWluZXIgbXktNSc+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIHRleHQtY2VudGVyIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImQtaW5saW5lLWJsb2NrIGFsZXJ0IGFsZXJ0LXdhcm5pbmciIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgPHN0cm9uZz5XQVJOSU5HOjwvc3Ryb25nPiBUaGlzIHNpdGUgaXMgaW4gPHN0cm9uZz5BTFBIQTwvc3Ryb25nPiAKICAgICAgICAgICAgYW5kIGlzIG5vdCB5ZXQgZ2VuZXJhbGx5IGF2YWlsYWJsZS4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAge3tlbmR9fQogICAgPGRpdiBjbGFzcz0icHJpY2luZy1oZWFkZXIgcHgtMyBweS01IHB0LW1kLTUgcGItbWQtNCBteC1hdXRvIHRleHQtY2VudGVyIj4KICAgICAgPGltZyB3aWR0aD0yMDAgaGVpZ2h0PTIwMCBzcmM9Jy9zdGF0aWMvaW1nL2xvZ28tYmxhY2suc3ZnJyAvPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktMSI+U2tpcHBlciBDTVM8L2gxPgogICAgICA8cCBjbGFzcz0ibGVhZCI+QW4gb2xkLXNjaG9vbCBjb250ZW50IG1hbmFnZW1lbnQgc3lzdGVtIGZvciBtb3N0LjwvcD4KICAgIDwvZGl2PgogICAge3tpZiBub3QgLlVzZXJ9fQogICAgPGRpdiBjbGFzcz0nY29udGFpbmVyIG15LTUnPgogICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTInPgogICAgICAgICAgPGgyIGNsYXNzPSdkaXNwbGF5LTQgdGV4dC1jZW50ZXInPkNvbnRlbnQgTWFuYWdlbWVudCBTeXN0ZW0gKENNUyk8L2gyPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBvZmZzZXQtbGctMiBjb2wtbGctOCc+CiAgICAgICAgICA8dGFibGU+CiAgICAgICAgICAgIDx0ciB2YWxpZ249dG9wPgogICAgICAgICAgICAgIDx0ZD4KICAgICAgICAgICAgICAgIDxwIGNsYXNzPSdtci0zJz48c3Ryb25nPk5vdW4uPC9zdHJvbmc+PC9wPgogICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgICAgPHRkPgogICAgICAgICAgICAgICAgPHA+QSBjb21wdXRlciBzb2Z0d2FyZSBzeXN0ZW0gZm9yIG9yZ2FuaXppbmcgYW5kIGZhY2lsaXRhdGluZyBjb2xsYWJvcmF0aXZlIGNyZWF0aW9uIG9mIGRvY3VtZW50cyBhbmQgb3RoZXIgY29udGVudCwgZXNwZWNpYWxseSBmb3IgZGlzcGxheWluZyBjb250ZW50IHRvIGEgd2Vic2l0ZSBvciBtb2JpbGUgYXBwbGljYXRpb24uPC9wPgogICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgIDwvdHI+CiAgICAgICAgICA8L3RhYmxlPgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0nY29udGFpbmVyIG15LTUnPgogICAgICA8ZGl2IGNsYXNzPSJyb3ciPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCB0ZXh0LWNlbnRlciBtYi01Ij5GZWF0dXJlczwvaDE+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPXJvdz4KCiAgICAgICAgPGRpdiBjbGFzcz0nY29sIGNvbC0xMiBjb2wtbWQtNic+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkIG1iLTMnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLWJvZHknPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtdGV4dCc+CiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfQVBJJz5BUEk8L2E+CiAgICAgICAgICAgICAgICBmaXJzdCBDTVMuIFNraXBwZXIgaXMgYSBmdWxseS1mbGVkZ2VkIGNvbnRlbnQgCiAgICAgICAgICAgICAgICBtYW5hZ2VtZW50IDxtYXJrPmluZnJhc3RydWN0dXJlPC9tYXJrPiBhcyBtdWNoIGFzIGl0IGlzIGEKICAgICAgICAgICAgICAgIGNvbnRlbnQgbWFuYWdlbWVudCBzeXN0ZW0uIAogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIFlvdXIgY29udGVudCBtb2RlbCB5b3VyIHdheS4gWW91J3JlIDxtYXJrPm5ldmVyCiAgICAgICAgICAgICAgICByZXN0cmljdGVkPC9tYXJrPiB0byBhCiAgICAgICAgICAgICAgICBibGVzc2VkIGNvbnRlbnQgbW9kZWwsIGEgbGEgY2F0ZWdvcnkvdGFncyBmb3IgcGFnZXMvcG9zdHMuIAogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkxpZ2h0d2VpZ2h0PC9tYXJrPiBhbmQgPG1hcms+ZmFzdDwvbWFyaz47IEFQSSBjYWxscyB0bwogICAgICAgICAgICAgICAgU2tpcHBlciBDTVMgd2lsbCBub3QgYmUgeW91ciBib3R0bGVuZWNrLiBTa2lwcGVyIENNUyBtYWtlcyBoZWF2eQogICAgICAgICAgICAgICAgdXNlIG9mIGNhY2hpbmcuCiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTIgY29sLW1kLTYnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZCBtYi0zJz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC1ib2R5Jz4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLXRleHQnPgogICAgICAgICAgICAgICAgMTAwJSBjb21taXR0ZWQgdG8gPG1hcms+b3BlbiBzb3VyY2U8L21hcms+OyB5b3UgY2FuIHNlZSBleGFjdGx5IHdoYXQgdGhlIGNvZGUKICAgICAgICAgICAgICAgIGRvZXMgYW5kIG1ha2UgaW1wcm92ZW1lbnRzLiBTZWUgCiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2dpdC5zci5odC9+ZXZhbmovY21zJz5zb3VyY2VodXQ8L2E+LgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkVhc3k8L21hcms+IHRvIHVzZSBmb3IgPG1hcms+YWxsPC9tYXJrPi4gV2Uga2VlcCBhIGJpZwogICAgICAgICAgICAgICAgdGVudC4gTm8gbWF0dGVyIHlvdXIgYmFja2dyb3VuZCwgU2tpcHBlciBDTVMgaXMgY29tbWl0dGVkIHRvCiAgICAgICAgICAgICAgICBhc3Npc3RpbmcgeW91IHdlbGwuCiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTIgY29sLW1kLTYnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZCBtYi0zJz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC1ib2R5Jz4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLXRleHQnPgogICAgICAgICAgICAgICAgPG1hcms+UXVpY2tseTwvbWFyaz4gc2V0dXAgc3RhZ2luZyBhbmQgdGVzdCBlbnZpcm9ubWVudHMgZm9yCiAgICAgICAgICAgICAgICB5b3VyIGRhdGEuIFRhaWxvcmVkIHVzZSBmb3IgPG1hcms+eW91ciBlbnZpcm9ubWVudHM8L21hcms+LgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkFwcHJvYWNoYWJsZTwvbWFyaz4gCiAgICAgICAgICAgICAgICBkb2N1bWVudGlvbi4gRXhhbXBsZXMgcHJvdmlkZWQgaW4gCiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2xpbnV4LmRpZS5uZXQvbWFuLzEvY3VybCc+Y1VSTDwvYT4uCiAgICAgICAgICAgICAgICBVc2UgZnJvbSB5b3VyIHByb2dyYW1taW5nIGxhbmd1YWdlIG9yIHJ1bnRpbWUgb2YgY2hvaWNlLgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkZyZWVkb208L21hcms+IHJlc3BlY3RpbmcgbGljZW5zZS4gVGhlIAogICAgICAgICAgICAgICAgPGEgaHJlZj0naHR0cDovL3d3dy5nbnUub3JnL3BoaWxvc29waHkvZnJlZS1zdy5odG1sI2NvbnRlbnQnPmZvdXIgZXNzZW50aWFsIGZyZWVkb21zPC9hPiAKICAgICAgICAgICAgICAgIGFyZSB1cGhlbGQgdW5kZXIgdGhlIEVVUEwgdjEuMiBsaWNlbnNlLiBDb21wYXRpYmxlIHdpdGggQUdQTCB2My4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSdjb250YWluZXIgbXktNSc+CiAgICAgIDxkaXYgaWQ9J3ByaWNpbmcnIGNsYXNzPSJyb3ciPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCB0ZXh0LWNlbnRlciBtYi01Ij5QcmljaW5nPC9oMT4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9InJvdyByb3ctY29scy0xIHJvdy1jb2xzLW1kLTIgcm93LWNvbHMteGwtNCBtYi01IHRleHQtY2VudGVyIj4KICAgICAgICB7e3JhbmdlIC5UaWVyc319CiAgICAgICAgPGRpdiBjbGFzcz0iY29sIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20iPgogICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZWFkZXIiPgogICAgICAgICAgICA8aDQgY2xhc3M9Im15LTAgZm9udC13ZWlnaHQtbm9ybWFsIj57ey5OYW1lfX08L2g0PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkiPgogICAgICAgICAgICA8aDEgY2xhc3M9ImNhcmQtdGl0bGUgcHJpY2luZy1jYXJkLXRpdGxlIj57ey5QcmljZX19IDxzbWFsbCBjbGFzcz0idGV4dC1tdXRlZCI+LyB7ey5UaW1lVW5pdH19PC9zbWFsbD48L2gxPgogICAgICAgICAgICA8dWwgY2xhc3M9Imxpc3QtdW5zdHlsZWQgbXQtMyBtYi00Ij4KICAgICAgICAgICAgICB7e3JhbmdlIC5PcHRzfX0KICAgICAgICAgICAgICAgIDxsaT57ey5UZXh0fX08L2xpPgogICAgICAgICAgICAgIHt7ZW5kfX0KICAgICAgICAgICAgPC91bD4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIHt7ZW5kfX0KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIHt7ZW5kfX0KICAgIDxhcnRpY2xlPgogICAgICB7eyBpZiAuVXNlciB9fQogICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICAgIDxpbnB1dCB0eXBlPWhpZGRlbiBuYW1lPW1ldGhvZCB2YWx1ZT1QT1NUIC8+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZXhhbXBsZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJleGFtcGxlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImV4YW1wbGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcgc3BhY2U8L2g1PgogICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNwYWNlRGVzYyI+RGVzY3JpcHRpb248L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1kZXNjIHR5cGU9dGV4dCBpZD0ic3BhY2VEZXNjIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJEZXNjcmlwdGlvbiIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9mb3JtPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdvZmZzZXQtbGctMyBjb2wtbGctNic+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2V4YW1wbGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHNwYWNlPC9hPgogICAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAgPGg2IGNsYXNzPSJib3JkZXItYm90dG9tIGJvcmRlci1ncmF5IHBiLTIgbWItMCI+WW91ciBzcGFjZXM8L2g2PgogICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5MaXN0IH19CiAgICAgICAgICAgICAgICAgIHt7IHJhbmdlIC5TcGFjZXMuTGlzdCB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtZWRpYSB0ZXh0LW11dGVkIHB0LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9zcGFjZS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICAgICAge3sgLkRlc2MgfX0KICAgICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii8/YmVmb3JlPXt7IC5TcGFjZXMuQmVmb3JlIH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgICBZb3UgaGF2ZW4ndCBjcmVhdGVkIGFueSBzcGFjZXMgeWV0LiAKICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAge3sgZWxzZSB9fQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciBteS01Ij4KICAgICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICAgICAgPGgxIGNsYXNzPSJkaXNwbGF5LTQgdGV4dC1jZW50ZXIgbWItNSI+TGV0J3MgZ288L2gxPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPGRpdiBjbGFzcz0ncm93IGp1c3RpZnktY29udGVudC1jZW50ZXInPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgY29sLW1kLTYgY29sLWxnLTQgb2Zmc2V0LWNvbC1sZy0yIGNvbC14bC0zIG9mZnNldC1jb2wteGwtMyBkLWZsZXgiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20gZmxleC1maWxsIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg0IGNsYXNzPSJteS0wIGZvbnQtd2VpZ2h0LW5vcm1hbCI+U2lnbnVwPC9oND4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGZvcm0gaWQ9J3NpZ251cCcgbWV0aG9kPVBPU1QgYWN0aW9uPScvdXNlci9zaWdudXAnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0VXNlcm5hbWUiIGNsYXNzPSJzci1vbmx5Ij5FbWFpbCBhZGRyZXNzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT11c2VybmFtZSB0eXBlPSJ0ZXh0IiBpZD0ic2lnbnVwSW5wdXRVc2VybmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0UGFzc3dvcmQiIGNsYXNzPSJzci1vbmx5Ij5QYXNzd29yZDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9cGFzc3dvcmQgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFBhc3N3b3JkIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRWZXJpZnkiIGNsYXNzPSJzci1vbmx5Ij5Db25maXJtIFBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT12ZXJpZnkgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFZlcmlmeSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iQ29uZmlybSBQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1sZyBidG4tcHJpbWFyeSBidG4tYmxvY2siIHR5cGU9InN1Ym1pdCI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgY29sLW1kLTYgY29sLWxnLTQgY29sLXhsLTMgZC1mbGV4Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkIG1iLTQgc2hhZG93LXNtIGZsZXgtZmlsbCI+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgIDxoNCBjbGFzcz0ibXktMCBmb250LXdlaWdodC1ub3JtYWwiPkxvZ2luPC9oND4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1ib2R5IGQtZmxleCI+CiAgICAgICAgICAgICAgICAgIDxmb3JtIGlkPSdsb2dpbicgY2xhc3M9J2QtZmxleCBmbGV4LWdyb3ctMSBmbGV4LWNvbHVtbicgbWV0aG9kPVBPU1QgYWN0aW9uPScvdXNlci9sb2dpbicgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ibG9naW5JbnB1dFVzZXJuYW1lIiBjbGFzcz0ic3Itb25seSI+RW1haWwgYWRkcmVzczwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9dXNlcm5hbWUgdHlwZT0idGV4dCIgaWQ9ImxvZ2luSW5wdXRVc2VybmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImxvZ2luSW5wdXRQYXNzd29yZCIgY2xhc3M9InNyLW9ubHkiPlBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1wYXNzd29yZCB0eXBlPSJwYXNzd29yZCIgaWQ9ImxvZ2luSW5wdXRQYXNzd29yZCIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iUGFzc3dvcmQiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9Im10LWF1dG8gYnRuIGJ0bi1sZyBidG4tcHJpbWFyeSBidG4tYmxvY2siIHR5cGU9InN1Ym1pdCI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIHt7IGVuZCB9fQogICAgPC9hcnRpY2xlPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiAkIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CiAge3sgaWYgLlVzZXIgfX0KICAgIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL21haW4uanMiICQgfX08L3NjcmlwdD4KICB7eyBlbHNlIH19CiAgICA8c2NyaXB0PgogICAgICAoZnVuY3Rpb24oKSB7IAogICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgaGFuZGxlSGFzaENsaWNrKTsKICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIGhhbmRsZUhhc2hDbGljayk7CiAgICAgICAgZnVuY3Rpb24gaGFuZGxlSGFzaENsaWNrKCkgeyAKICAgICAgICAgIHZhciBlbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGxvY2F0aW9uLmhhc2guc3Vic3RyKDEpKTsKICAgICAgICAgIGlmIChlbCkgZWwucXVlcnlTZWxlY3RvcignaW5wdXQnKS5mb2N1cygpOwogICAgICAgIH07CiAgICAgIH0pKCk7CiAgICA8L3NjcmlwdD4KICB7eyBlbmQgfX0KPC9ib2R5Pgo8L2h0bWw+Cg==")
	tmpls["html/index.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUzwvdGl0bGU+CjwvaGVhZD4KPGJvZHkgY2xhc3M9J2luZGV4IGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICB7e2lmIG5vdCAuVXNlcn19CiAgICA8ZGl2IGNsYXNzPSdjb250YWluZXIgbXktNSc+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIHRleHQtY2VudGVyIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImQtaW5saW5lLWJsb2NrIGFsZXJ0IGFsZXJ0LXdhcm5pbmciIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgPHN0cm9uZz5XQVJOSU5HOjwvc3Ryb25nPiBUaGlzIHNpdGUgaXMgaW4gPHN0cm9uZz5BTFBIQTwvc3Ryb25nPiAKICAgICAgICAgICAgYW5kIGlzIG5vdCB5ZXQgZ2VuZXJhbGx5IGF2YWlsYWJsZS4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAge3tlbmR9fQogICAgPGRpdiBjbGFzcz0icHJpY2luZy1oZWFkZXIgcHgtMyBweS01IHB0LW1kLTUgcGItbWQtNCBteC1hdXRvIHRleHQtY2VudGVyIj4KICAgICAgPGltZyB3aWR0aD0yMDAgaGVpZ2h0PTIwMCBzcmM9Jy9zdGF0aWMvaW1nL2xvZ28tYmxhY2suc3ZnJyAvPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktMSI+U2tpcHBlciBDTVM8L2gxPgogICAgICA8cCBjbGFzcz0ibGVhZCI+QW4gb2xkLXNjaG9vbCBjb250ZW50IG1hbmFnZW1lbnQgc3lzdGVtIGZvciBtb3N0LjwvcD4KICAgIDwvZGl2PgogICAge3tpZiBub3QgLlVzZXJ9fQogICAgPGRpdiBjbGFzcz0nY29udGFpbmVyIG15LTUnPgogICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTInPgogICAgICAgICAgPGgyIGNsYXNzPSdkaXNwbGF5LTQgdGV4dC1jZW50ZXInPkNvbnRlbnQgTWFuYWdlbWVudCBTeXN0ZW0gKENNUyk8L2gyPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBvZmZzZXQtbGctMiBjb2wtbGctOCc+CiAgICAgICAgICA8dGFibGU+CiAgICAgICAgICAgIDx0ciB2YWxpZ249dG9wPgogICAgICAgICAgICAgIDx0ZD4KICAgICAgICAgICAgICAgIDxwIGNsYXNzPSdtci0zJz48c3Ryb25nPk5vdW4uPC9zdHJvbmc+PC9wPgogICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgICAgPHRkPgogICAgICAgICAgICAgICAgPHA+QSBjb21wdXRlciBzb2Z0d2FyZSBzeXN0ZW0gZm9yIG9yZ2FuaXppbmcgYW5kIGZhY2lsaXRhdGluZyBjb2xsYWJvcmF0aXZlIGNyZWF0aW9uIG9mIGRvY3VtZW50cyBhbmQgb3RoZXIgY29udGVudCwgZXNwZWNpYWxseSBmb3IgZGlzcGxheWluZyBjb250ZW50IHRvIGEgd2Vic2l0ZSBvciBtb2JpbGUgYXBwbGljYXRpb24uPC9wPgogICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgIDwvdHI+CiAgICAgICAgICA8L3RhYmxlPgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0nY29udGFpbmVyIG15LTUnPgogICAgICA8ZGl2IGNsYXNzPSJyb3ciPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCB0ZXh0LWNlbnRlciBtYi01Ij5GZWF0dXJlczwvaDE+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPXJvdz4KCiAgICAgICAgPGRpdiBjbGFzcz0nY29sIGNvbC0xMiBjb2wtbWQtNic+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkIG1iLTMnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLWJvZHknPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtdGV4dCc+CiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfQVBJJz5BUEk8L2E+CiAgICAgICAgICAgICAgICBmaXJzdCBDTVMuIFNraXBwZXIgaXMgYSBmdWxseS1mbGVkZ2VkIGNvbnRlbnQgCiAgICAgICAgICAgICAgICBtYW5hZ2VtZW50IDxtYXJrPmluZnJhc3RydWN0dXJlPC9tYXJrPiBhcyBtdWNoIGFzIGl0IGlzIGEKICAgICAgICAgICAgICAgIGNvbnRlbnQgbWFuYWdlbWVudCBzeXN0ZW0uIAogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIFlvdXIgY29udGVudCBtb2RlbCB5b3VyIHdheS4gWW91J3JlIDxtYXJrPm5ldmVyCiAgICAgICAgICAgICAgICByZXN0cmljdGVkPC9tYXJrPiB0byBhCiAgICAgICAgICAgICAgICBibGVzc2VkIGNvbnRlbnQgbW9kZWwsIGEgbGEgY2F0ZWdvcnkvdGFncyBmb3IgcGFnZXMvcG9zdHMuIAogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkxpZ2h0d2VpZ2h0PC9tYXJrPiBhbmQgPG1hcms+ZmFzdDwvbWFyaz47IEFQSSBjYWxscyB0bwogICAgICAgICAgICAgICAgU2tpcHBlciBDTVMgd2lsbCBub3QgYmUgeW91ciBib3R0bGVuZWNrLiBTa2lwcGVyIENNUyBtYWtlcyBoZWF2eQogICAgICAgICAgICAgICAgdXNlIG9mIGNhY2hpbmcuCiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTIgY29sLW1kLTYnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZCBtYi0zJz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC1ib2R5Jz4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLXRleHQnPgogICAgICAgICAgICAgICAgMTAwJSBjb21taXR0ZWQgdG8gPG1hcms+b3BlbiBzb3VyY2U8L21hcms+OyB5b3UgY2FuIHNlZSBleGFjdGx5IHdoYXQgdGhlIGNvZGUKICAgICAgICAgICAgICAgIGRvZXMgYW5kIG1ha2UgaW1wcm92ZW1lbnRzLiBTZWUgCiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2dpdC5zci5odC9+ZXZhbmovY21zJz5zb3VyY2VodXQ8L2E+LgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkVhc3k8L21hcms+IHRvIHVzZSBmb3IgPG1hcms+YWxsPC9tYXJrPi4gV2Uga2VlcCBhIGJpZwogICAgICAgICAgICAgICAgdGVudC4gTm8gbWF0dGVyIHlvdXIgYmFja2dyb3VuZCwgU2tpcHBlciBDTVMgaXMgY29tbWl0dGVkIHRvCiAgICAgICAgICAgICAgICBhc3Npc3RpbmcgeW91IHdlbGwuCiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxkaXYgY2xhc3M9J2NvbCBjb2wtMTIgY29sLW1kLTYnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZCBtYi0zJz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC1ib2R5Jz4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjYXJkLXRleHQnPgogICAgICAgICAgICAgICAgPG1hcms+UXVpY2tseTwvbWFyaz4gc2V0dXAgc3RhZ2luZyBhbmQgdGVzdCBlbnZpcm9ubWVudHMgZm9yCiAgICAgICAgICAgICAgICB5b3VyIGRhdGEuIFRhaWxvcmVkIHVzZSBmb3IgPG1hcms+eW91ciBlbnZpcm9ubWVudHM8L21hcms+LgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkFwcHJvYWNoYWJsZTwvbWFyaz4gCiAgICAgICAgICAgICAgICBkb2N1bWVudGlvbi4gRXhhbXBsZXMgcHJvdmlkZWQgaW4gCiAgICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2xpbnV4LmRpZS5uZXQvbWFuLzEvY3VybCc+Y1VSTDwvYT4uCiAgICAgICAgICAgICAgICBVc2UgZnJvbSB5b3VyIHByb2dyYW1taW5nIGxhbmd1YWdlIG9yIHJ1bnRpbWUgb2YgY2hvaWNlLgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGNsYXNzPSdjb2wgY29sLTEyIGNvbC1tZC02Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQgbWItMyc+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NhcmQtYm9keSc+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY2FyZC10ZXh0Jz4KICAgICAgICAgICAgICAgIDxtYXJrPkZyZWVkb208L21hcms+IHJlc3BlY3RpbmcgbGljZW5zZS4gVGhlIAogICAgICAgICAgICAgICAgPGEgaHJlZj0naHR0cDovL3d3dy5nbnUub3JnL3BoaWxvc29waHkvZnJlZS1zdy5odG1sI2NvbnRlbnQnPmZvdXIgZXNzZW50aWFsIGZyZWVkb21zPC9hPiAKICAgICAgICAgICAgICAgIGFyZSB1cGhlbGQgdW5kZXIgdGhlIEVVUEwgdjEuMiBsaWNlbnNlLiBDb21wYXRpYmxlIHdpdGggQUdQTCB2My4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSdjb250YWluZXIgbXktNSc+CiAgICAgIDxkaXYgaWQ9J3ByaWNpbmcnIGNsYXNzPSJyb3ciPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCB0ZXh0LWNlbnRlciBtYi01Ij5QcmljaW5nPC9oMT4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9InJvdyByb3ctY29scy0xIHJvdy1jb2xzLW1kLTIgcm93LWNvbHMtbGctMyBtYi01IHRleHQtY2VudGVyIj4KICAgICAgICB7e3JhbmdlIC5UaWVyc319CiAgICAgICAgPGRpdiBjbGFzcz0iY29sIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20iPgogICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZWFkZXIiPgogICAgICAgICAgICA8aDQgY2xhc3M9Im15LTAgZm9udC13ZWlnaHQtbm9ybWFsIj57ey5OYW1lfX08L2g0PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkiPgogICAgICAgICAgICA8aDEgY2xhc3M9ImNhcmQtdGl0bGUgcHJpY2luZy1jYXJkLXRpdGxlIj57ey5QcmljZX19IDxzbWFsbCBjbGFzcz0idGV4dC1tdXRlZCI+LyB7ey5UaW1lVW5pdH19PC9zbWFsbD48L2gxPgogICAgICAgICAgICA8dWwgY2xhc3M9Imxpc3QtdW5zdHlsZWQgbXQtMyBtYi00Ij4KICAgICAgICAgICAgICB7e3JhbmdlIC5PcHRzfX0KICAgICAgICAgICAgICAgIDxsaT57ey5UZXh0fX08L2xpPgogICAgICAgICAgICAgIHt7ZW5kfX0KICAgICAgICAgICAgPC91bD4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIHt7ZW5kfX0KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIHt7ZW5kfX0KICAgIDxhcnRpY2xlPgogICAgICB7eyBpZiAuVXNlciB9fQogICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICAgIDxpbnB1dCB0eXBlPWhpZGRlbiBuYW1lPW1ldGhvZCB2YWx1ZT1QT1NUIC8+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZXhhbXBsZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJleGFtcGxlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImV4YW1wbGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcgc3BhY2U8L2g1PgogICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNwYWNlRGVzYyI+RGVzY3JpcHRpb248L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1kZXNjIHR5cGU9dGV4dCBpZD0ic3BhY2VEZXNjIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJEZXNjcmlwdGlvbiIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9mb3JtPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdvZmZzZXQtbGctMyBjb2wtbGctNic+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2V4YW1wbGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHNwYWNlPC9hPgogICAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAgPGg2IGNsYXNzPSJib3JkZXItYm90dG9tIGJvcmRlci1ncmF5IHBiLTIgbWItMCI+WW91ciBzcGFjZXM8L2g2PgogICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5MaXN0IH19CiAgICAgICAgICAgICAgICAgIHt7IHJhbmdlIC5TcGFjZXMuTGlzdCB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtZWRpYSB0ZXh0LW11dGVkIHB0LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9zcGFjZS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICAgICAge3sgLkRlc2MgfX0KICAgICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii8/YmVmb3JlPXt7IC5TcGFjZXMuQmVmb3JlIH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgICBZb3UgaGF2ZW4ndCBjcmVhdGVkIGFueSBzcGFjZXMgeWV0LiAKICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAge3sgZWxzZSB9fQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciBteS01Ij4KICAgICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbCI+CiAgICAgICAgICAgICAgPGgxIGNsYXNzPSJkaXNwbGF5LTQgdGV4dC1jZW50ZXIgbWItNSI+TGV0J3MgZ288L2gxPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPGRpdiBjbGFzcz0ncm93IGp1c3RpZnktY29udGVudC1jZW50ZXInPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgY29sLW1kLTYgY29sLWxnLTQgb2Zmc2V0LWNvbC1sZy0yIGNvbC14bC0zIG9mZnNldC1jb2wteGwtMyBkLWZsZXgiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20gZmxleC1maWxsIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg0IGNsYXNzPSJteS0wIGZvbnQtd2VpZ2h0LW5vcm1hbCI+U2lnbnVwPC9oND4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGZvcm0gaWQ9J3NpZ251cCcgbWV0aG9kPVBPU1QgYWN0aW9uPScvdXNlci9zaWdudXAnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0VXNlcm5hbWUiIGNsYXNzPSJzci1vbmx5Ij5FbWFpbCBhZGRyZXNzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT11c2VybmFtZSB0eXBlPSJ0ZXh0IiBpZD0ic2lnbnVwSW5wdXRVc2VybmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0UGFzc3dvcmQiIGNsYXNzPSJzci1vbmx5Ij5QYXNzd29yZDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9cGFzc3dvcmQgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFBhc3N3b3JkIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRWZXJpZnkiIGNsYXNzPSJzci1vbmx5Ij5Db25maXJtIFBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT12ZXJpZnkgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFZlcmlmeSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iQ29uZmlybSBQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRQbGFuIiBjbGFzcz0ic3Itb25seSI+U2VsZWN0IHRpZXI8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxzZWxlY3QgbmFtZT10aWVyIGlkPSJzaWdudXBJbnB1dFBsYW4iIGNsYXNzPSJ3LTEwMCBmb3JtLWNvbnRyb2wgbWItMyIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHNlbGVjdGVkIHZhbHVlPlBheW1lbnQgdGllcjwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAge3tyYW5nZSAuVGllcnN9fQogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPSJ7ey5OYW1lfX0iPnt7Lk5hbWV9fTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAge3tlbmR9fQogICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PgogICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9ImJ0biBidG4tbGcgYnRuLXByaW1hcnkgYnRuLWJsb2NrIiB0eXBlPSJzdWJtaXQiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIGNvbC1tZC02IGNvbC1sZy00IGNvbC14bC0zIGQtZmxleCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCBtYi00IHNoYWRvdy1zbSBmbGV4LWZpbGwiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICA8aDQgY2xhc3M9Im15LTAgZm9udC13ZWlnaHQtbm9ybWFsIj5Mb2dpbjwvaDQ+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtYm9keSBkLWZsZXgiPgogICAgICAgICAgICAgICAgICA8Zm9ybSBpZD0nbG9naW4nIGNsYXNzPSdkLWZsZXggZmxleC1ncm93LTEgZmxleC1jb2x1bW4nIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3VzZXIvbG9naW4nIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImxvZ2luSW5wdXRVc2VybmFtZSIgY2xhc3M9InNyLW9ubHkiPkVtYWlsIGFkZHJlc3M8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPXVzZXJuYW1lIHR5cGU9InRleHQiIGlkPSJsb2dpbklucHV0VXNlcm5hbWUiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlVzZXJuYW1lIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJsb2dpbklucHV0UGFzc3dvcmQiIGNsYXNzPSJzci1vbmx5Ij5QYXNzd29yZDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9cGFzc3dvcmQgdHlwZT0icGFzc3dvcmQiIGlkPSJsb2dpbklucHV0UGFzc3dvcmQiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlBhc3N3b3JkIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJtdC1hdXRvIGJ0biBidG4tbGcgYnRuLXByaW1hcnkgYnRuLWJsb2NrIiB0eXBlPSJzdWJtaXQiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICB7eyBlbmQgfX0KICAgIDwvYXJ0aWNsZT4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgJCB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQogIHt7IGlmIC5Vc2VyIH19CiAgICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9tYWluLmpzIiAkIH19PC9zY3JpcHQ+CiAge3sgZWxzZSB9fQogICAgPHNjcmlwdD4KICAgICAgKGZ1bmN0aW9uKCkgeyAKICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGhhbmRsZUhhc2hDbGljayk7CiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2hhc2hjaGFuZ2UnLCBoYW5kbGVIYXNoQ2xpY2spOwogICAgICAgIGZ1bmN0aW9uIGhhbmRsZUhhc2hDbGljaygpIHsgCiAgICAgICAgICB2YXIgZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChsb2NhdGlvbi5oYXNoLnN1YnN0cigxKSk7CiAgICAgICAgICBpZiAoZWwpIGVsLnF1ZXJ5U2VsZWN0b3IoJ2lucHV0JykuZm9jdXMoKTsKICAgICAgICB9OwogICAgICB9KSgpOwogICAgPC9zY3JpcHQ+CiAge3sgZW5kIH19CjwvYm9keT4KPC9odG1sPgo=")

	tmpls["html/privacy.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IFByaXZhY3k8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5IGNsYXNzPSdwYWdlIGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+UHJpdmFjeTwvaDE+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9J2NvbnRhaW5lcic+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIG9mZnNldC0wIGNvbC1sZy04IG9mZnNldC1sZy0yIj4KICAgICAgICAgIFRPRE8KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgJCB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQo8L2JvZHk+CjwvaHRtbD4K")



@@ 50,6 50,8 @@ func init() {

	tmpls["html/space.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19PC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0nc3BhY2UgYmctbGlnaHQnPgogIDxzdHlsZT57eyB0ZW1wbGF0ZSAiY3NzL21haW4uY3NzIiB9fTwvc3R5bGU+CiAgPG1haW4+CiAgICB7eyB0ZW1wbGF0ZSAiaHRtbC9faGVhZGVyLmh0bWwiICQgfX0KICAgIDxkaXYgY2xhc3M9InByaWNpbmctaGVhZGVyIHB4LTMgcHktMyBwdC1tZC01IHBiLW1kLTQgbXgtYXV0byB0ZXh0LWNlbnRlciI+CiAgICAgIDxoMSBjbGFzcz0iZGlzcGxheS00Ij57ey5TcGFjZS5OYW1lfX08L2gxPgogICAgICA8cCBjbGFzcz0ibGVhZCI+e3suU3BhY2UuRGVzY319PC9wPgogICAgPC9kaXY+CiAgICA8YXJ0aWNsZT4KICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudHR5cGUnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCB0eXBlPWhpZGRlbiBuYW1lPW1ldGhvZCB2YWx1ZT1QT1NUIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iY3JlYXRlLWNvbnRlbnR0eXBlIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJDcmVhdGUgYSBuZXcgY29udGVudCB0eXBlIG1vZGFsLiIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJjb250ZW50dHlwZU1vZGFsTGFiZWwiPkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGU8L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iY29udGVudHR5cGVOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPW5hbWUgdHlwZT10ZXh0IGlkPSJjb250ZW50dHlwZU5hbWUiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9Ik5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgPGRpdiBpZD0nZmlyc3QtZmllbGRzZXQnIGNsYXNzPSdjb250YWluZXItZmx1aWQgcHgtMCBtYi0zJz4KICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iZmllbGRzZXRGaXJzdCI+RmllbGRzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgPGlucHV0IGlkPSJmaWVsZHNldEZpcnN0IiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHJlYWRvbmx5PSJyZWFkb25seSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9ImZpZWxkX25hbWVfMSIgdmFsdWU9Im5hbWUiIC8+CiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2Zvcm0tZ3JvdXAgcm93Jz4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtNic+CiAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPSJ3LTEwMCBmb3JtLWNvbnRyb2wiIHJlYWRvbmx5PSJyZWFkb25seSIgcmVxdWlyZWQgbmFtZT0iZmllbGRfdHlwZV8xIj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT5GaWVsZCBUeXBlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gc2VsZWN0ZWQgdmFsdWU9IlN0cmluZ1NtYWxsIj5TdHJpbmcgU21hbGw8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iU3RyaW5nQmlnIj5TdHJpbmcgQmlnPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IklucHV0SFRNTCI+SFRNTDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJJbnB1dE1hcmtkb3duIj5NYXJrZG93bjwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJGaWxlIj5GaWxlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IkRhdGUiPkRhdGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlIj5SZWZlcmVuY2U8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlTGlzdCI+UmVmZXJlbmNlTGlzdDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndy0xMDAgYnRuIGJ0bi1wcmltYXJ5JyBkaXNhYmxlZCB0eXBlPWJ1dHRvbj5SZW1vdmUgRmllbGQ8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxhIGhyZWY9JyMnIGNsYXNzPSdidG4gYnRuLWxpbmsnIGlkPSdhZGQtZmllbGRidG4nPkFkZCBBbm90aGVyIEZpZWxkPC9hPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KCiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL2hvb2snIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCB0eXBlPWhpZGRlbiBuYW1lPW1ldGhvZCB2YWx1ZT1QT1NUIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iaG9va01vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJob29rTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJob29rTW9kYWxMYWJlbCI+Q3JlYXRlIGEgbmV3IGhvb2s8L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iaG9va1VSTCI+VVJMPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPXVybCB0eXBlPXVybCBpZD0iaG9va1VSTCIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTXVzdCBlbnRlciBmdWxsIFVSTCBvZiB0YXJnZXQiIHJlcXVpcmVkPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KCiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgdHlwZT1oaWRkZW4gbmFtZT1tZXRob2QgdmFsdWU9UFVUIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iY29weU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJjb3B5TW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJjb3B5TW9kYWxMYWJlbCI+Q29weSB7ey5TcGFjZS5OYW1lfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPW5hbWUgdHlwZT10ZXh0IGlkPSJzcGFjZU5hbWUiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9Ik5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VEZXNjIj5EZXNjcmlwdGlvbjwvbGFiZWw+CiAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1kZXNjIHR5cGU9dGV4dCBpZD0ic3BhY2VEZXNjIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJEZXNjcmlwdGlvbiIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvc3BhY2UnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCB0eXBlPWhpZGRlbiBuYW1lPW1ldGhvZCB2YWx1ZT1QQVRDSCAvPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InVwZGF0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJ1cGRhdGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9InVwZGF0ZU1vZGFsTGFiZWwiPlVwZGF0ZSB7ey5TcGFjZS5OYW1lfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLk5hbWUgfX0iIG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZURlc2MiPkRlc2NyaXB0aW9uPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLkRlc2MgfX0iIG5hbWU9ZGVzYyB0eXBlPXRleHQgaWQ9InNwYWNlRGVzYyIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iRGVzY3JpcHRpb24iIHJlcXVpcmVkPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KICAgICAgCiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgdHlwZT1oaWRkZW4gbmFtZT1tZXRob2QgdmFsdWU9REVMRVRFIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZGVsZXRlTW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9ImRlbGV0ZU1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctc2Nyb2xsYWJsZSI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iZGVsZXRlTW9kYWxMYWJlbCI+RGVsZXRlIHt7LlNwYWNlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY29sLWxnLTYnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJteS0zIHAtMyBiZy13aGl0ZSByb3VuZGVkIHNoYWRvdy1zbSI+CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2NyZWF0ZS1jb250ZW50dHlwZSI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9IiMiPkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIgY29udGVudCB0eXBlczwvaDY+CiAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuQ29udGVudFR5cGVzLkxpc3QgfX0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1lZGlhIHRleHQtbXV0ZWQgcHQtMyI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9jb250ZW50dHlwZS97eyAkLlNwYWNlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBtdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iL3NwYWNlL3t7IC5TcGFjZS5JRCB9fT9iZWZvcmVjdD17eyAuQ29udGVudFR5cGVzLkJlZm9yZSB9fSI+TG9hZCBtb3JlPC9hPgogICAgICAgICAgICAgICAgPC9zbWFsbD4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgIHt7IGVsc2UgfX0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im10LTMgYWxlcnQgYWxlcnQtcHJpbWFyeSIgcm9sZT0iYWxlcnQiPgogICAgICAgICAgICAgICAgICBZb3UgaGF2ZW4ndCBjcmVhdGVkIGFueSBjb250ZW50IHR5cGVzIHlldC4gCiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9J2NvbC1sZy02Jz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPSJkLWJsb2NrIHRleHQtcmlnaHQgZmxvYXQtcmlnaHQiIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNob29rTW9kYWwiPgogICAgICAgICAgICAgICAgICA8YSBocmVmPSIjIj5DcmVhdGUgYSBuZXcgd2ViaG9vazwvYT4KICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgPGg2IGNsYXNzPSJib3JkZXItYm90dG9tIGJvcmRlci1ncmF5IHBiLTIgbWItMCI+WW91ciB3ZWJob29rczwvaDY+CiAgICAgICAgICAgICAge3sgaWYgLkhvb2tzLkxpc3QgfX0KICAgICAgICAgICAgICAgIHt7IHJhbmdlIC5Ib29rcy5MaXN0IH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtZWRpYSB0ZXh0LW11dGVkIHB0LTMiPgogICAgICAgICAgICAgICAgICA8YSBocmVmPScvaG9vay97eyAkLlNwYWNlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuVVJMIH19PC9zdHJvbmc+CiAgICAgICAgICAgICAgICAgIDwvYT4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICB7eyBpZiAuSG9va3MuTW9yZSB9fQogICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPSJkLWJsb2NrIHRleHQtcmlnaHQgbXQtMyI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii9zcGFjZS97eyAuU3BhY2UuSUQgfX0/YmVmb3JlaG9vaz17eyAuSG9va3MuQmVmb3JlIH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtMyBhbGVydCBhbGVydC1wcmltYXJ5IiByb2xlPSJhbGVydCI+CiAgICAgICAgICAgICAgICAgIFlvdSBoYXZlbid0IGNyZWF0ZWQgYW55IHdlYmhvb2tzIHlldC4gCiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CgogICAgPC9hcnRpY2xlPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiAkIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvbWFpbi5qcyIgJCB9fTwvc2NyaXB0PgogIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL3NwYWNlLmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")

	tmpls["html/stripe.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IERvY3M8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5IGNsYXNzPSdwYWdlIGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+UHJvY2Vzc2luZy4uLjwvaDE+CiAgICA8L2Rpdj4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgJCB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQogIDxzY3JpcHQgc3JjPSIvL2pzLnN0cmlwZS5jb20vdjMvIj48L3NjcmlwdD4KICA8c2NyaXB0PgogICAgKGZ1bmN0aW9uKCkgeyAKICAgICAgdmFyIHN0cmlwZSA9IFN0cmlwZSgne3suU3RyaXBlUEt9fScpOwogICAgICB2YXIgY2hlY2tvdXRCdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hlY2tvdXQtYnV0dG9uJyk7CiAgICAgIHN0cmlwZS5yZWRpcmVjdFRvQ2hlY2tvdXQoewogICAgICAgIHNlc3Npb25JZDogJ3t7LlN0cmlwZUNoZWNrb3V0U2Vzc2lvbklEfX0nCiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgIGNvbnNvbGUubG9nKHJlc3VsdCkKICAgICAgICBhbGVydChyZXN1bHQuZXJyb3IubWVzc2FnZSk7CiAgICAgIH0pOwogICAgfSkoKTsKICA8L3NjcmlwdD4KPC9ib2R5Pgo8L2h0bWw+Cg==")

	tmpls["html/terms.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IFRlcm1zPC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0ncGFnZSBiZy1saWdodCc+CiAgPHN0eWxlPnt7IHRlbXBsYXRlICJjc3MvbWFpbi5jc3MiIH19PC9zdHlsZT4KICA8bWFpbj4KICAgIHt7IHRlbXBsYXRlICJodG1sL19oZWFkZXIuaHRtbCIgJCB9fQogICAgPGRpdiBjbGFzcz0icHJpY2luZy1oZWFkZXIgcHgtMyBweS0zIHB0LW1kLTUgcGItbWQtNCBteC1hdXRvIHRleHQtY2VudGVyIj4KICAgICAgPGgxIGNsYXNzPSJkaXNwbGF5LTQiPlRlcm1zPC9oMT4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0nY29udGFpbmVyJz4KICAgICAgPGRpdiBjbGFzcz0ncm93Jz4KICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgb2Zmc2V0LTAgY29sLWxnLTggb2Zmc2V0LWxnLTIiPgogICAgICAgICAgVE9ETwogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiAkIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CjwvYm9keT4KPC9odG1sPgo=")

	tmpls["js/bootstrap.js"] = tostring("LyohCiAgKiBCb290c3RyYXAgdjUuMC4wLWFscGhhMSAoaHR0cHM6Ly9nZXRib290c3RyYXAuY29tLykKICAqIENvcHlyaWdodCAyMDExLTIwMjAgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycykKICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKQogICovCiFmdW5jdGlvbih0LGUpeyJvYmplY3QiPT10eXBlb2YgZXhwb3J0cyYmInVuZGVmaW5lZCIhPXR5cGVvZiBtb2R1bGU/bW9kdWxlLmV4cG9ydHM9ZShyZXF1aXJlKCJwb3BwZXIuanMiKSk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoWyJwb3BwZXIuanMiXSxlKToodD10fHxzZWxmKS5ib290c3RyYXA9ZSh0LlBvcHBlcil9KHRoaXMsKGZ1bmN0aW9uKHQpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBlKHQsZSl7Zm9yKHZhciBuPTA7bjxlLmxlbmd0aDtuKyspe3ZhciBpPWVbbl07aS5lbnVtZXJhYmxlPWkuZW51bWVyYWJsZXx8ITEsaS5jb25maWd1cmFibGU9ITAsInZhbHVlImluIGkmJihpLndyaXRhYmxlPSEwKSxPYmplY3QuZGVmaW5lUHJvcGVydHkodCxpLmtleSxpKX19ZnVuY3Rpb24gbih0LG4saSl7cmV0dXJuIG4mJmUodC5wcm90b3R5cGUsbiksaSYmZSh0LGkpLHR9ZnVuY3Rpb24gaSh0LGUsbil7cmV0dXJuIGUgaW4gdD9PYmplY3QuZGVmaW5lUHJvcGVydHkodCxlLHt2YWx1ZTpuLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwLHdyaXRhYmxlOiEwfSk6dFtlXT1uLHR9ZnVuY3Rpb24gbyh0LGUpe3ZhciBuPU9iamVjdC5rZXlzKHQpO2lmKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpe3ZhciBpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModCk7ZSYmKGk9aS5maWx0ZXIoKGZ1bmN0aW9uKGUpe3JldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHQsZSkuZW51bWVyYWJsZX0pKSksbi5wdXNoLmFwcGx5KG4saSl9cmV0dXJuIG59ZnVuY3Rpb24gcyh0KXtmb3IodmFyIGU9MTtlPGFyZ3VtZW50cy5sZW5ndGg7ZSsrKXt2YXIgbj1udWxsIT1hcmd1bWVudHNbZV0/YXJndW1lbnRzW2VdOnt9O2UlMj9vKE9iamVjdChuKSwhMCkuZm9yRWFjaCgoZnVuY3Rpb24oZSl7aSh0LGUsbltlXSl9KSk6T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnM/T2JqZWN0LmRlZmluZVByb3BlcnRpZXModCxPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhuKSk6byhPYmplY3QobikpLmZvckVhY2goKGZ1bmN0aW9uKGUpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGUsT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihuLGUpKX0pKX1yZXR1cm4gdH10PXQmJk9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LCJkZWZhdWx0Iik/dC5kZWZhdWx0OnQ7dmFyIHIsYSxsLGMsdT1mdW5jdGlvbih0KXtkb3t0Kz1NYXRoLmZsb29yKDFlNipNYXRoLnJhbmRvbSgpKX13aGlsZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0KSk7cmV0dXJuIHR9LGg9ZnVuY3Rpb24odCl7dmFyIGU9dC5nZXRBdHRyaWJ1dGUoImRhdGEtdGFyZ2V0Iik7aWYoIWV8fCIjIj09PWUpe3ZhciBuPXQuZ2V0QXR0cmlidXRlKCJocmVmIik7ZT1uJiYiIyIhPT1uP24udHJpbSgpOm51bGx9cmV0dXJuIGV9LGY9ZnVuY3Rpb24odCl7dmFyIGU9aCh0KTtyZXR1cm4gZSYmZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlKT9lOm51bGx9LGQ9ZnVuY3Rpb24odCl7dmFyIGU9aCh0KTtyZXR1cm4gZT9kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGUpOm51bGx9LGc9ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJuIDA7dmFyIGU9d2luZG93LmdldENvbXB1dGVkU3R5bGUodCksbj1lLnRyYW5zaXRpb25EdXJhdGlvbixpPWUudHJhbnNpdGlvbkRlbGF5LG89cGFyc2VGbG9hdChuKSxzPXBhcnNlRmxvYXQoaSk7cmV0dXJuIG98fHM/KG49bi5zcGxpdCgiLCIpWzBdLGk9aS5zcGxpdCgiLCIpWzBdLDFlMyoocGFyc2VGbG9hdChuKStwYXJzZUZsb2F0KGkpKSk6MH0scD1mdW5jdGlvbih0KXt0LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCJ0cmFuc2l0aW9uZW5kIikpfSxtPWZ1bmN0aW9uKHQpe3JldHVybih0WzBdfHx0KS5ub2RlVHlwZX0sXz1mdW5jdGlvbih0LGUpe3ZhciBuPSExLGk9ZSs1O3QuYWRkRXZlbnRMaXN0ZW5lcigidHJhbnNpdGlvbmVuZCIsKGZ1bmN0aW9uIGUoKXtuPSEwLHQucmVtb3ZlRXZlbnRMaXN0ZW5lcigidHJhbnNpdGlvbmVuZCIsZSl9KSksc2V0VGltZW91dCgoZnVuY3Rpb24oKXtufHxwKHQpfSksaSl9LHY9ZnVuY3Rpb24odCxlLG4pe09iamVjdC5rZXlzKG4pLmZvckVhY2goKGZ1bmN0aW9uKGkpe3ZhciBvLHM9bltpXSxyPWVbaV0sYT1yJiZtKHIpPyJlbGVtZW50IjpudWxsPT0obz1yKT8iIitvOnt9LnRvU3RyaW5nLmNhbGwobykubWF0Y2goL1xzKFthLXpdKykvaSlbMV0udG9Mb3dlckNhc2UoKTtpZighbmV3IFJlZ0V4cChzKS50ZXN0KGEpKXRocm93IG5ldyBFcnJvcih0LnRvVXBwZXJDYXNlKCkrJzogT3B0aW9uICInK2krJyIgcHJvdmlkZWQgdHlwZSAiJythKyciIGJ1dCBleHBlY3RlZCB0eXBlICInK3MrJyIuJyl9KSl9LGI9ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJuITE7aWYodC5zdHlsZSYmdC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUuc3R5bGUpe3ZhciBlPWdldENvbXB1dGVkU3R5bGUodCksbj1nZXRDb21wdXRlZFN0eWxlKHQucGFyZW50Tm9kZSk7cmV0dXJuIm5vbmUiIT09ZS5kaXNwbGF5JiYibm9uZSIhPT1uLmRpc3BsYXkmJiJoaWRkZW4iIT09ZS52aXNpYmlsaXR5fXJldHVybiExfSx5PWZ1bmN0aW9uKCl7cmV0dXJuIGZ1bmN0aW9uKCl7fX0sdz1mdW5jdGlvbih0KXtyZXR1cm4gdC5vZmZzZXRIZWlnaHR9LEU9ZnVuY3Rpb24oKXt2YXIgdD13aW5kb3cualF1ZXJ5O3JldHVybiB0JiYhZG9jdW1lbnQuYm9keS5oYXNBdHRyaWJ1dGUoImRhdGEtbm8tanF1ZXJ5Iik/dDpudWxsfSxrPShyPXt9LGE9MSx7c2V0OmZ1bmN0aW9uKHQsZSxuKXt2b2lkIDA9PT10LmtleSYmKHQua2V5PXtrZXk6ZSxpZDphfSxhKyspLHJbdC5rZXkuaWRdPW59LGdldDpmdW5jdGlvbih0LGUpe2lmKCF0fHx2b2lkIDA9PT10LmtleSlyZXR1cm4gbnVsbDt2YXIgbj10LmtleTtyZXR1cm4gbi5rZXk9PT1lP3Jbbi5pZF06bnVsbH0sZGVsZXRlOmZ1bmN0aW9uKHQsZSl7aWYodm9pZCAwIT09dC5rZXkpe3ZhciBuPXQua2V5O24ua2V5PT09ZSYmKGRlbGV0ZSByW24uaWRdLGRlbGV0ZSB0LmtleSl9fX0pLFQ9ZnVuY3Rpb24odCxlLG4pe2suc2V0KHQsZSxuKX0sTD1mdW5jdGlvbih0LGUpe3JldHVybiBrLmdldCh0LGUpfSxDPWZ1bmN0aW9uKHQsZSl7ay5kZWxldGUodCxlKX0sQT1FbGVtZW50LnByb3RvdHlwZS5xdWVyeVNlbGVjdG9yQWxsLFM9RWxlbWVudC5wcm90b3R5cGUucXVlcnlTZWxlY3RvcixPPShsPW5ldyBDdXN0b21FdmVudCgiQm9vdHN0cmFwIix7Y2FuY2VsYWJsZTohMH0pLChjPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpKS5hZGRFdmVudExpc3RlbmVyKCJCb290c3RyYXAiLChmdW5jdGlvbigpe3JldHVybiBudWxsfSkpLGwucHJldmVudERlZmF1bHQoKSxjLmRpc3BhdGNoRXZlbnQobCksbC5kZWZhdWx0UHJldmVudGVkKSxEPS86c2NvcGVcYi87KGZ1bmN0aW9uKCl7dmFyIHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7dHJ5e3QucXVlcnlTZWxlY3RvckFsbCgiOnNjb3BlICoiKX1jYXRjaCh0KXtyZXR1cm4hMX1yZXR1cm4hMH0pKCl8fChBPWZ1bmN0aW9uKHQpe2lmKCFELnRlc3QodCkpcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvckFsbCh0KTt2YXIgZT1Cb29sZWFuKHRoaXMuaWQpO2V8fCh0aGlzLmlkPXUoInNjb3BlIikpO3ZhciBuPW51bGw7dHJ5e3Q9dC5yZXBsYWNlKEQsIiMiK3RoaXMuaWQpLG49dGhpcy5xdWVyeVNlbGVjdG9yQWxsKHQpfWZpbmFsbHl7ZXx8dGhpcy5yZW1vdmVBdHRyaWJ1dGUoImlkIil9cmV0dXJuIG59LFM9ZnVuY3Rpb24odCl7aWYoIUQudGVzdCh0KSlyZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKHQpO3ZhciBlPUEuY2FsbCh0aGlzLHQpO3JldHVybiB2b2lkIDAhPT1lWzBdP2VbMF06bnVsbH0pO3ZhciBJPUUoKSxOPS9bXi5dKig/PVwuLiopXC58LiovLGo9L1wuLiovLFA9Lzo6XGQrJC8seD17fSxSPTEsSD17bW91c2VlbnRlcjoibW91c2VvdmVyIixtb3VzZWxlYXZlOiJtb3VzZW91dCJ9LEI9WyJjbGljayIsImRibGNsaWNrIiwibW91c2V1cCIsIm1vdXNlZG93biIsImNvbnRleHRtZW51IiwibW91c2V3aGVlbCIsIkRPTU1vdXNlU2Nyb2xsIiwibW91c2VvdmVyIiwibW91c2VvdXQiLCJtb3VzZW1vdmUiLCJzZWxlY3RzdGFydCIsInNlbGVjdGVuZCIsImtleWRvd24iLCJrZXlwcmVzcyIsImtleXVwIiwib3JpZW50YXRpb25jaGFuZ2UiLCJ0b3VjaHN0YXJ0IiwidG91Y2htb3ZlIiwidG91Y2hlbmQiLCJ0b3VjaGNhbmNlbCIsInBvaW50ZXJkb3duIiwicG9pbnRlcm1vdmUiLCJwb2ludGVydXAiLCJwb2ludGVybGVhdmUiLCJwb2ludGVyY2FuY2VsIiwiZ2VzdHVyZXN0YXJ0IiwiZ2VzdHVyZWNoYW5nZSIsImdlc3R1cmVlbmQiLCJmb2N1cyIsImJsdXIiLCJjaGFuZ2UiLCJyZXNldCIsInNlbGVjdCIsInN1Ym1pdCIsImZvY3VzaW4iLCJmb2N1c291dCIsImxvYWQiLCJ1bmxvYWQiLCJiZWZvcmV1bmxvYWQiLCJyZXNpemUiLCJtb3ZlIiwiRE9NQ29udGVudExvYWRlZCIsInJlYWR5c3RhdGVjaGFuZ2UiLCJlcnJvciIsImFib3J0Iiwic2Nyb2xsIl07ZnVuY3Rpb24gTSh0LGUpe3JldHVybiBlJiZlKyI6OiIrUisrfHx0LnVpZEV2ZW50fHxSKyt9ZnVuY3Rpb24gUSh0KXt2YXIgZT1NKHQpO3JldHVybiB0LnVpZEV2ZW50PWUseFtlXT14W2VdfHx7fSx4W2VdfWZ1bmN0aW9uIFUodCxlLG4pe3ZvaWQgMD09PW4mJihuPW51bGwpO2Zvcih2YXIgaT1PYmplY3Qua2V5cyh0KSxvPTAscz1pLmxlbmd0aDtvPHM7bysrKXt2YXIgcj10W2lbb11dO2lmKHIub3JpZ2luYWxIYW5kbGVyPT09ZSYmci5kZWxlZ2F0aW9uU2VsZWN0b3I9PT1uKXJldHVybiByfXJldHVybiBudWxsfWZ1bmN0aW9uIEYodCxlLG4pe3ZhciBpPSJzdHJpbmciPT10eXBlb2YgZSxvPWk/bjplLHM9dC5yZXBsYWNlKGosIiIpLHI9SFtzXTtyZXR1cm4gciYmKHM9ciksQi5pbmRleE9mKHMpPi0xfHwocz10KSxbaSxvLHNdfWZ1bmN0aW9uIFcodCxlLG4saSxvKXtpZigic3RyaW5nIj09dHlwZW9mIGUmJnQpe258fChuPWksaT1udWxsKTt2YXIgcz1GKGUsbixpKSxyPXNbMF0sYT1zWzFdLGw9c1syXSxjPVEodCksdT1jW2xdfHwoY1tsXT17fSksaD1VKHUsYSxyP246bnVsbCk7aWYoaCloLm9uZU9mZj1oLm9uZU9mZiYmbztlbHNle3ZhciBmPU0oYSxlLnJlcGxhY2UoTiwiIikpLGQ9cj9mdW5jdGlvbih0LGUsbil7cmV0dXJuIGZ1bmN0aW9uIGkobyl7Zm9yKHZhciBzPXQucXVlcnlTZWxlY3RvckFsbChlKSxyPW8udGFyZ2V0O3ImJnIhPT10aGlzO3I9ci5wYXJlbnROb2RlKWZvcih2YXIgYT1zLmxlbmd0aDthLS07KWlmKHNbYV09PT1yKXJldHVybiBpLm9uZU9mZiYmcS5vZmYodCxvLnR5cGUsbiksbi5hcHBseShyLFtvXSk7cmV0dXJuIG51bGx9fSh0LG4saSk6ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24gbihpKXtyZXR1cm4gbi5vbmVPZmYmJnEub2ZmKHQsaS50eXBlLGUpLGUuYXBwbHkodCxbaV0pfX0odCxuKTtkLmRlbGVnYXRpb25TZWxlY3Rvcj1yP246bnVsbCxkLm9yaWdpbmFsSGFuZGxlcj1hLGQub25lT2ZmPW8sZC51aWRFdmVudD1mLHVbZl09ZCx0LmFkZEV2ZW50TGlzdGVuZXIobCxkLHIpfX19ZnVuY3Rpb24gVih0LGUsbixpLG8pe3ZhciBzPVUoZVtuXSxpLG8pO3MmJih0LnJlbW92ZUV2ZW50TGlzdGVuZXIobixzLEJvb2xlYW4obykpLGRlbGV0ZSBlW25dW3MudWlkRXZlbnRdKX12YXIgcT17b246ZnVuY3Rpb24odCxlLG4saSl7Vyh0LGUsbixpLCExKX0sb25lOmZ1bmN0aW9uKHQsZSxuLGkpe1codCxlLG4saSwhMCl9LG9mZjpmdW5jdGlvbih0LGUsbixpKXtpZigic3RyaW5nIj09dHlwZW9mIGUmJnQpe3ZhciBvPUYoZSxuLGkpLHM9b1swXSxyPW9bMV0sYT1vWzJdLGw9YSE9PWUsYz1RKHQpLHU9Ii4iPT09ZS5jaGFyQXQoMCk7aWYodm9pZCAwPT09cil7dSYmT2JqZWN0LmtleXMoYykuZm9yRWFjaCgoZnVuY3Rpb24obil7IWZ1bmN0aW9uKHQsZSxuLGkpe3ZhciBvPWVbbl18fHt9O09iamVjdC5rZXlzKG8pLmZvckVhY2goKGZ1bmN0aW9uKHMpe2lmKHMuaW5kZXhPZihpKT4tMSl7dmFyIHI9b1tzXTtWKHQsZSxuLHIub3JpZ2luYWxIYW5kbGVyLHIuZGVsZWdhdGlvblNlbGVjdG9yKX19KSl9KHQsYyxuLGUuc2xpY2UoMSkpfSkpO3ZhciBoPWNbYV18fHt9O09iamVjdC5rZXlzKGgpLmZvckVhY2goKGZ1bmN0aW9uKG4pe3ZhciBpPW4ucmVwbGFjZShQLCIiKTtpZighbHx8ZS5pbmRleE9mKGkpPi0xKXt2YXIgbz1oW25dO1YodCxjLGEsby5vcmlnaW5hbEhhbmRsZXIsby5kZWxlZ2F0aW9uU2VsZWN0b3IpfX0pKX1lbHNle2lmKCFjfHwhY1thXSlyZXR1cm47Vih0LGMsYSxyLHM/bjpudWxsKX19fSx0cmlnZ2VyOmZ1bmN0aW9uKHQsZSxuKXtpZigic3RyaW5nIiE9dHlwZW9mIGV8fCF0KXJldHVybiBudWxsO3ZhciBpLG89ZS5yZXBsYWNlKGosIiIpLHM9ZSE9PW8scj1CLmluZGV4T2Yobyk+LTEsYT0hMCxsPSEwLGM9ITEsdT1udWxsO3JldHVybiBzJiZJJiYoaT1JLkV2ZW50KGUsbiksSSh0KS50cmlnZ2VyKGkpLGE9IWkuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSxsPSFpLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkKCksYz1pLmlzRGVmYXVsdFByZXZlbnRlZCgpKSxyPyh1PWRvY3VtZW50LmNyZWF0ZUV2ZW50KCJIVE1MRXZlbnRzIikpLmluaXRFdmVudChvLGEsITApOnU9bmV3IEN1c3RvbUV2ZW50KGUse2J1YmJsZXM6YSxjYW5jZWxhYmxlOiEwfSksdm9pZCAwIT09biYmT2JqZWN0LmtleXMobikuZm9yRWFjaCgoZnVuY3Rpb24odCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHUsdCx7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIG5bdF19fSl9KSksYyYmKHUucHJldmVudERlZmF1bHQoKSxPfHxPYmplY3QuZGVmaW5lUHJvcGVydHkodSwiZGVmYXVsdFByZXZlbnRlZCIse2dldDpmdW5jdGlvbigpe3JldHVybiEwfX0pKSxsJiZ0LmRpc3BhdGNoRXZlbnQodSksdS5kZWZhdWx0UHJldmVudGVkJiZ2b2lkIDAhPT1pJiZpLnByZXZlbnREZWZhdWx0KCksdX19LHo9ImFsZXJ0IixLPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0KXt0aGlzLl9lbGVtZW50PXQsdGhpcy5fZWxlbWVudCYmVCh0LCJicy5hbGVydCIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUuY2xvc2U9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fZWxlbWVudDt0JiYoZT10aGlzLl9nZXRSb290RWxlbWVudCh0KSk7dmFyIG49dGhpcy5fdHJpZ2dlckNsb3NlRXZlbnQoZSk7bnVsbD09PW58fG4uZGVmYXVsdFByZXZlbnRlZHx8dGhpcy5fcmVtb3ZlRWxlbWVudChlKX0sZS5kaXNwb3NlPWZ1bmN0aW9uKCl7Qyh0aGlzLl9lbGVtZW50LCJicy5hbGVydCIpLHRoaXMuX2VsZW1lbnQ9bnVsbH0sZS5fZ2V0Um9vdEVsZW1lbnQ9ZnVuY3Rpb24odCl7cmV0dXJuIGQodCl8fHQuY2xvc2VzdCgiLmFsZXJ0Iil9LGUuX3RyaWdnZXJDbG9zZUV2ZW50PWZ1bmN0aW9uKHQpe3JldHVybiBxLnRyaWdnZXIodCwiY2xvc2UuYnMuYWxlcnQiKX0sZS5fcmVtb3ZlRWxlbWVudD1mdW5jdGlvbih0KXt2YXIgZT10aGlzO2lmKHQuY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLHQuY2xhc3NMaXN0LmNvbnRhaW5zKCJmYWRlIikpe3ZhciBuPWcodCk7cS5vbmUodCwidHJhbnNpdGlvbmVuZCIsKGZ1bmN0aW9uKCl7cmV0dXJuIGUuX2Rlc3Ryb3lFbGVtZW50KHQpfSkpLF8odCxuKX1lbHNlIHRoaXMuX2Rlc3Ryb3lFbGVtZW50KHQpfSxlLl9kZXN0cm95RWxlbWVudD1mdW5jdGlvbih0KXt0LnBhcmVudE5vZGUmJnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0KSxxLnRyaWdnZXIodCwiY2xvc2VkLmJzLmFsZXJ0Iil9LHQualF1ZXJ5SW50ZXJmYWNlPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVhY2goKGZ1bmN0aW9uKCl7dmFyIG49TCh0aGlzLCJicy5hbGVydCIpO258fChuPW5ldyB0KHRoaXMpKSwiY2xvc2UiPT09ZSYmbltlXSh0aGlzKX0pKX0sdC5oYW5kbGVEaXNtaXNzPWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtlJiZlLnByZXZlbnREZWZhdWx0KCksdC5jbG9zZSh0aGlzKX19LHQuZ2V0SW5zdGFuY2U9ZnVuY3Rpb24odCl7cmV0dXJuIEwodCwiYnMuYWxlcnQiKX0sbih0LG51bGwsW3trZXk6IlZFUlNJT04iLGdldDpmdW5jdGlvbigpe3JldHVybiI1LjAuMC1hbHBoYTEifX1dKSx0fSgpO3Eub24oZG9jdW1lbnQsImNsaWNrLmJzLmFsZXJ0LmRhdGEtYXBpIiwnW2RhdGEtZGlzbWlzcz0iYWxlcnQiXScsSy5oYW5kbGVEaXNtaXNzKG5ldyBLKSk7dmFyIFg9RSgpO2lmKFgpe3ZhciBZPVguZm5bel07WC5mblt6XT1LLmpRdWVyeUludGVyZmFjZSxYLmZuW3pdLkNvbnN0cnVjdG9yPUssWC5mblt6XS5ub0NvbmZsaWN0PWZ1bmN0aW9uKCl7cmV0dXJuIFguZm5bel09WSxLLmpRdWVyeUludGVyZmFjZX19dmFyICQ9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQpe3RoaXMuX2VsZW1lbnQ9dCxUKHQsImJzLmJ1dHRvbiIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUudG9nZ2xlPWZ1bmN0aW9uKCl7dGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoImFyaWEtcHJlc3NlZCIsdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKCJhY3RpdmUiKSl9LGUuZGlzcG9zZT1mdW5jdGlvbigpe0ModGhpcy5fZWxlbWVudCwiYnMuYnV0dG9uIiksdGhpcy5fZWxlbWVudD1udWxsfSx0LmpRdWVyeUludGVyZmFjZT1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5lYWNoKChmdW5jdGlvbigpe3ZhciBuPUwodGhpcywiYnMuYnV0dG9uIik7bnx8KG49bmV3IHQodGhpcykpLCJ0b2dnbGUiPT09ZSYmbltlXSgpfSkpfSx0LmdldEluc3RhbmNlPWZ1bmN0aW9uKHQpe3JldHVybiBMKHQsImJzLmJ1dHRvbiIpfSxuKHQsbnVsbCxbe2tleToiVkVSU0lPTiIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIjUuMC4wLWFscGhhMSJ9fV0pLHR9KCk7cS5vbihkb2N1bWVudCwiY2xpY2suYnMuYnV0dG9uLmRhdGEtYXBpIiwnW2RhdGEtdG9nZ2xlPSJidXR0b24iXScsKGZ1bmN0aW9uKHQpe3QucHJldmVudERlZmF1bHQoKTt2YXIgZT10LnRhcmdldC5jbG9zZXN0KCdbZGF0YS10b2dnbGU9ImJ1dHRvbiJdJyksbj1MKGUsImJzLmJ1dHRvbiIpO258fChuPW5ldyAkKGUpKSxuLnRvZ2dsZSgpfSkpO3ZhciBHPUUoKTtpZihHKXt2YXIgWj1HLmZuLmJ1dHRvbjtHLmZuLmJ1dHRvbj0kLmpRdWVyeUludGVyZmFjZSxHLmZuLmJ1dHRvbi5Db25zdHJ1Y3Rvcj0kLEcuZm4uYnV0dG9uLm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gRy5mbi5idXR0b249WiwkLmpRdWVyeUludGVyZmFjZX19ZnVuY3Rpb24gSih0KXtyZXR1cm4idHJ1ZSI9PT10fHwiZmFsc2UiIT09dCYmKHQ9PT1OdW1iZXIodCkudG9TdHJpbmcoKT9OdW1iZXIodCk6IiI9PT10fHwibnVsbCI9PT10P251bGw6dCl9ZnVuY3Rpb24gdHQodCl7cmV0dXJuIHQucmVwbGFjZSgvW0EtWl0vZywoZnVuY3Rpb24odCl7cmV0dXJuIi0iK3QudG9Mb3dlckNhc2UoKX0pKX12YXIgZXQ9e3NldERhdGFBdHRyaWJ1dGU6ZnVuY3Rpb24odCxlLG4pe3Quc2V0QXR0cmlidXRlKCJkYXRhLSIrdHQoZSksbil9LHJlbW92ZURhdGFBdHRyaWJ1dGU6ZnVuY3Rpb24odCxlKXt0LnJlbW92ZUF0dHJpYnV0ZSgiZGF0YS0iK3R0KGUpKX0sZ2V0RGF0YUF0dHJpYnV0ZXM6ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJue307dmFyIGU9cyh7fSx0LmRhdGFzZXQpO3JldHVybiBPYmplY3Qua2V5cyhlKS5mb3JFYWNoKChmdW5jdGlvbih0KXtlW3RdPUooZVt0XSl9KSksZX0sZ2V0RGF0YUF0dHJpYnV0ZTpmdW5jdGlvbih0LGUpe3JldHVybiBKKHQuZ2V0QXR0cmlidXRlKCJkYXRhLSIrdHQoZSkpKX0sb2Zmc2V0OmZ1bmN0aW9uKHQpe3ZhciBlPXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7cmV0dXJue3RvcDplLnRvcCtkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCxsZWZ0OmUubGVmdCtkb2N1bWVudC5ib2R5LnNjcm9sbExlZnR9fSxwb3NpdGlvbjpmdW5jdGlvbih0KXtyZXR1cm57dG9wOnQub2Zmc2V0VG9wLGxlZnQ6dC5vZmZzZXRMZWZ0fX0sdG9nZ2xlQ2xhc3M6ZnVuY3Rpb24odCxlKXt0JiYodC5jbGFzc0xpc3QuY29udGFpbnMoZSk/dC5jbGFzc0xpc3QucmVtb3ZlKGUpOnQuY2xhc3NMaXN0LmFkZChlKSl9fSxudD17bWF0Y2hlczpmdW5jdGlvbih0LGUpe3JldHVybiB0Lm1hdGNoZXMoZSl9LGZpbmQ6ZnVuY3Rpb24odCxlKXt2YXIgbjtyZXR1cm4gdm9pZCAwPT09ZSYmKGU9ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSwobj1bXSkuY29uY2F0LmFwcGx5KG4sQS5jYWxsKGUsdCkpfSxmaW5kT25lOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHZvaWQgMD09PWUmJihlPWRvY3VtZW50LmRvY3VtZW50RWxlbWVudCksUy5jYWxsKGUsdCl9LGNoaWxkcmVuOmZ1bmN0aW9uKHQsZSl7dmFyIG4saT0obj1bXSkuY29uY2F0LmFwcGx5KG4sdC5jaGlsZHJlbik7cmV0dXJuIGkuZmlsdGVyKChmdW5jdGlvbih0KXtyZXR1cm4gdC5tYXRjaGVzKGUpfSkpfSxwYXJlbnRzOmZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuPVtdLGk9dC5wYXJlbnROb2RlO2kmJmkubm9kZVR5cGU9PT1Ob2RlLkVMRU1FTlRfTk9ERSYmMyE9PWkubm9kZVR5cGU7KXRoaXMubWF0Y2hlcyhpLGUpJiZuLnB1c2goaSksaT1pLnBhcmVudE5vZGU7cmV0dXJuIG59LHByZXY6ZnVuY3Rpb24odCxlKXtmb3IodmFyIG49dC5wcmV2aW91c0VsZW1lbnRTaWJsaW5nO247KXtpZihuLm1hdGNoZXMoZSkpcmV0dXJuW25dO249bi5wcmV2aW91c0VsZW1lbnRTaWJsaW5nfXJldHVybltdfSxuZXh0OmZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuPXQubmV4dEVsZW1lbnRTaWJsaW5nO247KXtpZih0aGlzLm1hdGNoZXMobixlKSlyZXR1cm5bbl07bj1uLm5leHRFbGVtZW50U2libGluZ31yZXR1cm5bXX19LGl0PSJjYXJvdXNlbCIsb3Q9Ii5icy5jYXJvdXNlbCIsc3Q9e2ludGVydmFsOjVlMyxrZXlib2FyZDohMCxzbGlkZTohMSxwYXVzZToiaG92ZXIiLHdyYXA6ITAsdG91Y2g6ITB9LHJ0PXtpbnRlcnZhbDoiKG51bWJlcnxib29sZWFuKSIsa2V5Ym9hcmQ6ImJvb2xlYW4iLHNsaWRlOiIoYm9vbGVhbnxzdHJpbmcpIixwYXVzZToiKHN0cmluZ3xib29sZWFuKSIsd3JhcDoiYm9vbGVhbiIsdG91Y2g6ImJvb2xlYW4ifSxhdD17VE9VQ0g6InRvdWNoIixQRU46InBlbiJ9LGx0PWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUpe3RoaXMuX2l0ZW1zPW51bGwsdGhpcy5faW50ZXJ2YWw9bnVsbCx0aGlzLl9hY3RpdmVFbGVtZW50PW51bGwsdGhpcy5faXNQYXVzZWQ9ITEsdGhpcy5faXNTbGlkaW5nPSExLHRoaXMudG91Y2hUaW1lb3V0PW51bGwsdGhpcy50b3VjaFN0YXJ0WD0wLHRoaXMudG91Y2hEZWx0YVg9MCx0aGlzLl9jb25maWc9dGhpcy5fZ2V0Q29uZmlnKGUpLHRoaXMuX2VsZW1lbnQ9dCx0aGlzLl9pbmRpY2F0b3JzRWxlbWVudD1udC5maW5kT25lKCIuY2Fyb3VzZWwtaW5kaWNhdG9ycyIsdGhpcy5fZWxlbWVudCksdGhpcy5fdG91Y2hTdXBwb3J0ZWQ9Im9udG91Y2hzdGFydCJpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnR8fG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cz4wLHRoaXMuX3BvaW50ZXJFdmVudD1Cb29sZWFuKHdpbmRvdy5Qb2ludGVyRXZlbnQpLHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCksVCh0LCJicy5jYXJvdXNlbCIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUubmV4dD1mdW5jdGlvbigpe3RoaXMuX2lzU2xpZGluZ3x8dGhpcy5fc2xpZGUoIm5leHQiKX0sZS5uZXh0V2hlblZpc2libGU9ZnVuY3Rpb24oKXshZG9jdW1lbnQuaGlkZGVuJiZiKHRoaXMuX2VsZW1lbnQpJiZ0aGlzLm5leHQoKX0sZS5wcmV2PWZ1bmN0aW9uKCl7dGhpcy5faXNTbGlkaW5nfHx0aGlzLl9zbGlkZSgicHJldiIpfSxlLnBhdXNlPWZ1bmN0aW9uKHQpe3R8fCh0aGlzLl9pc1BhdXNlZD0hMCksbnQuZmluZE9uZSgiLmNhcm91c2VsLWl0ZW0tbmV4dCwgLmNhcm91c2VsLWl0ZW0tcHJldiIsdGhpcy5fZWxlbWVudCkmJihwKHRoaXMuX2VsZW1lbnQpLHRoaXMuY3ljbGUoITApKSxjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKSx0aGlzLl9pbnRlcnZhbD1udWxsfSxlLmN5Y2xlPWZ1bmN0aW9uKHQpe3R8fCh0aGlzLl9pc1BhdXNlZD0hMSksdGhpcy5faW50ZXJ2YWwmJihjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKSx0aGlzLl9pbnRlcnZhbD1udWxsKSx0aGlzLl9jb25maWcmJnRoaXMuX2NvbmZpZy5pbnRlcnZhbCYmIXRoaXMuX2lzUGF1c2VkJiYodGhpcy5faW50ZXJ2YWw9c2V0SW50ZXJ2YWwoKGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZT90aGlzLm5leHRXaGVuVmlzaWJsZTp0aGlzLm5leHQpLmJpbmQodGhpcyksdGhpcy5fY29uZmlnLmludGVydmFsKSl9LGUudG89ZnVuY3Rpb24odCl7dmFyIGU9dGhpczt0aGlzLl9hY3RpdmVFbGVtZW50PW50LmZpbmRPbmUoIi5hY3RpdmUuY2Fyb3VzZWwtaXRlbSIsdGhpcy5fZWxlbWVudCk7dmFyIG49dGhpcy5fZ2V0SXRlbUluZGV4KHRoaXMuX2FjdGl2ZUVsZW1lbnQpO2lmKCEodD50aGlzLl9pdGVtcy5sZW5ndGgtMXx8dDwwKSlpZih0aGlzLl9pc1NsaWRpbmcpcS5vbmUodGhpcy5fZWxlbWVudCwic2xpZC5icy5jYXJvdXNlbCIsKGZ1bmN0aW9uKCl7cmV0dXJuIGUudG8odCl9KSk7ZWxzZXtpZihuPT09dClyZXR1cm4gdGhpcy5wYXVzZSgpLHZvaWQgdGhpcy5jeWNsZSgpO3ZhciBpPXQ+bj8ibmV4dCI6InByZXYiO3RoaXMuX3NsaWRlKGksdGhpcy5faXRlbXNbdF0pfX0sZS5kaXNwb3NlPWZ1bmN0aW9uKCl7cS5vZmYodGhpcy5fZWxlbWVudCxvdCksQyh0aGlzLl9lbGVtZW50LCJicy5jYXJvdXNlbCIpLHRoaXMuX2l0ZW1zPW51bGwsdGhpcy5fY29uZmlnPW51bGwsdGhpcy5fZWxlbWVudD1udWxsLHRoaXMuX2ludGVydmFsPW51bGwsdGhpcy5faXNQYXVzZWQ9bnVsbCx0aGlzLl9pc1NsaWRpbmc9bnVsbCx0aGlzLl9hY3RpdmVFbGVtZW50PW51bGwsdGhpcy5faW5kaWNhdG9yc0VsZW1lbnQ9bnVsbH0sZS5fZ2V0Q29uZmlnPWZ1bmN0aW9uKHQpe3JldHVybiB0PXMocyh7fSxzdCksdCksdihpdCx0LHJ0KSx0fSxlLl9oYW5kbGVTd2lwZT1mdW5jdGlvbigpe3ZhciB0PU1hdGguYWJzKHRoaXMudG91Y2hEZWx0YVgpO2lmKCEodDw9NDApKXt2YXIgZT10L3RoaXMudG91Y2hEZWx0YVg7dGhpcy50b3VjaERlbHRhWD0wLGU+MCYmdGhpcy5wcmV2KCksZTwwJiZ0aGlzLm5leHQoKX19LGUuX2FkZEV2ZW50TGlzdGVuZXJzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpczt0aGlzLl9jb25maWcua2V5Ym9hcmQmJnEub24odGhpcy5fZWxlbWVudCwia2V5ZG93bi5icy5jYXJvdXNlbCIsKGZ1bmN0aW9uKGUpe3JldHVybiB0Ll9rZXlkb3duKGUpfSkpLCJob3ZlciI9PT10aGlzLl9jb25maWcucGF1c2UmJihxLm9uKHRoaXMuX2VsZW1lbnQsIm1vdXNlZW50ZXIuYnMuY2Fyb3VzZWwiLChmdW5jdGlvbihlKXtyZXR1cm4gdC5wYXVzZShlKX0pKSxxLm9uKHRoaXMuX2VsZW1lbnQsIm1vdXNlbGVhdmUuYnMuY2Fyb3VzZWwiLChmdW5jdGlvbihlKXtyZXR1cm4gdC5jeWNsZShlKX0pKSksdGhpcy5fY29uZmlnLnRvdWNoJiZ0aGlzLl90b3VjaFN1cHBvcnRlZCYmdGhpcy5fYWRkVG91Y2hFdmVudExpc3RlbmVycygpfSxlLl9hZGRUb3VjaEV2ZW50TGlzdGVuZXJzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxlPWZ1bmN0aW9uKGUpe3QuX3BvaW50ZXJFdmVudCYmYXRbZS5wb2ludGVyVHlwZS50b1VwcGVyQ2FzZSgpXT90LnRvdWNoU3RhcnRYPWUuY2xpZW50WDp0Ll9wb2ludGVyRXZlbnR8fCh0LnRvdWNoU3RhcnRYPWUudG91Y2hlc1swXS5jbGllbnRYKX0sbj1mdW5jdGlvbihlKXt0Ll9wb2ludGVyRXZlbnQmJmF0W2UucG9pbnRlclR5cGUudG9VcHBlckNhc2UoKV0mJih0LnRvdWNoRGVsdGFYPWUuY2xpZW50WC10LnRvdWNoU3RhcnRYKSx0Ll9oYW5kbGVTd2lwZSgpLCJob3ZlciI9PT10Ll9jb25maWcucGF1c2UmJih0LnBhdXNlKCksdC50b3VjaFRpbWVvdXQmJmNsZWFyVGltZW91dCh0LnRvdWNoVGltZW91dCksdC50b3VjaFRpbWVvdXQ9c2V0VGltZW91dCgoZnVuY3Rpb24oZSl7cmV0dXJuIHQuY3ljbGUoZSl9KSw1MDArdC5fY29uZmlnLmludGVydmFsKSl9O250LmZpbmQoIi5jYXJvdXNlbC1pdGVtIGltZyIsdGhpcy5fZWxlbWVudCkuZm9yRWFjaCgoZnVuY3Rpb24odCl7cS5vbih0LCJkcmFnc3RhcnQuYnMuY2Fyb3VzZWwiLChmdW5jdGlvbih0KXtyZXR1cm4gdC5wcmV2ZW50RGVmYXVsdCgpfSkpfSkpLHRoaXMuX3BvaW50ZXJFdmVudD8ocS5vbih0aGlzLl9lbGVtZW50LCJwb2ludGVyZG93bi5icy5jYXJvdXNlbCIsKGZ1bmN0aW9uKHQpe3JldHVybiBlKHQpfSkpLHEub24odGhpcy5fZWxlbWVudCwicG9pbnRlcnVwLmJzLmNhcm91c2VsIiwoZnVuY3Rpb24odCl7cmV0dXJuIG4odCl9KSksdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKCJwb2ludGVyLWV2ZW50IikpOihxLm9uKHRoaXMuX2VsZW1lbnQsInRvdWNoc3RhcnQuYnMuY2Fyb3VzZWwiLChmdW5jdGlvbih0KXtyZXR1cm4gZSh0KX0pKSxxLm9uKHRoaXMuX2VsZW1lbnQsInRvdWNobW92ZS5icy5jYXJvdXNlbCIsKGZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbihlKXtlLnRvdWNoZXMmJmUudG91Y2hlcy5sZW5ndGg+MT90LnRvdWNoRGVsdGFYPTA6dC50b3VjaERlbHRhWD1lLnRvdWNoZXNbMF0uY2xpZW50WC10LnRvdWNoU3RhcnRYfShlKX0pKSxxLm9uKHRoaXMuX2VsZW1lbnQsInRvdWNoZW5kLmJzLmNhcm91c2VsIiwoZnVuY3Rpb24odCl7cmV0dXJuIG4odCl9KSkpfSxlLl9rZXlkb3duPWZ1bmN0aW9uKHQpe2lmKCEvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KHQudGFyZ2V0LnRhZ05hbWUpKXN3aXRjaCh0LmtleSl7Y2FzZSJBcnJvd0xlZnQiOnQucHJldmVudERlZmF1bHQoKSx0aGlzLnByZXYoKTticmVhaztjYXNlIkFycm93UmlnaHQiOnQucHJldmVudERlZmF1bHQoKSx0aGlzLm5leHQoKX19LGUuX2dldEl0ZW1JbmRleD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5faXRlbXM9dCYmdC5wYXJlbnROb2RlP250LmZpbmQoIi5jYXJvdXNlbC1pdGVtIix0LnBhcmVudE5vZGUpOltdLHRoaXMuX2l0ZW1zLmluZGV4T2YodCl9LGUuX2dldEl0ZW1CeURpcmVjdGlvbj1mdW5jdGlvbih0LGUpe3ZhciBuPSJuZXh0Ij09PXQsaT0icHJldiI9PT10LG89dGhpcy5fZ2V0SXRlbUluZGV4KGUpLHM9dGhpcy5faXRlbXMubGVuZ3RoLTE7aWYoKGkmJjA9PT1vfHxuJiZvPT09cykmJiF0aGlzLl9jb25maWcud3JhcClyZXR1cm4gZTt2YXIgcj0obysoInByZXYiPT09dD8tMToxKSkldGhpcy5faXRlbXMubGVuZ3RoO3JldHVybi0xPT09cj90aGlzLl9pdGVtc1t0aGlzLl9pdGVtcy5sZW5ndGgtMV06dGhpcy5faXRlbXNbcl19LGUuX3RyaWdnZXJTbGlkZUV2ZW50PWZ1bmN0aW9uKHQsZSl7dmFyIG49dGhpcy5fZ2V0SXRlbUluZGV4KHQpLGk9dGhpcy5fZ2V0SXRlbUluZGV4KG50LmZpbmRPbmUoIi5hY3RpdmUuY2Fyb3VzZWwtaXRlbSIsdGhpcy5fZWxlbWVudCkpO3JldHVybiBxLnRyaWdnZXIodGhpcy5fZWxlbWVudCwic2xpZGUuYnMuY2Fyb3VzZWwiLHtyZWxhdGVkVGFyZ2V0OnQsZGlyZWN0aW9uOmUsZnJvbTppLHRvOm59KX0sZS5fc2V0QWN0aXZlSW5kaWNhdG9yRWxlbWVudD1mdW5jdGlvbih0KXtpZih0aGlzLl9pbmRpY2F0b3JzRWxlbWVudCl7Zm9yKHZhciBlPW50LmZpbmQoIi5hY3RpdmUiLHRoaXMuX2luZGljYXRvcnNFbGVtZW50KSxuPTA7bjxlLmxlbmd0aDtuKyspZVtuXS5jbGFzc0xpc3QucmVtb3ZlKCJhY3RpdmUiKTt2YXIgaT10aGlzLl9pbmRpY2F0b3JzRWxlbWVudC5jaGlsZHJlblt0aGlzLl9nZXRJdGVtSW5kZXgodCldO2kmJmkuY2xhc3NMaXN0LmFkZCgiYWN0aXZlIil9fSxlLl9zbGlkZT1mdW5jdGlvbih0LGUpe3ZhciBuLGksbyxzPXRoaXMscj1udC5maW5kT25lKCIuYWN0aXZlLmNhcm91c2VsLWl0ZW0iLHRoaXMuX2VsZW1lbnQpLGE9dGhpcy5fZ2V0SXRlbUluZGV4KHIpLGw9ZXx8ciYmdGhpcy5fZ2V0SXRlbUJ5RGlyZWN0aW9uKHQsciksYz10aGlzLl9nZXRJdGVtSW5kZXgobCksdT1Cb29sZWFuKHRoaXMuX2ludGVydmFsKTtpZigibmV4dCI9PT10PyhuPSJjYXJvdXNlbC1pdGVtLWxlZnQiLGk9ImNhcm91c2VsLWl0ZW0tbmV4dCIsbz0ibGVmdCIpOihuPSJjYXJvdXNlbC1pdGVtLXJpZ2h0IixpPSJjYXJvdXNlbC1pdGVtLXByZXYiLG89InJpZ2h0IiksbCYmbC5jbGFzc0xpc3QuY29udGFpbnMoImFjdGl2ZSIpKXRoaXMuX2lzU2xpZGluZz0hMTtlbHNlIGlmKCF0aGlzLl90cmlnZ2VyU2xpZGVFdmVudChsLG8pLmRlZmF1bHRQcmV2ZW50ZWQmJnImJmwpe2lmKHRoaXMuX2lzU2xpZGluZz0hMCx1JiZ0aGlzLnBhdXNlKCksdGhpcy5fc2V0QWN0aXZlSW5kaWNhdG9yRWxlbWVudChsKSx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygic2xpZGUiKSl7bC5jbGFzc0xpc3QuYWRkKGkpLHcobCksci5jbGFzc0xpc3QuYWRkKG4pLGwuY2xhc3NMaXN0LmFkZChuKTt2YXIgaD1wYXJzZUludChsLmdldEF0dHJpYnV0ZSgiZGF0YS1pbnRlcnZhbCIpLDEwKTtoPyh0aGlzLl9jb25maWcuZGVmYXVsdEludGVydmFsPXRoaXMuX2NvbmZpZy5kZWZhdWx0SW50ZXJ2YWx8fHRoaXMuX2NvbmZpZy5pbnRlcnZhbCx0aGlzLl9jb25maWcuaW50ZXJ2YWw9aCk6dGhpcy5fY29uZmlnLmludGVydmFsPXRoaXMuX2NvbmZpZy5kZWZhdWx0SW50ZXJ2YWx8fHRoaXMuX2NvbmZpZy5pbnRlcnZhbDt2YXIgZj1nKHIpO3Eub25lKHIsInRyYW5zaXRpb25lbmQiLChmdW5jdGlvbigpe2wuY2xhc3NMaXN0LnJlbW92ZShuLGkpLGwuY2xhc3NMaXN0LmFkZCgiYWN0aXZlIiksci5jbGFzc0xpc3QucmVtb3ZlKCJhY3RpdmUiLGksbikscy5faXNTbGlkaW5nPSExLHNldFRpbWVvdXQoKGZ1bmN0aW9uKCl7cS50cmlnZ2VyKHMuX2VsZW1lbnQsInNsaWQuYnMuY2Fyb3VzZWwiLHtyZWxhdGVkVGFyZ2V0OmwsZGlyZWN0aW9uOm8sZnJvbTphLHRvOmN9KX0pLDApfSkpLF8ocixmKX1lbHNlIHIuY2xhc3NMaXN0LnJlbW92ZSgiYWN0aXZlIiksbC5jbGFzc0xpc3QuYWRkKCJhY3RpdmUiKSx0aGlzLl9pc1NsaWRpbmc9ITEscS50cmlnZ2VyKHRoaXMuX2VsZW1lbnQsInNsaWQuYnMuY2Fyb3VzZWwiLHtyZWxhdGVkVGFyZ2V0OmwsZGlyZWN0aW9uOm8sZnJvbTphLHRvOmN9KTt1JiZ0aGlzLmN5Y2xlKCl9fSx0LmNhcm91c2VsSW50ZXJmYWNlPWZ1bmN0aW9uKGUsbil7dmFyIGk9TChlLCJicy5jYXJvdXNlbCIpLG89cyhzKHt9LHN0KSxldC5nZXREYXRhQXR0cmlidXRlcyhlKSk7Im9iamVjdCI9PXR5cGVvZiBuJiYobz1zKHMoe30sbyksbikpO3ZhciByPSJzdHJpbmciPT10eXBlb2Ygbj9uOm8uc2xpZGU7aWYoaXx8KGk9bmV3IHQoZSxvKSksIm51bWJlciI9PXR5cGVvZiBuKWkudG8obik7ZWxzZSBpZigic3RyaW5nIj09dHlwZW9mIHIpe2lmKHZvaWQgMD09PWlbcl0pdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gbWV0aG9kIG5hbWVkICInK3IrJyInKTtpW3JdKCl9ZWxzZSBvLmludGVydmFsJiZvLnJpZGUmJihpLnBhdXNlKCksaS5jeWNsZSgpKX0sdC5qUXVlcnlJbnRlcmZhY2U9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZWFjaCgoZnVuY3Rpb24oKXt0LmNhcm91c2VsSW50ZXJmYWNlKHRoaXMsZSl9KSl9LHQuZGF0YUFwaUNsaWNrSGFuZGxlcj1mdW5jdGlvbihlKXt2YXIgbj1kKHRoaXMpO2lmKG4mJm4uY2xhc3NMaXN0LmNvbnRhaW5zKCJjYXJvdXNlbCIpKXt2YXIgaT1zKHMoe30sZXQuZ2V0RGF0YUF0dHJpYnV0ZXMobikpLGV0LmdldERhdGFBdHRyaWJ1dGVzKHRoaXMpKSxvPXRoaXMuZ2V0QXR0cmlidXRlKCJkYXRhLXNsaWRlLXRvIik7byYmKGkuaW50ZXJ2YWw9ITEpLHQuY2Fyb3VzZWxJbnRlcmZhY2UobixpKSxvJiZMKG4sImJzLmNhcm91c2VsIikudG8obyksZS5wcmV2ZW50RGVmYXVsdCgpfX0sdC5nZXRJbnN0YW5jZT1mdW5jdGlvbih0KXtyZXR1cm4gTCh0LCJicy5jYXJvdXNlbCIpfSxuKHQsbnVsbCxbe2tleToiVkVSU0lPTiIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIjUuMC4wLWFscGhhMSJ9fSx7a2V5OiJEZWZhdWx0IixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gc3R9fV0pLHR9KCk7cS5vbihkb2N1bWVudCwiY2xpY2suYnMuY2Fyb3VzZWwuZGF0YS1hcGkiLCJbZGF0YS1zbGlkZV0sIFtkYXRhLXNsaWRlLXRvXSIsbHQuZGF0YUFwaUNsaWNrSGFuZGxlcikscS5vbih3aW5kb3csImxvYWQuYnMuY2Fyb3VzZWwuZGF0YS1hcGkiLChmdW5jdGlvbigpe2Zvcih2YXIgdD1udC5maW5kKCdbZGF0YS1yaWRlPSJjYXJvdXNlbCJdJyksZT0wLG49dC5sZW5ndGg7ZTxuO2UrKylsdC5jYXJvdXNlbEludGVyZmFjZSh0W2VdLEwodFtlXSwiYnMuY2Fyb3VzZWwiKSl9KSk7dmFyIGN0PUUoKTtpZihjdCl7dmFyIHV0PWN0LmZuW2l0XTtjdC5mbltpdF09bHQualF1ZXJ5SW50ZXJmYWNlLGN0LmZuW2l0XS5Db25zdHJ1Y3Rvcj1sdCxjdC5mbltpdF0ubm9Db25mbGljdD1mdW5jdGlvbigpe3JldHVybiBjdC5mbltpdF09dXQsbHQualF1ZXJ5SW50ZXJmYWNlfX12YXIgaHQ9ImNvbGxhcHNlIixmdD17dG9nZ2xlOiEwLHBhcmVudDoiIn0sZHQ9e3RvZ2dsZToiYm9vbGVhbiIscGFyZW50OiIoc3RyaW5nfGVsZW1lbnQpIn0sZ3Q9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQsZSl7dGhpcy5faXNUcmFuc2l0aW9uaW5nPSExLHRoaXMuX2VsZW1lbnQ9dCx0aGlzLl9jb25maWc9dGhpcy5fZ2V0Q29uZmlnKGUpLHRoaXMuX3RyaWdnZXJBcnJheT1udC5maW5kKCdbZGF0YS10b2dnbGU9ImNvbGxhcHNlIl1baHJlZj0iIycrdC5pZCsnIl0sW2RhdGEtdG9nZ2xlPSJjb2xsYXBzZSJdW2RhdGEtdGFyZ2V0PSIjJyt0LmlkKyciXScpO2Zvcih2YXIgbj1udC5maW5kKCdbZGF0YS10b2dnbGU9ImNvbGxhcHNlIl0nKSxpPTAsbz1uLmxlbmd0aDtpPG87aSsrKXt2YXIgcz1uW2ldLHI9ZihzKSxhPW50LmZpbmQocikuZmlsdGVyKChmdW5jdGlvbihlKXtyZXR1cm4gZT09PXR9KSk7bnVsbCE9PXImJmEubGVuZ3RoJiYodGhpcy5fc2VsZWN0b3I9cix0aGlzLl90cmlnZ2VyQXJyYXkucHVzaChzKSl9dGhpcy5fcGFyZW50PXRoaXMuX2NvbmZpZy5wYXJlbnQ/dGhpcy5fZ2V0UGFyZW50KCk6bnVsbCx0aGlzLl9jb25maWcucGFyZW50fHx0aGlzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3ModGhpcy5fZWxlbWVudCx0aGlzLl90cmlnZ2VyQXJyYXkpLHRoaXMuX2NvbmZpZy50b2dnbGUmJnRoaXMudG9nZ2xlKCksVCh0LCJicy5jb2xsYXBzZSIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUudG9nZ2xlPWZ1bmN0aW9uKCl7dGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKT90aGlzLmhpZGUoKTp0aGlzLnNob3coKX0sZS5zaG93PWZ1bmN0aW9uKCl7dmFyIGU9dGhpcztpZighdGhpcy5faXNUcmFuc2l0aW9uaW5nJiYhdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKSl7dmFyIG4saTt0aGlzLl9wYXJlbnQmJjA9PT0obj1udC5maW5kKCIuc2hvdywgLmNvbGxhcHNpbmciLHRoaXMuX3BhcmVudCkuZmlsdGVyKChmdW5jdGlvbih0KXtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIGUuX2NvbmZpZy5wYXJlbnQ/dC5nZXRBdHRyaWJ1dGUoImRhdGEtcGFyZW50Iik9PT1lLl9jb25maWcucGFyZW50OnQuY2xhc3NMaXN0LmNvbnRhaW5zKCJjb2xsYXBzZSIpfSkpKS5sZW5ndGgmJihuPW51bGwpO3ZhciBvPW50LmZpbmRPbmUodGhpcy5fc2VsZWN0b3IpO2lmKG4pe3ZhciBzPW4uZmlsdGVyKChmdW5jdGlvbih0KXtyZXR1cm4gbyE9PXR9KSk7aWYoKGk9c1swXT9MKHNbMF0sImJzLmNvbGxhcHNlIik6bnVsbCkmJmkuX2lzVHJhbnNpdGlvbmluZylyZXR1cm59aWYoIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJzaG93LmJzLmNvbGxhcHNlIikuZGVmYXVsdFByZXZlbnRlZCl7biYmbi5mb3JFYWNoKChmdW5jdGlvbihlKXtvIT09ZSYmdC5jb2xsYXBzZUludGVyZmFjZShlLCJoaWRlIiksaXx8VChlLCJicy5jb2xsYXBzZSIsbnVsbCl9KSk7dmFyIHI9dGhpcy5fZ2V0RGltZW5zaW9uKCk7dGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCJjb2xsYXBzZSIpLHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZCgiY29sbGFwc2luZyIpLHRoaXMuX2VsZW1lbnQuc3R5bGVbcl09MCx0aGlzLl90cmlnZ2VyQXJyYXkubGVuZ3RoJiZ0aGlzLl90cmlnZ2VyQXJyYXkuZm9yRWFjaCgoZnVuY3Rpb24odCl7dC5jbGFzc0xpc3QucmVtb3ZlKCJjb2xsYXBzZWQiKSx0LnNldEF0dHJpYnV0ZSgiYXJpYS1leHBhbmRlZCIsITApfSkpLHRoaXMuc2V0VHJhbnNpdGlvbmluZyghMCk7dmFyIGE9InNjcm9sbCIrKHJbMF0udG9VcHBlckNhc2UoKStyLnNsaWNlKDEpKSxsPWcodGhpcy5fZWxlbWVudCk7cS5vbmUodGhpcy5fZWxlbWVudCwidHJhbnNpdGlvbmVuZCIsKGZ1bmN0aW9uKCl7ZS5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCJjb2xsYXBzaW5nIiksZS5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKCJjb2xsYXBzZSIsInNob3ciKSxlLl9lbGVtZW50LnN0eWxlW3JdPSIiLGUuc2V0VHJhbnNpdGlvbmluZyghMSkscS50cmlnZ2VyKGUuX2VsZW1lbnQsInNob3duLmJzLmNvbGxhcHNlIil9KSksXyh0aGlzLl9lbGVtZW50LGwpLHRoaXMuX2VsZW1lbnQuc3R5bGVbcl09dGhpcy5fZWxlbWVudFthXSsicHgifX19LGUuaGlkZT1mdW5jdGlvbigpe3ZhciB0PXRoaXM7aWYoIXRoaXMuX2lzVHJhbnNpdGlvbmluZyYmdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKSYmIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJoaWRlLmJzLmNvbGxhcHNlIikuZGVmYXVsdFByZXZlbnRlZCl7dmFyIGU9dGhpcy5fZ2V0RGltZW5zaW9uKCk7dGhpcy5fZWxlbWVudC5zdHlsZVtlXT10aGlzLl9lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpW2VdKyJweCIsdyh0aGlzLl9lbGVtZW50KSx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoImNvbGxhcHNpbmciKSx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoImNvbGxhcHNlIiwic2hvdyIpO3ZhciBuPXRoaXMuX3RyaWdnZXJBcnJheS5sZW5ndGg7aWYobj4wKWZvcih2YXIgaT0wO2k8bjtpKyspe3ZhciBvPXRoaXMuX3RyaWdnZXJBcnJheVtpXSxzPWQobyk7cyYmIXMuY2xhc3NMaXN0LmNvbnRhaW5zKCJzaG93IikmJihvLmNsYXNzTGlzdC5hZGQoImNvbGxhcHNlZCIpLG8uc2V0QXR0cmlidXRlKCJhcmlhLWV4cGFuZGVkIiwhMSkpfXRoaXMuc2V0VHJhbnNpdGlvbmluZyghMCk7dGhpcy5fZWxlbWVudC5zdHlsZVtlXT0iIjt2YXIgcj1nKHRoaXMuX2VsZW1lbnQpO3Eub25lKHRoaXMuX2VsZW1lbnQsInRyYW5zaXRpb25lbmQiLChmdW5jdGlvbigpe3Quc2V0VHJhbnNpdGlvbmluZyghMSksdC5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCJjb2xsYXBzaW5nIiksdC5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKCJjb2xsYXBzZSIpLHEudHJpZ2dlcih0Ll9lbGVtZW50LCJoaWRkZW4uYnMuY29sbGFwc2UiKX0pKSxfKHRoaXMuX2VsZW1lbnQscil9fSxlLnNldFRyYW5zaXRpb25pbmc9ZnVuY3Rpb24odCl7dGhpcy5faXNUcmFuc2l0aW9uaW5nPXR9LGUuZGlzcG9zZT1mdW5jdGlvbigpe0ModGhpcy5fZWxlbWVudCwiYnMuY29sbGFwc2UiKSx0aGlzLl9jb25maWc9bnVsbCx0aGlzLl9wYXJlbnQ9bnVsbCx0aGlzLl9lbGVtZW50PW51bGwsdGhpcy5fdHJpZ2dlckFycmF5PW51bGwsdGhpcy5faXNUcmFuc2l0aW9uaW5nPW51bGx9LGUuX2dldENvbmZpZz1mdW5jdGlvbih0KXtyZXR1cm4odD1zKHMoe30sZnQpLHQpKS50b2dnbGU9Qm9vbGVhbih0LnRvZ2dsZSksdihodCx0LGR0KSx0fSxlLl9nZXREaW1lbnNpb249ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoIndpZHRoIik/IndpZHRoIjoiaGVpZ2h0In0sZS5fZ2V0UGFyZW50PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxlPXRoaXMuX2NvbmZpZy5wYXJlbnQ7bShlKT92b2lkIDA9PT1lLmpxdWVyeSYmdm9pZCAwPT09ZVswXXx8KGU9ZVswXSk6ZT1udC5maW5kT25lKGUpO3ZhciBuPSdbZGF0YS10b2dnbGU9ImNvbGxhcHNlIl1bZGF0YS1wYXJlbnQ9IicrZSsnIl0nO3JldHVybiBudC5maW5kKG4sZSkuZm9yRWFjaCgoZnVuY3Rpb24oZSl7dmFyIG49ZChlKTt0Ll9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MobixbZV0pfSkpLGV9LGUuX2FkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcz1mdW5jdGlvbih0LGUpe2lmKHQpe3ZhciBuPXQuY2xhc3NMaXN0LmNvbnRhaW5zKCJzaG93Iik7ZS5sZW5ndGgmJmUuZm9yRWFjaCgoZnVuY3Rpb24odCl7bj90LmNsYXNzTGlzdC5yZW1vdmUoImNvbGxhcHNlZCIpOnQuY2xhc3NMaXN0LmFkZCgiY29sbGFwc2VkIiksdC5zZXRBdHRyaWJ1dGUoImFyaWEtZXhwYW5kZWQiLG4pfSkpfX0sdC5jb2xsYXBzZUludGVyZmFjZT1mdW5jdGlvbihlLG4pe3ZhciBpPUwoZSwiYnMuY29sbGFwc2UiKSxvPXMocyhzKHt9LGZ0KSxldC5nZXREYXRhQXR0cmlidXRlcyhlKSksIm9iamVjdCI9PXR5cGVvZiBuJiZuP246e30pO2lmKCFpJiZvLnRvZ2dsZSYmInN0cmluZyI9PXR5cGVvZiBuJiYvc2hvd3xoaWRlLy50ZXN0KG4pJiYoby50b2dnbGU9ITEpLGl8fChpPW5ldyB0KGUsbykpLCJzdHJpbmciPT10eXBlb2Ygbil7aWYodm9pZCAwPT09aVtuXSl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyBtZXRob2QgbmFtZWQgIicrbisnIicpO2lbbl0oKX19LHQualF1ZXJ5SW50ZXJmYWNlPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVhY2goKGZ1bmN0aW9uKCl7dC5jb2xsYXBzZUludGVyZmFjZSh0aGlzLGUpfSkpfSx0LmdldEluc3RhbmNlPWZ1bmN0aW9uKHQpe3JldHVybiBMKHQsImJzLmNvbGxhcHNlIil9LG4odCxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHQiLGdldDpmdW5jdGlvbigpe3JldHVybiBmdH19XSksdH0oKTtxLm9uKGRvY3VtZW50LCJjbGljay5icy5jb2xsYXBzZS5kYXRhLWFwaSIsJ1tkYXRhLXRvZ2dsZT0iY29sbGFwc2UiXScsKGZ1bmN0aW9uKHQpeyJBIj09PXQudGFyZ2V0LnRhZ05hbWUmJnQucHJldmVudERlZmF1bHQoKTt2YXIgZT1ldC5nZXREYXRhQXR0cmlidXRlcyh0aGlzKSxuPWYodGhpcyk7bnQuZmluZChuKS5mb3JFYWNoKChmdW5jdGlvbih0KXt2YXIgbixpPUwodCwiYnMuY29sbGFwc2UiKTtpPyhudWxsPT09aS5fcGFyZW50JiYic3RyaW5nIj09dHlwZW9mIGUucGFyZW50JiYoaS5fY29uZmlnLnBhcmVudD1lLnBhcmVudCxpLl9wYXJlbnQ9aS5fZ2V0UGFyZW50KCkpLG49InRvZ2dsZSIpOm49ZSxndC5jb2xsYXBzZUludGVyZmFjZSh0LG4pfSkpfSkpO3ZhciBwdD1FKCk7aWYocHQpe3ZhciBtdD1wdC5mbltodF07cHQuZm5baHRdPWd0LmpRdWVyeUludGVyZmFjZSxwdC5mbltodF0uQ29uc3RydWN0b3I9Z3QscHQuZm5baHRdLm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gcHQuZm5baHRdPW10LGd0LmpRdWVyeUludGVyZmFjZX19dmFyIF90PSJkcm9wZG93biIsdnQ9bmV3IFJlZ0V4cCgiQXJyb3dVcHxBcnJvd0Rvd258RXNjYXBlIiksYnQ9e29mZnNldDowLGZsaXA6ITAsYm91bmRhcnk6InNjcm9sbFBhcmVudCIscmVmZXJlbmNlOiJ0b2dnbGUiLGRpc3BsYXk6ImR5bmFtaWMiLHBvcHBlckNvbmZpZzpudWxsfSx5dD17b2Zmc2V0OiIobnVtYmVyfHN0cmluZ3xmdW5jdGlvbikiLGZsaXA6ImJvb2xlYW4iLGJvdW5kYXJ5OiIoc3RyaW5nfGVsZW1lbnQpIixyZWZlcmVuY2U6IihzdHJpbmd8ZWxlbWVudCkiLGRpc3BsYXk6InN0cmluZyIscG9wcGVyQ29uZmlnOiIobnVsbHxvYmplY3QpIn0sd3Q9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKHQsZSl7dGhpcy5fZWxlbWVudD10LHRoaXMuX3BvcHBlcj1udWxsLHRoaXMuX2NvbmZpZz10aGlzLl9nZXRDb25maWcoZSksdGhpcy5fbWVudT10aGlzLl9nZXRNZW51RWxlbWVudCgpLHRoaXMuX2luTmF2YmFyPXRoaXMuX2RldGVjdE5hdmJhcigpLHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCksVCh0LCJicy5kcm9wZG93biIsdGhpcyl9dmFyIGk9ZS5wcm90b3R5cGU7cmV0dXJuIGkudG9nZ2xlPWZ1bmN0aW9uKCl7aWYoIXRoaXMuX2VsZW1lbnQuZGlzYWJsZWQmJiF0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygiZGlzYWJsZWQiKSl7dmFyIHQ9dGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKTtlLmNsZWFyTWVudXMoKSx0fHx0aGlzLnNob3coKX19LGkuc2hvdz1mdW5jdGlvbigpe2lmKCEodGhpcy5fZWxlbWVudC5kaXNhYmxlZHx8dGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoImRpc2FibGVkIil8fHRoaXMuX21lbnUuY2xhc3NMaXN0LmNvbnRhaW5zKCJzaG93IikpKXt2YXIgbj1lLmdldFBhcmVudEZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpLGk9e3JlbGF0ZWRUYXJnZXQ6dGhpcy5fZWxlbWVudH07aWYoIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJzaG93LmJzLmRyb3Bkb3duIixpKS5kZWZhdWx0UHJldmVudGVkKXtpZighdGhpcy5faW5OYXZiYXIpe2lmKHZvaWQgMD09PXQpdGhyb3cgbmV3IFR5cGVFcnJvcigiQm9vdHN0cmFwJ3MgZHJvcGRvd25zIHJlcXVpcmUgUG9wcGVyLmpzIChodHRwczovL3BvcHBlci5qcy5vcmcpIik7dmFyIG89dGhpcy5fZWxlbWVudDsicGFyZW50Ij09PXRoaXMuX2NvbmZpZy5yZWZlcmVuY2U/bz1uOm0odGhpcy5fY29uZmlnLnJlZmVyZW5jZSkmJihvPXRoaXMuX2NvbmZpZy5yZWZlcmVuY2Usdm9pZCAwIT09dGhpcy5fY29uZmlnLnJlZmVyZW5jZS5qcXVlcnkmJihvPXRoaXMuX2NvbmZpZy5yZWZlcmVuY2VbMF0pKSwic2Nyb2xsUGFyZW50IiE9PXRoaXMuX2NvbmZpZy5ib3VuZGFyeSYmbi5jbGFzc0xpc3QuYWRkKCJwb3NpdGlvbi1zdGF0aWMiKSx0aGlzLl9wb3BwZXI9bmV3IHQobyx0aGlzLl9tZW51LHRoaXMuX2dldFBvcHBlckNvbmZpZygpKX12YXIgcztpZigib250b3VjaHN0YXJ0ImluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCYmIW4uY2xvc2VzdCgiLm5hdmJhci1uYXYiKSkocz1bXSkuY29uY2F0LmFwcGx5KHMsZG9jdW1lbnQuYm9keS5jaGlsZHJlbikuZm9yRWFjaCgoZnVuY3Rpb24odCl7cmV0dXJuIHEub24odCwibW91c2VvdmVyIixudWxsLChmdW5jdGlvbigpe30pKX0pKTt0aGlzLl9lbGVtZW50LmZvY3VzKCksdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoImFyaWEtZXhwYW5kZWQiLCEwKSxldC50b2dnbGVDbGFzcyh0aGlzLl9tZW51LCJzaG93IiksZXQudG9nZ2xlQ2xhc3ModGhpcy5fZWxlbWVudCwic2hvdyIpLHEudHJpZ2dlcihuLCJzaG93bi5icy5kcm9wZG93biIsaSl9fX0saS5oaWRlPWZ1bmN0aW9uKCl7aWYoIXRoaXMuX2VsZW1lbnQuZGlzYWJsZWQmJiF0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygiZGlzYWJsZWQiKSYmdGhpcy5fbWVudS5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKSl7dmFyIHQ9ZS5nZXRQYXJlbnRGcm9tRWxlbWVudCh0aGlzLl9lbGVtZW50KSxuPXtyZWxhdGVkVGFyZ2V0OnRoaXMuX2VsZW1lbnR9O3EudHJpZ2dlcih0LCJoaWRlLmJzLmRyb3Bkb3duIixuKS5kZWZhdWx0UHJldmVudGVkfHwodGhpcy5fcG9wcGVyJiZ0aGlzLl9wb3BwZXIuZGVzdHJveSgpLGV0LnRvZ2dsZUNsYXNzKHRoaXMuX21lbnUsInNob3ciKSxldC50b2dnbGVDbGFzcyh0aGlzLl9lbGVtZW50LCJzaG93IikscS50cmlnZ2VyKHQsImhpZGRlbi5icy5kcm9wZG93biIsbikpfX0saS5kaXNwb3NlPWZ1bmN0aW9uKCl7Qyh0aGlzLl9lbGVtZW50LCJicy5kcm9wZG93biIpLHEub2ZmKHRoaXMuX2VsZW1lbnQsIi5icy5kcm9wZG93biIpLHRoaXMuX2VsZW1lbnQ9bnVsbCx0aGlzLl9tZW51PW51bGwsdGhpcy5fcG9wcGVyJiYodGhpcy5fcG9wcGVyLmRlc3Ryb3koKSx0aGlzLl9wb3BwZXI9bnVsbCl9LGkudXBkYXRlPWZ1bmN0aW9uKCl7dGhpcy5faW5OYXZiYXI9dGhpcy5fZGV0ZWN0TmF2YmFyKCksdGhpcy5fcG9wcGVyJiZ0aGlzLl9wb3BwZXIuc2NoZWR1bGVVcGRhdGUoKX0saS5fYWRkRXZlbnRMaXN0ZW5lcnM9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO3Eub24odGhpcy5fZWxlbWVudCwiY2xpY2suYnMuZHJvcGRvd24iLChmdW5jdGlvbihlKXtlLnByZXZlbnREZWZhdWx0KCksZS5zdG9wUHJvcGFnYXRpb24oKSx0LnRvZ2dsZSgpfSkpfSxpLl9nZXRDb25maWc9ZnVuY3Rpb24odCl7cmV0dXJuIHQ9cyhzKHMoe30sdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0KSxldC5nZXREYXRhQXR0cmlidXRlcyh0aGlzLl9lbGVtZW50KSksdCksdihfdCx0LHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdFR5cGUpLHR9LGkuX2dldE1lbnVFbGVtZW50PWZ1bmN0aW9uKCl7cmV0dXJuIG50Lm5leHQodGhpcy5fZWxlbWVudCwiLmRyb3Bkb3duLW1lbnUiKVswXX0saS5fZ2V0UGxhY2VtZW50PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLGU9ImJvdHRvbS1zdGFydCI7cmV0dXJuIHQuY2xhc3NMaXN0LmNvbnRhaW5zKCJkcm9wdXAiKT8oZT0idG9wLXN0YXJ0Iix0aGlzLl9tZW51LmNsYXNzTGlzdC5jb250YWlucygiZHJvcGRvd24tbWVudS1yaWdodCIpJiYoZT0idG9wLWVuZCIpKTp0LmNsYXNzTGlzdC5jb250YWlucygiZHJvcHJpZ2h0Iik/ZT0icmlnaHQtc3RhcnQiOnQuY2xhc3NMaXN0LmNvbnRhaW5zKCJkcm9wbGVmdCIpP2U9ImxlZnQtc3RhcnQiOnRoaXMuX21lbnUuY2xhc3NMaXN0LmNvbnRhaW5zKCJkcm9wZG93bi1tZW51LXJpZ2h0IikmJihlPSJib3R0b20tZW5kIiksZX0saS5fZGV0ZWN0TmF2YmFyPWZ1bmN0aW9uKCl7cmV0dXJuIEJvb2xlYW4odGhpcy5fZWxlbWVudC5jbG9zZXN0KCIubmF2YmFyIikpfSxpLl9nZXRPZmZzZXQ9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLGU9e307cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMuX2NvbmZpZy5vZmZzZXQ/ZS5mbj1mdW5jdGlvbihlKXtyZXR1cm4gZS5vZmZzZXRzPXMocyh7fSxlLm9mZnNldHMpLHQuX2NvbmZpZy5vZmZzZXQoZS5vZmZzZXRzLHQuX2VsZW1lbnQpfHx7fSksZX06ZS5vZmZzZXQ9dGhpcy5fY29uZmlnLm9mZnNldCxlfSxpLl9nZXRQb3BwZXJDb25maWc9ZnVuY3Rpb24oKXt2YXIgdD17cGxhY2VtZW50OnRoaXMuX2dldFBsYWNlbWVudCgpLG1vZGlmaWVyczp7b2Zmc2V0OnRoaXMuX2dldE9mZnNldCgpLGZsaXA6e2VuYWJsZWQ6dGhpcy5fY29uZmlnLmZsaXB9LHByZXZlbnRPdmVyZmxvdzp7Ym91bmRhcmllc0VsZW1lbnQ6dGhpcy5fY29uZmlnLmJvdW5kYXJ5fX19O3JldHVybiJzdGF0aWMiPT09dGhpcy5fY29uZmlnLmRpc3BsYXkmJih0Lm1vZGlmaWVycy5hcHBseVN0eWxlPXtlbmFibGVkOiExfSkscyhzKHt9LHQpLHRoaXMuX2NvbmZpZy5wb3BwZXJDb25maWcpfSxlLmRyb3Bkb3duSW50ZXJmYWNlPWZ1bmN0aW9uKHQsbil7dmFyIGk9TCh0LCJicy5kcm9wZG93biIpO2lmKGl8fChpPW5ldyBlKHQsIm9iamVjdCI9PXR5cGVvZiBuP246bnVsbCkpLCJzdHJpbmciPT10eXBlb2Ygbil7aWYodm9pZCAwPT09aVtuXSl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyBtZXRob2QgbmFtZWQgIicrbisnIicpO2lbbl0oKX19LGUualF1ZXJ5SW50ZXJmYWNlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmVhY2goKGZ1bmN0aW9uKCl7ZS5kcm9wZG93bkludGVyZmFjZSh0aGlzLHQpfSkpfSxlLmNsZWFyTWVudXM9ZnVuY3Rpb24odCl7aWYoIXR8fDIhPT10LmJ1dHRvbiYmKCJrZXl1cCIhPT10LnR5cGV8fCJUYWIiPT09dC5rZXkpKWZvcih2YXIgbj1udC5maW5kKCdbZGF0YS10b2dnbGU9ImRyb3Bkb3duIl0nKSxpPTAsbz1uLmxlbmd0aDtpPG87aSsrKXt2YXIgcz1lLmdldFBhcmVudEZyb21FbGVtZW50KG5baV0pLHI9TChuW2ldLCJicy5kcm9wZG93biIpLGE9e3JlbGF0ZWRUYXJnZXQ6bltpXX07aWYodCYmImNsaWNrIj09PXQudHlwZSYmKGEuY2xpY2tFdmVudD10KSxyKXt2YXIgbD1yLl9tZW51O2lmKG5baV0uY2xhc3NMaXN0LmNvbnRhaW5zKCJzaG93IikpaWYoISh0JiYoImNsaWNrIj09PXQudHlwZSYmL2lucHV0fHRleHRhcmVhL2kudGVzdCh0LnRhcmdldC50YWdOYW1lKXx8ImtleXVwIj09PXQudHlwZSYmIlRhYiI9PT10LmtleSkmJmwuY29udGFpbnModC50YXJnZXQpKSlpZighcS50cmlnZ2VyKHMsImhpZGUuYnMuZHJvcGRvd24iLGEpLmRlZmF1bHRQcmV2ZW50ZWQpe3ZhciBjO2lmKCJvbnRvdWNoc3RhcnQiaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KShjPVtdKS5jb25jYXQuYXBwbHkoYyxkb2N1bWVudC5ib2R5LmNoaWxkcmVuKS5mb3JFYWNoKChmdW5jdGlvbih0KXtyZXR1cm4gcS5vZmYodCwibW91c2VvdmVyIixudWxsLChmdW5jdGlvbigpe30pKX0pKTtuW2ldLnNldEF0dHJpYnV0ZSgiYXJpYS1leHBhbmRlZCIsImZhbHNlIiksci5fcG9wcGVyJiZyLl9wb3BwZXIuZGVzdHJveSgpLGwuY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLG5baV0uY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLHEudHJpZ2dlcihzLCJoaWRkZW4uYnMuZHJvcGRvd24iLGEpfX19fSxlLmdldFBhcmVudEZyb21FbGVtZW50PWZ1bmN0aW9uKHQpe3JldHVybiBkKHQpfHx0LnBhcmVudE5vZGV9LGUuZGF0YUFwaUtleWRvd25IYW5kbGVyPWZ1bmN0aW9uKHQpe2lmKCEoL2lucHV0fHRleHRhcmVhL2kudGVzdCh0LnRhcmdldC50YWdOYW1lKT8iU3BhY2UiPT09dC5rZXl8fCJFc2NhcGUiIT09dC5rZXkmJigiQXJyb3dEb3duIiE9PXQua2V5JiYiQXJyb3dVcCIhPT10LmtleXx8dC50YXJnZXQuY2xvc2VzdCgiLmRyb3Bkb3duLW1lbnUiKSk6IXZ0LnRlc3QodC5rZXkpKSYmKHQucHJldmVudERlZmF1bHQoKSx0LnN0b3BQcm9wYWdhdGlvbigpLCF0aGlzLmRpc2FibGVkJiYhdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoImRpc2FibGVkIikpKXt2YXIgbj1lLmdldFBhcmVudEZyb21FbGVtZW50KHRoaXMpLGk9dGhpcy5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKTtpZigiRXNjYXBlIj09PXQua2V5KXJldHVybih0aGlzLm1hdGNoZXMoJ1tkYXRhLXRvZ2dsZT0iZHJvcGRvd24iXScpP3RoaXM6bnQucHJldih0aGlzLCdbZGF0YS10b2dnbGU9ImRyb3Bkb3duIl0nKVswXSkuZm9jdXMoKSx2b2lkIGUuY2xlYXJNZW51cygpO2lmKGkmJiJTcGFjZSIhPT10LmtleSl7dmFyIG89bnQuZmluZCgiLmRyb3Bkb3duLW1lbnUgLmRyb3Bkb3duLWl0ZW06bm90KC5kaXNhYmxlZCk6bm90KDpkaXNhYmxlZCkiLG4pLmZpbHRlcihiKTtpZihvLmxlbmd0aCl7dmFyIHM9by5pbmRleE9mKHQudGFyZ2V0KTsiQXJyb3dVcCI9PT10LmtleSYmcz4wJiZzLS0sIkFycm93RG93biI9PT10LmtleSYmczxvLmxlbmd0aC0xJiZzKyssb1tzPS0xPT09cz8wOnNdLmZvY3VzKCl9fWVsc2UgZS5jbGVhck1lbnVzKCl9fSxlLmdldEluc3RhbmNlPWZ1bmN0aW9uKHQpe3JldHVybiBMKHQsImJzLmRyb3Bkb3duIil9LG4oZSxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHQiLGdldDpmdW5jdGlvbigpe3JldHVybiBidH19LHtrZXk6IkRlZmF1bHRUeXBlIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4geXR9fV0pLGV9KCk7cS5vbihkb2N1bWVudCwia2V5ZG93bi5icy5kcm9wZG93bi5kYXRhLWFwaSIsJ1tkYXRhLXRvZ2dsZT0iZHJvcGRvd24iXScsd3QuZGF0YUFwaUtleWRvd25IYW5kbGVyKSxxLm9uKGRvY3VtZW50LCJrZXlkb3duLmJzLmRyb3Bkb3duLmRhdGEtYXBpIiwiLmRyb3Bkb3duLW1lbnUiLHd0LmRhdGFBcGlLZXlkb3duSGFuZGxlcikscS5vbihkb2N1bWVudCwiY2xpY2suYnMuZHJvcGRvd24uZGF0YS1hcGkiLHd0LmNsZWFyTWVudXMpLHEub24oZG9jdW1lbnQsImtleXVwLmJzLmRyb3Bkb3duLmRhdGEtYXBpIix3dC5jbGVhck1lbnVzKSxxLm9uKGRvY3VtZW50LCJjbGljay5icy5kcm9wZG93bi5kYXRhLWFwaSIsJ1tkYXRhLXRvZ2dsZT0iZHJvcGRvd24iXScsKGZ1bmN0aW9uKHQpe3QucHJldmVudERlZmF1bHQoKSx0LnN0b3BQcm9wYWdhdGlvbigpLHd0LmRyb3Bkb3duSW50ZXJmYWNlKHRoaXMsInRvZ2dsZSIpfSkpLHEub24oZG9jdW1lbnQsImNsaWNrLmJzLmRyb3Bkb3duLmRhdGEtYXBpIiwiLmRyb3Bkb3duIGZvcm0iLChmdW5jdGlvbih0KXtyZXR1cm4gdC5zdG9wUHJvcGFnYXRpb24oKX0pKTt2YXIgRXQ9RSgpO2lmKEV0KXt2YXIga3Q9RXQuZm5bX3RdO0V0LmZuW190XT13dC5qUXVlcnlJbnRlcmZhY2UsRXQuZm5bX3RdLkNvbnN0cnVjdG9yPXd0LEV0LmZuW190XS5ub0NvbmZsaWN0PWZ1bmN0aW9uKCl7cmV0dXJuIEV0LmZuW190XT1rdCx3dC5qUXVlcnlJbnRlcmZhY2V9fXZhciBUdD17YmFja2Ryb3A6ITAsa2V5Ym9hcmQ6ITAsZm9jdXM6ITAsc2hvdzohMH0sTHQ9e2JhY2tkcm9wOiIoYm9vbGVhbnxzdHJpbmcpIixrZXlib2FyZDoiYm9vbGVhbiIsZm9jdXM6ImJvb2xlYW4iLHNob3c6ImJvb2xlYW4ifSxDdD1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlKXt0aGlzLl9jb25maWc9dGhpcy5fZ2V0Q29uZmlnKGUpLHRoaXMuX2VsZW1lbnQ9dCx0aGlzLl9kaWFsb2c9bnQuZmluZE9uZSgiLm1vZGFsLWRpYWxvZyIsdCksdGhpcy5fYmFja2Ryb3A9bnVsbCx0aGlzLl9pc1Nob3duPSExLHRoaXMuX2lzQm9keU92ZXJmbG93aW5nPSExLHRoaXMuX2lnbm9yZUJhY2tkcm9wQ2xpY2s9ITEsdGhpcy5faXNUcmFuc2l0aW9uaW5nPSExLHRoaXMuX3Njcm9sbGJhcldpZHRoPTAsVCh0LCJicy5tb2RhbCIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUudG9nZ2xlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9pc1Nob3duP3RoaXMuaGlkZSgpOnRoaXMuc2hvdyh0KX0sZS5zaG93PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXM7aWYoIXRoaXMuX2lzU2hvd24mJiF0aGlzLl9pc1RyYW5zaXRpb25pbmcpe3RoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCJmYWRlIikmJih0aGlzLl9pc1RyYW5zaXRpb25pbmc9ITApO3ZhciBuPXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJzaG93LmJzLm1vZGFsIix7cmVsYXRlZFRhcmdldDp0fSk7dGhpcy5faXNTaG93bnx8bi5kZWZhdWx0UHJldmVudGVkfHwodGhpcy5faXNTaG93bj0hMCx0aGlzLl9jaGVja1Njcm9sbGJhcigpLHRoaXMuX3NldFNjcm9sbGJhcigpLHRoaXMuX2FkanVzdERpYWxvZygpLHRoaXMuX3NldEVzY2FwZUV2ZW50KCksdGhpcy5fc2V0UmVzaXplRXZlbnQoKSxxLm9uKHRoaXMuX2VsZW1lbnQsImNsaWNrLmRpc21pc3MuYnMubW9kYWwiLCdbZGF0YS1kaXNtaXNzPSJtb2RhbCJdJywoZnVuY3Rpb24odCl7cmV0dXJuIGUuaGlkZSh0KX0pKSxxLm9uKHRoaXMuX2RpYWxvZywibW91c2Vkb3duLmRpc21pc3MuYnMubW9kYWwiLChmdW5jdGlvbigpe3Eub25lKGUuX2VsZW1lbnQsIm1vdXNldXAuZGlzbWlzcy5icy5tb2RhbCIsKGZ1bmN0aW9uKHQpe3QudGFyZ2V0PT09ZS5fZWxlbWVudCYmKGUuX2lnbm9yZUJhY2tkcm9wQ2xpY2s9ITApfSkpfSkpLHRoaXMuX3Nob3dCYWNrZHJvcCgoZnVuY3Rpb24oKXtyZXR1cm4gZS5fc2hvd0VsZW1lbnQodCl9KSkpfX0sZS5oaWRlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXM7aWYoKHQmJnQucHJldmVudERlZmF1bHQoKSx0aGlzLl9pc1Nob3duJiYhdGhpcy5faXNUcmFuc2l0aW9uaW5nKSYmIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJoaWRlLmJzLm1vZGFsIikuZGVmYXVsdFByZXZlbnRlZCl7dGhpcy5faXNTaG93bj0hMTt2YXIgbj10aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygiZmFkZSIpO2lmKG4mJih0aGlzLl9pc1RyYW5zaXRpb25pbmc9ITApLHRoaXMuX3NldEVzY2FwZUV2ZW50KCksdGhpcy5fc2V0UmVzaXplRXZlbnQoKSxxLm9mZihkb2N1bWVudCwiZm9jdXNpbi5icy5tb2RhbCIpLHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLHEub2ZmKHRoaXMuX2VsZW1lbnQsImNsaWNrLmRpc21pc3MuYnMubW9kYWwiKSxxLm9mZih0aGlzLl9kaWFsb2csIm1vdXNlZG93bi5kaXNtaXNzLmJzLm1vZGFsIiksbil7dmFyIGk9Zyh0aGlzLl9lbGVtZW50KTtxLm9uZSh0aGlzLl9lbGVtZW50LCJ0cmFuc2l0aW9uZW5kIiwoZnVuY3Rpb24odCl7cmV0dXJuIGUuX2hpZGVNb2RhbCh0KX0pKSxfKHRoaXMuX2VsZW1lbnQsaSl9ZWxzZSB0aGlzLl9oaWRlTW9kYWwoKX19LGUuZGlzcG9zZT1mdW5jdGlvbigpe1t3aW5kb3csdGhpcy5fZWxlbWVudCx0aGlzLl9kaWFsb2ddLmZvckVhY2goKGZ1bmN0aW9uKHQpe3JldHVybiBxLm9mZih0LCIuYnMubW9kYWwiKX0pKSxxLm9mZihkb2N1bWVudCwiZm9jdXNpbi5icy5tb2RhbCIpLEModGhpcy5fZWxlbWVudCwiYnMubW9kYWwiKSx0aGlzLl9jb25maWc9bnVsbCx0aGlzLl9lbGVtZW50PW51bGwsdGhpcy5fZGlhbG9nPW51bGwsdGhpcy5fYmFja2Ryb3A9bnVsbCx0aGlzLl9pc1Nob3duPW51bGwsdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmc9bnVsbCx0aGlzLl9pZ25vcmVCYWNrZHJvcENsaWNrPW51bGwsdGhpcy5faXNUcmFuc2l0aW9uaW5nPW51bGwsdGhpcy5fc2Nyb2xsYmFyV2lkdGg9bnVsbH0sZS5oYW5kbGVVcGRhdGU9ZnVuY3Rpb24oKXt0aGlzLl9hZGp1c3REaWFsb2coKX0sZS5fZ2V0Q29uZmlnPWZ1bmN0aW9uKHQpe3JldHVybiB0PXMocyh7fSxUdCksdCksdigibW9kYWwiLHQsTHQpLHR9LGUuX3Nob3dFbGVtZW50PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMsbj10aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygiZmFkZSIpLGk9bnQuZmluZE9uZSgiLm1vZGFsLWJvZHkiLHRoaXMuX2RpYWxvZyk7dGhpcy5fZWxlbWVudC5wYXJlbnROb2RlJiZ0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUubm9kZVR5cGU9PT1Ob2RlLkVMRU1FTlRfTk9ERXx8ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0aGlzLl9lbGVtZW50KSx0aGlzLl9lbGVtZW50LnN0eWxlLmRpc3BsYXk9ImJsb2NrIix0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgiYXJpYS1oaWRkZW4iKSx0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgiYXJpYS1tb2RhbCIsITApLHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCJyb2xlIiwiZGlhbG9nIiksdGhpcy5fZWxlbWVudC5zY3JvbGxUb3A9MCxpJiYoaS5zY3JvbGxUb3A9MCksbiYmdyh0aGlzLl9lbGVtZW50KSx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoInNob3ciKSx0aGlzLl9jb25maWcuZm9jdXMmJnRoaXMuX2VuZm9yY2VGb2N1cygpO3ZhciBvPWZ1bmN0aW9uKCl7ZS5fY29uZmlnLmZvY3VzJiZlLl9lbGVtZW50LmZvY3VzKCksZS5faXNUcmFuc2l0aW9uaW5nPSExLHEudHJpZ2dlcihlLl9lbGVtZW50LCJzaG93bi5icy5tb2RhbCIse3JlbGF0ZWRUYXJnZXQ6dH0pfTtpZihuKXt2YXIgcz1nKHRoaXMuX2RpYWxvZyk7cS5vbmUodGhpcy5fZGlhbG9nLCJ0cmFuc2l0aW9uZW5kIixvKSxfKHRoaXMuX2RpYWxvZyxzKX1lbHNlIG8oKX0sZS5fZW5mb3JjZUZvY3VzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcztxLm9mZihkb2N1bWVudCwiZm9jdXNpbi5icy5tb2RhbCIpLHEub24oZG9jdW1lbnQsImZvY3VzaW4uYnMubW9kYWwiLChmdW5jdGlvbihlKXtkb2N1bWVudD09PWUudGFyZ2V0fHx0Ll9lbGVtZW50PT09ZS50YXJnZXR8fHQuX2VsZW1lbnQuY29udGFpbnMoZS50YXJnZXQpfHx0Ll9lbGVtZW50LmZvY3VzKCl9KSl9LGUuX3NldEVzY2FwZUV2ZW50PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpczt0aGlzLl9pc1Nob3duP3Eub24odGhpcy5fZWxlbWVudCwia2V5ZG93bi5kaXNtaXNzLmJzLm1vZGFsIiwoZnVuY3Rpb24oZSl7dC5fY29uZmlnLmtleWJvYXJkJiYiRXNjYXBlIj09PWUua2V5PyhlLnByZXZlbnREZWZhdWx0KCksdC5oaWRlKCkpOnQuX2NvbmZpZy5rZXlib2FyZHx8IkVzY2FwZSIhPT1lLmtleXx8dC5fdHJpZ2dlckJhY2tkcm9wVHJhbnNpdGlvbigpfSkpOnEub2ZmKHRoaXMuX2VsZW1lbnQsImtleWRvd24uZGlzbWlzcy5icy5tb2RhbCIpfSxlLl9zZXRSZXNpemVFdmVudD1mdW5jdGlvbigpe3ZhciB0PXRoaXM7dGhpcy5faXNTaG93bj9xLm9uKHdpbmRvdywicmVzaXplLmJzLm1vZGFsIiwoZnVuY3Rpb24oKXtyZXR1cm4gdC5fYWRqdXN0RGlhbG9nKCl9KSk6cS5vZmYod2luZG93LCJyZXNpemUuYnMubW9kYWwiKX0sZS5faGlkZU1vZGFsPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpczt0aGlzLl9lbGVtZW50LnN0eWxlLmRpc3BsYXk9Im5vbmUiLHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCJhcmlhLWhpZGRlbiIsITApLHRoaXMuX2VsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCJhcmlhLW1vZGFsIiksdGhpcy5fZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoInJvbGUiKSx0aGlzLl9pc1RyYW5zaXRpb25pbmc9ITEsdGhpcy5fc2hvd0JhY2tkcm9wKChmdW5jdGlvbigpe2RvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgibW9kYWwtb3BlbiIpLHQuX3Jlc2V0QWRqdXN0bWVudHMoKSx0Ll9yZXNldFNjcm9sbGJhcigpLHEudHJpZ2dlcih0Ll9lbGVtZW50LCJoaWRkZW4uYnMubW9kYWwiKX0pKX0sZS5fcmVtb3ZlQmFja2Ryb3A9ZnVuY3Rpb24oKXt0aGlzLl9iYWNrZHJvcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2JhY2tkcm9wKSx0aGlzLl9iYWNrZHJvcD1udWxsfSxlLl9zaG93QmFja2Ryb3A9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcyxuPXRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCJmYWRlIik/ImZhZGUiOiIiO2lmKHRoaXMuX2lzU2hvd24mJnRoaXMuX2NvbmZpZy5iYWNrZHJvcCl7aWYodGhpcy5fYmFja2Ryb3A9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IiksdGhpcy5fYmFja2Ryb3AuY2xhc3NOYW1lPSJtb2RhbC1iYWNrZHJvcCIsbiYmdGhpcy5fYmFja2Ryb3AuY2xhc3NMaXN0LmFkZChuKSxkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuX2JhY2tkcm9wKSxxLm9uKHRoaXMuX2VsZW1lbnQsImNsaWNrLmRpc21pc3MuYnMubW9kYWwiLChmdW5jdGlvbih0KXtlLl9pZ25vcmVCYWNrZHJvcENsaWNrP2UuX2lnbm9yZUJhY2tkcm9wQ2xpY2s9ITE6dC50YXJnZXQ9PT10LmN1cnJlbnRUYXJnZXQmJmUuX3RyaWdnZXJCYWNrZHJvcFRyYW5zaXRpb24oKX0pKSxuJiZ3KHRoaXMuX2JhY2tkcm9wKSx0aGlzLl9iYWNrZHJvcC5jbGFzc0xpc3QuYWRkKCJzaG93IiksIW4pcmV0dXJuIHZvaWQgdCgpO3ZhciBpPWcodGhpcy5fYmFja2Ryb3ApO3Eub25lKHRoaXMuX2JhY2tkcm9wLCJ0cmFuc2l0aW9uZW5kIix0KSxfKHRoaXMuX2JhY2tkcm9wLGkpfWVsc2UgaWYoIXRoaXMuX2lzU2hvd24mJnRoaXMuX2JhY2tkcm9wKXt0aGlzLl9iYWNrZHJvcC5jbGFzc0xpc3QucmVtb3ZlKCJzaG93Iik7dmFyIG89ZnVuY3Rpb24oKXtlLl9yZW1vdmVCYWNrZHJvcCgpLHQoKX07aWYodGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoImZhZGUiKSl7dmFyIHM9Zyh0aGlzLl9iYWNrZHJvcCk7cS5vbmUodGhpcy5fYmFja2Ryb3AsInRyYW5zaXRpb25lbmQiLG8pLF8odGhpcy5fYmFja2Ryb3Ascyl9ZWxzZSBvKCl9ZWxzZSB0KCl9LGUuX3RyaWdnZXJCYWNrZHJvcFRyYW5zaXRpb249ZnVuY3Rpb24oKXt2YXIgdD10aGlzO2lmKCJzdGF0aWMiPT09dGhpcy5fY29uZmlnLmJhY2tkcm9wKXtpZihxLnRyaWdnZXIodGhpcy5fZWxlbWVudCwiaGlkZVByZXZlbnRlZC5icy5tb2RhbCIpLmRlZmF1bHRQcmV2ZW50ZWQpcmV0dXJuO3RoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZCgibW9kYWwtc3RhdGljIik7dmFyIGU9Zyh0aGlzLl9lbGVtZW50KTtxLm9uZSh0aGlzLl9lbGVtZW50LCJ0cmFuc2l0aW9uZW5kIiwoZnVuY3Rpb24oKXt0Ll9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoIm1vZGFsLXN0YXRpYyIpfSkpLF8odGhpcy5fZWxlbWVudCxlKSx0aGlzLl9lbGVtZW50LmZvY3VzKCl9ZWxzZSB0aGlzLmhpZGUoKX0sZS5fYWRqdXN0RGlhbG9nPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fZWxlbWVudC5zY3JvbGxIZWlnaHQ+ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodDshdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcmJnQmJih0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdMZWZ0PXRoaXMuX3Njcm9sbGJhcldpZHRoKyJweCIpLHRoaXMuX2lzQm9keU92ZXJmbG93aW5nJiYhdCYmKHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ1JpZ2h0PXRoaXMuX3Njcm9sbGJhcldpZHRoKyJweCIpfSxlLl9yZXNldEFkanVzdG1lbnRzPWZ1bmN0aW9uKCl7dGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nTGVmdD0iIix0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodD0iIn0sZS5fY2hlY2tTY3JvbGxiYXI9ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudC5ib2R5LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO3RoaXMuX2lzQm9keU92ZXJmbG93aW5nPU1hdGgucm91bmQodC5sZWZ0K3QucmlnaHQpPHdpbmRvdy5pbm5lcldpZHRoLHRoaXMuX3Njcm9sbGJhcldpZHRoPXRoaXMuX2dldFNjcm9sbGJhcldpZHRoKCl9LGUuX3NldFNjcm9sbGJhcj1mdW5jdGlvbigpe3ZhciB0PXRoaXM7aWYodGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcpe250LmZpbmQoIi5maXhlZC10b3AsIC5maXhlZC1ib3R0b20sIC5pcy1maXhlZCwgLnN0aWNreS10b3AiKS5mb3JFYWNoKChmdW5jdGlvbihlKXt2YXIgbj1lLnN0eWxlLnBhZGRpbmdSaWdodCxpPXdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGUpWyJwYWRkaW5nLXJpZ2h0Il07ZXQuc2V0RGF0YUF0dHJpYnV0ZShlLCJwYWRkaW5nLXJpZ2h0IixuKSxlLnN0eWxlLnBhZGRpbmdSaWdodD1wYXJzZUZsb2F0KGkpK3QuX3Njcm9sbGJhcldpZHRoKyJweCJ9KSksbnQuZmluZCgiLnN0aWNreS10b3AiKS5mb3JFYWNoKChmdW5jdGlvbihlKXt2YXIgbj1lLnN0eWxlLm1hcmdpblJpZ2h0LGk9d2luZG93LmdldENvbXB1dGVkU3R5bGUoZSlbIm1hcmdpbi1yaWdodCJdO2V0LnNldERhdGFBdHRyaWJ1dGUoZSwibWFyZ2luLXJpZ2h0IixuKSxlLnN0eWxlLm1hcmdpblJpZ2h0PXBhcnNlRmxvYXQoaSktdC5fc2Nyb2xsYmFyV2lkdGgrInB4In0pKTt2YXIgZT1kb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmdSaWdodCxuPXdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmJvZHkpWyJwYWRkaW5nLXJpZ2h0Il07ZXQuc2V0RGF0YUF0dHJpYnV0ZShkb2N1bWVudC5ib2R5LCJwYWRkaW5nLXJpZ2h0IixlKSxkb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmdSaWdodD1wYXJzZUZsb2F0KG4pK3RoaXMuX3Njcm9sbGJhcldpZHRoKyJweCJ9ZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCJtb2RhbC1vcGVuIil9LGUuX3Jlc2V0U2Nyb2xsYmFyPWZ1bmN0aW9uKCl7bnQuZmluZCgiLmZpeGVkLXRvcCwgLmZpeGVkLWJvdHRvbSwgLmlzLWZpeGVkLCAuc3RpY2t5LXRvcCIpLmZvckVhY2goKGZ1bmN0aW9uKHQpe3ZhciBlPWV0LmdldERhdGFBdHRyaWJ1dGUodCwicGFkZGluZy1yaWdodCIpO3ZvaWQgMCE9PWUmJihldC5yZW1vdmVEYXRhQXR0cmlidXRlKHQsInBhZGRpbmctcmlnaHQiKSx0LnN0eWxlLnBhZGRpbmdSaWdodD1lKX0pKSxudC5maW5kKCIuc3RpY2t5LXRvcCIpLmZvckVhY2goKGZ1bmN0aW9uKHQpe3ZhciBlPWV0LmdldERhdGFBdHRyaWJ1dGUodCwibWFyZ2luLXJpZ2h0Iik7dm9pZCAwIT09ZSYmKGV0LnJlbW92ZURhdGFBdHRyaWJ1dGUodCwibWFyZ2luLXJpZ2h0IiksdC5zdHlsZS5tYXJnaW5SaWdodD1lKX0pKTt2YXIgdD1ldC5nZXREYXRhQXR0cmlidXRlKGRvY3VtZW50LmJvZHksInBhZGRpbmctcmlnaHQiKTt2b2lkIDA9PT10P2RvY3VtZW50LmJvZHkuc3R5bGUucGFkZGluZ1JpZ2h0PSIiOihldC5yZW1vdmVEYXRhQXR0cmlidXRlKGRvY3VtZW50LmJvZHksInBhZGRpbmctcmlnaHQiKSxkb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmdSaWdodD10KX0sZS5fZ2V0U2Nyb2xsYmFyV2lkdGg9ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTt0LmNsYXNzTmFtZT0ibW9kYWwtc2Nyb2xsYmFyLW1lYXN1cmUiLGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodCk7dmFyIGU9dC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aC10LmNsaWVudFdpZHRoO3JldHVybiBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHQpLGV9LHQualF1ZXJ5SW50ZXJmYWNlPWZ1bmN0aW9uKGUsbil7cmV0dXJuIHRoaXMuZWFjaCgoZnVuY3Rpb24oKXt2YXIgaT1MKHRoaXMsImJzLm1vZGFsIiksbz1zKHMocyh7fSxUdCksZXQuZ2V0RGF0YUF0dHJpYnV0ZXModGhpcykpLCJvYmplY3QiPT10eXBlb2YgZSYmZT9lOnt9KTtpZihpfHwoaT1uZXcgdCh0aGlzLG8pKSwic3RyaW5nIj09dHlwZW9mIGUpe2lmKHZvaWQgMD09PWlbZV0pdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gbWV0aG9kIG5hbWVkICInK2UrJyInKTtpW2VdKG4pfWVsc2Ugby5zaG93JiZpLnNob3cobil9KSl9LHQuZ2V0SW5zdGFuY2U9ZnVuY3Rpb24odCl7cmV0dXJuIEwodCwiYnMubW9kYWwiKX0sbih0LG51bGwsW3trZXk6IlZFUlNJT04iLGdldDpmdW5jdGlvbigpe3JldHVybiI1LjAuMC1hbHBoYTEifX0se2tleToiRGVmYXVsdCIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIFR0fX1dKSx0fSgpO3Eub24oZG9jdW1lbnQsImNsaWNrLmJzLm1vZGFsLmRhdGEtYXBpIiwnW2RhdGEtdG9nZ2xlPSJtb2RhbCJdJywoZnVuY3Rpb24odCl7dmFyIGU9dGhpcyxuPWQodGhpcyk7IkEiIT09dGhpcy50YWdOYW1lJiYiQVJFQSIhPT10aGlzLnRhZ05hbWV8fHQucHJldmVudERlZmF1bHQoKSxxLm9uZShuLCJzaG93LmJzLm1vZGFsIiwoZnVuY3Rpb24odCl7dC5kZWZhdWx0UHJldmVudGVkfHxxLm9uZShuLCJoaWRkZW4uYnMubW9kYWwiLChmdW5jdGlvbigpe2IoZSkmJmUuZm9jdXMoKX0pKX0pKTt2YXIgaT1MKG4sImJzLm1vZGFsIik7aWYoIWkpe3ZhciBvPXMocyh7fSxldC5nZXREYXRhQXR0cmlidXRlcyhuKSksZXQuZ2V0RGF0YUF0dHJpYnV0ZXModGhpcykpO2k9bmV3IEN0KG4sbyl9aS5zaG93KHRoaXMpfSkpO3ZhciBBdD1FKCk7aWYoQXQpe3ZhciBTdD1BdC5mbi5tb2RhbDtBdC5mbi5tb2RhbD1DdC5qUXVlcnlJbnRlcmZhY2UsQXQuZm4ubW9kYWwuQ29uc3RydWN0b3I9Q3QsQXQuZm4ubW9kYWwubm9Db25mbGljdD1mdW5jdGlvbigpe3JldHVybiBBdC5mbi5tb2RhbD1TdCxDdC5qUXVlcnlJbnRlcmZhY2V9fXZhciBPdD1bImJhY2tncm91bmQiLCJjaXRlIiwiaHJlZiIsIml0ZW10eXBlIiwibG9uZ2Rlc2MiLCJwb3N0ZXIiLCJzcmMiLCJ4bGluazpocmVmIl0sRHQ9L14oPzooPzpodHRwcz98bWFpbHRvfGZ0cHx0ZWx8ZmlsZSk6fFteIyYvOj9dKig/OlsjLz9dfCQpKS9naSxJdD0vXmRhdGE6KD86aW1hZ2VcLyg/OmJtcHxnaWZ8anBlZ3xqcGd8cG5nfHRpZmZ8d2VicCl8dmlkZW9cLyg/Om1wZWd8bXA0fG9nZ3x3ZWJtKXxhdWRpb1wvKD86bXAzfG9nYXxvZ2d8b3B1cykpO2Jhc2U2NCxbXGQrL2Etel0rPSokL2ksTnQ9eyIqIjpbImNsYXNzIiwiZGlyIiwiaWQiLCJsYW5nIiwicm9sZSIsL15hcmlhLVtcdy1dKiQvaV0sYTpbInRhcmdldCIsImhyZWYiLCJ0aXRsZSIsInJlbCJdLGFyZWE6W10sYjpbXSxicjpbXSxjb2w6W10sY29kZTpbXSxkaXY6W10sZW06W10saHI6W10saDE6W10saDI6W10saDM6W10saDQ6W10saDU6W10saDY6W10saTpbXSxpbWc6WyJzcmMiLCJzcmNzZXQiLCJhbHQiLCJ0aXRsZSIsIndpZHRoIiwiaGVpZ2h0Il0sbGk6W10sb2w6W10scDpbXSxwcmU6W10sczpbXSxzbWFsbDpbXSxzcGFuOltdLHN1YjpbXSxzdXA6W10sc3Ryb25nOltdLHU6W10sdWw6W119O2Z1bmN0aW9uIGp0KHQsZSxuKXt2YXIgaTtpZighdC5sZW5ndGgpcmV0dXJuIHQ7aWYobiYmImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuIG4odCk7Zm9yKHZhciBvPShuZXcgd2luZG93LkRPTVBhcnNlcikucGFyc2VGcm9tU3RyaW5nKHQsInRleHQvaHRtbCIpLHM9T2JqZWN0LmtleXMoZSkscj0oaT1bXSkuY29uY2F0LmFwcGx5KGksby5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGwoIioiKSksYT1mdW5jdGlvbih0LG4pe3ZhciBpLG89clt0XSxhPW8ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtpZigtMT09PXMuaW5kZXhPZihhKSlyZXR1cm4gby5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG8pLCJjb250aW51ZSI7dmFyIGw9KGk9W10pLmNvbmNhdC5hcHBseShpLG8uYXR0cmlidXRlcyksYz1bXS5jb25jYXQoZVsiKiJdfHxbXSxlW2FdfHxbXSk7bC5mb3JFYWNoKChmdW5jdGlvbih0KXsoZnVuY3Rpb24odCxlKXt2YXIgbj10Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7aWYoLTEhPT1lLmluZGV4T2YobikpcmV0dXJuLTE9PT1PdC5pbmRleE9mKG4pfHxCb29sZWFuKHQubm9kZVZhbHVlLm1hdGNoKER0KXx8dC5ub2RlVmFsdWUubWF0Y2goSXQpKTtmb3IodmFyIGk9ZS5maWx0ZXIoKGZ1bmN0aW9uKHQpe3JldHVybiB0IGluc3RhbmNlb2YgUmVnRXhwfSkpLG89MCxzPWkubGVuZ3RoO288cztvKyspaWYobi5tYXRjaChpW29dKSlyZXR1cm4hMDtyZXR1cm4hMX0pKHQsYyl8fG8ucmVtb3ZlQXR0cmlidXRlKHQubm9kZU5hbWUpfSkpfSxsPTAsYz1yLmxlbmd0aDtsPGM7bCsrKWEobCk7cmV0dXJuIG8uYm9keS5pbm5lckhUTUx9dmFyIFB0PSJ0b29sdGlwIix4dD1uZXcgUmVnRXhwKCIoXnxcXHMpYnMtdG9vbHRpcFxcUysiLCJnIiksUnQ9WyJzYW5pdGl6ZSIsIndoaXRlTGlzdCIsInNhbml0aXplRm4iXSxIdD17YW5pbWF0aW9uOiJib29sZWFuIix0ZW1wbGF0ZToic3RyaW5nIix0aXRsZToiKHN0cmluZ3xlbGVtZW50fGZ1bmN0aW9uKSIsdHJpZ2dlcjoic3RyaW5nIixkZWxheToiKG51bWJlcnxvYmplY3QpIixodG1sOiJib29sZWFuIixzZWxlY3RvcjoiKHN0cmluZ3xib29sZWFuKSIscGxhY2VtZW50OiIoc3RyaW5nfGZ1bmN0aW9uKSIsb2Zmc2V0OiIobnVtYmVyfHN0cmluZ3xmdW5jdGlvbikiLGNvbnRhaW5lcjoiKHN0cmluZ3xlbGVtZW50fGJvb2xlYW4pIixmYWxsYmFja1BsYWNlbWVudDoiKHN0cmluZ3xhcnJheSkiLGJvdW5kYXJ5OiIoc3RyaW5nfGVsZW1lbnQpIixzYW5pdGl6ZToiYm9vbGVhbiIsc2FuaXRpemVGbjoiKG51bGx8ZnVuY3Rpb24pIix3aGl0ZUxpc3Q6Im9iamVjdCIscG9wcGVyQ29uZmlnOiIobnVsbHxvYmplY3QpIn0sQnQ9e0FVVE86ImF1dG8iLFRPUDoidG9wIixSSUdIVDoicmlnaHQiLEJPVFRPTToiYm90dG9tIixMRUZUOiJsZWZ0In0sTXQ9e2FuaW1hdGlvbjohMCx0ZW1wbGF0ZTonPGRpdiBjbGFzcz0idG9vbHRpcCIgcm9sZT0idG9vbHRpcCI+PGRpdiBjbGFzcz0idG9vbHRpcC1hcnJvdyI+PC9kaXY+PGRpdiBjbGFzcz0idG9vbHRpcC1pbm5lciI+PC9kaXY+PC9kaXY+Jyx0cmlnZ2VyOiJob3ZlciBmb2N1cyIsdGl0bGU6IiIsZGVsYXk6MCxodG1sOiExLHNlbGVjdG9yOiExLHBsYWNlbWVudDoidG9wIixvZmZzZXQ6MCxjb250YWluZXI6ITEsZmFsbGJhY2tQbGFjZW1lbnQ6ImZsaXAiLGJvdW5kYXJ5OiJzY3JvbGxQYXJlbnQiLHNhbml0aXplOiEwLHNhbml0aXplRm46bnVsbCx3aGl0ZUxpc3Q6TnQscG9wcGVyQ29uZmlnOm51bGx9LFF0PXtISURFOiJoaWRlLmJzLnRvb2x0aXAiLEhJRERFTjoiaGlkZGVuLmJzLnRvb2x0aXAiLFNIT1c6InNob3cuYnMudG9vbHRpcCIsU0hPV046InNob3duLmJzLnRvb2x0aXAiLElOU0VSVEVEOiJpbnNlcnRlZC5icy50b29sdGlwIixDTElDSzoiY2xpY2suYnMudG9vbHRpcCIsRk9DVVNJTjoiZm9jdXNpbi5icy50b29sdGlwIixGT0NVU09VVDoiZm9jdXNvdXQuYnMudG9vbHRpcCIsTU9VU0VFTlRFUjoibW91c2VlbnRlci5icy50b29sdGlwIixNT1VTRUxFQVZFOiJtb3VzZWxlYXZlLmJzLnRvb2x0aXAifSxVdD1mdW5jdGlvbigpe2Z1bmN0aW9uIGUoZSxuKXtpZih2b2lkIDA9PT10KXRocm93IG5ldyBUeXBlRXJyb3IoIkJvb3RzdHJhcCdzIHRvb2x0aXBzIHJlcXVpcmUgUG9wcGVyLmpzIChodHRwczovL3BvcHBlci5qcy5vcmcpIik7dGhpcy5faXNFbmFibGVkPSEwLHRoaXMuX3RpbWVvdXQ9MCx0aGlzLl9ob3ZlclN0YXRlPSIiLHRoaXMuX2FjdGl2ZVRyaWdnZXI9e30sdGhpcy5fcG9wcGVyPW51bGwsdGhpcy5lbGVtZW50PWUsdGhpcy5jb25maWc9dGhpcy5fZ2V0Q29uZmlnKG4pLHRoaXMudGlwPW51bGwsdGhpcy5fc2V0TGlzdGVuZXJzKCksVChlLHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVksdGhpcyl9dmFyIGk9ZS5wcm90b3R5cGU7cmV0dXJuIGkuZW5hYmxlPWZ1bmN0aW9uKCl7dGhpcy5faXNFbmFibGVkPSEwfSxpLmRpc2FibGU9ZnVuY3Rpb24oKXt0aGlzLl9pc0VuYWJsZWQ9ITF9LGkudG9nZ2xlRW5hYmxlZD1mdW5jdGlvbigpe3RoaXMuX2lzRW5hYmxlZD0hdGhpcy5faXNFbmFibGVkfSxpLnRvZ2dsZT1mdW5jdGlvbih0KXtpZih0aGlzLl9pc0VuYWJsZWQpaWYodCl7dmFyIGU9dGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSxuPUwodC50YXJnZXQsZSk7bnx8KG49bmV3IHRoaXMuY29uc3RydWN0b3IodC50YXJnZXQsdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSksVCh0LnRhcmdldCxlLG4pKSxuLl9hY3RpdmVUcmlnZ2VyLmNsaWNrPSFuLl9hY3RpdmVUcmlnZ2VyLmNsaWNrLG4uX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKT9uLl9lbnRlcihudWxsLG4pOm4uX2xlYXZlKG51bGwsbil9ZWxzZXtpZih0aGlzLmdldFRpcEVsZW1lbnQoKS5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKSlyZXR1cm4gdm9pZCB0aGlzLl9sZWF2ZShudWxsLHRoaXMpO3RoaXMuX2VudGVyKG51bGwsdGhpcyl9fSxpLmRpc3Bvc2U9ZnVuY3Rpb24oKXtjbGVhclRpbWVvdXQodGhpcy5fdGltZW91dCksQyh0aGlzLmVsZW1lbnQsdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSkscS5vZmYodGhpcy5lbGVtZW50LHRoaXMuY29uc3RydWN0b3IuRVZFTlRfS0VZKSxxLm9mZih0aGlzLmVsZW1lbnQuY2xvc2VzdCgiLm1vZGFsIiksImhpZGUuYnMubW9kYWwiLHRoaXMuX2hpZGVNb2RhbEhhbmRsZXIpLHRoaXMudGlwJiZ0aGlzLnRpcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMudGlwKSx0aGlzLl9pc0VuYWJsZWQ9bnVsbCx0aGlzLl90aW1lb3V0PW51bGwsdGhpcy5faG92ZXJTdGF0ZT1udWxsLHRoaXMuX2FjdGl2ZVRyaWdnZXI9bnVsbCx0aGlzLl9wb3BwZXImJnRoaXMuX3BvcHBlci5kZXN0cm95KCksdGhpcy5fcG9wcGVyPW51bGwsdGhpcy5lbGVtZW50PW51bGwsdGhpcy5jb25maWc9bnVsbCx0aGlzLnRpcD1udWxsfSxpLnNob3c9ZnVuY3Rpb24oKXt2YXIgZT10aGlzO2lmKCJub25lIj09PXRoaXMuZWxlbWVudC5zdHlsZS5kaXNwbGF5KXRocm93IG5ldyBFcnJvcigiUGxlYXNlIHVzZSBzaG93IG9uIHZpc2libGUgZWxlbWVudHMiKTtpZih0aGlzLmlzV2l0aENvbnRlbnQoKSYmdGhpcy5faXNFbmFibGVkKXt2YXIgbj1xLnRyaWdnZXIodGhpcy5lbGVtZW50LHRoaXMuY29uc3RydWN0b3IuRXZlbnQuU0hPVyksaT1mdW5jdGlvbiB0KGUpe2lmKCFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYXR0YWNoU2hhZG93KXJldHVybiBudWxsO2lmKCJmdW5jdGlvbiI9PXR5cGVvZiBlLmdldFJvb3ROb2RlKXt2YXIgbj1lLmdldFJvb3ROb2RlKCk7cmV0dXJuIG4gaW5zdGFuY2VvZiBTaGFkb3dSb290P246bnVsbH1yZXR1cm4gZSBpbnN0YW5jZW9mIFNoYWRvd1Jvb3Q/ZTplLnBhcmVudE5vZGU/dChlLnBhcmVudE5vZGUpOm51bGx9KHRoaXMuZWxlbWVudCksbz1udWxsPT09aT90aGlzLmVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY29udGFpbnModGhpcy5lbGVtZW50KTppLmNvbnRhaW5zKHRoaXMuZWxlbWVudCk7aWYobi5kZWZhdWx0UHJldmVudGVkfHwhbylyZXR1cm47dmFyIHM9dGhpcy5nZXRUaXBFbGVtZW50KCkscj11KHRoaXMuY29uc3RydWN0b3IuTkFNRSk7cy5zZXRBdHRyaWJ1dGUoImlkIixyKSx0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCJhcmlhLWRlc2NyaWJlZGJ5IixyKSx0aGlzLnNldENvbnRlbnQoKSx0aGlzLmNvbmZpZy5hbmltYXRpb24mJnMuY2xhc3NMaXN0LmFkZCgiZmFkZSIpO3ZhciBhPSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLmNvbmZpZy5wbGFjZW1lbnQ/dGhpcy5jb25maWcucGxhY2VtZW50LmNhbGwodGhpcyxzLHRoaXMuZWxlbWVudCk6dGhpcy5jb25maWcucGxhY2VtZW50LGw9dGhpcy5fZ2V0QXR0YWNobWVudChhKTt0aGlzLl9hZGRBdHRhY2htZW50Q2xhc3MobCk7dmFyIGMsaD10aGlzLl9nZXRDb250YWluZXIoKTtpZihUKHMsdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSx0aGlzKSx0aGlzLmVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY29udGFpbnModGhpcy50aXApfHxoLmFwcGVuZENoaWxkKHMpLHEudHJpZ2dlcih0aGlzLmVsZW1lbnQsdGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5JTlNFUlRFRCksdGhpcy5fcG9wcGVyPW5ldyB0KHRoaXMuZWxlbWVudCxzLHRoaXMuX2dldFBvcHBlckNvbmZpZyhsKSkscy5jbGFzc0xpc3QuYWRkKCJzaG93IiksIm9udG91Y2hzdGFydCJpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpKGM9W10pLmNvbmNhdC5hcHBseShjLGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pLmZvckVhY2goKGZ1bmN0aW9uKHQpe3Eub24odCwibW91c2VvdmVyIiwoZnVuY3Rpb24oKXt9KSl9KSk7dmFyIGY9ZnVuY3Rpb24oKXtlLmNvbmZpZy5hbmltYXRpb24mJmUuX2ZpeFRyYW5zaXRpb24oKTt2YXIgdD1lLl9ob3ZlclN0YXRlO2UuX2hvdmVyU3RhdGU9bnVsbCxxLnRyaWdnZXIoZS5lbGVtZW50LGUuY29uc3RydWN0b3IuRXZlbnQuU0hPV04pLCJvdXQiPT09dCYmZS5fbGVhdmUobnVsbCxlKX07aWYodGhpcy50aXAuY2xhc3NMaXN0LmNvbnRhaW5zKCJmYWRlIikpe3ZhciBkPWcodGhpcy50aXApO3Eub25lKHRoaXMudGlwLCJ0cmFuc2l0aW9uZW5kIixmKSxfKHRoaXMudGlwLGQpfWVsc2UgZigpfX0saS5oaWRlPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxlPXRoaXMuZ2V0VGlwRWxlbWVudCgpLG49ZnVuY3Rpb24oKXsic2hvdyIhPT10Ll9ob3ZlclN0YXRlJiZlLnBhcmVudE5vZGUmJmUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlKSx0Ll9jbGVhblRpcENsYXNzKCksdC5lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgiYXJpYS1kZXNjcmliZWRieSIpLHEudHJpZ2dlcih0LmVsZW1lbnQsdC5jb25zdHJ1Y3Rvci5FdmVudC5ISURERU4pLHQuX3BvcHBlci5kZXN0cm95KCl9O2lmKCFxLnRyaWdnZXIodGhpcy5lbGVtZW50LHRoaXMuY29uc3RydWN0b3IuRXZlbnQuSElERSkuZGVmYXVsdFByZXZlbnRlZCl7dmFyIGk7aWYoZS5jbGFzc0xpc3QucmVtb3ZlKCJzaG93IiksIm9udG91Y2hzdGFydCJpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpKGk9W10pLmNvbmNhdC5hcHBseShpLGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pLmZvckVhY2goKGZ1bmN0aW9uKHQpe3JldHVybiBxLm9mZih0LCJtb3VzZW92ZXIiLHkpfSkpO2lmKHRoaXMuX2FjdGl2ZVRyaWdnZXIuY2xpY2s9ITEsdGhpcy5fYWN0aXZlVHJpZ2dlci5mb2N1cz0hMSx0aGlzLl9hY3RpdmVUcmlnZ2VyLmhvdmVyPSExLHRoaXMudGlwLmNsYXNzTGlzdC5jb250YWlucygiZmFkZSIpKXt2YXIgbz1nKGUpO3Eub25lKGUsInRyYW5zaXRpb25lbmQiLG4pLF8oZSxvKX1lbHNlIG4oKTt0aGlzLl9ob3ZlclN0YXRlPSIifX0saS51cGRhdGU9ZnVuY3Rpb24oKXtudWxsIT09dGhpcy5fcG9wcGVyJiZ0aGlzLl9wb3BwZXIuc2NoZWR1bGVVcGRhdGUoKX0saS5pc1dpdGhDb250ZW50PWZ1bmN0aW9uKCl7cmV0dXJuIEJvb2xlYW4odGhpcy5nZXRUaXRsZSgpKX0saS5nZXRUaXBFbGVtZW50PWZ1bmN0aW9uKCl7aWYodGhpcy50aXApcmV0dXJuIHRoaXMudGlwO3ZhciB0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpO3JldHVybiB0LmlubmVySFRNTD10aGlzLmNvbmZpZy50ZW1wbGF0ZSx0aGlzLnRpcD10LmNoaWxkcmVuWzBdLHRoaXMudGlwfSxpLnNldENvbnRlbnQ9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmdldFRpcEVsZW1lbnQoKTt0aGlzLnNldEVsZW1lbnRDb250ZW50KG50LmZpbmRPbmUoIi50b29sdGlwLWlubmVyIix0KSx0aGlzLmdldFRpdGxlKCkpLHQuY2xhc3NMaXN0LnJlbW92ZSgiZmFkZSIsInNob3ciKX0saS5zZXRFbGVtZW50Q29udGVudD1mdW5jdGlvbih0LGUpe2lmKG51bGwhPT10KXJldHVybiJvYmplY3QiPT10eXBlb2YgZSYmbShlKT8oZS5qcXVlcnkmJihlPWVbMF0pLHZvaWQodGhpcy5jb25maWcuaHRtbD9lLnBhcmVudE5vZGUhPT10JiYodC5pbm5lckhUTUw9IiIsdC5hcHBlbmRDaGlsZChlKSk6dC50ZXh0Q29udGVudD1lLnRleHRDb250ZW50KSk6dm9pZCh0aGlzLmNvbmZpZy5odG1sPyh0aGlzLmNvbmZpZy5zYW5pdGl6ZSYmKGU9anQoZSx0aGlzLmNvbmZpZy53aGl0ZUxpc3QsdGhpcy5jb25maWcuc2FuaXRpemVGbikpLHQuaW5uZXJIVE1MPWUpOnQudGV4dENvbnRlbnQ9ZSl9LGkuZ2V0VGl0bGU9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCJkYXRhLW9yaWdpbmFsLXRpdGxlIik7cmV0dXJuIHR8fCh0PSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLmNvbmZpZy50aXRsZT90aGlzLmNvbmZpZy50aXRsZS5jYWxsKHRoaXMuZWxlbWVudCk6dGhpcy5jb25maWcudGl0bGUpLHR9LGkuX2dldFBvcHBlckNvbmZpZz1mdW5jdGlvbih0KXt2YXIgZT10aGlzO3JldHVybiBzKHMoe30se3BsYWNlbWVudDp0LG1vZGlmaWVyczp7b2Zmc2V0OnRoaXMuX2dldE9mZnNldCgpLGZsaXA6e2JlaGF2aW9yOnRoaXMuY29uZmlnLmZhbGxiYWNrUGxhY2VtZW50fSxhcnJvdzp7ZWxlbWVudDoiLiIrdGhpcy5jb25zdHJ1Y3Rvci5OQU1FKyItYXJyb3cifSxwcmV2ZW50T3ZlcmZsb3c6e2JvdW5kYXJpZXNFbGVtZW50OnRoaXMuY29uZmlnLmJvdW5kYXJ5fX0sb25DcmVhdGU6ZnVuY3Rpb24odCl7dC5vcmlnaW5hbFBsYWNlbWVudCE9PXQucGxhY2VtZW50JiZlLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UodCl9LG9uVXBkYXRlOmZ1bmN0aW9uKHQpe3JldHVybiBlLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UodCl9fSksdGhpcy5jb25maWcucG9wcGVyQ29uZmlnKX0saS5fYWRkQXR0YWNobWVudENsYXNzPWZ1bmN0aW9uKHQpe3RoaXMuZ2V0VGlwRWxlbWVudCgpLmNsYXNzTGlzdC5hZGQoImJzLXRvb2x0aXAtIit0KX0saS5fZ2V0T2Zmc2V0PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxlPXt9O3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLmNvbmZpZy5vZmZzZXQ/ZS5mbj1mdW5jdGlvbihlKXtyZXR1cm4gZS5vZmZzZXRzPXMocyh7fSxlLm9mZnNldHMpLHQuY29uZmlnLm9mZnNldChlLm9mZnNldHMsdC5lbGVtZW50KXx8e30pLGV9OmUub2Zmc2V0PXRoaXMuY29uZmlnLm9mZnNldCxlfSxpLl9nZXRDb250YWluZXI9ZnVuY3Rpb24oKXtyZXR1cm4hMT09PXRoaXMuY29uZmlnLmNvbnRhaW5lcj9kb2N1bWVudC5ib2R5Om0odGhpcy5jb25maWcuY29udGFpbmVyKT90aGlzLmNvbmZpZy5jb250YWluZXI6bnQuZmluZE9uZSh0aGlzLmNvbmZpZy5jb250YWluZXIpfSxpLl9nZXRBdHRhY2htZW50PWZ1bmN0aW9uKHQpe3JldHVybiBCdFt0LnRvVXBwZXJDYXNlKCldfSxpLl9zZXRMaXN0ZW5lcnM9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO3RoaXMuY29uZmlnLnRyaWdnZXIuc3BsaXQoIiAiKS5mb3JFYWNoKChmdW5jdGlvbihlKXtpZigiY2xpY2siPT09ZSlxLm9uKHQuZWxlbWVudCx0LmNvbnN0cnVjdG9yLkV2ZW50LkNMSUNLLHQuY29uZmlnLnNlbGVjdG9yLChmdW5jdGlvbihlKXtyZXR1cm4gdC50b2dnbGUoZSl9KSk7ZWxzZSBpZigibWFudWFsIiE9PWUpe3ZhciBuPSJob3ZlciI9PT1lP3QuY29uc3RydWN0b3IuRXZlbnQuTU9VU0VFTlRFUjp0LmNvbnN0cnVjdG9yLkV2ZW50LkZPQ1VTSU4saT0iaG92ZXIiPT09ZT90LmNvbnN0cnVjdG9yLkV2ZW50Lk1PVVNFTEVBVkU6dC5jb25zdHJ1Y3Rvci5FdmVudC5GT0NVU09VVDtxLm9uKHQuZWxlbWVudCxuLHQuY29uZmlnLnNlbGVjdG9yLChmdW5jdGlvbihlKXtyZXR1cm4gdC5fZW50ZXIoZSl9KSkscS5vbih0LmVsZW1lbnQsaSx0LmNvbmZpZy5zZWxlY3RvciwoZnVuY3Rpb24oZSl7cmV0dXJuIHQuX2xlYXZlKGUpfSkpfX0pKSx0aGlzLl9oaWRlTW9kYWxIYW5kbGVyPWZ1bmN0aW9uKCl7dC5lbGVtZW50JiZ0LmhpZGUoKX0scS5vbih0aGlzLmVsZW1lbnQuY2xvc2VzdCgiLm1vZGFsIiksImhpZGUuYnMubW9kYWwiLHRoaXMuX2hpZGVNb2RhbEhhbmRsZXIpLHRoaXMuY29uZmlnLnNlbGVjdG9yP3RoaXMuY29uZmlnPXMocyh7fSx0aGlzLmNvbmZpZykse30se3RyaWdnZXI6Im1hbnVhbCIsc2VsZWN0b3I6IiJ9KTp0aGlzLl9maXhUaXRsZSgpfSxpLl9maXhUaXRsZT1mdW5jdGlvbigpe3ZhciB0PXR5cGVvZiB0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCJkYXRhLW9yaWdpbmFsLXRpdGxlIik7KHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoInRpdGxlIil8fCJzdHJpbmciIT09dCkmJih0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCJkYXRhLW9yaWdpbmFsLXRpdGxlIix0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCJ0aXRsZSIpfHwiIiksdGhpcy5lbGVtZW50LnNldEF0dHJpYnV0ZSgidGl0bGUiLCIiKSl9LGkuX2VudGVyPWZ1bmN0aW9uKHQsZSl7dmFyIG49dGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTsoZT1lfHxMKHQudGFyZ2V0LG4pKXx8KGU9bmV3IHRoaXMuY29uc3RydWN0b3IodC50YXJnZXQsdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSksVCh0LnRhcmdldCxuLGUpKSx0JiYoZS5fYWN0aXZlVHJpZ2dlclsiZm9jdXNpbiI9PT10LnR5cGU/ImZvY3VzIjoiaG92ZXIiXT0hMCksZS5nZXRUaXBFbGVtZW50KCkuY2xhc3NMaXN0LmNvbnRhaW5zKCJzaG93Iil8fCJzaG93Ij09PWUuX2hvdmVyU3RhdGU/ZS5faG92ZXJTdGF0ZT0ic2hvdyI6KGNsZWFyVGltZW91dChlLl90aW1lb3V0KSxlLl9ob3ZlclN0YXRlPSJzaG93IixlLmNvbmZpZy5kZWxheSYmZS5jb25maWcuZGVsYXkuc2hvdz9lLl90aW1lb3V0PXNldFRpbWVvdXQoKGZ1bmN0aW9uKCl7InNob3ciPT09ZS5faG92ZXJTdGF0ZSYmZS5zaG93KCl9KSxlLmNvbmZpZy5kZWxheS5zaG93KTplLnNob3coKSl9LGkuX2xlYXZlPWZ1bmN0aW9uKHQsZSl7dmFyIG49dGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTsoZT1lfHxMKHQudGFyZ2V0LG4pKXx8KGU9bmV3IHRoaXMuY29uc3RydWN0b3IodC50YXJnZXQsdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSksVCh0LnRhcmdldCxuLGUpKSx0JiYoZS5fYWN0aXZlVHJpZ2dlclsiZm9jdXNvdXQiPT09dC50eXBlPyJmb2N1cyI6ImhvdmVyIl09ITEpLGUuX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKXx8KGNsZWFyVGltZW91dChlLl90aW1lb3V0KSxlLl9ob3ZlclN0YXRlPSJvdXQiLGUuY29uZmlnLmRlbGF5JiZlLmNvbmZpZy5kZWxheS5oaWRlP2UuX3RpbWVvdXQ9c2V0VGltZW91dCgoZnVuY3Rpb24oKXsib3V0Ij09PWUuX2hvdmVyU3RhdGUmJmUuaGlkZSgpfSksZS5jb25maWcuZGVsYXkuaGlkZSk6ZS5oaWRlKCkpfSxpLl9pc1dpdGhBY3RpdmVUcmlnZ2VyPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuX2FjdGl2ZVRyaWdnZXIpaWYodGhpcy5fYWN0aXZlVHJpZ2dlclt0XSlyZXR1cm4hMDtyZXR1cm4hMX0saS5fZ2V0Q29uZmlnPWZ1bmN0aW9uKHQpe3ZhciBlPWV0LmdldERhdGFBdHRyaWJ1dGVzKHRoaXMuZWxlbWVudCk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmZvckVhY2goKGZ1bmN0aW9uKHQpey0xIT09UnQuaW5kZXhPZih0KSYmZGVsZXRlIGVbdF19KSksdCYmIm9iamVjdCI9PXR5cGVvZiB0LmNvbnRhaW5lciYmdC5jb250YWluZXIuanF1ZXJ5JiYodC5jb250YWluZXI9dC5jb250YWluZXJbMF0pLCJudW1iZXIiPT10eXBlb2YodD1zKHMocyh7fSx0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHQpLGUpLCJvYmplY3QiPT10eXBlb2YgdCYmdD90Ont9KSkuZGVsYXkmJih0LmRlbGF5PXtzaG93OnQuZGVsYXksaGlkZTp0LmRlbGF5fSksIm51bWJlciI9PXR5cGVvZiB0LnRpdGxlJiYodC50aXRsZT10LnRpdGxlLnRvU3RyaW5nKCkpLCJudW1iZXIiPT10eXBlb2YgdC5jb250ZW50JiYodC5jb250ZW50PXQuY29udGVudC50b1N0cmluZygpKSx2KFB0LHQsdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSksdC5zYW5pdGl6ZSYmKHQudGVtcGxhdGU9anQodC50ZW1wbGF0ZSx0LndoaXRlTGlzdCx0LnNhbml0aXplRm4pKSx0fSxpLl9nZXREZWxlZ2F0ZUNvbmZpZz1mdW5jdGlvbigpe3ZhciB0PXt9O2lmKHRoaXMuY29uZmlnKWZvcih2YXIgZSBpbiB0aGlzLmNvbmZpZyl0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRbZV0hPT10aGlzLmNvbmZpZ1tlXSYmKHRbZV09dGhpcy5jb25maWdbZV0pO3JldHVybiB0fSxpLl9jbGVhblRpcENsYXNzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5nZXRUaXBFbGVtZW50KCksZT10LmdldEF0dHJpYnV0ZSgiY2xhc3MiKS5tYXRjaCh4dCk7bnVsbCE9PWUmJmUubGVuZ3RoPjAmJmUubWFwKChmdW5jdGlvbih0KXtyZXR1cm4gdC50cmltKCl9KSkuZm9yRWFjaCgoZnVuY3Rpb24oZSl7cmV0dXJuIHQuY2xhc3NMaXN0LnJlbW92ZShlKX0pKX0saS5faGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlPWZ1bmN0aW9uKHQpe3ZhciBlPXQuaW5zdGFuY2U7dGhpcy50aXA9ZS5wb3BwZXIsdGhpcy5fY2xlYW5UaXBDbGFzcygpLHRoaXMuX2FkZEF0dGFjaG1lbnRDbGFzcyh0aGlzLl9nZXRBdHRhY2htZW50KHQucGxhY2VtZW50KSl9LGkuX2ZpeFRyYW5zaXRpb249ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmdldFRpcEVsZW1lbnQoKSxlPXRoaXMuY29uZmlnLmFuaW1hdGlvbjtudWxsPT09dC5nZXRBdHRyaWJ1dGUoIngtcGxhY2VtZW50IikmJih0LmNsYXNzTGlzdC5yZW1vdmUoImZhZGUiKSx0aGlzLmNvbmZpZy5hbmltYXRpb249ITEsdGhpcy5oaWRlKCksdGhpcy5zaG93KCksdGhpcy5jb25maWcuYW5pbWF0aW9uPWUpfSxlLmpRdWVyeUludGVyZmFjZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5lYWNoKChmdW5jdGlvbigpe3ZhciBuPUwodGhpcywiYnMudG9vbHRpcCIpLGk9Im9iamVjdCI9PXR5cGVvZiB0JiZ0O2lmKChufHwhL2Rpc3Bvc2V8aGlkZS8udGVzdCh0KSkmJihufHwobj1uZXcgZSh0aGlzLGkpKSwic3RyaW5nIj09dHlwZW9mIHQpKXtpZih2b2lkIDA9PT1uW3RdKXRocm93IG5ldyBUeXBlRXJyb3IoJ05vIG1ldGhvZCBuYW1lZCAiJyt0KyciJyk7blt0XSgpfX0pKX0sZS5nZXRJbnN0YW5jZT1mdW5jdGlvbih0KXtyZXR1cm4gTCh0LCJicy50b29sdGlwIil9LG4oZSxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHQiLGdldDpmdW5jdGlvbigpe3JldHVybiBNdH19LHtrZXk6Ik5BTUUiLGdldDpmdW5jdGlvbigpe3JldHVybiBQdH19LHtrZXk6IkRBVEFfS0VZIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iYnMudG9vbHRpcCJ9fSx7a2V5OiJFdmVudCIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIFF0fX0se2tleToiRVZFTlRfS0VZIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iLmJzLnRvb2x0aXAifX0se2tleToiRGVmYXVsdFR5cGUiLGdldDpmdW5jdGlvbigpe3JldHVybiBIdH19XSksZX0oKSxGdD1FKCk7aWYoRnQpe3ZhciBXdD1GdC5mbltQdF07RnQuZm5bUHRdPVV0LmpRdWVyeUludGVyZmFjZSxGdC5mbltQdF0uQ29uc3RydWN0b3I9VXQsRnQuZm5bUHRdLm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gRnQuZm5bUHRdPVd0LFV0LmpRdWVyeUludGVyZmFjZX19dmFyIFZ0PSJwb3BvdmVyIixxdD1uZXcgUmVnRXhwKCIoXnxcXHMpYnMtcG9wb3ZlclxcUysiLCJnIiksenQ9cyhzKHt9LFV0LkRlZmF1bHQpLHt9LHtwbGFjZW1lbnQ6InJpZ2h0Iix0cmlnZ2VyOiJjbGljayIsY29udGVudDoiIix0ZW1wbGF0ZTonPGRpdiBjbGFzcz0icG9wb3ZlciIgcm9sZT0idG9vbHRpcCI+PGRpdiBjbGFzcz0icG9wb3Zlci1hcnJvdyI+PC9kaXY+PGgzIGNsYXNzPSJwb3BvdmVyLWhlYWRlciI+PC9oMz48ZGl2IGNsYXNzPSJwb3BvdmVyLWJvZHkiPjwvZGl2PjwvZGl2Pid9KSxLdD1zKHMoe30sVXQuRGVmYXVsdFR5cGUpLHt9LHtjb250ZW50OiIoc3RyaW5nfGVsZW1lbnR8ZnVuY3Rpb24pIn0pLFh0PXtISURFOiJoaWRlLmJzLnBvcG92ZXIiLEhJRERFTjoiaGlkZGVuLmJzLnBvcG92ZXIiLFNIT1c6InNob3cuYnMucG9wb3ZlciIsU0hPV046InNob3duLmJzLnBvcG92ZXIiLElOU0VSVEVEOiJpbnNlcnRlZC5icy5wb3BvdmVyIixDTElDSzoiY2xpY2suYnMucG9wb3ZlciIsRk9DVVNJTjoiZm9jdXNpbi5icy5wb3BvdmVyIixGT0NVU09VVDoiZm9jdXNvdXQuYnMucG9wb3ZlciIsTU9VU0VFTlRFUjoibW91c2VlbnRlci5icy5wb3BvdmVyIixNT1VTRUxFQVZFOiJtb3VzZWxlYXZlLmJzLnBvcG92ZXIifSxZdD1mdW5jdGlvbih0KXt2YXIgZSxpO2Z1bmN0aW9uIG8oKXtyZXR1cm4gdC5hcHBseSh0aGlzLGFyZ3VtZW50cyl8fHRoaXN9aT10LChlPW8pLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGkucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUuX19wcm90b19fPWk7dmFyIHM9by5wcm90b3R5cGU7cmV0dXJuIHMuaXNXaXRoQ29udGVudD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmdldFRpdGxlKCl8fHRoaXMuX2dldENvbnRlbnQoKX0scy5zZXRDb250ZW50PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5nZXRUaXBFbGVtZW50KCk7dGhpcy5zZXRFbGVtZW50Q29udGVudChudC5maW5kT25lKCIucG9wb3Zlci1oZWFkZXIiLHQpLHRoaXMuZ2V0VGl0bGUoKSk7dmFyIGU9dGhpcy5fZ2V0Q29udGVudCgpOyJmdW5jdGlvbiI9PXR5cGVvZiBlJiYoZT1lLmNhbGwodGhpcy5lbGVtZW50KSksdGhpcy5zZXRFbGVtZW50Q29udGVudChudC5maW5kT25lKCIucG9wb3Zlci1ib2R5Iix0KSxlKSx0LmNsYXNzTGlzdC5yZW1vdmUoImZhZGUiLCJzaG93Iil9LHMuX2FkZEF0dGFjaG1lbnRDbGFzcz1mdW5jdGlvbih0KXt0aGlzLmdldFRpcEVsZW1lbnQoKS5jbGFzc0xpc3QuYWRkKCJicy1wb3BvdmVyLSIrdCl9LHMuX2dldENvbnRlbnQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5lbGVtZW50LmdldEF0dHJpYnV0ZSgiZGF0YS1jb250ZW50Iil8fHRoaXMuY29uZmlnLmNvbnRlbnR9LHMuX2NsZWFuVGlwQ2xhc3M9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmdldFRpcEVsZW1lbnQoKSxlPXQuZ2V0QXR0cmlidXRlKCJjbGFzcyIpLm1hdGNoKHF0KTtudWxsIT09ZSYmZS5sZW5ndGg+MCYmZS5tYXAoKGZ1bmN0aW9uKHQpe3JldHVybiB0LnRyaW0oKX0pKS5mb3JFYWNoKChmdW5jdGlvbihlKXtyZXR1cm4gdC5jbGFzc0xpc3QucmVtb3ZlKGUpfSkpfSxvLmpRdWVyeUludGVyZmFjZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5lYWNoKChmdW5jdGlvbigpe3ZhciBlPUwodGhpcywiYnMucG9wb3ZlciIpLG49Im9iamVjdCI9PXR5cGVvZiB0P3Q6bnVsbDtpZigoZXx8IS9kaXNwb3NlfGhpZGUvLnRlc3QodCkpJiYoZXx8KGU9bmV3IG8odGhpcyxuKSxUKHRoaXMsImJzLnBvcG92ZXIiLGUpKSwic3RyaW5nIj09dHlwZW9mIHQpKXtpZih2b2lkIDA9PT1lW3RdKXRocm93IG5ldyBUeXBlRXJyb3IoJ05vIG1ldGhvZCBuYW1lZCAiJyt0KyciJyk7ZVt0XSgpfX0pKX0sby5nZXRJbnN0YW5jZT1mdW5jdGlvbih0KXtyZXR1cm4gTCh0LCJicy5wb3BvdmVyIil9LG4obyxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHQiLGdldDpmdW5jdGlvbigpe3JldHVybiB6dH19LHtrZXk6Ik5BTUUiLGdldDpmdW5jdGlvbigpe3JldHVybiBWdH19LHtrZXk6IkRBVEFfS0VZIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iYnMucG9wb3ZlciJ9fSx7a2V5OiJFdmVudCIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIFh0fX0se2tleToiRVZFTlRfS0VZIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iLmJzLnBvcG92ZXIifX0se2tleToiRGVmYXVsdFR5cGUiLGdldDpmdW5jdGlvbigpe3JldHVybiBLdH19XSksb30oVXQpLCR0PUUoKTtpZigkdCl7dmFyIEd0PSR0LmZuW1Z0XTskdC5mbltWdF09WXQualF1ZXJ5SW50ZXJmYWNlLCR0LmZuW1Z0XS5Db25zdHJ1Y3Rvcj1ZdCwkdC5mbltWdF0ubm9Db25mbGljdD1mdW5jdGlvbigpe3JldHVybiAkdC5mbltWdF09R3QsWXQualF1ZXJ5SW50ZXJmYWNlfX12YXIgWnQ9InNjcm9sbHNweSIsSnQ9e29mZnNldDoxMCxtZXRob2Q6ImF1dG8iLHRhcmdldDoiIn0sdGU9e29mZnNldDoibnVtYmVyIixtZXRob2Q6InN0cmluZyIsdGFyZ2V0OiIoc3RyaW5nfGVsZW1lbnQpIn0sZWU9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQsZSl7dmFyIG49dGhpczt0aGlzLl9lbGVtZW50PXQsdGhpcy5fc2Nyb2xsRWxlbWVudD0iQk9EWSI9PT10LnRhZ05hbWU/d2luZG93OnQsdGhpcy5fY29uZmlnPXRoaXMuX2dldENvbmZpZyhlKSx0aGlzLl9zZWxlY3Rvcj10aGlzLl9jb25maWcudGFyZ2V0KyIgLm5hdi1saW5rLCIrdGhpcy5fY29uZmlnLnRhcmdldCsiIC5saXN0LWdyb3VwLWl0ZW0sIit0aGlzLl9jb25maWcudGFyZ2V0KyIgLmRyb3Bkb3duLWl0ZW0iLHRoaXMuX29mZnNldHM9W10sdGhpcy5fdGFyZ2V0cz1bXSx0aGlzLl9hY3RpdmVUYXJnZXQ9bnVsbCx0aGlzLl9zY3JvbGxIZWlnaHQ9MCxxLm9uKHRoaXMuX3Njcm9sbEVsZW1lbnQsInNjcm9sbC5icy5zY3JvbGxzcHkiLChmdW5jdGlvbih0KXtyZXR1cm4gbi5fcHJvY2Vzcyh0KX0pKSx0aGlzLnJlZnJlc2goKSx0aGlzLl9wcm9jZXNzKCksVCh0LCJicy5zY3JvbGxzcHkiLHRoaXMpfXZhciBlPXQucHJvdG90eXBlO3JldHVybiBlLnJlZnJlc2g9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLGU9dGhpcy5fc2Nyb2xsRWxlbWVudD09PXRoaXMuX3Njcm9sbEVsZW1lbnQud2luZG93PyJvZmZzZXQiOiJwb3NpdGlvbiIsbj0iYXV0byI9PT10aGlzLl9jb25maWcubWV0aG9kP2U6dGhpcy5fY29uZmlnLm1ldGhvZCxpPSJwb3NpdGlvbiI9PT1uP3RoaXMuX2dldFNjcm9sbFRvcCgpOjA7dGhpcy5fb2Zmc2V0cz1bXSx0aGlzLl90YXJnZXRzPVtdLHRoaXMuX3Njcm9sbEhlaWdodD10aGlzLl9nZXRTY3JvbGxIZWlnaHQoKSxudC5maW5kKHRoaXMuX3NlbGVjdG9yKS5tYXAoKGZ1bmN0aW9uKHQpe3ZhciBlLG89Zih0KTtpZihvJiYoZT1udC5maW5kT25lKG8pKSxlKXt2YXIgcz1lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO2lmKHMud2lkdGh8fHMuaGVpZ2h0KXJldHVybltldFtuXShlKS50b3AraSxvXX1yZXR1cm4gbnVsbH0pKS5maWx0ZXIoKGZ1bmN0aW9uKHQpe3JldHVybiB0fSkpLnNvcnQoKGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRbMF0tZVswXX0pKS5mb3JFYWNoKChmdW5jdGlvbihlKXt0Ll9vZmZzZXRzLnB1c2goZVswXSksdC5fdGFyZ2V0cy5wdXNoKGVbMV0pfSkpfSxlLmRpc3Bvc2U9ZnVuY3Rpb24oKXtDKHRoaXMuX2VsZW1lbnQsImJzLnNjcm9sbHNweSIpLHEub2ZmKHRoaXMuX3Njcm9sbEVsZW1lbnQsIi5icy5zY3JvbGxzcHkiKSx0aGlzLl9lbGVtZW50PW51bGwsdGhpcy5fc2Nyb2xsRWxlbWVudD1udWxsLHRoaXMuX2NvbmZpZz1udWxsLHRoaXMuX3NlbGVjdG9yPW51bGwsdGhpcy5fb2Zmc2V0cz1udWxsLHRoaXMuX3RhcmdldHM9bnVsbCx0aGlzLl9hY3RpdmVUYXJnZXQ9bnVsbCx0aGlzLl9zY3JvbGxIZWlnaHQ9bnVsbH0sZS5fZ2V0Q29uZmlnPWZ1bmN0aW9uKHQpe2lmKCJzdHJpbmciIT10eXBlb2YodD1zKHMoe30sSnQpLCJvYmplY3QiPT10eXBlb2YgdCYmdD90Ont9KSkudGFyZ2V0JiZtKHQudGFyZ2V0KSl7dmFyIGU9dC50YXJnZXQuaWQ7ZXx8KGU9dShadCksdC50YXJnZXQuaWQ9ZSksdC50YXJnZXQ9IiMiK2V9cmV0dXJuIHYoWnQsdCx0ZSksdH0sZS5fZ2V0U2Nyb2xsVG9wPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3Njcm9sbEVsZW1lbnQ9PT13aW5kb3c/dGhpcy5fc2Nyb2xsRWxlbWVudC5wYWdlWU9mZnNldDp0aGlzLl9zY3JvbGxFbGVtZW50LnNjcm9sbFRvcH0sZS5fZ2V0U2Nyb2xsSGVpZ2h0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3Njcm9sbEVsZW1lbnQuc2Nyb2xsSGVpZ2h0fHxNYXRoLm1heChkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodCxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsSGVpZ2h0KX0sZS5fZ2V0T2Zmc2V0SGVpZ2h0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3Njcm9sbEVsZW1lbnQ9PT13aW5kb3c/d2luZG93LmlubmVySGVpZ2h0OnRoaXMuX3Njcm9sbEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0fSxlLl9wcm9jZXNzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fZ2V0U2Nyb2xsVG9wKCkrdGhpcy5fY29uZmlnLm9mZnNldCxlPXRoaXMuX2dldFNjcm9sbEhlaWdodCgpLG49dGhpcy5fY29uZmlnLm9mZnNldCtlLXRoaXMuX2dldE9mZnNldEhlaWdodCgpO2lmKHRoaXMuX3Njcm9sbEhlaWdodCE9PWUmJnRoaXMucmVmcmVzaCgpLHQ+PW4pe3ZhciBpPXRoaXMuX3RhcmdldHNbdGhpcy5fdGFyZ2V0cy5sZW5ndGgtMV07dGhpcy5fYWN0aXZlVGFyZ2V0IT09aSYmdGhpcy5fYWN0aXZhdGUoaSl9ZWxzZXtpZih0aGlzLl9hY3RpdmVUYXJnZXQmJnQ8dGhpcy5fb2Zmc2V0c1swXSYmdGhpcy5fb2Zmc2V0c1swXT4wKXJldHVybiB0aGlzLl9hY3RpdmVUYXJnZXQ9bnVsbCx2b2lkIHRoaXMuX2NsZWFyKCk7Zm9yKHZhciBvPXRoaXMuX29mZnNldHMubGVuZ3RoO28tLTspe3RoaXMuX2FjdGl2ZVRhcmdldCE9PXRoaXMuX3RhcmdldHNbb10mJnQ+PXRoaXMuX29mZnNldHNbb10mJih2b2lkIDA9PT10aGlzLl9vZmZzZXRzW28rMV18fHQ8dGhpcy5fb2Zmc2V0c1tvKzFdKSYmdGhpcy5fYWN0aXZhdGUodGhpcy5fdGFyZ2V0c1tvXSl9fX0sZS5fYWN0aXZhdGU9ZnVuY3Rpb24odCl7dGhpcy5fYWN0aXZlVGFyZ2V0PXQsdGhpcy5fY2xlYXIoKTt2YXIgZT10aGlzLl9zZWxlY3Rvci5zcGxpdCgiLCIpLm1hcCgoZnVuY3Rpb24oZSl7cmV0dXJuIGUrJ1tkYXRhLXRhcmdldD0iJyt0KyciXSwnK2UrJ1tocmVmPSInK3QrJyJdJ30pKSxuPW50LmZpbmRPbmUoZS5qb2luKCIsIikpO24uY2xhc3NMaXN0LmNvbnRhaW5zKCJkcm9wZG93bi1pdGVtIik/KG50LmZpbmRPbmUoIi5kcm9wZG93bi10b2dnbGUiLG4uY2xvc2VzdCgiLmRyb3Bkb3duIikpLmNsYXNzTGlzdC5hZGQoImFjdGl2ZSIpLG4uY2xhc3NMaXN0LmFkZCgiYWN0aXZlIikpOihuLmNsYXNzTGlzdC5hZGQoImFjdGl2ZSIpLG50LnBhcmVudHMobiwiLm5hdiwgLmxpc3QtZ3JvdXAiKS5mb3JFYWNoKChmdW5jdGlvbih0KXtudC5wcmV2KHQsIi5uYXYtbGluaywgLmxpc3QtZ3JvdXAtaXRlbSIpLmZvckVhY2goKGZ1bmN0aW9uKHQpe3JldHVybiB0LmNsYXNzTGlzdC5hZGQoImFjdGl2ZSIpfSkpLG50LnByZXYodCwiLm5hdi1pdGVtIikuZm9yRWFjaCgoZnVuY3Rpb24odCl7bnQuY2hpbGRyZW4odCwiLm5hdi1saW5rIikuZm9yRWFjaCgoZnVuY3Rpb24odCl7cmV0dXJuIHQuY2xhc3NMaXN0LmFkZCgiYWN0aXZlIil9KSl9KSl9KSkpLHEudHJpZ2dlcih0aGlzLl9zY3JvbGxFbGVtZW50LCJhY3RpdmF0ZS5icy5zY3JvbGxzcHkiLHtyZWxhdGVkVGFyZ2V0OnR9KX0sZS5fY2xlYXI9ZnVuY3Rpb24oKXtudC5maW5kKHRoaXMuX3NlbGVjdG9yKS5maWx0ZXIoKGZ1bmN0aW9uKHQpe3JldHVybiB0LmNsYXNzTGlzdC5jb250YWlucygiYWN0aXZlIil9KSkuZm9yRWFjaCgoZnVuY3Rpb24odCl7cmV0dXJuIHQuY2xhc3NMaXN0LnJlbW92ZSgiYWN0aXZlIil9KSl9LHQualF1ZXJ5SW50ZXJmYWNlPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmVhY2goKGZ1bmN0aW9uKCl7dmFyIG49TCh0aGlzLCJicy5zY3JvbGxzcHkiKTtpZihufHwobj1uZXcgdCh0aGlzLCJvYmplY3QiPT10eXBlb2YgZSYmZSkpLCJzdHJpbmciPT10eXBlb2YgZSl7aWYodm9pZCAwPT09bltlXSl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyBtZXRob2QgbmFtZWQgIicrZSsnIicpO25bZV0oKX19KSl9LHQuZ2V0SW5zdGFuY2U9ZnVuY3Rpb24odCl7cmV0dXJuIEwodCwiYnMuc2Nyb2xsc3B5Iil9LG4odCxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHQiLGdldDpmdW5jdGlvbigpe3JldHVybiBKdH19XSksdH0oKTtxLm9uKHdpbmRvdywibG9hZC5icy5zY3JvbGxzcHkuZGF0YS1hcGkiLChmdW5jdGlvbigpe250LmZpbmQoJ1tkYXRhLXNweT0ic2Nyb2xsIl0nKS5mb3JFYWNoKChmdW5jdGlvbih0KXtyZXR1cm4gbmV3IGVlKHQsZXQuZ2V0RGF0YUF0dHJpYnV0ZXModCkpfSkpfSkpO3ZhciBuZT1FKCk7aWYobmUpe3ZhciBpZT1uZS5mbltadF07bmUuZm5bWnRdPWVlLmpRdWVyeUludGVyZmFjZSxuZS5mbltadF0uQ29uc3RydWN0b3I9ZWUsbmUuZm5bWnRdLm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gbmUuZm5bWnRdPWllLGVlLmpRdWVyeUludGVyZmFjZX19dmFyIG9lPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0KXt0aGlzLl9lbGVtZW50PXQsVCh0aGlzLl9lbGVtZW50LCJicy50YWIiLHRoaXMpfXZhciBlPXQucHJvdG90eXBlO3JldHVybiBlLnNob3c9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO2lmKCEodGhpcy5fZWxlbWVudC5wYXJlbnROb2RlJiZ0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUubm9kZVR5cGU9PT1Ob2RlLkVMRU1FTlRfTk9ERSYmdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoImFjdGl2ZSIpfHx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygiZGlzYWJsZWQiKSkpe3ZhciBlLG49ZCh0aGlzLl9lbGVtZW50KSxpPXRoaXMuX2VsZW1lbnQuY2xvc2VzdCgiLm5hdiwgLmxpc3QtZ3JvdXAiKTtpZihpKXt2YXIgbz0iVUwiPT09aS5ub2RlTmFtZXx8Ik9MIj09PWkubm9kZU5hbWU/IjpzY29wZSA+IGxpID4gLmFjdGl2ZSI6Ii5hY3RpdmUiO2U9KGU9bnQuZmluZChvLGkpKVtlLmxlbmd0aC0xXX12YXIgcz1udWxsO2lmKGUmJihzPXEudHJpZ2dlcihlLCJoaWRlLmJzLnRhYiIse3JlbGF0ZWRUYXJnZXQ6dGhpcy5fZWxlbWVudH0pKSwhKHEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJzaG93LmJzLnRhYiIse3JlbGF0ZWRUYXJnZXQ6ZX0pLmRlZmF1bHRQcmV2ZW50ZWR8fG51bGwhPT1zJiZzLmRlZmF1bHRQcmV2ZW50ZWQpKXt0aGlzLl9hY3RpdmF0ZSh0aGlzLl9lbGVtZW50LGkpO3ZhciByPWZ1bmN0aW9uKCl7cS50cmlnZ2VyKGUsImhpZGRlbi5icy50YWIiLHtyZWxhdGVkVGFyZ2V0OnQuX2VsZW1lbnR9KSxxLnRyaWdnZXIodC5fZWxlbWVudCwic2hvd24uYnMudGFiIix7cmVsYXRlZFRhcmdldDplfSl9O24/dGhpcy5fYWN0aXZhdGUobixuLnBhcmVudE5vZGUscik6cigpfX19LGUuZGlzcG9zZT1mdW5jdGlvbigpe0ModGhpcy5fZWxlbWVudCwiYnMudGFiIiksdGhpcy5fZWxlbWVudD1udWxsfSxlLl9hY3RpdmF0ZT1mdW5jdGlvbih0LGUsbil7dmFyIGk9dGhpcyxvPSghZXx8IlVMIiE9PWUubm9kZU5hbWUmJiJPTCIhPT1lLm5vZGVOYW1lP250LmNoaWxkcmVuKGUsIi5hY3RpdmUiKTpudC5maW5kKCI6c2NvcGUgPiBsaSA+IC5hY3RpdmUiLGUpKVswXSxzPW4mJm8mJm8uY2xhc3NMaXN0LmNvbnRhaW5zKCJmYWRlIikscj1mdW5jdGlvbigpe3JldHVybiBpLl90cmFuc2l0aW9uQ29tcGxldGUodCxvLG4pfTtpZihvJiZzKXt2YXIgYT1nKG8pO28uY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLHEub25lKG8sInRyYW5zaXRpb25lbmQiLHIpLF8obyxhKX1lbHNlIHIoKX0sZS5fdHJhbnNpdGlvbkNvbXBsZXRlPWZ1bmN0aW9uKHQsZSxuKXtpZihlKXtlLmNsYXNzTGlzdC5yZW1vdmUoImFjdGl2ZSIpO3ZhciBpPW50LmZpbmRPbmUoIjpzY29wZSA+IC5kcm9wZG93bi1tZW51IC5hY3RpdmUiLGUucGFyZW50Tm9kZSk7aSYmaS5jbGFzc0xpc3QucmVtb3ZlKCJhY3RpdmUiKSwidGFiIj09PWUuZ2V0QXR0cmlidXRlKCJyb2xlIikmJmUuc2V0QXR0cmlidXRlKCJhcmlhLXNlbGVjdGVkIiwhMSl9KHQuY2xhc3NMaXN0LmFkZCgiYWN0aXZlIiksInRhYiI9PT10LmdldEF0dHJpYnV0ZSgicm9sZSIpJiZ0LnNldEF0dHJpYnV0ZSgiYXJpYS1zZWxlY3RlZCIsITApLHcodCksdC5jbGFzc0xpc3QuY29udGFpbnMoImZhZGUiKSYmdC5jbGFzc0xpc3QuYWRkKCJzaG93IiksdC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCJkcm9wZG93bi1tZW51IikpJiYodC5jbG9zZXN0KCIuZHJvcGRvd24iKSYmbnQuZmluZCgiLmRyb3Bkb3duLXRvZ2dsZSIpLmZvckVhY2goKGZ1bmN0aW9uKHQpe3JldHVybiB0LmNsYXNzTGlzdC5hZGQoImFjdGl2ZSIpfSkpLHQuc2V0QXR0cmlidXRlKCJhcmlhLWV4cGFuZGVkIiwhMCkpO24mJm4oKX0sdC5qUXVlcnlJbnRlcmZhY2U9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZWFjaCgoZnVuY3Rpb24oKXt2YXIgbj1MKHRoaXMsImJzLnRhYiIpfHxuZXcgdCh0aGlzKTtpZigic3RyaW5nIj09dHlwZW9mIGUpe2lmKHZvaWQgMD09PW5bZV0pdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gbWV0aG9kIG5hbWVkICInK2UrJyInKTtuW2VdKCl9fSkpfSx0LmdldEluc3RhbmNlPWZ1bmN0aW9uKHQpe3JldHVybiBMKHQsImJzLnRhYiIpfSxuKHQsbnVsbCxbe2tleToiVkVSU0lPTiIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIjUuMC4wLWFscGhhMSJ9fV0pLHR9KCk7cS5vbihkb2N1bWVudCwiY2xpY2suYnMudGFiLmRhdGEtYXBpIiwnW2RhdGEtdG9nZ2xlPSJ0YWIiXSwgW2RhdGEtdG9nZ2xlPSJwaWxsIl0sIFtkYXRhLXRvZ2dsZT0ibGlzdCJdJywoZnVuY3Rpb24odCl7dC5wcmV2ZW50RGVmYXVsdCgpLChMKHRoaXMsImJzLnRhYiIpfHxuZXcgb2UodGhpcykpLnNob3coKX0pKTt2YXIgc2U9RSgpO2lmKHNlKXt2YXIgcmU9c2UuZm4udGFiO3NlLmZuLnRhYj1vZS5qUXVlcnlJbnRlcmZhY2Usc2UuZm4udGFiLkNvbnN0cnVjdG9yPW9lLHNlLmZuLnRhYi5ub0NvbmZsaWN0PWZ1bmN0aW9uKCl7cmV0dXJuIHNlLmZuLnRhYj1yZSxvZS5qUXVlcnlJbnRlcmZhY2V9fXZhciBhZT17YW5pbWF0aW9uOiJib29sZWFuIixhdXRvaGlkZToiYm9vbGVhbiIsZGVsYXk6Im51bWJlciJ9LGxlPXthbmltYXRpb246ITAsYXV0b2hpZGU6ITAsZGVsYXk6NTAwfSxjZT1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlKXt0aGlzLl9lbGVtZW50PXQsdGhpcy5fY29uZmlnPXRoaXMuX2dldENvbmZpZyhlKSx0aGlzLl90aW1lb3V0PW51bGwsdGhpcy5fc2V0TGlzdGVuZXJzKCksVCh0LCJicy50b2FzdCIsdGhpcyl9dmFyIGU9dC5wcm90b3R5cGU7cmV0dXJuIGUuc2hvdz1mdW5jdGlvbigpe3ZhciB0PXRoaXM7aWYoIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJzaG93LmJzLnRvYXN0IikuZGVmYXVsdFByZXZlbnRlZCl7dGhpcy5fY29uZmlnLmFuaW1hdGlvbiYmdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKCJmYWRlIik7dmFyIGU9ZnVuY3Rpb24oKXt0Ll9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoInNob3dpbmciKSx0Ll9lbGVtZW50LmNsYXNzTGlzdC5hZGQoInNob3ciKSxxLnRyaWdnZXIodC5fZWxlbWVudCwic2hvd24uYnMudG9hc3QiKSx0Ll9jb25maWcuYXV0b2hpZGUmJih0Ll90aW1lb3V0PXNldFRpbWVvdXQoKGZ1bmN0aW9uKCl7dC5oaWRlKCl9KSx0Ll9jb25maWcuZGVsYXkpKX07aWYodGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCJoaWRlIiksdyh0aGlzLl9lbGVtZW50KSx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoInNob3dpbmciKSx0aGlzLl9jb25maWcuYW5pbWF0aW9uKXt2YXIgbj1nKHRoaXMuX2VsZW1lbnQpO3Eub25lKHRoaXMuX2VsZW1lbnQsInRyYW5zaXRpb25lbmQiLGUpLF8odGhpcy5fZWxlbWVudCxuKX1lbHNlIGUoKX19LGUuaGlkZT1mdW5jdGlvbigpe3ZhciB0PXRoaXM7aWYodGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoInNob3ciKSYmIXEudHJpZ2dlcih0aGlzLl9lbGVtZW50LCJoaWRlLmJzLnRvYXN0IikuZGVmYXVsdFByZXZlbnRlZCl7dmFyIGU9ZnVuY3Rpb24oKXt0Ll9lbGVtZW50LmNsYXNzTGlzdC5hZGQoImhpZGUiKSxxLnRyaWdnZXIodC5fZWxlbWVudCwiaGlkZGVuLmJzLnRvYXN0Iil9O2lmKHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgic2hvdyIpLHRoaXMuX2NvbmZpZy5hbmltYXRpb24pe3ZhciBuPWcodGhpcy5fZWxlbWVudCk7cS5vbmUodGhpcy5fZWxlbWVudCwidHJhbnNpdGlvbmVuZCIsZSksXyh0aGlzLl9lbGVtZW50LG4pfWVsc2UgZSgpfX0sZS5kaXNwb3NlPWZ1bmN0aW9uKCl7Y2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVvdXQpLHRoaXMuX3RpbWVvdXQ9bnVsbCx0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygic2hvdyIpJiZ0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoInNob3ciKSxxLm9mZih0aGlzLl9lbGVtZW50LCJjbGljay5kaXNtaXNzLmJzLnRvYXN0IiksQyh0aGlzLl9lbGVtZW50LCJicy50b2FzdCIpLHRoaXMuX2VsZW1lbnQ9bnVsbCx0aGlzLl9jb25maWc9bnVsbH0sZS5fZ2V0Q29uZmlnPWZ1bmN0aW9uKHQpe3JldHVybiB0PXMocyhzKHt9LGxlKSxldC5nZXREYXRhQXR0cmlidXRlcyh0aGlzLl9lbGVtZW50KSksIm9iamVjdCI9PXR5cGVvZiB0JiZ0P3Q6e30pLHYoInRvYXN0Iix0LHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdFR5cGUpLHR9LGUuX3NldExpc3RlbmVycz1mdW5jdGlvbigpe3ZhciB0PXRoaXM7cS5vbih0aGlzLl9lbGVtZW50LCJjbGljay5kaXNtaXNzLmJzLnRvYXN0IiwnW2RhdGEtZGlzbWlzcz0idG9hc3QiXScsKGZ1bmN0aW9uKCl7cmV0dXJuIHQuaGlkZSgpfSkpfSx0LmpRdWVyeUludGVyZmFjZT1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5lYWNoKChmdW5jdGlvbigpe3ZhciBuPUwodGhpcywiYnMudG9hc3QiKTtpZihufHwobj1uZXcgdCh0aGlzLCJvYmplY3QiPT10eXBlb2YgZSYmZSkpLCJzdHJpbmciPT10eXBlb2YgZSl7aWYodm9pZCAwPT09bltlXSl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyBtZXRob2QgbmFtZWQgIicrZSsnIicpO25bZV0odGhpcyl9fSkpfSx0LmdldEluc3RhbmNlPWZ1bmN0aW9uKHQpe3JldHVybiBMKHQsImJzLnRvYXN0Iil9LG4odCxudWxsLFt7a2V5OiJWRVJTSU9OIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4iNS4wLjAtYWxwaGExIn19LHtrZXk6IkRlZmF1bHRUeXBlIixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gYWV9fSx7a2V5OiJEZWZhdWx0IixnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gbGV9fV0pLHR9KCksdWU9RSgpO2lmKHVlKXt2YXIgaGU9dWUuZm4udG9hc3Q7dWUuZm4udG9hc3Q9Y2UualF1ZXJ5SW50ZXJmYWNlLHVlLmZuLnRvYXN0LkNvbnN0cnVjdG9yPWNlLHVlLmZuLnRvYXN0Lm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gdWUuZm4udG9hc3Q9aGUsY2UualF1ZXJ5SW50ZXJmYWNlfX1yZXR1cm57QWxlcnQ6SyxCdXR0b246JCxDYXJvdXNlbDpsdCxDb2xsYXBzZTpndCxEcm9wZG93bjp3dCxNb2RhbDpDdCxQb3BvdmVyOll0LFNjcm9sbFNweTplZSxUYWI6b2UsVG9hc3Q6Y2UsVG9vbHRpcDpVdH19KSk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPWJvb3RzdHJhcC5taW4uanMubWFw")

A vendor/github.com/stripe/stripe-go/v71/.gitignore => vendor/github.com/stripe/stripe-go/v71/.gitignore +4 -0
@@ 0,0 1,4 @@
.DS_Store
.env
*.test
*.coverprofile

A vendor/github.com/stripe/stripe-go/v71/.travis.yml => vendor/github.com/stripe/stripe-go/v71/.travis.yml +60 -0
@@ 0,0 1,60 @@
before_install:
  # Install various build dependencies. We use `travis_retry` because `go get`
  # will occasionally fail intermittently.

  # The testify require framework is used for assertions in the test suite
  - travis_retry go get -u github.com/stretchr/testify/require

  # Install lint / code coverage / coveralls tooling
  - travis_retry go get -u golang.org/x/net/http2
  - travis_retry go get -u golang.org/x/tools/cmd/cover
  - travis_retry go get -u github.com/mattn/goveralls
  - travis_retry go get -u golang.org/x/lint/golint

  # Unpack and start the Stripe API stub so that the test suite can talk to it
  - |
    if [ ! -d "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}" ]; then
      mkdir -p stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/
      curl -L "https://github.com/stripe/stripe-mock/releases/download/v${STRIPE_MOCK_VERSION}/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -o "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz"
      tar -zxf "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -C "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/"
    fi
  - |
    stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/stripe-mock -https-port 12112 -strict-version-check > /dev/null &
    STRIPE_MOCK_PID=$!

  # stripe-mock must be in PATH for `scripts/test_with_stripe_mock.go` to work.
  - export PATH="${PATH}:${PWD}/stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}"

cache:
  directories:
    - stripe-mock

env:
  global:
    # If changing this number, please also change it in `testing/testing.go`.
    - STRIPE_MOCK_VERSION=0.93.0

go:
  - "1.10.x"
  - "1.11.x"
  - "1.12.x"
  - "1.13.x"
  - "1.14.x"
  - tip

language: go

matrix:
  allow_failures:
    - go: tip
  fast_finish: true

script:
  - make
  - make coverage

after_script:
  # Send code coverage report to coveralls.io
  - goveralls -service=travis-ci -coverprofile=combined.coverprofile

sudo: false

A vendor/github.com/stripe/stripe-go/v71/CHANGELOG => vendor/github.com/stripe/stripe-go/v71/CHANGELOG +1 -0
@@ 0,0 1,1 @@
CHANGELOG has changed to be Markdown-formatted. Please see CHANGELOG.md.

A vendor/github.com/stripe/stripe-go/v71/CHANGELOG.md => vendor/github.com/stripe/stripe-go/v71/CHANGELOG.md +1786 -0
@@ 0,0 1,1786 @@
# Changelog

## 71.28.0 - 2020-06-23
* [#1127](https://github.com/stripe/stripe-go/pull/1127) Add `FilePurposeDocumentProviderIdentityDocument` on `File`
* [#1126](https://github.com/stripe/stripe-go/pull/1126) Add support for `Discounts` on `LineItem`

## 71.27.0 - 2020-06-18
* [#1124](https://github.com/stripe/stripe-go/pull/1124) Add support for `RefreshURL` and `ReturnURL` on `AccountLink`

## 71.26.0 - 2020-06-15
* [#1090](https://github.com/stripe/stripe-go/pull/1090) Add support for `PaymentMethodData` on `PaymentIntent`

## 71.25.1 - 2020-06-11
* [#1123](https://github.com/stripe/stripe-go/pull/1123) Attach LastResponse after unmarshaling

## 71.25.0 - 2020-06-11
* [#1122](https://github.com/stripe/stripe-go/pull/1122) Add support for `Transaction` on Issuing `Dispute`
* [#1121](https://github.com/stripe/stripe-go/pull/1121) Add `Mandate`, `InstitutionNumber` and `TransitNumber` to `ChargePaymentMethodDetailsAcssDebit`

## 71.24.0 - 2020-06-10
* [#1120](https://github.com/stripe/stripe-go/pull/1120) Add support for Cartes Bancaires payments on `PaymentIntent` and `PaymentMethod`

## 71.23.0 - 2020-06-09
* [#1119](https://github.com/stripe/stripe-go/pull/1119) Add support for `TaxIDTypeIDNPWP` and `TaxIDTypeMYFRP` on `TaxId`

## 71.22.0 - 2020-06-09
* [#1118](https://github.com/stripe/stripe-go/pull/1118) Add missing information for BACS Debit in `PaymentMethod`

## 71.21.0 - 2020-06-05
* [#1117](https://github.com/stripe/stripe-go/pull/1117) Add `PaymentMethodIdealParams` to `PaymentMethodParams`

## 71.20.0 - 2020-06-04
* [#1116](https://github.com/stripe/stripe-go/pull/1116) Clean up the error deserialization and ensure `DeclineCode` is properly set.

## 71.19.0 - 2020-06-03
* [#1113](https://github.com/stripe/stripe-go/pull/1113) Add support for `TransferGroup` on Checkout `Session`

## 71.18.0 - 2020-06-03
* [#1110](https://github.com/stripe/stripe-go/pull/1110) Add support for reading SEPA and BACS debit settings on `Account`
* [#1111](https://github.com/stripe/stripe-go/pull/1111) Add support for Bancontact, EPS, Giropay and P24 on `PaymentMethod`
* [#1112](https://github.com/stripe/stripe-go/pull/1112) Add support for BACS Debit as a `Capability` on `Account`

## 71.17.0 - 2020-05-29
* [#1109](https://github.com/stripe/stripe-go/pull/1109) Add support for BACS Debit as a `PaymentMethod`

## 71.16.0 - 2020-05-29
* [#1108](https://github.com/stripe/stripe-go/pull/1108) Add `Metadata` and `Object` on `Topup`

## 71.15.0 - 2020-05-28
* [#1106](https://github.com/stripe/stripe-go/pull/1106) Add support for `ProductData` on `LineItems` for Checkout `Session`
* [#1105](https://github.com/stripe/stripe-go/pull/1105) Add `AuthenticationFlow` to `ChargePaymentMethodDetailsCardThreeDSecure`

## 71.14.0 - 2020-05-22
* [#1104](https://github.com/stripe/stripe-go/pull/1104) Add support for `TaxIDTypeAETRN`, `TaxIDTypeCLTIN` and `TaxIDTypeSAVAT` on `TaxId`
* [#1103](https://github.com/stripe/stripe-go/pull/1103) Add support for `Result` and `ResultReason` on `ChargePaymentMethodDetailsCardThreeDSecure`

## 71.13.0 - 2020-05-20
* [#1101](https://github.com/stripe/stripe-go/pull/1101) Multiple API Changes
  * Add `BalanceTransactionTypeAnticipationRepayment` as a `Type` on `BalanceTransaction`
  * Add `PaymentMethodTypeInteracPresent` as a `Type` on `PaymentMethod`
  * Add `ChargePaymentMethodDetailsInteracPresent` on `Charge`
  * Add `TransferData ` on `SubscriptionSchedule`

## 71.12.0 - 2020-05-18
* [#1099](https://github.com/stripe/stripe-go/pull/1099) Multiple API changes
  * Add `issuing_dispute` as a `type` on `BalanceTransaction`
  * Add `BalanceTransactions` as a a list of `BalanceTransaction` on Issuing `Dispute`
  * Add `Fingerprint` and `TransactionId` in `ChargePaymentMethodDetailsAlipay` on `Charge`
  * Add `Amount` in `InvoiceTransferData` and `InvoiceTransferDataParams` on `Invoice`
  * Add `AmountPercent` in `SubscriptionTransferData` and `SubscriptionTransferDataParams` on `Subscription`

## 71.11.1 - 2020-05-13
* [#1097](https://github.com/stripe/stripe-go/pull/1097) Fixing `LineItems` to be `LineItemList` on Checkout `Session`

## 71.11.0 - 2020-05-13
* [#1096](https://github.com/stripe/stripe-go/pull/1096) Add support for `PurchaseDetails` on Issuing `Transaction`

## 71.10.0 - 2020-05-12
* [#1091](https://github.com/stripe/stripe-go/pull/1091) Add support for the `LineItem` resource and APIs

## 71.9.0 - 2020-05-07
* [#1093](https://github.com/stripe/stripe-go/pull/1093) Add support for `Metadata` for `PaymentIntentData` and `SubscriptionData` on Checkout `Session`
* [#1095](https://github.com/stripe/stripe-go/pull/1095) Add `SupportAddress` in `BusinessProfile` on `Account` creation and update
* [#1094](https://github.com/stripe/stripe-go/pull/1094) Fix parameters supported in `Recurring` for `PriceData` across the API

## 71.8.0 - 2020-05-01
* [#1089](https://github.com/stripe/stripe-go/pull/1089) Add support for `Issuing` in `Balance`

## 71.7.0 - 2020-04-29
* [#1087](https://github.com/stripe/stripe-go/pull/1087) Add support for Brazilian tax ids on `TaxID`
* [#1085](https://github.com/stripe/stripe-go/pull/1085) Add `Object` on `BankAccount`
* [#1065](https://github.com/stripe/stripe-go/pull/1065) Adding support for the `Price` resource and APIs

## 71.6.0 - 2020-04-23
* [#1083](https://github.com/stripe/stripe-go/pull/1083) Add support for `JCBPayments` and `CardIssuing` as a `Capability`
* [#1082](https://github.com/stripe/stripe-go/pull/1082) Add support for expandable `CVC` and `Number` on Issuing `Card`

## 71.5.0 - 2020-04-22
* [#1080](https://github.com/stripe/stripe-go/pull/1080) Remove spurious newline in logs

## 71.4.0 - 2020-04-22
* [#1079](https://github.com/stripe/stripe-go/pull/1079) Add support for `Coupon` when for subscriptions on Checkout

## 71.3.0 - 2020-04-22
* [#1078](https://github.com/stripe/stripe-go/pull/1078) Add missing error codes such as `ErrorCodeCardDeclinedRateLimitExceeded`
* [#1063](https://github.com/stripe/stripe-go/pull/1063) Add support for the `BillingPortal` namespace and the `Session` API and resource

## 71.2.0 - 2020-04-21
* [#1076](https://github.com/stripe/stripe-go/pull/1076) Add `Deleted` on `Invoice`

## 71.1.0 - 2020-04-17
* [#1074](https://github.com/stripe/stripe-go/pull/1074) Add `CardholderName` to `ChargePaymentMethodDetailsCardPresent` on `Charge`
* [#1075](https://github.com/stripe/stripe-go/pull/1075) Add new enum values for `AccountCompanyStructure` on `Account`

## 71.0.0 - 2020-04-17
Version 71 of stripe-go contains some major changes. Many of them are breaking, but only in minor ways. We've written [a migration guide](https://github.com/stripe/stripe-go/blob/master/v71_migration_guide.md) with more details to help with the upgrade.

* [#1052](https://github.com/stripe/stripe-go/pull/1052) Remove all beta features from Issuing APIs
* [#1054](https://github.com/stripe/stripe-go/pull/1054) Make API response accessible on returned API structs
* [#1061](https://github.com/stripe/stripe-go/pull/1061) Start using Go Modules
* [#1068](https://github.com/stripe/stripe-go/pull/1068) Multiple breaking API changes
  * `PaymentIntent` is now expandable on `Charge`
  * `Percentage` was removed as a filter when listing `TaxRate`
  * Removed `RenewalInterval` on `SubscriptionSchedule`
  * Removed `Country` and `RoutingNumber` from `ChargePaymentMethodDetailsAcssDebit`
* [#1069](https://github.com/stripe/stripe-go/pull/1069) Default number of network retries to 2
* [#1070](https://github.com/stripe/stripe-go/pull/1070) Clean up logging for next major

## 70.15.0 - 2020-04-14
* [#1066](https://github.com/stripe/stripe-go/pull/1066) Add support for `SecondaryColor` on `Account`

## 70.14.0 - 2020-04-13
* [#1062](https://github.com/stripe/stripe-go/pull/1062) Add `Description` on `WebhookEndpoint`

## 70.13.0 - 2020-04-10
* [#1060](https://github.com/stripe/stripe-go/pull/1060) Add support for `CancellationReason` on Issuing `Card`
* [#1058](https://github.com/stripe/stripe-go/pull/1058) Add support for `TaxIDTypeSGGST` on `TaxId`

## 70.12.0 - 2020-04-09
* [#1057](https://github.com/stripe/stripe-go/pull/1057) Add missing properties on `Review`

## 70.11.0 - 2020-04-03
* [#1056](https://github.com/stripe/stripe-go/pull/1056) Add `CalculatedStatementDescriptor` on `Charge`

## 70.10.0 - 2020-03-30
* [#1053](https://github.com/stripe/stripe-go/pull/1053) Add `AccountCapabilityCardIssuing` as a `Capability`

## 70.9.0 - 2020-03-26
* [#1050](https://github.com/stripe/stripe-go/pull/1050) Multiple API changes for Issuing
  * Add support for `SpendingControls` on `Card` and `Cardholder`
  * Add new values for `Reason` on `Authorization`
  * Add new value for `Type` on `Cardholder`
  * Add new value for `Service` on `Card`
  * Mark many classes and other fields as deprecated for the next major

## 70.8.0 - 2020-03-24
* [#1049](https://github.com/stripe/stripe-go/pull/1049) Add support for `PauseCollection` on `Subscription`

## 70.7.0 - 2020-03-23
* [#1048](https://github.com/stripe/stripe-go/pull/1048) Add new capabilities for AU Becs Debit and tax reporting

## 70.6.0 - 2020-03-20
* [#1046](https://github.com/stripe/stripe-go/pull/1046) Add new fields to Issuing `Card` and `Authorization`

## 70.5.0 - 2020-03-13
* [#1044](https://github.com/stripe/stripe-go/pull/1044) Multiple changes for Issuing APIs
  * Rename `Speed` to `Service` on Issuing `Card`
  * Rename `WalletProvider` to `Wallet` and `AddressZipCheck` to `AddressPostalCodeCheck` on Issuing `Authorization`
  * Mark `IsDefault` as deprecated on Issuing `Cardholder`

## 70.4.0 - 2020-03-12
* [#1043](https://github.com/stripe/stripe-go/pull/1043) Add support for `Shipping` and `ShippingAddressCollection` on Checkout `Session`

## 70.3.0 - 2020-03-12
* [#1042](https://github.com/stripe/stripe-go/pull/1042) Add support for `ThreeDSecure` on Issuing `Authorization`

## 70.2.0 - 2020-03-04
* [#1041](https://github.com/stripe/stripe-go/pull/1041) Add new reason values and `ExpiryCheck` for Issuing `authorization

## 70.1.0 - 2020-03-04
* [#1040](https://github.com/stripe/stripe-go/pull/1040) Add support for `Errors` in `Requirements` on `Account`, `Capability` and `Person`

## 70.0.0 - 2020-03-03
* [#1039](https://github.com/stripe/stripe-go/pull/1039) Multiple API changes:
  * Move to latest API version `2020-03-02`
  * Add support for `NextInvoiceSequence` on `Customer`

## 69.4.0 - 2020-02-28
* [#1038](https://github.com/stripe/stripe-go/pull/1038) Add `TaxIDTypeMYSST` for `TaxId`

## 69.3.0 - 2020-02-24
* [#1037](https://github.com/stripe/stripe-go/pull/1037) Add new enum values for `IssuingDisputeReason`

## 69.2.0 - 2020-02-24
* [#1036](https://github.com/stripe/stripe-go/pull/1036) Add support for listing Checkout `Session` and passing tax rate information

## 69.1.0 - 2020-02-21
* [#1035](https://github.com/stripe/stripe-go/pull/1035) Add support for `ProrationBehavior` on `SubscriptionSchedule`
* [#1034](https://github.com/stripe/stripe-go/pull/1034) Add support for `Timezone` on `ReportRun`

## 69.0.0 - 2020-02-20
* [#1033](https://github.com/stripe/stripe-go/pull/1033) Make `Subscription` expandable on `Invoice`

## 68.20.0 - 2020-02-12
* [#1029](https://github.com/stripe/stripe-go/pull/1029) Add support for `Amount` in `CheckoutSessionPaymentIntentDataTransferDataParams`

## 68.19.0 - 2020-02-10
* [#1027](https://github.com/stripe/stripe-go/pull/1027) Add new constants for `TaxIDType`
* [#1028](https://github.com/stripe/stripe-go/pull/1028) Add support for `StatementDescriptorSuffix` on Checkout `Session`

## 68.18.0 - 2020-02-05
* [#1026](https://github.com/stripe/stripe-go/pull/1026) Multiple changes on the `Balance` resource:
  * Add support for `ConnectReserved`
  * Add support for `SourceTypes` for a given type of balance.
  * Add support for FPX balance as a constant.

## 68.17.0 - 2020-02-03
* [#1024](https://github.com/stripe/stripe-go/pull/1024) Add `FilePurposeAdditionalVerification` and `FilePurposeBusinessIcon` on `File`
* [#1018](https://github.com/stripe/stripe-go/pull/1018) Add support for `ErrorOnRequiresAction` on `PaymentIntent`

## 68.16.0 - 2020-01-31
* [#1023](https://github.com/stripe/stripe-go/pull/1023) Add support for `TaxIDTypeTHVAT` and `TaxIDTypeTWVAT` on `TaxId`

## 68.15.0 - 2020-01-30
* [#1022](https://github.com/stripe/stripe-go/pull/1022) Add support for `Structure` on `Account`

## 68.14.0 - 2020-01-28
* [#1021](https://github.com/stripe/stripe-go/pull/1021) Add support for `TaxIDTypeESCIF` on `TaxId`

## 68.13.0 - 2020-01-24
* [#1019](https://github.com/stripe/stripe-go/pull/1019) Add support for `Shipping.Speed` and `Shipping.TrackingURL` on `IssuingCard`

## 68.12.0 - 2020-01-23
* [#1017](https://github.com/stripe/stripe-go/pull/1017) Add new values for `TaxIDType` and fix `TaxIDTypeCHVAT`
* [#1015](https://github.com/stripe/stripe-go/pull/1015) Replace duplicate code in GetBackend method

## 68.11.0 - 2020-01-17
* [#1014](https://github.com/stripe/stripe-go/pull/1014) Add `Metadata` support on Checkout `Session`

## 68.10.0 - 2020-01-15
* [#1012](https://github.com/stripe/stripe-go/pull/1012) Adds `PendingUpdate` to `Subscription`

## 68.9.0 - 2020-01-14
* [#1013](https://github.com/stripe/stripe-go/pull/1013) Add support for `CreditNoteLineItem`

## 68.8.0 - 2020-01-08
* [#1011](https://github.com/stripe/stripe-go/pull/1011) Add support for `InvoiceItem` and fix `Livemode` on `InvoiceLine`

## 68.7.0 - 2020-01-07
* [#1008](https://github.com/stripe/stripe-go/pull/1008) Add `ReportingCategory` to `BalanceTransaction`

## 68.6.0 - 2020-01-06
* [#1009](https://github.com/stripe/stripe-go/pull/1009) Add constant for `TaxIDTypeSGUEN` on `TaxId`

## 68.5.0 - 2020-01-03
* [#1007](https://github.com/stripe/stripe-go/pull/1007) Add support for `SpendingLimitsCurrency` on Issuing `Card` and `Cardholder`

## 68.4.0 - 2019-12-20
* [#1006](https://github.com/stripe/stripe-go/pull/1006) Adds `ExecutivesProvided` to `Account`

## 68.3.0 - 2019-12-19
* [#1005](https://github.com/stripe/stripe-go/pull/1005) Add `Metadata` and `Livemode` to Terminal `Reader` and `Location'

## 68.2.0 - 2019-12-09
* [#1002](https://github.com/stripe/stripe-go/pull/1002) Add support for AU BECS Debit on PaymentMethod

## 68.1.0 - 2019-12-04
* [#1001](https://github.com/stripe/stripe-go/pull/1001) Add support for `Network` on `Charge`

## 68.0.0 - 2019-12-03
* [#1000](https://github.com/stripe/stripe-go/pull/1000) Multiple breaking changes:
  * Pin to API version `2019-12-03`
  * Rename `InvoiceBillingStatus` to `InvoiceStatus` for consistency
  * Remove typo-ed field `OutOfBankdAmount` on `CreditNote`
  * Remove deprecated `PaymentIntentPaymentMethodOptionsCardRequestThreeDSecureChallengeOnly` and `SetupIntentPaymentMethodOptionsCardRequestThreeDSecureChallengeOnly` from `PaymentIntent` and `SetupIntent`.
  * Remove `OperatorAccount` on `TerminalLocationListParams`

## 67.10.0 - 2019-12-02
* [#999](https://github.com/stripe/stripe-go/pull/999) Add support for `Status` filter when listing `Invoice`s.

## 67.9.0 - 2019-11-26
* [#997](https://github.com/stripe/stripe-go/pull/997) Add new refund reason `RefundReasonExpiredUncapturedCharge`

## 67.8.0 - 2019-11-26
* [#998](https://github.com/stripe/stripe-go/pull/998) Add support for `CreditNote` preview

## 67.7.0 - 2019-11-25
* [#996](https://github.com/stripe/stripe-go/pull/996) Add support for `OutOfBandAmount` on `CreditNote` creation
* [#995](https://github.com/stripe/stripe-go/pull/995) Fix comment typos

## 67.6.0 - 2019-11-22
* [#994](https://github.com/stripe/stripe-go/pull/994) Support for the `now` on `StartDate` on Subscription Schedule creation

## 67.5.0 - 2019-11-21
* [#993](https://github.com/stripe/stripe-go/pull/993) Add `PaymentIntent` filter when listing `Dispute`s

## 67.4.1 - 2019-11-19
* [#991](https://github.com/stripe/stripe-go/pull/991) Add missing constant for PaymentMethod of type FPX

## 67.4.0 - 2019-11-18
* [#989](https://github.com/stripe/stripe-go/pull/989) Add support for `ViolatedAuthorizationControls` on Issuing `Authorization`

## 67.3.0 - 2019-11-07
* [#988](https://github.com/stripe/stripe-go/pull/988) Add `Company` and `Individual` to Issuing `Cardholder`

## 67.2.0 - 2019-11-06
* [#985](https://github.com/stripe/stripe-go/pull/985) Multiple API changes
  * Add `Disputed` to `Charge`
  * Add `PaymentIntent` to `Refund` and `Dispute`
  * Add `Charge` to `DisputeListParams`
  * Add `PaymentIntent` to `RefundListParams` and `RefundParams`

## 67.1.0 - 2019-11-06
* [#986](https://github.com/stripe/stripe-go/pull/986) Add support for iDEAL and SEPA debit on `PaymentMethod`

## 67.0.0 - 2019-11-05
* [#987](https://github.com/stripe/stripe-go/pull/987) Move to the latest API version and add new changes
  * Move to API version `2019-11-05`
  * Add `DefaultSettings` on `SubscritionSchedule`
  * Remove `BillingThresholds`, `CollectionMethod`, `DefaultPaymentMethod` and `DefaultSource` and `invoice_settings` from `SubscriptionSchedule`
  * `OffSession` on `PaymentIntent` is now always a boolean

## 66.3.0 - 2019-11-04
* [#984](https://github.com/stripe/stripe-go/pull/984) Add support for `UseStripeSDK` on `PaymentIntent` create and confirm

## 66.2.0 - 2019-11-04
* [#983](https://github.com/stripe/stripe-go/pull/983) Add support for cloning saved PaymentMethods
* [#980](https://github.com/stripe/stripe-go/pull/980) Improve docs for ephemeral keys

## 66.1.1 - 2019-10-24
* [#978](https://github.com/stripe/stripe-go/pull/978) Properly pass `Type` in `PaymentIntentPaymentMethodOptionsCardInstallmentsPlanParams`
  * Note that this is technically a breaking change, however we've chosen to release it as a patch version as this shipped yesterday and is a new feature
* [#977](https://github.com/stripe/stripe-go/pull/977) Contributor Convenant

## 66.1.0 - 2019-10-23
* [#974](https://github.com/stripe/stripe-go/pull/974) Add support for installments on `PaymentIntent` and `Charge`
* [#975](https://github.com/stripe/stripe-go/pull/975) Add support for `PendingInvoiceItemInterval` on `Subscription`
* [#976](https://github.com/stripe/stripe-go/pull/976) Add `TaxIDTypeMXRFC` constant to `TaxIDType`

## 66.0.0 - 2019-10-18
* [#973](https://github.com/stripe/stripe-go/pull/973) Multiple breaking changes
  * Pin to the latest API version `2019-10-17`
  * Remove `RenewalBehavior` on `SubscriptionSchedule`
  * Remove `RenewalBehavior` and `RenewalInterval` as parameters on `SubscriptionSchedule`

## 65.2.0 - 2019-10-17
* [#972](https://github.com/stripe/stripe-go/pull/972) Various API changes
  * `Requirements` on Issuing `Cardholder`
  * `PaymentMethodDetails.AuBecsDebit.Mandate` on `Charge`
  * `PaymentBehavior` on `Subscription` creation can now take the value `pending_if_incomplete`
  * `PaymentBehavior` on `SubscriptionItem` creation is now supported
  * `SubscriptionData.TrialFromPlan` is now supported on Checkout `Session` creation
  * New values for `TaxIDType`

## 65.1.1 - 2019-10-11
* [#970](https://github.com/stripe/stripe-go/pull/970) Properly deserialize `Fulfilled` on `StatusTransitions` in the `order` package

## 65.1.0 - 2019-10-09
* [#969](https://github.com/stripe/stripe-go/pull/969) Add `DeviceType` filter when listing Terminal `Reader`s

## 65.0.0 - 2019-10-09
* [#951](https://github.com/stripe/stripe-go/pull/951) Move to API version [`2019-10-08`](https://stripe.com/docs/upgrades#2019-10-08) and other changes
  * [#950](https://github.com/stripe/stripe-go/pull/950) Remove lossy "MarshalJSON" implementations
  * [#962](https://github.com/stripe/stripe-go/pull/962) Removed deprecated properties and most todos
    * Removed `GetBalanceTransaction` and `List` from the `balance` package. Prefer using `Get` and `List` in the `balancetransaction` package.
    * Removed `ApplicationFee` from the `charge` and `paymentintent` packages. Prefer using `ApplicationFeeAmount`.
    * Removed `TaxInfo` and related fields from the `customer` packager. Prefer using the `customertaxid` package.
    * Removed unsupported `Customer` parameter on `PaymentMethodParams` and `PaymentMethodDetachParams` in the `paymentmethod` package.
    * Removed `Billing` properties in the `invoice`, `sub` and `subschedule` packages. Prefer using `CollectionMethod`.
    * Removed the `InvoiceBilling` type from the `invoice` package. Prefer using `InvoiceCollectionMethod`.
    * Removed the `SubscriptionBilling` type from the `sub` package. Prefer using `SubscriptionCollectionMethod`.
    * Removed deprecated constants for `PaymentIntentConfirmationMethod` in `paymentintent` package.
    * Removed `OperatorAccount` from Terminal APIs.
  * [#960](https://github.com/stripe/stripe-go/pull/960) Remove `issuerfraudrecord` package. Prefer using `earlyfraudwarning`
  * [#968](https://github.com/stripe/stripe-go/pull/968) Rename `AccountOpener` to `Representative` and update to latest API version

## 64.1.0 - 2019-10-09
* [#967](https://github.com/stripe/stripe-go/pull/967) Add `Get` method to `OrderReturn`

## 64.0.0 - 2019-10-08
* ~[#968](https://github.com/stripe/stripe-go/pull/968) Update to latest API version [`2019-10-08`](https://stripe.com/docs/upgrades#2019-10-08)~
  * **Note:** This release is actually a no-op as we failed to merge the changes. Please use 65.0.0 instead.

## 63.5.0 - 2019-10-03
* [#955](https://github.com/stripe/stripe-go/pull/955) Add FPX `PaymentMethod` Support
* [#966](https://github.com/stripe/stripe-go/pull/966) Add the `Account` field to `BankAccount`

## 63.4.0 - 2019-09-30
* [#952](https://github.com/stripe/stripe-go/pull/952) Add AU BECS Debit Support

## 63.3.0 - 2019-09-30
* [#964](https://github.com/stripe/stripe-go/pull/964) Add support for `Status` and `Location` filters when listing `Reader`s

## 63.2.2 - 2019-09-26
* [#963](https://github.com/stripe/stripe-go/pull/963) Update `SourceSourceOrder` `Items` field to fix unmarshalling errors

## 63.2.1 - 2019-09-25
* [#961](https://github.com/stripe/stripe-go/pull/961) Properly tag `Customer` as deprecated in `PaymentMethodDetachParams`

## 63.2.0 - 2019-09-25
* [#959](https://github.com/stripe/stripe-go/pull/959) Mark `Customer` on `PaymentMethodDetachParams` as deprecated
* [#957](https://github.com/stripe/stripe-go/pull/957) Add missing error code

## 63.1.1 - 2019-09-23
* [#954](https://github.com/stripe/stripe-go/pull/954) Add support for `Stripe-Should-Retry` header

## 63.1.0 - 2019-09-13
* [#949](https://github.com/stripe/stripe-go/pull/949) Add support for `DeclineCode` on `Error` top-level

## 63.0.0 - 2019-09-10
* [#947](https://github.com/stripe/stripe-go/pull/947) Bump API version to [`2019-09-09`](https://stripe.com/docs/upgrades#2019-09-09)

## 62.10.0 - 2019-09-09
* [#945](https://github.com/stripe/stripe-go/pull/945) Changes to `Account` and `Person` to represent identity verification state

## 62.9.0 - 2019-09-04
* [#943](https://github.com/stripe/stripe-go/pull/943) Add support for `Authentication` and `URL` on Issuing `Authorization`

## 62.8.2 - 2019-08-29
* [#939](https://github.com/stripe/stripe-go/pull/939) Also log error in case of non-`stripe.Error`

## 62.8.1 - 2019-08-29
* [#938](https://github.com/stripe/stripe-go/pull/938) Rearrange error logging so that 402 doesn't log an error

## 62.8.0 - 2019-08-29
* [#937](https://github.com/stripe/stripe-go/pull/937) Add support for `EndBehavior` on `SubscriptionSchedule`

## 62.7.0 - 2019-08-27
* [#935](https://github.com/stripe/stripe-go/pull/935) Retry requests on a 429 that's a lock timeout

## 62.6.0 - 2019-08-26
* [#934](https://github.com/stripe/stripe-go/pull/934) Add support for `SubscriptionBillingCycleAnchorNow` and `SubscriptionBillingCycleAnchorUnchanged` on `Invoice`
* [#933](https://github.com/stripe/stripe-go/pull/933) Add `PendingVerification` on `Account`, `Person` and `Capability`

## 62.5.0 - 2019-08-23
* [#930](https://github.com/stripe/stripe-go/pull/930) Add `FailureReason` to `Refund`

## 62.4.0 - 2019-08-22
* [#926](https://github.com/stripe/stripe-go/pull/926) Add support for decimal amounts on Billing resources

## 62.3.0 - 2019-08-22
* [#928](https://github.com/stripe/stripe-go/pull/928) Bring retry code in-line with current best practices

## 62.2.0 - 2019-08-21
* [#922](https://github.com/stripe/stripe-go/pull/922) A few Billing changes
  * Add `Schedule` to `Subscription`
  * Add missing parameters for the Upcoming Invoice API: `Schedule`, `SubscriptionCancelAt`, `SubscriptionCancelNow`
  * Add missing properties and parameters for a `SubscriptionSchedule` phase: `BillingThresholds`, `CollectionMethod`, `DefaultPaymentMethod`, `InvoiceSettings`
* [#923](https://github.com/stripe/stripe-go/pull/923) Add support for `Mode` on Checkout `Session`

## 62.1.2 - 2019-08-19
* [#921](https://github.com/stripe/stripe-go/pull/921) Mark `Customer` as an invalid parameter on PaymentMethod creation

## 62.1.1 - 2019-08-15
* [#918](https://github.com/stripe/stripe-go/pull/918) Fix `RadarEarlyFraudWarnings` to use the proper API endpoint

## 62.1.0 - 2019-08-15
* [#916](https://github.com/stripe/stripe-go/pull/916)
  * Add support for `PIN` on Issuing `Card` to reflect the status of a card's PIN
  * Add support for `Executive` on Person create, update and list

## 62.0.0 - 2019-08-14
* [#915](https://github.com/stripe/stripe-go/pull/915) Move to API version [`2019-08-14`](https://stripe.com/docs/upgrades#2019-08-14) and other changes
  * Pin to API version `2019-08-14`
  * Rename `AccountCapabilityPlatformPayments` to `AccountCapabilityTransfers`
  * Add `Executive` in `PersonRelationship`
  * Remove `PayentMethodOptions` as there was a typo which was fixed
  * Make `OffSession` only support booleans on `PaymentIntent`
  * Remove `PaymentIntentLastPaymentError` and use `Error` instead
  * Move `DeclineCode` on `Error` to the `DeclineCode` type instead of `string`
* [#914](https://github.com/stripe/stripe-go/pull/914) Update webhook handler example to use `http.MaxBytesReader`

## 61.27.0 - 2019-08-09
* [#913](https://github.com/stripe/stripe-go/pull/913) Remove `SubscriptionScheduleRevision`
  * Note that this is technically a breaking change, however we've chosen to release it as a minor version in light of the fact that this resource and its API methods were virtually unused.

## 61.26.0 - 2019-08-08
* [#911](https://github.com/stripe/stripe-go/pull/911)
  * Add support for `PaymentMethodDetails.Card.Moto` on `Charge`
  * Add support `StatementDescriptorSuffix` on `Charge` and `PaymentIntent`
  * Add support `SubscriptionData.ApplicationFeePercent` on Checkout `Session`

## 61.25.0 - 2019-07-30
* [#910](https://github.com/stripe/stripe-go/pull/910) Add `balancetransaction` package with a `Get` and `List` methods

## 61.24.0 - 2019-07-30
* [#906](https://github.com/stripe/stripe-go/pull/906) Add decline code type and constants (for use with card errors)

## 61.23.0 - 2019-07-29
* [#879](https://github.com/stripe/stripe-go/pull/879) Add support for OAuth API endpoints

## 61.22.0 - 2019-07-29
* [#909](https://github.com/stripe/stripe-go/pull/909) Rename `PayentMethodOptions` to `PaymentMethodOptions` on `PaymentIntent` and `SetupIntent`. Keep the old name until the next major version for backwards-compatibility

## 61.21.0 - 2019-07-26
* [#904](https://github.com/stripe/stripe-go/pull/904) Add support for Klarna and source orders

## 61.20.0 - 2019-07-25
* [#897](https://github.com/stripe/stripe-go/pull/897) Add all missing error codes
* [#903](https://github.com/stripe/stripe-go/pull/903) Disable HTTP/2 by default (until underlying bug in Go's implementation is fixed)
* [#905](https://github.com/stripe/stripe-go/pull/905) Add missing `Authenticated` field for 3DS charges

## 61.19.0 - 2019-07-22
* [#902](https://github.com/stripe/stripe-go/pull/902) Add support for `StatementDescriptor` when capturing a `PaymentIntent`

## 61.18.0 - 2019-07-19
* [#898](https://github.com/stripe/stripe-go/pull/898) Add `Customer` filter when listing `CreditNote`
* [#899](https://github.com/stripe/stripe-go/pull/899) Add `OffSession` parameter when updating `SubscriptionItem`

## 61.17.0 - 2019-07-17
* [#895](https://github.com/stripe/stripe-go/pull/895) Add `VoidedAt` on `CreditNote`

## 61.16.0 - 2019-07-16
* [#894](https://github.com/stripe/stripe-go/pull/894) Introduce encoding for high precision decimal fields

## 61.15.0 - 2019-07-15
* [#893](https://github.com/stripe/stripe-go/pull/893)
  * Add support for `PaymentMethodOptions` on `PaymentIntent` and `SetupIntent`
  * Add missing parameters to `PaymentIntentConfirmParams`

## 61.14.0 - 2019-07-15
* [#891](https://github.com/stripe/stripe-go/pull/891) Various changes relaed to SCA for Billing
  * Add support for `PendingSetupIntent` on `Subscription`
  * Add support for `PaymentBehavior` on `Subscription` creation and update
  * Add support for `PaymentBehavior` on `SubscriptionItem` update
  * Add support for `OffSession` when paying an `Invoice`
  * Add support for `OffSession` on `Subscription` creation and update

## 61.13.0 - 2019-07-05
* [#888](https://github.com/stripe/stripe-go/pull/888) Add support for `SetupFutureUsage` on `PaymentIntent` update and confirm
* [#890](https://github.com/stripe/stripe-go/pull/890) Add support for `SetupFutureUsage` on Checkout `Session`

## 61.12.0 - 2019-07-01
* [#887](https://github.com/stripe/stripe-go/pull/887) Allow `OffSession` to be a bool on `PaymentIntent` creation and confirmation

## 61.11.0 - 2019-07-01
* [#886](https://github.com/stripe/stripe-go/pull/886) Add `CardVerificationUnavailable` constant value

## 61.10.0 - 2019-07-01
* [#884](https://github.com/stripe/stripe-go/pull/884) Add support for the `SetupIntent` resource and APIs
* [#885](https://github.com/stripe/stripe-go/pull/885) Quick fix to the `NextAction` property on `SetupIntent`

## 61.9.0 - 2019-06-27
* [#882](https://github.com/stripe/stripe-go/pull/882) Add `DefaultPaymentMethod` and `DefaultSource` to `SubscriptionSchedule`

## 61.8.0 - 2019-06-27
* **Note:** This release was deleted after we merged some bad code. Please use 61.9.0 instead.

## 61.7.1 - 2019-06-25
* [#881](https://github.com/stripe/stripe-go/pull/881) Documentation fixes

## 61.7.0 - 2019-06-25
* [#880](https://github.com/stripe/stripe-go/pull/880)
  * Add support for `CollectionMethod` on `Invoice`, `Subscription` and `SubscriptionSchedule`
  * Add support for `UnifiedProration` on `InvoiceLine`

## 61.6.0 - 2019-06-24
* [#878](https://github.com/stripe/stripe-go/pull/878) Enable request latency telemetry by default

## 61.5.0 - 2019-06-20
* [#877](https://github.com/stripe/stripe-go/pull/877) Add `CancellationReason` to `PaymentIntent`

## 61.4.0 - 2019-06-18
* [#845](https://github.com/stripe/stripe-go/pull/845) Add support for `CustomerBalanceTransaction` resource and APIs
* [#875](https://github.com/stripe/stripe-go/pull/875) Add missing `Account` settings

## 61.3.0 - 2019-06-18
* [#874](https://github.com/stripe/stripe-go/pull/874) Log only to info on 402 errors from Stripe

## 61.2.0 - 2019-06-14
* [#870](https://github.com/stripe/stripe-go/pull/870) Add support for `MerchantAmount` `MerchantCurrency` to Issuing `Transaction`
* [#871](https://github.com/stripe/stripe-go/pull/871) Add support for `SubmitType` to Checkout `Session`

## 61.1.0 - 2019-06-06
* [#867](https://github.com/stripe/stripe-go/pull/867) Add support for `Location` on Terminal `ConnectionToken`
* [#868](https://github.com/stripe/stripe-go/pull/868) Add support for `Balance` and deprecate `AccountBalance` on Customer

## 61.0.1 - 2019-05-24
* [#865](https://github.com/stripe/stripe-go/pull/865) Fix `earlyfraudwarning` client

## 61.0.0 - 2019-05-24
* [#864](https://github.com/stripe/stripe-go/pull/864) Pin library to API version `2019-05-16`

## 60.19.0 - 2019-05-24
* [#862](https://github.com/stripe/stripe-go/pull/862) Add support for `radar.early_fraud_warning` resource

## 60.18.0 - 2019-05-22
* [#861](https://github.com/stripe/stripe-go/pull/861) Add new tax ID types: `TaxIDTypeINGST` and `TaxIDTypeNOVAT`

## 60.17.0 - 2019-05-16
* [#860](https://github.com/stripe/stripe-go/pull/860) Add `OffSession` parameter to payment intents

## 60.16.0 - 2019-05-14
* [#859](https://github.com/stripe/stripe-go/pull/859) Add missing `InvoiceSettings` to `Customer`

## 60.15.0 - 2019-05-14
* [#855](https://github.com/stripe/stripe-go/pull/855) Add support for the capability resource and APIs

## 60.14.0 - 2019-05-10
* [#858](https://github.com/stripe/stripe-go/pull/858) Add `StartDate` to `Subscription`

## 60.13.2 - 2019-05-10
* [#857](https://github.com/stripe/stripe-go/pull/857) Fix invoice's `PaymentIntent` so its JSON tag uses API snakecase

## 60.13.1 - 2019-05-08
* [#853](https://github.com/stripe/stripe-go/pull/853) Add paymentmethod package to the clients list

## 60.13.0 - 2019-05-07
* [#850](https://github.com/stripe/stripe-go/pull/850) `OperatorAccount` is now deprecated across all Terminal endpoints
* [#851](https://github.com/stripe/stripe-go/pull/851) Add `Customer` on the `Source` object

## 60.12.2 - 2019-05-06
* [#843](https://github.com/stripe/stripe-go/pull/843) Lock mutex while in `SetBackends`

## 60.12.1 - 2019-05-06
* [#848](https://github.com/stripe/stripe-go/pull/848) Fix `Items` on `CheckoutSessionSubscriptionDataParams` to be a slice

## 60.12.0 - 2019-05-05
* [#846](https://github.com/stripe/stripe-go/pull/846) Add support for the `PaymentIntent` filter on `ChargeListParams`

## 60.11.0 - 2019-05-02
* [#841](https://github.com/stripe/stripe-go/pull/841) Add support for the `Customer` filter on `PaymentIntentListParams`
* [#842](https://github.com/stripe/stripe-go/pull/842) Add support for replacing another Issuing `Card` on creation

## 60.10.0 - 2019-04-30
* [#839](https://github.com/stripe/stripe-go/pull/839) Add support for ACSS Debit in `PaymentMethodDetails` on `Charge`
* [#840](https://github.com/stripe/stripe-go/pull/840) Add support for `FileLinkData` on `File` creation

## 60.9.0 - 2019-04-24
* [#828](https://github.com/stripe/stripe-go/pull/828) Add support for the `TaxRate` resource and APIs

## 60.8.0 - 2019-04-23
* [#834](https://github.com/stripe/stripe-go/pull/834) Add support for the `TaxId` resource and APIs

## 60.7.0 - 2019-04-18
* [#823](https://github.com/stripe/stripe-go/pull/823) Add support for the `CreditNote` resource and APIs
* [#829](https://github.com/stripe/stripe-go/pull/829) Add support for `Address`, `Name`, `Phone` and `PreferredLocales` on `Customer` and related fields on `Invoice`

## 60.6.0 - 2019-04-18
* [#837](https://github.com/stripe/stripe-go/pull/837) Add helpers to go from `[]T` to `[]*T` for `string`, `int64`, `float64`, `bool`

## 60.5.1 - 2019-04-16
* [#836](https://github.com/stripe/stripe-go/pull/836) Fix `SpendingLimits` on `AuthorizationControlsParams` and `AuthorizationControls` to be a slice on Issuing `Card` and `Cardholder`

## 60.5.0 - 2019-04-16
* [#740](https://github.com/stripe/stripe-go/pull/740) Add support for the Checkout `Session` resource and APIs
* [#832](https://github.com/stripe/stripe-go/pull/832) Add support for `version` and `succeeded` properties in the `payment_method_details[card][three_d_secure]` hash for `Charge`.
* [#835](https://github.com/stripe/stripe-go/pull/835) Add support for passing `payment_method` on `Customer` creation

## 60.4.0 - 2019-04-15
* [#833](https://github.com/stripe/stripe-go/pull/833) Add more context when failing to unmarshal JSON

## 60.3.0 - 2019-04-12
* [#831](https://github.com/stripe/stripe-go/pull/831) Add support for `authorization_controls` on `Cardholder` and `authorization_controls[spending_limits]` added to `Card` too for Issuing resources

## 60.2.0 - 2019-04-09
* [#827](https://github.com/stripe/stripe-go/pull/827) Add support for `confirmation_method` on `PaymentIntent` creation

## 60.1.0 - 2019-04-09
* [#824](https://github.com/stripe/stripe-go/pull/824) Add support for `PaymentIntent` and `PaymentMethod` on `Customer`, `Subscription` and `Invoice`.

## 60.0.1 - 2019-04-02
* [#825](https://github.com/stripe/stripe-go/pull/825) Fix the API for usage record summary listing

## 60.0.0 - 2019-03-27
* [#820](https://github.com/stripe/stripe-go/pull/820) Add various missing parameters
    * On `PIIParams` the previous `PersonalIDNumber` is fixed to `IDNumber` which we're releasing as a minor breaking change even though the old version probably didn't work correctly

## 59.1.0 - 2019-03-22
* [#819](https://github.com/stripe/stripe-go/pull/819) Add default level prefixes in messages from `LeveledLogger`

## 59.0.0 - 2019-03-22
* [#818](https://github.com/stripe/stripe-go/pull/818) Implement leveled logging (very minor breaking change -- only a couple properties were removed from the internal `BackendImplementation`)

## 58.1.0 - 2019-03-19
* [#815](https://github.com/stripe/stripe-go/pull/815) Add support for passing token on account or person creation

## 58.0.0 - 2019-03-19
* [#811](https://github.com/stripe/stripe-go/pull/811) Add support for API version 2019-03-14
* [#814](https://github.com/stripe/stripe-go/pull/814) Properly override API version if it's set in the request

## 57.8.0 - 2019-03-18
* [#806](https://github.com/stripe/stripe-go/pull/806) Add support for the `PaymentMethod` resource and APIs
* [#812](https://github.com/stripe/stripe-go/pull/812) Add support for deleting a Terminal `Location` and `Reader`

## 57.7.0 - 2019-03-13
* [#810](https://github.com/stripe/stripe-go/pull/810) Add support for `columns` on `ReportRun` and `default_columns` on `ReportType`.

## 57.6.0 - 2019-03-06
* [#808](https://github.com/stripe/stripe-go/pull/808) Add support for `backdate_start_date` and `cancel_at` on `Subscription`.

## 57.5.0 - 2019-03-05
* [#807](https://github.com/stripe/stripe-go/pull/807) Add support for `current_period_end` and `current_period_start` filters when listing `Invoice`.

## 57.4.0 - 2019-03-04
* [#798](https://github.com/stripe/stripe-go/pull/798) Properly support serialization of `Event`.

## 57.3.0 - 2019-02-28
* [#803](https://github.com/stripe/stripe-go/pull/803) Add support for `api_version` on `WebhookEndpoint`.

## 57.2.0 - 2019-02-27
* [#795](https://github.com/stripe/stripe-go/pull/795) Add support for `created` and `status_transitions` on `Invoice`
* [#802](https://github.com/stripe/stripe-go/pull/802) Add support for `latest_invoice` on `Subscription`

## 57.1.1 - 2019-02-26
* [#800](https://github.com/stripe/stripe-go/pull/800) Add `UsageRecordSummaries` to the list of clients.

## 57.1.0 - 2019-02-22
* [#796](https://github.com/stripe/stripe-go/pull/796) Correct `InvoiceItems` in `InvoiceParams` to be a slice of structs instead of a struct (this is technically a breaking change, but the previous implementation was non-functional, so we're releasing it as a minor version)

## 57.0.1 - 2019-02-20
* [#794](https://github.com/stripe/stripe-go/pull/794) Properly pin to API version `2019-02-19`. The previous major version incorrectly stayed on API version `2019-02-11` which prevented requests to manage Connected accounts from working and charges to have the new statement descriptor behavior.

## 57.0.0 - 2019-02-19
**Important:** This version is non-functional and has been yanked in favor of 57.0.1.
* [#782](https://github.com/stripe/stripe-go/pull/782) Changes related to the new API version `2019-02-19`:
  * The library is now pinned to API version `2019-02-19`
  * Numerous changes to the `Account` resource and APIs:
    * The `legal_entity` property on the Account API resource has been replaced with `individual`, `company`, and `business_type`
    * The `verification` hash has been replaced with a `requirements` hash
    * Multiple top-level properties were moved to the `settings` hash
    * The `keys` property on `Account` has been removed. Platforms should authenticate as their connected accounts with their own key via the `Stripe-Account` [header](https://stripe.com/docs/connect/authentication#authentication-via-the-stripe-account-header)
  * The `requested_capabilities` property on `Account` creation is now required for accounts in the US
  * The deprecated parameter `save_source_to_customer` on `PaymentIntent` has now been removed. Use `save_payment_method` instead

## 56.1.0 - 2019-02-18
* [#737](https://github.com/stripe/stripe-go/pull/737) Add support for setting `request_capabilities` and retrieving `capabilities` on `Account`
* [#793](https://github.com/stripe/stripe-go/pull/793) Add support for `save_payment_method` on `PaymentIntent`

## 56.0.0 - 2019-02-13
* [#785](https://github.com/stripe/stripe-go/pull/785) Changes to the Payment Intent APIs for the next API version
* [#789](https://github.com/stripe/stripe-go/pull/789) Allow API arrays to be emptied by setting an empty array

## 55.15.0 - 2019-02-12
* [#764](https://github.com/stripe/stripe-go/pull/764) Add support for `transfer_data[destination]` on `Invoice` and `Subscription`
* [#784](https://github.com/stripe/stripe-go/pull/784)
    * Add support for `SubscriptionSchedule` and `SubscriptionScheduleRevision`
    * Add support for `payment_method_types` on `PaymentIntent`
* [#787](https://github.com/stripe/stripe-go/pull/787) Add support for `transfer_data[amount]` on `Charge`

## 55.14.0 - 2019-01-25
* [#765](https://github.com/stripe/stripe-go/pull/765) Add support for `destination_payment_refund` and `source_refund` on the `Reversal` resource

## 55.13.0 - 2019-01-17
* [#779](https://github.com/stripe/stripe-go/pull/779) Add support for `receipt_url` on `Charge`

## 55.12.0 - 2019-01-17
* [#766](https://github.com/stripe/stripe-go/pull/766) Add optional support for sending request telemetry to Stripe

## 55.11.0 - 2019-01-17
* [#776](https://github.com/stripe/stripe-go/pull/776) Add support for billing thresholds

## 55.10.0 - 2019-01-16
* [#773](https://github.com/stripe/stripe-go/pull/773) Add support for `custom_fields` and `footer` on `Invoice`
* [#774](https://github.com/stripe/stripe-go/pull/774) Revert Go module support

## 55.9.0 - 2019-01-15
* [#769](https://github.com/stripe/stripe-go/pull/769) Add field `Amount` to `IssuingTransaction`

## 55.8.0 - 2019-01-09
* [#763](https://github.com/stripe/stripe-go/pull/763) Add `application_fee_amount` to `Charge` and on charge create and capture params

## 55.7.0 - 2019-01-09
* [#738](https://github.com/stripe/stripe-go/pull/738) Add support for the account link resource

## 55.6.0 - 2019-01-09
* [#762](https://github.com/stripe/stripe-go/pull/762) Add support for new invoice items parameters when retrieving an upcoming invoice

## 55.5.0 - 2019-01-07
* [#744](https://github.com/stripe/stripe-go/pull/744) Add support for `transfer_data[destination]` on Charge struct and params
* [#746](https://github.com/stripe/stripe-go/pull/746) Add support for `wallet_provider` on the Issuing Authorization

## 55.4.0 - 2019-01-07
* [#745](https://github.com/stripe/stripe-go/pull/745) Add support for `pending` parameter when listing invoice items

## 55.3.0 - 2019-01-02
* [#742](https://github.com/stripe/stripe-go/pull/742) Add field `FraudType` to `IssuerFraudRecord`

## 55.2.0 - 2018-12-31
* [#741](https://github.com/stripe/stripe-go/pull/741) Add missing parameters `InvoiceNow` and `Prorate` for subscription cancellation

## 55.1.0 - 2018-12-27
* [#743](https://github.com/stripe/stripe-go/pull/743) Add support for `clear_usage` on `SubscriptionItem` deletion

## 55.0.0 - 2018-12-13
* [#739](https://github.com/stripe/stripe-go/pull/739) Use `ApplicationFee` struct for `FeeRefund.Fee` (minor breaking change)

## 54.2.0 - 2018-11-30
* [#734](https://github.com/stripe/stripe-go/pull/734) Put `/v1/` prefix as part of all paths instead of URL

## 54.1.1 - 2018-11-30
* [#733](https://github.com/stripe/stripe-go/pull/733) Fix malformed URL generated for the uploads API when using `NewBackends`

## 54.1.0 - 2018-11-28
* [#730](https://github.com/stripe/stripe-go/pull/730) Add support for the Review resource
* [#731](https://github.com/stripe/stripe-go/pull/731) Add missing properties on the Refund resource

## 54.0.0 - 2018-11-27
* [#721](https://github.com/stripe/stripe-go/pull/721) Add support for `RadarValueList` and `RadarValueListItem`
* [#721](https://github.com/stripe/stripe-go/pull/721) Remove `Closed` and `Forgiven` from `InvoiceParams`
* [#721](https://github.com/stripe/stripe-go/pull/721) Add `PaidOutOfBand` to `InvoicePayParams`

## 53.4.0 - 2018-11-26
* [#728](https://github.com/stripe/stripe-go/pull/728) Add `IssuingCard` to `EphemeralKeyParams`

## 53.3.0 - 2018-11-26
* [#727](https://github.com/stripe/stripe-go/pull/727) Add support for `TransferData` on payment intent create and update

## 53.2.0 - 2018-11-21
* [#725](https://github.com/stripe/stripe-go/pull/725) Improved error deserialization

## 53.1.0 - 2018-11-15
* [#723](https://github.com/stripe/stripe-go/pull/723) Add support for `last_payment_error` on `PaymentIntent`.
* [#724](https://github.com/stripe/stripe-go/pull/724) Add support for `transfer_data[destination]` on `PaymentIntent`.

## 53.0.1 - 2018-11-12
* [#714](https://github.com/stripe/stripe-go/pull/714) Fix bug in retry logic that would cause the client to panic

## 53.0.0 - 2018-11-08
* [#716](https://github.com/stripe/stripe-go/pull/716) Drop support for Go 1.8.
* [#715](https://github.com/stripe/stripe-go/pull/715) Ship changes to the `PaymentIntent` resource to match the final layout.
* [#717](https://github.com/stripe/stripe-go/pull/717) Add support for `flat_amount` on `Plan` tiers.
* [#718](https://github.com/stripe/stripe-go/pull/718) Add support for `supported_transfer_countries` on `CountrySpec`.
* [#720](https://github.com/stripe/stripe-go/pull/720) Add support for `review` on `PaymentIntent`.
* [#707](https://github.com/stripe/stripe-go/pull/707) Add new invoice methods and fixes to the Issuing Cardholder resource (multiple breaking changes)
    * Move to API version 2018-11-08.
    * Add support for new API methods, properties and parameters for `Invoice`.
    * Add support for `default_source` on `Subscription` and `Invoice`.

## 52.1.0 - 2018-10-31
* [#705](https://github.com/stripe/stripe-go/pull/705) Add support for the `Person` resource
* [#706](https://github.com/stripe/stripe-go/pull/706) Add support for the `WebhookEndpoint` resource

## 52.0.0 - 2018-10-29
* [#711](https://github.com/stripe/stripe-go/pull/711) Set `Request.GetBody` when making requests
* [#711](https://github.com/stripe/stripe-go/pull/711) Drop support for Go 1.7 (hasn't been supported by Go core since the release of Go 1.9 in August 2017)

## 51.4.0 - 2018-10-19
* [#708](https://github.com/stripe/stripe-go/pull/708) Add Stripe Terminal endpoints to master to `client.API`

## 51.3.0 - 2018-10-09
* [#704](https://github.com/stripe/stripe-go/pull/704) Add support for `subscription_cancel_at_period_end` on the Upcoming Invoice API.

## 51.2.0 - 2018-10-09
* [#702](https://github.com/stripe/stripe-go/pull/702) Add support for `delivery_success` filter when listing Events.

## 51.1.0 - 2018-10-03
* [#700](https://github.com/stripe/stripe-go/pull/700) Add support for `on_behalf_of` on Subscription and Charge resources.

## 51.0.0 - 2018-09-27
* [#698](https://github.com/stripe/stripe-go/pull/698) Move to API version 2018-09-24
    * Rename `FileUpload` to `File` (and all `FileUpload*` structs to `File*`)
	* Fix file links client

## 50.0.0 - 2018-09-24
* [#695](https://github.com/stripe/stripe-go/pull/695) Rename `Transaction` to `DisputedTransaction` in `IssuingDisputeParams` (minor breaking change)
* [#695](https://github.com/stripe/stripe-go/pull/695) Add support for Stripe Terminal

## 49.2.0 - 2018-09-24
* [#697](https://github.com/stripe/stripe-go/pull/697) Fix `number` JSON tag on the `IssuingCardDetails` resource.

## 49.1.0 - 2018-09-11
* [#694](https://github.com/stripe/stripe-go/pull/694) Add `ErrorCodeResourceMissing` error code constant

## 49.0.0 - 2018-09-11
* [#693](https://github.com/stripe/stripe-go/pull/693) Change `Product` under `Plan` from a string to a full `Product` struct pointer (this is a minor breaking change -- upgrade by changing to `plan.Product.ID`)

## 48.3.0 - 2018-09-06
* [#691](https://github.com/stripe/stripe-go/pull/691) Add `InvoicePrefix` to `Customer` and `CustomerParams`

## 48.2.0 - 2018-09-05
* [#690](https://github.com/stripe/stripe-go/pull/690) Add support for reporting resources

## 48.1.0 - 2018-09-05
* [#683](https://github.com/stripe/stripe-go/pull/683) Add `StatusTransitions` filter parameters to `OrderListParams`

## 48.0.0 - 2018-09-05
* [#681](https://github.com/stripe/stripe-go/pull/681) Handle deserialization of `OrderItem` parent into an object if expanded (minor breaking change)

## 47.0.0 - 2018-09-04
* New major version for better compatibility with Go's new module system (no breaking changes)

## 46.1.0 - 2018-09-04
* [#688](https://github.com/stripe/stripe-go/pull/688) Encode `Params` in `AppendToAsSourceOrExternalAccount` (bug fix)
* [#689](https://github.com/stripe/stripe-go/pull/689) Add `go.mod` for the new module system

## 46.0.0 - 2018-09-04
* [#686](https://github.com/stripe/stripe-go/pull/686) Add `Mandate` and `Receiver` to `SourceObjectParams` and change `Date` on `SourceMandateAcceptance` to `int64` (minor breaking change)

## 45.0.0 - 2018-08-30
* [#680](https://github.com/stripe/stripe-go/pull/680) Change `SubscriptionTaxPercent` on `Invoice` from `int64` to `float64` (minor breaking change)

## 44.0.0 - 2018-08-28
* [#678](https://github.com/stripe/stripe-go/pull/678) Allow payment intent capture to take its own parameters

## 43.1.1 - 2018-08-28
* [#675](https://github.com/stripe/stripe-go/pull/675) Fix incorrectly encoded parameter in `UsageRecordSummaryListParams`

## 43.1.0 - 2018-08-28
* [#669](https://github.com/stripe/stripe-go/pull/669) Add `AuthorizationCode` to `Charge`
* [#671](https://github.com/stripe/stripe-go/pull/671) Fix deserialization of `TaxID` on `CustomerTaxInfo`

## 43.0.0 - 2018-08-23
* [#668](https://github.com/stripe/stripe-go/pull/668) Move to API version 2018-08-23
    * Add `TaxInfo` and `TaxInfoVerification` to `Customer`
	* Rename `Amount` to `UnitAmount` on `PlanTierParams`
	* Remove `BusinessVATID` from `Customer`
	* Remove `AtPeriodEnd` from `SubscriptionCancelParams`

## 42.3.0 - 2018-08-23
* [#667](https://github.com/stripe/stripe-go/pull/667) Add `Forgive` to `InvoicePayParams`

## 42.2.0 - 2018-08-22
* [#666](https://github.com/stripe/stripe-go/pull/666) Add `Subscription` to `SubscriptionItem`

## 42.1.0 - 2018-08-22
* [#664](https://github.com/stripe/stripe-go/pull/664) Add `AvailablePayoutMethods` to `Card`

## 42.0.0 - 2018-08-20
* [#663](https://github.com/stripe/stripe-go/pull/663) Add support for usage record summaries and rename `Live` on `IssuerFraudRecord, `SourceTransaction`, and `UsageRecord` to `Livemode` (a minor breaking change)

## 41.0.0 - 2018-08-17
* [#659](https://github.com/stripe/stripe-go/pull/659) Remove mutating Bitcoin receiver API calls (these were no longer functional anyway)
* [#661](https://github.com/stripe/stripe-go/pull/661) Correct `IssuingCardShipping`'s type to `int64`
* [#662](https://github.com/stripe/stripe-go/pull/662) Rename `IssuingCardShipping`'s `Eta` to `ETA`

## 40.2.0 - 2018-08-15
* [#657](https://github.com/stripe/stripe-go/pull/657) Use integer-indexed encoding for all arrays

## 40.1.0 - 2018-08-10
* [#656](https://github.com/stripe/stripe-go/pull/656) Expose new `ValidatePayload` functions for validating incoming payloads without constructing an event

## 40.0.2 - 2018-08-07
* [#652](https://github.com/stripe/stripe-go/pull/652) Change the type of `FileUpload.Links` to `FileLinkList` (this is a bug fix given that the previous type would never have worked)

## 40.0.1 - 2018-08-07
* [#653](https://github.com/stripe/stripe-go/pull/653) All `BackendImplementation`s should sleep by default on retries

## 40.0.0 - 2018-08-06
* [#648](https://github.com/stripe/stripe-go/pull/648) Introduce buffers so a request's body can be read multiple times (this modifies the interface of a few exported internal functions so it's technically breaking, but it will probably not be breaking for most users)
* [#649](https://github.com/stripe/stripe-go/pull/649) Rename `BackendConfiguration` to `BackendImplementation` (likewise, technically breaking, but minor)
* [#650](https://github.com/stripe/stripe-go/pull/650) Export `webhook.ComputeSignature`

## 39.0.0 - 2018-08-04
* [#646](https://github.com/stripe/stripe-go/pull/646) Set request body before every retry (this modifies the interface of a few exported internal functions so it's technically breaking, but it will probably not be breaking for most users)

## 38.2.0 - 2018-08-03
* [#644](https://github.com/stripe/stripe-go/pull/644) Add support for file links
* [#645](https://github.com/stripe/stripe-go/pull/645) Add support for `Cancel` to topups

## 38.1.0 - 2018-08-01
* [#643](https://github.com/stripe/stripe-go/pull/643) Bug fix and various code/logging improvements to retry code

## 38.0.0 - 2018-07-30
* [#641](https://github.com/stripe/stripe-go/pull/641) Minor breaking changes to correct a few naming inconsistencies:
    * `IdentityVerificationDetailsCodeScanIdCountryNotSupported` becomes `IdentityVerificationDetailsCodeScanIDCountryNotSupported`
    * `IdentityVerificationDetailsCodeScanIdTypeNotSupported` becomes `IdentityVerificationDetailsCodeScanIDTypeNotSupported`
    * `BitcoinUri` on `BitcoinReceiver` becomes `BitcoinURI`
    * `NetworkId` on `IssuingAuthorization` becomes `NetworkID`

## 37.0.0 - 2018-07-30
* [#637](https://github.com/stripe/stripe-go/pull/637) Add support for Sigma scheduled query runs
* [#639](https://github.com/stripe/stripe-go/pull/639) Move to API version `2018-07-27` (breaking)
    * Remove `SKUs` from `Product`
    * Subscription creation and update can no longer take a source
    * Change `PercentOff` on coupon struct and params from integer to float
* [#640](https://github.com/stripe/stripe-go/pull/640) Add missing field `Created` to `Account`

## 36.3.0 - 2018-07-27
* [#636](https://github.com/stripe/stripe-go/pull/636) Add `RiskScore` to `ChargeOutcome`

## 36.2.0 - 2018-07-26
* [#635](https://github.com/stripe/stripe-go/pull/635) Add support for Stripe Issuing

## 36.1.2 - 2018-07-24
* [#633](https://github.com/stripe/stripe-go/pull/633) Fix encoding of list params for bank accounts and cards

## 36.1.1 - 2018-07-17
* [#627](https://github.com/stripe/stripe-go/pull/627) Wire an `http.Client` from `NewBackends` through to backends

## 36.1.0 - 2018-07-11
* [#624](https://github.com/stripe/stripe-go/pull/624) Add `AutoAdvance` for `Invoice`

## 36.0.0 - 2018-07-09
* [#606](https://github.com/stripe/stripe-go/pull/606) Add support for payment intents
* [#623](https://github.com/stripe/stripe-go/pull/623) Changed `Payout.Destination` from `string` to `*PayoutDestination` to support expanding (minor breaking change)

## 35.13.0 - 2018-07-06
* [#622](https://github.com/stripe/stripe-go/pull/622) Correct position of `DeclineChargeOn` (it was added accidentally on `LegalEntityParams` when it should have been on `AccountParams`)

## 35.12.0 - 2018-07-05
* [#620](https://github.com/stripe/stripe-go/pull/620) Add support for `Quantity` and `UnitAmount` to `InvoiceItemParams` and `Quantity` to `InvoiceItem`

## 35.11.0 - 2018-07-05
* [#618](https://github.com/stripe/stripe-go/pull/618) Add support for `DeclineChargeOn` to `Account` and `AccountParams`

## 35.10.0 - 2018-07-04
* [#616](https://github.com/stripe/stripe-go/pull/616) Adding missing clients to the `API` struct including a `UsageRecords` entry

## 35.9.0 - 2018-07-03
* [#611](https://github.com/stripe/stripe-go/pull/611) Introduce `GetBackendWithConfig` and make logging configurable per backend

## 35.8.0 - 2018-06-28
* [#607](https://github.com/stripe/stripe-go/pull/607) Add support for `PartnerID` from `stripe.SetAppInfo`

## 35.7.0 - 2018-06-26
* [#604](https://github.com/stripe/stripe-go/pull/604) Add extra parameters `CustomerReference` and `ShippingFromZip` to `ChargeLevel3Params` and `ChargeLevel3`

## 35.6.0 - 2018-06-25
* [#603](https://github.com/stripe/stripe-go/pull/603) Add support for Level III data on charge creation

## 35.5.0 - 2018-06-22
* [#601](https://github.com/stripe/stripe-go/pull/601) Add missing parameters for retrieving an upcoming invoice

## 35.4.0 - 2018-06-21
* [#599](https://github.com/stripe/stripe-go/pull/599) Add `ExchangeRate` to `BalanceTransaction`

## 35.3.0 - 2018-06-20
* [#596](https://github.com/stripe/stripe-go/pull/596) Add `Type` to `ProductListParams` so that products can be listed by type

## 35.2.0 - 2018-06-19
* [#595](https://github.com/stripe/stripe-go/pull/595) Add `Product` to `PlanListParams` so that plans can be listed by product

## 35.1.0 - 2018-06-17
* [#592](https://github.com/stripe/stripe-go/pull/592) Add `Name` field to `Coupon` and `CouponParams`

## 35.0.0 - 2018-06-15
* [#557](https://github.com/stripe/stripe-go/pull/557) Add automatic retries for intermittent errors (enabling using `BackendConfiguration.SetMaxNetworkRetries`)
* [#589](https://github.com/stripe/stripe-go/pull/589) Fix all `Get` methods to support standardized parameter structs + remove some deprecated functions
	* `IssuerFraudRecordListParams` now uses `*string` for `Charge` (set it using `stripe.String` like elsewhere)
	* `event.Get` now takes `stripe.EventParams` instead of `Params` for consistency
	* The `Get` method for `countryspec`, `exchangerate`, `issuerfraudrecord` now take an extra params struct parameter to be consistent and allow setting a connected account (use `stripe.CountrySpecParams`, `stripe.ExchangeRateParams`, and `IssuerFraudRecordParams`)
	* `charge.MarkFraudulent` and `charge.MarkSafe` have been removed; use `charge.Update` instead
	* `charge.CloseDispute` and `charge.UpdateDispute` have been removed; use `dispute.Update` or `dispute.Close` instead
	* `loginlink.New` now properly passes its params struct into its API call

## 34.3.0 - 2018-06-14
* [#587](https://github.com/stripe/stripe-go/pull/587) Use `net/http` constants instead of string literals for HTTP verbs (this is an internal cleanup and should not affect library behavior)

## 34.2.0 - 2018-06-14
* [#581](https://github.com/stripe/stripe-go/pull/581) Push parameter encoding into `BackendConfiguration.Call` (this is an internal cleanup and should not affect library behavior)

## 34.1.0 - 2018-06-13
* [#586](https://github.com/stripe/stripe-go/pull/586) Add `AmountPaid`, `AmountRemaining`, `BillingReason` (including new `InvoiceBillingReason` and constants), and `SubscriptionProrationDate` to `Invoice`

## 34.0.0 - 2018-06-12
* [#585](https://github.com/stripe/stripe-go/pull/585) Remove `File` in favor of `FileUpload`, and consolidating both classes which were already nearly identical except `MIMEType` has been replaced by `Type` (this is technically a breaking change, but quite a small one)

## 33.1.0 - 2018-06-12
* [#578](https://github.com/stripe/stripe-go/pull/578) Improve expansion parsing by not discarding unmarshal errors

## 33.0.0 - 2018-06-11
* [#583](https://github.com/stripe/stripe-go/pull/583) Add new account constants, rename one, and fix `DueBy` (this is technically a breaking change, but quite a small one)

## 32.4.1 - 2018-06-11
* [#582](https://github.com/stripe/stripe-go/pull/582) Fix unmarshaling of `LegalEntity` (specifically when we have `legal_entity[additional_owners][][verification]`) so that it comes out as a struct

## 32.4.0 - 2018-06-07
* [#577](https://github.com/stripe/stripe-go/pull/577) Add `DocumentBack` to account legal entity identity verification parameters and response

## 32.3.0 - 2018-06-07
* [#576](https://github.com/stripe/stripe-go/pull/576) Fix plan transform usage to use `BucketSize` instead of `DivideBy`; note this is technically a breaking API change, but we've released it as a minor because the previous manifestation didn't work

## 32.2.0 - 2018-06-06
* [#571](https://github.com/stripe/stripe-go/pull/571) Add `HostedInvoiceURL` and `InvoicePDF` to `Invoice`
* [#573](https://github.com/stripe/stripe-go/pull/573) Add `FormatURLPath` helper to allow safer URL path building

## 32.1.0 - 2018-06-06
* [#572](https://github.com/stripe/stripe-go/pull/572) Add `Active` to plan parameters and response

## 32.0.1 - 2018-06-06
* [#569](https://github.com/stripe/stripe-go/pull/569) Fix unmarshaling of expanded transaction sources in balance transactions

## 32.0.0 - 2018-06-06
* [#544](https://github.com/stripe/stripe-go/pull/544) **MAJOR** changes that make all fields on parameter structs pointers, and rename many fields on parameter and response structs to be consistent with naming in the REST API; we've written [a migration guide with complete details](https://github.com/stripe/stripe-go/blob/master/v32_migration_guide.md) to help with the upgrade

## 31.0.0 - 2018-06-06
* [#566](https://github.com/stripe/stripe-go/pull/566) Support `DisputeParams` in `dispute.Close`

## 30.8.1 - 2018-05-24
* [#562](https://github.com/stripe/stripe-go/pull/562) Add `go.mod` for vgo support

## 30.8.0 - 2018-05-22
* [#558](https://github.com/stripe/stripe-go/pull/558) Add `SubscriptionItem` to `InvoiceLine`

## 30.7.0 - 2018-05-09
* [#552](https://github.com/stripe/stripe-go/pull/552) Add support for issuer fraud records

## 30.6.1 - 2018-05-04
* [#550](https://github.com/stripe/stripe-go/pull/550) Append standard `Params` as well as card options when encoding `CardParams`

## 30.6.0 - 2018-04-17
* [#546](https://github.com/stripe/stripe-go/pull/546) Add `SubParams.TrialFromPlan` and `SubItemsParams.ClearUsage`

## 30.5.0 - 2018-04-09
* [#543](https://github.com/stripe/stripe-go/pull/543) Support listing orders by customer (add `Customer` to `OrderListParams`)

## 30.4.0 - 2018-04-06
* [#541](https://github.com/stripe/stripe-go/pull/541) Add `Mandate` on `Source` (and associated mandate structs)

## 30.3.0 - 2018-04-02
* [#538](https://github.com/stripe/stripe-go/pull/538) Introduce flexible billing primitives for subscriptions

## 30.2.0 - 2018-03-23
* [#535](https://github.com/stripe/stripe-go/pull/535) Add constant for redirect status `not_required` (`RedirectFlowStatusNotRequired`)

## 30.1.0 - 2018-03-17
* [#534](https://github.com/stripe/stripe-go/pull/534) Add `AmountZero` to `InvoiceItemParams`

## 30.0.0 - 2018-03-14
* [#533](https://github.com/stripe/stripe-go/pull/533) Make `DestPayment` under `Transfer` expandable by changing it from a string to a `Charge`

## 29.3.1 - 2018-03-08
* [#530](https://github.com/stripe/stripe-go/pull/530) Fix mixed up types in `CountrySpec.SupportedBankAccountCurrencies`

## 29.3.0 - 2018-03-01
* [#527](https://github.com/stripe/stripe-go/pull/527) Add `MaidenName`, `PersonalIDNumber`, `PersonalIDNumberProvided` fields to `Owner` struct

## 29.2.0 - 2018-02-26
* [#525](https://github.com/stripe/stripe-go/pull/525) Support shipping carrier and tracking number in orders
* [#526](https://github.com/stripe/stripe-go/pull/526) Fix ignored `commonParams` when returning an order

## 29.1.1 - 2018-02-21
* [#522](https://github.com/stripe/stripe-go/pull/522) Bump API version and fix creating plans with a product

## 29.1.0 - 2018-02-21
* [#520](https://github.com/stripe/stripe-go/pull/520) Add support for topups

## 29.0.1 - 2018-02-16
**WARNING:** Please use 29.1.1 instead.
* [#519](https://github.com/stripe/stripe-go/pull/519) Correct the implementation of `PaymentSource.MarshalJSON` to also handle bank account sources

## 29.0.0 - 2018-02-14
**WARNING:** Please use 29.1.1 instead.
* [#518](https://github.com/stripe/stripe-go/pull/518) Bump API version to 2018-02-06 and add support for Product & Plan API

## 28.12.0 - 2018-02-09
* [#517](https://github.com/stripe/stripe-go/pull/517) Add `BillingCycleAnchor` to `Sub` and `BillingCycleAnchorUnchanged` to `SubParams`

## 28.11.0 - 2018-01-29
* [#516](https://github.com/stripe/stripe-go/pull/516) Add `AmountZero` to `PlanParams` to it's possible to send zero values when creating or updating a plan

## 28.10.1 - 2018-01-18
* [#512](https://github.com/stripe/stripe-go/pull/512) Encode empty values found in maps (like `Meta`)

## 28.10.0 - 2018-01-09
* [#509](https://github.com/stripe/stripe-go/pull/509) Plumb through additional possible errors when unmarshaling polymorphic types (please test your integrations while upgrading)

## 28.9.0 - 2018-01-08
* [#506](https://github.com/stripe/stripe-go/pull/506) Add support for recursing into slices in `event.GetObjValue`

## 28.8.0 - 2017-12-12
* [#500](https://github.com/stripe/stripe-go/pull/500) Support sharing for bank accounts and cards (adds `ID` field to bank account and charge parameters)

## 28.7.0 - 2017-12-05
* [#494](https://github.com/stripe/stripe-go/pull/494) Add `Automatic` to `Payout` struct

## 28.6.1 - 2017-11-02
* [#492](https://github.com/stripe/stripe-go/pull/492) Correct name of user agent header used to send Go version to Stripe's API

## 28.6.0 - 2017-10-31
* [#491](https://github.com/stripe/stripe-go/pull/491) Support for exchange rates APIs

## 28.5.0 - 2017-10-27
* [#488](https://github.com/stripe/stripe-go/pull/488) Support for listing source transactions

## 28.4.2 - 2017-10-25
* [#486](https://github.com/stripe/stripe-go/pull/486) Send the required `object=bank_account` parameter when adding a bank account through an account
* [#487](https://github.com/stripe/stripe-go/pull/487) Make bank account's `account_holder_name` and `account_holder_type` parameters truly optional

## 28.4.1 - 2017-10-24
* [#484](https://github.com/stripe/stripe-go/pull/484) Error early when params not specified for card-related API calls

## 28.4.0 - 2017-10-19
* [#477](https://github.com/stripe/stripe-go/pull/477) Support context on API requests with `Params.Context` and `ListParams.Context`

## 28.3.2 - 2017-10-19
* [#479](https://github.com/stripe/stripe-go/pull/479) Pass token in only one of `external_account` *or* source when appending card

## 28.3.1 - 2017-10-17
* [#476](https://github.com/stripe/stripe-go/pull/476) Make initializing new backends concurrency-safe

## 28.3.0 - 2017-10-10
* [#359](https://github.com/stripe/stripe-go/pull/359) Add support for verify sources (added `Values` on `SourceVerifyParams`)

## 28.2.0 - 2017-10-09
* [#472](https://github.com/stripe/stripe-go/pull/472) Add support for `statement_descriptor` in source objects
* [#473](https://github.com/stripe/stripe-go/pull/473) Add support for detaching sources from customers

## 28.1.0 - 2017-10-05
* [#471](https://github.com/stripe/stripe-go/pull/471) Add support for `RedirectFlow.FailureReason` for sources

## 28.0.1 - 2017-10-03
* [#468](https://github.com/stripe/stripe-go/pull/468) Fix encoding of pointer-based scalars (e.g. `Active *bool` in `Product`)
* [#470](https://github.com/stripe/stripe-go/pull/470) Fix concurrent race in `form` package's encoding caches

## 28.0.0 - 2017-09-27
* [#467](https://github.com/stripe/stripe-go/pull/467) Change `Product.Get` to include `ProductParams` for request metadata
* [#467](https://github.com/stripe/stripe-go/pull/467) Fix sending extra parameters on product and SKU requests

## 27.0.2 - 2017-09-26
* [#465](https://github.com/stripe/stripe-go/pull/465) Fix encoding of `CVC` parameter in `CardParams`

## 27.0.1 - 2017-09-20
* [#461](https://github.com/stripe/stripe-go/pull/461) Fix encoding of `TypeData` under sources

## 27.0.0 - 2017-09-19
* [#458](https://github.com/stripe/stripe-go/pull/458) Remove `ChargeParams.Token` (this seems like it was added accidentally)

## 26.0.0 - 2017-09-17
* Introduce `form` package so it's no longer necessary to build conditional structures to encode parameters -- this may result in parameters that were set but previously not encoded to now be encoded so **PLEASE TEST CAREFULLY WHEN UPGRADING**!
* Alphabetize all struct fields -- this may result in position-based struct initialization to fail if it was being used
* Switch to stripe-mock for testing (test suite now runs completely!)
* Remote Displayer interface and Display implementations
* Add `FraudDetails` to `ChargeParams`
* Remove `FraudReport` from `ChargeParams` (use `FraudDetails` instead)

## 25.2.0 - 2017-09-13
* Add `OnBehalfOf` to charge parameters.
* Add `OnBehalfOf` to subscription parameters.

## 25.1.0 - 2017-09-06
* Use bearer token authentication for API requests

## 25.0.0 - 2017-08-21
* All `Del` methods now take params as second argument (which may be `nil`)
* Product `Delete` has been renamed to `Del` for consistency
* Product `Delete` now returns `(*Product, error)` for consistency
* SKU `Delete` has been renamed to `Del` for consistency
* SKU `Delete` now returns `(*SKU, error)` for consistency

## 24.3.0 - 2017-08-08
* Add `FeeZero` to invoice and `TaxPercentZero` to subscription for zeroing values

## 24.2.0 - 2017-07-25
* Add "range queries" for supported parameters (e.g. `created[gte]=123`)

## 24.1.0 - 2017-07-17
* Add metadata to subscription items

## 24.0.0 - 2017-06-27
	`Pay` on invoice now takes specific pay parameters

## 23.2.1 - 2017-06-26
* Fix bank account retrieval when using a customer ID

## 23.2.0 - 2017-06-26
* Support sharing path while creating a source

## 23.1.0 - 2017-06-26
* Add LoginLinks to client list

## 23.0.0 - 2017-06-23
	plan.Del now takes `stripe.PlanParams` as a second argument

## 22.6.0 - 2017-06-19
* Support for ephemeral keys

## 22.5.0 - 2017-06-15
* Support for checking webhook signatures

## 22.4.1 - 2017-06-15
* Fix returned type of subscription items list
* Note: I meant to release this as 22.3.1, but I'm leaving it as it was released

## 22.3.0 - 2017-06-14
* Fix parameters for subscription items list

## 22.2.0 - 2017-06-13
* Support subscription items when getting upcoming invoice
* Support setting subscription's quantity to zero when getting upcoming invoice

## 22.1.1 - 2017-06-12
* Handle `deleted` parameter when updating subscription items in a subscription

## 22.1.0 - 2017-05-25
* Change `Logger` to a `log.Logger`-like interface so other loggers are usable

## 22.0.0 - 2017-05-25
* Add support for login links
* Add support for new `Type` for accounts
* Make `Event` `Request` (renamed from `Req`) a struct with a new idempotency key
* Rename `Event` `UserID` to `Account`

## 21.5.1 - 2017-05-23
* Fix plan update so `TrialPeriod` parameter is sent

## 21.5.0 - 2017-05-15
* Implement `Get` for `RequestValues`

## 21.4.1 - 2017-05-11
* Pass extra parameters to API calls on bank account deletion

## 21.4.0 - 2017-05-04
* Add `Billing` and `DueDate` filters to invoice listing
* Add `Billing` filter to subscription listing

## 21.3.0 - 2017-05-02
* Add `DetailsCode` to `IdentityVerification`

## 21.2.0 - 2017-04-19
* Send user agent information with `X-Stripe-Client-User-Agent`
* Add `stripe.SetAppInfo` for plugin authors to register app information

## 21.1.0 - 2017-04-12
* Allow coupon to be specified when creating orders
* No longer require that items have descriptions when creating orders

## 21.0.0 - 2017-04-07
* Balances are now retrieved by payout instead of by transfer

## 20.0.0 - 2017-04-06
* Bump API version to 2017-04-06: https://stripe.com/docs/upgrades#2017-04-06
* Add support for payouts and recipient transfers
* Change the transfer resource to support its new format
* Deprecate recipient creation
* Disputes under charges are now expandable and collapsed by default
* Rules under charge outcomes are now expandable and collapsed by default

## 19.17.0 - 2017-04-06
* Please see 20.0.0 (bad release)

## 19.16.0 - 2017-03-23
* Allow the ID of an identity document to be passed into an account owner update

## 19.15.0 - 2017-03-22
* Add `ShippingCarrier` to dispute evidence

## 19.14.0 - 2017-03-20
* Add `Period`, `Plan`, and `Quantity` to `InvoiceItem`

## 19.13.0 - 2017-03-20
* Add `AdditionalOwnersEmpty` to allow additional owners to be unset

## 19.12.0 - 2017-03-17
* Add new form of file upload using `io.FileReader` and filename

## 19.11.0 - 2017-03-13
* Add `Token` to `SourceObjectParams`

## 19.10.0 - 2017-03-13
* Add `CouponEmpty` (allowing a coupon to be cleared) to customer parameters
* Add `CouponEmpty` (allowing a coupon to be cleared) to subscription parameters

## 19.9.0 - 2017-03-08
* Add missing value "all" to subscription statuses

## 19.8.0 - 2017-03-02
* Add subscription items client to main `client.API` struct

## 19.7.0 - 2017-03-01
* Add `Statement` (statement descriptor) to `CaptureParams`

## 19.6.0 - 2017-02-22
* Add new parameters for invoices and subscriptions

## 19.5.0 - 2017-02-13
* Add new rich `Destination` type to `ChargeParams`

## 19.4.0 - 2017-02-03
* Support Connect account as payment source

## 19.3.0 - 2017-02-02
* Add transfer group to charges and transfers

## 19.2.0 - 2017-01-23
* Add `Rule` to `ChargeOutcome`

## 19.1.0 - 2017-01-18
* Add support for updating sources

## 19.0.2 - 2017-01-04
* Fix subscription `trial_period_days` to be populated by the right value

## 19.0.1 - 2016-12-08
* Include verification document details when persisting `LegalEntity`

## 19.0.0 - 2016-12-07
* Remote `SubProrationDateNow` field from `InvoiceParams`

## 18.14.1 - 2016-12-05
* Truncate `tax_percent` at four decimals (e.g. 3.9750%) instead of two

## 18.14.0 - 2016-11-23
* Add retrieve method for 3-D Secure resources

## 18.13.0 - 2016-11-15
* Add `PaymentSource` to `API`

## 18.12.0 - 2016-11-14
* Allow bank accounts to be created as a customer source

## 18.11.0 - 2016-11-14
* Add `TrialPeriodEnd` to `SubParams`

## 18.10.0 - 2016-11-09
* Add `StatusTransitions` to `Order`

## 18.9.0 - 2016-11-04
* Add `Application` to `Charge`

## 18.8.0 - 2016-10-24
* Add `Review` to `Charge` for the charge reviews

## 18.7.0 - 2016-10-18
* Add `RiskLevel` to `ChargeOutcome`

## 18.6.0 - 2016-10-18
* Support for 403 status codes (permission denied)

## 18.5.0 - 2016-10-18
* Add `Status` to `SubListParams` to allow filtering subscriptions by status

## 18.4.0 - 2016-10-14
* Add `HasEvidence` and `PastDue` to `EvidenceDetails`

## 18.3.0 - 2016-10-10
* Add `NoDiscountable` to `InvoiceItemParams`

## 18.2.0 - 2016-10-10
* Add `BusinessLogo` to `Account`
* Add `ReceiptNumber` to `Charge`
* Add `DestPayment` to `Transfer`

## 18.1.0 - 2016-10-04
* Support for Apple Pay domains

## 18.0.0 - 2016-10-03
* Support for subscription items
* Correct `SourceTx` on `Transfer` to be a `SourceTransaction`
* Change `Charge` on `Resource` to be expandable (now a struct instead of string)

## 17.5.0 - 2016-09-22
* Support customer-related operations for bank accounts

## 17.4.2 - 2016-09-19
* Fix but where some parameters were not being included on order update

## 17.4.1 - 2016-09-15
* Fix bug that required a date of birth to be included on account update

## 17.4.0 - 2016-09-13
* Add missing Kana and Kanji address and name fields to account's legal entity
* Add `ReceiptNumber` and `Status` to `Refund`

## 17.3.0 - 2016-09-07
* Add support for sources endpoint

## 17.2.0 - 2016-08-29
* Add order returns to `API`

## 17.1.0 - 2016-08-22
* Add `DeactiveOn` to `Product`

## 17.0.0 - 2016-08-18
* Allow expansion of destination on transfers
* Allow expansion of sources on balance transactions

## 16.8.0 - 2016-08-17
* Add `OriginatingTransaction` to `Fee`

## 16.7.1 - 2016-08-17
* Allow params to be nil when retrieving a refund

## 16.7.0 - 2016-08-11
* Add support for 3-D Secure

## 16.6.0 - 2016-08-09
* Add `ReceiptNumber` to `Invoice`

## 16.5.0 - 2016-08-08
* Add `Meta` to `Account`

## 16.4.0 - 2016-08-05
* Allow the migration of recipients to accounts
* Add `MigratedTo` to `Recipient`

## 16.3.1 - 2016-07-25
* URL-escape the IDs of coupons and plans when making API requests

## 16.3.0 - 2016-07-19
* Add `NoClosed` to `InvoiceParams` to allow an invoice to be reopened

## 16.2.1 - 2016-07-11
* Consider `SubParams.QuantityZero` when updating a subscription

## 16.2.0 - 2016-07-07
* Upgrade API version to 2016-07-06

## 16.1.0 - 2016-07-07
* Add `Returns` field to `Order`

## 16.0.0 - 2016-06-30
* Remove `Name` field on `SKU`; it's not actually supported
* Support updating `Product` on `SKU`

## 15.6.0 - 2016-06-24
* Allow product and SKU attributes to be updated

## 15.5.0 - 2016-06-24
* Add `TaxPercent` and `TaxPercentZero` to `CustomerParams`

## 15.4.0 - 2016-06-20
* Add `TokenizationMethod` to `Card` struct

## 15.3.0 - 2016-06-15
* Add `BalanceZero` to `CustomerParams` so that balance can be zeroed out

## 15.2.0 - 2016-06-03
* Add `ToValues` to `RequestValues` struct

## 15.1.0 - 2016-05-26
* Add `BusinessVatID` to customer creation parameters

## 15.0.0 - 2016-05-24
* Fix handling of nested objects in arrays in request parameters

## 14.4.0 - 2016-05-24
* Add granular error types in new `Err` field on `stripe.Error`

## 14.3.0 - 2016-05-20
* Allow Relay orders to be returned and add associated types

## 14.2.3 - 2016-05-20
* When creating a bank account token, only send routing number if it's been set

## 14.2.2 - 2016-05-17
* When creating a bank account, only send routing number if it's been set

## 14.2.1 - 2016-05-17
* Add missing SKU clinet to client API type

## 14.2.0 - 2016-05-11
* Add `Reversed` and `AmountReversed` fields to `Transfer`

## 14.1.0 - 2016-05-05
* Allow `default_for_currency` to be set when creating a card

## 14.0.0 - 2016-05-04
* Change the signature for `sub.Delete`. The customer ID is no longer required.

## 13.12.0 - 2016-04-28
* Add `Currency` to `Card`

## 13.11.1 - 2016-04-22
* Fix bug where new external accounts could not be marked default from token

## 13.11.0 - 2016-04-21
* Expose a number of list types that were previously internal (full list below)
* Expose `stripe.AccountList`
* Expose `stripe.TransactionList`
* Expose `stripe.BitcoinReceiverList`
* Expose `stripe.ChargeList`
* Expose `stripe.CountrySpecList`
* Expose `stripe.CouponList`
* Expose `stripe.CustomerList`
* Expose `stripe.DisputeList`
* Expose `stripe.EventList`
* Expose `stripe.FeeList`
* Expose `stripe.FileUploadList`
* Expose `stripe.InvoiceList`
* Expose `stripe.OrderList`
* Expose `stripe.ProductList`
* Expose `stripe.RecipientList`
* Expose `stripe.TransferList`
* Switch to use of `stripe.BitcoinTransactionList`
* Switch to use of `stripe.SKUList`

## 13.10.1 - 2016-04-20
* Add support for `TaxPercentZero` to invoice and subscription updates

## 13.10.0 - 2016-04-19
* Expose `stripe.PlanList` (previously an internal type)

## 13.9.0 - 2016-04-18
* Add `TaxPercentZero` struct to `InvoiceParams`
* Add `TaxPercentZero` to `SubParams`

## 13.8.0 - 2016-04-12
* Add `Outcome` struct to `Charge`

## 13.7.0 - 2016-04-06
* Add `Description`, `IIN`, and `Issuer` to `Card`

## 13.6.0 - 2016-04-05
* Add `SourceType` (and associated constants) to `Transfer`

## 13.5.0 - 2016-03-29
* Add `Meta` (metadata) to `BankAccount`

## 13.4.0 - 2016-03-29
* Add `Meta` (metadata) to `Card`

## 13.3.0 - 2016-03-29
* Add `DefaultCurrency` to `CountrySpec`

## 13.2.0 - 2016-03-18
* Add `SourceTransfer` to `Charge`
* Add `SourceTx` to `Transfer`

## 13.1.0 - 2016-03-15
* Add `Reject` on `Account` to support the new API feature

## 13.0.0 - 2016-03-15
* Upgrade API version to 2016-03-07
* Remove `Account.BankAccounts` in favor of `ExternalAccounts`
* Remove `Account.Currencies` in favor of `CountrySpec`

## 12.1.0 - 2016-02-04
* Add `ListParams.StripeAccount` for making list calls on behalf of connected accounts
* Add `Params.StripeAccount` for symmetry with `ListParams.StripeAccount`
* Deprecate `Params.Account` in favor of `Params.StripeAccount`

## 12.0.0 - 2016-02-02
* Add support for fetching events for managed accounts (`event.Get` now takes `Params`)

## 11.5.0 - 2016-02-26
* Allow a `PII.PersonalIDNumber` number to be used to create a token

## 11.4.0 - 2016-02-24
* Add missing subscription fields to `InvoiceParams` for use with `invoice.GetNext`

## 11.3.0 - 2016-02-19
* Add `AccountHolderName` and `AccountHolderType` to bank accounts

## 11.2.0 - 2016-02-11
* Add support for `CountrySpec`
* Add `SSNProvided`, `PersonalIDProvided` and `BusinessTaxIDProvided` to `LegalEntity`

## 11.1.2 - 2016-02-02
* Fix card update method to correctly take expiration date

## 11.1.1 - 2016-02-01
* Fix recipient update so that it can take a bank token (like create)

## 11.0.1 - 2016-01-11
* Add missing field `country` to shipping details of `Charge` and `Customer`

## 11.0.0 - 2016-01-07
* Add missing field `Default` to `BankAccount`
* Add `OrderParams` parameter to `Order` retrieval
* Fix parameter bug when creating a new `Order`
* Support special value of 'now' for trial end when updating subscriptions

## 10.3.0 - 2015-12-10
* Allow an account to be referenced when creating a card

## 10.2.0 - 2015-12-04
* Add `Update` function on `Coupon` client so that metadata can be set

## 10.1.0 - 2015-12-01
* Add a verification routine for external accounts

## 10.0.0 - 2015-11-30
* Return models along with `error` when deleting resources with `Del`
* Fix bug where country parameter wasn't included for some account creation

## 9.0.0 - 2015-11-13
* Return model (`Sub`) when cancelling a subscription (`sub.Cancel`)

## 8.0.0 - 2015-08-17
* Add ability to list and retrieve refunds without a Charge

## 7.0.0 - 2015-08-03
* Add ability to list and retrieve disputes

## 6.8.0 - 2015-07-29
* Add ability to delete an account

## 6.7.1 - 2015-07-17
* Bug fixes

## 6.7.0 - 2015-07-16
* Expand logging object
* Move proration date to subscription update
* Send country when creating/updating account

## 6.6.0 - 2015-07-06
* Add request ID to errors

## 6.5.0 - 2015-07-06
* Update bank account creation API
* Add destination, application fee, transfer to Charge struct
* Add missing fields to invoice line item
* Rename deprecated customer param value

## 6.4.2 - 2015-06-23
* Add BusinessUrl, BusinessUrl, BusinessPrimaryColor, SupportEmail, and
* SupportUrl to Account.

## 6.4.1 - 2015-06-16
* Change card.dynamic_last_four to card.dynamic_last4

## 6.4.0 - 2015-05-28
* Rename customer.default_card -> default_source

## 6.3.0 - 2015-05-19
* Add shipping address to charges
* Expose card.dynamic_last_four
* Expose account.tos_acceptance
* Bug fixes
* Bump API version to most recent one

## 6.2.0 - 2015-04-09
* Bug fixes
* Add Extra to parameters

## 6.1.0 - 2015-03-17
* Add TaxPercent for subscriptions
* Event bug fixes

## 6.0.0 - 2015-03-15
* Add more operations for /accounts endpoint
* Add /transfers/reversals endpoint
* Add /accounts/bank_accounts endpoint
* Add support for Stripe-Account header

## 5.1.0 - 2015-02-25
* Add new dispute status `warning_closed`
* Add SubParams.TrialEndNow to support `trial_end = "now"`

## 5.0.1 - 2015-02-25
* Fix URL for upcoming invoices

## 5.0.0 - 2015-02-19
* Bump to API version 2014-02-18
* Change Card, DefaultCard, Cards to Source, DefaultSource, Sources in Stripe response objects
* Add paymentsource package for manipulating Customer's sources
* Support Update action for Bitcoin Receivers

## 4.4.3 - 2015-02-08
* Modify NewIdempotencyKey() algorithm to increase likelihood of randomness

## 4.4.2 - 2015-01-24
* Add BankAccountParams.Token
* Add Token.ClientIP
* Add LogLevel

## 4.4.0 - 2015-01-20
* Add Bitcoin support

## 4.3.0 - 2015-01-13
* Added support for listing FileUploads
* Mime parameter on FileUpload has been changed to Type

## 4.2.1 - 2014-12-28
* Handle charges with customer card tokens

## 4.2.0 - 2014-12-18
* Add idempotency support

## 4.1.0 - 2014-12-17
* Bump to API version 2014-12-17.

## 4.0.0 - 2014-12-16
* Add FileUpload resource. This brings in a new endpoint (uploads.stripe.com) and thus makes changes to some of the existing interfaces.
* This also adds support for multipart content.

## 3.1.0 - 2014-12-16
* Add Charge.FraudDetails

## 3.0.1 - 2014-12-15
* Add timeout value to HTTP requests

## 3.0.0 - 2014-12-05
* Add Dispute.EvidenceDetails
* Remove Dispute.DueDate
* Change Dispute.Evidence from string to struct

## 2.0.0 - 2014-11-26
* Change List interface to .Next() and .Resource()
* Better error messages for Get() methods
* EventData.Raw contains the raw event message
* SubParams.QuantityZero can be used for free subscriptions

## 1.0.3 - 2014-10-22
* Add AddMeta method

## 1.0.2 - 2014-09-23
* Minor fixes

## 1.0.1 - 2014-09-23
* Linter-based updates

## 1.0.0 - 2014-09-22
* Initial version

A vendor/github.com/stripe/stripe-go/v71/CODE_OF_CONDUCT.md => vendor/github.com/stripe/stripe-go/v71/CODE_OF_CONDUCT.md +77 -0
@@ 0,0 1,77 @@
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
  advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at conduct@stripe.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


A vendor/github.com/stripe/stripe-go/v71/LICENSE => vendor/github.com/stripe/stripe-go/v71/LICENSE +21 -0
@@ 0,0 1,21 @@
The MIT License (MIT)

Copyright (c) 2014- Stripe, Inc. (https://stripe.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

A vendor/github.com/stripe/stripe-go/v71/Makefile => vendor/github.com/stripe/stripe-go/v71/Makefile +28 -0
@@ 0,0 1,28 @@
all: test bench vet lint check-api-clients check-gofmt

bench:
	go test -race -bench . -run "Benchmark" ./form

build:
	go build ./...

check-api-clients:
	go run scripts/check_api_clients/main.go

check-gofmt:
	scripts/check_gofmt.sh

lint:
	golint -set_exit_status ./...

test:
	go run scripts/test_with_stripe_mock/main.go -race ./...

vet:
	go vet ./...

coverage:
	go run scripts/test_with_stripe_mock/main.go -covermode=count -coverprofile=combined.coverprofile ./...

clean:
	find . -name \*.coverprofile -delete

A vendor/github.com/stripe/stripe-go/v71/README.md => vendor/github.com/stripe/stripe-go/v71/README.md +402 -0
@@ 0,0 1,402 @@
# Go Stripe

[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/stripe/stripe-go)
[![Build Status](https://travis-ci.org/stripe/stripe-go.svg?branch=master)](https://travis-ci.org/stripe/stripe-go)
[![Coverage Status](https://coveralls.io/repos/github/stripe/stripe-go/badge.svg?branch=master)](https://coveralls.io/github/stripe/stripe-go?branch=master)

The official [Stripe][stripe] Go client library.

## Installation

Make sure your project is using Go Modules (it will have a `go.mod` file in its
root if it already is):

``` sh
go mod init
```

Then, reference stripe-go in a Go program with `import`:

``` go
import (
    "github.com/stripe/stripe-go/v71"
    "github.com/stripe/stripe-go/v71/customer"
)
```

Run any of the normal `go` commands (`build`/`install`/`test`). The Go
toolchain will resolve and fetch the stripe-go module automatically.

## Documentation

For a comprehensive list of examples, check out the [API
documentation][api-docs].

For details on all the functionality in this library, see the [GoDoc][godoc]
documentation.

Below are a few simple examples:

### Customers

```go
params := &stripe.CustomerParams{
	Description: stripe.String("Stripe Developer"),
	Email:       stripe.String("gostripe@stripe.com"),
}

customer, err := customer.New(params)
```

### PaymentIntents

```go
params := &stripe.PaymentIntentListParams{
    Customer: stripe.String(customer.ID),
}

// set this so you can easily retry your request in case of a timeout
params.Params.IdempotencyKey = stripe.NewIdempotencyKey()

i := paymentintent.List(params)
for i.Next() {
	pi := i.PaymentIntent()
}

if err := i.Err(); err != nil {
	// handle
}
```

### Events

```go
i := event.List(nil)
for i.Next() {
	e := i.Event()

	// access event data via e.GetObjectValue("resource_name_based_on_type", "resource_property_name")
	// alternatively you can access values via e.Data.Object["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"]

	// access previous attributes via e.GetPreviousValue("resource_name_based_on_type", "resource_property_name")
	// alternatively you can access values via e.Data.PrevPreviousAttributes["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"]
}
```

Alternatively, you can use the `event.Data.Raw` property to unmarshal to the
appropriate struct.

### Authentication with Connect

There are two ways of authenticating requests when performing actions on behalf
of a connected account, one that uses the `Stripe-Account` header containing an
account's ID, and one that uses the account's keys. Usually the former is the
recommended approach. [See the documentation for more information][connect].

To use the `Stripe-Account` approach, use `SetStripeAccount()` on a `ListParams`
or `Params` class. For example:

```go
// For a list request
listParams := &stripe.CustomerListParams{}
listParams.SetStripeAccount("acct_123")
```

```go
// For any other kind of request
params := &stripe.CustomerParams{}
params.SetStripeAccount("acct_123")
```

To use a key, pass it to `API`'s `Init` function:

```go

import (
	"github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/client"
)

stripe := &client.API{}
stripe.Init("access_token", nil)
```

### Google AppEngine

If you're running the client in a Google AppEngine environment, you'll need to
create a per-request Stripe client since the `http.DefaultClient` is not
available. Here's a sample handler:

```go
import (
	"fmt"
	"net/http"

	"google.golang.org/appengine"
	"google.golang.org/appengine/urlfetch"

	"github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/client"
)

func handler(w http.ResponseWriter, r *http.Request) {
        c := appengine.NewContext(r)
        httpClient := urlfetch.Client(c)

        sc := stripeClient.New("sk_test_123", stripe.NewBackends(httpClient))

        params := &stripe.CustomerParams{
            Description: stripe.String("Stripe Developer"),
            Email:       stripe.String("gostripe@stripe.com"),
        }
        customer, err := sc.Customers.New(params)
        if err != nil {
            fmt.Fprintf(w, "Could not create customer: %v", err)
        }
        fmt.Fprintf(w, "Customer created: %v", customer.ID)
}
```

## Usage

While some resources may contain more/less APIs, the following pattern is
applied throughout the library for a given `$resource$`:

### Without a Client

If you're only dealing with a single key, you can simply import the packages
required for the resources you're interacting with without the need to create a
client.

```go
import (
	"github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/$resource$"
)

// Setup
stripe.Key = "sk_key"

stripe.SetBackend("api", backend) // optional, useful for mocking

// Create
$resource$, err := $resource$.New(stripe.$Resource$Params)

// Get
$resource$, err := $resource$.Get(id, stripe.$Resource$Params)

// Update
$resource$, err := $resource$.Update(stripe.$Resource$Params)

// Delete
resourceDeleted, err := $resource$.Del(id, stripe.$Resource$Params)

// List
i := $resource$.List(stripe.$Resource$ListParams)
for i.Next() {
	$resource$ := i.$Resource$()
}

if err := i.Err(); err != nil {
	// handle
}
```

### With a Client

If you're dealing with multiple keys, it is recommended you use `client.API`.
This allows you to create as many clients as needed, each with their own
individual key.

```go
import (
	"github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/client"
)

// Setup
sc := &client.API{}
sc.Init("sk_key", nil) // the second parameter overrides the backends used if needed for mocking

// Create
$resource$, err := sc.$Resource$s.New(stripe.$Resource$Params)

// Get
$resource$, err := sc.$Resource$s.Get(id, stripe.$Resource$Params)

// Update
$resource$, err := sc.$Resource$s.Update(stripe.$Resource$Params)

// Delete
resourceDeleted, err := sc.$Resource$s.Del(id, stripe.$Resource$Params)

// List
i := sc.$Resource$s.List(stripe.$Resource$ListParams)
for i.Next() {
	resource := i.$Resource$()
}

if err := i.Err(); err != nil {
	// handle
}
```

### Automatic Retries

The library automatically retries requests on intermittent failures like on a
connection error, timeout, or on certain API responses like a status `409
Conflict`. [Idempotency keys][idempotency-keys] are always added to requests to
make any such subsequent retries safe.

By default, it will perform up to two retries. That number can be configured
with `MaxNetworkRetries`:

```go
import (
	"github.com/stripe/stripe-go/v71"
	"github.com/stripe/stripe-go/v71/client"
)

config := &stripe.BackendConfig{
    MaxNetworkRetries: stripe.Int64(0), // Zero retries
}

sc := &client.API{}
sc.Init("sk_key", &stripe.Backends{
    API:     stripe.GetBackendWithConfig(stripe.APIBackend, config),
    Uploads: stripe.GetBackendWithConfig(stripe.UploadsBackend, config),
})

coupon, err := sc.Coupons.New(...)
```

### Configuring Logging

By default, the library logs error messages only (which are sent to `stderr`).
Configure default logging using the global `DefaultLeveledLogger` variable:

```go
stripe.DefaultLeveledLogger = &stripe.LeveledLogger{
    Level: stripe.LevelInfo,
}
```

Or on a per-backend basis:

```go
config := &stripe.BackendConfig{
    LeveledLogger: &stripe.LeveledLogger{
        Level: stripe.LevelInfo,
    },
}
```

It's possible to use non-Stripe leveled loggers as well. Stripe expects loggers
to comply to the following interface:

```go
type LeveledLoggerInterface interface {
	Debugf(format string, v ...interface{})
	Errorf(format string, v ...interface{})
	Infof(format string, v ...interface{})
	Warnf(format string, v ...interface{})
}
```

Some loggers like [Logrus][logrus] and Zap's [SugaredLogger][zapsugaredlogger]
support this interface out-of-the-box so it's possible to set
`DefaultLeveledLogger` to a `*logrus.Logger` or `*zap.SugaredLogger` directly.
For others it may be necessary to write a thin shim layer to support them.

### Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you
identified using `stripe.SetAppInfo`:

```go
stripe.SetAppInfo(&stripe.AppInfo{
    Name:    "MyAwesomePlugin",
    URL:     "https://myawesomeplugin.info",
    Version: "1.2.34",
})
```

This information is passed along when the library makes calls to the Stripe
API. Note that while `Name` is always required, `URL` and `Version` are
optional.

### Request latency telemetry

By default, the library sends request latency telemetry to Stripe. These
numbers help Stripe improve the overall latency of its API for all users.

You can disable this behavior if you prefer:

```go
config := &stripe.BackendConfig{
	EnableTelemetry: stripe.Bool(false),
}
```

## Development

Pull requests from the community are welcome. If you submit one, please keep
the following guidelines in mind:

1. Code must be `go fmt` compliant.
2. All types, structs and funcs should be documented.
3. Ensure that `make test` succeeds.

## Test

The test suite needs testify's `require` package to run:

    github.com/stretchr/testify/require

Before running the tests, make sure to grab all of the package's dependencies:

    go get -t -v

It also depends on [stripe-mock][stripe-mock], so make sure to fetch and run it from a
background terminal ([stripe-mock's README][stripe-mock-usage] also contains
instructions for installing via Homebrew and other methods):

    go get -u github.com/stripe/stripe-mock
    stripe-mock

Run all tests:

    make test

Run tests for one package:

    go test ./invoice

Run a single test:

    go test ./invoice -run TestInvoiceGet

For any requests, bug or comments, please [open an issue][issues] or [submit a
pull request][pulls].

[api-docs]: https://stripe.com/docs/api/go
[api-changelog]: https://stripe.com/docs/upgrades
[connect]: https://stripe.com/docs/connect/authentication
[depgomodsupport]: https://github.com/golang/dep/pull/1963
[godoc]: http://godoc.org/github.com/stripe/stripe-go
[gomodrevert]: https://github.com/stripe/stripe-go/pull/774
[gomodvsdep]: https://github.com/stripe/stripe-go/pull/712
[idempotency-keys]: https://stripe.com/docs/api/ruby#idempotent_requests
[issues]: https://github.com/stripe/stripe-go/issues/new
[logrus]: https://github.com/sirupsen/logrus/
[modules]: https://github.com/golang/go/wiki/Modules
[package-management]: https://code.google.com/p/go-wiki/wiki/PackageManagementTools
[pulls]: https://github.com/stripe/stripe-go/pulls
[stripe]: https://stripe.com
[stripe-mock]: https://github.com/stripe/stripe-mock
[stripe-mock-usage]: https://github.com/stripe/stripe-mock#usage
[zapsugaredlogger]: https://godoc.org/go.uber.org/zap#SugaredLogger

<!--
# vim: set tw=79:
-->

A vendor/github.com/stripe/stripe-go/v71/VERSION => vendor/github.com/stripe/stripe-go/v71/VERSION +1 -0
@@ 0,0 1,1 @@
71.28.0

A vendor/github.com/stripe/stripe-go/v71/account.go => vendor/github.com/stripe/stripe-go/v71/account.go +605 -0
@@ 0,0 1,605 @@
package stripe

import (
	"encoding/json"

	"github.com/stripe/stripe-go/v71/form"
)

// AccountType is the type of an account.
type AccountType string

// List of values that AccountType can take.
const (
	AccountTypeCustom   AccountType = "custom"
	AccountTypeExpress  AccountType = "express"
	AccountTypeStandard AccountType = "standard"
)

// AccountCapability maps to a given capability for an account.
type AccountCapability string

// List of values that AccountCapability can take.
const (
	AccountCapabilityAUBECSDebitPayments    AccountCapability = "au_becs_debit_payments"
	AccountCapabilityBACSDebitPayments      AccountCapability = "bacs_debit_payments"
	AccountCapabilityCardIssuing            AccountCapability = "card_issuing"
	AccountCapabilityCardPayments           AccountCapability = "card_payments"
	AccountCapabilityJCBPayments            AccountCapability = "jcb_payments"
	AccountCapabilityLegacyPayments         AccountCapability = "legacy_payments"
	AccountCapabilityTaxReportingUS1099K    AccountCapability = "tax_reporting_us_1099_k"
	AccountCapabilityTaxReportingUS1099MISC AccountCapability = "tax_reporting_us_1099_misc"
	AccountCapabilityTransfers              AccountCapability = "transfers"
)

// AccountCapabilityStatus is the status a given capability can have
type AccountCapabilityStatus string

// List of values that AccountCapabilityStatus can take.
const (
	AccountCapabilityStatusActive   AccountCapabilityStatus = "active"
	AccountCapabilityStatusInactive AccountCapabilityStatus = "inactive"
	AccountCapabilityStatusPending  AccountCapabilityStatus = "pending"
)

// ExternalAccountType is the type of an external account.
type ExternalAccountType string

// List of values that ExternalAccountType can take.
const (
	ExternalAccountTypeBankAccount ExternalAccountType = "bank_account"
	ExternalAccountTypeCard        ExternalAccountType = "card"
)

// AccountBusinessType describes the business type associated with an account.