~evanj/cms

515c5fd9b9df1ff4652d7ce3e5b2f7df58ee5b85 — Evan M Jones 4 months ago 715dccc
Feat(content search): Pagination for content search complete. Fix up
rest of pagination. Better queries + tmp tables for per contenttype
content searches.
M TODO => TODO +2 -1
@@ 1,6 1,7 @@
[todo]
Cache listicles.
Pagination for content search.
X Pagination for content search.
Make sure full space copy hasn't broke

[revisit] 
Fullscreen takeover for html/markdown editors.

M go.mod => go.mod +1 -1
@@ 3,13 3,13 @@ module git.sr.ht/~evanj/cms
go 1.12

require (
	git.sr.ht/~evanj/embed v0.0.0-20200525225021-2cde7dae7bfa // indirect
	git.sr.ht/~evanj/security v0.0.0-20200228044358-9b9bc6682997
	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
	github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
	github.com/go-playground/assert/v2 v2.0.1
	github.com/go-sql-driver/mysql v1.5.0
	github.com/golang/mock v1.4.3
	github.com/google/uuid v1.1.1
	github.com/kr/pretty v0.2.0 // indirect
	github.com/pkg/errors v0.9.1
	golang.org/x/crypto v0.0.0-20200320181102-891825fb96df // indirect

M go.sum => go.sum +2 -8
@@ 1,5 1,3 @@
git.sr.ht/~evanj/embed v0.0.0-20200525225021-2cde7dae7bfa h1:gpQ2a3/AYs0o1F/kg2V2GIUIS8pPkvoSlJPZCbF9Mvw=
git.sr.ht/~evanj/embed v0.0.0-20200525225021-2cde7dae7bfa/go.mod h1:o3sadZPJeN9scjfsbpsABLF2nNr6qUqMMkGLfCCsILc=
git.sr.ht/~evanj/security v0.0.0-20200228044358-9b9bc6682997 h1:fdAj8fR4mpS/OAvetjc9Xn96ZYrnJcQpbn/AUG0jihs=
git.sr.ht/~evanj/security v0.0.0-20200228044358-9b9bc6682997/go.mod h1:40791KVgThT97CT6mTsF4NUNPeX2BAVlsuH1RiiSrAs=
github.com/Pallinder/go-randomdata v1.2.0 h1:DZ41wBchNRb/0GfsePLiSwb0PHZmT67XY00lCDlaYPg=


@@ 16,6 14,8 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=


@@ 24,15 24,12 @@ 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=
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=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=


@@ 45,9 42,6 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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/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=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

M internal/c/content/content.go => internal/c/content/content.go +5 -8
@@ 46,7 46,7 @@ type DBer interface {
	ContentGet(space space.Space, ct contenttype.ContentType, contentID string) (content.Content, error)
	ContentUpdate(space space.Space, ct contenttype.ContentType, content content.Content, newParams []db.ContentNewParam, updateParams []db.ContentUpdateParam) (content.Content, error)
	ContentDelete(space space.Space, ct contenttype.ContentType, content content.Content) error
	ContentSearch(space space.Space, ct contenttype.ContentType, name, query string, page int) ([]content.Content, error)
	ContentSearch(space space.Space, ct contenttype.ContentType, name, query string, before int) (content.ContentList, error)
}

type E3er interface {


@@ 398,12 398,6 @@ func (c *Content) search(w http.ResponseWriter, r *http.Request) {
		field = "name"
	}

	page, err := strconv.Atoi(r.URL.Query().Get("page"))
	if err != nil || page < 1 {
		page = 1
	}
	page-- // Show one to user but start counting at zero for us.

	user, err := c.GetCookieUser(w, r)
	if err != nil {
		c.log.Println(err)


@@ 415,15 409,18 @@ func (c *Content) search(w http.ResponseWriter, r *http.Request) {
	if err != nil {
		c.log.Println(err)
		c.Error(w, r, http.StatusInternalServerError, "failed to find required space")
		return
	}

	ct, err := c.db.ContentTypeGet(space, contenttypeID)
	if err != nil {
		c.log.Println(err)
		c.Error(w, r, http.StatusInternalServerError, "failed to find required contenttype")
		return
	}

	list, err := c.db.ContentSearch(space, ct, field, query, page)
	before, _ := strconv.Atoi(r.URL.Query().Get("before"))
	list, err := c.db.ContentSearch(space, ct, field, query, before)
	if err != nil {
		c.log.Println(err)
		c.Error(w, r, http.StatusInternalServerError, "failed to find desired content")

M internal/m/content/content.go => internal/m/content/content.go +1 -1
@@ 15,5 15,5 @@ type Content interface {
type ContentList interface {
	List() []Content
	More() bool
	Last() Content
	Last() int // Some table ID to fetch next set of results.
}

M internal/m/contenttype/contenttype.go => internal/m/contenttype/contenttype.go +1 -1
@@ 14,5 14,5 @@ type ContentType interface {
type ContentTypeList interface {
	List() []ContentType
	More() bool
	Last() ContentType
	Last() int
}

M internal/m/hook/hook.go => internal/m/hook/hook.go +1 -1
@@ 8,5 8,5 @@ type Hook interface {
type HookList interface {
	List() []Hook
	More() bool
	Last() Hook
	Last() int
}

M internal/m/space/space.go => internal/m/space/space.go +1 -1
@@ 9,5 9,5 @@ type Space interface {
type SpaceList interface {
	List() []Space
	More() bool
	Last() Space
	Last() int
}

M internal/s/db/content.go => internal/s/db/content.go +188 -112
@@ 3,6 3,7 @@ package db
import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"strings"



@@ 11,6 12,7 @@ import (
	"git.sr.ht/~evanj/cms/internal/m/space"
	"git.sr.ht/~evanj/cms/internal/m/value"
	"git.sr.ht/~evanj/cms/internal/m/valuetype"
	"github.com/google/uuid"
)

// iota doesn't quite pass the compile time checks I want.


@@ 21,6 23,17 @@ var (
	OrderDesc OrderType = OrderType{val: "DESC"}
)

func orderTypeReverse(o OrderType) OrderType {
	switch o {
	case OrderAsc:
		return OrderDesc
	case OrderDesc:
		return OrderAsc
	default:
		panic("unreachable")
	}
}

const (
	defaultDepth = 3 // For fetching reference types.
)


@@ 133,39 146,6 @@ var (
		WHERE ID = ?;
	`

	queryContentListByContentType = func(order OrderType) string {
		// Careful, we only do this for OrderType.
		return fmt.Sprintf(`
			SELECT cms_content.ID, cms_content.CONTENTTYPE_ID
			FROM cms_value
	
			JOIN cms_content
			ON cms_value.CONTENT_ID = cms_content.ID
	
			JOIN cms_contenttype_to_valuetype
			ON cms_contenttype_to_valuetype.ID = cms_value.CONTENTTYPE_TO_VALUETYPE_ID
	
			JOIN cms_valuetype
			ON cms_valuetype.ID = cms_contenttype_to_valuetype.VALUETYPE_ID
	
			LEFT JOIN cms_value_string_small
			ON cms_value_string_small.ID = cms_value.VALUE_ID
	
			LEFT JOIN cms_value_string_big
			ON cms_value_string_big.ID = cms_value.VALUE_ID
			
			LEFT JOIN cms_value_date
			ON cms_value_date.ID = cms_value.VALUE_ID
	
		 	WHERE cms_content.CONTENTTYPE_ID = ? 
		 	AND cms_contenttype_to_valuetype.NAME = ?
			AND cms_content.ID < ?
	
			ORDER BY cms_content.ID DESC, cms_value_date.VALUE %s, cms_value_string_small.VALUE %s, cms_value_string_big.VALUE %s
		 	LIMIT ? 
		`, order.val, order.val, order.val)
	}

	queryValueNew = `
		INSERT INTO cms_value (CONTENT_ID, CONTENTTYPE_TO_VALUETYPE_ID, VALUE_ID)
		VALUES (?, (SELECT ID FROM cms_contenttype_to_valuetype WHERE CONTENTTYPE_ID = ? AND NAME = ? LIMIT 1), ?);


@@ 372,37 352,6 @@ var (

		ORDER BY ORDER_ID ASC;
	`

	queryContentListByNameAndContentType = `
		SELECT cms_content.ID
		FROM cms_value

		JOIN cms_content
		ON cms_value.CONTENT_ID = cms_content.ID

		JOIN cms_contenttype_to_valuetype
		ON cms_contenttype_to_valuetype.ID = cms_value.CONTENTTYPE_TO_VALUETYPE_ID

		JOIN cms_valuetype
		ON cms_valuetype.ID = cms_contenttype_to_valuetype.VALUETYPE_ID

		LEFT JOIN cms_value_string_small
		ON cms_value_string_small.ID = cms_value.VALUE_ID

		LEFT JOIN cms_value_string_big
		ON cms_value_string_big.ID = cms_value.VALUE_ID
		
		LEFT JOIN cms_value_date
		ON cms_value_date.ID = cms_value.VALUE_ID

	 	WHERE cms_content.CONTENTTYPE_ID = ? 
	 	AND cms_contenttype_to_valuetype.NAME = ?
	 	AND (
			cms_value_string_small.VALUE LIKE ?
			OR cms_value_date.VALUE LIKE ?
		)
	 	LIMIT ? OFFSET ?;
	`
)

func (db *DB) valueReferenceListUpdate(s space.Space, ct contenttype.ContentType, c *Content, t *sql.Tx, valueID string, IDs []string, depth int) error {


@@ 784,15 733,108 @@ func (db *DB) ContentDelete(space space.Space, ct contenttype.ContentType, conte
	return t.Commit()
}

func sortinfo(t *sql.Tx, ct contenttype.ContentType, sortField string) (string, string, error) {
	var (
		sortFieldValueType string
		sortFieldTableName string
	)

	q := `
		SELECT VALUE FROM cms_contenttype_to_valuetype
		JOIN cms_valuetype ON cms_valuetype.ID=cms_contenttype_to_valuetype.VALUETYPE_ID
		WHERE NAME=? AND CONTENTTYPE_ID=?
	`
	if err := t.QueryRow(q, sortField, ct.ID()).Scan(&sortFieldValueType); err != nil {
		return "", "", err
	}

	switch sortFieldValueType {

	case valuetype.StringSmall:
		fallthrough
	case valuetype.File:
		sortFieldTableName = "cms_value_string_small"

	case valuetype.StringBig:
		fallthrough
	case valuetype.InputHTML:
		fallthrough
	case valuetype.InputMarkdown:
		sortFieldTableName = "cms_value_string_big"

	case valuetype.Date:
		sortFieldTableName = "cms_value_date"

	case valuetype.Reference:
	case valuetype.ReferenceList:
		return "", "", errors.New("cannot search by reference field type")

	default:
		return "", "", errors.New("unexpected error: failed to find table name for value type (developer error)")

	}

	return sortFieldValueType, sortFieldTableName, nil
}

func (db *DB) contentPerContentType(t *sql.Tx, space space.Space, ct contenttype.ContentType, before int, order OrderType, sortField string, depth int) (content.ContentList, error) {
	var (
		tmpID        int
		tmpContentID string

		r       []content.Content
		hasMore bool
	)

	before = beformat(before)
	order = orderTypeReverse(order)

	rows, err := db.Query(queryContentListByContentType(order), ct.ID(), sortField, before, perPage+1)
	// Create temporary table for queries.
	tbl := fmt.Sprintf("cms_tmp_cl_by_ct_%s", strings.ReplaceAll(uuid.New().String(), "-", "_"))

	// Get the table the sortField is part of.
	_, sortFieldTableName, err := sortinfo(t, ct, sortField)
	if err != nil {
		return nil, err
	}

	// Fill temporary table with data.
	q := fmt.Sprintf(`
		CREATE TEMPORARY TABLE %s (
			ID INTEGER PRIMARY KEY AUTO_INCREMENT,
			CONTENT_ID INTEGER NOT NULL
		)
	`, tbl)
	if _, err := t.Exec(q); err != nil {
		return nil, err
	}

	// Careful...
	q = fmt.Sprintf(`
		INSERT INTO %s (CONTENT_ID)

		SELECT cms_content.ID AS CONTENT_ID FROM cms_value

		JOIN cms_content ON cms_value.CONTENT_ID = cms_content.ID

		JOIN cms_contenttype_to_valuetype ON cms_contenttype_to_valuetype.ID = cms_value.CONTENTTYPE_TO_VALUETYPE_ID

		JOIN cms_valuetype ON cms_valuetype.ID = cms_contenttype_to_valuetype.VALUETYPE_ID

		LEFT JOIN %s ON %s.ID = cms_value.VALUE_ID

		WHERE cms_content.CONTENTTYPE_ID = ?
		AND cms_contenttype_to_valuetype.NAME = ?

		ORDER BY %s.VALUE %s
	`, tbl, sortFieldTableName, sortFieldTableName, sortFieldTableName, order.val)
	if _, err := t.Exec(q, ct.ID(), sortField); err != nil {
		return nil, err
	}

	// Query the temporary table.
	q = fmt.Sprintf("SELECT ID, CONTENT_ID FROM %s WHERE ID < ? ORDER BY ID DESC LIMIT ?", tbl)
	rows, err := t.Query(q, before, perPage+1)
	if err != nil {
		return nil, err
	}


@@ 804,38 846,19 @@ func (db *DB) contentPerContentType(t *sql.Tx, space space.Space, ct contenttype
			break
		}

		var content Content
		if err := rows.Scan(&content.ContentID, &content.ContentParentTypeID); err != nil {
		if err := rows.Scan(&tmpID, &tmpContentID); err != nil {
			return nil, err
		}

		rows, err := db.Query(queryValueListByContent, content.ContentID, content.ContentID, content.ContentID, content.ContentID, content.ContentID)
		c, err := db.ContentGet(space, ct, tmpContentID)
		if err != nil {
			return nil, err
		}
		defer rows.Close()

		for rows.Next() {
			var value ContentValue
			if err := rows.Scan(&value.FieldID, &value.FieldType, &value.FieldName, &value.FieldValue); err != nil {
				return nil, err
			}

			if err := db.contentValueAttachRef(t, &value, depth); err != nil {
				return nil, err
			}

			if err := db.contentValueAttachRefList(t, &value, depth); err != nil {
				return nil, err
			}

			content.ContentValues = append(content.ContentValues, value)
		}

		r = append(r, &content)
		r = append(r, c)
	}

	return newContentList(r, hasMore), nil
	return newContentList(r, hasMore, tmpID), nil
}

func (db *DB) ContentPerContentType(space space.Space, ct contenttype.ContentType, before int, order OrderType, sortField string) (content.ContentList, error) {


@@ 852,31 875,93 @@ func (db *DB) ContentPerContentType(space space.Space, ct contenttype.ContentTyp
	return list, t.Commit()
}

func (db *DB) ContentSearch(space space.Space, ct contenttype.ContentType, name, query string, page int) ([]content.Content, error) {
	s := fmt.Sprintf("%%%s%%", query)
func (db *DB) ContentSearch(space space.Space, ct contenttype.ContentType, sortField, query string, before int) (content.ContentList, error) {
	var (
		tmpID        int
		tmpContentID string

		s       = fmt.Sprintf("%%%s%%", query)
		r       []content.Content
		hasMore bool
	)

	before = beformat(before)

	// TODO: Move:
	t, err := db.Begin()
	if err != nil {
		return nil, err
	}

	// Create temporary table for queries.
	tbl := fmt.Sprintf("cms_tmp_cl_search_%s", strings.ReplaceAll(uuid.New().String(), "-", "_"))

	var ret []content.Content
	rows, err := db.Query(queryContentListByNameAndContentType, ct.ID(), name, s, s, perPage, perPage*page)
	// Get the table the sortField is part of.
	_, sortFieldTableName, err := sortinfo(t, ct, sortField)
	if err != nil {
		return nil, err
	}

	// Fill temporary table with data.
	q := fmt.Sprintf(`
		CREATE TEMPORARY TABLE %s (
			ID INTEGER PRIMARY KEY AUTO_INCREMENT,
			CONTENT_ID INTEGER NOT NULL
		)
	`, tbl)
	if _, err := t.Exec(q); err != nil {
		return nil, err
	}

	// Careful...
	q = fmt.Sprintf(`
		INSERT INTO %s (CONTENT_ID)

		SELECT cms_content.ID FROM cms_value

		JOIN cms_content ON cms_value.CONTENT_ID = cms_content.ID

		JOIN cms_contenttype_to_valuetype ON cms_contenttype_to_valuetype.ID = cms_value.CONTENTTYPE_TO_VALUETYPE_ID

		JOIN cms_valuetype ON cms_valuetype.ID = cms_contenttype_to_valuetype.VALUETYPE_ID

		LEFT JOIN %s ON %s.ID = cms_value.VALUE_ID

	 	WHERE cms_content.CONTENTTYPE_ID = ? 
	 	AND cms_contenttype_to_valuetype.NAME = ?
		AND %s.VALUE LIKE ?
	`, tbl, sortFieldTableName, sortFieldTableName, sortFieldTableName)
	if _, err := t.Exec(q, ct.ID(), sortField, s); err != nil {
		return nil, err
	}

	// Query the temporary table.
	q = fmt.Sprintf("SELECT ID, CONTENT_ID FROM %s WHERE ID < ? ORDER BY ID DESC LIMIT ?", tbl)
	rows, err := t.Query(q, before, perPage+1)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var contentID string
		if err := rows.Scan(&contentID); err != nil {
	for i := 0; rows.Next(); i++ {
		if i == perPage {
			hasMore = true
			break
		}

		if err := rows.Scan(&tmpID, &tmpContentID); err != nil {
			return nil, err
		}

		c, err := db.ContentGet(space, ct, contentID)
		c, err := db.ContentGet(space, ct, tmpContentID)
		if err != nil {
			return nil, err
		}

		ret = append(ret, c)
		r = append(r, c)
	}

	return ret, nil
	return newContentList(r, hasMore, tmpID), nil
}

func (db *DB) contentGet(t *sql.Tx, space space.Space, ct contenttype.ContentType, contentID string, depth int) (content.Content, error) {


@@ 1197,7 1282,7 @@ func (iter *contentIter) Scan() (content.Content, error) {
	list := iter.list.List()
	first, rest := list[0], list[1:]

	iter.list = newContentList(rest, iter.list.More())
	iter.list = newContentList(rest, iter.list.More(), iter.list.Last())
	if err != nil {
		return nil, err
	}


@@ 1215,22 1300,13 @@ func (iter *contentIter) Scan() (content.Content, error) {
type ContentList struct {
	ContentList     []content.Content
	ContentListMore bool
	ContentListLast content.Content
	ContentListLast int
}

func newContentList(list []content.Content, hasMore bool) *ContentList {
	var (
		r = ContentList{list, hasMore, nil}
		l = len(list)
	)

	if hasMore {
		r.ContentListLast = list[l-1]
	}

	return &r
func newContentList(list []content.Content, hasMore bool, last int) *ContentList {
	return &ContentList{list, hasMore, last}
}

func (cl *ContentList) List() []content.Content { return cl.ContentList }
func (cl *ContentList) More() bool              { return cl.ContentListMore }
func (cl *ContentList) Last() content.Content   { return cl.ContentListLast }
func (cl *ContentList) Last() int               { return cl.ContentListLast }

M internal/s/db/contenttype.go => internal/s/db/contenttype.go +8 -17
@@ 171,7 171,7 @@ func (db *DB) ContentTypeUpdate(space space.Space, contenttype contenttype.Conte
func (db *DB) contentTypesPerSpace(t *sql.Tx, space space.Space, before int) (contenttype.ContentTypeList, error) {
	var (
		r       []contenttype.ContentType
		id      string
		id      int
		hasMore bool
	)



@@ 199,7 199,7 @@ func (db *DB) contentTypesPerSpace(t *sql.Tx, space space.Space, before int) (co
			return nil, err
		}

		ct, err := db.contentTypeGet(t, space, id)
		ct, err := db.contentTypeGet(t, space, strconv.Itoa(id))
		if err != nil {
			return nil, err
		}


@@ 207,7 207,7 @@ func (db *DB) contentTypesPerSpace(t *sql.Tx, space space.Space, before int) (co
		r = append(r, ct)
	}

	return newContentTypeList(r, hasMore), nil
	return newContentTypeList(r, hasMore, id), nil
}

func (db *DB) ContentTypesPerSpace(space space.Space, before int) (contenttype.ContentTypeList, error) {


@@ 383,7 383,7 @@ func (iter *contentTypeIter) Scan() (contenttype.ContentType, error) {
	list := iter.list.List()
	first, rest := list[0], list[1:]

	iter.list = newContentTypeList(rest, iter.list.More())
	iter.list = newContentTypeList(rest, iter.list.More(), iter.list.Last())
	if err != nil {
		return nil, err
	}


@@ 401,22 401,13 @@ func (iter *contentTypeIter) Scan() (contenttype.ContentType, error) {
type ContentTypeList struct {
	ContentTypeList     []contenttype.ContentType
	ContentTypeListMore bool
	ContentTypeListLast contenttype.ContentType
	ContentTypeListLast int
}

func newContentTypeList(list []contenttype.ContentType, hasMore bool) *ContentTypeList {
	var (
		r = ContentTypeList{list, hasMore, nil}
		l = len(list)
	)

	if hasMore {
		r.ContentTypeListLast = list[l-1]
	}

	return &r
func newContentTypeList(list []contenttype.ContentType, hasMore bool, last int) *ContentTypeList {
	return &ContentTypeList{list, hasMore, last}
}

func (ctl *ContentTypeList) List() []contenttype.ContentType { return ctl.ContentTypeList }
func (ctl *ContentTypeList) More() bool                      { return ctl.ContentTypeListMore }
func (ctl *ContentTypeList) Last() contenttype.ContentType   { return ctl.ContentTypeListLast }
func (ctl *ContentTypeList) Last() int                       { return ctl.ContentTypeListLast }

M internal/s/db/hook.go => internal/s/db/hook.go +8 -16
@@ 2,6 2,7 @@ package db

import (
	"database/sql"
	"strconv"

	"git.sr.ht/~evanj/cms/internal/m/hook"
	"git.sr.ht/~evanj/cms/internal/m/space"


@@ 95,7 96,7 @@ func (db *DB) HookDelete(s space.Space, h hook.Hook) error {
func (db *DB) hooksPerSpace(t *sql.Tx, space space.Space, before int) (hook.HookList, error) {
	var (
		r       []hook.Hook
		id      string
		id      int
		hasMore bool
	)



@@ 122,7 123,7 @@ func (db *DB) hooksPerSpace(t *sql.Tx, space space.Space, before int) (hook.Hook
			return nil, err
		}

		ct, err := db.hookGet(t, space, id)
		ct, err := db.hookGet(t, space, strconv.Itoa(id))
		if err != nil {
			return nil, err
		}


@@ 130,7 131,7 @@ func (db *DB) hooksPerSpace(t *sql.Tx, space space.Space, before int) (hook.Hook
		r = append(r, ct)
	}

	return newHookList(r, hasMore), nil
	return newHookList(r, hasMore, id), nil
}

func (db *DB) HooksPerSpace(space space.Space, before int) (hook.HookList, error) {


@@ 159,22 160,13 @@ func (h *Hook) URL() string { return h.url }
type HookList struct {
	HookList     []hook.Hook
	HookListMore bool
	HookListLast hook.Hook
	HookListLast int
}

func newHookList(list []hook.Hook, hasMore bool) *HookList {
	var (
		r = HookList{list, hasMore, nil}
		l = len(list)
	)

	if hasMore {
		r.HookListLast = list[l-1]
	}

	return &r
func newHookList(list []hook.Hook, hasMore bool, last int) *HookList {
	return &HookList{list, hasMore, last}
}

func (hl *HookList) List() []hook.Hook { return hl.HookList }
func (hl *HookList) More() bool        { return hl.HookListMore }
func (hl *HookList) Last() hook.Hook   { return hl.HookListLast }
func (hl *HookList) Last() int         { return hl.HookListLast }

M internal/s/db/space.go => internal/s/db/space.go +7 -16
@@ 344,7 344,7 @@ func (db *DB) SpaceDelete(user user.User, space space.Space) error {
func (db *DB) spacesPerUser(t *sql.Tx, user user.User, before int) (space.SpaceList, error) {
	var (
		r       []space.Space
		id      string
		id      int
		hasMore bool
	)



@@ 371,7 371,7 @@ func (db *DB) spacesPerUser(t *sql.Tx, user user.User, before int) (space.SpaceL
			return nil, err
		}

		s, err := db.spaceGet(t, user, id)
		s, err := db.spaceGet(t, user, strconv.Itoa(id))
		if err != nil {
			return nil, err
		}


@@ 379,7 379,7 @@ func (db *DB) spacesPerUser(t *sql.Tx, user user.User, before int) (space.SpaceL
		r = append(r, s)
	}

	return newSpaceList(r, hasMore), nil
	return newSpaceList(r, hasMore, id), nil
}

func (db *DB) SpacesPerUser(user user.User, before int) (space.SpaceList, error) {


@@ 415,22 415,13 @@ func (s *Space) Desc() string {
type SpaceList struct {
	SpaceList     []space.Space
	SpaceListMore bool
	SpaceListLast space.Space
	SpaceListLast int
}

func newSpaceList(list []space.Space, hasMore bool) *SpaceList {
	var (
		r = SpaceList{list, hasMore, nil}
		l = len(list)
	)

	if hasMore {
		r.SpaceListLast = list[l-1]
	}

	return &r
func newSpaceList(list []space.Space, hasMore bool, last int) *SpaceList {
	return &SpaceList{list, hasMore, last}
}

func (sl *SpaceList) List() []space.Space { return sl.SpaceList }
func (sl *SpaceList) More() bool          { return sl.SpaceListMore }
func (sl *SpaceList) Last() space.Space   { return sl.SpaceListLast }
func (sl *SpaceList) Last() int           { return sl.SpaceListLast }

M internal/s/tmpl/html/contenttype.html => internal/s/tmpl/html/contenttype.html +1 -1
@@ 242,7 242,7 @@
                {{ end }}
                {{ if .ContentList.More }}
                <small class="d-block text-right mt-3">
                  <a href="/contenttype/{{ .Space.ID }}/{{ .ContentType.ID }}?before={{ .ContentList.Last.ID }}">Load more</a>
                  <a href="/contenttype/{{ .Space.ID }}/{{ .ContentType.ID }}?before={{ .ContentList.Last }}">Load more</a>
                </small>
                {{ end }}
              {{ else }}

M internal/s/tmpl/html/index.html => internal/s/tmpl/html/index.html +1 -1
@@ 78,7 78,7 @@
                  {{ end }}
                  {{ if .Spaces.More }}
                  <small class="d-block text-right mt-3">
                    <a href="/?before={{ .Spaces.Last.ID}}">Load more</a>
                    <a href="/?before={{ .Spaces.Last }}">Load more</a>
                  </small>
                  {{ end }}
                {{ else }}

M internal/s/tmpl/html/space.html => internal/s/tmpl/html/space.html +2 -2
@@ 174,7 174,7 @@
                {{ end }}
                {{ if .ContentTypes.More }}
                <small class="d-block text-right mt-3">
                  <a href="/space/{{ .Space.ID }}?beforect={{ .ContentTypes.Last.ID }}">Load more</a>
                  <a href="/space/{{ .Space.ID }}?beforect={{ .ContentTypes.Last }}">Load more</a>
                </small>
                {{ end }}
              {{ else }}


@@ 200,7 200,7 @@
                {{ end }}
                {{ if .Hooks.More }}
                <small class="d-block text-right mt-3">
                  <a href="/space/{{ .Space.ID }}?beforehook={{ .Hooks.Last.ID }}">Load more</a>
                  <a href="/space/{{ .Space.ID }}?beforehook={{ .Hooks.Last }}">Load more</a>
                </small>
                {{ end }}
              {{ else }}

M internal/s/tmpl/tmpls_embed.go => internal/s/tmpl/tmpls_embed.go +3 -3
@@ 30,13 30,13 @@ func init() {

	tmpls["html/content.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19IHwge3sgLkNvbnRlbnRUeXBlLk5hbWUgfX0gfCB7eyAoLkNvbnRlbnQuTXVzdFZhbHVlQnlOYW1lICJuYW1lIikuVmFsdWUgfX08L3RpdGxlPgo8L2hlYWQ+Cjxib2R5IGNsYXNzPSdjb250ZW50IGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+e3sgKC5Db250ZW50Lk11c3RWYWx1ZUJ5TmFtZSAibmFtZSIpLlZhbHVlIH19PC9oMT4KICAgIDwvZGl2PgogICAgPGFydGljbGUgY2xhc3M9J2NvbnRhaW5lcic+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0nY29sLTEyIGNvbC1sZy04IG9mZnNldC1sZy0yJz4KICAgICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL2NvbnRlbnQvdXBkYXRlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9Y29udGVudHR5cGUgdmFsdWU9Int7IC5Db250ZW50VHlwZS5JRCB9fSIgLz4KICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9Y29udGVudCB2YWx1ZT0ie3sgLkNvbnRlbnQuSUQgfX0iIC8+CgogICAgICAgICAgICB7eyByYW5nZSAkaW5kZXgsICRpdGVtIDo9IC5Db250ZW50VHlwZS5GaWVsZHMgfX0KICAgICAgICAgICAgICB7eyAkdmFsIDo9ICQuQ29udGVudC5NdXN0VmFsdWVCeU5hbWUgKCAkaXRlbS5OYW1lICkgfX0KCiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nZm9ybS1ncm91cCc+CiAgICAgICAgICAgICAge3sgaWYgJHZhbCB9fSAKICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSI+e3sgdGl0bGUgJHZhbC5OYW1lIH19PC9sYWJlbD4KCiAgICAgICAgICAgICAgICB7eyBpZiBlcSAkdmFsLlR5cGUgIlN0cmluZ1NtYWxsIiB9fQogICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY29udHJvbCIge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiB2YWx1ZT0ie3sgJHZhbC5WYWx1ZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9InZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSIgcGxhY2Vob2xkZXI9Int7ICR2YWwuTmFtZSB9fSIgLz4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQoKICAgICAgICAgICAgICAgIHt7IGlmIGVxICR2YWwuVHlwZSAiU3RyaW5nQmlnIiB9fQogICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCIge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiBwbGFjZWhvbGRlcj0ie3sgJHZhbC5OYW1lIH19Ij57eyAkdmFsLlZhbHVlIH19PC90ZXh0YXJlYT4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQoKICAgICAgICAgICAgICAgIHt7IGlmIGVxICR2YWwuVHlwZSAiSW5wdXRIVE1MIiB9fQogICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCBpbnB1dC1odG1sIiB7eyBpZiBlcSAkaW5kZXggMCB9fSBhdXRvZm9jdXMge3sgZW5kIH19IGlkPSJ2YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIHZhbHVlPSJ7eyAkdmFsLlZhbHVlIH19IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiBwbGFjZWhvbGRlcj0ie3sgJHZhbC5OYW1lIH19Ij57eyAkdmFsLlZhbHVlIH19PC90ZXh0YXJlYT4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQoKICAgICAgICAgICAgICAgIHt7IGlmIGVxICR2YWwuVHlwZSAiSW5wdXRNYXJrZG93biIgfX0KICAgICAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtbWFya2Rvd24iIHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gaWQ9InZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSIgdmFsdWU9Int7ICR2YWwuVmFsdWUgfX0iIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJ2YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIHBsYWNlaG9sZGVyPSJ7eyAkdmFsLk5hbWUgfX0iPnt7ICR2YWwuVmFsdWUgfX08L3RleHRhcmVhPgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgJHZhbC5UeXBlICJGaWxlIiB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb3JtLWZpbGUgbWItMyI+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gbmFtZT0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiBpZD0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiB2YWx1ZT0ie3sgJHZhbC5WYWx1ZSB9fSIgcmVxdWlyZWQgbXVsdGlwbGU9ZmFsc2UgdHlwZT0iZmlsZSIgY2xhc3M9ImZvcm0tZmlsZS1pbnB1dCI+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJmb3JtLWZpbGUtbGFiZWwiIGZvcj0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19Ij4KICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJmb3JtLWZpbGUtdGV4dCI+Q2hvb3NlIGZpbGUuLi48L3NwYW4+CiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iZm9ybS1maWxlLWJ1dHRvbiI+QnJvd3NlPC9zcGFuPgogICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgJHZhbC5UeXBlICJEYXRlIiB9fQogICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY29udHJvbCIge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiB2YWx1ZT0ie3sgJHZhbC5WYWx1ZSB9fSIgcmVxdWlyZWQgdHlwZT1kYXRlIG5hbWU9InZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSIgcGxhY2Vob2xkZXI9Int7ICR2YWwuTmFtZSB9fSIgLz4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQoKICAgICAgICAgICAgICAgIHt7IGlmIGVxICR2YWwuVHlwZSAiUmVmZXJlbmNlIiB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdyZWYtbW9kYWwnPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCB7eyBpZiBlcSAkaW5kZXggMCB9fSBhdXRvZm9jdXMge3sgZW5kIH19IGlkPSJ2YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIGNsYXNzPSdvdXRwdXQtcmVmJyByZXF1aXJlZCB0eXBlPWhpZGRlbiB2YWx1ZT0ie3sgJHZhbC5WYWx1ZSB9fSIgbmFtZT0idmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNtb2RhbF92YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtcmVmIHctYXV0byIgdHlwZT1idXR0b24gdmFsdWU9Int7IGlmICAkdmFsLlJlZk5hbWUgfX17eyAkdmFsLlJlZk5hbWUgfX17eyBlbHNlIH19T3Blbnt7IGVuZH19Ii8+CiAgICAgICAgICAgICAgICAgICAgPGRpdiBpZD0ibW9kYWxfdmFsdWVfdXBkYXRlX3t7ICR2YWwuVHlwZSB9fS17eyAkdmFsLklEIH19IiBkYXRhLWZvY3VzPSJmYWxzZSIgY2xhc3M9Im1vZGFsIGZhZGUiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9InJlZk1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctY2VudGVyZWQiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSI+RmluZCBDb250ZW50IGZvciBSZWZlcmVuY2U8L2g1PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzLWlubmVyPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J21vZGFsLWJvZHkgb3ZlcmZsb3ctaW5pdGlhbCc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9J2QtYmxvY2snPkNvbnRlbnQgVHlwZTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnR0eXBlJyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IFR5cGUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9J2QtYmxvY2snPkNvbnRlbnQgTmFtZTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgZGlzYWJsZWQgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnQnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgTmFtZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSBidG4tY2xlYXIiPkNsZWFyPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSIgZGF0YS1kaXNtaXNzLWlubmVyPSJtb2RhbCI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KCiAgICAgICAgICAgICAgICB7eyBpZiBlcSAkdmFsLlR5cGUgIlJlZmVyZW5jZUxpc3QiIH19CiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J3JlZi1tb2RhbCByZWYtbGlzdCc+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gaWQ9InZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSIgY2xhc3M9J291dHB1dC1yZWYnIHJlcXVpcmVkIHR5cGU9aGlkZGVuIHZhbHVlPSJ7eyAkdmFsLlZhbHVlIH19IiBuYW1lPSJ2YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNtb2RhbF92YWx1ZV91cGRhdGVfe3sgJHZhbC5UeXBlIH19LXt7ICR2YWwuSUQgfX0iIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtcmVmIHctYXV0byIgdHlwZT1idXR0b24gdmFsdWU9Int7IGlmICAkdmFsLlJlZkxpc3ROYW1lcyB9fXt7ICR2YWwuUmVmTGlzdE5hbWVzIH19e3sgZWxzZSB9fU9wZW57eyBlbmR9fSIvPgogICAgICAgICAgICAgICAgICAgIDxkaXYgaWQ9Im1vZGFsX3ZhbHVlX3VwZGF0ZV97eyAkdmFsLlR5cGUgfX0te3sgJHZhbC5JRCB9fSIgZGF0YS1mb2N1cz0iZmFsc2UiIGNsYXNzPSJtb2RhbCBmYWRlIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJyZWZNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLWNlbnRlcmVkIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiPkZpbmQgQ29udGVudCBmb3IgUmVmZXJlbmNlPC9oNT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdtb2RhbC1ib2R5IG92ZXJmbG93LWluaXRpYWwnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IFR5cGU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50dHlwZScgdHlwZT10ZXh0IHBsYWNlaG9sZGVyPSdTZWFyY2ggYnkgQ29udGVudCBUeXBlJyAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IE5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRpc2FibGVkIGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50JyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IE5hbWUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkgYnRuLWNsZWFyIj5DbGVhcjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIj48L2Rpdj4KICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJ2YWx1ZV91cGRhdGVfe3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iPnt7IHRpdGxlIC5OYW1lIH19PC9sYWJlbD4KCiAgICAgICAgICAgICAgICB7eyBpZiBlcSAuVHlwZSAiU3RyaW5nU21hbGwiIH19CiAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz0iZm9ybS1jb250cm9sIiB7eyBpZiBlcSAkaW5kZXggMCB9fSBhdXRvZm9jdXMge3sgZW5kIH19IGlkPSJ2YWx1ZV91cGRhdGVfe3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcGxhY2Vob2xkZXI9Int7IC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlN0cmluZ0JpZyIgfX0KICAgICAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPSJmb3JtLWNvbnRyb2wiIHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gaWQ9InZhbHVlX3VwZGF0ZV97eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIklucHV0SFRNTCIgfX0KICAgICAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtaHRtbCIge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7IC5UeXBlIH19LXt7IC5OYW1lIH19IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHBsYWNlaG9sZGVyPSJ7eyAuTmFtZSB9fSIgPjwvdGV4dGFyZWE+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KCiAgICAgICAgICAgICAgICB7eyBpZiBlcSAuVHlwZSAiSW5wdXRNYXJrZG93biIgfX0KICAgICAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtbWFya2Rvd24iIHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gaWQ9InZhbHVlX3VwZGF0ZV97eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIkZpbGUiIH19CiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvcm0tZmlsZSBtYi0zIj4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgbXVsdGlwbGU9ZmFsc2UgdHlwZT0iZmlsZSIgY2xhc3M9ImZvcm0tZmlsZS1pbnB1dCI+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJmb3JtLWZpbGUtbGFiZWwiIGZvcj0idmFsdWVfdXBkYXRlX3t7IC5UeXBlIH19LXt7IC5OYW1lIH19Ij4KICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJmb3JtLWZpbGUtdGV4dCI+Q2hvb3NlIGZpbGUuLi48L3NwYW4+CiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iZm9ybS1maWxlLWJ1dHRvbiI+QnJvd3NlPC9zcGFuPgogICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIkRhdGUiIH19CiAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz0iZm9ybS1jb250cm9sIiB7eyBpZiBlcSAkaW5kZXggMCB9fSBhdXRvZm9jdXMge3sgZW5kIH19IGlkPSJ2YWx1ZV91cGRhdGVfe3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9ZGF0ZSBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcGxhY2Vob2xkZXI9Int7IC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZSIgfX0KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ncmVmLW1vZGFsJz4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQge3sgaWYgZXEgJGluZGV4IDAgfX0gYXV0b2ZvY3VzIHt7IGVuZCB9fSBpZD0idmFsdWVfdXBkYXRlX3t7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0nb3V0cHV0LXJlZicgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNtb2RhbF92YWx1ZV91cGRhdGVfe3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtcmVmIHctYXV0byIgdHlwZT1idXR0b24gdmFsdWU9T3BlbiAvPgogICAgICAgICAgICAgICAgICAgIDxkaXYgaWQ9Im1vZGFsX3ZhbHVlX3VwZGF0ZV97eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgZGF0YS1mb2N1cz0iZmFsc2UiIGNsYXNzPSJtb2RhbCBmYWRlIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJyZWZNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLWNlbnRlcmVkIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiPkZpbmQgQ29udGVudCBmb3IgUmVmZXJlbmNlPC9oNT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdtb2RhbC1ib2R5IG92ZXJmbG93LWluaXRpYWwnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IFR5cGU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50dHlwZScgdHlwZT10ZXh0IHBsYWNlaG9sZGVyPSdTZWFyY2ggYnkgQ29udGVudCBUeXBlJyAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IE5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRpc2FibGVkIGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50JyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IE5hbWUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkgYnRuLWNsZWFyIj5DbGVhcjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZUxpc3QiIH19CiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J3JlZi1tb2RhbCByZWYtbGlzdCc+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHt7IGlmIGVxICRpbmRleCAwIH19IGF1dG9mb2N1cyB7eyBlbmQgfX0gaWQ9InZhbHVlX3VwZGF0ZV97eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgY2xhc3M9J291dHB1dC1yZWYnIHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjbW9kYWxfdmFsdWVfdXBkYXRlX3t7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0iZm9ybS1jb250cm9sIGlucHV0LXJlZiB3LWF1dG8iIHR5cGU9YnV0dG9uIHZhbHVlPU9wZW4gLz4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGlkPSJtb2RhbF92YWx1ZV91cGRhdGVfe3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGRhdGEtZm9jdXM9ImZhbHNlIiBjbGFzcz0ibW9kYWwgZmFkZSIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0icmVmTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1jZW50ZXJlZCI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIj5GaW5kIENvbnRlbnQgZm9yIFJlZmVyZW5jZTwvaDU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nbW9kYWwtYm9keSBvdmVyZmxvdy1pbml0aWFsJz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0nZC1ibG9jayc+Q29udGVudCBUeXBlPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz0nbWItMyBmb3JtLWNvbnRyb2wgaW5wdXQtY29udGVudHR5cGUnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgVHlwZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0nZC1ibG9jayc+Q29udGVudCBOYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBkaXNhYmxlZCBjbGFzcz0nbWItMyBmb3JtLWNvbnRyb2wgaW5wdXQtY29udGVudCcgdHlwZT10ZXh0IHBsYWNlaG9sZGVyPSdTZWFyY2ggYnkgQ29udGVudCBOYW1lJyAvPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IGJ0bi1jbGVhciI+Q2xlYXI8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIj5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdyZWYtbW9kYWwnPgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIj48L2Rpdj4KICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAge3sgZW5kfX0KICAgICAgICAgICAgPGRpdiBjbGFzcz0nZC1mbGV4IGp1c3RpZnktY29udGVudC1lbmQgbWItMyc+CiAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPlNhdmU8L2J1dHRvbj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Zvcm0+CgogICAgICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudC9kZWxldGUnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50dHlwZSB2YWx1ZT0ie3sgLkNvbnRlbnRUeXBlLklEIH19IiAvPgogICAgICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50IHZhbHVlPSJ7eyAuQ29udGVudC5JRCB9fSIgLz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9ImRlbGV0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJkZWxldGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJkZWxldGVNb2RhbExhYmVsIj5EZWxldGUge3sgKC5Db250ZW50Lk11c3RWYWx1ZUJ5TmFtZSAibmFtZSIpLlZhbHVlIH19PC9oNT4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Zvcm0+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZGl2PgogICAgPC9hcnRpY2xlPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQogIDxzY3JpcHQgc3JjPSIvL3VucGtnLmNvbS90aW55bWNlQDUuMi4wL3RpbnltY2UubWluLmpzIj48L3NjcmlwdD4KICA8c2NyaXB0IHNyYz0nLy91bnBrZy5jb20vYXV0b2NvbXBsZXRlLmpzQDAuMzcuMS9kaXN0L2F1dG9jb21wbGV0ZS5taW4uanMnPjwvc2NyaXB0PgogIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL21haW4uanMiICQgfX08L3NjcmlwdD4KICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9jb250ZW50LmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")

	tmpls["html/contenttype.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+Cgo8aGVhZD4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9faGVhZC5odG1sIiB9fQogIDx0aXRsZT5DTVMgfCB7eyAuU3BhY2UuTmFtZSB9fSB8IHt7IC5Db250ZW50VHlwZS5OYW1lIH19PC90aXRsZT4KPC9oZWFkPgoKPGJvZHkgY2xhc3M9J2NvbnRlbnR0eXBlIGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+e3suQ29udGVudFR5cGUuTmFtZX19PC9oMT4KICAgIDwvZGl2PgogICAgPGFydGljbGU+CiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL2NvbnRlbnR0eXBlL2RlbGV0ZScgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50dHlwZSB2YWx1ZT0ie3sgLkNvbnRlbnRUeXBlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJkZWxldGVNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iZGVsZXRlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJkZWxldGVNb2RhbExhYmVsIj5EZWxldGUge3suQ29udGVudFR5cGUuTmFtZX19PC9oNT4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcz0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9jb250ZW50L25ldycgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50dHlwZSB2YWx1ZT0ie3sgLkNvbnRlbnRUeXBlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjcmVhdGVNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iY3JlYXRlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtbGcgbW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJjcmVhdGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcge3suQ29udGVudFR5cGUuTmFtZX19IGNvbnRlbnQ8L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAge3sgcmFuZ2UgJGluZGV4IDo9IC5Db250ZW50VHlwZS5GaWVsZHMgfX0KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nZm9ybS1ncm91cCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iPnt7dGl0bGUgLk5hbWV9fTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlN0cmluZ1NtYWxsIiB9fQogICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPSJmb3JtLWNvbnRyb2wiIGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcGxhY2Vob2xkZXI9Int7IHRpdGxlIC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdCaWciIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJJbnB1dEhUTUwiIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCBpbnB1dC1odG1sIiBpZD0iY3JlYXRlLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHBsYWNlaG9sZGVyPSJ7eyB0aXRsZSAuTmFtZSB9fSIgPjwvdGV4dGFyZWE+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIklucHV0TWFya2Rvd24iIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCBpbnB1dC1tYXJrZG93biIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJGaWxlIiB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9ybS1maWxlIG1iLTMiPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIG11bHRpcGxlPWZhbHNlIGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9ImZpbGUiIGNsYXNzPSJmb3JtLWZpbGUtaW5wdXQiIGlkPSJpbnB1dEdyb3VwRmlsZUFkZG9ue3sgJGluZGV4IH19Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJmb3JtLWZpbGUtbGFiZWwiIGZvcj0iaW5wdXRHcm91cEZpbGVBZGRvbnt7ICRpbmRleCB9fSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImZvcm0tZmlsZS10ZXh0Ij5DaG9vc2UgZmlsZS4uLjwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iZm9ybS1maWxlLWJ1dHRvbiI+QnJvd3NlPC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIkRhdGUiIH19CiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY29udHJvbCIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT1kYXRlIG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZSIgfX0KICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J3JlZi1tb2RhbCc+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0iY3JlYXRlLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0nb3V0cHV0LXJlZicgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjcmVmLW1vZGFsLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0iZm9ybS1jb250cm9sIGlucHV0LXJlZiB3LWF1dG8iIHR5cGU9YnV0dG9uIHZhbHVlPU9wZW4gLz4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBkYXRhLWZvY3VzPSJmYWxzZSIgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJyZWYtbW9kYWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9InJlZk1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLWNlbnRlcmVkIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJyZWYtbW9kYWwtbGFiZWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iPkZpbmQgQ29udGVudCBmb3IgUmVmZXJlbmNlPC9oNT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J21vZGFsLWJvZHkgb3ZlcmZsb3ctaW5pdGlhbCc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0nc2VhcmNoLWN0LXt7IC5UeXBlIH19LXt7IC5OYW1lIH19JyBjbGFzcz0nZC1ibG9jayc+Q29udGVudCBUeXBlPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgaWQ9J3NlYXJjaC1jdC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnR0eXBlJyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IFR5cGUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0nc2VhcmNoLWMte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IE5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0nc2VhcmNoLWMte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGRpc2FibGVkIGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50JyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IE5hbWUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkgYnRuLWNsZWFyIj5DbGVhcjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIj5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJSZWZlcmVuY2VMaXN0IiB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ncmVmLW1vZGFsIHJlZi1saXN0Jz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGNsYXNzPSdvdXRwdXQtcmVmJyByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgLz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNyZWYtbW9kYWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtcmVmIHctYXV0byIgdHlwZT1idXR0b24gdmFsdWU9T3BlbiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGRhdGEtZm9jdXM9ImZhbHNlIiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InJlZi1tb2RhbC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0icmVmTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctY2VudGVyZWQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9InJlZi1tb2RhbC1sYWJlbC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSI+RmluZCBDb250ZW50IGZvciBSZWZlcmVuY2U8L2g1PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nbW9kYWwtYm9keSBvdmVyZmxvdy1pbml0aWFsJz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSdzZWFyY2gtY3Qte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IFR5cGU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0nc2VhcmNoLWN0LXt7IC5UeXBlIH19LXt7IC5OYW1lIH19JyBjbGFzcz0nbWItMyBmb3JtLWNvbnRyb2wgaW5wdXQtY29udGVudHR5cGUnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgVHlwZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSdzZWFyY2gtYy17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgY2xhc3M9J2QtYmxvY2snPkNvbnRlbnQgTmFtZTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGlkPSdzZWFyY2gtYy17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgZGlzYWJsZWQgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnQnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgTmFtZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSBidG4tY2xlYXIiPkNsZWFyPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudHR5cGUvdXBkYXRlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPWNvbnRlbnR0eXBlIHZhbHVlPSJ7eyAuQ29udGVudFR5cGUuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InVwZGF0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJVcGRhdGUge3suQ29udGVudFR5cGUuTmFtZX19IiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvbnRlbnR0eXBlTW9kYWxMYWJlbCI+VXBkYXRlIHt7LkNvbnRlbnRUeXBlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjb250ZW50dHlwZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IHZhbHVlPSJ7ey5Db250ZW50VHlwZS5OYW1lfX0iIG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9ImNvbnRlbnR0eXBlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8ZGl2PgogICAgICAgICAgICAgICAgICB7eyByYW5nZSAkaW5kZXgsICRpdGVtIDo9IC5Db250ZW50VHlwZS5GaWVsZHMgfX0KICAgICAgICAgICAgICAgICAgICB7eyBpZiBlcSAkaW5kZXggMCB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBpZD0nZmlyc3QtZmllbGRzZXQnIGNsYXNzPSdjb250YWluZXItZmx1aWQgcHgtMCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iZmllbGRzZXRGaXJzdCI+RmllbGRzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9ImZpZWxkX3VwZGF0ZV9pZF97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLklEIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiByZWFkb25seT0icmVhZG9ubHkiIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJmaWVsZF91cGRhdGVfbmFtZV97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2Zvcm0tZ3JvdXAgcm93Jz4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtNic+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPSJ3LTEwMCBmb3JtLWNvbnRyb2wiIHZhbHVlPSJ7eyAuVHlwZSB9fSIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCBuYW1lPSJmaWVsZF91cGRhdGVfdHlwZV97eyBpbmMgJGluZGV4IH19Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT5GaWVsZCBUeXBlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gc2VsZWN0ZWQgdmFsdWU9IlN0cmluZ1NtYWxsIj5TdHJpbmcgU21hbGw8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iU3RyaW5nQmlnIj5TdHJpbmcgQmlnPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IklucHV0SFRNTCI+SFRNTDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJJbnB1dE1hcmtkb3duIj5NYXJrZG93bjwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJGaWxlIj5GaWxlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IkRhdGUiPkRhdGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlIj5SZWZlcmVuY2U8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlTGlzdCI+UmVmZXJlbmNlTGlzdDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndy0xMDAgYnRuIGJ0bi1wcmltYXJ5JyBkaXNhYmxlZCB0eXBlPWJ1dHRvbj5SZW1vdmUgRmllbGQ8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb250YWluZXItZmx1aWQgcHgtMCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9ImZpZWxkX3VwZGF0ZV9pZF97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLklEIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0iZmllbGRfdXBkYXRlX25hbWVfe3sgaW5jICRpbmRleCB9fSIgdmFsdWU9Int7IC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdmb3JtLWdyb3VwIHJvdyc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz0idy0xMDAgZm9ybS1jb250cm9sIiB2YWx1ZT0ie3sgLlR5cGUgfX0iIHJlYWRvbmx5PSJyZWFkb25seSIgcmVxdWlyZWQgbmFtZT0iZmllbGRfdXBkYXRlX3R5cGVfe3sgaW5jICRpbmRleCB9fSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU+RmllbGQgVHlwZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdTbWFsbCIgfX0gICBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iU3RyaW5nU21hbGwiPlN0cmluZyBTbWFsbDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdCaWciIH19ICAgICBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iU3RyaW5nQmlnIj5TdHJpbmcgQmlnPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIklucHV0SFRNTCIgfX0gICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJJbnB1dEhUTUwiPkhUTUw8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB7eyBpZiBlcSAuVHlwZSAiSW5wdXRNYXJrZG93biIgfX0gc2VsZWN0ZWQge3sgZWxzZSB9fSBkaXNhYmxlZCB7eyBlbmQgfX0gdmFsdWU9IklucHV0TWFya2Rvd24iPk1hcmtkb3duPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIkZpbGUiIH19ICAgICAgICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJGaWxlIj5GaWxlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIkRhdGUiIH19ICAgICAgICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJEYXRlIj5EYXRlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZSIgfX0gICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJSZWZlcmVuY2UiPlJlZmVyZW5jZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJSZWZlcmVuY2VMaXN0IiB9fSBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iUmVmZXJlbmNlTGlzdCI+UmVmZXJlbmNlTGlzdDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndy0xMDAgYnRuIGJ0bi1wcmltYXJ5IGJ0bi1yZW1vdmUnIHR5cGU9YnV0dG9uPlJlbW92ZSBGaWVsZDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgIDxhIGhyZWY9JyMnIGNsYXNzPSdidG4gYnRuLWxpbmsnIGlkPSdhZGQtZmllbGRidG4nPkFkZCBBbm90aGVyIEZpZWxkPC9hPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KCiAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgPGRpdiBjbGFzcz0ncm93Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J29mZnNldC1sZy0zIGNvbC1sZy02Jz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPSJkLWJsb2NrIHRleHQtcmlnaHQgZmxvYXQtcmlnaHQiIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNjcmVhdGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9IiMiPkNyZWF0ZSBhIG5ldyBjb250ZW50PC9hPgogICAgICAgICAgICAgICAgPC9zbWFsbD4KICAgICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIge3suQ29udGVudFR5cGUuTmFtZX19IGNvbnRlbnQ8L2g2PgogICAgICAgICAgICAgIHt7IGlmIC5Db250ZW50TGlzdC5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuQ29udGVudExpc3QuTGlzdCB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibWVkaWEgdGV4dC1tdXRlZCBwdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0nL2NvbnRlbnQve3sgJC5TcGFjZS5JRCB9fS97eyAkLkNvbnRlbnRUeXBlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj4KICAgICAgICAgICAgICAgICAgICAgIHt7ICguTXVzdFZhbHVlQnlOYW1lICJuYW1lIikuVmFsdWUgfX0KICAgICAgICAgICAgICAgICAgICA8L3N0cm9uZz4KICAgICAgICAgICAgICAgICAgPC9hPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgIHt7IGlmIC5Db250ZW50TGlzdC5Nb3JlIH19CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBtdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iL2NvbnRlbnR0eXBlL3t7IC5TcGFjZS5JRCB9fS97eyAuQ29udGVudFR5cGUuSUQgfX0/YmVmb3JlPXt7IC5Db250ZW50TGlzdC5MYXN0LklEIH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtMyBhbGVydCBhbGVydC1wcmltYXJ5IiByb2xlPSJhbGVydCI+CiAgICAgICAgICAgICAgICAgIFlvdSBoYXZlbid0IGNyZWF0ZWQgYW55IGNvbnRlbnQgeWV0LiAKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvYXJ0aWNsZT4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgfX0KICA8L21haW4+CiAge3sgdGVtcGxhdGUgImh0bWwvX3NjcmlwdHMuaHRtbCIgfX0KICA8c2NyaXB0IHNyYz0nLy91bnBrZy5jb20vdGlueW1jZUA1LjIuMC90aW55bWNlLm1pbi5qcyc+PC9zY3JpcHQ+CiAgPHNjcmlwdCBzcmM9Jy8vdW5wa2cuY29tL2F1dG9jb21wbGV0ZS5qc0AwLjM3LjEvZGlzdC9hdXRvY29tcGxldGUubWluLmpzJz48L3NjcmlwdD4KICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9tYWluLmpzIiAkIH19PC9zY3JpcHQ+CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvc3BhY2UuanMiICQgfX08L3NjcmlwdD4KICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9jb250ZW50LmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")
	tmpls["html/contenttype.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+Cgo8aGVhZD4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9faGVhZC5odG1sIiB9fQogIDx0aXRsZT5DTVMgfCB7eyAuU3BhY2UuTmFtZSB9fSB8IHt7IC5Db250ZW50VHlwZS5OYW1lIH19PC90aXRsZT4KPC9oZWFkPgoKPGJvZHkgY2xhc3M9J2NvbnRlbnR0eXBlIGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+e3suQ29udGVudFR5cGUuTmFtZX19PC9oMT4KICAgIDwvZGl2PgogICAgPGFydGljbGU+CiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL2NvbnRlbnR0eXBlL2RlbGV0ZScgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50dHlwZSB2YWx1ZT0ie3sgLkNvbnRlbnRUeXBlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJkZWxldGVNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iZGVsZXRlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJkZWxldGVNb2RhbExhYmVsIj5EZWxldGUge3suQ29udGVudFR5cGUuTmFtZX19PC9oNT4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcz0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9jb250ZW50L25ldycgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1jb250ZW50dHlwZSB2YWx1ZT0ie3sgLkNvbnRlbnRUeXBlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjcmVhdGVNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iY3JlYXRlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtbGcgbW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1zY3JvbGxhYmxlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJjcmVhdGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcge3suQ29udGVudFR5cGUuTmFtZX19IGNvbnRlbnQ8L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAge3sgcmFuZ2UgJGluZGV4IDo9IC5Db250ZW50VHlwZS5GaWVsZHMgfX0KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nZm9ybS1ncm91cCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iPnt7dGl0bGUgLk5hbWV9fTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlN0cmluZ1NtYWxsIiB9fQogICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPSJmb3JtLWNvbnRyb2wiIGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcGxhY2Vob2xkZXI9Int7IHRpdGxlIC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdCaWciIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJJbnB1dEhUTUwiIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCBpbnB1dC1odG1sIiBpZD0iY3JlYXRlLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHBsYWNlaG9sZGVyPSJ7eyB0aXRsZSAuTmFtZSB9fSIgPjwvdGV4dGFyZWE+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIklucHV0TWFya2Rvd24iIH19CiAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9ImZvcm0tY29udHJvbCBpbnB1dC1tYXJrZG93biIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT10ZXh0IG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iID48L3RleHRhcmVhPgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJGaWxlIiB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9ybS1maWxlIG1iLTMiPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIG11bHRpcGxlPWZhbHNlIGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHJlcXVpcmVkIHR5cGU9ImZpbGUiIGNsYXNzPSJmb3JtLWZpbGUtaW5wdXQiIGlkPSJpbnB1dEdyb3VwRmlsZUFkZG9ue3sgJGluZGV4IH19Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJmb3JtLWZpbGUtbGFiZWwiIGZvcj0iaW5wdXRHcm91cEZpbGVBZGRvbnt7ICRpbmRleCB9fSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImZvcm0tZmlsZS10ZXh0Ij5DaG9vc2UgZmlsZS4uLjwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iZm9ybS1maWxlLWJ1dHRvbiI+QnJvd3NlPC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIkRhdGUiIH19CiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY29udHJvbCIgaWQ9ImNyZWF0ZS17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgcmVxdWlyZWQgdHlwZT1kYXRlIG5hbWU9Int7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBwbGFjZWhvbGRlcj0ie3sgdGl0bGUgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgICAge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZSIgfX0KICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J3JlZi1tb2RhbCc+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0iY3JlYXRlLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0nb3V0cHV0LXJlZicgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT0ie3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjcmVmLW1vZGFsLXt7IC5UeXBlIH19LXt7IC5OYW1lIH19IiBjbGFzcz0iZm9ybS1jb250cm9sIGlucHV0LXJlZiB3LWF1dG8iIHR5cGU9YnV0dG9uIHZhbHVlPU9wZW4gLz4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBkYXRhLWZvY3VzPSJmYWxzZSIgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJyZWYtbW9kYWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9InJlZk1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLWNlbnRlcmVkIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJyZWYtbW9kYWwtbGFiZWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iPkZpbmQgQ29udGVudCBmb3IgUmVmZXJlbmNlPC9oNT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J21vZGFsLWJvZHkgb3ZlcmZsb3ctaW5pdGlhbCc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0nc2VhcmNoLWN0LXt7IC5UeXBlIH19LXt7IC5OYW1lIH19JyBjbGFzcz0nZC1ibG9jayc+Q29udGVudCBUeXBlPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgaWQ9J3NlYXJjaC1jdC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnR0eXBlJyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IFR5cGUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0nc2VhcmNoLWMte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IE5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0nc2VhcmNoLWMte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGRpc2FibGVkIGNsYXNzPSdtYi0zIGZvcm0tY29udHJvbCBpbnB1dC1jb250ZW50JyB0eXBlPXRleHQgcGxhY2Vob2xkZXI9J1NlYXJjaCBieSBDb250ZW50IE5hbWUnIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkgYnRuLWNsZWFyIj5DbGVhcjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLWRpc21pc3MtaW5uZXI9Im1vZGFsIj5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICAgIHt7IGlmIGVxIC5UeXBlICJSZWZlcmVuY2VMaXN0IiB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ncmVmLW1vZGFsIHJlZi1saXN0Jz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGlkPSJjcmVhdGUte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGNsYXNzPSdvdXRwdXQtcmVmJyByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPSJ7eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgLz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNyZWYtbW9kYWwte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0iIGNsYXNzPSJmb3JtLWNvbnRyb2wgaW5wdXQtcmVmIHctYXV0byIgdHlwZT1idXR0b24gdmFsdWU9T3BlbiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGRhdGEtZm9jdXM9ImZhbHNlIiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InJlZi1tb2RhbC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0icmVmTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctY2VudGVyZWQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY29udGVudCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9InJlZi1tb2RhbC1sYWJlbC17eyAuVHlwZSB9fS17eyAuTmFtZSB9fSI+RmluZCBDb250ZW50IGZvciBSZWZlcmVuY2U8L2g1PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nbW9kYWwtYm9keSBvdmVyZmxvdy1pbml0aWFsJz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSdzZWFyY2gtY3Qte3sgLlR5cGUgfX0te3sgLk5hbWUgfX0nIGNsYXNzPSdkLWJsb2NrJz5Db250ZW50IFR5cGU8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBpZD0nc2VhcmNoLWN0LXt7IC5UeXBlIH19LXt7IC5OYW1lIH19JyBjbGFzcz0nbWItMyBmb3JtLWNvbnRyb2wgaW5wdXQtY29udGVudHR5cGUnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgVHlwZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSdzZWFyY2gtYy17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgY2xhc3M9J2QtYmxvY2snPkNvbnRlbnQgTmFtZTwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGlkPSdzZWFyY2gtYy17eyAuVHlwZSB9fS17eyAuTmFtZSB9fScgZGlzYWJsZWQgY2xhc3M9J21iLTMgZm9ybS1jb250cm9sIGlucHV0LWNvbnRlbnQnIHR5cGU9dGV4dCBwbGFjZWhvbGRlcj0nU2VhcmNoIGJ5IENvbnRlbnQgTmFtZScgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSBidG4tY2xlYXIiPkNsZWFyPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtZGlzbWlzcy1pbm5lcj0ibW9kYWwiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudHR5cGUvdXBkYXRlJyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPWNvbnRlbnR0eXBlIHZhbHVlPSJ7eyAuQ29udGVudFR5cGUuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InVwZGF0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJVcGRhdGUge3suQ29udGVudFR5cGUuTmFtZX19IiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvbnRlbnR0eXBlTW9kYWxMYWJlbCI+VXBkYXRlIHt7LkNvbnRlbnRUeXBlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjb250ZW50dHlwZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IHZhbHVlPSJ7ey5Db250ZW50VHlwZS5OYW1lfX0iIG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9ImNvbnRlbnR0eXBlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8ZGl2PgogICAgICAgICAgICAgICAgICB7eyByYW5nZSAkaW5kZXgsICRpdGVtIDo9IC5Db250ZW50VHlwZS5GaWVsZHMgfX0KICAgICAgICAgICAgICAgICAgICB7eyBpZiBlcSAkaW5kZXggMCB9fQogICAgICAgICAgICAgICAgICAgICAgPGRpdiBpZD0nZmlyc3QtZmllbGRzZXQnIGNsYXNzPSdjb250YWluZXItZmx1aWQgcHgtMCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iZmllbGRzZXRGaXJzdCI+RmllbGRzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9ImZpZWxkX3VwZGF0ZV9pZF97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLklEIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiByZWFkb25seT0icmVhZG9ubHkiIHJlcXVpcmVkIHR5cGU9dGV4dCBuYW1lPSJmaWVsZF91cGRhdGVfbmFtZV97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLk5hbWUgfX0iIC8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2Zvcm0tZ3JvdXAgcm93Jz4KICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtNic+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPSJ3LTEwMCBmb3JtLWNvbnRyb2wiIHZhbHVlPSJ7eyAuVHlwZSB9fSIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCBuYW1lPSJmaWVsZF91cGRhdGVfdHlwZV97eyBpbmMgJGluZGV4IH19Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT5GaWVsZCBUeXBlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gc2VsZWN0ZWQgdmFsdWU9IlN0cmluZ1NtYWxsIj5TdHJpbmcgU21hbGw8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iU3RyaW5nQmlnIj5TdHJpbmcgQmlnPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IklucHV0SFRNTCI+SFRNTDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJJbnB1dE1hcmtkb3duIj5NYXJrZG93bjwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJGaWxlIj5GaWxlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IkRhdGUiPkRhdGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlIj5SZWZlcmVuY2U8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iUmVmZXJlbmNlTGlzdCI+UmVmZXJlbmNlTGlzdDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndy0xMDAgYnRuIGJ0bi1wcmltYXJ5JyBkaXNhYmxlZCB0eXBlPWJ1dHRvbj5SZW1vdmUgRmllbGQ8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb250YWluZXItZmx1aWQgcHgtMCBtYi0zJz4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9ImZpZWxkX3VwZGF0ZV9pZF97eyBpbmMgJGluZGV4IH19IiB2YWx1ZT0ie3sgLklEIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0iZmllbGRfdXBkYXRlX25hbWVfe3sgaW5jICRpbmRleCB9fSIgdmFsdWU9Int7IC5OYW1lIH19IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdmb3JtLWdyb3VwIHJvdyc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz0idy0xMDAgZm9ybS1jb250cm9sIiB2YWx1ZT0ie3sgLlR5cGUgfX0iIHJlYWRvbmx5PSJyZWFkb25seSIgcmVxdWlyZWQgbmFtZT0iZmllbGRfdXBkYXRlX3R5cGVfe3sgaW5jICRpbmRleCB9fSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU+RmllbGQgVHlwZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdTbWFsbCIgfX0gICBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iU3RyaW5nU21hbGwiPlN0cmluZyBTbWFsbDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJTdHJpbmdCaWciIH19ICAgICBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iU3RyaW5nQmlnIj5TdHJpbmcgQmlnPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIklucHV0SFRNTCIgfX0gICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJJbnB1dEhUTUwiPkhUTUw8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB7eyBpZiBlcSAuVHlwZSAiSW5wdXRNYXJrZG93biIgfX0gc2VsZWN0ZWQge3sgZWxzZSB9fSBkaXNhYmxlZCB7eyBlbmQgfX0gdmFsdWU9IklucHV0TWFya2Rvd24iPk1hcmtkb3duPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIkZpbGUiIH19ICAgICAgICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJGaWxlIj5GaWxlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIkRhdGUiIH19ICAgICAgICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJEYXRlIj5EYXRlPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24ge3sgaWYgZXEgLlR5cGUgIlJlZmVyZW5jZSIgfX0gICAgIHNlbGVjdGVkIHt7IGVsc2UgfX0gZGlzYWJsZWQge3sgZW5kIH19IHZhbHVlPSJSZWZlcmVuY2UiPlJlZmVyZW5jZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHt7IGlmIGVxIC5UeXBlICJSZWZlcmVuY2VMaXN0IiB9fSBzZWxlY3RlZCB7eyBlbHNlIH19IGRpc2FibGVkIHt7IGVuZCB9fSB2YWx1ZT0iUmVmZXJlbmNlTGlzdCI+UmVmZXJlbmNlTGlzdDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nY29sLTYnPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndy0xMDAgYnRuIGJ0bi1wcmltYXJ5IGJ0bi1yZW1vdmUnIHR5cGU9YnV0dG9uPlJlbW92ZSBGaWVsZDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgIDxhIGhyZWY9JyMnIGNsYXNzPSdidG4gYnRuLWxpbmsnIGlkPSdhZGQtZmllbGRidG4nPkFkZCBBbm90aGVyIEZpZWxkPC9hPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KCiAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgPGRpdiBjbGFzcz0ncm93Jz4KICAgICAgICAgIDxkaXYgY2xhc3M9J29mZnNldC1sZy0zIGNvbC1sZy02Jz4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPSJkLWJsb2NrIHRleHQtcmlnaHQgZmxvYXQtcmlnaHQiIGRhdGEtdG9nZ2xlPSJtb2RhbCIgZGF0YS10YXJnZXQ9IiNjcmVhdGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9IiMiPkNyZWF0ZSBhIG5ldyBjb250ZW50PC9hPgogICAgICAgICAgICAgICAgPC9zbWFsbD4KICAgICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIge3suQ29udGVudFR5cGUuTmFtZX19IGNvbnRlbnQ8L2g2PgogICAgICAgICAgICAgIHt7IGlmIC5Db250ZW50TGlzdC5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuQ29udGVudExpc3QuTGlzdCB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibWVkaWEgdGV4dC1tdXRlZCBwdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0nL2NvbnRlbnQve3sgJC5TcGFjZS5JRCB9fS97eyAkLkNvbnRlbnRUeXBlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj4KICAgICAgICAgICAgICAgICAgICAgIHt7ICguTXVzdFZhbHVlQnlOYW1lICJuYW1lIikuVmFsdWUgfX0KICAgICAgICAgICAgICAgICAgICA8L3N0cm9uZz4KICAgICAgICAgICAgICAgICAgPC9hPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgIHt7IGlmIC5Db250ZW50TGlzdC5Nb3JlIH19CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBtdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iL2NvbnRlbnR0eXBlL3t7IC5TcGFjZS5JRCB9fS97eyAuQ29udGVudFR5cGUuSUQgfX0/YmVmb3JlPXt7IC5Db250ZW50TGlzdC5MYXN0IH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtMyBhbGVydCBhbGVydC1wcmltYXJ5IiByb2xlPSJhbGVydCI+CiAgICAgICAgICAgICAgICAgIFlvdSBoYXZlbid0IGNyZWF0ZWQgYW55IGNvbnRlbnQgeWV0LiAKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvYXJ0aWNsZT4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgfX0KICA8L21haW4+CiAge3sgdGVtcGxhdGUgImh0bWwvX3NjcmlwdHMuaHRtbCIgfX0KICA8c2NyaXB0IHNyYz0nLy91bnBrZy5jb20vdGlueW1jZUA1LjIuMC90aW55bWNlLm1pbi5qcyc+PC9zY3JpcHQ+CiAgPHNjcmlwdCBzcmM9Jy8vdW5wa2cuY29tL2F1dG9jb21wbGV0ZS5qc0AwLjM3LjEvZGlzdC9hdXRvY29tcGxldGUubWluLmpzJz48L3NjcmlwdD4KICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9tYWluLmpzIiAkIH19PC9zY3JpcHQ+CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvc3BhY2UuanMiICQgfX08L3NjcmlwdD4KICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9jb250ZW50LmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")

	tmpls["html/hook.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19IHwge3sgLkhvb2suVVJMIH19PC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0naG9vayBiZy1saWdodCc+CiAgPHN0eWxlPnt7IHRlbXBsYXRlICJjc3MvbWFpbi5jc3MiIH19PC9zdHlsZT4KICA8bWFpbj4KICAgIHt7IHRlbXBsYXRlICJodG1sL19oZWFkZXIuaHRtbCIgJCB9fQogICAgPGRpdiBjbGFzcz0icHJpY2luZy1oZWFkZXIgcHgtMyBweS0zIHB0LW1kLTUgcGItbWQtNCBteC1hdXRvIHRleHQtY2VudGVyIj4KICAgICAgPGgxIGNsYXNzPSJkaXNwbGF5LTQiPnt7IC5Ib29rLlVSTCB9fTwvaDE+CiAgICA8L2Rpdj4KICAgIDxhcnRpY2xlIGNsYXNzPWNvbnRhaW5lcj4KICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvaG9vay9kZWxldGUnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9aG9vayB2YWx1ZT0ie3sgLkhvb2suSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9ImRlbGV0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJkZWxldGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImRlbGV0ZU1vZGFsTGFiZWwiPkRlbGV0ZSB7eyAuSG9vay5VUkwgfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KICAgIDwvZGl2PgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQogIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL21haW4uanMiICQgfX08L3NjcmlwdD4KPC9ib2R5Pgo8L2h0bWw+Cg==")

	tmpls["html/index.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUzwvdGl0bGU+CjwvaGVhZD4KPGJvZHkgY2xhc3M9J2luZGV4IGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+Q01TPC9oMT4KICAgICAgPHAgY2xhc3M9ImxlYWQiPkFuIG9sZC1zY2hvb2wgY29udGVudCBtYW5hZ2VtZW50IDxtYXJrPmluZnJhc3RydWN0dXJlPC9tYXJrPiBmb3IgbW9zdC48L3A+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9J2NvbnRhaW5lcic+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIG9mZnNldC0wIGNvbC1sZy04IG9mZnNldC1sZy0yIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgPHA+PHN0cm9uZz5XQVJOSU5HOjwvc3Ryb25nPiBUaGlzIHNpdGUgaXMgaW4gPHN0cm9uZz5BTFBIQTwvc3Ryb25nPi4gCiAgICAgICAgICAgIFRoaXMgc2l0ZSBpcyBhIGNvbnRlbnQgbWFuYWdlbWVudCBzeXN0ZW0vaW5mcmFzdHJ1Y3R1cmUuIE1lYW5pbmc6IAogICAgICAgICAgICBpdCdzIHB1cnBvc2UgaXMgdG8gYWxsb3cgdXNlcnMgdG8gZ2VuZXJhdGUgY29udGVudC4gVGhhdCdzIGEgCiAgICAgICAgICAgIGRhbmdlcm91cyB0aGluZy4gSW5zdGVhZCBvZiBmb2N1c2luZyBvbiBmaWdodGluZyBhYnVzZSBJJ2xsIGJlIGF1dG8gCiAgICAgICAgICAgIGRlbGV0aW5nIGFsbCBjb250ZW50IChleGNlcHQgZm9yIG15IG93bikgb24gYSByZWd1bGFyIGFuZCB0aWdodCAKICAgICAgICAgICAgaW50ZXJ2YWwuIFlvdSBzdGlsbCBtaWdodCBoYXZlIGZ1biBwb2tpbmcgYXJvdW5kIG9uIHRoaXMgc2l0ZS4gSXQncyAKICAgICAgICAgICAgYWxzbyA8YSBocmVmPSdodHRwczovL3d3dy5nbnUub3JnL3BoaWxvc29waHkvZmxvc3MtYW5kLWZvc3MuZW4uaHRtbCc+RkxPU1MsPC9hPgogICAgICAgICAgICBzbyB5b3UgY2FuIGVuam95IHNlbGYtaG9zdGluZyB5b3Vyc2VsZiBpZiB5b3UgYXJlIHNvIGluY2xpbmVkLiBJZiB5b3UKICAgICAgICAgICAgZmluZCBidWdzICh5b3UgbW9zdCBsaWtlbHkgd2lsbCkgb3IgaGF2ZSBmZWF0dXJlIHJlcXVlc3RzIHBsZWFzZSBzZW5kIAogICAgICAgICAgICB0aGVtIG15IHdheS4gSXQgaXMgYXBwcmVjaWF0ZWQuIFRoYW5rIHlvdS48L3A+CiAgICAgICAgICAgIDxwPklmIHlvdSBuZWVkIHRvIGhpdCB0aGUgQVBJIHRyeSBjVVJMJ2luZyBhbnkgcGFnZSB5b3Ugc2VlIGluIHRoZSAKICAgICAgICAgICAgVVJMIGJhciAoaW5jbHVkZSBiYXNpYyBhdXRoKS4gQSBzaW1wbGUgdXNlIGNhc2Ugb2YgY29uc3VtaW5nIHRoaXMgc2l0ZSBjYW4gYmUgZm91bmQgb24gbXkgCiAgICAgICAgICAgIDxhIGhyZWY9J2h0dHBzOi8vZ2l0LnNyLmh0L35ldmFuai9ldmFuam9uLmVzL3RyZWUvbWFzdGVyL3BrZy9jbXMvY21zLmdvJz5wZXJzb25hbCBzaXRlPC9hPi48L3A+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIDxhcnRpY2xlPgogICAgICB7eyBpZiAuVXNlciB9fQogICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlL25ldycgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZXhhbXBsZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJleGFtcGxlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImV4YW1wbGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcgc3BhY2U8L2g1PgogICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNwYWNlRGVzYyI+RGVzY3JpcHRpb248L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1kZXNjIHR5cGU9dGV4dCBpZD0ic3BhY2VEZXNjIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJEZXNjcmlwdGlvbiIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9mb3JtPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdvZmZzZXQtbGctMyBjb2wtbGctNic+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2V4YW1wbGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHNwYWNlPC9hPgogICAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAgPGg2IGNsYXNzPSJib3JkZXItYm90dG9tIGJvcmRlci1ncmF5IHBiLTIgbWItMCI+WW91ciBzcGFjZXM8L2g2PgogICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5MaXN0IH19CiAgICAgICAgICAgICAgICAgIHt7IHJhbmdlIC5TcGFjZXMuTGlzdCB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtZWRpYSB0ZXh0LW11dGVkIHB0LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9zcGFjZS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICAgICAge3sgLkRlc2MgfX0KICAgICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii8/YmVmb3JlPXt7IC5TcGFjZXMuTGFzdC5JRH19Ij5Mb2FkIG1vcmU8L2E+CiAgICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgZWxzZSB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgICBZb3UgaGF2ZW4ndCBjcmVhdGVkIGFueSBzcGFjZXMgeWV0LiAKICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAge3sgZWxzZSB9fQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdyb3cganVzdGlmeS1jb250ZW50LWNlbnRlcic+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC0xMiBjb2wtbWQtNiBjb2wtbGctNCBvZmZzZXQtY29sLWxnLTIgY29sLXhsLTMgb2Zmc2V0LWNvbC14bC0zIGQtZmxleCI+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCBtYi00IHNoYWRvdy1zbSBmbGV4LWZpbGwiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICA8aDQgY2xhc3M9Im15LTAgZm9udC13ZWlnaHQtbm9ybWFsIj5TaWdudXA8L2g0PgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkiPgogICAgICAgICAgICAgICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy91c2VyL3NpZ251cCcgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRVc2VybmFtZSIgY2xhc3M9InNyLW9ubHkiPkVtYWlsIGFkZHJlc3M8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPXVzZXJuYW1lIHR5cGU9InRleHQiIGlkPSJzaWdudXBJbnB1dFVzZXJuYW1lIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJVc2VybmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRQYXNzd29yZCIgY2xhc3M9InNyLW9ubHkiPlBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1wYXNzd29yZCB0eXBlPSJwYXNzd29yZCIgaWQ9InNpZ251cElucHV0UGFzc3dvcmQiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlBhc3N3b3JkIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzaWdudXBJbnB1dFZlcmlmeSIgY2xhc3M9InNyLW9ubHkiPkNvbmZpcm0gUGFzc3dvcmQ8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPXZlcmlmeSB0eXBlPSJwYXNzd29yZCIgaWQ9InNpZ251cElucHV0VmVyaWZ5IiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJDb25maXJtIFBhc3N3b3JkIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJidG4gYnRuLWxnIGJ0bi1wcmltYXJ5IGJ0bi1ibG9jayIgdHlwZT0ic3VibWl0Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgICA8L2Zvcm0+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC0xMiBjb2wtbWQtNiBjb2wtbGctNCBjb2wteGwtMyBkLWZsZXgiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20gZmxleC1maWxsIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg0IGNsYXNzPSJteS0wIGZvbnQtd2VpZ2h0LW5vcm1hbCI+TG9naW48L2g0PgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkgZC1mbGV4Ij4KICAgICAgICAgICAgICAgICAgPGZvcm0gY2xhc3M9J2QtZmxleCBmbGV4LWdyb3ctMSBmbGV4LWNvbHVtbicgbWV0aG9kPVBPU1QgYWN0aW9uPScvdXNlci9sb2dpbicgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ibG9naW5JbnB1dFVzZXJuYW1lIiBjbGFzcz0ic3Itb25seSI+RW1haWwgYWRkcmVzczwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9dXNlcm5hbWUgdHlwZT0idGV4dCIgaWQ9ImxvZ2luSW5wdXRVc2VybmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImxvZ2luSW5wdXRQYXNzd29yZCIgY2xhc3M9InNyLW9ubHkiPlBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1wYXNzd29yZCB0eXBlPSJwYXNzd29yZCIgaWQ9ImxvZ2luSW5wdXRQYXNzd29yZCIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iUGFzc3dvcmQiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9Im10LWF1dG8gYnRuIGJ0bi1sZyBidG4tcHJpbWFyeSBidG4tYmxvY2siIHR5cGU9InN1Ym1pdCI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIHt7IGVuZCB9fQogICAgPC9hcnRpY2xlPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2Zvb3Rlci5odG1sIiB9fQogIDwvbWFpbj4KICB7eyB0ZW1wbGF0ZSAiaHRtbC9fc2NyaXB0cy5odG1sIiB9fQogIHt7IGlmIC5Vc2VyIH19CiAgICA8c2NyaXB0Pnt7IHRlbXBsYXRlICJqcy9tYWluLmpzIiAkIH19PC9zY3JpcHQ+CiAge3sgZW5kIH19CjwvYm9keT4KPC9odG1sPgo=")
	tmpls["html/index.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUzwvdGl0bGU+CjwvaGVhZD4KPGJvZHkgY2xhc3M9J2luZGV4IGJnLWxpZ2h0Jz4KICA8c3R5bGU+e3sgdGVtcGxhdGUgImNzcy9tYWluLmNzcyIgfX08L3N0eWxlPgogIDxtYWluPgogICAge3sgdGVtcGxhdGUgImh0bWwvX2hlYWRlci5odG1sIiAkIH19CiAgICA8ZGl2IGNsYXNzPSJwcmljaW5nLWhlYWRlciBweC0zIHB5LTMgcHQtbWQtNSBwYi1tZC00IG14LWF1dG8gdGV4dC1jZW50ZXIiPgogICAgICA8aDEgY2xhc3M9ImRpc3BsYXktNCI+Q01TPC9oMT4KICAgICAgPHAgY2xhc3M9ImxlYWQiPkFuIG9sZC1zY2hvb2wgY29udGVudCBtYW5hZ2VtZW50IDxtYXJrPmluZnJhc3RydWN0dXJlPC9tYXJrPiBmb3IgbW9zdC48L3A+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9J2NvbnRhaW5lcic+CiAgICAgIDxkaXYgY2xhc3M9J3Jvdyc+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLTEyIG9mZnNldC0wIGNvbC1sZy04IG9mZnNldC1sZy0yIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgPHA+PHN0cm9uZz5XQVJOSU5HOjwvc3Ryb25nPiBUaGlzIHNpdGUgaXMgaW4gPHN0cm9uZz5BTFBIQTwvc3Ryb25nPi4gCiAgICAgICAgICAgIFRoaXMgc2l0ZSBpcyBhIGNvbnRlbnQgbWFuYWdlbWVudCBzeXN0ZW0vaW5mcmFzdHJ1Y3R1cmUuIE1lYW5pbmc6IAogICAgICAgICAgICBpdCdzIHB1cnBvc2UgaXMgdG8gYWxsb3cgdXNlcnMgdG8gZ2VuZXJhdGUgY29udGVudC4gVGhhdCdzIGEgCiAgICAgICAgICAgIGRhbmdlcm91cyB0aGluZy4gSW5zdGVhZCBvZiBmb2N1c2luZyBvbiBmaWdodGluZyBhYnVzZSBJJ2xsIGJlIGF1dG8gCiAgICAgICAgICAgIGRlbGV0aW5nIGFsbCBjb250ZW50IChleGNlcHQgZm9yIG15IG93bikgb24gYSByZWd1bGFyIGFuZCB0aWdodCAKICAgICAgICAgICAgaW50ZXJ2YWwuIFlvdSBzdGlsbCBtaWdodCBoYXZlIGZ1biBwb2tpbmcgYXJvdW5kIG9uIHRoaXMgc2l0ZS4gSXQncyAKICAgICAgICAgICAgYWxzbyA8YSBocmVmPSdodHRwczovL3d3dy5nbnUub3JnL3BoaWxvc29waHkvZmxvc3MtYW5kLWZvc3MuZW4uaHRtbCc+RkxPU1MsPC9hPgogICAgICAgICAgICBzbyB5b3UgY2FuIGVuam95IHNlbGYtaG9zdGluZyB5b3Vyc2VsZiBpZiB5b3UgYXJlIHNvIGluY2xpbmVkLiBJZiB5b3UKICAgICAgICAgICAgZmluZCBidWdzICh5b3UgbW9zdCBsaWtlbHkgd2lsbCkgb3IgaGF2ZSBmZWF0dXJlIHJlcXVlc3RzIHBsZWFzZSBzZW5kIAogICAgICAgICAgICB0aGVtIG15IHdheS4gSXQgaXMgYXBwcmVjaWF0ZWQuIFRoYW5rIHlvdS48L3A+CiAgICAgICAgICAgIDxwPklmIHlvdSBuZWVkIHRvIGhpdCB0aGUgQVBJIHRyeSBjVVJMJ2luZyBhbnkgcGFnZSB5b3Ugc2VlIGluIHRoZSAKICAgICAgICAgICAgVVJMIGJhciAoaW5jbHVkZSBiYXNpYyBhdXRoKS4gQSBzaW1wbGUgdXNlIGNhc2Ugb2YgY29uc3VtaW5nIHRoaXMgc2l0ZSBjYW4gYmUgZm91bmQgb24gbXkgCiAgICAgICAgICAgIDxhIGhyZWY9J2h0dHBzOi8vZ2l0LnNyLmh0L35ldmFuai9ldmFuam9uLmVzL3RyZWUvbWFzdGVyL3BrZy9jbXMvY21zLmdvJz5wZXJzb25hbCBzaXRlPC9hPi48L3A+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIDxhcnRpY2xlPgogICAgICB7eyBpZiAuVXNlciB9fQogICAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlL25ldycgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZXhhbXBsZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJleGFtcGxlTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImV4YW1wbGVNb2RhbExhYmVsIj5DcmVhdGUgYSBuZXcgc3BhY2U8L2g1PgogICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNwYWNlRGVzYyI+RGVzY3JpcHRpb248L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT1kZXNjIHR5cGU9dGV4dCBpZD0ic3BhY2VEZXNjIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJEZXNjcmlwdGlvbiIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9mb3JtPgogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSdvZmZzZXQtbGctMyBjb2wtbGctNic+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXktMyBwLTMgYmctd2hpdGUgcm91bmRlZCBzaGFkb3ctc20iPgogICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2V4YW1wbGVNb2RhbCI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHNwYWNlPC9hPgogICAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAgPGg2IGNsYXNzPSJib3JkZXItYm90dG9tIGJvcmRlci1ncmF5IHBiLTIgbWItMCI+WW91ciBzcGFjZXM8L2g2PgogICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5MaXN0IH19CiAgICAgICAgICAgICAgICAgIHt7IHJhbmdlIC5TcGFjZXMuTGlzdCB9fQogICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtZWRpYSB0ZXh0LW11dGVkIHB0LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9zcGFjZS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICAgICAge3sgLkRlc2MgfX0KICAgICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgICAge3sgaWYgLlNwYWNlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii8/YmVmb3JlPXt7IC5TcGFjZXMuTGFzdCB9fSI+TG9hZCBtb3JlPC9hPgogICAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICAgIHt7IGVsc2UgfX0KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtMyBhbGVydCBhbGVydC1wcmltYXJ5IiByb2xlPSJhbGVydCI+CiAgICAgICAgICAgICAgICAgICAgWW91IGhhdmVuJ3QgY3JlYXRlZCBhbnkgc3BhY2VzIHlldC4gCiAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIHt7IGVsc2UgfX0KICAgICAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIiPgogICAgICAgICAgPGRpdiBjbGFzcz0ncm93IGp1c3RpZnktY29udGVudC1jZW50ZXInPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgY29sLW1kLTYgY29sLWxnLTQgb2Zmc2V0LWNvbC1sZy0yIGNvbC14bC0zIG9mZnNldC1jb2wteGwtMyBkLWZsZXgiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItNCBzaGFkb3ctc20gZmxleC1maWxsIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtaGVhZGVyIj4KICAgICAgICAgICAgICAgICAgPGg0IGNsYXNzPSJteS0wIGZvbnQtd2VpZ2h0LW5vcm1hbCI+U2lnbnVwPC9oND4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvdXNlci9zaWdudXAnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0VXNlcm5hbWUiIGNsYXNzPSJzci1vbmx5Ij5FbWFpbCBhZGRyZXNzPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT11c2VybmFtZSB0eXBlPSJ0ZXh0IiBpZD0ic2lnbnVwSW5wdXRVc2VybmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InNpZ251cElucHV0UGFzc3dvcmQiIGNsYXNzPSJzci1vbmx5Ij5QYXNzd29yZDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9cGFzc3dvcmQgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFBhc3N3b3JkIiBjbGFzcz0ibWItMyBmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic2lnbnVwSW5wdXRWZXJpZnkiIGNsYXNzPSJzci1vbmx5Ij5Db25maXJtIFBhc3N3b3JkPC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT12ZXJpZnkgdHlwZT0icGFzc3dvcmQiIGlkPSJzaWdudXBJbnB1dFZlcmlmeSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iQ29uZmlybSBQYXNzd29yZCIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1sZyBidG4tcHJpbWFyeSBidG4tYmxvY2siIHR5cGU9InN1Ym1pdCI+R288L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIgY29sLW1kLTYgY29sLWxnLTQgY29sLXhsLTMgZC1mbGV4Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkIG1iLTQgc2hhZG93LXNtIGZsZXgtZmlsbCI+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgIDxoNCBjbGFzcz0ibXktMCBmb250LXdlaWdodC1ub3JtYWwiPkxvZ2luPC9oND4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1ib2R5IGQtZmxleCI+CiAgICAgICAgICAgICAgICAgIDxmb3JtIGNsYXNzPSdkLWZsZXggZmxleC1ncm93LTEgZmxleC1jb2x1bW4nIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3VzZXIvbG9naW4nIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImxvZ2luSW5wdXRVc2VybmFtZSIgY2xhc3M9InNyLW9ubHkiPkVtYWlsIGFkZHJlc3M8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPXVzZXJuYW1lIHR5cGU9InRleHQiIGlkPSJsb2dpbklucHV0VXNlcm5hbWUiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlVzZXJuYW1lIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJsb2dpbklucHV0UGFzc3dvcmQiIGNsYXNzPSJzci1vbmx5Ij5QYXNzd29yZDwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9cGFzc3dvcmQgdHlwZT0icGFzc3dvcmQiIGlkPSJsb2dpbklucHV0UGFzc3dvcmQiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IlBhc3N3b3JkIiByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJtdC1hdXRvIGJ0biBidG4tbGcgYnRuLXByaW1hcnkgYnRuLWJsb2NrIiB0eXBlPSJzdWJtaXQiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICB7eyBlbmQgfX0KICAgIDwvYXJ0aWNsZT4KICAgIHt7IHRlbXBsYXRlICJodG1sL19mb290ZXIuaHRtbCIgfX0KICA8L21haW4+CiAge3sgdGVtcGxhdGUgImh0bWwvX3NjcmlwdHMuaHRtbCIgfX0KICB7eyBpZiAuVXNlciB9fQogICAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvbWFpbi5qcyIgJCB9fTwvc2NyaXB0PgogIHt7IGVuZCB9fQo8L2JvZHk+CjwvaHRtbD4K")

	tmpls["html/space.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19PC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0nc3BhY2UgYmctbGlnaHQnPgogIDxzdHlsZT57eyB0ZW1wbGF0ZSAiY3NzL21haW4uY3NzIiB9fTwvc3R5bGU+CiAgPG1haW4+CiAgICB7eyB0ZW1wbGF0ZSAiaHRtbC9faGVhZGVyLmh0bWwiICQgfX0KICAgIDxkaXYgY2xhc3M9InByaWNpbmctaGVhZGVyIHB4LTMgcHktMyBwdC1tZC01IHBiLW1kLTQgbXgtYXV0byB0ZXh0LWNlbnRlciI+CiAgICAgIDxoMSBjbGFzcz0iZGlzcGxheS00Ij57ey5TcGFjZS5OYW1lfX08L2gxPgogICAgICA8cCBjbGFzcz0ibGVhZCI+e3suU3BhY2UuRGVzY319PC9wPgogICAgPC9kaXY+CiAgICA8YXJ0aWNsZT4KICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudHR5cGUvbmV3JyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjcmVhdGUtY29udGVudHR5cGUiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9IkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGUgbW9kYWwuIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvbnRlbnR0eXBlTW9kYWxMYWJlbCI+Q3JlYXRlIGEgbmV3IGNvbnRlbnQgdHlwZTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjb250ZW50dHlwZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9ImNvbnRlbnR0eXBlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8ZGl2IGlkPSdmaXJzdC1maWVsZHNldCcgY2xhc3M9J2NvbnRhaW5lci1mbHVpZCBweC0wIG1iLTMnPgogICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJmaWVsZHNldEZpcnN0Ij5GaWVsZHM8L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgaWQ9ImZpZWxkc2V0Rmlyc3QiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0iZmllbGRfbmFtZV8xIiB2YWx1ZT0ibmFtZSIgLz4KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nZm9ybS1ncm91cCByb3cnPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NvbC02Jz4KICAgICAgICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9InctMTAwIGZvcm0tY29udHJvbCIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCBuYW1lPSJmaWVsZF90eXBlXzEiPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPkZpZWxkIFR5cGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBzZWxlY3RlZCB2YWx1ZT0iU3RyaW5nU21hbGwiPlN0cmluZyBTbWFsbDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJTdHJpbmdCaWciPlN0cmluZyBCaWc8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iSW5wdXRIVE1MIj5IVE1MPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IklucHV0TWFya2Rvd24iPk1hcmtkb3duPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IkZpbGUiPkZpbGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iRGF0ZSI+RGF0ZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJSZWZlcmVuY2UiPlJlZmVyZW5jZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJSZWZlcmVuY2VMaXN0Ij5SZWZlcmVuY2VMaXN0PC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICA8L3NlbGVjdD4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtNic+CiAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSd3LTEwMCBidG4gYnRuLXByaW1hcnknIGRpc2FibGVkIHR5cGU9YnV0dG9uPlJlbW92ZSBGaWVsZDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGEgaHJlZj0nIycgY2xhc3M9J2J0biBidG4tbGluaycgaWQ9J2FkZC1maWVsZGJ0bic+QWRkIEFub3RoZXIgRmllbGQ8L2E+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvaG9vay9uZXcnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9Imhvb2tNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iaG9va01vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctc2Nyb2xsYWJsZSI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iaG9va01vZGFsTGFiZWwiPkNyZWF0ZSBhIG5ldyBob29rPC9oNT4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcz0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9Imhvb2tVUkwiPlVSTDwvbGFiZWw+CiAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT11cmwgdHlwZT11cmwgaWQ9Imhvb2tVUkwiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9Ik11c3QgZW50ZXIgZnVsbCBVUkwgb2YgdGFyZ2V0IiByZXF1aXJlZD4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9zcGFjZS9jb3B5JyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjb3B5TW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9ImNvcHlNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvcHlNb2RhbExhYmVsIj5Db3B5IHt7LlNwYWNlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZURlc2MiPkRlc2NyaXB0aW9uPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPWRlc2MgdHlwZT10ZXh0IGlkPSJzcGFjZURlc2MiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IkRlc2NyaXB0aW9uIiByZXF1aXJlZD4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9zcGFjZS91cGRhdGUnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InVwZGF0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJ1cGRhdGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9InVwZGF0ZU1vZGFsTGFiZWwiPlVwZGF0ZSB7ey5TcGFjZS5OYW1lfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLk5hbWUgfX0iIG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZURlc2MiPkRlc2NyaXB0aW9uPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLkRlc2MgfX0iIG5hbWU9ZGVzYyB0eXBlPXRleHQgaWQ9InNwYWNlRGVzYyIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iRGVzY3JpcHRpb24iIHJlcXVpcmVkPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KICAgICAgCiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlL2RlbGV0ZScgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZGVsZXRlTW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9ImRlbGV0ZU1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctc2Nyb2xsYWJsZSI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iZGVsZXRlTW9kYWxMYWJlbCI+RGVsZXRlIHt7LlNwYWNlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY29sLWxnLTYnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJteS0zIHAtMyBiZy13aGl0ZSByb3VuZGVkIHNoYWRvdy1zbSI+CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2NyZWF0ZS1jb250ZW50dHlwZSI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9IiMiPkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIgY29udGVudCB0eXBlczwvaDY+CiAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuQ29udGVudFR5cGVzLkxpc3QgfX0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1lZGlhIHRleHQtbXV0ZWQgcHQtMyI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9jb250ZW50dHlwZS97eyAkLlNwYWNlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBtdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iL3NwYWNlL3t7IC5TcGFjZS5JRCB9fT9iZWZvcmVjdD17eyAuQ29udGVudFR5cGVzLkxhc3QuSUQgfX0iPkxvYWQgbW9yZTwvYT4KICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgWW91IGhhdmVuJ3QgY3JlYXRlZCBhbnkgY29udGVudCB0eXBlcyB5ZXQuIAogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtbGctNic+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im15LTMgcC0zIGJnLXdoaXRlIHJvdW5kZWQgc2hhZG93LXNtIj4KICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IGZsb2F0LXJpZ2h0IiBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjaG9va01vZGFsIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHdlYmhvb2s8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIgd2ViaG9va3M8L2g2PgogICAgICAgICAgICAgIHt7IGlmIC5Ib29rcy5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuSG9va3MuTGlzdCB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibWVkaWEgdGV4dC1tdXRlZCBwdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0nL2hvb2sve3sgJC5TcGFjZS5JRCB9fS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgPHN0cm9uZyBjbGFzcz0iZC1ibG9jayB0ZXh0LWdyYXktZGFyayI+e3sgLlVSTCB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgaWYgLkhvb2tzLk1vcmUgfX0KICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICA8YSBocmVmPSIvc3BhY2Uve3sgLlNwYWNlLklEIH19P2JlZm9yZWhvb2s9e3sgLkhvb2tzLkxhc3QuSUQgfX0iPkxvYWQgbW9yZTwvYT4KICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgWW91IGhhdmVuJ3QgY3JlYXRlZCBhbnkgd2ViaG9va3MgeWV0LiAKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KCiAgICA8L2FydGljbGU+CiAgICB7eyB0ZW1wbGF0ZSAiaHRtbC9fZm9vdGVyLmh0bWwiIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvbWFpbi5qcyIgJCB9fTwvc2NyaXB0PgogIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL3NwYWNlLmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")
	tmpls["html/space.html"] = tostring("PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CjxoZWFkPgogIHt7IHRlbXBsYXRlICJodG1sL19oZWFkLmh0bWwiIH19CiAgPHRpdGxlPkNNUyB8IHt7IC5TcGFjZS5OYW1lIH19PC90aXRsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0nc3BhY2UgYmctbGlnaHQnPgogIDxzdHlsZT57eyB0ZW1wbGF0ZSAiY3NzL21haW4uY3NzIiB9fTwvc3R5bGU+CiAgPG1haW4+CiAgICB7eyB0ZW1wbGF0ZSAiaHRtbC9faGVhZGVyLmh0bWwiICQgfX0KICAgIDxkaXYgY2xhc3M9InByaWNpbmctaGVhZGVyIHB4LTMgcHktMyBwdC1tZC01IHBiLW1kLTQgbXgtYXV0byB0ZXh0LWNlbnRlciI+CiAgICAgIDxoMSBjbGFzcz0iZGlzcGxheS00Ij57ey5TcGFjZS5OYW1lfX08L2gxPgogICAgICA8cCBjbGFzcz0ibGVhZCI+e3suU3BhY2UuRGVzY319PC9wPgogICAgPC9kaXY+CiAgICA8YXJ0aWNsZT4KICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvY29udGVudHR5cGUvbmV3JyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjcmVhdGUtY29udGVudHR5cGUiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9IkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGUgbW9kYWwuIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvbnRlbnR0eXBlTW9kYWxMYWJlbCI+Q3JlYXRlIGEgbmV3IGNvbnRlbnQgdHlwZTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJjb250ZW50dHlwZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9ImNvbnRlbnR0eXBlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8ZGl2IGlkPSdmaXJzdC1maWVsZHNldCcgY2xhc3M9J2NvbnRhaW5lci1mbHVpZCBweC0wIG1iLTMnPgogICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJmaWVsZHNldEZpcnN0Ij5GaWVsZHM8L2xhYmVsPgogICAgICAgICAgICAgICAgICA8aW5wdXQgaWQ9ImZpZWxkc2V0Rmlyc3QiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCB0eXBlPXRleHQgbmFtZT0iZmllbGRfbmFtZV8xIiB2YWx1ZT0ibmFtZSIgLz4KICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0nZm9ybS1ncm91cCByb3cnPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J2NvbC02Jz4KICAgICAgICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9InctMTAwIGZvcm0tY29udHJvbCIgcmVhZG9ubHk9InJlYWRvbmx5IiByZXF1aXJlZCBuYW1lPSJmaWVsZF90eXBlXzEiPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPkZpZWxkIFR5cGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBzZWxlY3RlZCB2YWx1ZT0iU3RyaW5nU21hbGwiPlN0cmluZyBTbWFsbDwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJTdHJpbmdCaWciPlN0cmluZyBCaWc8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iSW5wdXRIVE1MIj5IVE1MPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IklucHV0TWFya2Rvd24iPk1hcmtkb3duPC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gZGlzYWJsZWQgdmFsdWU9IkZpbGUiPkZpbGU8L29wdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBkaXNhYmxlZCB2YWx1ZT0iRGF0ZSI+RGF0ZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJSZWZlcmVuY2UiPlJlZmVyZW5jZTwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJSZWZlcmVuY2VMaXN0Ij5SZWZlcmVuY2VMaXN0PC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICA8L3NlbGVjdD4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtNic+CiAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSd3LTEwMCBidG4gYnRuLXByaW1hcnknIGRpc2FibGVkIHR5cGU9YnV0dG9uPlJlbW92ZSBGaWVsZDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGEgaHJlZj0nIycgY2xhc3M9J2J0biBidG4tbGluaycgaWQ9J2FkZC1maWVsZGJ0bic+QWRkIEFub3RoZXIgRmllbGQ8L2E+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGZvcm0gbWV0aG9kPVBPU1QgYWN0aW9uPScvaG9vay9uZXcnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9Imhvb2tNb2RhbCIgdGFiaW5kZXg9Ii0xIiByb2xlPSJkaWFsb2ciIGFyaWEtbGFiZWxsZWRieT0iaG9va01vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctc2Nyb2xsYWJsZSI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iaG9va01vZGFsTGFiZWwiPkNyZWF0ZSBhIG5ldyBob29rPC9oNT4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiIGRhdGEtZGlzbWlzcz0ibW9kYWwiIGFyaWEtbGFiZWw9IkNsb3NlIj4KICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49InRydWUiPiZ0aW1lczs8L3NwYW4+CiAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9Imhvb2tVUkwiPlVSTDwvbGFiZWw+CiAgICAgICAgICAgICAgICA8aW5wdXQgbmFtZT11cmwgdHlwZT11cmwgaWQ9Imhvb2tVUkwiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9Ik11c3QgZW50ZXIgZnVsbCBVUkwgb2YgdGFyZ2V0IiByZXF1aXJlZD4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9zcGFjZS9jb3B5JyBlbmN0eXBlPSdtdWx0aXBhcnQvZm9ybS1kYXRhJz4KICAgICAgICA8aW5wdXQgcmVxdWlyZWQgdHlwZT1oaWRkZW4gbmFtZT1zcGFjZSB2YWx1ZT0ie3sgLlNwYWNlLklEIH19IiAvPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjb3B5TW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9ImNvcHlNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImNvcHlNb2RhbExhYmVsIj5Db3B5IHt7LlNwYWNlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZU5hbWUiPk5hbWU8L2xhYmVsPgogICAgICAgICAgICAgICAgPGlucHV0IG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZURlc2MiPkRlc2NyaXB0aW9uPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPWRlc2MgdHlwZT10ZXh0IGlkPSJzcGFjZURlc2MiIGNsYXNzPSJtYi0zIGZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9IkRlc2NyaXB0aW9uIiByZXF1aXJlZD4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLXNlY29uZGFyeSIgZGF0YS1kaXNtaXNzPSJtb2RhbCI+Q2xvc2U8L2J1dHRvbj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5HbzwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvcm0+CgogICAgICA8Zm9ybSBtZXRob2Q9UE9TVCBhY3Rpb249Jy9zcGFjZS91cGRhdGUnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPgogICAgICAgIDxpbnB1dCByZXF1aXJlZCB0eXBlPWhpZGRlbiBuYW1lPXNwYWNlIHZhbHVlPSJ7eyAuU3BhY2UuSUQgfX0iIC8+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InVwZGF0ZU1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJ1cGRhdGVNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1kaWFsb2cgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jb250ZW50Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9InVwZGF0ZU1vZGFsTGFiZWwiPlVwZGF0ZSB7ey5TcGFjZS5OYW1lfX08L2g1PgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjbG9zZSIgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPgogICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+JnRpbWVzOzwvc3Bhbj4KICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ic3BhY2VOYW1lIj5OYW1lPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLk5hbWUgfX0iIG5hbWU9bmFtZSB0eXBlPXRleHQgaWQ9InNwYWNlTmFtZSIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iTmFtZSIgcmVxdWlyZWQ+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJzcGFjZURlc2MiPkRlc2NyaXB0aW9uPC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB2YWx1ZT0ie3sgLlNwYWNlLkRlc2MgfX0iIG5hbWU9ZGVzYyB0eXBlPXRleHQgaWQ9InNwYWNlRGVzYyIgY2xhc3M9Im1iLTMgZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iRGVzY3JpcHRpb24iIHJlcXVpcmVkPgogICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc2Vjb25kYXJ5IiBkYXRhLWRpc21pc3M9Im1vZGFsIj5DbG9zZTwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiPkdvPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZm9ybT4KICAgICAgCiAgICAgIDxmb3JtIG1ldGhvZD1QT1NUIGFjdGlvbj0nL3NwYWNlL2RlbGV0ZScgZW5jdHlwZT0nbXVsdGlwYXJ0L2Zvcm0tZGF0YSc+CiAgICAgICAgPGlucHV0IHJlcXVpcmVkIHR5cGU9aGlkZGVuIG5hbWU9c3BhY2UgdmFsdWU9Int7IC5TcGFjZS5JRCB9fSIgLz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBmYWRlIiBpZD0iZGVsZXRlTW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBhcmlhLWxhYmVsbGVkYnk9ImRlbGV0ZU1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1kaWFsb2ctc2Nyb2xsYWJsZSI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iZGVsZXRlTW9kYWxMYWJlbCI+RGVsZXRlIHt7LlNwYWNlLk5hbWV9fTwvaDU+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImNsb3NlIiBkYXRhLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+CiAgICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPSJ0cnVlIj4mdGltZXM7PC9zcGFuPgogICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1zZWNvbmRhcnkiIGRhdGEtZGlzbWlzcz0ibW9kYWwiPkNsb3NlPC9idXR0b24+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSI+R288L2J1dHRvbj4KICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9mb3JtPgoKICAgICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KICAgICAgICA8ZGl2IGNsYXNzPSdyb3cnPgogICAgICAgICAgPGRpdiBjbGFzcz0nY29sLWxnLTYnPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJteS0zIHAtMyBiZy13aGl0ZSByb3VuZGVkIHNoYWRvdy1zbSI+CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBmbG9hdC1yaWdodCIgZGF0YS10b2dnbGU9Im1vZGFsIiBkYXRhLXRhcmdldD0iI2NyZWF0ZS1jb250ZW50dHlwZSI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9IiMiPkNyZWF0ZSBhIG5ldyBjb250ZW50IHR5cGU8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIgY29udGVudCB0eXBlczwvaDY+CiAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuQ29udGVudFR5cGVzLkxpc3QgfX0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1lZGlhIHRleHQtbXV0ZWQgcHQtMyI+CiAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Jy9jb250ZW50dHlwZS97eyAkLlNwYWNlLklEIH19L3t7IC5JRCB9fScgIGNsYXNzPSJkLWJsb2NrIG1lZGlhLWJvZHkgcGItMyBtYi0wIHNtYWxsIGxoLTEyNSBib3JkZXItYm90dG9tIGJvcmRlci1ncmF5Ij4KICAgICAgICAgICAgICAgICAgICA8c3Ryb25nIGNsYXNzPSJkLWJsb2NrIHRleHQtZ3JheS1kYXJrIj57eyAuTmFtZSB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgaWYgLkNvbnRlbnRUeXBlcy5Nb3JlIH19CiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9ImQtYmxvY2sgdGV4dC1yaWdodCBtdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iL3NwYWNlL3t7IC5TcGFjZS5JRCB9fT9iZWZvcmVjdD17eyAuQ29udGVudFR5cGVzLkxhc3QgfX0iPkxvYWQgbW9yZTwvYT4KICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgWW91IGhhdmVuJ3QgY3JlYXRlZCBhbnkgY29udGVudCB0eXBlcyB5ZXQuIAogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAge3sgZW5kIH19CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSdjb2wtbGctNic+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im15LTMgcC0zIGJnLXdoaXRlIHJvdW5kZWQgc2hhZG93LXNtIj4KICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IGZsb2F0LXJpZ2h0IiBkYXRhLXRvZ2dsZT0ibW9kYWwiIGRhdGEtdGFyZ2V0PSIjaG9va01vZGFsIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iIyI+Q3JlYXRlIGEgbmV3IHdlYmhvb2s8L2E+CiAgICAgICAgICAgICAgICA8L3NtYWxsPgogICAgICAgICAgICAgIDxoNiBjbGFzcz0iYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSBwYi0yIG1iLTAiPllvdXIgd2ViaG9va3M8L2g2PgogICAgICAgICAgICAgIHt7IGlmIC5Ib29rcy5MaXN0IH19CiAgICAgICAgICAgICAgICB7eyByYW5nZSAuSG9va3MuTGlzdCB9fQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibWVkaWEgdGV4dC1tdXRlZCBwdC0zIj4KICAgICAgICAgICAgICAgICAgPGEgaHJlZj0nL2hvb2sve3sgJC5TcGFjZS5JRCB9fS97eyAuSUQgfX0nICBjbGFzcz0iZC1ibG9jayBtZWRpYS1ib2R5IHBiLTMgbWItMCBzbWFsbCBsaC0xMjUgYm9yZGVyLWJvdHRvbSBib3JkZXItZ3JheSI+CiAgICAgICAgICAgICAgICAgICAgPHN0cm9uZyBjbGFzcz0iZC1ibG9jayB0ZXh0LWdyYXktZGFyayI+e3sgLlVSTCB9fTwvc3Ryb25nPgogICAgICAgICAgICAgICAgICA8L2E+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICAgICAge3sgaWYgLkhvb2tzLk1vcmUgfX0KICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz0iZC1ibG9jayB0ZXh0LXJpZ2h0IG10LTMiPgogICAgICAgICAgICAgICAgICA8YSBocmVmPSIvc3BhY2Uve3sgLlNwYWNlLklEIH19P2JlZm9yZWhvb2s9e3sgLkhvb2tzLkxhc3QgfX0iPkxvYWQgbW9yZTwvYT4KICAgICAgICAgICAgICAgIDwvc21hbGw+CiAgICAgICAgICAgICAgICB7eyBlbmQgfX0KICAgICAgICAgICAgICB7eyBlbHNlIH19CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtdC0zIGFsZXJ0IGFsZXJ0LXByaW1hcnkiIHJvbGU9ImFsZXJ0Ij4KICAgICAgICAgICAgICAgICAgWW91IGhhdmVuJ3QgY3JlYXRlZCBhbnkgd2ViaG9va3MgeWV0LiAKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgIHt7IGVuZCB9fQogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KCiAgICA8L2FydGljbGU+CiAgICB7eyB0ZW1wbGF0ZSAiaHRtbC9fZm9vdGVyLmh0bWwiIH19CiAgPC9tYWluPgogIHt7IHRlbXBsYXRlICJodG1sL19zY3JpcHRzLmh0bWwiIH19CiAgPHNjcmlwdD57eyB0ZW1wbGF0ZSAianMvbWFpbi5qcyIgJCB9fTwvc2NyaXB0PgogIDxzY3JpcHQ+e3sgdGVtcGxhdGUgImpzL3NwYWNlLmpzIiAkIH19PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4K")

	tmpls["js/content.js"] = tostring("Ly8gU2V0dXAgaW5wdXRzIGZvciBjb250ZW50IGNyZWF0ZS91cGRhdGUuCihmdW5jdGlvbigpIHsgCgogIC8vIFNhdmUgYnV0dG9uIAogIHZhciBzYXZlQnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXRbdmFsdWU9U2F2ZV0nKQogIGlmIChzYXZlQnRuKSB7CiAgICBzYXZlQnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gY29udGVudFVwZGF0ZShlKSB7IAogICAgICBlLnByZXZlbnREZWZhdWx0KCkKICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKQogICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtW2FjdGlvbj0iL2NvbnRlbnQvdXBkYXRlIl0nKS5zdWJtaXQoKQogICAgfSkKICB9CgogIC8vIEhUTUwKICB0aW55bWNlLmluaXQoeyAKICAgIGVuZF9jb250YWluZXJfb25fZW1wdHlfYmxvY2s6IHRydWUsCiAgICByZWxhdGl2ZV91cmxzOiBmYWxzZSwKICAgIGNvbnZlcnRfdXJsczogZmFsc2UsCiAgICByZW1vdmVfc2NyaXB0X2hvc3Q6IGZhbHNlLAogICAgYWxsb3dfc2NyaXB0X3VybHM6IHRydWUsCiAgICBicm93c2VyX3NwZWxsY2hlY2s6IHRydWUsCiAgICBmb3JjZWRfcm9vdF9ibG9jazogZmFsc2UsCiAgICBicmFuZGluZzogZmFsc2UsCiAgICBkcmFnZ2FibGVfbW9kYWw6IHRydWUsCiAgICBtb2JpbGU6IHsgbWVudWJhcjogdHJ1ZSB9LAogICAgc3RhdHVzYmFyOiBmYWxzZSwKICAgIHNlbGVjdG9yOiAndGV4dGFyZWEuaW5wdXQtaHRtbCcsCiAgICBwbHVnaW5zOiAiYXV0b3Jlc2l6ZSxjb2RlIiwKICAgIGNvbnRlbnRfY3NzOiAiL3N0YXRpYy90aW55bWNlLmNzcyIsCiAgICBzZXR1cDogZnVuY3Rpb24oaXRlbSkgeyAKICAgICAgaXRlbS5vbignY2hhbmdlJywgZnVuY3Rpb24oKSB7IAogICAgICAgIGl0ZW0udGFyZ2V0RWxtLnZhbHVlID0gaXRlbS5nZXRDb250ZW50KCkKICAgICAgfSkKICAgIH0KICB9KQoKICAvLyBNQVJLRE9XTgogIHRpbnltY2UuaW5pdCh7CiAgICBlbmRfY29udGFpbmVyX29uX2VtcHR5X2Jsb2NrOiB0cnVlLAogICAgcmVsYXRpdmVfdXJsczogZmFsc2UsCiAgICBjb252ZXJ0X3VybHM6IGZhbHNlLAogICAgcmVtb3ZlX3NjcmlwdF9ob3N0OiBmYWxzZSwKICAgIGFsbG93X3NjcmlwdF91cmxzOiB0cnVlLAogICAgYnJvd3Nlcl9zcGVsbGNoZWNrOiB0cnVlLAogICAgZm9yY2VkX3Jvb3RfYmxvY2s6IGZhbHNlLAogICAgYnJhbmRpbmc6IGZhbHNlLAogICAgZHJhZ2dhYmxlX21vZGFsOiB0cnVlLAogICAgbW9iaWxlOiB7IG1lbnViYXI6IHRydWUgfSwKICAgIHN0YXR1c2JhcjogZmFsc2UsCiAgICBzZWxlY3RvcjogInRleHRhcmVhLmlucHV0LW1hcmtkb3duIiwKICAgIHBsdWdpbjogJ2F1dG9yZXNpemUsdGV4dHBhdHRlcm4nLAogICAgZXh0ZXJuYWxfcGx1Z2luczogeyAKICAgICAgdGV4dHBhdHRlcm46ICcvL3VucGtnLmNvbS90aW55bWNlQDUuMi4wL3BsdWdpbnMvdGV4dHBhdHRlcm4vcGx1Z2luLm1pbi5qcycKICAgIH0sCiAgICBtZW51YmFyOiBmYWxzZSwKICAgIHRvb2xiYXI6ICd1bmRvIHJlZG8nLAogICAgY29udGVudF9jc3M6ICIvc3RhdGljL3RpbnltY2UuY3NzIiwKICAgIHRleHRwYXR0ZXJuX3BhdHRlcm5zOiBbCiAgICAgIHtzdGFydDogJyonLCBlbmQ6ICcqJywgZm9ybWF0OiAnaXRhbGljJ30sCiAgICAgIHtzdGFydDogJyoqJywgZW5kOiAnKionLCBmb3JtYXQ6ICdib2xkJ30sCiAgICAgIHtzdGFydDogJ18nLCBlbmQ6ICdfJywgZm9ybWF0OiAnYm9sZCd9LAogICAgICB7c3RhcnQ6ICcjJywgZm9ybWF0OiAnaDEnfSwKICAgICAge3N0YXJ0OiAnIyMnLCBmb3JtYXQ6ICdoMid9LAogICAgICB7c3RhcnQ6ICcjIyMnLCBmb3JtYXQ6ICdoMyd9LAogICAgICB7c3RhcnQ6ICcjIyMjJywgZm9ybWF0OiAnaDQnfSwKICAgICAge3N0YXJ0OiAnIyMjIyMnLCBmb3JtYXQ6ICdoNSd9LAogICAgICB7c3RhcnQ6ICcjIyMjIyMnLCBmb3JtYXQ6ICdoNid9LAogICAgICB7c3RhcnQ6ICcxLiAnLCBjbWQ6ICdJbnNlcnRPcmRlcmVkTGlzdCd9LAogICAgICB7c3RhcnQ6ICcqICcsIGNtZDogJ0luc2VydFVub3JkZXJlZExpc3QnfSwKICAgICAge3N0YXJ0OiAnLSAnLCBjbWQ6ICdJbnNlcnRVbm9yZGVyZWRMaXN0J30KICAgIF0sCiAgICBzZXR1cDogZnVuY3Rpb24oaXRlbSkgeyAKICAgICAgaXRlbS5vbignY2hhbmdlJywgZnVuY3Rpb24oKSB7IAogICAgICAgIGl0ZW0udGFyZ2V0RWxtLnZhbHVlID0gaXRlbS5nZXRDb250ZW50KCkKICAgICAgfSkKICAgIH0KICB9KTsKCiAgLy8gUkVGRVJFTkNFIC8gUkVGRVJFTkNFIExJU1QKICB2YXIgcmVmcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5yZWYtbW9kYWwnKQogIGZvciAodmFyIGkgPSAwOyBpIDwgcmVmcy5sZW5ndGg7IGkrKykgeyAKICAgIHZhciByZWYgICAgID0gcmVmc1tpXTsKICAgIHZhciBpbnB1dHMgID0gcmVmLnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0Jyk7CiAgICB2YXIgb3V0cHV0ICA9IGlucHV0c1swXTsKICAgIHZhciBidG4gICAgID0gaW5wdXRzWzFdOwogICAgdmFyIGlucHV0Q1QgPSBpbnB1dHNbMl07CiAgICB2YXIgaW5wdXRDICA9IGlucHV0c1szXTsKICAgIHZhciBtb2RhbCAgID0gcmVmLnF1ZXJ5U2VsZWN0b3IoJy5tb2RhbCcpOwogICAgdmFyIGNsZWFyICAgPSByZWYucXVlcnlTZWxlY3RvcignLmJ0bi1jbGVhcicpOwoKICAgIChmdW5jdGlvbihyZWYsIG91dHB1dCwgYnRuLCBjb250ZW50dHlwZSwgY29udGVudCwgbW9kYWwpIHsKICAgICAgdmFyIGF1dG9DVCA9IHthdXRvY29tcGxldGU6e2Rlc3Ryb3k6ZnVuY3Rpb24oKXt9fX07CiAgICAgIHZhciBhdXRvQyA9IHthdXRvY29tcGxldGU6e2Rlc3Ryb3k6ZnVuY3Rpb24oKXt9fX07CiAgICAgIHZhciBpc0xpc3QgPSByZWYuY2xhc3NOYW1lLmluZGV4T2YoJ3JlZi1saXN0JykgIT0gLTE7CgogICAgICB2YXIgY2hvc2VuQ29udGVudFR5cGVJRCAvLyB1c2VkIGJ5IGJvdGgKICAgICAgdmFyIGNob3NlbkNvbnRlbnRJRHMgPSBbXSAvLyBvbmx5IHVzZWQgYmUgcmVmIGxpc3QKICAgICAgdmFyIGNob3NlbkNvbnRlbnROYW1lcyA9IFtdIC8vIG9ubHkgdXNlZCBiZSByZWYgbGlzdAoKICAgICAgbW9kYWwuYWRkRXZlbnRMaXN0ZW5lcignc2hvd24uYnMubW9kYWwnLCBmdW5jdGlvbigpIHsgCiAgICAgICAgdmFyIG9wdHMgPSB7CiAgICAgICAgICBhdXRvc2VsZWN0OiB0cnVlLAogICAgICAgICAgYXV0b3NlbGVjdE9uQmx1cjogdHJ1ZSwgCiAgICAgICAgICB0YWJBdXRvY29tcGxldGU6IHRydWUsCiAgICAgICAgICAvLyBjbGVhck9uU2VsZWN0ZWQ6IHRydWUsCiAgICAgICAgICBoaW50OiBmYWxzZSwKICAgICAgICAgIC8vIGRlYnVnOiB0cnVlCiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBnZXRvcHRzKHVybCwgdHJhbnNmb3JtLCBkaXNwbGF5S2V5KSB7IAogICAgICAgICAgdmFyIGNvbnRlbnR0eXBlQWJvcnQgPSBmdW5jdGlvbigpIHt9CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBkaXNwbGF5S2V5OiBkaXNwbGF5S2V5LAogICAgICAgICAgICBzb3VyY2U6IGZ1bmN0aW9uKHF1ZXJ5LCBjYikgeyAKICAgICAgICAgICAgICBjYihbXSkKICAgICAgICAgICAgICBjb250ZW50dHlwZUFib3J0KCkKICAgICAgICAgICAgICB2YXIgcmVxID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCkKICAgICAgICAgICAgICBjb250ZW50dHlwZUFib3J0ID0gZnVuY3Rpb24oKSB7IHJlcS5hYm9ydCgpIH0gCiAgICAgICAgICAgICAgcmVxLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSAhPSA0KSB7CiAgICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXR1cyAhPSAyMDApIHsKICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzcG9uc2VUZXh0ICE9ICIiKSB7CiAgICAgICAgICAgICAgICAgICAgYWxlcnQodGhpcy5yZXNwb25zZVRleHQpCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgY2IoW10pCiAgICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHRyeSB7IAogICAgICAgICAgICAgICAgICBjYih0cmFuc2Zvcm0oSlNPTi5wYXJzZSh0aGlzLnJlc3BvbnNlVGV4dCkpKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2goZSkgeyAKICAgICAgICAgICAgICAgICAgdmFyIG1zZyA9IGUudG9TdHJpbmcoKQogICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyh7ZSxtc2d9KQogICAgICAgICAgICAgICAgICBpZiAobXNnICE9ICIiKSB7IC8vIENhbmNlbGxlZCByZXF1ZXN0cyBoaXQgdGhpcy4KICAgICAgICAgICAgICAgICAgICBhbGVydChtc2cpCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmVxLm9wZW4oJ0dFVCcsIHVybCgpICsgcXVlcnksIHRydWUpCiAgICAgICAgICAgICAgcmVxLnNlbmQoKQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2YXIgY29udGVudHR5cGVPcHRzID0gZ2V0b3B0cygKICAgICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gJy9jb250ZW50dHlwZS9zZWFyY2g/c3BhY2U9e3sgLlNwYWNlLklEIH19JnF1ZXJ5PSc7IH0sIAogICAgICAgICAgZnVuY3Rpb24oZGF0YSkgeyByZXR1cm4gZGF0YSB9LAogICAgICAgICAgJ0NvbnRlbnRUeXBlTmFtZScKICAgICAgICApCgogICAgICAgIGF1dG9DVCA9IHdpbmRvdy5hdXRvY29tcGxldGUoY29udGVudHR5cGUsIG9wdHMsIFtjb250ZW50dHlwZU9wdHNdKS5vbignYXV0b2NvbXBsZXRlOnNlbGVjdGVkJywgb25Db250ZW50VHlwZVNlbGVjdGVkKQogICAgICAgIGZ1bmN0aW9uIG9uQ29udGVudFR5cGVTZWxlY3RlZChlLCBpdGVtLCBkYXRhc2V0LCBjdHgpIHsKICAgICAgICAgIGNob3NlbkNvbnRlbnRUeXBlSUQgPSBpdGVtLkNvbnRlbnRUeXBlSUQKICAgICAgICAgIGNvbnRlbnQuZGlzYWJsZWQgPSBmYWxzZQogICAgICAgICAgY29udGVudC5mb2N1cygpCiAgICAgICAgfQoKICAgICAgICB2YXIgY29udGVudE9wdHMgPSBnZXRvcHRzKAogICAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiAnL2NvbnRlbnQvc2VhcmNoP3NwYWNlPXt7IC5TcGFjZS5JRCB9fSZjb250ZW50dHlwZT0nICsgY2hvc2VuQ29udGVudFR5cGVJRCArICcmcXVlcnk9JzsgfSwgCiAgICAgICAgICBmdW5jdGlvbihkYXRhKSB7IAogICAgICAgICAgICAvLyBCaWcgaGFjay4KICAgICAgICAgICAgZGF0YSA9IGRhdGEgPyBkYXRhIDogW10KCiAgICAgICAgICAgIC8vIFRPRE86IFJlbW92ZSBjdXJyZW50IGNvbnRlbnQgZnJvbSBsaXN0IGlmIGF2YWlsYWJsZS4gVGhpcyAKICAgICAgICAgICAgLy8gc2hvdWxkIGJlIGRvbmUgb24gdGhlIHNlcnZlci4KICAgICAgICAgICAge3sgaWYgLkNvbnRlbnQgfX0KICAgICAgICAgICAgZGF0YSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uKGl0ZW0pIHsgcmV0dXJuIGl0ZW0uQ29udGVudElEICE9IHt7IC5Db250ZW50LklEIH19OyB9KTsKICAgICAgICAgICAge3sgZW5kIH19CgogICAgICAgICAgICBpZiAoaXNMaXN0KSB7CiAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uKGl0ZW0pIHsgcmV0dXJuIGNob3NlbkNvbnRlbnRJRHMuaW5kZXhPZihpdGVtLkNvbnRlbnRJRCkgPT09IC0xOyB9KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHsgLy8gVGhpcyByZXNwb25zZSBpcyBwYWdlZCwgZG9uJ3Qgd29ycnkgYWJvdXQgT14yLiBNYXggb2YgMjAgaXRlbXMuCgogICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBkYXRhW2ldLkNvbnRlbnRWYWx1ZXMubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgIGlmIChkYXRhW2ldLkNvbnRlbnRWYWx1ZXNbal0uRmllbGROYW1lID09ICJuYW1lIikgeyAvLyBXZSdyZSBndWFyYW50ZWVkIHRvIGhhdmUgdGhpcy4KICAgICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihkYXRhW2ldLCBkYXRhW2ldLkNvbnRlbnRWYWx1ZXNbal0pCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBkYXRhCiAgICAgICAgICB9LAogICAgICAgICAgJ0ZpZWxkVmFsdWUnCiAgICAgICAgKQoKICAgICAgICAvLyBUT0RPOiBXZWlyZCBiZWhhdmlvciBoZXJlLCB3aHkgZG8gSSBoYXZlIHRvIGlubGluZSB0aGlzIGNsZWFyIG9uCiAgICAgICAgLy8gc2VsZWN0ZWQ/IFdoeSBjYW4ndCBpdCBleGlzdHMgaW4gY29udGVudE9wdHM/CiAgICAgICAgYXV0b0MgPSB3aW5kb3cuYXV0b2NvbXBsZXRlKGNvbnRlbnQsIE9iamVjdC5hc3NpZ24oe30sIG9wdHMsIHtjbGVhck9uU2VsZWN0ZWQ6dHJ1ZX0pLCBbY29udGVudE9wdHNdKS5vbignYXV0b2NvbXBsZXRlOnNlbGVjdGVkJywgb25Db250ZW50U2VsZWN0ZWQpCiAgICAgICAgZnVuY3Rpb24gb25Db250ZW50U2VsZWN0ZWQoZSwgaXRlbSwgZGF0YXNldCwgY3R4KSB7CiAgICAgICAgICBpZiAoaXNMaXN0KSB7CiAgICAgICAgICAgIGNob3NlbkNvbnRlbnRJRHMucHVzaChpdGVtLkNvbnRlbnRJRCkKICAgICAgICAgICAgY2hvc2VuQ29udGVudE5hbWVzLnB1c2goaXRlbS5GaWVsZFZhbHVlKQogICAgICAgICAgICBvdXRwdXQudmFsdWUgPSBjaG9zZW5Db250ZW50SURzCiAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbih2YWwsIGksIHNlbGYpIHsgcmV0dXJuIHNlbGYuaW5kZXhPZih2YWwpID09PSBpIH0pCiAgICAgICAgICAgICAgLmpvaW4oJy0nKQogICAgICAgICAgICBidG4udmFsdWUgPSBjaG9zZW5Db250ZW50TmFtZXMKICAgICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKHZhbCwgaSwgc2VsZikgeyByZXR1cm4gc2VsZi5pbmRleE9mKHZhbCkgPT09IGkgfSkKICAgICAgICAgICAgICAuam9pbignLCAnKQogICAgICAgICAgfQogICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIG91dHB1dC52YWx1ZSA9IGl0ZW0uQ29udGVudElECiAgICAgICAgICAgIGJ0bi52YWx1ZSA9IGl0ZW0uRmllbGRWYWx1ZQogICAgICAgICAgICBib290c3RyYXAuTW9kYWwuZ2V0SW5zdGFuY2UobW9kYWwpLmhpZGUoKQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSkKCiAgICAgIG1vZGFsLmFkZEV2ZW50TGlzdGVuZXIoJ2hpZGRlbi5icy5tb2RhbCcsIGZ1bmN0aW9uKCkgeyAKICAgICAgICBpbnB1dENULnZhbHVlID0gJycKICAgICAgICBhdXRvQ1QuYXV0b2NvbXBsZXRlLmRlc3Ryb3koKQogICAgICAgIGF1dG9DVCA9IGZhbHNlOwogICAgICAgIGlucHV0Qy52YWx1ZSA9ICcnCiAgICAgICAgaW5wdXRDLmRpc2FibGVkID0gdHJ1ZQogICAgICAgIGF1dG9DLmF1dG9jb21wbGV0ZS5kZXN0cm95KCkKICAgICAgICBhdXRvQyA9IGZhbHNlOwogICAgICB9KQoKICAgICAgY2xlYXIuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpIHsgCiAgICAgICAgaW5wdXRDVC52YWx1ZSA9ICcnOwogICAgICAgIGlucHV0Qy52YWx1ZSA9ICcnOwogICAgICAgIGlucHV0Qy5kaXNhYmxlZCA9IHRydWU7CiAgICAgICAgaW5wdXRDVC5mb2N1cygpOwogICAgICAgIG91dHB1dC52YWx1ZSA9ICcnOwogICAgICAgIGJ0bi52YWx1ZSA9ICdPcGVuJzsKICAgICAgICBjaG9zZW5Db250ZW50VHlwZUlEID0gdm9pZCAwOwogICAgICAgIGNob3NlbkNvbnRlbnRJRHMgPSBbXTsKICAgICAgICBjaG9zZW5Db250ZW50TmFtZXMgPSBbXTsKICAgICAgfSkKCiAgICB9KShyZWYsIG91dHB1dCwgYnRuLCBpbnB1dENULCBpbnB1dEMsIG1vZGFsLCBjbGVhcik7CiAgfQoKfSkoKTsK")


A vendor/github.com/google/uuid/.travis.yml => vendor/github.com/google/uuid/.travis.yml +9 -0
@@ 0,0 1,9 @@
language: go

go:
  - 1.4.3
  - 1.5.3
  - tip

script:
  - go test -v ./...

A vendor/github.com/google/uuid/CONTRIBUTING.md => vendor/github.com/google/uuid/CONTRIBUTING.md +10 -0
@@ 0,0 1,10 @@
# How to contribute

We definitely welcome patches and contribution to this project!

### Legal requirements

In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).

You may have already signed it for other Google projects.

A vendor/github.com/google/uuid/CONTRIBUTORS => vendor/github.com/google/uuid/CONTRIBUTORS +9 -0
@@ 0,0 1,9 @@
Paul Borman <borman@google.com>
bmatsuo
shawnps
theory
jboverfelt
dsymonds
cd1
wallclockbuilder
dansouza

A vendor/github.com/google/uuid/LICENSE => vendor/github.com/google/uuid/LICENSE +27 -0
@@ 0,0 1,27 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
   * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

A vendor/github.com/google/uuid/README.md => vendor/github.com/google/uuid/README.md +19 -0
@@ 0,0 1,19 @@
# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on
[RFC 4122](http://tools.ietf.org/html/rfc4122)
and DCE 1.1: Authentication and Security Services. 

This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid).  It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice.  One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).

###### Install
`go get github.com/google/uuid`

###### Documentation 
[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid)

Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here: 
http://godoc.org/github.com/google/uuid

A vendor/github.com/google/uuid/dce.go => vendor/github.com/google/uuid/dce.go +80 -0
@@ 0,0 1,80 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"encoding/binary"
	"fmt"
	"os"
)

// A Domain represents a Version 2 domain
type Domain byte

// Domain constants for DCE Security (Version 2) UUIDs.
const (
	Person = Domain(0)
	Group  = Domain(1)
	Org    = Domain(2)
)

// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group.  The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
	uuid, err := NewUUID()
	if err == nil {
		uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
		uuid[9] = byte(domain)
		binary.BigEndian.PutUint32(uuid[0:], id)
	}
	return uuid, err
}

// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
//  NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
	return NewDCESecurity(Person, uint32(os.Getuid()))
}

// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
//  NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
	return NewDCESecurity(Group, uint32(os.Getgid()))
}

// Domain returns the domain for a Version 2 UUID.  Domains are only defined
// for Version 2 UUIDs.
func (uuid UUID) Domain() Domain {
	return Domain(uuid[9])
}

// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
// UUIDs.
func (uuid UUID) ID() uint32 {
	return binary.BigEndian.Uint32(uuid[0:4])
}

func (d Domain) String() string {
	switch d {
	case Person:
		return "Person"
	case Group:
		return "Group"
	case Org:
		return "Org"
	}
	return fmt.Sprintf("Domain%d", int(d))
}

A vendor/github.com/google/uuid/doc.go => vendor/github.com/google/uuid/doc.go +12 -0
@@ 0,0 1,12 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package uuid generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// A UUID is a 16 byte (128 bit) array.  UUIDs may be used as keys to
// maps or compared directly.
package uuid

A vendor/github.com/google/uuid/go.mod => vendor/github.com/google/uuid/go.mod +1 -0
@@ 0,0 1,1 @@
module github.com/google/uuid

A vendor/github.com/google/uuid/hash.go => vendor/github.com/google/uuid/hash.go +53 -0
@@ 0,0 1,53 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"crypto/md5"
	"crypto/sha1"
	"hash"
)

// Well known namespace IDs and UUIDs
var (
	NameSpaceDNS  = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
	NameSpaceURL  = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
	NameSpaceOID  = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
	NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
	Nil           UUID // empty UUID, all zeros
)

// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h.  The hash should be at least 16 byte in length.  The
// first 16 bytes of the hash are used to form the UUID.  The version of the
// UUID will be the lower 4 bits of version.  NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
	h.Reset()
	h.Write(space[:])
	h.Write(data)
	s := h.Sum(nil)
	var uuid UUID
	copy(uuid[:], s)
	uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
	uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
	return uuid
}

// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data.  It is the same as calling:
//
//  NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
	return NewHash(md5.New(), space, data, 3)
}

// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data.  It is the same as calling:
//
//  NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
	return NewHash(sha1.New(), space, data, 5)
}

A vendor/github.com/google/uuid/marshal.go => vendor/github.com/google/uuid/marshal.go +37 -0
@@ 0,0 1,37 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import "fmt"

// MarshalText implements encoding.TextMarshaler.
func (uuid UUID) MarshalText() ([]byte, error) {
	var js [36]byte
	encodeHex(js[:], uuid)
	return js[:], nil
}

// UnmarshalText implements encoding.TextUnmarshaler.
func (uuid *UUID) UnmarshalText(data []byte) error {
	id, err := ParseBytes(data)
	if err == nil {
		*uuid = id
	}
	return err
}

// MarshalBinary implements encoding.BinaryMarshaler.
func (uuid UUID) MarshalBinary() ([]byte, error) {
	return uuid[:], nil
}

// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (uuid *UUID) UnmarshalBinary(data []byte) error {
	if len(data) != 16 {
		return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
	}
	copy(uuid[:], data)
	return nil
}

A vendor/github.com/google/uuid/node.go => vendor/github.com/google/uuid/node.go +90 -0
@@ 0,0 1,90 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"sync"
)

var (
	nodeMu sync.Mutex
	ifname string  // name of interface being used
	nodeID [6]byte // hardware for version 1 UUIDs
	zeroID [6]byte // nodeID with only 0's
)

// NodeInterface returns the name of the interface from which the NodeID was
// derived.  The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
	defer nodeMu.Unlock()
	nodeMu.Lock()
	return ifname
}

// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated.  If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
	defer nodeMu.Unlock()
	nodeMu.Lock()
	return setNodeInterface(name)
}

func setNodeInterface(name string) bool {
	iname, addr := getHardwareInterface(name) // null implementation for js
	if iname != "" && addr != nil {
		ifname = iname
		copy(nodeID[:], addr)
		return true
	}

	// We found no interfaces with a valid hardware address.  If name
	// does not specify a specific interface generate a random Node ID
	// (section 4.1.6)
	if name == "" {
		ifname = "random"
		randomBits(nodeID[:])
		return true
	}
	return false
}

// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
	defer nodeMu.Unlock()
	nodeMu.Lock()
	if nodeID == zeroID {
		setNodeInterface("")
	}
	nid := nodeID
	return nid[:]
}

// SetNodeID sets the Node ID to be used for Version 1 UUIDs.  The first 6 bytes
// of id are used.  If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
	if len(id) < 6 {
		return false
	}
	defer nodeMu.Unlock()
	nodeMu.Lock()
	copy(nodeID[:], id)
	ifname = "user"
	return true
}

// NodeID returns the 6 byte node id encoded in uuid.  It returns nil if uuid is
// not valid.  The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
	var node [6]byte
	copy(node[:], uuid[10:])
	return node[:]
}

A vendor/github.com/google/uuid/node_js.go => vendor/github.com/google/uuid/node_js.go +12 -0
@@ 0,0 1,12 @@
// Copyright 2017 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build js

package uuid

// getHardwareInterface returns nil values for the JS version of the code.
// This remvoves the "net" dependency, because it is not used in the browser.
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
func getHardwareInterface(name string) (string, []byte) { return "", nil }

A vendor/github.com/google/uuid/node_net.go => vendor/github.com/google/uuid/node_net.go +33 -0
@@ 0,0 1,33 @@
// Copyright 2017 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !js

package uuid

import "net"

var interfaces []net.Interface // cached list of interfaces

// getHardwareInterface returns the name and hardware address of interface name.
// If name is "" then the name and hardware address of one of the system's
// interfaces is returned.  If no interfaces are found (name does not exist or
// there are no interfaces) then "", nil is returned.
//
// Only addresses of at least 6 bytes are returned.
func getHardwareInterface(name string) (string, []byte) {
	if interfaces == nil {
		var err error
		interfaces, err = net.Interfaces()
		if err != nil {
			return "", nil
		}
	}
	for _, ifs := range interfaces {
		if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
			return ifs.Name, ifs.HardwareAddr
		}
	}
	return "", nil
}

A vendor/github.com/google/uuid/sql.go => vendor/github.com/google/uuid/sql.go +59 -0
@@ 0,0 1,59 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"database/sql/driver"
	"fmt"
)

// Scan implements sql.Scanner so UUIDs can be read from databases transparently
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
	switch src := src.(type) {
	case nil:
		return nil

	case string:
		// if an empty UUID comes from a table, we return a null UUID
		if src == "" {
			return nil
		}

		// see Parse for required string format
		u, err := Parse(src)
		if err != nil {
			return fmt.Errorf("Scan: %v", err)
		}

		*uuid = u

	case []byte:
		// if an empty UUID comes from a table, we return a null UUID
		if len(src) == 0 {
			return nil
		}

		// assumes a simple slice of bytes if 16 bytes
		// otherwise attempts to parse
		if len(src) != 16 {
			return uuid.Scan(string(src))
		}
		copy((*uuid)[:], src)

	default:
		return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
	}

	return nil
}

// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
	return uuid.String(), nil
}

A vendor/github.com/google/uuid/time.go => vendor/github.com/google/uuid/time.go +123 -0
@@ 0,0 1,123 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"encoding/binary"
	"sync"
	"time"
)

// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64

const (
	lillian    = 2299160          // Julian day of 15 Oct 1582
	unix       = 2440587          // Julian day of 1 Jan 1970
	epoch      = unix - lillian   // Days between epochs
	g1582      = epoch * 86400    // seconds between epochs
	g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)

var (
	timeMu   sync.Mutex
	lasttime uint64 // last time we returned
	clockSeq uint16 // clock sequence for this run

	timeNow = time.Now // for testing
)

// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
	sec = int64(t - g1582ns100)
	nsec = (sec % 10000000) * 100
	sec /= 10000000
	return sec, nsec
}

// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed.  An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) {
	defer timeMu.Unlock()
	timeMu.Lock()
	return getTime()
}

func getTime() (Time, uint16, error) {
	t := timeNow()

	// If we don't have a clock sequence already, set one.
	if clockSeq == 0 {
		setClockSequence(-1)
	}
	now := uint64(t.UnixNano()/100) + g1582ns100

	// If time has gone backwards with this clock sequence then we
	// increment the clock sequence
	if now <= lasttime {
		clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
	}
	lasttime = now
	return Time(now), clockSeq, nil
}

// ClockSequence returns the current clock sequence, generating one if not
// already set.  The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated.  Unless SetClockSequence is used, a new
// random clock sequence is generated the first time a clock sequence is
// requested by ClockSequence, GetTime, or NewUUID.  (section 4.2.1.1)
func ClockSequence() int {
	defer timeMu.Unlock()
	timeMu.Lock()
	return clockSequence()
}

func clockSequence() int {
	if clockSeq == 0 {
		setClockSequence(-1)
	}
	return int(clockSeq & 0x3fff)
}

// SetClockSequence sets the clock sequence to the lower 14 bits of seq.  Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
	defer timeMu.Unlock()
	timeMu.Lock()
	setClockSequence(seq)
}

func setClockSequence(seq int) {
	if seq == -1 {
		var b [2]byte
		randomBits(b[:]) // clock sequence
		seq = int(b[0])<<8 | int(b[1])
	}
	oldSeq := clockSeq
	clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
	if oldSeq != clockSeq {
		lasttime = 0
	}
}

// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid.  The time is only defined for version 1 and 2 UUIDs.
func (uuid UUID) Time() Time {
	time := int64(binary.BigEndian.Uint32(uuid[0:4]))
	time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
	time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
	return Time(time)
}

// ClockSequence returns the clock sequence encoded in uuid.
// The clock sequence is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) ClockSequence() int {
	return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
}

A vendor/github.com/google/uuid/util.go => vendor/github.com/google/uuid/util.go +43 -0
@@ 0,0 1,43 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"io"
)

// randomBits completely fills slice b with random data.
func randomBits(b []byte) {
	if _, err := io.ReadFull(rander, b); err != nil {
		panic(err.Error()) // rand should never fail
	}
}

// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}

// xtob converts hex characters x1 and x2 into a byte.
func xtob(x1, x2 byte) (byte, bool) {
	b1 := xvalues[x1]
	b2 := xvalues[x2]
	return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

A vendor/github.com/google/uuid/uuid.go => vendor/github.com/google/uuid/uuid.go +245 -0
@@ 0,0 1,245 @@
// Copyright 2018 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"strings"
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID [16]byte

// A Version represents a UUID's version.
type Version byte

// A Variant represents a UUID's variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

var rander = rand.Reader // random function

// Parse decodes s into a UUID or returns an error.  Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (UUID, error) {
	var uuid UUID
	switch len(s) {
	// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36:

	// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36 + 9:
		if strings.ToLower(s[:9]) != "urn:uuid:" {
			return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
		}
		s = s[9:]

	// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
	case 36 + 2:
		s = s[1:]

	// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	case 32:
		var ok bool
		for i := range uuid {
			uuid[i], ok = xtob(s[i*2], s[i*2+1])
			if !ok {
				return uuid, errors.New("invalid UUID format")
			}
		}
		return uuid, nil
	default:
		return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
	}
	// s is now at least 36 bytes long
	// it must be of the form  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return uuid, errors.New("invalid UUID format")
	}
	for i, x := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		v, ok := xtob(s[x], s[x+1])
		if !ok {
			return uuid, errors.New("invalid UUID format")
		}
		uuid[i] = v
	}
	return uuid, nil
}

// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
	var uuid UUID
	switch len(b) {
	case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
		if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
			return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
		}
		b = b[9:]
	case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
		b = b[1:]
	case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		var ok bool
		for i := 0; i < 32; i += 2 {
			uuid[i/2], ok = xtob(b[i], b[i+1])
			if !ok {
				return uuid, errors.New("invalid UUID format")
			}
		}
		return uuid, nil
	default:
		return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
	}
	// s is now at least 36 bytes long
	// it must be of the form  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
		return uuid, errors.New("invalid UUID format")
	}
	for i, x := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		v, ok := xtob(b[x], b[x+1])
		if !ok {
			return uuid, errors.New("invalid UUID format")
		}
		uuid[i] = v
	}
	return uuid, nil
}

// MustParse is like Parse but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding compiled UUIDs.
func MustParse(s string) UUID {
	uuid, err := Parse(s)
	if err != nil {
		panic(`uuid: Parse(` + s + `): ` + err.Error())
	}
	return uuid
}

// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
// does not have a length of 16. The bytes are copied from the slice.
func FromBytes(b []byte) (uuid UUID, err error) {
	err = uuid.UnmarshalBinary(b)
	return uuid, err
}

// Must returns uuid if err is nil and panics otherwise.
func Must(uuid UUID, err error) UUID {
	if err != nil {
		panic(err)
	}
	return uuid
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
	var buf [36]byte
	encodeHex(buf[:], uuid)
	return string(buf[:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func (uuid UUID) URN() string {
	var buf [36 + 9]byte
	copy(buf[:], "urn:uuid:")
	encodeHex(buf[9:], uuid)
	return string(buf[:])
}

func encodeHex(dst []byte, uuid UUID) {
	hex.Encode(dst, uuid[:4])
	dst[8] = '-'
	hex.Encode(dst[9:13], uuid[4:6])
	dst[13] = '-'
	hex.Encode(dst[14:18], uuid[6:8])
	dst[18] = '-'
	hex.Encode(dst[19:23], uuid[8:10])
	dst[23] = '-'
	hex.Encode(dst[24:], uuid[10:])
}

// Variant returns the variant encoded in uuid.
func (uuid UUID) Variant() Variant {
	switch {
	case (uuid[8] & 0xc0) == 0x80:
		return RFC4122
	case (uuid[8] & 0xe0) == 0xc0:
		return Microsoft
	case (uuid[8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
}

// Version returns the version of uuid.
func (uuid UUID) Version() Version {
	return Version(uuid[6] >> 4)
}

func (v Version) String() string {
	if v > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", v)
	}
	return fmt.Sprintf("VERSION_%d", v)
}

func (v Variant) String() string {
	switch v {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int(v))
}

// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
	if r == nil {
		rander = rand.Reader
		return
	}
	rander = r
}

A vendor/github.com/google/uuid/version1.go => vendor/github.com/google/uuid/version1.go +44 -0
@@ 0,0 1,44 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"encoding/binary"
)

// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time.  If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically.  If the NodeID cannot
// be set NewUUID returns nil.  If clock sequence has not been set by
// SetClockSequence then it will be set automatically.  If GetTime fails to
// return the current NewUUID returns nil and an error.
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
	nodeMu.Lock()
	if nodeID == zeroID {
		setNodeInterface("")
	}
	nodeMu.Unlock()

	var uuid UUID
	now, seq, err := GetTime()
	if err != nil {
		return uuid, err
	}

	timeLow := uint32(now & 0xffffffff)
	timeMid := uint16((now >> 32) & 0xffff)
	timeHi := uint16((now >> 48) & 0x0fff)
	timeHi |= 0x1000 // Version 1

	binary.BigEndian.PutUint32(uuid[0:], timeLow)
	binary.BigEndian.PutUint16(uuid[4:], timeMid)
	binary.BigEndian.PutUint16(uuid[6:], timeHi)
	binary.BigEndian.PutUint16(uuid[8:], seq)
	copy(uuid[10:], nodeID[:])

	return uuid, nil
}

A vendor/github.com/google/uuid/version4.go => vendor/github.com/google/uuid/version4.go +38 -0
@@ 0,0 1,38 @@
// Copyright 2016 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import "io"

// New creates a new random UUID or panics.  New is equivalent to
// the expression
//
//    uuid.Must(uuid.NewRandom())
func New() UUID {
	return Must(NewRandom())
}

// NewRandom returns a Random (Version 4) UUID.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
//  Randomly generated UUIDs have 122 random bits.  One's annual risk of being
//  hit by a meteorite is estimated to be one chance in 17 billion, that
//  means the probability is about 0.00000000006 (6 × 10−11),
//  equivalent to the odds of creating a few tens of trillions of UUIDs in a
//  year and having one duplicate.
func NewRandom() (UUID, error) {
	var uuid UUID
	_, err := io.ReadFull(rander, uuid[:])
	if err != nil {
		return Nil, err
	}
	uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
	uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
	return uuid, nil
}

M vendor/modules.txt => vendor/modules.txt +2 -0
@@ 12,6 12,8 @@ github.com/go-playground/assert/v2
github.com/go-sql-driver/mysql
# github.com/golang/mock v1.4.3
github.com/golang/mock/gomock
# github.com/google/uuid v1.1.1
github.com/google/uuid
# github.com/kr/pretty v0.2.0
github.com/kr/pretty
# github.com/kr/text v0.1.0