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 => +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
+
+[](http://godoc.org/github.com/stripe/stripe-go)
+[](https://travis-ci.org/stripe/stripe-go)
+[](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
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.